diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..f8ca06d3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ + +*.opendb +*.sln +*.vcxproj +*.filters +*.obj +*.lastbuildstate +*.tlog +*.user +*.ini +*.log +*.pdb +*.lib +*.exe +*.ilk +*.dll +*.exp +*.db +*.jpg +*.cache +*.mtl +*/OutputImages/* +*/ReferenceImages/* +*/cache/*.bin + +build/ + +.vs/ +CMakeSettings.json +CppProperties.json \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index e7bc81ac..ca2918a5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "RadeonRays"] path = RadeonRays url = https://github.com/GPUOpen-LibrariesAndSDKs/RadeonRays_SDK.git + branch = master diff --git a/3rdparty/RprSupport/bin/x64/RprSupport64.dll b/3rdparty/RprSupport/bin/x64/RprSupport64.dll new file mode 100644 index 00000000..2b0ede3a Binary files /dev/null and b/3rdparty/RprSupport/bin/x64/RprSupport64.dll differ diff --git a/3rdparty/RprSupport/include/RprSupport.h b/3rdparty/RprSupport/include/RprSupport.h new file mode 100644 index 00000000..1059438c --- /dev/null +++ b/3rdparty/RprSupport/include/RprSupport.h @@ -0,0 +1,260 @@ +/*****************************************************************************\ +* +* Module Name RprSupport.h +* Project RRP support library +* +* Description RRP support library interface header +* +* Copyright 2017 Advanced Micro Devices, Inc. +* +* All rights reserved. This notice is intended as a precaution against +* inadvertent publication and does not imply publication or any waiver +* of confidentiality. The year included in the foregoing notice is the +* year of creation of the work. +\*****************************************************************************/ +#ifndef __RPRSUPPORT_H +#define __RPRSUPPORT_H + +#include "RadeonProRender.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define RPRX_SUPPORT_API_VERSION 0x0000002 +#define RPRX_FLAGS_ENABLE_LOGGING 0x1 + +/*rprx_material_type*/ +#define RPRX_MATERIAL_UBER 0x1 +#define RPRX_MATERIAL_ARCHITECTURAL 0x2 +#define RPRX_MATERIAL_SKIN 0x3 +#define RPRX_MATERIAL_CARPAINT 0x4 + +typedef rpr_uint rprx_material_type; +typedef rpr_uint rprx_parameter; +typedef rpr_uint rprx_parameter_type; + +struct _rprxcontext +{ + rpr_uint padding; +}; +struct _rprxmaterial +{ + rpr_uint padding; +}; + +typedef _rprxcontext *rprx_context; +typedef _rprxmaterial *rprx_material; + +/*rprx_material_type*/ +#define RPRX_UBER_MATERIAL_DIFFUSE_COLOR 0x100U +#define RPRX_UBER_MATERIAL_DIFFUSE_WEIGHT 0x101U +#define RPRX_UBER_MATERIAL_DIFFUSE_ROUGHNESS 0x102U +#define RPRX_UBER_MATERIAL_REFLECTION_COLOR 0x103U +#define RPRX_UBER_MATERIAL_REFLECTION_WEIGHT 0x104U +#define RPRX_UBER_MATERIAL_REFLECTION_ROUGHNESS 0x105U +#define RPRX_UBER_MATERIAL_REFLECTION_ANISOTROPY 0x106U +#define RPRX_UBER_MATERIAL_REFLECTION_ANISOTROPY_ROTATION 0x107U +#define RPRX_UBER_MATERIAL_REFLECTION_MODE 0x108U +#define RPRX_UBER_MATERIAL_REFLECTION_IOR 0x109U +#define RPRX_UBER_MATERIAL_REFLECTION_METALNESS 0x109U +#define RPRX_UBER_MATERIAL_REFRACTION_COLOR 0x10AU +#define RPRX_UBER_MATERIAL_REFRACTION_WEIGHT 0x10BU +#define RPRX_UBER_MATERIAL_REFRACTION_ROUGHNESS 0x10CU +#define RPRX_UBER_MATERIAL_REFRACTION_IOR 0x10DU +#define RPRX_UBER_MATERIAL_REFRACTION_IOR_MODE 0x10EU +#define RPRX_UBER_MATERIAL_REFRACTION_THIN_SURFACE 0x10FU +#define RPRX_UBER_MATERIAL_COATING_COLOR 0x110U +#define RPRX_UBER_MATERIAL_COATING_WEIGHT 0x111U +#define RPRX_UBER_MATERIAL_COATING_ROUGHNESS 0x112U +#define RPRX_UBER_MATERIAL_COATING_MODE 0x113U +#define RPRX_UBER_MATERIAL_COATING_IOR 0x114U +#define RPRX_UBER_MATERIAL_COATING_METALNESS 0x114U +#define RPRX_UBER_MATERIAL_EMISSION_COLOR 0x115U +#define RPRX_UBER_MATERIAL_EMISSION_WEIGHT 0x116U +#define RPRX_UBER_MATERIAL_EMISSION_MODE 0x117U +#define RPRX_UBER_MATERIAL_TRANSPARENCY 0x118U +#define RPRX_UBER_MATERIAL_NORMAL 0x119U +#define RPRX_UBER_MATERIAL_BUMP 0x11AU +#define RPRX_UBER_MATERIAL_DISPLACEMENT 0x11BU +#define RPRX_UBER_MATERIAL_SSS_ABSORPTION_COLOR 0x11CU +#define RPRX_UBER_MATERIAL_SSS_SCATTER_COLOR 0x11DU +#define RPRX_UBER_MATERIAL_SSS_ABSORPTION_DISTANCE 0x11EU +#define RPRX_UBER_MATERIAL_SSS_SCATTER_DISTANCE 0x11FU +#define RPRX_UBER_MATERIAL_SSS_SCATTER_DIRECTION 0x120U +#define RPRX_UBER_MATERIAL_SSS_WEIGHT 0x121U +#define RPRX_UBER_MATERIAL_SSS_SUBSURFACE_COLOR 0x122U +#define RPRX_UBER_MATERIAL_SSS_MULTISCATTER 0x123U + +#define RPRX_UBER_MATERIAL_REFLECTION_MODE_PBR 0x1U +#define RPRX_UBER_MATERIAL_REFLECTION_MODE_METALNESS 0x2U +#define RPRX_UBER_MATERIAL_REFRACTION_MODE_SEPARATE 0x1U +#define RPRX_UBER_MATERIAL_REFRACTION_MODE_LINKED 0x2U +#define RPRX_UBER_MATERIAL_COATING_MODE_PBR 0x1U +#define RPRX_UBER_MATERIAL_COATING_MODE_METALNESS 0x2U +#define RPRX_UBER_MATERIAL_EMISSION_MODE_SINGLESIDED 0x1U +#define RPRX_UBER_MATERIAL_EMISSION_MODE_DOUBLESIDED 0x2U + +/*rprx_parameter_type*/ +#define RPRX_PARAMETER_TYPE_FLOAT4 0x1U +#define RPRX_PARAMETER_TYPE_UINT 0x2U +#define RPRX_PARAMETER_TYPE_NODE 0x3U + +/** @brief Create RPRX context. + * + * RPR contexts allow to track several RPR contexts and material systems at the same time. + * + * @param material_system Material system to use + * @param flags Additional options (currently only RPRX_FLAGS_ENABLE_LOGGING supported) + * @param out_context Context + * @return RPR_SUCCESS in case of success, error code otherwise + */ +extern RPR_API_ENTRY rpr_int rprxCreateContext(rpr_material_system material_system, rpr_uint flags, rprx_context* out_context); + +/** @brief Create RPRX material + * + * The function creates a material of a specified type. Supported types: + * RPRX_MATERIAL_UBER + * + * @param context RPRX context + * @param type Material type + * @param out_material Pointer to newly created material + * @return RPR_SUCCESS in case of success, error code otherwise + */ +extern RPR_API_ENTRY rpr_int rprxCreateMaterial(rprx_context context, rprx_material_type type, rprx_material* out_material); + +/** @brief Delete RPRX material + * + * The function deletes the material passed in. The function also remove material from + * the set of tracked materials. + * + * Warning : this function will manipulate all the rpr_shape objects attached to this material (with rprxShapeAttachMaterial) + * So do not call rprObjectDelete(shape) before calling rprxMaterialDelete. + * Or call rprxShapeDetachMaterial on all the shapes using material before calling rprxMaterialDelete. + * + * @param context RPRX context + * @param material Material to delete + * @return RPR_SUCCESS in case of success, error code otherwise + */ +extern RPR_API_ENTRY rpr_int rprxMaterialDelete(rprx_context context, rprx_material material); + +/** @brief Set the parameter for a material + * + * The function sets specified parameter for a given material. + * + * @param context RPRX context + * @param material Material + * @param parameter parameter Parameter to set + * @param node Input node + * @return RPR_SUCCESS in case of success, error code otherwise + */ +extern RPR_API_ENTRY rpr_int rprxMaterialSetParameterN(rprx_context context, rprx_material material, rprx_parameter parameter, rpr_material_node node); +extern RPR_API_ENTRY rpr_int rprxMaterialSetParameterU(rprx_context context, rprx_material material, rprx_parameter parameter, rpr_uint value); +extern RPR_API_ENTRY rpr_int rprxMaterialSetParameterF(rprx_context context, rprx_material material, rprx_parameter parameter, rpr_float x, rpr_float y, rpr_float z, rpr_float w); +extern RPR_API_ENTRY rpr_int rprxMaterialGetParameterType(rprx_context context, rprx_material material, rprx_parameter parameter, rprx_parameter_type * out_type); +extern RPR_API_ENTRY rpr_int rprxMaterialGetParameterValue(rprx_context context, rprx_material material, rprx_parameter parameter, void * out_value); + +/** @brief Commit changes for a specified material + * + * initializes internal data structures and established necessary conditions + * + * @param context RPRX context + * @param material Material to commit changes for + * @return RPR_SUCCESS in case of success, error code otherwise + */ +extern RPR_API_ENTRY rpr_int rprxMaterialCommit(rprx_context context, rprx_material material); + +/** @brief Attach RPRX material for a shape + * + * RPRX library internally optimizes material by recompiling internal material graph structure. + * Change-commit approach allows to minimize the number of costly unnecessary recompilations and only + * recompile once before the rendering has started. As a result of this recompilation the output node + * of the material graph might change and the library might need to reapply the material to the shape. + * To implement this, the library needs to "track" the objects material is assigned to. + * + * @param context RPRX context + * @param shape Shape + * @param material Material + * @return RPR_SUCCESS in case of success, error code otherwise + */ +extern RPR_API_ENTRY rpr_int rprxShapeAttachMaterial(rprx_context context, rpr_shape shape, rprx_material material); + +/** @brief Detach RPRX material from a shape + * + * RPRX library internally optimizes material by recompiling internal material graph structure. + * Change-commit approach allows to minimize the number of costly unnecessary recompilations and only + * recompile once before the rendering has started. As a result of this recompilation the output node + * of the material graph might change and the library might need to reapply the material to the shape. + * To implement this, the library needs to "track" the objects material is assigned to. + * rprxShapeDetachMaterial function resets shape material back to nullptr and removes the object + * from the set of "tracked" objects. + * + * @param context RPRX context + * @param shape Shape + * @param material Material + * @return RPR_SUCCESS in case of success, error code otherwise + */ +extern RPR_API_ENTRY rpr_int rprxShapeDetachMaterial(rprx_context context, rpr_shape shape, rprx_material material); + +/** @brief Attach RPRX material for a shape + * + * RPRX library internally optimizes material by recompiling internal material graph structure. + * Change-commit approach allows to minimize the number of costly unnecessary recompilations and only + * recompile once before the rendering has started. As a result of this recompilation the output node + * of the material graph might change. If materials is acting in compounds with basic RPR materials + * (for example in blends), this compound materials should be updated with a new output node, so + * the library needs to reapply their inputs. To implement this, the library needs to "track" + * the objects material is bound to. + * + * @param context RPRX context + * @param node Material node to bind to + * @param parameter Parameter to bind + * @param material Material + * @return RPR_SUCCESS in case of success, error code otherwise + */ +extern RPR_API_ENTRY rpr_int rprxMaterialAttachMaterial(rprx_context context, rpr_material_node node, rpr_char const * parameter, rprx_material material); + +/** @brief Detach RPRX material from a shape + * + * RPRX library internally optimizes material by recompiling internal material graph structure. + * Change-commit approach allows to minimize the number of costly unnecessary recompilations and only + * recompile once before the rendering has started. As a result of this recompilation the output node + * of the material graph might change. If materials is acting in compounds with basic RPR materials + * (for example in blends), this compound materials should be updated with a new output node, so + * the library needs to reapply their inputs. To implement this, the library needs to "track" + * the objects material is bound to. rprxMaterialDetachMaterial resets specified parameter back + * to nullptr and removes the node from the set of "tracked" nodes. + * + * @param context RPRX context + * @param node Material node to bind to + * @param parameter Parameter to bind + * @param material Material + * @return RPR_SUCCESS in case of success, error code otherwise + */ +extern RPR_API_ENTRY rpr_int rprxMaterialDetachMaterial(rprx_context context, rpr_material_node node, rpr_char const * parameter, rprx_material material); + +/** @brief Delete RPRX context + * + * The function deletes the context passed in. + * + * @param context RPRX context + * @return RPR_SUCCESS in case of success, error code otherwise + */ +extern RPR_API_ENTRY rpr_int rprxDeleteContext(rprx_context context); + +/** @brief Check whether specified rpr_material_node belongs to rprx material + * + * @param context RPRX context + * @param node RPR material node + * @param material RPRX material + * @param result out_result result + * @return RPR_SUCCESS in case of success, error code otherwise + */ +extern RPR_API_ENTRY rpr_int rprxIsMaterialRprx(rprx_context context, rpr_material_node node, rprx_material * out_material, rpr_bool* out_result); +extern RPR_API_ENTRY rpr_int rprxGetLog(rprx_context context, rpr_char* log, size_t* size); +extern RPR_API_ENTRY rpr_int rprxShapeGetMaterial(rprx_context context, rpr_shape shape, rprx_material* material); +#ifdef __cplusplus +} +#endif + +#endif /*__RPRSUPPORT_H */ diff --git a/3rdparty/RprSupport/lib/x64/RprSupport64.lib b/3rdparty/RprSupport/lib/x64/RprSupport64.lib new file mode 100644 index 00000000..3b0a85fc Binary files /dev/null and b/3rdparty/RprSupport/lib/x64/RprSupport64.lib differ diff --git a/3rdparty/oiio16/include/OpenImageIO/SHA1.h b/3rdparty/oiio16/include/OpenImageIO/SHA1.h deleted file mode 100644 index 4951da0b..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/SHA1.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - 100% free public domain implementation of the SHA-1 algorithm - by Dominik Reichl - Web: http://www.dominik-reichl.de/ - - Version 1.8 - 2008-03-16 - - Converted project files to Visual Studio 2008 format. - - Added Unicode support for HashFile utility method. - - Added support for hashing files using the HashFile method that are - larger than 2 GB. - - HashFile now returns an error code instead of copying an error - message into the output buffer. - - GetHash now returns an error code and validates the input parameter. - - Added ReportHashStl STL utility method. - - Added REPORT_HEX_SHORT reporting mode. - - Improved Linux compatibility of test program. - - Version 1.7 - 2006-12-21 - - Fixed buffer underrun warning that appeared when compiling with - Borland C Builder (thanks to Rex Bloom and Tim Gallagher for the - patch). - - Breaking change: ReportHash writes the final hash to the start - of the buffer, i.e. it's not appending it to the string anymore. - - Made some function parameters const. - - Added Visual Studio 2005 project files to demo project. - - Version 1.6 - 2005-02-07 (thanks to Howard Kapustein for patches) - - You can set the endianness in your files, no need to modify the - header file of the CSHA1 class anymore. - - Aligned data support. - - Made support/compilation of the utility functions (ReportHash and - HashFile) optional (useful when bytes count, for example in embedded - environments). - - Version 1.5 - 2005-01-01 - - 64-bit compiler compatibility added. - - Made variable wiping optional (define SHA1_WIPE_VARIABLES). - - Removed unnecessary variable initializations. - - ROL32 improvement for the Microsoft compiler (using _rotl). - - Version 1.4 - 2004-07-22 - - CSHA1 now compiles fine with GCC 3.3 under MacOS X (thanks to Larry - Hastings). - - Version 1.3 - 2003-08-17 - - Fixed a small memory bug and made a buffer array a class member to - ensure correct working when using multiple CSHA1 class instances at - one time. - - Version 1.2 - 2002-11-16 - - Borlands C++ compiler seems to have problems with string addition - using sprintf. Fixed the bug which caused the digest report function - not to work properly. CSHA1 is now Borland compatible. - - Version 1.1 - 2002-10-11 - - Removed two unnecessary header file includes and changed BOOL to - bool. Fixed some minor bugs in the web page contents. - - Version 1.0 - 2002-06-20 - - First official release. - - ======== Test Vectors (from FIPS PUB 180-1) ======== - - SHA1("abc") = - A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D - - SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = - 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 - - SHA1(A million repetitions of "a") = - 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F -*/ - -#ifndef ___SHA1_HDR___ -#define ___SHA1_HDR___ - -#include - -#include "export.h" -#include "oiioversion.h" -#include "platform.h" - -#if !defined(SHA1_UTILITY_FUNCTIONS) && !defined(SHA1_NO_UTILITY_FUNCTIONS) -#define SHA1_UTILITY_FUNCTIONS -#endif - -#if !defined(SHA1_STL_FUNCTIONS) && !defined(SHA1_NO_STL_FUNCTIONS) -#define SHA1_STL_FUNCTIONS -#if !defined(SHA1_UTILITY_FUNCTIONS) -#error STL functions require SHA1_UTILITY_FUNCTIONS. -#endif -#endif - -#include - -#ifdef SHA1_UTILITY_FUNCTIONS -#include -#include -#endif - -#ifdef SHA1_STL_FUNCTIONS -#include -#endif - -#ifdef _MSC_VER -#include -#endif - -// You can define the endian mode in your files without modifying the SHA-1 -// source files. Just #define SHA1_LITTLE_ENDIAN or #define SHA1_BIG_ENDIAN -// in your files, before including the SHA1.h header file. If you don't -// define anything, the class defaults to little endian. -#if !defined(SHA1_LITTLE_ENDIAN) && !defined(SHA1_BIG_ENDIAN) -#define SHA1_LITTLE_ENDIAN -#endif - -// If you want variable wiping, #define SHA1_WIPE_VARIABLES, if not, -// #define SHA1_NO_WIPE_VARIABLES. If you don't define anything, it -// defaults to wiping. -#if !defined(SHA1_WIPE_VARIABLES) && !defined(SHA1_NO_WIPE_VARIABLES) -#define SHA1_WIPE_VARIABLES -#endif - -#if defined(SHA1_HAS_TCHAR) -#include -#else -#ifdef _MSC_VER -#include -#else -#ifndef TCHAR -#define TCHAR char -#endif -#ifndef _T -#define _T(__x) (__x) -#define _tmain main -#define _tprintf printf -#define _getts gets -#define _tcslen strlen -#define _tfopen fopen -#define _tcscpy strcpy -#define _tcscat strcat -#define _sntprintf snprintf -#endif -#endif -#endif - -// Fallback, if no 64-bit support -#ifndef _fseeki64 -#define _fseeki64 fseek -#endif -#ifndef _ftelli64 -#define _ftelli64 ftell -#endif - -/////////////////////////////////////////////////////////////////////////// -// Define variable types - -#define UINT_8 uint8_t -#define UINT_32 uint32_t -#define UINT_64 uint64_t -#define INT_64 int64_t - - -/////////////////////////////////////////////////////////////////////////// -// Declare SHA-1 workspace - -OIIO_NAMESPACE_BEGIN - -typedef union -{ - UINT_8 c[64]; - UINT_32 l[16]; -} SHA1_WORKSPACE_BLOCK; - -class CSHA1 -{ -public: -#ifdef SHA1_UTILITY_FUNCTIONS - // Different formats for ReportHash - enum REPORT_TYPE - { - REPORT_HEX = 0, - REPORT_DIGIT = 1, - REPORT_HEX_SHORT = 2 - }; -#endif - - // Constructor and destructor - CSHA1(); - ~CSHA1(); - - UINT_32 m_state[5]; - UINT_32 m_count[2]; - UINT_32 m_reserved0[1]; // Memory alignment padding - UINT_8 m_buffer[64]; - UINT_8 m_digest[20]; - UINT_32 m_reserved1[3]; // Memory alignment padding - - void Reset(); - - // Update the hash value - void Update(const UINT_8* pbData, UINT_32 uLen); - -#ifdef SHA1_UTILITY_FUNCTIONS - // Hash in file contents - bool HashFile(const TCHAR* tszFileName); -#endif - - // Finalize hash, call before using ReportHash(Stl) - void Final(); - -#ifdef SHA1_UTILITY_FUNCTIONS - bool ReportHash(TCHAR* tszReport, REPORT_TYPE rtReportType = REPORT_HEX) const; -#endif - -#ifdef SHA1_STL_FUNCTIONS - bool ReportHashStl(std::basic_string& strOut, REPORT_TYPE rtReportType = - REPORT_HEX) const; -#endif - - bool GetHash(UINT_8* pbDest) const; - -private: - // Private SHA-1 transformation - void Transform(UINT_32* pState, const UINT_8* pBuffer); - - // Member variables - UINT_8 m_workspace[64]; - SHA1_WORKSPACE_BLOCK* m_block; // SHA1 pointer to the byte array above -}; - -OIIO_NAMESPACE_END - -#endif // ___SHA1_HDR___ diff --git a/3rdparty/oiio16/include/OpenImageIO/argparse.h b/3rdparty/oiio16/include/OpenImageIO/argparse.h deleted file mode 100644 index dab838d5..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/argparse.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - All Rights Reserved. - Based on BSD-licensed software Copyright 2004 NVIDIA Corp. - - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -/// \file -/// \brief Simple parsing of program command-line arguments. - - -#ifndef OPENIMAGEIO_ARGPARSE_H -#define OPENIMAGEIO_ARGPARSE_H - -#if defined(_MSC_VER) -// Ignore warnings about DLL exported classes with member variables that are template classes. -// This happens with the std::string m_errmessage member of ArgParse below. -# pragma warning (disable : 4251) -#endif - -#include - -#include "export.h" -#include "oiioversion.h" -#include "tinyformat.h" - - -OIIO_NAMESPACE_BEGIN - - -class ArgOption; // Forward declaration - - - -///////////////////////////////////////////////////////////////////////////// -/// -/// \class ArgParse -/// -/// Argument Parsing -/// -/// The parse function takes a list of options and variables or functions -/// for storing option values and return <0 on failure: -/// -/// \code -/// static int parse_files (int argc, const char *argv[]) -/// { -/// for (int i = 0; i < argc; i++) -/// filenames.push_back (argv[i]); -/// return 0; -/// } -/// -/// static int blah_callback (int argc, const char *argv[]) -/// { -/// std::cout << "blah argument was " << argv[1] << "\n"; -/// return 0; -/// } -/// -/// ... -/// -/// ArgParse ap; -/// -/// ap.options ("Usage: myapp [options] filename...", -/// "%*", parse_objects, "", -/// "-camera %f %f %f", &camera[0], &camera[1], &camera[2], -/// "set the camera position", -/// "-lookat %f %f %f", &lx, &ly, &lz, -/// "set the position of interest", -/// "-oversampling %d", &oversampling, "oversamping rate", -/// "-passes %d", &passes, "number of passes", -/// "-lens %f %f %f", &aperture, &focalDistance, &focalLength, -/// "set aperture, focal distance, focal length", -/// "-format %d %d %f", &width, &height, &aspect, -/// "set width, height, aspect ratio", -/// "-v", &verbose, "verbose output", -/// "-q %!", &verbose, "quiet mode", -/// "--blah %@ %s", blahcallback, "Make the callback", -/// NULL); -/// -/// if (ap.parse (argc, argv) < 0) { -/// std::cerr << ap.geterror() << std::endl; -/// ap.usage (); -/// return EXIT_FAILURE; -/// } -/// \endcode -/// -/// The available argument types are: -/// - no \% argument - bool flag -/// - \%! - a bool flag, but set it to false if the option is set -/// - \%d - 32bit integer -/// - \%f - 32bit float -/// - \%F - 64bit float (double) -/// - \%s - std::string -/// - \%L - std::vector (takes 1 arg, appends to list) -/// - \%@ - a function pointer for a callback function will be invoked -/// immediately. The prototype for the callback is -/// int callback (int argc, char *argv[]) -/// - \%* - catch all non-options and pass individually as an (argc,argv) -/// sublist to a callback, each immediately after it's found -/// -/// There are several special format tokens: -/// - "" - not an option at all, just a description to print -/// in the usage output. -/// -/// Notes: -/// - If an option doesn't have any arguments, a bool flag argument is -/// assumed. -/// - No argument destinations are initialized. -/// - The empty string, "", is used as a global sublist (ie. "%*"). -/// - Sublist functions are all of the form "int func(int argc, char **argv)". -/// - If a sublist function returns -1, parse() will terminate early. -/// - It is perfectly legal for the user to append ':' and more characters -/// to the end of an option name, it will match only the portion before -/// the semicolon (but a callback can detect the full string, this is -/// useful for making arguments: myprog --flag:myopt=1 foobar -/// -///////////////////////////////////////////////////////////////////////////// - - -class OIIO_API ArgParse { -public: - ArgParse (int argc=0, const char **argv=NULL); - ~ArgParse (); - - /// Declare the command line options. After the introductory - /// message, parameters are a set of format strings and variable - /// pointers. Each string contains an option name and a scanf-like - /// format string to enumerate the arguments of that option - /// (eg. "-option %d %f %s"). The format string is followed by a - /// list of pointers to the argument variables, just like scanf. A - /// NULL terminates the list. Multiple calls to options() will - /// append additional options. - int options (const char *intro, ...); - - /// With the options already set up, parse the command line. - /// Return 0 if ok, -1 if it's a malformed command line. - int parse (int argc, const char **argv); - - /// Return any error messages generated during the course of parse() - /// (and clear any error flags). If no error has occurred since the - /// last time geterror() was called, it will return an empty string. - std::string geterror () const; - - /// Print the usage message to stdout. The usage message is - /// generated and formatted automatically based on the command and - /// description arguments passed to parse(). - void usage () const; - - /// Print a brief usage message to stdout. The usage message is - /// generated and formatted automatically based on the command and - /// description arguments passed to parse(). - void briefusage () const; - - /// Return the entire command-line as one string. - /// - std::string command_line () const; - -private: - int m_argc; // a copy of the command line argc - const char **m_argv; // a copy of the command line argv - mutable std::string m_errmessage; // error message - ArgOption *m_global; // option for extra cmd line arguments - std::string m_intro; - std::vector m_option; - - ArgOption *find_option(const char *name); - // void error (const char *format, ...) - TINYFORMAT_WRAP_FORMAT (void, error, /**/, - std::ostringstream msg;, msg, m_errmessage = msg.str();) - - int found (const char *option); // number of times option was parsed -}; - - - -// Define symbols that let client applications determine if newly added -// features are supported. -#define OIIO_ARGPARSE_SUPPORTS_BRIEFUSAGE 1 - - -OIIO_NAMESPACE_END - - -#endif // OPENIMAGEIO_ARGPARSE_H diff --git a/3rdparty/oiio16/include/OpenImageIO/array_view.h b/3rdparty/oiio16/include/OpenImageIO/array_view.h deleted file mode 100644 index 75d80dcd..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/array_view.h +++ /dev/null @@ -1,314 +0,0 @@ -/* - Copyright 2015 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -#pragma once - -#include -#include -#include - -#if OIIO_CPLUSPLUS_VERSION >= 11 -# include -# include -#else /* FIXME(C++11): this case can go away when C++11 is our minimum */ -# include -#endif - -#include "oiioversion.h" -#include "platform.h" -#include "dassert.h" -#include "coordinate.h" - -OIIO_NAMESPACE_BEGIN - -#if OIIO_CPLUSPLUS_VERSION >= 11 -using std::remove_const; -using std::is_array; -#else /* FIXME(C++11): this case can go away when C++11 is our minimum */ -using boost::remove_const; -using boost::is_array; -#endif - - -template class array_view; -template class array_view_strided; - - - - -/// array_view : a non-owning reference to a contiguous array with -/// known length. If Rank > 1, it's multi-dimensional. An array_view is -/// mutable (the values in the array may be modified), whereas an -/// array_view is not mutable. -/// -/// Background: Functions whose input requires a set of contiguous values -/// (an array) are faced with a dilemma. If the caller passes just a -/// pointer, the function has no inherent way to determine how many elements -/// may safely be accessed. Passing a std::vector& is "safe", but the caller -/// may not have the data in a vector. The function could require an -/// explicit length to be passed (or a begin/end pair of iterators or -/// pointers). Any way you shake it, there is some awkwardness. -/// -/// The array_view template tries to address this problem by providing -/// a way to pass array parameters that are non-owning, non-copying, -/// non-allocating, and contain a length reference (which in many cases -/// is transparently and automatically computed without additional user -/// code). - -template -class array_view { - OIIO_STATIC_ASSERT (Rank >= 1); - OIIO_STATIC_ASSERT (is_array::value == false); -public: -#if OIIO_CPLUSPLUS_VERSION >= 11 - // using iterator = bounds_iterator; - // using const_iterator = bounds_iterator; - static OIIO_CONSTEXPR_OR_CONST size_t rank = Rank; - using offset_type = offset; - using bounds_type = OIIO::bounds; - using stride_type = offset; - using size_type = size_t; - using value_type = T; - using pointer = T*; - using const_pointer = const T*; - using reference = T&; -#else - static const size_t rank = Rank; - typedef offset offset_type; - typedef OIIO::bounds bounds_type; - typedef offset stride_type; - typedef size_t size_type; - typedef T value_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; -#endif - - /// Default ctr -- points to nothing - array_view () : m_data(NULL) { } - - /// Copy constructor - array_view (const array_view ©) - : m_data(copy.data()), m_bounds(copy.bounds()) {} - - /// Construct from T* and length. - array_view (pointer data, bounds_type bounds) - : m_data(data), m_bounds(bounds) { } - - /// Construct from a single T&. - array_view (T &data) : m_data(&data), m_bounds(1) { } - - /// Construct from a fixed-length C array. Template magic automatically - /// finds the length from the declared type of the array. - template - array_view (T (&data)[N]) : m_data(data), m_bounds(N) { - DASSERT (Rank == 1); - } - - /// Construct from std::vector. - array_view (std::vector &v) - : m_data(v.size() ? &v[0] : NULL), m_bounds(v.size()) { - DASSERT (Rank == 1); - } - - /// Construct from const std::vector. - /// This turns const std::vector into an array_view (the - /// array_view isn't const, but the data it points to will be). - array_view (const std::vector::type> &v) - : m_data(v.size() ? &v[0] : NULL), m_bounds(v.size()) { - DASSERT (Rank == 1); - } - - // assignments - array_view& operator= (const array_view ©) { - m_data = copy.data(); - m_bounds = copy.bounds(); - return *this; - } - - OIIO_CONSTEXPR bounds_type bounds() const OIIO_NOEXCEPT { - return m_bounds; - } - OIIO_CONSTEXPR14 size_type size() const OIIO_NOEXCEPT { - return m_bounds.size(); - } - OIIO_CONSTEXPR14 offset_type stride() const OIIO_NOEXCEPT { - if (Rank == 1) { - return offset_type(1); - } else { - offset_type offset; - offset[Rank-1] = 1; - for (int i = int(Rank)-2; i >= 0; --i) - offset[i] = offset[i+1] * m_bounds[i+1]; - return offset; - } - } - OIIO_CONSTEXPR pointer data() const OIIO_NOEXCEPT { return m_data; } - - OIIO_CONSTEXPR T& operator[] (offset_type idx) const { - return VIEW_ACCESS(data(), idx, stride(), Rank); - } - T& at (offset_type idx) const { // FIXME -- should be offset_type - if (! bounds().contains(idx)) - throw (std::out_of_range ("OpenImageIO::array_view::at")); - return VIEW_ACCESS(data(), idx, stride(), Rank); - } - // T& front() const { return m_data[0]; } // FIXME - delete? - // T& back() const { return m_data[size()-1]; } // FIXME - delete? - - // FIXME -- slicing and sectioning - -private: - T * m_data; - bounds_type m_bounds; - - reference VIEW_ACCESS (T* data, const offset_type &idx, - const stride_type &stride, size_t rank=Rank) const { - ptrdiff_t offset = 0; - for (size_t i = 0; i < rank; ++i) - offset += idx[i] * stride[i]; - return data[offset]; - } -}; - - - - -/// array_view_strided : a non-owning, mutable reference to a contiguous -/// array with known length and optionally non-default strides through the -/// data. An array_view_strided is mutable (the values in the array may -/// be modified), whereas an array_view_strided is not mutable. -template -class array_view_strided { - OIIO_STATIC_ASSERT (Rank >= 1); - OIIO_STATIC_ASSERT (is_array::value == false); -public: -#if OIIO_CPLUSPLUS_VERSION >= 11 - static OIIO_CONSTEXPR_OR_CONST size_t rank = Rank; - using offset_type = offset; - using bounds_type = OIIO::bounds; - using stride_type = offset; - using size_type = size_t; - using value_type = T; - using pointer = T*; - using const_pointer = const T*; - using reference = T&; -#else - static const size_t rank = Rank; - typedef offset offset_type; - typedef OIIO::bounds bounds_type; - typedef offset stride_type; - typedef size_t size_type; - typedef T value_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; -#endif - - /// Default ctr -- points to nothing - array_view_strided () : m_data(NULL), m_stride(0) { } - - /// Copy constructor - array_view_strided (const array_view_strided ©) - : m_data(copy.data()), m_bounds(copy.bounds()), m_stride(copy.stride()) {} - - /// Construct from T* and bounds. - array_view_strided (T *data, bounds_type bounds) - : m_data(data), m_bounds(bounds), m_stride(1) { } - - /// Construct from T*, bounds, and stride. - array_view_strided (T *data, bounds_type bounds, stride_type stride) - : m_data(data), m_bounds(bounds), m_stride(stride) { } - - /// Construct from a single T&. - array_view_strided (T &data) : m_data(&data), m_bounds(1), m_stride(1) { } - - /// Construct from a fixed-length C array. Template magic automatically - /// finds the length from the declared type of the array. - template - array_view_strided (T (&data)[N]) : m_data(data), m_bounds(N), m_stride(1) { - DASSERT (Rank == 1); - } - /// Construct from std::vector. - array_view_strided (std::vector &v) - : m_data(v.size() ? &v[0] : NULL), m_bounds(v.size()), m_stride(1) { - DASSERT (Rank == 1); - } - - /// Construct from const std::vector. - /// This turns const std::vector into an array_view (the - /// array_view isn't const, but the data it points to will be). - array_view_strided (const std::vector::type> &v) - : m_data(v.size() ? &v[0] : NULL), m_bounds(v.size()), m_stride(1) { - DASSERT (Rank == 1); - } - - // assignments - array_view_strided& operator= (const array_view_strided ©) { - m_data = copy.data(); - m_bounds = copy.bounds(); - m_stride = copy.stride(); - return *this; - } - - size_type size() const { return m_bounds.size(); } - stride_type stride() const { return m_stride; } - - OIIO_CONSTEXPR T& operator[] (size_type idx) const { - return VIEW_ACCESS(data(), idx, stride(), Rank); - } - const T& at (size_t idx) const { - if (! bounds().contains(idx)) - throw (std::out_of_range ("OpenImageIO::array_view_strided::at")); - return VIEW_ACCESS(data(), idx, stride(), Rank); - } - T& front() const { return m_data[0]; } - T& back() const { return get(size()-1); } - pointer data() const { return m_data; } - bounds_type bounds () const { return m_bounds; } - -private: - T * m_data; - bounds_type m_bounds; - stride_type m_stride; - - reference VIEW_ACCESS (T* data, const offset_type &idx, - const stride_type &stride, size_t rank=Rank) const { - ptrdiff_t offset = 0; - for (size_t i = 0; i < rank; ++i) - offset += idx[i] * stride[i]; - return data[offset]; - } -}; - - - -OIIO_NAMESPACE_END diff --git a/3rdparty/oiio16/include/OpenImageIO/color.h b/3rdparty/oiio16/include/OpenImageIO/color.h deleted file mode 100644 index f0c95648..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/color.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - Copyright 2010 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - -#ifndef OPENIMAGEIO_COLOR_H -#define OPENIMAGEIO_COLOR_H - -#include "export.h" -#include "oiioversion.h" -#include "typedesc.h" - - -OIIO_NAMESPACE_BEGIN - -/// The ColorProcessor encapsulates a baked color transformation, suitable for -/// application to raw pixels, or ImageBuf(s). These are generated using -/// ColorConfig::createColorProcessor, and referenced in ImageBufAlgo -/// (amongst other places) - -class OIIO_API ColorProcessor; - - - -/// Represents the set of all color transformations that are allowed. -/// If OpenColorIO is enabled at build time, this configuration is loaded -/// at runtime, allowing the user to have complete control of all color -/// transformation math. ($OCIO) (See opencolorio.org for details). -/// If OpenColorIO is not enabled at build time, a generic color configuration -/// is provided for minimal color support. -/// -/// NOTE: ColorConfig(s) and ColorProcessor(s) are potentially heavy-weight. -/// Their construction / destruction should be kept to a minimum. - -class OIIO_API ColorConfig -{ -public: - /// Construct a ColorConfig using the named OCIO configuration file, - /// or if filename is empty, to the current color configuration - /// specified by env variable $OCIO. - /// - /// Multiple calls to this are potentially expensive. A ColorConfig - /// should usually be shared by an app for its entire runtime. - ColorConfig (string_view filename = ""); - - ~ColorConfig(); - - /// Reset the config to the named OCIO configuration file, or if - /// filename is empty, to the current color configuration specified - /// by env variable $OCIO. Return true for success, false if there - /// was an error. - /// - /// Multiple calls to this are potentially expensive. A ColorConfig - /// should usually be shared by an app for its entire runtime. - bool reset (string_view filename = ""); - - /// Has an error string occurred? - /// (This will not affect the error state.) - bool error () const; - - /// This routine will return the error string (and clear any error - /// flags). If no error has occurred since the last time geterror() - /// was called, it will return an empty string. - std::string geterror (); - - /// Get the number of ColorSpace(s) defined in this configuration - int getNumColorSpaces() const; - - /// Query the name of the specified ColorSpace. - const char * getColorSpaceNameByIndex (int index) const; - - /// Get the name of the color space representing the named role, - /// or NULL if none could be identified. - const char * getColorSpaceNameByRole (string_view role) const; - - /// Get the data type that OCIO thinks this color space is. The name - /// may be either a color space name or a role. - OIIO::TypeDesc getColorSpaceDataType (string_view name, int *bits) const; - - - /// Get the number of Looks defined in this configuration - int getNumLooks() const; - - /// Query the name of the specified Look. - const char * getLookNameByIndex (int index) const; - - /// Given the specified input and output ColorSpace, construct the - /// processor. It is possible that this will return NULL, if the - /// inputColorSpace doesnt exist, the outputColorSpace doesn't - /// exist, or if the specified transformation is illegal (for - /// example, it may require the inversion of a 3D-LUT, etc). When - /// the user is finished with a ColorProcess, deleteColorProcessor - /// should be called. ColorProcessor(s) remain valid even if the - /// ColorConfig that created them no longer exists. - /// - /// Multiple calls to this are potentially expensive, so you should - /// call once to create a ColorProcessor to use on an entire image - /// (or multiple images), NOT for every scanline or pixel - /// separately! - ColorProcessor* createColorProcessor (string_view inputColorSpace, - string_view outputColorSpace) const; - - /// Given the named look(s), input and output color spaces, - /// construct a color processor that applies an OCIO look - /// transformation. If inverse==true, construct the inverse - /// transformation. The context_key and context_value can - /// optionally be used to establish an extra token/value pair in the - /// OCIO context. - /// - /// It is possible that this will return NULL, if one of the color - /// spaces or the look itself doesnt exist or is not allowed. When - /// the user is finished with a ColorProcess, deleteColorProcessor - /// should be called. ColorProcessor(s) remain valid even if the - /// ColorConfig that created them no longer exists. - /// - /// Multiple calls to this are potentially expensive, so you should - /// call once to create a ColorProcessor to use on an entire image - /// (or multiple images), NOT for every scanline or pixel - /// separately! - ColorProcessor* createLookTransform (string_view looks, - string_view inputColorSpace, - string_view outputColorSpace, - bool inverse=false, - string_view context_key="", - string_view context_value="") const; - - /// Get the number of displays defined in this configuration - int getNumDisplays() const; - - /// Query the name of the specified display. - const char * getDisplayNameByIndex (int index) const; - - /// Get the number of views for a given display defined in this configuration - int getNumViews (string_view display) const; - - /// Query the name of the specified view for the specified display - const char * getViewNameByIndex (string_view display, int index) const; - - /// Query the name of the default display - const char * getDefaultDisplayName() const; - - /// Query the name of the default view for the specified display - const char * getDefaultViewName (string_view display) const; - - /// Construct a processor to transform from the given color space - /// to the color space of the given display and view. You may optionally - /// override the looks that are, by default, used with the display/view - /// combination. Looks is a potentially comma (or colon) delimited list - /// of lookNames, where +/- prefixes are optionally allowed to denote - /// forward/inverse transformation (and forward is assumed in the - /// absence of either). It is possible to remove all looks from the - /// display by passing an empty string. The context_key and context_value - /// can optionally be used to establish an extra token/value pair in the - /// OCIO context. - /// - /// It is possible that this will return NULL, if one of the color - /// spaces or the display or view doesn't exist or is not allowed. When - /// the user is finished with a ColorProcess, deleteColorProcessor - /// should be called. ColorProcessor(s) remain valid even if the - /// ColorConfig that created them no longer exists. - /// - /// Multiple calls to this are potentially expensive, so you should - /// call once to create a ColorProcessor to use on an entire image - /// (or multiple images), NOT for every scanline or pixel - /// separately! - ColorProcessor* createDisplayTransform (string_view display, - string_view view, - string_view inputColorSpace, - string_view looks="", - string_view context_key="", - string_view context_value="") const; - - /// Construct a processor to perform color transforms determined by an - /// OpenColorIO FileTransform. - /// - /// It is possible that this will return NULL, if the FileTransform - /// doesn't exist or is not allowed. When the user is finished with a - /// ColorProcess, deleteColorProcessor should be called. - /// ColorProcessor(s) remain valid even if the ColorConfig that created - /// them no longer exists. - /// - /// Multiple calls to this are potentially expensive, so you should - /// call once to create a ColorProcessor to use on an entire image - /// (or multiple images), NOT for every scanline or pixel - /// separately! - ColorProcessor* createFileTransform (string_view name, - bool inverse=false) const; - - /// Given a string (like a filename), look for the longest, right-most - /// colorspace substring that appears. Returns "" if no such color space - /// is found. (This is just a wrapper around OCIO's - /// ColorConfig::parseColorSpaceFromString.) - string_view parseColorSpaceFromString (string_view str) const; - - /// Delete the specified ColorProcessor - static void deleteColorProcessor(ColorProcessor * processor); - - /// Return if OpenImageIO was built with OCIO support - static bool supportsOpenColorIO(); - -private: - ColorConfig(const ColorConfig &); - ColorConfig& operator= (const ColorConfig &); - - class Impl; - friend class Impl; - Impl * m_impl; - Impl * getImpl() { return m_impl; } - const Impl * getImpl() const { return m_impl; } -}; - - - -/// Utility -- convert sRGB value to linear -/// http://en.wikipedia.org/wiki/SRGB -inline float sRGB_to_linear (float x) -{ - return (x <= 0.04045f) ? (x / 12.92f) - : powf ((x + 0.055f) / 1.055f, 2.4f); -} - -/// Utility -- convert linear value to sRGB -inline float linear_to_sRGB (float x) -{ - if (x < 0.0f) - return 0.0f; - return (x <= 0.0031308f) ? (12.92f * x) - : (1.055f * powf (x, 1.f/2.4f) - 0.055f); -} - - -/// Utility -- convert Rec709 value to linear -/// http://en.wikipedia.org/wiki/Rec._709 -inline float Rec709_to_linear (float x) -{ - if (x < 0.081f) - return (x < 0.0f) ? 0.0f : x * (1.0f/4.5f); - else - return powf ((x + 0.099f) * (1.0f/1.099f), (1.0f/0.45f)); -} - -/// Utility -- convert linear value to Rec709 -inline float linear_to_Rec709 (float x) -{ - if (x < 0.018f) - return (x < 0.0f)? 0.0f : x * 4.5f; - else - return 1.099f * powf(x, 0.45f) - 0.099f; -} - - -OIIO_NAMESPACE_END - -#endif // OPENIMAGEIO_COLOR_H diff --git a/3rdparty/oiio16/include/OpenImageIO/coordinate.h b/3rdparty/oiio16/include/OpenImageIO/coordinate.h deleted file mode 100644 index 5ccb07a2..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/coordinate.h +++ /dev/null @@ -1,519 +0,0 @@ -/* - Copyright 2015 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -#pragma once - -#include -#include -#include - -#include "oiioversion.h" -#include "platform.h" -#include "dassert.h" - -#if OIIO_CPLUSPLUS_VERSION >= 11 -# include -#endif - -OIIO_NAMESPACE_BEGIN - -template class offset; -template class bounds; -template class bounds_iterator; - - - -/// An offset represents a Rank-dimensional offset. Think of it as -/// a generalization of an array index. Underneath, it's a bit like a -/// int[Rank]. - -template -class offset { - OIIO_STATIC_ASSERT (Rank >= 1); -public: - // constants and types -#if OIIO_CPLUSPLUS_VERSION >= 11 - static OIIO_CONSTEXPR_OR_CONST size_t rank = Rank; - using reference = ptrdiff_t&; - using const_reference = const ptrdiff_t&; - using size_type = size_t; - using value_type = ptrdiff_t; -#else - static const size_t rank = Rank; - typedef ptrdiff_t& reference; - typedef const ptrdiff_t& const_reference; - typedef size_t size_type; - typedef ptrdiff_t value_type; -#endif - - /// Default constructor - OIIO_CONSTEXPR14 offset() OIIO_NOEXCEPT { - std::fill (m_ind+0, m_ind+Rank, 0); - } - /// Constructor for 1D case - OIIO_CONSTEXPR14 offset (value_type v) OIIO_NOEXCEPT { - DASSERT (Rank == 1); - m_ind[0] = v; - std::fill (m_ind+1, m_ind+Rank, 1); - } - /// Constructor for 2D case - OIIO_CONSTEXPR14 offset (value_type v0, value_type v1) OIIO_NOEXCEPT { - DASSERT (Rank == 2); - m_ind[0] = v0; - m_ind[1] = v1; - std::fill (m_ind+2, m_ind+Rank, 1); - } -#if OIIO_CPLUSPLUS_VERSION >= 11 - /// Constructor from initializer_list. Only for C++11. - OIIO_CONSTEXPR14 offset (std::initializer_list il) { - DASSERT (il.size() == Rank); - std::copy (il.begin(), il.end(), m_ind+0); - } -#endif - - /// Equality test. - OIIO_CONSTEXPR bool operator== (const offset& rhs) const OIIO_NOEXCEPT { - return std::equal (m_ind+0, m_ind+Rank, rhs.m_ind+0); - } - /// Inequality test. - OIIO_CONSTEXPR bool operator!= (const offset& rhs) const OIIO_NOEXCEPT { - return ! (*this == rhs); - } - - /// Component access - reference operator[](size_type n) { - DASSERT (n < Rank); - return m_ind[n]; - } - OIIO_CONSTEXPR14 const_reference operator[] (size_type n) const { - DASSERT (n < Rank); - return m_ind[n]; - } - - // Arithmetic - OIIO_CONSTEXPR14 offset operator+ (const offset& rhs) const { - offset result; - for (size_t i = 0; i < Rank; ++i) - result[i] = m_ind[i] + rhs[i]; - return result; - } - OIIO_CONSTEXPR14 offset operator- (const offset& rhs) const { - offset result; - for (size_t i = 0; i < Rank; ++i) - result[i] = m_ind[i] - rhs[i]; - return result; - }; - OIIO_CONSTEXPR14 offset& operator+= (const offset& rhs) { - for (size_t i = 0; i < Rank; ++i) - m_ind[i] += rhs[i]; - return *this; - } - OIIO_CONSTEXPR14 offset& operator-= (const offset& rhs) { - for (size_t i = 0; i < Rank; ++i) - m_ind[i] -= rhs[i]; - return *this; - } - - OIIO_CONSTEXPR14 offset& operator++ () { // prefix increment - DASSERT (Rank == 1); - ++m_ind[0]; - return *this; - } - OIIO_CONSTEXPR14 offset operator++ (int) { // postfix increment - DASSERT (Rank == 1); - offset ret; - ++(*this); - return ret; - } - OIIO_CONSTEXPR14 offset& operator-- () { // prefix increment - DASSERT (Rank == 1); - --m_ind[0]; - return *this; - } - OIIO_CONSTEXPR14 offset operator-- (int) { // postfix increment - DASSERT (Rank == 1); - offset ret; - --(*this); - return ret; - } - - OIIO_CONSTEXPR offset operator+ () const OIIO_NOEXCEPT { return *this; } - OIIO_CONSTEXPR14 offset operator- () const { - offset result; - for (size_t i = 0; i < Rank; ++i) - result[i] = -m_ind[i]; - return result; - }; - - OIIO_CONSTEXPR14 offset operator* (value_type v) const { - offset result = *this; - result *= v; - return result; - } - friend OIIO_CONSTEXPR14 offset operator* (value_type v, const offset &off) { - offset result = off; - result *= v; - return result; - } - OIIO_CONSTEXPR14 offset operator/ (value_type v) const { - offset result = *this; - result /= v; - return result; - } - OIIO_CONSTEXPR14 offset& operator*= (value_type v) { - for (size_t i = 0; i < Rank; ++i) - m_ind[i] *= v; - return *this; - } - OIIO_CONSTEXPR14 offset& operator/= (value_type v) { - for (size_t i = 0; i < Rank; ++i) - m_ind[i] /= v; - return *this; - } - friend std::ostream& operator<< (std::ostream& out, const offset& off) { - out << off[0]; - for (size_t i = 1; i < Rank; ++i) - out << ',' << off[i]; - return out; - } -private: - value_type m_ind[Rank]; -}; - - - -/// A bounds represents the size of a Rank-dimensional array. -template -class bounds { - OIIO_STATIC_ASSERT (Rank >= 1); -public: - // constants and types -#if OIIO_CPLUSPLUS_VERSION >= 11 - static OIIO_CONSTEXPR_OR_CONST size_t rank = Rank; - using reference = ptrdiff_t&; - using const_reference = const ptrdiff_t&; - using size_type = size_t; - using value_type = ptrdiff_t; - using iterator = bounds_iterator; - using const_iterator = bounds_iterator; -#else - static const size_t rank = Rank; - typedef ptrdiff_t& reference; - typedef const ptrdiff_t& const_reference; - typedef size_t size_type; - typedef ptrdiff_t value_type; - typedef bounds_iterator iterator; - typedef bounds_iterator const_iterator; -#endif - - /// Default constructor - OIIO_CONSTEXPR14 bounds() OIIO_NOEXCEPT { - std::fill (m_bnd+0, m_bnd+Rank, 0); - } - /// Constructor for 1D case - OIIO_CONSTEXPR14 bounds (value_type v) { - DASSERT (Rank == 1); // only if Rank == 1 - m_bnd[0] = v; - std::fill (m_bnd+1, m_bnd+Rank, 1); - } - /// Constructor for 2D case - OIIO_CONSTEXPR14 bounds (value_type v0, value_type v1) { - DASSERT (Rank == 2); - m_bnd[0] = v0; - m_bnd[1] = v1; - std::fill (m_bnd+2, m_bnd+Rank, 1); - } -#if OIIO_CPLUSPLUS_VERSION >= 11 - /// Constructor from initializer_list. Only for C++11. - OIIO_CONSTEXPR14 bounds (std::initializer_list il) { - DASSERT (il.size() == Rank); - std::copy (il.begin(), il.end(), m_bnd+0); - } -#endif - - OIIO_CONSTEXPR14 size_type size() const OIIO_NOEXCEPT { - size_type r = m_bnd[0]; - for (size_t i = 1; i < Rank; ++i) - r *= m_bnd[i]; - return r; - } - OIIO_CONSTEXPR14 bool contains(const offset& idx) const OIIO_NOEXCEPT { - for (size_t i = 0; i < Rank; ++i) - if (idx[i] < 0 || idx[i] > m_bnd[i]) - return false; - return true; - } - - /// Equality test. - OIIO_CONSTEXPR bool operator== (const bounds& rhs) const OIIO_NOEXCEPT { - return std::equal (m_bnd+0, m_bnd+Rank, rhs.m_bnd+0); - } - /// Inequality test. - OIIO_CONSTEXPR bool operator!= (const bounds& rhs) const OIIO_NOEXCEPT { - return ! (*this == rhs); - } - - // bounds iterators - const_iterator begin() const OIIO_NOEXCEPT { - return const_iterator(*this, offset()); - } - // Return a bounds_iterator that is one-past-the-end of *this. - const_iterator end() const OIIO_NOEXCEPT { - offset off; - off[0] = m_bnd[0]; - return const_iterator (*this, off); - } - - /// Component access - OIIO_CONSTEXPR14 reference operator[] (size_type n) { - DASSERT (n < Rank); - return m_bnd[n]; - } - OIIO_CONSTEXPR14 const_reference operator[] (size_type n) const { - DASSERT (n < Rank); - return m_bnd[n]; - } - - // bounds arithmetic - friend OIIO_CONSTEXPR14 bounds operator+ (const bounds& bnd, const offset& off) { - bounds result; - for (size_t i = 0; i < Rank; ++i) - result[i] = bnd[i] + off[i]; - return result; - } - friend OIIO_CONSTEXPR14 bounds operator+ (const offset& off, const bounds& bnd) { - return bnd + off; - } - friend OIIO_CONSTEXPR14 bounds operator- (const bounds& bnd, const offset& off) { - bounds result; - for (size_t i = 0; i < Rank; ++i) - result[i] = bnd[i] - off[i]; - return result; - } - friend OIIO_CONSTEXPR14 bounds operator- (const offset& off, const bounds& bnd) { - return bnd - off; - } - friend OIIO_CONSTEXPR14 bounds operator* (const bounds& bnd, const value_type v) { - bounds result; - for (size_t i = 0; i < Rank; ++i) - result[i] = bnd[i] * v; - return result; - } - friend OIIO_CONSTEXPR14 bounds operator* (const value_type v, const bounds& bnd) { - return bnd * v; - } - friend OIIO_CONSTEXPR14 bounds operator/ (const bounds& bnd, const value_type v) { - bounds result; - for (size_t i = 0; i < Rank; ++i) - result[i] = bnd[i] / v; - return result; - } - OIIO_CONSTEXPR14 bounds& operator+= (const offset& rhs) { - for (size_t i = 0; i < Rank; ++i) - m_bnd[i] += rhs[i]; - return *this; - } - OIIO_CONSTEXPR14 bounds& operator-= (const offset& rhs) { - for (size_t i = 0; i < Rank; ++i) - m_bnd[i] -= rhs[i]; - return *this; - } - OIIO_CONSTEXPR14 bounds& operator*= (value_type v) { - for (size_t i = 0; i < Rank; ++i) - m_bnd[i] *= v; - return *this; - } - OIIO_CONSTEXPR14 bounds& operator/= (value_type v) { - for (size_t i = 0; i < Rank; ++i) - m_bnd[i] /= v; - return *this; - } - - friend std::ostream& operator<< (std::ostream& out, const bounds& bnd) { - out << bnd[0]; - for (size_t i = 1; i < Rank; ++i) - out << ',' << bnd[i]; - return out; - } - -private: - value_type m_bnd[Rank]; -}; - - - -namespace detail { -template -class bounds_iterator_pointer -{ -public: - explicit bounds_iterator_pointer (offset const& off) : m_off(off) { } - offset const& operator*() const { return m_off; } - offset const* operator->() const { return &m_off; } -private: - offset m_off; -}; -} // end namespace detail - - - -template -class bounds_iterator -{ - OIIO_STATIC_ASSERT (Rank >= 1); -public: -#if OIIO_CPLUSPLUS_VERSION >= 11 - using iterator_category = std::random_access_iterator_tag; - using value_type = offset; - using difference_type = ptrdiff_t; - using pointer = detail::bounds_iterator_pointer; - using reference = const offset; -#else - typedef offset value_type; - typedef ptrdiff_t difference_type; - typedef detail::bounds_iterator_pointer pointer; - typedef const offset reference; -#endif - - explicit bounds_iterator (const bounds &bnd, const offset &off) - : bnd_(bnd), off_(off) - {} - - bool operator== (const bounds_iterator &rhs) const { - return off_ == rhs.off_; - } - bool operator!= (const bounds_iterator &rhs) const { - return ! (*this == rhs); - } - bool operator< (bounds_iterator const& rhs) const { - for (std::size_t i = 0; i < Rank; ++i) { - if (off_[i] < rhs.off_[i]) - return true; - else if (off_[i] > rhs.off_[i]) - return false; - } - return false; - } - bool operator<= (bounds_iterator const& rhs) const { - return !(rhs < *this); - } - bool operator> (bounds_iterator const& rhs) const { - return rhs < *this; - } - bool operator>= (bounds_iterator const& rhs) const { - return !(*this < rhs); - } - - bounds_iterator& operator++() { - for (int i = Rank - 1; i >= 0; --i) { - if (++off_[i] < bnd_[i]) - return *this; - off_[i] = 0; - } - off_[0] = bnd_[0]; - return *this; - } - - bounds_iterator operator++ (int) { - bounds_iterator r(*this); - ++(*this); - return r; - } - - bounds_iterator& operator--() { - for (int i = int(Rank) - 1; i >= 0; --i) { - if (--off_[i] >= 0) - return *this; - off_[i] = bnd_[i] - 1; - } - // off_[Rank - 1] == -1; - return *this; - } - - bounds_iterator operator-- (int) { - bounds_iterator r(*this); - --(*this); - return r; - } - - bounds_iterator operator+ (difference_type n) const { - return bounds_iterator(*this) += n; - } - - bounds_iterator& operator+= (difference_type n) { - for (int i = Rank - 1; i >= 0 && n != 0; --i) { - std::ptrdiff_t nx = off_[i] + n; - if (nx >= bnd_[i]) { - n = nx / bnd_[i]; - off_[i] = nx % bnd_[i]; - } else { - off_[i] = nx; - return *this; - } - } - off_[0] = bnd_[0]; - return *this; - } - - bounds_iterator operator- (difference_type n) const { - return bounds_iterator(*this) -= n; - } - - bounds_iterator& operator-= (difference_type n) { - return (*this += (-n)); - } - - difference_type operator- (bounds_iterator const& rhs) const { - difference_type r = 0; - difference_type flat_bounds = 1; - for (int i = Rank - 1; i >= 0; --i) { - r += (off_[i] - rhs.off_[i]) * flat_bounds; - flat_bounds *= bnd_[i]; - } - return r; - } - - reference operator*() const { return off_; } - pointer operator->() const { return pointer(off_); } - reference operator[] (difference_type n) const { return *(*this+n); } - - friend std::ostream& operator<< (std::ostream& out, const bounds_iterator& i) { - return out << i.off_; - } - -private: - bounds bnd_; // exposition only - offset off_; // exposition only -}; - - - -OIIO_NAMESPACE_END diff --git a/3rdparty/oiio16/include/OpenImageIO/dassert.h b/3rdparty/oiio16/include/OpenImageIO/dassert.h deleted file mode 100644 index 33712362..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/dassert.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -#ifndef OPENIMAGEIO_DASSERT_H -#define OPENIMAGEIO_DASSERT_H - -#include -#include - -#include "platform.h" - - -/// \file -/// -/// Handy macros for debugging assertions. -/// -/// - ASSERT (if not already defined) is defined to check if a condition -/// is met, and if not, calls ABORT with an error message -/// indicating the module and line where it occurred. -/// - ASSERT_MSG: like ASSERT, but takes printf-like extra arguments -/// - DASSERT is the same as ASSERT when NDEBUG is not defined but a -/// no-op when not in debug mode. -/// - DASSERT_MSG: like DASSERT, but takes printf-like extra arguments -/// - OIIO_STATIC_ASSERT(cond) : static assertion -/// - OIIO_STATIC_ASSERT_MSG(cond,msg) : static assertion + message -/// -/// The presumed usage is that you want ASSERT for dire conditions that -/// must be checked at runtime even in an optimized build. DASSERT is -/// for checks we should do for debugging, but that we don't want to -/// bother with in a shipping optimized build. -/// -/// In both cases, these are NOT a substitute for actual error checking -/// and recovery! Never ASSERT or DASSERT to check invalid user input, -/// for example. They should be used only to verify that there aren't -/// errors in the *code* that are so severe that there is no point even -/// trying to recover gracefully. - - -/// ASSERT(condition) checks if the condition is met, and if not, prints -/// an error message indicating the module and line where the error -/// occurred and then aborts. - -#ifndef ASSERT -# define ASSERT(x) \ - (OIIO_LIKELY(x) ? ((void)0) \ - : (fprintf (stderr, "%s:%u: failed assertion '%s'\n", \ - __FILE__, __LINE__, #x), abort())) -#endif - -/// ASSERT_MSG(condition,msg,...) is like ASSERT, but lets you add -/// formatted output (a la printf) to the failure message. -#ifndef ASSERT_MSG -# define ASSERT_MSG(x,msg,...) \ - (OIIO_LIKELY(x) ? ((void)0) \ - : (fprintf (stderr, "%s:%u: failed assertion '%s': " msg "\n", \ - __FILE__, __LINE__, #x, __VA_ARGS__), abort())) -#endif - -#ifndef ASSERTMSG -#define ASSERTMSG ASSERT_MSG -#endif - - -/// DASSERT(condition) is just like ASSERT, except that it only is -/// functional in DEBUG mode, but does nothing when in a non-DEBUG -/// (optimized, shipping) build. -#ifndef NDEBUG -# define DASSERT(x) ASSERT(x) -#else - /* DASSERT does nothing when not debugging; sizeof trick prevents warnings */ -# define DASSERT(x) ((void)sizeof(x)) -#endif - -/// DASSERT_MSG(condition,msg,...) is just like ASSERT_MSG, except that it -/// only is functional in DEBUG mode, but does nothing when in a -/// non-DEBUG (optimized, shipping) build. -#ifndef NDEBUG -# define DASSERT_MSG ASSERT_MSG -#else -# define DASSERT_MSG(x,...) ((void)sizeof(x)) /* does nothing when not debugging */ -#endif - -#ifndef DASSERTMSG -#define DASSERTMSG DASSERT_MSG -#endif - - - -/// Define OIIO_STATIC_ASSERT and OIIO_STATIC_ASSERT_MSG as wrappers around -/// static_assert and static_assert_msg, with appropriate fallbacks for -/// older C++ standards. -#if (__cplusplus >= 201700L) /* FIXME - guess the token, fix when C++17 */ -# define OIIO_STATIC_ASSERT(cond) static_assert(cond) -# define OIIO_STATIC_ASSERT_MSG(cond,msg) static_assert(cond,msg) -#elif (__cplusplus >= 201103L) -# define OIIO_STATIC_ASSERT(cond) static_assert(cond,"") -# define OIIO_STATIC_ASSERT_MSG(cond,msg) static_assert(cond,msg) -#else /* FIXME(C++11): this case can go away when C++11 is our minimum */ -# include -# define OIIO_STATIC_ASSERT(cond) BOOST_STATIC_ASSERT(cond) -# define OIIO_STATIC_ASSERT_MSG(cond,msg) BOOST_STATIC_ASSERT_MSG(cond,msg) -#endif - - -#endif // OPENIMAGEIO_DASSERT_H diff --git a/3rdparty/oiio16/include/OpenImageIO/errorhandler.h b/3rdparty/oiio16/include/OpenImageIO/errorhandler.h deleted file mode 100644 index dfa6af22..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/errorhandler.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - Copyright 2009 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -#ifndef OPENIMAGEIO_ERRORMANAGER_H -#define OPENIMAGEIO_ERRORMANAGER_H - -#include - -#include "export.h" -#include "oiioversion.h" -#include "strutil.h" - - -OIIO_NAMESPACE_BEGIN - -/// ErrorHandler is a simple class that accepts error messages -/// (classified as errors, severe errors, warnings, info, messages, or -/// debug output) and handles them somehow. By default it just prints -/// the messages to stdout and/or stderr (and supresses some based on a -/// "verbosity" level). -/// -/// The basic idea is that your library code has no idea whether some -/// application that will use it someday will want errors or other -/// output to be sent to the console, go to a log file, be intercepted -/// by the calling application, or something else. So you punt, by -/// having your library take a pointer to an ErrorHandler, passed in -/// from the calling app (and possibly subclassed to have arbitrarily -/// different behavior from the default console output) and make all -/// error-like output via the ErrorHandler*. -/// -class OIIO_API ErrorHandler { -public: - /// Error categories. We use broad categories in the high order bits. - /// A library may just use these categories, or may create individual - /// error codes as long as they have the right high bits to designate - /// their category (file not found = ERROR + 1, etc.). - enum ErrCode { - EH_NO_ERROR = 0, // never sent to handler - EH_MESSAGE = 0 << 16, - EH_INFO = 1 << 16, - EH_WARNING = 2 << 16, - EH_ERROR = 3 << 16, - EH_SEVERE = 4 << 16, - EH_DEBUG = 5 << 16 - }; - - /// VerbosityLevel controls how much detail the calling app wants. - /// - enum VerbosityLevel { - QUIET = 0, ///< Show MESSAGE, SEVERE, ERROR only - NORMAL = 1, ///< Show MESSAGE, SEVERE, ERROR, WARNING - VERBOSE = 2 ///< Like NORMAL, but also show INFO - }; - - ErrorHandler () : m_verbosity(NORMAL) { } - virtual ~ErrorHandler () { } - - /// The main (or "full detail") method -- takes a code (with high - /// bits being an ErrCode) and writes the message, with a prefix - /// indicating the error category (no prefix for "MESSAGE") and - /// error string. - virtual void operator () (int errcode, const std::string &msg); - - /// Info message with printf-like formatted error message. - /// Will not print unless verbosity >= VERBOSE. - void info (const char *format, ...) OPENIMAGEIO_PRINTF_ARGS(2,3); - - /// Warning message with printf-like formatted error message. - /// Will not print unless verbosity >= NORMAL (i.e. will suppress - /// for QUIET). - void warning (const char *format, ...) OPENIMAGEIO_PRINTF_ARGS(2,3); - - /// Error message with printf-like formatted error message. - /// Will print regardless of verbosity. - void error (const char *format, ...) OPENIMAGEIO_PRINTF_ARGS(2,3); - - /// Severe error message with printf-like formatted error message. - /// Will print regardless of verbosity. - void severe (const char *format, ...) OPENIMAGEIO_PRINTF_ARGS(2,3); - - /// Prefix-less message with printf-like formatted error message. - /// Will not print if verbosity is QUIET. Also note that unlike - /// the other routines, message() will NOT append a newline. - void message (const char *format, ...) OPENIMAGEIO_PRINTF_ARGS(2,3); - - /// Debugging message with printf-like formatted error message. - /// This will not produce any output if not in DEBUG mode, or - /// if verbosity is QUIET. -#ifndef NDEBUG - void debug (const char *format, ...) OPENIMAGEIO_PRINTF_ARGS(2,3); -#else - void debug (const char * /*format*/, ...) OPENIMAGEIO_PRINTF_ARGS(2,3) { } -#endif - - void vInfo (const char *format, va_list argptr); - void vWarning (const char *format, va_list argptr); - void vError (const char *format, va_list argptr); - void vSevere (const char *format, va_list argptr); - void vMessage (const char *format, va_list argptr); -#ifndef NDEBUG - void vDebug (const char *format, va_list argptr); -#else - void vDebug (const char *, va_list) { } -#endif - - void info (const std::string &msg) { (*this)(EH_INFO, msg); } - void warning (const std::string &msg) { (*this)(EH_WARNING, msg); } - void error (const std::string &msg) { (*this)(EH_ERROR, msg); } - void severe (const std::string &msg) { (*this)(EH_SEVERE, msg); } - void message (const std::string &msg) { (*this)(EH_MESSAGE, msg); } -#ifndef NDEBUG - void debug (const std::string &msg) { (*this)(EH_DEBUG, msg); } -#else - void debug (const std::string &) { } -#endif - - /// Set desired verbosity level. - /// - void verbosity (int v) { m_verbosity = v; } - - /// Return the current verbosity level. - /// - int verbosity () const { return m_verbosity; } - - /// One built-in handler that can always be counted on to be present - /// and just echoes the error messages to the console (stdout or - /// stderr, depending on the error category). - static ErrorHandler & default_handler (); - -private: - int m_verbosity; -}; - -OIIO_NAMESPACE_END - -#endif /* !defined(OPENIMAGEIO_ERRORMANAGER_H) */ diff --git a/3rdparty/oiio16/include/OpenImageIO/export.h b/3rdparty/oiio16/include/OpenImageIO/export.h deleted file mode 100644 index 31e4462e..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/export.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -#ifndef OPENIMAGEIO_EXPORT_H -#define OPENIMAGEIO_EXPORT_H - -/// \file -/// Macros necessary for proper symbol export from dynamic libraries. - - -/// -/// On Windows, when compiling code that will end up in a DLL, symbols -/// must be marked as 'exported' (i.e. __declspec(dllexport)) or they -/// won't be visible to programs linking against the DLL. -/// -/// In addition, when compiling the application code that calls the DLL, -/// if a routine is marked as 'imported' (i.e. __declspec(dllimport)), -/// the compiler can be smart about eliminating a level of calling -/// indirection. But you DON'T want to use __declspec(dllimport) when -/// calling a function from within its own DLL (it will still compile -/// correctly, just not with maximal efficiency). Which is quite the -/// dilemma since the same header file is used by both the library and -/// its clients. Sheesh! -/// -/// But on Linux/OSX as well, we want to only have the DSO export the -/// symbols we designate as the public interface. So we link with -/// -fvisibility=hidden to default to hiding the symbols. See -/// http://gcc.gnu.org/wiki/Visibility -/// -/// We solve this awful mess by defining these macros: -/// -/// OIIO_API - used for the OpenImageIO public API. Normally, assumes -/// that it's being seen by a client of the library, and -/// therefore declare as 'imported'. But if -/// OpenImageIO_EXPORT is defined (as is done by CMake -/// when compiling the library itself), change the -/// declaration to 'exported'. -/// OIIO_EXPORT - explicitly exports a symbol that isn't part of the -/// public API but still needs to be visible. -/// OIIO_LOCAL - explicitly hides a symbol that might otherwise be -/// exported -/// -/// - -#if defined(_MSC_VER) || defined(__CYGWIN__) - #ifndef OIIO_STATIC_BUILD - #define OIIO_IMPORT __declspec(dllimport) - #define OIIO_EXPORT __declspec(dllexport) - #else - #define OIIO_IMPORT - #define OIIO_EXPORT - #endif - #define OIIO_LOCAL -#else - #if (10000*__GNUC__ + 100*__GNUC_MINOR__ + __GNUC_PATCHLEVEL__) > 40102 - #define OIIO_IMPORT __attribute__ ((visibility ("default"))) - #define OIIO_EXPORT __attribute__ ((visibility ("default"))) - #define OIIO_LOCAL __attribute__ ((visibility ("hidden"))) - #else - #define OIIO_IMPORT - #define OIIO_EXPORT - #define OIIO_LOCAL - #endif -#endif - -#if defined(OpenImageIO_EXPORTS) || defined(OpenImageIO_Util_EXPORTS) -# define OIIO_API OIIO_EXPORT -#else -# define OIIO_API OIIO_IMPORT -#endif - - -// Back compatibility macros (DEPRECATED) -#define DLLPUBLIC OIIO_API -#define DLLEXPORT OIIO_EXPORT - -#endif // OPENIMAGEIO_EXPORT_H diff --git a/3rdparty/oiio16/include/OpenImageIO/filesystem.h b/3rdparty/oiio16/include/OpenImageIO/filesystem.h deleted file mode 100644 index e015cebf..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/filesystem.h +++ /dev/null @@ -1,319 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -/// @file filesystem.h -/// -/// @brief Utilities for dealing with file names and files portably. -/// -/// Some helpful nomenclature: -/// - "filename" - a file or directory name, relative or absolute -/// - "searchpath" - a list of directories separated by ':' or ';'. -/// - - -#ifndef OPENIMAGEIO_FILESYSTEM_H -#define OPENIMAGEIO_FILESYSTEM_H - -#include -#include -#include -#include -#include -#include - -#include "export.h" -#include "oiioversion.h" -#include "string_view.h" - -#if defined(_WIN32) && defined(__GLIBCXX__) -#define OIIO_FILESYSTEM_USE_STDIO_FILEBUF 1 -#include "fstream_mingw.h" -#endif - -OIIO_NAMESPACE_BEGIN - -#if OIIO_FILESYSTEM_USE_STDIO_FILEBUF -// MingW uses GCC to build, but does not support having a wchar_t* passed as argument -// of ifstream::open or ofstream::open. To properly support UTF-8 encoding on MingW we must -// use the __gnu_cxx::stdio_filebuf GNU extension that can be used with _wfsopen and returned -// into a istream which share the same API as ifsteam. The same reasoning holds for ofstream. -typedef basic_ifstream ifstream; -typedef basic_ofstream ofstream; -#else -typedef std::ifstream ifstream; -typedef std::ofstream ofstream; -#endif - -/// @namespace Filesystem -/// -/// @brief Platform-independent utilities for manipulating file names, -/// files, directories, and other file system miscellany. - -namespace Filesystem { - -/// Return the filename (excluding any directories, but including the -/// file extension, if any) of a filepath. -OIIO_API std::string filename (const std::string &filepath); - -/// Return the file extension (including the last '.' if -/// include_dot=true) of a filename or filepath. -OIIO_API std::string extension (const std::string &filepath, - bool include_dot=true); - -/// Return all but the last part of the path, for example, -/// parent_path("foo/bar") returns "foo", and parent_path("foo") -/// returns "". -OIIO_API std::string parent_path (const std::string &filepath); - -/// Replace the file extension of a filename or filepath. Does not alter -/// filepath, just returns a new string. Note that the new_extension -/// should contain a leading '.' dot. -OIIO_API std::string replace_extension (const std::string &filepath, - const std::string &new_extension); - -/// Turn a searchpath (multiple directory paths separated by ':' or ';') -/// into a vector containing each individual directory. If -/// validonly is true, only existing and readable directories will end -/// up in the list. N.B., the directory names will not have trailing -/// slashes. -OIIO_API void searchpath_split (const std::string &searchpath, - std::vector &dirs, - bool validonly = false); - -/// Find the first instance of a filename existing in a vector of -/// directories, returning the full path as a string. If the file is -/// not found in any of the listed directories, return an empty string. -/// If the filename is absolute, the directory list will not be used. -/// If testcwd is true, "." will be tested before the searchpath; -/// otherwise, "." will only be tested if it's explicitly in dirs. If -/// recursive is true, the directories will be searched recursively, -/// finding a matching file in any subdirectory of the directories -/// listed in dirs; otherwise. -OIIO_API std::string searchpath_find (const std::string &filename, - const std::vector &dirs, - bool testcwd = true, - bool recursive = false); - -/// Fill a vector-of-strings with the names of all files contained by -/// directory dirname. If recursive is true, it will return all files -/// below the directory (even in subdirectories), but if recursive is -/// false (the default)If filter_regex is supplied and non-empty, only -/// filenames matching the regular expression will be returned. Return -/// true if ok, false if there was an error (such as dirname not being -/// found or not actually being a directory). -OIIO_API bool get_directory_entries (const std::string &dirname, - std::vector &filenames, - bool recursive = false, - const std::string &filter_regex=std::string()); - -/// Return true if the path is an "absolute" (not relative) path. -/// If 'dot_is_absolute' is true, consider "./foo" absolute. -OIIO_API bool path_is_absolute (const std::string &path, - bool dot_is_absolute=false); - -/// Return true if the file exists. -/// -OIIO_API bool exists (const std::string &path); - - -/// Return true if the file exists and is a directory. -/// -OIIO_API bool is_directory (const std::string &path); - -/// Return true if the file exists and is a regular file. -/// -OIIO_API bool is_regular (const std::string &path); - -/// Create the directory. Return true for success, false for failure and -/// place an error message in err. -OIIO_API bool create_directory (string_view path, std::string &err); -inline bool create_directory (string_view path) { - std::string err; - return create_directory (path, err); -} - -/// Copy a file, directory, or link. It is an error if 'to' already exists. -/// Return true upon success, false upon failure and place an error message -/// in err. -OIIO_API bool copy (string_view from, string_view to, std::string &err); -inline bool copy (string_view from, string_view to) { - std::string err; - return copy (from, to, err); -} - -/// Rename (or move) a file, directory, or link. Return true upon success, -/// false upon failure and place an error message in err. -OIIO_API bool rename (string_view from, string_view to, std::string &err); -inline bool rename (string_view from, string_view to) { - std::string err; - return rename (from, to, err); -} - -/// Remove the file or directory. Return true for success, false for -/// failure and place an error message in err. -OIIO_API bool remove (string_view path, std::string &err); -inline bool remove (string_view path) { - std::string err; - return remove (path, err); -} - -/// Remove the file or directory, including any children (recursively). -/// Return the number of files removed. Place an error message (if -/// applicable in err. -OIIO_API unsigned long long remove_all (string_view path, std::string &err); -inline unsigned long long remove_all (string_view path) { - std::string err; - return remove_all (path, err); -} - -/// Return a directory path where temporary files can be made. -/// -OIIO_API std::string temp_directory_path (); - -/// Return a unique filename suitable for making a temporary file or -/// directory. -OIIO_API std::string unique_path (string_view model="%%%%-%%%%-%%%%-%%%%"); - -/// Version of fopen that can handle UTF-8 paths even on Windows -/// -OIIO_API FILE *fopen (string_view path, string_view mode); - -/// Return the current (".") directory path. -/// -OIIO_API std::string current_path (); - -/// Version of std::ifstream.open that can handle UTF-8 paths -/// -OIIO_API void open (OIIO::ifstream &stream, string_view path, - std::ios_base::openmode mode = std::ios_base::in); - -/// Version of std::ofstream.open that can handle UTF-8 paths -/// -OIIO_API void open (OIIO::ofstream &stream, string_view path, - std::ios_base::openmode mode = std::ios_base::out); - - - -/// Read the entire contents of the named text file and place it in str, -/// returning true on success, false on failure. -OIIO_API bool read_text_file (string_view filename, std::string &str); - -/// Get last modified time of file -/// -OIIO_API std::time_t last_write_time (const std::string& path); - -/// Set last modified time on file -/// -OIIO_API void last_write_time (const std::string& path, std::time_t time); - -/// Ensure command line arguments are UTF-8 everywhere -/// -OIIO_API void convert_native_arguments (int argc, const char *argv[]); - -/// Turn a sequence description string into a vector of integers. -/// The sequence description can be any of the following -/// * A value (e.g., "3") -/// * A value range ("1-10", "10-1", "1-10x3", "1-10y3"): -/// START-FINISH A range, inclusive of start & finish -/// START-FINISHxSTEP A range with step size -/// START-FINISHySTEP The complement of a stepped range, that is, -/// all numbers within the range that would -/// NOT have been selected by 'x'. -/// Note that START may be > FINISH, or STEP may be negative. -/// * Multiple values or ranges, separated by a comma (e.g., "3,4,10-20x2") -/// Retrn true upon success, false if the description was too malformed -/// to generate a sequence. -OIIO_API bool enumerate_sequence (string_view desc, - std::vector &numbers); - -/// Given a pattern (such as "foo.#.tif" or "bar.1-10#.exr"), return a -/// normalized pattern in printf format (such as "foo.%04d.tif") and a -/// framespec (such as "1-10"). -/// -/// If framepadding_override is > 0, it overrides any specific padding amount -/// in the original pattern. -/// -/// Return true upon success, false if the description was too malformed -/// to generate a sequence. -OIIO_API bool parse_pattern (const char *pattern, - int framepadding_override, - std::string &normalized_pattern, - std::string &framespec); - - -/// Given a normalized pattern (such as "foo.%04d.tif") and a list of frame -/// numbers, generate a list of filenames. -/// -/// Return true upon success, false if the description was too malformed -/// to generate a sequence. -OIIO_API bool enumerate_file_sequence (const std::string &pattern, - const std::vector &numbers, - std::vector &filenames); - -/// Given a normalized pattern (such as "foo_%V.%04d.tif") and a list of frame -/// numbers, generate a list of filenames. "views" is list of per-frame -/// views, or empty. In each frame filename, "%V" is replaced with the view, -/// and "%v" is replaced with the first character of the view. -/// -/// Return true upon success, false if the description was too malformed -/// to generate a sequence. -OIIO_API bool enumerate_file_sequence (const std::string &pattern, - const std::vector &numbers, - const std::vector &views, - std::vector &filenames); - -/// Given a normalized pattern (such as "/path/to/foo.%04d.tif") scan the -/// containing directory (/path/to) for matching frame numbers, views and files. -/// "%V" in the pattern matches views, while "%v" matches the first character -/// of each entry in views. -/// -/// Return true upon success, false if the directory doesn't exist or the -/// pattern can't be parsed. -OIIO_API bool scan_for_matching_filenames (const std::string &pattern, - const std::vector &views, - std::vector &frame_numbers, - std::vector &frame_views, - std::vector &filenames); - -/// Given a normalized pattern (such as "/path/to/foo.%04d.tif") scan the -/// containing directory (/path/to) for matching frame numbers and files. -/// -/// Return true upon success, false if the directory doesn't exist or the -/// pattern can't be parsed. -OIIO_API bool scan_for_matching_filenames (const std::string &pattern, - std::vector &numbers, - std::vector &filenames); - -}; // namespace Filesystem - -OIIO_NAMESPACE_END - -#endif // OPENIMAGEIO_FILESYSTEM_H diff --git a/3rdparty/oiio16/include/OpenImageIO/filter.h b/3rdparty/oiio16/include/OpenImageIO/filter.h deleted file mode 100644 index 9ac18533..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/filter.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - All Rights Reserved. - Based on BSD-licensed software Copyright 2004 NVIDIA Corp. - - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -#ifndef OPENIMAGEIO_FILTER_H -#define OPENIMAGEIO_FILTER_H - -#include "oiioversion.h" -#include "export.h" -#include "string_view.h" - - -OIIO_NAMESPACE_BEGIN - -/// Quick structure that describes a filter. -/// -class OIIO_API FilterDesc { -public: - const char *name; ///< name of the filter - int dim; ///< dimensionality: 1 or 2 - float width; ///< Recommended width or window - bool fixedwidth; ///< Is the width the only one that makes sense? - bool scalable; ///< Is it scalable (otherwise, the width is a window)? - bool separable; ///< Is it separable? (only matters if dim==2) -}; - - - -/// Filter1D is the abstract data type for a 1D filter. -/// The filters are NOT expected to have their results normalized. -class OIIO_API Filter1D { -public: - Filter1D (float width) : m_w(width) { } - virtual ~Filter1D (void) { }; - - /// Get the width of the filter - float width (void) const { return m_w; } - - /// Evalutate the filter at an x position (relative to filter center) - virtual float operator() (float x) const = 0; - - /// Return the name of the filter, e.g., "box", "gaussian" - virtual string_view name (void) const = 0; - - /// This static function allocates and returns an instance of the - /// specific filter implementation for the name you provide. - /// Example use: - /// Filter1D *myfilt = Filter1::create ("box", 1); - /// The caller is responsible for deleting it when it's done. - /// If the name is not recognized, return NULL. - static Filter1D *create (string_view filtername, float width); - - /// Destroy a filter that was created with create(). - static void destroy (Filter1D *filt); - - /// Get the number of filters supported. - static int num_filters (); - /// Get the info for a particular index (0..num_filters()-1). - static void get_filterdesc (int filternum, FilterDesc *filterdesc); - -protected: - float m_w; -}; - - - -/// Filter2D is the abstract data type for a 2D filter. -/// The filters are NOT expected to have their results normalized. -class OIIO_API Filter2D { -public: - Filter2D (float width, float height) : m_w(width), m_h(height) { } - virtual ~Filter2D (void) { }; - - /// Get the width of the filter - float width (void) const { return m_w; } - /// Get the height of the filter - float height (void) const { return m_h; } - - /// Is the filter separable? - /// - virtual bool separable () const { return false; } - - /// Evalutate the filter at an x and y position (relative to filter - /// center). - virtual float operator() (float x, float y) const = 0; - - /// Evaluate just the horizontal filter (if separable; for non-separable - /// it just evaluates at (x,0). - virtual float xfilt (float x) const { return (*this)(x,0.0f); } - - /// Evaluate just the vertical filter (if separable; for non-separable - /// it just evaluates at (0,y). - virtual float yfilt (float y) const { return (*this)(0.0f,y); } - - /// Return the name of the filter, e.g., "box", "gaussian" - virtual string_view name (void) const = 0; - - /// This static function allocates and returns an instance of the - /// specific filter implementation for the name you provide. - /// Example use: - /// Filter2D *myfilt = Filter2::create ("box", 1, 1); - /// The caller is responsible for deleting it when it's done. - /// If the name is not recognized, return NULL. - static Filter2D *create (string_view filtername, - float width, float height); - - /// Destroy a filter that was created with create(). - static void destroy (Filter2D *filt); - - /// Get the number of filters supported. - static int num_filters (); - /// Get the info for a particular index (0..num_filters()-1). - static void get_filterdesc (int filternum, FilterDesc *filterdesc); - -protected: - float m_w, m_h; -}; - - -OIIO_NAMESPACE_END - -#endif // OPENIMAGEIO_FILTER_H diff --git a/3rdparty/oiio16/include/OpenImageIO/fmath.h b/3rdparty/oiio16/include/OpenImageIO/fmath.h deleted file mode 100644 index 8302ae09..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/fmath.h +++ /dev/null @@ -1,1438 +0,0 @@ -/* - Copyright 2008-2014 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) - - A few bits here are based upon code from NVIDIA that was also released - under the same modified BSD license, and marked as: - Copyright 2004 NVIDIA Corporation. All Rights Reserved. - - Some parts of this file were first open-sourced in Open Shading Language, - then later moved here. The original copyright notice was: - Copyright (c) 2009-2014 Sony Pictures Imageworks Inc., et al. - - Many of the math functions were copied from or inspired by other - public domain sources or open source packages with compatible licenses. - The individual functions give references were applicable. -*/ - - -/// \file -/// -/// A variety of floating-point math helper routines (and, slight -/// misnomer, some int stuff as well). -/// - - -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "oiioversion.h" /* Just for the OIIO_NAMESPACE stuff */ -#include "platform.h" -#include "dassert.h" -#include "missing_math.h" - - -OIIO_NAMESPACE_BEGIN - - -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -// -// INTEGER HELPER FUNCTIONS -// -// A variety of handy functions that operate on integers. -// - -/// Quick test for whether an integer is a power of 2. -/// -template -inline bool -ispow2 (T x) -{ - // Numerous references for this bit trick are on the web. The - // principle is that x is a power of 2 <=> x == 1< x-1 is - // all 1 bits for bits < b. - return (x & (x-1)) == 0 && (x >= 0); -} - - - -/// Round up to next higher power of 2 (return x if it's already a power -/// of 2). -inline int -pow2roundup (int x) -{ - // Here's a version with no loops. - if (x < 0) - return 0; - // Subtract 1, then round up to a power of 2, that way if we are - // already a power of 2, we end up with the same number. - --x; - // Make all bits past the first 1 also be 1, i.e. 0001xxxx -> 00011111 - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - // Now we have 2^n-1, by adding 1, we make it a power of 2 again - return x+1; -} - - - -/// Round down to next lower power of 2 (return x if it's already a power -/// of 2). -inline int -pow2rounddown (int x) -{ - // Make all bits past the first 1 also be 1, i.e. 0001xxxx -> 00011111 - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - // Strip off all but the high bit, i.e. 00011111 -> 00010000 - // That's the power of two <= the original x - return x & ~(x >> 1); -} - - - -/// Round up to the next whole multiple of m. -/// -inline int -round_to_multiple (int x, int m) -{ - return ((x + m - 1) / m) * m; -} - - - -/// Round up to the next whole multiple of m, for the special case where -/// m is definitely a power of 2 (somewhat simpler than the more general -/// round_to_multiple). This is a template that should work for any -// integer type. -template -inline T -round_to_multiple_of_pow2 (T x, T m) -{ - DASSERT (ispow2 (m)); - return (x + m - 1) & (~(m-1)); -} - - - -/// Multiply two unsigned 32-bit ints safely, carefully checking for -/// overflow, and clamping to uint32_t's maximum value. -inline uint32_t -clamped_mult32 (uint32_t a, uint32_t b) -{ - const uint32_t Err = std::numeric_limits::max(); - uint64_t r = (uint64_t)a * (uint64_t)b; // Multiply into a bigger int - return r < Err ? (uint32_t)r : Err; -} - - - -/// Multiply two unsigned 64-bit ints safely, carefully checking for -/// overflow, and clamping to uint64_t's maximum value. -inline uint64_t -clamped_mult64 (uint64_t a, uint64_t b) -{ - uint64_t ab = a*b; - if (b && ab/b != a) - return std::numeric_limits::max(); - else - return ab; -} - - - -/// Bitwise circular rotation left by k bits (for 32 bit unsigned integers) -OIIO_FORCEINLINE uint32_t rotl32 (uint32_t x, int k) { - return (x<>(32-k)); -} - -/// Bitwise circular rotation left by k bits (for 64 bit unsigned integers) -OIIO_FORCEINLINE uint64_t rotl64 (uint64_t x, int k) { - return (x<>(64-k)); -} - - -// (end of integer helper functions) -//////////////////////////////////////////////////////////////////////////// - - - - -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -// -// FLOAT UTILITY FUNCTIONS -// -// Helper/utility functions: clamps, blends, interpolations... -// - - -/// clamp a to bounds [low,high]. -template -inline T -clamp (T a, T low, T high) -{ - return (a < low) ? low : ((a > high) ? high : a); -} - - - -/// Multiply and add: (a * b) + c -template -inline T madd (const T& a, const T& b, const T& c) { - // NOTE: in the future we may want to explicitly ask for a fused - // multiply-add in a specialized version for float. - // NOTE2: GCC/ICC will turn this (for float) into a FMA unless - // explicitly asked not to, clang seems to leave the code alone. - return a * b + c; -} - - - -/// Linearly interpolate values v0-v1 at x: v0*(1-x) + v1*x. -/// This is a template, and so should work for any types. -template -inline T -lerp (const T& v0, const T& v1, const Q& x) -{ - // NOTE: a*(1-x) + b*x is much more numerically stable than a+x*(b-a) - return v0*(Q(1)-x) + v1*x; -} - - - -/// Bilinearly interoplate values v0-v3 (v0 upper left, v1 upper right, -/// v2 lower left, v3 lower right) at coordinates (s,t) and return the -/// result. This is a template, and so should work for any types. -template -inline T -bilerp(const T& v0, const T& v1, const T& v2, const T& v3, const Q& s, const Q& t) -{ - // NOTE: a*(t-1) + b*t is much more numerically stable than a+t*(b-a) - Q s1 = Q(1) - s; - return T ((Q(1)-t)*(v0*s1 + v1*s) + t*(v2*s1 + v3*s)); -} - - - -/// Bilinearly interoplate arrays of values v0-v3 (v0 upper left, v1 -/// upper right, v2 lower left, v3 lower right) at coordinates (s,t), -/// storing the results in 'result'. These are all vectors, so do it -/// for each of 'n' contiguous values (using the same s,t interpolants). -template -inline void -bilerp (const T *v0, const T *v1, - const T *v2, const T *v3, - Q s, Q t, int n, T *result) -{ - Q s1 = Q(1) - s; - Q t1 = Q(1) - t; - for (int i = 0; i < n; ++i) - result[i] = T (t1*(v0[i]*s1 + v1[i]*s) + t*(v2[i]*s1 + v3[i]*s)); -} - - - -/// Bilinearly interoplate arrays of values v0-v3 (v0 upper left, v1 -/// upper right, v2 lower left, v3 lower right) at coordinates (s,t), -/// SCALING the interpolated value by 'scale' and then ADDING to -/// 'result'. These are all vectors, so do it for each of 'n' -/// contiguous values (using the same s,t interpolants). -template -inline void -bilerp_mad (const T *v0, const T *v1, - const T *v2, const T *v3, - Q s, Q t, Q scale, int n, T *result) -{ - Q s1 = Q(1) - s; - Q t1 = Q(1) - t; - for (int i = 0; i < n; ++i) - result[i] += T (scale * (t1*(v0[i]*s1 + v1[i]*s) + - t*(v2[i]*s1 + v3[i]*s))); -} - - - -/// Trilinearly interoplate arrays of values v0-v7 (v0 upper left top, v1 -/// upper right top, ...) at coordinates (s,t,r), and return the -/// result. This is a template, and so should work for any types. -template -inline T -trilerp (T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, Q s, Q t, Q r) -{ - // NOTE: a*(t-1) + b*t is much more numerically stable than a+t*(b-a) - Q s1 = Q(1) - s; - Q t1 = Q(1) - t; - Q r1 = Q(1) - r; - return T (r1*(t1*(v0*s1 + v1*s) + t*(v2*s1 + v3*s)) + - r*(t1*(v4*s1 + v5*s) + t*(v6*s1 + v7*s))); -} - - - -/// Trilinearly interoplate arrays of values v0-v7 (v0 upper left top, v1 -/// upper right top, ...) at coordinates (s,t,r), -/// storing the results in 'result'. These are all vectors, so do it -/// for each of 'n' contiguous values (using the same s,t,r interpolants). -template -inline void -trilerp (const T *v0, const T *v1, const T *v2, const T *v3, - const T *v4, const T *v5, const T *v6, const T *v7, - Q s, Q t, Q r, int n, T *result) -{ - Q s1 = Q(1) - s; - Q t1 = Q(1) - t; - Q r1 = Q(1) - r; - for (int i = 0; i < n; ++i) - result[i] = T (r1*(t1*(v0[i]*s1 + v1[i]*s) + t*(v2[i]*s1 + v3[i]*s)) + - r*(t1*(v4[i]*s1 + v5[i]*s) + t*(v6[i]*s1 + v7[i]*s))); -} - - - -/// Trilinearly interoplate arrays of values v0-v7 (v0 upper left top, v1 -/// upper right top, ...) at coordinates (s,t,r), -/// SCALING the interpolated value by 'scale' and then ADDING to -/// 'result'. These are all vectors, so do it for each of 'n' -/// contiguous values (using the same s,t,r interpolants). -template -inline void -trilerp_mad (const T *v0, const T *v1, const T *v2, const T *v3, - const T *v4, const T *v5, const T *v6, const T *v7, - Q s, Q t, Q r, Q scale, int n, T *result) -{ - Q r1 = Q(1) - r; - bilerp_mad (v0, v1, v2, v3, s, t, scale*r1, n, result); - bilerp_mad (v4, v5, v6, v7, s, t, scale*r, n, result); -} - - - -/// Evaluate B-spline weights in w[0..3] for the given fraction. This -/// is an important component of performing a cubic interpolation. -template -inline void evalBSplineWeights (T w[4], T fraction) -{ - T one_frac = 1 - fraction; - w[0] = T(1.0 / 6.0) * one_frac * one_frac * one_frac; - w[1] = T(2.0 / 3.0) - T(0.5) * fraction * fraction * (2 - fraction); - w[2] = T(2.0 / 3.0) - T(0.5) * one_frac * one_frac * (2 - one_frac); - w[3] = T(1.0 / 6.0) * fraction * fraction * fraction; -} - - -/// Evaluate B-spline derivative weights in w[0..3] for the given -/// fraction. This is an important component of performing a cubic -/// interpolation with derivatives. -template -inline void evalBSplineWeightDerivs (T dw[4], T fraction) -{ - T one_frac = 1 - fraction; - dw[0] = -T(0.5) * one_frac * one_frac; - dw[1] = T(0.5) * fraction * (3 * fraction - 4); - dw[2] = -T(0.5) * one_frac * (3 * one_frac - 4); - dw[3] = T(0.5) * fraction * fraction; -} - - - -/// Bicubically interoplate arrays of pointers arranged in a 4x4 pattern -/// with val[0] pointing to the data in the upper left corner, val[15] -/// pointing to the lower right) at coordinates (s,t), storing the -/// results in 'result'. These are all vectors, so do it for each of -/// 'n' contiguous values (using the same s,t interpolants). -template -inline void -bicubic_interp (const T **val, T s, T t, int n, T *result) -{ - for (int c = 0; c < n; ++c) - result[c] = T(0); - T wx[4]; evalBSplineWeights (wx, s); - T wy[4]; evalBSplineWeights (wy, t); - for (int j = 0; j < 4; ++j) { - for (int i = 0; i < 4; ++i) { - T w = wx[i] * wy[j]; - for (int c = 0; c < n; ++c) - result[c] += w * val[j*4+i][c]; - } - } -} - - - -/// Return (x-floor(x)) and put (int)floor(x) in *xint. This is similar -/// to the built-in modf, but returns a true int, always rounds down -/// (compared to modf which rounds toward 0), and always returns -/// frac >= 0 (comapred to modf which can return <0 if x<0). -inline float -floorfrac (float x, int *xint) -{ - // Find the greatest whole number <= x. This cast is faster than - // calling floorf. - int i = (int) x - (x < 0.0f ? 1 : 0); - *xint = i; - return x - static_cast(i); // Return the fraction left over -} - - - -/// Convert degrees to radians. -template -inline T radians (T deg) { return deg * T(M_PI / 180.0); } - -/// Convert radians to degrees -template -inline T degrees (T rad) { return rad * T(180.0 / M_PI); } - - - -inline void -sincos (float x, float* sine, float* cosine) -{ -#if defined(__GNUC__) && defined(__linux__) && !defined(__clang__) - __builtin_sincosf(x, sine, cosine); -#else - *sine = std::sin(x); - *cosine = std::cos(x); -#endif -} - -inline void -sincos (double x, double* sine, double* cosine) -{ -#if defined(__GNUC__) && defined(__linux__) && !defined(__clang__) - __builtin_sincos(x, sine, cosine); -#else - *sine = std::sin(x); - *cosine = std::cos(x); -#endif -} - - -// (end of float helper functions) -//////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -// -// CONVERSION -// -// Type and range conversion helper functions and classes. - - -/// Helper template to let us tell if two types are the same. -template struct is_same { static const bool value = false; }; -template struct is_same { static const bool value = true; }; - - - -template -inline OUT_TYPE bit_cast (const IN_TYPE in) { - // NOTE: this is the only standards compliant way of doing this type of casting, - // luckily the compilers we care about know how to optimize away this idiom. - OUT_TYPE out; - memcpy (&out, &in, sizeof(IN_TYPE)); - return out; -} - - - -/// Change endian-ness of one or more data items that are each 2, 4, -/// or 8 bytes. This should work for any of short, unsigned short, int, -/// unsigned int, float, long long, pointers. -template -inline void -swap_endian (T *f, int len=1) -{ - for (char *c = (char *) f; len--; c += sizeof(T)) { - if (sizeof(T) == 2) { - std::swap (c[0], c[1]); - } else if (sizeof(T) == 4) { - std::swap (c[0], c[3]); - std::swap (c[1], c[2]); - } else if (sizeof(T) == 8) { - std::swap (c[0], c[7]); - std::swap (c[1], c[6]); - std::swap (c[2], c[5]); - std::swap (c[3], c[4]); - } - } -} - - - -/// Multiply src by scale, clamp to [min,max], and round to the nearest D -/// (presumed to be integer). This is just a helper for the convert_type -/// templates, it probably has no other use. -template -inline D -scaled_conversion (const S &src, F scale, F min, F max) -{ - if (std::numeric_limits::is_signed) { - F s = src * scale; - s += (s < 0 ? (F)-0.5 : (F)0.5); - return (D) clamp (s, min, max); - } else { - return (D) clamp ((F)src * scale + (F)0.5, min, max); - } -} - - - -/// Convert n consecutive values from the type of S to the type of D. -/// The conversion is not a simple cast, but correctly remaps the -/// 0.0->1.0 range from and to the full positive range of integral -/// types. Take a memcpy shortcut if both types are the same and no -/// conversion is necessary. Optional arguments can give nonstandard -/// quantizations. -// -// FIXME: make table-based specializations for common types with only a -// few possible src values (like unsigned char -> float). -template -void convert_type (const S *src, D *dst, size_t n, D _zero=0, D _one=1, - D _min=std::numeric_limits::min(), - D _max=std::numeric_limits::max()) -{ - if (is_same::value) { - // They must be the same type. Just memcpy. - memcpy (dst, src, n*sizeof(D)); - return; - } - typedef double F; - F scale = std::numeric_limits::is_integer ? - ((F)1.0)/std::numeric_limits::max() : (F)1.0; - if (std::numeric_limits::is_integer) { - // Converting to an integer-like type. - F min = (F)_min; // std::numeric_limits::min(); - F max = (F)_max; // std::numeric_limits::max(); - scale *= _max; - // Unroll loop for speed - for ( ; n >= 16; n -= 16) { - *dst++ = scaled_conversion (*src++, scale, min, max); - *dst++ = scaled_conversion (*src++, scale, min, max); - *dst++ = scaled_conversion (*src++, scale, min, max); - *dst++ = scaled_conversion (*src++, scale, min, max); - *dst++ = scaled_conversion (*src++, scale, min, max); - *dst++ = scaled_conversion (*src++, scale, min, max); - *dst++ = scaled_conversion (*src++, scale, min, max); - *dst++ = scaled_conversion (*src++, scale, min, max); - *dst++ = scaled_conversion (*src++, scale, min, max); - *dst++ = scaled_conversion (*src++, scale, min, max); - *dst++ = scaled_conversion (*src++, scale, min, max); - *dst++ = scaled_conversion (*src++, scale, min, max); - *dst++ = scaled_conversion (*src++, scale, min, max); - *dst++ = scaled_conversion (*src++, scale, min, max); - *dst++ = scaled_conversion (*src++, scale, min, max); - *dst++ = scaled_conversion (*src++, scale, min, max); - } - while (n--) - *dst++ = scaled_conversion (*src++, scale, min, max); - } else { - // Converting to a float-like type, so we don't need to remap - // the range - // Unroll loop for speed - for ( ; n >= 16; n -= 16) { - *dst++ = (D)((*src++) * scale); - *dst++ = (D)((*src++) * scale); - *dst++ = (D)((*src++) * scale); - *dst++ = (D)((*src++) * scale); - *dst++ = (D)((*src++) * scale); - *dst++ = (D)((*src++) * scale); - *dst++ = (D)((*src++) * scale); - *dst++ = (D)((*src++) * scale); - *dst++ = (D)((*src++) * scale); - *dst++ = (D)((*src++) * scale); - *dst++ = (D)((*src++) * scale); - *dst++ = (D)((*src++) * scale); - *dst++ = (D)((*src++) * scale); - *dst++ = (D)((*src++) * scale); - *dst++ = (D)((*src++) * scale); - *dst++ = (D)((*src++) * scale); - } - while (n--) - *dst++ = (D)((*src++) * scale); - } -} - - - -/// Convert a single value from the type of S to the type of D. -/// The conversion is not a simple cast, but correctly remaps the -/// 0.0->1.0 range from and to the full positive range of integral -/// types. Take a copy shortcut if both types are the same and no -/// conversion is necessary. -template -inline D -convert_type (const S &src) -{ - if (is_same::value) { - // They must be the same type. Just return it. - return (D)src; - } - typedef double F; - F scale = std::numeric_limits::is_integer ? - ((F)1.0)/std::numeric_limits::max() : (F)1.0; - if (std::numeric_limits::is_integer) { - // Converting to an integer-like type. - typedef double F; - F min = (F) std::numeric_limits::min(); - F max = (F) std::numeric_limits::max(); - scale *= max; - return scaled_conversion (src, scale, min, max); - } else { - // Converting to a float-like type, so we don't need to remap - // the range - return (D)((F)src * scale); - } -} - - - -/// Helper function to convert channel values between different bit depths. -/// Roughly equivalent to: -/// -/// out = round (in * (pow (2, TO_BITS) - 1) / (pow (2, FROM_BITS) - 1)); -/// -/// but utilizes an integer math trick for speed. It can be proven that the -/// absolute error of this method is less or equal to 1, with an average error -/// (with respect to the entire domain) below 0.2. -/// -/// It is assumed that the original value is a valid FROM_BITS integer, i.e. -/// shifted fully to the right. -template -inline unsigned int bit_range_convert(unsigned int in) { - unsigned int out = 0; - int shift = TO_BITS - FROM_BITS; - for (; shift > 0; shift -= FROM_BITS) - out |= in << shift; - out |= in >> -shift; - return out; -} - - - -// non-templated version. Slow but general -inline unsigned int -bit_range_convert(unsigned int in, unsigned int FROM_BITS, unsigned int TO_BITS) -{ - unsigned int out = 0; - int shift = TO_BITS - FROM_BITS; - for (; shift > 0; shift -= FROM_BITS) - out |= in << shift; - out |= in >> -shift; - return out; -} - - - -/// A DataProxy looks like an (E &), but it really holds an (I &) -/// and does conversions (via convert_type) as it reads in and out. -/// (I and E are for INTERNAL and EXTERNAL data types, respectively). -template -struct DataProxy { - DataProxy (I &data) : m_data(data) { } - E operator= (E newval) { m_data = convert_type(newval); return newval; } - operator E () const { return convert_type(m_data); } -private: - DataProxy& operator = (const DataProxy&); // Do not implement - I &m_data; -}; - - - -/// A ConstDataProxy looks like a (const E &), but it really holds -/// a (const I &) and does conversions (via convert_type) as it reads. -/// (I and E are for INTERNAL and EXTERNAL data types, respectively). -template -struct ConstDataProxy { - ConstDataProxy (const I &data) : m_data(data) { } - operator E () const { return convert_type(*m_data); } -private: - const I &m_data; -}; - - - -/// A DataArrayProxy looks like an (E *), but it really holds an (I *) -/// and does conversions (via convert_type) as it reads in and out. -/// (I and E are for INTERNAL and EXTERNAL data types, respectively). -template -struct DataArrayProxy { - DataArrayProxy (I *data=NULL) : m_data(data) { } - E operator* () const { return convert_type(*m_data); } - E operator[] (int i) const { return convert_type(m_data[i]); } - DataProxy operator[] (int i) { return DataProxy (m_data[i]); } - void set (I *data) { m_data = data; } - I * get () const { return m_data; } - const DataArrayProxy & operator+= (int i) { - m_data += i; return *this; - } -private: - I *m_data; -}; - - - -/// A ConstDataArrayProxy looks like an (E *), but it really holds an -/// (I *) and does conversions (via convert_type) as it reads in and out. -/// (I and E are for INTERNAL and EXTERNAL data types, respectively). -template -struct ConstDataArrayProxy { - ConstDataArrayProxy (const I *data=NULL) : m_data(data) { } - E operator* () const { return convert_type(*m_data); } - E operator[] (int i) const { return convert_type(m_data[i]); } - void set (const I *data) { m_data = data; } - const I * get () const { return m_data; } - const ConstDataArrayProxy & operator+= (int i) { - m_data += i; return *this; - } -private: - const I *m_data; -}; - - - -/// Fast table-based conversion of 8-bit to other types. Declare this -/// as static to avoid the expensive ctr being called all the time. -template -class EightBitConverter { -public: - EightBitConverter () { init(); } - T operator() (unsigned char c) const { return val[c]; } -private: - T val[256]; - void init () { - float scale = 1.0f / 255.0f; - if (std::numeric_limits::is_integer) - scale *= (float)std::numeric_limits::max(); - for (int i = 0; i < 256; ++i) - val[i] = (T)(i * scale); - } -}; - - - -/// Simple conversion of a (presumably non-negative) float into a -/// rational. This does not attempt to find the simplest fraction -/// that approximates the float, for example 52.83 will simply -/// return 5283/100. This does not attempt to gracefully handle -/// floats that are out of range that could be easily int/int. -inline void -float_to_rational (float f, unsigned int &num, unsigned int &den) -{ - if (f <= 0) { // Trivial case of zero, and handle all negative values - num = 0; - den = 1; - } else if ((int)(1.0/f) == (1.0/f)) { // Exact results for perfect inverses - num = 1; - den = (int)f; - } else { - num = (int)f; - den = 1; - while (fabsf(f-static_cast(num)) > 0.00001f && den < 1000000) { - den *= 10; - f *= 10; - num = (int)f; - } - } -} - - - -/// Simple conversion of a float into a rational. This does not attempt -/// to find the simplest fraction that approximates the float, for -/// example 52.83 will simply return 5283/100. This does not attempt to -/// gracefully handle floats that are out of range that could be easily -/// int/int. -inline void -float_to_rational (float f, int &num, int &den) -{ - unsigned int n, d; - float_to_rational (fabsf(f), n, d); - num = (f >= 0) ? (int)n : -(int)n; - den = (int) d; -} - - -// (end of conversion helpers) -//////////////////////////////////////////////////////////////////////////// - - - - -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -// -// SAFE MATH -// -// The functions named "safe_*" are versions with various internal clamps -// or other deviations from IEEE standards with the specific intent of -// never producing NaN or Inf values or throwing exceptions. But within the -// valid range, they should be full precision and match IEEE standards. -// - - -/// Safe (clamping) sqrt: safe_sqrt(x<0) returns 0, not NaN. -template -inline T safe_sqrt (T x) { - return x >= T(0) ? std::sqrt(x) : T(0); -} - -/// Safe (clamping) inverse sqrt: safe_inversesqrt(x<=0) returns 0. -template -inline T safe_inversesqrt (T x) { - return x > T(0) ? T(1) / std::sqrt(x) : T(0); -} - - -/// Safe (clamping) arcsine: clamp to the valid domain. -template -inline T safe_asin (T x) { - if (x <= T(-1)) return T(-M_PI_2); - if (x >= T(+1)) return T(+M_PI_2); - return std::asin(x); -} - -/// Safe (clamping) arccosine: clamp to the valid domain. -template -inline T safe_acos (T x) { - if (x <= T(-1)) return T(M_PI); - if (x >= T(+1)) return T(0); - return std::acos(x); -} - - -/// Safe log2: clamp to valid domain. -template -inline T safe_log2 (T x) { - // match clamping from fast version - if (x < std::numeric_limits::min()) x = std::numeric_limits::min(); - if (x > std::numeric_limits::max()) x = std::numeric_limits::max(); -#if OIIO_CPLUSPLUS_VERSION >= 11 - return std::log2(x); -#else - return log2f(x); // punt: just use the float one -#endif -} - -/// Safe log: clamp to valid domain. -template -inline T safe_log (T x) { - // slightly different than fast version since clamping happens before scaling - if (x < std::numeric_limits::min()) x = std::numeric_limits::min(); - if (x > std::numeric_limits::max()) x = std::numeric_limits::max(); - return std::log(x); -} - -/// Safe log10: clamp to valid domain. -template -inline T safe_log10 (T x) { - // slightly different than fast version since clamping happens before scaling - if (x < std::numeric_limits::min()) x = std::numeric_limits::min(); - if (x > std::numeric_limits::max()) x = std::numeric_limits::max(); - return log10f(x); -} - -/// Safe logb: clamp to valid domain. -template -inline T safe_logb (T x) { -#if OIIO_CPLUSPLUS_VERSION >= 11 - return (x != T(0)) ? std::logb(x) : -std::numeric_limits::max(); -#else - return (x != T(0)) ? logbf(x) : -std::numeric_limits::max(); -#endif -} - -/// Safe pow: clamp the domain so it never returns Inf or NaN or has divide -/// by zero error. -template -inline T safe_pow (T x, T y) { - if (y == T(0)) return T(1); - if (x == T(0)) return T(0); - // if x is negative, only deal with integer powers - if ((x < T(0)) && (y != floor(y))) return T(0); - // FIXME: this does not match "fast" variant because clamping limits are different - T r = std::pow(x, y); - // Clamp to avoid returning Inf. - const T big = std::numeric_limits::max(); - return clamp (r, -big, big); -} - -// (end of safe_* functions) -//////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -// -// FAST & APPROXIMATE MATH -// -// The functions named "fast_*" provide a set of replacements to libm that -// are much faster at the expense of some accuracy and robust handling of -// extreme values. One design goal for these approximation was to avoid -// branches as much as possible and operate on single precision values only -// so that SIMD versions should be straightforward ports We also try to -// implement "safe" semantics (ie: clamp to valid range where possible) -// natively since wrapping these inline calls in another layer would be -// wasteful. -// -// Some functions are fast_safe_*, which is both a faster approximation as -// well as clamped input domain to ensure no NaN, Inf, or divide by zero. -// - - -/// Round to nearest integer, returning as an int. -inline int fast_rint (float x) { - // used by sin/cos/tan range reduction -#if OIIO_SIMD_SSE >= 4 - // single roundps instruction on SSE4.1+ (for gcc/clang at least) - return static_cast(rintf(x)); -#else - // emulate rounding by adding/substracting 0.5 - return static_cast(x + copysignf(0.5f, x)); -#endif -} - - -inline float fast_sin (float x) { - // very accurate argument reduction from SLEEF - // starts failing around x=262000 - // Results on: [-2pi,2pi] - // Examined 2173837240 values of sin: 0.00662760244 avg ulp diff, 2 max ulp, 1.19209e-07 max error - int q = fast_rint (x * float(M_1_PI)); - float qf = q; - x = madd(qf, -0.78515625f*4, x); - x = madd(qf, -0.00024187564849853515625f*4, x); - x = madd(qf, -3.7747668102383613586e-08f*4, x); - x = madd(qf, -1.2816720341285448015e-12f*4, x); - x = float(M_PI_2) - (float(M_PI_2) - x); // crush denormals - float s = x * x; - if ((q & 1) != 0) x = -x; - // this polynomial approximation has very low error on [-pi/2,+pi/2] - // 1.19209e-07 max error in total over [-2pi,+2pi] - float u = 2.6083159809786593541503e-06f; - u = madd(u, s, -0.0001981069071916863322258f); - u = madd(u, s, +0.00833307858556509017944336f); - u = madd(u, s, -0.166666597127914428710938f); - u = madd(s, u * x, x); - // For large x, the argument reduction can fail and the polynomial can be - // evaluated with arguments outside the valid internal. Just clamp the bad - // values away (setting to 0.0f means no branches need to be generated). - if (fabsf(u) > 1.0f) u = 0.0f; - return u; -} - - -inline float fast_cos (float x) { - // same argument reduction as fast_sin - int q = fast_rint (x * float(M_1_PI)); - float qf = q; - x = madd(qf, -0.78515625f*4, x); - x = madd(qf, -0.00024187564849853515625f*4, x); - x = madd(qf, -3.7747668102383613586e-08f*4, x); - x = madd(qf, -1.2816720341285448015e-12f*4, x); - x = float(M_PI_2) - (float(M_PI_2) - x); // crush denormals - float s = x * x; - // polynomial from SLEEF's sincosf, max error is - // 4.33127e-07 over [-2pi,2pi] (98% of values are "exact") - float u = -2.71811842367242206819355e-07f; - u = madd(u, s, +2.47990446951007470488548e-05f); - u = madd(u, s, -0.00138888787478208541870117f); - u = madd(u, s, +0.0416666641831398010253906f); - u = madd(u, s, -0.5f); - u = madd(u, s, +1.0f); - if ((q & 1) != 0) u = -u; - if (fabsf(u) > 1.0f) u = 0.0f; - return u; -} - -inline void fast_sincos (float x, float* sine, float* cosine) { - // same argument reduction as fast_sin - int q = fast_rint (x * float(M_1_PI)); - float qf = q; - x = madd(qf, -0.78515625f*4, x); - x = madd(qf, -0.00024187564849853515625f*4, x); - x = madd(qf, -3.7747668102383613586e-08f*4, x); - x = madd(qf, -1.2816720341285448015e-12f*4, x); - x = float(M_PI_2) - (float(M_PI_2) - x); // crush denormals - float s = x * x; - // NOTE: same exact polynomials as fast_sin and fast_cos above - if ((q & 1) != 0) x = -x; - float su = 2.6083159809786593541503e-06f; - su = madd(su, s, -0.0001981069071916863322258f); - su = madd(su, s, +0.00833307858556509017944336f); - su = madd(su, s, -0.166666597127914428710938f); - su = madd(s, su * x, x); - float cu = -2.71811842367242206819355e-07f; - cu = madd(cu, s, +2.47990446951007470488548e-05f); - cu = madd(cu, s, -0.00138888787478208541870117f); - cu = madd(cu, s, +0.0416666641831398010253906f); - cu = madd(cu, s, -0.5f); - cu = madd(cu, s, +1.0f); - if ((q & 1) != 0) cu = -cu; - if (fabsf(su) > 1.0f) su = 0.0f; - if (fabsf(cu) > 1.0f) cu = 0.0f; - *sine = su; - *cosine = cu; -} - -// NOTE: this approximation is only valid on [-8192.0,+8192.0], it starts becoming -// really poor outside of this range because the reciprocal amplifies errors -inline float fast_tan (float x) { - // derived from SLEEF implementation - // note that we cannot apply the "denormal crush" trick everywhere because - // we sometimes need to take the reciprocal of the polynomial - int q = fast_rint (x * float(2 * M_1_PI)); - float qf = q; - x = madd(qf, -0.78515625f*2, x); - x = madd(qf, -0.00024187564849853515625f*2, x); - x = madd(qf, -3.7747668102383613586e-08f*2, x); - x = madd(qf, -1.2816720341285448015e-12f*2, x); - if ((q & 1) == 0) - x = float(M_PI_4) - (float(M_PI_4) - x); // crush denormals (only if we aren't inverting the result later) - float s = x * x; - float u = 0.00927245803177356719970703f; - u = madd(u, s, 0.00331984995864331722259521f); - u = madd(u, s, 0.0242998078465461730957031f); - u = madd(u, s, 0.0534495301544666290283203f); - u = madd(u, s, 0.133383005857467651367188f); - u = madd(u, s, 0.333331853151321411132812f); - u = madd(s, u * x, x); - if ((q & 1) != 0) u = -1.0f / u; - return u; -} - -/// Fast, approximate sin(x*M_PI) with maximum absolute error of 0.000918954611. -/// Adapted from http://devmaster.net/posts/9648/fast-and-accurate-sine-cosine#comment-76773 -inline float fast_sinpi (float x) -{ - // Fast trick to strip the integral part off, so our domain is [-1,1] - const float z = x - ((x + 25165824.0f) - 25165824.0f); - const float y = z - z * fabsf(z); - const float Q = 3.10396624f; - const float P = 3.584135056f; // P = 16-4*Q - return y * (Q + P * fabsf(y)); - /* The original article used used inferior constants for Q and P and - * so had max error 1.091e-3. - * - * The optimal value for Q was determined by exhaustive search, minimizing - * the absolute numerical error relative to float(std::sin(double(phi*M_PI))) - * over the interval [0,2] (which is where most of the invocations happen). - * - * The basic idea of this approximation starts with the coarse approximation: - * sin(pi*x) ~= f(x) = 4 * (x - x * abs(x)) - * - * This approximation always _over_ estimates the target. On the otherhand, the - * curve: - * sin(pi*x) ~= f(x) * abs(f(x)) / 4 - * - * always lies _under_ the target. Thus we can simply numerically search for the - * optimal constant to LERP these curves into a more precise approximation. - * After folding the constants together and simplifying the resulting math, we - * end up with the compact implementation below. - * - * NOTE: this function actually computes sin(x * pi) which avoids one or two - * mults in many cases and guarantees exact values at integer periods. - */ -} - -/// Fast approximate cos(x*M_PI) with ~0.1% absolute error. -inline float fast_cospi (float x) -{ - return fast_sinpi (x+0.5f); -} - -inline float fast_acos (float x) { - const float f = fabsf(x); - const float m = (f < 1.0f) ? 1.0f - (1.0f - f) : 1.0f; // clamp and crush denormals - // based on http://www.pouet.net/topic.php?which=9132&page=2 - // 85% accurate (ulp 0) - // Examined 2130706434 values of acos: 15.2000597 avg ulp diff, 4492 max ulp, 4.51803e-05 max error // without "denormal crush" - // Examined 2130706434 values of acos: 15.2007108 avg ulp diff, 4492 max ulp, 4.51803e-05 max error // with "denormal crush" - const float a = sqrtf(1.0f - m) * (1.5707963267f + m * (-0.213300989f + m * (0.077980478f + m * -0.02164095f))); - return x < 0 ? float(M_PI) - a : a; -} - -inline float fast_asin (float x) { - // based on acosf approximation above - // max error is 4.51133e-05 (ulps are higher because we are consistently off by a little amount) - const float f = fabsf(x); - const float m = (f < 1.0f) ? 1.0f - (1.0f - f) : 1.0f; // clamp and crush denormals - const float a = float(M_PI_2) - sqrtf(1.0f - m) * (1.5707963267f + m * (-0.213300989f + m * (0.077980478f + m * -0.02164095f))); - return copysignf(a, x); -} - -inline float fast_atan (float x) { - const float a = fabsf(x); - const float k = a > 1.0f ? 1 / a : a; - const float s = 1.0f - (1.0f - k); // crush denormals - const float t = s * s; - // http://mathforum.org/library/drmath/view/62672.html - // Examined 4278190080 values of atan: 2.36864877 avg ulp diff, 302 max ulp, 6.55651e-06 max error // (with denormals) - // Examined 4278190080 values of atan: 171160502 avg ulp diff, 855638016 max ulp, 6.55651e-06 max error // (crush denormals) - float r = s * madd(0.43157974f, t, 1.0f) / madd(madd(0.05831938f, t, 0.76443945f), t, 1.0f); - if (a > 1.0f) r = 1.570796326794896557998982f - r; - return copysignf(r, x); -} - -inline float fast_atan2 (float y, float x) { - // based on atan approximation above - // the special cases around 0 and infinity were tested explicitly - // the only case not handled correctly is x=NaN,y=0 which returns 0 instead of nan - const float a = fabsf(x); - const float b = fabsf(y); - - const float k = (b == 0) ? 0.0f : ((a == b) ? 1.0f : (b > a ? a / b : b / a)); - const float s = 1.0f - (1.0f - k); // crush denormals - const float t = s * s; - - float r = s * madd(0.43157974f, t, 1.0f) / madd(madd(0.05831938f, t, 0.76443945f), t, 1.0f); - - if (b > a) r = 1.570796326794896557998982f - r; // account for arg reduction - if (bit_cast(x) & 0x80000000u) // test sign bit of x - r = float(M_PI) - r; - return copysignf(r, y); -} - -static inline float fast_log2 (float x) { - // NOTE: clamp to avoid special cases and make result "safe" from large negative values/nans - if (x < std::numeric_limits::min()) x = std::numeric_limits::min(); - if (x > std::numeric_limits::max()) x = std::numeric_limits::max(); - // based on https://github.com/LiraNuna/glsl-sse2/blob/master/source/vec4.h - unsigned bits = bit_cast(x); - int exponent = int(bits >> 23) - 127; - float f = bit_cast((bits & 0x007FFFFF) | 0x3f800000) - 1.0f; - // Examined 2130706432 values of log2 on [1.17549435e-38,3.40282347e+38]: 0.0797524457 avg ulp diff, 3713596 max ulp, 7.62939e-06 max error - // ulp histogram: - // 0 = 97.46% - // 1 = 2.29% - // 2 = 0.11% - float f2 = f * f; - float f4 = f2 * f2; - float hi = madd(f, -0.00931049621349f, 0.05206469089414f); - float lo = madd(f, 0.47868480909345f, -0.72116591947498f); - hi = madd(f, hi, -0.13753123777116f); - hi = madd(f, hi, 0.24187369696082f); - hi = madd(f, hi, -0.34730547155299f); - lo = madd(f, lo, 1.442689881667200f); - return ((f4 * hi) + (f * lo)) + exponent; -} - -inline float fast_log (float x) { - // Examined 2130706432 values of logf on [1.17549435e-38,3.40282347e+38]: 0.313865375 avg ulp diff, 5148137 max ulp, 7.62939e-06 max error - return fast_log2(x) * float(M_LN2); -} - -inline float fast_log10 (float x) { - // Examined 2130706432 values of log10f on [1.17549435e-38,3.40282347e+38]: 0.631237033 avg ulp diff, 4471615 max ulp, 3.8147e-06 max error - return fast_log2(x) * float(M_LN2 / M_LN10); -} - -inline float fast_logb (float x) { - // don't bother with denormals - x = fabsf(x); - if (x < std::numeric_limits::min()) x = std::numeric_limits::min(); - if (x > std::numeric_limits::max()) x = std::numeric_limits::max(); - unsigned bits = bit_cast(x); - return int(bits >> 23) - 127; -} - -inline float fast_exp2 (float x) { - // clamp to safe range for final addition - if (x < -126.0f) x = -126.0f; - if (x > 126.0f) x = 126.0f; - // range reduction - int m = int(x); x -= m; - x = 1.0f - (1.0f - x); // crush denormals (does not affect max ulps!) - // 5th degree polynomial generated with sollya - // Examined 2247622658 values of exp2 on [-126,126]: 2.75764912 avg ulp diff, 232 max ulp - // ulp histogram: - // 0 = 87.81% - // 1 = 4.18% - float r = 1.33336498402e-3f; - r = madd(x, r, 9.810352697968e-3f); - r = madd(x, r, 5.551834031939e-2f); - r = madd(x, r, 0.2401793301105f); - r = madd(x, r, 0.693144857883f); - r = madd(x, r, 1.0f); - // multiply by 2 ^ m by adding in the exponent - // NOTE: left-shift of negative number is undefined behavior - return bit_cast(bit_cast(r) + (unsigned(m) << 23)); -} - -inline float fast_exp (float x) { - // Examined 2237485550 values of exp on [-87.3300018,87.3300018]: 2.6666452 avg ulp diff, 230 max ulp - return fast_exp2(x * float(1 / M_LN2)); -} - - -/// Faster float exp than is in libm, but still 100% accurate -inline float fast_correct_exp (float x) -{ -#if defined(__x86_64__) && defined(__GNU_LIBRARY__) && defined(__GLIBC__ ) && defined(__GLIBC_MINOR__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 16 - // On x86_64, versions of glibc < 2.16 have an issue where expf is - // much slower than the double version. This was fixed in glibc 2.16. - return static_cast(std::exp(static_cast(x))); -#else - return std::exp(x); -#endif -} - - -inline float fast_exp10 (float x) { - // Examined 2217701018 values of exp10 on [-37.9290009,37.9290009]: 2.71732409 avg ulp diff, 232 max ulp - return fast_exp2(x * float(M_LN10 / M_LN2)); -} - -inline float fast_expm1 (float x) { - if (fabsf(x) < 1e-5f) { - x = 1.0f - (1.0f - x); // crush denormals - return madd(0.5f, x * x, x); - } else - return fast_exp(x) - 1.0f; -} - -inline float fast_sinh (float x) { - float a = fabsf(x); - if (a > 1.0f) { - // Examined 53389559 values of sinh on [1,87.3300018]: 33.6886442 avg ulp diff, 178 max ulp - float e = fast_exp(a); - return copysignf(0.5f * e - 0.5f / e, x); - } else { - a = 1.0f - (1.0f - a); // crush denorms - float a2 = a * a; - // degree 7 polynomial generated with sollya - // Examined 2130706434 values of sinh on [-1,1]: 1.19209e-07 max error - float r = 2.03945513931e-4f; - r = madd(r, a2, 8.32990277558e-3f); - r = madd(r, a2, 0.1666673421859f); - r = madd(r * a, a2, a); - return copysignf(r, x); - } -} - -inline float fast_cosh (float x) { - // Examined 2237485550 values of cosh on [-87.3300018,87.3300018]: 1.78256726 avg ulp diff, 178 max ulp - float e = fast_exp(fabsf(x)); - return 0.5f * e + 0.5f / e; -} - -inline float fast_tanh (float x) { - // Examined 4278190080 values of tanh on [-3.40282347e+38,3.40282347e+38]: 3.12924e-06 max error - // NOTE: ulp error is high because of sub-optimal handling around the origin - float e = fast_exp(2.0f * fabsf(x)); - return copysignf(1 - 2 / (1 + e), x); -} - -inline float fast_safe_pow (float x, float y) { - if (y == 0) return 1.0f; // x^0=1 - if (x == 0) return 0.0f; // 0^y=0 - // be cheap & exact for special case of squaring and identity - if (y == 1.0f) - return x; - if (y == 2.0f) - return std::min (x*x, std::numeric_limits::max()); - float sign = 1.0f; - if (x < 0) { - // if x is negative, only deal with integer powers - // powf returns NaN for non-integers, we will return 0 instead - int ybits = bit_cast(y) & 0x7fffffff; - if (ybits >= 0x4b800000) { - // always even int, keep positive - } else if (ybits >= 0x3f800000) { - // bigger than 1, check - int k = (ybits >> 23) - 127; // get exponent - int j = ybits >> (23 - k); // shift out possible fractional bits - if ((j << (23 - k)) == ybits) // rebuild number and check for a match - sign = bit_cast(0x3f800000 | (j << 31)); // +1 for even, -1 for odd - else - return 0.0f; // not integer - } else { - return 0.0f; // not integer - } - } - return sign * fast_exp2(y * fast_log2(fabsf(x))); -} - -inline float fast_erf (float x) -{ - // Examined 1082130433 values of erff on [0,4]: 1.93715e-06 max error - // Abramowitz and Stegun, 7.1.28 - const float a1 = 0.0705230784f; - const float a2 = 0.0422820123f; - const float a3 = 0.0092705272f; - const float a4 = 0.0001520143f; - const float a5 = 0.0002765672f; - const float a6 = 0.0000430638f; - const float a = fabsf(x); - const float b = 1.0f - (1.0f - a); // crush denormals - const float r = madd(madd(madd(madd(madd(madd(a6, b, a5), b, a4), b, a3), b, a2), b, a1), b, 1.0f); - const float s = r * r; // ^2 - const float t = s * s; // ^4 - const float u = t * t; // ^8 - const float v = u * u; // ^16 - return copysignf(1.0f - 1.0f / v, x); -} - -inline float fast_erfc (float x) -{ - // Examined 2164260866 values of erfcf on [-4,4]: 1.90735e-06 max error - // ulp histogram: - // 0 = 80.30% - return 1.0f - fast_erf(x); -} - -inline float fast_ierf (float x) -{ - // from: Approximating the erfinv function by Mike Giles - // to avoid trouble at the limit, clamp input to 1-eps - float a = fabsf(x); if (a > 0.99999994f) a = 0.99999994f; - float w = -fast_log((1.0f - a) * (1.0f + a)), p; - if (w < 5.0f) { - w = w - 2.5f; - p = 2.81022636e-08f; - p = madd(p, w, 3.43273939e-07f); - p = madd(p, w, -3.5233877e-06f ); - p = madd(p, w, -4.39150654e-06f); - p = madd(p, w, 0.00021858087f ); - p = madd(p, w, -0.00125372503f ); - p = madd(p, w, -0.00417768164f ); - p = madd(p, w, 0.246640727f ); - p = madd(p, w, 1.50140941f ); - } else { - w = sqrtf(w) - 3.0f; - p = -0.000200214257f; - p = madd(p, w, 0.000100950558f); - p = madd(p, w, 0.00134934322f ); - p = madd(p, w, -0.00367342844f ); - p = madd(p, w, 0.00573950773f ); - p = madd(p, w, -0.0076224613f ); - p = madd(p, w, 0.00943887047f ); - p = madd(p, w, 1.00167406f ); - p = madd(p, w, 2.83297682f ); - } - return p * x; -} - -// (end of fast* functions) -//////////////////////////////////////////////////////////////////////////// - - - - -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -// -// MISCELLANEOUS NUMERICAL METHODS -// - - -/// Solve for the x for which func(x) == y on the interval [xmin,xmax]. -/// Use a maximum of maxiter iterations, and stop any time the remaining -/// search interval or the function evaluations <= eps. If brack is -/// non-NULL, set it to true if y is in [f(xmin), f(xmax)], otherwise -/// false (in which case the caller should know that the results may be -/// unreliable. Results are undefined if the function is not monotonic -/// on that interval or if there are multiple roots in the interval (it -/// may not converge, or may converge to any of the roots without -/// telling you that there are more than one). -template -T invert (Func &func, T y, T xmin=0.0, T xmax=1.0, - int maxiters=32, T eps=1.0e-6, bool *brack=0) -{ - // Use the Regula Falsi method, falling back to bisection if it - // hasn't converged after 3/4 of the maximum number of iterations. - // See, e.g., Numerical Recipes for the basic ideas behind both - // methods. - T v0 = func(xmin), v1 = func(xmax); - T x = xmin, v = v0; - bool increasing = (v0 < v1); - T vmin = increasing ? v0 : v1; - T vmax = increasing ? v1 : v0; - bool bracketed = (y >= vmin && y <= vmax); - if (brack) - *brack = bracketed; - if (! bracketed) { - // If our bounds don't bracket the zero, just give up, and - // return the approprate "edge" of the interval - return ((y < vmin) == increasing) ? xmin : xmax; - } - if (fabs(v0-v1) < eps) // already close enough - return x; - int rfiters = (3*maxiters)/4; // how many times to try regula falsi - for (int iters = 0; iters < maxiters; ++iters) { - T t; // interpolation factor - if (iters < rfiters) { - // Regula falsi - t = (y-v0)/(v1-v0); - if (t <= T(0) || t >= T(1)) - t = T(0.5); // RF convergence failure -- bisect instead - } else { - t = T(0.5); // bisection - } - x = lerp (xmin, xmax, t); - v = func(x); - if ((v < y) == increasing) { - xmin = x; v0 = v; - } else { - xmax = x; v1 = v; - } - if (fabs(xmax-xmin) < eps || fabs(v-y) < eps) - return x; // converged - } - return x; -} - -// (end miscellaneous numerical methods) -//////////////////////////////////////////////////////////////////////////// - - -// DEPRECATED(1.5) - Some back-compatibility, will remove soon -inline float safe_sqrtf (float x) { return safe_sqrt(x); } -inline float safe_acosf (float x) { return safe_acos(x); } -inline float fast_expf (float x) { return fast_exp(x); } - - - -OIIO_NAMESPACE_END diff --git a/3rdparty/oiio16/include/OpenImageIO/fstream_mingw.h b/3rdparty/oiio16/include/OpenImageIO/fstream_mingw.h deleted file mode 100644 index df5fbe21..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/fstream_mingw.h +++ /dev/null @@ -1,352 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -/// @file fstream_mingw.h -/// -/// @brief Utilities for dealing with fstream on MingW. -/// Basically accepting wchar_t* filenames in the std::ifstream::open function -/// is a Windows MSVC extension and does not work on MingW. This file implements -/// ifstream and ofstream so that they work with UTF-16 filenames. - - -#ifndef OPENIMAGEIO_FSTREAM_MINGW_H -#define OPENIMAGEIO_FSTREAM_MINGW_H - -#include -#include -#include - -#if defined(_WIN32) && defined(__GLIBCXX__) -#include // __gnu_cxx::stdio_filebuf -#include -#include -#include - - -OIIO_NAMESPACE_BEGIN - - -template > -class basic_ifstream -: public std::basic_istream<_CharT, _Traits> -{ -public: - typedef _CharT char_type; - typedef _Traits traits_type; - typedef typename traits_type::int_type int_type; - typedef typename traits_type::pos_type pos_type; - typedef typename traits_type::off_type off_type; - - typedef typename __gnu_cxx::stdio_filebuf stdio_filebuf; - - - basic_ifstream(); - explicit basic_ifstream(const std::wstring& path, std::ios_base::openmode __mode = std::ios_base::in); - - virtual ~basic_ifstream(); - - stdio_filebuf* rdbuf() const; - bool is_open() const; - void open(const std::wstring& path, std::ios_base::openmode __mode = std::ios_base::in); - void close(); - -private: - - void open_internal(const std::wstring& path, std::ios_base::openmode mode); - - stdio_filebuf* __sb_; -}; - -template -inline -basic_ifstream<_CharT, _Traits>::basic_ifstream() -: std::basic_istream(0) -, __sb_(0) -{ -} - - -template -inline -basic_ifstream<_CharT, _Traits>::basic_ifstream(const std::wstring& path, std::ios_base::openmode __mode) -: std::basic_istream(0) -, __sb_(0) -{ - open_internal(path, __mode | std::ios_base::in); -} - -template -inline -basic_ifstream<_CharT, _Traits>::~basic_ifstream() -{ - delete __sb_; -} - - -inline int -ios_open_mode_to_oflag(std::ios_base::openmode mode) -{ - int f = 0; - if (mode & std::ios_base::in) { - f |= _O_RDONLY; - } - if (mode & std::ios_base::out) { - f |= _O_WRONLY; - f |= _O_CREAT; - if (mode & std::ios_base::app) { - f |= _O_APPEND; - } - if (mode & std::ios_base::trunc) { - f |= _O_TRUNC; - } - } - if (mode & std::ios_base::binary) { - f |= _O_BINARY; - } else { - f |= _O_TEXT; - } - return f; -} - -template -inline -void -basic_ifstream<_CharT, _Traits>::open_internal(const std::wstring& path, std::ios_base::openmode mode) -{ - if (is_open()) { - // if the stream is already associated with a file (i.e., it is already open), calling this function fails. - this->setstate(std::ios_base::failbit); - return; - } - int fd; - int oflag = ios_open_mode_to_oflag(mode); - errno_t errcode = _wsopen_s(&fd, path.c_str(), oflag, _SH_DENYNO, _S_IREAD | _S_IWRITE); - if (errcode != 0) { - this->setstate(std::ios_base::failbit); - return; - } - __sb_ = new stdio_filebuf(fd, mode, 1); - if (__sb_ == 0) { - this->setstate(std::ios_base::failbit); - return; - } - // 409. Closing an fstream should clear error state - this->clear(); - assert(__sb_); - - // In init() the rdstate() is set to badbit if __sb_ is NULL and - // goodbit otherwise. The assert afterwards ensures this. - this->init(__sb_); - assert(this->good() && !this->fail()); -} - -template -inline -typename basic_ifstream<_CharT, _Traits>::stdio_filebuf* -basic_ifstream<_CharT, _Traits>::rdbuf() const -{ - return const_cast(__sb_); -} - - -template -inline -bool -basic_ifstream<_CharT, _Traits>::is_open() const -{ - return __sb_ && __sb_->is_open(); -} - - -template -void -basic_ifstream<_CharT, _Traits>::open(const std::wstring& path, std::ios_base::openmode __mode) -{ - open_internal(path, __mode | std::ios_base::in); -} - -template -inline -void -basic_ifstream<_CharT, _Traits>::close() -{ - if (!__sb_) { - return; - } - if (__sb_->close() == 0) - this->setstate(std::ios_base::failbit); - - delete __sb_; - __sb_= 0; - -} - - - -template > -class basic_ofstream -: public std::basic_ostream<_CharT, _Traits> -{ -public: - typedef _CharT char_type; - typedef _Traits traits_type; - typedef typename traits_type::int_type int_type; - typedef typename traits_type::pos_type pos_type; - typedef typename traits_type::off_type off_type; - - typedef typename __gnu_cxx::stdio_filebuf stdio_filebuf; - - - basic_ofstream(); - explicit basic_ofstream(const std::wstring& path, std::ios_base::openmode __mode = std::ios_base::out); - - virtual ~basic_ofstream(); - - stdio_filebuf* rdbuf() const; - bool is_open() const; - void open(const std::wstring& path, std::ios_base::openmode __mode = std::ios_base::out); - void close(); - -private: - - void open_internal(const std::wstring& path, std::ios_base::openmode mode); - - stdio_filebuf* __sb_; -}; - -template -inline -basic_ofstream<_CharT, _Traits>::basic_ofstream() -: std::basic_ostream(0) -, __sb_(0) -{ -} - - -template -inline -basic_ofstream<_CharT, _Traits>::basic_ofstream(const std::wstring& path, std::ios_base::openmode __mode) -: std::basic_ostream(0) -, __sb_(0) -{ - open_internal(path, __mode | std::ios_base::out); -} - -template -inline -basic_ofstream<_CharT, _Traits>::~basic_ofstream() -{ - delete __sb_; -} - - -template -inline -void -basic_ofstream<_CharT, _Traits>::open_internal(const std::wstring& path, std::ios_base::openmode mode) -{ - if (is_open()) { - // if the stream is already associated with a file (i.e., it is already open), calling this function fails. - this->setstate(std::ios_base::failbit); - return; - } - int fd; - int oflag = ios_open_mode_to_oflag(mode); - errno_t errcode = _wsopen_s(&fd, path.c_str(), oflag, _SH_DENYNO, _S_IREAD | _S_IWRITE); - if (errcode != 0) { - this->setstate(std::ios_base::failbit); - return; - } - __sb_ = new stdio_filebuf(fd, mode, 1); - if (__sb_ == 0) { - this->setstate(std::ios_base::failbit); - return; - } - // 409. Closing an fstream should clear error state - this->clear(); - assert(__sb_); - - // In init() the rdstate() is set to badbit if __sb_ is NULL and - // goodbit otherwise. The assert afterwards ensures this. - this->init(__sb_); - assert(this->good() && !this->fail()); -} - - -template -inline -typename basic_ofstream<_CharT, _Traits>::stdio_filebuf* -basic_ofstream<_CharT, _Traits>::rdbuf() const -{ - return const_cast(__sb_); -} - - - -template -inline -bool -basic_ofstream<_CharT, _Traits>::is_open() const -{ - return __sb_ && __sb_->is_open(); -} - - -template -void -basic_ofstream<_CharT, _Traits>::open(const std::wstring& path, std::ios_base::openmode __mode) -{ - open_internal(path, __mode | std::ios_base::out); -} - -template -inline -void -basic_ofstream<_CharT, _Traits>::close() -{ - if (!__sb_) { - return; - } - if (__sb_->close() == 0) - this->setstate(std::ios_base::failbit); - - delete __sb_; - __sb_= 0; -} -// basic_fstream - -OIIO_NAMESPACE_END - - -#endif // #if defined(_WIN32) && defined(__GLIBCXX__) - - -#endif // OPENIMAGEIO_FSTREAM_MINGW_H diff --git a/3rdparty/oiio16/include/OpenImageIO/hash.h b/3rdparty/oiio16/include/OpenImageIO/hash.h deleted file mode 100644 index 831ce16d..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/hash.h +++ /dev/null @@ -1,512 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -/// \file -/// -/// Wrapper so that hash_map and hash_set mean what we want regardless -/// of the compiler. -/// - -#ifndef OPENIMAGEIO_HASH_H -#define OPENIMAGEIO_HASH_H - -#include -#include -#include -#include -#include // for memcpy and memset -#include - -#include "export.h" -#include "oiioversion.h" -#include "fmath.h" /* for endian */ -#include "string_view.h" /* for endian */ - - -OIIO_NAMESPACE_BEGIN - -namespace xxhash { - -// xxhash: http://code.google.com/p/xxhash/ -// It's BSD licensed. - -// DEPRECATED -unsigned int OIIO_API XXH_fast32 (const void* input, int len, - unsigned int seed=1771); - -// DEPRECATED -unsigned int OIIO_API XXH_strong32 (const void* input, int len, - unsigned int seed=1771); - -unsigned int OIIO_API XXH32 (const void* input, size_t length, - unsigned seed=1771); -unsigned long long OIIO_API XXH64 (const void* input, size_t length, - unsigned long long seed=1771); - -inline size_t xxhash (const void* input, size_t length, size_t seed=1771) -{ - return size_t (XXH64 (input, length, (unsigned long long)seed)); -} - -template -inline size_t xxhash (const Str& s, size_t seed=1771) { - assert(sizeof(s[0]) == 1); - return xxhash (s.data(), s.length(), seed); -} - -} // end namespace xxhash - - - - -namespace bjhash { - -// Bob Jenkins "lookup3" hashes: http://burtleburtle.net/bob/c/lookup3.c -// It's in the public domain. - -// Mix up the bits of a, b, and c (changing their values in place). -inline void bjmix (uint32_t &a, uint32_t &b, uint32_t &c) -{ - a -= c; a ^= rotl32(c, 4); c += b; - b -= a; b ^= rotl32(a, 6); a += c; - c -= b; c ^= rotl32(b, 8); b += a; - a -= c; a ^= rotl32(c,16); c += b; - b -= a; b ^= rotl32(a,19); a += c; - c -= b; c ^= rotl32(b, 4); b += a; -} - -// Mix up and combine the bits of a, b, and c (doesn't change them, but -// returns a hash of those three original values). 21 ops -inline uint32_t bjfinal (uint32_t a, uint32_t b, uint32_t c=0xdeadbeef) -{ - c ^= b; c -= rotl32(b,14); - a ^= c; a -= rotl32(c,11); - b ^= a; b -= rotl32(a,25); - c ^= b; c -= rotl32(b,16); - a ^= c; a -= rotl32(c,4); - b ^= a; b -= rotl32(a,14); - c ^= b; c -= rotl32(b,24); - return c; -} - -// Mix up 4 64-bit inputs (non-destructively), and return a 64 bit hash. -// Adapted from http://burtleburtle.net/bob/c/SpookyV2.h 33 ops -inline uint64_t bjfinal64 (uint64_t h0, uint64_t h1, uint64_t h2, uint64_t h3) -{ - h3 ^= h2; h2 = rotl64(h2,15); h3 += h2; - h0 ^= h3; h3 = rotl64(h3,52); h0 += h3; - h1 ^= h0; h0 = rotl64(h0,26); h1 += h0; - h2 ^= h1; h1 = rotl64(h1,51); h2 += h1; - h3 ^= h2; h2 = rotl64(h2,28); h3 += h2; - h0 ^= h3; h3 = rotl64(h3,9); h0 += h3; - h1 ^= h0; h0 = rotl64(h0,47); h1 += h0; - h2 ^= h1; h1 = rotl64(h1,54); h2 += h1; - h3 ^= h2; h2 = rotl64(h2,32); h3 += h2; - h0 ^= h3; h3 = rotl64(h3,25); h0 += h3; - h1 ^= h0; h0 = rotl64(h0,63); h1 += h0; - return h1; -} - -// Standard "lookup3" hash, arbitrary length in bytes. -uint32_t OIIO_API hashlittle (const void *key, size_t length, - uint32_t seed=1771); - -// Hash an array of 32 bit words -- faster than hashlittle if you know -// it's a whole number of 4-byte words. -uint32_t OIIO_API hashword (const uint32_t *key, size_t nwords, - uint32_t seed=1771); - -// Hash a string without pre-known length. We use the Jenkins -// one-at-a-time hash (http://en.wikipedia.org/wiki/Jenkins_hash_function), -// which seems to be a good speed/quality/requirements compromise. -inline size_t -strhash (const char *s) -{ - if (! s) return 0; - unsigned int h = 0; - while (*s) { - h += (unsigned char)(*s); - h += h << 10; - h ^= h >> 6; - ++s; - } - h += h << 3; - h ^= h >> 11; - h += h << 15; - return h; -} - - -// Hash a string_view. We use the Jenkins -// one-at-a-time hash (http://en.wikipedia.org/wiki/Jenkins_hash_function), -// which seems to be a good speed/quality/requirements compromise. -inline size_t -strhash (string_view s) -{ - size_t len = s.length(); - if (! len) return 0; - unsigned int h = 0; - for (size_t i = 0; i < len; ++i) { - h += (unsigned char)(s[i]); - h += h << 10; - h ^= h >> 6; - } - h += h << 3; - h ^= h >> 11; - h += h << 15; - return h; -} - -} // end namespace bjhash - - -namespace murmur { - -// These functions were lifted from the public domain Murmurhash3. We -// don't bother using Murmurhash -- in my tests, it was slower than -// xxhash in all cases, and comparable to bjhash. But these two fmix -// functions are useful for scrambling the bits of a single 32 or 64 bit -// value. - -inline uint32_t fmix (uint32_t h) -{ - h ^= h >> 16; - h *= 0x85ebca6b; - h ^= h >> 13; - h *= 0xc2b2ae35; - h ^= h >> 16; - return h; -} - -inline uint64_t fmix (uint64_t k) -{ - k ^= k >> 33; - k *= 0xff51afd7ed558ccdULL; - k ^= k >> 33; - k *= 0xc4ceb9fe1a85ec53ULL; - k ^= k >> 33; - return k; -} - -} // end namespace murmur - - - -namespace farmhash { - -// Copyright (c) 2014 Google, Inc. -// http://code.google.com/p/farmhash/ -// See OpenImageIO's hashes.cpp for the MIT license for this code. - - -#if defined(FARMHASH_UINT128_T_DEFINED) -inline uint64_t Uint128Low64(const uint128_t x) { - return static_cast(x); -} -inline uint64_t Uint128High64(const uint128_t x) { - return static_cast(x >> 64); -} -inline uint128_t Uint128(uint64_t lo, uint64_t hi) { - return lo + (((uint128_t)hi) << 64); -} -#else -typedef std::pair uint128_t; -inline uint64_t Uint128Low64(const uint128_t x) { return x.first; } -inline uint64_t Uint128High64(const uint128_t x) { return x.second; } -inline uint128_t Uint128(uint64_t lo, uint64_t hi) { return uint128_t(lo, hi); } -#endif - - -// BASIC STRING HASHING - -// Hash function for a byte array. -// May change from time to time, may differ on different platforms, may differ -// depending on NDEBUG. -size_t OIIO_API Hash(const char* s, size_t len); - -// Hash function for a byte array. Most useful in 32-bit binaries. -// May change from time to time, may differ on different platforms, may differ -// depending on NDEBUG. -uint32_t OIIO_API Hash32(const char* s, size_t len); - -// Hash function for a byte array. For convenience, a 32-bit seed is also -// hashed into the result. -// May change from time to time, may differ on different platforms, may differ -// depending on NDEBUG. -uint32_t OIIO_API Hash32WithSeed(const char* s, size_t len, uint32_t seed); - -// Hash 128 input bits down to 64 bits of output. -// Hash function for a byte array. -// May change from time to time, may differ on different platforms, may differ -// depending on NDEBUG. -uint64_t OIIO_API Hash64(const char* s, size_t len); - -// Hash function for a byte array. For convenience, a 64-bit seed is also -// hashed into the result. -// May change from time to time, may differ on different platforms, may differ -// depending on NDEBUG. -uint64_t OIIO_API Hash64WithSeed(const char* s, size_t len, uint64_t seed); - -// Hash function for a byte array. For convenience, two seeds are also -// hashed into the result. -// May change from time to time, may differ on different platforms, may differ -// depending on NDEBUG. -uint64_t OIIO_API Hash64WithSeeds(const char* s, size_t len, - uint64_t seed0, uint64_t seed1); - -// Hash function for a byte array. -// May change from time to time, may differ on different platforms, may differ -// depending on NDEBUG. -uint128_t OIIO_API Hash128(const char* s, size_t len); - -// Hash function for a byte array. For convenience, a 128-bit seed is also -// hashed into the result. -// May change from time to time, may differ on different platforms, may differ -// depending on NDEBUG. -uint128_t OIIO_API Hash128WithSeed(const char* s, size_t len, uint128_t seed); - -// BASIC NON-STRING HASHING - -// This is intended to be a reasonably good hash function. -// May change from time to time, may differ on different platforms, may differ -// depending on NDEBUG. -inline uint64_t Hash128to64(uint128_t x) { - // Murmur-inspired hashing. - const uint64_t kMul = 0x9ddfea08eb382d69ULL; - uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul; - a ^= (a >> 47); - uint64_t b = (Uint128High64(x) ^ a) * kMul; - b ^= (b >> 47); - b *= kMul; - return b; -} - -// FINGERPRINTING (i.e., good, portable, forever-fixed hash functions) - -// Fingerprint function for a byte array. Most useful in 32-bit binaries. -uint32_t OIIO_API Fingerprint32(const char* s, size_t len); - -// Fingerprint function for a byte array. -uint64_t OIIO_API Fingerprint64(const char* s, size_t len); - -// Fingerprint function for a byte array. -uint128_t OIIO_API Fingerprint128(const char* s, size_t len); - -// This is intended to be a good fingerprinting primitive. -// See below for more overloads. -inline uint64_t Fingerprint(uint128_t x) { - // Murmur-inspired hashing. - const uint64_t kMul = 0x9ddfea08eb382d69ULL; - uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul; - a ^= (a >> 47); - uint64_t b = (Uint128High64(x) ^ a) * kMul; - b ^= (b >> 44); - b *= kMul; - b ^= (b >> 41); - b *= kMul; - return b; -} - -// This is intended to be a good fingerprinting primitive. -inline uint64_t Fingerprint(uint64_t x) { - // Murmur-inspired hashing. - const uint64_t kMul = 0x9ddfea08eb382d69ULL; - uint64_t b = x * kMul; - b ^= (b >> 44); - b *= kMul; - b ^= (b >> 41); - b *= kMul; - return b; -} - -#ifndef FARMHASH_NO_CXX_STRING - -// Convenience functions to hash or fingerprint C++ strings. -// These require that Str::data() return a pointer to the first char -// (as a const char*) and that Str::length() return the string's length; -// they work with std::string, for example. - -// Hash function for a byte array. -// May change from time to time, may differ on different platforms, may differ -// depending on NDEBUG. -template -inline size_t Hash(const Str& s) { - assert(sizeof(s[0]) == 1); - return Hash(s.data(), s.length()); -} - -// Hash function for a byte array. Most useful in 32-bit binaries. -// May change from time to time, may differ on different platforms, may differ -// depending on NDEBUG. -template -inline uint32_t Hash32(const Str& s) { - assert(sizeof(s[0]) == 1); - return Hash32(s.data(), s.length()); -} - -// Hash function for a byte array. For convenience, a 32-bit seed is also -// hashed into the result. -// May change from time to time, may differ on different platforms, may differ -// depending on NDEBUG. -template -inline uint32_t Hash32WithSeed(const Str& s, uint32_t seed) { - assert(sizeof(s[0]) == 1); - return Hash32WithSeed(s.data(), s.length(), seed); -} - -// Hash 128 input bits down to 64 bits of output. -// Hash function for a byte array. -// May change from time to time, may differ on different platforms, may differ -// depending on NDEBUG. -template -inline uint64_t Hash64(const Str& s) { - assert(sizeof(s[0]) == 1); - return Hash64(s.data(), s.length()); -} - -// Hash function for a byte array. For convenience, a 64-bit seed is also -// hashed into the result. -// May change from time to time, may differ on different platforms, may differ -// depending on NDEBUG. -template -inline uint64_t Hash64WithSeed(const Str& s, uint64_t seed) { - assert(sizeof(s[0]) == 1); - return Hash64WithSeed(s.data(), s.length(), seed); -} - -// Hash function for a byte array. For convenience, two seeds are also -// hashed into the result. -// May change from time to time, may differ on different platforms, may differ -// depending on NDEBUG. -template -inline uint64_t Hash64WithSeeds(const Str& s, uint64_t seed0, uint64_t seed1) { - assert(sizeof(s[0]) == 1); - return Hash64WithSeeds(s.data(), s.length(), seed0, seed1); -} - -// Hash function for a byte array. -// May change from time to time, may differ on different platforms, may differ -// depending on NDEBUG. -template -inline uint128_t Hash128(const Str& s) { - assert(sizeof(s[0]) == 1); - return Hash128(s.data(), s.length()); -} - -// Hash function for a byte array. For convenience, a 128-bit seed is also -// hashed into the result. -// May change from time to time, may differ on different platforms, may differ -// depending on NDEBUG. -template -inline uint128_t Hash128WithSeed(const Str& s, uint128_t seed) { - assert(sizeof(s[0]) == 1); - return Hash128(s.data(), s.length(), seed); -} - -// FINGERPRINTING (i.e., good, portable, forever-fixed hash functions) - -// Fingerprint function for a byte array. Most useful in 32-bit binaries. -template -inline uint32_t Fingerprint32(const Str& s) { - assert(sizeof(s[0]) == 1); - return Fingerprint32(s.data(), s.length()); -} - -// Fingerprint 128 input bits down to 64 bits of output. -// Fingerprint function for a byte array. -template -inline uint64_t Fingerprint64(const Str& s) { - assert(sizeof(s[0]) == 1); - return Fingerprint64(s.data(), s.length()); -} - -// Fingerprint function for a byte array. -template -inline uint128_t Fingerprint128(const Str& s) { - assert(sizeof(s[0]) == 1); - return Fingerprint128(s.data(), s.length()); -} - -#endif - -} // namespace farmhash - - - - -class CSHA1; // opaque forward declaration - - -/// Class that encapsulates SHA-1 hashing, a crypticographic-strength -/// 160-bit hash function. It's not as fast as our other hashing -/// methods, but has an extremely low chance of having collisions. -class OIIO_API SHA1 { -public: - /// Create SHA1, optionally read data - SHA1 (const void *data=NULL, size_t size=0); - ~SHA1 (); - - /// Append more data - void append (const void *data, size_t size); - /// Append more data from a vector, without thinking about sizes. - template void appendvec (const std::vector &v) { - append (&v[0], v.size()*sizeof(T)); - } - - /// Type for storing the raw bits of the hash - struct Hash { - unsigned char hash[20]; - }; - - /// Get the digest and store it in Hash h. - void gethash (Hash &h); - - /// Get the digest and store it in h (must point to enough storage - /// to accommodate 20 bytes). - void gethash (void *h) { gethash (*(Hash *)h); } - - /// Return the digest as a hex string - std::string digest (); - - /// Roll the whole thing into one functor, return the string digest. - static std::string digest (const void *data, size_t size) { - SHA1 s (data, size); return s.digest(); - } - -private: - CSHA1 *m_csha1; - bool m_final; -}; - - -OIIO_NAMESPACE_END - -#endif // OPENIMAGEIO_HASH_H diff --git a/3rdparty/oiio16/include/OpenImageIO/image_view.h b/3rdparty/oiio16/include/OpenImageIO/image_view.h deleted file mode 100644 index 0775f7c5..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/image_view.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - Copyright 2014 Larry Gritz and the other authors and contributors. - All Rights Reserved. - Based on BSD-licensed software Copyright 2004 NVIDIA Corp. - - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -#pragma once - -#include -#include - -// We're including stdint.h to get int64_t and INT64_MIN. But on some -// platforms, stdint.h only defines them if __STDC_LIMIT_MACROS is defined, -// so we do so. But, oops, if user code included stdint.h before this file, -// and without defining the macro, it may have had ints one and only include -// and not seen the definitions we need, so at least try to make a helpful -// compile-time error in that case. -// And very old MSVC 9 versions don't even have stdint.h. -#if defined(_MSC_VER) && _MSC_VER < 1600 - typedef __int64 int64_t; -#else -# ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS /* needed for some defs in stdint.h */ -# endif -# include -# if ! defined(INT64_MIN) -# error You must define __STDC_LIMIT_MACROS prior to including stdint.h -# endif -#endif - -#include "oiioversion.h" -#include "strided_ptr.h" - - -OIIO_NAMESPACE_BEGIN - - -/// image_view : a non-owning reference to an image-like array (indexed by -/// x, y, z, and channel) with known dimensions and optionally non-default -/// strides (expressed in bytes) through the data. An image_view is -/// mutable (the values in the image may be modified), whereas an -/// image_view is not mutable. -template -class image_view { -public: - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef int64_t stride_t; -#ifdef INT64_MIN - static const stride_t AutoStride = INT64_MIN; -#else - // Some systems don't have INT64_MIN defined. Sheesh. - static const stride_t AutoStride = (-9223372036854775807LL-1); -#endif - - /// Default ctr -- points to nothing - image_view () { init(); } - - /// Copy constructor - image_view (const image_view ©) { - init (copy.m_data, copy.m_nchannels,copy.m_width, copy.m_height, copy.m_depth, - copy.m_chanstride, copy.m_xstride, copy.m_ystride, copy.m_zstride); - } - - /// Construct from T*, dimensions, and (possibly default) strides (in - /// bytes). - image_view (T *data, int nchannels, - int width, int height, int depth=1, - stride_t chanstride=AutoStride, stride_t xstride=AutoStride, - stride_t ystride=AutoStride, stride_t zstride=AutoStride) { - init (data, nchannels, width, height, depth, - chanstride, xstride, ystride, zstride); - } - - /// assignments -- not a deep copy, just make this image_view - /// point to the same data as the operand. - image_view& operator= (const image_view ©) { - init (copy.m_data, copy.m_nchannels,copy.m_width, copy.m_height, copy.m_depth, - copy.m_chanstride, copy.m_xstride, copy.m_ystride, copy.m_zstride); - return *this; - } - - /// iav(x,y,z)returns a strided_ptr for the pixel (x,y,z). The z - /// can be omitted for 2D images. Note than the resulting - /// strided_ptr can then have individual channels accessed with - /// operator[]. - strided_ptr operator() (int x, int y, int z=0) { - return strided_ptr (getptr(0,x,y,z), m_chanstride); - } - - int nchannels() const { return m_nchannels; } - int width() const { return m_width; } - int height() const { return m_height; } - int depth() const { return m_depth; } - - stride_t chanstride() const { return m_chanstride; } - stride_t xstride() const { return m_xstride; } - stride_t ystride() const { return m_ystride; } - stride_t zstride() const { return m_zstride; } - - const T* data() const { return m_data; } - - void clear() { init(); } - -private: - const T * m_data; - int m_nchannels, m_width, m_height, m_depth; - stride_t m_chanstride, m_xstride, m_ystride, m_zstride; - - void init (T *data, int nchannels, - int width, int height, int depth=1, - stride_t chanstride=AutoStride, stride_t xstride=AutoStride, - stride_t ystride=AutoStride, stride_t zstride=AutoStride) { - m_data = data; - m_nchannels = nchannels; - m_width = width; m_height = height; m_depth = depth; - m_chanstride = chanstride != AutoStride ? chanstride : sizeof(T); - m_xstride = xstride != AutoStride ? xstride : m_nchannels * m_chanstride; - m_ystride = ystride != AutoStride ? ystride : m_width * m_xstride; - m_zstride = zstride != AutoStride ? zstride : m_height * m_ystride; - } - - inline T* getptr (int c, int x, int y, int z=0) const { - return (T*)((char *)m_data + - c*m_chanstride + x*m_xstride + - y*m_ystride + z*m_zstride); - } - inline T& get (int c, int x, int y, int z=0) const { - return *getptr (c, x, y, z); - } - -}; - - -OIIO_NAMESPACE_END diff --git a/3rdparty/oiio16/include/OpenImageIO/imagebuf.h b/3rdparty/oiio16/include/OpenImageIO/imagebuf.h deleted file mode 100644 index 1e08c8b0..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/imagebuf.h +++ /dev/null @@ -1,1276 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -/// \file -/// Classes for in-memory storage and simple manipulation of whole images, -/// which uses ImageInput and ImageOutput underneath for the file access. - - -#ifndef OPENIMAGEIO_IMAGEBUF_H -#define OPENIMAGEIO_IMAGEBUF_H - -#if defined(_MSC_VER) -// Ignore warnings about DLL exported classes with member variables that are template classes. -// This happens with the std::vector and std::string protected members of ImageBuf below. -# pragma warning (disable : 4251) -#endif - -#include "imageio.h" -#include "fmath.h" -#include "imagecache.h" -#include "dassert.h" - -#include - - -OIIO_NAMESPACE_BEGIN - -class ImageBuf; - - -/// Helper struct describing a region of interest in an image. -/// The region is [xbegin,xend) x [begin,yend) x [zbegin,zend), -/// with the "end" designators signifying one past the last pixel, -/// a la STL style. -struct ROI { - int xbegin, xend, ybegin, yend, zbegin, zend; - int chbegin, chend; - - /// Default constructor is an undefined region. - /// - ROI () : xbegin(std::numeric_limits::min()), xend(0), - ybegin(0), yend(0), zbegin(0), zend(0), chbegin(0), chend(0) - { } - - /// Constructor with an explicitly defined region. - /// - ROI (int xbegin, int xend, int ybegin, int yend, - int zbegin=0, int zend=1, int chbegin=0, int chend=10000) - : xbegin(xbegin), xend(xend), ybegin(ybegin), yend(yend), - zbegin(zbegin), zend(zend), chbegin(chbegin), chend(chend) - { } - - /// Is a region defined? - bool defined () const { return (xbegin != std::numeric_limits::min()); } - - // Region dimensions. - int width () const { return xend - xbegin; } - int height () const { return yend - ybegin; } - int depth () const { return zend - zbegin; } - - /// Number of channels in the region. Beware -- this defaults to a - /// huge number, and to be meaningful you must consider - /// std::min (imagebuf.nchannels(), roi.nchannels()). - int nchannels () const { return chend - chbegin; } - - /// Total number of pixels in the region. - imagesize_t npixels () const { - if (! defined()) - return 0; - imagesize_t w = width(), h = height(), d = depth(); - return w*h*d; - } - - /// Documentary sugar -- although the static ROI::All() function - /// simply returns the results of the default ROI constructor, it - /// makes it very clear when using as a default function argument - /// that it means "all" of the image. For example, - /// float myfunc (ImageBuf &buf, ROI roi = ROI::All()); - /// Doesn't that make it abundantly clear? - static ROI All () { return ROI(); } - - /// Test equality of two ROIs - friend bool operator== (const ROI &a, const ROI &b) { - return (a.xbegin == b.xbegin && a.xend == b.xend && - a.ybegin == b.ybegin && a.yend == b.yend && - a.zbegin == b.zbegin && a.zend == b.zend && - a.chbegin == b.chbegin && a.chend == b.chend); - } - /// Test inequality of two ROIs - friend bool operator!= (const ROI &a, const ROI &b) { - return (a.xbegin != b.xbegin || a.xend != b.xend || - a.ybegin != b.ybegin || a.yend != b.yend || - a.zbegin != b.zbegin || a.zend != b.zend || - a.chbegin != b.chbegin || a.chend != b.chend); - } - - /// Stream output of the range - friend std::ostream & operator<< (std::ostream &out, const ROI &roi) { - out << roi.xbegin << ' ' << roi.xend << ' ' << roi.ybegin << ' ' - << roi.yend << ' ' << roi.zbegin << ' ' << roi.zend << ' ' - << roi.chbegin << ' ' << roi.chend; - return out; - } -}; - - -/// Union of two regions, the smallest region containing both. -OIIO_API ROI roi_union (const ROI &A, const ROI &B); - -/// Intersection of two regions. -OIIO_API ROI roi_intersection (const ROI &A, const ROI &B); - -/// Return pixel data window for this ImageSpec as a ROI. -OIIO_API ROI get_roi (const ImageSpec &spec); - -/// Return full/display window for this ImageSpec as a ROI. -OIIO_API ROI get_roi_full (const ImageSpec &spec); - -/// Set pixel data window for this ImageSpec to a ROI. -/// Does NOT change the channels of the spec, regardless of newroi. -OIIO_API void set_roi (ImageSpec &spec, const ROI &newroi); - -/// Set full/display window for this ImageSpec to a ROI. -/// Does NOT change the channels of the spec, regardless of newroi. -OIIO_API void set_roi_full (ImageSpec &spec, const ROI &newroi); - - - -class ImageBufImpl; // Opaque pointer - - - -/// An ImageBuf is a simple in-memory representation of a 2D image. It -/// uses ImageInput and ImageOutput underneath for its file I/O, and has -/// simple routines for setting and getting individual pixels, that -/// hides most of the details of memory layout and data representation -/// (translating to/from float automatically). -class OIIO_API ImageBuf { -public: - /// Construct an empty/uninitialized ImageBuf. This is relatively - /// useless until you call reset(). - ImageBuf (); - - /// Construct an ImageBuf to read the named image (at the designated - /// subimage/MIPlevel -- but don't actually read it yet! The image - /// will actually be read when other methods need to access the spec - /// and/or pixels, or when an explicit call to init_spec() or read() is - /// made, whichever comes first. If a non-NULL imagecache is supplied, - /// it will specifiy a custom ImageCache to use; if otherwise, the - /// global/shared ImageCache will be used. - /// If 'config' is not NULL, it points to an ImageSpec giving requests - /// or special instructions to be passed on to the eventual - /// ImageInput::open() call. - explicit ImageBuf (string_view name, int subimage=0, int miplevel=0, - ImageCache *imagecache = NULL, - const ImageSpec *config = NULL); - - /// Construct an ImageBuf to read the named image -- but don't actually - /// read it yet! The image will actually be read when other methods - /// need to access the spec and/or pixels, or when an explicit call to - /// init_spec() or read() is made, whichever comes first. If a non-NULL - /// imagecache is supplied, it will specifiy a custom ImageCache to use; - /// if otherwise, the global/shared ImageCache will be used. - ImageBuf (string_view name, ImageCache *imagecache); - - /// Construct an Imagebuf given a proposed spec describing the image - /// size and type, and allocate storage for the pixels of the image - /// (whose values will be uninitialized). - explicit ImageBuf (const ImageSpec &spec); - - /// Construct an Imagebuf given both a name and a proposed spec - /// describing the image size and type, and allocate storage for - /// the pixels of the image (whose values will be undefined). - ImageBuf (string_view name, const ImageSpec &spec); - - /// Construct an ImageBuf that "wraps" a memory buffer owned by the - /// calling application. It can write pixels to this buffer, but - /// can't change its resolution or data type. - ImageBuf (const ImageSpec &spec, void *buffer); - - /// Construct an ImageBuf that "wraps" a memory buffer owned by the - /// calling application. It can write pixels to this buffer, but - /// can't change its resolution or data type. - ImageBuf (string_view name, const ImageSpec &spec, void *buffer); - - /// Construct a copy of an ImageBuf. - /// - ImageBuf (const ImageBuf &src); - - /// Destructor for an ImageBuf. - /// - ~ImageBuf (); - - /// Description of where the pixels live for this ImageBuf. - enum IBStorage { UNINITIALIZED, // no pixel memory - LOCALBUFFER, // The IB owns the memory - APPBUFFER, // The IB wraps app's memory - IMAGECACHE // Backed by ImageCache - }; - - /// Restore the ImageBuf to an uninitialized state. - /// - void clear (); - - /// Forget all previous info, reset this ImageBuf to a new image - /// that is uninitialized (no pixel values, no size or spec). - /// If 'config' is not NULL, it points to an ImageSpec giving requests - /// or special instructions to be passed on to the eventual - /// ImageInput::open() call. - void reset (string_view name, int subimage, int miplevel, - ImageCache *imagecache = NULL, - const ImageSpec *config = NULL); - - /// Forget all previous info, reset this ImageBuf to a new image - /// that is uninitialized (no pixel values, no size or spec). - void reset (string_view name, ImageCache *imagecache=NULL); - - /// Forget all previous info, reset this ImageBuf to a blank - /// image of the given dimensions. - void reset (const ImageSpec &spec); - - /// Forget all previous info, reset this ImageBuf to a blank - /// image of the given name and dimensions. - void reset (string_view name, const ImageSpec &spec); - - /// Which type of storage is being used for the pixels? - IBStorage storage () const; - - /// Is this ImageBuf object initialized? - bool initialized () const; - - /// Read the file from disk. Generally will skip the read if we've - /// already got a current version of the image in memory, unless - /// force==true. This uses ImageInput underneath, so will read any - /// file format for which an appropriate imageio plugin can be found. - /// Return value is true if all is ok, otherwise false. - bool read (int subimage=0, int miplevel=0, bool force=false, - TypeDesc convert=TypeDesc::UNKNOWN, - ProgressCallback progress_callback=NULL, - void *progress_callback_data=NULL); - - /// Initialize this ImageBuf with the named image file, and read its - /// header to fill out the spec correctly. Return true if this - /// succeeded, false if the file could not be read. But don't - /// allocate or read the pixels. - bool init_spec (string_view filename, - int subimage, int miplevel); - - /// Write the image to the named file and file format ("" means to infer - /// the type from the filename extension). Return true if all went ok, - /// false if there were errors writing. - bool write (string_view filename, - string_view fileformat = string_view(), - ProgressCallback progress_callback=NULL, - void *progress_callback_data=NULL) const; - - /// Inform the ImageBuf what data format you'd like for any subsequent - /// write(). - void set_write_format (TypeDesc format); - - /// Inform the ImageBuf what tile size (or no tiling, for 0) for - /// any subsequent write(). - void set_write_tiles (int width=0, int height=0, int depth=0); - - /// Write the image to the open ImageOutput 'out'. Return true if - /// all went ok, false if there were errors writing. It does NOT - /// close the file when it's done (and so may be called in a loop to - /// write a multi-image file). - bool write (ImageOutput *out, - ProgressCallback progress_callback=NULL, - void *progress_callback_data=NULL) const; - - /// Force the ImageBuf to be writeable. That means that if it was - /// previously backed by ImageCache (storage was IMAGECACHE), it will - /// force a full read so that the whole image is in local memory. This - /// will invalidate any current iterators on the image. It has no effect - /// if the image storage not IMAGECACHE. Return true if it works - /// (including if no read was necessary), false if something went - /// horribly wrong. If keep_cache_type is true, it preserves any IC- - /// forced data types (you might want to do this if it is critical that - /// the apparent data type doesn't change, for example if you are - /// calling make_writeable from within a type-specialized function). - bool make_writeable (bool keep_cache_type = false); - - /// Copy all the metadata from src to *this (except for pixel data - /// resolution, channel information, and data format). - void copy_metadata (const ImageBuf &src); - - /// Copy the pixel data from src to *this, automatically converting - /// to the existing data format of *this. It only copies pixels in - /// the overlap regions (and channels) of the two images; pixel data - /// in *this that do exist in src will be set to 0, and pixel data - /// in src that do not exist in *this will not be copied. - bool copy_pixels (const ImageBuf &src); - - /// Try to copy the pixels and metadata from src to *this, returning - /// true upon success and false upon error/failure. - /// - /// If the previous state of *this was uninitialized, owning its own - /// local pixel memory, or referring to a read-only image backed by - /// ImageCache, then local pixel memory will be allocated to hold - /// the new pixels and the call always succeeds unless the memory - /// cannot be allocated. - /// - /// If *this previously referred to an app-owned memory buffer, the - /// memory cannot be re-allocated, so the call will only succeed if - /// the app-owned buffer is already the correct resolution and - /// number of channels. The data type of the pixels will be - /// converted automatically to the data type of the app buffer. - bool copy (const ImageBuf &src); - - /// copy(src), but with optional override of pixel data type - bool copy (const ImageBuf &src, TypeDesc format /*= TypeDesc::UNKNOWN*/); - - /// Swap with another ImageBuf - void swap (ImageBuf &other) { std::swap (m_impl, other.m_impl); } - - /// Error reporting for ImageBuf: call this with printf-like - /// arguments. Note however that this is fully typesafe! - /// void error (const char *format, ...) - TINYFORMAT_WRAP_FORMAT (void, error, const, - std::ostringstream msg;, msg, append_error(msg.str());) - - /// Return true if the IB has had an error and has an error message - /// to retrieve via geterror(). - bool has_error (void) const; - - /// Return the text of all error messages issued since geterror() - /// was called (or an empty string if no errors are pending). This - /// also clears the error message for next time. - std::string geterror (void) const; - - /// Return a read-only (const) reference to the image spec that - /// describes the buffer. - const ImageSpec & spec () const; - - /// Return a writable reference to the image spec that describes the - /// buffer. Use with extreme caution! If you use this for anything - /// other than adding attribute metadata, you are really taking your - /// chances! - ImageSpec & specmod (); - - /// Return a read-only (const) reference to the "native" image spec - /// (that describes the file, which may be slightly different than - /// the spec of the ImageBuf, particularly if the IB is backed by an - /// ImageCache that is imposing some particular data format or tile - /// size). - const ImageSpec & nativespec () const; - - /// Return the name of this image. - /// - string_view name (void) const; - - /// Return the name of the image file format of the disk file we - /// read into this image. Returns an empty string if this image - /// was not the result of a read(). - string_view file_format_name (void) const; - - /// Return the index of the subimage are we currently viewing - /// - int subimage () const; - - /// Return the number of subimages in the file. - /// - int nsubimages () const; - - /// Return the index of the miplevel are we currently viewing - /// - int miplevel () const; - - /// Return the number of miplevels of the current subimage. - /// - int nmiplevels () const; - - /// Return the number of color channels in the image. - /// - int nchannels () const; - - /// Wrap mode describes what happens when an iterator points to - /// a value outside the usual data range of an image. - enum WrapMode { WrapDefault, WrapBlack, WrapClamp, WrapPeriodic, - WrapMirror, _WrapLast }; - - /// Retrieve a single channel of one pixel. - /// - float getchannel (int x, int y, int z, int c, WrapMode wrap=WrapBlack) const; - - /// Retrieve the pixel value by x and y pixel indices, - /// storing the floating point version in pixel[]. Retrieve at most - /// maxchannels (will be clamped to the actual number of channels). - void getpixel (int x, int y, float *pixel, int maxchannels=1000) const { - getpixel (x, y, 0, pixel, maxchannels); - } - - /// Retrieve the pixel value by x, y, z pixel indices, - /// storing the floating point version in pixel[]. Retrieve at most - /// maxchannels (will be clamped to the actual number of channels). - void getpixel (int x, int y, int z, float *pixel, int maxchannels=1000, - WrapMode wrap=WrapBlack) const; - - /// Sample the image plane at coordinates (x,y), using linear - /// interpolation between pixels, placing the result in pixel[0..n-1] - /// where n is the smaller of maxchannels or the actual number of - /// channels stored in the buffer. It is up to the application to - /// ensure that pixel points to enough memory to hold the required - /// number of channels. Note that pixel data values themselves are at - /// the pixel centers, so pixel (i,j) is at image plane coordinate - /// (i+0.5, j+0.5). - void interppixel (float x, float y, float *pixel, - WrapMode wrap=WrapBlack) const; - - /// Linearly interpolate at NDC coordinates (s,t), where (0,0) is - /// the upper left corner of the display window, (1,1) the lower - /// right corner of the display window. - void interppixel_NDC (float s, float t, float *pixel, - WrapMode wrap=WrapBlack) const; - - /// DEPCRECATED (1.5) synonym for interppixel_NDC. - void interppixel_NDC_full (float s, float t, float *pixel, - WrapMode wrap=WrapBlack) const; - - /// Bicubic interpolation at pixel coordinates (x,y), where (0,0) is - /// the upper left corner, (xres,yres) the lower right corner of - /// the pixel data. - void interppixel_bicubic (float x, float y, float *pixel, - WrapMode wrap=WrapBlack) const; - - /// Bicubic interpolattion at NDC space coordinates (s,t), where (0,0) - /// is the upper left corner of the display (aka "full") window, (1,1) - /// the lower right corner of the display window. - void interppixel_bicubic_NDC (float s, float t, float *pixel, - WrapMode wrap=WrapBlack) const; - - - /// Set the pixel with coordinates (x,y,0) to have the values in - /// pixel[0..n-1]. The number of channels copied, n, is the minimum - /// of maxchannels and the actual number of channels in the image. - void setpixel (int x, int y, const float *pixel, int maxchannels=1000) { - setpixel (x, y, 0, pixel, maxchannels); - } - - /// Set the pixel with coordinates (x,y,z) to have the values in - /// pixel[0..n-1]. The number of channels copied, n, is the minimum - /// of maxchannels and the actual number of channels in the image. - void setpixel (int x, int y, int z, - const float *pixel, int maxchannels=1000); - - /// Set the i-th pixel value of the image (out of width*height*depth), - /// from floating-point values in pixel[]. Set at most - /// maxchannels (will be clamped to the actual number of channels). - void setpixel (int i, const float *pixel, int maxchannels=1000); - - /// Retrieve the rectangle of pixels spanning the ROI (including - /// channels) at the current subimage and MIP-map level, storing the - /// pixel values beginning at the address specified by result and with - /// the given strides (by default, AutoStride means the usual contiguous - /// packing of pixels) and converting into the data type described by - /// 'format'. It is up to the caller to ensure that result points to an - /// area of memory big enough to accommodate the requested rectangle. - /// Return true if the operation could be completed, otherwise return - /// false. - bool get_pixels (ROI roi, TypeDesc format, void *result, - stride_t xstride=AutoStride, - stride_t ystride=AutoStride, - stride_t zstride=AutoStride) const; - - /// Copy the data into the given ROI of the ImageBuf. The data points to - /// values specified by 'format', with layout detailed by the stride - /// values (in bytes, with AutoStride indicating "contiguous" layout). - /// It is up to the caller to ensure that data points to an area of - /// memory big enough to account for the ROI. Return true if the - /// operation could be completed, otherwise return false. - bool set_pixels (ROI roi, TypeDesc format, const void *data, - stride_t xstride=AutoStride, - stride_t ystride=AutoStride, - stride_t zstride=AutoStride); - - /// DEPRECATED (1.6) -- use get_pixels(ROI, ...) instead. - bool get_pixel_channels (int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend, int chbegin, int chend, - TypeDesc format, void *result, - stride_t xstride=AutoStride, - stride_t ystride=AutoStride, - stride_t zstride=AutoStride) const; - - /// DEPRECATED (1.6) -- use get_pixels(ROI, ...) instead. - bool get_pixels (int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend, - TypeDesc format, void *result, - stride_t xstride=AutoStride, - stride_t ystride=AutoStride, - stride_t zstride=AutoStride) const; - - /// DEPRECATED (1.6) -- use get_pixels(ROI, ...) instead. - template - bool get_pixel_channels (int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend, int chbegin, int chend, - T *result, stride_t xstride=AutoStride, - stride_t ystride=AutoStride, - stride_t zstride=AutoStride) const; - - /// DEPRECATED (1.6) -- use get_pixels(ROI, ...) instead. - template - bool get_pixels (int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend, T *result, - stride_t xstride=AutoStride, stride_t ystride=AutoStride, - stride_t zstride=AutoStride) const - { - return get_pixel_channels (xbegin, xend, ybegin, yend, zbegin, zend, - 0, nchannels(), result, - xstride, ystride, zstride); - } - - /// DEPRECATED (1.6) -- use get_pixels(ROI, ...) instead. - template - bool get_pixels (int xbegin_, int xend_, int ybegin_, int yend_, - int zbegin_, int zend_, - std::vector &result) const - { - result.resize (nchannels() * ((zend_-zbegin_)*(yend_-ybegin_)*(xend_-xbegin_))); - return get_pixels (xbegin_, xend_, ybegin_, yend_, zbegin_, zend_, - &result[0]); - } - - - int orientation () const; - void set_orientation (int orient); - - int oriented_width () const; - int oriented_height () const; - int oriented_x () const; - int oriented_y () const; - int oriented_full_width () const; - int oriented_full_height () const; - int oriented_full_x () const; - int oriented_full_y () const; - - /// Return the beginning (minimum) x coordinate of the defined image. - int xbegin () const; - - /// Return the end (one past maximum) x coordinate of the defined image. - int xend () const; - - /// Return the beginning (minimum) y coordinate of the defined image. - int ybegin () const; - - /// Return the end (one past maximum) y coordinate of the defined image. - int yend () const; - - /// Return the beginning (minimum) z coordinate of the defined image. - int zbegin () const; - - /// Return the end (one past maximum) z coordinate of the defined image. - int zend () const; - - /// Return the minimum x coordinate of the defined image. - int xmin () const; - - /// Return the maximum x coordinate of the defined image. - int xmax () const; - - /// Return the minimum y coordinate of the defined image. - int ymin () const; - - /// Return the maximum y coordinate of the defined image. - int ymax () const; - - /// Return the minimum z coordinate of the defined image. - int zmin () const; - - /// Return the maximum z coordinate of the defined image. - int zmax () const; - - /// Set the "full" (a.k.a. display) window to [xbegin,xend) x - /// [ybegin,yend) x [zbegin,zend). - void set_full (int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend); - - /// Return pixel data window for this ImageBuf as a ROI. - ROI roi () const; - - /// Return full/display window for this ImageBuf as a ROI. - ROI roi_full () const; - - /// Set full/display window for this ImageBuf to a ROI. - /// Does NOT change the channels of the spec, regardless of newroi. - void set_roi_full (const ROI &newroi); - - bool pixels_valid (void) const; - - TypeDesc pixeltype () const; - - /// A raw pointer to "local" pixel memory, if they are fully in RAM - /// and not backed by an ImageCache, or NULL otherwise. You can - /// also test it like a bool to find out if pixels are local. - void *localpixels (); - const void *localpixels () const; - - /// Are the pixels backed by an ImageCache, rather than the whole - /// image being in RAM somewhere? - bool cachedpixels () const; - - ImageCache *imagecache () const; - - /// Return the address where pixel (x,y,z) is stored in the image buffer. - /// Use with extreme caution! Will return NULL if the pixel values - /// aren't local. - const void *pixeladdr (int x, int y, int z=0) const; - - /// Return the address where pixel (x,y) is stored in the image buffer. - /// Use with extreme caution! Will return NULL if the pixel values - /// aren't local. - void *pixeladdr (int x, int y) { return pixeladdr (x, y, 0); } - - /// Return the address where pixel (x,y,z) is stored in the image buffer. - /// Use with extreme caution! Will return NULL if the pixel values - /// aren't local. - void *pixeladdr (int x, int y, int z); - - /// Does this ImageBuf store deep data? - bool deep () const; - - /// Retrieve the number of deep data samples corresponding to pixel - /// (x,y,z). Return 0 if not a deep image or if the pixel is out of - /// range or has no deep samples. - int deep_samples (int x, int y, int z=0) const; - - /// Return a pointer to the raw array of deep data samples for - /// channel c of pixel (x,y,z). Return NULL if the pixel - /// coordinates or channel number are out of range, if the - /// pixel/channel has no deep samples, or if the image is not deep. - const void *deep_pixel_ptr (int x, int y, int z, int c) const; - - /// Return the value (as a float) of sample s of channel c of pixel - /// (x,y,z). Return 0.0 if not a deep image or if the pixel - /// coordinates or channel number are out of range or if it has no - /// deep samples. - float deep_value (int x, int y, int z, int c, int s) const; - - /// Retrieve deep sample value within a pixel, as an untigned int. - uint32_t deep_value_uint (int x, int y, int z, int c, int s) const; - - /// Set the number of deep samples for a particular pixel. - void set_deep_samples (int x, int y, int z, int nsamples); - - /// Set deep sample value within a pixel, as a float. - void set_deep_value (int x, int y, int z, int c, int s, float value); - /// Set deep sample value within a pixel, as a uint32. - void set_deep_value_uint (int x, int y, int z, int c, int s, uint32_t value); - - /// Allocate all the deep samples, called after deepdata()->nsamples - /// is set. - void deep_alloc (); - - /// Retrieve the "deep" data. - DeepData *deepdata (); - const DeepData *deepdata () const; - - /// Set the current thread-spawning policy: the maximum number of - /// threads that may be spawned by ImagBuf internals. A value of 1 - /// means all work will be done by the calling thread; 0 means to use - /// the global OIIO::attribute("threads") value. - void threads (int n) const; - - /// Retrieve the current thread-spawning policy of this ImageBuf. - int threads () const; - - friend class IteratorBase; - - class IteratorBase { - public: - IteratorBase (const ImageBuf &ib, WrapMode wrap) - : m_ib(&ib), m_tile(NULL), m_proxydata(NULL) - { - init_ib (wrap); - range_is_image (); - } - - /// Construct valid iteration region from ImageBuf and ROI. - IteratorBase (const ImageBuf &ib, const ROI &roi, WrapMode wrap) - : m_ib(&ib), m_tile(NULL), m_proxydata(NULL) - { - init_ib (wrap); - if (roi.defined()) { - m_rng_xbegin = roi.xbegin; - m_rng_xend = roi.xend; - m_rng_ybegin = roi.ybegin; - m_rng_yend = roi.yend; - m_rng_zbegin = roi.zbegin; - m_rng_zend = roi.zend; - } else { - range_is_image (); - } - } - - /// Construct from an ImageBuf and designated region -- iterate - /// over region, starting with the upper left pixel. - IteratorBase (const ImageBuf &ib, int xbegin, int xend, - int ybegin, int yend, int zbegin, int zend, - WrapMode wrap) - : m_ib(&ib), m_tile(NULL), m_proxydata(NULL) - { - init_ib (wrap); - m_rng_xbegin = xbegin; - m_rng_xend = xend; - m_rng_ybegin = ybegin; - m_rng_yend = yend; - m_rng_zbegin = zbegin; - m_rng_zend = zend; - } - - IteratorBase (const IteratorBase &i) - : m_ib (i.m_ib), - m_rng_xbegin(i.m_rng_xbegin), m_rng_xend(i.m_rng_xend), - m_rng_ybegin(i.m_rng_ybegin), m_rng_yend(i.m_rng_yend), - m_rng_zbegin(i.m_rng_zbegin), m_rng_zend(i.m_rng_zend), - m_tile(NULL), m_proxydata(i.m_proxydata) - { - init_ib (i.m_wrap); - } - - ~IteratorBase () { - if (m_tile) - m_ib->imagecache()->release_tile (m_tile); - } - - /// Assign one IteratorBase to another - /// - const IteratorBase & assign_base (const IteratorBase &i) { - if (m_tile) - m_ib->imagecache()->release_tile (m_tile); - m_tile = NULL; - m_proxydata = i.m_proxydata; - m_ib = i.m_ib; - init_ib (i.m_wrap); - m_rng_xbegin = i.m_rng_xbegin; m_rng_xend = i.m_rng_xend; - m_rng_ybegin = i.m_rng_ybegin; m_rng_yend = i.m_rng_yend; - m_rng_zbegin = i.m_rng_zbegin; m_rng_zend = i.m_rng_zend; - return *this; - } - - /// Retrieve the current x location of the iterator. - /// - int x () const { return m_x; } - /// Retrieve the current y location of the iterator. - /// - int y () const { return m_y; } - /// Retrieve the current z location of the iterator. - /// - int z () const { return m_z; } - - /// Is the current location within the designated iteration range? - bool valid () const { - return m_valid; - } - - /// Is the location (x,y[,z]) within the designated iteration - /// range? - bool valid (int x_, int y_, int z_=0) const { - return (x_ >= m_rng_xbegin && x_ < m_rng_xend && - y_ >= m_rng_ybegin && y_ < m_rng_yend && - z_ >= m_rng_zbegin && z_ < m_rng_zend); - } - - /// Is the location (x,y[,z]) within the region of the ImageBuf - /// that contains pixel values (sometimes called the "data window")? - bool exists (int x_, int y_, int z_=0) const { - return (x_ >= m_img_xbegin && x_ < m_img_xend && - y_ >= m_img_ybegin && y_ < m_img_yend && - z_ >= m_img_zbegin && z_ < m_img_zend); - } - /// Does the current location exist within the ImageBuf's - /// data window? - bool exists () const { - return m_exists; - } - - /// Are we finished iterating over the region? - // - bool done () const { - // We're "done" if we are both invalid and in exactly the - // spot that we would end up after iterating off of the last - // pixel in the range. (The m_valid test is just a quick - // early-out for when we're in the correct pixel range.) - return (m_valid == false && m_x == m_rng_xbegin && - m_y == m_rng_ybegin && m_z == m_rng_zend); - } - - /// Retrieve the number of deep data samples at this pixel. - int deep_samples () const { return m_ib->deep_samples (m_x, m_y, m_z); } - - /// Return the wrap mode - WrapMode wrap () const { return m_wrap; } - - /// Explicitly point the iterator. This results in an invalid - /// iterator if outside the previously-designated region. - void pos (int x_, int y_, int z_=0) { - if (x_ == m_x+1 && x_ < m_rng_xend && y_ == m_y && z_ == m_z && - m_valid && m_exists) { - // Special case for what is in effect just incrementing x - // within the iteration region. - m_x = x_; - pos_xincr (); - // Not necessary? m_exists = (x_ < m_img_xend); - DASSERT ((x_ < m_img_xend) == m_exists); - return; - } - bool v = valid(x_,y_,z_); - bool e = exists(x_,y_,z_); - if (m_localpixels) { - if (e) - m_proxydata = (char *)m_ib->pixeladdr (x_, y_, z_); - else { // pixel not in data window - m_x = x_; m_y = y_; m_z = z_; - if (m_wrap == WrapBlack) { - m_proxydata = (char *)m_ib->blackpixel(); - } else { - if (m_ib->do_wrap (x_, y_, z_, m_wrap)) - m_proxydata = (char *)m_ib->pixeladdr (x_, y_, z_); - else - m_proxydata = (char *)m_ib->blackpixel(); - } - m_valid = v; - m_exists = e; - return; - } - } - else if (! m_deep) - m_proxydata = (char *)m_ib->retile (x_, y_, z_, m_tile, - m_tilexbegin, m_tileybegin, - m_tilezbegin, m_tilexend, - e, m_wrap); - m_x = x_; m_y = y_; m_z = z_; - m_valid = v; - m_exists = e; - } - - /// Increment to the next pixel in the region. - /// - OIIO_FORCEINLINE void operator++ () { - if (++m_x < m_rng_xend) { - // Special case: we only incremented x, didn't change y - // or z, and the previous position was within the data - // window. Call a shortcut version of pos. - if (m_exists) { - pos_xincr (); - return; - } - } else { - // Wrap to the next scanline - m_x = m_rng_xbegin; - if (++m_y >= m_rng_yend) { - m_y = m_rng_ybegin; - if (++m_z >= m_rng_zend) { - m_valid = false; // shortcut -- finished iterating - return; - } - } - } - pos (m_x, m_y, m_z); - } - /// Increment to the next pixel in the region. - /// - void operator++ (int) { - ++(*this); - } - - /// Return the iteration range - ROI range () const { - return ROI (m_rng_xbegin, m_rng_xend, m_rng_ybegin, m_rng_yend, - m_rng_zbegin, m_rng_zend, 0, m_ib->nchannels()); - } - - /// Reset the iteration range for this iterator and reposition to - /// the beginning of the range, but keep referring to the same - /// image. - void rerange (int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend, WrapMode wrap=WrapDefault) - { - m_x = 1<<31; - m_y = 1<<31; - m_z = 1<<31; - m_wrap = (wrap == WrapDefault ? WrapBlack : wrap); - m_rng_xbegin = xbegin; - m_rng_xend = xend; - m_rng_ybegin = ybegin; - m_rng_yend = yend; - m_rng_zbegin = zbegin; - m_rng_zend = zend; - pos (xbegin, ybegin, zbegin); - } - - protected: - friend class ImageBuf; - friend class ImageBufImpl; - const ImageBuf *m_ib; - bool m_valid, m_exists; - bool m_deep; - bool m_localpixels; - // Image boundaries - int m_img_xbegin, m_img_xend, m_img_ybegin, m_img_yend, - m_img_zbegin, m_img_zend; - // Iteration range - int m_rng_xbegin, m_rng_xend, m_rng_ybegin, m_rng_yend, - m_rng_zbegin, m_rng_zend; - int m_x, m_y, m_z; - ImageCache::Tile *m_tile; - int m_tilexbegin, m_tileybegin, m_tilezbegin; - int m_tilexend; - int m_nchannels; - size_t m_pixel_bytes; - char *m_proxydata; - WrapMode m_wrap; - - // Helper called by ctrs -- set up some locally cached values - // that are copied or derived from the ImageBuf. - void init_ib (WrapMode wrap) { - const ImageSpec &spec (m_ib->spec()); - m_deep = spec.deep; - m_localpixels = (m_ib->localpixels() != NULL); - m_img_xbegin = spec.x; m_img_xend = spec.x+spec.width; - m_img_ybegin = spec.y; m_img_yend = spec.y+spec.height; - m_img_zbegin = spec.z; m_img_zend = spec.z+spec.depth; - m_nchannels = spec.nchannels; -// m_tilewidth = spec.tile_width; - m_pixel_bytes = spec.pixel_bytes(); - m_x = 1<<31; - m_y = 1<<31; - m_z = 1<<31; - m_wrap = (wrap == WrapDefault ? WrapBlack : wrap); - } - - // Helper called by ctrs -- make the iteration range the full - // image data window. - void range_is_image () { - m_rng_xbegin = m_img_xbegin; m_rng_xend = m_img_xend; - m_rng_ybegin = m_img_ybegin; m_rng_yend = m_img_yend; - m_rng_zbegin = m_img_zbegin; m_rng_zend = m_img_zend; - } - - // Helper called by pos(), but ONLY for the case where we are - // moving from an existing pixel to the next spot in +x. - // Note: called *after* m_x was incremented! - OIIO_FORCEINLINE void pos_xincr () { - DASSERT (m_exists && m_valid); // precondition - DASSERT (valid(m_x,m_y,m_z)); // should be true by definition - m_proxydata += m_pixel_bytes; - if (m_localpixels) { - if (OIIO_UNLIKELY(m_x >= m_img_xend)) { - // Ran off the end of the row - m_exists = false; - if (m_wrap == WrapBlack) { - m_proxydata = (char *)m_ib->blackpixel(); - } else { - int x = m_x, y = m_y, z = m_z; - if (m_ib->do_wrap (x, y, z, m_wrap)) - m_proxydata = (char *)m_ib->pixeladdr (x, y, z); - else - m_proxydata = (char *)m_ib->blackpixel(); - } - } - } else if (m_deep) { - m_proxydata = NULL; - } else { - // Cached image - bool e = m_x < m_img_xend; - if (OIIO_UNLIKELY( !(e && m_x < m_tilexend && m_tile))) { - // Crossed a tile boundary - m_proxydata = (char *)m_ib->retile (m_x, m_y, m_z, m_tile, - m_tilexbegin, m_tileybegin, m_tilezbegin, - m_tilexend, e, m_wrap); - m_exists = e; - } - } - } - - // Set to the "done" position - void pos_done () { - m_valid = false; - m_x = m_rng_xbegin; - m_y = m_rng_ybegin; - m_z = m_rng_zend; - } - - // Make sure it's writeable. Use with caution! - void make_writeable () { - if (! m_localpixels) { - const_cast(m_ib)->make_writeable (true); - DASSERT (m_ib->storage() != IMAGECACHE); - m_tile = NULL; - m_proxydata = NULL; - init_ib (m_wrap); - } - } - }; - - /// Templated class for referring to an individual pixel in an - /// ImageBuf, iterating over the pixels of an ImageBuf, or iterating - /// over the pixels of a specified region of the ImageBuf - /// [xbegin..xend) X [ybegin..yend). It is templated on BUFT, the - /// type known to be in the internal representation of the ImageBuf, - /// and USERT, the type that the user wants to retrieve or set the - /// data (defaulting to float). the whole idea is to allow this: - /// \code - /// ImageBuf img (...); - /// ImageBuf::Iterator pixel (img, 0, 512, 0, 512); - /// for ( ; ! pixel.done(); ++pixel) { - /// for (int c = 0; c < img.nchannels(); ++c) { - /// float x = pixel[c]; - /// pixel[c] = ...; - /// } - /// } - /// \endcode - /// - template - class Iterator : public IteratorBase { - public: - /// Construct from just an ImageBuf -- iterate over the whole - /// region, starting with the upper left pixel of the region. - Iterator (ImageBuf &ib, WrapMode wrap=WrapDefault) - : IteratorBase(ib,wrap) - { - make_writeable (); - pos (m_rng_xbegin,m_rng_ybegin,m_rng_zbegin); - if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend - || m_rng_zbegin == m_rng_zend) - pos_done(); // make empty range look "done" - } - /// Construct from an ImageBuf and a specific pixel index. - /// The iteration range is the full image. - Iterator (ImageBuf &ib, int x, int y, int z=0, - WrapMode wrap=WrapDefault) - : IteratorBase(ib,wrap) - { - make_writeable (); - pos (x, y, z); - } - /// Construct read-write iteration region from ImageBuf and ROI. - Iterator (ImageBuf &ib, const ROI &roi, WrapMode wrap=WrapDefault) - : IteratorBase (ib, roi, wrap) - { - make_writeable (); - pos (m_rng_xbegin, m_rng_ybegin, m_rng_zbegin); - if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend - || m_rng_zbegin == m_rng_zend) - pos_done(); // make empty range look "done" - } - /// Construct from an ImageBuf and designated region -- iterate - /// over region, starting with the upper left pixel. - Iterator (ImageBuf &ib, int xbegin, int xend, - int ybegin, int yend, int zbegin=0, int zend=1, - WrapMode wrap=WrapDefault) - : IteratorBase(ib, xbegin, xend, ybegin, yend, zbegin, zend, wrap) - { - make_writeable (); - pos (m_rng_xbegin, m_rng_ybegin, m_rng_zbegin); - if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend - || m_rng_zbegin == m_rng_zend) - pos_done(); // make empty range look "done" - } - /// Copy constructor. - /// - Iterator (Iterator &i) - : IteratorBase (i.m_ib, i.m_wrap) - { - make_writeable (); - pos (i.m_x, i.m_y, i.m_z); - } - - ~Iterator () { } - - /// Assign one Iterator to another - /// - const Iterator & operator= (const Iterator &i) { - assign_base (i); - pos (i.m_x, i.m_y, i.m_z); - return *this; - } - - /// Dereferencing the iterator gives us a proxy for the pixel, - /// which we can index for reading or assignment. - DataArrayProxy& operator* () { - return *(DataArrayProxy *)(void *)&m_proxydata; - } - - /// Array indexing retrieves the value of the i-th channel of - /// the current pixel. - USERT operator[] (int i) const { - DataArrayProxy proxy((BUFT*)m_proxydata); - return proxy[i]; - } - - /// Array referencing retrieve a proxy (which may be "assigned - /// to") of i-th channel of the current pixel, so that this - /// works: me[i] = val; - DataProxy operator[] (int i) { - DataArrayProxy proxy((BUFT*)m_proxydata); - return proxy[i]; - } - - void * rawptr () const { return m_proxydata; } - - /// Set the number of deep data samples at this pixel. (Only use - /// this if deep_alloc() has not yet been called on the buffer.) - void set_deep_samples (int n) { - return const_cast(m_ib)->set_deep_samples (m_x, m_y, m_z, n); - } - - /// Retrieve the deep data value of sample s of channel c. - USERT deep_value (int c, int s) const { - return convert_type(m_ib->deep_value (m_x, m_y, m_z, c, s)); - } - - /// Set the deep data value of sample s of channel c. (Only use this - /// if deep_alloc() has been called.) - void set_deep_value (int c, int s, float value) { - return const_cast(m_ib)->set_deep_value (m_x, m_y, m_z, c, s, value); - } - void set_deep_value (int c, int s, uint32_t value) { - return const_cast(m_ib)->set_deep_value_uint (m_x, m_y, m_z, c, s, value); - } - - }; - - - /// Just like an ImageBuf::Iterator, except that it refers to a - /// const ImageBuf. - template - class ConstIterator : public IteratorBase { - public: - /// Construct from just an ImageBuf -- iterate over the whole - /// region, starting with the upper left pixel of the region. - ConstIterator (const ImageBuf &ib, WrapMode wrap=WrapDefault) - : IteratorBase(ib,wrap) - { - pos (m_rng_xbegin,m_rng_ybegin,m_rng_zbegin); - if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend - || m_rng_zbegin == m_rng_zend) - pos_done(); // make empty range look "done" - } - /// Construct from an ImageBuf and a specific pixel index. - /// The iteration range is the full image. - ConstIterator (const ImageBuf &ib, int x_, int y_, int z_=0, - WrapMode wrap=WrapDefault) - : IteratorBase(ib,wrap) - { - pos (x_, y_, z_); - } - /// Construct read-only iteration region from ImageBuf and ROI. - ConstIterator (const ImageBuf &ib, const ROI &roi, - WrapMode wrap=WrapDefault) - : IteratorBase (ib, roi, wrap) - { - pos (m_rng_xbegin, m_rng_ybegin, m_rng_zbegin); - if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend - || m_rng_zbegin == m_rng_zend) - pos_done(); // make empty range look "done" - } - /// Construct from an ImageBuf and designated region -- iterate - /// over region, starting with the upper left pixel. - ConstIterator (const ImageBuf &ib, int xbegin, int xend, - int ybegin, int yend, int zbegin=0, int zend=1, - WrapMode wrap=WrapDefault) - : IteratorBase(ib, xbegin, xend, ybegin, yend, zbegin, zend, wrap) - { - pos (m_rng_xbegin, m_rng_ybegin, m_rng_zbegin); - if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend - || m_rng_zbegin == m_rng_zend) - pos_done(); // make empty range look "done" - } - /// Copy constructor. - /// - ConstIterator (const ConstIterator &i) - : IteratorBase (i) - { - pos (i.m_x, i.m_y, i.m_z); - } - - ~ConstIterator () { } - - /// Assign one ConstIterator to another - /// - const ConstIterator & operator= (const ConstIterator &i) { - assign_base (i); - pos (i.m_x, i.m_y, i.m_z); - return *this; - } - - /// Dereferencing the iterator gives us a proxy for the pixel, - /// which we can index for reading or assignment. - ConstDataArrayProxy& operator* () const { - return *(ConstDataArrayProxy *)&m_proxydata; - } - - /// Array indexing retrieves the value of the i-th channel of - /// the current pixel. - USERT operator[] (int i) const { - ConstDataArrayProxy proxy ((BUFT*)m_proxydata); - return proxy[i]; - } - - const void * rawptr () const { return m_proxydata; } - - /// Retrieve the deep data value of sample s of channel c. - USERT deep_value (int c, int s) const { - return convert_type(m_ib->deep_value (m_x, m_y, m_z, c, s)); - } - uint32_t deep_value_uint (int c, int s) const { - return m_ib->deep_value_uint (m_x, m_y, m_z, c, s); - } - }; - - -protected: - ImageBufImpl *m_impl; //< PIMPL idiom - - ImageBufImpl * impl () { return m_impl; } - const ImageBufImpl * impl () const { return m_impl; } - - // Reset the ImageCache::Tile * to reserve and point to the correct - // tile for the given pixel, and return the ptr to the actual pixel - // within the tile. - const void * retile (int x, int y, int z, - ImageCache::Tile* &tile, int &tilexbegin, - int &tileybegin, int &tilezbegin, - int &tilexend, bool exists, - WrapMode wrap=WrapDefault) const; - - const void *blackpixel () const; - - // Given x,y,z known to be outside the pixel data range, and a wrap - // mode, alter xyz to implement the wrap. Return true if the resulting - // x,y,z is within the valid pixel data window, false if it still is - // not. - bool do_wrap (int &x, int &y, int &z, WrapMode wrap) const; - - /// Private and unimplemented. - const ImageBuf& operator= (const ImageBuf &src); - - /// Add to the error message list for this IB. - void append_error (const std::string& message) const; - -}; - - -OIIO_NAMESPACE_END - -#endif // OPENIMAGEIO_IMAGEBUF_H diff --git a/3rdparty/oiio16/include/OpenImageIO/imagebufalgo.h b/3rdparty/oiio16/include/OpenImageIO/imagebufalgo.h deleted file mode 100644 index 60af4ee0..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/imagebufalgo.h +++ /dev/null @@ -1,1975 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -#ifndef OPENIMAGEIO_IMAGEBUFALGO_H -#define OPENIMAGEIO_IMAGEBUFALGO_H - -#if defined(_MSC_VER) -// Ignore warnings about DLL exported classes with member variables that are template classes. -// This happens with the std::vector members of PixelStats below. -# pragma warning (disable : 4251) -#endif - -#include "imageio.h" -#include "imagebuf.h" -#include "fmath.h" -#include "color.h" - -#include /* because we need M33f */ - -#include - -#ifndef __OPENCV_CORE_TYPES_H__ -struct IplImage; // Forward declaration; used by Intel Image lib & OpenCV -#endif - - - -OIIO_NAMESPACE_BEGIN - -class Filter2D; // forward declaration - - - -/// Some generalities about ImageBufAlgo functions: -/// -/// All IBA functions take a ROI. Only the pixels (and channels) in dst -/// that are specified by the ROI will be altered; the default ROI is to -/// alter all the pixels in dst. Exceptions will be noted, including -/// functions that do not honor their channel range. -/// -/// In general, IBA functions that are passed an initialized 'dst' or -/// 'result' image do not reallocate it or alter its existing pixels -/// that lie outside the ROI (exceptions will be noted). If passed an -/// uninitialized result image, it will be reallocatd to be the size of -/// the ROI (and with float pixels). If the result image passed is -/// uninitialized and also the ROI is undefined, the ROI will be the -/// union of the pixel data regions of any input images. (A small -/// number of IBA functions, such as fill(), have only a result image -/// and no input image; in such cases, it's an error to have both an -/// uninitiailized result image and an undefined ROI.) -/// -/// IBA functions that have an 'nthreads' parameter use it to specify -/// how many threads (potentially) may be used, but it's not a -/// guarantee. If nthreads == 0, it will use the global OIIO attribute -/// "nthreads". If nthreads == 1, it guarantees that it will not launch -/// any new threads. -/// -/// All IBA functions return true on success, false on error (with an -/// appropriate error message set in dst). - - - -namespace ImageBufAlgo { - -/// Zero out (set to 0, black) the image region. -/// -/// Only the pixels (and channels) in dst that are specified by roi will -/// be altered; the default roi is to alter all the pixels in dst. -/// -/// If dst is uninitialized, it will be resized to be a float ImageBuf -/// large enough to hold the region specified by roi. It is an error to -/// pass both an uninitialied dst and an undefined roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API zero (ImageBuf &dst, ROI roi=ROI::All(), int nthreads=0); - - -/// Fill the image region with given channel values. Note that the -/// values pointer starts with channel 0, even if the ROI indicates that -/// a later channel is the first to be changed. -/// -/// Three varieties of fill() exist: (a) a single set of channel values that -/// will apply to the whole ROI, (b) two sets of values that will create a -/// linearly interpolated gradient from top to bottom of the ROI, (c) four -/// sets of values that will be bilnearly interpolated across all four -/// corners of the ROI. -/// -/// Only the pixels (and channels) in dst that are specified by roi will -/// be altered; the default roi is to alter all the pixels in dst. -/// -/// If dst is uninitialized, it will be resized to be a float ImageBuf -/// large enough to hold the region specified by roi. It is an error to -/// pass both an uninitialied dst and an undefined roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API fill (ImageBuf &dst, const float *values, - ROI roi=ROI::All(), int nthreads=0); -bool OIIO_API fill (ImageBuf &dst, const float *top, const float *bottom, - ROI roi=ROI::All(), int nthreads=0); -bool OIIO_API fill (ImageBuf &dst, const float *topleft, const float *topright, - const float *bottomleft, const float *bottomright, - ROI roi=ROI::All(), int nthreads=0); - - -/// Fill the image region with a checkerboard with origin -/// (xoffset,yoffset,zoffset) and that alternates between color1[] and -/// color2[] every width pixels in x, every height pixels in y, and -/// every depth pixels in z. The pattern is definied in abstract "image -/// space" independently of the pixel data window of dst or the ROI. -/// -/// Only the pixels (and channels) in dst that are specified by roi will -/// be altered; the default roi is to alter all the pixels in dst. -/// -/// If dst is uninitialized, it will be resized to be a float ImageBuf -/// large enough to hold the region specified by roi. It is an error -/// to pass both an uninitialied dst and an undefined roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API checker (ImageBuf &dst, int width, int height, int depth, - const float *color1, const float *color2, - int xoffset=0, int yoffset=0, int zoffset=0, - ROI roi=ROI::All(), int nthreads=0); - - -/// Inject pseudorandom noise into image dst, in every pixel and channel -/// specified by the roi (defaulting to all pixels, all channels). There are -/// several noise types to choose from, and each behaves differently and has -/// a different interpretation of the A and B parameters: -/// "gaussian" adds Gaussian (normal distribution) noise values with -/// mean value A and standard deviation B. -/// "uniform" adds noise values uninformly distributed on range [A,B). -/// "salt" changes to value A a portion of pixels given by B. -/// If the 'mono' flag is true, a single noise value will be applied to all -/// channels specified by roi, but if 'mono' is false, a separate noise -/// value will be computed for each channel in the region. -/// -/// The random number generator is actually driven by a hash on the "image -/// space" coordinates and channel, independently of the pixel data window -/// of dst or the ROI. Choosing different seed values will result in a -/// different pattern, but for the same seed value, the noise at a given -/// pixel coordinate (x,y,z) channel c will is completely deterministic and -/// repeatable. -/// -/// If dst is uninitialized, it will be resized to be a float ImageBuf -/// large enough to hold the region specified by roi. It is an error -/// to pass both an uninitialied dst and an undefined roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API noise (ImageBuf &dst, string_view noisetype, - float A = 0.0f, float B = 0.1f, bool mono = false, - int seed = 0, ROI roi=ROI::All(), int nthreads=0); - - -/// Generic channel shuffling -- copy src to dst, but with channels in -/// the order channelorder[0..nchannels-1]. Does not support in-place -/// operation. For any channel in which channelorder[i] < 0, it will -/// just make dst channel i a constant color -- set to channelvalues[i] -/// (if channelvalues != NULL) or 0.0 (if channelvalues == NULL). -/// -/// If channelorder is NULL, it will be interpreted as -/// {0, 1, ..., nchannels-1}, meaning that it's only renaming channels, -/// not reordering them. -/// -/// If newchannelnames is not NULL, it points to an array of new channel -/// names. Channels for which newchannelnames[i] is the empty string (or -/// all channels, if newchannelnames == NULL) will be named as follows: -/// If shuffle_channel_names is false, the resulting dst image will have -/// default channel names in the usual order ("R", "G", etc.), but if -/// shuffle_channel_names is true, the names will be taken from the -/// corresponding channels of the source image -- be careful with this, -/// shuffling both channel ordering and their names could result in no -/// semantic change at all, if you catch the drift. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// N.B. If you are merely interested in extending the number of channels -/// or truncating channels at the end (but leaving the other channels -/// intact), then you should call this as: -/// channels (dst, src, nchannels, NULL, NULL, NULL, true); -bool OIIO_API channels (ImageBuf &dst, const ImageBuf &src, - int nchannels, const int *channelorder, - const float *channelvalues=NULL, - const std::string *newchannelnames=NULL, - bool shuffle_channel_names=false, int nthreads=0); - - -/// Append the channels of A and B together into dst over the region of -/// interest. If the region passed is uninitialized (the default), it -/// will be interpreted as being the union of the pixel windows of A and -/// B (and all channels of both images). If dst is not already -/// initialized, it will be resized to be big enough for the region. -bool OIIO_API channel_append (ImageBuf &dst, const ImageBuf &A, - const ImageBuf &B, ROI roi=ROI::All(), - int nthreads=0); - - -/// Set dst to the "deep" version of "flat" input src. Turning a flat -/// image into a deep one means: -/// -/// If the src image has a "Z" channel: if the source pixel's Z channel -/// value is not infinite, the corresponding pixel of dst will get a single -/// depth sample that copies the data from the soruce pixel; otherwise, dst -/// will get an empty pixel. In other words, infinitely far pixels will not -/// turn into deep samples. -/// -/// If the src image lacks a "Z" channel: if any of the source pixel's -/// channel values are nonzero, the corresponding pixel of dst will get a -/// single depth sample that copies the data from the source pixel and uses -/// the zvalue parameter for the depth; otherwise, if all source channels in -/// that pixel are zero, the destination pixel will get no depth samples. -/// -/// If src is already a deep image, it will just copy pixel values from src -/// to dst. If dst is not already an initialized ImageBuf, it will be sized -/// to match src (but made deep). -/// -/// 'roi' specifies the region of dst's pixels which will be computed; -/// existing pixels outside this range will not be altered. If not -/// specified, the default ROI value will be the pixel data window of src. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -bool OIIO_API deepen (ImageBuf &dst, const ImageBuf &src, float zvalue = 1.0f, - ROI roi = ROI::All(), int nthreads = 0); - - -/// Set dst to the ``flattened'' composite of deep image src. That is, it -/// converts a deep image to a simple flat image by front-to-back -/// compositing the samples within each pixel. If src is already a non- -/// deep/flat image, it will just copy pixel values from src to dst. If dst -/// is not already an initialized ImageBuf, it will be sized to match src -/// (but made non-deep). -/// -/// 'roi' specifies the region of dst's pixels which will be computed; -/// existing pixels outside this range will not be altered. If not -/// specified, the default ROI value will be the pixel data window of src. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -bool OIIO_API flatten (ImageBuf &dst, const ImageBuf &src, - ROI roi = ROI::All(), int nthreads = 0); - - -/// Reset dst to be the specified region of src. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API crop (ImageBuf &dst, const ImageBuf &src, - ROI roi = ROI::All(), int nthreads = 0); - - -/// Assign to dst the designated region of src, but shifted to be at the -/// (0,0) origin, and with the full/display resolution set to be identical -/// to the data region. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API cut (ImageBuf &dst, const ImageBuf &src, - ROI roi=ROI::All(), int nthreads = 0); - - -/// Copy into dst, beginning at (xbegin,ybegin,zbegin), the pixels of -/// src described by srcroi. If srcroi is ROI::All(), the entirety of src -/// will be used. It will copy into channels [chbegin...], as many -/// channels as are described by srcroi. Pixels or channels of dst outside -/// the range of roi will not be altered. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API paste (ImageBuf &dst, int xbegin, int ybegin, - int zbegin, int chbegin, - const ImageBuf &src, ROI srcroi=ROI::All(), - int nthreads = 0); - - -/// Copy src to dst, but with the image pixels rotated 90 degrees -/// clockwise. In other words, -/// AB --> CA -/// CD DB -/// -/// Only the pixels (and channels) in src that are specified by roi will be -/// copied to their corresponding positions in dst; the default roi is to -/// copy the whole data region of src. If dst is uninitialized, it will be -/// resized to be a float ImageBuf large enough to hold the region specified -/// by roi. It is an error to pass both an uninitialied dst and an undefined -/// roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may be -/// used, but it's not a guarantee. If nthreads == 0, it will use the -/// global OIIO attribute "nthreads". If nthreads == 1, it guarantees that -/// it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API rotate90 (ImageBuf &dst, const ImageBuf &src, - ROI roi=ROI::All(), int nthreads=0); - -/// Copy src to dst, but with the image pixels rotated 180 degrees. -/// In other words, -/// AB --> DC -/// CD BA -/// -/// Only the pixels (and channels) in src that are specified by roi will be -/// copied to their corresponding positions in dst; the default roi is to -/// copy the whole data region of src. If dst is uninitialized, it will be -/// resized to be a float ImageBuf large enough to hold the region specified -/// by roi. It is an error to pass both an uninitialied dst and an undefined -/// roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may be -/// used, but it's not a guarantee. If nthreads == 0, it will use the -/// global OIIO attribute "nthreads". If nthreads == 1, it guarantees that -/// it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API rotate180 (ImageBuf &dst, const ImageBuf &src, - ROI roi=ROI::All(), int nthreads=0); -/// DEPRECATED(1.5) synonym for rotate180. -bool OIIO_API flipflop (ImageBuf &dst, const ImageBuf &src, - ROI roi=ROI::All(), int nthreads=0); - -/// Copy src to dst, but with the image pixels rotated 90 degrees -/// clockwise. In other words, -/// AB --> BD -/// CD AC -/// -/// Only the pixels (and channels) in src that are specified by roi will be -/// copied to their corresponding positions in dst; the default roi is to -/// copy the whole data region of src. If dst is uninitialized, it will be -/// resized to be a float ImageBuf large enough to hold the region specified -/// by roi. It is an error to pass both an uninitialied dst and an undefined -/// roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may be -/// used, but it's not a guarantee. If nthreads == 0, it will use the -/// global OIIO attribute "nthreads". If nthreads == 1, it guarantees that -/// it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API rotate270 (ImageBuf &dst, const ImageBuf &src, - ROI roi=ROI::All(), int nthreads=0); - -/// Copy src to dst, but with the scanlines exchanged vertically within -/// the display/full window. In other words, -/// AB --> CD -/// CD AB -/// -/// Only the pixels (and channels) in src that are specified by roi will be -/// copied to their corresponding positions in dst; the default roi is to -/// copy the whole data region of src. If dst is uninitialized, it will be -/// resized to be a float ImageBuf large enough to hold the region specified -/// by roi. It is an error to pass both an uninitialied dst and an undefined -/// roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may be -/// used, but it's not a guarantee. If nthreads == 0, it will use the -/// global OIIO attribute "nthreads". If nthreads == 1, it guarantees that -/// it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API flip (ImageBuf &dst, const ImageBuf &src, - ROI roi=ROI::All(), int nthreads=0); - -/// Copy src to dst, but with the columns exchanged horizontally within -/// the display/full window. In other words, -/// AB --> BA -/// CD DC -/// -/// Only the pixels (and channels) in src that are specified by roi will be -/// copied to their corresponding positions in dst; the default roi is to -/// copy the whole data region of src. If dst is uninitialized, it will be -/// resized to be a float ImageBuf large enough to hold the region specified -/// by roi. It is an error to pass both an uninitialied dst and an undefined -/// roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may be -/// used, but it's not a guarantee. If nthreads == 0, it will use the -/// global OIIO attribute "nthreads". If nthreads == 1, it guarantees that -/// it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API flop (ImageBuf &dst, const ImageBuf &src, - ROI roi=ROI::All(), int nthreads=0); - -/// Copy src to dst, but with whatever seties of rotations, flips, or flops -/// are necessary to transform the pixels into the configuration suggested -/// by the Orientation metadata of the image (and the Orientation metadata -/// is then set to 1, ordinary orientation). -/// -/// The nthreads parameter specifies how many threads (potentially) may be -/// used, but it's not a guarantee. If nthreads == 0, it will use the -/// global OIIO attribute "nthreads". If nthreads == 1, it guarantees that -/// it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API reorient (ImageBuf &dst, const ImageBuf &src, - int nthreads=0); - -/// Copy a subregion of src to the corresponding transposed (x<->y) -/// pixels of dst. In other words, for all (x,y) within the ROI, set -/// dst[y,x] = src[x,y]. -/// AB --> AC -/// CD BD -/// -/// Only the pixels (and channels) of src that are specified by roi will -/// be copied to dst; the default roi is to alter all the pixels in dst. -/// If dst is uninitialized, it will be resized to be an ImageBuf large -/// enough to hold the region specified by the transposed roi. It is an -/// error to pass both an uninitialied dst and an undefined roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API transpose (ImageBuf &dst, const ImageBuf &src, - ROI roi=ROI::All(), int nthreads=0); - - -/// Copy a subregion of src to the pixels of dst, but circularly -/// shifting by the given amount. To clarify, the circular shift -/// of [0,1,2,3,4,5] by +2 is [4,5,0,1,2,3]. -/// -/// Only the pixels (and channels) of src that are specified by roi will -/// be copied to dst; the default roi is to alter all the pixels in dst. -/// If dst is uninitialized, it will be resized to be an ImageBuf large -/// enough to hold the region specified by the transposed roi. It is an -/// error to pass both an uninitialied dst and an undefined roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API circular_shift (ImageBuf &dst, const ImageBuf &src, - int xshift, int yshift, int zshift=0, - ROI roi=ROI::All(), int nthreads=0); - - -/// Copy pixels from src to dst (within the ROI), clamping the values -/// as follows: -/// min[0..nchans-1] specifies the minimum clamp value for each channel -/// (if min is NULL, no minimum clamping is performed). -/// max[0..nchans-1] specifies the maximum clamp value for each channel -/// (if max is NULL, no maximum clamping is performed). -/// If clampalpha01 is true, then additionally any alpha channel is -/// clamped to the 0-1 range. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API clamp (ImageBuf &dst, const ImageBuf &src, - const float *min=NULL, const float *max=NULL, - bool clampalpha01 = false, - ROI roi = ROI::All(), int nthreads = 0); - -/// Copy pixels from src to dst (within the ROI), clamping the values of -/// as follows: -/// All channels are clamped to [min,max]. -/// If clampalpha01 is true, then additionally any alpha channel is -/// clamped to the 0-1 range. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API clamp (ImageBuf &dst, const ImageBuf &src, - float min=-std::numeric_limits::max(), - float max=std::numeric_limits::max(), - bool clampalpha01 = false, - ROI roi = ROI::All(), int nthreads = 0); - - -/// For all pixels within the designated region, set dst = A + B. -/// It is permitted for any of dst, A, or B to be the same image. -/// -/// If roi is not initialized, it will be set to the union of the pixel -/// regions of A and B. If dst is not initialized, it will be sized -/// based on roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API add (ImageBuf &dst, const ImageBuf &A, const ImageBuf &B, - ROI roi=ROI::All(), int nthreads=0); - -/// For all pixels and channels of dst within the designated region, set -/// dst = A + B. (B must point to nchannels floats.) It is permitted for -/// dst and A to be the same image. -/// -/// If roi is not initialized, it will be set to the pixel region of A. -/// If dst is not initialized, it will be sized based on roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API add (ImageBuf &dst, const ImageBuf &A, const float *B, - ROI roi=ROI::All(), int nthreads=0); - -/// For all pixels and channels of dst within the designated region, set -/// dst = A + B. (B is a single float that is added to all channels.) -/// It is permitted for dst and A to be the same image. -/// -/// If roi is not initialized, it will be set to the pixel region of A. -/// If dst is not initialized, it will be sized based on roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API add (ImageBuf &dst, const ImageBuf &A, float B, - ROI roi=ROI::All(), int nthreads=0); - - -/// For all pixels within the designated ROI, compute dst = A - B. -/// It is permitted for any of dst, A, or B to be the same image. -/// -/// If roi is not initialized, it will be set to the union of the pixel -/// regions of A and B. If dst is not initialized, it will be sized -/// based on roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API sub (ImageBuf &dst, const ImageBuf &A, const ImageBuf &B, - ROI roi=ROI::All(), int nthreads=0); - -/// For all pixels and channels of dst within the designated region, set -/// dst = A - B. (B must point to nchannels floats.) -/// It is permitted for dst and A to be the same image. -/// -/// If roi is not initialized, it will be set to the pixel region of A. -/// If dst is not initialized, it will be sized based on roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API sub (ImageBuf &dst, const ImageBuf &A, const float *B, - ROI roi=ROI::All(), int nthreads=0); - -/// For all pixels and channels of dst within the designated region, set -/// dst = A - B. (B is a single float that is added to all channels.) -/// It is permitted for dst and A to be the same image. -/// -/// If roi is not initialized, it will be set to the pixel region of A. -/// If dst is not initialized, it will be sized based on roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API sub (ImageBuf &dst, const ImageBuf &A, float B, - ROI roi=ROI::All(), int nthreads=0); - - -/// For all pixels within the designated ROI, compute dst = abs(A - B). -/// It is permitted for any of dst, A, or B to be the same image. -/// -/// A is an ImageBuf. B may be an ImageBuf (with the same number of channels -/// as A), or an array of floats (one per channel, for each channel of A), -/// or a single float (same value for all channels). -/// -/// If roi is not initialized, it will be set to the union of the pixel -/// regions of A and B. If dst is not initialized, it will be sized based -/// on roi. If dst is initialized, it also must have the same number of -/// channels as A. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API absdiff (ImageBuf &dst, const ImageBuf &A, const ImageBuf &B, - ROI roi=ROI::All(), int nthreads=0); -bool OIIO_API absdiff (ImageBuf &dst, const ImageBuf &A, const float *B, - ROI roi=ROI::All(), int nthreads=0); -bool OIIO_API absdiff (ImageBuf &dst, const ImageBuf &A, float B, - ROI roi=ROI::All(), int nthreads=0); - - -/// For all pixels within the designated ROI, compute dst = abs(A). -/// It is permitted for dst and A to be the same image. -/// -/// If roi is not initialized, it will be set to the pixel data region of A. -/// If dst is not initialized, it will be sized based on roi. If dst is -/// initialized, it must have the same number of channels as A. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API abs (ImageBuf &dst, const ImageBuf &A, - ROI roi=ROI::All(), int nthreads=0); - - -/// For all pixels within the designated ROI, compute dst = A * B. -/// All three images must have the same number of channels. -/// It is permitted for dst and A to be the same image. -/// -/// If roi is not initialized, it will be set to the union of the pixel -/// regions of A and B. If dst is not initialized, it will be sized -/// based on roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API mul (ImageBuf &dst, const ImageBuf &A, const ImageBuf &B, - ROI roi=ROI::All(), int nthreads=0); - - -/// For all pixels and channels of dst within region roi (defaulting to -/// all the defined pixels of dst), set dst = A * B. -/// It is permitted for dst and A to be the same image. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API mul (ImageBuf &dst, const ImageBuf &A, float B, - ROI roi=ROI::All(), int nthreads=0); - -/// For all pixels and channels of dst within region roi (defaulting to -/// all the defined pixels of dst), set dst = A * B. -/// It is permitted for dst and A to be the same image. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API mul (ImageBuf &dst, const ImageBuf &A, const float *B, - ROI roi=ROI::All(), int nthreads=0); - - -/// For all pixels within the designated ROI, compute dst = A / B. -/// We define division-by-zero to result in 0. -/// It is permitted for any of dst, A, or B to be the same image. -/// -/// A is an ImageBuf. B may be an ImageBuf (with the same number of channels -/// as A), or an array of floats (one per channel, for each channel of A), -/// or a single float (same value for all channels). -/// -/// If roi is not initialized, it will be set to the union of the pixel -/// regions of A and B. If dst is not initialized, it will be sized based -/// on roi. If dst is initialized, it also must have the same number of -/// channels as A. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API div (ImageBuf &dst, const ImageBuf &A, const ImageBuf &B, - ROI roi=ROI::All(), int nthreads=0); -bool OIIO_API div (ImageBuf &dst, const ImageBuf &A, const float *B, - ROI roi=ROI::All(), int nthreads=0); -bool OIIO_API div (ImageBuf &dst, const ImageBuf &A, float B, - ROI roi=ROI::All(), int nthreads=0); - - -/// For all pixels and channels of dst within region roi (defaulting to -/// all the defined pixels of dst), set dst = A * B + C. This is equivalent -/// to the sequence { mul(tmp,A,B); add(dst,tmp,C); }, but is likely to be -/// more efficient and not require a temporary ImageBuf. -/// It is permitted for any of dst, A, B, or C to be the same image. -/// -/// A is always an ImageBuf. B and C may either both be ImageBuf or both be -/// arrays of floats (one per channel, for each channel of A), -/// or both be a single float (same value for all channels). -/// -/// If roi is not initialized, it will be set to the union of the pixel -/// regions of A and B. If dst is not initialized, it will be sized based -/// on roi. If dst is initialized, it also must have the same number of -/// channels as A. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API mad (ImageBuf &dst, const ImageBuf &A, const ImageBuf &B, - const ImageBuf &C, ROI roi=ROI::All(), int nthreads=0); -bool OIIO_API mad (ImageBuf &dst, const ImageBuf &A, const float *B, - const float *C, ROI roi=ROI::All(), int nthreads=0); -bool OIIO_API mad (ImageBuf &dst, const ImageBuf &A, float B, - float C, ROI roi=ROI::All(), int nthreads=0); -inline bool OIIO_API mad (ImageBuf &dst, float A, const ImageBuf &B, - float C, ROI roi=ROI::All(), int nthreads=0) { - return mad (dst, B, A, C, roi, nthreads); -} - - -/// For all pixels and channels within the designated ROI, compute -/// dst = 1 - A. It is permitted for dst and A to be the same image. -/// -/// Tips for callers: (1) You probably want to set roi to restrict the -/// operation to only the color channels, and not accidentally include -/// alpha, z, or others. (2) There may be situations where you want to -/// unpremult() before the inverst, then premult() the result, so that you -/// are computing the inverse of the unmasked color. -/// -/// If roi is not initialized, it will be set to the pixel data region of A. -/// If dst is not initialized, it will be sized based on roi. If dst is -/// initialized, it must have the same number of channels as A. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API invert (ImageBuf &dst, const ImageBuf &A, - ROI roi=ROI::All(), int nthreads=0); - - -/// For all pixels and channels of dst within region roi (defaulting to -/// all the defined pixels of dst), set dst = A ^ b. (raise to power) -/// B may be either a single float (for all channels), or a float* pointing -/// to one value per channel of A. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API pow (ImageBuf &dst, const ImageBuf &A, float B, - ROI roi=ROI::All(), int nthreads=0); -bool OIIO_API pow (ImageBuf &dst, const ImageBuf &A, const float *B, - ROI roi=ROI::All(), int nthreads=0); - - -/// Converts a multi-channel image into a 1-channel image via a weighted -/// sum of channels. For each pixel of src within the designated ROI -/// (defaulting to all of src, if not defined), sum the channels -/// designated by roi and store the result in channel 0 of dst. If -/// weights is not NULL, weight[i] will provide a per-channel weight -/// (rather than defaulting to 1.0 for each channel). -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API channel_sum (ImageBuf &dst, const ImageBuf &src, - const float *weights=NULL, ROI roi=ROI::All(), - int nthreads=0); - -/// For all pixels and color channels within region roi (defaulting to all -/// the defined pixels of dst), copy pixels from src to dst, rescaling their -/// range with a logarithmic transformation. Alpha and z channels are not -/// transformed. If dst is not already defined and allocated, it will be -/// sized based on src and roi. -/// -/// If useluma is true, the luma of channels [roi.chbegin..roi.chbegin+2] -/// (presumed to be R, G, and B) are used to compute a single scale -/// factor for all color channels, rather than scaling all channels -/// individually (which could result in a color shift). -/// -/// Some image operations (such as resizing with a "good" filter that -/// contains negative lobes) can have objectionable artifacts when applied -/// to images with very high-contrast regions involving extra bright pixels -/// (such as highlights in HDR captured or rendered images). By compressing -/// the range pixel values, then performing the operation, then expanding -/// the range of the result again, the result can be much more pleasing -/// (even if not exactly correct). -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API rangecompress (ImageBuf &dst, const ImageBuf &src, - bool useluma = false, - ROI roi = ROI::All(), int nthreads=0); - -/// rangeexpand is the opposite operation of rangecompress -- rescales -/// the logarithmic color channel values back to a linear response. -bool OIIO_API rangeexpand (ImageBuf &dst, const ImageBuf &src, - bool useluma = false, - ROI roi = ROI::All(), int nthreads=0); - - -/// Copy pixels within the ROI from src to dst, applying a color transform. -/// In-place operations (dst == src) are supported. -/// -/// If dst is not yet initialized, it will be allocated to the same -/// size as specified by roi. If roi is not defined it will be all -/// of dst, if dst is defined, or all of src, if dst is not yet defined. -/// -/// If unpremult is true, unpremultiply before color conversion, then -/// premultiply after the color conversion. You may want to use this -/// flag if your image contains an alpha channel. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API colorconvert (ImageBuf &dst, const ImageBuf &src, - string_view from, string_view to, - bool unpremult=false, - ColorConfig *colorconfig=NULL, - ROI roi=ROI::All(), int nthreads=0); -// DEPRECATED (1.6) -bool OIIO_API colorconvert (ImageBuf &dst, const ImageBuf &src, - string_view from, string_view to, - bool unpremult, ROI roi, int nthreads=0); - -/// Copy pixels within the ROI from src to dst, applying a color transform. -/// In-place operations (dst == src) are supported. -/// -/// If dst is not yet initialized, it will be allocated to the same -/// size as specified by roi. If roi is not defined it will be all -/// of dst, if dst is defined, or all of src, if dst is not yet defined. -/// -/// If unpremult is true, unpremultiply before color conversion, then -/// premultiply after the color conversion. You may want to use this -/// flag if your image contains an alpha channel. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API colorconvert (ImageBuf &dst, const ImageBuf &src, - const ColorProcessor *processor, - bool unpremult, - ROI roi=ROI::All(), int nthreads=0); - -/// Apply a color transform in-place to just one color: -/// color[0..nchannels-1]. nchannels should either be 3 or 4 (if 4, the -/// last channel is alpha). -/// -/// If unpremult is true, unpremultiply before color conversion, then -/// premultiply after the color conversion. You'll may want to use this -/// flag if your image contains an alpha channel. -bool OIIO_API colorconvert (float *color, int nchannels, - const ColorProcessor *processor, bool unpremult); - - -/// Copy pixels within the ROI from src to dst, applying an OpenColorIO -/// "look" transform. In-place operations (dst == src) are supported. -/// -/// If dst is not yet initialized, it will be allocated to the same -/// size as specified by roi. If roi is not defined it will be all -/// of dst, if dst is defined, or all of src, if dst is not yet defined. -/// -/// If unpremult is true, unpremultiply before color conversion, then -/// premultiply after the color conversion. You may want to use this -/// flag if your image contains an alpha channel. If inverse is true, it -/// will reverse the color transformation. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API ociolook (ImageBuf &dst, const ImageBuf &src, - string_view looks, string_view from, string_view to, - bool unpremult=false, bool inverse=false, - string_view key="", string_view value="", - ColorConfig *colorconfig=NULL, - ROI roi=ROI::All(), int nthreads=0); -// DEPRECATED (1.6) -bool OIIO_API ociolook (ImageBuf &dst, const ImageBuf &src, - string_view looks, string_view from, string_view to, - bool unpremult, bool inverse, - string_view key, string_view value, - ROI roi, int nthreads=0); - -/// Copy pixels within the ROI from src to dst, applying an OpenColorIO -/// "display" transform. If from or looks are NULL, it will not -/// override the look or source color space (subtly different than -/// passing "", the empty string, which means to use no look or source -/// space). -/// -/// If dst is not yet initialized, it will be allocated to the same -/// size as specified by roi. If roi is not defined it will be all -/// of dst, if dst is defined, or all of src, if dst is not yet defined. -/// In-place operations (dst == src) are supported. -/// -/// If unpremult is true, unpremultiply before color conversion, then -/// premultiply after the color conversion. You may want to use this -/// flag if your image contains an alpha channel. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API ociodisplay (ImageBuf &dst, const ImageBuf &src, - string_view display, string_view view, - string_view from="", string_view looks="", - bool unpremult=false, - string_view key="", string_view value="", - ColorConfig *colorconfig=NULL, - ROI roi=ROI::All(), int nthreads=0); -// DEPRECATED (1.6) -bool OIIO_API ociodisplay (ImageBuf &dst, const ImageBuf &src, - string_view display, string_view view, - string_view from, string_view looks, - bool unpremult, string_view key, string_view value, - ROI roi, int nthreads=0); - -/// Copy pixels within the ROI from src to dst, applying an OpenColorIO -/// "file" transform. If inverse is true, it will reverse the color -/// transformation. In-place operations (dst == src) are supported. -/// -/// If dst is not yet initialized, it will be allocated to the same -/// size as specified by roi. If roi is not defined it will be all -/// of dst, if dst is defined, or all of src, if dst is not yet defined. -/// -/// If unpremult is true, unpremultiply before color conversion, then -/// premultiply after the color conversion. You may want to use this -/// flag if your image contains an alpha channel. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API ociofiletransform (ImageBuf &dst, const ImageBuf &src, - string_view name, - bool unpremult=false, bool inverse=false, - ColorConfig *colorconfig=NULL, - ROI roi=ROI::All(), int nthreads=0); - -/// Copy pixels from dst to src, and in the process divide all color -/// channels (those not alpha or z) by the alpha value, to "un-premultiply" -/// them. This presumes that the image starts of as "associated alpha" -/// a.k.a. "premultipled." The alterations are restricted to the pixels and -/// channels of the supplied ROI (which defaults to all of src). Pixels in -/// which the alpha channel is 0 will not be modified (since the operation -/// is undefined in that case). This is just a copy if there is no -/// identified alpha channel (and a no-op if dst and src are the same -/// image). -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API unpremult (ImageBuf &dst, const ImageBuf &src, - ROI roi = ROI::All(), int nthreads = 0); - -/// Copy pixels from dst to src, and in the process multiply all color -/// channels (those not alpha or z) by the alpha value, to "-premultiply" -/// them. This presumes that the image starts off as "unassociated alpha" -/// a.k.a. "non-premultiplied." The alterations are restricted to the -/// pixels and channels of the supplied ROI (which defaults to all of src). -/// Pixels in which the alpha channel is 0 will not be modified (since the -/// operation is undefined in that case). This is just a copy if there is -/// no identified alpha channel (and a no-op if dst and src are the same -/// image). -/// -/// For all dst pixels and channels within the ROI, divide all color -/// channels (those not alpha or z) by the alpha, to "un-premultiply" -/// them. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API premult (ImageBuf &dst, const ImageBuf &src, - ROI roi = ROI::All(), int nthreads = 0); - - - -struct OIIO_API PixelStats { - std::vector min; - std::vector max; - std::vector avg; - std::vector stddev; - std::vector nancount; - std::vector infcount; - std::vector finitecount; - std::vector sum, sum2; // for intermediate calculation -}; - - -/// Compute statistics about the ROI of the specified image. Upon success, -/// the returned vectors will have size == src.nchannels(). -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API computePixelStats (PixelStats &stats, const ImageBuf &src, - ROI roi=ROI::All(), int nthreads=0); - - -/// Struct holding all the results computed by ImageBufAlgo::compare(). -/// (maxx,maxy,maxz,maxc) gives the pixel coordintes (x,y,z) and color -/// channel of the pixel that differed maximally between the two images. -/// nwarn and nfail are the number of "warnings" and "failures", -/// respectively. -struct CompareResults { - double meanerror, rms_error, PSNR, maxerror; - int maxx, maxy, maxz, maxc; - imagesize_t nwarn, nfail; -}; - -/// Numerically compare two images. The difference threshold (for any -/// individual color channel in any pixel) for a "failure" is -/// failthresh, and for a "warning" is warnthresh. The results are -/// stored in result. If roi is defined, pixels will be compared for -/// the pixel and channel range that is specified. If roi is not -/// defined, the comparison will be for all channels, on the union of -/// the defined pixel windows of the two images (for either image, -/// undefined pixels will be assumed to be black). -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error. -bool OIIO_API compare (const ImageBuf &A, const ImageBuf &B, - float failthresh, float warnthresh, - CompareResults &result, - ROI roi = ROI::All(), int nthreads=0); - -/// Compare two images using Hector Yee's perceptual metric, returning -/// the number of pixels that fail the comparison. Only the first three -/// channels (or first three channels specified by roi) are compared. -/// Free parameters are the ambient luminance in the room and the field -/// of view of the image display; our defaults are probably reasonable -/// guesses for an office environment. The 'result' structure will -/// store the maxerror, and the maxx, maxy, maxz of the pixel that -/// failed most severely. (The other fields of the CompareResults -/// are not used for Yee comparison.) -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Works for all pixel types. But it's basically meaningless if the -/// first three channels aren't RGB in a linear color space that sort -/// of resembles AdobeRGB. -/// -/// Return true on success, false on error. -int OIIO_API compare_Yee (const ImageBuf &A, const ImageBuf &B, - CompareResults &result, - float luminance = 100, float fov = 45, - ROI roi = ROI::All(), int nthreads = 0); - - -/// Do all pixels within the ROI have the same values for channels -/// [roi.chbegin..roi.chend-1]? If so, return true and store that color -/// in color[chbegin...chend-1] (if color != NULL); otherwise return -/// false. If roi is not defined (the default), it will be understood -/// to be all of the defined pixels and channels of source. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -bool OIIO_API isConstantColor (const ImageBuf &src, float *color = NULL, - ROI roi = ROI::All(), int nthreads=0); - -/// Does the requested channel have a given value over the ROI? (For -/// this function, the ROI's chbegin/chend are ignored.) Return true if -/// so, otherwise return false. If roi is not defined (the default), it -/// will be understood to be all of the defined pixels and channels of -/// source. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -bool OIIO_API isConstantChannel (const ImageBuf &src, int channel, float val, - ROI roi = ROI::All(), int nthreads = 0); - -/// Is the image monochrome within the ROI, i.e., for all pixels within -/// the region, do all channels [roi.chbegin, roi.chend) have the same -/// value? If roi is not defined (the default), it will be understood -/// to be all of the defined pixels and channels of source. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -bool OIIO_API isMonochrome (const ImageBuf &src, - ROI roi = ROI::All(), int nthreads = 0); - -/// Count how many pixels in the ROI match a list of colors. -/// -/// The colors to match are in colors[0..nchans-1], -/// colors[nchans..2*nchans-1], and so on, a total of ncolors -/// consecutive colors of nchans each. -/// -/// eps[0..nchans-1] are the error tolerances for a match, for each -/// channel. Setting eps[c] = numeric_limits::max() will -/// effectively make it ignore the channel. Passing eps == NULL will be -/// interpreted as a tolerance of 0.001 for all channels (requires exact -/// matches for 8 bit images, but allows a wee bit of imprecision for -/// float images. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Upon success, return true and store the number of pixels that -/// matched each color count[..ncolors-1]. If there is an error, -/// returns false and sets an appropriate error message set in src. -bool OIIO_API color_count (const ImageBuf &src, - imagesize_t *count, - int ncolors, const float *color, - const float *eps=NULL, - ROI roi=ROI::All(), int nthreads=0); - -/// Count how many pixels in the ROI are outside the value range. -/// low[0..nchans-1] and high[0..nchans-1] are the low and high -/// acceptable values for each color channel. -/// -/// The number of pixels containing values that fall below the lower -/// bound will be stored in *lowcount, the number of pixels containing -/// values that fall above the upper bound will be stored in *highcount, -/// and the number of pixels for which all channels fell within the -/// bounds will be stored in *inrangecount. Any of these may be NULL, -/// which simply means that the counts need not be collected or stored. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true if the operation can be performed, false if there is -/// some sort of error (and sets an appropriate error message in src). -bool OIIO_API color_range_check (const ImageBuf &src, - imagesize_t *lowcount, - imagesize_t *highcount, - imagesize_t *inrangecount, - const float *low, const float *high, - ROI roi=ROI::All(), int nthreads=0); - -/// Find the minimal rectangular region within roi (which defaults to -/// the entire pixel data window of src) that consists of nonzero pixel -/// values. In other words, gives the region that is a "shrink-wraps" -/// of src to exclude black border pixels. Note that if the entire -/// image was black, the ROI returned will contain no pixels. -/// -/// For "deep" images, this function returns the smallest ROI that contains -/// all pixels that contain depth samples, and excludes the border pixels -/// that contain no depth samples at all. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -OIIO_API ROI nonzero_region (const ImageBuf &src, - ROI roi=ROI::All(), int nthreads=0); - -/// Compute the SHA-1 byte hash for all the pixels in the specifed -/// region of the image. If blocksize > 0, the function will compute -/// separate SHA-1 hashes of each 'blocksize' batch of scanlines, then -/// return a hash of the individual hashes. This is just as strong a -/// hash, but will NOT match a single hash of the entire image -/// (blocksize==0). But by breaking up the hash into independent -/// blocks, we can parallelize across multiple threads, given by -/// nthreads (if nthreads is 0, it will use the global OIIO thread -/// count). The 'extrainfo' provides additional text that will be -/// incorporated into the hash. -std::string OIIO_API computePixelHashSHA1 (const ImageBuf &src, - string_view extrainfo = "", - ROI roi = ROI::All(), - int blocksize = 0, int nthreads=0); - - -/// Warp the src image using the supplied 3x3 transformation matrix. -/// -/// Only the pixels (and channels) of dst that are specified by roi will be -/// copied from the warped src; the default roi is to alter all the pixels -/// in dst. If dst is uninitialized, it will be sized to be an ImageBuf -/// large enough to hold the warped image if recompute_roi is true, or -/// will have the same ROI as src if recompute_roi is false. It is an error -/// to pass both an uninitialied dst and an undefined roi. -/// -/// The filter is used to weight the src pixels falling underneath it for -/// each dst pixel. The caller may specify a reconstruction filter by name -/// and width (expressed in pixels unts of the dst image), or rotate() will -/// choose a reasonable default high-quality default filter (lanczos3) if -/// the empty string is passed, and a reasonable filter width if filterwidth -/// is 0. (Note that some filter choices only make sense with particular -/// width, in which case this filterwidth parameter may be ignored.) -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API warp (ImageBuf &dst, const ImageBuf &src, - const Imath::M33f &M, - string_view filtername = string_view(), - float filterwidth = 0.0f, - bool recompute_roi = false, - ImageBuf::WrapMode wrap = ImageBuf::WrapDefault, - ROI roi=ROI::All(), int nthreads=0); -bool OIIO_API warp (ImageBuf &dst, const ImageBuf &src, - const Imath::M33f &M, - const Filter2D *filter, - bool recompute_roi = false, - ImageBuf::WrapMode wrap = ImageBuf::WrapDefault, - ROI roi = ROI::All(), int nthreads = 0); - - -/// Rotate the src image by the angle (in radians, with positive angles -/// clockwise). When center_x and center_y are supplied, they denote the -/// center of rotation; in their absence, the rotation will be about the -/// center of the image's display window. -/// -/// Only the pixels (and channels) of dst that are specified by roi will be -/// copied from the rotated src; the default roi is to alter all the pixels -/// in dst. If dst is uninitialized, it will be resized to be an ImageBuf -/// large enough to hold the rotated image if recompute_roi is true, or will -/// have the same ROI as src if recompute_roi is false. It is an error to -/// pass both an uninitialied dst and an undefined roi. -/// -/// The filter is used to weight the src pixels falling underneath it for -/// each dst pixel. The caller may specify a reconstruction filter by name -/// and width (expressed in pixels unts of the dst image), or rotate() will -/// choose a reasonable default high-quality default filter (lanczos3) if -/// the empty string is passed, and a reasonable filter width if filterwidth -/// is 0. (Note that some filter choices only make sense with particular -/// width, in which case this filterwidth parameter may be ignored.) -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API rotate (ImageBuf &dst, const ImageBuf &src, float angle, - string_view filtername = string_view(), - float filterwidth = 0.0f, - bool recompute_roi = false, - ROI roi=ROI::All(), int nthreads=0); -bool OIIO_API rotate (ImageBuf &dst, const ImageBuf &src, float angle, - Filter2D *filter, - bool recompute_roi = false, - ROI roi = ROI::All(), int nthreads = 0); -bool OIIO_API rotate (ImageBuf &dst, const ImageBuf &src, - float angle, float center_x, float center_y, - string_view filtername = string_view(), - float filterwidth = 0.0f, - bool recompute_roi = false, - ROI roi=ROI::All(), int nthreads=0); -bool OIIO_API rotate (ImageBuf &dst, const ImageBuf &src, - float angle, float center_x, float center_y, - Filter2D *filter, - bool recompute_roi = false, - ROI roi = ROI::All(), int nthreads = 0); - - -/// Set dst, over the region of interest, to be a resized version of the -/// corresponding portion of src (mapping such that the "full" image -/// window of each correspond to each other, regardless of resolution). -/// -/// The filter is used to weight the src pixels falling underneath it for -/// each dst pixel. The caller may specify a reconstruction filter by name -/// and width (expressed in pixels unts of the dst image), or resize() will -/// choose a reasonable default high-quality default filter (blackman-harris -/// when upsizing, lanczos3 when downsizing) if the empty string is passed -/// or if filterwidth is 0. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API resize (ImageBuf &dst, const ImageBuf &src, - string_view filtername = "", - float filterwidth = 0.0f, - ROI roi = ROI::All(), int nthreads = 0); - -/// Set dst, over the region of interest, to be a resized version of the -/// corresponding portion of src (mapping such that the "full" image -/// window of each correspond to each other, regardless of resolution). -/// -/// The caller may explicitly pass a reconstruction filter, or resize() -/// will choose a reasonable default if NULL is passed. The filter is -/// used to weight the src pixels falling underneath it for each dst -/// pixel; the filter's size is expressed in pixel units of the dst -/// image. If no filter is supplied, a default medium-quality -/// (triangle) filter will be used. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API resize (ImageBuf &dst, const ImageBuf &src, - Filter2D *filter, - ROI roi = ROI::All(), int nthreads = 0); - - -/// Set dst, over the region of interest, to be a resampled version of the -/// corresponding portion of src (mapping such that the "full" image -/// window of each correspond to each other, regardless of resolution). -/// -/// Unlike ImageBufAlgo::resize(), resample does not take a filter; it -/// just samples either with a bilinear interpolation (if interpolate is -/// true, the default) or uses the single "closest" pixel (if -/// interpolate is false). This makes it a lot faster than a proper -/// resize(), though obviously with lower quality (aliasing when -/// downsizing, pixel replication when upsizing). -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API resample (ImageBuf &dst, const ImageBuf &src, - bool interpolate = true, - ROI roi = ROI::All(), int nthreads = 0); - -/// Replace the given ROI of dst with the convolution of src and -/// a kernel. If roi is not defined, it defaults to the full size -/// of dst (or src, if dst was uninitialized). If dst is uninitialized, -/// it will be allocated to be the size specified by roi. If -/// normalized is true, the kernel will be normalized for the -/// convolution, otherwise the original values will be used. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API convolve (ImageBuf &dst, const ImageBuf &src, - const ImageBuf &kernel, bool normalize = true, - ROI roi = ROI::All(), int nthreads = 0); - -/// Initialize dst to be a 1-channel FLOAT image of the named kernel. -/// The size of the dst image will be big enough to contain the kernel -/// given its size (width x height) and rounded up to odd resolution so -/// that the center of the kernel can be at the center of the middle -/// pixel. The kernel image will be offset so that its center is at the -/// (0,0) coordinate. If normalize is true, the values will be -/// normalized so that they sum to 1.0. -/// -/// If depth > 1, a volumetric kernel will be created. Use with caution! -/// -/// Kernel names can be: "gaussian", "sharp-gaussian", "box", -/// "triangle", "blackman-harris", "mitchell", "b-spline", "catmull-rom", -/// "lanczos3", "disk", "binomial." -/// -/// Note that "catmull-rom" and "lanczos3" are fixed-size kernels that -/// don't scale with the width, and are therefore probably less useful -/// in most cases. -/// -bool OIIO_API make_kernel (ImageBuf &dst, string_view name, - float width, float height, float depth = 1.0f, - bool normalize = true); - -/// Replace the given ROI of dst with a sharpened version of the -/// corresponding region of src using the ``unsharp mask'' technique. -/// Unsharp masking basically works by first blurring the image (low -/// pass filter), subtracting this from the original image, then -/// adding the residual back to the original to emphasize the edges. -/// Roughly speaking, -/// dst = src + contrast * thresh(src - blur(src)) -/// -/// The specific blur can be selected by kernel name and width. The -/// contrast is a multiplier on the overall sharpening effect. The -/// thresholding step causes all differences less than 'threshold' to be -/// squashed to zero, which can be useful for suppressing sharpening of -/// low-contrast details (like noise) but allow sharpening of -/// higher-contrast edges. -/// -/// If roi is not defined, it defaults to the full size of dst (or src, -/// if dst was undefined). If dst is uninitialized, it will be -/// allocated to be the size specified by roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API unsharp_mask (ImageBuf &dst, const ImageBuf &src, - string_view kernel="gaussian", float width = 3.0f, - float contrast = 1.0f, float threshold = 0.0f, - ROI roi = ROI::All(), int nthreads = 0); - - -/// Replace the given ROI of dst with a median-filtered version of the -/// corresponding region of src. The size of the window over which the -/// median is computed is given by width and height (if height is <= 0, -/// it will be set to width, making a square filter). -/// -/// Median filters are good for removing high-frequency detail smaller than -/// the window size (including noise), without blurring edges that are -/// larger than the window size. -/// -/// If roi is not defined, it defaults to the full size of dst (or src, -/// if dst was undefined). If dst is uninitialized, it will be -/// allocated to be the size specified by roi. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API median_filter (ImageBuf &dst, const ImageBuf &src, - int width = 3, int height = -1, - ROI roi = ROI::All(), int nthreads = 0); - - -/// Take the discrete Fourier transform (DFT) of the section of src -/// denoted by roi, store it in dst. If roi is not defined, it will be -/// all of src's pixels. Only one channel of src may be FFT'd at a -/// time, so it will be the first channel described by roi (or, again, -/// channel 0 if roi is undefined). If not already in the correct -/// format, dst will be re-allocated to be a 2-channel float buffer of -/// size width x height, with channel 0 being the "real" part and -/// channel 1 being the the "imaginary" part. The values returned are -/// actually the unitary DFT, meaning that it is scaled by 1/sqrt(npixels). -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Works on all pixel data type for src; dst will always be reallocated -/// as FLOAT. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API fft (ImageBuf &dst, const ImageBuf &src, - ROI roi = ROI::All(), int nthreads = 0); - -/// Take the inverse discrete Fourier transform of the section of src -/// denoted by roi, store it in dst. If roi is not defined, it will be -/// all of src's pixels. -/// -/// Src MUST be a 2-channel float image, and is assumed to be a complex -/// frequency-domain signal with the "real" component in channel 0 and -/// the "imaginary" component in channel 1. Dst will end up being a -/// float image of one channel (the real component is kept, the -/// imaginary component of the spatial-domain will be discarded). -/// Just as with fft(), the ifft() function is dealing with the unitary -/// DFT, so it is scaled by 1/sqrt(npixels). -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API ifft (ImageBuf &dst, const ImageBuf &src, - ROI roi = ROI::All(), int nthreads = 0); - - -/// Convert a 2-channel image with "polar" values (amplitude, phase) -/// into a 2-channel image with complex values (real, imaginary). -/// -/// The transformation between the two representations are: -/// real = amplitude * cos(phase); -/// imag = amplitude * sin(phase); -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API polar_to_complex (ImageBuf &dst, const ImageBuf &src, - ROI roi = ROI::All(), int nthreads = 0); - -/// Convert a 2-channel image with complex values (real, imaginary) into a -/// 2-channel image with "polar" values (amplitude, phase). -/// -/// The transformation between the two representations are: -/// amplitude = hypot (real, imag); -/// phase = atan2 (imag, real); -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API complex_to_polar (ImageBuf &dst, const ImageBuf &src, - ROI roi = ROI::All(), int nthreads = 0); - - -enum OIIO_API NonFiniteFixMode -{ - NONFINITE_NONE = 0, ///< Do nothing - NONFINITE_BLACK = 1, ///< Replace nonfinite pixels with black - NONFINITE_BOX3 = 2, ///< Replace nonfinite pixels with 3x3 finite average -}; - -/// Copy the values of src (within the ROI) to dst, while repairing any -/// non-finite (NaN/Inf) pixels. If pixelsFound is not NULL, store in it the -/// number of pixels that contained non-finite value. It is permissible -/// to operate in-place (with src and dst referring to the same image). -/// -/// How the non-finite values are repaired is specified by one of the -/// following modes: -/// NONFINITE_NONE do not alter the pixels (but do count the number -/// of nonfinite pixels in *pixelsFixed, if non-NULL). -/// NONFINITE_BLACK change non-finite values to 0. -/// NONFINITE_BOX3 replace non-finite values by the average of any -/// finite pixels within a 3x3 window. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Works on all pixel data types, though it's just a copy for images with -/// pixel data types that cannot represent NaN or Inf values. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API fixNonFinite (ImageBuf &dst, const ImageBuf &src, - NonFiniteFixMode mode=NONFINITE_BOX3, - int *pixelsFixed = NULL, - ROI roi = ROI::All(), int nthreads = 0); - - -/// Fill the holes using a push-pull technique. The src image must have -/// an alpha channel. The dst image will end up with a copy of src, but -/// will have an alpha of 1.0 everywhere, and any place where the alpha -/// of src was < 1, dst will have a pixel color that is a plausible -/// "filling" of the original alpha hole. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -/// -/// Return true on success, false on error (with an appropriate error -/// message set in dst). -bool OIIO_API fillholes_pushpull (ImageBuf &dst, const ImageBuf &src, - ROI roi = ROI::All(), int nthreads = 0); - - -/// Convert an IplImage, used by OpenCV and Intel's Image Libray, and -/// set ImageBuf dst to be the same image (copying the pixels). If -/// convert is not set to UNKNOWN, try to establish dst as holding that -/// data type and convert the IplImage data. Return true if ok, false -/// if it couldn't figure out how to make the conversion from IplImage -/// to ImageBuf. If OpenImageIO was compiled without OpenCV support, -/// this function will return false without modifying dst. -bool OIIO_API from_IplImage (ImageBuf &dst, const IplImage *ipl, - TypeDesc convert=TypeDesc::UNKNOWN); - -/// Construct an IplImage*, used by OpenCV and Intel's Image Library, -/// that is equivalent to the ImageBuf src. If it is not possible, or -/// if OpenImageIO was compiled without OpenCV support, then return -/// NULL. The ownership of the IplImage is fully transferred to the -/// calling application. -OIIO_API IplImage* to_IplImage (const ImageBuf &src); - -/// Capture a still image from a designated camera. If able to do so, -/// store the image in dst and return true. If there is no such device, -/// or support for camera capture is not available (such as if OpenCV -/// support was not enabled at compile time), return false and do not -/// alter dst. -bool OIIO_API capture_image (ImageBuf &dst, int cameranum = 0, - TypeDesc convert=TypeDesc::UNKNOWN); - - - -/// Set dst to the composite of A over B using the Porter/Duff definition -/// of "over", returning true upon success and false for any of a -/// variety of failures (as described below). -/// -/// A and B (and dst, if already defined/allocated) must have valid alpha -/// channels identified by their ImageSpec alpha_channel field. If A or -/// B do not have alpha channels (as determined by those rules) or if -/// the number of non-alpha channels do not match between A and B, -/// over() will fail, returning false. -/// -/// If dst is not already an initialized ImageBuf, it will be sized to -/// encompass the minimal rectangular pixel region containing the union -/// of the defined pixels of A and B, and with a number of channels -/// equal to the number of non-alpha channels of A and B, plus an alpha -/// channel. However, if dst is already initialized, it will not be -/// resized, and the "over" operation will apply to its existing pixel -/// data window. In this case, dst must have an alpha channel designated -/// and must have the same number of non-alpha channels as A and B, -/// otherwise it will fail, returning false. -/// -/// 'roi' specifies the region of dst's pixels which will be computed; -/// existing pixels outside this range will not be altered. If not -/// specified, the default ROI value will be interpreted as a request to -/// apply "A over B" to the entire region of dst's pixel data. -/// -/// A, B, and dst need not perfectly overlap in their pixel data windows; -/// pixel values of A or B that are outside their respective pixel data -/// window will be treated as having "zero" (0,0,0...) value. -/// -/// The nthreads parameter specifies how many threads (potentially) may -/// be used, but it's not a guarantee. If nthreads == 0, it will use -/// the global OIIO attribute "nthreads". If nthreads == 1, it -/// guarantees that it will not launch any new threads. -bool OIIO_API over (ImageBuf &dst, const ImageBuf &A, const ImageBuf &B, - ROI roi = ROI::All(), int nthreads = 0); - - -/// Just like ImageBufAlgo::over(), but inputs A and B must have -/// designated 'z' channels, and on a pixel-by-pixel basis, the z values -/// will determine which of A or B will be considered the foreground or -/// background (lower z is foreground). If z_zeroisinf is true, then -/// z=0 values will be treated as if they are infinitely far away. -bool OIIO_API zover (ImageBuf &dst, const ImageBuf &A, const ImageBuf &B, - bool z_zeroisinf = false, - ROI roi = ROI::All(), int nthreads = 0); - - - -/// Render a text string (encoded as UTF-8) into image dst, essentially -/// doing an "over" of the character into the existing pixel data. The -/// baseline of the first character will start at position (x,y). The font -/// is given by fontname as a full pathname to the font file (defaulting to -/// some reasonable system font if not supplied at all), and with a nominal -/// height of fontsize (in pixels). The characters will be drawn in opaque -/// white (1.0,1.0,...) in all channels, unless textcolor is supplied (and -/// is expected to point to a float array of length at least equal to -/// R.spec().nchannels). -bool OIIO_API render_text (ImageBuf &dst, int x, int y, - string_view text, - int fontsize=16, string_view fontname="", - const float *textcolor = NULL); - - -/// ImageBufAlgo::histogram -------------------------------------------------- -/// Parameters: -/// src - Input image that contains the one channel to be histogramed. -/// src must contain float pixel data and have at least 1 channel, -/// but it can have more. -/// channel - Only this channel in src will be histogramed. It must satisfy -/// 0 <= channel < src.nchannels(). -/// histogram - Clear old content and store the histogram here. -/// bins - Number of bins must be at least 1. -/// min, max - Pixel values outside of the min->max range are not used for -/// computing the histogram. If min max. -/// roi - Only pixels in this region of the image are histogramed. If -/// roi is not defined then the full size image will be -/// histogramed. -/// -------------------------------------------------------------------------- -bool OIIO_API histogram (const ImageBuf &src, int channel, - std::vector &histogram, int bins=256, - float min=0, float max=1, imagesize_t *submin=NULL, - imagesize_t *supermax=NULL, ROI roi=ROI::All()); - - - -/// ImageBufAlgo::histogram_draw --------------------------------------------- -/// Parameters: -/// dst - The histogram will be drawn in the image dst. which must -/// have only 1 channel with float pixel data, and width equal -/// to the number of bins, that is elements in histogram. -/// histogram - The histogram to be drawn, must have at least 1 bin. -/// -------------------------------------------------------------------------- -bool OIIO_API histogram_draw (ImageBuf &dst, - const std::vector &histogram); - - - -enum OIIO_API MakeTextureMode { - MakeTxTexture, MakeTxShadow, MakeTxEnvLatl, - MakeTxEnvLatlFromLightProbe, - _MakeTxLast -}; - -/// Turn an image into a tiled, MIP-mapped, texture file and write it to -/// disk (outputfilename). The 'mode' describes what type of texture -/// file we are creating and may be one of: -/// MakeTxTexture Ordinary 2D texture -/// MakeTxEnvLatl Latitude-longitude environment map -/// MakeTxEnvLatlFromLightProbe Latitude-longitude environment map -/// constructed from a "light probe" image. -/// -/// If the outstream pointer is not NULL, it should point to a stream -/// (for example, &std::out, or a pointer to a local std::stringstream -/// to capture output), which is where console output and error messages -/// will be deposited. -/// -/// The 'config' is an ImageSpec that contains all the information and -/// special instructions for making the texture. Anything set in config -/// (format, tile size, or named metadata) will take precedence over -/// whatever is specified by the input file itself. Additionally, named -/// metadata that starts with "maketx:" will not be output to the file -/// itself, but may contain instructions controlling how the texture is -/// created. The full list of supported configuration options is: -/// -/// Named fields: -/// format Data format of the texture file (default: UNKNOWN = -/// same format as the input) -/// tile_width Preferred tile size (default: 64x64x1) -/// tile_height -/// tile_depth -/// Metadata in config.extra_attribs: -/// compression (string) Default: "zip" -/// fovcot (float) Default: aspect ratio of the image resolution -/// planarconfig (string) Default: "separate" -/// worldtocamera (matrix) World-to-camera matrix of the view. -/// worldtoscreen (matrix) World-to-screen space matrix of the view. -/// wrapmodes (string) Default: "black,black" -/// maketx:verbose (int) How much detail should go to outstream (0). -/// maketx:runstats (int) If nonzero, print run stats to outstream (0). -/// maketx:resize (int) If nonzero, resize to power of 2. (0) -/// maketx:nomipmap (int) If nonzero, only output the top MIP level (0). -/// maketx:updatemode (int) If nonzero, write new output only if the -/// output file doesn't already exist, or is -/// older than the input file, or was created -/// with different command-line arguments. (0) -/// maketx:constant_color_detect (int) -/// If nonzero, detect images that are entirely -/// one color, and change them to be low -/// resolution (default: 0). -/// maketx:monochrome_detect (int) -/// If nonzero, change RGB images which have -/// R==G==B everywhere to single-channel -/// grayscale (default: 0). -/// maketx:opaque_detect (int) -/// If nonzero, drop the alpha channel if alpha -/// is 1.0 in all pixels (default: 0). -/// maketx:compute_average (int) -/// If nonzero, compute and store the average -/// color of the texture (default: 1). -/// maketx:unpremult (int) If nonzero, unpremultiply color by alpha before -/// color conversion, then multiply by alpha -/// after color conversion (default: 0). -/// maketx:incolorspace (string) -/// maketx:outcolorspace (string) -/// These two together will apply a color conversion -/// (with OpenColorIO, if compiled). Default: "" -/// maketx:checknan (int) If nonzero, will consider it an error if the -/// input image has any NaN pixels. (0) -/// maketx:fixnan (string) If set to "black" or "box3", will attempt -/// to repair any NaN pixels found in the -/// input image (default: "none"). -/// maketx:set_full_to_pixels (int) -/// If nonzero, doctors the full/display window -/// of the texture to be identical to the -/// pixel/data window and reset the origin -/// to 0,0 (default: 0). -/// maketx:filtername (string) -/// If set, will specify the name of a high-quality -/// filter to use when resampling for MIPmap -/// levels. Default: "", use bilinear resampling. -/// maketx:highlightcomp (int) -/// If nonzero, performs highlight compensation -- -/// range compression and expansion around -/// the resize, plus clamping negative plxel -/// values to zero. This reduces ringing when -/// using filters with negative lobes on HDR -/// images. -/// maketx:sharpen (float) If nonzero, sharpens details when creating -/// MIPmap levels. The amount is the contrast -/// matric. The default is 0, meaning no -/// sharpening. -/// maketx:nchannels (int) If nonzero, will specify how many channels -/// the output texture should have, padding with -/// 0 values or dropping channels, if it doesn't -/// the number of channels in the input. -/// (default: 0, meaning keep all input channels) -/// maketx:channelnames (string) -/// If set, overrides the channel names of the -/// output image (comma-separated). -/// maketx:fileformatname (string) -/// If set, will specify the output file format. -/// (default: "", meaning infer the format from -/// the output filename) -/// maketx:prman_metadata (int) -/// If set, output some metadata that PRMan will -/// need for its textures. (0) -/// maketx:oiio_options (int) -/// (Deprecated; all are handled by default) -/// maketx:prman_options (int) -/// If nonzero, override a whole bunch of settings -/// as needed to make textures that are -/// compatible with PRMan. (0) -/// maketx:mipimages (string) -/// Semicolon-separated list of alternate images -/// to be used for individual MIPmap levels, -/// rather than simply downsizing. (default: "") -/// maketx:full_command_line (string) -/// The command or program used to generate this -/// call, will be embedded in the metadata. -/// (default: "") -/// maketx:ignore_unassoc (int) -/// If nonzero, will disbelieve any evidence that -/// the input image is unassociated alpha. (0) -/// maketx:read_local_MB (int) -/// If nonzero, will read the full input file locally -/// if it is smaller than this threshold. Zero -/// causes the system to make a good guess at -/// a reasonable threshold (e.g. 1 GB). (0) -/// maketx:forcefloat (int) -/// Forces a conversion through float data for -/// the sake of ImageBuf math. (1) -/// maketx:hash (int) -/// Compute the sha1 hash of the file in parallel. (1) -/// maketx:allow_pixel_shift (int) -/// Allow up to a half pixel shift per mipmap level. -/// The fastest path may result in a slight shift -/// in the image, accumulated for each mip level -/// with an odd resolution. (0) -/// -bool OIIO_API make_texture (MakeTextureMode mode, - const ImageBuf &input, - string_view outputfilename, - const ImageSpec &config, - std::ostream *outstream = NULL); - -/// Version of make_texture that starts with a filename and reads the input -/// from that file, rather than being given an ImageBuf directly. -bool OIIO_API make_texture (MakeTextureMode mode, - string_view filename, - string_view outputfilename, - const ImageSpec &config, - std::ostream *outstream = NULL); - -/// Version of make_texture that takes multiple filenames (reserved for -/// future expansion, such as assembling several faces into a cube map). -bool OIIO_API make_texture (MakeTextureMode mode, - const std::vector &filenames, - string_view outputfilename, - const ImageSpec &config, - std::ostream *outstream = NULL); - - - - -} // end namespace ImageBufAlgo - -OIIO_NAMESPACE_END - -#endif // OPENIMAGEIO_IMAGEBUFALGO_H diff --git a/3rdparty/oiio16/include/OpenImageIO/imagebufalgo_util.h b/3rdparty/oiio16/include/OpenImageIO/imagebufalgo_util.h deleted file mode 100644 index b92a7bbf..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/imagebufalgo_util.h +++ /dev/null @@ -1,415 +0,0 @@ -/* - Copyright 2013 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -#ifndef OPENIMAGEIO_IMAGEBUFALGO_UTIL_H -#define OPENIMAGEIO_IMAGEBUFALGO_UTIL_H - -#include -#include -#include - -#if OIIO_CPLUSPLUS_VERSION >= 11 -# include -#else -# include -#endif - - -OIIO_NAMESPACE_BEGIN - -#if OIIO_CPLUSPLUS_VERSION >= 11 -using std::bind; -using std::ref; -using std::cref; -using namespace std::placeholders; -using std::placeholders::_1; -#else -using boost::bind; -using boost::ref; -using boost::cref; -using boost::this_thread::get_id; -#endif - - - -namespace ImageBufAlgo { - -/// Helper template for generalized multithreading for image processing -/// functions. Some function/functor f is applied to every pixel the -/// region of interest roi, dividing the region into multiple threads if -/// threads != 1. Note that threads == 0 indicates that the number of -/// threads should be as set by the global OIIO "threads" attribute. -/// -/// Most image operations will require additional arguments, including -/// additional input and output images or other parameters. The -/// parallel_image template can still be used by employing the -/// std::bind (or boost::bind, for C++ < 11). For example, suppose you -/// have an image operation defined as: -/// void my_image_op (ImageBuf &out, const ImageBuf &in, -/// float scale, ROI roi); -/// Then you can parallelize it as follows: -/// ImageBuf R /*result*/, A /*input*/; -/// ROI roi = get_roi (R.spec()); -/// parallel_image (bind(my_image_op,ref(R), cref(A),3.14,_1), -/// roi); -/// -template -void -parallel_image (Func f, ROI roi, int nthreads=0) -{ - // Special case: threads <= 0 means to use the "threads" attribute - if (nthreads <= 0) - OIIO::getattribute ("threads", nthreads); - - if (nthreads <= 1 || roi.npixels() < 1000) { - // Just one thread, or a small image region: use this thread only - f (roi); - } else { - // Spawn threads by dividing the region into y bands. - OIIO::thread_group threads; - int blocksize = std::max (1, (roi.height() + nthreads - 1) / nthreads); - int roi_ybegin = roi.ybegin; - int roi_yend = roi.yend; - for (int i = 0; i < nthreads; i++) { - roi.ybegin = roi_ybegin + i * blocksize; - roi.yend = std::min (roi.ybegin + blocksize, roi_yend); - if (roi.ybegin >= roi.yend) - break; // no more work to dole out - threads.add_thread (new OIIO::thread (f, roi)); - } - threads.join_all (); - } -} - - - -/// Common preparation for IBA functions: Given an ROI (which may or may not -/// be the default ROI::All()), destination image (which may or may not yet -/// be allocated), and optional input images, adjust roi if necessary and -/// allocate pixels for dst if necessary. If dst is already initialized, it -/// will keep its "full" (aka display) window, otherwise its full/display -/// window will be set to the union of A's and B's full/display windows. If -/// dst is uninitialized and force_spec is not NULL, use *force_spec as -/// dst's new spec rather than using A's. Also, if A or B inputs are -/// specified but not initialized or broken, it's an error so return false. -/// If all is ok, return true. Some additional checks and behaviors may be -/// specified by the 'prepflags', which is a bit field defined by -/// IBAprep_flags. -bool OIIO_API IBAprep (ROI &roi, ImageBuf *dst, const ImageBuf *A=NULL, - const ImageBuf *B=NULL, const ImageBuf *C=NULL, - ImageSpec *force_spec=NULL, int prepflags=0); -inline bool IBAprep (ROI &roi, ImageBuf *dst, const ImageBuf *A, - const ImageBuf *B, ImageSpec *force_spec, - int prepflags=0) { - return IBAprep (roi, dst, A, B, NULL, force_spec, prepflags); -} -inline bool IBAprep (ROI &roi, ImageBuf *dst, - const ImageBuf *A, int prepflags) { - return IBAprep (roi, dst, A, NULL, NULL, NULL, prepflags); -} - -enum IBAprep_flags { - IBAprep_DEFAULT = 0, - IBAprep_REQUIRE_ALPHA = 1, - IBAprep_REQUIRE_Z = 2, - IBAprep_REQUIRE_SAME_NCHANNELS = 4, - IBAprep_NO_COPY_ROI_FULL = 8, // Don't copy the src's roi_full - IBAprep_NO_SUPPORT_VOLUME = 16, // Don't know how to do volumes - IBAprep_NO_COPY_METADATA = 256, // N.B. default copies all metadata - IBAprep_COPY_ALL_METADATA = 512, // Even unsafe things - IBAprep_CLAMP_MUTUAL_NCHANNELS = 1<<10, // Clamp roi.chend to max of inputs - IBAprep_SUPPORT_DEEP = 1<<11, // Operation allows deep images - IBAprep_DEEP_MIXED = 1<<12, // Allow deep & non-deep combinations -}; - - - -/// Given data types a and b, return a type that is a best guess for one -/// that can handle both without any loss of range or precision. -TypeDesc::BASETYPE OIIO_API type_merge (TypeDesc::BASETYPE a, TypeDesc::BASETYPE b); - -inline TypeDesc::BASETYPE -type_merge (TypeDesc::BASETYPE a, TypeDesc::BASETYPE b, TypeDesc::BASETYPE c) -{ - return type_merge (type_merge(a,b), c); -} - -inline TypeDesc type_merge (TypeDesc a, TypeDesc b) { - return type_merge (TypeDesc::BASETYPE(a.basetype), TypeDesc::BASETYPE(b.basetype)); -} - -inline TypeDesc type_merge (TypeDesc a, TypeDesc b, TypeDesc c) -{ - return type_merge (type_merge(a,b), c); -} - - - -// Macro to call a type-specialzed version func(R,...) -#define OIIO_DISPATCH_TYPES(ret,name,func,type,R,...) \ - switch (type.basetype) { \ - case TypeDesc::FLOAT : \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::UINT8 : \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::HALF : \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::UINT16: \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::INT8 : \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::INT16 : \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::UINT : \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::INT : \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::DOUBLE: \ - ret = func (R, __VA_ARGS__); break; \ - default: \ - (R).error ("%s: Unsupported pixel data format '%s'", name, type); \ - ret = false; \ - } - -// Helper, do not call from the outside world. -#define OIIO_DISPATCH_TYPES2_HELP(ret,name,func,Rtype,Atype,R,...) \ - switch (Atype.basetype) { \ - case TypeDesc::FLOAT : \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::UINT8 : \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::HALF : \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::UINT16: \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::INT8 : \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::INT16 : \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::UINT : \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::INT : \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::DOUBLE : \ - ret = func (R, __VA_ARGS__); break; \ - default: \ - (R).error ("%s: Unsupported pixel data format '%s'", name, Atype); \ - ret = false; \ - } - -// Macro to call a type-specialzed version func(R,...). -#define OIIO_DISPATCH_TYPES2(ret,name,func,Rtype,Atype,R,...) \ - switch (Rtype.basetype) { \ - case TypeDesc::FLOAT : \ - OIIO_DISPATCH_TYPES2_HELP(ret,name,func,float,Atype,R,__VA_ARGS__); \ - break; \ - case TypeDesc::UINT8 : \ - OIIO_DISPATCH_TYPES2_HELP(ret,name,func,unsigned char,Atype,R,__VA_ARGS__); \ - break; \ - case TypeDesc::HALF : \ - OIIO_DISPATCH_TYPES2_HELP(ret,name,func,half,Atype,R,__VA_ARGS__); \ - break; \ - case TypeDesc::UINT16: \ - OIIO_DISPATCH_TYPES2_HELP(ret,name,func,unsigned short,Atype,R,__VA_ARGS__); \ - break; \ - case TypeDesc::INT8: \ - OIIO_DISPATCH_TYPES2_HELP(ret,name,func,char,Atype,R,__VA_ARGS__); \ - break; \ - case TypeDesc::INT16: \ - OIIO_DISPATCH_TYPES2_HELP(ret,name,func,short,Atype,R,__VA_ARGS__); \ - break; \ - case TypeDesc::UINT: \ - OIIO_DISPATCH_TYPES2_HELP(ret,name,func,unsigned int,Atype,R,__VA_ARGS__); \ - break; \ - case TypeDesc::INT: \ - OIIO_DISPATCH_TYPES2_HELP(ret,name,func,int,Atype,R,__VA_ARGS__); \ - break; \ - case TypeDesc::DOUBLE: \ - OIIO_DISPATCH_TYPES2_HELP(ret,name,func,double,Atype,R,__VA_ARGS__);\ - break; \ - default: \ - (R).error ("%s: Unsupported pixel data format '%s'", name, Rtype); \ - ret = false; \ - } - - -// Macro to call a type-specialzed version func(R,...) for -// the most common types, will auto-convert the rest to float. -#define OIIO_DISPATCH_COMMON_TYPES(ret,name,func,type,R,...) \ - switch (type.basetype) { \ - case TypeDesc::FLOAT : \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::UINT8 : \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::HALF : \ - ret = func (R, __VA_ARGS__); break; \ - case TypeDesc::UINT16: \ - ret = func (R, __VA_ARGS__); break; \ - default: { \ - /* other types: punt and convert to float, then copy back */ \ - ImageBuf Rtmp; \ - if ((R).initialized()) \ - Rtmp.copy (R, TypeDesc::FLOAT); \ - ret = func (Rtmp, __VA_ARGS__); \ - if (ret) \ - (R).copy (Rtmp); \ - else \ - (R).error ("%s", Rtmp.geterror()); \ - } \ - } - -// Helper, do not call from the outside world. -#define OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,Rtype,Atype,R,A,...) \ - switch (Atype.basetype) { \ - case TypeDesc::FLOAT : \ - ret = func (R, A, __VA_ARGS__); break; \ - case TypeDesc::UINT8 : \ - ret = func (R, A, __VA_ARGS__); break; \ - case TypeDesc::HALF : \ - ret = func (R, A, __VA_ARGS__); break; \ - case TypeDesc::UINT16: \ - ret = func (R, A, __VA_ARGS__); break; \ - default: { \ - /* other types: punt and convert to float, then copy back */ \ - ImageBuf Atmp; \ - Atmp.copy (A, TypeDesc::FLOAT); \ - ret = func (R, Atmp, __VA_ARGS__); \ - } \ - } - -// Macro to call a type-specialzed version func(R,A,...) for -// the most common types, will auto-convert the rest to float. -#define OIIO_DISPATCH_COMMON_TYPES2(ret,name,func,Rtype,Atype,R,A,...) \ - switch (Rtype.basetype) { \ - case TypeDesc::FLOAT : \ - OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,float,Atype,R,A,__VA_ARGS__); \ - break; \ - case TypeDesc::UINT8 : \ - OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,unsigned char,Atype,R,A,__VA_ARGS__); \ - break; \ - case TypeDesc::HALF : \ - OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,half,Atype,R,A,__VA_ARGS__); \ - break; \ - case TypeDesc::UINT16: \ - OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,unsigned short,Atype,R,A,__VA_ARGS__); \ - break; \ - default: { \ - /* other types: punt and convert to float, then copy back */ \ - ImageBuf Rtmp; \ - if ((R).initialized()) \ - Rtmp.copy (R, TypeDesc::FLOAT); \ - OIIO_DISPATCH_COMMON_TYPES2_HELP(ret,name,func,float,Atype,Rtmp,A,__VA_ARGS__); \ - if (ret) \ - (R).copy (Rtmp); \ - else \ - (R).error ("%s", Rtmp.geterror()); \ - } \ - } - - -// Helper, do not call from the outside world. -#define OIIO_DISPATCH_COMMON_TYPES3_HELP2(ret,name,func,Rtype,Atype,Btype,R,A,B,...) \ - switch (Rtype.basetype) { \ - case TypeDesc::FLOAT : \ - ret = func (R,A,B,__VA_ARGS__); break; \ - case TypeDesc::UINT8 : \ - ret = func (R,A,B,__VA_ARGS__); break; \ - case TypeDesc::HALF : \ - ret = func (R,A,B,__VA_ARGS__); break; \ - case TypeDesc::UINT16: \ - ret = func (R,A,B,__VA_ARGS__); break; \ - default: { \ - /* other types: punt and convert to float, then copy back */ \ - ImageBuf Rtmp; \ - if ((R).initialized()) \ - Rtmp.copy (R, TypeDesc::FLOAT); \ - ret = func (R,A,B,__VA_ARGS__); \ - if (ret) \ - (R).copy (Rtmp); \ - else \ - (R).error ("%s", Rtmp.geterror()); \ - } \ - } - -// Helper, do not call from the outside world. -#define OIIO_DISPATCH_COMMON_TYPES3_HELP(ret,name,func,Rtype,Atype,Btype,R,A,B,...) \ - switch (Btype.basetype) { \ - case TypeDesc::FLOAT : \ - OIIO_DISPATCH_COMMON_TYPES3_HELP2(ret,name,func,Rtype,Atype,float,R,A,B,__VA_ARGS__); \ - break; \ - case TypeDesc::UINT8 : \ - OIIO_DISPATCH_COMMON_TYPES3_HELP2(ret,name,func,Rtype,Atype,unsigned char,R,A,B,__VA_ARGS__); \ - break; \ - case TypeDesc::HALF : \ - OIIO_DISPATCH_COMMON_TYPES3_HELP2(ret,name,func,Rtype,Atype,half,R,A,B,__VA_ARGS__); \ - break; \ - case TypeDesc::UINT16 : \ - OIIO_DISPATCH_COMMON_TYPES3_HELP2(ret,name,func,Rtype,Atype,unsigned short,R,A,B,__VA_ARGS__); \ - break; \ - default: { \ - /* other types: punt and convert to float */ \ - ImageBuf Btmp; \ - Btmp.copy (B, TypeDesc::FLOAT); \ - OIIO_DISPATCH_COMMON_TYPES3_HELP2(ret,name,func,Rtype,Atype,float,R,A,Btmp,__VA_ARGS__); \ - } \ - } - -// Macro to call a type-specialzed version func(R,A,B,...) -// the most common types, will auto-convert the rest to float. -#define OIIO_DISPATCH_COMMON_TYPES3(ret,name,func,Rtype,Atype,Btype,R,A,B,...) \ - switch (Atype.basetype) { \ - case TypeDesc::FLOAT : \ - OIIO_DISPATCH_COMMON_TYPES3_HELP(ret,name,func,Rtype,float,Btype,R,A,B,__VA_ARGS__); \ - break; \ - case TypeDesc::UINT8 : \ - OIIO_DISPATCH_COMMON_TYPES3_HELP(ret,name,func,Rtype,unsigned char,Btype,R,A,B,__VA_ARGS__); \ - break; \ - case TypeDesc::HALF : \ - OIIO_DISPATCH_COMMON_TYPES3_HELP(ret,name,func,Rtype,half,Btype,R,A,B,__VA_ARGS__); \ - break; \ - case TypeDesc::UINT16: \ - OIIO_DISPATCH_COMMON_TYPES3_HELP(ret,name,func,Rtype,unsigned short,Btype,R,A,B,__VA_ARGS__); \ - break; \ - default: \ - /* other types: punt and convert to float */ \ - ImageBuf Atmp; \ - Atmp.copy (A, TypeDesc::FLOAT); \ - OIIO_DISPATCH_COMMON_TYPES3_HELP(ret,name,func,Rtype,float,Btype,R,Atmp,B,__VA_ARGS__); \ - } - - - -} // end namespace ImageBufAlgo - - -OIIO_NAMESPACE_END - -#endif // OPENIMAGEIO_IMAGEBUFALGO_UTIL_H diff --git a/3rdparty/oiio16/include/OpenImageIO/imagecache.h b/3rdparty/oiio16/include/OpenImageIO/imagecache.h deleted file mode 100644 index 044d26f2..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/imagecache.h +++ /dev/null @@ -1,406 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -/// \file -/// An API for accessing images via a system that -/// automatically manages a cache of resident image data. - - -#ifndef OPENIMAGEIO_IMAGECACHE_H -#define OPENIMAGEIO_IMAGECACHE_H - -#include "OpenImageIO/ustring.h" -#include "OpenImageIO/imageio.h" - - -OIIO_NAMESPACE_BEGIN - -struct ROI; - -namespace pvt { -// Forward declaration -class ImageCacheImpl; -class ImageCacheFile; -class ImageCachePerThreadInfo; -}; - - - - -/// Define an API to an abstract class that manages image files, -/// caches of open file handles as well as tiles of pixels so that truly -/// huge amounts of image data may be accessed by an application with low -/// memory footprint. -class OIIO_API ImageCache { -public: - /// Create a ImageCache and return a pointer. This should only be - /// freed by passing it to ImageCache::destroy()! - /// - /// If shared==true, it's intended to be shared with other like-minded - /// owners in the same process who also ask for a shared cache. If - /// false, a private image cache will be created. - static ImageCache *create (bool shared=true); - - /// Destroy a ImageCache that was created using ImageCache::create(). - /// The variety that takes a 'teardown' parameter, when set to true, - /// will fully destroy even a "shared" ImageCache. - static void destroy (ImageCache * x); - static void destroy (ImageCache * x, bool teardown); - - ImageCache (void) { } - virtual ~ImageCache () { } - - /// Close everything, free resources, start from scratch. - /// - virtual void clear () = 0; - - /// Set an attribute controlling the image cache. Return true - /// if the name and type were recognized and the attrib was set. - /// Documented attributes: - /// int max_open_files : maximum number of file handles held open - /// float max_memory_MB : maximum tile cache size, in MB - /// string searchpath : colon-separated search path for images - /// string plugin_searchpath : colon-separated search path for plugins - /// int autotile : if >0, tile size to emulate for non-tiled images - /// int autoscanline : autotile using full width tiles - /// int automip : if nonzero, emulate mipmap on the fly - /// int accept_untiled : if nonzero, accept untiled images, but - /// if zero, reject untiled images (default=1) - /// int accept_unmipped : if nonzero, accept unmipped images (def=1) - /// int statistics:level : verbosity of statistics auto-printed. - /// int forcefloat : if nonzero, convert all to float. - /// int failure_retries : number of times to retry a read before fail. - /// int deduplicate : if nonzero, detect duplicate textures (default=1) - /// string substitute_image : uses the named image in place of all - /// texture and image references. - /// int unassociatedalpha : if nonzero, keep unassociated alpha images - /// - virtual bool attribute (string_view name, TypeDesc type, - const void *val) = 0; - // Shortcuts for common types - virtual bool attribute (string_view name, int val) = 0; - virtual bool attribute (string_view name, float val) = 0; - virtual bool attribute (string_view name, double val) = 0; - virtual bool attribute (string_view name, string_view val) = 0; - - /// Get the named attribute, store it in value. - virtual bool getattribute (string_view name, TypeDesc type, - void *val) const = 0; - // Shortcuts for common types - virtual bool getattribute (string_view name, int &val) const = 0; - virtual bool getattribute (string_view name, float &val) const = 0; - virtual bool getattribute (string_view name, double &val) const = 0; - virtual bool getattribute (string_view name, char **val) const = 0; - virtual bool getattribute (string_view name, std::string &val) const = 0; - - /// Define an opaque data type that allows us to have a pointer - /// to certain per-thread information that the ImageCache maintains. - /// Any given one of these should NEVER be shared between running - /// threads. - typedef pvt::ImageCachePerThreadInfo Perthread; - - /// Retrieve a Perthread, unique to the calling thread. This is a - /// thread-specific pointer that will always return the Perthread for a - /// thread, which will also be automatically destroyed when the thread - /// terminates. - /// - /// Applications that want to manage their own Perthread pointers (with - /// create_thread_info and destroy_thread_info) should still call this, - /// but passing in their managed pointer. If the passed-in thread_info - /// is not NULL, it won't create a new one or retrieve a TSP, but it - /// will do other necessary housekeeping on the Perthread information. - virtual Perthread * get_perthread_info (Perthread *thread_info = NULL) = 0; - - /// Create a new Perthread. It is the caller's responsibility to - /// eventually destroy it using destroy_thread_info(). - virtual Perthread * create_thread_info () = 0; - - /// Destroy a Perthread that was allocated by create_thread_info(). - virtual void destroy_thread_info (Perthread *thread_info) = 0; - - /// Define an opaque data type that allows us to have a handle to an - /// image (already having its name resolved) but without exposing - /// any internals. - typedef pvt::ImageCacheFile ImageHandle; - - /// Retrieve an opaque handle for fast image lookups. The opaque - /// pointer thread_info is thread-specific information returned by - /// get_perthread_info(). Return NULL if something has gone - /// horribly wrong. - virtual ImageHandle * get_image_handle (ustring filename, - Perthread *thread_info=NULL) = 0; - - /// Return true if the image handle (previously returned by - /// get_image_handle()) is a valid image that can be subsequently read. - virtual bool good (ImageHandle *file) = 0; - - /// Given possibly-relative 'filename', resolve it using the search - /// path rules and return the full resolved filename. - virtual std::string resolve_filename (const std::string &filename) const=0; - - /// Get information about the named image. Return true if found - /// and the data has been put in *data. Return false if the image - /// doesn't exist, doesn't have the requested data, if the data - /// doesn't match the type requested. or some other failure. - virtual bool get_image_info (ustring filename, int subimage, int miplevel, - ustring dataname, TypeDesc datatype, void *data) = 0; - virtual bool get_image_info (ImageHandle *file, Perthread *thread_info, - int subimage, int miplevel, - ustring dataname, TypeDesc datatype, void *data) = 0; - - /// Get the ImageSpec associated with the named image (the first - /// subimage & miplevel by default, or as set by 'subimage' and - /// 'miplevel'). If the file is found and is an image format that - /// can be read, store a copy of its specification in spec and - /// return true. Return false if the file was not found or could - /// not be opened as an image file by any available ImageIO plugin. - virtual bool get_imagespec (ustring filename, ImageSpec &spec, - int subimage=0, int miplevel=0, - bool native=false) = 0; - virtual bool get_imagespec (ImageHandle *file, Perthread *thread_info, - ImageSpec &spec, - int subimage=0, int miplevel=0, - bool native=false) = 0; - - /// Return a pointer to an ImageSpec associated with the named image - /// (the first subimage & miplevel by default, or as set by - /// 'subimage' and 'miplevel') if the file is found and is an image - /// format that can be read, otherwise return NULL. - /// - /// This method is much more efficient than get_imagespec(), since - /// it just returns a pointer to the spec held internally by the - /// ImageCache (rather than copying the spec to the user's memory). - /// However, the caller must beware that the pointer is only valid - /// as long as nobody (even other threads) calls invalidate() on the - /// file, or invalidate_all(), or destroys the ImageCache. - virtual const ImageSpec *imagespec (ustring filename, int subimage=0, - int miplevel=0, bool native=false) = 0; - virtual const ImageSpec *imagespec (ImageHandle *file, - Perthread *thread_info, - int subimage=0, int miplevel=0, - bool native=false) = 0; - - /// Retrieve the rectangle of pixels spanning [xbegin..xend) X - /// [ybegin..yend) X [zbegin..zend), with "exclusive end" a la STL, - /// specified as integer pixel coordinates in the designated - /// subimage & miplevel, storing the pixel values beginning at the - /// address specified by result. The pixel values will be converted - /// to the type specified by format. It is up to the caller to - /// ensure that result points to an area of memory big enough to - /// accommodate the requested rectangle (taking into consideration - /// its dimensions, number of channels, and data format). Requested - /// pixels outside the valid pixel data region will be filled in - /// with 0 values. - /// - /// Return true if the file is found and could be opened by an - /// available ImageIO plugin, otherwise return false. - virtual bool get_pixels (ustring filename, int subimage, int miplevel, - int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend, - TypeDesc format, void *result) = 0; - virtual bool get_pixels (ImageHandle *file, Perthread *thread_info, - int subimage, int miplevel, - int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend, - TypeDesc format, void *result) = 0; - - /// Retrieve the rectangle of pixels spanning [xbegin..xend) X - /// [ybegin..yend) X [zbegin..zend), channels [chbegin..chend), - /// with "exclusive end" a la STL, specified as integer pixel - /// coordinates in the designated subimage & miplevel, storing the - /// pixel values beginning at the address specified by result and - /// with the given x, y, and z strides (in bytes). The pixel values - /// will be converted to the type specified by format. If the - /// strides are set to AutoStride, they will be automatically - /// computed assuming a contiguous data layout. It is up to the - /// caller to ensure that result points to an area of memory big - /// enough to accommodate the requested rectangle (taking into - /// consideration its dimensions, number of channels, and data - /// format). Requested pixels outside the valid pixel data region - /// will be filled in with 0 values. The optional cache_chbegin and - /// cache_chend hint as to which range of channels should be cached - /// (which by default will be all channels of the file). - /// - /// Return true if the file is found and could be opened by an - /// available ImageIO plugin, otherwise return false. - virtual bool get_pixels (ustring filename, - int subimage, int miplevel, int xbegin, int xend, - int ybegin, int yend, int zbegin, int zend, - int chbegin, int chend, TypeDesc format, void *result, - stride_t xstride=AutoStride, stride_t ystride=AutoStride, - stride_t zstride=AutoStride, - int cache_chbegin = 0, int cache_chend = -1) = 0; - virtual bool get_pixels (ImageHandle *file, Perthread *thread_info, - int subimage, int miplevel, int xbegin, int xend, - int ybegin, int yend, int zbegin, int zend, - int chbegin, int chend, TypeDesc format, void *result, - stride_t xstride=AutoStride, stride_t ystride=AutoStride, - stride_t zstride=AutoStride, - int cache_chbegin = 0, int cache_chend = -1) = 0; - - /// Define an opaque data type that allows us to have a pointer - /// to a tile but without exposing any internals. - class Tile; - - /// Find a tile given by an image filename, subimage & miplevel, channel - /// range, and pixel coordinates. An opaque pointer to the tile will be - /// returned, or NULL if no such file (or tile within the file) exists - /// or can be read. The tile will not be purged from the cache until - /// after release_tile() is called on the tile pointer the same number - /// of times that get_tile() was called (refcnt). This is thread-safe! - /// If chend < chbegin, it will retrieve a tile containing all channels - /// in the file. - virtual Tile * get_tile (ustring filename, int subimage, int miplevel, - int x, int y, int z, - int chbegin = 0, int chend = -1) = 0; - virtual Tile * get_tile (ImageHandle *file, Perthread *thread_info, - int subimage, int miplevel, - int x, int y, int z, - int chbegin = 0, int chend = -1) = 0; - - /// After finishing with a tile, release_tile will allow it to - /// once again be purged from the tile cache if required. - virtual void release_tile (Tile *tile) const = 0; - - /// Retrieve the data type of the pixels stored in the tile, which may - /// be different than the type of the pixels in the disk file. - virtual TypeDesc tile_format (const Tile *tile) const = 0; - - /// Retrieve the ROI describing the pixels and channels stored in the - /// tile. - virtual ROI tile_roi (const Tile *tile) const = 0; - - /// For a tile retrived by get_tile(), return a pointer to the - /// pixel data itself, and also store in 'format' the data type that - /// the pixels are internally stored in (which may be different than - /// the data type of the pixels in the disk file). - virtual const void * tile_pixels (Tile *tile, TypeDesc &format) const = 0; - - /// The add_file() call causes a file to be opened or added to the - /// cache. There is no reason to use this method unless you are - /// supplying a custom creator, or configuration, or both. - /// - /// If creator is not NULL, it points to an ImageInput::Creator that - /// will be used rather than the default ImageInput::create(), thus - /// instead of reading from disk, creates and uses a custom ImageInput - /// to generate the image. The 'creator' is a factory that creates the - /// custom ImageInput and will be called like this: - /// ImageInput *in = creator(); - /// Once created, the ImageCache owns the ImageInput and is responsible - /// for destroying it when done. Custom ImageInputs allow "procedural" - /// images, among other things. Also, this is the method you use to set - /// up a "writeable" ImageCache images (perhaps with a type of - /// ImageInput that's just a stub that does as little as possible). - /// - /// If config is not NULL, it points to an ImageSpec with configuration - /// options/hints that will be passed to the underlying - /// ImageInput::open() call. Thus, this can be used to ensure that the - /// ImageCache opens a call with special configuration options. - /// - /// This call (including any custom creator or configuration hints) will - /// have no effect if there's already an image by the same name in the - /// cache. Custom creators or configurations only "work" the FIRST time - /// a particular filename is referenced in the lifetime of the - /// ImageCache. - virtual bool add_file (ustring filename, ImageInput::Creator creator=NULL, - const ImageSpec *config=NULL) = 0; - - /// Preemptively add a tile corresponding to the named image, at the - /// given subimage, MIP level, and channel range. The tile added is the - /// one whose corner is (x,y,z), and buffer points to the pixels (in the - /// given format, with supplied strides) which will be copied and - /// inserted into the cache and made available for future lookups. - /// If chend < chbegin, it will add a tile containing the full set of - /// channels for the image. - virtual bool add_tile (ustring filename, int subimage, int miplevel, - int x, int y, int z, int chbegin, int chend, - TypeDesc format, const void *buffer, - stride_t xstride=AutoStride, stride_t ystride=AutoStride, - stride_t zstride=AutoStride) = 0; - // DEPRECATED(1.6) -- add a tile with all channels. - virtual bool add_tile (ustring filename, int subimage, int miplevel, - int x, int y, int z, TypeDesc format, const void *buffer, - stride_t xstride=AutoStride, stride_t ystride=AutoStride, - stride_t zstride=AutoStride) { - return add_tile (filename, subimage, miplevel, x, y, z, 0, -1, - format, buffer, xstride, ystride, zstride); - } - - /// If any of the API routines returned false indicating an error, - /// this routine will return the error string (and clear any error - /// flags). If no error has occurred since the last time geterror() - /// was called, it will return an empty string. - virtual std::string geterror () const = 0; - - /// Return the statistics output as a huge string. - /// - virtual std::string getstats (int level=1) const = 0; - - /// Reset most statistics to be as they were with a fresh - /// ImageCache. Caveat emptor: this does not flush the cache itelf, - /// so the resulting statistics from the next set of texture - /// requests will not match the number of tile reads, etc., that - /// would have resulted from a new ImageCache. - virtual void reset_stats () = 0; - - /// Invalidate any loaded tiles or open file handles associated with - /// the filename, so that any subsequent queries will be forced to - /// re-open the file or re-load any tiles (even those that were - /// previously loaded and would ordinarily be reused). A client - /// might do this if, for example, they are aware that an image - /// being held in the cache has been updated on disk. This is safe - /// to do even if other procedures are currently holding - /// reference-counted tile pointers from the named image, but those - /// procedures will not get updated pixels until they release the - /// tiles they are holding. - virtual void invalidate (ustring filename) = 0; - - /// Invalidate all loaded tiles and open file handles. This is safe - /// to do even if other procedures are currently holding - /// reference-counted tile pointers from the named image, but those - /// procedures will not get updated pixels until they release the - /// tiles they are holding. If force is true, everything will be - /// invalidated, no matter how wasteful it is, but if force is - /// false, in actuality files will only be invalidated if their - /// modification times have been changed since they were first - /// opened. - virtual void invalidate_all (bool force=false) = 0; - -private: - // Make delete private and unimplemented in order to prevent apps - // from calling it. Instead, they should call ImageCache::destroy(). - void operator delete (void * /*todel*/) { } -}; - - -OIIO_NAMESPACE_END - -#endif // OPENIMAGEIO_IMAGECACHE_H diff --git a/3rdparty/oiio16/include/OpenImageIO/imageio.h b/3rdparty/oiio16/include/OpenImageIO/imageio.h deleted file mode 100644 index fae29957..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/imageio.h +++ /dev/null @@ -1,1554 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - All Rights Reserved. - Based on BSD-licensed software Copyright 2004 NVIDIA Corp. - - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -///////////////////////////////////////////////////////////////////////////// -/// \file -/// -/// Provides a simple API that abstracts the reading and writing of -/// images. Subclasses, which may be found in DSO/DLL's, implement -/// particular formats. -/// -///////////////////////////////////////////////////////////////////////////// - - -#ifndef OPENIMAGEIO_IMAGEIO_H -#define OPENIMAGEIO_IMAGEIO_H - -#if defined(_MSC_VER) -// Ignore warnings about DLL exported classes with member variables that are template classes. -// This happens with the std::vector and std::string members of the classes below. -# pragma warning (disable : 4251) -#endif - -#include -#include -#include -#include - -#include "export.h" -#include "oiioversion.h" -#include "platform.h" -#include "typedesc.h" /* Needed for TypeDesc definition */ -#include "paramlist.h" - -OIIO_NAMESPACE_BEGIN - -/// Type we use for stride lengths. This is only used to designate -/// pixel, scanline, tile, or image plane sizes in user-allocated memory, -/// so it doesn't need to represent sizes larger than can be malloced, -/// therefore ptrdiff_t seemed right. -typedef ptrdiff_t stride_t; - - -/// Type we use to express how many pixels (or bytes) constitute an image, -/// tile, or scanline. Needs to be large enough to handle very big images -/// (which we presume could be > 4GB). -#if defined(LINUX64) || defined(_WIN64) || defined(__x86_64__) /* add others if we know for sure size_t is ok */ -typedef size_t imagesize_t; -#else -typedef unsigned long long imagesize_t; -#endif - - - -/// Special value to indicate a stride length that should be -/// auto-computed. -const stride_t AutoStride = std::numeric_limits::min(); - - - -/// Pointer to a function called periodically by read_image and -/// write_image. This can be used to implement progress feedback, etc. -/// It takes an opaque data pointer (passed to read_image/write_image) -/// and a float giving the portion of work done so far. It returns a -/// bool, which if 'true' will STOP the read or write. -typedef bool (*ProgressCallback)(void *opaque_data, float portion_done); - - - -typedef ParamValue ImageIOParameter; -typedef ParamValueList ImageIOParameterList; - - - -/// ImageSpec describes the data format of an image -- -/// dimensions, layout, number and meanings of image channels. -class OIIO_API ImageSpec { -public: - int x, y, z; ///< origin (upper left corner) of pixel data - int width; ///< width of the pixel data window - int height; ///< height of the pixel data window - int depth; ///< depth of pixel data, >1 indicates a "volume" - int full_x; ///< origin of the full (display) window - int full_y; ///< origin of the full (display) window - int full_z; ///< origin of the full (display) window - int full_width; ///< width of the full (display) window - int full_height; ///< height of the full (display) window - int full_depth; ///< depth of the full (display) window - int tile_width; ///< tile width (0 for a non-tiled image) - int tile_height; ///< tile height (0 for a non-tiled image) - int tile_depth; ///< tile depth (0 for a non-tiled image, - ///< 1 for a non-volume image) - int nchannels; ///< number of image channels, e.g., 4 for RGBA - TypeDesc format; ///< data format of the channels - std::vector channelformats; ///< Optional per-channel formats - std::vector channelnames; ///< Names for each channel, - ///< e.g., {"R","G","B","A"} - int alpha_channel; ///< Index of alpha channel, or -1 if not known - int z_channel; ///< Index of depth channel, or -1 if not known - bool deep; ///< Contains deep data - - /// The above contains all the information that is likely needed for - /// every image file, and common to all formats. Rather than bloat - /// this structure, customize it for new formats, or break back - /// compatibility as we think of new things, we provide extra_attribs - /// as a holder for any other properties of the image. The public - /// functions attribute and find_attribute may be used to access - /// these data. Note, however, that the names and semantics of such - /// extra attributes are plugin-dependent and are not enforced by - /// the imageio library itself. - ImageIOParameterList extra_attribs; ///< Additional attributes - - /// Constructor: given just the data format, set all other fields to - /// something reasonable. - ImageSpec (TypeDesc format = TypeDesc::UNKNOWN); - - /// Constructor for simple 2D scanline image with nothing special. - /// If fmt is not supplied, default to unsigned 8-bit data. - ImageSpec (int xres, int yres, int nchans, TypeDesc fmt = TypeDesc::UINT8); - - /// Set the data format. - void set_format (TypeDesc fmt); - - /// Set the channelnames to reasonable defaults ("R", "G", "B", "A"), - /// and alpha_channel, based on the number of channels. - void default_channel_names (); - - /// Return the number of bytes for each channel datum, assuming they - /// are all stored using the data format given by this->format. - size_t channel_bytes() const { return format.size(); } - - /// Return the number of bytes needed for the single specified - /// channel. If native is false (default), compute the size of one - /// channel of this->format, but if native is true, compute the size - /// of the channel in terms of the "native" data format of that - /// channel as stored in the file. - size_t channel_bytes (int chan, bool native=false) const; - - /// Return the number of bytes for each pixel (counting all channels). - /// If native is false (default), assume all channels are in - /// this->format, but if native is true, compute the size of a pixel - /// in the "native" data format of the file (these may differ in - /// the case of per-channel formats). - /// This will return std::numeric_limits::max() in the - /// event of an overflow where it's not representable in a size_t. - size_t pixel_bytes (bool native=false) const; - - /// Return the number of bytes for just the subset of channels in - /// each pixel described by [chbegin,chend). - /// If native is false (default), assume all channels are in - /// this->format, but if native is true, compute the size of a pixel - /// in the "native" data format of the file (these may differ in - /// the case of per-channel formats). - /// This will return std::numeric_limits::max() in the - /// event of an overflow where it's not representable in a size_t. - size_t pixel_bytes (int chbegin, int chend, bool native=false) const; - - /// Return the number of bytes for each scanline. This will return - /// std::numeric_limits::max() in the event of an - /// overflow where it's not representable in an imagesize_t. - /// If native is false (default), assume all channels are in - /// this->format, but if native is true, compute the size of a pixel - /// in the "native" data format of the file (these may differ in - /// the case of per-channel formats). - imagesize_t scanline_bytes (bool native=false) const; - - /// Return the number of pixels for a tile. This will return - /// std::numeric_limits::max() in the event of an - /// overflow where it's not representable in an imagesize_t. - imagesize_t tile_pixels () const; - - /// Return the number of bytes for each a tile of the image. This - /// will return std::numeric_limits::max() in the event - /// of an overflow where it's not representable in an imagesize_t. - /// If native is false (default), assume all channels are in - /// this->format, but if native is true, compute the size of a pixel - /// in the "native" data format of the file (these may differ in - /// the case of per-channel formats). - imagesize_t tile_bytes (bool native=false) const; - - /// Return the number of pixels for an entire image. This will - /// return std::numeric_limits::max() in the event of - /// an overflow where it's not representable in an imagesize_t. - imagesize_t image_pixels () const; - - /// Return the number of bytes for an entire image. This will - /// return std::numeric_limits::max() in the event of - /// an overflow where it's not representable in an imagesize_t. - /// If native is false (default), assume all channels are in - /// this->format, but if native is true, compute the size of a pixel - /// in the "native" data format of the file (these may differ in - /// the case of per-channel formats). - imagesize_t image_bytes (bool native=false) const; - - /// Verify that on this platform, a size_t is big enough to hold the - /// number of bytes (and pixels) in a scanline, a tile, and the - /// whole image. If this returns false, the image is much too big - /// to allocate and read all at once, so client apps beware and check - /// these routines for overflows! - bool size_t_safe() const { - const imagesize_t big = std::numeric_limits::max(); - return image_bytes() < big && scanline_bytes() < big && - tile_bytes() < big; - } - - /// Adjust the stride values, if set to AutoStride, to be the right - /// sizes for contiguous data with the given format, channels, - /// width, height. - static void auto_stride (stride_t &xstride, stride_t &ystride, - stride_t &zstride, stride_t channelsize, - int nchannels, int width, int height) { - if (xstride == AutoStride) - xstride = nchannels * channelsize; - if (ystride == AutoStride) - ystride = xstride * width; - if (zstride == AutoStride) - zstride = ystride * height; - } - - /// Adjust the stride values, if set to AutoStride, to be the right - /// sizes for contiguous data with the given format, channels, - /// width, height. - static void auto_stride (stride_t &xstride, stride_t &ystride, - stride_t &zstride, TypeDesc format, - int nchannels, int width, int height) { - auto_stride (xstride, ystride, zstride, format.size(), - nchannels, width, height); - } - - /// Adjust xstride, if set to AutoStride, to be the right size for - /// contiguous data with the given format and channels. - static void auto_stride (stride_t &xstride, TypeDesc format, int nchannels) { - if (xstride == AutoStride) - xstride = nchannels * format.size(); - } - - /// Add an optional attribute to the extra attribute list - /// - void attribute (string_view name, TypeDesc type, const void *value); - - /// Add an optional attribute to the extra attribute list. - /// - void attribute (string_view name, TypeDesc type, string_view value); - - /// Add an unsigned int attribute - /// - void attribute (string_view name, unsigned int value) { - attribute (name, TypeDesc::UINT, &value); - } - - /// Add an int attribute - /// - void attribute (string_view name, int value) { - attribute (name, TypeDesc::INT, &value); - } - - /// Add a float attribute - /// - void attribute (string_view name, float value) { - attribute (name, TypeDesc::FLOAT, &value); - } - - /// Add a string attribute - /// - void attribute (string_view name, string_view value) { - const char *s = value.c_str(); - attribute (name, TypeDesc::STRING, &s); - } - - /// Remove the specified attribute from the list of extra_attribs. If - /// not found, do nothing. If searchtype is anything but UNKNOWN, - /// restrict matches to only those of the given type. If casesensitive - /// is true, the name search will be case-sensitive, otherwise the name - /// search will be performed without regard to case (this is the - /// default). - void erase_attribute (string_view name, - TypeDesc searchtype=TypeDesc::UNKNOWN, - bool casesensitive=false); - - /// Search for an attribute of the given name in the list of - /// extra_attribs. If searchtype is anything but UNKNOWN, restrict - /// matches to only those of the given type. If casesensitive is true, - /// the name search will be case-sensitive, otherwise the name search - /// will be performed without regard to case (this is the default). - ImageIOParameter * find_attribute (string_view name, - TypeDesc searchtype=TypeDesc::UNKNOWN, - bool casesensitive=false); - const ImageIOParameter *find_attribute (string_view name, - TypeDesc searchtype=TypeDesc::UNKNOWN, - bool casesensitive=false) const; - - /// Search for the named attribute and return a pointer to an - /// ImageIOParameter record, or NULL if not found. This variety of - /// find_attribute() can retrieve items such as "width", which are part - /// of the ImageSpec, but not in extra_attribs. The tmpparam is a - /// temporary storage area owned by the caller, which is used as - /// temporary buffer in cases where the information does not correspond - /// to an actual extra_attribs (in this case, the return value will be - /// &tmpparam). - const ImageIOParameter * find_attribute (string_view name, - ImageIOParameter &tmpparam, - TypeDesc searchtype=TypeDesc::UNKNOWN, - bool casesensitive=false) const; - - /// Simple way to get an integer attribute, with default provided. - /// Automatically will return an int even if the data is really - /// unsigned, short, or byte. - int get_int_attribute (string_view name, int defaultval=0) const; - - /// Simple way to get a float attribute, with default provided. - /// Automatically will return a float even if the data is really - /// double or half. - float get_float_attribute (string_view name, float defaultval=0) const; - - /// Simple way to get a string attribute, with default provided. - /// - string_view get_string_attribute (string_view name, - string_view defaultval = string_view()) const; - - /// For a given parameter p, format the value nicely as a string. If - /// 'human' is true, use especially human-readable explanations (units, - /// or decoding of values) for certain known metadata. - static std::string metadata_val (const ImageIOParameter &p, - bool human=false); - - /// Convert ImageSpec class into XML string. - /// - std::string to_xml () const; - - /// Get an ImageSpec class from XML string. - /// - void from_xml (const char *xml); - - /// Helper function to verify that the given pixel range exactly covers - /// a set of tiles. Also returns false if the spec indicates that the - /// image isn't tiled at all. - bool valid_tile_range (int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend) { - return (tile_width && - ((xbegin-x) % tile_width) == 0 && - ((ybegin-y) % tile_height) == 0 && - ((zbegin-z) % tile_depth) == 0 && - (((xend-x) % tile_width) == 0 || (xend-x) == width) && - (((yend-y) % tile_height) == 0 || (yend-y) == height) && - (((zend-z) % tile_depth) == 0 || (zend-z) == depth)); - } - - /// Return teh channelformat of the given channel. - TypeDesc channelformat (int chan) const { - return chan >= 0 && chan < (int)channelformats.size() - ? channelformats[chan] : format; - } - - /// Fill in an array of channel formats describing all channels in - /// the image. (Note that this differs slightly from the member - /// data channelformats, which is empty if there are not separate - /// per-channel formats.) - void get_channelformats (std::vector &formats) const { - formats = channelformats; - if ((int)formats.size() < nchannels) - formats.resize (nchannels, format); - } -}; - - - -/// Structure to hold "deep" data -- multiple samples per pixel. -struct OIIO_API DeepData { -public: - int npixels, nchannels; - std::vector channeltypes; // for each channel [c] - std::vector nsamples;// for each pixel [z][y][x] - std::vector pointers; // for each channel per pixel [z][y][x][c] - std::vector data; // for each sample [z][y][x][c][s] - - /// Construct an empty DeepData. - DeepData () : npixels(0), nchannels(0) { } - - /// Construct and init from an ImageSpec. - DeepData (const ImageSpec &spec) {init (spec); } - - /// Clear the vectors and reset size to 0. - void clear (); - /// Deallocate all space in the vectors - void free (); - - /// Initialize size and allocate nsamples, pointers. It is important to - /// completely fill in nsamples after init() but before alling alloc(). - /// DEPRECATED - void init (int npix, int nchan, - const TypeDesc *chbegin, const TypeDesc *chend); - - /// Initialize size and allocate nsamples, pointers based on the number - /// of pixels, channels, and channel types in the ImageSpec. It is - /// important to completely fill in nsamples after init() but before - /// alling alloc(). - void init (const ImageSpec &spec); - - /// Retrieve the total number of pixels. - int pixels () const { return npixels; } - /// Retrieve the number of channels. - int channels () const { return nchannels; } - /// Retrieve the channel type of channel c. - TypeDesc channeltype (int c) const { return channeltypes[c]; } - - /// Retrieve the number of samples for the given pixel index. - int samples (int pixel) const; - - /// Set the number of samples for the given pixel. This must be called - /// after init(), but before alloc(). - void set_samples (int pixel, int samps); - - /// After set_samples() has been set for all pixels, call alloc() to - /// allocate enough scratch space for data and set up all the pointers. - void alloc (); - - /// Retrieve deep sample value within a pixel, cast to a float. - float deep_value (int pixel, int channel, int sample) const; - /// Retrieve deep sample value within a pixel, as an untigned int. - uint32_t deep_value_uint (int pixel, int channel, int sample) const; - - /// Set deep sample value within a pixel, as a float. - /// It will automatically call alloc() if it has not yet been called. - void set_deep_value (int pixel, int channel, int sample, float value); - /// Set deep sample value within a pixel, as a uint32. - /// It will automatically call alloc() if it has not yet been called. - void set_deep_value (int pixel, int channel, int sample, uint32_t value); - - /// Retrieve the pointer to the first sample of the given pixel and - /// channel. Return NULL if there are no samples for that pixel. - /// Use with care. - void *channel_ptr (int pixel, int channel); - const void *channel_ptr (int pixel, int channel) const; -}; - - - -/// ImageInput abstracts the reading of an image file in a file -/// format-agnostic manner. -class OIIO_API ImageInput { -public: - /// Create an ImageInput subclass instance that is able to read - /// the given file and open it, returning the opened ImageInput if - /// successful. If it fails, return NULL and set an error that can - /// be retrieved by OpenImageIO::geterror(). - /// - /// The 'config', if not NULL, points to an ImageSpec giving - /// requests or special instructions. ImageInput implementations - /// are free to not respond to any such requests, so the default - /// implementation is just to ignore config. - /// - /// open() will first try to make an ImageInput corresponding to - /// the format implied by the file extension (for example, "foo.tif" - /// will try the TIFF plugin), but if one is not found or if the - /// inferred one does not open the file, every known ImageInput type - /// will be tried until one is found that will open the file. - static ImageInput *open (const std::string &filename, - const ImageSpec *config = NULL); - - /// Create and return an ImageInput implementation that is willing - /// to read the given file. The plugin_searchpath parameter is a - /// colon-separated list of directories to search for ImageIO plugin - /// DSO/DLL's (not a searchpath for the image itself!). This will - /// actually just try every imageio plugin it can locate, until it - /// finds one that's able to open the file without error. This just - /// creates the ImageInput, it does not open the file. - /// - /// If the caller intends to immediately open the file, then it is - /// simpler to call static ImageInput::open(). - static ImageInput *create (const std::string &filename, - const std::string &plugin_searchpath=""); - - /// Destroy an ImageInput that was created using ImageInput::create() or - /// the static open(). For some systems (Windows, I'm looking at you), - /// it is not necessarily safe to allocate memory in one DLL and free it - /// in another, so directly calling 'delete' on an ImageInput allocated - /// by create() or open() may be unusafe, but passing it to destroy() - /// should be safe. - static void destroy (ImageInput *x); - - ImageInput (); - virtual ~ImageInput (); - - /// Return the name of the format implemented by this class. - /// - virtual const char *format_name (void) const = 0; - - /// Given the name of a 'feature', return whether this ImageInput - /// supports input of images with the given properties. Most queries - /// will simply return 0 for "doesn't support" and nonzero for "supports - /// it", but it is acceptable to have queries return other nonzero - /// integers to indicate varying degrees of support or limits (but - /// should be clearly documented as such). - /// - /// Feature names that ImageIO plugins are expected to recognize - /// include: - /// "arbitrary_metadata" Does this format allow metadata with - /// arbitrary names and types? - /// "exif" Can this format store Exif camera data? - /// "iptc" Can this format store IPTC data? - /// "procedural" Can this format create images without reading - /// from a disk file? - /// - /// Note that main advantage of this approach, versus having - /// separate individual supports_foo() methods, is that this allows - /// future expansion of the set of possible queries without changing - /// the API, adding new entry points, or breaking linkage - /// compatibility. - virtual int supports (string_view feature) const { return false; } - - /// Return true if the named file is file of the type for this - /// ImageInput. The implementation will try to determine this as - /// efficiently as possible, in most cases much less expensively - /// than doing a full open(). Note that a file can appear to be of - /// the right type (i.e., valid_file() returning true) but still - /// fail a subsequent call to open(), such as if the contents of the - /// file are truncated, nonsensical, or otherwise corrupted. - virtual bool valid_file (const std::string &filename) const; - - /// Open file with given name. Various file attributes are put in - /// newspec and a copy is also saved in this->spec. From these - /// attributes, you can discern the resolution, if it's tiled, - /// number of channels, and native data format. Return true if the - /// file was found and opened okay. - virtual bool open (const std::string &name, ImageSpec &newspec) = 0; - - /// Open file with given name, similar to open(name,newspec). The - /// 'config' is an ImageSpec giving requests or special - /// instructions. ImageInput implementations are free to not - /// respond to any such requests, so the default implementation is - /// just to ignore config and call regular open(name,newspec). - virtual bool open (const std::string &name, ImageSpec &newspec, - const ImageSpec & /*config*/) { return open(name,newspec); } - - /// Return a reference to the image format specification of the - /// current subimage/MIPlevel. Note that the contents of the spec - /// are invalid before open() or after close(), and may change with - /// a call to seek_subimage(). - const ImageSpec &spec (void) const { return m_spec; } - - /// Close an image that we are totally done with. - /// - virtual bool close () = 0; - - /// Returns the index of the subimage that is currently being read. - /// The first subimage (or the only subimage, if there is just one) - /// is number 0. - virtual int current_subimage (void) const { return 0; } - - /// Returns the index of the MIPmap image that is currently being read. - /// The highest-res MIP level (or the only level, if there is just - /// one) is number 0. - virtual int current_miplevel (void) const { return 0; } - - /// Seek to the given subimage and MIP-map level within the open - /// image file. The first subimage of the file has index 0, the - /// highest-resolution MIP level has index 0. Return true on - /// success, false on failure (including that there is not a - /// subimage or MIP level with the specified index). The new - /// subimage's vital statistics are put in newspec (and also saved - /// in this->spec). The reader is expected to give the appearance - /// of random access to subimages and MIP levels -- in other words, - /// if it can't randomly seek to the given subimage/level, it should - /// transparently close, reopen, and sequentially read through prior - /// subimages and levels. - virtual bool seek_subimage (int subimage, int miplevel, - ImageSpec &newspec) { - if (subimage == current_subimage() && miplevel == current_miplevel()) { - newspec = spec(); - return true; - } - return false; - } - - /// Seek to the given subimage -- backwards-compatible call that - /// doesn't worry about MIP-map levels at all. - bool seek_subimage (int subimage, ImageSpec &newspec) { - return seek_subimage (subimage, 0 /* miplevel */, newspec); - } - - /// Read the scanline that includes pixels (*,y,z) into data, - /// converting if necessary from the native data format of the file - /// into the 'format' specified (z==0 for non-volume images). The - /// stride value gives the data spacing of adjacent pixels (in - /// bytes). Strides set to AutoStride imply 'contiguous' data, i.e., - /// xstride == spec.nchannels*format.size() - /// If format is TypeDesc::UNKNOWN, then rather than converting to - /// format, it will just copy pixels in the file's native data layout - /// (including, possibly, per-channel data formats). - /// The reader is expected to give the appearance of random access -- - /// in other words, if it can't randomly seek to the given scanline, - /// it should transparently close, reopen, and sequentially read - /// through prior scanlines. The base ImageInput class has a - /// default implementation that calls read_native_scanline and then - /// does appropriate format conversion, so there's no reason for - /// each format plugin to override this method. - virtual bool read_scanline (int y, int z, TypeDesc format, void *data, - stride_t xstride=AutoStride); - - /// - /// Simple read_scanline reads to contiguous float pixels. - bool read_scanline (int y, int z, float *data) { - return read_scanline (y, z, TypeDesc::FLOAT, data); - } - - /// Read multiple scanlines that include pixels (*,y,z) for all - /// ybegin <= y < yend, into data, using the strides given and - /// converting to the requested data format (unless format is - /// TypeDesc::UNKNOWN, in which case pixels will be copied in the - /// native data layout, including per-channel data formats). This - /// is analogous to read_scanline except that it may be used to read - /// more than one scanline at a time (which, for some formats, may - /// be able to be done much more efficiently or in parallel). - virtual bool read_scanlines (int ybegin, int yend, int z, - TypeDesc format, void *data, - stride_t xstride=AutoStride, - stride_t ystride=AutoStride); - - /// Read multiple scanlines that include pixels (*,y,z) for all - /// ybegin <= y < yend, into data, using the strides given and - /// converting to the requested data format (unless format is - /// TypeDesc::UNKNOWN, in which case pixels will be copied in the - /// native data layout, including per-channel data formats). Only - /// channels [chbegin,chend) will be read/copied (chbegin=0, - /// chend=spec.nchannels reads all channels, yielding equivalent - /// behavior to the simpler variant of read_scanlines). - virtual bool read_scanlines (int ybegin, int yend, int z, - int chbegin, int chend, - TypeDesc format, void *data, - stride_t xstride=AutoStride, - stride_t ystride=AutoStride); - - /// Read the tile whose upper-left origin is (x,y,z) into data, - /// converting if necessary from the native data format of the file - /// into the 'format' specified. (z==0 for non-volume images.) The - /// stride values give the data spacing of adjacent pixels, scanlines, - /// and volumetric slices (measured in bytes). Strides set to AutoStride - /// imply 'contiguous' data in the shape of a full tile, i.e., - /// xstride == spec.nchannels*format.size() - /// ystride == xstride*spec.tile_width - /// zstride == ystride*spec.tile_height - /// If format is TypeDesc::UNKNOWN, then rather than converting to - /// format, it will just copy pixels in the file's native data layout - /// (including, possibly, per-channel data formats). - /// The reader is expected to give the appearance of random access - /// -- in other words, if it can't randomly seek to the given tile, - /// it should transparently close, reopen, and sequentially read - /// through prior tiles. The base ImageInput class has a default - /// implementation that calls read_native_tile and then does - /// appropriate format conversion, so there's no reason for each - /// format plugin to override this method. - virtual bool read_tile (int x, int y, int z, TypeDesc format, - void *data, stride_t xstride=AutoStride, - stride_t ystride=AutoStride, - stride_t zstride=AutoStride); - - /// - /// Simple read_tile reads to contiguous float pixels. - bool read_tile (int x, int y, int z, float *data) { - return read_tile (x, y, z, TypeDesc::FLOAT, data, - AutoStride, AutoStride, AutoStride); - } - - /// Read the block of multiple tiles that include all pixels in - /// [xbegin,xend) X [ybegin,yend) X [zbegin,zend), into data, using - /// the strides given and converting to the requested data format - /// (unless format is TypeDesc::UNKNOWN, in which case pixels will - /// be copied in the native data layout, including per-channel data - /// formats). This is analogous to read_tile except that it may be - /// used to read more than one tile at a time (which, for some - /// formats, may be able to be done much more efficiently or in - /// parallel). The begin/end pairs must correctly delineate tile - /// boundaries, with the exception that it may also be the end of - /// the image data if the image resolution is not a whole multiple - /// of the tile size. - /// The stride values give the data spacing of adjacent pixels, - /// scanlines, and volumetric slices (measured in bytes). Strides set to - /// AutoStride imply 'contiguous' data in the shape of the [begin,end) - /// region, i.e., - /// xstride == spec.nchannels*format.size() - /// ystride == xstride * (xend-xbegin) - /// zstride == ystride * (yend-ybegin) - virtual bool read_tiles (int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend, TypeDesc format, - void *data, stride_t xstride=AutoStride, - stride_t ystride=AutoStride, - stride_t zstride=AutoStride); - - /// Read the block of multiple tiles that include all pixels in - /// [xbegin,xend) X [ybegin,yend) X [zbegin,zend), into data, using - /// the strides given and converting to the requested data format - /// (unless format is TypeDesc::UNKNOWN, in which case pixels will - /// be copied in the native data layout, including per-channel data - /// formats). Only channels [chbegin,chend) will be read/copied - /// (chbegin=0, chend=spec.nchannels reads all channels, yielding - /// equivalent behavior to the simpler variant of read_tiles). - virtual bool read_tiles (int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend, - int chbegin, int chend, TypeDesc format, - void *data, stride_t xstride=AutoStride, - stride_t ystride=AutoStride, - stride_t zstride=AutoStride); - - /// Read the entire image of spec.width x spec.height x spec.depth - /// pixels into data (which must already be sized large enough for - /// the entire image) with the given strides and in the desired - /// format. Read tiles or scanlines automatically. Strides set to - /// AutoStride imply 'contiguous' data, i.e., - /// xstride == spec.nchannels*format.size() - /// ystride == xstride*spec.width - /// zstride == ystride*spec.height - /// If format is TypeDesc::UNKNOWN, then rather than converting to - /// format, it will just copy pixels in the file's native data layout - /// (including, possibly, per-channel data formats). - /// Because this may be an expensive operation, a progress callback - /// may be passed. Periodically, it will be called as follows: - /// progress_callback (progress_callback_data, float done) - /// where 'done' gives the portion of the image - virtual bool read_image (TypeDesc format, void *data, - stride_t xstride=AutoStride, - stride_t ystride=AutoStride, - stride_t zstride=AutoStride, - ProgressCallback progress_callback=NULL, - void *progress_callback_data=NULL); - - /// Read the entire image of spec.width x spec.height x spec.depth - /// pixels into data (which must already be sized large enough for - /// the entire image) with the given strides and in the desired - /// format. Read tiles or scanlines automatically. Only channels - /// [chbegin,chend) will be read/copied (chbegin=0, chend=spec.nchannels - /// reads all channels, yielding equivalent behavior to the simpler - /// variant of read_image). - virtual bool read_image (int chbegin, int chend, - TypeDesc format, void *data, - stride_t xstride=AutoStride, - stride_t ystride=AutoStride, - stride_t zstride=AutoStride, - ProgressCallback progress_callback=NULL, - void *progress_callback_data=NULL); - - /// - /// Simple read_image reads to contiguous float pixels. - bool read_image (float *data) { - return read_image (TypeDesc::FLOAT, data); - } - - - /// read_native_scanline is just like read_scanline, except that it - /// keeps the data in the native format of the disk file and always - /// reads into contiguous memory (no strides). It's up to the user to - /// have enough space allocated and know what to do with the data. - /// IT IS EXPECTED THAT EACH FORMAT PLUGIN WILL OVERRIDE THIS METHOD. - virtual bool read_native_scanline (int y, int z, void *data) = 0; - - /// read_native_scanlines is just like read_scanlines, except that - /// it keeps the data in the native format of the disk file and - /// always reads into contiguous memory (no strides). It's up to - /// the user to have enough space allocated and know what to do with - /// the data. If a format reader subclass does not override this - /// method, the default implementation it will simply be a loop - /// calling read_native_scanline for each scanline. - virtual bool read_native_scanlines (int ybegin, int yend, int z, - void *data); - - /// A variant of read_native_scanlines that reads only channels - /// [chbegin,chend). If a format reader subclass does - /// not override this method, the default implementation will simply - /// call the all-channel version of read_native_scanlines into a - /// temporary buffer and copy the subset of channels. - virtual bool read_native_scanlines (int ybegin, int yend, int z, - int chbegin, int chend, void *data); - - /// read_native_tile is just like read_tile, except that it - /// keeps the data in the native format of the disk file and always - /// read into contiguous memory (no strides). It's up to the user to - /// have enough space allocated and know what to do with the data. - /// IT IS EXPECTED THAT EACH FORMAT PLUGIN WILL OVERRIDE THIS METHOD - /// IF IT SUPPORTS TILED IMAGES. - virtual bool read_native_tile (int x, int y, int z, void *data); - - /// read_native_tiles is just like read_tiles, except that it keeps - /// the data in the native format of the disk file and always reads - /// into contiguous memory (no strides). It's up to the caller to - /// have enough space allocated and know what to do with the data. - /// If a format reader does not override this method, the default - /// implementation it will simply be a loop calling read_native_tile - /// for each tile in the block. - virtual bool read_native_tiles (int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend, void *data); - - /// A variant of read_native_tiles that reads only channels - /// [chbegin,chend). If a format reader subclass does - /// not override this method, the default implementation will simply - /// call the all-channel version of read_native_tiles into a - /// temporary buffer and copy the subset of channels. - virtual bool read_native_tiles (int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend, - int chbegin, int chend, void *data); - - /// Read native deep data from multiple scanlines that include - /// pixels (*,y,z) for all ybegin <= y < yend, into deepdata. Only - /// channels [chbegin, chend) will be read (chbegin=0, - /// chend=spec.nchannels reads all channels). - virtual bool read_native_deep_scanlines (int ybegin, int yend, int z, - int chbegin, int chend, - DeepData &deepdata); - - /// Read the block of multiple native deep data tiles that include - /// all pixels in [xbegin,xend) X [ybegin,yend) X [zbegin,zend), - /// into deepdata. Only channels [chbegin,chend) will - /// be read (chbegin=0, chend=spec.nchannels reads all channels). - virtual bool read_native_deep_tiles (int xbegin, int xend, - int ybegin, int yend, - int zbegin, int zend, - int chbegin, int chend, - DeepData &deepdata); - - /// Read the entire deep data image of spec.width x spec.height x - /// spec.depth pixels, all channels, into deepdata. - virtual bool read_native_deep_image (DeepData &deepdata); - - - /// General message passing between client and image input server - /// - virtual int send_to_input (const char *format, ...); - int send_to_client (const char *format, ...); - - /// If any of the API routines returned false indicating an error, - /// this routine will return the error string (and clear any error - /// flags). If no error has occurred since the last time geterror() - /// was called, it will return an empty string. - std::string geterror () const { - std::string e = m_errmessage; - m_errmessage.clear (); - return e; - } - - /// An ImageInput::Creator is a function that creates and returns an - /// ImageInput. Once invoked, the resulting ImageInput is owned by - /// the caller, who is responsible for deleting it when done with it. - typedef ImageInput* (*Creator)(); - - /// Error reporting for the plugin implementation: call this with - /// printf-like arguments. Note however that this is fully typesafe! - // void error (const char *format, ...) const; - TINYFORMAT_WRAP_FORMAT (void, error, const, - std::ostringstream msg;, msg, append_error(msg.str());) - - /// Set the current thread-spawning policy: the maximum number of - /// threads that may be spawned by ImageInput internals. A value of 1 - /// means all work will be done by the calling thread; 0 means to use - /// the global OIIO::attribute("threads") value. - void threads (int n) { m_threads = n; } - - /// Retrieve the current thread-spawning policy. - int threads () const { return m_threads; } - -protected: - ImageSpec m_spec; // format spec of the current open subimage/MIPlevel - -private: - mutable std::string m_errmessage; // private storage of error message - int m_threads; // Thread policy - void append_error (const std::string& message) const; // add to m_errmessage - static ImageInput *create (const std::string &filename, bool do_open, - const std::string &plugin_searchpath); - -}; - - - - -/// ImageOutput abstracts the writing of an image file in a file -/// format-agnostic manner. -class OIIO_API ImageOutput { -public: - /// Create an ImageOutput that will write to a file, with the format - /// inferred from the extension of the name. The plugin_searchpath - /// parameter is a colon-separated list of directories to search for - /// ImageIO plugin DSO/DLL's. This just creates the ImageOutput, it - /// does not open the file. - static ImageOutput *create (const std::string &filename, - const std::string &plugin_searchpath=""); - - /// Destroy an ImageOutput that was created using ImageOutput::create(). - /// For some systems (Windows, I'm looking at you), it is not - /// necessarily safe to allocate memory in one DLL and free it in - /// another, so directly calling 'delete' on an ImageOutput allocated by - /// create() may be unusafe, but passing it to destroy() should be safe. - static void destroy (ImageOutput *x); - - ImageOutput (); - virtual ~ImageOutput (); - - /// Return the name of the format implemented by this class. - /// - virtual const char *format_name (void) const = 0; - - // Overrride these functions in your derived output class - // to inform the client which formats are supported - - /// Given the name of a 'feature', return whether this ImageOutput - /// supports output of images with the given properties. Most queries - /// will simply return 0 for "doesn't support" and nonzero for "supports - /// it", but it is acceptable to have queries return other nonzero - /// integers to indicate varying degrees of support or limits (but - /// should be clearly documented as such). - /// - /// Feature names that ImageIO plugins are expected to recognize - /// include: - /// "tiles" Is this format able to write tiled images? - /// "rectangles" Does this plugin accept arbitrary rectangular - /// pixel regions, not necessarily aligned to - /// scanlines or tiles? - /// "random_access" May tiles or scanlines be written in - /// any order (false indicates that they MUST - /// be in successive order). - /// "multiimage" Does this format support multiple subimages - /// within a file? - /// "appendsubimage" Does this format support adding subimages one at - /// a time through open(name,spec,AppendSubimage)? - /// If not, then open(name,subimages,specs) must - /// be used instead. - /// "mipmap" Does this format support multiple resolutions - /// for an image/subimage? - /// "volumes" Does this format support "3D" pixel arrays? - /// "alpha" Can this format support an alpha channel? - /// "nchannels" Can this format support arbitrary number of - /// channels (beyond RGBA)? - /// "rewrite" May the same scanline or tile be sent more than - /// once? (Generally, this will be true for - /// plugins that implement interactive display.) - /// "empty" Does this plugin support passing a NULL data - /// pointer to write_scanline or write_tile to - /// indicate that the entire data block is zero? - /// "channelformats" Does the plugin/format support per-channel - /// data formats? - /// "displaywindow" Does the format support display ("full") windows - /// distinct from the pixel data window? - /// "origin" Does the format support a nonzero x,y,z - /// origin of the pixel data window? - /// "negativeorigin" Does the format support negative x,y,z - /// and full_{x,y,z} origin values? - /// "deepdata" Deep (multi-sample per pixel) data - /// "arbitrary_metadata" Does this format allow metadata with - /// arbitrary names and types? - /// "exif" Can this format store Exif camera data? - /// "iptc" Can this format store IPTC data? - /// - /// Note that main advantage of this approach, versus having - /// separate individual supports_foo() methods, is that this allows - /// future expansion of the set of possible queries without changing - /// the API, adding new entry points, or breaking linkage - /// compatibility. - virtual int supports (string_view feature) const { return false; } - - enum OpenMode { Create, AppendSubimage, AppendMIPLevel }; - - /// Open the file with given name, with resolution and other format - /// data as given in newspec. Open returns true for success, false - /// for failure. Note that it is legal to call open multiple times - /// on the same file without a call to close(), if it supports - /// multiimage and mode is AppendSubimage, or if it supports - /// MIP-maps and mode is AppendMIPLevel -- this is interpreted as - /// appending a subimage, or a MIP level to the current subimage, - /// respectively. - virtual bool open (const std::string &name, const ImageSpec &newspec, - OpenMode mode=Create) = 0; - - /// Open the file with given name, expecting to have a given total - /// number of subimages, described by specs[0..subimages-1]. - /// Return true for success, false for failure. Upon success, the - /// first subimage will be open and ready for transmission of - /// pixels. Subsequent subimages will be denoted with the usual - /// call of open(name,spec,AppendSubimage) (and MIP levels by - /// open(name,spec,AppendMIPLevel)). - /// - /// The purpose of this call is to accommodate format-writing - /// libraries that fmust know the number and specifications of the - /// subimages upon first opening the file; such formats can be - /// detected by - /// supports("multiimage") && !supports("appendsubimage") - /// The individual specs passed to the appending open() calls for - /// subsequent subimages MUST match the ones originally passed. - virtual bool open (const std::string &name, int subimages, - const ImageSpec *specs) { - // Default implementation: just a regular open, assume that - // appending will work. - return open (name, specs[0]); - } - - /// Return a reference to the image format specification of the - /// current subimage. Note that the contents of the spec are - /// invalid before open() or after close(). - const ImageSpec &spec (void) const { return m_spec; } - - /// Close an image that we are totally done with. This should leave - /// the plugin in a state where it could open a new file safely, - /// without having to destroy the writer. - virtual bool close () = 0; - - /// Write a full scanline that includes pixels (*,y,z). (z is - /// ignored for 2D non-volume images.) The stride value gives the - /// distance between successive pixels (in bytes). Strides set to - /// AutoStride imply 'contiguous' data, i.e., - /// xstride == spec.nchannels*format.size() - /// The data are automatically converted from 'format' to the actual - /// output format (as specified to open()) by this method. - /// If format is TypeDesc::UNKNOWN, then rather than converting from - /// format, it will just copy pixels in the file's native data layout - /// (including, possibly, per-channel data formats). - /// Return true for success, false for failure. It is a failure to - /// call write_scanline with an out-of-order scanline if this format - /// driver does not support random access. - virtual bool write_scanline (int y, int z, TypeDesc format, - const void *data, stride_t xstride=AutoStride); - - /// Write multiple scanlines that include pixels (*,y,z) for all - /// ybegin <= y < yend, from data. This is analogous to - /// write_scanline except that it may be used to write more than one - /// scanline at a time (which, for some formats, may be able to be - /// done much more efficiently or in parallel). - virtual bool write_scanlines (int ybegin, int yend, int z, - TypeDesc format, const void *data, - stride_t xstride=AutoStride, - stride_t ystride=AutoStride); - - /// Write the tile with (x,y,z) as the upper left corner. (z is - /// ignored for 2D non-volume images.) The three stride values give - /// the distance (in bytes) between successive pixels, scanlines, - /// and volumetric slices, respectively. Strides set to AutoStride - /// imply 'contiguous' data in the shape of a full tile, i.e., - - /// xstride == spec.nchannels*format.size() - /// ystride == xstride*spec.tile_width - /// zstride == ystride*spec.tile_height - /// The data are automatically converted from 'format' to the actual - /// output format (as specified to open()) by this method. - /// If format is TypeDesc::UNKNOWN, then rather than converting from - /// format, it will just copy pixels in the file's native data layout - /// (including, possibly, per-channel data formats). - /// Return true for success, false for failure. It is a failure to - /// call write_tile with an out-of-order tile if this format driver - /// does not support random access. - virtual bool write_tile (int x, int y, int z, TypeDesc format, - const void *data, stride_t xstride=AutoStride, - stride_t ystride=AutoStride, - stride_t zstride=AutoStride); - - /// Write the block of multiple tiles that include all pixels in - /// [xbegin,xend) X [ybegin,yend) X [zbegin,zend). This is analogous to - /// write_tile except that it may be used to write more than one tile at - /// a time (which, for some formats, may be able to be done much more - /// efficiently or in parallel). - /// The begin/end pairs must correctly delineate tile boundaries, with - /// the exception that it may also be the end of the image data if the - /// image resolution is not a whole multiple of the tile size. - /// The stride values give the data spacing of adjacent pixels, - /// scanlines, and volumetric slices (measured in bytes). Strides set to - /// AutoStride imply 'contiguous' data in the shape of the [begin,end) - /// region, i.e., - /// xstride == spec.nchannels*format.size() - /// ystride == xstride * (xend-xbegin) - /// zstride == ystride * (yend-ybegin) - virtual bool write_tiles (int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend, TypeDesc format, - const void *data, stride_t xstride=AutoStride, - stride_t ystride=AutoStride, - stride_t zstride=AutoStride); - - /// Write a rectangle of pixels given by the range - /// [xbegin,xend) X [ybegin,yend) X [zbegin,zend) - /// The stride values give the data spacing of adjacent pixels, - /// scanlines, and volumetric slices (measured in bytes). Strides set to - /// AutoStride imply 'contiguous' data in the shape of the [begin,end) - /// region, i.e., - /// xstride == spec.nchannels*format.size() - /// ystride == xstride * (xend-xbegin) - /// zstride == ystride * (yend-ybegin) - /// The data are automatically converted from 'format' to the actual - /// output format (as specified to open()) by this method. If - /// format is TypeDesc::UNKNOWN, it will just copy pixels assuming - /// they are already in the file's native data layout (including, - /// possibly, per-channel data formats). - /// - /// Return true for success, false for failure. It is a failure to - /// call write_rectangle for a format plugin that does not return - /// true for supports("rectangles"). - virtual bool write_rectangle (int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend, TypeDesc format, - const void *data, stride_t xstride=AutoStride, - stride_t ystride=AutoStride, - stride_t zstride=AutoStride); - - /// Write the entire image of spec.width x spec.height x spec.depth - /// pixels, with the given strides and in the desired format. - /// Strides set to AutoStride imply 'contiguous' data, i.e., - /// xstride == spec.nchannels*format.size() - /// ystride == xstride*spec.width - /// zstride == ystride*spec.height - /// Depending on spec, write either all tiles or all scanlines. - /// Assume that data points to a layout in row-major order. - /// If format is TypeDesc::UNKNOWN, then rather than converting from - /// format, it will just copy pixels in the file's native data layout - /// (including, possibly, per-channel data formats). - /// Because this may be an expensive operation, a progress callback - /// may be passed. Periodically, it will be called as follows: - /// progress_callback (progress_callback_data, float done) - /// where 'done' gives the portion of the image - virtual bool write_image (TypeDesc format, const void *data, - stride_t xstride=AutoStride, - stride_t ystride=AutoStride, - stride_t zstride=AutoStride, - ProgressCallback progress_callback=NULL, - void *progress_callback_data=NULL); - - /// Write deep scanlines containing pixels (*,y,z), for all y in - /// [ybegin,yend), to a deep file. - virtual bool write_deep_scanlines (int ybegin, int yend, int z, - const DeepData &deepdata); - - /// Write the block of deep tiles that include all pixels in - /// [xbegin,xend) X [ybegin,yend) X [zbegin,zend). - /// The begin/end pairs must correctly delineate tile boundaries, - /// with the exception that it may also be the end of the image data - /// if the image resolution is not a whole multiple of the tile size. - virtual bool write_deep_tiles (int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend, - const DeepData &deepdata); - - /// Write the entire deep image denoted by data. - virtual bool write_deep_image (const DeepData &deepdata); - - /// Read the current subimage of 'in', and write it as the next - /// subimage of *this, in a way that is efficient and does not alter - /// pixel values, if at all possible. Both in and this must be a - /// properly-opened ImageInput and ImageOutput, respectively, and - /// their current images must match in size and number of channels. - /// Return true if it works ok, false if for some reason the - /// operation wasn't possible. - /// - /// If a particular ImageOutput implementation does not supply a - /// copy_image method, it will inherit the default implementation, - /// which is to simply read scanlines or tiles from 'in' and write - /// them to *this. However, some ImageIO implementations may have a - /// special technique for directly copying raw pixel data from the - /// input to the output, when both input and output are the SAME - /// file type and the same data format. This can be more efficient - /// than in->read_image followed by out->write_image, and avoids any - /// unintended pixel alterations, especially for formats that use - /// lossy compression. - virtual bool copy_image (ImageInput *in); - - /// General message passing between client and image output server - /// - virtual int send_to_output (const char *format, ...); - int send_to_client (const char *format, ...); - - /// If any of the API routines returned false indicating an error, - /// this routine will return the error string (and clear any error - /// flags). If no error has occurred since the last time geterror() - /// was called, it will return an empty string. - std::string geterror () const { - std::string e = m_errmessage; - m_errmessage.clear (); - return e; - } - - /// An ImageOutput::Creator is a function that creates and returns an - /// ImageOutput. Once invoked, the resulting ImageOutput is owned by - /// the caller, who is responsible for deleting it when done with it. - typedef ImageOutput* (*Creator)(); - - /// Error reporting for the plugin implementation: call this with - /// printf-like arguments. Note however that this is fully typesafe! - /// void error (const char *format, ...) - TINYFORMAT_WRAP_FORMAT (void, error, const, - std::ostringstream msg;, msg, append_error(msg.str());) - - /// Set the current thread-spawning policy: the maximum number of - /// threads that may be spawned by ImageOutput internals. A value of 1 - /// means all work will be done by the calling thread; 0 means to use - /// the global OIIO::attribute("threads") value. - void threads (int n) { m_threads = n; } - - /// Retrieve the current thread-spawning policy. - int threads () const { return m_threads; } - -protected: - /// Helper routines used by write_* implementations: convert data (in - /// the given format and stride) to the "native" format of the file - /// (described by the 'spec' member variable), in contiguous order. This - /// requires a scratch space to be passed in so that there are no memory - /// leaks. Returns a pointer to the native data, which may be the - /// original data if it was already in native format and contiguous, or - /// it may point to the scratch space if it needed to make a copy or do - /// conversions. For float->uint8 conversions only, if dither is - /// nonzero, random dither will be added to reduce quantization banding - /// artifacts; in this case, the specific nonzero dither value is used - /// as a seed for the hash function that produces the per-pixel dither - /// amounts, and the optional [xyz]origin parameters help it to align - /// the pixels to the right position in the dither pattern. - const void *to_native_scanline (TypeDesc format, - const void *data, stride_t xstride, - std::vector &scratch, - unsigned int dither=0, - int yorigin=0, int zorigin=0); - const void *to_native_tile (TypeDesc format, const void *data, - stride_t xstride, stride_t ystride, - stride_t zstride, - std::vector &scratch, - unsigned int dither=0, - int xorigin=0, int yorigin=0, int zorigin=0); - const void *to_native_rectangle (int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend, - TypeDesc format, const void *data, - stride_t xstride, stride_t ystride, - stride_t zstride, - std::vector &scratch, - unsigned int dither=0, - int xorigin=0, int yorigin=0, int zorigin=0); - - /// Helper function to copy a rectangle of data into the right spot in - /// an image-sized buffer. In addition to copying to the right place, - /// this handles data format conversion and dither (if the spec's - /// "oiio:dither" is nonzero, and if it's converting from a float-like - /// type to UINT8). The buf_format describes the type of image_buffer, - /// if it's TypeDesc::UNKNOWN it will be assumed to be spec.format. - bool copy_to_image_buffer (int xbegin, int xend, int ybegin, int yend, - int zbegin, int zend, TypeDesc format, - const void *data, stride_t xstride, - stride_t ystride, stride_t zstride, - void *image_buffer, - TypeDesc buf_format = TypeDesc::UNKNOWN); - /// Helper function to copy a tile of data into the right spot in an - /// image-sized buffer. This is really just a wrapper for - /// copy_to_image_buffer, passing all the right parameters to copy - /// exactly one tile. - bool copy_tile_to_image_buffer (int x, int y, int z, TypeDesc format, - const void *data, stride_t xstride, - stride_t ystride, stride_t zstride, - void *image_buffer, - TypeDesc buf_format = TypeDesc::UNKNOWN); - -protected: - ImageSpec m_spec; ///< format spec of the currently open image - -private: - void append_error (const std::string& message) const; // add to m_errmessage - mutable std::string m_errmessage; ///< private storage of error message - int m_threads; // Thread policy -}; - - - -// Utility functions - -/// Retrieve the version of OpenImageIO for the library. This is so -/// plugins can query to be sure they are linked against an adequate -/// version of the library. -OIIO_API int openimageio_version (); - -/// Special geterror() called after ImageInput::create or -/// ImageOutput::create, since if create fails, there's no object on -/// which call obj->geterror(). This function returns the last error -/// for this particular thread; separate threads will not clobber each -/// other's global error messages. -OIIO_API std::string geterror (); - -/// Set a global attribute controlling OpenImageIO. Return true -/// if the name and type were recognized and the attribute was set. -/// -/// Documented attributes: -/// int threads -/// How many threads to use for operations that can be sped -/// by spawning threads (default=0, meaning to use the full -/// available hardware concurrency detected). -/// int exr_threads -/// The size of the internal OpenEXR thread pool. The default -/// is to use the full available hardware concurrency detected. -/// string plugin_searchpath -/// Colon-separated list of directories to search for -/// dynamically-loaded format plugins. -/// string format_list (for 'getattribute' only, cannot set) -/// Comma-separated list of all format names supported -/// or for which plugins could be found. -/// string extension_list (for 'getattribute' only, cannot set) -/// For each format, the format name followed by a colon, -/// followed by comma-separated list of all extensions that -/// are presumed to be used for that format. Semicolons -/// separate the lists for formats. For example, -/// "tiff:tif;jpeg:jpg,jpeg;openexr:exr" -/// int read_chunk -/// The number of scanlines that will be attempted to read at -/// once for read_image calls (default: 256). -/// int debug -/// When nonzero, various debug messages may be printed. -/// The default is 0 for release builds, 1 for DEBUG builds, -/// but also may be overridden by the OPENIMAGEIO_DEBUG env -/// variable. -OIIO_API bool attribute (string_view name, TypeDesc type, const void *val); -// Shortcuts for common types -inline bool attribute (string_view name, int val) { - return attribute (name, TypeDesc::TypeInt, &val); -} -inline bool attribute (string_view name, float val) { - return attribute (name, TypeDesc::TypeFloat, &val); -} -inline bool attribute (string_view name, string_view val) { - const char *s = val.c_str(); - return attribute (name, TypeDesc::TypeString, &s); -} - -/// Get the named global attribute of OpenImageIO, store it in *val. -/// Return true if found and it was compatible with the type specified, -/// otherwise return false and do not modify the contents of *val. It -/// is up to the caller to ensure that val points to the right kind and -/// size of storage for the given type. -OIIO_API bool getattribute (string_view name, TypeDesc type, void *val); -// Shortcuts for common types -inline bool getattribute (string_view name, int &val) { - return getattribute (name, TypeDesc::TypeInt, &val); -} -inline bool getattribute (string_view name, float &val) { - return getattribute (name, TypeDesc::TypeFloat, &val); -} -inline bool getattribute (string_view name, char **val) { - return getattribute (name, TypeDesc::TypeString, val); -} -inline bool getattribute (string_view name, std::string &val) { - ustring s; - bool ok = getattribute (name, TypeDesc::TypeString, &s); - if (ok) - val = s.string(); - return ok; -} -inline int get_int_attribute (string_view name, int defaultval=0) { - int val; - return getattribute (name, TypeDesc::TypeInt, &val) ? val : defaultval; -} -inline float get_float_attribute (string_view name, float defaultval=0) { - float val; - return getattribute (name, TypeDesc::TypeFloat, &val) ? val : defaultval; -} -inline string_view get_string_attribute (string_view name, - string_view defaultval = string_view()) { - ustring val; - return getattribute (name, TypeDesc::TypeString, &val) ? string_view(val) : defaultval; -} - - -/// Register the input and output 'create' routines and list of file -/// extensions for a particular format. -OIIO_API void declare_imageio_format (const std::string &format_name, - ImageInput::Creator input_creator, - const char **input_extensions, - ImageOutput::Creator output_creator, - const char **output_extensions); - - -/// Helper function: convert contiguous arbitrary data between two -/// arbitrary types (specified by TypeDesc's) -/// Return true if ok, false if it didn't know how to do the -/// conversion. If dst_type is UNKNOWN, it will be assumed to be the -/// same as src_type. -OIIO_API bool convert_types (TypeDesc src_type, const void *src, - TypeDesc dst_type, void *dst, int n); - -/// DEPRECATED(1.4) -- for some reason we had a convert_types that took -/// alpha_channel and z_channel parameters, but never did anything -/// with them. -OIIO_API bool convert_types (TypeDesc src_type, const void *src, - TypeDesc dst_type, void *dst, int n, - int alpha_channel, int z_channel = -1); - -/// Helper routine for data conversion: Convert an image of nchannels x -/// width x height x depth from src to dst. The src and dst may have -/// different data formats and layouts. Clever use of this function can -/// not only exchange data among different formats (e.g., half to 8-bit -/// unsigned), but also can copy selective channels, copy subimages, -/// etc. If you're lazy, it's ok to pass AutoStride for any of the -/// stride values, and they will be auto-computed assuming contiguous -/// data. Return true if ok, false if it didn't know how to do the -/// conversion. -OIIO_API bool convert_image (int nchannels, int width, int height, int depth, - const void *src, TypeDesc src_type, - stride_t src_xstride, stride_t src_ystride, - stride_t src_zstride, - void *dst, TypeDesc dst_type, - stride_t dst_xstride, stride_t dst_ystride, - stride_t dst_zstride, - int alpha_channel = -1, int z_channel = -1); - -/// A version of convert_image that will break up big jobs into multiple -/// threads. -OIIO_API bool parallel_convert_image ( - int nchannels, int width, int height, int depth, - const void *src, TypeDesc src_type, - stride_t src_xstride, stride_t src_ystride, - stride_t src_zstride, - void *dst, TypeDesc dst_type, - stride_t dst_xstride, stride_t dst_ystride, - stride_t dst_zstride, - int alpha_channel=-1, int z_channel=-1, int nthreads=0); - -/// Add random [-theramplitude,ditheramplitude] dither to the color channels -/// of the image. Dither will not be added to the alpha or z channel. The -/// image origin and dither seed values allow a reproducible (or variable) -/// dither pattern. If the strides are set to AutoStride, they will be -/// assumed to be contiguous floats in data of the given dimensions. -OIIO_API void add_dither (int nchannels, int width, int height, int depth, - float *data, - stride_t xstride, stride_t ystride, stride_t zstride, - float ditheramplitude, - int alpha_channel = -1, int z_channel = -1, - unsigned int ditherseed = 1, - int chorigin=0, int xorigin=0, - int yorigin=0, int zorigin=0); - -/// Convert unassociated to associated alpha by premultiplying all color -/// (non-alpha, non-z) channels by alpha. -OIIO_API void premult (int nchannels, int width, int height, int depth, - int chbegin, int chend, - TypeDesc datatype, void *data, stride_t xstride, - stride_t ystride, stride_t zstride, - int alpha_channel = -1, int z_channel = -1); - -/// Helper routine for data conversion: Copy an image of nchannels x -/// width x height x depth from src to dst. The src and dst may have -/// different data layouts, but must have the same data type. Clever -/// use of this function can change layouts or strides, copy selective -/// channels, copy subimages, etc. If you're lazy, it's ok to pass -/// AutoStride for any of the stride values, and they will be -/// auto-computed assuming contiguous data. Return true if ok, false if -/// it didn't know how to do the conversion. -OIIO_API bool copy_image (int nchannels, int width, int height, int depth, - const void *src, stride_t pixelsize, - stride_t src_xstride, stride_t src_ystride, - stride_t src_zstride, - void *dst, stride_t dst_xstride, - stride_t dst_ystride, stride_t dst_zstride); - -/// Decode a raw Exif data block and save all the metadata in an -/// ImageSpec. Return true if all is ok, false if the exif block was -/// somehow malformed. The binary data pointed to by 'exif' should -/// start with a TIFF directory header. -OIIO_API bool decode_exif (const void *exif, int length, ImageSpec &spec); - -/// Construct an Exif data block from the ImageSpec, appending the Exif -/// data as a big blob to the char vector. -OIIO_API void encode_exif (const ImageSpec &spec, std::vector &blob); - -/// Helper: For the given OIIO metadata attribute name, look up the Exif tag -/// ID, TIFFDataType (expressed as an int), and count. Return true and fill -/// in the fields if found, return false if not found. -OIIO_API bool exif_tag_lookup (string_view name, int &tag, - int &tifftype, int &count); - -/// Add metadata to spec based on raw IPTC (International Press -/// Telecommunications Council) metadata in the form of an IIM -/// (Information Interchange Model). Return true if all is ok, false if -/// the iptc block was somehow malformed. This is a utility function to -/// make it easy for multiple format plugins to support embedding IPTC -/// metadata without having to duplicate functionality within each -/// plugin. Note that IIM is actually considered obsolete and is -/// replaced by an XML scheme called XMP. -OIIO_API bool decode_iptc_iim (const void *iptc, int length, ImageSpec &spec); - -/// Find all the IPTC-amenable metadata in spec and assemble it into an -/// IIM data block in iptc. This is a utility function to make it easy -/// for multiple format plugins to support embedding IPTC metadata -/// without having to duplicate functionality within each plugin. Note -/// that IIM is actually considered obsolete and is replaced by an XML -/// scheme called XMP. -OIIO_API void encode_iptc_iim (const ImageSpec &spec, std::vector &iptc); - -/// Add metadata to spec based on XMP data in an XML block. Return true -/// if all is ok, false if the xml was somehow malformed. This is a -/// utility function to make it easy for multiple format plugins to -/// support embedding XMP metadata without having to duplicate -/// functionality within each plugin. -OIIO_API bool decode_xmp (const std::string &xml, ImageSpec &spec); - -/// Find all the relavant metadata (IPTC, Exif, etc.) in spec and -/// assemble it into an XMP XML string. This is a utility function to -/// make it easy for multiple format plugins to support embedding XMP -/// metadata without having to duplicate functionality within each -/// plugin. If 'minimal' is true, then don't encode things that would -/// be part of ordinary TIFF or exif tags. -OIIO_API std::string encode_xmp (const ImageSpec &spec, bool minimal=false); - -// All the wrap_foo functions implement a wrap mode, wherein coord is -// altered to be origin <= coord < origin+width. The return value -// indicates if the resulting wrapped value is valid (example, for -// wrap_black, values outside the region are invalid and do not modify -// the coord parameter). -OIIO_API bool wrap_black (int &coord, int origin, int width); -OIIO_API bool wrap_clamp (int &coord, int origin, int width); -OIIO_API bool wrap_periodic (int &coord, int origin, int width); -OIIO_API bool wrap_periodic_pow2 (int &coord, int origin, int width); -OIIO_API bool wrap_mirror (int &coord, int origin, int width); - -// Typedef for the function signature of a wrap implementation. -typedef bool (*wrap_impl) (int &coord, int origin, int width); - - -namespace pvt { -// For internal use - use debugmsg() below for a nicer interface. -OIIO_API void debugmsg_ (string_view message); -}; - -/// debugmsg(format, ...) prints debugging message when attribute "debug" is -/// nonzero, which it is by default for DEBUG compiles or when the -/// environment variable OPENIMAGEIO_DEBUG is set. This is preferred to raw -/// output to stderr for debugging statements. -/// void debugmsg (const char *format, ...); -TINYFORMAT_WRAP_FORMAT (void, debugmsg, /**/, - std::ostringstream msg;, msg, pvt::debugmsg_(msg.str());) - - -// to force correct linkage on some systems -OIIO_API void _ImageIO_force_link (); - -OIIO_NAMESPACE_END - -#endif // OPENIMAGEIO_IMAGEIO_H diff --git a/3rdparty/oiio16/include/OpenImageIO/missing_math.h b/3rdparty/oiio16/include/OpenImageIO/missing_math.h deleted file mode 100644 index c27516ba..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/missing_math.h +++ /dev/null @@ -1,295 +0,0 @@ -/* - Copyright 2008-2014 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -/// \file -/// -/// This adds definitions we think *should* be in math.h, but which on -/// on some platforms appears to be missing in action. -/// - - -#pragma once - -#include - -#include "oiioversion.h" /* Just for the OIIO_NAMESPACE stuff */ - - -#ifndef M_PI -/// PI -# define M_PI 3.14159265358979323846264338327950288 -#endif - -#ifndef M_PI_2 -/// PI / 2 -# define M_PI_2 1.57079632679489661923132169163975144 -#endif - -#ifndef M_PI_4 -/// PI / 4 -# define M_PI_4 0.785398163397448309615660845819875721 -#endif - -#ifndef M_TWO_PI -/// PI * 2 -# define M_TWO_PI (M_PI * 2.0) -#endif - -#ifndef M_1_PI -/// 1/PI -# define M_1_PI 0.318309886183790671537767526745028724 -#endif - -#ifndef M_2_PI -/// 2/PI -# define M_2_PI 0.636619772367581343075535053490057448 -#endif - -#ifndef M_SQRT2 -/// sqrt(2) -# define M_SQRT2 1.41421356237309504880168872420969808 -#endif - -#ifndef M_SQRT1_2 -/// 1/sqrt(2) -# define M_SQRT1_2 0.707106781186547524400844362104849039 -#endif - -#ifndef M_LN2 -/// ln(2) -# define M_LN2 0.69314718055994530941723212145817656 -#endif - -#ifndef M_LN10 -/// ln(10) -# define M_LN10 2.30258509299404568401799145468436421 -#endif - -#ifndef M_E -/// e, Euler's number -# define M_E 2.71828182845904523536028747135266250 -#endif - -#ifndef M_LOG2E -/// log2(e) -# define M_LOG2E 1.44269504088896340735992468100189214 -#endif - - -OIIO_NAMESPACE_BEGIN - -#ifdef _WIN32 -// Windows doesn't define these functions from math.h -#define hypotf _hypotf -#define copysign(x,y) _copysign(x,y) -#define copysignf(x,y) copysign(x,y) - - - -inline float -truncf (float val) -{ - return (float)(int)val; -} - - -#if defined(_MSC_VER) -#if _MSC_VER < 1800 /* Needed for MSVS prior to 2013 */ - -template -inline int isnan (T x) { - return _isnan(x); -} - - -template -inline int isfinite (T x) { - return _finite(x); -} - - -template -inline int isinf (T x) { - return (isfinite(x)||isnan(x)) ? 0 : static_cast(copysign(T(1.0), x)); -} - - -inline double -round (float val) { - return floor (val + 0.5); -} - - -inline float -roundf (float val) { - return static_cast(round (val)); -} - - -inline float -log2f (float val) { - return logf (val)/static_cast(M_LN2); -} - - -inline float -cbrtf (float val) { - return powf (val, 1.0/3.0); -} - - -inline float -rintf (float val) { - return val + copysignf(0.5f, val); -} - -#elif _MSC_VER >= 1800 && __cplusplus <= 201103L -// Prior to c++11, these were implementation defined, and on msvc, were not in the -// std namespace -using ::isnan; -using ::isinf; -using ::isfinite; -#else -using std::isnan; -using std::isinf; -using std::isfinite; -#endif - -#endif /* MSVS < 2013 */ - - -inline float -exp2f (float val) { - // 2^val = e^(val*ln(2)) - return exp( val * M_LN2 ); -} - - -#if defined(_MSC_VER) && _MSC_VER < 1800 /* Needed for MSVS prior to 2013 */ -inline float -logbf (float val) { - // please see http://www.kernel.org/doc/man-pages/online/pages/man3/logb.3.html - return floorf (logf(fabsf(val))/logf(FLT_RADIX)); -} - - -// from http://www.johndcook.com/cpp_expm1.html -inline double -expm1(double val) -{ - // exp(x) - 1 without loss of precision for small values of x. - if (fabs(val) < 1e-5) - return val + 0.5*val*val; - else - return exp(val) - 1.0; -} - - -inline float -expm1f (float val) -{ - return (float)expm1(val); -} - - -// from http://www.johndcook.com/cpp_erf.html -inline double -erf(double x) -{ - // constants - double a1 = 0.254829592; - double a2 = -0.284496736; - double a3 = 1.421413741; - double a4 = -1.453152027; - double a5 = 1.061405429; - double p = 0.3275911; - - // Save the sign of x - int sign = 1; - if (x < 0) - sign = -1; - x = fabs(x); - - // A&S formula 7.1.26 - double t = 1.0/(1.0 + p*x); - double y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*exp(-x*x); - - return sign*y; -} - - -inline float -erff (float val) -{ - return (float)erf(val); -} - - -inline double -erfc(double val) -{ - return 1.0 - erf(val); -} - - -inline float -erfcf (float val) -{ - return (float)erfc(val); -} - -#endif /* MSVS < 2013 */ - -#endif /* _WIN32 */ - - -#if !defined(_MSC_VER) - using std::isnan; - using std::isinf; - using std::isfinite; -#endif - - - -// Functions missing from FreeBSD -#if (defined(__FreeBSD__) && (__FreeBSD_version < 803000)) - -inline float -log2f (float val) { - return logf (val)/static_cast(M_LN2); -} - -#endif - - -OIIO_NAMESPACE_END - - diff --git a/3rdparty/oiio16/include/OpenImageIO/oiioversion.h b/3rdparty/oiio16/include/OpenImageIO/oiioversion.h deleted file mode 100644 index d346f6f7..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/oiioversion.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -#ifndef OPENIMAGEIO_VERSION_H -#define OPENIMAGEIO_VERSION_H - - -// Versioning of the OpenImageIO software - -#define OIIO_NAMESPACE OpenImageIO -#define OIIO_VERSION_MAJOR 1 -#define OIIO_VERSION_MINOR 6 -#define OIIO_VERSION_PATCH 11 -#define OIIO_VERSION_RELEASE_TYPE dev -#define OIIO_VERSION_NS v1_6 - -#define OIIO_VERSION (10000 * OIIO_VERSION_MAJOR + \ - 100 * OIIO_VERSION_MINOR + \ - OIIO_VERSION_PATCH) -// We also define the old name for backwards compatibility purposes. -#define OPENIMAGEIO_VERSION OIIO_VERSION - -// Magic macros to make OPENIMAGEIO_VERSION_STRING that looks like "1.2.3" -#define OIIO_MAKE_VERSION_STRING2(a,b,c,d) #a "." #b "." #c #d -#define OIIO_MAKE_VERSION_STRING(a,b,c,d) OIIO_MAKE_VERSION_STRING2(a,b,c,d) -#define OIIO_VERSION_STRING \ - OIIO_MAKE_VERSION_STRING(OIIO_VERSION_MAJOR, \ - OIIO_VERSION_MINOR, OIIO_VERSION_PATCH, \ - OIIO_VERSION_RELEASE_TYPE) -#define OIIO_INTRO_STRING "OpenImageIO " OIIO_VERSION_STRING " http://www.openimageio.org" - - -#ifndef NAMESPACE_BEGIN -# define NAMESPACE_BEGIN(name) namespace name { -#endif -#ifndef NAMESPACE_END -# define NAMESPACE_END(name) } -#endif - -// Macros to use in each file to enter and exit the right name spaces. -#define OIIO_NAMESPACE_BEGIN \ - NAMESPACE_BEGIN(OIIO_NAMESPACE) \ - NAMESPACE_BEGIN(OIIO_VERSION_NS) -#define OIIO_NAMESPACE_END \ - NAMESPACE_END(OIIO_VERSION_NS) \ - using namespace OIIO_VERSION_NS;\ - NAMESPACE_END(OIIO_NAMESPACE) -#define OIIO_NAMESPACE_USING using namespace OIIO_NAMESPACE; - -// Establish the name spaces and make an alias 'OIIO' that gives us what -// everybody really wants. -namespace OIIO_NAMESPACE { namespace OIIO_VERSION_NS { } } -namespace OIIO = OIIO_NAMESPACE::OIIO_VERSION_NS; - - -/// Each imageio DSO/DLL should include this statement: -/// DLLPUBLIC int FORMAT_imageio_version = OPENIMAGEIO_PLUGIN_VERSION; -/// libOpenImageIO will check for compatibility this way. -/// This should get bumped any time we change the API in any way that -/// will make previously-compiled plugins break. -/// -/// History: -/// Version 3 added supports_rectangles() and write_rectangle() to -/// ImageOutput, and added stride parameters to the ImageInput read -/// routines. -/// Version 10 represents forking from NVIDIA's open source version, -/// with which we break backwards compatibility. -/// Version 11 teased apart subimage versus miplevel specification in -/// the APIs and per-channel formats (introduced in OIIO 0.9). -/// Version 12 added read_scanlines(), write_scanlines(), read_tiles(), -/// write_tiles(), and ImageInput::supports(). (OIIO 1.0) -/// Version 13 added ImageInput::valid_file(). (OIIO 1.1) -/// Version 14 added ImageOutput::open() variety for multiple subimages. -/// Version 15 added support for "deep" images (changing ImageSpec, -/// ImageInput, ImageOutput). -/// Version 16 changed the ImageInput functions taking channel ranges -/// from firstchan,nchans to chbegin,chend. -/// Version 17 changed to int supports(string_view) rather than -/// bool supports(const std::string&)). (OIIO 1.6) -/// Version 18 changed to add an m_threads member to ImageInput/Output. - -#define OIIO_PLUGIN_VERSION 18 - -#define OIIO_PLUGIN_NAMESPACE_BEGIN OIIO_NAMESPACE_BEGIN -#define OIIO_PLUGIN_NAMESPACE_END OIIO_NAMESPACE_END - -#ifdef EMBED_PLUGINS -#define OIIO_PLUGIN_EXPORTS_BEGIN -#define OIIO_PLUGIN_EXPORTS_END -#else -#define OIIO_PLUGIN_EXPORTS_BEGIN extern "C" { -#define OIIO_PLUGIN_EXPORTS_END } -#endif - -/// OIIO_BUILD_CPP11 will be 1 if this OIIO was built using C++11 -#define OIIO_BUILD_CPP11 -/// OIIO_BUILD_CPP14 will be 1 if this OIIO was built using C++14 -/// OIIO_BUILD_USELIBPLUSPLUS will be 1 if this OIIO was built using libc++ -#define OIIO_BUILD_LIBCPLUSPLUS - -#endif - diff --git a/3rdparty/oiio16/include/OpenImageIO/oiioversion.h.in b/3rdparty/oiio16/include/OpenImageIO/oiioversion.h.in deleted file mode 100644 index 365148c4..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/oiioversion.h.in +++ /dev/null @@ -1,131 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -#ifndef OPENIMAGEIO_VERSION_H -#define OPENIMAGEIO_VERSION_H - - -// Versioning of the OpenImageIO software - -#define OIIO_NAMESPACE @OIIO_NAMESPACE@ -#define OIIO_VERSION_MAJOR @OIIO_VERSION_MAJOR@ -#define OIIO_VERSION_MINOR @OIIO_VERSION_MINOR@ -#define OIIO_VERSION_PATCH @OIIO_VERSION_PATCH@ -#define OIIO_VERSION_RELEASE_TYPE @OIIO_VERSION_RELEASE_TYPE@ -#define OIIO_VERSION_NS @OIIO_VERSION_NS@ - -#define OIIO_VERSION (10000 * OIIO_VERSION_MAJOR + \ - 100 * OIIO_VERSION_MINOR + \ - OIIO_VERSION_PATCH) -// We also define the old name for backwards compatibility purposes. -#define OPENIMAGEIO_VERSION OIIO_VERSION - -// Magic macros to make OPENIMAGEIO_VERSION_STRING that looks like "1.2.3" -#define OIIO_MAKE_VERSION_STRING2(a,b,c,d) #a "." #b "." #c #d -#define OIIO_MAKE_VERSION_STRING(a,b,c,d) OIIO_MAKE_VERSION_STRING2(a,b,c,d) -#define OIIO_VERSION_STRING \ - OIIO_MAKE_VERSION_STRING(OIIO_VERSION_MAJOR, \ - OIIO_VERSION_MINOR, OIIO_VERSION_PATCH, \ - OIIO_VERSION_RELEASE_TYPE) -#define OIIO_INTRO_STRING "OpenImageIO " OIIO_VERSION_STRING " http://www.openimageio.org" - - -#ifndef NAMESPACE_BEGIN -# define NAMESPACE_BEGIN(name) namespace name { -#endif -#ifndef NAMESPACE_END -# define NAMESPACE_END(name) } -#endif - -// Macros to use in each file to enter and exit the right name spaces. -#define OIIO_NAMESPACE_BEGIN \ - NAMESPACE_BEGIN(OIIO_NAMESPACE) \ - NAMESPACE_BEGIN(OIIO_VERSION_NS) -#define OIIO_NAMESPACE_END \ - NAMESPACE_END(OIIO_VERSION_NS) \ - using namespace OIIO_VERSION_NS;\ - NAMESPACE_END(OIIO_NAMESPACE) -#define OIIO_NAMESPACE_USING using namespace OIIO_NAMESPACE; - -// Establish the name spaces and make an alias 'OIIO' that gives us what -// everybody really wants. -namespace OIIO_NAMESPACE { namespace OIIO_VERSION_NS { } } -namespace OIIO = OIIO_NAMESPACE::OIIO_VERSION_NS; - - -/// Each imageio DSO/DLL should include this statement: -/// DLLPUBLIC int FORMAT_imageio_version = OPENIMAGEIO_PLUGIN_VERSION; -/// libOpenImageIO will check for compatibility this way. -/// This should get bumped any time we change the API in any way that -/// will make previously-compiled plugins break. -/// -/// History: -/// Version 3 added supports_rectangles() and write_rectangle() to -/// ImageOutput, and added stride parameters to the ImageInput read -/// routines. -/// Version 10 represents forking from NVIDIA's open source version, -/// with which we break backwards compatibility. -/// Version 11 teased apart subimage versus miplevel specification in -/// the APIs and per-channel formats (introduced in OIIO 0.9). -/// Version 12 added read_scanlines(), write_scanlines(), read_tiles(), -/// write_tiles(), and ImageInput::supports(). (OIIO 1.0) -/// Version 13 added ImageInput::valid_file(). (OIIO 1.1) -/// Version 14 added ImageOutput::open() variety for multiple subimages. -/// Version 15 added support for "deep" images (changing ImageSpec, -/// ImageInput, ImageOutput). -/// Version 16 changed the ImageInput functions taking channel ranges -/// from firstchan,nchans to chbegin,chend. -/// Version 17 changed to int supports(string_view) rather than -/// bool supports(const std::string&)). (OIIO 1.6) -/// Version 18 changed to add an m_threads member to ImageInput/Output. - -#define OIIO_PLUGIN_VERSION 18 - -#define OIIO_PLUGIN_NAMESPACE_BEGIN OIIO_NAMESPACE_BEGIN -#define OIIO_PLUGIN_NAMESPACE_END OIIO_NAMESPACE_END - -#ifdef EMBED_PLUGINS -#define OIIO_PLUGIN_EXPORTS_BEGIN -#define OIIO_PLUGIN_EXPORTS_END -#else -#define OIIO_PLUGIN_EXPORTS_BEGIN extern "C" { -#define OIIO_PLUGIN_EXPORTS_END } -#endif - -/// OIIO_BUILD_CPP11 will be 1 if this OIIO was built using C++11 -#cmakedefine01 OIIO_BUILD_CPP11 -/// OIIO_BUILD_CPP14 will be 1 if this OIIO was built using C++14 -#cmakedefine01 OIIO_BUILD_CPP14 -/// OIIO_BUILD_USELIBPLUSPLUS will be 1 if this OIIO was built using libc++ -#cmakedefine01 OIIO_BUILD_LIBCPLUSPLUS - -#endif - diff --git a/3rdparty/oiio16/include/OpenImageIO/optparser.h b/3rdparty/oiio16/include/OpenImageIO/optparser.h deleted file mode 100644 index dcf8ce03..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/optparser.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - Copyright 2011 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -///////////////////////////////////////////////////////////////////////// -/// @file optparser.h -/// -/// @brief Option parser template -///////////////////////////////////////////////////////////////////////// - - -#ifndef OPENIMAGEIO_OPTPARSER_H -#define OPENIMAGEIO_OPTPARSER_H - -#include - -OIIO_NAMESPACE_BEGIN - - -/// Parse a string of the form "name=value" and then call -/// system.attribute (name, value), with appropriate type conversions. -template -inline bool -optparse1 (C &system, const std::string &opt) -{ - std::string::size_type eq_pos = opt.find_first_of ("="); - if (eq_pos == std::string::npos) { - // malformed option - return false; - } - std::string name (opt, 0, eq_pos); - // trim the name - while (name.size() && name[0] == ' ') - name.erase (0); - while (name.size() && name[name.size()-1] == ' ') - name.erase (name.size()-1); - std::string value (opt, eq_pos+1, std::string::npos); - if (name.empty()) - return false; - char v = value.size() ? value[0] : ' '; - if ((v >= '0' && v <= '9') || v == '+' || v == '-') { // numeric - if (strchr (value.c_str(), '.')) // float - return system.attribute (name.c_str(), (float)atof(value.c_str())); - else // int - return system.attribute (name.c_str(), (int)atoi(value.c_str())); - } - // otherwise treat it as a string - - // trim surrounding double quotes - if (value.size() >= 2 && - value[0] == '\"' && value[value.size()-1] == '\"') - value = std::string (value, 1, value.size()-2); - - return system.attribute (name.c_str(), value.c_str()); -} - - - -/// Parse a string with comma-separated name=value directives, calling -/// system.attribute(name,value) for each one, with appropriate type -/// conversions. Examples: -/// optparser(texturesystem, "verbose=1"); -/// optparser(texturesystem, "max_memory_MB=32.0"); -/// optparser(texturesystem, "a=1,b=2,c=3.14,d=\"a string\""); -template -inline bool -optparser (C &system, const std::string &optstring) -{ - bool ok = true; - size_t len = optstring.length(); - size_t pos = 0; - while (pos < len) { - std::string opt; - bool inquote = false; - while (pos < len) { - unsigned char c = optstring[pos]; - if (c == '\"') { - // Hit a double quote -- toggle "inquote" and add the quote - inquote = !inquote; - opt += c; - ++pos; - } else if (c == ',' && !inquote) { - // Hit a comma and not inside a quote -- we have an option - ++pos; // skip the comma - break; // done with option - } else { - // Anything else: add to the option - opt += c; - ++pos; - } - } - // At this point, opt holds an option - ok &= optparse1 (system, opt); - } - return ok; -} - - -OIIO_NAMESPACE_END - -#endif // OPENIMAGEIO_OPTPARSER_H diff --git a/3rdparty/oiio16/include/OpenImageIO/osdep.h b/3rdparty/oiio16/include/OpenImageIO/osdep.h deleted file mode 100644 index 4b233133..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/osdep.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - Copyright 2009 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ -#ifndef OPENIMAGEIO_OSDEP_H -#define OPENIMAGEIO_OSDEP_H - -#ifdef _WIN32 -# define WIN32_LEAN_AND_MEAN -# define VC_EXTRALEAN -# define NOMINMAX -# include -#endif - -#endif // OPENIMAGEIO_OSDEP_H diff --git a/3rdparty/oiio16/include/OpenImageIO/paramlist.h b/3rdparty/oiio16/include/OpenImageIO/paramlist.h deleted file mode 100644 index 98ff2faa..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/paramlist.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -/// \file -/// -/// Define the ParamValue and ParamValueList classes, which are used to -/// store lists of arbitrary name/data pairs for internal storage of -/// parameter lists, attributes, geometric primitive data, etc. - - -#ifndef OPENIMAGEIO_PARAMLIST_H -#define OPENIMAGEIO_PARAMLIST_H - -#if defined(_MSC_VER) -// Ignore warnings about DLL exported classes with member variables that are template classes. -// This happens with the Rep m_vals member variable of ParamValueList below, which is a std::vector. -# pragma warning (disable : 4251) -#endif - -#include - -#include "export.h" -#include "typedesc.h" -#include "ustring.h" - - -OIIO_NAMESPACE_BEGIN - -/// ParamValue holds a parameter and a pointer to its value(s) -/// -/// Nomenclature: if you have an array of 4 colors for each of 15 points... -/// - There are 15 VALUES -/// - Each value has an array of 4 ELEMENTS, each of which is a color -/// - A color has 3 COMPONENTS (R, G, B) -/// -class OIIO_API ParamValue { -public: - /// Interpolation types - /// - enum Interp { - INTERP_CONSTANT = 0, ///< Constant for all pieces/faces - INTERP_PERPIECE = 1, ///< Piecewise constant per piece/face - INTERP_LINEAR = 2, ///< Linearly interpolated across each piece/face - INTERP_VERTEX = 3 ///< Interpolated like vertices - }; - - ParamValue () : m_type(TypeDesc::UNKNOWN), m_nvalues(0), - m_interp(INTERP_CONSTANT), m_copy(false), m_nonlocal(false) - { - m_data.ptr = NULL; - } - ParamValue (const ustring &_name, TypeDesc _type, - int _nvalues, const void *_value, bool _copy=true) { - init_noclear (_name, _type, _nvalues, _value, _copy); - } - ParamValue (const ustring &_name, TypeDesc _type, int _nvalues, - Interp _interp, const void *_value, bool _copy=true) { - init_noclear (_name, _type, _nvalues, _interp, _value, _copy); - } - ParamValue (string_view _name, TypeDesc _type, - int _nvalues, const void *_value, bool _copy=true) { - init_noclear (ustring(_name), _type, _nvalues, _value, _copy); - } - ParamValue (string_view _name, TypeDesc _type, int _nvalues, - Interp _interp, const void *_value, bool _copy=true) { - init_noclear (ustring(_name), _type, _nvalues, _interp, _value, _copy); - } - ParamValue (const ParamValue &p, bool _copy=true) { - init_noclear (p.name(), p.type(), p.nvalues(), p.interp(), p.data(), _copy); - } - ~ParamValue () { clear_value(); } - void init (ustring _name, TypeDesc _type, int _nvalues, - Interp _interp, const void *_value, bool _copy=true) { - clear_value (); - init_noclear (_name, _type, _nvalues, _interp, _value, _copy); - } - void init (ustring _name, TypeDesc _type, - int _nvalues, const void *_value, bool _copy=true) { - init (_name, _type, _nvalues, INTERP_CONSTANT, _value, _copy); - } - void init (string_view _name, TypeDesc _type, - int _nvalues, const void *_value, bool _copy=true) { - init (ustring(_name), _type, _nvalues, _value, _copy); - } - void init (string_view _name, TypeDesc _type, int _nvalues, - Interp _interp, const void *_value, bool _copy=true) { - init (ustring(_name), _type, _nvalues, _interp, _value, _copy); - } - const ParamValue& operator= (const ParamValue &p) { - init (p.name(), p.type(), p.nvalues(), p.interp(), p.data(), p.m_copy); - return *this; - } - - // FIXME -- some time in the future (after more cleanup), we should make - // name() return a string_view, and use uname() for the rare time when - // the caller truly requires the ustring. - const ustring &name () const { return m_name; } - const ustring &uname () const { return m_name; } - TypeDesc type () const { return m_type; } - int nvalues () const { return m_nvalues; } - const void *data () const { return m_nonlocal ? m_data.ptr : &m_data; } - int datasize () const { return m_nvalues * static_cast(m_type.size()); } - Interp interp () const { return (Interp)m_interp; } - void interp (Interp i) { m_interp = (unsigned char )i; } - - friend void swap (ParamValue &a, ParamValue &b) { - std::swap (a.m_name, b.m_name); - std::swap (a.m_type, b.m_type); - std::swap (a.m_nvalues, b.m_nvalues); - std::swap (a.m_interp, b.m_interp); - std::swap (a.m_data.ptr, b.m_data.ptr); - std::swap (a.m_copy, b.m_copy); - std::swap (a.m_nonlocal, b.m_nonlocal); - } - -private: - ustring m_name; ///< data name - TypeDesc m_type; ///< data type, which may itself be an array - int m_nvalues; ///< number of values of the given type - unsigned char m_interp; ///< Interpolation type - bool m_copy, m_nonlocal; - union { - ptrdiff_t localval; - const void *ptr; - } m_data; ///< Our data, either a pointer or small local value - - void init_noclear (ustring _name, TypeDesc _type, - int _nvalues, const void *_value, bool _copy=true); - void init_noclear (ustring _name, TypeDesc _type,int _nvalues, - Interp _interp, const void *_value, - bool _copy=true); - void clear_value(); -}; - - - -/// A list of ParamValue entries, that can be iterated over or searched. -/// -class OIIO_API ParamValueList { - typedef std::vector Rep; -public: - ParamValueList () { } - - typedef Rep::iterator iterator; - typedef Rep::const_iterator const_iterator; - typedef ParamValue value_type; - typedef value_type & reference; - typedef const value_type & const_reference; - typedef value_type * pointer; - typedef const value_type * const_pointer; - - iterator begin () { return m_vals.begin(); } - iterator end () { return m_vals.end(); } - const_iterator begin () const { return m_vals.begin(); } - const_iterator end () const { return m_vals.end(); } - const_iterator cbegin () const { return m_vals.begin(); } - const_iterator cend () const { return m_vals.end(); } - - reference front () { return m_vals.front(); } - reference back () { return m_vals.back(); } - const_reference front () const { return m_vals.front(); } - const_reference back () const { return m_vals.back(); } - - reference operator[] (int i) { return m_vals[i]; } - const_reference operator[] (int i) const { return m_vals[i]; } - reference operator[] (size_t i) { return m_vals[i]; } - const_reference operator[] (size_t i) const { return m_vals[i]; } - - void resize (size_t newsize) { m_vals.resize (newsize); } - size_t size () const { return m_vals.size(); } - - /// Add space for one more ParamValue to the list, and return a - /// reference to its slot. - reference grow () { - resize (size()+1); - return back (); - } - - /// Add a ParamValue to the end of the list. - /// - void push_back (const ParamValue &p) { m_vals.push_back (p); } - - /// Find the first entry with matching name, and if type != UNKNOWN, - /// then also with matching type. The name search is case sensitive if - /// casesensitive == true. - iterator find (string_view name, TypeDesc type = TypeDesc::UNKNOWN, - bool casesensitive = true); - iterator find (ustring name, TypeDesc type = TypeDesc::UNKNOWN, - bool casesensitive = true); - const_iterator find (string_view name, TypeDesc type = TypeDesc::UNKNOWN, - bool casesensitive = true) const; - const_iterator find (ustring name, TypeDesc type = TypeDesc::UNKNOWN, - bool casesensitive = true) const; - - /// Removes from the ParamValueList container a single element. - /// - iterator erase (iterator position) { return m_vals.erase (position); } - - /// Removes from the ParamValueList container a range of elements ([first,last)). - /// - iterator erase (iterator first, iterator last) { return m_vals.erase (first, last); } - - /// Remove all the values in the list. - /// - void clear () { m_vals.clear(); } - - /// Even more radical than clear, free ALL memory associated with the - /// list itself. - void free () { Rep tmp; std::swap (m_vals, tmp); } - -private: - Rep m_vals; -}; - - -OIIO_NAMESPACE_END - -#endif /* !defined(OPENIMAGEIO_PARAMLIST_H) */ diff --git a/3rdparty/oiio16/include/OpenImageIO/platform.h b/3rdparty/oiio16/include/OpenImageIO/platform.h deleted file mode 100644 index 06e7d374..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/platform.h +++ /dev/null @@ -1,360 +0,0 @@ -/* - Copyright 2014 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -///////////////////////////////////////////////////////////////////////// -/// @file platform.h -/// -/// @brief Platform-related macros. -///////////////////////////////////////////////////////////////////////// - - -#pragma once - -// Make sure all platforms have the explicit sized integer types -#if defined(_MSC_VER) && _MSC_VER < 1600 - typedef __int8 int8_t; - typedef __int16 int16_t; - typedef __int32 int32_t; - typedef __int64 int64_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; -# ifndef _UINT64_T - typedef unsigned __int32 uint32_t; - typedef unsigned __int64 uint64_t; -# define _UINT32_T -# define _UINT64_T -# endif -#else -# ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS /* needed for some defs in stdint.h */ -# endif -# include -#endif - -#if defined(__FreeBSD__) -#include -#endif - -#ifdef __MINGW32__ -#include // for alloca -#endif - -#if defined(_MSC_VER) || defined(_WIN32) -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# ifndef VC_EXTRALEAN -# define VC_EXTRALEAN -# endif -# ifndef NOMINMAX -# define NOMINMAX -# endif -# include -#endif - -# ifdef _MSC_VER -#include -#endif - -#include "oiioversion.h" - -// Detect which C++ standard we're using, and handy macros. -// -// OIIO_CPLUSPLUS_VERSION : which C++ standard is compiling (3, 11, 14, ...) -// OIIO_USING_CPP11 : (deprecated) defined and 1 if using C++11 or newer. -// OIIO_CONSTEXPR : constexpr for C++ >= 11, otherwise nothing -// OIIO_CONSTEXPR_OR_CONST : constexpr for C++ >= 11, otherwise const -// OIIO_CONSTEXPR14 : constexpr for C++ >= 14, otherwise nothing (this is -// useful for things that can only be constexpr for 14) -// OIIO_NOEXCEPT : noexcept for C++ >= 11, otherwise nothing -// -// Note: oiioversion.h defines OIIO_BUILD_CPP11 or OIIO_BUILD_CPP14 to be 1 -// if OIIO itself was built using C++11 or C++14, respectively. In contrast, -// OIIO_CPLUSPLUS_VERSION defined below will be set to the right number for -// the C++ standard being compiled RIGHT NOW. These two things may be the -// same when compiling OIIO, but they may not be the same if another -// packages is compiling against OIIO and using these headers (OIIO may be -// C++11 but the client package may be older, or vice versa -- use these two -// symbols to differentiate these cases, when important). -#if (__cplusplus >= 201402L) -# define OIIO_USING_CPP11 1 -# define OIIO_CPLUSPLUS_VERSION 14 -# define OIIO_CONSTEXPR constexpr -# define OIIO_CONSTEXPR_OR_CONST constexpr -# define OIIO_CONSTEXPR14 constexpr -# define OIIO_NOEXCEPT noexcept -#elif (__cplusplus >= 201103L) -# define OIIO_USING_CPP11 1 /* deprecated */ -# define OIIO_CPLUSPLUS_VERSION 11 -# define OIIO_CONSTEXPR constexpr -# define OIIO_CONSTEXPR_OR_CONST constexpr -# define OIIO_CONSTEXPR14 /* not constexpr before C++14 */ -# define OIIO_NOEXCEPT noexcept -#else -# define OIIO_CPLUSPLUS_VERSION 3 /* presume C++03 */ -# define OIIO_CONSTEXPR /* not constexpr before C++11 */ -# define OIIO_CONSTEXPR_OR_CONST const /* not constexpr before C++11 */ -# define OIIO_CONSTEXPR14 /* not constexpr before C++14 */ -# define OIIO_NOEXCEPT /* no noexcept before C++11 */ -#endif - - - -// Fallback definitions for feature testing. Some newer compilers define -// these for real, and it may be standard for C++17. -#ifndef __has_feature -# define __has_feature(x) 0 -#endif -#ifndef __has_extension -# define __has_extension(x) __has_feature(x) -#endif -#ifndef __has_attribute -# define __has_attribute(x) 0 -#endif -#ifndef __has_builtin -# define __has_builtin(x) 0 -#endif -#ifndef __has_include -# define __has_include(x) 0 -#endif - - - -// Define OIIO_GNUC_VERSION to hold an encoded gcc version (e.g. 40802 for -// 4.8.2), or 0 if not a GCC release. -#ifdef __GNUC__ -# define OIIO_GNUC_VERSION (10000*__GNUC__ + 100*__GNUC_MINOR__ + __GNUC_PATCHLEVEL__) -#else -# define OIIO_GNUC_VERSION 0 -#endif - -// Tests for MSVS versions, always 0 if not MSVS at all. -#define OIIO_MSVS_AT_LEAST_2013 (defined(_MSC_VER) && _MSC_VER >= 1800) -#define OIIO_MSVS_BEFORE_2013 (defined(_MSC_VER) && _MSC_VER < 1800) -#define OIIO_MSVS_AT_LEAST_2015 (defined(_MSC_VER) && _MSC_VER >= 1900) -#define OIIO_MSVS_BEFORE_2015 (defined(_MSC_VER) && _MSC_VER < 1900) - - - -/// allocates memory, equivalent of C99 type var_name[size] -#define OIIO_ALLOCA(type, size) ((type*)alloca((size) * sizeof (type))) - -/// Deprecated (for namespace pollution reasons) -#define ALLOCA(type, size) ((type*)alloca((size) * sizeof (type))) - - -// Define a macro that can be used for memory alignment. -// I think that in a future world of C++1x compatibility, all these can -// be replaced with [[ align(size) ]]. -#if defined (__GNUC__) || __has_attribute(aligned) -# define OIIO_ALIGN(size) __attribute__((aligned(size))) -#elif defined (_MSC_VER) -# define OIIO_ALIGN(size) __declspec(align(size)) -#elif defined (__INTEL_COMPILER) -# define OIIO_ALIGN(size) __declspec(align((size))) -#else -# error "Don't know how to define OIIO_ALIGN" -#endif - -// Cache line size is 64 on all modern x86 CPUs. If this changes or we -// anticipate ports to other architectures, we'll need to change this. -#define OIIO_CACHE_LINE_SIZE 64 - -// Align the next declaration to be on its own cache line -#define OIIO_CACHE_ALIGN OIIO_ALIGN(OIIO_CACHE_LINE_SIZE) - - - -// gcc defines a special intrinsic to use in conditionals that can speed -// up extremely performance-critical spots if the conditional usually -// (or rarely) is true. You use it by replacing -// if (x) ... -// with -// if (OIIO_LIKELY(x)) ... // if you think x will usually be true -// or -// if (OIIO_UNLIKELY(x)) ... // if you think x will rarely be true -// Caveat: Programmers are notoriously bad at guessing this, so it -// should be used only with thorough benchmarking. -#if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER) -#define OIIO_LIKELY(x) (__builtin_expect(bool(x), true)) -#define OIIO_UNLIKELY(x) (__builtin_expect(bool(x), false)) -#else -#define OIIO_LIKELY(x) (x) -#define OIIO_UNLIKELY(x) (x) -#endif - - -// OIIO_FORCELINE is a function attribute that attempts to make the function -// always inline. On many compilers regular 'inline' is only advisory. Put -// this attribute before the function return type, just like you would use -// 'inline'. -#if defined(__GNUC__) || defined(__clang__) || __has_attribute(always_inline) -# define OIIO_FORCEINLINE inline __attribute__((always_inline)) -#elif defined(_MSC_VER) || defined(__INTEL_COMPILER) -# define OIIO_FORCEINLINE __forceinline -#else -# define OIIO_FORCEINLINE inline -#endif - -// OIIO_PURE_FUNC is a function attribute that assures the compiler that the -// function does not write to any non-local memory other than its return -// value and has no side effects. This can ebable additional compiler -// optimizations by knowing that calling the function cannot possibly alter -// any other memory. This declaration goes after the function declaration: -// int blah (int arg) OIIO_PURE_FUNC; -#if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER) || __has_attribute(pure) -# define OIIO_PURE_FUNC __attribute__((pure)) -#elif defined(_MSC_VER) -# define OIIO_PURE_FUNC /* seems not supported by MSVS */ -#else -# define OIIO_PURE_FUNC -#endif - -// OIIO_CONST_FUNC is a function attribute that assures the compiler that -// the function does not examine (read) any values except for its arguments, -// does not write any non-local memory other than its return value, and has -// no side effects. This is even more strict than 'pure', and allows even -// more optimizations (such as eliminating multiple calls to the function -// that have the exact same argument values). -#if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER) || __has_attribute(const) -# define OIIO_CONST_FUNC __attribute__((const)) -#elif defined(_MSC_VER) -# define OIIO_CONST_FUNC /* seems not supported by MSVS */ -#else -# define OIIO_CONST_FUNC -#endif - -// OIIO_NOTHROW is a function attribute that assures the compiler that -// neither the function nor any other function it calls will throw an -// exception. This declaration goes after the -// function declaration: int blah (int arg) OIIO_NOTHROW; -#if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER) || __has_attribute(nothrow) -# define OIIO_NOTHROW __attribute__((nothrow)) -#elif defined(_MSC_VER) -# define OIIO_NOTHROW __declspec(nothrow) -#else -# define OIIO_NOTHROW -#endif - -// OIIO_UNUSED_OK is a function or variable attribute that assures tells the -// compiler that it's fine for the item to appear to be unused. -#if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER) || __has_attribute(unused) -# define OIIO_UNUSED_OK __attribute__((unused)) -#else -# define OIIO_UNUSED_OK -#endif - -// OIIO_RESTRICT is a parameter attribute that indicates a promise that the -// parameter definitely will not alias any other parameters in such a way -// that creates a data dependency. Use with caution! -#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) || defined(__INTEL_COMPILER) -# define OIIO_RESTRICT __restrict -#else -# define OIIO_RESTRICT -#endif - - - -// Try to deduce endianness -#if (defined(_WIN32) || defined(__i386__) || defined(__x86_64__)) -# ifndef __LITTLE_ENDIAN__ -# define __LITTLE_ENDIAN__ 1 -# undef __BIG_ENDIAN__ -# endif -#endif - - -OIIO_NAMESPACE_BEGIN - -/// Return true if the architecture we are running on is little endian -OIIO_FORCEINLINE bool littleendian (void) -{ -#if defined(__BIG_ENDIAN__) - return false; -#elif defined(__LITTLE_ENDIAN__) - return true; -#else - // Otherwise, do something quick to compute it - int i = 1; - return *((char *) &i); -#endif -} - - -/// Return true if the architecture we are running on is big endian -OIIO_FORCEINLINE bool bigendian (void) -{ - return ! littleendian(); -} - - - -/// Retrieve cpuid flags into 'info'. -inline void cpuid (int info[4], int infoType, int extra) -{ - // Implementation cribbed from Halide (http://halide-lang.org), which - // cribbed it from ISPC (https://github.com/ispc/ispc). -#if (defined(_WIN32) || defined(__i386__) || defined(__x86_64__)) -# ifdef _MSC_VER - __cpuidex(info, infoType, extra); -# elif defined(__x86_64__) - __asm__ __volatile__ ( - "cpuid \n\t" - : "=a" (info[0]), "=b" (info[1]), "=c" (info[2]), "=d" (info[3]) - : "0" (infoType), "2" (extra)); -# else - __asm__ __volatile__ ( - "mov{l}\t{%%}ebx, %1 \n\t" - "cpuid \n\t" - "xchg{l}\t{%%}ebx, %1 \n\t" - : "=a" (info[0]), "=r" (info[1]), "=c" (info[2]), "=d" (info[3]) - : "0" (infoType), "2" (extra)); -# endif -#else - info[0] = 0; info[1] = 0; info[2] = 0; info[3] = 0; -#endif -} - - -inline bool cpu_has_sse2 () {int i[4]; cpuid(i,1,0); return i[3] & (1<<26); } -inline bool cpu_has_sse3 () {int i[4]; cpuid(i,1,0); return i[2] & (1<<0); } -inline bool cpu_has_ssse3 () {int i[4]; cpuid(i,1,0); return i[2] & (1<<9); } -inline bool cpu_has_fma () {int i[4]; cpuid(i,1,0); return i[2] & (1<<12); } -inline bool cpu_has_sse41 () {int i[4]; cpuid(i,1,0); return i[2] & (1<<19); } -inline bool cpu_has_sse42 () {int i[4]; cpuid(i,1,0); return i[2] & (1<<20); } -inline bool cpu_has_popcnt() {int i[4]; cpuid(i,1,0); return i[2] & (1<<23); } -inline bool cpu_has_avx () {int i[4]; cpuid(i,1,0); return i[2] & (1<<28); } -inline bool cpu_has_f16c () {int i[4]; cpuid(i,1,0); return i[2] & (1<<29); } -inline bool cpu_has_rdrand() {int i[4]; cpuid(i,1,0); return i[2] & (1<<30); } - - -OIIO_NAMESPACE_END - diff --git a/3rdparty/oiio16/include/OpenImageIO/plugin.h b/3rdparty/oiio16/include/OpenImageIO/plugin.h deleted file mode 100644 index 63c21327..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/plugin.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -///////////////////////////////////////////////////////////////////////// -/// \file -/// -/// Helper routines for managing runtime-loadable "plugins", implemented -/// variously as DSO's (traditional Unix/Linux), dynamic libraries (Mac -/// OS X), DLL's (Windows). -///////////////////////////////////////////////////////////////////////// - - -#ifndef OPENIMAGEIO_PLUGIN_H -#define OPENIMAGEIO_PLUGIN_H - -#include - -#include "export.h" -#include "oiioversion.h" - - -OIIO_NAMESPACE_BEGIN - -namespace Plugin { - -typedef void * Handle; - -/// Return the platform-dependent suffix for plug-ins ("dll" on -/// Windows, "so" on Linux, "dylib" on Mac OS X. -OIIO_API const char *plugin_extension (void); - -/// Open the named plugin, return its handle. If it could not be -/// opened, return 0 and the next call to geterror() will contain -/// an explanatory message. If the 'global' parameter is true, all -/// symbols from the plugin will be available to the app (on Unix-like -/// platforms; this has no effect on Windows). -OIIO_API Handle open (const char *plugin_filename, bool global=true); - -inline Handle -open (const std::string &plugin_filename, bool global=true) -{ - return open (plugin_filename.c_str(), global); -} - -/// Close the open plugin with the given handle and return true upon -/// success. If some error occurred, return false and the next call to -/// geterror() will contain an explanatory message. -OIIO_API bool close (Handle plugin_handle); - -/// Get the address of the named symbol from the open plugin handle. If -/// some error occurred, return NULL and the next call to -/// geterror() will contain an explanatory message. -OIIO_API void * getsym (Handle plugin_handle, const char *symbol_name); - -inline void * -getsym (Handle plugin_handle, const std::string &symbol_name) -{ - return getsym (plugin_handle, symbol_name.c_str()); -} - -/// Return any error messages associated with the last call to any of -/// open, close, or getsym. Note that in a multithreaded environment, -/// it's up to the caller to properly mutex to ensure that no other -/// thread has called open, close, or getsym (all of which clear or -/// overwrite the error message) between the error-generating call and -/// geterror. -OIIO_API std::string geterror (void); - - - -} // namespace Plugin - -OIIO_NAMESPACE_END - -#endif // OPENIMAGEIO_PLUGIN_H diff --git a/3rdparty/oiio16/include/OpenImageIO/pugiconfig.hpp b/3rdparty/oiio16/include/OpenImageIO/pugiconfig.hpp deleted file mode 100644 index f1aa900e..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/pugiconfig.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/** - * pugixml parser - version 1.2 - * -------------------------------------------------------- - * Copyright (C) 2006-2012, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) - * Report bugs and download new versions at http://pugixml.org/ - * - * This library is distributed under the MIT License. See notice at the end - * of this file. - * - * This work is based on the pugxml parser, which is: - * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) - */ - -#ifndef HEADER_PUGICONFIG_HPP -#define HEADER_PUGICONFIG_HPP - -// Uncomment this to enable wchar_t mode -// #define PUGIXML_WCHAR_MODE - -// Uncomment this to disable XPath -// #define PUGIXML_NO_XPATH - -// Uncomment this to disable STL -// #define PUGIXML_NO_STL - -// Uncomment this to disable exceptions -// #define PUGIXML_NO_EXCEPTIONS - -// Set this to control attributes for public classes/functions, i.e.: -// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL -// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL -// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall -// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead - -// OIIO: use already defined OIIO_API -#include "export.h" -#define PUGIXML_API OIIO_API - -// Uncomment this to switch to header-only version -#define PUGIXML_HEADER_ONLY -#include "pugixml.cpp" - -// Tune these constants to adjust memory-related behavior -// #define PUGIXML_MEMORY_PAGE_SIZE 32768 -// #define PUGIXML_MEMORY_OUTPUT_STACK 10240 -// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096 - -#endif - -/** - * Copyright (c) 2006-2012 Arseny Kapoulkine - * - * 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. - */ diff --git a/3rdparty/oiio16/include/OpenImageIO/pugixml.cpp b/3rdparty/oiio16/include/OpenImageIO/pugixml.cpp deleted file mode 100644 index 48a411d8..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/pugixml.cpp +++ /dev/null @@ -1,10256 +0,0 @@ -/** - * pugixml parser - version 1.2 - * -------------------------------------------------------- - * Copyright (C) 2006-2012, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) - * Report bugs and download new versions at http://pugixml.org/ - * - * This library is distributed under the MIT License. See notice at the end - * of this file. - * - * This work is based on the pugxml parser, which is: - * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) - */ - -#ifndef SOURCE_PUGIXML_CPP -#define SOURCE_PUGIXML_CPP - -#include "pugixml.hpp" - -#include -#include -#include -#include -#include - -#ifndef PUGIXML_NO_XPATH -# include -# include -# ifdef PUGIXML_NO_EXCEPTIONS -# include -# endif -#endif - -#ifndef PUGIXML_NO_STL -# include -# include -# include -#endif - -// For placement new -#include - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable: 4127) // conditional expression is constant -# pragma warning(disable: 4324) // structure was padded due to __declspec(align()) -# pragma warning(disable: 4611) // interaction between '_setjmp' and C++ object destruction is non-portable -# pragma warning(disable: 4702) // unreachable code -# pragma warning(disable: 4996) // this function or variable may be unsafe -# pragma warning(disable: 4793) // function compiled as native: presence of '_setjmp' makes a function unmanaged -#endif - -#ifdef __INTEL_COMPILER -# pragma warning(disable: 177) // function was declared but never referenced -# pragma warning(disable: 279) // controlling expression is constant -# pragma warning(disable: 1478 1786) // function was declared "deprecated" -# pragma warning(disable: 1684) // conversion from pointer to same-sized integral type -#endif - -#if defined(__BORLANDC__) && defined(PUGIXML_HEADER_ONLY) -# pragma warn -8080 // symbol is declared but never used; disabling this inside push/pop bracket does not make the warning go away -#endif - -#ifdef __BORLANDC__ -# pragma option push -# pragma warn -8008 // condition is always false -# pragma warn -8066 // unreachable code -#endif - -#ifdef __SNC__ -// Using diag_push/diag_pop does not disable the warnings inside templates due to a compiler bug -# pragma diag_suppress=178 // function was declared but never referenced -# pragma diag_suppress=237 // controlling expression is constant -#endif - -// Inlining controls -#if defined(_MSC_VER) && _MSC_VER >= 1300 -# define PUGI__NO_INLINE __declspec(noinline) -#elif defined(__GNUC__) -# define PUGI__NO_INLINE __attribute__((noinline)) -#else -# define PUGI__NO_INLINE -#endif - -// Simple static assertion -#define PUGI__STATIC_ASSERT(cond) { static const char condition_failed[(cond) ? 1 : -1] = {0}; (void)condition_failed[0]; } - -// Digital Mars C++ bug workaround for passing char loaded from memory via stack -#ifdef __DMC__ -# define PUGI__DMC_VOLATILE volatile -#else -# define PUGI__DMC_VOLATILE -#endif - -// Borland C++ bug workaround for not defining ::memcpy depending on header include order (can't always use std::memcpy because some compilers don't have it at all) -#if defined(__BORLANDC__) && !defined(__MEM_H_USING_LIST) -using std::memcpy; -using std::memmove; -#endif - -// In some environments MSVC is a compiler but the CRT lacks certain MSVC-specific features -#if defined(_MSC_VER) && !defined(__S3E__) -# define PUGI__MSVC_CRT_VERSION _MSC_VER -#endif - -#ifdef PUGIXML_HEADER_ONLY -# define PUGI__NS_BEGIN OIIO_NAMESPACE_BEGIN NAMESPACE_BEGIN(pugi) NAMESPACE_BEGIN(impl) -# define PUGI__NS_END NAMESPACE_END(impl) NAMESPACE_END(pugi) OIIO_NAMESPACE_END -# define PUGI__FN inline -# define PUGI__FN_NO_INLINE inline -#else -# if defined(_MSC_VER) && _MSC_VER < 1300 // MSVC6 seems to have an amusing bug with anonymous namespaces inside namespaces -# define PUGI__NS_BEGIN OIIO_NAMESPACE_BEGIN NAMESPACE_BEGIN(pugi) NAMESPACE_BEGIN(impl) -# define PUGI__NS_END NAMESPACE_END(impl) NAMESPACE_END(pugi) OIIO_NAMESPACE_END -# else -# define PUGI__NS_BEGIN OIIO_NAMESPACE_BEGIN NAMESPACE_BEGIN(pugi) NAMESPACE_BEGIN(impl) namespace { -# define PUGI__NS_END NAMESPACE_END(impl) NAMESPACE_END(pugi) } OIIO_NAMESPACE_END -# endif -# define PUGI__FN -# define PUGI__FN_NO_INLINE PUGI__NO_INLINE -#endif - -// uintptr_t -#if !defined(_MSC_VER) || _MSC_VER >= 1600 -# include -#else -# ifndef _UINTPTR_T_DEFINED -// No native uintptr_t in MSVC6 and in some WinCE versions -typedef size_t uintptr_t; -#define _UINTPTR_T_DEFINED -# endif -PUGI__NS_BEGIN - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; -PUGI__NS_END -#endif - -// Memory allocation -PUGI__NS_BEGIN - PUGI__FN void* default_allocate(size_t size) - { - return malloc(size); - } - - PUGI__FN void default_deallocate(void* ptr) - { - free(ptr); - } - - template - struct xml_memory_management_function_storage - { - static allocation_function allocate; - static deallocation_function deallocate; - }; - - template allocation_function xml_memory_management_function_storage::allocate = default_allocate; - template deallocation_function xml_memory_management_function_storage::deallocate = default_deallocate; - - typedef xml_memory_management_function_storage xml_memory; -PUGI__NS_END - -// String utilities -PUGI__NS_BEGIN - // Get string length - PUGI__FN size_t strlength(const char_t* s) - { - assert(s); - - #ifdef PUGIXML_WCHAR_MODE - return wcslen(s); - #else - return strlen(s); - #endif - } - - // Compare two strings - PUGI__FN bool strequal(const char_t* src, const char_t* dst) - { - assert(src && dst); - - #ifdef PUGIXML_WCHAR_MODE - return wcscmp(src, dst) == 0; - #else - return strcmp(src, dst) == 0; - #endif - } - - // Compare lhs with [rhs_begin, rhs_end) - PUGI__FN bool strequalrange(const char_t* lhs, const char_t* rhs, size_t count) - { - for (size_t i = 0; i < count; ++i) - if (lhs[i] != rhs[i]) - return false; - - return lhs[count] == 0; - } - -#ifdef PUGIXML_WCHAR_MODE - // Convert string to wide string, assuming all symbols are ASCII - PUGI__FN void widen_ascii(wchar_t* dest, const char* source) - { - for (const char* i = source; *i; ++i) *dest++ = *i; - *dest = 0; - } -#endif -PUGI__NS_END - -#if !defined(PUGIXML_NO_STL) || !defined(PUGIXML_NO_XPATH) -// auto_ptr-like buffer holder for exception recovery -PUGI__NS_BEGIN - struct buffer_holder - { - void* data; - void (*deleter)(void*); - - buffer_holder(void* data_, void (*deleter_)(void*)): data(data_), deleter(deleter_) - { - } - - ~buffer_holder() - { - if (data) deleter(data); - } - - void* release() - { - void* result = data; - data = 0; - return result; - } - }; -PUGI__NS_END -#endif - -PUGI__NS_BEGIN - static const size_t xml_memory_page_size = - #ifdef PUGIXML_MEMORY_PAGE_SIZE - PUGIXML_MEMORY_PAGE_SIZE - #else - 32768 - #endif - ; - - static const uintptr_t xml_memory_page_alignment = 32; - static const uintptr_t xml_memory_page_pointer_mask = ~(xml_memory_page_alignment - 1); - static const uintptr_t xml_memory_page_name_allocated_mask = 16; - static const uintptr_t xml_memory_page_value_allocated_mask = 8; - static const uintptr_t xml_memory_page_type_mask = 7; - - struct xml_allocator; - - struct xml_memory_page - { - static xml_memory_page* construct(void* memory) - { - if (!memory) return 0; //$ redundant, left for performance - - xml_memory_page* result = static_cast(memory); - - result->allocator = 0; - result->memory = 0; - result->prev = 0; - result->next = 0; - result->busy_size = 0; - result->freed_size = 0; - - return result; - } - - xml_allocator* allocator; - - void* memory; - - xml_memory_page* prev; - xml_memory_page* next; - - size_t busy_size; - size_t freed_size; - - char data[1]; - }; - - struct xml_memory_string_header - { - uint16_t page_offset; // offset from page->data - uint16_t full_size; // 0 if string occupies whole page - }; - - struct xml_allocator - { - xml_allocator(xml_memory_page* root): _root(root), _busy_size(root->busy_size) - { - } - - xml_memory_page* allocate_page(size_t data_size) - { - size_t size = offsetof(xml_memory_page, data) + data_size; - - // allocate block with some alignment, leaving memory for worst-case padding - void* memory = xml_memory::allocate(size + xml_memory_page_alignment); - if (!memory) return 0; - - // align upwards to page boundary - void* page_memory = reinterpret_cast((reinterpret_cast(memory) + (xml_memory_page_alignment - 1)) & ~(xml_memory_page_alignment - 1)); - - // prepare page structure - xml_memory_page* page = xml_memory_page::construct(page_memory); - - page->memory = memory; - page->allocator = _root->allocator; - - return page; - } - - static void deallocate_page(xml_memory_page* page) - { - xml_memory::deallocate(page->memory); - } - - void* allocate_memory_oob(size_t size, xml_memory_page*& out_page); - - void* allocate_memory(size_t size, xml_memory_page*& out_page) - { - if (_busy_size + size > xml_memory_page_size) return allocate_memory_oob(size, out_page); - - void* buf = _root->data + _busy_size; - - _busy_size += size; - - out_page = _root; - - return buf; - } - - void deallocate_memory(void* ptr, size_t size, xml_memory_page* page) - { - if (page == _root) page->busy_size = _busy_size; - - assert(ptr >= page->data && ptr < page->data + page->busy_size); - (void)!ptr; - - page->freed_size += size; - assert(page->freed_size <= page->busy_size); - - if (page->freed_size == page->busy_size) - { - if (page->next == 0) - { - assert(_root == page); - - // top page freed, just reset sizes - page->busy_size = page->freed_size = 0; - _busy_size = 0; - } - else - { - assert(_root != page); - assert(page->prev); - - // remove from the list - page->prev->next = page->next; - page->next->prev = page->prev; - - // deallocate - deallocate_page(page); - } - } - } - - char_t* allocate_string(size_t length) - { - // allocate memory for string and header block - size_t size = sizeof(xml_memory_string_header) + length * sizeof(char_t); - - // round size up to pointer alignment boundary - size_t full_size = (size + (sizeof(void*) - 1)) & ~(sizeof(void*) - 1); - - xml_memory_page* page; - xml_memory_string_header* header = static_cast(allocate_memory(full_size, page)); - - if (!header) return 0; - - // setup header - ptrdiff_t page_offset = reinterpret_cast(header) - page->data; - - assert(page_offset >= 0 && page_offset < (1 << 16)); - header->page_offset = static_cast(page_offset); - - // full_size == 0 for large strings that occupy the whole page - assert(full_size < (1 << 16) || (page->busy_size == full_size && page_offset == 0)); - header->full_size = static_cast(full_size < (1 << 16) ? full_size : 0); - - // round-trip through void* to avoid 'cast increases required alignment of target type' warning - // header is guaranteed a pointer-sized alignment, which should be enough for char_t - return static_cast(static_cast(header + 1)); - } - - void deallocate_string(char_t* string) - { - // this function casts pointers through void* to avoid 'cast increases required alignment of target type' warnings - // we're guaranteed the proper (pointer-sized) alignment on the input string if it was allocated via allocate_string - - // get header - xml_memory_string_header* header = static_cast(static_cast(string)) - 1; - - // deallocate - size_t page_offset = offsetof(xml_memory_page, data) + header->page_offset; - xml_memory_page* page = reinterpret_cast(static_cast(reinterpret_cast(header) - page_offset)); - - // if full_size == 0 then this string occupies the whole page - size_t full_size = header->full_size == 0 ? page->busy_size : header->full_size; - - deallocate_memory(header, full_size, page); - } - - xml_memory_page* _root; - size_t _busy_size; - }; - - PUGI__FN_NO_INLINE void* xml_allocator::allocate_memory_oob(size_t size, xml_memory_page*& out_page) - { - const size_t large_allocation_threshold = xml_memory_page_size / 4; - - xml_memory_page* page = allocate_page(size <= large_allocation_threshold ? xml_memory_page_size : size); - out_page = page; - - if (!page) return 0; - - if (size <= large_allocation_threshold) - { - _root->busy_size = _busy_size; - - // insert page at the end of linked list - page->prev = _root; - _root->next = page; - _root = page; - - _busy_size = size; - } - else - { - // insert page before the end of linked list, so that it is deleted as soon as possible - // the last page is not deleted even if it's empty (see deallocate_memory) - assert(_root->prev); - - page->prev = _root->prev; - page->next = _root; - - _root->prev->next = page; - _root->prev = page; - } - - // allocate inside page - page->busy_size = size; - - return page->data; - } -PUGI__NS_END - -OIIO_NAMESPACE_BEGIN -namespace pugi -{ - /// A 'name=value' XML attribute structure. - struct xml_attribute_struct - { - /// Default ctor - xml_attribute_struct(impl::xml_memory_page* page): header(reinterpret_cast(page)), name(0), value(0), prev_attribute_c(0), next_attribute(0) - { - } - - uintptr_t header; - - char_t* name; ///< Pointer to attribute name. - char_t* value; ///< Pointer to attribute value. - - xml_attribute_struct* prev_attribute_c; ///< Previous attribute (cyclic list) - xml_attribute_struct* next_attribute; ///< Next attribute - }; - - /// An XML document tree node. - struct xml_node_struct - { - /// Default ctor - /// \param type - node type - xml_node_struct(impl::xml_memory_page* page, xml_node_type type): header(reinterpret_cast(page) | (type - 1)), parent(0), name(0), value(0), first_child(0), prev_sibling_c(0), next_sibling(0), first_attribute(0) - { - } - - uintptr_t header; - - xml_node_struct* parent; ///< Pointer to parent - - char_t* name; ///< Pointer to element name. - char_t* value; ///< Pointer to any associated string data. - - xml_node_struct* first_child; ///< First child - - xml_node_struct* prev_sibling_c; ///< Left brother (cyclic list) - xml_node_struct* next_sibling; ///< Right brother - - xml_attribute_struct* first_attribute; ///< First attribute - }; -} -OIIO_NAMESPACE_END - -PUGI__NS_BEGIN - struct xml_document_struct: public xml_node_struct, public xml_allocator - { - xml_document_struct(xml_memory_page* page): xml_node_struct(page, node_document), xml_allocator(page), buffer(0) - { - } - - const char_t* buffer; - }; - - inline xml_allocator& get_allocator(const xml_node_struct* node) - { - assert(node); - - return *reinterpret_cast(node->header & xml_memory_page_pointer_mask)->allocator; - } -PUGI__NS_END - -// Low-level DOM operations -PUGI__NS_BEGIN - inline xml_attribute_struct* allocate_attribute(xml_allocator& alloc) - { - xml_memory_page* page; - void* memory = alloc.allocate_memory(sizeof(xml_attribute_struct), page); - - return new (memory) xml_attribute_struct(page); - } - - inline xml_node_struct* allocate_node(xml_allocator& alloc, xml_node_type type) - { - xml_memory_page* page; - void* memory = alloc.allocate_memory(sizeof(xml_node_struct), page); - - return new (memory) xml_node_struct(page, type); - } - - inline void destroy_attribute(xml_attribute_struct* a, xml_allocator& alloc) - { - uintptr_t header = a->header; - - if (header & impl::xml_memory_page_name_allocated_mask) alloc.deallocate_string(a->name); - if (header & impl::xml_memory_page_value_allocated_mask) alloc.deallocate_string(a->value); - - alloc.deallocate_memory(a, sizeof(xml_attribute_struct), reinterpret_cast(header & xml_memory_page_pointer_mask)); - } - - inline void destroy_node(xml_node_struct* n, xml_allocator& alloc) - { - uintptr_t header = n->header; - - if (header & impl::xml_memory_page_name_allocated_mask) alloc.deallocate_string(n->name); - if (header & impl::xml_memory_page_value_allocated_mask) alloc.deallocate_string(n->value); - - for (xml_attribute_struct* attr = n->first_attribute; attr; ) - { - xml_attribute_struct* next = attr->next_attribute; - - destroy_attribute(attr, alloc); - - attr = next; - } - - for (xml_node_struct* child = n->first_child; child; ) - { - xml_node_struct* next = child->next_sibling; - - destroy_node(child, alloc); - - child = next; - } - - alloc.deallocate_memory(n, sizeof(xml_node_struct), reinterpret_cast(header & xml_memory_page_pointer_mask)); - } - - PUGI__FN_NO_INLINE xml_node_struct* append_node(xml_node_struct* node, xml_allocator& alloc, xml_node_type type = node_element) - { - xml_node_struct* child = allocate_node(alloc, type); - if (!child) return 0; - - child->parent = node; - - xml_node_struct* first_child = node->first_child; - - if (first_child) - { - xml_node_struct* last_child = first_child->prev_sibling_c; - - last_child->next_sibling = child; - child->prev_sibling_c = last_child; - first_child->prev_sibling_c = child; - } - else - { - node->first_child = child; - child->prev_sibling_c = child; - } - - return child; - } - - PUGI__FN_NO_INLINE xml_attribute_struct* append_attribute_ll(xml_node_struct* node, xml_allocator& alloc) - { - xml_attribute_struct* a = allocate_attribute(alloc); - if (!a) return 0; - - xml_attribute_struct* first_attribute = node->first_attribute; - - if (first_attribute) - { - xml_attribute_struct* last_attribute = first_attribute->prev_attribute_c; - - last_attribute->next_attribute = a; - a->prev_attribute_c = last_attribute; - first_attribute->prev_attribute_c = a; - } - else - { - node->first_attribute = a; - a->prev_attribute_c = a; - } - - return a; - } -PUGI__NS_END - -// Helper classes for code generation -PUGI__NS_BEGIN - struct opt_false - { - enum { value = 0 }; - }; - - struct opt_true - { - enum { value = 1 }; - }; -PUGI__NS_END - -// Unicode utilities -PUGI__NS_BEGIN - inline uint16_t endian_swap(uint16_t value) - { - return static_cast(((value & 0xff) << 8) | (value >> 8)); - } - - inline uint32_t endian_swap(uint32_t value) - { - return ((value & 0xff) << 24) | ((value & 0xff00) << 8) | ((value & 0xff0000) >> 8) | (value >> 24); - } - - struct utf8_counter - { - typedef size_t value_type; - - static value_type low(value_type result, uint32_t ch) - { - // U+0000..U+007F - if (ch < 0x80) return result + 1; - // U+0080..U+07FF - else if (ch < 0x800) return result + 2; - // U+0800..U+FFFF - else return result + 3; - } - - static value_type high(value_type result, uint32_t) - { - // U+10000..U+10FFFF - return result + 4; - } - }; - - struct utf8_writer - { - typedef uint8_t* value_type; - - static value_type low(value_type result, uint32_t ch) - { - // U+0000..U+007F - if (ch < 0x80) - { - *result = static_cast(ch); - return result + 1; - } - // U+0080..U+07FF - else if (ch < 0x800) - { - result[0] = static_cast(0xC0 | (ch >> 6)); - result[1] = static_cast(0x80 | (ch & 0x3F)); - return result + 2; - } - // U+0800..U+FFFF - else - { - result[0] = static_cast(0xE0 | (ch >> 12)); - result[1] = static_cast(0x80 | ((ch >> 6) & 0x3F)); - result[2] = static_cast(0x80 | (ch & 0x3F)); - return result + 3; - } - } - - static value_type high(value_type result, uint32_t ch) - { - // U+10000..U+10FFFF - result[0] = static_cast(0xF0 | (ch >> 18)); - result[1] = static_cast(0x80 | ((ch >> 12) & 0x3F)); - result[2] = static_cast(0x80 | ((ch >> 6) & 0x3F)); - result[3] = static_cast(0x80 | (ch & 0x3F)); - return result + 4; - } - - static value_type any(value_type result, uint32_t ch) - { - return (ch < 0x10000) ? low(result, ch) : high(result, ch); - } - }; - - struct utf16_counter - { - typedef size_t value_type; - - static value_type low(value_type result, uint32_t) - { - return result + 1; - } - - static value_type high(value_type result, uint32_t) - { - return result + 2; - } - }; - - struct utf16_writer - { - typedef uint16_t* value_type; - - static value_type low(value_type result, uint32_t ch) - { - *result = static_cast(ch); - - return result + 1; - } - - static value_type high(value_type result, uint32_t ch) - { - uint32_t msh = static_cast(ch - 0x10000) >> 10; - uint32_t lsh = static_cast(ch - 0x10000) & 0x3ff; - - result[0] = static_cast(0xD800 + msh); - result[1] = static_cast(0xDC00 + lsh); - - return result + 2; - } - - static value_type any(value_type result, uint32_t ch) - { - return (ch < 0x10000) ? low(result, ch) : high(result, ch); - } - }; - - struct utf32_counter - { - typedef size_t value_type; - - static value_type low(value_type result, uint32_t) - { - return result + 1; - } - - static value_type high(value_type result, uint32_t) - { - return result + 1; - } - }; - - struct utf32_writer - { - typedef uint32_t* value_type; - - static value_type low(value_type result, uint32_t ch) - { - *result = ch; - - return result + 1; - } - - static value_type high(value_type result, uint32_t ch) - { - *result = ch; - - return result + 1; - } - - static value_type any(value_type result, uint32_t ch) - { - *result = ch; - - return result + 1; - } - }; - - struct latin1_writer - { - typedef uint8_t* value_type; - - static value_type low(value_type result, uint32_t ch) - { - *result = static_cast(ch > 255 ? '?' : ch); - - return result + 1; - } - - static value_type high(value_type result, uint32_t ch) - { - (void)ch; - - *result = '?'; - - return result + 1; - } - }; - - template struct wchar_selector; - - template <> struct wchar_selector<2> - { - typedef uint16_t type; - typedef utf16_counter counter; - typedef utf16_writer writer; - }; - - template <> struct wchar_selector<4> - { - typedef uint32_t type; - typedef utf32_counter counter; - typedef utf32_writer writer; - }; - - typedef wchar_selector::counter wchar_counter; - typedef wchar_selector::writer wchar_writer; - - template struct utf_decoder - { - static inline typename Traits::value_type decode_utf8_block(const uint8_t* data, size_t size, typename Traits::value_type result) - { - const uint8_t utf8_byte_mask = 0x3f; - - while (size) - { - uint8_t lead = *data; - - // 0xxxxxxx -> U+0000..U+007F - if (lead < 0x80) - { - result = Traits::low(result, lead); - data += 1; - size -= 1; - - // process aligned single-byte (ascii) blocks - if ((reinterpret_cast(data) & 3) == 0) - { - // round-trip through void* to silence 'cast increases required alignment of target type' warnings - while (size >= 4 && (*static_cast(static_cast(data)) & 0x80808080) == 0) - { - result = Traits::low(result, data[0]); - result = Traits::low(result, data[1]); - result = Traits::low(result, data[2]); - result = Traits::low(result, data[3]); - data += 4; - size -= 4; - } - } - } - // 110xxxxx -> U+0080..U+07FF - else if (static_cast(lead - 0xC0) < 0x20 && size >= 2 && (data[1] & 0xc0) == 0x80) - { - result = Traits::low(result, ((lead & ~0xC0) << 6) | (data[1] & utf8_byte_mask)); - data += 2; - size -= 2; - } - // 1110xxxx -> U+0800-U+FFFF - else if (static_cast(lead - 0xE0) < 0x10 && size >= 3 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80) - { - result = Traits::low(result, ((lead & ~0xE0) << 12) | ((data[1] & utf8_byte_mask) << 6) | (data[2] & utf8_byte_mask)); - data += 3; - size -= 3; - } - // 11110xxx -> U+10000..U+10FFFF - else if (static_cast(lead - 0xF0) < 0x08 && size >= 4 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80 && (data[3] & 0xc0) == 0x80) - { - result = Traits::high(result, ((lead & ~0xF0) << 18) | ((data[1] & utf8_byte_mask) << 12) | ((data[2] & utf8_byte_mask) << 6) | (data[3] & utf8_byte_mask)); - data += 4; - size -= 4; - } - // 10xxxxxx or 11111xxx -> invalid - else - { - data += 1; - size -= 1; - } - } - - return result; - } - - static inline typename Traits::value_type decode_utf16_block(const uint16_t* data, size_t size, typename Traits::value_type result) - { - const uint16_t* end = data + size; - - while (data < end) - { - uint16_t lead = opt_swap::value ? endian_swap(*data) : *data; - - // U+0000..U+D7FF - if (lead < 0xD800) - { - result = Traits::low(result, lead); - data += 1; - } - // U+E000..U+FFFF - else if (static_cast(lead - 0xE000) < 0x2000) - { - result = Traits::low(result, lead); - data += 1; - } - // surrogate pair lead - else if (static_cast(lead - 0xD800) < 0x400 && data + 1 < end) - { - uint16_t next = opt_swap::value ? endian_swap(data[1]) : data[1]; - - if (static_cast(next - 0xDC00) < 0x400) - { - result = Traits::high(result, 0x10000 + ((lead & 0x3ff) << 10) + (next & 0x3ff)); - data += 2; - } - else - { - data += 1; - } - } - else - { - data += 1; - } - } - - return result; - } - - static inline typename Traits::value_type decode_utf32_block(const uint32_t* data, size_t size, typename Traits::value_type result) - { - const uint32_t* end = data + size; - - while (data < end) - { - uint32_t lead = opt_swap::value ? endian_swap(*data) : *data; - - // U+0000..U+FFFF - if (lead < 0x10000) - { - result = Traits::low(result, lead); - data += 1; - } - // U+10000..U+10FFFF - else - { - result = Traits::high(result, lead); - data += 1; - } - } - - return result; - } - - static inline typename Traits::value_type decode_latin1_block(const uint8_t* data, size_t size, typename Traits::value_type result) - { - for (size_t i = 0; i < size; ++i) - { - result = Traits::low(result, data[i]); - } - - return result; - } - - static inline typename Traits::value_type decode_wchar_block_impl(const uint16_t* data, size_t size, typename Traits::value_type result) - { - return decode_utf16_block(data, size, result); - } - - static inline typename Traits::value_type decode_wchar_block_impl(const uint32_t* data, size_t size, typename Traits::value_type result) - { - return decode_utf32_block(data, size, result); - } - - static inline typename Traits::value_type decode_wchar_block(const wchar_t* data, size_t size, typename Traits::value_type result) - { - return decode_wchar_block_impl(reinterpret_cast::type*>(data), size, result); - } - }; - - template PUGI__FN void convert_utf_endian_swap(T* result, const T* data, size_t length) - { - for (size_t i = 0; i < length; ++i) result[i] = endian_swap(data[i]); - } - -#ifdef PUGIXML_WCHAR_MODE - PUGI__FN void convert_wchar_endian_swap(wchar_t* result, const wchar_t* data, size_t length) - { - for (size_t i = 0; i < length; ++i) result[i] = static_cast(endian_swap(static_cast::type>(data[i]))); - } -#endif -PUGI__NS_END - -PUGI__NS_BEGIN - enum chartype_t - { - ct_parse_pcdata = 1, // \0, &, \r, < - ct_parse_attr = 2, // \0, &, \r, ', " - ct_parse_attr_ws = 4, // \0, &, \r, ', ", \n, tab - ct_space = 8, // \r, \n, space, tab - ct_parse_cdata = 16, // \0, ], >, \r - ct_parse_comment = 32, // \0, -, >, \r - ct_symbol = 64, // Any symbol > 127, a-z, A-Z, 0-9, _, :, -, . - ct_start_symbol = 128 // Any symbol > 127, a-z, A-Z, _, : - }; - - static const unsigned char chartype_table[256] = - { - 55, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 63, 0, 0, // 0-15 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 - 8, 0, 6, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 96, 64, 0, // 32-47 - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192, 0, 1, 0, 48, 0, // 48-63 - 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 64-79 - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 16, 0, 192, // 80-95 - 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 96-111 - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 0, 0, 0, // 112-127 - - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 128+ - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192 - }; - - enum chartypex_t - { - ctx_special_pcdata = 1, // Any symbol >= 0 and < 32 (except \t, \r, \n), &, <, > - ctx_special_attr = 2, // Any symbol >= 0 and < 32 (except \t), &, <, >, " - ctx_start_symbol = 4, // Any symbol > 127, a-z, A-Z, _ - ctx_digit = 8, // 0-9 - ctx_symbol = 16 // Any symbol > 127, a-z, A-Z, 0-9, _, -, . - }; - - static const unsigned char chartypex_table[256] = - { - 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 2, 3, 3, // 0-15 - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 16-31 - 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 16, 16, 0, // 32-47 - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 3, 0, 3, 0, // 48-63 - - 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 64-79 - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 20, // 80-95 - 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 96-111 - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, // 112-127 - - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 128+ - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 - }; - -#ifdef PUGIXML_WCHAR_MODE - #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) ((static_cast(c) < 128 ? table[static_cast(c)] : table[128]) & (ct)) -#else - #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) (table[static_cast(c)] & (ct)) -#endif - - #define PUGI__IS_CHARTYPE(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartype_table) - #define PUGI__IS_CHARTYPEX(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartypex_table) - - PUGI__FN bool is_little_endian() - { - unsigned int ui = 1; - - return *reinterpret_cast(&ui) == 1; - } - - PUGI__FN xml_encoding get_wchar_encoding() - { - PUGI__STATIC_ASSERT(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4); - - if (sizeof(wchar_t) == 2) - return is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - else - return is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - } - - PUGI__FN xml_encoding guess_buffer_encoding(uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) - { - // look for BOM in first few bytes - if (d0 == 0 && d1 == 0 && d2 == 0xfe && d3 == 0xff) return encoding_utf32_be; - if (d0 == 0xff && d1 == 0xfe && d2 == 0 && d3 == 0) return encoding_utf32_le; - if (d0 == 0xfe && d1 == 0xff) return encoding_utf16_be; - if (d0 == 0xff && d1 == 0xfe) return encoding_utf16_le; - if (d0 == 0xef && d1 == 0xbb && d2 == 0xbf) return encoding_utf8; - - // look for <, (contents); - - PUGI__DMC_VOLATILE uint8_t d0 = data[0], d1 = data[1], d2 = data[2], d3 = data[3]; - - return guess_buffer_encoding(d0, d1, d2, d3); - } - - PUGI__FN bool get_mutable_buffer(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) - { - if (is_mutable) - { - out_buffer = static_cast(const_cast(contents)); - } - else - { - void* buffer = xml_memory::allocate(size > 0 ? size : 1); - if (!buffer) return false; - - memcpy(buffer, contents, size); - - out_buffer = static_cast(buffer); - } - - out_length = size / sizeof(char_t); - - return true; - } - -#ifdef PUGIXML_WCHAR_MODE - PUGI__FN bool need_endian_swap_utf(xml_encoding le, xml_encoding re) - { - return (le == encoding_utf16_be && re == encoding_utf16_le) || (le == encoding_utf16_le && re == encoding_utf16_be) || - (le == encoding_utf32_be && re == encoding_utf32_le) || (le == encoding_utf32_le && re == encoding_utf32_be); - } - - PUGI__FN bool convert_buffer_endian_swap(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) - { - const char_t* data = static_cast(contents); - - if (is_mutable) - { - out_buffer = const_cast(data); - } - else - { - out_buffer = static_cast(xml_memory::allocate(size > 0 ? size : 1)); - if (!out_buffer) return false; - } - - out_length = size / sizeof(char_t); - - convert_wchar_endian_swap(out_buffer, data, out_length); - - return true; - } - - PUGI__FN bool convert_buffer_utf8(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size) - { - const uint8_t* data = static_cast(contents); - - // first pass: get length in wchar_t units - out_length = utf_decoder::decode_utf8_block(data, size, 0); - - // allocate buffer of suitable length - out_buffer = static_cast(xml_memory::allocate((out_length > 0 ? out_length : 1) * sizeof(char_t))); - if (!out_buffer) return false; - - // second pass: convert utf8 input to wchar_t - wchar_writer::value_type out_begin = reinterpret_cast(out_buffer); - wchar_writer::value_type out_end = utf_decoder::decode_utf8_block(data, size, out_begin); - - assert(out_end == out_begin + out_length); - (void)!out_end; - - return true; - } - - template PUGI__FN bool convert_buffer_utf16(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, opt_swap) - { - const uint16_t* data = static_cast(contents); - size_t length = size / sizeof(uint16_t); - - // first pass: get length in wchar_t units - out_length = utf_decoder::decode_utf16_block(data, length, 0); - - // allocate buffer of suitable length - out_buffer = static_cast(xml_memory::allocate((out_length > 0 ? out_length : 1) * sizeof(char_t))); - if (!out_buffer) return false; - - // second pass: convert utf16 input to wchar_t - wchar_writer::value_type out_begin = reinterpret_cast(out_buffer); - wchar_writer::value_type out_end = utf_decoder::decode_utf16_block(data, length, out_begin); - - assert(out_end == out_begin + out_length); - (void)!out_end; - - return true; - } - - template PUGI__FN bool convert_buffer_utf32(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, opt_swap) - { - const uint32_t* data = static_cast(contents); - size_t length = size / sizeof(uint32_t); - - // first pass: get length in wchar_t units - out_length = utf_decoder::decode_utf32_block(data, length, 0); - - // allocate buffer of suitable length - out_buffer = static_cast(xml_memory::allocate((out_length > 0 ? out_length : 1) * sizeof(char_t))); - if (!out_buffer) return false; - - // second pass: convert utf32 input to wchar_t - wchar_writer::value_type out_begin = reinterpret_cast(out_buffer); - wchar_writer::value_type out_end = utf_decoder::decode_utf32_block(data, length, out_begin); - - assert(out_end == out_begin + out_length); - (void)!out_end; - - return true; - } - - PUGI__FN bool convert_buffer_latin1(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size) - { - const uint8_t* data = static_cast(contents); - - // get length in wchar_t units - out_length = size; - - // allocate buffer of suitable length - out_buffer = static_cast(xml_memory::allocate((out_length > 0 ? out_length : 1) * sizeof(char_t))); - if (!out_buffer) return false; - - // convert latin1 input to wchar_t - wchar_writer::value_type out_begin = reinterpret_cast(out_buffer); - wchar_writer::value_type out_end = utf_decoder::decode_latin1_block(data, size, out_begin); - - assert(out_end == out_begin + out_length); - (void)!out_end; - - return true; - } - - PUGI__FN bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable) - { - // get native encoding - xml_encoding wchar_encoding = get_wchar_encoding(); - - // fast path: no conversion required - if (encoding == wchar_encoding) return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable); - - // only endian-swapping is required - if (need_endian_swap_utf(encoding, wchar_encoding)) return convert_buffer_endian_swap(out_buffer, out_length, contents, size, is_mutable); - - // source encoding is utf8 - if (encoding == encoding_utf8) return convert_buffer_utf8(out_buffer, out_length, contents, size); - - // source encoding is utf16 - if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) - { - xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - - return (native_encoding == encoding) ? - convert_buffer_utf16(out_buffer, out_length, contents, size, opt_false()) : - convert_buffer_utf16(out_buffer, out_length, contents, size, opt_true()); - } - - // source encoding is utf32 - if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) - { - xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - - return (native_encoding == encoding) ? - convert_buffer_utf32(out_buffer, out_length, contents, size, opt_false()) : - convert_buffer_utf32(out_buffer, out_length, contents, size, opt_true()); - } - - // source encoding is latin1 - if (encoding == encoding_latin1) return convert_buffer_latin1(out_buffer, out_length, contents, size); - - assert(!"Invalid encoding"); - return false; - } -#else - template PUGI__FN bool convert_buffer_utf16(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, opt_swap) - { - const uint16_t* data = static_cast(contents); - size_t length = size / sizeof(uint16_t); - - // first pass: get length in utf8 units - out_length = utf_decoder::decode_utf16_block(data, length, 0); - - // allocate buffer of suitable length - out_buffer = static_cast(xml_memory::allocate((out_length > 0 ? out_length : 1) * sizeof(char_t))); - if (!out_buffer) return false; - - // second pass: convert utf16 input to utf8 - uint8_t* out_begin = reinterpret_cast(out_buffer); - uint8_t* out_end = utf_decoder::decode_utf16_block(data, length, out_begin); - - assert(out_end == out_begin + out_length); - (void)!out_end; - - return true; - } - - template PUGI__FN bool convert_buffer_utf32(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, opt_swap) - { - const uint32_t* data = static_cast(contents); - size_t length = size / sizeof(uint32_t); - - // first pass: get length in utf8 units - out_length = utf_decoder::decode_utf32_block(data, length, 0); - - // allocate buffer of suitable length - out_buffer = static_cast(xml_memory::allocate((out_length > 0 ? out_length : 1) * sizeof(char_t))); - if (!out_buffer) return false; - - // second pass: convert utf32 input to utf8 - uint8_t* out_begin = reinterpret_cast(out_buffer); - uint8_t* out_end = utf_decoder::decode_utf32_block(data, length, out_begin); - - assert(out_end == out_begin + out_length); - (void)!out_end; - - return true; - } - - PUGI__FN size_t get_latin1_7bit_prefix_length(const uint8_t* data, size_t size) - { - for (size_t i = 0; i < size; ++i) - if (data[i] > 127) - return i; - - return size; - } - - PUGI__FN bool convert_buffer_latin1(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) - { - const uint8_t* data = static_cast(contents); - - // get size of prefix that does not need utf8 conversion - size_t prefix_length = get_latin1_7bit_prefix_length(data, size); - assert(prefix_length <= size); - - const uint8_t* postfix = data + prefix_length; - size_t postfix_length = size - prefix_length; - - // if no conversion is needed, just return the original buffer - if (postfix_length == 0) return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable); - - // first pass: get length in utf8 units - out_length = prefix_length + utf_decoder::decode_latin1_block(postfix, postfix_length, 0); - - // allocate buffer of suitable length - out_buffer = static_cast(xml_memory::allocate((out_length > 0 ? out_length : 1) * sizeof(char_t))); - if (!out_buffer) return false; - - // second pass: convert latin1 input to utf8 - memcpy(out_buffer, data, prefix_length); - - uint8_t* out_begin = reinterpret_cast(out_buffer); - uint8_t* out_end = utf_decoder::decode_latin1_block(postfix, postfix_length, out_begin + prefix_length); - - assert(out_end == out_begin + out_length); - (void)!out_end; - - return true; - } - - PUGI__FN bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable) - { - // fast path: no conversion required - if (encoding == encoding_utf8) return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable); - - // source encoding is utf16 - if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) - { - xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - - return (native_encoding == encoding) ? - convert_buffer_utf16(out_buffer, out_length, contents, size, opt_false()) : - convert_buffer_utf16(out_buffer, out_length, contents, size, opt_true()); - } - - // source encoding is utf32 - if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) - { - xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - - return (native_encoding == encoding) ? - convert_buffer_utf32(out_buffer, out_length, contents, size, opt_false()) : - convert_buffer_utf32(out_buffer, out_length, contents, size, opt_true()); - } - - // source encoding is latin1 - if (encoding == encoding_latin1) return convert_buffer_latin1(out_buffer, out_length, contents, size, is_mutable); - - assert(!"Invalid encoding"); - return false; - } -#endif - - PUGI__FN size_t as_utf8_begin(const wchar_t* str, size_t length) - { - // get length in utf8 characters - return utf_decoder::decode_wchar_block(str, length, 0); - } - - PUGI__FN void as_utf8_end(char* buffer, size_t size, const wchar_t* str, size_t length) - { - // convert to utf8 - uint8_t* begin = reinterpret_cast(buffer); - uint8_t* end = utf_decoder::decode_wchar_block(str, length, begin); - - assert(begin + size == end); - (void)!end; - - // zero-terminate - buffer[size] = 0; - } - -#ifndef PUGIXML_NO_STL - PUGI__FN std::string as_utf8_impl(const wchar_t* str, size_t length) - { - // first pass: get length in utf8 characters - size_t size = as_utf8_begin(str, length); - - // allocate resulting string - std::string result; - result.resize(size); - - // second pass: convert to utf8 - if (size > 0) as_utf8_end(&result[0], size, str, length); - - return result; - } - - PUGI__FN std::basic_string as_wide_impl(const char* str, size_t size) - { - const uint8_t* data = reinterpret_cast(str); - - // first pass: get length in wchar_t units - size_t length = utf_decoder::decode_utf8_block(data, size, 0); - - // allocate resulting string - std::basic_string result; - result.resize(length); - - // second pass: convert to wchar_t - if (length > 0) - { - wchar_writer::value_type begin = reinterpret_cast(&result[0]); - wchar_writer::value_type end = utf_decoder::decode_utf8_block(data, size, begin); - - assert(begin + length == end); - (void)!end; - } - - return result; - } -#endif - - inline bool strcpy_insitu_allow(size_t length, uintptr_t allocated, char_t* target) - { - assert(target); - size_t target_length = strlength(target); - - // always reuse document buffer memory if possible - if (!allocated) return target_length >= length; - - // reuse heap memory if waste is not too great - const size_t reuse_threshold = 32; - - return target_length >= length && (target_length < reuse_threshold || target_length - length < target_length / 2); - } - - PUGI__FN bool strcpy_insitu(char_t*& dest, uintptr_t& header, uintptr_t header_mask, const char_t* source) - { - size_t source_length = strlength(source); - - if (source_length == 0) - { - // empty string and null pointer are equivalent, so just deallocate old memory - xml_allocator* alloc = reinterpret_cast(header & xml_memory_page_pointer_mask)->allocator; - - if (header & header_mask) alloc->deallocate_string(dest); - - // mark the string as not allocated - dest = 0; - header &= ~header_mask; - - return true; - } - else if (dest && strcpy_insitu_allow(source_length, header & header_mask, dest)) - { - // we can reuse old buffer, so just copy the new data (including zero terminator) - memcpy(dest, source, (source_length + 1) * sizeof(char_t)); - - return true; - } - else - { - xml_allocator* alloc = reinterpret_cast(header & xml_memory_page_pointer_mask)->allocator; - - // allocate new buffer - char_t* buf = alloc->allocate_string(source_length + 1); - if (!buf) return false; - - // copy the string (including zero terminator) - memcpy(buf, source, (source_length + 1) * sizeof(char_t)); - - // deallocate old buffer (*after* the above to protect against overlapping memory and/or allocation failures) - if (header & header_mask) alloc->deallocate_string(dest); - - // the string is now allocated, so set the flag - dest = buf; - header |= header_mask; - - return true; - } - } - - struct gap - { - char_t* end; - size_t size; - - gap(): end(0), size(0) - { - } - - // Push new gap, move s count bytes further (skipping the gap). - // Collapse previous gap. - void push(char_t*& s, size_t count) - { - if (end) // there was a gap already; collapse it - { - // Move [old_gap_end, new_gap_start) to [old_gap_start, ...) - assert(s >= end); - memmove(end - size, end, reinterpret_cast(s) - reinterpret_cast(end)); - } - - s += count; // end of current gap - - // "merge" two gaps - end = s; - size += count; - } - - // Collapse all gaps, return past-the-end pointer - char_t* flush(char_t* s) - { - if (end) - { - // Move [old_gap_end, current_pos) to [old_gap_start, ...) - assert(s >= end); - memmove(end - size, end, reinterpret_cast(s) - reinterpret_cast(end)); - - return s - size; - } - else return s; - } - }; - - PUGI__FN char_t* strconv_escape(char_t* s, gap& g) - { - char_t* stre = s + 1; - - switch (*stre) - { - case '#': // &#... - { - unsigned int ucsc = 0; - - if (stre[1] == 'x') // &#x... (hex code) - { - stre += 2; - - char_t ch = *stre; - - if (ch == ';') return stre; - - for (;;) - { - if (static_cast(ch - '0') <= 9) - ucsc = 16 * ucsc + (ch - '0'); - else if (static_cast((ch | ' ') - 'a') <= 5) - ucsc = 16 * ucsc + ((ch | ' ') - 'a' + 10); - else if (ch == ';') - break; - else // cancel - return stre; - - ch = *++stre; - } - - ++stre; - } - else // &#... (dec code) - { - char_t ch = *++stre; - - if (ch == ';') return stre; - - for (;;) - { - if (static_cast(ch - '0') <= 9) - ucsc = 10 * ucsc + (ch - '0'); - else if (ch == ';') - break; - else // cancel - return stre; - - ch = *++stre; - } - - ++stre; - } - - #ifdef PUGIXML_WCHAR_MODE - s = reinterpret_cast(wchar_writer::any(reinterpret_cast(s), ucsc)); - #else - s = reinterpret_cast(utf8_writer::any(reinterpret_cast(s), ucsc)); - #endif - - g.push(s, stre - s); - return stre; - } - - case 'a': // &a - { - ++stre; - - if (*stre == 'm') // &am - { - if (*++stre == 'p' && *++stre == ';') // & - { - *s++ = '&'; - ++stre; - - g.push(s, stre - s); - return stre; - } - } - else if (*stre == 'p') // &ap - { - if (*++stre == 'o' && *++stre == 's' && *++stre == ';') // ' - { - *s++ = '\''; - ++stre; - - g.push(s, stre - s); - return stre; - } - } - break; - } - - case 'g': // &g - { - if (*++stre == 't' && *++stre == ';') // > - { - *s++ = '>'; - ++stre; - - g.push(s, stre - s); - return stre; - } - break; - } - - case 'l': // &l - { - if (*++stre == 't' && *++stre == ';') // < - { - *s++ = '<'; - ++stre; - - g.push(s, stre - s); - return stre; - } - break; - } - - case 'q': // &q - { - if (*++stre == 'u' && *++stre == 'o' && *++stre == 't' && *++stre == ';') // " - { - *s++ = '"'; - ++stre; - - g.push(s, stre - s); - return stre; - } - break; - } - - default: - break; - } - - return stre; - } - - // Utility macro for last character handling - #define ENDSWITH(c, e) ((c) == (e) || ((c) == 0 && endch == (e))) - - PUGI__FN char_t* strconv_comment(char_t* s, char_t endch) - { - gap g; - - while (true) - { - while (!PUGI__IS_CHARTYPE(*s, ct_parse_comment)) ++s; - - if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair - { - *s++ = '\n'; // replace first one with 0x0a - - if (*s == '\n') g.push(s, 1); - } - else if (s[0] == '-' && s[1] == '-' && ENDSWITH(s[2], '>')) // comment ends here - { - *g.flush(s) = 0; - - return s + (s[2] == '>' ? 3 : 2); - } - else if (*s == 0) - { - return 0; - } - else ++s; - } - } - - PUGI__FN char_t* strconv_cdata(char_t* s, char_t endch) - { - gap g; - - while (true) - { - while (!PUGI__IS_CHARTYPE(*s, ct_parse_cdata)) ++s; - - if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair - { - *s++ = '\n'; // replace first one with 0x0a - - if (*s == '\n') g.push(s, 1); - } - else if (s[0] == ']' && s[1] == ']' && ENDSWITH(s[2], '>')) // CDATA ends here - { - *g.flush(s) = 0; - - return s + 1; - } - else if (*s == 0) - { - return 0; - } - else ++s; - } - } - - typedef char_t* (*strconv_pcdata_t)(char_t*); - - template struct strconv_pcdata_impl - { - static char_t* parse(char_t* s) - { - gap g; - - while (true) - { - while (!PUGI__IS_CHARTYPE(*s, ct_parse_pcdata)) ++s; - - if (*s == '<') // PCDATA ends here - { - *g.flush(s) = 0; - - return s + 1; - } - else if (opt_eol::value && *s == '\r') // Either a single 0x0d or 0x0d 0x0a pair - { - *s++ = '\n'; // replace first one with 0x0a - - if (*s == '\n') g.push(s, 1); - } - else if (opt_escape::value && *s == '&') - { - s = strconv_escape(s, g); - } - else if (*s == 0) - { - return s; - } - else ++s; - } - } - }; - - PUGI__FN strconv_pcdata_t get_strconv_pcdata(unsigned int optmask) - { - PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20); - - switch ((optmask >> 4) & 3) // get bitmask for flags (eol escapes) - { - case 0: return strconv_pcdata_impl::parse; - case 1: return strconv_pcdata_impl::parse; - case 2: return strconv_pcdata_impl::parse; - case 3: return strconv_pcdata_impl::parse; - default: return 0; // should not get here - } - } - - typedef char_t* (*strconv_attribute_t)(char_t*, char_t); - - template struct strconv_attribute_impl - { - static char_t* parse_wnorm(char_t* s, char_t end_quote) - { - gap g; - - // trim leading whitespaces - if (PUGI__IS_CHARTYPE(*s, ct_space)) - { - char_t* str = s; - - do ++str; - while (PUGI__IS_CHARTYPE(*str, ct_space)); - - g.push(s, str - s); - } - - while (true) - { - while (!PUGI__IS_CHARTYPE(*s, ct_parse_attr_ws | ct_space)) ++s; - - if (*s == end_quote) - { - char_t* str = g.flush(s); - - do *str-- = 0; - while (PUGI__IS_CHARTYPE(*str, ct_space)); - - return s + 1; - } - else if (PUGI__IS_CHARTYPE(*s, ct_space)) - { - *s++ = ' '; - - if (PUGI__IS_CHARTYPE(*s, ct_space)) - { - char_t* str = s + 1; - while (PUGI__IS_CHARTYPE(*str, ct_space)) ++str; - - g.push(s, str - s); - } - } - else if (opt_escape::value && *s == '&') - { - s = strconv_escape(s, g); - } - else if (!*s) - { - return 0; - } - else ++s; - } - } - - static char_t* parse_wconv(char_t* s, char_t end_quote) - { - gap g; - - while (true) - { - while (!PUGI__IS_CHARTYPE(*s, ct_parse_attr_ws)) ++s; - - if (*s == end_quote) - { - *g.flush(s) = 0; - - return s + 1; - } - else if (PUGI__IS_CHARTYPE(*s, ct_space)) - { - if (*s == '\r') - { - *s++ = ' '; - - if (*s == '\n') g.push(s, 1); - } - else *s++ = ' '; - } - else if (opt_escape::value && *s == '&') - { - s = strconv_escape(s, g); - } - else if (!*s) - { - return 0; - } - else ++s; - } - } - - static char_t* parse_eol(char_t* s, char_t end_quote) - { - gap g; - - while (true) - { - while (!PUGI__IS_CHARTYPE(*s, ct_parse_attr)) ++s; - - if (*s == end_quote) - { - *g.flush(s) = 0; - - return s + 1; - } - else if (*s == '\r') - { - *s++ = '\n'; - - if (*s == '\n') g.push(s, 1); - } - else if (opt_escape::value && *s == '&') - { - s = strconv_escape(s, g); - } - else if (!*s) - { - return 0; - } - else ++s; - } - } - - static char_t* parse_simple(char_t* s, char_t end_quote) - { - gap g; - - while (true) - { - while (!PUGI__IS_CHARTYPE(*s, ct_parse_attr)) ++s; - - if (*s == end_quote) - { - *g.flush(s) = 0; - - return s + 1; - } - else if (opt_escape::value && *s == '&') - { - s = strconv_escape(s, g); - } - else if (!*s) - { - return 0; - } - else ++s; - } - } - }; - - PUGI__FN strconv_attribute_t get_strconv_attribute(unsigned int optmask) - { - PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_wconv_attribute == 0x40 && parse_wnorm_attribute == 0x80); - - switch ((optmask >> 4) & 15) // get bitmask for flags (wconv wnorm eol escapes) - { - case 0: return strconv_attribute_impl::parse_simple; - case 1: return strconv_attribute_impl::parse_simple; - case 2: return strconv_attribute_impl::parse_eol; - case 3: return strconv_attribute_impl::parse_eol; - case 4: return strconv_attribute_impl::parse_wconv; - case 5: return strconv_attribute_impl::parse_wconv; - case 6: return strconv_attribute_impl::parse_wconv; - case 7: return strconv_attribute_impl::parse_wconv; - case 8: return strconv_attribute_impl::parse_wnorm; - case 9: return strconv_attribute_impl::parse_wnorm; - case 10: return strconv_attribute_impl::parse_wnorm; - case 11: return strconv_attribute_impl::parse_wnorm; - case 12: return strconv_attribute_impl::parse_wnorm; - case 13: return strconv_attribute_impl::parse_wnorm; - case 14: return strconv_attribute_impl::parse_wnorm; - case 15: return strconv_attribute_impl::parse_wnorm; - default: return 0; // should not get here - } - } - - inline xml_parse_result make_parse_result(xml_parse_status status, ptrdiff_t offset = 0) - { - xml_parse_result result; - result.status = status; - result.offset = offset; - - return result; - } - - struct xml_parser - { - xml_allocator alloc; - char_t* error_offset; - xml_parse_status error_status; - - // Parser utilities. - #define PUGI__SKIPWS() { while (PUGI__IS_CHARTYPE(*s, ct_space)) ++s; } - #define PUGI__OPTSET(OPT) ( optmsk & (OPT) ) - #define PUGI__PUSHNODE(TYPE) { cursor = append_node(cursor, alloc, TYPE); if (!cursor) PUGI__THROW_ERROR(status_out_of_memory, s); } - #define PUGI__POPNODE() { cursor = cursor->parent; } - #define PUGI__SCANFOR(X) { while (*s != 0 && !(X)) ++s; } - #define PUGI__SCANWHILE(X) { while ((X)) ++s; } - #define PUGI__ENDSEG() { ch = *s; *s = 0; ++s; } - #define PUGI__THROW_ERROR(err, m) return error_offset = m, error_status = err, static_cast(0) - #define PUGI__CHECK_ERROR(err, m) { if (*s == 0) PUGI__THROW_ERROR(err, m); } - - xml_parser(const xml_allocator& alloc_): alloc(alloc_), error_offset(0), error_status(status_ok) - { - } - - // DOCTYPE consists of nested sections of the following possible types: - // , , "...", '...' - // - // - // First group can not contain nested groups - // Second group can contain nested groups of the same type - // Third group can contain all other groups - char_t* parse_doctype_primitive(char_t* s) - { - if (*s == '"' || *s == '\'') - { - // quoted string - char_t ch = *s++; - PUGI__SCANFOR(*s == ch); - if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); - - s++; - } - else if (s[0] == '<' && s[1] == '?') - { - // - s += 2; - PUGI__SCANFOR(s[0] == '?' && s[1] == '>'); // no need for ENDSWITH because ?> can't terminate proper doctype - if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); - - s += 2; - } - else if (s[0] == '<' && s[1] == '!' && s[2] == '-' && s[3] == '-') - { - s += 4; - PUGI__SCANFOR(s[0] == '-' && s[1] == '-' && s[2] == '>'); // no need for ENDSWITH because --> can't terminate proper doctype - if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); - - s += 4; - } - else PUGI__THROW_ERROR(status_bad_doctype, s); - - return s; - } - - char_t* parse_doctype_ignore(char_t* s) - { - assert(s[0] == '<' && s[1] == '!' && s[2] == '['); - s++; - - while (*s) - { - if (s[0] == '<' && s[1] == '!' && s[2] == '[') - { - // nested ignore section - s = parse_doctype_ignore(s); - if (!s) return s; - } - else if (s[0] == ']' && s[1] == ']' && s[2] == '>') - { - // ignore section end - s += 3; - - return s; - } - else s++; - } - - PUGI__THROW_ERROR(status_bad_doctype, s); - } - - char_t* parse_doctype_group(char_t* s, char_t endch, bool toplevel) - { - assert(s[0] == '<' && s[1] == '!'); - s++; - - while (*s) - { - if (s[0] == '<' && s[1] == '!' && s[2] != '-') - { - if (s[2] == '[') - { - // ignore - s = parse_doctype_ignore(s); - if (!s) return s; - } - else - { - // some control group - s = parse_doctype_group(s, endch, false); - if (!s) return s; - } - } - else if (s[0] == '<' || s[0] == '"' || s[0] == '\'') - { - // unknown tag (forbidden), or some primitive group - s = parse_doctype_primitive(s); - if (!s) return s; - } - else if (*s == '>') - { - s++; - - return s; - } - else s++; - } - - if (!toplevel || endch != '>') PUGI__THROW_ERROR(status_bad_doctype, s); - - return s; - } - - char_t* parse_exclamation(char_t* s, xml_node_struct* cursor, unsigned int optmsk, char_t endch) - { - // parse node contents, starting with exclamation mark - ++s; - - if (*s == '-') // 'value = s; // Save the offset. - } - - if (PUGI__OPTSET(parse_eol) && PUGI__OPTSET(parse_comments)) - { - s = strconv_comment(s, endch); - - if (!s) PUGI__THROW_ERROR(status_bad_comment, cursor->value); - } - else - { - // Scan for terminating '-->'. - PUGI__SCANFOR(s[0] == '-' && s[1] == '-' && ENDSWITH(s[2], '>')); - PUGI__CHECK_ERROR(status_bad_comment, s); - - if (PUGI__OPTSET(parse_comments)) - *s = 0; // Zero-terminate this segment at the first terminating '-'. - - s += (s[2] == '>' ? 3 : 2); // Step over the '\0->'. - } - } - else PUGI__THROW_ERROR(status_bad_comment, s); - } - else if (*s == '[') - { - // 'value = s; // Save the offset. - - if (PUGI__OPTSET(parse_eol)) - { - s = strconv_cdata(s, endch); - - if (!s) PUGI__THROW_ERROR(status_bad_cdata, cursor->value); - } - else - { - // Scan for terminating ']]>'. - PUGI__SCANFOR(s[0] == ']' && s[1] == ']' && ENDSWITH(s[2], '>')); - PUGI__CHECK_ERROR(status_bad_cdata, s); - - *s++ = 0; // Zero-terminate this segment. - } - } - else // Flagged for discard, but we still have to scan for the terminator. - { - // Scan for terminating ']]>'. - PUGI__SCANFOR(s[0] == ']' && s[1] == ']' && ENDSWITH(s[2], '>')); - PUGI__CHECK_ERROR(status_bad_cdata, s); - - ++s; - } - - s += (s[1] == '>' ? 2 : 1); // Step over the last ']>'. - } - else PUGI__THROW_ERROR(status_bad_cdata, s); - } - else if (s[0] == 'D' && s[1] == 'O' && s[2] == 'C' && s[3] == 'T' && s[4] == 'Y' && s[5] == 'P' && ENDSWITH(s[6], 'E')) - { - s -= 2; - - if (cursor->parent) PUGI__THROW_ERROR(status_bad_doctype, s); - - char_t* mark = s + 9; - - s = parse_doctype_group(s, endch, true); - if (!s) return s; - - if (PUGI__OPTSET(parse_doctype)) - { - while (PUGI__IS_CHARTYPE(*mark, ct_space)) ++mark; - - PUGI__PUSHNODE(node_doctype); - - cursor->value = mark; - - assert((s[0] == 0 && endch == '>') || s[-1] == '>'); - s[*s == 0 ? 0 : -1] = 0; - - PUGI__POPNODE(); - } - } - else if (*s == 0 && endch == '-') PUGI__THROW_ERROR(status_bad_comment, s); - else if (*s == 0 && endch == '[') PUGI__THROW_ERROR(status_bad_cdata, s); - else PUGI__THROW_ERROR(status_unrecognized_tag, s); - - return s; - } - - char_t* parse_question(char_t* s, xml_node_struct*& ref_cursor, unsigned int optmsk, char_t endch) - { - // load into registers - xml_node_struct* cursor = ref_cursor; - char_t ch = 0; - - // parse node contents, starting with question mark - ++s; - - // read PI target - char_t* target = s; - - if (!PUGI__IS_CHARTYPE(*s, ct_start_symbol)) PUGI__THROW_ERROR(status_bad_pi, s); - - PUGI__SCANWHILE(PUGI__IS_CHARTYPE(*s, ct_symbol)); - PUGI__CHECK_ERROR(status_bad_pi, s); - - // determine node type; stricmp / strcasecmp is not portable - bool declaration = (target[0] | ' ') == 'x' && (target[1] | ' ') == 'm' && (target[2] | ' ') == 'l' && target + 3 == s; - - if (declaration ? PUGI__OPTSET(parse_declaration) : PUGI__OPTSET(parse_pi)) - { - if (declaration) - { - // disallow non top-level declarations - if (cursor->parent) PUGI__THROW_ERROR(status_bad_pi, s); - - PUGI__PUSHNODE(node_declaration); - } - else - { - PUGI__PUSHNODE(node_pi); - } - - cursor->name = target; - - PUGI__ENDSEG(); - - // parse value/attributes - if (ch == '?') - { - // empty node - if (!ENDSWITH(*s, '>')) PUGI__THROW_ERROR(status_bad_pi, s); - s += (*s == '>'); - - PUGI__POPNODE(); - } - else if (PUGI__IS_CHARTYPE(ch, ct_space)) - { - PUGI__SKIPWS(); - - // scan for tag end - char_t* value = s; - - PUGI__SCANFOR(s[0] == '?' && ENDSWITH(s[1], '>')); - PUGI__CHECK_ERROR(status_bad_pi, s); - - if (declaration) - { - // replace ending ? with / so that 'element' terminates properly - *s = '/'; - - // we exit from this function with cursor at node_declaration, which is a signal to parse() to go to LOC_ATTRIBUTES - s = value; - } - else - { - // store value and step over > - cursor->value = value; - PUGI__POPNODE(); - - PUGI__ENDSEG(); - - s += (*s == '>'); - } - } - else PUGI__THROW_ERROR(status_bad_pi, s); - } - else - { - // scan for tag end - PUGI__SCANFOR(s[0] == '?' && ENDSWITH(s[1], '>')); - PUGI__CHECK_ERROR(status_bad_pi, s); - - s += (s[1] == '>' ? 2 : 1); - } - - // store from registers - ref_cursor = cursor; - - return s; - } - - char_t* parse(char_t* s, xml_node_struct* xmldoc, unsigned int optmsk, char_t endch) - { - strconv_attribute_t strconv_attribute = get_strconv_attribute(optmsk); - strconv_pcdata_t strconv_pcdata = get_strconv_pcdata(optmsk); - - char_t ch = 0; - xml_node_struct* cursor = xmldoc; - char_t* mark = s; - - while (*s != 0) - { - if (*s == '<') - { - ++s; - - LOC_TAG: - if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // '<#...' - { - PUGI__PUSHNODE(node_element); // Append a new node to the tree. - - cursor->name = s; - - PUGI__SCANWHILE(PUGI__IS_CHARTYPE(*s, ct_symbol)); // Scan for a terminator. - PUGI__ENDSEG(); // Save char in 'ch', terminate & step over. - - if (ch == '>') - { - // end of tag - } - else if (PUGI__IS_CHARTYPE(ch, ct_space)) - { - LOC_ATTRIBUTES: - while (true) - { - PUGI__SKIPWS(); // Eat any whitespace. - - if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // <... #... - { - xml_attribute_struct* a = append_attribute_ll(cursor, alloc); // Make space for this attribute. - if (!a) PUGI__THROW_ERROR(status_out_of_memory, s); - - a->name = s; // Save the offset. - - PUGI__SCANWHILE(PUGI__IS_CHARTYPE(*s, ct_symbol)); // Scan for a terminator. - PUGI__CHECK_ERROR(status_bad_attribute, s); //$ redundant, left for performance - - PUGI__ENDSEG(); // Save char in 'ch', terminate & step over. - PUGI__CHECK_ERROR(status_bad_attribute, s); //$ redundant, left for performance - - if (PUGI__IS_CHARTYPE(ch, ct_space)) - { - PUGI__SKIPWS(); // Eat any whitespace. - PUGI__CHECK_ERROR(status_bad_attribute, s); //$ redundant, left for performance - - ch = *s; - ++s; - } - - if (ch == '=') // '<... #=...' - { - PUGI__SKIPWS(); // Eat any whitespace. - - if (*s == '"' || *s == '\'') // '<... #="...' - { - ch = *s; // Save quote char to avoid breaking on "''" -or- '""'. - ++s; // Step over the quote. - a->value = s; // Save the offset. - - s = strconv_attribute(s, ch); - - if (!s) PUGI__THROW_ERROR(status_bad_attribute, a->value); - - // After this line the loop continues from the start; - // Whitespaces, / and > are ok, symbols and EOF are wrong, - // everything else will be detected - if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) PUGI__THROW_ERROR(status_bad_attribute, s); - } - else PUGI__THROW_ERROR(status_bad_attribute, s); - } - else PUGI__THROW_ERROR(status_bad_attribute, s); - } - else if (*s == '/') - { - ++s; - - if (*s == '>') - { - PUGI__POPNODE(); - s++; - break; - } - else if (*s == 0 && endch == '>') - { - PUGI__POPNODE(); - break; - } - else PUGI__THROW_ERROR(status_bad_start_element, s); - } - else if (*s == '>') - { - ++s; - - break; - } - else if (*s == 0 && endch == '>') - { - break; - } - else PUGI__THROW_ERROR(status_bad_start_element, s); - } - - // !!! - } - else if (ch == '/') // '<#.../' - { - if (!ENDSWITH(*s, '>')) PUGI__THROW_ERROR(status_bad_start_element, s); - - PUGI__POPNODE(); // Pop. - - s += (*s == '>'); - } - else if (ch == 0) - { - // we stepped over null terminator, backtrack & handle closing tag - --s; - - if (endch != '>') PUGI__THROW_ERROR(status_bad_start_element, s); - } - else PUGI__THROW_ERROR(status_bad_start_element, s); - } - else if (*s == '/') - { - ++s; - - char_t* name = cursor->name; - if (!name) PUGI__THROW_ERROR(status_end_element_mismatch, s); - - while (PUGI__IS_CHARTYPE(*s, ct_symbol)) - { - if (*s++ != *name++) PUGI__THROW_ERROR(status_end_element_mismatch, s); - } - - if (*name) - { - if (*s == 0 && name[0] == endch && name[1] == 0) PUGI__THROW_ERROR(status_bad_end_element, s); - else PUGI__THROW_ERROR(status_end_element_mismatch, s); - } - - PUGI__POPNODE(); // Pop. - - PUGI__SKIPWS(); - - if (*s == 0) - { - if (endch != '>') PUGI__THROW_ERROR(status_bad_end_element, s); - } - else - { - if (*s != '>') PUGI__THROW_ERROR(status_bad_end_element, s); - ++s; - } - } - else if (*s == '?') // 'header & xml_memory_page_type_mask) + 1 == node_declaration) goto LOC_ATTRIBUTES; - } - else if (*s == '!') // 'first_child) continue; - } - } - - s = mark; - - if (cursor->parent) - { - PUGI__PUSHNODE(node_pcdata); // Append a new node on the tree. - cursor->value = s; // Save the offset. - - s = strconv_pcdata(s); - - PUGI__POPNODE(); // Pop since this is a standalone. - - if (!*s) break; - } - else - { - PUGI__SCANFOR(*s == '<'); // '...<' - if (!*s) break; - - ++s; - } - - // We're after '<' - goto LOC_TAG; - } - } - - // check that last tag is closed - if (cursor != xmldoc) PUGI__THROW_ERROR(status_end_element_mismatch, s); - - return s; - } - - static xml_parse_result parse(char_t* buffer, size_t length, xml_node_struct* root, unsigned int optmsk) - { - xml_document_struct* xmldoc = static_cast(root); - - // store buffer for offset_debug - xmldoc->buffer = buffer; - - // early-out for empty documents - if (length == 0) return make_parse_result(status_ok); - - // create parser on stack - xml_parser parser(*xmldoc); - - // save last character and make buffer zero-terminated (speeds up parsing) - char_t endch = buffer[length - 1]; - buffer[length - 1] = 0; - - // perform actual parsing - parser.parse(buffer, xmldoc, optmsk, endch); - - xml_parse_result result = make_parse_result(parser.error_status, parser.error_offset ? parser.error_offset - buffer : 0); - assert(result.offset >= 0 && static_cast(result.offset) <= length); - - // update allocator state - *static_cast(xmldoc) = parser.alloc; - - // since we removed last character, we have to handle the only possible false positive - if (result && endch == '<') - { - // there's no possible well-formed document with < at the end - return make_parse_result(status_unrecognized_tag, length); - } - - return result; - } - }; - - // Output facilities - PUGI__FN xml_encoding get_write_native_encoding() - { - #ifdef PUGIXML_WCHAR_MODE - return get_wchar_encoding(); - #else - return encoding_utf8; - #endif - } - - PUGI__FN xml_encoding get_write_encoding(xml_encoding encoding) - { - // replace wchar encoding with utf implementation - if (encoding == encoding_wchar) return get_wchar_encoding(); - - // replace utf16 encoding with utf16 with specific endianness - if (encoding == encoding_utf16) return is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - - // replace utf32 encoding with utf32 with specific endianness - if (encoding == encoding_utf32) return is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - - // only do autodetection if no explicit encoding is requested - if (encoding != encoding_auto) return encoding; - - // assume utf8 encoding - return encoding_utf8; - } - -#ifdef PUGIXML_WCHAR_MODE - PUGI__FN size_t get_valid_length(const char_t* data, size_t length) - { - assert(length > 0); - - // discard last character if it's the lead of a surrogate pair - return (sizeof(wchar_t) == 2 && static_cast(static_cast(data[length - 1]) - 0xD800) < 0x400) ? length - 1 : length; - } - - PUGI__FN size_t convert_buffer(char_t* r_char, uint8_t* r_u8, uint16_t* r_u16, uint32_t* r_u32, const char_t* data, size_t length, xml_encoding encoding) - { - // only endian-swapping is required - if (need_endian_swap_utf(encoding, get_wchar_encoding())) - { - convert_wchar_endian_swap(r_char, data, length); - - return length * sizeof(char_t); - } - - // convert to utf8 - if (encoding == encoding_utf8) - { - uint8_t* dest = r_u8; - uint8_t* end = utf_decoder::decode_wchar_block(data, length, dest); - - return static_cast(end - dest); - } - - // convert to utf16 - if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) - { - uint16_t* dest = r_u16; - - // convert to native utf16 - uint16_t* end = utf_decoder::decode_wchar_block(data, length, dest); - - // swap if necessary - xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - - if (native_encoding != encoding) convert_utf_endian_swap(dest, dest, static_cast(end - dest)); - - return static_cast(end - dest) * sizeof(uint16_t); - } - - // convert to utf32 - if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) - { - uint32_t* dest = r_u32; - - // convert to native utf32 - uint32_t* end = utf_decoder::decode_wchar_block(data, length, dest); - - // swap if necessary - xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - - if (native_encoding != encoding) convert_utf_endian_swap(dest, dest, static_cast(end - dest)); - - return static_cast(end - dest) * sizeof(uint32_t); - } - - // convert to latin1 - if (encoding == encoding_latin1) - { - uint8_t* dest = r_u8; - uint8_t* end = utf_decoder::decode_wchar_block(data, length, dest); - - return static_cast(end - dest); - } - - assert(!"Invalid encoding"); - return 0; - } -#else - PUGI__FN size_t get_valid_length(const char_t* data, size_t length) - { - assert(length > 4); - - for (size_t i = 1; i <= 4; ++i) - { - uint8_t ch = static_cast(data[length - i]); - - // either a standalone character or a leading one - if ((ch & 0xc0) != 0x80) return length - i; - } - - // there are four non-leading characters at the end, sequence tail is broken so might as well process the whole chunk - return length; - } - - PUGI__FN size_t convert_buffer(char_t* /* r_char */, uint8_t* r_u8, uint16_t* r_u16, uint32_t* r_u32, const char_t* data, size_t length, xml_encoding encoding) - { - if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) - { - uint16_t* dest = r_u16; - - // convert to native utf16 - uint16_t* end = utf_decoder::decode_utf8_block(reinterpret_cast(data), length, dest); - - // swap if necessary - xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - - if (native_encoding != encoding) convert_utf_endian_swap(dest, dest, static_cast(end - dest)); - - return static_cast(end - dest) * sizeof(uint16_t); - } - - if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) - { - uint32_t* dest = r_u32; - - // convert to native utf32 - uint32_t* end = utf_decoder::decode_utf8_block(reinterpret_cast(data), length, dest); - - // swap if necessary - xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - - if (native_encoding != encoding) convert_utf_endian_swap(dest, dest, static_cast(end - dest)); - - return static_cast(end - dest) * sizeof(uint32_t); - } - - if (encoding == encoding_latin1) - { - uint8_t* dest = r_u8; - uint8_t* end = utf_decoder::decode_utf8_block(reinterpret_cast(data), length, dest); - - return static_cast(end - dest); - } - - assert(!"Invalid encoding"); - return 0; - } -#endif - - class xml_buffered_writer - { - xml_buffered_writer(const xml_buffered_writer&); - xml_buffered_writer& operator=(const xml_buffered_writer&); - - public: - xml_buffered_writer(xml_writer& writer_, xml_encoding user_encoding): writer(writer_), bufsize(0), encoding(get_write_encoding(user_encoding)) - { - PUGI__STATIC_ASSERT(bufcapacity >= 8); - } - - ~xml_buffered_writer() - { - flush(); - } - - void flush() - { - flush(buffer, bufsize); - bufsize = 0; - } - - void flush(const char_t* data, size_t size) - { - if (size == 0) return; - - // fast path, just write data - if (encoding == get_write_native_encoding()) - writer.write(data, size * sizeof(char_t)); - else - { - // convert chunk - size_t result = convert_buffer(scratch.data_char, scratch.data_u8, scratch.data_u16, scratch.data_u32, data, size, encoding); - assert(result <= sizeof(scratch)); - - // write data - writer.write(scratch.data_u8, result); - } - } - - void write(const char_t* data, size_t length) - { - if (bufsize + length > bufcapacity) - { - // flush the remaining buffer contents - flush(); - - // handle large chunks - if (length > bufcapacity) - { - if (encoding == get_write_native_encoding()) - { - // fast path, can just write data chunk - writer.write(data, length * sizeof(char_t)); - return; - } - - // need to convert in suitable chunks - while (length > bufcapacity) - { - // get chunk size by selecting such number of characters that are guaranteed to fit into scratch buffer - // and form a complete codepoint sequence (i.e. discard start of last codepoint if necessary) - size_t chunk_size = get_valid_length(data, bufcapacity); - - // convert chunk and write - flush(data, chunk_size); - - // iterate - data += chunk_size; - length -= chunk_size; - } - - // small tail is copied below - bufsize = 0; - } - } - - memcpy(buffer + bufsize, data, length * sizeof(char_t)); - bufsize += length; - } - - void write(const char_t* data) - { - write(data, strlength(data)); - } - - void write(char_t d0) - { - if (bufsize + 1 > bufcapacity) flush(); - - buffer[bufsize + 0] = d0; - bufsize += 1; - } - - void write(char_t d0, char_t d1) - { - if (bufsize + 2 > bufcapacity) flush(); - - buffer[bufsize + 0] = d0; - buffer[bufsize + 1] = d1; - bufsize += 2; - } - - void write(char_t d0, char_t d1, char_t d2) - { - if (bufsize + 3 > bufcapacity) flush(); - - buffer[bufsize + 0] = d0; - buffer[bufsize + 1] = d1; - buffer[bufsize + 2] = d2; - bufsize += 3; - } - - void write(char_t d0, char_t d1, char_t d2, char_t d3) - { - if (bufsize + 4 > bufcapacity) flush(); - - buffer[bufsize + 0] = d0; - buffer[bufsize + 1] = d1; - buffer[bufsize + 2] = d2; - buffer[bufsize + 3] = d3; - bufsize += 4; - } - - void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4) - { - if (bufsize + 5 > bufcapacity) flush(); - - buffer[bufsize + 0] = d0; - buffer[bufsize + 1] = d1; - buffer[bufsize + 2] = d2; - buffer[bufsize + 3] = d3; - buffer[bufsize + 4] = d4; - bufsize += 5; - } - - void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4, char_t d5) - { - if (bufsize + 6 > bufcapacity) flush(); - - buffer[bufsize + 0] = d0; - buffer[bufsize + 1] = d1; - buffer[bufsize + 2] = d2; - buffer[bufsize + 3] = d3; - buffer[bufsize + 4] = d4; - buffer[bufsize + 5] = d5; - bufsize += 6; - } - - // utf8 maximum expansion: x4 (-> utf32) - // utf16 maximum expansion: x2 (-> utf32) - // utf32 maximum expansion: x1 - enum - { - bufcapacitybytes = - #ifdef PUGIXML_MEMORY_OUTPUT_STACK - PUGIXML_MEMORY_OUTPUT_STACK - #else - 10240 - #endif - , - bufcapacity = bufcapacitybytes / (sizeof(char_t) + 4) - }; - - char_t buffer[bufcapacity]; - - union - { - uint8_t data_u8[4 * bufcapacity]; - uint16_t data_u16[2 * bufcapacity]; - uint32_t data_u32[bufcapacity]; - char_t data_char[bufcapacity]; - } scratch; - - xml_writer& writer; - size_t bufsize; - xml_encoding encoding; - }; - - PUGI__FN void text_output_escaped(xml_buffered_writer& writer, const char_t* s, chartypex_t type) - { - while (*s) - { - const char_t* prev = s; - - // While *s is a usual symbol - while (!PUGI__IS_CHARTYPEX(*s, type)) ++s; - - writer.write(prev, static_cast(s - prev)); - - switch (*s) - { - case 0: break; - case '&': - writer.write('&', 'a', 'm', 'p', ';'); - ++s; - break; - case '<': - writer.write('&', 'l', 't', ';'); - ++s; - break; - case '>': - writer.write('&', 'g', 't', ';'); - ++s; - break; - case '"': - writer.write('&', 'q', 'u', 'o', 't', ';'); - ++s; - break; - default: // s is not a usual symbol - { - unsigned int ch = static_cast(*s++); - assert(ch < 32); - - writer.write('&', '#', static_cast((ch / 10) + '0'), static_cast((ch % 10) + '0'), ';'); - } - } - } - } - - PUGI__FN void text_output(xml_buffered_writer& writer, const char_t* s, chartypex_t type, unsigned int flags) - { - if (flags & format_no_escapes) - writer.write(s); - else - text_output_escaped(writer, s, type); - } - - PUGI__FN void text_output_cdata(xml_buffered_writer& writer, const char_t* s) - { - do - { - writer.write('<', '!', '[', 'C', 'D'); - writer.write('A', 'T', 'A', '['); - - const char_t* prev = s; - - // look for ]]> sequence - we can't output it as is since it terminates CDATA - while (*s && !(s[0] == ']' && s[1] == ']' && s[2] == '>')) ++s; - - // skip ]] if we stopped at ]]>, > will go to the next CDATA section - if (*s) s += 2; - - writer.write(prev, static_cast(s - prev)); - - writer.write(']', ']', '>'); - } - while (*s); - } - - PUGI__FN void node_output_attributes(xml_buffered_writer& writer, const xml_node& node, unsigned int flags) - { - const char_t* default_name = PUGIXML_TEXT(":anonymous"); - - for (xml_attribute a = node.first_attribute(); a; a = a.next_attribute()) - { - writer.write(' '); - writer.write(a.name()[0] ? a.name() : default_name); - writer.write('=', '"'); - - text_output(writer, a.value(), ctx_special_attr, flags); - - writer.write('"'); - } - } - - PUGI__FN void node_output(xml_buffered_writer& writer, const xml_node& node, const char_t* indent, unsigned int flags, unsigned int depth) - { - const char_t* default_name = PUGIXML_TEXT(":anonymous"); - - if ((flags & format_indent) != 0 && (flags & format_raw) == 0) - for (unsigned int i = 0; i < depth; ++i) writer.write(indent); - - switch (node.type()) - { - case node_document: - { - for (xml_node n = node.first_child(); n; n = n.next_sibling()) - node_output(writer, n, indent, flags, depth); - break; - } - - case node_element: - { - const char_t* name = node.name()[0] ? node.name() : default_name; - - writer.write('<'); - writer.write(name); - - node_output_attributes(writer, node, flags); - - if (flags & format_raw) - { - if (!node.first_child()) - writer.write(' ', '/', '>'); - else - { - writer.write('>'); - - for (xml_node n = node.first_child(); n; n = n.next_sibling()) - node_output(writer, n, indent, flags, depth + 1); - - writer.write('<', '/'); - writer.write(name); - writer.write('>'); - } - } - else if (!node.first_child()) - writer.write(' ', '/', '>', '\n'); - else if (node.first_child() == node.last_child() && (node.first_child().type() == node_pcdata || node.first_child().type() == node_cdata)) - { - writer.write('>'); - - if (node.first_child().type() == node_pcdata) - text_output(writer, node.first_child().value(), ctx_special_pcdata, flags); - else - text_output_cdata(writer, node.first_child().value()); - - writer.write('<', '/'); - writer.write(name); - writer.write('>', '\n'); - } - else - { - writer.write('>', '\n'); - - for (xml_node n = node.first_child(); n; n = n.next_sibling()) - node_output(writer, n, indent, flags, depth + 1); - - if ((flags & format_indent) != 0 && (flags & format_raw) == 0) - for (unsigned int i = 0; i < depth; ++i) writer.write(indent); - - writer.write('<', '/'); - writer.write(name); - writer.write('>', '\n'); - } - - break; - } - - case node_pcdata: - text_output(writer, node.value(), ctx_special_pcdata, flags); - if ((flags & format_raw) == 0) writer.write('\n'); - break; - - case node_cdata: - text_output_cdata(writer, node.value()); - if ((flags & format_raw) == 0) writer.write('\n'); - break; - - case node_comment: - writer.write('<', '!', '-', '-'); - writer.write(node.value()); - writer.write('-', '-', '>'); - if ((flags & format_raw) == 0) writer.write('\n'); - break; - - case node_pi: - case node_declaration: - writer.write('<', '?'); - writer.write(node.name()[0] ? node.name() : default_name); - - if (node.type() == node_declaration) - { - node_output_attributes(writer, node, flags); - } - else if (node.value()[0]) - { - writer.write(' '); - writer.write(node.value()); - } - - writer.write('?', '>'); - if ((flags & format_raw) == 0) writer.write('\n'); - break; - - case node_doctype: - writer.write('<', '!', 'D', 'O', 'C'); - writer.write('T', 'Y', 'P', 'E'); - - if (node.value()[0]) - { - writer.write(' '); - writer.write(node.value()); - } - - writer.write('>'); - if ((flags & format_raw) == 0) writer.write('\n'); - break; - - default: - assert(!"Invalid node type"); - } - } - - inline bool has_declaration(const xml_node& node) - { - for (xml_node child = node.first_child(); child; child = child.next_sibling()) - { - xml_node_type type = child.type(); - - if (type == node_declaration) return true; - if (type == node_element) return false; - } - - return false; - } - - inline bool allow_insert_child(xml_node_type parent, xml_node_type child) - { - if (parent != node_document && parent != node_element) return false; - if (child == node_document || child == node_null) return false; - if (parent != node_document && (child == node_declaration || child == node_doctype)) return false; - - return true; - } - - PUGI__FN void recursive_copy_skip(xml_node& dest, const xml_node& source, const xml_node& skip) - { - assert(dest.type() == source.type()); - - switch (source.type()) - { - case node_element: - { - dest.set_name(source.name()); - - for (xml_attribute a = source.first_attribute(); a; a = a.next_attribute()) - dest.append_attribute(a.name()).set_value(a.value()); - - for (xml_node c = source.first_child(); c; c = c.next_sibling()) - { - if (c == skip) continue; - - xml_node cc = dest.append_child(c.type()); - assert(cc); - - recursive_copy_skip(cc, c, skip); - } - - break; - } - - case node_pcdata: - case node_cdata: - case node_comment: - case node_doctype: - dest.set_value(source.value()); - break; - - case node_pi: - dest.set_name(source.name()); - dest.set_value(source.value()); - break; - - case node_declaration: - { - dest.set_name(source.name()); - - for (xml_attribute a = source.first_attribute(); a; a = a.next_attribute()) - dest.append_attribute(a.name()).set_value(a.value()); - - break; - } - - default: - assert(!"Invalid node type"); - } - } - - inline bool is_text_node(xml_node_struct* node) - { - xml_node_type type = static_cast((node->header & impl::xml_memory_page_type_mask) + 1); - - return type == node_pcdata || type == node_cdata; - } - - // get value with conversion functions - PUGI__FN int get_value_int(const char_t* value, int def) - { - if (!value) return def; - - #ifdef PUGIXML_WCHAR_MODE - return static_cast(wcstol(value, 0, 10)); - #else - return static_cast(strtol(value, 0, 10)); - #endif - } - - PUGI__FN unsigned int get_value_uint(const char_t* value, unsigned int def) - { - if (!value) return def; - - #ifdef PUGIXML_WCHAR_MODE - return static_cast(wcstoul(value, 0, 10)); - #else - return static_cast(strtoul(value, 0, 10)); - #endif - } - - PUGI__FN double get_value_double(const char_t* value, double def) - { - if (!value) return def; - - #ifdef PUGIXML_WCHAR_MODE - return wcstod(value, 0); - #else - return strtod(value, 0); - #endif - } - - PUGI__FN float get_value_float(const char_t* value, float def) - { - if (!value) return def; - - #ifdef PUGIXML_WCHAR_MODE - return static_cast(wcstod(value, 0)); - #else - return static_cast(strtod(value, 0)); - #endif - } - - PUGI__FN bool get_value_bool(const char_t* value, bool def) - { - if (!value) return def; - - // only look at first char - char_t first = *value; - - // 1*, t* (true), T* (True), y* (yes), Y* (YES) - return (first == '1' || first == 't' || first == 'T' || first == 'y' || first == 'Y'); - } - - // set value with conversion functions - PUGI__FN bool set_value_buffer(char_t*& dest, uintptr_t& header, uintptr_t header_mask, char (&buf)[128]) - { - #ifdef PUGIXML_WCHAR_MODE - char_t wbuf[128]; - impl::widen_ascii(wbuf, buf); - - return strcpy_insitu(dest, header, header_mask, wbuf); - #else - return strcpy_insitu(dest, header, header_mask, buf); - #endif - } - - PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, int value) - { - char buf[128]; - sprintf(buf, "%d", value); - - return set_value_buffer(dest, header, header_mask, buf); - } - - PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, unsigned int value) - { - char buf[128]; - sprintf(buf, "%u", value); - - return set_value_buffer(dest, header, header_mask, buf); - } - - PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, double value) - { - char buf[128]; - sprintf(buf, "%g", value); - - return set_value_buffer(dest, header, header_mask, buf); - } - - PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, bool value) - { - return strcpy_insitu(dest, header, header_mask, value ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false")); - } - - // we need to get length of entire file to load it in memory; the only (relatively) sane way to do it is via seek/tell trick - PUGI__FN xml_parse_status get_file_size(FILE* file, size_t& out_result) - { - #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE) - // there are 64-bit versions of fseek/ftell, let's use them - typedef __int64 length_type; - - _fseeki64(file, 0, SEEK_END); - length_type length = _ftelli64(file); - _fseeki64(file, 0, SEEK_SET); - #elif defined(__MINGW32__) && !defined(__NO_MINGW_LFS) && !defined(__STRICT_ANSI__) - // there are 64-bit versions of fseek/ftell, let's use them - typedef off64_t length_type; - - fseeko64(file, 0, SEEK_END); - length_type length = ftello64(file); - fseeko64(file, 0, SEEK_SET); - #else - // if this is a 32-bit OS, long is enough; if this is a unix system, long is 64-bit, which is enough; otherwise we can't do anything anyway. - typedef long length_type; - - fseek(file, 0, SEEK_END); - length_type length = ftell(file); - fseek(file, 0, SEEK_SET); - #endif - - // check for I/O errors - if (length < 0) return status_io_error; - - // check for overflow - size_t result = static_cast(length); - - if (static_cast(result) != length) return status_out_of_memory; - - // finalize - out_result = result; - - return status_ok; - } - - PUGI__FN xml_parse_result load_file_impl(xml_document& doc, FILE* file, unsigned int options, xml_encoding encoding) - { - if (!file) return make_parse_result(status_file_not_found); - - // get file size (can result in I/O errors) - size_t size = 0; - xml_parse_status size_status = get_file_size(file, size); - - if (size_status != status_ok) - { - fclose(file); - return make_parse_result(size_status); - } - - // allocate buffer for the whole file - char* contents = static_cast(xml_memory::allocate(size > 0 ? size : 1)); - - if (!contents) - { - fclose(file); - return make_parse_result(status_out_of_memory); - } - - // read file in memory - size_t read_size = fread(contents, 1, size, file); - fclose(file); - - if (read_size != size) - { - xml_memory::deallocate(contents); - return make_parse_result(status_io_error); - } - - return doc.load_buffer_inplace_own(contents, size, options, encoding); - } - -#ifndef PUGIXML_NO_STL - template struct xml_stream_chunk - { - static xml_stream_chunk* create() - { - void* memory = xml_memory::allocate(sizeof(xml_stream_chunk)); - - return new (memory) xml_stream_chunk(); - } - - static void destroy(void* ptr) - { - xml_stream_chunk* chunk = static_cast(ptr); - - // free chunk chain - while (chunk) - { - xml_stream_chunk* next = chunk->next; - xml_memory::deallocate(chunk); - chunk = next; - } - } - - xml_stream_chunk(): next(0), size(0) - { - } - - xml_stream_chunk* next; - size_t size; - - T data[xml_memory_page_size / sizeof(T)]; - }; - - template PUGI__FN xml_parse_status load_stream_data_noseek(std::basic_istream& stream, void** out_buffer, size_t* out_size) - { - buffer_holder chunks(0, xml_stream_chunk::destroy); - - // read file to a chunk list - size_t total = 0; - xml_stream_chunk* last = 0; - - while (!stream.eof()) - { - // allocate new chunk - xml_stream_chunk* chunk = xml_stream_chunk::create(); - if (!chunk) return status_out_of_memory; - - // append chunk to list - if (last) last = last->next = chunk; - else chunks.data = last = chunk; - - // read data to chunk - stream.read(chunk->data, static_cast(sizeof(chunk->data) / sizeof(T))); - chunk->size = static_cast(stream.gcount()) * sizeof(T); - - // read may set failbit | eofbit in case gcount() is less than read length, so check for other I/O errors - if (stream.bad() || (!stream.eof() && stream.fail())) return status_io_error; - - // guard against huge files (chunk size is small enough to make this overflow check work) - if (total + chunk->size < total) return status_out_of_memory; - total += chunk->size; - } - - // copy chunk list to a contiguous buffer - char* buffer = static_cast(xml_memory::allocate(total)); - if (!buffer) return status_out_of_memory; - - char* write = buffer; - - for (xml_stream_chunk* chunk = static_cast*>(chunks.data); chunk; chunk = chunk->next) - { - assert(write + chunk->size <= buffer + total); - memcpy(write, chunk->data, chunk->size); - write += chunk->size; - } - - assert(write == buffer + total); - - // return buffer - *out_buffer = buffer; - *out_size = total; - - return status_ok; - } - - template PUGI__FN xml_parse_status load_stream_data_seek(std::basic_istream& stream, void** out_buffer, size_t* out_size) - { - // get length of remaining data in stream - typename std::basic_istream::pos_type pos = stream.tellg(); - stream.seekg(0, std::ios::end); - std::streamoff length = stream.tellg() - pos; - stream.seekg(pos); - - if (stream.fail() || pos < 0) return status_io_error; - - // guard against huge files - size_t read_length = static_cast(length); - - if (static_cast(read_length) != length || length < 0) return status_out_of_memory; - - // read stream data into memory (guard against stream exceptions with buffer holder) - buffer_holder buffer(xml_memory::allocate((read_length > 0 ? read_length : 1) * sizeof(T)), xml_memory::deallocate); - if (!buffer.data) return status_out_of_memory; - - stream.read(static_cast(buffer.data), static_cast(read_length)); - - // read may set failbit | eofbit in case gcount() is less than read_length (i.e. line ending conversion), so check for other I/O errors - if (stream.bad() || (!stream.eof() && stream.fail())) return status_io_error; - - // return buffer - size_t actual_length = static_cast(stream.gcount()); - assert(actual_length <= read_length); - - *out_buffer = buffer.release(); - *out_size = actual_length * sizeof(T); - - return status_ok; - } - - template PUGI__FN xml_parse_result load_stream_impl(xml_document& doc, std::basic_istream& stream, unsigned int options, xml_encoding encoding) - { - void* buffer = 0; - size_t size = 0; - - // load stream to memory (using seek-based implementation if possible, since it's faster and takes less memory) - xml_parse_status status = (stream.tellg() < 0) ? load_stream_data_noseek(stream, &buffer, &size) : load_stream_data_seek(stream, &buffer, &size); - if (status != status_ok) return make_parse_result(status); - - return doc.load_buffer_inplace_own(buffer, size, options, encoding); - } -#endif - -#if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && !defined(__STRICT_ANSI__)) - PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) - { - return _wfopen(path, mode); - } -#else - PUGI__FN char* convert_path_heap(const wchar_t* str) - { - assert(str); - - // first pass: get length in utf8 characters - size_t length = wcslen(str); - size_t size = as_utf8_begin(str, length); - - // allocate resulting string - char* result = static_cast(xml_memory::allocate(size + 1)); - if (!result) return 0; - - // second pass: convert to utf8 - as_utf8_end(result, size, str, length); - - return result; - } - - PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) - { - // there is no standard function to open wide paths, so our best bet is to try utf8 path - char* path_utf8 = convert_path_heap(path); - if (!path_utf8) return 0; - - // convert mode to ASCII (we mirror _wfopen interface) - char mode_ascii[4] = {0}; - for (size_t i = 0; mode[i]; ++i) mode_ascii[i] = static_cast(mode[i]); - - // try to open the utf8 path - FILE* result = fopen(path_utf8, mode_ascii); - - // free dummy buffer - xml_memory::deallocate(path_utf8); - - return result; - } -#endif - - PUGI__FN bool save_file_impl(const xml_document& doc, FILE* file, const char_t* indent, unsigned int flags, xml_encoding encoding) - { - if (!file) return false; - - xml_writer_file writer(file); - doc.save(writer, indent, flags, encoding); - - int result = ferror(file); - - fclose(file); - - return result == 0; - } -PUGI__NS_END - -OIIO_NAMESPACE_BEGIN -namespace pugi -{ - PUGI__FN xml_writer_file::xml_writer_file(void* file_): file(file_) - { - } - - PUGI__FN void xml_writer_file::write(const void* data, size_t size) - { - size_t result = fwrite(data, 1, size, static_cast(file)); - (void)!result; // unfortunately we can't do proper error handling here - } - -#ifndef PUGIXML_NO_STL - PUGI__FN xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(&stream), wide_stream(0) - { - } - - PUGI__FN xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(0), wide_stream(&stream) - { - } - - PUGI__FN void xml_writer_stream::write(const void* data, size_t size) - { - if (narrow_stream) - { - assert(!wide_stream); - narrow_stream->write(reinterpret_cast(data), static_cast(size)); - } - else - { - assert(wide_stream); - assert(size % sizeof(wchar_t) == 0); - - wide_stream->write(reinterpret_cast(data), static_cast(size / sizeof(wchar_t))); - } - } -#endif - - PUGI__FN xml_tree_walker::xml_tree_walker(): _depth(0) - { - } - - PUGI__FN xml_tree_walker::~xml_tree_walker() - { - } - - PUGI__FN int xml_tree_walker::depth() const - { - return _depth; - } - - PUGI__FN bool xml_tree_walker::begin(xml_node&) - { - return true; - } - - PUGI__FN bool xml_tree_walker::end(xml_node&) - { - return true; - } - - PUGI__FN xml_attribute::xml_attribute(): _attr(0) - { - } - - PUGI__FN xml_attribute::xml_attribute(xml_attribute_struct* attr): _attr(attr) - { - } - - PUGI__FN static void unspecified_bool_xml_attribute(xml_attribute***) - { - } - - PUGI__FN xml_attribute::operator xml_attribute::unspecified_bool_type() const - { - return _attr ? unspecified_bool_xml_attribute : 0; - } - - PUGI__FN bool xml_attribute::operator!() const - { - return !_attr; - } - - PUGI__FN bool xml_attribute::operator==(const xml_attribute& r) const - { - return (_attr == r._attr); - } - - PUGI__FN bool xml_attribute::operator!=(const xml_attribute& r) const - { - return (_attr != r._attr); - } - - PUGI__FN bool xml_attribute::operator<(const xml_attribute& r) const - { - return (_attr < r._attr); - } - - PUGI__FN bool xml_attribute::operator>(const xml_attribute& r) const - { - return (_attr > r._attr); - } - - PUGI__FN bool xml_attribute::operator<=(const xml_attribute& r) const - { - return (_attr <= r._attr); - } - - PUGI__FN bool xml_attribute::operator>=(const xml_attribute& r) const - { - return (_attr >= r._attr); - } - - PUGI__FN xml_attribute xml_attribute::next_attribute() const - { - return _attr ? xml_attribute(_attr->next_attribute) : xml_attribute(); - } - - PUGI__FN xml_attribute xml_attribute::previous_attribute() const - { - return _attr && _attr->prev_attribute_c->next_attribute ? xml_attribute(_attr->prev_attribute_c) : xml_attribute(); - } - - PUGI__FN const char_t* xml_attribute::as_string(const char_t* def) const - { - return (_attr && _attr->value) ? _attr->value : def; - } - - PUGI__FN int xml_attribute::as_int(int def) const - { - return impl::get_value_int(_attr ? _attr->value : 0, def); - } - - PUGI__FN unsigned int xml_attribute::as_uint(unsigned int def) const - { - return impl::get_value_uint(_attr ? _attr->value : 0, def); - } - - PUGI__FN double xml_attribute::as_double(double def) const - { - return impl::get_value_double(_attr ? _attr->value : 0, def); - } - - PUGI__FN float xml_attribute::as_float(float def) const - { - return impl::get_value_float(_attr ? _attr->value : 0, def); - } - - PUGI__FN bool xml_attribute::as_bool(bool def) const - { - return impl::get_value_bool(_attr ? _attr->value : 0, def); - } - - PUGI__FN bool xml_attribute::empty() const - { - return !_attr; - } - - PUGI__FN const char_t* xml_attribute::name() const - { - return (_attr && _attr->name) ? _attr->name : PUGIXML_TEXT(""); - } - - PUGI__FN const char_t* xml_attribute::value() const - { - return (_attr && _attr->value) ? _attr->value : PUGIXML_TEXT(""); - } - - PUGI__FN size_t xml_attribute::hash_value() const - { - return static_cast(reinterpret_cast(_attr) / sizeof(xml_attribute_struct)); - } - - PUGI__FN xml_attribute_struct* xml_attribute::internal_object() const - { - return _attr; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(const char_t* rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(int rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(unsigned int rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(double rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(bool rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN bool xml_attribute::set_name(const char_t* rhs) - { - if (!_attr) return false; - - return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs); - } - - PUGI__FN bool xml_attribute::set_value(const char_t* rhs) - { - if (!_attr) return false; - - return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); - } - - PUGI__FN bool xml_attribute::set_value(int rhs) - { - if (!_attr) return false; - - return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); - } - - PUGI__FN bool xml_attribute::set_value(unsigned int rhs) - { - if (!_attr) return false; - - return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); - } - - PUGI__FN bool xml_attribute::set_value(double rhs) - { - if (!_attr) return false; - - return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); - } - - PUGI__FN bool xml_attribute::set_value(bool rhs) - { - if (!_attr) return false; - - return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); - } - -#ifdef __BORLANDC__ - PUGI__FN bool operator&&(const xml_attribute& lhs, bool rhs) - { - return (bool)lhs && rhs; - } - - PUGI__FN bool operator||(const xml_attribute& lhs, bool rhs) - { - return (bool)lhs || rhs; - } -#endif - - PUGI__FN xml_node::xml_node(): _root(0) - { - } - - PUGI__FN xml_node::xml_node(xml_node_struct* p): _root(p) - { - } - - PUGI__FN static void unspecified_bool_xml_node(xml_node***) - { - } - - PUGI__FN xml_node::operator xml_node::unspecified_bool_type() const - { - return _root ? unspecified_bool_xml_node : 0; - } - - PUGI__FN bool xml_node::operator!() const - { - return !_root; - } - - PUGI__FN xml_node::iterator xml_node::begin() const - { - return iterator(_root ? _root->first_child : 0, _root); - } - - PUGI__FN xml_node::iterator xml_node::end() const - { - return iterator(0, _root); - } - - PUGI__FN xml_node::attribute_iterator xml_node::attributes_begin() const - { - return attribute_iterator(_root ? _root->first_attribute : 0, _root); - } - - PUGI__FN xml_node::attribute_iterator xml_node::attributes_end() const - { - return attribute_iterator(0, _root); - } - - PUGI__FN xml_object_range xml_node::children() const - { - return xml_object_range(begin(), end()); - } - - PUGI__FN xml_object_range xml_node::children(const char_t* name_) const - { - return xml_object_range(xml_named_node_iterator(child(name_), name_), xml_named_node_iterator()); - } - - PUGI__FN xml_object_range xml_node::attributes() const - { - return xml_object_range(attributes_begin(), attributes_end()); - } - - PUGI__FN bool xml_node::operator==(const xml_node& r) const - { - return (_root == r._root); - } - - PUGI__FN bool xml_node::operator!=(const xml_node& r) const - { - return (_root != r._root); - } - - PUGI__FN bool xml_node::operator<(const xml_node& r) const - { - return (_root < r._root); - } - - PUGI__FN bool xml_node::operator>(const xml_node& r) const - { - return (_root > r._root); - } - - PUGI__FN bool xml_node::operator<=(const xml_node& r) const - { - return (_root <= r._root); - } - - PUGI__FN bool xml_node::operator>=(const xml_node& r) const - { - return (_root >= r._root); - } - - PUGI__FN bool xml_node::empty() const - { - return !_root; - } - - PUGI__FN const char_t* xml_node::name() const - { - return (_root && _root->name) ? _root->name : PUGIXML_TEXT(""); - } - - PUGI__FN xml_node_type xml_node::type() const - { - return _root ? static_cast((_root->header & impl::xml_memory_page_type_mask) + 1) : node_null; - } - - PUGI__FN const char_t* xml_node::value() const - { - return (_root && _root->value) ? _root->value : PUGIXML_TEXT(""); - } - - PUGI__FN xml_node xml_node::child(const char_t* name_) const - { - if (!_root) return xml_node(); - - for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); - - return xml_node(); - } - - PUGI__FN xml_attribute xml_node::attribute(const char_t* name_) const - { - if (!_root) return xml_attribute(); - - for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute) - if (i->name && impl::strequal(name_, i->name)) - return xml_attribute(i); - - return xml_attribute(); - } - - PUGI__FN xml_node xml_node::next_sibling(const char_t* name_) const - { - if (!_root) return xml_node(); - - for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); - - return xml_node(); - } - - PUGI__FN xml_node xml_node::next_sibling() const - { - if (!_root) return xml_node(); - - if (_root->next_sibling) return xml_node(_root->next_sibling); - else return xml_node(); - } - - PUGI__FN xml_node xml_node::previous_sibling(const char_t* name_) const - { - if (!_root) return xml_node(); - - for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); - - return xml_node(); - } - - PUGI__FN xml_node xml_node::previous_sibling() const - { - if (!_root) return xml_node(); - - if (_root->prev_sibling_c->next_sibling) return xml_node(_root->prev_sibling_c); - else return xml_node(); - } - - PUGI__FN xml_node xml_node::parent() const - { - return _root ? xml_node(_root->parent) : xml_node(); - } - - PUGI__FN xml_node xml_node::root() const - { - if (!_root) return xml_node(); - - impl::xml_memory_page* page = reinterpret_cast(_root->header & impl::xml_memory_page_pointer_mask); - - return xml_node(static_cast(page->allocator)); - } - - PUGI__FN xml_text xml_node::text() const - { - return xml_text(_root); - } - - PUGI__FN const char_t* xml_node::child_value() const - { - if (!_root) return PUGIXML_TEXT(""); - - for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (i->value && impl::is_text_node(i)) - return i->value; - - return PUGIXML_TEXT(""); - } - - PUGI__FN const char_t* xml_node::child_value(const char_t* name_) const - { - return child(name_).child_value(); - } - - PUGI__FN xml_attribute xml_node::first_attribute() const - { - return _root ? xml_attribute(_root->first_attribute) : xml_attribute(); - } - - PUGI__FN xml_attribute xml_node::last_attribute() const - { - return _root && _root->first_attribute ? xml_attribute(_root->first_attribute->prev_attribute_c) : xml_attribute(); - } - - PUGI__FN xml_node xml_node::first_child() const - { - return _root ? xml_node(_root->first_child) : xml_node(); - } - - PUGI__FN xml_node xml_node::last_child() const - { - return _root && _root->first_child ? xml_node(_root->first_child->prev_sibling_c) : xml_node(); - } - - PUGI__FN bool xml_node::set_name(const char_t* rhs) - { - switch (type()) - { - case node_pi: - case node_declaration: - case node_element: - return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs); - - default: - return false; - } - } - - PUGI__FN bool xml_node::set_value(const char_t* rhs) - { - switch (type()) - { - case node_pi: - case node_cdata: - case node_pcdata: - case node_comment: - case node_doctype: - return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs); - - default: - return false; - } - } - - PUGI__FN xml_attribute xml_node::append_attribute(const char_t* name_) - { - if (type() != node_element && type() != node_declaration) return xml_attribute(); - - xml_attribute a(impl::append_attribute_ll(_root, impl::get_allocator(_root))); - a.set_name(name_); - - return a; - } - - PUGI__FN xml_attribute xml_node::prepend_attribute(const char_t* name_) - { - if (type() != node_element && type() != node_declaration) return xml_attribute(); - - xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); - if (!a) return xml_attribute(); - - a.set_name(name_); - - xml_attribute_struct* head = _root->first_attribute; - - if (head) - { - a._attr->prev_attribute_c = head->prev_attribute_c; - head->prev_attribute_c = a._attr; - } - else - a._attr->prev_attribute_c = a._attr; - - a._attr->next_attribute = head; - _root->first_attribute = a._attr; - - return a; - } - - PUGI__FN xml_attribute xml_node::insert_attribute_before(const char_t* name_, const xml_attribute& attr) - { - if ((type() != node_element && type() != node_declaration) || attr.empty()) return xml_attribute(); - - // check that attribute belongs to *this - xml_attribute_struct* cur = attr._attr; - - while (cur->prev_attribute_c->next_attribute) cur = cur->prev_attribute_c; - - if (cur != _root->first_attribute) return xml_attribute(); - - xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); - if (!a) return xml_attribute(); - - a.set_name(name_); - - if (attr._attr->prev_attribute_c->next_attribute) - attr._attr->prev_attribute_c->next_attribute = a._attr; - else - _root->first_attribute = a._attr; - - a._attr->prev_attribute_c = attr._attr->prev_attribute_c; - a._attr->next_attribute = attr._attr; - attr._attr->prev_attribute_c = a._attr; - - return a; - } - - PUGI__FN xml_attribute xml_node::insert_attribute_after(const char_t* name_, const xml_attribute& attr) - { - if ((type() != node_element && type() != node_declaration) || attr.empty()) return xml_attribute(); - - // check that attribute belongs to *this - xml_attribute_struct* cur = attr._attr; - - while (cur->prev_attribute_c->next_attribute) cur = cur->prev_attribute_c; - - if (cur != _root->first_attribute) return xml_attribute(); - - xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); - if (!a) return xml_attribute(); - - a.set_name(name_); - - if (attr._attr->next_attribute) - attr._attr->next_attribute->prev_attribute_c = a._attr; - else - _root->first_attribute->prev_attribute_c = a._attr; - - a._attr->next_attribute = attr._attr->next_attribute; - a._attr->prev_attribute_c = attr._attr; - attr._attr->next_attribute = a._attr; - - return a; - } - - PUGI__FN xml_attribute xml_node::append_copy(const xml_attribute& proto) - { - if (!proto) return xml_attribute(); - - xml_attribute result = append_attribute(proto.name()); - result.set_value(proto.value()); - - return result; - } - - PUGI__FN xml_attribute xml_node::prepend_copy(const xml_attribute& proto) - { - if (!proto) return xml_attribute(); - - xml_attribute result = prepend_attribute(proto.name()); - result.set_value(proto.value()); - - return result; - } - - PUGI__FN xml_attribute xml_node::insert_copy_after(const xml_attribute& proto, const xml_attribute& attr) - { - if (!proto) return xml_attribute(); - - xml_attribute result = insert_attribute_after(proto.name(), attr); - result.set_value(proto.value()); - - return result; - } - - PUGI__FN xml_attribute xml_node::insert_copy_before(const xml_attribute& proto, const xml_attribute& attr) - { - if (!proto) return xml_attribute(); - - xml_attribute result = insert_attribute_before(proto.name(), attr); - result.set_value(proto.value()); - - return result; - } - - PUGI__FN xml_node xml_node::append_child(xml_node_type type_) - { - if (!impl::allow_insert_child(this->type(), type_)) return xml_node(); - - xml_node n(impl::append_node(_root, impl::get_allocator(_root), type_)); - - if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); - - return n; - } - - PUGI__FN xml_node xml_node::prepend_child(xml_node_type type_) - { - if (!impl::allow_insert_child(this->type(), type_)) return xml_node(); - - xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); - if (!n) return xml_node(); - - n._root->parent = _root; - - xml_node_struct* head = _root->first_child; - - if (head) - { - n._root->prev_sibling_c = head->prev_sibling_c; - head->prev_sibling_c = n._root; - } - else - n._root->prev_sibling_c = n._root; - - n._root->next_sibling = head; - _root->first_child = n._root; - - if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); - - return n; - } - - PUGI__FN xml_node xml_node::insert_child_before(xml_node_type type_, const xml_node& node) - { - if (!impl::allow_insert_child(this->type(), type_)) return xml_node(); - if (!node._root || node._root->parent != _root) return xml_node(); - - xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); - if (!n) return xml_node(); - - n._root->parent = _root; - - if (node._root->prev_sibling_c->next_sibling) - node._root->prev_sibling_c->next_sibling = n._root; - else - _root->first_child = n._root; - - n._root->prev_sibling_c = node._root->prev_sibling_c; - n._root->next_sibling = node._root; - node._root->prev_sibling_c = n._root; - - if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); - - return n; - } - - PUGI__FN xml_node xml_node::insert_child_after(xml_node_type type_, const xml_node& node) - { - if (!impl::allow_insert_child(this->type(), type_)) return xml_node(); - if (!node._root || node._root->parent != _root) return xml_node(); - - xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); - if (!n) return xml_node(); - - n._root->parent = _root; - - if (node._root->next_sibling) - node._root->next_sibling->prev_sibling_c = n._root; - else - _root->first_child->prev_sibling_c = n._root; - - n._root->next_sibling = node._root->next_sibling; - n._root->prev_sibling_c = node._root; - node._root->next_sibling = n._root; - - if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); - - return n; - } - - PUGI__FN xml_node xml_node::append_child(const char_t* name_) - { - xml_node result = append_child(node_element); - - result.set_name(name_); - - return result; - } - - PUGI__FN xml_node xml_node::prepend_child(const char_t* name_) - { - xml_node result = prepend_child(node_element); - - result.set_name(name_); - - return result; - } - - PUGI__FN xml_node xml_node::insert_child_after(const char_t* name_, const xml_node& node) - { - xml_node result = insert_child_after(node_element, node); - - result.set_name(name_); - - return result; - } - - PUGI__FN xml_node xml_node::insert_child_before(const char_t* name_, const xml_node& node) - { - xml_node result = insert_child_before(node_element, node); - - result.set_name(name_); - - return result; - } - - PUGI__FN xml_node xml_node::append_copy(const xml_node& proto) - { - xml_node result = append_child(proto.type()); - - if (result) impl::recursive_copy_skip(result, proto, result); - - return result; - } - - PUGI__FN xml_node xml_node::prepend_copy(const xml_node& proto) - { - xml_node result = prepend_child(proto.type()); - - if (result) impl::recursive_copy_skip(result, proto, result); - - return result; - } - - PUGI__FN xml_node xml_node::insert_copy_after(const xml_node& proto, const xml_node& node) - { - xml_node result = insert_child_after(proto.type(), node); - - if (result) impl::recursive_copy_skip(result, proto, result); - - return result; - } - - PUGI__FN xml_node xml_node::insert_copy_before(const xml_node& proto, const xml_node& node) - { - xml_node result = insert_child_before(proto.type(), node); - - if (result) impl::recursive_copy_skip(result, proto, result); - - return result; - } - - PUGI__FN bool xml_node::remove_attribute(const char_t* name_) - { - return remove_attribute(attribute(name_)); - } - - PUGI__FN bool xml_node::remove_attribute(const xml_attribute& a) - { - if (!_root || !a._attr) return false; - - // check that attribute belongs to *this - xml_attribute_struct* attr = a._attr; - - while (attr->prev_attribute_c->next_attribute) attr = attr->prev_attribute_c; - - if (attr != _root->first_attribute) return false; - - if (a._attr->next_attribute) a._attr->next_attribute->prev_attribute_c = a._attr->prev_attribute_c; - else if (_root->first_attribute) _root->first_attribute->prev_attribute_c = a._attr->prev_attribute_c; - - if (a._attr->prev_attribute_c->next_attribute) a._attr->prev_attribute_c->next_attribute = a._attr->next_attribute; - else _root->first_attribute = a._attr->next_attribute; - - impl::destroy_attribute(a._attr, impl::get_allocator(_root)); - - return true; - } - - PUGI__FN bool xml_node::remove_child(const char_t* name_) - { - return remove_child(child(name_)); - } - - PUGI__FN bool xml_node::remove_child(const xml_node& n) - { - if (!_root || !n._root || n._root->parent != _root) return false; - - if (n._root->next_sibling) n._root->next_sibling->prev_sibling_c = n._root->prev_sibling_c; - else if (_root->first_child) _root->first_child->prev_sibling_c = n._root->prev_sibling_c; - - if (n._root->prev_sibling_c->next_sibling) n._root->prev_sibling_c->next_sibling = n._root->next_sibling; - else _root->first_child = n._root->next_sibling; - - impl::destroy_node(n._root, impl::get_allocator(_root)); - - return true; - } - - PUGI__FN xml_node xml_node::find_child_by_attribute(const char_t* name_, const char_t* attr_name, const char_t* attr_value) const - { - if (!_root) return xml_node(); - - for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) - { - for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) - if (impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value)) - return xml_node(i); - } - - return xml_node(); - } - - PUGI__FN xml_node xml_node::find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const - { - if (!_root) return xml_node(); - - for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) - if (impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value)) - return xml_node(i); - - return xml_node(); - } - -#ifndef PUGIXML_NO_STL - PUGI__FN string_t xml_node::path(char_t delimiter) const - { - xml_node cursor = *this; // Make a copy. - - string_t result = cursor.name(); - - while (cursor.parent()) - { - cursor = cursor.parent(); - - string_t temp = cursor.name(); - temp += delimiter; - temp += result; - result.swap(temp); - } - - return result; - } -#endif - - PUGI__FN xml_node xml_node::first_element_by_path(const char_t* path_, char_t delimiter) const - { - xml_node found = *this; // Current search context. - - if (!_root || !path_ || !path_[0]) return found; - - if (path_[0] == delimiter) - { - // Absolute path; e.g. '/foo/bar' - found = found.root(); - ++path_; - } - - const char_t* path_segment = path_; - - while (*path_segment == delimiter) ++path_segment; - - const char_t* path_segment_end = path_segment; - - while (*path_segment_end && *path_segment_end != delimiter) ++path_segment_end; - - if (path_segment == path_segment_end) return found; - - const char_t* next_segment = path_segment_end; - - while (*next_segment == delimiter) ++next_segment; - - if (*path_segment == '.' && path_segment + 1 == path_segment_end) - return found.first_element_by_path(next_segment, delimiter); - else if (*path_segment == '.' && *(path_segment+1) == '.' && path_segment + 2 == path_segment_end) - return found.parent().first_element_by_path(next_segment, delimiter); - else - { - for (xml_node_struct* j = found._root->first_child; j; j = j->next_sibling) - { - if (j->name && impl::strequalrange(j->name, path_segment, static_cast(path_segment_end - path_segment))) - { - xml_node subsearch = xml_node(j).first_element_by_path(next_segment, delimiter); - - if (subsearch) return subsearch; - } - } - - return xml_node(); - } - } - - PUGI__FN bool xml_node::traverse(xml_tree_walker& walker) - { - walker._depth = -1; - - xml_node arg_begin = *this; - if (!walker.begin(arg_begin)) return false; - - xml_node cur = first_child(); - - if (cur) - { - ++walker._depth; - - do - { - xml_node arg_for_each = cur; - if (!walker.for_each(arg_for_each)) - return false; - - if (cur.first_child()) - { - ++walker._depth; - cur = cur.first_child(); - } - else if (cur.next_sibling()) - cur = cur.next_sibling(); - else - { - // Borland C++ workaround - while (!cur.next_sibling() && cur != *this && !cur.parent().empty()) - { - --walker._depth; - cur = cur.parent(); - } - - if (cur != *this) - cur = cur.next_sibling(); - } - } - while (cur && cur != *this); - } - - assert(walker._depth == -1); - - xml_node arg_end = *this; - return walker.end(arg_end); - } - - PUGI__FN size_t xml_node::hash_value() const - { - return static_cast(reinterpret_cast(_root) / sizeof(xml_node_struct)); - } - - PUGI__FN xml_node_struct* xml_node::internal_object() const - { - return _root; - } - - PUGI__FN void xml_node::print(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const - { - if (!_root) return; - - impl::xml_buffered_writer buffered_writer(writer, encoding); - - impl::node_output(buffered_writer, *this, indent, flags, depth); - } - -#ifndef PUGIXML_NO_STL - PUGI__FN void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const - { - xml_writer_stream writer(stream); - - print(writer, indent, flags, encoding, depth); - } - - PUGI__FN void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, unsigned int depth) const - { - xml_writer_stream writer(stream); - - print(writer, indent, flags, encoding_wchar, depth); - } -#endif - - PUGI__FN ptrdiff_t xml_node::offset_debug() const - { - xml_node_struct* r = root()._root; - - if (!r) return -1; - - const char_t* buffer = static_cast(r)->buffer; - - if (!buffer) return -1; - - switch (type()) - { - case node_document: - return 0; - - case node_element: - case node_declaration: - case node_pi: - return (_root->header & impl::xml_memory_page_name_allocated_mask) ? -1 : _root->name - buffer; - - case node_pcdata: - case node_cdata: - case node_comment: - case node_doctype: - return (_root->header & impl::xml_memory_page_value_allocated_mask) ? -1 : _root->value - buffer; - - default: - return -1; - } - } - -#ifdef __BORLANDC__ - PUGI__FN bool operator&&(const xml_node& lhs, bool rhs) - { - return (bool)lhs && rhs; - } - - PUGI__FN bool operator||(const xml_node& lhs, bool rhs) - { - return (bool)lhs || rhs; - } -#endif - - PUGI__FN xml_text::xml_text(xml_node_struct* root): _root(root) - { - } - - PUGI__FN xml_node_struct* xml_text::_data() const - { - if (!_root || impl::is_text_node(_root)) return _root; - - for (xml_node_struct* node = _root->first_child; node; node = node->next_sibling) - if (impl::is_text_node(node)) - return node; - - return 0; - } - - PUGI__FN xml_node_struct* xml_text::_data_new() - { - xml_node_struct* d = _data(); - if (d) return d; - - return xml_node(_root).append_child(node_pcdata).internal_object(); - } - - PUGI__FN xml_text::xml_text(): _root(0) - { - } - - PUGI__FN static void unspecified_bool_xml_text(xml_text***) - { - } - - PUGI__FN xml_text::operator xml_text::unspecified_bool_type() const - { - return _data() ? unspecified_bool_xml_text : 0; - } - - PUGI__FN bool xml_text::operator!() const - { - return !_data(); - } - - PUGI__FN bool xml_text::empty() const - { - return _data() == 0; - } - - PUGI__FN const char_t* xml_text::get() const - { - xml_node_struct* d = _data(); - - return (d && d->value) ? d->value : PUGIXML_TEXT(""); - } - - PUGI__FN const char_t* xml_text::as_string(const char_t* def) const - { - xml_node_struct* d = _data(); - - return (d && d->value) ? d->value : def; - } - - PUGI__FN int xml_text::as_int(int def) const - { - xml_node_struct* d = _data(); - - return impl::get_value_int(d ? d->value : 0, def); - } - - PUGI__FN unsigned int xml_text::as_uint(unsigned int def) const - { - xml_node_struct* d = _data(); - - return impl::get_value_uint(d ? d->value : 0, def); - } - - PUGI__FN double xml_text::as_double(double def) const - { - xml_node_struct* d = _data(); - - return impl::get_value_double(d ? d->value : 0, def); - } - - PUGI__FN float xml_text::as_float(float def) const - { - xml_node_struct* d = _data(); - - return impl::get_value_float(d ? d->value : 0, def); - } - - PUGI__FN bool xml_text::as_bool(bool def) const - { - xml_node_struct* d = _data(); - - return impl::get_value_bool(d ? d->value : 0, def); - } - - PUGI__FN bool xml_text::set(const char_t* rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; - } - - PUGI__FN bool xml_text::set(int rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; - } - - PUGI__FN bool xml_text::set(unsigned int rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; - } - - PUGI__FN bool xml_text::set(double rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; - } - - PUGI__FN bool xml_text::set(bool rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; - } - - PUGI__FN xml_text& xml_text::operator=(const char_t* rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(int rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(unsigned int rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(double rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(bool rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_node xml_text::data() const - { - return xml_node(_data()); - } - -#ifdef __BORLANDC__ - PUGI__FN bool operator&&(const xml_text& lhs, bool rhs) - { - return (bool)lhs && rhs; - } - - PUGI__FN bool operator||(const xml_text& lhs, bool rhs) - { - return (bool)lhs || rhs; - } -#endif - - PUGI__FN xml_node_iterator::xml_node_iterator() - { - } - - PUGI__FN xml_node_iterator::xml_node_iterator(const xml_node& node): _wrap(node), _parent(node.parent()) - { - } - - PUGI__FN xml_node_iterator::xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent) - { - } - - PUGI__FN bool xml_node_iterator::operator==(const xml_node_iterator& rhs) const - { - return _wrap._root == rhs._wrap._root && _parent._root == rhs._parent._root; - } - - PUGI__FN bool xml_node_iterator::operator!=(const xml_node_iterator& rhs) const - { - return _wrap._root != rhs._wrap._root || _parent._root != rhs._parent._root; - } - - PUGI__FN xml_node& xml_node_iterator::operator*() const - { - assert(_wrap._root); - return _wrap; - } - - PUGI__FN xml_node* xml_node_iterator::operator->() const - { - assert(_wrap._root); - return const_cast(&_wrap); // BCC32 workaround - } - - PUGI__FN const xml_node_iterator& xml_node_iterator::operator++() - { - assert(_wrap._root); - _wrap._root = _wrap._root->next_sibling; - return *this; - } - - PUGI__FN xml_node_iterator xml_node_iterator::operator++(int) - { - xml_node_iterator temp = *this; - ++*this; - return temp; - } - - PUGI__FN const xml_node_iterator& xml_node_iterator::operator--() - { - _wrap = _wrap._root ? _wrap.previous_sibling() : _parent.last_child(); - return *this; - } - - PUGI__FN xml_node_iterator xml_node_iterator::operator--(int) - { - xml_node_iterator temp = *this; - --*this; - return temp; - } - - PUGI__FN xml_attribute_iterator::xml_attribute_iterator() - { - } - - PUGI__FN xml_attribute_iterator::xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent): _wrap(attr), _parent(parent) - { - } - - PUGI__FN xml_attribute_iterator::xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent) - { - } - - PUGI__FN bool xml_attribute_iterator::operator==(const xml_attribute_iterator& rhs) const - { - return _wrap._attr == rhs._wrap._attr && _parent._root == rhs._parent._root; - } - - PUGI__FN bool xml_attribute_iterator::operator!=(const xml_attribute_iterator& rhs) const - { - return _wrap._attr != rhs._wrap._attr || _parent._root != rhs._parent._root; - } - - PUGI__FN xml_attribute& xml_attribute_iterator::operator*() const - { - assert(_wrap._attr); - return _wrap; - } - - PUGI__FN xml_attribute* xml_attribute_iterator::operator->() const - { - assert(_wrap._attr); - return const_cast(&_wrap); // BCC32 workaround - } - - PUGI__FN const xml_attribute_iterator& xml_attribute_iterator::operator++() - { - assert(_wrap._attr); - _wrap._attr = _wrap._attr->next_attribute; - return *this; - } - - PUGI__FN xml_attribute_iterator xml_attribute_iterator::operator++(int) - { - xml_attribute_iterator temp = *this; - ++*this; - return temp; - } - - PUGI__FN const xml_attribute_iterator& xml_attribute_iterator::operator--() - { - _wrap = _wrap._attr ? _wrap.previous_attribute() : _parent.last_attribute(); - return *this; - } - - PUGI__FN xml_attribute_iterator xml_attribute_iterator::operator--(int) - { - xml_attribute_iterator temp = *this; - --*this; - return temp; - } - - PUGI__FN xml_named_node_iterator::xml_named_node_iterator(): _name(0) - { - } - - PUGI__FN xml_named_node_iterator::xml_named_node_iterator(const xml_node& node, const char_t* name): _node(node), _name(name) - { - } - - PUGI__FN bool xml_named_node_iterator::operator==(const xml_named_node_iterator& rhs) const - { - return _node == rhs._node; - } - - PUGI__FN bool xml_named_node_iterator::operator!=(const xml_named_node_iterator& rhs) const - { - return _node != rhs._node; - } - - PUGI__FN xml_node& xml_named_node_iterator::operator*() const - { - assert(_node._root); - return _node; - } - - PUGI__FN xml_node* xml_named_node_iterator::operator->() const - { - assert(_node._root); - return const_cast(&_node); // BCC32 workaround - } - - PUGI__FN const xml_named_node_iterator& xml_named_node_iterator::operator++() - { - assert(_node._root); - _node = _node.next_sibling(_name); - return *this; - } - - PUGI__FN xml_named_node_iterator xml_named_node_iterator::operator++(int) - { - xml_named_node_iterator temp = *this; - ++*this; - return temp; - } - - PUGI__FN xml_parse_result::xml_parse_result(): status(status_internal_error), offset(0), encoding(encoding_auto) - { - } - - PUGI__FN xml_parse_result::operator bool() const - { - return status == status_ok; - } - - PUGI__FN const char* xml_parse_result::description() const - { - switch (status) - { - case status_ok: return "No error"; - - case status_file_not_found: return "File was not found"; - case status_io_error: return "Error reading from file/stream"; - case status_out_of_memory: return "Could not allocate memory"; - case status_internal_error: return "Internal error occurred"; - - case status_unrecognized_tag: return "Could not determine tag type"; - - case status_bad_pi: return "Error parsing document declaration/processing instruction"; - case status_bad_comment: return "Error parsing comment"; - case status_bad_cdata: return "Error parsing CDATA section"; - case status_bad_doctype: return "Error parsing document type declaration"; - case status_bad_pcdata: return "Error parsing PCDATA section"; - case status_bad_start_element: return "Error parsing start element tag"; - case status_bad_attribute: return "Error parsing element attribute"; - case status_bad_end_element: return "Error parsing end element tag"; - case status_end_element_mismatch: return "Start-end tags mismatch"; - - default: return "Unknown error"; - } - } - - PUGI__FN xml_document::xml_document(): _buffer(0) - { - create(); - } - - PUGI__FN xml_document::~xml_document() - { - destroy(); - } - - PUGI__FN void xml_document::reset() - { - destroy(); - create(); - } - - PUGI__FN void xml_document::reset(const xml_document& proto) - { - reset(); - - for (xml_node cur = proto.first_child(); cur; cur = cur.next_sibling()) - append_copy(cur); - } - - PUGI__FN void xml_document::create() - { - // initialize sentinel page - PUGI__STATIC_ASSERT(offsetof(impl::xml_memory_page, data) + sizeof(impl::xml_document_struct) + impl::xml_memory_page_alignment <= sizeof(_memory)); - - // align upwards to page boundary - void* page_memory = reinterpret_cast((reinterpret_cast(_memory) + (impl::xml_memory_page_alignment - 1)) & ~(impl::xml_memory_page_alignment - 1)); - - // prepare page structure - impl::xml_memory_page* page = impl::xml_memory_page::construct(page_memory); - - page->busy_size = impl::xml_memory_page_size; - - // allocate new root - _root = new (page->data) impl::xml_document_struct(page); - _root->prev_sibling_c = _root; - - // setup sentinel page - page->allocator = static_cast(_root); - } - - PUGI__FN void xml_document::destroy() - { - // destroy static storage - if (_buffer) - { - impl::xml_memory::deallocate(_buffer); - _buffer = 0; - } - - // destroy dynamic storage, leave sentinel page (it's in static memory) - if (_root) - { - impl::xml_memory_page* root_page = reinterpret_cast(_root->header & impl::xml_memory_page_pointer_mask); - assert(root_page && !root_page->prev && !root_page->memory); - - // destroy all pages - for (impl::xml_memory_page* page = root_page->next; page; ) - { - impl::xml_memory_page* next = page->next; - - impl::xml_allocator::deallocate_page(page); - - page = next; - } - - // cleanup root page - root_page->allocator = 0; - root_page->next = 0; - root_page->busy_size = root_page->freed_size = 0; - - _root = 0; - } - } - -#ifndef PUGIXML_NO_STL - PUGI__FN xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options, xml_encoding encoding) - { - reset(); - - return impl::load_stream_impl(*this, stream, options, encoding); - } - - PUGI__FN xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options) - { - reset(); - - return impl::load_stream_impl(*this, stream, options, encoding_wchar); - } -#endif - - PUGI__FN xml_parse_result xml_document::load(const char_t* contents, unsigned int options) - { - // Force native encoding (skip autodetection) - #ifdef PUGIXML_WCHAR_MODE - xml_encoding encoding = encoding_wchar; - #else - xml_encoding encoding = encoding_utf8; - #endif - - return load_buffer(contents, impl::strlength(contents) * sizeof(char_t), options, encoding); - } - - PUGI__FN xml_parse_result xml_document::load_file(const char* path_, unsigned int options, xml_encoding encoding) - { - reset(); - - FILE* file = fopen(path_, "rb"); - - return impl::load_file_impl(*this, file, options, encoding); - } - - PUGI__FN xml_parse_result xml_document::load_file(const wchar_t* path_, unsigned int options, xml_encoding encoding) - { - reset(); - - FILE* file = impl::open_file_wide(path_, L"rb"); - - return impl::load_file_impl(*this, file, options, encoding); - } - - PUGI__FN xml_parse_result xml_document::load_buffer_impl(void* contents, size_t size, unsigned int options, xml_encoding encoding, bool is_mutable, bool own) - { - reset(); - - // check input buffer - assert(contents || size == 0); - - // get actual encoding - xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size); - - // get private buffer - char_t* buffer = 0; - size_t length = 0; - - if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory); - - // delete original buffer if we performed a conversion - if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents); - - // parse - xml_parse_result res = impl::xml_parser::parse(buffer, length, _root, options); - - // remember encoding - res.encoding = buffer_encoding; - - // grab onto buffer if it's our buffer, user is responsible for deallocating contens himself - if (own || buffer != contents) _buffer = buffer; - - return res; - } - - PUGI__FN xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding) - { - return load_buffer_impl(const_cast(contents), size, options, encoding, false, false); - } - - PUGI__FN xml_parse_result xml_document::load_buffer_inplace(void* contents, size_t size, unsigned int options, xml_encoding encoding) - { - return load_buffer_impl(contents, size, options, encoding, true, false); - } - - PUGI__FN xml_parse_result xml_document::load_buffer_inplace_own(void* contents, size_t size, unsigned int options, xml_encoding encoding) - { - return load_buffer_impl(contents, size, options, encoding, true, true); - } - - PUGI__FN void xml_document::save(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding) const - { - impl::xml_buffered_writer buffered_writer(writer, encoding); - - if ((flags & format_write_bom) && encoding != encoding_latin1) - { - // BOM always represents the codepoint U+FEFF, so just write it in native encoding - #ifdef PUGIXML_WCHAR_MODE - unsigned int bom = 0xfeff; - buffered_writer.write(static_cast(bom)); - #else - buffered_writer.write('\xef', '\xbb', '\xbf'); - #endif - } - - if (!(flags & format_no_declaration) && !impl::has_declaration(*this)) - { - buffered_writer.write(PUGIXML_TEXT("'); - if (!(flags & format_raw)) buffered_writer.write('\n'); - } - - impl::node_output(buffered_writer, *this, indent, flags, 0); - } - -#ifndef PUGIXML_NO_STL - PUGI__FN void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding) const - { - xml_writer_stream writer(stream); - - save(writer, indent, flags, encoding); - } - - PUGI__FN void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags) const - { - xml_writer_stream writer(stream); - - save(writer, indent, flags, encoding_wchar); - } -#endif - - PUGI__FN bool xml_document::save_file(const char* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const - { - FILE* file = fopen(path_, (flags & format_save_file_text) ? "w" : "wb"); - return impl::save_file_impl(*this, file, indent, flags, encoding); - } - - PUGI__FN bool xml_document::save_file(const wchar_t* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const - { - FILE* file = impl::open_file_wide(path_, (flags & format_save_file_text) ? L"w" : L"wb"); - return impl::save_file_impl(*this, file, indent, flags, encoding); - } - - PUGI__FN xml_node xml_document::document_element() const - { - for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if ((i->header & impl::xml_memory_page_type_mask) + 1 == node_element) - return xml_node(i); - - return xml_node(); - } - -#ifndef PUGIXML_NO_STL - PUGI__FN std::string PUGIXML_FUNCTION as_utf8(const wchar_t* str) - { - assert(str); - - return impl::as_utf8_impl(str, wcslen(str)); - } - - PUGI__FN std::string PUGIXML_FUNCTION as_utf8(const std::basic_string& str) - { - return impl::as_utf8_impl(str.c_str(), str.size()); - } - - PUGI__FN std::basic_string PUGIXML_FUNCTION as_wide(const char* str) - { - assert(str); - - return impl::as_wide_impl(str, strlen(str)); - } - - PUGI__FN std::basic_string PUGIXML_FUNCTION as_wide(const std::string& str) - { - return impl::as_wide_impl(str.c_str(), str.size()); - } -#endif - - PUGI__FN void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate) - { - impl::xml_memory::allocate = allocate; - impl::xml_memory::deallocate = deallocate; - } - - PUGI__FN allocation_function PUGIXML_FUNCTION get_memory_allocation_function() - { - return impl::xml_memory::allocate; - } - - PUGI__FN deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function() - { - return impl::xml_memory::deallocate; - } -} -OIIO_NAMESPACE_END - -#if !defined(PUGIXML_NO_STL) && ((defined(_MSC_VER) && _MSC_VER < 1400) || defined(__ICC)) -namespace std -{ - // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier) - PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const OpenImageIO::pugi::xml_node_iterator&) - { - return std::bidirectional_iterator_tag(); - } - - PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const OpenImageIO::pugi::xml_attribute_iterator&) - { - return std::bidirectional_iterator_tag(); - } - - PUGI__FN std::forward_iterator_tag _Iter_cat(const OpenImageIO::pugi::xml_named_node_iterator&) - { - return std::forward_iterator_tag(); - } -} -#endif - -#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC) -namespace std -{ - // Workarounds for (non-standard) iterator category detection - PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_node_iterator&) - { - return std::bidirectional_iterator_tag(); - } - - PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_attribute_iterator&) - { - return std::bidirectional_iterator_tag(); - } - - PUGI__FN std::forward_iterator_tag __iterator_category(const pugi::xml_named_node_iterator&) - { - return std::forward_iterator_tag(); - } -} -#endif - -#ifndef PUGIXML_NO_XPATH - -// STL replacements -PUGI__NS_BEGIN - struct equal_to - { - template bool operator()(const T& lhs, const T& rhs) const - { - return lhs == rhs; - } - }; - - struct not_equal_to - { - template bool operator()(const T& lhs, const T& rhs) const - { - return lhs != rhs; - } - }; - - struct less - { - template bool operator()(const T& lhs, const T& rhs) const - { - return lhs < rhs; - } - }; - - struct less_equal - { - template bool operator()(const T& lhs, const T& rhs) const - { - return lhs <= rhs; - } - }; - - template void swap(T& lhs, T& rhs) - { - T temp = lhs; - lhs = rhs; - rhs = temp; - } - - template I min_element(I begin, I end, const Pred& pred) - { - I result = begin; - - for (I it = begin + 1; it != end; ++it) - if (pred(*it, *result)) - result = it; - - return result; - } - - template void reverse(I begin, I end) - { - while (begin + 1 < end) swap(*begin++, *--end); - } - - template I unique(I begin, I end) - { - // fast skip head - while (begin + 1 < end && *begin != *(begin + 1)) begin++; - - if (begin == end) return begin; - - // last written element - I write = begin++; - - // merge unique elements - while (begin != end) - { - if (*begin != *write) - *++write = *begin++; - else - begin++; - } - - // past-the-end (write points to live element) - return write + 1; - } - - template void copy_backwards(I begin, I end, I target) - { - while (begin != end) *--target = *--end; - } - - template void insertion_sort(I begin, I end, const Pred& pred, T*) - { - assert(begin != end); - - for (I it = begin + 1; it != end; ++it) - { - T val = *it; - - if (pred(val, *begin)) - { - // move to front - copy_backwards(begin, it, it + 1); - *begin = val; - } - else - { - I hole = it; - - // move hole backwards - while (pred(val, *(hole - 1))) - { - *hole = *(hole - 1); - hole--; - } - - // fill hole with element - *hole = val; - } - } - } - - // std variant for elements with == - template void partition(I begin, I middle, I end, const Pred& pred, I* out_eqbeg, I* out_eqend) - { - I eqbeg = middle, eqend = middle + 1; - - // expand equal range - while (eqbeg != begin && *(eqbeg - 1) == *eqbeg) --eqbeg; - while (eqend != end && *eqend == *eqbeg) ++eqend; - - // process outer elements - I ltend = eqbeg, gtbeg = eqend; - - for (;;) - { - // find the element from the right side that belongs to the left one - for (; gtbeg != end; ++gtbeg) - if (!pred(*eqbeg, *gtbeg)) - { - if (*gtbeg == *eqbeg) swap(*gtbeg, *eqend++); - else break; - } - - // find the element from the left side that belongs to the right one - for (; ltend != begin; --ltend) - if (!pred(*(ltend - 1), *eqbeg)) - { - if (*eqbeg == *(ltend - 1)) swap(*(ltend - 1), *--eqbeg); - else break; - } - - // scanned all elements - if (gtbeg == end && ltend == begin) - { - *out_eqbeg = eqbeg; - *out_eqend = eqend; - return; - } - - // make room for elements by moving equal area - if (gtbeg == end) - { - if (--ltend != --eqbeg) swap(*ltend, *eqbeg); - swap(*eqbeg, *--eqend); - } - else if (ltend == begin) - { - if (eqend != gtbeg) swap(*eqbeg, *eqend); - ++eqend; - swap(*gtbeg++, *eqbeg++); - } - else swap(*gtbeg++, *--ltend); - } - } - - template void median3(I first, I middle, I last, const Pred& pred) - { - if (pred(*middle, *first)) swap(*middle, *first); - if (pred(*last, *middle)) swap(*last, *middle); - if (pred(*middle, *first)) swap(*middle, *first); - } - - template void median(I first, I middle, I last, const Pred& pred) - { - if (last - first <= 40) - { - // median of three for small chunks - median3(first, middle, last, pred); - } - else - { - // median of nine - size_t step = (last - first + 1) / 8; - - median3(first, first + step, first + 2 * step, pred); - median3(middle - step, middle, middle + step, pred); - median3(last - 2 * step, last - step, last, pred); - median3(first + step, middle, last - step, pred); - } - } - - template void sort(I begin, I end, const Pred& pred) - { - // sort large chunks - while (end - begin > 32) - { - // find median element - I middle = begin + (end - begin) / 2; - median(begin, middle, end - 1, pred); - - // partition in three chunks (< = >) - I eqbeg, eqend; - partition(begin, middle, end, pred, &eqbeg, &eqend); - - // loop on larger half - if (eqbeg - begin > end - eqend) - { - sort(eqend, end, pred); - end = eqbeg; - } - else - { - sort(begin, eqbeg, pred); - begin = eqend; - } - } - - // insertion sort small chunk - if (begin != end) insertion_sort(begin, end, pred, &*begin); - } -PUGI__NS_END - -// Allocator used for AST and evaluation stacks -PUGI__NS_BEGIN - struct xpath_memory_block - { - xpath_memory_block* next; - - char data[ - #ifdef PUGIXML_MEMORY_XPATH_PAGE_SIZE - PUGIXML_MEMORY_XPATH_PAGE_SIZE - #else - 4096 - #endif - ]; - }; - - class xpath_allocator - { - xpath_memory_block* _root; - size_t _root_size; - - public: - #ifdef PUGIXML_NO_EXCEPTIONS - jmp_buf* error_handler; - #endif - - xpath_allocator(xpath_memory_block* root, size_t root_size = 0): _root(root), _root_size(root_size) - { - #ifdef PUGIXML_NO_EXCEPTIONS - error_handler = 0; - #endif - } - - void* allocate_nothrow(size_t size) - { - const size_t block_capacity = sizeof(_root->data); - - // align size so that we're able to store pointers in subsequent blocks - size = (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); - - if (_root_size + size <= block_capacity) - { - void* buf = _root->data + _root_size; - _root_size += size; - return buf; - } - else - { - size_t block_data_size = (size > block_capacity) ? size : block_capacity; - size_t block_size = block_data_size + offsetof(xpath_memory_block, data); - - xpath_memory_block* block = static_cast(xml_memory::allocate(block_size)); - if (!block) return 0; - - block->next = _root; - - _root = block; - _root_size = size; - - return block->data; - } - } - - void* allocate(size_t size) - { - void* result = allocate_nothrow(size); - - if (!result) - { - #ifdef PUGIXML_NO_EXCEPTIONS - assert(error_handler); - longjmp(*error_handler, 1); - #else - throw std::bad_alloc(); - #endif - } - - return result; - } - - void* reallocate(void* ptr, size_t old_size, size_t new_size) - { - // align size so that we're able to store pointers in subsequent blocks - old_size = (old_size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); - new_size = (new_size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); - - // we can only reallocate the last object - assert(ptr == 0 || static_cast(ptr) + old_size == _root->data + _root_size); - - // adjust root size so that we have not allocated the object at all - bool only_object = (_root_size == old_size); - - if (ptr) _root_size -= old_size; - - // allocate a new version (this will obviously reuse the memory if possible) - void* result = allocate(new_size); - assert(result); - - // we have a new block - if (result != ptr && ptr) - { - // copy old data - assert(new_size > old_size); - memcpy(result, ptr, old_size); - - // free the previous page if it had no other objects - if (only_object) - { - assert(_root->data == result); - assert(_root->next); - - xpath_memory_block* next = _root->next->next; - - if (next) - { - // deallocate the whole page, unless it was the first one - xml_memory::deallocate(_root->next); - _root->next = next; - } - } - } - - return result; - } - - void revert(const xpath_allocator& state) - { - // free all new pages - xpath_memory_block* cur = _root; - - while (cur != state._root) - { - xpath_memory_block* next = cur->next; - - xml_memory::deallocate(cur); - - cur = next; - } - - // restore state - _root = state._root; - _root_size = state._root_size; - } - - void release() - { - xpath_memory_block* cur = _root; - assert(cur); - - while (cur->next) - { - xpath_memory_block* next = cur->next; - - xml_memory::deallocate(cur); - - cur = next; - } - } - }; - - struct xpath_allocator_capture - { - xpath_allocator_capture(xpath_allocator* alloc): _target(alloc), _state(*alloc) - { - } - - ~xpath_allocator_capture() - { - _target->revert(_state); - } - - xpath_allocator* _target; - xpath_allocator _state; - }; - - struct xpath_stack - { - xpath_allocator* result; - xpath_allocator* temp; - }; - - struct xpath_stack_data - { - xpath_memory_block blocks[2]; - xpath_allocator result; - xpath_allocator temp; - xpath_stack stack; - - #ifdef PUGIXML_NO_EXCEPTIONS - jmp_buf error_handler; - #endif - - xpath_stack_data(): result(blocks + 0), temp(blocks + 1) - { - blocks[0].next = blocks[1].next = 0; - - stack.result = &result; - stack.temp = &temp; - - #ifdef PUGIXML_NO_EXCEPTIONS - result.error_handler = temp.error_handler = &error_handler; - #endif - } - - ~xpath_stack_data() - { - result.release(); - temp.release(); - } - }; -PUGI__NS_END - -// String class -PUGI__NS_BEGIN - class xpath_string - { - const char_t* _buffer; - bool _uses_heap; - - static char_t* duplicate_string(const char_t* string, size_t length, xpath_allocator* alloc) - { - char_t* result = static_cast(alloc->allocate((length + 1) * sizeof(char_t))); - assert(result); - - memcpy(result, string, length * sizeof(char_t)); - result[length] = 0; - - return result; - } - - static char_t* duplicate_string(const char_t* string, xpath_allocator* alloc) - { - return duplicate_string(string, strlength(string), alloc); - } - - public: - xpath_string(): _buffer(PUGIXML_TEXT("")), _uses_heap(false) - { - } - - explicit xpath_string(const char_t* str, xpath_allocator* alloc) - { - bool empty_ = (*str == 0); - - _buffer = empty_ ? PUGIXML_TEXT("") : duplicate_string(str, alloc); - _uses_heap = !empty_; - } - - explicit xpath_string(const char_t* str, bool use_heap): _buffer(str), _uses_heap(use_heap) - { - } - - xpath_string(const char_t* begin, const char_t* end, xpath_allocator* alloc) - { - assert(begin <= end); - - bool empty_ = (begin == end); - - _buffer = empty_ ? PUGIXML_TEXT("") : duplicate_string(begin, static_cast(end - begin), alloc); - _uses_heap = !empty_; - } - - void append(const xpath_string& o, xpath_allocator* alloc) - { - // skip empty sources - if (!*o._buffer) return; - - // fast append for constant empty target and constant source - if (!*_buffer && !_uses_heap && !o._uses_heap) - { - _buffer = o._buffer; - } - else - { - // need to make heap copy - size_t target_length = strlength(_buffer); - size_t source_length = strlength(o._buffer); - size_t result_length = target_length + source_length; - - // allocate new buffer - char_t* result = static_cast(alloc->reallocate(_uses_heap ? const_cast(_buffer) : 0, (target_length + 1) * sizeof(char_t), (result_length + 1) * sizeof(char_t))); - assert(result); - - // append first string to the new buffer in case there was no reallocation - if (!_uses_heap) memcpy(result, _buffer, target_length * sizeof(char_t)); - - // append second string to the new buffer - memcpy(result + target_length, o._buffer, source_length * sizeof(char_t)); - result[result_length] = 0; - - // finalize - _buffer = result; - _uses_heap = true; - } - } - - const char_t* c_str() const - { - return _buffer; - } - - size_t length() const - { - return strlength(_buffer); - } - - char_t* data(xpath_allocator* alloc) - { - // make private heap copy - if (!_uses_heap) - { - _buffer = duplicate_string(_buffer, alloc); - _uses_heap = true; - } - - return const_cast(_buffer); - } - - bool empty() const - { - return *_buffer == 0; - } - - bool operator==(const xpath_string& o) const - { - return strequal(_buffer, o._buffer); - } - - bool operator!=(const xpath_string& o) const - { - return !strequal(_buffer, o._buffer); - } - - bool uses_heap() const - { - return _uses_heap; - } - }; - - PUGI__FN xpath_string xpath_string_const(const char_t* str) - { - return xpath_string(str, false); - } -PUGI__NS_END - -PUGI__NS_BEGIN - PUGI__FN bool starts_with(const char_t* string, const char_t* pattern) - { - while (*pattern && *string == *pattern) - { - string++; - pattern++; - } - - return *pattern == 0; - } - - PUGI__FN const char_t* find_char(const char_t* s, char_t c) - { - #ifdef PUGIXML_WCHAR_MODE - return wcschr(s, c); - #else - return strchr(s, c); - #endif - } - - PUGI__FN const char_t* find_substring(const char_t* s, const char_t* p) - { - #ifdef PUGIXML_WCHAR_MODE - // MSVC6 wcsstr bug workaround (if s is empty it always returns 0) - return (*p == 0) ? s : wcsstr(s, p); - #else - return strstr(s, p); - #endif - } - - // Converts symbol to lower case, if it is an ASCII one - PUGI__FN char_t tolower_ascii(char_t ch) - { - return static_cast(ch - 'A') < 26 ? static_cast(ch | ' ') : ch; - } - - PUGI__FN xpath_string string_value(const xpath_node& na, xpath_allocator* alloc) - { - if (na.attribute()) - return xpath_string_const(na.attribute().value()); - else - { - const xml_node& n = na.node(); - - switch (n.type()) - { - case node_pcdata: - case node_cdata: - case node_comment: - case node_pi: - return xpath_string_const(n.value()); - - case node_document: - case node_element: - { - xpath_string result; - - xml_node cur = n.first_child(); - - while (cur && cur != n) - { - if (cur.type() == node_pcdata || cur.type() == node_cdata) - result.append(xpath_string_const(cur.value()), alloc); - - if (cur.first_child()) - cur = cur.first_child(); - else if (cur.next_sibling()) - cur = cur.next_sibling(); - else - { - while (!cur.next_sibling() && cur != n) - cur = cur.parent(); - - if (cur != n) cur = cur.next_sibling(); - } - } - - return result; - } - - default: - return xpath_string(); - } - } - } - - PUGI__FN unsigned int node_height(xml_node n) - { - unsigned int result = 0; - - while (n) - { - ++result; - n = n.parent(); - } - - return result; - } - - PUGI__FN bool node_is_before(xml_node ln, unsigned int lh, xml_node rn, unsigned int rh) - { - // normalize heights - for (unsigned int i = rh; i < lh; i++) ln = ln.parent(); - for (unsigned int j = lh; j < rh; j++) rn = rn.parent(); - - // one node is the ancestor of the other - if (ln == rn) return lh < rh; - - // find common ancestor - while (ln.parent() != rn.parent()) - { - ln = ln.parent(); - rn = rn.parent(); - } - - // there is no common ancestor (the shared parent is null), nodes are from different documents - if (!ln.parent()) return ln < rn; - - // determine sibling order - for (; ln; ln = ln.next_sibling()) - if (ln == rn) - return true; - - return false; - } - - PUGI__FN bool node_is_ancestor(xml_node parent, xml_node node) - { - while (node && node != parent) node = node.parent(); - - return parent && node == parent; - } - - PUGI__FN const void* document_order(const xpath_node& xnode) - { - xml_node_struct* node = xnode.node().internal_object(); - - if (node) - { - if (node->name && (node->header & xml_memory_page_name_allocated_mask) == 0) return node->name; - if (node->value && (node->header & xml_memory_page_value_allocated_mask) == 0) return node->value; - return 0; - } - - xml_attribute_struct* attr = xnode.attribute().internal_object(); - - if (attr) - { - if ((attr->header & xml_memory_page_name_allocated_mask) == 0) return attr->name; - if ((attr->header & xml_memory_page_value_allocated_mask) == 0) return attr->value; - return 0; - } - - return 0; - } - - struct document_order_comparator - { - bool operator()(const xpath_node& lhs, const xpath_node& rhs) const - { - // optimized document order based check - const void* lo = document_order(lhs); - const void* ro = document_order(rhs); - - if (lo && ro) return lo < ro; - - // slow comparison - xml_node ln = lhs.node(), rn = rhs.node(); - - // compare attributes - if (lhs.attribute() && rhs.attribute()) - { - // shared parent - if (lhs.parent() == rhs.parent()) - { - // determine sibling order - for (xml_attribute a = lhs.attribute(); a; a = a.next_attribute()) - if (a == rhs.attribute()) - return true; - - return false; - } - - // compare attribute parents - ln = lhs.parent(); - rn = rhs.parent(); - } - else if (lhs.attribute()) - { - // attributes go after the parent element - if (lhs.parent() == rhs.node()) return false; - - ln = lhs.parent(); - } - else if (rhs.attribute()) - { - // attributes go after the parent element - if (rhs.parent() == lhs.node()) return true; - - rn = rhs.parent(); - } - - if (ln == rn) return false; - - unsigned int lh = node_height(ln); - unsigned int rh = node_height(rn); - - return node_is_before(ln, lh, rn, rh); - } - }; - - struct duplicate_comparator - { - bool operator()(const xpath_node& lhs, const xpath_node& rhs) const - { - if (lhs.attribute()) return rhs.attribute() ? lhs.attribute() < rhs.attribute() : true; - else return rhs.attribute() ? false : lhs.node() < rhs.node(); - } - }; - - PUGI__FN double gen_nan() - { - #if defined(__STDC_IEC_559__) || ((FLT_RADIX - 0 == 2) && (FLT_MAX_EXP - 0 == 128) && (FLT_MANT_DIG - 0 == 24)) - union { float f; uint32_t i; } u[sizeof(float) == sizeof(uint32_t) ? 1 : -1]; - u[0].i = 0x7fc00000; - return u[0].f; - #else - // fallback - const volatile double zero = 0.0; - return zero / zero; - #endif - } - - PUGI__FN bool is_nan(double value) - { - #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) - return !!_isnan(value); - #elif defined(fpclassify) && defined(FP_NAN) - return fpclassify(value) == FP_NAN; - #else - // fallback - const volatile double v = value; - return v != v; - #endif - } - - PUGI__FN const char_t* convert_number_to_string_special(double value) - { - #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) - if (_finite(value)) return (value == 0) ? PUGIXML_TEXT("0") : 0; - if (_isnan(value)) return PUGIXML_TEXT("NaN"); - return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity"); - #elif defined(fpclassify) && defined(FP_NAN) && defined(FP_INFINITE) && defined(FP_ZERO) - switch (fpclassify(value)) - { - case FP_NAN: - return PUGIXML_TEXT("NaN"); - - case FP_INFINITE: - return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity"); - - case FP_ZERO: - return PUGIXML_TEXT("0"); - - default: - return 0; - } - #else - // fallback - const volatile double v = value; - - if (v == 0) return PUGIXML_TEXT("0"); - if (v != v) return PUGIXML_TEXT("NaN"); - if (v * 2 == v) return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity"); - return 0; - #endif - } - - PUGI__FN bool convert_number_to_boolean(double value) - { - return (value != 0 && !is_nan(value)); - } - - PUGI__FN void truncate_zeros(char* begin, char* end) - { - while (begin != end && end[-1] == '0') end--; - - *end = 0; - } - - // gets mantissa digits in the form of 0.xxxxx with 0. implied and the exponent -#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE) - PUGI__FN void convert_number_to_mantissa_exponent(double value, char* buffer, size_t buffer_size, char** out_mantissa, int* out_exponent) - { - // get base values - int sign, exponent; - _ecvt_s(buffer, buffer_size, value, DBL_DIG + 1, &exponent, &sign); - - // truncate redundant zeros - truncate_zeros(buffer, buffer + strlen(buffer)); - - // fill results - *out_mantissa = buffer; - *out_exponent = exponent; - } -#else - PUGI__FN void convert_number_to_mantissa_exponent(double value, char* buffer, size_t buffer_size, char** out_mantissa, int* out_exponent) - { - // get a scientific notation value with IEEE DBL_DIG decimals - sprintf(buffer, "%.*e", DBL_DIG, value); - assert(strlen(buffer) < buffer_size); - (void)!buffer_size; - - // get the exponent (possibly negative) - char* exponent_string = strchr(buffer, 'e'); - assert(exponent_string); - - int exponent = atoi(exponent_string + 1); - - // extract mantissa string: skip sign - char* mantissa = buffer[0] == '-' ? buffer + 1 : buffer; - assert(mantissa[0] != '0' && mantissa[1] == '.'); - - // divide mantissa by 10 to eliminate integer part - mantissa[1] = mantissa[0]; - mantissa++; - exponent++; - - // remove extra mantissa digits and zero-terminate mantissa - truncate_zeros(mantissa, exponent_string); - - // fill results - *out_mantissa = mantissa; - *out_exponent = exponent; - } -#endif - - PUGI__FN xpath_string convert_number_to_string(double value, xpath_allocator* alloc) - { - // try special number conversion - const char_t* special = convert_number_to_string_special(value); - if (special) return xpath_string_const(special); - - // get mantissa + exponent form - char mantissa_buffer[64]; - - char* mantissa; - int exponent; - convert_number_to_mantissa_exponent(value, mantissa_buffer, sizeof(mantissa_buffer), &mantissa, &exponent); - - // make the number! - char_t result[512]; - char_t* s = result; - - // sign - if (value < 0) *s++ = '-'; - - // integer part - if (exponent <= 0) - { - *s++ = '0'; - } - else - { - while (exponent > 0) - { - assert(*mantissa == 0 || static_cast(*mantissa - '0') <= 9); - *s++ = *mantissa ? *mantissa++ : '0'; - exponent--; - } - } - - // fractional part - if (*mantissa) - { - // decimal point - *s++ = '.'; - - // extra zeroes from negative exponent - while (exponent < 0) - { - *s++ = '0'; - exponent++; - } - - // extra mantissa digits - while (*mantissa) - { - assert(static_cast(*mantissa - '0') <= 9); - *s++ = *mantissa++; - } - } - - // zero-terminate - assert(s < result + sizeof(result) / sizeof(result[0])); - *s = 0; - - return xpath_string(result, alloc); - } - - PUGI__FN bool check_string_to_number_format(const char_t* string) - { - // parse leading whitespace - while (PUGI__IS_CHARTYPE(*string, ct_space)) ++string; - - // parse sign - if (*string == '-') ++string; - - if (!*string) return false; - - // if there is no integer part, there should be a decimal part with at least one digit - if (!PUGI__IS_CHARTYPEX(string[0], ctx_digit) && (string[0] != '.' || !PUGI__IS_CHARTYPEX(string[1], ctx_digit))) return false; - - // parse integer part - while (PUGI__IS_CHARTYPEX(*string, ctx_digit)) ++string; - - // parse decimal part - if (*string == '.') - { - ++string; - - while (PUGI__IS_CHARTYPEX(*string, ctx_digit)) ++string; - } - - // parse trailing whitespace - while (PUGI__IS_CHARTYPE(*string, ct_space)) ++string; - - return *string == 0; - } - - PUGI__FN double convert_string_to_number(const char_t* string) - { - // check string format - if (!check_string_to_number_format(string)) return gen_nan(); - - // parse string - #ifdef PUGIXML_WCHAR_MODE - return wcstod(string, 0); - #else - return atof(string); - #endif - } - - PUGI__FN bool convert_string_to_number(const char_t* begin, const char_t* end, double* out_result) - { - char_t buffer[32]; - - size_t length = static_cast(end - begin); - char_t* scratch = buffer; - - if (length >= sizeof(buffer) / sizeof(buffer[0])) - { - // need to make dummy on-heap copy - scratch = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!scratch) return false; - } - - // copy string to zero-terminated buffer and perform conversion - memcpy(scratch, begin, length * sizeof(char_t)); - scratch[length] = 0; - - *out_result = convert_string_to_number(scratch); - - // free dummy buffer - if (scratch != buffer) xml_memory::deallocate(scratch); - - return true; - } - - PUGI__FN double round_nearest(double value) - { - return floor(value + 0.5); - } - - PUGI__FN double round_nearest_nzero(double value) - { - // same as round_nearest, but returns -0 for [-0.5, -0] - // ceil is used to differentiate between +0 and -0 (we return -0 for [-0.5, -0] and +0 for +0) - return (value >= -0.5 && value <= 0) ? ceil(value) : floor(value + 0.5); - } - - PUGI__FN const char_t* qualified_name(const xpath_node& node) - { - return node.attribute() ? node.attribute().name() : node.node().name(); - } - - PUGI__FN const char_t* local_name(const xpath_node& node) - { - const char_t* name = qualified_name(node); - const char_t* p = find_char(name, ':'); - - return p ? p + 1 : name; - } - - struct namespace_uri_predicate - { - const char_t* prefix; - size_t prefix_length; - - namespace_uri_predicate(const char_t* name) - { - const char_t* pos = find_char(name, ':'); - - prefix = pos ? name : 0; - prefix_length = pos ? static_cast(pos - name) : 0; - } - - bool operator()(const xml_attribute& a) const - { - const char_t* name = a.name(); - - if (!starts_with(name, PUGIXML_TEXT("xmlns"))) return false; - - return prefix ? name[5] == ':' && strequalrange(name + 6, prefix, prefix_length) : name[5] == 0; - } - }; - - PUGI__FN const char_t* namespace_uri(const xml_node& node) - { - namespace_uri_predicate pred = node.name(); - - xml_node p = node; - - while (p) - { - xml_attribute a = p.find_attribute(pred); - - if (a) return a.value(); - - p = p.parent(); - } - - return PUGIXML_TEXT(""); - } - - PUGI__FN const char_t* namespace_uri(const xml_attribute& attr, const xml_node& parent) - { - namespace_uri_predicate pred = attr.name(); - - // Default namespace does not apply to attributes - if (!pred.prefix) return PUGIXML_TEXT(""); - - xml_node p = parent; - - while (p) - { - xml_attribute a = p.find_attribute(pred); - - if (a) return a.value(); - - p = p.parent(); - } - - return PUGIXML_TEXT(""); - } - - PUGI__FN const char_t* namespace_uri(const xpath_node& node) - { - return node.attribute() ? namespace_uri(node.attribute(), node.parent()) : namespace_uri(node.node()); - } - - PUGI__FN void normalize_space(char_t* buffer) - { - char_t* write = buffer; - - for (char_t* it = buffer; *it; ) - { - char_t ch = *it++; - - if (PUGI__IS_CHARTYPE(ch, ct_space)) - { - // replace whitespace sequence with single space - while (PUGI__IS_CHARTYPE(*it, ct_space)) it++; - - // avoid leading spaces - if (write != buffer) *write++ = ' '; - } - else *write++ = ch; - } - - // remove trailing space - if (write != buffer && PUGI__IS_CHARTYPE(write[-1], ct_space)) write--; - - // zero-terminate - *write = 0; - } - - PUGI__FN void translate(char_t* buffer, const char_t* from, const char_t* to) - { - size_t to_length = strlength(to); - - char_t* write = buffer; - - while (*buffer) - { - PUGI__DMC_VOLATILE char_t ch = *buffer++; - - const char_t* pos = find_char(from, ch); - - if (!pos) - *write++ = ch; // do not process - else if (static_cast(pos - from) < to_length) - *write++ = to[pos - from]; // replace - } - - // zero-terminate - *write = 0; - } - - struct xpath_variable_boolean: xpath_variable - { - xpath_variable_boolean(): value(false) - { - } - - bool value; - char_t name[1]; - }; - - struct xpath_variable_number: xpath_variable - { - xpath_variable_number(): value(0) - { - } - - double value; - char_t name[1]; - }; - - struct xpath_variable_string: xpath_variable - { - xpath_variable_string(): value(0) - { - } - - ~xpath_variable_string() - { - if (value) xml_memory::deallocate(value); - } - - char_t* value; - char_t name[1]; - }; - - struct xpath_variable_node_set: xpath_variable - { - xpath_node_set value; - char_t name[1]; - }; - - static const xpath_node_set dummy_node_set; - - PUGI__FN unsigned int hash_string(const char_t* str) - { - // Jenkins one-at-a-time hash (http://en.wikipedia.org/wiki/Jenkins_hash_function#one-at-a-time) - unsigned int result = 0; - - while (*str) - { - result += static_cast(*str++); - result += result << 10; - result ^= result >> 6; - } - - result += result << 3; - result ^= result >> 11; - result += result << 15; - - return result; - } - - template PUGI__FN T* new_xpath_variable(const char_t* name) - { - size_t length = strlength(name); - if (length == 0) return 0; // empty variable names are invalid - - // $$ we can't use offsetof(T, name) because T is non-POD, so we just allocate additional length characters - void* memory = xml_memory::allocate(sizeof(T) + length * sizeof(char_t)); - if (!memory) return 0; - - T* result = new (memory) T(); - - memcpy(result->name, name, (length + 1) * sizeof(char_t)); - - return result; - } - - PUGI__FN xpath_variable* new_xpath_variable(xpath_value_type type, const char_t* name) - { - switch (type) - { - case xpath_type_node_set: - return new_xpath_variable(name); - - case xpath_type_number: - return new_xpath_variable(name); - - case xpath_type_string: - return new_xpath_variable(name); - - case xpath_type_boolean: - return new_xpath_variable(name); - - default: - return 0; - } - } - - template PUGI__FN void delete_xpath_variable(T* var) - { - var->~T(); - xml_memory::deallocate(var); - } - - PUGI__FN void delete_xpath_variable(xpath_value_type type, xpath_variable* var) - { - switch (type) - { - case xpath_type_node_set: - delete_xpath_variable(static_cast(var)); - break; - - case xpath_type_number: - delete_xpath_variable(static_cast(var)); - break; - - case xpath_type_string: - delete_xpath_variable(static_cast(var)); - break; - - case xpath_type_boolean: - delete_xpath_variable(static_cast(var)); - break; - - default: - assert(!"Invalid variable type"); - } - } - - PUGI__FN xpath_variable* get_variable(xpath_variable_set* set, const char_t* begin, const char_t* end) - { - char_t buffer[32]; - - size_t length = static_cast(end - begin); - char_t* scratch = buffer; - - if (length >= sizeof(buffer) / sizeof(buffer[0])) - { - // need to make dummy on-heap copy - scratch = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!scratch) return 0; - } - - // copy string to zero-terminated buffer and perform lookup - memcpy(scratch, begin, length * sizeof(char_t)); - scratch[length] = 0; - - xpath_variable* result = set->get(scratch); - - // free dummy buffer - if (scratch != buffer) xml_memory::deallocate(scratch); - - return result; - } -PUGI__NS_END - -// Internal node set class -PUGI__NS_BEGIN - PUGI__FN xpath_node_set::type_t xpath_sort(xpath_node* begin, xpath_node* end, xpath_node_set::type_t type, bool rev) - { - xpath_node_set::type_t order = rev ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted; - - if (type == xpath_node_set::type_unsorted) - { - sort(begin, end, document_order_comparator()); - - type = xpath_node_set::type_sorted; - } - - if (type != order) reverse(begin, end); - - return order; - } - - PUGI__FN xpath_node xpath_first(const xpath_node* begin, const xpath_node* end, xpath_node_set::type_t type) - { - if (begin == end) return xpath_node(); - - switch (type) - { - case xpath_node_set::type_sorted: - return *begin; - - case xpath_node_set::type_sorted_reverse: - return *(end - 1); - - case xpath_node_set::type_unsorted: - return *min_element(begin, end, document_order_comparator()); - - default: - assert(!"Invalid node set type"); - return xpath_node(); - } - } - - class xpath_node_set_raw - { - xpath_node_set::type_t _type; - - xpath_node* _begin; - xpath_node* _end; - xpath_node* _eos; - - public: - xpath_node_set_raw(): _type(xpath_node_set::type_unsorted), _begin(0), _end(0), _eos(0) - { - } - - xpath_node* begin() const - { - return _begin; - } - - xpath_node* end() const - { - return _end; - } - - bool empty() const - { - return _begin == _end; - } - - size_t size() const - { - return static_cast(_end - _begin); - } - - xpath_node first() const - { - return xpath_first(_begin, _end, _type); - } - - void push_back(const xpath_node& node, xpath_allocator* alloc) - { - if (_end == _eos) - { - size_t capacity = static_cast(_eos - _begin); - - // get new capacity (1.5x rule) - size_t new_capacity = capacity + capacity / 2 + 1; - - // reallocate the old array or allocate a new one - xpath_node* data = static_cast(alloc->reallocate(_begin, capacity * sizeof(xpath_node), new_capacity * sizeof(xpath_node))); - assert(data); - - // finalize - _begin = data; - _end = data + capacity; - _eos = data + new_capacity; - } - - *_end++ = node; - } - - void append(const xpath_node* begin_, const xpath_node* end_, xpath_allocator* alloc) - { - size_t size_ = static_cast(_end - _begin); - size_t capacity = static_cast(_eos - _begin); - size_t count = static_cast(end_ - begin_); - - if (size_ + count > capacity) - { - // reallocate the old array or allocate a new one - xpath_node* data = static_cast(alloc->reallocate(_begin, capacity * sizeof(xpath_node), (size_ + count) * sizeof(xpath_node))); - assert(data); - - // finalize - _begin = data; - _end = data + size_; - _eos = data + size_ + count; - } - - memcpy(_end, begin_, count * sizeof(xpath_node)); - _end += count; - } - - void sort_do() - { - _type = xpath_sort(_begin, _end, _type, false); - } - - void truncate(xpath_node* pos) - { - assert(_begin <= pos && pos <= _end); - - _end = pos; - } - - void remove_duplicates() - { - if (_type == xpath_node_set::type_unsorted) - sort(_begin, _end, duplicate_comparator()); - - _end = unique(_begin, _end); - } - - xpath_node_set::type_t type() const - { - return _type; - } - - void set_type(xpath_node_set::type_t value) - { - _type = value; - } - }; -PUGI__NS_END - -PUGI__NS_BEGIN - struct xpath_context - { - xpath_node n; - size_t position, size; - - xpath_context(const xpath_node& n_, size_t position_, size_t size_): n(n_), position(position_), size(size_) - { - } - }; - - enum lexeme_t - { - lex_none = 0, - lex_equal, - lex_not_equal, - lex_less, - lex_greater, - lex_less_or_equal, - lex_greater_or_equal, - lex_plus, - lex_minus, - lex_multiply, - lex_union, - lex_var_ref, - lex_open_brace, - lex_close_brace, - lex_quoted_string, - lex_number, - lex_slash, - lex_double_slash, - lex_open_square_brace, - lex_close_square_brace, - lex_string, - lex_comma, - lex_axis_attribute, - lex_dot, - lex_double_dot, - lex_double_colon, - lex_eof - }; - - struct xpath_lexer_string - { - const char_t* begin; - const char_t* end; - - xpath_lexer_string(): begin(0), end(0) - { - } - - bool operator==(const char_t* other) const - { - size_t length = static_cast(end - begin); - - return strequalrange(other, begin, length); - } - }; - - class xpath_lexer - { - const char_t* _cur; - const char_t* _cur_lexeme_pos; - xpath_lexer_string _cur_lexeme_contents; - - lexeme_t _cur_lexeme; - - public: - explicit xpath_lexer(const char_t* query): _cur(query) - { - next(); - } - - const char_t* state() const - { - return _cur; - } - - void next() - { - const char_t* cur = _cur; - - while (PUGI__IS_CHARTYPE(*cur, ct_space)) ++cur; - - // save lexeme position for error reporting - _cur_lexeme_pos = cur; - - switch (*cur) - { - case 0: - _cur_lexeme = lex_eof; - break; - - case '>': - if (*(cur+1) == '=') - { - cur += 2; - _cur_lexeme = lex_greater_or_equal; - } - else - { - cur += 1; - _cur_lexeme = lex_greater; - } - break; - - case '<': - if (*(cur+1) == '=') - { - cur += 2; - _cur_lexeme = lex_less_or_equal; - } - else - { - cur += 1; - _cur_lexeme = lex_less; - } - break; - - case '!': - if (*(cur+1) == '=') - { - cur += 2; - _cur_lexeme = lex_not_equal; - } - else - { - _cur_lexeme = lex_none; - } - break; - - case '=': - cur += 1; - _cur_lexeme = lex_equal; - - break; - - case '+': - cur += 1; - _cur_lexeme = lex_plus; - - break; - - case '-': - cur += 1; - _cur_lexeme = lex_minus; - - break; - - case '*': - cur += 1; - _cur_lexeme = lex_multiply; - - break; - - case '|': - cur += 1; - _cur_lexeme = lex_union; - - break; - - case '$': - cur += 1; - - if (PUGI__IS_CHARTYPEX(*cur, ctx_start_symbol)) - { - _cur_lexeme_contents.begin = cur; - - while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; - - if (cur[0] == ':' && PUGI__IS_CHARTYPEX(cur[1], ctx_symbol)) // qname - { - cur++; // : - - while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; - } - - _cur_lexeme_contents.end = cur; - - _cur_lexeme = lex_var_ref; - } - else - { - _cur_lexeme = lex_none; - } - - break; - - case '(': - cur += 1; - _cur_lexeme = lex_open_brace; - - break; - - case ')': - cur += 1; - _cur_lexeme = lex_close_brace; - - break; - - case '[': - cur += 1; - _cur_lexeme = lex_open_square_brace; - - break; - - case ']': - cur += 1; - _cur_lexeme = lex_close_square_brace; - - break; - - case ',': - cur += 1; - _cur_lexeme = lex_comma; - - break; - - case '/': - if (*(cur+1) == '/') - { - cur += 2; - _cur_lexeme = lex_double_slash; - } - else - { - cur += 1; - _cur_lexeme = lex_slash; - } - break; - - case '.': - if (*(cur+1) == '.') - { - cur += 2; - _cur_lexeme = lex_double_dot; - } - else if (PUGI__IS_CHARTYPEX(*(cur+1), ctx_digit)) - { - _cur_lexeme_contents.begin = cur; // . - - ++cur; - - while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; - - _cur_lexeme_contents.end = cur; - - _cur_lexeme = lex_number; - } - else - { - cur += 1; - _cur_lexeme = lex_dot; - } - break; - - case '@': - cur += 1; - _cur_lexeme = lex_axis_attribute; - - break; - - case '"': - case '\'': - { - char_t terminator = *cur; - - ++cur; - - _cur_lexeme_contents.begin = cur; - while (*cur && *cur != terminator) cur++; - _cur_lexeme_contents.end = cur; - - if (!*cur) - _cur_lexeme = lex_none; - else - { - cur += 1; - _cur_lexeme = lex_quoted_string; - } - - break; - } - - case ':': - if (*(cur+1) == ':') - { - cur += 2; - _cur_lexeme = lex_double_colon; - } - else - { - _cur_lexeme = lex_none; - } - break; - - default: - if (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) - { - _cur_lexeme_contents.begin = cur; - - while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; - - if (*cur == '.') - { - cur++; - - while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; - } - - _cur_lexeme_contents.end = cur; - - _cur_lexeme = lex_number; - } - else if (PUGI__IS_CHARTYPEX(*cur, ctx_start_symbol)) - { - _cur_lexeme_contents.begin = cur; - - while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; - - if (cur[0] == ':') - { - if (cur[1] == '*') // namespace test ncname:* - { - cur += 2; // :* - } - else if (PUGI__IS_CHARTYPEX(cur[1], ctx_symbol)) // namespace test qname - { - cur++; // : - - while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; - } - } - - _cur_lexeme_contents.end = cur; - - _cur_lexeme = lex_string; - } - else - { - _cur_lexeme = lex_none; - } - } - - _cur = cur; - } - - lexeme_t current() const - { - return _cur_lexeme; - } - - const char_t* current_pos() const - { - return _cur_lexeme_pos; - } - - const xpath_lexer_string& contents() const - { - assert(_cur_lexeme == lex_var_ref || _cur_lexeme == lex_number || _cur_lexeme == lex_string || _cur_lexeme == lex_quoted_string); - - return _cur_lexeme_contents; - } - }; - - enum ast_type_t - { - ast_op_or, // left or right - ast_op_and, // left and right - ast_op_equal, // left = right - ast_op_not_equal, // left != right - ast_op_less, // left < right - ast_op_greater, // left > right - ast_op_less_or_equal, // left <= right - ast_op_greater_or_equal, // left >= right - ast_op_add, // left + right - ast_op_subtract, // left - right - ast_op_multiply, // left * right - ast_op_divide, // left / right - ast_op_mod, // left % right - ast_op_negate, // left - right - ast_op_union, // left | right - ast_predicate, // apply predicate to set; next points to next predicate - ast_filter, // select * from left where right - ast_filter_posinv, // select * from left where right; proximity position invariant - ast_string_constant, // string constant - ast_number_constant, // number constant - ast_variable, // variable - ast_func_last, // last() - ast_func_position, // position() - ast_func_count, // count(left) - ast_func_id, // id(left) - ast_func_local_name_0, // local-name() - ast_func_local_name_1, // local-name(left) - ast_func_namespace_uri_0, // namespace-uri() - ast_func_namespace_uri_1, // namespace-uri(left) - ast_func_name_0, // name() - ast_func_name_1, // name(left) - ast_func_string_0, // string() - ast_func_string_1, // string(left) - ast_func_concat, // concat(left, right, siblings) - ast_func_starts_with, // starts_with(left, right) - ast_func_contains, // contains(left, right) - ast_func_substring_before, // substring-before(left, right) - ast_func_substring_after, // substring-after(left, right) - ast_func_substring_2, // substring(left, right) - ast_func_substring_3, // substring(left, right, third) - ast_func_string_length_0, // string-length() - ast_func_string_length_1, // string-length(left) - ast_func_normalize_space_0, // normalize-space() - ast_func_normalize_space_1, // normalize-space(left) - ast_func_translate, // translate(left, right, third) - ast_func_boolean, // boolean(left) - ast_func_not, // not(left) - ast_func_true, // true() - ast_func_false, // false() - ast_func_lang, // lang(left) - ast_func_number_0, // number() - ast_func_number_1, // number(left) - ast_func_sum, // sum(left) - ast_func_floor, // floor(left) - ast_func_ceiling, // ceiling(left) - ast_func_round, // round(left) - ast_step, // process set left with step - ast_step_root // select root node - }; - - enum axis_t - { - axis_ancestor, - axis_ancestor_or_self, - axis_attribute, - axis_child, - axis_descendant, - axis_descendant_or_self, - axis_following, - axis_following_sibling, - axis_namespace, - axis_parent, - axis_preceding, - axis_preceding_sibling, - axis_self - }; - - enum nodetest_t - { - nodetest_none, - nodetest_name, - nodetest_type_node, - nodetest_type_comment, - nodetest_type_pi, - nodetest_type_text, - nodetest_pi, - nodetest_all, - nodetest_all_in_namespace - }; - - template struct axis_to_type - { - static const axis_t axis; - }; - - template const axis_t axis_to_type::axis = N; - - class xpath_ast_node - { - private: - // node type - char _type; - char _rettype; - - // for ast_step / ast_predicate - char _axis; - char _test; - - // tree node structure - xpath_ast_node* _left; - xpath_ast_node* _right; - xpath_ast_node* _next; - - union - { - // value for ast_string_constant - const char_t* string; - // value for ast_number_constant - double number; - // variable for ast_variable - xpath_variable* variable; - // node test for ast_step (node name/namespace/node type/pi target) - const char_t* nodetest; - } _data; - - xpath_ast_node(const xpath_ast_node&); - xpath_ast_node& operator=(const xpath_ast_node&); - - template static bool compare_eq(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c, const xpath_stack& stack, const Comp& comp) - { - xpath_value_type lt = lhs->rettype(), rt = rhs->rettype(); - - if (lt != xpath_type_node_set && rt != xpath_type_node_set) - { - if (lt == xpath_type_boolean || rt == xpath_type_boolean) - return comp(lhs->eval_boolean(c, stack), rhs->eval_boolean(c, stack)); - else if (lt == xpath_type_number || rt == xpath_type_number) - return comp(lhs->eval_number(c, stack), rhs->eval_number(c, stack)); - else if (lt == xpath_type_string || rt == xpath_type_string) - { - xpath_allocator_capture cr(stack.result); - - xpath_string ls = lhs->eval_string(c, stack); - xpath_string rs = rhs->eval_string(c, stack); - - return comp(ls, rs); - } - } - else if (lt == xpath_type_node_set && rt == xpath_type_node_set) - { - xpath_allocator_capture cr(stack.result); - - xpath_node_set_raw ls = lhs->eval_node_set(c, stack); - xpath_node_set_raw rs = rhs->eval_node_set(c, stack); - - for (const xpath_node* li = ls.begin(); li != ls.end(); ++li) - for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) - { - xpath_allocator_capture cri(stack.result); - - if (comp(string_value(*li, stack.result), string_value(*ri, stack.result))) - return true; - } - - return false; - } - else - { - if (lt == xpath_type_node_set) - { - swap(lhs, rhs); - swap(lt, rt); - } - - if (lt == xpath_type_boolean) - return comp(lhs->eval_boolean(c, stack), rhs->eval_boolean(c, stack)); - else if (lt == xpath_type_number) - { - xpath_allocator_capture cr(stack.result); - - double l = lhs->eval_number(c, stack); - xpath_node_set_raw rs = rhs->eval_node_set(c, stack); - - for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) - { - xpath_allocator_capture cri(stack.result); - - if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str()))) - return true; - } - - return false; - } - else if (lt == xpath_type_string) - { - xpath_allocator_capture cr(stack.result); - - xpath_string l = lhs->eval_string(c, stack); - xpath_node_set_raw rs = rhs->eval_node_set(c, stack); - - for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) - { - xpath_allocator_capture cri(stack.result); - - if (comp(l, string_value(*ri, stack.result))) - return true; - } - - return false; - } - } - - assert(!"Wrong types"); - return false; - } - - template static bool compare_rel(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c, const xpath_stack& stack, const Comp& comp) - { - xpath_value_type lt = lhs->rettype(), rt = rhs->rettype(); - - if (lt != xpath_type_node_set && rt != xpath_type_node_set) - return comp(lhs->eval_number(c, stack), rhs->eval_number(c, stack)); - else if (lt == xpath_type_node_set && rt == xpath_type_node_set) - { - xpath_allocator_capture cr(stack.result); - - xpath_node_set_raw ls = lhs->eval_node_set(c, stack); - xpath_node_set_raw rs = rhs->eval_node_set(c, stack); - - for (const xpath_node* li = ls.begin(); li != ls.end(); ++li) - { - xpath_allocator_capture cri(stack.result); - - double l = convert_string_to_number(string_value(*li, stack.result).c_str()); - - for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) - { - xpath_allocator_capture crii(stack.result); - - if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str()))) - return true; - } - } - - return false; - } - else if (lt != xpath_type_node_set && rt == xpath_type_node_set) - { - xpath_allocator_capture cr(stack.result); - - double l = lhs->eval_number(c, stack); - xpath_node_set_raw rs = rhs->eval_node_set(c, stack); - - for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) - { - xpath_allocator_capture cri(stack.result); - - if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str()))) - return true; - } - - return false; - } - else if (lt == xpath_type_node_set && rt != xpath_type_node_set) - { - xpath_allocator_capture cr(stack.result); - - xpath_node_set_raw ls = lhs->eval_node_set(c, stack); - double r = rhs->eval_number(c, stack); - - for (const xpath_node* li = ls.begin(); li != ls.end(); ++li) - { - xpath_allocator_capture cri(stack.result); - - if (comp(convert_string_to_number(string_value(*li, stack.result).c_str()), r)) - return true; - } - - return false; - } - else - { - assert(!"Wrong types"); - return false; - } - } - - void apply_predicate(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack) - { - assert(ns.size() >= first); - - size_t i = 1; - size_t size = ns.size() - first; - - xpath_node* last = ns.begin() + first; - - // remove_if... or well, sort of - for (xpath_node* it = last; it != ns.end(); ++it, ++i) - { - xpath_context c(*it, i, size); - - if (expr->rettype() == xpath_type_number) - { - if (expr->eval_number(c, stack) == i) - *last++ = *it; - } - else if (expr->eval_boolean(c, stack)) - *last++ = *it; - } - - ns.truncate(last); - } - - void apply_predicates(xpath_node_set_raw& ns, size_t first, const xpath_stack& stack) - { - if (ns.size() == first) return; - - for (xpath_ast_node* pred = _right; pred; pred = pred->_next) - { - apply_predicate(ns, first, pred->_left, stack); - } - } - - void step_push(xpath_node_set_raw& ns, const xml_attribute& a, const xml_node& parent, xpath_allocator* alloc) - { - if (!a) return; - - const char_t* name = a.name(); - - // There are no attribute nodes corresponding to attributes that declare namespaces - // That is, "xmlns:..." or "xmlns" - if (starts_with(name, PUGIXML_TEXT("xmlns")) && (name[5] == 0 || name[5] == ':')) return; - - switch (_test) - { - case nodetest_name: - if (strequal(name, _data.nodetest)) ns.push_back(xpath_node(a, parent), alloc); - break; - - case nodetest_type_node: - case nodetest_all: - ns.push_back(xpath_node(a, parent), alloc); - break; - - case nodetest_all_in_namespace: - if (starts_with(name, _data.nodetest)) - ns.push_back(xpath_node(a, parent), alloc); - break; - - default: - ; - } - } - - void step_push(xpath_node_set_raw& ns, const xml_node& n, xpath_allocator* alloc) - { - if (!n) return; - - switch (_test) - { - case nodetest_name: - if (n.type() == node_element && strequal(n.name(), _data.nodetest)) ns.push_back(n, alloc); - break; - - case nodetest_type_node: - ns.push_back(n, alloc); - break; - - case nodetest_type_comment: - if (n.type() == node_comment) - ns.push_back(n, alloc); - break; - - case nodetest_type_text: - if (n.type() == node_pcdata || n.type() == node_cdata) - ns.push_back(n, alloc); - break; - - case nodetest_type_pi: - if (n.type() == node_pi) - ns.push_back(n, alloc); - break; - - case nodetest_pi: - if (n.type() == node_pi && strequal(n.name(), _data.nodetest)) - ns.push_back(n, alloc); - break; - - case nodetest_all: - if (n.type() == node_element) - ns.push_back(n, alloc); - break; - - case nodetest_all_in_namespace: - if (n.type() == node_element && starts_with(n.name(), _data.nodetest)) - ns.push_back(n, alloc); - break; - - default: - assert(!"Unknown axis"); - } - } - - template void step_fill(xpath_node_set_raw& ns, const xml_node& n, xpath_allocator* alloc, T) - { - const axis_t axis = T::axis; - - switch (axis) - { - case axis_attribute: - { - for (xml_attribute a = n.first_attribute(); a; a = a.next_attribute()) - step_push(ns, a, n, alloc); - - break; - } - - case axis_child: - { - for (xml_node c = n.first_child(); c; c = c.next_sibling()) - step_push(ns, c, alloc); - - break; - } - - case axis_descendant: - case axis_descendant_or_self: - { - if (axis == axis_descendant_or_self) - step_push(ns, n, alloc); - - xml_node cur = n.first_child(); - - while (cur && cur != n) - { - step_push(ns, cur, alloc); - - if (cur.first_child()) - cur = cur.first_child(); - else if (cur.next_sibling()) - cur = cur.next_sibling(); - else - { - while (!cur.next_sibling() && cur != n) - cur = cur.parent(); - - if (cur != n) cur = cur.next_sibling(); - } - } - - break; - } - - case axis_following_sibling: - { - for (xml_node c = n.next_sibling(); c; c = c.next_sibling()) - step_push(ns, c, alloc); - - break; - } - - case axis_preceding_sibling: - { - for (xml_node c = n.previous_sibling(); c; c = c.previous_sibling()) - step_push(ns, c, alloc); - - break; - } - - case axis_following: - { - xml_node cur = n; - - // exit from this node so that we don't include descendants - while (cur && !cur.next_sibling()) cur = cur.parent(); - cur = cur.next_sibling(); - - for (;;) - { - step_push(ns, cur, alloc); - - if (cur.first_child()) - cur = cur.first_child(); - else if (cur.next_sibling()) - cur = cur.next_sibling(); - else - { - while (cur && !cur.next_sibling()) cur = cur.parent(); - cur = cur.next_sibling(); - - if (!cur) break; - } - } - - break; - } - - case axis_preceding: - { - xml_node cur = n; - - while (cur && !cur.previous_sibling()) cur = cur.parent(); - cur = cur.previous_sibling(); - - for (;;) - { - if (cur.last_child()) - cur = cur.last_child(); - else - { - // leaf node, can't be ancestor - step_push(ns, cur, alloc); - - if (cur.previous_sibling()) - cur = cur.previous_sibling(); - else - { - do - { - cur = cur.parent(); - if (!cur) break; - - if (!node_is_ancestor(cur, n)) step_push(ns, cur, alloc); - } - while (!cur.previous_sibling()); - - cur = cur.previous_sibling(); - - if (!cur) break; - } - } - } - - break; - } - - case axis_ancestor: - case axis_ancestor_or_self: - { - if (axis == axis_ancestor_or_self) - step_push(ns, n, alloc); - - xml_node cur = n.parent(); - - while (cur) - { - step_push(ns, cur, alloc); - - cur = cur.parent(); - } - - break; - } - - case axis_self: - { - step_push(ns, n, alloc); - - break; - } - - case axis_parent: - { - if (n.parent()) step_push(ns, n.parent(), alloc); - - break; - } - - default: - assert(!"Unimplemented axis"); - } - } - - template void step_fill(xpath_node_set_raw& ns, const xml_attribute& a, const xml_node& p, xpath_allocator* alloc, T v) - { - const axis_t axis = T::axis; - - switch (axis) - { - case axis_ancestor: - case axis_ancestor_or_self: - { - if (axis == axis_ancestor_or_self && _test == nodetest_type_node) // reject attributes based on principal node type test - step_push(ns, a, p, alloc); - - xml_node cur = p; - - while (cur) - { - step_push(ns, cur, alloc); - - cur = cur.parent(); - } - - break; - } - - case axis_descendant_or_self: - case axis_self: - { - if (_test == nodetest_type_node) // reject attributes based on principal node type test - step_push(ns, a, p, alloc); - - break; - } - - case axis_following: - { - xml_node cur = p; - - for (;;) - { - if (cur.first_child()) - cur = cur.first_child(); - else if (cur.next_sibling()) - cur = cur.next_sibling(); - else - { - while (cur && !cur.next_sibling()) cur = cur.parent(); - cur = cur.next_sibling(); - - if (!cur) break; - } - - step_push(ns, cur, alloc); - } - - break; - } - - case axis_parent: - { - step_push(ns, p, alloc); - - break; - } - - case axis_preceding: - { - // preceding:: axis does not include attribute nodes and attribute ancestors (they are the same as parent's ancestors), so we can reuse node preceding - step_fill(ns, p, alloc, v); - break; - } - - default: - assert(!"Unimplemented axis"); - } - } - - template xpath_node_set_raw step_do(const xpath_context& c, const xpath_stack& stack, T v) - { - const axis_t axis = T::axis; - bool attributes = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_descendant_or_self || axis == axis_following || axis == axis_parent || axis == axis_preceding || axis == axis_self); - - xpath_node_set_raw ns; - ns.set_type((axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_preceding || axis == axis_preceding_sibling) ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted); - - if (_left) - { - xpath_node_set_raw s = _left->eval_node_set(c, stack); - - // self axis preserves the original order - if (axis == axis_self) ns.set_type(s.type()); - - for (const xpath_node* it = s.begin(); it != s.end(); ++it) - { - size_t size = ns.size(); - - // in general, all axes generate elements in a particular order, but there is no order guarantee if axis is applied to two nodes - if (axis != axis_self && size != 0) ns.set_type(xpath_node_set::type_unsorted); - - if (it->node()) - step_fill(ns, it->node(), stack.result, v); - else if (attributes) - step_fill(ns, it->attribute(), it->parent(), stack.result, v); - - apply_predicates(ns, size, stack); - } - } - else - { - if (c.n.node()) - step_fill(ns, c.n.node(), stack.result, v); - else if (attributes) - step_fill(ns, c.n.attribute(), c.n.parent(), stack.result, v); - - apply_predicates(ns, 0, stack); - } - - // child, attribute and self axes always generate unique set of nodes - // for other axis, if the set stayed sorted, it stayed unique because the traversal algorithms do not visit the same node twice - if (axis != axis_child && axis != axis_attribute && axis != axis_self && ns.type() == xpath_node_set::type_unsorted) - ns.remove_duplicates(); - - return ns; - } - - public: - xpath_ast_node(ast_type_t type, xpath_value_type rettype_, const char_t* value): - _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) - { - assert(type == ast_string_constant); - _data.string = value; - } - - xpath_ast_node(ast_type_t type, xpath_value_type rettype_, double value): - _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) - { - assert(type == ast_number_constant); - _data.number = value; - } - - xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_variable* value): - _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) - { - assert(type == ast_variable); - _data.variable = value; - } - - xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_ast_node* left = 0, xpath_ast_node* right = 0): - _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(left), _right(right), _next(0) - { - } - - xpath_ast_node(ast_type_t type, xpath_ast_node* left, axis_t axis, nodetest_t test, const char_t* contents): - _type(static_cast(type)), _rettype(xpath_type_node_set), _axis(static_cast(axis)), _test(static_cast(test)), _left(left), _right(0), _next(0) - { - _data.nodetest = contents; - } - - void set_next(xpath_ast_node* value) - { - _next = value; - } - - void set_right(xpath_ast_node* value) - { - _right = value; - } - - bool eval_boolean(const xpath_context& c, const xpath_stack& stack) - { - switch (_type) - { - case ast_op_or: - return _left->eval_boolean(c, stack) || _right->eval_boolean(c, stack); - - case ast_op_and: - return _left->eval_boolean(c, stack) && _right->eval_boolean(c, stack); - - case ast_op_equal: - return compare_eq(_left, _right, c, stack, equal_to()); - - case ast_op_not_equal: - return compare_eq(_left, _right, c, stack, not_equal_to()); - - case ast_op_less: - return compare_rel(_left, _right, c, stack, less()); - - case ast_op_greater: - return compare_rel(_right, _left, c, stack, less()); - - case ast_op_less_or_equal: - return compare_rel(_left, _right, c, stack, less_equal()); - - case ast_op_greater_or_equal: - return compare_rel(_right, _left, c, stack, less_equal()); - - case ast_func_starts_with: - { - xpath_allocator_capture cr(stack.result); - - xpath_string lr = _left->eval_string(c, stack); - xpath_string rr = _right->eval_string(c, stack); - - return starts_with(lr.c_str(), rr.c_str()); - } - - case ast_func_contains: - { - xpath_allocator_capture cr(stack.result); - - xpath_string lr = _left->eval_string(c, stack); - xpath_string rr = _right->eval_string(c, stack); - - return find_substring(lr.c_str(), rr.c_str()) != 0; - } - - case ast_func_boolean: - return _left->eval_boolean(c, stack); - - case ast_func_not: - return !_left->eval_boolean(c, stack); - - case ast_func_true: - return true; - - case ast_func_false: - return false; - - case ast_func_lang: - { - if (c.n.attribute()) return false; - - xpath_allocator_capture cr(stack.result); - - xpath_string lang = _left->eval_string(c, stack); - - for (xml_node n = c.n.node(); n; n = n.parent()) - { - xml_attribute a = n.attribute(PUGIXML_TEXT("xml:lang")); - - if (a) - { - const char_t* value = a.value(); - - // strnicmp / strncasecmp is not portable - for (const char_t* lit = lang.c_str(); *lit; ++lit) - { - if (tolower_ascii(*lit) != tolower_ascii(*value)) return false; - ++value; - } - - return *value == 0 || *value == '-'; - } - } - - return false; - } - - case ast_variable: - { - assert(_rettype == _data.variable->type()); - - if (_rettype == xpath_type_boolean) - return _data.variable->get_boolean(); - - // fallthrough to type conversion - } - - default: - { - switch (_rettype) - { - case xpath_type_number: - return convert_number_to_boolean(eval_number(c, stack)); - - case xpath_type_string: - { - xpath_allocator_capture cr(stack.result); - - return !eval_string(c, stack).empty(); - } - - case xpath_type_node_set: - { - xpath_allocator_capture cr(stack.result); - - return !eval_node_set(c, stack).empty(); - } - - default: - assert(!"Wrong expression for return type boolean"); - return false; - } - } - } - } - - double eval_number(const xpath_context& c, const xpath_stack& stack) - { - switch (_type) - { - case ast_op_add: - return _left->eval_number(c, stack) + _right->eval_number(c, stack); - - case ast_op_subtract: - return _left->eval_number(c, stack) - _right->eval_number(c, stack); - - case ast_op_multiply: - return _left->eval_number(c, stack) * _right->eval_number(c, stack); - - case ast_op_divide: - return _left->eval_number(c, stack) / _right->eval_number(c, stack); - - case ast_op_mod: - return fmod(_left->eval_number(c, stack), _right->eval_number(c, stack)); - - case ast_op_negate: - return -_left->eval_number(c, stack); - - case ast_number_constant: - return _data.number; - - case ast_func_last: - return static_cast(c.size); - - case ast_func_position: - return static_cast(c.position); - - case ast_func_count: - { - xpath_allocator_capture cr(stack.result); - - return static_cast(_left->eval_node_set(c, stack).size()); - } - - case ast_func_string_length_0: - { - xpath_allocator_capture cr(stack.result); - - return static_cast(string_value(c.n, stack.result).length()); - } - - case ast_func_string_length_1: - { - xpath_allocator_capture cr(stack.result); - - return static_cast(_left->eval_string(c, stack).length()); - } - - case ast_func_number_0: - { - xpath_allocator_capture cr(stack.result); - - return convert_string_to_number(string_value(c.n, stack.result).c_str()); - } - - case ast_func_number_1: - return _left->eval_number(c, stack); - - case ast_func_sum: - { - xpath_allocator_capture cr(stack.result); - - double r = 0; - - xpath_node_set_raw ns = _left->eval_node_set(c, stack); - - for (const xpath_node* it = ns.begin(); it != ns.end(); ++it) - { - xpath_allocator_capture cri(stack.result); - - r += convert_string_to_number(string_value(*it, stack.result).c_str()); - } - - return r; - } - - case ast_func_floor: - { - double r = _left->eval_number(c, stack); - - return r == r ? floor(r) : r; - } - - case ast_func_ceiling: - { - double r = _left->eval_number(c, stack); - - return r == r ? ceil(r) : r; - } - - case ast_func_round: - return round_nearest_nzero(_left->eval_number(c, stack)); - - case ast_variable: - { - assert(_rettype == _data.variable->type()); - - if (_rettype == xpath_type_number) - return _data.variable->get_number(); - - // fallthrough to type conversion - } - - default: - { - switch (_rettype) - { - case xpath_type_boolean: - return eval_boolean(c, stack) ? 1 : 0; - - case xpath_type_string: - { - xpath_allocator_capture cr(stack.result); - - return convert_string_to_number(eval_string(c, stack).c_str()); - } - - case xpath_type_node_set: - { - xpath_allocator_capture cr(stack.result); - - return convert_string_to_number(eval_string(c, stack).c_str()); - } - - default: - assert(!"Wrong expression for return type number"); - return 0; - } - - } - } - } - - xpath_string eval_string_concat(const xpath_context& c, const xpath_stack& stack) - { - assert(_type == ast_func_concat); - - xpath_allocator_capture ct(stack.temp); - - // count the string number - size_t count = 1; - for (xpath_ast_node* nc = _right; nc; nc = nc->_next) count++; - - // gather all strings - xpath_string static_buffer[4]; - xpath_string* buffer = static_buffer; - - // allocate on-heap for large concats - if (count > sizeof(static_buffer) / sizeof(static_buffer[0])) - { - buffer = static_cast(stack.temp->allocate(count * sizeof(xpath_string))); - assert(buffer); - } - - // evaluate all strings to temporary stack - xpath_stack swapped_stack = {stack.temp, stack.result}; - - buffer[0] = _left->eval_string(c, swapped_stack); - - size_t pos = 1; - for (xpath_ast_node* n = _right; n; n = n->_next, ++pos) buffer[pos] = n->eval_string(c, swapped_stack); - assert(pos == count); - - // get total length - size_t length = 0; - for (size_t i = 0; i < count; ++i) length += buffer[i].length(); - - // create final string - char_t* result = static_cast(stack.result->allocate((length + 1) * sizeof(char_t))); - assert(result); - - char_t* ri = result; - - for (size_t j = 0; j < count; ++j) - for (const char_t* bi = buffer[j].c_str(); *bi; ++bi) - *ri++ = *bi; - - *ri = 0; - - return xpath_string(result, true); - } - - xpath_string eval_string(const xpath_context& c, const xpath_stack& stack) - { - switch (_type) - { - case ast_string_constant: - return xpath_string_const(_data.string); - - case ast_func_local_name_0: - { - xpath_node na = c.n; - - return xpath_string_const(local_name(na)); - } - - case ast_func_local_name_1: - { - xpath_allocator_capture cr(stack.result); - - xpath_node_set_raw ns = _left->eval_node_set(c, stack); - xpath_node na = ns.first(); - - return xpath_string_const(local_name(na)); - } - - case ast_func_name_0: - { - xpath_node na = c.n; - - return xpath_string_const(qualified_name(na)); - } - - case ast_func_name_1: - { - xpath_allocator_capture cr(stack.result); - - xpath_node_set_raw ns = _left->eval_node_set(c, stack); - xpath_node na = ns.first(); - - return xpath_string_const(qualified_name(na)); - } - - case ast_func_namespace_uri_0: - { - xpath_node na = c.n; - - return xpath_string_const(namespace_uri(na)); - } - - case ast_func_namespace_uri_1: - { - xpath_allocator_capture cr(stack.result); - - xpath_node_set_raw ns = _left->eval_node_set(c, stack); - xpath_node na = ns.first(); - - return xpath_string_const(namespace_uri(na)); - } - - case ast_func_string_0: - return string_value(c.n, stack.result); - - case ast_func_string_1: - return _left->eval_string(c, stack); - - case ast_func_concat: - return eval_string_concat(c, stack); - - case ast_func_substring_before: - { - xpath_allocator_capture cr(stack.temp); - - xpath_stack swapped_stack = {stack.temp, stack.result}; - - xpath_string s = _left->eval_string(c, swapped_stack); - xpath_string p = _right->eval_string(c, swapped_stack); - - const char_t* pos = find_substring(s.c_str(), p.c_str()); - - return pos ? xpath_string(s.c_str(), pos, stack.result) : xpath_string(); - } - - case ast_func_substring_after: - { - xpath_allocator_capture cr(stack.temp); - - xpath_stack swapped_stack = {stack.temp, stack.result}; - - xpath_string s = _left->eval_string(c, swapped_stack); - xpath_string p = _right->eval_string(c, swapped_stack); - - const char_t* pos = find_substring(s.c_str(), p.c_str()); - if (!pos) return xpath_string(); - - const char_t* result = pos + p.length(); - - return s.uses_heap() ? xpath_string(result, stack.result) : xpath_string_const(result); - } - - case ast_func_substring_2: - { - xpath_allocator_capture cr(stack.temp); - - xpath_stack swapped_stack = {stack.temp, stack.result}; - - xpath_string s = _left->eval_string(c, swapped_stack); - size_t s_length = s.length(); - - double first = round_nearest(_right->eval_number(c, stack)); - - if (is_nan(first)) return xpath_string(); // NaN - else if (first >= s_length + 1) return xpath_string(); - - size_t pos = first < 1 ? 1 : static_cast(first); - assert(1 <= pos && pos <= s_length + 1); - - const char_t* rbegin = s.c_str() + (pos - 1); - - return s.uses_heap() ? xpath_string(rbegin, stack.result) : xpath_string_const(rbegin); - } - - case ast_func_substring_3: - { - xpath_allocator_capture cr(stack.temp); - - xpath_stack swapped_stack = {stack.temp, stack.result}; - - xpath_string s = _left->eval_string(c, swapped_stack); - size_t s_length = s.length(); - - double first = round_nearest(_right->eval_number(c, stack)); - double last = first + round_nearest(_right->_next->eval_number(c, stack)); - - if (is_nan(first) || is_nan(last)) return xpath_string(); - else if (first >= s_length + 1) return xpath_string(); - else if (first >= last) return xpath_string(); - else if (last < 1) return xpath_string(); - - size_t pos = first < 1 ? 1 : static_cast(first); - size_t end = last >= s_length + 1 ? s_length + 1 : static_cast(last); - - assert(1 <= pos && pos <= end && end <= s_length + 1); - const char_t* rbegin = s.c_str() + (pos - 1); - const char_t* rend = s.c_str() + (end - 1); - - return (end == s_length + 1 && !s.uses_heap()) ? xpath_string_const(rbegin) : xpath_string(rbegin, rend, stack.result); - } - - case ast_func_normalize_space_0: - { - xpath_string s = string_value(c.n, stack.result); - - normalize_space(s.data(stack.result)); - - return s; - } - - case ast_func_normalize_space_1: - { - xpath_string s = _left->eval_string(c, stack); - - normalize_space(s.data(stack.result)); - - return s; - } - - case ast_func_translate: - { - xpath_allocator_capture cr(stack.temp); - - xpath_stack swapped_stack = {stack.temp, stack.result}; - - xpath_string s = _left->eval_string(c, stack); - xpath_string from = _right->eval_string(c, swapped_stack); - xpath_string to = _right->_next->eval_string(c, swapped_stack); - - translate(s.data(stack.result), from.c_str(), to.c_str()); - - return s; - } - - case ast_variable: - { - assert(_rettype == _data.variable->type()); - - if (_rettype == xpath_type_string) - return xpath_string_const(_data.variable->get_string()); - - // fallthrough to type conversion - } - - default: - { - switch (_rettype) - { - case xpath_type_boolean: - return xpath_string_const(eval_boolean(c, stack) ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false")); - - case xpath_type_number: - return convert_number_to_string(eval_number(c, stack), stack.result); - - case xpath_type_node_set: - { - xpath_allocator_capture cr(stack.temp); - - xpath_stack swapped_stack = {stack.temp, stack.result}; - - xpath_node_set_raw ns = eval_node_set(c, swapped_stack); - return ns.empty() ? xpath_string() : string_value(ns.first(), stack.result); - } - - default: - assert(!"Wrong expression for return type string"); - return xpath_string(); - } - } - } - } - - xpath_node_set_raw eval_node_set(const xpath_context& c, const xpath_stack& stack) - { - switch (_type) - { - case ast_op_union: - { - xpath_allocator_capture cr(stack.temp); - - xpath_stack swapped_stack = {stack.temp, stack.result}; - - xpath_node_set_raw ls = _left->eval_node_set(c, swapped_stack); - xpath_node_set_raw rs = _right->eval_node_set(c, stack); - - // we can optimize merging two sorted sets, but this is a very rare operation, so don't bother - rs.set_type(xpath_node_set::type_unsorted); - - rs.append(ls.begin(), ls.end(), stack.result); - rs.remove_duplicates(); - - return rs; - } - - case ast_filter: - case ast_filter_posinv: - { - xpath_node_set_raw set = _left->eval_node_set(c, stack); - - // either expression is a number or it contains position() call; sort by document order - if (_type == ast_filter) set.sort_do(); - - apply_predicate(set, 0, _right, stack); - - return set; - } - - case ast_func_id: - return xpath_node_set_raw(); - - case ast_step: - { - switch (_axis) - { - case axis_ancestor: - return step_do(c, stack, axis_to_type()); - - case axis_ancestor_or_self: - return step_do(c, stack, axis_to_type()); - - case axis_attribute: - return step_do(c, stack, axis_to_type()); - - case axis_child: - return step_do(c, stack, axis_to_type()); - - case axis_descendant: - return step_do(c, stack, axis_to_type()); - - case axis_descendant_or_self: - return step_do(c, stack, axis_to_type()); - - case axis_following: - return step_do(c, stack, axis_to_type()); - - case axis_following_sibling: - return step_do(c, stack, axis_to_type()); - - case axis_namespace: - // namespaced axis is not supported - return xpath_node_set_raw(); - - case axis_parent: - return step_do(c, stack, axis_to_type()); - - case axis_preceding: - return step_do(c, stack, axis_to_type()); - - case axis_preceding_sibling: - return step_do(c, stack, axis_to_type()); - - case axis_self: - return step_do(c, stack, axis_to_type()); - - default: - assert(!"Unknown axis"); - return xpath_node_set_raw(); - } - } - - case ast_step_root: - { - assert(!_right); // root step can't have any predicates - - xpath_node_set_raw ns; - - ns.set_type(xpath_node_set::type_sorted); - - if (c.n.node()) ns.push_back(c.n.node().root(), stack.result); - else if (c.n.attribute()) ns.push_back(c.n.parent().root(), stack.result); - - return ns; - } - - case ast_variable: - { - assert(_rettype == _data.variable->type()); - - if (_rettype == xpath_type_node_set) - { - const xpath_node_set& s = _data.variable->get_node_set(); - - xpath_node_set_raw ns; - - ns.set_type(s.type()); - ns.append(s.begin(), s.end(), stack.result); - - return ns; - } - - // fallthrough to type conversion - } - - default: - assert(!"Wrong expression for return type node set"); - return xpath_node_set_raw(); - } - } - - bool is_posinv() - { - switch (_type) - { - case ast_func_position: - return false; - - case ast_string_constant: - case ast_number_constant: - case ast_variable: - return true; - - case ast_step: - case ast_step_root: - return true; - - case ast_predicate: - case ast_filter: - case ast_filter_posinv: - return true; - - default: - if (_left && !_left->is_posinv()) return false; - - for (xpath_ast_node* n = _right; n; n = n->_next) - if (!n->is_posinv()) return false; - - return true; - } - } - - xpath_value_type rettype() const - { - return static_cast(_rettype); - } - }; - - struct xpath_parser - { - xpath_allocator* _alloc; - xpath_lexer _lexer; - - const char_t* _query; - xpath_variable_set* _variables; - - xpath_parse_result* _result; - - #ifdef PUGIXML_NO_EXCEPTIONS - jmp_buf _error_handler; - #endif - - void throw_error(const char* message) - { - _result->error = message; - _result->offset = _lexer.current_pos() - _query; - - #ifdef PUGIXML_NO_EXCEPTIONS - longjmp(_error_handler, 1); - #else - throw xpath_exception(*_result); - #endif - } - - void throw_error_oom() - { - #ifdef PUGIXML_NO_EXCEPTIONS - throw_error("Out of memory"); - #else - throw std::bad_alloc(); - #endif - } - - void* alloc_node() - { - void* result = _alloc->allocate_nothrow(sizeof(xpath_ast_node)); - - if (!result) throw_error_oom(); - - return result; - } - - const char_t* alloc_string(const xpath_lexer_string& value) - { - if (value.begin) - { - size_t length = static_cast(value.end - value.begin); - - char_t* c = static_cast(_alloc->allocate_nothrow((length + 1) * sizeof(char_t))); - if (!c) throw_error_oom(); - - memcpy(c, value.begin, length * sizeof(char_t)); - c[length] = 0; - - return c; - } - else return 0; - } - - xpath_ast_node* parse_function_helper(ast_type_t type0, ast_type_t type1, size_t argc, xpath_ast_node* args[2]) - { - assert(argc <= 1); - - if (argc == 1 && args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set"); - - return new (alloc_node()) xpath_ast_node(argc == 0 ? type0 : type1, xpath_type_string, args[0]); - } - - xpath_ast_node* parse_function(const xpath_lexer_string& name, size_t argc, xpath_ast_node* args[2]) - { - switch (name.begin[0]) - { - case 'b': - if (name == PUGIXML_TEXT("boolean") && argc == 1) - return new (alloc_node()) xpath_ast_node(ast_func_boolean, xpath_type_boolean, args[0]); - - break; - - case 'c': - if (name == PUGIXML_TEXT("count") && argc == 1) - { - if (args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set"); - return new (alloc_node()) xpath_ast_node(ast_func_count, xpath_type_number, args[0]); - } - else if (name == PUGIXML_TEXT("contains") && argc == 2) - return new (alloc_node()) xpath_ast_node(ast_func_contains, xpath_type_string, args[0], args[1]); - else if (name == PUGIXML_TEXT("concat") && argc >= 2) - return new (alloc_node()) xpath_ast_node(ast_func_concat, xpath_type_string, args[0], args[1]); - else if (name == PUGIXML_TEXT("ceiling") && argc == 1) - return new (alloc_node()) xpath_ast_node(ast_func_ceiling, xpath_type_number, args[0]); - - break; - - case 'f': - if (name == PUGIXML_TEXT("false") && argc == 0) - return new (alloc_node()) xpath_ast_node(ast_func_false, xpath_type_boolean); - else if (name == PUGIXML_TEXT("floor") && argc == 1) - return new (alloc_node()) xpath_ast_node(ast_func_floor, xpath_type_number, args[0]); - - break; - - case 'i': - if (name == PUGIXML_TEXT("id") && argc == 1) - return new (alloc_node()) xpath_ast_node(ast_func_id, xpath_type_node_set, args[0]); - - break; - - case 'l': - if (name == PUGIXML_TEXT("last") && argc == 0) - return new (alloc_node()) xpath_ast_node(ast_func_last, xpath_type_number); - else if (name == PUGIXML_TEXT("lang") && argc == 1) - return new (alloc_node()) xpath_ast_node(ast_func_lang, xpath_type_boolean, args[0]); - else if (name == PUGIXML_TEXT("local-name") && argc <= 1) - return parse_function_helper(ast_func_local_name_0, ast_func_local_name_1, argc, args); - - break; - - case 'n': - if (name == PUGIXML_TEXT("name") && argc <= 1) - return parse_function_helper(ast_func_name_0, ast_func_name_1, argc, args); - else if (name == PUGIXML_TEXT("namespace-uri") && argc <= 1) - return parse_function_helper(ast_func_namespace_uri_0, ast_func_namespace_uri_1, argc, args); - else if (name == PUGIXML_TEXT("normalize-space") && argc <= 1) - return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_normalize_space_0 : ast_func_normalize_space_1, xpath_type_string, args[0], args[1]); - else if (name == PUGIXML_TEXT("not") && argc == 1) - return new (alloc_node()) xpath_ast_node(ast_func_not, xpath_type_boolean, args[0]); - else if (name == PUGIXML_TEXT("number") && argc <= 1) - return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_number_0 : ast_func_number_1, xpath_type_number, args[0]); - - break; - - case 'p': - if (name == PUGIXML_TEXT("position") && argc == 0) - return new (alloc_node()) xpath_ast_node(ast_func_position, xpath_type_number); - - break; - - case 'r': - if (name == PUGIXML_TEXT("round") && argc == 1) - return new (alloc_node()) xpath_ast_node(ast_func_round, xpath_type_number, args[0]); - - break; - - case 's': - if (name == PUGIXML_TEXT("string") && argc <= 1) - return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_string_0 : ast_func_string_1, xpath_type_string, args[0]); - else if (name == PUGIXML_TEXT("string-length") && argc <= 1) - return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_string_length_0 : ast_func_string_length_1, xpath_type_string, args[0]); - else if (name == PUGIXML_TEXT("starts-with") && argc == 2) - return new (alloc_node()) xpath_ast_node(ast_func_starts_with, xpath_type_boolean, args[0], args[1]); - else if (name == PUGIXML_TEXT("substring-before") && argc == 2) - return new (alloc_node()) xpath_ast_node(ast_func_substring_before, xpath_type_string, args[0], args[1]); - else if (name == PUGIXML_TEXT("substring-after") && argc == 2) - return new (alloc_node()) xpath_ast_node(ast_func_substring_after, xpath_type_string, args[0], args[1]); - else if (name == PUGIXML_TEXT("substring") && (argc == 2 || argc == 3)) - return new (alloc_node()) xpath_ast_node(argc == 2 ? ast_func_substring_2 : ast_func_substring_3, xpath_type_string, args[0], args[1]); - else if (name == PUGIXML_TEXT("sum") && argc == 1) - { - if (args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set"); - return new (alloc_node()) xpath_ast_node(ast_func_sum, xpath_type_number, args[0]); - } - - break; - - case 't': - if (name == PUGIXML_TEXT("translate") && argc == 3) - return new (alloc_node()) xpath_ast_node(ast_func_translate, xpath_type_string, args[0], args[1]); - else if (name == PUGIXML_TEXT("true") && argc == 0) - return new (alloc_node()) xpath_ast_node(ast_func_true, xpath_type_boolean); - - break; - - default: - break; - } - - throw_error("Unrecognized function or wrong parameter count"); - - return 0; - } - - axis_t parse_axis_name(const xpath_lexer_string& name, bool& specified) - { - specified = true; - - switch (name.begin[0]) - { - case 'a': - if (name == PUGIXML_TEXT("ancestor")) - return axis_ancestor; - else if (name == PUGIXML_TEXT("ancestor-or-self")) - return axis_ancestor_or_self; - else if (name == PUGIXML_TEXT("attribute")) - return axis_attribute; - - break; - - case 'c': - if (name == PUGIXML_TEXT("child")) - return axis_child; - - break; - - case 'd': - if (name == PUGIXML_TEXT("descendant")) - return axis_descendant; - else if (name == PUGIXML_TEXT("descendant-or-self")) - return axis_descendant_or_self; - - break; - - case 'f': - if (name == PUGIXML_TEXT("following")) - return axis_following; - else if (name == PUGIXML_TEXT("following-sibling")) - return axis_following_sibling; - - break; - - case 'n': - if (name == PUGIXML_TEXT("namespace")) - return axis_namespace; - - break; - - case 'p': - if (name == PUGIXML_TEXT("parent")) - return axis_parent; - else if (name == PUGIXML_TEXT("preceding")) - return axis_preceding; - else if (name == PUGIXML_TEXT("preceding-sibling")) - return axis_preceding_sibling; - - break; - - case 's': - if (name == PUGIXML_TEXT("self")) - return axis_self; - - break; - - default: - break; - } - - specified = false; - return axis_child; - } - - nodetest_t parse_node_test_type(const xpath_lexer_string& name) - { - switch (name.begin[0]) - { - case 'c': - if (name == PUGIXML_TEXT("comment")) - return nodetest_type_comment; - - break; - - case 'n': - if (name == PUGIXML_TEXT("node")) - return nodetest_type_node; - - break; - - case 'p': - if (name == PUGIXML_TEXT("processing-instruction")) - return nodetest_type_pi; - - break; - - case 't': - if (name == PUGIXML_TEXT("text")) - return nodetest_type_text; - - break; - - default: - break; - } - - return nodetest_none; - } - - // PrimaryExpr ::= VariableReference | '(' Expr ')' | Literal | Number | FunctionCall - xpath_ast_node* parse_primary_expression() - { - switch (_lexer.current()) - { - case lex_var_ref: - { - xpath_lexer_string name = _lexer.contents(); - - if (!_variables) - throw_error("Unknown variable: variable set is not provided"); - - xpath_variable* var = get_variable(_variables, name.begin, name.end); - - if (!var) - throw_error("Unknown variable: variable set does not contain the given name"); - - _lexer.next(); - - return new (alloc_node()) xpath_ast_node(ast_variable, var->type(), var); - } - - case lex_open_brace: - { - _lexer.next(); - - xpath_ast_node* n = parse_expression(); - - if (_lexer.current() != lex_close_brace) - throw_error("Unmatched braces"); - - _lexer.next(); - - return n; - } - - case lex_quoted_string: - { - const char_t* value = alloc_string(_lexer.contents()); - - xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_string_constant, xpath_type_string, value); - _lexer.next(); - - return n; - } - - case lex_number: - { - double value = 0; - - if (!convert_string_to_number(_lexer.contents().begin, _lexer.contents().end, &value)) - throw_error_oom(); - - xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_number_constant, xpath_type_number, value); - _lexer.next(); - - return n; - } - - case lex_string: - { - xpath_ast_node* args[2] = {0}; - size_t argc = 0; - - xpath_lexer_string function = _lexer.contents(); - _lexer.next(); - - xpath_ast_node* last_arg = 0; - - if (_lexer.current() != lex_open_brace) - throw_error("Unrecognized function call"); - _lexer.next(); - - if (_lexer.current() != lex_close_brace) - args[argc++] = parse_expression(); - - while (_lexer.current() != lex_close_brace) - { - if (_lexer.current() != lex_comma) - throw_error("No comma between function arguments"); - _lexer.next(); - - xpath_ast_node* n = parse_expression(); - - if (argc < 2) args[argc] = n; - else last_arg->set_next(n); - - argc++; - last_arg = n; - } - - _lexer.next(); - - return parse_function(function, argc, args); - } - - default: - throw_error("Unrecognizable primary expression"); - - return 0; - } - } - - // FilterExpr ::= PrimaryExpr | FilterExpr Predicate - // Predicate ::= '[' PredicateExpr ']' - // PredicateExpr ::= Expr - xpath_ast_node* parse_filter_expression() - { - xpath_ast_node* n = parse_primary_expression(); - - while (_lexer.current() == lex_open_square_brace) - { - _lexer.next(); - - xpath_ast_node* expr = parse_expression(); - - if (n->rettype() != xpath_type_node_set) throw_error("Predicate has to be applied to node set"); - - bool posinv = expr->rettype() != xpath_type_number && expr->is_posinv(); - - n = new (alloc_node()) xpath_ast_node(posinv ? ast_filter_posinv : ast_filter, xpath_type_node_set, n, expr); - - if (_lexer.current() != lex_close_square_brace) - throw_error("Unmatched square brace"); - - _lexer.next(); - } - - return n; - } - - // Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep - // AxisSpecifier ::= AxisName '::' | '@'? - // NodeTest ::= NameTest | NodeType '(' ')' | 'processing-instruction' '(' Literal ')' - // NameTest ::= '*' | NCName ':' '*' | QName - // AbbreviatedStep ::= '.' | '..' - xpath_ast_node* parse_step(xpath_ast_node* set) - { - if (set && set->rettype() != xpath_type_node_set) - throw_error("Step has to be applied to node set"); - - bool axis_specified = false; - axis_t axis = axis_child; // implied child axis - - if (_lexer.current() == lex_axis_attribute) - { - axis = axis_attribute; - axis_specified = true; - - _lexer.next(); - } - else if (_lexer.current() == lex_dot) - { - _lexer.next(); - - return new (alloc_node()) xpath_ast_node(ast_step, set, axis_self, nodetest_type_node, 0); - } - else if (_lexer.current() == lex_double_dot) - { - _lexer.next(); - - return new (alloc_node()) xpath_ast_node(ast_step, set, axis_parent, nodetest_type_node, 0); - } - - nodetest_t nt_type = nodetest_none; - xpath_lexer_string nt_name; - - if (_lexer.current() == lex_string) - { - // node name test - nt_name = _lexer.contents(); - _lexer.next(); - - // was it an axis name? - if (_lexer.current() == lex_double_colon) - { - // parse axis name - if (axis_specified) throw_error("Two axis specifiers in one step"); - - axis = parse_axis_name(nt_name, axis_specified); - - if (!axis_specified) throw_error("Unknown axis"); - - // read actual node test - _lexer.next(); - - if (_lexer.current() == lex_multiply) - { - nt_type = nodetest_all; - nt_name = xpath_lexer_string(); - _lexer.next(); - } - else if (_lexer.current() == lex_string) - { - nt_name = _lexer.contents(); - _lexer.next(); - } - else throw_error("Unrecognized node test"); - } - - if (nt_type == nodetest_none) - { - // node type test or processing-instruction - if (_lexer.current() == lex_open_brace) - { - _lexer.next(); - - if (_lexer.current() == lex_close_brace) - { - _lexer.next(); - - nt_type = parse_node_test_type(nt_name); - - if (nt_type == nodetest_none) throw_error("Unrecognized node type"); - - nt_name = xpath_lexer_string(); - } - else if (nt_name == PUGIXML_TEXT("processing-instruction")) - { - if (_lexer.current() != lex_quoted_string) - throw_error("Only literals are allowed as arguments to processing-instruction()"); - - nt_type = nodetest_pi; - nt_name = _lexer.contents(); - _lexer.next(); - - if (_lexer.current() != lex_close_brace) - throw_error("Unmatched brace near processing-instruction()"); - _lexer.next(); - } - else - throw_error("Unmatched brace near node type test"); - - } - // QName or NCName:* - else - { - if (nt_name.end - nt_name.begin > 2 && nt_name.end[-2] == ':' && nt_name.end[-1] == '*') // NCName:* - { - nt_name.end--; // erase * - - nt_type = nodetest_all_in_namespace; - } - else nt_type = nodetest_name; - } - } - } - else if (_lexer.current() == lex_multiply) - { - nt_type = nodetest_all; - _lexer.next(); - } - else throw_error("Unrecognized node test"); - - xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step, set, axis, nt_type, alloc_string(nt_name)); - - xpath_ast_node* last = 0; - - while (_lexer.current() == lex_open_square_brace) - { - _lexer.next(); - - xpath_ast_node* expr = parse_expression(); - - xpath_ast_node* pred = new (alloc_node()) xpath_ast_node(ast_predicate, xpath_type_node_set, expr); - - if (_lexer.current() != lex_close_square_brace) - throw_error("Unmatched square brace"); - _lexer.next(); - - if (last) last->set_next(pred); - else n->set_right(pred); - - last = pred; - } - - return n; - } - - // RelativeLocationPath ::= Step | RelativeLocationPath '/' Step | RelativeLocationPath '//' Step - xpath_ast_node* parse_relative_location_path(xpath_ast_node* set) - { - xpath_ast_node* n = parse_step(set); - - while (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash) - { - lexeme_t l = _lexer.current(); - _lexer.next(); - - if (l == lex_double_slash) - n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); - - n = parse_step(n); - } - - return n; - } - - // LocationPath ::= RelativeLocationPath | AbsoluteLocationPath - // AbsoluteLocationPath ::= '/' RelativeLocationPath? | '//' RelativeLocationPath - xpath_ast_node* parse_location_path() - { - if (_lexer.current() == lex_slash) - { - _lexer.next(); - - xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step_root, xpath_type_node_set); - - // relative location path can start from axis_attribute, dot, double_dot, multiply and string lexemes; any other lexeme means standalone root path - lexeme_t l = _lexer.current(); - - if (l == lex_string || l == lex_axis_attribute || l == lex_dot || l == lex_double_dot || l == lex_multiply) - return parse_relative_location_path(n); - else - return n; - } - else if (_lexer.current() == lex_double_slash) - { - _lexer.next(); - - xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step_root, xpath_type_node_set); - n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); - - return parse_relative_location_path(n); - } - - // else clause moved outside of if because of bogus warning 'control may reach end of non-void function being inlined' in gcc 4.0.1 - return parse_relative_location_path(0); - } - - // PathExpr ::= LocationPath - // | FilterExpr - // | FilterExpr '/' RelativeLocationPath - // | FilterExpr '//' RelativeLocationPath - xpath_ast_node* parse_path_expression() - { - // Clarification. - // PathExpr begins with either LocationPath or FilterExpr. - // FilterExpr begins with PrimaryExpr - // PrimaryExpr begins with '$' in case of it being a variable reference, - // '(' in case of it being an expression, string literal, number constant or - // function call. - - if (_lexer.current() == lex_var_ref || _lexer.current() == lex_open_brace || - _lexer.current() == lex_quoted_string || _lexer.current() == lex_number || - _lexer.current() == lex_string) - { - if (_lexer.current() == lex_string) - { - // This is either a function call, or not - if not, we shall proceed with location path - const char_t* state = _lexer.state(); - - while (PUGI__IS_CHARTYPE(*state, ct_space)) ++state; - - if (*state != '(') return parse_location_path(); - - // This looks like a function call; however this still can be a node-test. Check it. - if (parse_node_test_type(_lexer.contents()) != nodetest_none) return parse_location_path(); - } - - xpath_ast_node* n = parse_filter_expression(); - - if (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash) - { - lexeme_t l = _lexer.current(); - _lexer.next(); - - if (l == lex_double_slash) - { - if (n->rettype() != xpath_type_node_set) throw_error("Step has to be applied to node set"); - - n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); - } - - // select from location path - return parse_relative_location_path(n); - } - - return n; - } - else return parse_location_path(); - } - - // UnionExpr ::= PathExpr | UnionExpr '|' PathExpr - xpath_ast_node* parse_union_expression() - { - xpath_ast_node* n = parse_path_expression(); - - while (_lexer.current() == lex_union) - { - _lexer.next(); - - xpath_ast_node* expr = parse_union_expression(); - - if (n->rettype() != xpath_type_node_set || expr->rettype() != xpath_type_node_set) - throw_error("Union operator has to be applied to node sets"); - - n = new (alloc_node()) xpath_ast_node(ast_op_union, xpath_type_node_set, n, expr); - } - - return n; - } - - // UnaryExpr ::= UnionExpr | '-' UnaryExpr - xpath_ast_node* parse_unary_expression() - { - if (_lexer.current() == lex_minus) - { - _lexer.next(); - - xpath_ast_node* expr = parse_unary_expression(); - - return new (alloc_node()) xpath_ast_node(ast_op_negate, xpath_type_number, expr); - } - else return parse_union_expression(); - } - - // MultiplicativeExpr ::= UnaryExpr - // | MultiplicativeExpr '*' UnaryExpr - // | MultiplicativeExpr 'div' UnaryExpr - // | MultiplicativeExpr 'mod' UnaryExpr - xpath_ast_node* parse_multiplicative_expression() - { - xpath_ast_node* n = parse_unary_expression(); - - while (_lexer.current() == lex_multiply || (_lexer.current() == lex_string && - (_lexer.contents() == PUGIXML_TEXT("mod") || _lexer.contents() == PUGIXML_TEXT("div")))) - { - ast_type_t op = _lexer.current() == lex_multiply ? ast_op_multiply : - _lexer.contents().begin[0] == 'd' ? ast_op_divide : ast_op_mod; - _lexer.next(); - - xpath_ast_node* expr = parse_unary_expression(); - - n = new (alloc_node()) xpath_ast_node(op, xpath_type_number, n, expr); - } - - return n; - } - - // AdditiveExpr ::= MultiplicativeExpr - // | AdditiveExpr '+' MultiplicativeExpr - // | AdditiveExpr '-' MultiplicativeExpr - xpath_ast_node* parse_additive_expression() - { - xpath_ast_node* n = parse_multiplicative_expression(); - - while (_lexer.current() == lex_plus || _lexer.current() == lex_minus) - { - lexeme_t l = _lexer.current(); - - _lexer.next(); - - xpath_ast_node* expr = parse_multiplicative_expression(); - - n = new (alloc_node()) xpath_ast_node(l == lex_plus ? ast_op_add : ast_op_subtract, xpath_type_number, n, expr); - } - - return n; - } - - // RelationalExpr ::= AdditiveExpr - // | RelationalExpr '<' AdditiveExpr - // | RelationalExpr '>' AdditiveExpr - // | RelationalExpr '<=' AdditiveExpr - // | RelationalExpr '>=' AdditiveExpr - xpath_ast_node* parse_relational_expression() - { - xpath_ast_node* n = parse_additive_expression(); - - while (_lexer.current() == lex_less || _lexer.current() == lex_less_or_equal || - _lexer.current() == lex_greater || _lexer.current() == lex_greater_or_equal) - { - lexeme_t l = _lexer.current(); - _lexer.next(); - - xpath_ast_node* expr = parse_additive_expression(); - - n = new (alloc_node()) xpath_ast_node(l == lex_less ? ast_op_less : l == lex_greater ? ast_op_greater : - l == lex_less_or_equal ? ast_op_less_or_equal : ast_op_greater_or_equal, xpath_type_boolean, n, expr); - } - - return n; - } - - // EqualityExpr ::= RelationalExpr - // | EqualityExpr '=' RelationalExpr - // | EqualityExpr '!=' RelationalExpr - xpath_ast_node* parse_equality_expression() - { - xpath_ast_node* n = parse_relational_expression(); - - while (_lexer.current() == lex_equal || _lexer.current() == lex_not_equal) - { - lexeme_t l = _lexer.current(); - - _lexer.next(); - - xpath_ast_node* expr = parse_relational_expression(); - - n = new (alloc_node()) xpath_ast_node(l == lex_equal ? ast_op_equal : ast_op_not_equal, xpath_type_boolean, n, expr); - } - - return n; - } - - // AndExpr ::= EqualityExpr | AndExpr 'and' EqualityExpr - xpath_ast_node* parse_and_expression() - { - xpath_ast_node* n = parse_equality_expression(); - - while (_lexer.current() == lex_string && _lexer.contents() == PUGIXML_TEXT("and")) - { - _lexer.next(); - - xpath_ast_node* expr = parse_equality_expression(); - - n = new (alloc_node()) xpath_ast_node(ast_op_and, xpath_type_boolean, n, expr); - } - - return n; - } - - // OrExpr ::= AndExpr | OrExpr 'or' AndExpr - xpath_ast_node* parse_or_expression() - { - xpath_ast_node* n = parse_and_expression(); - - while (_lexer.current() == lex_string && _lexer.contents() == PUGIXML_TEXT("or")) - { - _lexer.next(); - - xpath_ast_node* expr = parse_and_expression(); - - n = new (alloc_node()) xpath_ast_node(ast_op_or, xpath_type_boolean, n, expr); - } - - return n; - } - - // Expr ::= OrExpr - xpath_ast_node* parse_expression() - { - return parse_or_expression(); - } - - xpath_parser(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result): _alloc(alloc), _lexer(query), _query(query), _variables(variables), _result(result) - { - } - - xpath_ast_node* parse() - { - xpath_ast_node* result = parse_expression(); - - if (_lexer.current() != lex_eof) - { - // there are still unparsed tokens left, error - throw_error("Incorrect query"); - } - - return result; - } - - static xpath_ast_node* parse(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result) - { - xpath_parser parser(query, variables, alloc, result); - - #ifdef PUGIXML_NO_EXCEPTIONS - int error = setjmp(parser._error_handler); - - return (error == 0) ? parser.parse() : 0; - #else - return parser.parse(); - #endif - } - }; - - struct xpath_query_impl - { - static xpath_query_impl* create() - { - void* memory = xml_memory::allocate(sizeof(xpath_query_impl)); - - return new (memory) xpath_query_impl(); - } - - static void destroy(void* ptr) - { - if (!ptr) return; - - // free all allocated pages - static_cast(ptr)->alloc.release(); - - // free allocator memory (with the first page) - xml_memory::deallocate(ptr); - } - - xpath_query_impl(): root(0), alloc(&block) - { - block.next = 0; - } - - xpath_ast_node* root; - xpath_allocator alloc; - xpath_memory_block block; - }; - - PUGI__FN xpath_string evaluate_string_impl(xpath_query_impl* impl, const xpath_node& n, xpath_stack_data& sd) - { - if (!impl) return xpath_string(); - - #ifdef PUGIXML_NO_EXCEPTIONS - if (setjmp(sd.error_handler)) return xpath_string(); - #endif - - xpath_context c(n, 1, 1); - - return impl->root->eval_string(c, sd.stack); - } -PUGI__NS_END - -OIIO_NAMESPACE_BEGIN -namespace pugi -{ -#ifndef PUGIXML_NO_EXCEPTIONS - PUGI__FN xpath_exception::xpath_exception(const xpath_parse_result& result_): _result(result_) - { - assert(_result.error); - } - - PUGI__FN const char* xpath_exception::what() const throw() - { - return _result.error; - } - - PUGI__FN const xpath_parse_result& xpath_exception::result() const - { - return _result; - } -#endif - - PUGI__FN xpath_node::xpath_node() - { - } - - PUGI__FN xpath_node::xpath_node(const xml_node& node_): _node(node_) - { - } - - PUGI__FN xpath_node::xpath_node(const xml_attribute& attribute_, const xml_node& parent_): _node(attribute_ ? parent_ : xml_node()), _attribute(attribute_) - { - } - - PUGI__FN xml_node xpath_node::node() const - { - return _attribute ? xml_node() : _node; - } - - PUGI__FN xml_attribute xpath_node::attribute() const - { - return _attribute; - } - - PUGI__FN xml_node xpath_node::parent() const - { - return _attribute ? _node : _node.parent(); - } - - PUGI__FN static void unspecified_bool_xpath_node(xpath_node***) - { - } - - PUGI__FN xpath_node::operator xpath_node::unspecified_bool_type() const - { - return (_node || _attribute) ? unspecified_bool_xpath_node : 0; - } - - PUGI__FN bool xpath_node::operator!() const - { - return !(_node || _attribute); - } - - PUGI__FN bool xpath_node::operator==(const xpath_node& n) const - { - return _node == n._node && _attribute == n._attribute; - } - - PUGI__FN bool xpath_node::operator!=(const xpath_node& n) const - { - return _node != n._node || _attribute != n._attribute; - } - -#ifdef __BORLANDC__ - PUGI__FN bool operator&&(const xpath_node& lhs, bool rhs) - { - return (bool)lhs && rhs; - } - - PUGI__FN bool operator||(const xpath_node& lhs, bool rhs) - { - return (bool)lhs || rhs; - } -#endif - - PUGI__FN void xpath_node_set::_assign(const_iterator begin_, const_iterator end_) - { - assert(begin_ <= end_); - - size_t size_ = static_cast(end_ - begin_); - - if (size_ <= 1) - { - // deallocate old buffer - if (_begin != &_storage) impl::xml_memory::deallocate(_begin); - - // use internal buffer - if (begin_ != end_) _storage = *begin_; - - _begin = &_storage; - _end = &_storage + size_; - } - else - { - // make heap copy - xpath_node* storage = static_cast(impl::xml_memory::allocate(size_ * sizeof(xpath_node))); - - if (!storage) - { - #ifdef PUGIXML_NO_EXCEPTIONS - return; - #else - throw std::bad_alloc(); - #endif - } - - memcpy(storage, begin_, size_ * sizeof(xpath_node)); - - // deallocate old buffer - if (_begin != &_storage) impl::xml_memory::deallocate(_begin); - - // finalize - _begin = storage; - _end = storage + size_; - } - } - - PUGI__FN xpath_node_set::xpath_node_set(): _type(type_unsorted), _begin(&_storage), _end(&_storage) - { - } - - PUGI__FN xpath_node_set::xpath_node_set(const_iterator begin_, const_iterator end_, type_t type_): _type(type_), _begin(&_storage), _end(&_storage) - { - _assign(begin_, end_); - } - - PUGI__FN xpath_node_set::~xpath_node_set() - { - if (_begin != &_storage) impl::xml_memory::deallocate(_begin); - } - - PUGI__FN xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(ns._type), _begin(&_storage), _end(&_storage) - { - _assign(ns._begin, ns._end); - } - - PUGI__FN xpath_node_set& xpath_node_set::operator=(const xpath_node_set& ns) - { - if (this == &ns) return *this; - - _type = ns._type; - _assign(ns._begin, ns._end); - - return *this; - } - - PUGI__FN xpath_node_set::type_t xpath_node_set::type() const - { - return _type; - } - - PUGI__FN size_t xpath_node_set::size() const - { - return _end - _begin; - } - - PUGI__FN bool xpath_node_set::empty() const - { - return _begin == _end; - } - - PUGI__FN const xpath_node& xpath_node_set::operator[](size_t index) const - { - assert(index < size()); - return _begin[index]; - } - - PUGI__FN xpath_node_set::const_iterator xpath_node_set::begin() const - { - return _begin; - } - - PUGI__FN xpath_node_set::const_iterator xpath_node_set::end() const - { - return _end; - } - - PUGI__FN void xpath_node_set::sort(bool reverse) - { - _type = impl::xpath_sort(_begin, _end, _type, reverse); - } - - PUGI__FN xpath_node xpath_node_set::first() const - { - return impl::xpath_first(_begin, _end, _type); - } - - PUGI__FN xpath_parse_result::xpath_parse_result(): error("Internal error"), offset(0) - { - } - - PUGI__FN xpath_parse_result::operator bool() const - { - return error == 0; - } - - PUGI__FN const char* xpath_parse_result::description() const - { - return error ? error : "No error"; - } - - PUGI__FN xpath_variable::xpath_variable() - { - } - - PUGI__FN const char_t* xpath_variable::name() const - { - switch (_type) - { - case xpath_type_node_set: - return static_cast(this)->name; - - case xpath_type_number: - return static_cast(this)->name; - - case xpath_type_string: - return static_cast(this)->name; - - case xpath_type_boolean: - return static_cast(this)->name; - - default: - assert(!"Invalid variable type"); - return 0; - } - } - - PUGI__FN xpath_value_type xpath_variable::type() const - { - return _type; - } - - PUGI__FN bool xpath_variable::get_boolean() const - { - return (_type == xpath_type_boolean) ? static_cast(this)->value : false; - } - - PUGI__FN double xpath_variable::get_number() const - { - return (_type == xpath_type_number) ? static_cast(this)->value : impl::gen_nan(); - } - - PUGI__FN const char_t* xpath_variable::get_string() const - { - const char_t* value = (_type == xpath_type_string) ? static_cast(this)->value : 0; - return value ? value : PUGIXML_TEXT(""); - } - - PUGI__FN const xpath_node_set& xpath_variable::get_node_set() const - { - return (_type == xpath_type_node_set) ? static_cast(this)->value : impl::dummy_node_set; - } - - PUGI__FN bool xpath_variable::set(bool value) - { - if (_type != xpath_type_boolean) return false; - - static_cast(this)->value = value; - return true; - } - - PUGI__FN bool xpath_variable::set(double value) - { - if (_type != xpath_type_number) return false; - - static_cast(this)->value = value; - return true; - } - - PUGI__FN bool xpath_variable::set(const char_t* value) - { - if (_type != xpath_type_string) return false; - - impl::xpath_variable_string* var = static_cast(this); - - // duplicate string - size_t size = (impl::strlength(value) + 1) * sizeof(char_t); - - char_t* copy = static_cast(impl::xml_memory::allocate(size)); - if (!copy) return false; - - memcpy(copy, value, size); - - // replace old string - if (var->value) impl::xml_memory::deallocate(var->value); - var->value = copy; - - return true; - } - - PUGI__FN bool xpath_variable::set(const xpath_node_set& value) - { - if (_type != xpath_type_node_set) return false; - - static_cast(this)->value = value; - return true; - } - - PUGI__FN xpath_variable_set::xpath_variable_set() - { - for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) _data[i] = 0; - } - - PUGI__FN xpath_variable_set::~xpath_variable_set() - { - for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) - { - xpath_variable* var = _data[i]; - - while (var) - { - xpath_variable* next = var->_next; - - impl::delete_xpath_variable(var->_type, var); - - var = next; - } - } - } - - PUGI__FN xpath_variable* xpath_variable_set::find(const char_t* name) const - { - const size_t hash_size = sizeof(_data) / sizeof(_data[0]); - size_t hash = impl::hash_string(name) % hash_size; - - // look for existing variable - for (xpath_variable* var = _data[hash]; var; var = var->_next) - if (impl::strequal(var->name(), name)) - return var; - - return 0; - } - - PUGI__FN xpath_variable* xpath_variable_set::add(const char_t* name, xpath_value_type type) - { - const size_t hash_size = sizeof(_data) / sizeof(_data[0]); - size_t hash = impl::hash_string(name) % hash_size; - - // look for existing variable - for (xpath_variable* var = _data[hash]; var; var = var->_next) - if (impl::strequal(var->name(), name)) - return var->type() == type ? var : 0; - - // add new variable - xpath_variable* result = impl::new_xpath_variable(type, name); - - if (result) - { - result->_type = type; - result->_next = _data[hash]; - - _data[hash] = result; - } - - return result; - } - - PUGI__FN bool xpath_variable_set::set(const char_t* name, bool value) - { - xpath_variable* var = add(name, xpath_type_boolean); - return var ? var->set(value) : false; - } - - PUGI__FN bool xpath_variable_set::set(const char_t* name, double value) - { - xpath_variable* var = add(name, xpath_type_number); - return var ? var->set(value) : false; - } - - PUGI__FN bool xpath_variable_set::set(const char_t* name, const char_t* value) - { - xpath_variable* var = add(name, xpath_type_string); - return var ? var->set(value) : false; - } - - PUGI__FN bool xpath_variable_set::set(const char_t* name, const xpath_node_set& value) - { - xpath_variable* var = add(name, xpath_type_node_set); - return var ? var->set(value) : false; - } - - PUGI__FN xpath_variable* xpath_variable_set::get(const char_t* name) - { - return find(name); - } - - PUGI__FN const xpath_variable* xpath_variable_set::get(const char_t* name) const - { - return find(name); - } - - PUGI__FN xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables): _impl(0) - { - impl::xpath_query_impl* qimpl = impl::xpath_query_impl::create(); - - if (!qimpl) - { - #ifdef PUGIXML_NO_EXCEPTIONS - _result.error = "Out of memory"; - #else - throw std::bad_alloc(); - #endif - } - else - { - impl::buffer_holder impl_holder(qimpl, impl::xpath_query_impl::destroy); - - qimpl->root = impl::xpath_parser::parse(query, variables, &qimpl->alloc, &_result); - - if (qimpl->root) - { - _impl = static_cast(impl_holder.release()); - _result.error = 0; - } - } - } - - PUGI__FN xpath_query::~xpath_query() - { - impl::xpath_query_impl::destroy(_impl); - } - - PUGI__FN xpath_value_type xpath_query::return_type() const - { - if (!_impl) return xpath_type_none; - - return static_cast(_impl)->root->rettype(); - } - - PUGI__FN bool xpath_query::evaluate_boolean(const xpath_node& n) const - { - if (!_impl) return false; - - impl::xpath_context c(n, 1, 1); - impl::xpath_stack_data sd; - - #ifdef PUGIXML_NO_EXCEPTIONS - if (setjmp(sd.error_handler)) return false; - #endif - - return static_cast(_impl)->root->eval_boolean(c, sd.stack); - } - - PUGI__FN double xpath_query::evaluate_number(const xpath_node& n) const - { - if (!_impl) return impl::gen_nan(); - - impl::xpath_context c(n, 1, 1); - impl::xpath_stack_data sd; - - #ifdef PUGIXML_NO_EXCEPTIONS - if (setjmp(sd.error_handler)) return impl::gen_nan(); - #endif - - return static_cast(_impl)->root->eval_number(c, sd.stack); - } - -#ifndef PUGIXML_NO_STL - PUGI__FN string_t xpath_query::evaluate_string(const xpath_node& n) const - { - impl::xpath_stack_data sd; - - return impl::evaluate_string_impl(static_cast(_impl), n, sd).c_str(); - } -#endif - - PUGI__FN size_t xpath_query::evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const - { - impl::xpath_stack_data sd; - - impl::xpath_string r = impl::evaluate_string_impl(static_cast(_impl), n, sd); - - size_t full_size = r.length() + 1; - - if (capacity > 0) - { - size_t size = (full_size < capacity) ? full_size : capacity; - assert(size > 0); - - memcpy(buffer, r.c_str(), (size - 1) * sizeof(char_t)); - buffer[size - 1] = 0; - } - - return full_size; - } - - PUGI__FN xpath_node_set xpath_query::evaluate_node_set(const xpath_node& n) const - { - if (!_impl) return xpath_node_set(); - - impl::xpath_ast_node* root = static_cast(_impl)->root; - - if (root->rettype() != xpath_type_node_set) - { - #ifdef PUGIXML_NO_EXCEPTIONS - return xpath_node_set(); - #else - xpath_parse_result res; - res.error = "Expression does not evaluate to node set"; - - throw xpath_exception(res); - #endif - } - - impl::xpath_context c(n, 1, 1); - impl::xpath_stack_data sd; - - #ifdef PUGIXML_NO_EXCEPTIONS - if (setjmp(sd.error_handler)) return xpath_node_set(); - #endif - - impl::xpath_node_set_raw r = root->eval_node_set(c, sd.stack); - - return xpath_node_set(r.begin(), r.end(), r.type()); - } - - PUGI__FN const xpath_parse_result& xpath_query::result() const - { - return _result; - } - - PUGI__FN static void unspecified_bool_xpath_query(xpath_query***) - { - } - - PUGI__FN xpath_query::operator xpath_query::unspecified_bool_type() const - { - return _impl ? unspecified_bool_xpath_query : 0; - } - - PUGI__FN bool xpath_query::operator!() const - { - return !_impl; - } - - PUGI__FN xpath_node xml_node::select_single_node(const char_t* query, xpath_variable_set* variables) const - { - xpath_query q(query, variables); - return select_single_node(q); - } - - PUGI__FN xpath_node xml_node::select_single_node(const xpath_query& query) const - { - xpath_node_set s = query.evaluate_node_set(*this); - return s.empty() ? xpath_node() : s.first(); - } - - PUGI__FN xpath_node_set xml_node::select_nodes(const char_t* query, xpath_variable_set* variables) const - { - xpath_query q(query, variables); - return select_nodes(q); - } - - PUGI__FN xpath_node_set xml_node::select_nodes(const xpath_query& query) const - { - return query.evaluate_node_set(*this); - } -} -OIIO_NAMESPACE_END - -#endif - -#ifdef __BORLANDC__ -# pragma option pop -#endif - -// Intel C++ does not properly keep warning state for function templates, -// so popping warning state at the end of translation unit leads to warnings in the middle. -#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) -# pragma warning(pop) -#endif - -// Undefine all local macros (makes sure we're not leaking macros in header-only mode) -#undef PUGI__NO_INLINE -#undef PUGI__STATIC_ASSERT -#undef PUGI__DMC_VOLATILE -#undef PUGI__MSVC_CRT_VERSION -#undef PUGI__NS_BEGIN -#undef PUGI__NS_END -#undef PUGI__FN -#undef PUGI__FN_NO_INLINE -#undef PUGI__IS_CHARTYPE_IMPL -#undef PUGI__IS_CHARTYPE -#undef PUGI__IS_CHARTYPEX -#undef PUGI__SKIPWS -#undef PUGI__OPTSET -#undef PUGI__PUSHNODE -#undef PUGI__POPNODE -#undef PUGI__SCANFOR -#undef PUGI__SCANWHILE -#undef PUGI__ENDSEG -#undef PUGI__THROW_ERROR -#undef PUGI__CHECK_ERROR - -#endif - -/** - * Copyright (c) 2006-2012 Arseny Kapoulkine - * - * 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. - */ diff --git a/3rdparty/oiio16/include/OpenImageIO/pugixml.hpp b/3rdparty/oiio16/include/OpenImageIO/pugixml.hpp deleted file mode 100644 index b4dddb7c..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/pugixml.hpp +++ /dev/null @@ -1,1270 +0,0 @@ -/** - * pugixml parser - version 1.2 - * -------------------------------------------------------- - * Copyright (C) 2006-2012, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) - * Report bugs and download new versions at http://pugixml.org/ - * - * This library is distributed under the MIT License. See notice at the end - * of this file. - * - * This work is based on the pugxml parser, which is: - * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) - */ - -#ifndef PUGIXML_VERSION -// Define version macro; evaluates to major * 100 + minor so that it's safe to use in less-than comparisons -# define PUGIXML_VERSION 120 -#endif - -// Include user configuration file (this can define various configuration macros) -#include "pugiconfig.hpp" - -#ifndef HEADER_PUGIXML_HPP -#define HEADER_PUGIXML_HPP - -#include "oiioversion.h" -#define USING_OIIO_PUGI 1 - -// Include stddef.h for size_t and ptrdiff_t -#include - -// Include exception header for XPath -#if !defined(PUGIXML_NO_XPATH) && !defined(PUGIXML_NO_EXCEPTIONS) -# include -#endif - -// Include STL headers -#ifndef PUGIXML_NO_STL -# include -# include -# include -#endif - -// Macro for deprecated features -#ifndef PUGIXML_DEPRECATED -# if defined(__GNUC__) -# define PUGIXML_DEPRECATED __attribute__((deprecated)) -# elif defined(_MSC_VER) && _MSC_VER >= 1300 -# define PUGIXML_DEPRECATED __declspec(deprecated) -# else -# define PUGIXML_DEPRECATED -# endif -#endif - -// If no API is defined, assume default -#ifndef PUGIXML_API -# define PUGIXML_API -#endif - -// If no API for classes is defined, assume default -#ifndef PUGIXML_CLASS -# define PUGIXML_CLASS PUGIXML_API -#endif - -// If no API for functions is defined, assume default -#ifndef PUGIXML_FUNCTION -# define PUGIXML_FUNCTION PUGIXML_API -#endif - -// Character interface macros -#ifdef PUGIXML_WCHAR_MODE -# define PUGIXML_TEXT(t) L ## t -# define PUGIXML_CHAR wchar_t -#else -# define PUGIXML_TEXT(t) t -# define PUGIXML_CHAR char -#endif - -OIIO_NAMESPACE_BEGIN -namespace pugi -{ - // Character type used for all internal storage and operations; depends on PUGIXML_WCHAR_MODE - typedef PUGIXML_CHAR char_t; - -#ifndef PUGIXML_NO_STL - // String type used for operations that work with STL string; depends on PUGIXML_WCHAR_MODE - typedef std::basic_string, std::allocator > string_t; -#endif -} - -// The PugiXML namespace -namespace pugi -{ - // Tree node types - enum xml_node_type - { - node_null, // Empty (null) node handle - node_document, // A document tree's absolute root - node_element, // Element tag, i.e. '' - node_pcdata, // Plain character data, i.e. 'text' - node_cdata, // Character data, i.e. '' - node_comment, // Comment tag, i.e. '' - node_pi, // Processing instruction, i.e. '' - node_declaration, // Document declaration, i.e. '' - node_doctype // Document type declaration, i.e. '' - }; - - // Parsing options - - // Minimal parsing mode (equivalent to turning all other flags off). - // Only elements and PCDATA sections are added to the DOM tree, no text conversions are performed. - const unsigned int parse_minimal = 0x0000; - - // This flag determines if processing instructions (node_pi) are added to the DOM tree. This flag is off by default. - const unsigned int parse_pi = 0x0001; - - // This flag determines if comments (node_comment) are added to the DOM tree. This flag is off by default. - const unsigned int parse_comments = 0x0002; - - // This flag determines if CDATA sections (node_cdata) are added to the DOM tree. This flag is on by default. - const unsigned int parse_cdata = 0x0004; - - // This flag determines if plain character data (node_pcdata) that consist only of whitespace are added to the DOM tree. - // This flag is off by default; turning it on usually results in slower parsing and more memory consumption. - const unsigned int parse_ws_pcdata = 0x0008; - - // This flag determines if character and entity references are expanded during parsing. This flag is on by default. - const unsigned int parse_escapes = 0x0010; - - // This flag determines if EOL characters are normalized (converted to #xA) during parsing. This flag is on by default. - const unsigned int parse_eol = 0x0020; - - // This flag determines if attribute values are normalized using CDATA normalization rules during parsing. This flag is on by default. - const unsigned int parse_wconv_attribute = 0x0040; - - // This flag determines if attribute values are normalized using NMTOKENS normalization rules during parsing. This flag is off by default. - const unsigned int parse_wnorm_attribute = 0x0080; - - // This flag determines if document declaration (node_declaration) is added to the DOM tree. This flag is off by default. - const unsigned int parse_declaration = 0x0100; - - // This flag determines if document type declaration (node_doctype) is added to the DOM tree. This flag is off by default. - const unsigned int parse_doctype = 0x0200; - - // This flag determines if plain character data (node_pcdata) that is the only child of the parent node and that consists only - // of whitespace is added to the DOM tree. - // This flag is off by default; turning it on may result in slower parsing and more memory consumption. - const unsigned int parse_ws_pcdata_single = 0x0400; - - // The default parsing mode. - // Elements, PCDATA and CDATA sections are added to the DOM tree, character/reference entities are expanded, - // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules. - const unsigned int parse_default = parse_cdata | parse_escapes | parse_wconv_attribute | parse_eol; - - // The full parsing mode. - // Nodes of all types are added to the DOM tree, character/reference entities are expanded, - // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules. - const unsigned int parse_full = parse_default | parse_pi | parse_comments | parse_declaration | parse_doctype; - - // These flags determine the encoding of input data for XML document - enum xml_encoding - { - encoding_auto, // Auto-detect input encoding using BOM or < / class xml_object_range - { - public: - typedef It const_iterator; - - xml_object_range(It b, It e): _begin(b), _end(e) - { - } - - It begin() const { return _begin; } - It end() const { return _end; } - - private: - It _begin, _end; - }; - - // Writer interface for node printing (see xml_node::print) - class PUGIXML_CLASS xml_writer - { - public: - virtual ~xml_writer() {} - - // Write memory chunk into stream/file/whatever - virtual void write(const void* data, size_t size) = 0; - }; - - // xml_writer implementation for FILE* - class PUGIXML_CLASS xml_writer_file: public xml_writer - { - public: - // Construct writer from a FILE* object; void* is used to avoid header dependencies on stdio - xml_writer_file(void* file); - - virtual void write(const void* data, size_t size); - - private: - void* file; - }; - - #ifndef PUGIXML_NO_STL - // xml_writer implementation for streams - class PUGIXML_CLASS xml_writer_stream: public xml_writer - { - public: - // Construct writer from an output stream object - xml_writer_stream(std::basic_ostream >& stream); - xml_writer_stream(std::basic_ostream >& stream); - - virtual void write(const void* data, size_t size); - - private: - std::basic_ostream >* narrow_stream; - std::basic_ostream >* wide_stream; - }; - #endif - - // A light-weight handle for manipulating attributes in DOM tree - class PUGIXML_CLASS xml_attribute - { - friend class xml_attribute_iterator; - friend class xml_node; - - private: - xml_attribute_struct* _attr; - - typedef void (*unspecified_bool_type)(xml_attribute***); - - public: - // Default constructor. Constructs an empty attribute. - xml_attribute(); - - // Constructs attribute from internal pointer - explicit xml_attribute(xml_attribute_struct* attr); - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - - // Comparison operators (compares wrapped attribute pointers) - bool operator==(const xml_attribute& r) const; - bool operator!=(const xml_attribute& r) const; - bool operator<(const xml_attribute& r) const; - bool operator>(const xml_attribute& r) const; - bool operator<=(const xml_attribute& r) const; - bool operator>=(const xml_attribute& r) const; - - // Check if attribute is empty - bool empty() const; - - // Get attribute name/value, or "" if attribute is empty - const char_t* name() const; - const char_t* value() const; - - // Get attribute value, or the default value if attribute is empty - const char_t* as_string(const char_t* def = PUGIXML_TEXT("")) const; - - // Get attribute value as a number, or the default value if conversion did not succeed or attribute is empty - int as_int(int def = 0) const; - unsigned int as_uint(unsigned int def = 0) const; - double as_double(double def = 0) const; - float as_float(float def = 0) const; - - // Get attribute value as bool (returns true if first character is in '1tTyY' set), or the default value if attribute is empty - bool as_bool(bool def = false) const; - - // Set attribute name/value (returns false if attribute is empty or there is not enough memory) - bool set_name(const char_t* rhs); - bool set_value(const char_t* rhs); - - // Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") - bool set_value(int rhs); - bool set_value(unsigned int rhs); - bool set_value(double rhs); - bool set_value(bool rhs); - - // Set attribute value (equivalent to set_value without error checking) - xml_attribute& operator=(const char_t* rhs); - xml_attribute& operator=(int rhs); - xml_attribute& operator=(unsigned int rhs); - xml_attribute& operator=(double rhs); - xml_attribute& operator=(bool rhs); - - // Get next/previous attribute in the attribute list of the parent node - xml_attribute next_attribute() const; - xml_attribute previous_attribute() const; - - // Get hash value (unique for handles to the same object) - size_t hash_value() const; - - // Get internal pointer - xml_attribute_struct* internal_object() const; - }; - -#ifdef __BORLANDC__ - // Borland C++ workaround - bool PUGIXML_FUNCTION operator&&(const xml_attribute& lhs, bool rhs); - bool PUGIXML_FUNCTION operator||(const xml_attribute& lhs, bool rhs); -#endif - - // A light-weight handle for manipulating nodes in DOM tree - class PUGIXML_CLASS xml_node - { - friend class xml_attribute_iterator; - friend class xml_node_iterator; - friend class xml_named_node_iterator; - - protected: - xml_node_struct* _root; - - typedef void (*unspecified_bool_type)(xml_node***); - - public: - // Default constructor. Constructs an empty node. - xml_node(); - - // Constructs node from internal pointer - explicit xml_node(xml_node_struct* p); - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - - // Comparison operators (compares wrapped node pointers) - bool operator==(const xml_node& r) const; - bool operator!=(const xml_node& r) const; - bool operator<(const xml_node& r) const; - bool operator>(const xml_node& r) const; - bool operator<=(const xml_node& r) const; - bool operator>=(const xml_node& r) const; - - // Check if node is empty. - bool empty() const; - - // Get node type - xml_node_type type() const; - - // Get node name/value, or "" if node is empty or it has no name/value - const char_t* name() const; - const char_t* value() const; - - // Get attribute list - xml_attribute first_attribute() const; - xml_attribute last_attribute() const; - - // Get children list - xml_node first_child() const; - xml_node last_child() const; - - // Get next/previous sibling in the children list of the parent node - xml_node next_sibling() const; - xml_node previous_sibling() const; - - // Get parent node - xml_node parent() const; - - // Get root of DOM tree this node belongs to - xml_node root() const; - - // Get text object for the current node - xml_text text() const; - - // Get child, attribute or next/previous sibling with the specified name - xml_node child(const char_t* name) const; - xml_attribute attribute(const char_t* name) const; - xml_node next_sibling(const char_t* name) const; - xml_node previous_sibling(const char_t* name) const; - - // Get child value of current node; that is, value of the first child node of type PCDATA/CDATA - const char_t* child_value() const; - - // Get child value of child with specified name. Equivalent to child(name).child_value(). - const char_t* child_value(const char_t* name) const; - - // Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value) - bool set_name(const char_t* rhs); - bool set_value(const char_t* rhs); - - // Add attribute with specified name. Returns added attribute, or empty attribute on errors. - xml_attribute append_attribute(const char_t* name); - xml_attribute prepend_attribute(const char_t* name); - xml_attribute insert_attribute_after(const char_t* name, const xml_attribute& attr); - xml_attribute insert_attribute_before(const char_t* name, const xml_attribute& attr); - - // Add a copy of the specified attribute. Returns added attribute, or empty attribute on errors. - xml_attribute append_copy(const xml_attribute& proto); - xml_attribute prepend_copy(const xml_attribute& proto); - xml_attribute insert_copy_after(const xml_attribute& proto, const xml_attribute& attr); - xml_attribute insert_copy_before(const xml_attribute& proto, const xml_attribute& attr); - - // Add child node with specified type. Returns added node, or empty node on errors. - xml_node append_child(xml_node_type type = node_element); - xml_node prepend_child(xml_node_type type = node_element); - xml_node insert_child_after(xml_node_type type, const xml_node& node); - xml_node insert_child_before(xml_node_type type, const xml_node& node); - - // Add child element with specified name. Returns added node, or empty node on errors. - xml_node append_child(const char_t* name); - xml_node prepend_child(const char_t* name); - xml_node insert_child_after(const char_t* name, const xml_node& node); - xml_node insert_child_before(const char_t* name, const xml_node& node); - - // Add a copy of the specified node as a child. Returns added node, or empty node on errors. - xml_node append_copy(const xml_node& proto); - xml_node prepend_copy(const xml_node& proto); - xml_node insert_copy_after(const xml_node& proto, const xml_node& node); - xml_node insert_copy_before(const xml_node& proto, const xml_node& node); - - // Remove specified attribute - bool remove_attribute(const xml_attribute& a); - bool remove_attribute(const char_t* name); - - // Remove specified child - bool remove_child(const xml_node& n); - bool remove_child(const char_t* name); - - // Find attribute using predicate. Returns first attribute for which predicate returned true. - template xml_attribute find_attribute(Predicate pred) const - { - if (!_root) return xml_attribute(); - - for (xml_attribute attrib = first_attribute(); attrib; attrib = attrib.next_attribute()) - if (pred(attrib)) - return attrib; - - return xml_attribute(); - } - - // Find child node using predicate. Returns first child for which predicate returned true. - template xml_node find_child(Predicate pred) const - { - if (!_root) return xml_node(); - - for (xml_node node = first_child(); node; node = node.next_sibling()) - if (pred(node)) - return node; - - return xml_node(); - } - - // Find node from subtree using predicate. Returns first node from subtree (depth-first), for which predicate returned true. - template xml_node find_node(Predicate pred) const - { - if (!_root) return xml_node(); - - xml_node cur = first_child(); - - while (cur._root && cur._root != _root) - { - if (pred(cur)) return cur; - - if (cur.first_child()) cur = cur.first_child(); - else if (cur.next_sibling()) cur = cur.next_sibling(); - else - { - while (!cur.next_sibling() && cur._root != _root) cur = cur.parent(); - - if (cur._root != _root) cur = cur.next_sibling(); - } - } - - return xml_node(); - } - - // Find child node by attribute name/value - xml_node find_child_by_attribute(const char_t* name, const char_t* attr_name, const char_t* attr_value) const; - xml_node find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const; - - #ifndef PUGIXML_NO_STL - // Get the absolute node path from root as a text string. - string_t path(char_t delimiter = '/') const; - #endif - - // Search for a node by path consisting of node names and . or .. elements. - xml_node first_element_by_path(const char_t* path, char_t delimiter = '/') const; - - // Recursively traverse subtree with xml_tree_walker - bool traverse(xml_tree_walker& walker); - - #ifndef PUGIXML_NO_XPATH - // Select single node by evaluating XPath query. Returns first node from the resulting node set. - xpath_node select_single_node(const char_t* query, xpath_variable_set* variables = 0) const; - xpath_node select_single_node(const xpath_query& query) const; - - // Select node set by evaluating XPath query - xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = 0) const; - xpath_node_set select_nodes(const xpath_query& query) const; - #endif - - // Print subtree using a writer object - void print(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; - - #ifndef PUGIXML_NO_STL - // Print subtree to stream - void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; - void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, unsigned int depth = 0) const; - #endif - - // Child nodes iterators - typedef xml_node_iterator iterator; - - iterator begin() const; - iterator end() const; - - // Attribute iterators - typedef xml_attribute_iterator attribute_iterator; - - attribute_iterator attributes_begin() const; - attribute_iterator attributes_end() const; - - // Range-based for support - xml_object_range children() const; - xml_object_range children(const char_t* name) const; - xml_object_range attributes() const; - - // Get node offset in parsed file/string (in char_t units) for debugging purposes - ptrdiff_t offset_debug() const; - - // Get hash value (unique for handles to the same object) - size_t hash_value() const; - - // Get internal pointer - xml_node_struct* internal_object() const; - }; - -#ifdef __BORLANDC__ - // Borland C++ workaround - bool PUGIXML_FUNCTION operator&&(const xml_node& lhs, bool rhs); - bool PUGIXML_FUNCTION operator||(const xml_node& lhs, bool rhs); -#endif - - // A helper for working with text inside PCDATA nodes - class PUGIXML_CLASS xml_text - { - friend class xml_node; - - xml_node_struct* _root; - - typedef void (*unspecified_bool_type)(xml_text***); - - explicit xml_text(xml_node_struct* root); - - xml_node_struct* _data_new(); - xml_node_struct* _data() const; - - public: - // Default constructor. Constructs an empty object. - xml_text(); - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - - // Check if text object is empty - bool empty() const; - - // Get text, or "" if object is empty - const char_t* get() const; - - // Get text, or the default value if object is empty - const char_t* as_string(const char_t* def = PUGIXML_TEXT("")) const; - - // Get text as a number, or the default value if conversion did not succeed or object is empty - int as_int(int def = 0) const; - unsigned int as_uint(unsigned int def = 0) const; - double as_double(double def = 0) const; - float as_float(float def = 0) const; - - // Get text as bool (returns true if first character is in '1tTyY' set), or the default value if object is empty - bool as_bool(bool def = false) const; - - // Set text (returns false if object is empty or there is not enough memory) - bool set(const char_t* rhs); - - // Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") - bool set(int rhs); - bool set(unsigned int rhs); - bool set(double rhs); - bool set(bool rhs); - - // Set text (equivalent to set without error checking) - xml_text& operator=(const char_t* rhs); - xml_text& operator=(int rhs); - xml_text& operator=(unsigned int rhs); - xml_text& operator=(double rhs); - xml_text& operator=(bool rhs); - - // Get the data node (node_pcdata or node_cdata) for this object - xml_node data() const; - }; - -#ifdef __BORLANDC__ - // Borland C++ workaround - bool PUGIXML_FUNCTION operator&&(const xml_text& lhs, bool rhs); - bool PUGIXML_FUNCTION operator||(const xml_text& lhs, bool rhs); -#endif - - // Child node iterator (a bidirectional iterator over a collection of xml_node) - class PUGIXML_CLASS xml_node_iterator - { - friend class xml_node; - - private: - mutable xml_node _wrap; - xml_node _parent; - - xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent); - - public: - // Iterator traits - typedef ptrdiff_t difference_type; - typedef xml_node value_type; - typedef xml_node* pointer; - typedef xml_node& reference; - - #ifndef PUGIXML_NO_STL - typedef std::bidirectional_iterator_tag iterator_category; - #endif - - // Default constructor - xml_node_iterator(); - - // Construct an iterator which points to the specified node - xml_node_iterator(const xml_node& node); - - // Iterator operators - bool operator==(const xml_node_iterator& rhs) const; - bool operator!=(const xml_node_iterator& rhs) const; - - xml_node& operator*() const; - xml_node* operator->() const; - - const xml_node_iterator& operator++(); - xml_node_iterator operator++(int); - - const xml_node_iterator& operator--(); - xml_node_iterator operator--(int); - }; - - // Attribute iterator (a bidirectional iterator over a collection of xml_attribute) - class PUGIXML_CLASS xml_attribute_iterator - { - friend class xml_node; - - private: - mutable xml_attribute _wrap; - xml_node _parent; - - xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent); - - public: - // Iterator traits - typedef ptrdiff_t difference_type; - typedef xml_attribute value_type; - typedef xml_attribute* pointer; - typedef xml_attribute& reference; - - #ifndef PUGIXML_NO_STL - typedef std::bidirectional_iterator_tag iterator_category; - #endif - - // Default constructor - xml_attribute_iterator(); - - // Construct an iterator which points to the specified attribute - xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent); - - // Iterator operators - bool operator==(const xml_attribute_iterator& rhs) const; - bool operator!=(const xml_attribute_iterator& rhs) const; - - xml_attribute& operator*() const; - xml_attribute* operator->() const; - - const xml_attribute_iterator& operator++(); - xml_attribute_iterator operator++(int); - - const xml_attribute_iterator& operator--(); - xml_attribute_iterator operator--(int); - }; - - // Named node range helper - class xml_named_node_iterator - { - public: - // Iterator traits - typedef ptrdiff_t difference_type; - typedef xml_node value_type; - typedef xml_node* pointer; - typedef xml_node& reference; - - #ifndef PUGIXML_NO_STL - typedef std::forward_iterator_tag iterator_category; - #endif - - // Default constructor - xml_named_node_iterator(); - - // Construct an iterator which points to the specified node - xml_named_node_iterator(const xml_node& node, const char_t* name); - - // Iterator operators - bool operator==(const xml_named_node_iterator& rhs) const; - bool operator!=(const xml_named_node_iterator& rhs) const; - - xml_node& operator*() const; - xml_node* operator->() const; - - const xml_named_node_iterator& operator++(); - xml_named_node_iterator operator++(int); - - private: - mutable xml_node _node; - const char_t* _name; - }; - - // Abstract tree walker class (see xml_node::traverse) - class PUGIXML_CLASS xml_tree_walker - { - friend class xml_node; - - private: - int _depth; - - protected: - // Get current traversal depth - int depth() const; - - public: - xml_tree_walker(); - virtual ~xml_tree_walker(); - - // Callback that is called when traversal begins - virtual bool begin(xml_node& node); - - // Callback that is called for each node traversed - virtual bool for_each(xml_node& node) = 0; - - // Callback that is called when traversal ends - virtual bool end(xml_node& node); - }; - - // Parsing status, returned as part of xml_parse_result object - enum xml_parse_status - { - status_ok = 0, // No error - - status_file_not_found, // File was not found during load_file() - status_io_error, // Error reading from file/stream - status_out_of_memory, // Could not allocate memory - status_internal_error, // Internal error occurred - - status_unrecognized_tag, // Parser could not determine tag type - - status_bad_pi, // Parsing error occurred while parsing document declaration/processing instruction - status_bad_comment, // Parsing error occurred while parsing comment - status_bad_cdata, // Parsing error occurred while parsing CDATA section - status_bad_doctype, // Parsing error occurred while parsing document type declaration - status_bad_pcdata, // Parsing error occurred while parsing PCDATA section - status_bad_start_element, // Parsing error occurred while parsing start element tag - status_bad_attribute, // Parsing error occurred while parsing element attribute - status_bad_end_element, // Parsing error occurred while parsing end element tag - status_end_element_mismatch // There was a mismatch of start-end tags (closing tag had incorrect name, some tag was not closed or there was an excessive closing tag) - }; - - // Parsing result - struct PUGIXML_CLASS xml_parse_result - { - // Parsing status (see xml_parse_status) - xml_parse_status status; - - // Last parsed offset (in char_t units from start of input data) - ptrdiff_t offset; - - // Source document encoding - xml_encoding encoding; - - // Default constructor, initializes object to failed state - xml_parse_result(); - - // Cast to bool operator - operator bool() const; - - // Get error description - const char* description() const; - }; - - // Document class (DOM tree root) - class PUGIXML_CLASS xml_document: public xml_node - { - private: - char_t* _buffer; - - char _memory[192]; - - // Non-copyable semantics - xml_document(const xml_document&); - const xml_document& operator=(const xml_document&); - - void create(); - void destroy(); - - xml_parse_result load_buffer_impl(void* contents, size_t size, unsigned int options, xml_encoding encoding, bool is_mutable, bool own); - - public: - // Default constructor, makes empty document - xml_document(); - - // Destructor, invalidates all node/attribute handles to this document - ~xml_document(); - - // Removes all nodes, leaving the empty document - void reset(); - - // Removes all nodes, then copies the entire contents of the specified document - void reset(const xml_document& proto); - - #ifndef PUGIXML_NO_STL - // Load document from stream. - xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default); - #endif - - // Load document from zero-terminated string. No encoding conversions are applied. - xml_parse_result load(const char_t* contents, unsigned int options = parse_default); - - // Load document from file - xml_parse_result load_file(const char* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - xml_parse_result load_file(const wchar_t* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Load document from buffer. Copies/converts the buffer, so it may be deleted or changed after the function returns. - xml_parse_result load_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data). - // You should ensure that buffer data will persist throughout the document's lifetime, and free the buffer memory manually once document is destroyed. - xml_parse_result load_buffer_inplace(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data). - // You should allocate the buffer with pugixml allocation function; document will free the buffer when it is no longer needed (you can't use it anymore). - xml_parse_result load_buffer_inplace_own(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Save XML document to writer (semantics is slightly different from xml_node::print, see documentation for details). - void save(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; - - #ifndef PUGIXML_NO_STL - // Save XML document to stream (semantics is slightly different from xml_node::print, see documentation for details). - void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; - void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default) const; - #endif - - // Save XML to file - bool save_file(const char* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; - bool save_file(const wchar_t* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; - - // Get document element - xml_node document_element() const; - }; - -#ifndef PUGIXML_NO_XPATH - // XPath query return type - enum xpath_value_type - { - xpath_type_none, // Unknown type (query failed to compile) - xpath_type_node_set, // Node set (xpath_node_set) - xpath_type_number, // Number - xpath_type_string, // String - xpath_type_boolean // Boolean - }; - - // XPath parsing result - struct PUGIXML_CLASS xpath_parse_result - { - // Error message (0 if no error) - const char* error; - - // Last parsed offset (in char_t units from string start) - ptrdiff_t offset; - - // Default constructor, initializes object to failed state - xpath_parse_result(); - - // Cast to bool operator - operator bool() const; - - // Get error description - const char* description() const; - }; - - // A single XPath variable - class PUGIXML_CLASS xpath_variable - { - friend class xpath_variable_set; - - protected: - xpath_value_type _type; - xpath_variable* _next; - - xpath_variable(); - - // Non-copyable semantics - xpath_variable(const xpath_variable&); - xpath_variable& operator=(const xpath_variable&); - - public: - // Get variable name - const char_t* name() const; - - // Get variable type - xpath_value_type type() const; - - // Get variable value; no type conversion is performed, default value (false, NaN, empty string, empty node set) is returned on type mismatch error - bool get_boolean() const; - double get_number() const; - const char_t* get_string() const; - const xpath_node_set& get_node_set() const; - - // Set variable value; no type conversion is performed, false is returned on type mismatch error - bool set(bool value); - bool set(double value); - bool set(const char_t* value); - bool set(const xpath_node_set& value); - }; - - // A set of XPath variables - class PUGIXML_CLASS xpath_variable_set - { - private: - xpath_variable* _data[64]; - - // Non-copyable semantics - xpath_variable_set(const xpath_variable_set&); - xpath_variable_set& operator=(const xpath_variable_set&); - - xpath_variable* find(const char_t* name) const; - - public: - // Default constructor/destructor - xpath_variable_set(); - ~xpath_variable_set(); - - // Add a new variable or get the existing one, if the types match - xpath_variable* add(const char_t* name, xpath_value_type type); - - // Set value of an existing variable; no type conversion is performed, false is returned if there is no such variable or if types mismatch - bool set(const char_t* name, bool value); - bool set(const char_t* name, double value); - bool set(const char_t* name, const char_t* value); - bool set(const char_t* name, const xpath_node_set& value); - - // Get existing variable by name - xpath_variable* get(const char_t* name); - const xpath_variable* get(const char_t* name) const; - }; - - // A compiled XPath query object - class PUGIXML_CLASS xpath_query - { - private: - void* _impl; - xpath_parse_result _result; - - typedef void (*unspecified_bool_type)(xpath_query***); - - // Non-copyable semantics - xpath_query(const xpath_query&); - xpath_query& operator=(const xpath_query&); - - public: - // Construct a compiled object from XPath expression. - // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on compilation errors. - explicit xpath_query(const char_t* query, xpath_variable_set* variables = 0); - - // Destructor - ~xpath_query(); - - // Get query expression return type - xpath_value_type return_type() const; - - // Evaluate expression as boolean value in the specified context; performs type conversion if necessary. - // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. - bool evaluate_boolean(const xpath_node& n) const; - - // Evaluate expression as double value in the specified context; performs type conversion if necessary. - // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. - double evaluate_number(const xpath_node& n) const; - - #ifndef PUGIXML_NO_STL - // Evaluate expression as string value in the specified context; performs type conversion if necessary. - // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. - string_t evaluate_string(const xpath_node& n) const; - #endif - - // Evaluate expression as string value in the specified context; performs type conversion if necessary. - // At most capacity characters are written to the destination buffer, full result size is returned (includes terminating zero). - // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. - // If PUGIXML_NO_EXCEPTIONS is defined, returns empty set instead. - size_t evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const; - - // Evaluate expression as node set in the specified context. - // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on type mismatch and std::bad_alloc on out of memory errors. - // If PUGIXML_NO_EXCEPTIONS is defined, returns empty node set instead. - xpath_node_set evaluate_node_set(const xpath_node& n) const; - - // Get parsing result (used to get compilation errors in PUGIXML_NO_EXCEPTIONS mode) - const xpath_parse_result& result() const; - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - }; - - #ifndef PUGIXML_NO_EXCEPTIONS - // XPath exception class - class PUGIXML_CLASS xpath_exception: public std::exception - { - private: - xpath_parse_result _result; - - public: - // Construct exception from parse result - explicit xpath_exception(const xpath_parse_result& result); - - // Get error message - virtual const char* what() const throw(); - - // Get parse result - const xpath_parse_result& result() const; - }; - #endif - - // XPath node class (either xml_node or xml_attribute) - class PUGIXML_CLASS xpath_node - { - private: - xml_node _node; - xml_attribute _attribute; - - typedef void (*unspecified_bool_type)(xpath_node***); - - public: - // Default constructor; constructs empty XPath node - xpath_node(); - - // Construct XPath node from XML node/attribute - xpath_node(const xml_node& node); - xpath_node(const xml_attribute& attribute, const xml_node& parent); - - // Get node/attribute, if any - xml_node node() const; - xml_attribute attribute() const; - - // Get parent of contained node/attribute - xml_node parent() const; - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - - // Comparison operators - bool operator==(const xpath_node& n) const; - bool operator!=(const xpath_node& n) const; - }; - -#ifdef __BORLANDC__ - // Borland C++ workaround - bool PUGIXML_FUNCTION operator&&(const xpath_node& lhs, bool rhs); - bool PUGIXML_FUNCTION operator||(const xpath_node& lhs, bool rhs); -#endif - - // A fixed-size collection of XPath nodes - class PUGIXML_CLASS xpath_node_set - { - public: - // Collection type - enum type_t - { - type_unsorted, // Not ordered - type_sorted, // Sorted by document order (ascending) - type_sorted_reverse // Sorted by document order (descending) - }; - - // Constant iterator type - typedef const xpath_node* const_iterator; - - // Default constructor. Constructs empty set. - xpath_node_set(); - - // Constructs a set from iterator range; data is not checked for duplicates and is not sorted according to provided type, so be careful - xpath_node_set(const_iterator begin, const_iterator end, type_t type = type_unsorted); - - // Destructor - ~xpath_node_set(); - - // Copy constructor/assignment operator - xpath_node_set(const xpath_node_set& ns); - xpath_node_set& operator=(const xpath_node_set& ns); - - // Get collection type - type_t type() const; - - // Get collection size - size_t size() const; - - // Indexing operator - const xpath_node& operator[](size_t index) const; - - // Collection iterators - const_iterator begin() const; - const_iterator end() const; - - // Sort the collection in ascending/descending order by document order - void sort(bool reverse = false); - - // Get first node in the collection by document order - xpath_node first() const; - - // Check if collection is empty - bool empty() const; - - private: - type_t _type; - - xpath_node _storage; - - xpath_node* _begin; - xpath_node* _end; - - void _assign(const_iterator begin, const_iterator end); - }; -#endif - -#ifndef PUGIXML_NO_STL - // Convert wide string to UTF8 - std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const wchar_t* str); - std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const std::basic_string, std::allocator >& str); - - // Convert UTF8 to wide string - std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const char* str); - std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const std::basic_string, std::allocator >& str); -#endif - - // Memory allocation function interface; returns pointer to allocated memory or NULL on failure - typedef void* (*allocation_function)(size_t size); - - // Memory deallocation function interface - typedef void (*deallocation_function)(void* ptr); - - // Override default memory management functions. All subsequent allocations/deallocations will be performed via supplied functions. - void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate); - - // Get current memory management functions - allocation_function PUGIXML_FUNCTION get_memory_allocation_function(); - deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function(); -} -OIIO_NAMESPACE_END - -#if !defined(PUGIXML_NO_STL) && ((defined(_MSC_VER) && _MSC_VER < 1400) || defined(__ICC)) -namespace std -{ - // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier) - std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const OpenImageIO::pugi::xml_node_iterator&); - std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const OpenImageIO::pugi::xml_attribute_iterator&); - std::forward_iterator_tag PUGIXML_FUNCTION _Iter_cat(const OpenImageIO::pugi::xml_named_node_iterator&); -} -#endif - -#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC) -namespace std -{ - // Workarounds for (non-standard) iterator category detection - std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const OpenImageIO::pugi::xml_node_iterator&); - std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const OpenImageIO::pugi::xml_attribute_iterator&); - std::forward_iterator_tag PUGIXML_FUNCTION __iterator_category(const OpenImageIO::pugi::xml_named_node_iterator&); -} -#endif - -#endif - -/** - * Copyright (c) 2006-2012 Arseny Kapoulkine - * - * 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. - */ diff --git a/3rdparty/oiio16/include/OpenImageIO/refcnt.h b/3rdparty/oiio16/include/OpenImageIO/refcnt.h deleted file mode 100644 index 49255a96..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/refcnt.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -///////////////////////////////////////////////////////////////////////// -/// \file -/// -/// Wrappers and utilities for reference counting. -///////////////////////////////////////////////////////////////////////// - - -#ifndef OPENIMAGEIO_REFCNT_H -#define OPENIMAGEIO_REFCNT_H - -#include - -#if OIIO_CPLUSPLUS_VERSION >= 11 -# include -#else -# include -#endif - - - -OIIO_NAMESPACE_BEGIN - -#if OIIO_CPLUSPLUS_VERSION < 11 -using boost::shared_ptr; -#else -using std::shared_ptr; -#endif - - - -/// A simple intrusive pointer, modeled after std::shared_ptr and -/// boost::intrusive_ptr. -template -class intrusive_ptr -{ -public: - typedef T element_type; - - /// Default ctr - intrusive_ptr () OIIO_NOEXCEPT : m_ptr(NULL) { } - - /// Construct from a raw pointer (presumed to be just now allocated, - /// and now owned by us). - intrusive_ptr (T *ptr) : m_ptr(ptr) { - if (m_ptr) intrusive_ptr_add_ref(m_ptr); - } - - /// Construct from another intrusive_ptr. - intrusive_ptr (const intrusive_ptr &r) : m_ptr(r.get()) { - if (m_ptr) intrusive_ptr_add_ref (m_ptr); - } - -#if OIIO_CPLUSPLUS_VERSION >= 11 - /// Move construct from another intrusive_ptr. - intrusive_ptr (intrusive_ptr &&r) OIIO_NOEXCEPT : m_ptr(r.get()) { - r.m_ptr = NULL; - } -#endif - - /// Destructor - ~intrusive_ptr () { if (m_ptr) intrusive_ptr_release (m_ptr); } - - /// Assign from intrusive_ptr - intrusive_ptr & operator= (const intrusive_ptr &r) { - intrusive_ptr(r).swap (*this); - return *this; - } - -#if OIIO_CPLUSPLUS_VERSION >= 11 - /// Move assignment from intrusive_ptr - intrusive_ptr & operator= (intrusive_ptr&& r) OIIO_NOEXCEPT { - intrusive_ptr (static_cast(r)).swap(*this); - return *this; - } -#endif - - /// Reset to null reference - void reset () OIIO_NOEXCEPT { - if (m_ptr) { intrusive_ptr_release (m_ptr); m_ptr = NULL; } - } - - /// Reset to point to a pointer - void reset (T *r) { - if (m_ptr) intrusive_ptr_release (m_ptr); - m_ptr = r; - if (m_ptr) intrusive_ptr_add_ref (m_ptr); - } - - /// Swap intrusive pointers - void swap (intrusive_ptr &r) OIIO_NOEXCEPT { - T *tmp = m_ptr; m_ptr = r.m_ptr; r.m_ptr = tmp; - } - - /// Dereference - T& operator*() const { DASSERT (m_ptr); return *m_ptr; } - - /// Dereference - T* operator->() const { DASSERT (m_ptr); return m_ptr; } - - /// Get raw pointer - T* get() const OIIO_NOEXCEPT { return m_ptr; } - - /// Cast to bool to detect whether it points to anything - operator bool () const OIIO_NOEXCEPT { return m_ptr != NULL; } - -private: - T* m_ptr; // the raw pointer -}; - - - -/// Mix-in class that adds a reference count, implemented as an atomic -/// counter. -class RefCnt { -protected: - // Declare RefCnt constructors and destructors protected because they - // should only be called implicitly from within child class constructors or - // destructors. In particular, this prevents users from deleting a RefCnt* - // which is important because the destructor is non-virtual. - - RefCnt () { m_refcnt = 0; } - - /// Define copy constructor to NOT COPY reference counts! Copying a - /// struct doesn't change how many other things point to it. - RefCnt (RefCnt&) { m_refcnt = 0; } - - ~RefCnt () {} - -public: - /// Add a reference - /// - void _incref () const { ++m_refcnt; } - - /// Delete a reference, return true if that was the last reference. - /// - bool _decref () const { return (--m_refcnt) == 0; } - - /// Define operator= to NOT COPY reference counts! Assigning a struct - /// doesn't change how many other things point to it. - const RefCnt & operator= (const RefCnt&) const { return *this; } - -private: - mutable atomic_int m_refcnt; -}; - - - -/// Implementation of intrusive_ptr_add_ref, which is needed for -/// any class that you use with intrusive_ptr. -template -inline void intrusive_ptr_add_ref (T *x) -{ - x->_incref (); -} - -/// Implementation of intrusive_ptr_release, which is needed for -/// any class that you use with intrusive_ptr. -template -inline void intrusive_ptr_release (T *x) -{ - if (x->_decref ()) - delete x; -} - -// Note that intrusive_ptr_add_ref and intrusive_ptr_release MUST be a -// templated on the full type, so that they pass the right address to -// 'delete' and destroy the right type. If you try to just -// 'inline void intrusive_ptr_release (RefCnt *x)', that might seem -// clever, but it will end up getting the address of (and destroying) -// just the inherited RefCnt sub-object, not the full subclass you -// meant to delete and destroy. - - -OIIO_NAMESPACE_END - -#endif // OPENIMAGEIO_REFCNT_H diff --git a/3rdparty/oiio16/include/OpenImageIO/simd.h b/3rdparty/oiio16/include/OpenImageIO/simd.h deleted file mode 100644 index ed66be51..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/simd.h +++ /dev/null @@ -1,2289 +0,0 @@ -/* -Copyright (c) 2014 Larry Gritz et al. -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. -* Neither the name of Sony Pictures Imageworks nor the names of its - contributors may 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 simd.h -/// -/// @brief Classes for SIMD processing. -/// -/// Nice references for all the Intel intrinsics (SSE*, AVX*, etc.): -/// https://software.intel.com/sites/landingpage/IntrinsicsGuide/ -/// -/// It helped me a lot to peruse the source of these packages: -/// Syrah: https://github.com/boulos/syrah -/// Embree: https://github.com/embree -/// Vectorial: https://github.com/scoopr/vectorial -/// -/// To find out which CPU features you have: -/// Linux: cat /proc/cpuinfo -/// OSX: sysctl machdep.cpu.features - - -#pragma once - -#include -#include -#include - -#if (defined(__SSE2__) || (_MSC_VER >= 1300 && !_M_CEE_PURE)) && !defined(OIIO_NO_SSE) -#if OIIO_GNUC_VERSION >= 40400 || __clang__ -# include -#else /* this clause can go away when GCC 4.8 is the minimum: */ -# include -# include -# if defined(__SSE3__) -# include -# endif -# if defined(__SSSE3__) -# include -# endif -# if (defined(__SSE4_1__) || defined(__SSE4_2__)) -# include -# endif -#endif -# if (defined(__i386__) || defined(__x86_64__)) && (OIIO_GNUC_VERSION > 40400 || __clang__) -# include -# endif -# if (defined(__SSE4_1__) || defined(__SSE4_2__)) -# define OIIO_SIMD_SSE 4 - /* N.B. We consider both SSE4.1 and SSE4.2 to be "4". There are a few - * instructions specific to 4.2, but they are all related to string - * comparisons and CRCs, which don't currently seem relevant to OIIO, - * so for simplicity, we sweep this difference under the rug. - */ -# elif defined(__SSSE3__) -# define OIIO_SIMD_SSE 3 - /* N.B. We only use OIIO_SIMD_SSE = 3 when fully at SSSE3. In theory, - * there are a few older architectures that are SSE3 but not SSSE3, - * and this simplification means that these particular old platforms - * will only get SSE2 goodness out of our code. So be it. Anybody who - * cares about performance is probably using a 64 bit machine that's - * SSE 4.x or AVX by now. - */ -# else -# define OIIO_SIMD_SSE 2 -# endif -# define OIIO_SIMD 1 -# define OIIO_SIMD_MASK_BYTE_WIDTH 4 -# define OIIO_SIMD_MAX_SIZE_BYTES 16 -# define OIIO_SIMD_ALIGN OIIO_ALIGN(16) -# define OIIO_SIMD4_ALIGN OIIO_ALIGN(16) -# define OIIO_SSE_ALIGN OIIO_ALIGN(16) -#endif - -// FIXME Future: support AVX -#if defined(__AVX__) && !defined(OIIO_NO_AVX) - // N.B. Any machine with AVX will also have SSE -# define OIIO_SIMD_AVX 1 -// # define OIIO_SIMD_MASK_BYTE_WIDTH 4 -// # undef OIIO_SIMD_MAX_SIZE_BYTES -// # define OIIO_SIMD_MAX_SIZE_BYTES 32 -// # undef OIIO_SIMD_ALIGN -// # define OIIO_SIMD_ALIGN OIIO_ALIGN(32) -// # define OIIO_AVX_ALIGN OIIO_ALIGN(32) -#endif - -// FIXME Future: support ARM Neon -#if 0 && defined(__ARM_NEON__) && !defined(OIIO_NO_NEON) -# define OIIO_SIMD 1 -# define OIIO_SIMD_NEON 1 -# define OIIO_SIMD_MAX_SIZE_BYTES 16UL -# define OIIO_SIMD_MAX_SIZE_FLOATS 4UL -# define OIIO_SIMD_MASK_BYTE_WIDTH 4 -# define OIIO_SIMD_MAX_SIZE_BYTES 16 -# define OIIO_SIMD_ALIGN OIIO_ALIGN(16) -# define OIIO_SIMD4_ALIGN OIIO_ALIGN(16) -# define OIIO_SSE_ALIGN OIIO_ALIGN(16) -#endif - -#ifndef OIIO_SIMD -# define OIIO_SIMD 0 -# define OIIO_SIMD_ALIGN -# define OIIO_SIMD4_ALIGN -# define OIIO_SIMD_MAX_SIZE_BYTES 16 -#endif - -#include - - -OIIO_NAMESPACE_BEGIN - -namespace simd { - -class int4; -class float4; -class mask4; - - -// -// Additional private intrinsic wrappers -// -#if defined(OIIO_SIMD_SSE) - -// Shamelessly lifted from Syrah which lifted from Manta which lifted it -// from intel.com -OIIO_FORCEINLINE __m128i mm_mul_epi32 (__m128i a, __m128i b) { -#if OIIO_SIMD_SSE >= 4 /* SSE >= 4.1 */ - return _mm_mullo_epi32(a, b); -#else - // Prior to SSE 4.1, there is no _mm_mullo_epi32 instruction, so we have - // to fake it. - __m128i t0; - __m128i t1; - t0 = _mm_mul_epu32 (a, b); - t1 = _mm_mul_epu32 (_mm_shuffle_epi32 (a, 0xB1), - _mm_shuffle_epi32 (b, 0xB1)); - t0 = _mm_shuffle_epi32 (t0, 0xD8); - t1 = _mm_shuffle_epi32 (t1, 0xD8); - return _mm_unpacklo_epi32 (t0, t1); -#endif -} - - -// Shuffling. Use like this: x = shuffle<3,2,1,0>(b) -template -OIIO_FORCEINLINE __m128i shuffle_sse (__m128i v) { - return _mm_shuffle_epi32(v, _MM_SHUFFLE(i3, i2, i1, i0)); -} - -#if OIIO_SIMD_SSE >= 3 -// SSE3 has intrinsics for a few special cases -template<> OIIO_FORCEINLINE __m128i shuffle_sse<0, 0, 2, 2> (__m128i a) { - return _mm_castps_si128(_mm_moveldup_ps(_mm_castsi128_ps(a))); -} -template<> OIIO_FORCEINLINE __m128i shuffle_sse<1, 1, 3, 3> (__m128i a) { - return _mm_castps_si128(_mm_movehdup_ps(_mm_castsi128_ps(a))); -} -template<> OIIO_FORCEINLINE __m128i shuffle_sse<0, 1, 0, 1> (__m128i a) { - return _mm_castpd_si128(_mm_movedup_pd(_mm_castsi128_pd(a))); -} -#endif - -template -OIIO_FORCEINLINE __m128 shuffle_sse (__m128 a) { - return _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(a), _MM_SHUFFLE(i3, i2, i1, i0))); -} - -#if OIIO_SIMD_SSE >= 3 -// SSE3 has intrinsics for a few special cases -template<> OIIO_FORCEINLINE __m128 shuffle_sse<0, 0, 2, 2> (__m128 a) { - return _mm_moveldup_ps(a); -} -template<> OIIO_FORCEINLINE __m128 shuffle_sse<1, 1, 3, 3> (__m128 a) { - return _mm_movehdup_ps(a); -} -template<> OIIO_FORCEINLINE __m128 shuffle_sse<0, 1, 0, 1> (__m128 a) { - return _mm_castpd_ps(_mm_movedup_pd(_mm_castps_pd(a))); -} -#endif - -#endif - - - -/// mask4: A mask 4-vector, whose elements act mostly like bools, -/// accelerated by SIMD instructions when available. This is what is -/// naturally produced by SIMD comparison operators on the float4 and int4 -/// types. -class mask4 { -public: - static const char* type_name() { return "mask4"; } - typedef bool value_t; ///< Underlying equivalent scalar value type - enum { elements = 4 }; ///< Number of scalar elements - enum { bits = 128 }; ///< Total number of bits - /// simd_t is the native SIMD type used -#if defined(OIIO_SIMD_SSE) - typedef __m128 simd_t; -#endif - - /// Default constructor (contents undefined) - OIIO_FORCEINLINE mask4 () { } - - /// Destructor - OIIO_FORCEINLINE ~mask4 () { } - - /// Construct from a single value (store it in all slots) - OIIO_FORCEINLINE mask4 (bool a) { load(a); } - - /// Construct from 4 values - OIIO_FORCEINLINE mask4 (bool a, bool b, bool c, bool d) { load(a,b,c,d); } - - /// Copy construct from another mask4 - OIIO_FORCEINLINE mask4 (const mask4 &other) { -#if defined(OIIO_SIMD_SSE) - m_vec = other.m_vec; -#else - m_val[0] = other.m_val[0]; - m_val[1] = other.m_val[1]; - m_val[2] = other.m_val[2]; - m_val[3] = other.m_val[3]; -#endif - } - - /// Construct from an int4 (is each element nonzero?) - OIIO_FORCEINLINE mask4 (const int4 &i); - -#if OIIO_SIMD - /// Construct from the underlying SIMD type - OIIO_FORCEINLINE mask4 (const simd_t& m) : m_vec(m) { } - - /// Return the raw SIMD type - OIIO_FORCEINLINE operator simd_t () const { return m_vec; } - OIIO_FORCEINLINE simd_t simd () const { return m_vec; } -#endif - - /// Set all components to false - OIIO_FORCEINLINE void clear () { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_setzero_ps(); -#else - *this = false; -#endif - } - - /// Return a mask4 the is 'false' for all values - static OIIO_FORCEINLINE const mask4 False () { return mask4(false); } - - /// Return a mask4 the is 'true' for all values - static OIIO_FORCEINLINE const mask4 True () { return mask4(true); } - - /// Assign one value to all components - OIIO_FORCEINLINE const mask4 & operator= (bool a) { load(a); return *this; } - - /// Assignment of another mask4 - OIIO_FORCEINLINE const mask4 & operator= (const mask4 & other) { -#if defined(OIIO_SIMD_SSE) - m_vec = other.m_vec; -#else - m_val[0] = other.m_val[0]; - m_val[1] = other.m_val[1]; - m_val[2] = other.m_val[2]; - m_val[3] = other.m_val[3]; -#endif - return *this; - } - - /// Component access (get) - OIIO_FORCEINLINE bool operator[] (int i) const { - DASSERT(i >= 0 && i < 4); -#if defined(OIIO_SIMD_SSE) - return (_mm_movemask_ps(m_vec) >> i) & 1; -#else - return bool(m_val[i]); -#endif - } - - /// Component access (set). - /// NOTE: use with caution. The implementation sets the integer - /// value, which may not have the same bit pattern as the bool returned - /// by operator[]const. - OIIO_FORCEINLINE int& operator[] (int i) { - DASSERT(i >= 0 && i < 4); - return m_val[i]; - } - - /// Helper: load a single value into all components. - OIIO_FORCEINLINE void load (bool a) { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_castsi128_ps(_mm_set1_epi32(a ? -1 : 0)); -#else - int val = a ? -1 : 0; - m_val[0] = val; - m_val[1] = val; - m_val[2] = val; - m_val[3] = val; -#endif - } - - /// Helper: load separate values into each component. - OIIO_FORCEINLINE void load (bool a, bool b, bool c, bool d) { -#if defined(OIIO_SIMD_SSE) - // N.B. -- we need to reverse the order because of our convention - // of storing a,b,c,d in the same order in memory. - m_vec = _mm_castsi128_ps(_mm_set_epi32(d ? -1 : 0, - c ? -1 : 0, - b ? -1 : 0, - a ? -1 : 0)); -#else - m_val[0] = a ? -1 : 0; - m_val[1] = b ? -1 : 0; - m_val[2] = c ? -1 : 0; - m_val[3] = d ? -1 : 0; -#endif - } - - /// Helper: store the values into memory as bools. - OIIO_FORCEINLINE void store (bool *values) const { -#if 0 && defined(OIIO_SIMD_SSE) - // FIXME: is there a more efficient way to do this? -#else - values[0] = m_val[0] ? true : false; - values[1] = m_val[1] ? true : false; - values[2] = m_val[2] ? true : false; - values[3] = m_val[3] ? true : false; -#endif - } - - /// Store the first n values into memory. - OIIO_FORCEINLINE void store (bool *values, int n) const { - DASSERT (n >= 0 && n <= 4); - for (int i = 0; i < n; ++i) - values[i] = m_val[i] ? true : false; - } - - /// Logical "not", component-by-component - friend OIIO_FORCEINLINE mask4 operator! (const mask4 & a) { -#if defined(OIIO_SIMD_SSE) - return _mm_xor_ps (a.m_vec, True()); -#else - return mask4 (a.m_val[0] ^ (-1), a.m_val[1] ^ (-1), - a.m_val[2] ^ (-1), a.m_val[3] ^ (-1)); -#endif - } - - /// Logical "and", component-by-component - friend OIIO_FORCEINLINE mask4 operator& (const mask4 & a, const mask4 & b) { -#if defined(OIIO_SIMD_SSE) - return _mm_and_ps (a.m_vec, b.m_vec); -#else - return mask4 (a.m_val[0] & b.m_val[0], - a.m_val[1] & b.m_val[1], - a.m_val[2] & b.m_val[2], - a.m_val[3] & b.m_val[3]); -#endif - } - OIIO_FORCEINLINE const mask4& operator&= (const mask4 & b) { - return *this = *this & b; - } - - - /// Logical "or" component-by-component - friend OIIO_FORCEINLINE mask4 operator| (const mask4 & a, const mask4 & b) { -#if defined(OIIO_SIMD_SSE) - return _mm_or_ps (a.m_vec, b.m_vec); -#else - return mask4 (a.m_val[0] | b.m_val[0], - a.m_val[1] | b.m_val[1], - a.m_val[2] | b.m_val[2], - a.m_val[3] | b.m_val[3]); -#endif - } - OIIO_FORCEINLINE const mask4& operator|= (const mask4 & a) { - return *this = *this | a; - } - - /// Equality comparison, component by component - friend OIIO_FORCEINLINE const mask4 operator== (const mask4 & a, const mask4 & b) { -#if defined(OIIO_SIMD_SSE) - return _mm_castsi128_ps (_mm_cmpeq_epi32 (_mm_castps_si128 (a.m_vec), _mm_castps_si128(b.m_vec))); -#else - return mask4 (a[0] == b[0], - a[1] == b[1], - a[2] == b[2], - a[3] == b[3]); -#endif - } - - /// Inequality comparison, component by component - friend OIIO_FORCEINLINE const mask4 operator!= (const mask4 & a, const mask4 & b) { -#if defined(OIIO_SIMD_SSE) - return _mm_xor_ps (a.m_vec, b.m_vec); -#else - return mask4 (a[0] != b[0], - a[1] != b[1], - a[2] != b[2], - a[3] != b[3]); -#endif - } - - /// Stream output - friend inline std::ostream& operator<< (std::ostream& cout, const mask4 & a) { - return cout << a[0] << ' ' << a[1] << ' ' << a[2] << ' ' << a[3]; - } - -private: - // The actual data representation - union { -#if OIIO_SIMD - simd_t m_vec; -#endif - int m_val[4]; - }; -}; - - - - -/// Helper: shuffle/swizzle with constant (templated) indices. -/// Example: shuffle<1,1,2,2>(mask4(a,b,c,d)) returns (b,b,c,c) -template -OIIO_FORCEINLINE mask4 shuffle (const mask4& a) { -#if defined(OIIO_SIMD_SSE) - return shuffle_sse (a.simd()); -#else - return mask4(a[i0], a[i1], a[i2], a[i3]); -#endif -} - -/// shuffle(a) is the same as shuffle(a) -template OIIO_FORCEINLINE mask4 shuffle (const mask4& a) { return shuffle(a); } - - -/// Helper: as rapid as possible extraction of one component, when the -/// index is fixed. -template -OIIO_FORCEINLINE bool extract (const mask4& v) { - // No efficient way to do this in SSE? - return v[i]; -} - -/// Logical "and" reduction, i.e., 'and' all components together, resulting -/// in a single bool. -OIIO_FORCEINLINE bool reduce_and (const mask4& v) { -#if defined(OIIO_SIMD_SSE) - return _mm_movemask_ps(v.simd()) == 0xf; -#else - return v[0] & v[1] & v[2] & v[3]; -#endif -} - - -/// Logical "or" reduction, i.e., 'or' all components together, resulting -/// in a single bool. -OIIO_FORCEINLINE bool reduce_or (const mask4& v) { -#if defined(OIIO_SIMD_SSE) - return _mm_movemask_ps(v) != 0; -#else - return v[0] | v[1] | v[2] | v[3]; -#endif -} - - -/// Are all components true? -OIIO_FORCEINLINE bool all (const mask4& v) { return reduce_and(v) == true; } - -/// Are any components true? -OIIO_FORCEINLINE bool any (const mask4& v) { return reduce_or(v) == true; } - -/// Are all components false: -OIIO_FORCEINLINE bool none (const mask4& v) { return reduce_or(v) == false; } - - - - - -/// Integer 4-vector, accelerated by SIMD instructions when available. -class int4 { -public: - static const char* type_name() { return "int4"; } - typedef int value_t; ///< Underlying equivalent scalar value type - enum { elements = 4 }; ///< Number of scalar elements - enum { bits = 128 }; ///< Total number of bits - /// simd_t is the native SIMD type used -#if defined(OIIO_SIMD_SSE) - typedef __m128i simd_t; -#endif - - /// Default constructor (contents undefined) - OIIO_FORCEINLINE int4 () { } - - /// Destructor - OIIO_FORCEINLINE ~int4 () { } - - /// Construct from a single value (store it in all slots) - OIIO_FORCEINLINE int4 (int a) { load(a); } - - /// Construct from 2 values -- (a,a,b,b) - OIIO_FORCEINLINE int4 (int a, int b) { load(a,a,b,b); } - - /// Construct from 4 values - OIIO_FORCEINLINE int4 (int a, int b, int c, int d) { load(a,b,c,d); } - - /// Construct from a pointer to 4 values - OIIO_FORCEINLINE int4 (const int *vals) { load (vals); } - - /// Construct from a pointer to 4 unsigned short values - OIIO_FORCEINLINE explicit int4 (const unsigned short *vals) { load(vals); } - - /// Construct from a pointer to 4 signed short values - OIIO_FORCEINLINE explicit int4 (const short *vals) { load(vals); } - - /// Construct from a pointer to 4 unsigned char values (0 - 255) - OIIO_FORCEINLINE explicit int4 (const unsigned char *vals) { load(vals); } - - /// Construct from a pointer to 4 signed char values (-128 - 127) - OIIO_FORCEINLINE explicit int4 (const char *vals) { load(vals); } - - /// Copy construct from another int4 - OIIO_FORCEINLINE int4 (const int4 & other) { -#if defined(OIIO_SIMD_SSE) - m_vec = other.m_vec; -#else - m_val[0] = other.m_val[0]; - m_val[1] = other.m_val[1]; - m_val[2] = other.m_val[2]; - m_val[3] = other.m_val[3]; -#endif - } - - /// Convert a float4 to an int4. Equivalent to i = (int)f; - OIIO_FORCEINLINE explicit int4 (const float4& f); // implementation below - -#if OIIO_SIMD - /// Construct from the underlying SIMD type - OIIO_FORCEINLINE int4 (const simd_t& m) : m_vec(m) { } - - /// Return the raw SIMD type - OIIO_FORCEINLINE operator simd_t () const { return m_vec; } - OIIO_FORCEINLINE simd_t simd () const { return m_vec; } -#endif - - /// Sset all components to 0 - OIIO_FORCEINLINE void clear () { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_setzero_si128(); -#else - *this = 0.0f; -#endif - } - - /// Return an int4 with all components set to 0 - static OIIO_FORCEINLINE const int4 Zero () { -#if defined(OIIO_SIMD_SSE) - return _mm_setzero_si128(); -#else - return int4(0); -#endif - } - - /// Return an int4 with all components set to 1 - static OIIO_FORCEINLINE const int4 One () { return int4(1); } - - /// Return an int4 with incremented components (e.g., 0,1,2,3). - /// Optional argument can give a non-zero starting point. - static OIIO_FORCEINLINE const int4 Iota (int value=0) { - return int4(value,value+1,value+2,value+3); - } - - /// Assign one value to all components. - OIIO_FORCEINLINE const int4 & operator= (int a) { load(a); return *this; } - - /// Assignment from another int4 - OIIO_FORCEINLINE const int4 & operator= (int4 other) { -#if defined(OIIO_SIMD_SSE) - m_vec = other.m_vec; -#else - m_val[0] = other.m_val[0]; - m_val[1] = other.m_val[1]; - m_val[2] = other.m_val[2]; - m_val[3] = other.m_val[3]; -#endif - return *this; - } - - /// Component access (set) - OIIO_FORCEINLINE int& operator[] (int i) { - DASSERT(i<4); - return m_val[i]; - } - - /// Component access (get) - OIIO_FORCEINLINE int operator[] (int i) const { - DASSERT(i<4); - return m_val[i]; - } - - /// Helper: load a single int into all components - OIIO_FORCEINLINE void load (int a) { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_set1_epi32 (a); -#else - m_val[0] = a; - m_val[1] = a; - m_val[2] = a; - m_val[3] = a; -#endif - } - - /// Helper: load separate values into each component. - OIIO_FORCEINLINE void load (int a, int b, int c, int d) { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_set_epi32 (d, c, b, a); -#else - m_val[0] = a; - m_val[1] = b; - m_val[2] = c; - m_val[3] = d; -#endif - } - - /// Load from an array of 4 values - OIIO_FORCEINLINE void load (const int *values) { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_loadu_si128 ((const simd_t *)values); -#else - m_val[0] = values[0]; - m_val[1] = values[1]; - m_val[2] = values[2]; - m_val[3] = values[3]; -#endif - } - - OIIO_FORCEINLINE void load (const int *values, int n) { -#if defined(OIIO_SIMD_SSE) - switch (n) { - case 1: - m_vec = _mm_castps_si128 (_mm_load_ss ((const float *)values)); - break; - case 2: - // Trickery: load one double worth of bits! - m_vec = _mm_castpd_si128 (_mm_load_sd ((const double*)values)); - break; - case 3: - // Trickery: load one double worth of bits, then a float, - // and combine, casting to ints. - m_vec = _mm_castps_si128 ( - _mm_movelh_ps(_mm_castpd_ps(_mm_load_sd((const double*)values)), - _mm_load_ss ((const float *)values + 2))); - break; - case 4: - m_vec = _mm_loadu_si128 ((const simd_t *)values); - break; - default: - break; - } -#endif - for (int i = 0; i < n; ++i) - m_val[i] = values[i]; - for (int i = n; i < 4; ++i) - m_val[i] = 0; - } - - /// Load from an array of 4 unsigned short values, convert to int4 - OIIO_FORCEINLINE void load (const unsigned short *values) { -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 4 - // Trickery: load one double worth of bits = 4 uint16's! - simd_t a = _mm_castpd_si128 (_mm_load_sd ((const double *)values)); - m_vec = _mm_cvtepu16_epi32 (a); -#else - m_val[0] = values[0]; - m_val[1] = values[1]; - m_val[2] = values[2]; - m_val[3] = values[3]; -#endif - } - - /// Load from an array of 4 unsigned short values, convert to int4 - OIIO_FORCEINLINE void load (const short *values) { -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 4 - // Trickery: load one double worth of bits = 4 int16's! - simd_t a = _mm_castpd_si128 (_mm_load_sd ((const double *)values)); - m_vec = _mm_cvtepi16_epi32 (a); -#else - m_val[0] = values[0]; - m_val[1] = values[1]; - m_val[2] = values[2]; - m_val[3] = values[3]; -#endif - } - - /// Load from an array of 4 unsigned char values, convert to int4 - OIIO_FORCEINLINE void load (const unsigned char *values) { -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 4 - // Trickery: load one float worth of bits = 4 uint8's! - simd_t a = _mm_castps_si128 (_mm_load_ss ((const float *)values)); - m_vec = _mm_cvtepu8_epi32 (a); -#else - m_val[0] = values[0]; - m_val[1] = values[1]; - m_val[2] = values[2]; - m_val[3] = values[3]; -#endif - } - - /// Load from an array of 4 unsigned char values, convert to int4 - OIIO_FORCEINLINE void load (const char *values) { -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 4 - // Trickery: load one float worth of bits = 4 uint8's! - simd_t a = _mm_castps_si128 (_mm_load_ss ((const float *)values)); - m_vec = _mm_cvtepi8_epi32 (a); -#else - m_val[0] = values[0]; - m_val[1] = values[1]; - m_val[2] = values[2]; - m_val[3] = values[3]; -#endif - } - - /// Store the values into memory - OIIO_FORCEINLINE void store (int *values) const { -#if defined(OIIO_SIMD_SSE) - // Use an unaligned store -- it's just as fast when the memory turns - // out to be aligned, nearly as fast even when unaligned. Not worth - // the headache of using stores that require alignment. - _mm_storeu_si128 ((simd_t *)values, m_vec); -#else - values[0] = m_val[0]; - values[1] = m_val[1]; - values[2] = m_val[2]; - values[3] = m_val[3]; -#endif - } - - /// Store the first n values into memory - OIIO_FORCEINLINE void store (int *values, int n) const { - DASSERT (n >= 0 && n <= 4); -#if defined(OIIO_SIMD_SSE) - // For SSE, there is a speed advantage to storing all 4 components. - if (n == 4) - store (values); - else -#endif - for (int i = 0; i < n; ++i) - values[i] = m_val[i]; - } - - friend OIIO_FORCEINLINE int4 operator+ (const int4& a, const int4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_add_epi32 (a.m_vec, b.m_vec); -#else - return int4 (a.m_val[0] + b.m_val[0], - a.m_val[1] + b.m_val[1], - a.m_val[2] + b.m_val[2], - a.m_val[3] + b.m_val[3]); -#endif - } - - OIIO_FORCEINLINE const int4 & operator+= (const int4& a) { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_add_epi32 (m_vec, a.m_vec); -#else - m_val[0] += a.m_val[0]; - m_val[1] += a.m_val[1]; - m_val[2] += a.m_val[2]; - m_val[3] += a.m_val[3]; -#endif - return *this; - } - - OIIO_FORCEINLINE int4 operator- () const { -#if defined(OIIO_SIMD_SSE) - return _mm_sub_epi32 (_mm_setzero_si128(), m_vec); -#else - return int4 (-m_val[0], -m_val[1], -m_val[2], -m_val[3]); -#endif - } - - friend OIIO_FORCEINLINE int4 operator- (const int4& a, const int4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_sub_epi32 (a.m_vec, b.m_vec); -#else - return int4 (a.m_val[0] - b.m_val[0], - a.m_val[1] - b.m_val[1], - a.m_val[2] - b.m_val[2], - a.m_val[3] - b.m_val[3]); -#endif - } - - OIIO_FORCEINLINE const int4 & operator-= (const int4& a) { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_sub_epi32 (m_vec, a.m_vec); -#else - m_val[0] -= a.m_val[0]; - m_val[1] -= a.m_val[1]; - m_val[2] -= a.m_val[2]; - m_val[3] -= a.m_val[3]; -#endif - return *this; - } - - friend OIIO_FORCEINLINE int4 operator* (const int4& a, const int4& b) { -#if defined(OIIO_SIMD_SSE) - return mm_mul_epi32 (a.m_vec, b.m_vec); -#else - return int4 (a.m_val[0] * b.m_val[0], - a.m_val[1] * b.m_val[1], - a.m_val[2] * b.m_val[2], - a.m_val[3] * b.m_val[3]); -#endif - } - - OIIO_FORCEINLINE const int4 & operator*= (const int4& a) { -#if defined(OIIO_SIMD_SSE) - m_vec = mm_mul_epi32 (m_vec, a.m_vec); -#else - m_val[0] *= a.m_val[0]; - m_val[1] *= a.m_val[1]; - m_val[2] *= a.m_val[2]; - m_val[3] *= a.m_val[3]; -#endif - return *this; - } - - OIIO_FORCEINLINE const int4 & operator*= (int val) { -#if defined(OIIO_SIMD_SSE) - m_vec = mm_mul_epi32 (m_vec, _mm_set1_epi32(val)); -#else - m_val[0] *= val; - m_val[1] *= val; - m_val[2] *= val; - m_val[3] *= val; -#endif - return *this; - } - - friend OIIO_FORCEINLINE int4 operator/ (const int4& a, const int4& b) { - // NO INTEGER DIVISION IN SSE! - return int4 (a.m_val[0] / b.m_val[0], - a.m_val[1] / b.m_val[1], - a.m_val[2] / b.m_val[2], - a.m_val[3] / b.m_val[3]); - } - - OIIO_FORCEINLINE const int4 & operator/= (const int4& a) { - // NO INTEGER DIVISION IN SSE! - m_val[0] /= a.m_val[0]; - m_val[1] /= a.m_val[1]; - m_val[2] /= a.m_val[2]; - m_val[3] /= a.m_val[3]; - return *this; - } - - OIIO_FORCEINLINE const int4 & operator/= (int val) { - // NO INTEGER DIVISION IN SSE! - m_val[0] /= val; - m_val[1] /= val; - m_val[2] /= val; - m_val[3] /= val; - return *this; - } - - friend OIIO_FORCEINLINE int4 operator% (const int4& a, const int4& b) { - // NO INTEGER MODULUS in SSE! - return int4 (a.m_val[0] % b.m_val[0], - a.m_val[1] % b.m_val[1], - a.m_val[2] % b.m_val[2], - a.m_val[3] % b.m_val[3]); - } - OIIO_FORCEINLINE const int4 & operator%= (const int4& a) { - // NO INTEGER MODULUS in SSE! - m_val[0] %= a.m_val[0]; - m_val[1] %= a.m_val[1]; - m_val[2] %= a.m_val[2]; - m_val[3] %= a.m_val[3]; - return *this; - } - friend OIIO_FORCEINLINE int4 operator% (const int4& a, int w) { - // NO INTEGER MODULUS in SSE! - return int4 (a.m_val[0] % w, - a.m_val[1] % w, - a.m_val[2] % w, - a.m_val[3] % w); - } - OIIO_FORCEINLINE const int4 & operator%= (int a) { - // NO INTEGER MODULUS IN SSE! - m_val[0] %= a; - m_val[1] %= a; - m_val[2] %= a; - m_val[3] %= a; - return *this; - } - friend OIIO_FORCEINLINE int4 operator% (int a, const int4& b) { - // NO INTEGER MODULUS in SSE! - return int4 (a % b.m_val[0], - a % b.m_val[1], - a % b.m_val[2], - a % b.m_val[3]); - } - - - friend OIIO_FORCEINLINE int4 operator& (const int4& a, const int4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_and_si128 (a.m_vec, b.m_vec); -#else - return int4 (a.m_val[0] & b.m_val[0], - a.m_val[1] & b.m_val[1], - a.m_val[2] & b.m_val[2], - a.m_val[3] & b.m_val[3]); -#endif - } - OIIO_FORCEINLINE const int4 & operator&= (const int4& a) { - return *this = *this & a; - } - - - friend OIIO_FORCEINLINE int4 operator| (const int4& a, const int4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_or_si128 (a.m_vec, b.m_vec); -#else - return int4 (a.m_val[0] | b.m_val[0], - a.m_val[1] | b.m_val[1], - a.m_val[2] | b.m_val[2], - a.m_val[3] | b.m_val[3]); -#endif - } - OIIO_FORCEINLINE const int4 & operator|= (const int4& a) { - return *this = *this | a; - } - - friend OIIO_FORCEINLINE int4 operator^ (const int4& a, const int4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_xor_si128 (a.m_vec, b.m_vec); -#else - return int4 (a.m_val[0] ^ b.m_val[0], - a.m_val[1] ^ b.m_val[1], - a.m_val[2] ^ b.m_val[2], - a.m_val[3] ^ b.m_val[3]); -#endif - } - OIIO_FORCEINLINE const int4 & operator^= (const int4& a) { - return *this = *this ^ a; - } - - OIIO_FORCEINLINE int4 operator<< (const unsigned int bits) const { -#if defined(OIIO_SIMD_SSE) - return _mm_slli_epi32 (m_vec, bits); -#else - return int4 (m_val[0] << bits, - m_val[1] << bits, - m_val[2] << bits, - m_val[3] << bits); -#endif - } - - OIIO_FORCEINLINE const int4 & operator<<= (const unsigned int bits) { - return *this = *this << bits; - } - - // Arithmetic shift right (matches int>>, in that it preserves the - // sign bit). - OIIO_FORCEINLINE int4 operator>> (const unsigned int bits) { -#if defined(OIIO_SIMD_SSE) - return _mm_srai_epi32 (m_vec, bits); -#else - return int4 (m_val[0] >> bits, - m_val[1] >> bits, - m_val[2] >> bits, - m_val[3] >> bits); -#endif - } - - OIIO_FORCEINLINE const int4 & operator>>= (const unsigned int bits) { - return *this = *this >> bits; - } - - // Shift right logical -- unsigned shift. This differs from operator>> - // in how it handles the sign bit. (1<<31) >> 1 == (1<<31), but - // srl((1<<31),1) == 1<<30. - OIIO_FORCEINLINE friend int4 srl (const int4& val, const unsigned int bits) { -#if defined(OIIO_SIMD_SSE) - return _mm_srli_epi32 (val.m_vec, bits); -#else - return int4 (int ((unsigned int)(val.m_val[0]) >> bits), - int ((unsigned int)(val.m_val[1]) >> bits), - int ((unsigned int)(val.m_val[2]) >> bits), - int ((unsigned int)(val.m_val[3]) >> bits)); -#endif - } - - - friend OIIO_FORCEINLINE mask4 operator== (const int4& a, const int4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_castsi128_ps(_mm_cmpeq_epi32 (a.m_vec, b.m_vec)); -#else - return mask4 (a[0] == b[0], a[1] == b[1], a[2] == b[2], a[3] == b[3]); -#endif - } - - friend OIIO_FORCEINLINE mask4 operator!= (const int4& a, const int4& b) { - return ! (a == b); - } - - friend OIIO_FORCEINLINE mask4 operator< (const int4& a, const int4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_castsi128_ps(_mm_cmplt_epi32 (a.m_vec, b.m_vec)); -#else - return mask4 (a[0] < b[0], a[1] < b[1], a[2] < b[2], a[3] < b[3]); -#endif - } - - friend OIIO_FORCEINLINE mask4 operator> (const int4& a, const int4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_castsi128_ps(_mm_cmpgt_epi32 (a.m_vec, b.m_vec)); -#else - return mask4 (a[0] > b[0], a[1] > b[1], a[2] > b[2], a[3] > b[3]); -#endif - } - - friend OIIO_FORCEINLINE mask4 operator>= (const int4& a, const int4& b) { - return !(a < b); - } - - friend OIIO_FORCEINLINE mask4 operator<= (const int4& a, const int4& b) { - return !(a > b); - } - - /// Stream output - friend inline std::ostream& operator<< (std::ostream& cout, const int4& val) { - return cout << val[0] << ' ' << val[1] << ' ' << val[2] << ' ' << val[3]; - } - -private: - // The actual data representation - union { -#if OIIO_SIMD - simd_t m_vec; -#endif - value_t m_val[4]; - }; - -}; - - - -/// Helper: shuffle/swizzle with constant (templated) indices. -/// Example: shuffle<1,1,2,2>(mask4(a,b,c,d)) returns (b,b,c,c) -template -OIIO_FORCEINLINE int4 shuffle (const int4& a) { -#if defined(OIIO_SIMD_SSE) - return shuffle_sse (__m128i(a)); -#else - return int4(a[i0], a[i1], a[i2], a[i3]); -#endif -} - -/// shuffle(a) is the same as shuffle(a) -template OIIO_FORCEINLINE int4 shuffle (const int4& a) { return shuffle(a); } - - -/// Helper: as rapid as possible extraction of one component, when the -/// index is fixed. -template -OIIO_FORCEINLINE int extract (const int4& v) { -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 4 - return _mm_extract_epi32(v.simd(), i); // SSE4.1 only -#else - return v[i]; -#endif -} - - -/// Helper: substitute val for a[i] -template -OIIO_FORCEINLINE int4 insert (const int4& a, int val) { -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 4 - return _mm_insert_epi32 (a, val, i); -#else - int4 tmp = a; - tmp[i] = val; - return tmp; -#endif -} - - -/// The sum of all components, returned in all components. -OIIO_FORCEINLINE int4 vreduce_add (const int4& v) { -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 3 - // People seem to agree that SSE3 does add reduction best with 2 - // horizontal adds. - // suppose v = (a, b, c, d) - simd::int4 ab_cd = _mm_hadd_epi32 (v.simd(), v.simd()); - // ab_cd = (a+b, c+d, a+b, c+d) - simd::int4 abcd = _mm_hadd_epi32 (ab_cd.simd(), ab_cd.simd()); - // all abcd elements are a+b+c+d, return an element as fast as possible - return abcd; -#elif defined(OIIO_SIMD_SSE) - // I think this is the best we can do for SSE2, and I'm still not sure - // it's faster than the default scalar operation. But anyway... - // suppose v = (a, b, c, d) - int4 ab_ab_cd_cd = shuffle<1,0,3,2>(v) + v; - // ab_ab_cd_cd = (b,a,d,c) + (a,b,c,d) = (a+b,a+b,c+d,c+d) - int4 cd_cd_ab_ab = shuffle<2,3,0,1>(ab_ab_cd_cd); - // cd_cd_ab_ab = (c+d,c+d,a+b,a+b) - int4 abcd = ab_ab_cd_cd + cd_cd_ab_ab; // a+b+c+d in all components - return abcd; -#else - return int4(v[0] + v[1] + v[2] + v[3]); -#endif -} - - -/// The sum of all components, returned as a scalar. -OIIO_FORCEINLINE int reduce_add (const int4& v) { -#if defined(OIIO_SIMD_SSE) - return _mm_cvtsi128_si32(vreduce_add(v)); -#else - return v[0] + v[1] + v[2] + v[3]; -#endif -} - - -/// Bitwise "and" of all components. -OIIO_FORCEINLINE int reduce_and (const int4& v) { -#if defined(OIIO_SIMD_SSE) - // I think this is the best we can do for SSE, and I'm still not sure - // it's faster than the default scalar operation. But anyway... - // suppose v = (a, b, c, d) - int4 x = shuffle<1,0,3,2>(v) & v; - return extract<0>(x) & extract<2>(x); -#else - return v[0] & v[1] & v[2] & v[3]; -#endif -} - - -/// Bitwise "or" of all components. -OIIO_FORCEINLINE int reduce_or (const int4& v) { -#if defined(OIIO_SIMD_SSE) - // I think this is the best we can do for SSE, and I'm still not sure - // it's faster than the default scalar operation. But anyway... - // suppose v = (a, b, c, d) - int4 x = shuffle<1,0,3,2>(v) | v; - return extract<0>(x) | extract<2>(x); -#else - return v[0] | v[1] | v[2] | v[3]; -#endif -} - -/// Use a mask to select between components of a (if mask[i] is false) and -/// b (if mask[i] is true). -OIIO_FORCEINLINE int4 blend (const int4& a, const int4& b, const mask4& mask) -{ -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 4 /* SSE >= 4.1 */ - return _mm_blendv_epi8 (a.simd(), b.simd(), _mm_castps_si128(mask)); -#elif defined(OIIO_SIMD_SSE) /* SSE2 */ - return _mm_or_si128 (_mm_and_si128(_mm_castps_si128(mask.simd()), b.simd()), - _mm_andnot_si128(_mm_castps_si128(mask.simd()), a.simd())); -#else - return int4 (mask[0] ? b[0] : a[0], - mask[1] ? b[1] : a[1], - mask[2] ? b[2] : a[2], - mask[3] ? b[3] : a[3]); -#endif -} - - - -/// Use a mask to select between components of a (if mask[i] is true) or -/// 0 (if mask[i] is true). -OIIO_FORCEINLINE int4 blend0 (const int4& a, const mask4& mask) -{ -#if defined(OIIO_SIMD_SSE) - return _mm_and_si128(_mm_castps_si128(mask), a.simd()); -#else - return int4 (mask[0] ? a[0] : 0.0f, - mask[1] ? a[1] : 0.0f, - mask[2] ? a[2] : 0.0f, - mask[3] ? a[3] : 0.0f); -#endif -} - - - -/// Use a mask to select between components of a (if mask[i] is FALSE) or -/// 0 (if mask[i] is TRUE). -OIIO_FORCEINLINE int4 blend0not (const int4& a, const mask4& mask) -{ -#if defined(OIIO_SIMD_SSE) - return _mm_andnot_si128(_mm_castps_si128(mask), a.simd()); -#else - return int4 (mask[0] ? 0.0f : a[0], - mask[1] ? 0.0f : a[1], - mask[2] ? 0.0f : a[2], - mask[3] ? 0.0f : a[3]); -#endif -} - - - -/// Per-element absolute value. -OIIO_FORCEINLINE int4 abs (const int4& a) -{ -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 3 - return _mm_abs_epi32(a.simd()); -#else - return int4 (std::abs(a[0]), std::abs(a[1]), std::abs(a[2]), std::abs(a[3])); -#endif -} - -/// Per-element min -OIIO_FORCEINLINE int4 min (const int4& a, const int4& b) -{ -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 4 /* SSE >= 4.1 */ - return _mm_min_epi32 (a, b); -#else - return int4 (std::min (a[0], b[0]), - std::min (a[1], b[1]), - std::min (a[2], b[2]), - std::min (a[3], b[3])); -#endif -} - -/// Per-element max -OIIO_FORCEINLINE int4 max (const int4& a, const int4& b) -{ -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 4 /* SSE >= 4.1 */ - return _mm_max_epi32 (a, b); -#else - return int4 (std::max (a[0], b[0]), - std::max (a[1], b[1]), - std::max (a[2], b[2]), - std::max (a[3], b[3])); -#endif -} - - -// Circular bit rotate by k bits, for 4 values at once. -OIIO_FORCEINLINE int4 rotl32 (const int4& x, const unsigned int k) -{ - return (x<= 2 - // V4f is not defined for older Ilmbase. It's certainly safe for 2.x. - - /// Construct from a Imath::V4f - OIIO_FORCEINLINE float4 (const Imath::V4f &v) { load ((const float *)&v); } - - /// Cast to a Imath::V4f - OIIO_FORCEINLINE const Imath::V4f& V4f () const { return *(const Imath::V4f*)this; } -#endif - - /// Construct from a pointer to 4 unsigned short values - OIIO_FORCEINLINE explicit float4 (const unsigned short *vals) { load(vals); } - - /// Construct from a pointer to 4 short values - OIIO_FORCEINLINE explicit float4 (const short *vals) { load(vals); } - - /// Construct from a pointer to 4 unsigned char values - OIIO_FORCEINLINE explicit float4 (const unsigned char *vals) { load(vals); } - - /// Construct from a pointer to 4 char values - OIIO_FORCEINLINE explicit float4 (const char *vals) { load(vals); } - -#ifdef _HALF_H_ - /// Construct from a pointer to 4 half (16 bit float) values - OIIO_FORCEINLINE explicit float4 (const half *vals) { load(vals); } -#endif - - /// Assign a single value to all components - OIIO_FORCEINLINE const float4 & operator= (float a) { load(a); return *this; } - - /// Assign a float4 - OIIO_FORCEINLINE const float4 & operator= (float4 other) { -#if defined(OIIO_SIMD_SSE) - m_vec = other.m_vec; -#else - m_val[0] = other.m_val[0]; - m_val[1] = other.m_val[1]; - m_val[2] = other.m_val[2]; - m_val[3] = other.m_val[3]; -#endif - return *this; - } - - /// Return a float4 with all components set to 0.0 - static OIIO_FORCEINLINE const float4 Zero () { -#if defined(OIIO_SIMD_SSE) - return _mm_setzero_ps(); -#else - return float4(0.0f); -#endif - } - - /// Return a float4 with all components set to 1.0 - static OIIO_FORCEINLINE const float4 One () { return float4(1.0f); } - - /// Return a float4 with incremented components (e.g., 0.0,1.0,2.0,3.0). - /// Optional argument can give a non-zero starting point. - static OIIO_FORCEINLINE const float4 Iota (float value=0.0f) { - return float4(value,value+1.0f,value+2.0f,value+3.0f); - } - - /// Sset all components to 0.0 - OIIO_FORCEINLINE void clear () { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_setzero_ps(); -#else - *this = 0.0f; -#endif - } - -#if defined(ILMBASE_VERSION_MAJOR) && ILMBASE_VERSION_MAJOR >= 2 - /// Assign from a Imath::V4f - OIIO_FORCEINLINE const float4 & operator= (const Imath::V4f &v) { - load ((const float *)&v); - return *this; - } -#endif - - /// Assign from a Imath::V3f - OIIO_FORCEINLINE const float4 & operator= (const Imath::V3f &v) { - load (v[0], v[1], v[2], 0.0f); - return *this; - } - - /// Component access (set) - OIIO_FORCEINLINE float& operator[] (int i) { - DASSERT(i<4); - return m_val[i]; - } - /// Component access (get) - OIIO_FORCEINLINE float operator[] (int i) const { - DASSERT(i<4); - return m_val[i]; - } - - /// Helper: load a single value into all components - OIIO_FORCEINLINE void load (float val) { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_set1_ps (val); -#else - m_val[0] = val; - m_val[1] = val; - m_val[2] = val; - m_val[3] = val; -#endif - } - - /// Helper: load 3 or 4 values. (If 3 are supplied, the 4th will be 0.) - OIIO_FORCEINLINE void load (float a, float b, float c, float d=0.0f) { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_set_ps (d, c, b, a); -#else - m_val[0] = a; - m_val[1] = b; - m_val[2] = c; - m_val[3] = d; -#endif - } - - /// Load from an array of 4 values - OIIO_FORCEINLINE void load (const float *values) { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_loadu_ps (values); -#else - m_val[0] = values[0]; - m_val[1] = values[1]; - m_val[2] = values[2]; - m_val[3] = values[3]; -#endif - } - - /// Load from a partial array of <=4 values. Unassigned values are - /// undefined. - OIIO_FORCEINLINE void load (const float *values, int n) { -#if defined(OIIO_SIMD_SSE) - switch (n) { - case 1: - m_vec = _mm_load_ss (values); - break; - case 2: - // Trickery: load one double worth of bits! - m_vec = _mm_castpd_ps (_mm_load_sd ((const double*)values)); - break; - case 3: - m_vec = _mm_setr_ps (values[0], values[1], values[2], 0.0f); - // This looks wasteful, but benchmarks show that it's the - // fastest way to set 3 values with the 4th getting zero. - // Actually, gcc and clang both turn it into something more - // efficient than _mm_setr_ps. The version below looks smart, - // but was much more expensive as the _mm_setr_ps! - // __m128 xy = _mm_castsi128_ps(_mm_loadl_epi64((const __m128i*)values)); - // m_vec = _mm_movelh_ps(xy, _mm_load_ss (values + 2)); - break; - case 4: - m_vec = _mm_loadu_ps (values); - break; - default: - break; - } -#else - for (int i = 0; i < n; ++i) - m_val[i] = values[i]; - for (int i = n; i < 4; ++i) - m_val[i] = 0; -#endif - } - - /// Load from an array of 4 unsigned short values, convert to float - OIIO_FORCEINLINE void load (const unsigned short *values) { -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 2 - m_vec = _mm_cvtepi32_ps (int4(values).simd()); -#else - m_val[0] = values[0]; - m_val[1] = values[1]; - m_val[2] = values[2]; - m_val[3] = values[3]; -#endif - } - - /// Load from an array of 4 short values, convert to float - OIIO_FORCEINLINE void load (const short *values) { -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 2 - m_vec = _mm_cvtepi32_ps (int4(values).simd()); -#else - m_val[0] = values[0]; - m_val[1] = values[1]; - m_val[2] = values[2]; - m_val[3] = values[3]; -#endif - } - - /// Load from an array of 4 unsigned char values, convert to float - OIIO_FORCEINLINE void load (const unsigned char *values) { -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 2 - m_vec = _mm_cvtepi32_ps (int4(values).simd()); -#else - m_val[0] = values[0]; - m_val[1] = values[1]; - m_val[2] = values[2]; - m_val[3] = values[3]; -#endif - } - - /// Load from an array of 4 char values, convert to float - OIIO_FORCEINLINE void load (const char *values) { -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 2 - m_vec = _mm_cvtepi32_ps (int4(values).simd()); -#else - m_val[0] = values[0]; - m_val[1] = values[1]; - m_val[2] = values[2]; - m_val[3] = values[3]; -#endif - } - -#ifdef _HALF_H_ - /// Load from an array of 4 half values, convert to float - OIIO_FORCEINLINE void load (const half *values) { -#ifdef __F16C__ /* Enabled 16 bit float instructions! */ - __m128i a = _mm_castpd_si128 (_mm_load_sd ((const double *)values)); - m_vec = _mm_cvtph_ps (a); -#elif defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 2 - // SSE half-to-float by Fabian "ryg" Giesen. Public domain. - // https://gist.github.com/rygorous/2144712 - int4 h ((const unsigned short *)values); -# define SSE_CONST4(name, val) static const OIIO_SIMD_ALIGN uint32_t name[4] = { (val), (val), (val), (val) } -# define CONST(name) *(const __m128i *)&name -# define CONSTF(name) *(const __m128 *)&name - SSE_CONST4(mask_nosign, 0x7fff); - SSE_CONST4(magic, (254 - 15) << 23); - SSE_CONST4(was_infnan, 0x7bff); - SSE_CONST4(exp_infnan, 255 << 23); - __m128i mnosign = CONST(mask_nosign); - __m128i expmant = _mm_and_si128(mnosign, h); - __m128i justsign = _mm_xor_si128(h, expmant); - __m128i expmant2 = expmant; // copy (just here for counting purposes) - __m128i shifted = _mm_slli_epi32(expmant, 13); - __m128 scaled = _mm_mul_ps(_mm_castsi128_ps(shifted), *(const __m128 *)&magic); - __m128i b_wasinfnan = _mm_cmpgt_epi32(expmant2, CONST(was_infnan)); - __m128i sign = _mm_slli_epi32(justsign, 16); - __m128 infnanexp = _mm_and_ps(_mm_castsi128_ps(b_wasinfnan), CONSTF(exp_infnan)); - __m128 sign_inf = _mm_or_ps(_mm_castsi128_ps(sign), infnanexp); - __m128 final = _mm_or_ps(scaled, sign_inf); - // ~11 SSE2 ops. - m_vec = final; -# undef SSE_CONST4 -# undef CONST -# undef CONSTF -#else /* No SIMD defined: */ - m_val[0] = values[0]; - m_val[1] = values[1]; - m_val[2] = values[2]; - m_val[3] = values[3]; -#endif - } -#endif /* _HALF_H_ */ - - OIIO_FORCEINLINE void store (float *values) const { -#if defined(OIIO_SIMD_SSE) - // Use an unaligned store -- it's just as fast when the memory turns - // out to be aligned, nearly as fast even when unaligned. Not worth - // the headache of using stores that require alignment. - _mm_storeu_ps (values, m_vec); -#else - values[0] = m_val[0]; - values[1] = m_val[1]; - values[2] = m_val[2]; - values[3] = m_val[3]; -#endif - } - - /// Store the first n values into memory - OIIO_FORCEINLINE void store (float *values, int n) const { - DASSERT (n >= 0 && n <= 4); -#if defined(OIIO_SIMD_SSE) - switch (n) { - case 1: - _mm_store_ss (values, m_vec); - break; - case 2: - // Trickery: store two floats as a double worth of bits - _mm_store_sd ((double*)values, _mm_castps_pd(m_vec)); - break; - case 3: - values[0] = m_val[0]; - values[1] = m_val[1]; - values[2] = m_val[2]; - // This looks wasteful, but benchmarks show that it's the - // fastest way to store 3 values, in benchmarks was faster than - // this, below: - // _mm_store_sd ((double*)values, _mm_castps_pd(m_vec)); - // _mm_store_ss (values + 2, _mm_movehl_ps(m_vec,m_vec)); - break; - case 4: - store (values); - break; - default: - break; - } -#else - for (int i = 0; i < n; ++i) - values[i] = m_val[i]; -#endif - } - - friend OIIO_FORCEINLINE float4 operator+ (const float4& a, const float4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_add_ps (a.m_vec, b.m_vec); -#else - return float4 (a.m_val[0] + b.m_val[0], - a.m_val[1] + b.m_val[1], - a.m_val[2] + b.m_val[2], - a.m_val[3] + b.m_val[3]); -#endif - } - - OIIO_FORCEINLINE const float4 & operator+= (const float4& a) { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_add_ps (m_vec, a.m_vec); -#else - m_val[0] += a.m_val[0]; - m_val[1] += a.m_val[1]; - m_val[2] += a.m_val[2]; - m_val[3] += a.m_val[3]; -#endif - return *this; - } - - OIIO_FORCEINLINE float4 operator- () const { -#if defined(OIIO_SIMD_SSE) - return _mm_sub_ps (_mm_setzero_ps(), m_vec); -#else - return float4 (-m_val[0], -m_val[1], -m_val[2], -m_val[3]); -#endif - } - - friend OIIO_FORCEINLINE float4 operator- (const float4& a, const float4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_sub_ps (a.m_vec, b.m_vec); -#else - return float4 (a.m_val[0] - b.m_val[0], - a.m_val[1] - b.m_val[1], - a.m_val[2] - b.m_val[2], - a.m_val[3] - b.m_val[3]); -#endif - } - - OIIO_FORCEINLINE const float4 & operator-= (const float4& a) { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_sub_ps (m_vec, a.m_vec); -#else - m_val[0] -= a.m_val[0]; - m_val[1] -= a.m_val[1]; - m_val[2] -= a.m_val[2]; - m_val[3] -= a.m_val[3]; -#endif - return *this; - } - - friend OIIO_FORCEINLINE float4 operator* (const float4& a, const float4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_mul_ps (a.m_vec, b.m_vec); -#else - return float4 (a.m_val[0] * b.m_val[0], - a.m_val[1] * b.m_val[1], - a.m_val[2] * b.m_val[2], - a.m_val[3] * b.m_val[3]); -#endif - } - - OIIO_FORCEINLINE const float4 & operator*= (const float4& a) { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_mul_ps (m_vec, a.m_vec); -#else - m_val[0] *= a.m_val[0]; - m_val[1] *= a.m_val[1]; - m_val[2] *= a.m_val[2]; - m_val[3] *= a.m_val[3]; -#endif - return *this; - } - OIIO_FORCEINLINE const float4 & operator*= (float val) { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_mul_ps (m_vec, _mm_set1_ps(val)); -#else - m_val[0] *= val; - m_val[1] *= val; - m_val[2] *= val; - m_val[3] *= val; -#endif - return *this; - } - - friend OIIO_FORCEINLINE float4 operator/ (const float4& a, const float4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_div_ps (a.m_vec, b.m_vec); -#else - return float4 (a.m_val[0] / b.m_val[0], - a.m_val[1] / b.m_val[1], - a.m_val[2] / b.m_val[2], - a.m_val[3] / b.m_val[3]); -#endif - } - OIIO_FORCEINLINE const float4 & operator/= (const float4& a) { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_div_ps (m_vec, a.m_vec); -#else - m_val[0] /= a.m_val[0]; - m_val[1] /= a.m_val[1]; - m_val[2] /= a.m_val[2]; - m_val[3] /= a.m_val[3]; -#endif - return *this; - } - OIIO_FORCEINLINE const float4 & operator/= (float val) { -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_div_ps (m_vec, _mm_set1_ps(val)); -#else - m_val[0] /= val; - m_val[1] /= val; - m_val[2] /= val; - m_val[3] /= val; -#endif - return *this; - } - - - friend OIIO_FORCEINLINE mask4 operator== (const float4& a, const float4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_cmpeq_ps (a.m_vec, b.m_vec); -#else - return mask4 (a[0] == b[0], a[1] == b[1], a[2] == b[2], a[3] == b[3]); -#endif - } - - friend OIIO_FORCEINLINE mask4 operator!= (const float4& a, const float4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_cmpneq_ps (a.m_vec, b.m_vec); -#else - return mask4 (a[0] != b[0], a[1] != b[1], a[2] != b[2], a[3] != b[3]); -#endif - } - - friend OIIO_FORCEINLINE mask4 operator< (const float4& a, const float4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_cmplt_ps (a.m_vec, b.m_vec); -#else - return mask4 (a[0] < b[0], a[1] < b[1], a[2] < b[2], a[3] < b[3]); -#endif - } - - friend OIIO_FORCEINLINE mask4 operator> (const float4& a, const float4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_cmpgt_ps (a.m_vec, b.m_vec); -#else - return mask4 (a[0] > b[0], a[1] > b[1], a[2] > b[2], a[3] > b[3]); -#endif - } - - friend OIIO_FORCEINLINE mask4 operator>= (const float4& a, const float4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_cmpge_ps (a.m_vec, b.m_vec); -#else - return mask4 (a[0] >= b[0], a[1] >= b[1], a[2] >= b[2], a[3] >= b[3]); -#endif - } - - friend OIIO_FORCEINLINE mask4 operator<= (const float4& a, const float4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_cmple_ps (a.m_vec, b.m_vec); -#else - return mask4 (a[0] <= b[0], a[1] <= b[1], a[2] <= b[2], a[3] <= b[3]); -#endif - } - - // Some oddball items that are handy - - /// Combine the first two components of A with the first two components - /// of B. - friend OIIO_FORCEINLINE float4 AxyBxy (const float4& a, const float4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_movelh_ps (a.m_vec, b.m_vec); -#else - return float4 (a[0], a[1], b[0], b[1]); -#endif - } - - /// Combine the first two components of A with the first two components - /// of B, but interleaved. - friend OIIO_FORCEINLINE float4 AxBxAyBy (const float4& a, const float4& b) { -#if defined(OIIO_SIMD_SSE) - return _mm_unpacklo_ps (a.m_vec, b.m_vec); -#else - return float4 (a[0], b[0], a[1], b[1]); -#endif - } - - /// Return xyz components, plus 0 for w - float4 xyz0 () const { -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 4 - return _mm_insert_ps (m_vec, _mm_set_ss(0.0f), 3<<4); -#elif defined(OIIO_SIMD_SSE) /* SSE2 */ - float4 tmp = m_vec; - tmp[3] = 0.0f; - return tmp; -#else - return float4 (m_val[0], m_val[1], m_val[2], 0.0f); -#endif - } - - /// Stream output - friend inline std::ostream& operator<< (std::ostream& cout, const float4& val) { - return cout << val[0] << ' ' << val[1] << ' ' << val[2] << ' ' << val[3]; - } - -private: - // The actual data representation - union { -#if OIIO_SIMD - simd_t m_vec; -#endif - value_t m_val[4]; - }; -}; - - - - -// Implementation had to be after the definition of int4. -OIIO_FORCEINLINE mask4::mask4 (const int4& i) -{ -#if defined(OIIO_SIMD_SSE) - m_vec = (i != int4::Zero()); -#else - m_val[0] = i[0] ? -1 : 0; - m_val[1] = i[1] ? -1 : 0; - m_val[2] = i[2] ? -1 : 0; - m_val[3] = i[3] ? -1 : 0; -#endif -} - - -// Implementation had to be after the definition of float4. -OIIO_FORCEINLINE int4::int4 (const float4& f) -{ -#if defined(OIIO_SIMD_SSE) - m_vec = _mm_cvttps_epi32(f.simd()); -#else - m_val[0] = (int) f[0]; - m_val[1] = (int) f[1]; - m_val[2] = (int) f[2]; - m_val[3] = (int) f[3]; -#endif -} - - -/// Helper: shuffle/swizzle with constant (templated) indices. -/// Example: shuffle<1,1,2,2>(mask4(a,b,c,d)) returns (b,b,c,c) -template -OIIO_FORCEINLINE float4 shuffle (const float4& a) { -#if defined(OIIO_SIMD_SSE) - return shuffle_sse (__m128(a)); -#else - return float4(a[i0], a[i1], a[i2], a[i3]); -#endif -} - -/// shuffle(a) is the same as shuffle(a) -template OIIO_FORCEINLINE float4 shuffle (const float4& a) { return shuffle(a); } - - -/// Helper: as rapid as possible extraction of one component, when the -/// index is fixed. -template -OIIO_FORCEINLINE float extract (const float4& a) { -#if defined(OIIO_SIMD_SSE) - return _mm_cvtss_f32(shuffle_sse(a.simd())); -#else - return a[i]; -#endif -} - -#if defined(OIIO_SIMD_SSE) -template<> OIIO_FORCEINLINE float extract<0> (const float4& a) { - return _mm_cvtss_f32(a.simd()); -} -#endif - - -/// Helper: substitute val for a[i] -template -OIIO_FORCEINLINE float4 insert (const float4& a, float val) { -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 4 - return _mm_insert_ps (a, _mm_set_ss(val), i<<4); -#else - float4 tmp = a; - tmp[i] = val; - return tmp; -#endif -} - - -OIIO_FORCEINLINE int4 bitcast_to_int4 (const mask4& x) -{ -#if defined(OIIO_SIMD_SSE) - return _mm_castps_si128 (x.simd()); -#else - return *(int4 *)&x; -#endif -} - -OIIO_FORCEINLINE int4 bitcast_to_int4 (const float4& x) -{ -#if defined(OIIO_SIMD_SSE) - return _mm_castps_si128 (x.simd()); -#else - return *(int4 *)&x; -#endif -} - -OIIO_FORCEINLINE float4 bitcast_to_float4 (const int4& x) -{ -#if defined(OIIO_SIMD_SSE) - return _mm_castsi128_ps (x.simd()); -#else - return *(float4 *)&x; -#endif -} - - -/// The sum of all components, returned in all components. -OIIO_FORCEINLINE float4 vreduce_add (const float4& v) { -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 3 - // People seem to agree that SSE3 does add reduction best with 2 - // horizontal adds. - // suppose v = (a, b, c, d) - simd::float4 ab_cd = _mm_hadd_ps (v.simd(), v.simd()); - // ab_cd = (a+b, c+d, a+b, c+d) - simd::float4 abcd = _mm_hadd_ps (ab_cd.simd(), ab_cd.simd()); - // all abcd elements are a+b+c+d - return abcd; -#elif defined(OIIO_SIMD_SSE) - // I think this is the best we can do for SSE2, and I'm still not sure - // it's faster than the default scalar operation. But anyway... - // suppose v = (a, b, c, d) - float4 ab_ab_cd_cd = shuffle<1,0,3,2>(v) + v; - // now x = (b,a,d,c) + (a,b,c,d) = (a+b,a+b,c+d,c+d) - float4 cd_cd_ab_ab = shuffle<2,3,0,1>(ab_ab_cd_cd); - // now y = (c+d,c+d,a+b,a+b) - float4 abcd = ab_ab_cd_cd + cd_cd_ab_ab; // a+b+c+d in all components - return abcd; -#else - return float4 (v[0] + v[1] + v[2] + v[3]); -#endif -} - - -/// The sum of all components, returned as a scalar. -OIIO_FORCEINLINE float reduce_add (const float4& v) { -#if defined(OIIO_SIMD_SSE) - return _mm_cvtss_f32(vreduce_add (v)); -#else - return v[0] + v[1] + v[2] + v[3]; -#endif -} - - - -/// Return the float dot (inner) product of a and b. -OIIO_FORCEINLINE float dot (const float4 &a, const float4 &b) { - return reduce_add (a*b); -} - - -/// Return the float dot (inner) product of the first three components of -/// a and b. -OIIO_FORCEINLINE float dot3 (const float4 &a, const float4 &b) { - return reduce_add (insert<3>(a*b, 0.0f)); -} - - -/// Return the dot (inner) product of a and b in every component of a -/// float4. -OIIO_FORCEINLINE float4 vdot (const float4 &a, const float4 &b) { - return vreduce_add (a*b); -} - - -/// Return the dot (inner) product of the first three components of -/// a and b, in every product of a float4. -OIIO_FORCEINLINE float4 vdot3 (const float4 &a, const float4 &b) { - return vreduce_add (insert<3>(a*b, 0.0f)); -} - - -/// Use a mask to select between components of a (if mask[i] is false) and -/// b (if mask[i] is true). -OIIO_FORCEINLINE float4 blend (const float4& a, const float4& b, const mask4& mask) -{ -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 4 - // SSE >= 4.1 only - return _mm_blendv_ps (a.simd(), b.simd(), mask.simd()); -#elif defined(OIIO_SIMD_SSE) - // Trick for SSE < 4.1 - return _mm_or_ps (_mm_and_ps(mask.simd(), b.simd()), - _mm_andnot_ps(mask.simd(), a.simd())); -#else - return float4 (mask[0] ? b[0] : a[0], - mask[1] ? b[1] : a[1], - mask[2] ? b[2] : a[2], - mask[3] ? b[3] : a[3]); -#endif -} - - -/// Use a mask to select between components of a (if mask[i] is true) or -/// 0 (if mask[i] is true). -OIIO_FORCEINLINE float4 blend0 (const float4& a, const mask4& mask) -{ -#if defined(OIIO_SIMD_SSE) - return _mm_and_ps(mask.simd(), a.simd()); -#else - return float4 (mask[0] ? a[0] : 0.0f, - mask[1] ? a[1] : 0.0f, - mask[2] ? a[2] : 0.0f, - mask[3] ? a[3] : 0.0f); -#endif -} - - - -/// Use a mask to select between components of a (if mask[i] is FALSE) or -/// 0 (if mask[i] is TRUE). -OIIO_FORCEINLINE float4 blend0not (const float4& a, const mask4& mask) -{ -#if defined(OIIO_SIMD_SSE) - return _mm_andnot_ps(mask.simd(), a.simd()); -#else - return float4 (mask[0] ? 0.0f : a[0], - mask[1] ? 0.0f : a[1], - mask[2] ? 0.0f : a[2], - mask[3] ? 0.0f : a[3]); -#endif -} - - - -/// Per-element absolute value. -OIIO_FORCEINLINE float4 abs (const float4& a) -{ -#if defined(OIIO_SIMD_SSE) - // Just clear the sign bit for cheap fabsf - return _mm_and_ps (a.simd(), _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff))); -#else - return float4 (fabsf(a[0]), fabsf(a[1]), fabsf(a[2]), fabsf(a[3])); -#endif -} - -/// Per-element ceil. -OIIO_FORCEINLINE float4 ceil (const float4& a) -{ -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 4 /* SSE >= 4.1 */ - return _mm_ceil_ps (a); -#else - return float4 (ceilf(a[0]), ceilf(a[1]), ceilf(a[2]), ceilf(a[3])); -#endif -} - -/// Per-element floor. -OIIO_FORCEINLINE float4 floor (const float4& a) -{ -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 4 /* SSE >= 4.1 */ - return _mm_floor_ps (a); -#else - return float4 (floorf(a[0]), floorf(a[1]), floorf(a[2]), floorf(a[3])); -#endif -} - -/// Per-element (int)floor. -OIIO_FORCEINLINE int4 floori (const float4& a) -{ -#if defined(OIIO_SIMD_SSE) && OIIO_SIMD_SSE >= 4 /* SSE >= 4.1 */ - return int4(floor(a)); -#elif defined(OIIO_SIMD_SSE) /* SSE2/3 */ - int4 i (a); // truncates - int4 isneg = bitcast_to_int4 (a < float4::Zero()); - return i + isneg; - // The trick here (thanks, Cycles, for letting me spy on your code) is - // that the comparison will return (int)-1 for components that are less - // than zero, and adding that is the same as subtracting one! -#else - return int4 ((int)floorf(a[0]), (int)floorf(a[1]), - (int)floorf(a[2]), (int)floorf(a[3])); -#endif -} - -/// Per-element min -OIIO_FORCEINLINE float4 min (const float4& a, const float4& b) -{ -#if defined(OIIO_SIMD_SSE) - return _mm_min_ps (a, b); -#else - return float4 (std::min (a[0], b[0]), - std::min (a[1], b[1]), - std::min (a[2], b[2]), - std::min (a[3], b[3])); -#endif -} - -/// Per-element max -OIIO_FORCEINLINE float4 max (const float4& a, const float4& b) -{ -#if defined(OIIO_SIMD_SSE) - return _mm_max_ps (a, b); -#else - return float4 (std::max (a[0], b[0]), - std::max (a[1], b[1]), - std::max (a[2], b[2]), - std::max (a[3], b[3])); -#endif -} - - - -/// Transpose the rows and columns of the 4x4 matrix [a b c d]. -/// In the end, a will have the original (a[0], b[0], c[0], d[0]), -/// b will have the original (a[1], b[1], c[1], d[1]), and so on. -OIIO_FORCEINLINE void transpose (float4 &a, float4 &b, float4 &c, float4 &d) -{ -#if defined(OIIO_SIMD_SSE) - _MM_TRANSPOSE4_PS (a, b, c, d); -#else - float4 A (a[0], b[0], c[0], d[0]); - float4 B (a[1], b[1], c[1], d[1]); - float4 C (a[2], b[2], c[2], d[2]); - float4 D (a[3], b[3], c[3], d[3]); - a = A; b = B; c = C; d = D; -#endif -} - - - -OIIO_FORCEINLINE void transpose (const float4& a, const float4& b, const float4& c, const float4& d, - float4 &r0, float4 &r1, float4 &r2, float4 &r3) -{ -#if defined(OIIO_SIMD_SSE) - //_MM_TRANSPOSE4_PS (a, b, c, d); - float4 l02 = _mm_unpacklo_ps (a, c); - float4 h02 = _mm_unpackhi_ps (a, c); - float4 l13 = _mm_unpacklo_ps (b, d); - float4 h13 = _mm_unpackhi_ps (b, d); - r0 = _mm_unpacklo_ps (l02, l13); - r1 = _mm_unpackhi_ps (l02, l13); - r2 = _mm_unpacklo_ps (h02, h13); - r3 = _mm_unpackhi_ps (h02, h13); -#else - r0.load (a[0], b[0], c[0], d[0]); - r1.load (a[1], b[1], c[1], d[1]); - r2.load (a[2], b[2], c[2], d[2]); - r3.load (a[3], b[3], c[3], d[3]); -#endif -} - - -/// Transpose the rows and columns of the 4x4 matrix [a b c d]. -/// In the end, a will have the original (a[0], b[0], c[0], d[0]), -/// b will have the original (a[1], b[1], c[1], d[1]), and so on. -OIIO_FORCEINLINE void transpose (int4 &a, int4 &b, int4 &c, int4 &d) -{ -#if defined(OIIO_SIMD_SSE) - __m128 A = _mm_castsi128_ps (a); - __m128 B = _mm_castsi128_ps (b); - __m128 C = _mm_castsi128_ps (c); - __m128 D = _mm_castsi128_ps (d); - _MM_TRANSPOSE4_PS (A, B, C, D); - a = _mm_castps_si128 (A); - b = _mm_castps_si128 (B); - c = _mm_castps_si128 (C); - d = _mm_castps_si128 (D); -#else - int4 A (a[0], b[0], c[0], d[0]); - int4 B (a[1], b[1], c[1], d[1]); - int4 C (a[2], b[2], c[2], d[2]); - int4 D (a[3], b[3], c[3], d[3]); - a = A; b = B; c = C; d = D; -#endif -} - -OIIO_FORCEINLINE void transpose (const int4& a, const int4& b, const int4& c, const int4& d, - int4 &r0, int4 &r1, int4 &r2, int4 &r3) -{ -#if defined(OIIO_SIMD_SSE) - //_MM_TRANSPOSE4_PS (a, b, c, d); - __m128 A = _mm_castsi128_ps (a); - __m128 B = _mm_castsi128_ps (b); - __m128 C = _mm_castsi128_ps (c); - __m128 D = _mm_castsi128_ps (d); - _MM_TRANSPOSE4_PS (A, B, C, D); - r0 = _mm_castps_si128 (A); - r1 = _mm_castps_si128 (B); - r2 = _mm_castps_si128 (C); - r3 = _mm_castps_si128 (D); -#else - r0.load (a[0], b[0], c[0], d[0]); - r1.load (a[1], b[1], c[1], d[1]); - r2.load (a[2], b[2], c[2], d[2]); - r3.load (a[3], b[3], c[3], d[3]); -#endif -} - - - -/// Make a float4 consisting of the first element of each of 4 float4's. -OIIO_FORCEINLINE float4 AxBxCxDx (const float4& a, const float4& b, - const float4& c, const float4& d) -{ -#if defined(OIIO_SIMD_SSE) - float4 l02 = _mm_unpacklo_ps (a, c); - float4 l13 = _mm_unpacklo_ps (b, d); - return _mm_unpacklo_ps (l02, l13); -#else - return float4 (a[0], b[0], c[0], d[0]); -#endif -} - - -/// Make an int4 consisting of the first element of each of 4 int4's. -OIIO_FORCEINLINE int4 AxBxCxDx (const int4& a, const int4& b, - const int4& c, const int4& d) -{ -#if defined(OIIO_SIMD_SSE) - int4 l02 = _mm_unpacklo_epi32 (a, c); - int4 l13 = _mm_unpacklo_epi32 (b, d); - return _mm_unpacklo_epi32 (l02, l13); -#else - return int4 (a[0], b[0], c[0], d[0]); -#endif -} - - - -/// Template to retrieve the vector type from the scalar. For example, -/// simd::VecType will be float4. -template struct VecType {}; -template<> struct VecType { typedef int4 type; }; -template<> struct VecType { typedef float4 type; }; -template<> struct VecType { typedef mask4 type; }; - - -} // end namespace - -OIIO_NAMESPACE_END diff --git a/3rdparty/oiio16/include/OpenImageIO/strided_ptr.h b/3rdparty/oiio16/include/OpenImageIO/strided_ptr.h deleted file mode 100644 index bf2a34e2..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/strided_ptr.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - Copyright 2014 Larry Gritz and the other authors and contributors. - All Rights Reserved. - Based on BSD-licensed software Copyright 2004 NVIDIA Corp. - - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -#pragma once - -#include - -#include "oiioversion.h" - - -OIIO_NAMESPACE_BEGIN - - -/// strided_ptr looks like a 'T*', but it incorporates a stride (in -/// bytes) that may be different than sizeof(T). Operators ++, --, [], and -/// so on, take the stride into account when computing where each "array -/// element" actually exists. A strided_ptr is mutable (the values -/// pointed to may be modified), whereas an strided_ptr is not -/// mutable. -template -class strided_ptr { -public: - strided_ptr (T* ptr=NULL, ptrdiff_t stride=sizeof(T)) - : m_ptr(ptr), m_stride(stride) { } - strided_ptr (const strided_ptr &p) - : m_ptr(p.m_ptr), m_stride(p.m_stride) {} - const strided_ptr& operator= (const strided_ptr &p) { - m_ptr = p.m_ptr; - m_stride = p.m_stride; - return *this; - } - - T& operator* () const { return *m_ptr; } - T& operator[] (ptrdiff_t pos) const { return get(pos); } - T* data() const { return m_ptr; } - ptrdiff_t stride () const { return m_stride; } - bool operator== (const T *p) const { return m_ptr == p; } - bool operator!= (const T *p) const { return m_ptr != p; } - - const strided_ptr& operator++ () { // prefix - m_ptr = getptr(1); - return *this; - } - strided_ptr operator++(int) { // postfix - strided_ptr r; - ++(*this); - return r; - } - const strided_ptr& operator-- () { // prefix - m_ptr = getptr(-1); - return *this; - } - strided_ptr operator--(int) { // postfix - strided_ptr r; - --(*this); - return r; - } - - strided_ptr operator+ (int d) const { - return strided_ptr (getptr(d), m_stride); - } - const strided_ptr& operator+= (int d) { - m_ptr = getptr(d); - return *this; - } - strided_ptr operator- (int d) const { - return strided_ptr (getptr(-d), m_stride); - } - const strided_ptr& operator-= (int d) { - m_ptr = getptr(-d); - return *this; - } - -private: - T * m_ptr; - ptrdiff_t m_stride; - inline T* getptr (ptrdiff_t pos=0) const { - return (T*)((char *)m_ptr + pos*m_stride); - } - inline T& get (ptrdiff_t pos=0) const { - return *getptr(pos); - } -}; - - - -OIIO_NAMESPACE_END diff --git a/3rdparty/oiio16/include/OpenImageIO/string_view.h b/3rdparty/oiio16/include/OpenImageIO/string_view.h deleted file mode 100644 index 460fc18e..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/string_view.h +++ /dev/null @@ -1,353 +0,0 @@ -/* - Copyright 2014 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "oiioversion.h" -#include "export.h" - - -OIIO_NAMESPACE_BEGIN - - -/// string_view : a non-owning, non-copying, non-allocating reference to a -/// sequence of characters. It encapsulates both a character pointer and a -/// length. -/// -/// A function that takes a string input (but does not need to alter the -/// string in place) may use a string_view parameter and accept input that -/// is any of char* (C string), string literal (constant char array), a -/// std::string (C++ string), or OIIO ustring. For all of these cases, no -/// extra allocations are performed, and no extra copies of the string -/// contents are performed (as they would be, for example, if the function -/// took a const std::string& argument but was passed a char* or string -/// literal). -/// -/// Furthermore, a function that returns a copy or a substring of one of its -/// inputs (for example, a substr()-like function) may return a string_view -/// rather than a std::string, and thus generate its return value without -/// any allocation or copying. Upon assignment to a std::string or ustring, -/// it will properly auto-convert. -/// -/// There are two important caveats to using this class: -/// 1. The string_view merely refers to characters owned by another string, -/// so the string_view may not be used outside the lifetime of the string -/// it refers to. Thus, string_view is great for parameter passing, but -/// it's not a good idea to use a string_view to store strings in a data -/// structure (unless you are really sure you know what you're doing). -/// 2. Because the run of characters that the string_view refers to may not -/// be 0-terminated, it is important to distinguish between the data() -/// method, which returns the pointer to the characters, and the c_str() -/// method, which is guaranteed to return a valid C string that is -/// 0-terminated. Thus, if you want to pass the contents of a string_view -/// to a function that expects a 0-terminated string (say, fopen), you -/// must call fopen(my_string_view.c_str()). Note that the usual case -/// is that the string_view does refer to a 0-terminated string, and in -/// that case c_str() returns the same thing as data() without any extra -/// expense; but in the rare case that it is not 0-terminated, c_str() -/// will incur extra expense to internally allocate a valid C string. -/// - - -class OIIO_API string_view { -public: - typedef char charT; - typedef charT value_type; - typedef const charT* pointer; - typedef const charT* const_pointer; - typedef const charT& reference; - typedef const charT& const_reference; - typedef const_pointer const_iterator; - typedef const_iterator iterator; - typedef std::reverse_iterator const_reverse_iterator; - typedef const_reverse_iterator reverse_iterator; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef std::char_traits traits; - static const size_type npos = ~size_type(0); - - /// Default ctr - string_view () { init(NULL,0); } - /// Copy ctr - string_view (const string_view ©) { - init (copy.m_chars, copy.m_len); - } - /// Construct from char* and length. - string_view (const charT *chars, size_t len) { init (chars, len); } - /// Construct from char*, use strlen to determine length. - string_view (const charT *chars) { - init (chars, chars ? strlen(chars) : 0); - } - /// Construct from std::string. - string_view (const std::string &str) { init (str.data(), str.size()); } - - std::string str() const { - return (m_chars ? std::string(m_chars,m_len) : std::string()); - } - - /// Explicitly request a 0-terminated string. USUALLY, this turns out to - /// be just data(), with no significant added expense. But in the more - /// rare case that the string_view represetns a non-0-terminated - /// substring, it will force an allocation and copy underneath. - const char * c_str() const; - - // assignments - string_view& operator= (const string_view ©) { - init (copy.data(), copy.length()); - return *this; - } - - operator std::string() const { return str(); } - - // iterators - const_iterator begin() const { return m_chars; } - const_iterator end() const { return m_chars + m_len; } - const_iterator cbegin() const { return m_chars; } - const_iterator cend() const { return m_chars + m_len; } - const_reverse_iterator rbegin() const { return const_reverse_iterator (end()); } - const_reverse_iterator rend() const { return const_reverse_iterator (begin()); } - const_reverse_iterator crbegin() const { return const_reverse_iterator (end()); } - const_reverse_iterator crend() const { return const_reverse_iterator (begin()); } - - // capacity - size_type size() const { return m_len; } - size_type length() const { return m_len; } - size_type max_size() const { return m_len; } - bool empty() const { return m_len == 0; } - - // element access - const charT& operator[] (size_type pos) const { return m_chars[pos]; } - const charT& at (size_t pos) const { - if (pos >= m_len) - throw (std::out_of_range ("OpenImageIO::string_view::at")); - return m_chars[pos]; - } - const charT& front() const { return m_chars[0]; } - const charT& back() const { return m_chars[m_len-1]; } - const charT* data() const { return m_chars; } - - // modifiers - void clear() { init(NULL,0); } - void remove_prefix(size_type n) { - if (n > m_len) - n = m_len; - m_chars += n; - m_len -= n; - } - void remove_suffix(size_type n) { - if (n > m_len) - n = m_len; - m_len -= n; - } - - string_view substr (size_type pos, size_type n=npos) const { - if (pos > size()) - return string_view(); // start past end -> return empty - if (n == npos || pos + n > size()) - n = size() - pos; - return string_view (data() + pos, n); - } - - int compare (string_view x) const { - const int cmp = std::char_traits::compare (m_chars, x.m_chars, (std::min)(m_len, x.m_len)); - return cmp != 0 ? cmp : int(m_len - x.m_len); - // Equivalent to: - // cmp != 0 ? cmp : (m_len == x.m_len ? 0 : (m_len < x.m_len ? -1 : 1)); - } - -#if 0 - // Do these later if anybody needs them - bool starts_with(string_view x) const; - bool ends_with(string_view x) const; -#endif - - /// Find the first occurrence of substring s in *this, starting at - /// position pos. - size_type find (string_view s, size_t pos=0) const { - if (pos > size()) - pos = size(); - const_iterator i = std::search (this->cbegin()+pos, this->cend(), - s.cbegin(), s.cend(), traits::eq); - return i == this->cend() ? npos : std::distance (this->cbegin(), i); - } - - /// Find the first occurrence of character c in *this, starting at - /// position pos. - size_type find (charT c, size_t pos=0) const { - if (pos > size()) - pos = size(); - const_iterator i = std::find_if (this->cbegin()+pos, this->cend(), - traits_eq(c)); - return i == this->cend() ? npos : std::distance (this->cbegin(), i); - } - - /// Find the last occurrence of substring s *this, but only those - /// occurrences earlier than position pos. - size_type rfind (string_view s, size_t pos=npos) const { - if (pos > size()) - pos = size(); - const_reverse_iterator b = this->crbegin()+(size()-pos); - const_reverse_iterator e = this->crend(); - const_reverse_iterator i = std::search (b, e, s.crbegin(), s.crend(), traits::eq); - return i == e ? npos : (reverse_distance(this->crbegin(),i) - s.size() + 1); - } - - /// Find the last occurrence of character c in *this, but only those - /// occurrences earlier than position pos. - size_type rfind (charT c, size_t pos=npos) const { - if (pos > size()) - pos = size(); - const_reverse_iterator b = this->crbegin()+(size()-pos); - const_reverse_iterator e = this->crend(); - const_reverse_iterator i = std::find_if (b, e, traits_eq(c)); - return i == e ? npos : reverse_distance (this->crbegin(),i); - } - - size_type find_first_of (charT c, size_t pos=0) const { return find (c, pos); } - - size_type find_last_of (charT c, size_t pos=npos) const { return rfind (c, pos); } - - size_type find_first_of (string_view s) const { - const_iterator i = std::find_first_of (this->cbegin(), this->cend(), - s.cbegin(), s.cend(), traits::eq); - return i == this->cend() ? npos : std::distance (this->cbegin(), i); - } - - size_type find_last_of (string_view s) const { - const_reverse_iterator i = std::find_first_of (this->crbegin(), this->crend(), - s.cbegin(), s.cend(), traits::eq); - return i == this->crend() ? npos : reverse_distance (this->crbegin(), i); - } - - size_type find_first_not_of (string_view s) const { - const_iterator i = find_not_of (this->cbegin(), this->cend(), s); - return i == this->cend() ? npos : std::distance (this->cbegin(), i); - } - - size_type find_first_not_of (charT c) const { - for (const_iterator i = this->cbegin(); i != this->cend(); ++i) - if (! traits::eq (c, *i)) - return std::distance (this->cbegin(), i); - return npos; - } - - size_type find_last_not_of (string_view s) const { - const_reverse_iterator i = find_not_of (this->crbegin(), this->crend(), s); - return i == this->crend() ? npos : reverse_distance (this->crbegin(), i); - } - - size_type find_last_not_of (charT c) const { - for (const_reverse_iterator i = this->crbegin(); i != this->crend(); ++i) - if (! traits::eq (c, *i)) - return reverse_distance (this->crbegin(), i); - return npos; - } - -private: - const charT * m_chars; - size_t m_len; - - void init (const charT *chars, size_t len) { - m_chars = chars; - m_len = len; - } - - template - size_type reverse_distance (r_iter first, r_iter last) const { - return m_len - 1 - std::distance (first, last); - } - - template - iter find_not_of (iter first, iter last, string_view s) const { - for ( ; first != last ; ++first) - if (! traits::find (s.data(), s.length(), *first)) - return first; - return last; - } - - class traits_eq { - public: - traits_eq (charT ch) : ch(ch) {} - bool operator () (charT val) const { return traits::eq (ch, val); } - charT ch; - }; - -}; - - - -inline bool operator== (string_view x, string_view y) { - return x.size() == y.size() ? (x.compare (y) == 0) : false; -} - -inline bool operator!= (string_view x, string_view y) { - return x.size() == y.size() ? (x.compare (y) != 0) : true; -} - -inline bool operator< (string_view x, string_view y) { - return x.compare(y) < 0; -} - -inline bool operator> (string_view x, string_view y) { - return x.compare(y) > 0; -} - -inline bool operator<= (string_view x, string_view y) { - return x.compare(y) <= 0; -} - -inline bool operator>= (string_view x, string_view y) { - return x.compare(y) >= 0; -} - - - -// Inserter -inline std::ostream& operator<< (std::ostream& out, const string_view& str) { - if (out.good()) - out.write (str.data(), str.size()); - return out; -} - - - -// Temporary name equivalence -typedef string_view string_ref; - - -OIIO_NAMESPACE_END diff --git a/3rdparty/oiio16/include/OpenImageIO/strutil.h b/3rdparty/oiio16/include/OpenImageIO/strutil.h deleted file mode 100644 index 4af55840..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/strutil.h +++ /dev/null @@ -1,483 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -///////////////////////////////////////////////////////////////////////// -/// @file strutil.h -/// -/// @brief String-related utilities, all in namespace Strutil. -///////////////////////////////////////////////////////////////////////// - - - -#ifndef OPENIMAGEIO_STRUTIL_H -#define OPENIMAGEIO_STRUTIL_H - -#include -#include -#include -#include -#include -#include - -#include "export.h" -#include "oiioversion.h" -#include "tinyformat.h" -#include "string_view.h" -#include "hash.h" - -#ifndef OPENIMAGEIO_PRINTF_ARGS -# ifndef __GNUC__ -# define __attribute__(x) -# endif - // Enable printf-like warnings with gcc by attaching - // OPENIMAGEIO_PRINTF_ARGS to printf-like functions. Eg: - // - // void foo (const char* fmt, ...) OPENIMAGEIO_PRINTF_ARGS(1,2); - // - // The arguments specify the positions of the format string and the the - // beginning of the varargs parameter list respectively. - // - // For member functions with arguments like the example above, you need - // OPENIMAGEIO_PRINTF_ARGS(2,3) instead. (gcc includes the implicit this - // pointer when it counts member function arguments.) -# define OPENIMAGEIO_PRINTF_ARGS(fmtarg_pos, vararg_pos) \ - __attribute__ ((format (printf, fmtarg_pos, vararg_pos) )) -#endif - - -OIIO_NAMESPACE_BEGIN -/// @namespace Strutil -/// -/// @brief String-related utilities. -namespace Strutil { - -/// Construct a std::string in a printf-like fashion. In other words, -/// something like: -/// std::string s = Strutil::format ("blah %d %g", (int)foo, (float)bar); -/// -/// The printf argument list is fully typesafe via tinyformat; format -/// conceptually has the signature -/// -/// std::string Strutil::format (const char *fmt, ...); -TINYFORMAT_WRAP_FORMAT (std::string, format, /**/, - std::ostringstream msg;, msg, return msg.str();) - -/// Return a std::string formatted from printf-like arguments. Like the -/// real sprintf, this is not guaranteed type-safe and is not extensible -/// like format(). You would only want to use this instead of the safe -/// format() in rare situations where you really need to use obscure -/// printf features that aren't supported by tinyformat. -std::string OIIO_API format_raw (const char *fmt, ...) - OPENIMAGEIO_PRINTF_ARGS(1,2); - -/// Return a std::string formatted from printf-like arguments -- passed -/// already as a va_list. Like vsprintf, this is not guaranteed -/// type-safe and is not extensible like format(). -std::string OIIO_API vformat (const char *fmt, va_list ap) - OPENIMAGEIO_PRINTF_ARGS(1,0); - -/// Return a string expressing a number of bytes, in human readable form. -/// - memformat(153) -> "153 B" -/// - memformat(15300) -> "14.9 KB" -/// - memformat(15300000) -> "14.6 MB" -/// - memformat(15300000000LL) -> "14.2 GB" -std::string OIIO_API memformat (long long bytes, int digits=1); - -/// Return a string expressing an elapsed time, in human readable form. -/// e.g. "0:35.2" -std::string OIIO_API timeintervalformat (double secs, int digits=1); - - -/// Get a map with RESTful arguments extracted from the given string 'str'. -/// Add it into the 'result' argument (Warning: the 'result' argument may -/// be changed even if 'get_rest_arguments ()' return an error!). -/// Return true on success, false on error. -/// Acceptable forms: -/// - text?arg1=val1&arg2=val2... -/// - ?arg1=val1&arg2=val2... -/// Everything before question mark will be saved into the 'base' argument. -bool OIIO_API get_rest_arguments (const std::string &str, std::string &base, - std::map &result); - -/// Take a string that may have embedded newlines, tabs, etc., and turn -/// those characters into escape sequences like \n, \t, \v, \b, \r, \f, -/// \a, \\, \". -std::string OIIO_API escape_chars (string_view unescaped); - -/// Take a string that has embedded escape sequences (\\, \", \n, etc.) -/// and collapse them into the 'real' characters. -std::string OIIO_API unescape_chars (string_view escaped); - -/// Word-wrap string 'src' to no more than columns width, splitting at -/// space characters. It assumes that 'prefix' characters are already -/// printed, and furthermore, if it should need to wrap, it prefixes that -/// number of spaces in front of subsequent lines. By illustration, -/// wordwrap("0 1 2 3 4 5 6 7 8", 4, 10) should return: -/// "0 1 2\n 3 4 5\n 6 7 8" -std::string OIIO_API wordwrap (string_view src, int columns=80, int prefix=0); - -/// Hash a string_view. -inline size_t -strhash (string_view s) -{ - return s.length() ? farmhash::Hash (s) : 0; -} - - - -/// Case-insensitive comparison of strings. For speed, this always uses -/// a static locale that doesn't require a mutex. -bool OIIO_API iequals (string_view a, string_view b); - -/// Does 'a' start with the string 'b', with a case-sensitive comparison? -bool OIIO_API starts_with (string_view a, string_view b); - -/// Does 'a' start with the string 'b', with a case-insensitive comparison? -/// For speed, this always uses a static locale that doesn't require a mutex. -bool OIIO_API istarts_with (string_view a, string_view b); - -/// Does 'a' end with the string 'b', with a case-sensitive comparison? -bool OIIO_API ends_with (string_view a, string_view b); - -/// Does 'a' end with the string 'b', with a case-insensitive comparison? -/// For speed, this always uses a static locale that doesn't require a mutex. -bool OIIO_API iends_with (string_view a, string_view b); - -/// Does 'a' contain the string 'b' within it? -bool OIIO_API contains (string_view a, string_view b); - -/// Does 'a' contain the string 'b' within it, using a case-insensitive -/// comparison? -bool OIIO_API icontains (string_view a, string_view b); - -/// Convert to upper case, faster than std::toupper because we use -/// a static locale that doesn't require a mutex lock. -void OIIO_API to_lower (std::string &a); - -/// Convert to upper case, faster than std::toupper because we use -/// a static locale that doesn't require a mutex lock. -void OIIO_API to_upper (std::string &a); - -/// Return a reference to the section of str that has all consecutive -/// characters in chars removed from the beginning and ending. If chars is -/// empty, it will be interpreted as " \t\n\r\f\v" (whitespace). -string_view OIIO_API strip (string_view str, string_view chars=string_view()); - -/// Fills the "result" list with the words in the string, using sep as -/// the delimiter string. If maxsplit is > -1, at most maxsplit splits -/// are done. If sep is "", any whitespace string is a separator. -void OIIO_API split (string_view str, std::vector &result, - string_view sep = string_view(), int maxsplit = -1); -void OIIO_API split (string_view str, std::vector &result, - string_view sep = string_view(), int maxsplit = -1); - -/// Join all the strings in 'seq' into one big string, separated by the -/// 'sep' string. -std::string OIIO_API join (const std::vector &seq, - string_view sep = string_view()); -std::string OIIO_API join (const std::vector &seq, - string_view sep = string_view()); - -/// Repeat a string formed by concatenating str n times. -std::string OIIO_API repeat (string_view str, int n); - - -// Helper template to test if a string is a generic type -template -inline bool string_is (string_view /*s*/) { - return false; // Generic: assume there is an explicit specialization -} -// Special case for int -template <> inline bool string_is (string_view s) { - char *endptr = 0; - strtol (s.data(), &endptr, 10); - return (s.data() + s.size() == endptr); -} -// Special case for float -template <> inline bool string_is (string_view s) { - char *endptr = 0; - strtod (s.data(), &endptr); - return (s.data() + s.size() == endptr); -} - - - -// Helper template to convert from generic type to string -template -inline T from_string (string_view s) { - return T(s); // Generic: assume there is an explicit converter -} -// Special case for int -template<> inline int from_string (string_view s) { - return strtol (s.c_str(), NULL, 10); -} -// Special case for float -template<> inline float from_string (string_view s) { - return (float)strtod (s.c_str(), NULL); -} - - - -/// Given a string containing values separated by a comma (or optionally -/// another separator), extract the individual values, placing them into -/// vals[] which is presumed to already contain defaults. If only a single -/// value was in the list, replace all elements of vals[] with the value. -/// Otherwise, replace them in the same order. A missing value will simply -/// not be replaced. Return the number of values found in the list -/// (including blank or malformed ones). If the vals vector was empty -/// initially, grow it as necessary. -/// -/// For example, if T=float, suppose initially, vals[] = {0, 1, 2}, then -/// "3.14" results in vals[] = {3.14, 3.14, 3.14} -/// "3.14,,-2.0" results in vals[] = {3.14, 1, -2.0} -/// -/// This can work for type T = int, float, or any type for that has -/// an explicit constructor from a std::string. -template -int extract_from_list_string (std::vector &vals, - string_view list, - string_view sep = string_view(",",1)) -{ - size_t nvals = vals.size(); - std::vector valuestrings; - Strutil::split (list, valuestrings, sep); - for (size_t i = 0, e = valuestrings.size(); i < e; ++i) { - T v = from_string (valuestrings[i]); - if (nvals == 0) - vals.push_back (v); - else if (valuestrings[i].size()) - vals[i] = from_string (valuestrings[i]); - /* Otherwise, empty space between commas, so leave default alone */ - } - if (valuestrings.size() == 1 && nvals > 0) { - vals.resize (1); - vals.resize (nvals, vals[0]); - } - return list.size() ? (int) valuestrings.size() : 0; -} - - - - -/// C++ functor wrapper class for using strhash for unordered_map or -/// unordered_set. The way this is used, in conjunction with -/// StringEqual, to build an efficient hash map for char*'s or -/// std::string's is as follows: -/// \code -/// unordered_map -/// \endcode -class StringHash { -public: - size_t operator() (string_view s) const { - return (size_t)Strutil::strhash(s); - } -}; - - - -/// C++ functor class for comparing two char*'s or std::string's for -/// equality of their strings. -class StringEqual { -public: - bool operator() (const char *a, const char *b) const { - return strcmp (a, b) == 0; - } - bool operator() (string_view a, string_view b) const { - return a == b; - } -}; - - -#ifdef _WIN32 -/// Conversion functions between UTF-8 and UTF-16 for windows. -/// -/// For historical reasons, the standard encoding for strings on windows is -/// UTF-16, whereas the unix world seems to have settled on UTF-8. These two -/// encodings can be stored in std::string and std::wstring respectively, with -/// the caveat that they're both variable-width encodings, so not all the -/// standard string methods will make sense (for example std::string::size() -/// won't return the number of glyphs in a UTF-8 string, unless it happens to -/// be made up of only the 7-bit ASCII subset). -/// -/// The standard windows API functions usually have two versions, a UTF-16 -/// version with a 'W' suffix (using wchar_t* strings), and an ANSI version -/// with a 'A' suffix (using char* strings) which uses the current windows -/// code page to define the encoding. (To make matters more confusing there is -/// also a further "TCHAR" version which is #defined to the UTF-16 or ANSI -/// version, depending on whether UNICODE is defined during compilation. -/// This is meant to make it possible to support compiling libraries in -/// either unicode or ansi mode from the same codebase.) -/// -/// Using std::string as the string container (as in OIIO) implies that we -/// can't use UTF-16. It also means we need a variable-width encoding to -/// represent characters in non-Latin alphabets in an unambiguous way; the -/// obvious candidate is UTF-8. File paths in OIIO are considered to be -/// represented in UTF-8, and must be converted to UTF-16 before passing to -/// windows API file opening functions. - -/// On the other hand, the encoding used for the ANSI versions of the windows -/// API is the current windows code page. This is more compatible with the -/// default setup of the standard windows command prompt, and may be more -/// appropriate for error messages. - -// Conversion to wide char -// -std::wstring OIIO_API utf8_to_utf16 (string_view utf8str); - -// Conversion from wide char -// -std::string OIIO_API utf16_to_utf8(const std::wstring& utf16str); -#endif - - -/// Safe C string copy. Basically strncpy but ensuring that there's a -/// terminating 0 character at the end of the resulting string. -OIIO_API char * safe_strcpy (char *dst, const char *src, size_t size); - -inline char * safe_strcpy (char *dst, const std::string &src, size_t size) { - return safe_strcpy (dst, src.length() ? src.c_str() : NULL, size); -} - - - -/// Modify str to trim any whitespace (space, tab, linefeed, cr) from the -/// front. -void OIIO_API skip_whitespace (string_view &str); - -/// If str's first character is c (or first non-whitespace char is c, if -/// skip_whitespace is true), return true and additionally modify str to -/// skip over that first character if eat is also true. Otherwise, if str -/// does not begin with character c, return false and don't modify str. -bool OIIO_API parse_char (string_view &str, char c, - bool skip_whitespace = true, bool eat=true); - -/// Modify str to trim all characters up to (but not including) the first -/// occurrence of c, and return true if c was found or false if the whole -/// string was trimmed without ever finding c. But if eat is false, then -/// don't modify str, just return true if any c is found, false if no c -/// is found. -bool OIIO_API parse_until_char (string_view &str, char c, bool eat=true); - -/// If str's first non-whitespace characters are the prefix, return true and -/// additionally modify str to skip over that prefix if eat is also true. -/// Otherwise, if str doesn't start with optional whitespace and the prefix, -/// return false and don't modify str. -bool OIIO_API parse_prefix (string_view &str, string_view prefix, bool eat=true); - -/// If str's first non-whitespace characters form a valid integer, return -/// true, place the integer's value in val, and additionally modify str to -/// skip over the parsed integer if eat is also true. Otherwise, if no -/// integer is found at the beginning of str, return false and don't modify -/// val or str. -bool OIIO_API parse_int (string_view &str, int &val, bool eat=true); - -/// If str's first non-whitespace characters form a valid float, return -/// true, place the float's value in val, and additionally modify str to -/// skip over the parsed float if eat is also true. Otherwise, if no float -/// is found at the beginning of str, return false and don't modify val or -/// str. -bool OIIO_API parse_float (string_view &str, float &val, bool eat=true); - -enum QuoteBehavior { DeleteQuotes, KeepQuotes }; -/// If str's first non-whitespace characters form a valid string (either a -/// single word separated by whitespace or anything inside a double-quoted -/// string (""), return true, place the string's value (not including -/// surrounding double quotes) in val, and additionally modify str to skip -/// over the parsed string if eat is also true. Otherwise, if no string is -/// found at the beginning of str, return false and don't modify val or str. -/// If keep_quotes is true, the surrounding double quotes (if present) -/// will be kept in val. -bool OIIO_API parse_string (string_view &str, string_view &val, bool eat/*=true*/, - QuoteBehavior keep_quotes/*=DeleteQuotes*/); -// DEPRECATED (1.5) -bool OIIO_API parse_string (string_view &str, string_view &val, bool eat=true); - -/// Return the first "word" (set of contiguous alphabetical characters) in -/// str, and additionally modify str to skip over the parsed word if eat is -/// also true. Otherwise, if no word is found at the beginning of str, -/// return an empty string_view and don't modify str. -string_view OIIO_API parse_word (string_view &str, bool eat=true); - -/// If str's first non-whitespace characters form a valid C-like identifier, -/// return the identifier, and additionally modify str to skip over the -/// parsed identifier if eat is also true. Otherwise, if no identifier is -/// found at the beginning of str, return an empty string_view and don't -/// modify str. -string_view OIIO_API parse_identifier (string_view &str, bool eat=true); - -/// If str's first non-whitespace characters form a valid C-like identifier, -/// return the identifier, and additionally modify str to skip over the -/// parsed identifier if eat is also true. Otherwise, if no identifier is -/// found at the beginning of str, return an empty string_view and don't -/// modify str. The 'allowed' parameter may specify a additional characters -/// accepted that would not ordinarily be allowed in C identifiers, for -/// example, parse_identifier (blah, "$:") would allow "identifiers" -/// containing dollar signs and colons as well as the usual alphanumeric and -/// underscore characters. -string_view OIIO_API parse_identifier (string_view &str, - string_view allowed, bool eat); - -/// Return the characters until any character in sep is found, storing it in -/// str, and additionally modify str to skip over the parsed section if eat -/// is also true. Otherwise, if no word is found at the beginning of str, -/// return an empty string_view and don't modify str. -string_view OIIO_API parse_until (string_view &str, - string_view sep=" \t\r\n", bool eat=true); - -/// Assuming the string str starts with either '(', '[', or '{', return the -/// head, up to and including the corresponding closing character (')', ']', -/// or '}', respectively), recognizing nesting structures. For example, -/// parse_nested("(a(b)c)d") should return "(a(b)c)", NOT "(a(b)". Return an -/// empty string if str doesn't start with one of those characters, or -/// doesn't contain a correctly matching nested pair. If eat==true, str will -/// be modified to trim off the part of the string that is returned as the -/// match. -string_view OIIO_API parse_nested (string_view &str, bool eat=true); - - -/// Converts utf-8 string to vector of unicode codepoints. This function -/// will not stop on invalid sequences. It will let through some invalid -/// utf-8 sequences like: 0xfdd0-0xfdef, 0x??fffe/0x??ffff. It does not -/// support 5-6 bytes long utf-8 sequences. Will skip trailing character if -/// there are not enough bytes for decoding a codepoint. -/// -/// N.B. Following should probably return u32string instead of taking -/// vector, but C++11 support is not yet stabilized across compilers. -/// We will eventually add that and deprecate this one, after everybody -/// is caught up to C++11. -void OIIO_API utf8_to_unicode (string_view &str, std::vector &uvec); - -} // namespace Strutil - -OIIO_NAMESPACE_END - - -#endif // OPENIMAGEIO_STRUTIL_H diff --git a/3rdparty/oiio16/include/OpenImageIO/sysutil.h b/3rdparty/oiio16/include/OpenImageIO/sysutil.h deleted file mode 100644 index fead73b0..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/sysutil.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -///////////////////////////////////////////////////////////////////////// -/// @file sysutil.h -/// -/// @brief Platform-independent utilities for various OS, hardware, and -/// system resource functionality, all in namespace Sysutil. -///////////////////////////////////////////////////////////////////////// - - -#pragma once - -#include -#include - -#ifdef __MINGW32__ -#include // for alloca -#endif - -#include "export.h" -#include "oiioversion.h" -#include "platform.h" - - -OIIO_NAMESPACE_BEGIN - -/// @namespace Sysutil -/// -/// @brief Platform-independent utilities for various OS, hardware, and -/// system resource functionality. -namespace Sysutil { - -/// The amount of memory currently being used by this process, in bytes. -/// If resident==true (the default), it will report just the resident -/// set in RAM; if resident==false, it returns the full virtual arena -/// (which can be misleading because gcc allocates quite a bit of -/// virtual, but not actually resident until malloced, memory per -/// thread). -OIIO_API size_t memory_used (bool resident=true); - -/// The amount of physical RAM on this machine, in bytes. -/// If it can't figure it out, it will return 0. -OIIO_API size_t physical_memory (); - -/// Convert calendar time pointed by 'time' into local time and save it in -/// 'converted_time' variable -OIIO_API void get_local_time (const time_t *time, struct tm *converted_time); - -/// Return the full path of the currently-running executable program. -/// -OIIO_API std::string this_program_path (); - -/// Sleep for the given number of microseconds. -/// -OIIO_API void usleep (unsigned long useconds); - -/// Try to figure out how many columns wide the terminal window is. -/// May not be correct all all systems, will default to 80 if it can't -/// figure it out. -OIIO_API int terminal_columns (); - -/// Try to put the process into the background so it doesn't continue to -/// tie up any shell that it was launched from. The arguments are the -/// argc/argv that describe the program and its command line arguments. -/// Return true if successful, false if it was unable to do so. -OIIO_API bool put_in_background (int argc, char* argv[]); - -/// Number of virtual cores available on this platform (including -/// hyperthreads). -OIIO_API unsigned int hardware_concurrency (); - -/// Number of full hardware cores available on this platform (does not -/// include hyperthreads). This is not always accurate and on some -/// platforms will return the number of virtual cores. -OIIO_API unsigned int physical_concurrency (); - -} // namespace Sysutils - -OIIO_NAMESPACE_END diff --git a/3rdparty/oiio16/include/OpenImageIO/texture.h b/3rdparty/oiio16/include/OpenImageIO/texture.h deleted file mode 100644 index b699b43c..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/texture.h +++ /dev/null @@ -1,688 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -/// \file -/// An API for accessing filtered texture lookups via a system that -/// automatically manages a cache of resident texture. - - -#ifndef OPENIMAGEIO_TEXTURE_H -#define OPENIMAGEIO_TEXTURE_H - -#include "varyingref.h" -#include "ustring.h" -#include "imageio.h" - -#include /* because we need V3f */ - -OIIO_NAMESPACE_BEGIN - -// Forward declaration -namespace pvt { - -class TextureSystemImpl; - -// Used internally by TextureSystem. Unfortunately, this is the only -// clean place to store it. Sorry, users, this isn't really for you. -enum TexFormat { - TexFormatUnknown, TexFormatTexture, TexFormatTexture3d, - TexFormatShadow, TexFormatCubeFaceShadow, TexFormatVolumeShadow, - TexFormatLatLongEnv, TexFormatCubeFaceEnv, - TexFormatLast -}; - -enum EnvLayout { - LayoutTexture=0 /* ordinary texture - no special env wrap */, - LayoutLatLong, LayoutCubeThreeByTwo, LayoutCubeOneBySix, EnvLayoutLast -}; - -} // pvt namespace - - - - -/// Data type for flags that indicate on a point-by-point basis whether -/// we want computations to be performed. -typedef unsigned char Runflag; - -/// Pre-defined values for Runflag's. -/// -enum RunFlagVal { RunFlagOff = 0, RunFlagOn = 255 }; - -class TextureOptions; // forward declaration - - - -/// Encapsulate all the options needed for texture lookups. Making -/// these options all separate parameters to the texture API routines is -/// very ugly and also a big pain whenever we think of new options to -/// add. So instead we collect all those little options into one -/// structure that can just be passed by reference to the texture API -/// routines. -class OIIO_API TextureOpt { -public: - /// Wrap mode describes what happens when texture coordinates describe - /// a value outside the usual [0,1] range where a texture is defined. - enum Wrap { - WrapDefault, ///< Use the default found in the file - WrapBlack, ///< Black outside [0..1] - WrapClamp, ///< Clamp to [0..1] - WrapPeriodic, ///< Periodic mod 1 - WrapMirror, ///< Mirror the image - WrapPeriodicPow2, ///< Periodic, but only for powers of 2!!! - WrapPeriodicSharedBorder, ///< Periodic with shared border (env) - WrapLast ///< Mark the end -- don't use this! - }; - - /// Mip mode determines if/how we use mipmaps - /// - enum MipMode { - MipModeDefault, ///< Default high-quality lookup - MipModeNoMIP, ///< Just use highest-res image, no MIP mapping - MipModeOneLevel, ///< Use just one mipmap level - MipModeTrilinear, ///< Use two MIPmap levels (trilinear) - MipModeAniso ///< Use two MIPmap levels w/ anisotropic - }; - - /// Interp mode determines how we sample within a mipmap level - /// - enum InterpMode { - InterpClosest, ///< Force closest texel - InterpBilinear, ///< Force bilinear lookup within a mip level - InterpBicubic, ///< Force cubic lookup within a mip level - InterpSmartBicubic ///< Bicubic when maxifying, else bilinear - }; - - - /// Create a TextureOpt with all fields initialized to reasonable - /// defaults. - TextureOpt () - : firstchannel(0), subimage(0), - swrap(WrapDefault), twrap(WrapDefault), - mipmode(MipModeDefault), interpmode(InterpSmartBicubic), - anisotropic(32), conservative_filter(true), - sblur(0.0f), tblur(0.0f), swidth(1.0f), twidth(1.0f), - fill(0.0f), missingcolor(NULL), - // dresultds(NULL), dresultdt(NULL), - time(0.0f), // bias(0.0f), samples(1), - rwrap(WrapDefault), rblur(0.0f), rwidth(1.0f), // dresultdr(NULL), - // actualchannels(0), - envlayout(0) - { } - - /// Convert a TextureOptions for one index into a TextureOpt. - /// - TextureOpt (const TextureOptions &opt, int index); - - int firstchannel; ///< First channel of the lookup - int subimage; ///< Subimage or face ID - ustring subimagename; ///< Subimage name - Wrap swrap; ///< Wrap mode in the s direction - Wrap twrap; ///< Wrap mode in the t direction - MipMode mipmode; ///< Mip mode - InterpMode interpmode; ///< Interpolation mode - int anisotropic; ///< Maximum anisotropic ratio - bool conservative_filter; ///< True == over-blur rather than alias - float sblur, tblur; ///< Blur amount - float swidth, twidth; ///< Multiplier for derivatives - float fill; ///< Fill value for missing channels - const float *missingcolor;///< Color for missing texture - float time; ///< Time (for time-dependent texture lookups) - float bias; ///< Bias for shadows - int samples; ///< Number of samples for shadows - - // For 3D volume texture lookups only: - Wrap rwrap; ///< Wrap mode in the r direction - float rblur; ///< Blur amount in the r direction - float rwidth; ///< Multiplier for derivatives in r direction - - /// Utility: Return the Wrap enum corresponding to a wrap name: - /// "default", "black", "clamp", "periodic", "mirror". - static Wrap decode_wrapmode (const char *name); - static Wrap decode_wrapmode (ustring name); - - /// Utility: Parse a single wrap mode (e.g., "periodic") or a - /// comma-separated wrap modes string (e.g., "black,clamp") into - /// separate Wrap enums for s and t. - static void parse_wrapmodes (const char *wrapmodes, - TextureOpt::Wrap &swrapcode, - TextureOpt::Wrap &twrapcode); - -private: - // Options set INTERNALLY by libtexture after the options are passed - // by the user. Users should not attempt to alter these! - int envlayout; // Layout for environment wrap - friend class pvt::TextureSystemImpl; -}; - - - -/// Encapsulate all the options needed for texture lookups. Making -/// these options all separate parameters to the texture API routines is -/// very ugly and also a big pain whenever we think of new options to -/// add. So instead we collect all those little options into one -/// structure that can just be passed by reference to the texture API -/// routines. -class OIIO_API TextureOptions { -public: - /// Wrap mode describes what happens when texture coordinates describe - /// a value outside the usual [0,1] range where a texture is defined. - enum Wrap { - WrapDefault, ///< Use the default found in the file - WrapBlack, ///< Black outside [0..1] - WrapClamp, ///< Clamp to [0..1] - WrapPeriodic, ///< Periodic mod 1 - WrapMirror, ///< Mirror the image - WrapPeriodicPow2, ///< Periodic, but only for powers of 2!!! - WrapPeriodicSharedBorder, ///< Periodic with shared border (env) - WrapLast ///< Mark the end -- don't use this! - }; - - /// Mip mode determines if/how we use mipmaps - /// - enum MipMode { - MipModeDefault, ///< Default high-quality lookup - MipModeNoMIP, ///< Just use highest-res image, no MIP mapping - MipModeOneLevel, ///< Use just one mipmap level - MipModeTrilinear, ///< Use two MIPmap levels (trilinear) - MipModeAniso ///< Use two MIPmap levels w/ anisotropic - }; - - /// Interp mode determines how we sample within a mipmap level - /// - enum InterpMode { - InterpClosest, ///< Force closest texel - InterpBilinear, ///< Force bilinear lookup within a mip level - InterpBicubic, ///< Force cubic lookup within a mip level - InterpSmartBicubic ///< Bicubic when maxifying, else bilinear - }; - - /// Create a TextureOptions with all fields initialized to reasonable - /// defaults. - TextureOptions (); - - /// Convert a TextureOpt for one point into a TextureOptions with - /// uninform values. - TextureOptions (const TextureOpt &opt); - - // Options that must be the same for all points we're texturing at once - int firstchannel; ///< First channel of the lookup - int subimage; ///< Subimage or face ID - ustring subimagename; ///< Subimage name - Wrap swrap; ///< Wrap mode in the s direction - Wrap twrap; ///< Wrap mode in the t direction - MipMode mipmode; ///< Mip mode - InterpMode interpmode; ///< Interpolation mode - int anisotropic; ///< Maximum anisotropic ratio - bool conservative_filter; ///< True == over-blur rather than alias - - // Options that may be different for each point we're texturing - VaryingRef sblur, tblur; ///< Blur amount - VaryingRef swidth, twidth; ///< Multiplier for derivatives - VaryingRef time; ///< Time - VaryingRef bias; ///< Bias - VaryingRef fill; ///< Fill value for missing channels - VaryingRef missingcolor; ///< Color for missing texture - VaryingRef samples; ///< Number of samples - - // For 3D volume texture lookups only: - Wrap rwrap; ///< Wrap mode in the r direction - VaryingRef rblur; ///< Blur amount in the r direction - VaryingRef rwidth; ///< Multiplier for derivatives in r direction - - /// Utility: Return the Wrap enum corresponding to a wrap name: - /// "default", "black", "clamp", "periodic", "mirror". - static Wrap decode_wrapmode (const char *name) { - return (Wrap)TextureOpt::decode_wrapmode (name); - } - static Wrap decode_wrapmode (ustring name) { - return (Wrap)TextureOpt::decode_wrapmode (name); - } - - /// Utility: Parse a single wrap mode (e.g., "periodic") or a - /// comma-separated wrap modes string (e.g., "black,clamp") into - /// separate Wrap enums for s and t. - static void parse_wrapmodes (const char *wrapmodes, - TextureOptions::Wrap &swrapcode, - TextureOptions::Wrap &twrapcode) { - TextureOpt::parse_wrapmodes (wrapmodes, - *(TextureOpt::Wrap *)&swrapcode, - *(TextureOpt::Wrap *)&twrapcode); - } - -private: - // Options set INTERNALLY by libtexture after the options are passed - // by the user. Users should not attempt to alter these! - friend class pvt::TextureSystemImpl; - friend class TextureOpt; -}; - - - -/// Define an API to an abstract class that that manages texture files, -/// caches of open file handles as well as tiles of texels so that truly -/// huge amounts of texture may be accessed by an application with low -/// memory footprint, and ways to perform antialiased texture, shadow -/// map, and environment map lookups. -class OIIO_API TextureSystem { -public: - /// Create a TextureSystem and return a pointer. This should only be - /// freed by passing it to TextureSystem::destroy()! - /// - /// If shared==true, it's intended to be shared with other like-minded - /// owners in the same process who also ask for a shared texture system. - /// If false, a private texture system and cache will be created. - static TextureSystem *create (bool shared=true); - - /// Destroy a TextureSystem that was created using - /// TextureSystem::create(). For the variety that takes a - /// teardown_imagecache parameter, if set to true it will cause the - /// underlying ImageCache to be fully destroyed, even if it's the - /// "shared" ImageCache. - static void destroy (TextureSystem *x); - static void destroy (TextureSystem *x, bool teardown_imagecache); - - TextureSystem (void) { } - virtual ~TextureSystem () { } - - /// Close everything, free resources, start from scratch. - /// - virtual void clear () = 0; - - /// Set an attribute controlling the texture system. Return true - /// if the name and type were recognized and the attrib was set. - /// Documented attributes: - /// int max_open_files : maximum number of file handles held open - /// float max_memory_MB : maximum tile cache size, in MB - /// string searchpath : colon-separated search path for texture files - /// string plugin_searchpath : colon-separated search path for plugins - /// matrix44 worldtocommon : the world-to-common transformation - /// matrix44 commontoworld : the common-to-world transformation - /// int autotile : if >0, tile size to emulate for non-tiled images - /// int autoscanline : autotile using full width tiles - /// int automip : if nonzero, emulate mipmap on the fly - /// int accept_untiled : if nonzero, accept untiled images - /// int accept_unmipped : if nonzero, accept unmipped images - /// int failure_retries : how many times to retry a read failure - /// int deduplicate : if nonzero, detect duplicate textures (default=1) - /// int gray_to_rgb : make 1-channel images fill RGB lookups - /// int max_tile_channels : max channels to store all chans in a tile - /// string latlong_up : default "up" direction for latlong ("y") - /// - virtual bool attribute (string_view name, TypeDesc type, const void *val) = 0; - // Shortcuts for common types - virtual bool attribute (string_view name, int val) = 0; - virtual bool attribute (string_view name, float val) = 0; - virtual bool attribute (string_view name, double val) = 0; - virtual bool attribute (string_view name, string_view val) = 0; - - /// Get the named attribute, store it in value. - virtual bool getattribute (string_view name, - TypeDesc type, void *val) const = 0; - // Shortcuts for common types - virtual bool getattribute (string_view name, int &val) const = 0; - virtual bool getattribute (string_view name, float &val) const = 0; - virtual bool getattribute (string_view name, double &val) const = 0; - virtual bool getattribute (string_view name, char **val) const = 0; - virtual bool getattribute (string_view name, std::string &val) const = 0; - - /// Define an opaque data type that allows us to have a pointer - /// to certain per-thread information that the TextureSystem maintains. - /// Any given one of these should NEVER be shared between running - /// threads. - class Perthread; - - /// Retrieve a Perthread, unique to the calling thread. This is a - /// thread-specific pointer that will always return the Perthread for a - /// thread, which will also be automatically destroyed when the thread - /// terminates. - /// - /// Applications that want to manage their own Perthread pointers (with - /// create_thread_info and destroy_thread_info) should still call this, - /// but passing in their managed pointer. If the passed-in threadinfo is - /// not NULL, it won't create a new one or retrieve a TSP, but it will - /// do other necessary housekeeping on the Perthread information. - virtual Perthread * get_perthread_info (Perthread *thread_info=NULL) = 0; - - /// Create a new Perthread. It is the caller's responsibility to - /// eventually destroy it using destroy_thread_info(). - virtual Perthread * create_thread_info () = 0; - - /// Destroy a Perthread that was allocated by create_thread_info(). - virtual void destroy_thread_info (Perthread *threadinfo) = 0; - - /// Define an opaque data type that allows us to have a handle to a - /// texture (already having its name resolved) but without exposing - /// any internals. - class TextureHandle; - - /// Retrieve an opaque handle for fast texture lookups. The opaque - /// pointer thread_info is thread-specific information returned by - /// get_perthread_info(). Return NULL if something has gone - /// horribly wrong. - virtual TextureHandle * get_texture_handle (ustring filename, - Perthread *thread_info=NULL) = 0; - - /// Return true if the texture handle (previously returned by - /// get_texture_handle()) is a valid texture that can be subsequently - /// read or sampled. - virtual bool good (TextureHandle *texture_handle) = 0; - - /// Filtered 2D texture lookup for a single point. - /// - /// s,t are the texture coordinates; dsdx, dtdx, dsdy, and dtdy are - /// the differentials of s and t change in some canonical directions - /// x and y. The choice of x and y are not important to the - /// implementation; it can be any imposed 2D coordinates, such as - /// pixels in screen space, adjacent samples in parameter space on a - /// surface, etc. - /// - /// The result is placed in result[0..nchannels-1]. If dresuls and - /// dresultdt are non-NULL, then they [0..nchannels-1] will get the - /// texture gradients, i.e., the rate of change per unit s and t, - /// respectively, of the texture. - /// - /// Return true if the file is found and could be opened by an - /// available ImageIO plugin, otherwise return false. - virtual bool texture (ustring filename, TextureOpt &options, - float s, float t, float dsdx, float dtdx, - float dsdy, float dtdy, - int nchannels, float *result, - float *dresultds=NULL, float *dresultdt=NULL) = 0; - - /// Version that takes nchannels and derivatives explicitly, if the app - /// already has a texture handle and per-thread info. - virtual bool texture (TextureHandle *texture_handle, - Perthread *thread_info, TextureOpt &options, - float s, float t, float dsdx, float dtdx, - float dsdy, float dtdy, - int nchannels, float *result, - float *dresultds=NULL, float *dresultdt=NULL) = 0; - - /// Retrieve filtered (possibly anisotropic) texture lookups for - /// several points at once. - /// - /// All of the VaryingRef parameters (and fields in options) - /// describe texture lookup parameters at an array of positions. - /// But this routine only computes them from indices i where - /// beginactive <= i < endactive, and ONLY when runflags[i] is - /// nonzero. - /// - /// Return true if the file is found and could be opened by an - /// available ImageIO plugin, otherwise return false. - virtual bool texture (ustring filename, TextureOptions &options, - Runflag *runflags, int beginactive, int endactive, - VaryingRef s, VaryingRef t, - VaryingRef dsdx, VaryingRef dtdx, - VaryingRef dsdy, VaryingRef dtdy, - int nchannels, float *result, - float *dresultds=NULL, float *dresultdt=NULL) = 0; - virtual bool texture (TextureHandle *texture_handle, - Perthread *thread_info, TextureOptions &options, - Runflag *runflags, int beginactive, int endactive, - VaryingRef s, VaryingRef t, - VaryingRef dsdx, VaryingRef dtdx, - VaryingRef dsdy, VaryingRef dtdy, - int nchannels, float *result, - float *dresultds=NULL, float *dresultdt=NULL) = 0; - - /// Retrieve a 3D texture lookup at a single point. - /// - /// Return true if the file is found and could be opened by an - /// available ImageIO plugin, otherwise return false. - virtual bool texture3d (ustring filename, TextureOpt &options, - const Imath::V3f &P, const Imath::V3f &dPdx, - const Imath::V3f &dPdy, const Imath::V3f &dPdz, - int nchannels, float *result, - float *dresultds=NULL, float *dresultdt=NULL, - float *dresultdr=NULL) = 0; - - /// Slightly faster version of texture3d() lookup if the app already - /// has a texture handle and per-thread info. - virtual bool texture3d (TextureHandle *texture_handle, - Perthread *thread_info, TextureOpt &options, - const Imath::V3f &P, const Imath::V3f &dPdx, - const Imath::V3f &dPdy, const Imath::V3f &dPdz, - int nchannels, float *result, - float *dresultds=NULL, float *dresultdt=NULL, - float *dresultdr=NULL) = 0; - - /// Retrieve a 3D texture lookup at many points at once. - /// - /// Return true if the file is found and could be opened by an - /// available ImageIO plugin, otherwise return false. - virtual bool texture3d (ustring filename, TextureOptions &options, - Runflag *runflags, int beginactive, int endactive, - VaryingRef P, - VaryingRef dPdx, - VaryingRef dPdy, - VaryingRef dPdz, - int nchannels, float *result, - float *dresultds=NULL, float *dresultdt=NULL, - float *dresultdr=NULL) = 0; - virtual bool texture3d (TextureHandle *texture_handle, - Perthread *thread_info, TextureOptions &options, - Runflag *runflags, int beginactive, int endactive, - VaryingRef P, - VaryingRef dPdx, - VaryingRef dPdy, - VaryingRef dPdz, - int nchannels, float *result, - float *dresultds=NULL, float *dresultdt=NULL, - float *dresultdr=NULL) = 0; - - /// Retrieve a shadow lookup for a single position P. - /// - /// Return true if the file is found and could be opened by an - /// available ImageIO plugin, otherwise return false. - virtual bool shadow (ustring filename, TextureOpt &options, - const Imath::V3f &P, const Imath::V3f &dPdx, - const Imath::V3f &dPdy, float *result, - float *dresultds=NULL, float *dresultdt=NULL) = 0; - - /// Slightly faster version of shadow() lookup if the app already - /// has a texture handle and per-thread info. - virtual bool shadow (TextureHandle *texture_handle, Perthread *thread_info, - TextureOpt &options, - const Imath::V3f &P, const Imath::V3f &dPdx, - const Imath::V3f &dPdy, float *result, - float *dresultds=NULL, float *dresultdt=NULL) = 0; - - /// Retrieve a shadow lookup for position P at many points at once. - /// - /// Return true if the file is found and could be opened by an - /// available ImageIO plugin, otherwise return false. - virtual bool shadow (ustring filename, TextureOptions &options, - Runflag *runflags, int beginactive, int endactive, - VaryingRef P, - VaryingRef dPdx, - VaryingRef dPdy, - float *result, - float *dresultds=NULL, float *dresultdt=NULL) = 0; - virtual bool shadow (TextureHandle *texture_handle, Perthread *thread_info, - TextureOptions &options, - Runflag *runflags, int beginactive, int endactive, - VaryingRef P, - VaryingRef dPdx, - VaryingRef dPdy, - float *result, - float *dresultds=NULL, float *dresultdt=NULL) = 0; - - /// Retrieve an environment map lookup for direction R. - /// - /// Return true if the file is found and could be opened by an - /// available ImageIO plugin, otherwise return false. - virtual bool environment (ustring filename, TextureOpt &options, - const Imath::V3f &R, const Imath::V3f &dRdx, - const Imath::V3f &dRdy, int nchannels, float *result, - float *dresultds=NULL, float *dresultdt=NULL) = 0; - - /// Slightly faster version of environment() lookup if the app already - /// has a texture handle and per-thread info. - virtual bool environment (TextureHandle *texture_handle, - Perthread *thread_info, TextureOpt &options, - const Imath::V3f &R, const Imath::V3f &dRdx, - const Imath::V3f &dRdy, int nchannels, float *result, - float *dresultds=NULL, float *dresultdt=NULL) = 0; - - /// Retrieve an environment map lookup for direction R, for many - /// points at once. - /// - /// Return true if the file is found and could be opened by an - /// available ImageIO plugin, otherwise return false. - virtual bool environment (ustring filename, TextureOptions &options, - Runflag *runflags, int beginactive, int endactive, - VaryingRef R, - VaryingRef dRdx, - VaryingRef dRdy, - int nchannels, float *result, - float *dresultds=NULL, float *dresultdt=NULL) = 0; - virtual bool environment (TextureHandle *texture_handle, - Perthread *thread_info, TextureOptions &options, - Runflag *runflags, int beginactive, int endactive, - VaryingRef R, - VaryingRef dRdx, - VaryingRef dRdy, - int nchannels, float *result, - float *dresultds=NULL, float *dresultdt=NULL) = 0; - - /// Given possibly-relative 'filename', resolve it using the search - /// path rules and return the full resolved filename. - virtual std::string resolve_filename (const std::string &filename) const=0; - - /// Get information about the given texture. Return true if found - /// and the data has been put in *data. Return false if the texture - /// doesn't exist, doesn't have the requested data, if the data - /// doesn't match the type requested. or some other failure. - virtual bool get_texture_info (ustring filename, int subimage, - ustring dataname, TypeDesc datatype, void *data) = 0; - virtual bool get_texture_info (TextureHandle *texture_handle, - Perthread *thread_info, int subimage, - ustring dataname, TypeDesc datatype, void *data) = 0; - /// DEPRECATED (1.6.2) - virtual bool get_texture_info (TextureHandle *texture_handle, int subimage, - ustring dataname, TypeDesc datatype, void *data) = 0; - - /// Get the ImageSpec associated with the named texture - /// (specifically, the first MIP-map level). If the file is found - /// and is an image format that can be read, store a copy of its - /// specification in spec and return true. Return false if the file - /// was not found or could not be opened as an image file by any - /// available ImageIO plugin. - virtual bool get_imagespec (ustring filename, int subimage, - ImageSpec &spec) = 0; - virtual bool get_imagespec (TextureHandle *texture_handle, - Perthread *thread_info, int subimage, - ImageSpec &spec) = 0; - - /// Return a pointer to an ImageSpec associated with the named - /// texture (specifically, the first MIP-map level) if the file is - /// found and is an image format that can be read, otherwise return - /// NULL. - /// - /// This method is much more efficient than get_imagespec(), since - /// it just returns a pointer to the spec held internally by the - /// underlying ImageCache (rather than copying the spec to the - /// user's memory). However, the caller must beware that the - /// pointer is only valid as long as nobody (even other threads) - /// calls invalidate() on the file, or invalidate_all(), or destroys - /// the TextureSystem. - virtual const ImageSpec *imagespec (ustring filename, int subimage=0) = 0; - virtual const ImageSpec *imagespec (TextureHandle *texture_handle, - Perthread *thread_info = NULL, - int subimage=0) = 0; - - /// Retrieve the rectangle of raw unfiltered texels spanning - /// [xbegin..xend) X [ybegin..yend) X [zbegin..zend), with - /// "exclusive end" a la STL, specified as integer pixel coordinates - /// in the designated MIP-map level, storing the texel values - /// beginning at the address specified by result. - /// The texel values will be converted to the type specified by - /// format. It is up to the caller to ensure that result points to - /// an area of memory big enough to accommodate the requested - /// rectangle (taking into consideration its dimensions, number of - /// channels, and data format). Requested pixels outside - /// the valid pixel data region will be filled in with 0 values. - /// - /// Return true if the file is found and could be opened by an - /// available ImageIO plugin, otherwise return false. - virtual bool get_texels (ustring filename, TextureOpt &options, - int miplevel, int xbegin, int xend, - int ybegin, int yend, int zbegin, int zend, - int chbegin, int chend, - TypeDesc format, void *result) = 0; - virtual bool get_texels (TextureHandle *texture_handle, - Perthread *thread_info, TextureOpt &options, - int miplevel, int xbegin, int xend, - int ybegin, int yend, int zbegin, int zend, - int chbegin, int chend, - TypeDesc format, void *result) = 0; - - /// If any of the API routines returned false indicating an error, - /// this routine will return the error string (and clear any error - /// flags). If no error has occurred since the last time geterror() - /// was called, it will return an empty string. - virtual std::string geterror () const = 0; - - /// Return the statistics output as a huge string. - /// - virtual std::string getstats (int level=1, bool icstats=true) const = 0; - - /// Invalidate any cached information about the named file. A client - /// might do this if, for example, they are aware that an image - /// being held in the cache has been updated on disk. - virtual void invalidate (ustring filename) = 0; - - /// Invalidate all cached data for all textures. If force is true, - /// everything will be invalidated, no matter how wasteful it is, - /// but if force is false, in actuality files will only be - /// invalidated if their modification times have been changed since - /// they were first opened. - virtual void invalidate_all (bool force=false) = 0; - - /// Reset most statistics to be as they were with a fresh - /// TextureSystem. Caveat emptor: this does not flush the cache - /// itelf, so the resulting statistics from the next set of texture - /// requests will not match the number of tile reads, etc., that - /// would have resulted from a new TextureSystem. - virtual void reset_stats () = 0; - -private: - // Make delete private and unimplemented in order to prevent apps - // from calling it. Instead, they should call TextureSystem::destroy(). - void operator delete (void * /*todel*/) { } - -}; - - -OIIO_NAMESPACE_END - -#endif // OPENIMAGEIO_TEXTURE_H diff --git a/3rdparty/oiio16/include/OpenImageIO/thread.h b/3rdparty/oiio16/include/OpenImageIO/thread.h deleted file mode 100644 index 3d0737c6..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/thread.h +++ /dev/null @@ -1,878 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -///////////////////////////////////////////////////////////////////////// -/// @file thread.h -/// -/// @brief Wrappers and utilities for multithreading. -///////////////////////////////////////////////////////////////////////// - - -#ifndef OPENIMAGEIO_THREAD_H -#define OPENIMAGEIO_THREAD_H - -#include - -#include "oiioversion.h" -#include "platform.h" - - - -#if OIIO_CPLUSPLUS_VERSION >= 11 -# include -# include -# include -# define not_yet_OIIO_USE_STDATOMIC 1 -#else /* prior to C++11... */ - // Use Boost mutexes & guards when C++11 is not available -# include -# if defined(__GNUC__) && (BOOST_VERSION == 104500) - // gcc reports errors inside some of the boost headers with boost 1.45 - // See: https://svn.boost.org/trac/boost/ticket/4818 -# pragma GCC diagnostic ignored "-Wunused-variable" -# endif -# include -# if defined(__GNUC__) && (BOOST_VERSION == 104500) - // can't restore via push/pop in all versions of gcc (warning push/pop implemented for 4.6+ only) -# pragma GCC diagnostic error "-Wunused-variable" -# endif -#endif - - -#if defined(_MSC_VER) - // N.B. including platform.h also included -# pragma intrinsic (_InterlockedExchangeAdd) -# pragma intrinsic (_InterlockedCompareExchange) -# pragma intrinsic (_InterlockedCompareExchange64) -# if defined(_WIN64) -# pragma intrinsic(_InterlockedExchangeAdd64) -# endif -// InterlockedExchangeAdd64 & InterlockedExchange64 are not available for XP -# if defined(_WIN32_WINNT) && _WIN32_WINNT <= 0x0501 -inline long long -InterlockedExchangeAdd64 (volatile long long *Addend, long long Value) -{ - long long Old; - do { - Old = *Addend; - } while (_InterlockedCompareExchange64(Addend, Old + Value, Old) != Old); - return Old; -} - -inline long long -InterlockedExchange64 (volatile long long *Target, long long Value) -{ - long long Old; - do { - Old = *Target; - } while (_InterlockedCompareExchange64(Target, Value, Old) != Old); - return Old; -} -# endif -#endif - -#if defined(__GNUC__) && (defined(_GLIBCXX_ATOMIC_BUILTINS) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 401)) -# define USE_GCC_ATOMICS -# if !defined(__clang__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 408) -# define OIIO_USE_GCC_NEW_ATOMICS -# endif -#endif - - -// OIIO_THREAD_ALLOW_DCLP, if set to 0, prevents us from using a dodgy -// "double checked lock pattern" (DCLP). We are very careful to construct -// it safely and correctly, and these uses improve thread performance for -// us. But it confuses Thread Sanitizer, so this switch allows you to turn -// it off. Also set to 0 if you don't believe that we are correct in -// allowing this construct on all platforms. -#ifndef OIIO_THREAD_ALLOW_DCLP -#define OIIO_THREAD_ALLOW_DCLP 1 -#endif - - - -// Some helpful links: -// -// Descriptions of the "new" gcc atomic intrinsics: -// https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html -// Old gcc atomic intrinsics: -// https://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Atomic-Builtins.html -// C++11 and beyond std::atomic: -// http://en.cppreference.com/w/cpp/atomic - - - -OIIO_NAMESPACE_BEGIN - -/// Null mutex that can be substituted for a real one to test how much -/// overhead is associated with a particular mutex. -class null_mutex { -public: - null_mutex () { } - ~null_mutex () { } - void lock () { } - void unlock () { } - void lock_shared () { } - void unlock_shared () { } - bool try_lock () { return true; } -}; - -/// Null lock that can be substituted for a real one to test how much -/// overhead is associated with a particular lock. -template -class null_lock { -public: - null_lock (T &m) { } -}; - - - -#ifdef NOTHREADS - -// Definitions that we use for debugging to turn off all mutexes, locks, -// and atomics in order to test the performance hit of our thread safety. - -typedef null_mutex mutex; -typedef null_mutex recursive_mutex; -typedef null_lock lock_guard; -typedef null_lock recursive_lock_guard; - -#elif OIIO_CPLUSPLUS_VERSION >= 11 - -typedef std::mutex mutex; -typedef std::recursive_mutex recursive_mutex; -typedef std::lock_guard< mutex > lock_guard; -typedef std::lock_guard< recursive_mutex > recursive_lock_guard; -typedef std::thread thread; - -#else - -// Fairly modern Boost has all the mutex and lock types we need. - -typedef boost::mutex mutex; -typedef boost::recursive_mutex recursive_mutex; -typedef boost::lock_guard< mutex > lock_guard; -typedef boost::lock_guard< recursive_mutex > recursive_lock_guard; -typedef boost::thread thread; - -#endif - - - -#if OIIO_USE_STDATOMIC -using std::memory_order; -#else -enum memory_order { -#if defined(OIIO_USE_GCC_NEW_ATOMICS) - memory_order_relaxed = __ATOMIC_RELAXED, - memory_order_consume = __ATOMIC_CONSUME, - memory_order_acquire = __ATOMIC_ACQUIRE, - memory_order_release = __ATOMIC_RELEASE, - memory_order_acq_rel = __ATOMIC_ACQ_REL, - memory_order_seq_cst = __ATOMIC_SEQ_CST -#else - memory_order_relaxed, - memory_order_consume, - memory_order_acquire, - memory_order_release, - memory_order_acq_rel, - memory_order_seq_cst -#endif -}; -#endif - - - -/// Atomic version of: r = *at, *at += x, return r -/// For each of several architectures. -inline int -atomic_exchange_and_add (volatile int *at, int x, - memory_order order = memory_order_seq_cst) -{ -#ifdef NOTHREADS - int r = *at; *at += x; return r; -#elif defined(OIIO_USE_GCC_NEW_ATOMICS) - return __atomic_fetch_add (at, x, order); -#elif defined(USE_GCC_ATOMICS) - return __sync_fetch_and_add ((int *)at, x); -#elif defined(_MSC_VER) - // Windows - return _InterlockedExchangeAdd ((volatile LONG *)at, x); -#else -# error No atomics on this platform. -#endif -} - - - -inline long long -atomic_exchange_and_add (volatile long long *at, long long x, - memory_order order = memory_order_seq_cst) -{ -#ifdef NOTHREADS - long long r = *at; *at += x; return r; -#elif defined(OIIO_USE_GCC_NEW_ATOMICS) - return __atomic_fetch_add (at, x, order); -#elif defined(USE_GCC_ATOMICS) - return __sync_fetch_and_add (at, x); -#elif defined(_MSC_VER) - // Windows -# if defined(_WIN64) - return _InterlockedExchangeAdd64 ((volatile LONGLONG *)at, x); -# else - return InterlockedExchangeAdd64 ((volatile LONGLONG *)at, x); -# endif -#else -# error No atomics on this platform. -#endif -} - - - -/// Atomic version of: -/// if (*at == compareval) { -/// *at = newval; return true; -/// } else { -/// return false; -/// } -inline bool -atomic_compare_and_exchange (volatile int *at, int compareval, int newval, - bool weak = false, - memory_order success = memory_order_seq_cst, - memory_order failure = memory_order_seq_cst) -{ -#ifdef NOTHREADS - if (*at == compareval) { - *at = newval; return true; - } else { - return false; - } -#elif defined(OIIO_USE_GCC_NEW_ATOMICS) - return __atomic_compare_exchange_n (at, &compareval, newval, weak, - success, failure); -#elif defined(USE_GCC_ATOMICS) - return __sync_bool_compare_and_swap (at, compareval, newval); -#elif defined(_MSC_VER) - return (_InterlockedCompareExchange ((volatile LONG *)at, newval, compareval) == compareval); -#else -# error No atomics on this platform. -#endif -} - - - -inline bool -atomic_compare_and_exchange (volatile long long *at, long long compareval, long long newval, - bool weak = false, - memory_order success = memory_order_seq_cst, - memory_order failure = memory_order_seq_cst) -{ -#ifdef NOTHREADS - if (*at == compareval) { - *at = newval; return true; - } else { - return false; - } -#elif defined(OIIO_USE_GCC_NEW_ATOMICS) - return __atomic_compare_exchange_n (at, &compareval, newval, weak, - success, failure); -#elif defined(USE_GCC_ATOMICS) - return __sync_bool_compare_and_swap (at, compareval, newval); -#elif defined(_MSC_VER) - return (_InterlockedCompareExchange64 ((volatile LONGLONG *)at, newval, compareval) == compareval); -#else -# error No atomics on this platform. -#endif -} - - - -/// Atomic version of: r = *at, *at = x, return r -/// For each of several architectures. -inline int -atomic_exchange (volatile int *at, int x, - memory_order order = memory_order_seq_cst) -{ -#ifdef NOTHREADS - int r = *at; *at = x; return r; -#elif defined(OIIO_USE_GCC_NEW_ATOMICS) - return __atomic_exchange_n (at, x, order); -#elif defined(USE_GCC_ATOMICS) - // No __sync version of atomic exchange! Do it the hard way: - while (1) { - int old = *at; - if (atomic_compare_and_exchange (at, old, x)) - return old; - } - return 0; // can never happen -#elif defined(_MSC_VER) - // Windows - return _InterlockedExchange ((volatile LONG *)at, x); -#else -# error No atomics on this platform. -#endif -} - - - -inline long long -atomic_exchange (volatile long long *at, long long x, - memory_order order = memory_order_seq_cst) -{ -#ifdef NOTHREADS - long long r = *at; *at = x; return r; -#elif defined(OIIO_USE_GCC_NEW_ATOMICS) - return __atomic_exchange_n (at, x, order); -#elif defined(USE_GCC_ATOMICS) - // No __sync version of atomic exchange! Do it the hard way: - while (1) { - long long old = *at; - if (atomic_compare_and_exchange (at, old, x)) - return old; - } - return 0; // can never happen -#elif defined(_MSC_VER) - // Windows -# if defined(_WIN64) - return _InterlockedExchange64 ((volatile LONGLONG *)at, x); -# else - return InterlockedExchange64 ((volatile LONGLONG *)at, x); -# endif -#else -# error No atomics on this platform. -#endif -} - - - -/// Memory fence / synchronization barrier -OIIO_FORCEINLINE void -atomic_thread_fence (memory_order order = memory_order_seq_cst) -{ -#ifdef NOTHREADS - // nothing -#elif OIIO_USE_STDATOMIC - std::__atomic_thread_fence (order); -#elif defined(OIIO_USE_GCC_NEW_ATOMICS) - __atomic_thread_fence (order); -#elif defined(USE_GCC_ATOMICS) - __sync_synchronize (); -#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) - __asm__ __volatile__ ("":::"memory"); -#elif defined(_MSC_VER) - MemoryBarrier (); -#else -# error No atomics on this platform. -#endif -} - - - -/// Yield the processor for the rest of the timeslice. -/// -inline void -yield () -{ -#if defined(__GNUC__) - sched_yield (); -#elif defined(_MSC_VER) - SwitchToThread (); -#else -# error No yield on this platform. -#endif -} - - - -// Slight pause -inline void -pause (int delay) -{ -#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) - for (int i = 0; i < delay; ++i) - __asm__ __volatile__("pause;"); - -#elif defined(__GNUC__) && (defined(__arm__) || defined(__s390__)) - for (int i = 0; i < delay; ++i) - __asm__ __volatile__("NOP;"); - -#elif defined(_MSC_VER) - for (int i = 0; i < delay; ++i) { -#if defined (_WIN64) - YieldProcessor(); -#else - _asm pause -#endif /* _WIN64 */ - } - -#else - // No pause on this platform, just punt - for (int i = 0; i < delay; ++i) ; -#endif -} - - - -// Helper class to deliver ever longer pauses until we yield our timeslice. -class atomic_backoff { -public: - atomic_backoff () : m_count(1) { } - - void operator() () { - if (m_count <= 16) { - pause (m_count); - m_count *= 2; - } else { - yield(); - } - } - -private: - int m_count; -}; - - - -/// Atomic integer. Increment, decrement, add, and subtract in a -/// totally thread-safe manner. -template -class atomic { -public: - /// Construct with initial value. - /// - atomic (T val=0) : m_val(val) { } - - ~atomic () { } - - /// Retrieve value - /// - T load (memory_order order = memory_order_seq_cst) const { - return atomic_exchange_and_add (&m_val, 0, order); - } - - /// Retrieve value - /// - T operator() () const { return load(); } - - /// Retrieve value - /// - operator T() const { return load(); } - - /// Fast retrieval of value, no interchange, don't care about memory - /// fences. Use with extreme caution! - T fast_value () const { return m_val; } - - /// Assign new value, atomically. - void store (T x, memory_order order = memory_order_seq_cst) { - atomic_exchange (&m_val, x, order); - } - - /// Atomic exchange - T exchange (T x, memory_order order = memory_order_seq_cst) { - return atomic_exchange (&m_val, x, order); - } - - /// Atomic fetch-and-add: add x and return the old value. - T fetch_add (T x, memory_order order = memory_order_seq_cst) { - return atomic_exchange_and_add (&m_val, x, order); - } - /// Atomic fetch-and-subtract: subtract x and return the old value. - T fetch_sub (T x, memory_order order = memory_order_seq_cst) { - return atomic_exchange_and_add (&m_val, -x, order); - } - - /// Assign new value. - /// - T operator= (T x) { store(x); return x; } - - /// Pre-increment: ++foo - /// - T operator++ () { return fetch_add(1) + 1; } - - /// Post-increment: foo++ - /// - T operator++ (int) { return fetch_add(1); } - - /// Pre-decrement: --foo - /// - T operator-- () { return fetch_sub(1) - 1; } - - /// Post-decrement: foo-- - /// - T operator-- (int) { return fetch_sub(1); } - - /// Add to the value, return the new result - /// - T operator+= (T x) { return fetch_add(x) + x; } - - /// Subtract from the value, return the new result - /// - T operator-= (T x) { return fetch_sub(x) - x; } - - bool bool_compare_and_swap (T compareval, T newval) { - return atomic_compare_and_exchange (&m_val, compareval, newval); - } - - T operator= (const atomic &x) { - T r = x(); - *this = r; - return r; - } - -private: -#ifdef __arm__ - OIIO_ALIGN(8) -#endif - volatile mutable T m_val; - - // Disallow copy construction by making private and unimplemented. - atomic (atomic const &); -}; - - - -#ifdef NOTHREADS - -typedef int atomic_int; -typedef long long atomic_ll; - -#else - -typedef atomic atomic_int; -typedef atomic atomic_ll; - -#endif - - - -#ifdef NOTHREADS - -typedef null_mutex spin_mutex; -typedef null_lock spin_lock; - -#else - -// Define our own spin locks. - - -/// A spin_mutex is semantically equivalent to a regular mutex, except -/// for the following: -/// - A spin_mutex is just 4 bytes, whereas a regular mutex is quite -/// large (44 bytes for pthread). -/// - A spin_mutex is extremely fast to lock and unlock, whereas a regular -/// mutex is surprisingly expensive just to acquire a lock. -/// - A spin_mutex takes CPU while it waits, so this can be very -/// wasteful compared to a regular mutex that blocks (gives up its -/// CPU slices until it acquires the lock). -/// -/// The bottom line is that mutex is the usual choice, but in cases where -/// you need to acquire locks very frequently, but only need to hold the -/// lock for a very short period of time, you may save runtime by using -/// a spin_mutex, even though it's non-blocking. -/// -/// N.B. A spin_mutex is only the size of an int. To avoid "false -/// sharing", be careful not to put two spin_mutex objects on the same -/// cache line (within 128 bytes of each other), or the two mutexes may -/// effectively (and wastefully) lock against each other. -/// -class spin_mutex { -public: - /// Default constructor -- initialize to unlocked. - /// - spin_mutex (void) { m_locked = 0; } - - ~spin_mutex (void) { } - - /// Copy constructor -- initialize to unlocked. - /// - spin_mutex (const spin_mutex &) { m_locked = 0; } - - /// Assignment does not do anything, since lockedness should not - /// transfer. - const spin_mutex& operator= (const spin_mutex&) { return *this; } - - /// Acquire the lock, spin until we have it. - /// - void lock () { - // To avoid spinning too tightly, we use the atomic_backoff to - // provide increasingly longer pauses, and if the lock is under - // lots of contention, eventually yield the timeslice. - atomic_backoff backoff; - - // Try to get ownership of the lock. Though experimentation, we - // found that OIIO_UNLIKELY makes this just a bit faster on - // gcc x86/x86_64 systems. - while (! OIIO_UNLIKELY(try_lock())) { -#if OIIO_THREAD_ALLOW_DCLP - // The full try_lock() involves a compare_and_swap, which - // writes memory, and that will lock the bus. But a normal - // read of m_locked will let us spin until the value - // changes, without locking the bus. So it's faster to - // check in this manner until the mutex appears to be free. - // HOWEVER... Thread Sanitizer things this is an instance of - // an unsafe "double checked lock pattern" (DCLP) and flags it - // as an error. I think it's a false negative, because the - // outer loop is still an atomic check, the inner non-atomic - // loop only serves to delay, and can't lead to a true data - // race. But we provide this build-time switch to, at least, - // give a way to use tsan for other checks. - do { - backoff(); - } while (m_locked); -#else - backoff(); -#endif - } - } - - /// Release the lock that we hold. - /// - void unlock () { - // Fastest way to do it is with a store with "release" semantics -#if defined(OIIO_USE_GCC_NEW_ATOMICS) - __atomic_clear (&m_locked, __ATOMIC_RELEASE); -#elif defined(USE_GCC_ATOMICS) - __sync_lock_release (&m_locked); - // Equivalent, x86 specific code: - // __asm__ __volatile__("": : :"memory"); - // m_locked = 0; -#elif defined(_MSC_VER) - MemoryBarrier (); - m_locked = 0; -#else - // Otherwise, just assign zero to the atomic (but that's a full - // memory barrier). - *(atomic_int *)&m_locked = 0; -#endif - } - - /// Try to acquire the lock. Return true if we have it, false if - /// somebody else is holding the lock. - bool try_lock () { -#if defined(OIIO_USE_GCC_NEW_ATOMICS) - return __atomic_test_and_set (&m_locked, __ATOMIC_ACQUIRE) == 0; -#elif defined(USE_GCC_ATOMICS) - // GCC gives us an intrinsic that is even better -- an atomic - // exchange with "acquire" barrier semantics. - return __sync_lock_test_and_set (&m_locked, 1) == 0; -#else - // Our compare_and_swap returns true if it swapped - return atomic_compare_and_exchange (&m_locked, 0, 1); -#endif - } - - /// Helper class: scoped lock for a spin_mutex -- grabs the lock upon - /// construction, releases the lock when it exits scope. - class lock_guard { - public: - lock_guard (spin_mutex &fm) : m_fm(fm) { m_fm.lock(); } - ~lock_guard () { m_fm.unlock(); } - private: - lock_guard(); // Do not implement - lock_guard(const lock_guard& other); // Do not implement - lock_guard& operator = (const lock_guard& other); // Do not implement - spin_mutex & m_fm; - }; - -private: -#if defined(OIIO_USE_GCC_NEW_ATOMICS) - // Using the gcc >= 4.8 new atomics, we can easily do a single byte flag - volatile char m_locked; ///< Atomic counter is zero if nobody holds the lock -#else - // Otherwise, fall back on it being an int - volatile int m_locked; ///< Atomic counter is zero if nobody holds the lock -#endif -}; - - -typedef spin_mutex::lock_guard spin_lock; - -#endif - - - -/// Spinning reader/writer mutex. This is just like spin_mutex, except -/// that there are separate locking mechanisms for "writers" (exclusive -/// holders of the lock, presumably because they are modifying whatever -/// the lock is protecting) and "readers" (non-exclusive, non-modifying -/// tasks that may access the protectee simultaneously). -class spin_rw_mutex { -public: - /// Default constructor -- initialize to unlocked. - /// - spin_rw_mutex (void) { m_readers = 0; } - - ~spin_rw_mutex (void) { } - - /// Copy constructor -- initialize to unlocked. - /// - spin_rw_mutex (const spin_rw_mutex &) { m_readers = 0; } - - /// Assignment does not do anything, since lockedness should not - /// transfer. - const spin_rw_mutex& operator= (const spin_rw_mutex&) { return *this; } - - /// Acquire the reader lock. - /// - void read_lock () { - // Spin until there are no writers active - m_locked.lock(); - // Register ourself as a reader - ++m_readers; - // Release the lock, to let other readers work - m_locked.unlock(); - } - - /// Release the reader lock. - /// - void read_unlock () { - --m_readers; // it's atomic, no need to lock to release - } - - /// Acquire the writer lock. - /// - void write_lock () { - // Make sure no new readers (or writers) can start - m_locked.lock(); - // Spin until the last reader is done, at which point we will be - // the sole owners and nobody else (reader or writer) can acquire - // the resource until we release it. -#if OIIO_THREAD_ALLOW_DCLP - while (*(volatile int *)&m_readers > 0) - ; -#else - while (m_readers > 0) - ; -#endif - } - - /// Release the writer lock. - /// - void write_unlock () { - // Let other readers or writers get the lock - m_locked.unlock (); - } - - /// Acquire an exclusive ("writer") lock. - void lock () { write_lock(); } - - /// Release an exclusive ("writer") lock. - void unlock () { write_unlock(); } - - /// Acquire a shared ("reader") lock. - void lock_shared () { read_lock(); } - - /// Release a shared ("reader") lock. - void unlock_shared () { read_unlock(); } - - /// Helper class: scoped read lock for a spin_rw_mutex -- grabs the - /// read lock upon construction, releases the lock when it exits scope. - class read_lock_guard { - public: - read_lock_guard (spin_rw_mutex &fm) : m_fm(fm) { m_fm.read_lock(); } - ~read_lock_guard () { m_fm.read_unlock(); } - private: - read_lock_guard(); // Do not implement - read_lock_guard(const read_lock_guard& other); // Do not implement - read_lock_guard& operator = (const read_lock_guard& other); // Do not implement - spin_rw_mutex & m_fm; - }; - - /// Helper class: scoped write lock for a spin_rw_mutex -- grabs the - /// read lock upon construction, releases the lock when it exits scope. - class write_lock_guard { - public: - write_lock_guard (spin_rw_mutex &fm) : m_fm(fm) { m_fm.write_lock(); } - ~write_lock_guard () { m_fm.write_unlock(); } - private: - write_lock_guard(); // Do not implement - write_lock_guard(const write_lock_guard& other); // Do not implement - write_lock_guard& operator = (const write_lock_guard& other); // Do not implement - spin_rw_mutex & m_fm; - }; - -private: - OIIO_CACHE_ALIGN - spin_mutex m_locked; // write lock - char pad1_[OIIO_CACHE_LINE_SIZE-sizeof(spin_mutex)]; - OIIO_CACHE_ALIGN - atomic_int m_readers; // number of readers - char pad2_[OIIO_CACHE_LINE_SIZE-sizeof(atomic_int)]; -}; - - -typedef spin_rw_mutex::read_lock_guard spin_rw_read_lock; -typedef spin_rw_mutex::write_lock_guard spin_rw_write_lock; - - - -/// Simple thread group class. This is just as good as boost::thread_group, -/// for the limited functionality that we use. -class thread_group { -public: - thread_group () {} - ~thread_group () { - for (size_t i = 0, e = m_threads.size(); i < e; ++i) - delete m_threads[i]; - } - void add_thread (thread *t) { - if (t) { - lock_guard lock (m_mutex); - m_threads.push_back (t); - } - } - template - thread *create_thread (FUNC func) { - lock_guard lock (m_mutex); - thread *t = new thread (func); - m_threads.push_back (t); - return t; - } - void join_all () { - lock_guard lock (m_mutex); - for (size_t i = 0, e = m_threads.size(); i < e; ++i) { - if (m_threads[i]->joinable()) - m_threads[i]->join(); - } - } - size_t size () { - lock_guard lock (m_mutex); - return m_threads.size(); - } -private: - mutex m_mutex; - std::vector m_threads; -}; - - -OIIO_NAMESPACE_END - -#endif // OPENIMAGEIO_THREAD_H diff --git a/3rdparty/oiio16/include/OpenImageIO/timer.h b/3rdparty/oiio16/include/OpenImageIO/timer.h deleted file mode 100644 index 3259aeb3..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/timer.h +++ /dev/null @@ -1,286 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -/// @file timer.h -/// @brief Simple timer class. - - -#ifndef OPENIMAGEIO_TIMER_H -#define OPENIMAGEIO_TIMER_H - -#include "oiioversion.h" -#include "export.h" -#include "platform.h" /* Must be before windows.h */ - -#ifdef _WIN32 -# include -#elif defined(__APPLE__) -# include -#else -#include -#include // Just for NULL definition -#endif -#include - - -OIIO_NAMESPACE_BEGIN - -/// Simple timer class. -/// -/// This class allows you to time things, for runtime statistics and the -/// like. The simplest usage pattern is illustrated by the following -/// example: -/// -/// \code -/// Timer mytimer; // automatically starts upon construction -/// ...do stuff -/// float t = mytimer(); // seconds elapsed since start -/// -/// Timer another (false); // false means don't start ticking yet -/// another.start (); // start ticking now -/// another.stop (); // stop ticking -/// another.start (); // start again where we left off -/// another.stop (); -/// another.reset (); // reset to zero time again -/// \endcode -/// -/// These are not very high-resolution timers. A Timer begin/end pair -/// takes somewhere in the neighborhood of 0.1 - 0.3 us (microseconds), -/// and can vary by OS. This means that (a) it's not useful for timing -/// individual events near or below that resolution (things that would -/// take only tens or hundreds of processor cycles, for example), and -/// (b) calling it millions of times could make your program appreciably -/// more expensive due to the timers themselves. -/// -class OIIO_API Timer { -public: - typedef long long ticks_t; - enum StartNowVal { DontStartNow, StartNow }; - enum PrintDtrVal { DontPrintDtr, PrintDtr }; - - /// Constructor -- reset at zero, and start timing unless optional - /// 'startnow' argument is false. - Timer (StartNowVal startnow=StartNow, - PrintDtrVal printdtr=DontPrintDtr, - const char *name=NULL) - : m_ticking(false), m_printdtr(printdtr), - m_starttime(0), m_elapsed_ticks(0), - m_name(name) - { - if (startnow == StartNow) - start(); - } - - /// DEPRECATED Constructor -- reset at zero, and start timing unless - /// optional 'startnow' argument is false. - Timer (bool startnow) - : m_ticking(false), m_printdtr(DontPrintDtr), - m_starttime(0), m_elapsed_ticks(0), - m_name(NULL) - { - if (startnow) - start(); - } - - /// Destructor. - ~Timer () { - if (m_printdtr == PrintDtr) - std::cout << "Timer " << (m_name?m_name:"") << ": " - << seconds(ticks()) << "s\n"; - } - - /// Start (or restart) ticking, if we are not currently. - void start () { - if (! m_ticking) { - m_starttime = now(); - m_ticking = true; - } - } - - /// Stop ticking, return the total amount of time that has ticked - /// (both this round as well as previous laps). Current ticks will - /// be added to previous elapsed time. - double stop () { - if (m_ticking) { - ticks_t n = now(); - m_elapsed_ticks += tickdiff (m_starttime, n); - m_ticking = false; - } - return seconds(m_elapsed_ticks); - } - - /// Reset at zero and stop ticking. - /// - void reset (void) { - m_elapsed_ticks = 0; - m_ticking = false; - } - - /// Return just the ticks of the current lap (since the last call to - /// start() or lap()), add that to the previous elapsed time, reset - /// current start time to now, keep the timer going (if it was). - ticks_t lap_ticks () { - ticks_t n = now(); - ticks_t r = m_ticking ? tickdiff (m_starttime, n) : ticks_t(0); - m_elapsed_ticks += r; - m_starttime = n; - m_ticking = true; - return r; - } - - /// Return just the time of the current lap (since the last call to - /// start() or lap()), add that to the previous elapsed time, reset - /// current start time to now, keep the timer going (if it was). - double lap () { return seconds(lap_ticks()); } - - /// Total number of elapsed ticks so far, including both the currently- - /// ticking clock as well as any previously elapsed time. - ticks_t ticks () const { return ticks_since_start() + m_elapsed_ticks; } - - /// Operator () returns the elapsed time so far, in seconds, including - /// both the currently-ticking clock as well as any previously elapsed - /// time. - double operator() (void) const { return seconds (ticks()); } - - /// Return just the ticks since we called start(), not any elapsed - /// time in previous start-stop segments. - ticks_t ticks_since_start (void) const { - return m_ticking ? tickdiff (m_starttime, now()) : ticks_t(0); - } - - /// Return just the time since we called start(), not any elapsed - /// time in previous start-stop segments. - double time_since_start (void) const { return seconds (ticks_since_start()); } - - /// Convert number of ticks to seconds. - static double seconds (ticks_t ticks) { return ticks * seconds_per_tick; } - - /// Is the timer currently ticking? - bool ticking () const { return m_ticking; } - -private: - bool m_ticking; ///< Are we currently ticking? - bool m_printdtr; ///< Print upon destruction? - ticks_t m_starttime; ///< Time since last call to start() - ticks_t m_elapsed_ticks; ///< Time elapsed BEFORE the current start(). - const char *m_name; ///< Timer name - - /// Platform-dependent grab of current time, expressed as ticks_t. - /// - ticks_t now (void) const { -#ifdef _WIN32 - LARGE_INTEGER n; - QueryPerformanceCounter (&n); // From MSDN web site - return n.QuadPart; -#elif defined(__APPLE__) - return mach_absolute_time(); -#else - struct timeval t; - gettimeofday (&t, NULL); - return (long long) t.tv_sec*1000000ll + t.tv_usec; -#endif - } - - /// Difference between two times, expressed in (platform-dependent) - /// ticks. - ticks_t tickdiff (ticks_t then, ticks_t now) const { - return (now>then) ? now-then : then-now; - } - - /// Difference between two times, expressed in seconds. - double diff (ticks_t then, ticks_t now) const { - return seconds (tickdiff (then, now)); - } - - static double seconds_per_tick; - friend class TimerSetupOnce; -}; - - - -/// Helper class that starts and stops a timer when the ScopedTimer goes -/// in and out of scope. -class ScopedTimer { -public: - /// Given a reference to a timer, start it when this constructor - /// occurs. - ScopedTimer (Timer &t) : m_timer(t) { start(); } - - /// Stop the timer from ticking when this object is destroyed (i.e. - /// it leaves scope). - ~ScopedTimer () { stop(); } - - /// Explicit start of the timer. - /// - void start () { m_timer.start(); } - - /// Explicit stop of the timer. - /// - void stop () { m_timer.stop(); } - - /// Explicit reset of the timer. - /// - void reset () { m_timer.reset(); } - -private: - Timer &m_timer; -}; - - - -/// Helper template that runs a function (or functor) n times, using a -/// Timer to benchmark the results, and returning the fastest trial. If -/// 'range' is non-NULL, the range (max-min) of the various time trials -/// will be stored there. -template -double -time_trial (FUNC func, int n=1, double *range=NULL) -{ - double mintime = 1.0e30, maxtime = 0.0; - while (n-- > 0) { - Timer timer; - func (); - double t = timer(); - if (t < mintime) - mintime = t; - if (t > maxtime) - maxtime = t; - } - if (range) - *range = maxtime-mintime; - return mintime; -} - - - -OIIO_NAMESPACE_END - -#endif // OPENIMAGEIO_TIMER_H diff --git a/3rdparty/oiio16/include/OpenImageIO/tinyformat.h b/3rdparty/oiio16/include/OpenImageIO/tinyformat.h deleted file mode 100644 index d9a8d87c..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/tinyformat.h +++ /dev/null @@ -1,995 +0,0 @@ -// tinyformat.h -// Copyright (C) 2011, Chris Foster [chris42f (at) gmail (d0t) com] -// -// Boost Software License - Version 1.0 -// -// Permission is hereby granted, free of charge, to any person or organization -// obtaining a copy of the software and accompanying documentation covered by -// this license (the "Software") to use, reproduce, display, distribute, -// execute, and transmit the Software, and to prepare derivative works of the -// Software, and to permit third-parties to whom the Software is furnished to -// do so, all subject to the following: -// -// The copyright notices in the Software and this entire statement, including -// the above license grant, this restriction and the following disclaimer, -// must be included in all copies of the Software, in whole or in part, and -// all derivative works of the Software, unless such copies or derivative -// works are solely in the form of machine-executable object code generated by -// a source language processor. -// -// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT -// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -//------------------------------------------------------------------------------ -// Tinyformat: A minimal type safe printf replacement -// -// tinyformat.h is a type safe printf replacement library in a single C++ -// header file. Design goals include: -// -// * Type safety and extensibility for user defined types. -// * C99 printf() compatibility, to the extent possible using std::ostream -// * Simplicity and minimalism. A single header file to include and distribute -// with your projects. -// * Augment rather than replace the standard stream formatting mechanism -// * C++98 support, with optional C++11 niceties -// -// -// Main interface example usage -// ---------------------------- -// -// To print a date to std::cout: -// -// std::string weekday = "Wednesday"; -// const char* month = "July"; -// size_t day = 27; -// long hour = 14; -// int min = 44; -// -// tfm::printf("%s, %s %d, %.2d:%.2d\n", weekday, month, day, hour, min); -// -// The strange types here emphasize the type safety of the interface; it is -// possible to print a std::string using the "%s" conversion, and a -// size_t using the "%d" conversion. A similar result could be achieved -// using either of the tfm::format() functions. One prints on a user provided -// stream: -// -// tfm::format(std::cerr, "%s, %s %d, %.2d:%.2d\n", -// weekday, month, day, hour, min); -// -// The other returns a std::string: -// -// std::string date = tfm::format("%s, %s %d, %.2d:%.2d\n", -// weekday, month, day, hour, min); -// std::cout << date; -// -// These are the three primary interface functions. -// -// -// User defined format functions -// ----------------------------- -// -// Simulating variadic templates in C++98 is pretty painful since it requires -// writing out the same function for each desired number of arguments. To make -// this bearable tinyformat comes with a set of macros which are used -// internally to generate the API, but which may also be used in user code. -// -// The three macros TINYFORMAT_ARGTYPES(n), TINYFORMAT_VARARGS(n) and -// TINYFORMAT_PASSARGS(n) will generate a list of n argument types, -// type/name pairs and argument names respectively when called with an integer -// n between 1 and 16. We can use these to define a macro which generates the -// desired user defined function with n arguments. To generate all 16 user -// defined function bodies, use the macro TINYFORMAT_FOREACH_ARGNUM. For an -// example, see the implementation of printf() at the end of the source file. -// -// -// Additional API information -// -------------------------- -// -// Error handling: Define TINYFORMAT_ERROR to customize the error handling for -// format strings which are unsupported or have the wrong number of format -// specifiers (calls assert() by default). -// -// User defined types: Uses operator<< for user defined types by default. -// Overload formatValue() for more control. - - -#ifndef TINYFORMAT_H_INCLUDED -#define TINYFORMAT_H_INCLUDED - -namespace tinyformat {} -//------------------------------------------------------------------------------ -// Config section. Customize to your liking! - -// Namespace alias to encourage brevity -namespace tfm = tinyformat; - -// Error handling; calls assert() by default. -// #define TINYFORMAT_ERROR(reasonString) your_error_handler(reasonString) - -// Define for C++11 variadic templates which make the code shorter & more -// general. If you don't define this, C++11 support is autodetected below. -// #define TINYFORMAT_USE_VARIADIC_TEMPLATES - - -//------------------------------------------------------------------------------ -// Implementation details. -#include -#include -#include - -#ifndef TINYFORMAT_ERROR -# define TINYFORMAT_ERROR(reason) assert(0 && reason) -#endif - -#if !defined(TINYFORMAT_USE_VARIADIC_TEMPLATES) && !defined(TINYFORMAT_NO_VARIADIC_TEMPLATES) -# ifdef __GXX_EXPERIMENTAL_CXX0X__ -# define TINYFORMAT_USE_VARIADIC_TEMPLATES -# endif -#endif - -#ifdef __GNUC__ -# define TINYFORMAT_NOINLINE __attribute__((noinline)) -#elif defined(_MSC_VER) -# define TINYFORMAT_NOINLINE __declspec(noinline) -#else -# define TINYFORMAT_NOINLINE -#endif - -#if defined(__GLIBCXX__) && __GLIBCXX__ < 20080201 -// std::showpos is broken on old libstdc++ as provided with OSX. See -// http://gcc.gnu.org/ml/libstdc++/2007-11/msg00075.html -# define TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND -#endif - -namespace tinyformat { - -//------------------------------------------------------------------------------ -namespace detail { - -// Test whether type T1 is convertible to type T2 -template -struct is_convertible -{ - private: - // two types of different size - struct fail { char dummy[2]; }; - struct succeed { char dummy; }; - // Try to convert a T1 to a T2 by plugging into tryConvert - static fail tryConvert(...); - static succeed tryConvert(const T2&); - static const T1& makeT1(); - public: -# ifdef _MSC_VER - // Disable spurious loss of precision warnings in tryConvert(makeT1()) -# pragma warning(push) -# pragma warning(disable:4244) -# pragma warning(disable:4267) -# endif - // Standard trick: the (...) version of tryConvert will be chosen from - // the overload set only if the version taking a T2 doesn't match. - // Then we compare the sizes of the return types to check which - // function matched. Very neat, in a disgusting kind of way :) - static const bool value = - sizeof(tryConvert(makeT1())) == sizeof(succeed); -# ifdef _MSC_VER -# pragma warning(pop) -# endif -}; - - -// Detect when a type is not a wchar_t string -template struct is_wchar { typedef int tinyformat_wchar_is_not_supported; }; -template<> struct is_wchar {}; -template<> struct is_wchar {}; -template struct is_wchar {}; -template struct is_wchar {}; - - -// Format the value by casting to type fmtT. This default implementation -// should never be called. -template::value> -struct formatValueAsType -{ - static void invoke(std::ostream& /*out*/, const T& /*value*/) { assert(0); } -}; -// Specialized version for types that can actually be converted to fmtT, as -// indicated by the "convertible" template parameter. -template -struct formatValueAsType -{ - static void invoke(std::ostream& out, const T& value) - { out << static_cast(value); } -}; - -#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND -template::value> -struct formatZeroIntegerWorkaround -{ - static bool invoke(std::ostream& /**/, const T& /**/) { return false; } -}; -template -struct formatZeroIntegerWorkaround -{ - static bool invoke(std::ostream& out, const T& value) - { - if (static_cast(value) == 0 && out.flags() & std::ios::showpos) - { - out << "+0"; - return true; - } - return false; - } -}; -#endif // TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND - -// Convert an arbitrary type to integer. The version with convertible=false -// throws an error. -template::value> -struct convertToInt -{ - static int invoke(const T& /*value*/) - { - TINYFORMAT_ERROR("tinyformat: Cannot convert from argument type to " - "integer for use as variable width or precision"); - return 0; - } -}; -// Specialization for convertToInt when conversion is possible -template -struct convertToInt -{ - static int invoke(const T& value) { return static_cast(value); } -}; - -} // namespace detail - - -//------------------------------------------------------------------------------ -// Variable formatting functions. May be overridden for user-defined types if -// desired. - - -// Format a value into a stream. Called from format() for all types by default. -// -// Users may override this for their own types. When this function is called, -// the stream flags will have been modified according to the format string. -// The format specification is provided in the range [fmtBegin, fmtEnd). -// -// By default, formatValue() uses the usual stream insertion operator -// operator<< to format the type T, with special cases for the %c and %p -// conversions. -template -inline void formatValue(std::ostream& out, const char* /*fmtBegin*/, - const char* fmtEnd, const T& value) -{ -#ifndef TINYFORMAT_ALLOW_WCHAR_STRINGS - // Since we don't support printing of wchar_t using "%ls", make it fail at - // compile time in preference to printing as a void* at runtime. - typedef typename detail::is_wchar::tinyformat_wchar_is_not_supported DummyType; - (void) DummyType(); // avoid unused type warning with gcc-4.8 -#endif - // The mess here is to support the %c and %p conversions: if these - // conversions are active we try to convert the type to a char or const - // void* respectively and format that instead of the value itself. For the - // %p conversion it's important to avoid dereferencing the pointer, which - // could otherwise lead to a crash when printing a dangling (const char*). - const bool canConvertToChar = detail::is_convertible::value; - const bool canConvertToVoidPtr = detail::is_convertible::value; - if(canConvertToChar && *(fmtEnd-1) == 'c') - detail::formatValueAsType::invoke(out, value); - else if(canConvertToVoidPtr && *(fmtEnd-1) == 'p') - detail::formatValueAsType::invoke(out, value); -#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND - else if(detail::formatZeroIntegerWorkaround::invoke(out, value)) /**/; -#endif - else - out << value; -} - - -// Overloaded version for char types to support printing as an integer -#define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType) \ -inline void formatValue(std::ostream& out, const char* /*fmtBegin*/, \ - const char* fmtEnd, charType value) \ -{ \ - switch(*(fmtEnd-1)) \ - { \ - case 'u': case 'd': case 'i': case 'o': case 'X': case 'x': \ - out << static_cast(value); break; \ - default: \ - out << value; break; \ - } \ -} -// per 3.9.1: char, signed char and unsigned char are all distinct types -TINYFORMAT_DEFINE_FORMATVALUE_CHAR(char) -TINYFORMAT_DEFINE_FORMATVALUE_CHAR(signed char) -TINYFORMAT_DEFINE_FORMATVALUE_CHAR(unsigned char) -#undef TINYFORMAT_DEFINE_FORMATVALUE_CHAR - - -//------------------------------------------------------------------------------ -// Tools for emulating variadic templates in C++98. The basic idea here is -// stolen from the boost preprocessor metaprogramming library and cut down to -// be just general enough for what we need. - -#define TINYFORMAT_ARGTYPES(n) TINYFORMAT_ARGTYPES_ ## n -#define TINYFORMAT_VARARGS(n) TINYFORMAT_VARARGS_ ## n -#define TINYFORMAT_PASSARGS(n) TINYFORMAT_PASSARGS_ ## n -#define TINYFORMAT_PASSARGS_TAIL(n) TINYFORMAT_PASSARGS_TAIL_ ## n - -// To keep it as transparent as possible, the macros below have been generated -// using python via the excellent cog.py code generation script. This avoids -// the need for a bunch of complex (but more general) preprocessor tricks as -// used in boost.preprocessor. -// -// To rerun the code generation in place, use `cog.py -r tinyformat.h` -// (see http://nedbatchelder.com/code/cog). Alternatively you can just create -// extra versions by hand. - -/*[[[cog -maxParams = 16 - -def makeCommaSepLists(lineTemplate, elemTemplate, startInd=1): - for j in range(startInd,maxParams+1): - list = ', '.join([elemTemplate % {'i':i} for i in range(startInd,j+1)]) - cog.outl(lineTemplate % {'j':j, 'list':list}) - -makeCommaSepLists('#define TINYFORMAT_ARGTYPES_%(j)d %(list)s', - 'class T%(i)d') - -cog.outl() -makeCommaSepLists('#define TINYFORMAT_VARARGS_%(j)d %(list)s', - 'const T%(i)d& v%(i)d') - -cog.outl() -makeCommaSepLists('#define TINYFORMAT_PASSARGS_%(j)d %(list)s', 'v%(i)d') - -cog.outl() -cog.outl('#define TINYFORMAT_PASSARGS_TAIL_1') -makeCommaSepLists('#define TINYFORMAT_PASSARGS_TAIL_%(j)d , %(list)s', - 'v%(i)d', startInd = 2) - -cog.outl() -cog.outl('#define TINYFORMAT_FOREACH_ARGNUM(m) \\\n ' + - ' '.join(['m(%d)' % (j,) for j in range(1,maxParams+1)])) -]]]*/ -#define TINYFORMAT_ARGTYPES_1 class T1 -#define TINYFORMAT_ARGTYPES_2 class T1, class T2 -#define TINYFORMAT_ARGTYPES_3 class T1, class T2, class T3 -#define TINYFORMAT_ARGTYPES_4 class T1, class T2, class T3, class T4 -#define TINYFORMAT_ARGTYPES_5 class T1, class T2, class T3, class T4, class T5 -#define TINYFORMAT_ARGTYPES_6 class T1, class T2, class T3, class T4, class T5, class T6 -#define TINYFORMAT_ARGTYPES_7 class T1, class T2, class T3, class T4, class T5, class T6, class T7 -#define TINYFORMAT_ARGTYPES_8 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8 -#define TINYFORMAT_ARGTYPES_9 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9 -#define TINYFORMAT_ARGTYPES_10 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10 -#define TINYFORMAT_ARGTYPES_11 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11 -#define TINYFORMAT_ARGTYPES_12 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12 -#define TINYFORMAT_ARGTYPES_13 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13 -#define TINYFORMAT_ARGTYPES_14 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14 -#define TINYFORMAT_ARGTYPES_15 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 -#define TINYFORMAT_ARGTYPES_16 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15, class T16 - -#define TINYFORMAT_VARARGS_1 const T1& v1 -#define TINYFORMAT_VARARGS_2 const T1& v1, const T2& v2 -#define TINYFORMAT_VARARGS_3 const T1& v1, const T2& v2, const T3& v3 -#define TINYFORMAT_VARARGS_4 const T1& v1, const T2& v2, const T3& v3, const T4& v4 -#define TINYFORMAT_VARARGS_5 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5 -#define TINYFORMAT_VARARGS_6 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6 -#define TINYFORMAT_VARARGS_7 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7 -#define TINYFORMAT_VARARGS_8 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8 -#define TINYFORMAT_VARARGS_9 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9 -#define TINYFORMAT_VARARGS_10 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10 -#define TINYFORMAT_VARARGS_11 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10, const T11& v11 -#define TINYFORMAT_VARARGS_12 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10, const T11& v11, const T12& v12 -#define TINYFORMAT_VARARGS_13 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10, const T11& v11, const T12& v12, const T13& v13 -#define TINYFORMAT_VARARGS_14 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10, const T11& v11, const T12& v12, const T13& v13, const T14& v14 -#define TINYFORMAT_VARARGS_15 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10, const T11& v11, const T12& v12, const T13& v13, const T14& v14, const T15& v15 -#define TINYFORMAT_VARARGS_16 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10, const T11& v11, const T12& v12, const T13& v13, const T14& v14, const T15& v15, const T16& v16 - -#define TINYFORMAT_PASSARGS_1 v1 -#define TINYFORMAT_PASSARGS_2 v1, v2 -#define TINYFORMAT_PASSARGS_3 v1, v2, v3 -#define TINYFORMAT_PASSARGS_4 v1, v2, v3, v4 -#define TINYFORMAT_PASSARGS_5 v1, v2, v3, v4, v5 -#define TINYFORMAT_PASSARGS_6 v1, v2, v3, v4, v5, v6 -#define TINYFORMAT_PASSARGS_7 v1, v2, v3, v4, v5, v6, v7 -#define TINYFORMAT_PASSARGS_8 v1, v2, v3, v4, v5, v6, v7, v8 -#define TINYFORMAT_PASSARGS_9 v1, v2, v3, v4, v5, v6, v7, v8, v9 -#define TINYFORMAT_PASSARGS_10 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10 -#define TINYFORMAT_PASSARGS_11 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 -#define TINYFORMAT_PASSARGS_12 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12 -#define TINYFORMAT_PASSARGS_13 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13 -#define TINYFORMAT_PASSARGS_14 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14 -#define TINYFORMAT_PASSARGS_15 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 -#define TINYFORMAT_PASSARGS_16 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16 - -#define TINYFORMAT_PASSARGS_TAIL_1 -#define TINYFORMAT_PASSARGS_TAIL_2 , v2 -#define TINYFORMAT_PASSARGS_TAIL_3 , v2, v3 -#define TINYFORMAT_PASSARGS_TAIL_4 , v2, v3, v4 -#define TINYFORMAT_PASSARGS_TAIL_5 , v2, v3, v4, v5 -#define TINYFORMAT_PASSARGS_TAIL_6 , v2, v3, v4, v5, v6 -#define TINYFORMAT_PASSARGS_TAIL_7 , v2, v3, v4, v5, v6, v7 -#define TINYFORMAT_PASSARGS_TAIL_8 , v2, v3, v4, v5, v6, v7, v8 -#define TINYFORMAT_PASSARGS_TAIL_9 , v2, v3, v4, v5, v6, v7, v8, v9 -#define TINYFORMAT_PASSARGS_TAIL_10 , v2, v3, v4, v5, v6, v7, v8, v9, v10 -#define TINYFORMAT_PASSARGS_TAIL_11 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 -#define TINYFORMAT_PASSARGS_TAIL_12 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12 -#define TINYFORMAT_PASSARGS_TAIL_13 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13 -#define TINYFORMAT_PASSARGS_TAIL_14 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14 -#define TINYFORMAT_PASSARGS_TAIL_15 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 -#define TINYFORMAT_PASSARGS_TAIL_16 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16 - -#define TINYFORMAT_FOREACH_ARGNUM(m) \ - m(1) m(2) m(3) m(4) m(5) m(6) m(7) m(8) m(9) m(10) m(11) m(12) m(13) m(14) m(15) m(16) -//[[[end]]] - - - -namespace detail { - -// Class holding current position in format string and an output stream into -// which arguments are formatted. -class FormatIterator -{ - public: - // Flags for features not representable with standard stream state - enum ExtraFormatFlags - { - Flag_None = 0, - Flag_TruncateToPrecision = 1<<0, // truncate length to stream precision() - Flag_SpacePadPositive = 1<<1, // pad positive values with spaces - Flag_VariableWidth = 1<<2, // variable field width in arg list - Flag_VariablePrecision = 1<<3 // variable field precision in arg list - }; - - // out is the output stream, fmt is the full format string - FormatIterator(std::ostream& out, const char* fmt) - : m_out(out), - m_fmt(fmt), - m_extraFlags(Flag_None), - m_wantWidth(false), - m_wantPrecision(false), - m_variableWidth(0), - m_variablePrecision(0), - m_origWidth(out.width()), - m_origPrecision(out.precision()), - m_origFlags(out.flags()), - m_origFill(out.fill()) - { } - - // Print remaining part of format string. - void finish() - { - // It would be nice if we could do this from the destructor, but we - // can't if TINFORMAT_ERROR is used to throw an exception! - m_fmt = printFormatStringLiteral(m_out, m_fmt); - if(*m_fmt != '\0') - TINYFORMAT_ERROR("tinyformat: Too many conversion specifiers in format string"); - } - - ~FormatIterator() - { - // Restore stream state - m_out.width(m_origWidth); - m_out.precision(m_origPrecision); - m_out.flags(m_origFlags); - m_out.fill(m_origFill); - } - - template - void accept(const T& value); - - private: - // Parse and return an integer from the string c, as atoi() - // On return, c is set to one past the end of the integer. - static int parseIntAndAdvance(const char*& c) - { - int i = 0; - for(;*c >= '0' && *c <= '9'; ++c) - i = 10*i + (*c - '0'); - return i; - } - - // Format at most truncLen characters of a C string to the given - // stream. Return true if formatting proceeded (generic version always - // returns false) - template - static bool formatCStringTruncate(std::ostream& /*out*/, const T& /*value*/, - std::streamsize /*truncLen*/) - { - return false; - } -# define TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(type) \ - static bool formatCStringTruncate(std::ostream& out, type* value, \ - std::streamsize truncLen) \ - { \ - std::streamsize len = 0; \ - while(len < truncLen && value[len] != 0) \ - ++len; \ - out.write(value, len); \ - return true; \ - } - // Overload for const char* and char*. Could overload for signed & - // unsigned char too, but these are technically unneeded for printf - // compatibility. - TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(const char) - TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(char) -# undef TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE - - // Print literal part of format string and return next format spec - // position. - // - // Skips over any occurrences of '%%', printing a literal '%' to the - // output. The position of the first % character of the next - // nontrivial format spec is returned, or the end of string. - static const char* printFormatStringLiteral(std::ostream& out, - const char* fmt) - { - const char* c = fmt; - for(; true; ++c) - { - switch(*c) - { - case '\0': - out.write(fmt, static_cast(c - fmt)); - return c; - case '%': - out.write(fmt, static_cast(c - fmt)); - if(*(c+1) != '%') - return c; - // for "%%", tack trailing % onto next literal section. - fmt = ++c; - break; - } - } - } - - static const char* streamStateFromFormat(std::ostream& out, - unsigned int& extraFlags, - const char* fmtStart, - int variableWidth, - int variablePrecision); - - // Private copy & assign: Kill gcc warnings with -Weffc++ - FormatIterator(const FormatIterator&); - FormatIterator& operator=(const FormatIterator&); - - // Stream, current format string & state - std::ostream& m_out; - const char* m_fmt; - unsigned int m_extraFlags; - // State machine info for handling of variable width & precision - bool m_wantWidth; - bool m_wantPrecision; - int m_variableWidth; - int m_variablePrecision; - // Saved stream state - std::streamsize m_origWidth; - std::streamsize m_origPrecision; - std::ios::fmtflags m_origFlags; - char m_origFill; -}; - - -// Accept a value for formatting into the internal stream. -template -TINYFORMAT_NOINLINE // < greatly reduces bloat in optimized builds -void FormatIterator::accept(const T& value) -{ - // Parse the format string - const char* fmtEnd = 0; - if(m_extraFlags == Flag_None && !m_wantWidth && !m_wantPrecision) - { - m_fmt = printFormatStringLiteral(m_out, m_fmt); - fmtEnd = streamStateFromFormat(m_out, m_extraFlags, m_fmt, 0, 0); - m_wantWidth = (m_extraFlags & Flag_VariableWidth) != 0; - m_wantPrecision = (m_extraFlags & Flag_VariablePrecision) != 0; - } - // Consume value as variable width and precision specifier if necessary - if(m_extraFlags & (Flag_VariableWidth | Flag_VariablePrecision)) - { - if(m_wantWidth || m_wantPrecision) - { - int v = convertToInt::invoke(value); - if(m_wantWidth) - { - m_variableWidth = v; - m_wantWidth = false; - } - else if(m_wantPrecision) - { - m_variablePrecision = v; - m_wantPrecision = false; - } - return; - } - // If we get here, we've set both the variable precision and width as - // required and we need to rerun the stream state setup to insert these. - fmtEnd = streamStateFromFormat(m_out, m_extraFlags, m_fmt, - m_variableWidth, m_variablePrecision); - } - - // Format the value into the stream. - if(!(m_extraFlags & (Flag_SpacePadPositive | Flag_TruncateToPrecision))) - formatValue(m_out, m_fmt, fmtEnd, value); - else - { - // The following are special cases where there's no direct - // correspondence between stream formatting and the printf() behaviour. - // Instead, we simulate the behaviour crudely by formatting into a - // temporary string stream and munging the resulting string. - std::ostringstream tmpStream; - tmpStream.copyfmt(m_out); - if(m_extraFlags & Flag_SpacePadPositive) - tmpStream.setf(std::ios::showpos); - // formatCStringTruncate is required for truncating conversions like - // "%.4s" where at most 4 characters of the c-string should be read. - // If we didn't include this special case, we might read off the end. - if(!( (m_extraFlags & Flag_TruncateToPrecision) && - formatCStringTruncate(tmpStream, value, m_out.precision()) )) - { - // Not a truncated c-string; just format normally. - formatValue(tmpStream, m_fmt, fmtEnd, value); - } - std::string result = tmpStream.str(); // allocates... yuck. - if(m_extraFlags & Flag_SpacePadPositive) - { - for(size_t i = 0, iend = result.size(); i < iend; ++i) - if(result[i] == '+') - result[i] = ' '; - } - if((m_extraFlags & Flag_TruncateToPrecision) && - (int)result.size() > (int)m_out.precision()) - m_out.write(result.c_str(), m_out.precision()); - else - m_out << result; - } - m_extraFlags = Flag_None; - m_fmt = fmtEnd; -} - - -// Parse a format string and set the stream state accordingly. -// -// The format mini-language recognized here is meant to be the one from C99, -// with the form "%[flags][width][.precision][length]type". -// -// Formatting options which can't be natively represented using the ostream -// state are returned in the extraFlags parameter which is a bitwise -// combination of values from the ExtraFormatFlags enum. -inline const char* FormatIterator::streamStateFromFormat(std::ostream& out, - unsigned int& extraFlags, - const char* fmtStart, - int variableWidth, - int variablePrecision) -{ - if(*fmtStart != '%') - { - TINYFORMAT_ERROR("tinyformat: Not enough conversion specifiers in format string"); - return fmtStart; - } - // Reset stream state to defaults. - out.width(0); - out.precision(6); - out.fill(' '); - // Reset most flags; ignore irrelevant unitbuf & skipws. - out.unsetf(std::ios::adjustfield | std::ios::basefield | - std::ios::floatfield | std::ios::showbase | std::ios::boolalpha | - std::ios::showpoint | std::ios::showpos | std::ios::uppercase); - extraFlags = Flag_None; - bool precisionSet = false; - bool widthSet = false; - const char* c = fmtStart + 1; - // 1) Parse flags - for(;; ++c) - { - switch(*c) - { - case '#': - out.setf(std::ios::showpoint | std::ios::showbase); - continue; - case '0': - // overridden by left alignment ('-' flag) - if(!(out.flags() & std::ios::left)) - { - // Use internal padding so that numeric values are - // formatted correctly, eg -00010 rather than 000-10 - out.fill('0'); - out.setf(std::ios::internal, std::ios::adjustfield); - } - continue; - case '-': - out.fill(' '); - out.setf(std::ios::left, std::ios::adjustfield); - continue; - case ' ': - // overridden by show positive sign, '+' flag. - if(!(out.flags() & std::ios::showpos)) - extraFlags |= Flag_SpacePadPositive; - continue; - case '+': - out.setf(std::ios::showpos); - extraFlags &= ~Flag_SpacePadPositive; - continue; - } - break; - } - // 2) Parse width - if(*c >= '0' && *c <= '9') - { - widthSet = true; - out.width(parseIntAndAdvance(c)); - } - if(*c == '*') - { - widthSet = true; - if(variableWidth < 0) - { - // negative widths correspond to '-' flag set - out.fill(' '); - out.setf(std::ios::left, std::ios::adjustfield); - variableWidth = -variableWidth; - } - out.width(variableWidth); - extraFlags |= Flag_VariableWidth; - ++c; - } - // 3) Parse precision - if(*c == '.') - { - ++c; - int precision = 0; - if(*c == '*') - { - ++c; - extraFlags |= Flag_VariablePrecision; - precision = variablePrecision; - } - else - { - if(*c >= '0' && *c <= '9') - precision = parseIntAndAdvance(c); - else if(*c == '-') // negative precisions ignored, treated as zero. - parseIntAndAdvance(++c); - } - out.precision(precision); - precisionSet = true; - } - // 4) Ignore any C99 length modifier - while(*c == 'l' || *c == 'h' || *c == 'L' || - *c == 'j' || *c == 'z' || *c == 't') - ++c; - // 5) We're up to the conversion specifier character. - // Set stream flags based on conversion specifier (thanks to the - // boost::format class for forging the way here). - bool intConversion = false; - switch(*c) - { - case 'u': case 'd': case 'i': - out.setf(std::ios::dec, std::ios::basefield); - intConversion = true; - break; - case 'o': - out.setf(std::ios::oct, std::ios::basefield); - intConversion = true; - break; - case 'X': - out.setf(std::ios::uppercase); - case 'x': case 'p': - out.setf(std::ios::hex, std::ios::basefield); - intConversion = true; - break; - case 'E': - out.setf(std::ios::uppercase); - case 'e': - out.setf(std::ios::scientific, std::ios::floatfield); - out.setf(std::ios::dec, std::ios::basefield); - break; - case 'F': - out.setf(std::ios::uppercase); - case 'f': - out.setf(std::ios::fixed, std::ios::floatfield); - break; - case 'G': - out.setf(std::ios::uppercase); - case 'g': - out.setf(std::ios::dec, std::ios::basefield); - // As in boost::format, let stream decide float format. - out.flags(out.flags() & ~std::ios::floatfield); - break; - case 'a': case 'A': - TINYFORMAT_ERROR("tinyformat: the %a and %A conversion specs " - "are not supported"); - break; - case 'c': - // Handled as special case inside formatValue() - break; - case 's': - if(precisionSet) - extraFlags |= Flag_TruncateToPrecision; - // Make %s print booleans as "true" and "false" - out.setf(std::ios::boolalpha); - break; - case 'n': - // Not supported - will cause problems! - TINYFORMAT_ERROR("tinyformat: %n conversion spec not supported"); - break; - case '\0': - TINYFORMAT_ERROR("tinyformat: Conversion spec incorrectly " - "terminated by end of string"); - return c; - } - if(intConversion && precisionSet && !widthSet) - { - // "precision" for integers gives the minimum number of digits (to be - // padded with zeros on the left). This isn't really supported by the - // iostreams, but we can approximately simulate it with the width if - // the width isn't otherwise used. - out.width(out.precision()); - out.setf(std::ios::internal, std::ios::adjustfield); - out.fill('0'); - } - return c+1; -} - - - -//------------------------------------------------------------------------------ -// Private format function on top of which the public interface is implemented. -// We enforce a mimimum of one value to be formatted to prevent bugs looking like -// -// const char* myStr = "100% broken"; -// printf(myStr); // Parses % as a format specifier -#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES - -template -void format(FormatIterator& fmtIter, const T1& value1) -{ - fmtIter.accept(value1); - fmtIter.finish(); -} - -// General version for C++11 -template -void format(FormatIterator& fmtIter, const T1& value1, const Args&... args) -{ - fmtIter.accept(value1); - format(fmtIter, args...); -} - -#else - -inline void format(FormatIterator& fmtIter) -{ - fmtIter.finish(); -} - -// General version for C++98 -#define TINYFORMAT_MAKE_FORMAT_DETAIL(n) \ -template \ -void format(detail::FormatIterator& fmtIter, TINYFORMAT_VARARGS(n)) \ -{ \ - fmtIter.accept(v1); \ - format(fmtIter TINYFORMAT_PASSARGS_TAIL(n)); \ -} - -TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMAT_DETAIL) -#undef TINYFORMAT_MAKE_FORMAT_DETAIL - -#endif // End C++98 variadic template emulation for format() - -} // namespace detail - - -//------------------------------------------------------------------------------ -// Implement all the main interface functions here in terms of detail::format() - -#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES - -// C++11 - the simple case -template -void format(std::ostream& out, const char* fmt, const T1& v1, const Args&... args) -{ - detail::FormatIterator fmtIter(out, fmt); - format(fmtIter, v1, args...); -} - -template -std::string format(const char* fmt, const T1& v1, const Args&... args) -{ - std::ostringstream oss; - format(oss, fmt, v1, args...); - return oss.str(); -} - -template -void printf(const char* fmt, const T1& v1, const Args&... args) -{ - format(std::cout, fmt, v1, args...); -} - -#else - -// C++98 - define the interface functions using the wrapping macros -#define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \ - \ -template \ -void format(std::ostream& out, const char* fmt, TINYFORMAT_VARARGS(n)) \ -{ \ - tinyformat::detail::FormatIterator fmtIter(out, fmt); \ - tinyformat::detail::format(fmtIter, TINYFORMAT_PASSARGS(n)); \ -} \ - \ -template \ -std::string format(const char* fmt, TINYFORMAT_VARARGS(n)) \ -{ \ - std::ostringstream oss; \ - tinyformat::format(oss, fmt, TINYFORMAT_PASSARGS(n)); \ - return oss.str(); \ -} \ - \ -template \ -void printf(const char* fmt, TINYFORMAT_VARARGS(n)) \ -{ \ - tinyformat::format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \ -} - -TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMAT_FUNCS) -#undef TINYFORMAT_MAKE_FORMAT_FUNCS - -#endif - - -//------------------------------------------------------------------------------ -// Define deprecated wrapping macro for backward compatibility in tinyformat -// 1.x. Will be removed in version 2! -#define TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS -#define TINYFORMAT_WRAP_FORMAT_N(n, returnType, funcName, funcDeclSuffix, \ - bodyPrefix, streamName, bodySuffix) \ -template \ -returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt, \ - TINYFORMAT_VARARGS(n)) funcDeclSuffix \ -{ \ - bodyPrefix \ - tinyformat::format(streamName, fmt, TINYFORMAT_PASSARGS(n)); \ - bodySuffix \ -} \ - -#define TINYFORMAT_WRAP_FORMAT(returnType, funcName, funcDeclSuffix, \ - bodyPrefix, streamName, bodySuffix) \ -inline \ -returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt \ - ) funcDeclSuffix \ -{ \ - bodyPrefix \ - tinyformat::detail::FormatIterator(streamName, fmt).finish(); \ - bodySuffix \ -} \ -TINYFORMAT_WRAP_FORMAT_N(1 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(2 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(3 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(4 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(5 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(6 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(7 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(8 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(9 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(10, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(11, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(12, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(13, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(14, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(15, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(16, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ - - -} // namespace tinyformat - -#endif // TINYFORMAT_H_INCLUDED diff --git a/3rdparty/oiio16/include/OpenImageIO/typedesc.h b/3rdparty/oiio16/include/OpenImageIO/typedesc.h deleted file mode 100644 index 54b6a19f..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/typedesc.h +++ /dev/null @@ -1,361 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -/// \file -/// The TypeDesc class is used to describe simple data types. - - -#ifndef OPENIMAGEIO_TYPEDESC_H -#define OPENIMAGEIO_TYPEDESC_H - -#if defined(_MSC_VER) -// Ignore warnings about conditional expressions that always evaluate true -// on a given platform but may evaluate differently on another. There's -// nothing wrong with such conditionals. -# pragma warning (disable : 4127) -#endif - -#ifndef NULL -#define NULL 0 -#endif - -#include -#include -#include -#include - -#include "export.h" -#include "oiioversion.h" -#include "dassert.h" -#include "string_view.h" - - -OIIO_NAMESPACE_BEGIN - -///////////////////////////////////////////////////////////////////////////// -/// A TypeDesc describes simple data types. -/// -/// It frequently comes up (in my experience, with renderers and image -/// handling programs) that you want a way to describe data that is passed -/// through APIs through blind pointers. These are some simple classes -/// that provide a simple type descriptor system. This is not meant to -/// be comprehensive -- for example, there is no provision for structs, -/// unions, pointers, const, or 'nested' type definitions. Just simple -/// integer and floating point, *common* aggregates such as 3-points, -/// and reasonably-lengthed arrays thereof. -/// -///////////////////////////////////////////////////////////////////////////// - -struct OIIO_API TypeDesc { - /// BASETYPE is a simple enum for the C/C++ built-in types. - /// - enum BASETYPE { UNKNOWN, NONE, - UCHAR, UINT8=UCHAR, CHAR, INT8=CHAR, - USHORT, UINT16=USHORT, SHORT, INT16=SHORT, - UINT, UINT32=UINT, INT, INT32=INT, - ULONGLONG, UINT64=ULONGLONG, LONGLONG, INT64=LONGLONG, - HALF, FLOAT, DOUBLE, STRING, PTR, LASTBASE }; - /// AGGREGATE describes whether our type is a simple scalar of - /// one of the BASETYPE's, or one of several simple aggregates. - enum AGGREGATE { SCALAR=1, VEC2=2, VEC3=3, VEC4=4, MATRIX33=9, MATRIX44=16 }; - /// VECSEMANTICS gives hints about what the data represent (for - /// example, if a spatial vector, whether it should transform as - /// a point, direction vector, or surface normal). - enum VECSEMANTICS { NOXFORM=0, NOSEMANTICS=0, // no semantic hints - COLOR, // color - POINT, // spatial location - VECTOR, // spatial direction - NORMAL, // surface normal - TIMECODE, // SMPTE timecode (should be int[2]) - KEYCODE // SMPTE keycode (should be int[7]) - }; - - unsigned char basetype; ///< C data type at the heart of our type - unsigned char aggregate; ///< What kind of AGGREGATE is it? - unsigned char vecsemantics; ///< What does the vec represent? - unsigned char reserved; ///< Reserved for future expansion - int arraylen; ///< Array length, 0 = not array, -1 = unsized - - /// Construct from a BASETYPE and optional aggregateness and - /// transformation rules. - TypeDesc (BASETYPE btype=UNKNOWN, AGGREGATE agg=SCALAR, - VECSEMANTICS xform=NOXFORM) - : basetype(static_cast(btype)), - aggregate(static_cast(agg)), - vecsemantics(static_cast(xform)), reserved(0), - arraylen(0) - { } - - /// Construct an array of a non-aggregate BASETYPE. - /// - TypeDesc (BASETYPE btype, int arraylength) - : basetype(static_cast(btype)), - aggregate(SCALAR), vecsemantics(NOXFORM), - reserved(0), arraylen(arraylength) - { } - - /// Construct an array from BASETYPE, AGGREGATE, and array length, - /// with unspecified (or moot) vector transformation semantics. - TypeDesc (BASETYPE btype, AGGREGATE agg, int arraylength) - : basetype(static_cast(btype)), - aggregate(static_cast(agg)), - vecsemantics(NOXFORM), reserved(0), - arraylen(arraylength) - { } - - /// Construct an array from BASETYPE, AGGREGATE, VECSEMANTICS, and - /// array length. - TypeDesc (BASETYPE btype, AGGREGATE agg, - VECSEMANTICS xform, int arraylength) - : basetype(static_cast(btype)), - aggregate(static_cast(agg)), - vecsemantics(static_cast(xform)), - reserved(0), arraylen(arraylength) - { } - - /// Construct from a string (e.g., "float[3]"). If no valid - /// type could be assembled, set base to UNKNOWN. - TypeDesc (string_view typestring); - TypeDesc (const char *typestring); // DEPRECATED (1.6) - - /// Copy constructor. - TypeDesc (const TypeDesc &t) - : basetype(t.basetype), aggregate(t.aggregate), - vecsemantics(t.vecsemantics), reserved(0), arraylen(t.arraylen) - { } - - - /// Return the name, for printing and whatnot. For example, - /// "float", "int[5]", "normal" - const char *c_str() const; - - friend std::ostream& operator<< (std::ostream& o, TypeDesc t) { - o << t.c_str(); return o; - } - - /// Return the number of elements: 1 if not an array, or the array - /// length. - size_t numelements () const { - DASSERT_MSG (arraylen >= 0, "Called numelements() on TypeDesc " - "of array with unspecified length (%d)", arraylen); - return (arraylen >= 1 ? arraylen : 1); - } - - /// Does this TypeDesc describe an array? - bool is_array () const { return (arraylen != 0); } - - /// Does this TypeDesc describe an array, but whose length is not - /// specified? - bool is_unsized_array () const { return (arraylen < 0); } - - /// Does this TypeDesc describe an array, whose length is specified? - bool is_sized_array () const { return (arraylen > 0); } - - /// Return the size, in bytes, of this type. - /// - size_t size () const { - DASSERT_MSG (arraylen >= 0, "Called size() on TypeDesc " - "of array with unspecified length (%d)", arraylen); - size_t a = (size_t) (arraylen > 0 ? arraylen : 1); - if (sizeof(size_t) > sizeof(int)) { - // size_t has plenty of room for this multiplication - return a * elementsize(); - } else { - // need overflow protection - unsigned long long s = (unsigned long long) a * elementsize(); - const size_t toobig = std::numeric_limits::max(); - return s < toobig ? (size_t)s : toobig; - } - } - - /// Return the type of one element, i.e., strip out the array-ness. - /// - TypeDesc elementtype () const { - TypeDesc t (*this); t.arraylen = 0; return t; - } - - /// Return the size, in bytes, of one element of this type (that is, - /// ignoring whether it's an array). - size_t elementsize () const { return aggregate * basesize(); } - - // /// Return just the underlying C scalar type, i.e., strip out the - // /// array-ness and the aggregateness. -// BASETYPE basetype () const { return TypeDesc(base); } - - /// Return the base type size, i.e., stripped of both array-ness - /// and aggregateness. - size_t basesize () const; - - /// True if it's a floating-point type (versus a fundamentally - /// integral type or something else like a string). - bool is_floating_point () const; - - /// True if it's a signed type that allows for negative values. - bool is_signed () const; - - /// Set *this to the type described in the string. Return the - /// length of the part of the string that describes the type. If - /// no valid type could be assembled, return 0 and do not modify - /// *this. - size_t fromstring (string_view typestring); - size_t fromstring (const char *typestring); // DEPRECATED (1.6) - - /// Compare two TypeDesc values for equality. - /// - bool operator== (const TypeDesc &t) const { - return basetype == t.basetype && aggregate == t.aggregate && - vecsemantics == t.vecsemantics && arraylen == t.arraylen; - } - - /// Compare two TypeDesc values for inequality. - /// - bool operator!= (const TypeDesc &t) const { return ! (*this == t); } - - /// Compare a TypeDesc to a basetype (it's the same if it has the - /// same base type and is not an aggregate or an array). - friend bool operator== (const TypeDesc &t, BASETYPE b) { - return (BASETYPE)t.basetype == b && (AGGREGATE)t.aggregate == SCALAR && !t.is_array(); - } - friend bool operator== (BASETYPE b, const TypeDesc &t) { - return (BASETYPE)t.basetype == b && (AGGREGATE)t.aggregate == SCALAR && !t.is_array(); - } - - /// Compare a TypeDesc to a basetype (it's the same if it has the - /// same base type and is not an aggregate or an array). - friend bool operator!= (const TypeDesc &t, BASETYPE b) { - return (BASETYPE)t.basetype != b || (AGGREGATE)t.aggregate != SCALAR || t.is_array(); - } - friend bool operator!= (BASETYPE b, const TypeDesc &t) { - return (BASETYPE)t.basetype != b || (AGGREGATE)t.aggregate != SCALAR || t.is_array(); - } - - /// TypeDesc's are equivalent if they are equal, or if their only - /// inequality is differing vector semantics. - friend bool equivalent (const TypeDesc &a, const TypeDesc &b) { - return a.basetype == b.basetype && a.aggregate == b.aggregate && - (a.arraylen == b.arraylen || (a.is_unsized_array() && b.is_sized_array()) - || (a.is_sized_array() && b.is_unsized_array())); - } - /// Member version of equivalent - bool equivalent (const TypeDesc &b) const { - return this->basetype == b.basetype && this->aggregate == b.aggregate && - (this->arraylen == b.arraylen || (this->is_unsized_array() && b.is_sized_array()) - || (this->is_sized_array() && b.is_unsized_array())); - } - - /// Is this a 3-vector aggregate (of the given type, float by default)? - bool is_vec3 (BASETYPE b=FLOAT) const { - return this->aggregate == VEC3 && this->basetype == b && !is_array(); - } - - /// Is this a 3-vector aggregate (of the given type, float by default)? - bool is_vec4 (BASETYPE b=FLOAT) const { - return this->aggregate == VEC4 && this->basetype == b && !is_array(); - } - - /// Demote the type to a non-array - /// - void unarray (void) { arraylen = 0; } - - /// Test for lexicographic 'less', comes in handy for lots of STL - /// containers and algorithms. - bool operator< (const TypeDesc &x) const; - - static const TypeDesc TypeFloat; - static const TypeDesc TypeColor; - static const TypeDesc TypeString; - static const TypeDesc TypeInt; - static const TypeDesc TypeHalf; - static const TypeDesc TypePoint; - static const TypeDesc TypeVector; - static const TypeDesc TypeNormal; - static const TypeDesc TypeMatrix; - static const TypeDesc TypeMatrix33; - static const TypeDesc TypeMatrix44; - static const TypeDesc TypeTimeCode; - static const TypeDesc TypeKeyCode; - static const TypeDesc TypeFloat4; -}; - - - -/// Return a string containing the data values formatted according -/// to the type and the optional formatting arguments. -std::string tostring (TypeDesc type, const void *data, - const char *float_fmt = "%f", // E.g. "%g" - const char *string_fmt = "%s", // E.g. "\"%s\"" - const char aggregate_delim[2] = "()", // Both sides of vector - const char *aggregate_sep = ",", // E.g. ", " - const char array_delim[2] = "{}", // Both sides of array - const char *array_sep = ","); // E.g. "; " - - - -/// A template mechanism for getting the a base type from C type -/// -template struct BaseTypeFromC {}; -template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::UINT8; }; -template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::INT8; }; -template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::UINT16; }; -template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::INT16; }; -template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::UINT; }; -template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::INT; }; -template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::UINT64; }; -template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::INT64; }; -#ifdef _HALF_H_ -template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::HALF; }; -#endif -template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::FLOAT; }; -template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::DOUBLE; }; - - - -/// A template mechanism for getting C type of TypeDesc::BASETYPE. -/// -template struct CType {}; -template<> struct CType<(int)TypeDesc::UINT8> { typedef unsigned char type; }; -template<> struct CType<(int)TypeDesc::INT8> { typedef char type; }; -template<> struct CType<(int)TypeDesc::UINT16> { typedef unsigned short type; }; -template<> struct CType<(int)TypeDesc::INT16> { typedef short type; }; -template<> struct CType<(int)TypeDesc::UINT> { typedef unsigned int type; }; -template<> struct CType<(int)TypeDesc::INT> { typedef int type; }; -template<> struct CType<(int)TypeDesc::UINT64> { typedef unsigned long long type; }; -template<> struct CType<(int)TypeDesc::INT64> { typedef long long type; }; -#ifdef _HALF_H_ -template<> struct CType<(int)TypeDesc::HALF> { typedef half type; }; -#endif -template<> struct CType<(int)TypeDesc::FLOAT> { typedef float type; }; -template<> struct CType<(int)TypeDesc::DOUBLE> { typedef double type; }; - - -OIIO_NAMESPACE_END - -#endif /* !defined(OPENIMAGEIO_TYPEDESC_H) */ diff --git a/3rdparty/oiio16/include/OpenImageIO/unittest.h b/3rdparty/oiio16/include/OpenImageIO/unittest.h deleted file mode 100644 index 53abbae2..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/unittest.h +++ /dev/null @@ -1,102 +0,0 @@ - /* - Copyright 2010 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - -#ifndef OPENIMAGEIO_UNITTEST_H -#define OPENIMAGEIO_UNITTEST_H - -#include - - -static int unit_test_failures = 0; - -/// OIIO_CHECK_* macros checks if the conditions is met, and if not, -/// prints an error message indicating the module and line where the -/// error occurred, but does NOT abort. This is helpful for unit tests -/// where we do not want one failure. -#define OIIO_CHECK_ASSERT(x) \ - ((x) ? ((void)0) \ - : ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \ - << "FAILED: " << #x << "\n"), \ - (void)++unit_test_failures)) - -#define OIIO_CHECK_EQUAL(x,y) \ - (((x) == (y)) ? ((void)0) \ - : ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \ - << "FAILED: " << #x << " == " << #y << "\n" \ - << "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \ - (void)++unit_test_failures)) - -#define OIIO_CHECK_EQUAL_THRESH(x,y,eps) \ - ((std::abs((x)-(y)) <= eps) ? ((void)0) \ - : ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \ - << "FAILED: " << #x << " == " << #y << "\n" \ - << "\tvalues were '" << (x) << "' and '" << (y) << "'" \ - << ", diff was " << std::abs((x)-(y)) << "\n"), \ - (void)++unit_test_failures)) - -#define OIIO_CHECK_NE(x,y) \ - (((x) != (y)) ? ((void)0) \ - : ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \ - << "FAILED: " << #x << " != " << #y << "\n" \ - << "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \ - (void)++unit_test_failures)) - -#define OIIO_CHECK_LT(x,y) \ - (((x) < (y)) ? ((void)0) \ - : ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \ - << "FAILED: " << #x << " < " << #y << "\n" \ - << "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \ - (void)++unit_test_failures)) - -#define OIIO_CHECK_GT(x,y) \ - (((x) > (y)) ? ((void)0) \ - : ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \ - << "FAILED: " << #x << " > " << #y << "\n" \ - << "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \ - (void)++unit_test_failures)) - -#define OIIO_CHECK_LE(x,y) \ - (((x) <= (y)) ? ((void)0) \ - : ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \ - << "FAILED: " << #x << " <= " << #y << "\n" \ - << "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \ - (void)++unit_test_failures)) - -#define OIIO_CHECK_GE(x,y) \ - (((x) >= (y)) ? ((void)0) \ - : ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \ - << "FAILED: " << #x << " >= " << #y << "\n" \ - << "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \ - (void)++unit_test_failures)) - - - -#endif /* OPENIMAGEIO_UNITTEST_H */ - diff --git a/3rdparty/oiio16/include/OpenImageIO/unordered_map_concurrent.h b/3rdparty/oiio16/include/OpenImageIO/unordered_map_concurrent.h deleted file mode 100644 index 33eb521d..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/unordered_map_concurrent.h +++ /dev/null @@ -1,436 +0,0 @@ -/* -Copyright 2012 Larry Gritz and the other authors and contributors. -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. -* Neither the name of the software's owners nor the names of its - contributors may 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. - -(This is the Modified BSD License) -*/ - - -#pragma once - -#ifndef OPENIMAGEIO_UNORDERED_MAP_CONCURRENT_H -#define OPENIMAGEIO_UNORDERED_MAP_CONCURRENT_H - -#include -#include -#include - -#if OIIO_CPLUSPLUS_VERSION >= 11 -# include -#else /* FIXME(C++11): remove this after making C++11 the baseline */ -# include -#endif - -OIIO_NAMESPACE_BEGIN - - -// Define OIIO::unordered_map as either std or boost. -#if OIIO_CPLUSPLUS_VERSION >= 11 -using std::unordered_map; -#else /* FIXME(C++11): remove this after making C++11 the baseline */ -using boost::unordered_map; -#endif - - -/// unordered_map_concurrent provides an unordered_map replacement that -/// is optimized for concurrent access. Its principle of operation is -/// similar to Java's ConcurrentHashMap. -/// -/// With naive use of an unordered_map, multiple threads would have to -/// lock a mutex of some kind to control access to the map, either with -/// a unique full lock, or with a reader/writer lock. But as the number -/// of threads contending for this shared resource rises, they end up -/// locking each other out and the map becomes a thread bottleneck. -/// -/// unordered_map_concurrent solves this problem by internally splitting -/// the hash map into several disjoint bins, each of which is a standard -/// unordered_map. For any given map item, the hash of its key -/// determines both the bin as well as its hashing within the bin (i.e., -/// we break a big hash map into lots of little hash maps, -/// deterministically determined by the key). Thus, we should expect -/// map entries to be spread more or less evenly among the bins. There -/// is no mutex that locks the map as a whole; instead, each bin is -/// locked individually. If the number of bins is larger than the -/// typical number of threads, most of the time two (or more) threads -/// accessing the map simultaneously will not be accessing the same bin, -/// and therefore will not be contending for the same lock. -/// -/// unordered_map_concurrent provides an iterator which points to an -/// entry in the map and also knows which bin it is in and implicitly -/// holds a lock on the bin. When the iterator is destroyed, the lock -/// on that bin is released. When the iterator is incremented in such a -/// way that it transitions from the last entry of its current bin to -/// the first entry of the next bin, it will also release its current -/// lock and obtain a lock on the next bin. -/// - -template, - class PRED=std::equal_to, size_t BINS=16, - class BINMAP=unordered_map > -class unordered_map_concurrent { -public: - typedef BINMAP BinMap_t; - typedef typename BINMAP::iterator BinMap_iterator_t; - -public: - unordered_map_concurrent () { m_size = 0; } - - ~unordered_map_concurrent () { -// for (size_t i = 0; i < BINS; ++i) -// std::cout << "Bin " << i << ": " << m_bins[i].map.size() << "\n"; - } - - /// An unordered_map_concurrent::iterator points to a specific entry - /// in the umc, and holds a lock to the bin the entry is in. - class iterator { - public: - friend class unordered_map_concurrent; - public: - /// Construct an unordered_map_concurrent iterator that points - /// to nothing. - iterator (unordered_map_concurrent *umc = NULL) - : m_umc(umc), m_bin(-1), m_locked(false) { } - - /// Copy constructor of an unordered_map_concurrent iterator - /// transfers the lock (if held) to this. Caveat: the copied - /// iterator no longer holds the lock! - iterator (const iterator &src) { - m_umc = src.m_umc; - m_bin = src.m_bin; - m_biniterator = src.m_biniterator; - m_locked = src.m_locked; - // assignment transfers lock ownership - *(const_cast(&src.m_locked)) = false; - } - - /// Destroying an unordered_map_concurrent iterator releases any - /// bin locks it held. - ~iterator () { clear(); } - - /// Totally invalidate this iterator -- point it to nothing - /// (releasing any locks it may have had). - void clear () { - if (m_umc) { - unbin (); - m_umc = NULL; - } - } - - // Dereferencing returns a reference to the hash table entry the - // iterator refers to. - typename BinMap_t::value_type & operator* () { - return *m_biniterator; - } - - /// Dereferencing returns a reference to the hash table entry the - /// iterator refers to. - typename BinMap_t::value_type * operator-> () { - return &(*m_biniterator); - } - - /// Treating an iterator as a bool yields true if it points to a - /// valid element of one of the bins of the map, false if it's - /// equivalent to the end() iterator. - operator bool() { - return m_umc && m_bin >= 0 && - m_biniterator != m_umc->m_bins[m_bin].map.end(); - } - - /// Iterator assignment transfers ownership of any bin locks - /// held by the operand. - iterator& operator= (const iterator &src) { - unbin(); - m_umc = src.m_umc; - m_bin = src.m_bin; - m_biniterator = src.m_biniterator; - m_locked = src.m_locked; - // assignment transfers lock ownership - *(const_cast(&src.m_locked)) = false; - return *this; - } - - bool operator== (const iterator &other) const { - if (m_umc != other.m_umc) - return false; - if (m_bin == -1 && other.m_bin == -1) - return true; - return m_bin == other.m_bin && - m_biniterator == other.m_biniterator; - } - bool operator!= (const iterator &other) { - return ! (*this == other); - } - - /// Increment to the next entry in the map. If we finish the - /// bin we're in, move on to the next bin (releasing our lock on - /// the old bin and acquiring a lock on the new bin). If we - /// finish the last bin of the map, return the end() iterator. - void operator++ () { - DASSERT (m_umc); - DASSERT (m_bin >= 0); - ++m_biniterator; - while (m_biniterator == m_umc->m_bins[m_bin].map.end()) { - if (m_bin == BINS-1) { - // ran off the end - unbin(); - return; - } - rebin (m_bin+1); - } - } - void operator++ (int) { ++(*this); } - - /// Lock the bin we point to, if not already locked. - void lock () { - if (m_bin >= 0 && !m_locked) { - m_umc->m_bins[m_bin].lock(); - m_locked = true; - } - } - /// Unlock the bin we point to, if locked. - void unlock () { - if (m_bin >= 0 && m_locked) { - m_umc->m_bins[m_bin].unlock(); - m_locked = false; - } - } - - /// Without changing the lock status (i.e., the caller already - /// holds the lock on the iterator's bin), increment to the next - /// element within the bin. Return true if it's pointing to a - /// valid element afterwards, false if it ran off the end of the - /// bin contents. - bool incr_no_lock () { - ++m_biniterator; - return (m_biniterator != m_umc->m_bins[m_bin].map.end()); - } - - private: - // No longer refer to a particular bin, release lock on the bin - // it had (if any). - void unbin () { - if (m_bin >= 0) { - if (m_locked) - unlock (); - m_bin = -1; - } - } - - // Point this iterator to a different bin, releasing locks on - // the bin it previously referred to. - void rebin (int newbin) { - DASSERT (m_umc); - unbin (); - m_bin = newbin; - lock (); - m_biniterator = m_umc->m_bins[m_bin].map.begin(); - } - - unordered_map_concurrent *m_umc; // which umc this iterator refers to - int m_bin; // which bin within the umc - BinMap_iterator_t m_biniterator; // which entry within the bin - bool m_locked; // do we own the lock on the bin? - }; - - - /// Return an interator pointing to the first entry in the map. - iterator begin () { - iterator i (this); - i.rebin (0); - while (i.m_biniterator == m_bins[i.m_bin].map.end()) { - if (i.m_bin == BINS-1) { - // ran off the end - i.unbin(); - return i; - } - i.rebin (i.m_bin+1); - } - return i; - } - - /// Return an iterator signifying the end of the map (no valid - /// entry pointed to). - iterator end () { - iterator i (this); - return i; - } - - /// Search for key. If found, return an iterator referring to the - /// element, otherwise, return an iterator that is equivalent to - /// this->end(). If do_lock is true, lock the bin that we're - /// searching and return the iterator in a locked state, and unlock - /// the bin again if not found; however, if do_lock is false, assume - /// that the caller already has the bin locked, so do no locking or - /// unlocking and return an iterator that is unaware that it holds a - /// lock. - iterator find (const KEY &key, bool do_lock = true) { - size_t b = whichbin(key); - Bin &bin (m_bins[b]); - if (do_lock) - bin.lock (); - typename BinMap_t::iterator it = bin.map.find (key); - if (it == bin.map.end()) { - // not found -- return the 'end' iterator - if (do_lock) - bin.unlock(); - return end(); - } - // Found - iterator i (this); - i.m_bin = (unsigned) b; - i.m_biniterator = it; - i.m_locked = do_lock; - return i; - } - - /// Search for key. If found, return true and store the value. If not - /// found, return false and do not alter value. If do_lock is true, - /// read-lock the bin while we're searching, and release it before - /// returning; however, if do_lock is false, assume that the caller - /// already has the bin locked, so do no locking or unlocking. - bool retrieve (const KEY &key, VALUE &value, bool do_lock = true) { - size_t b = whichbin(key); - Bin &bin (m_bins[b]); - if (do_lock) - bin.lock (); - typename BinMap_t::iterator it = bin.map.find (key); - bool found = (it != bin.map.end()); - if (found) - value = it->second; - if (do_lock) - bin.unlock(); - return found; - } - - /// Insert into the hash map if it's not already there. - /// Return true if added, false if it was already present. - /// If do_lock is true, lock the bin containing key while doing this - /// operation; if do_lock is false, assume that the caller already - /// has the bin locked, so do no locking or unlocking. - bool insert (const KEY &key, const VALUE &value, - bool do_lock = true) { - size_t b = whichbin(key); - Bin &bin (m_bins[b]); - if (do_lock) - bin.lock (); - bool add = (bin.map.find (key) == bin.map.end()); - if (add) { - // not found -- add it! - bin.map[key] = value; - ++m_size; - } - if (do_lock) - bin.unlock(); - return add; - } - - /// If the key is in the map, safely erase it. - /// If do_lock is true, lock the bin containing key while doing this - /// operation; if do_lock is false, assume that the caller already - /// has the bin locked, so do no locking or unlocking. - void erase (const KEY &key, bool do_lock = true) { - size_t b = whichbin(key); - Bin &bin (m_bins[b]); - if (do_lock) - bin.lock (); - typename BinMap_t::iterator it = bin.map.find (key); - if (it != bin.map.end()) { - bin.map.erase (it); - } - if (do_lock) - bin.unlock(); - } - - /// Return true if the entire map is empty. - bool empty() { return m_size == 0; } - - /// Expliticly lock the bin that will contain the key (regardless of - /// whether there is such an entry in the map), and return its bin - /// number. - size_t lock_bin (const KEY &key) { - size_t b = whichbin(key); - m_bins[b].lock (); - return b; - } - - /// Explicitly unlock the specified bin (this assumes that the caller - /// holds the lock). - void unlock_bin (size_t bin) { - m_bins[bin].unlock (); - } - -private: - struct Bin { - OIIO_CACHE_ALIGN // align bin to cache line - mutable spin_mutex mutex; // mutex for this bin - BinMap_t map; // hash map for this bin -#ifndef NDEBUG - mutable atomic_int m_nlocks; // for debugging -#endif - - Bin () { -#ifndef NDEBUG - m_nlocks = 0; -#endif - } - ~Bin () { -#ifndef NDEBUG - DASSERT (m_nlocks == 0); -#endif - } - void lock () const { - mutex.lock(); -#ifndef NDEBUG - ++m_nlocks; - DASSERT_MSG (m_nlocks == 1, "oops, m_nlocks = %d", (int)m_nlocks); -#endif - } - void unlock () const { -#ifndef NDEBUG - DASSERT_MSG (m_nlocks == 1, "oops, m_nlocks = %d", (int)m_nlocks); - --m_nlocks; -#endif - mutex.unlock(); - } - }; - - HASH m_hash; // hashing function - atomic_int m_size; // total entries in all bins - Bin m_bins[BINS]; // the bins - - // Which bin will this key always appear in? - size_t whichbin (const KEY &key) { - size_t h = m_hash(key); - h = (size_t) murmur::fmix (uint64_t(h)); // scramble again - return h % BINS; - } - -}; - - -OIIO_NAMESPACE_END - -#endif // OPENIMAGEIO_UNORDERED_MAP_CONCURRENT_H diff --git a/3rdparty/oiio16/include/OpenImageIO/ustring.h b/3rdparty/oiio16/include/OpenImageIO/ustring.h deleted file mode 100644 index e9a44caa..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/ustring.h +++ /dev/null @@ -1,756 +0,0 @@ -/* - Copyright 2008 Larry Gritz and the other authors and contributors. - 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. - * Neither the name of the software's owners nor the names of its - contributors may 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. - - (This is the Modified BSD License) -*/ - - -/// \file -/// Define the ustring class, unique strings with efficient storage and -/// very fast copy and comparison. - - -///////////////////////////////////////////////////////////////////////////// -/// \class ustring -/// -/// A ustring is an alternative to char* or std::string for storing -/// strings, in which the character sequence is unique (allowing many -/// speed advantages for assignment, equality testing, and inequality -/// testing). -/// -/// The implementation is that behind the scenes there is a hash set of -/// allocated strings, so the characters of each string are unique. A -/// ustring itself is a pointer to the characters of one of these canonical -/// strings. Therefore, assignment and equality testing is just a single -/// 32- or 64-bit int operation, the only mutex is when a ustring is -/// created from raw characters, and the only malloc is the first time -/// each canonical ustring is created. -/// -/// The internal table also contains a std::string version and the length -/// of the string, so converting a ustring to a std::string (via -/// ustring::string()) or querying the number of characters (via -/// ustring::size() or ustring::length()) is extremely inexpensive, and does -/// not involve creation/allocation of a new std::string or a call to -/// strlen. -/// -/// We try very hard to completely mimic the API of std::string, -/// including all the constructors, comparisons, iterations, etc. Of -/// course, the charaters of a ustring are non-modifiable, so we do not -/// replicate any of the non-const methods of std::string. But in most -/// other ways it looks and acts like a std::string and so most templated -/// algorthms that would work on a "const std::string &" will also work -/// on a ustring. -/// -/// Usage guidelines: -/// -/// Compared to standard strings, ustrings have several advantages: -/// -/// - Each individual ustring is very small -- in fact, we guarantee that -/// a ustring is the same size and memory layout as an ordinary char*. -/// - Storage is frugal, since there is only one allocated copy of each -/// unique character sequence, throughout the lifetime of the program. -/// - Assignment from one ustring to another is just copy of the pointer; -/// no allocation, no character copying, no reference counting. -/// - Equality testing (do the strings contain the same characters) is -/// a single operation, the comparison of the pointer. -/// - Memory allocation only occurs when a new ustring is construted from -/// raw characters the FIRST time -- subsequent constructions of the -/// same string just finds it in the canonial string set, but doesn't -/// need to allocate new storage. Destruction of a ustring is trivial, -/// there is no de-allocation because the canonical version stays in -/// the set. Also, therefore, no user code mistake can lead to -/// memory leaks. -/// -/// But there are some problems, too. Canonical strings are never freed -/// from the table. So in some sense all the strings "leak", but they -/// only leak one copy for each unique string that the program ever comes -/// across. Also, creation of unique strings from raw characters is more -/// expensive than for standard strings, due to hashing, table queries, -/// and other overhead. -/// -/// On the whole, ustrings are a really great string representation -/// - if you tend to have (relatively) few unique strings, but many -/// copies of those strings; -/// - if the creation of strings from raw characters is relatively -/// rare compared to copying or comparing to existing strings; -/// - if you tend to make the same strings over and over again, and -/// if it's relatively rare that a single unique character sequence -/// is used only once in the entire lifetime of the program; -/// - if your most common string operations are assignment and equality -/// testing and you want them to be as fast as possible; -/// - if you are doing relatively little character-by-character assembly -/// of strings, string concatenation, or other "string manipulation" -/// (other than equality testing). -/// -/// ustrings are not so hot -/// - if your program tends to have very few copies of each character -/// sequence over the entire lifetime of the program; -/// - if your program tends to generate a huge variety of unique -/// strings over its lifetime, each of which is used only a short -/// time and then discarded, never to be needed again; -/// - if you don't need to do a lot of string assignment or equality -/// testing, but lots of more complex string manipulation. -/// -///////////////////////////////////////////////////////////////////////////// - - -#ifndef OPENIMAGEIO_USTRING_H -#define OPENIMAGEIO_USTRING_H - -#if defined(_MSC_VER) -// Ignore warnings about DLL exported classes with member variables that are template classes. -// This happens with the std::string empty_std_string static member variable of ustring below. -// Also remove a warning about the strncpy function not being safe and deprecated in MSVC. -// There is no equivalent safe and portable function and trying to fix this is more trouble than -// its worth. (see http://stackoverflow.com/questions/858252/alternatives-to-ms-strncpy-s) -# pragma warning (disable : 4251 4996) -#endif - -#include -#include -#include -#include "export.h" -#include "strutil.h" -#include "string_view.h" -#include "dassert.h" -#include "oiioversion.h" - -#ifndef NULL -#define NULL 0 -#endif - -OIIO_NAMESPACE_BEGIN - -class OIIO_API ustring { -public: - typedef char value_type; - typedef value_type * pointer; - typedef value_type & reference; - typedef const value_type & const_reference; - typedef size_t size_type; - static const size_type npos = static_cast(-1); - typedef std::string::const_iterator const_iterator; - typedef std::string::const_reverse_iterator const_reverse_iterator; - - /// Default ctr for ustring -- make an empty string. - /// - ustring (void) : m_chars(NULL) { } - - /// Construct a ustring from a null-terminated C string (char *). - /// - explicit ustring (const char *str) { - m_chars = str ? make_unique(str) : NULL; - } - - /// Construct a ustring from a string_view, which can be auto-converted - /// from either a null-terminated C string (char *) or a C++ - /// std::string. - explicit ustring (string_view str) { - m_chars = str.data() ? make_unique(str) : NULL; - } - - /// Construct a ustring from at most n characters of str, starting at - /// position pos. - ustring (const char *str, size_type pos, size_type n) - : m_chars (make_unique(std::string(str,pos,n).c_str())) { } - - /// Construct a ustring from the first n characters of str. - /// - ustring (const char *str, size_type n) - : m_chars (make_unique(string_view(str,n))) { } - - /// Construct a ustring from n copies of character c. - /// - ustring (size_type n, char c) - : m_chars (make_unique(std::string(n,c).c_str())) { } - - /// Construct a ustring from an indexed substring of a std::string. - /// - ustring (const std::string &str, size_type pos, size_type n=npos) { - string_view sref(str); - sref = sref.substr (pos, n); - m_chars = make_unique(sref); - } - - /// Copy construct a ustring from another ustring. - /// - ustring (const ustring &str) : m_chars(str.m_chars) { } - - /// Construct a ustring from an indexed substring of a ustring. - /// - ustring (const ustring &str, size_type pos, size_type n=npos) { - string_view sref(str); - sref = sref.substr (pos, n); - m_chars = make_unique(sref); - } - - /// ustring destructor. - /// - ~ustring () { } - - /// Conversion to string_view - operator string_view() const { return string_view(c_str(), length()); } - - /// Assign a ustring to *this. - /// - const ustring & assign (const ustring &str) { - m_chars = str.m_chars; - return *this; - } - - /// Assign a substring of a ustring to *this. - /// - const ustring & assign (const ustring &str, size_type pos, size_type n=npos) - { *this = ustring(str,pos,n); return *this; } - - /// Assign a std::string to *this. - /// - const ustring & assign (const std::string &str) { - assign (str.c_str()); - return *this; - } - - /// Assign a substring of a std::string to *this. - /// - const ustring & assign (const std::string &str, size_type pos, - size_type n=npos) - { *this = ustring(str,pos,n); return *this; } - - /// Assign a null-terminated C string (char*) to *this. - /// - const ustring & assign (const char *str) { - m_chars = str ? make_unique(str) : NULL; - return *this; - } - - /// Assign the first n characters of str to *this. - /// - const ustring & assign (const char *str, size_type n) - { *this = ustring(str,n); return *this; } - - /// Assign n copies of c to *this. - /// - const ustring & assign (size_type n, char c) - { *this = ustring(n,c); return *this; } - - /// Assign a string_view to *this. - const ustring & assign (string_view str) { - m_chars = str.length() ? make_unique(str) : NULL; - return *this; - } - - /// Assign a ustring to another ustring. - /// - const ustring & operator= (const ustring &str) { return assign(str); } - - /// Assign a null-terminated C string (char *) to a ustring. - /// - const ustring & operator= (const char *str) { return assign(str); } - - /// Assign a C++ std::string to a ustring. - /// - const ustring & operator= (const std::string &str) { return assign(str); } - - /// Assign a string_view to a ustring. - /// - const ustring & operator= (string_view str) { return assign(str); } - - /// Assign a single char to a ustring. - /// - const ustring & operator= (char c) { - char s[2]; - s[0] = c; s[1] = 0; - *this = ustring (s); - return *this; - } - - /// Return a C string representation of a ustring. - /// - const char *c_str () const { - return m_chars; - } - - /// Return a C string representation of a ustring. - /// - const char *data () const { return c_str(); } - - /// Return a C++ std::string representation of a ustring. - /// - const std::string & string () const { - if (m_chars) { - const TableRep *rep = (const TableRep *)m_chars - 1; - return rep->str; - } - else return empty_std_string; - } - - /// Reset to an empty string. - /// - void clear (void) { - m_chars = NULL; - } - - /// Return the number of characters in the string. - /// - size_t length (void) const { - if (! m_chars) - return 0; - const TableRep *rep = ((const TableRep *)m_chars) - 1; - return rep->length; - } - - /// Return a hashed version of the string - /// - size_t hash (void) const { - if (! m_chars) - return 0; - const TableRep *rep = ((const TableRep *)m_chars) - 1; - return rep->hashed; - } - - /// Return the number of characters in the string. - /// - size_t size (void) const { return length(); } - - /// Is the string empty -- i.e., is it the NULL pointer or does it - /// point to an empty string? - bool empty (void) const { return (size() == 0); } - - /// Cast to int, which is interpreted as testing whether it's not an - /// empty string. This allows you to write "if (t)" with the same - /// semantics as if it were a char*. - operator int (void) const { return !empty(); } - - /// Return a const_iterator that references the first character of - /// the string. - const_iterator begin () const { return string().begin(); } - - /// Return a const_iterator that references the end of a traversal - /// of the characters of the string. - const_iterator end () const { return string().end(); } - - /// Return a const_reverse_iterator that references the last - /// character of the string. - const_reverse_iterator rbegin () const { return string().rbegin(); } - - /// Return a const_reverse_iterator that references the end of - /// a reverse traversal of the characters of the string. - const_reverse_iterator rend () const { return string().rend(); } - - /// Return a reference to the character at the given position. - /// Note that it's up to the caller to be sure pos is within the - /// size of the string. - const_reference operator[] (size_type pos) const { return c_str()[pos]; } - - /// Dump into character array s the characters of this ustring, - /// beginning with position pos and copying at most n characters. - size_type copy (char* s, size_type n, size_type pos = 0) const { - if (m_chars == NULL) { - s[0] = 0; - return 0; - } - char *c = strncpy (s, c_str()+pos, n); - return (size_type)(c-s); - } - - /// Returns a substring of the ustring object consisting of n - /// characters starting at position pos. - ustring substr (size_type pos = 0, size_type n = npos) const { - return ustring (*this, pos, n); - } - - // FIXME: implement compare. - - size_type find(const ustring &str, size_type pos = 0) const { - return string().find(str.string(), pos); - } - - size_type find(const std::string &str, size_type pos = 0) const { - return string().find(str, pos); - } - - size_type find(const char *s, size_type pos, size_type n) const { - return string().find(s, pos, n); - } - - size_type find(const char *s, size_type pos = 0) const { - return string().find(s, pos); - } - - size_type find(char c, size_type pos = 0) const { - return string().find(c, pos); - } - - size_type rfind(const ustring &str, size_type pos = npos) const { - return string().rfind(str.string(), pos); - } - - size_type rfind(const std::string &str, size_type pos = npos) const { - return string().rfind(str, pos); - } - - size_type rfind(const char *s, size_type pos, size_type n) const { - return string().rfind(s, pos, n); - } - - size_type rfind(const char *s, size_type pos = npos) const { - return string().rfind(s, pos); - } - - size_type rfind(char c, size_type pos = npos) const { - return string().rfind(c, pos); - } - - size_type find_first_of(const ustring &str, size_type pos = 0) const { - return string().find_first_of(str.string(), pos); - } - - size_type find_first_of(const std::string &str, size_type pos = 0) const { - return string().find_first_of(str, pos); - } - - size_type find_first_of(const char *s, size_type pos, size_type n) const { - return string().find_first_of(s, pos, n); - } - - size_type find_first_of(const char *s, size_type pos = 0) const { - return string().find_first_of(s, pos); - } - - size_type find_first_of(char c, size_type pos = 0) const { - return string().find_first_of(c, pos); - } - - size_type find_last_of(const ustring &str, size_type pos = npos) const { - return string().find_last_of(str.string(), pos); - } - - size_type find_last_of(const std::string &str, size_type pos = npos) const { - return string().find_last_of(str, pos); - } - - size_type find_last_of(const char *s, size_type pos, size_type n) const { - return string().find_last_of(s, pos, n); - } - - size_type find_last_of(const char *s, size_type pos = npos) const { - return string().find_last_of(s, pos); - } - - size_type find_last_of(char c, size_type pos = npos) const { - return string().find_last_of(c, pos); - } - - size_type find_first_not_of(const ustring &str, size_type pos = 0) const { - return string().find_first_not_of(str.string(), pos); - } - - size_type find_first_not_of(const std::string &str, size_type pos = 0) const { - return string().find_first_not_of(str, pos); - } - - size_type find_first_not_of(const char *s, size_type pos, size_type n) const { - return string().find_first_not_of(s, pos, n); - } - - size_type find_first_not_of(const char *s, size_type pos = 0) const { - return string().find_first_not_of(s, pos); - } - - size_type find_first_not_of(char c, size_type pos = 0) const { - return string().find_first_not_of(c, pos); - } - - size_type find_last_not_of(const ustring &str, size_type pos = npos) const { - return string().find_last_not_of(str.string(), pos); - } - - size_type find_last_not_of(const std::string &str, size_type pos = npos) const { - return string().find_last_not_of(str, pos); - } - - size_type find_last_not_of(const char *s, size_type pos, size_type n) const { - return string().find_last_not_of(s, pos, n); - } - - size_type find_last_not_of(const char *s, size_type pos = npos) const { - return string().find_last_not_of(s, pos); - } - - size_type find_last_not_of(char c, size_type pos = npos) const { - return string().find_last_not_of(c, pos); - } - - /// Return 0 if *this is lexicographically equal to str, -1 if - /// *this is lexicographically earlier than str, 1 if *this is - /// lexicographically after str. - - int compare (const ustring& str) const { - return (c_str() == str.c_str()) ? 0 - : strcmp (c_str() ? c_str() : "", str.c_str() ? str.c_str() : ""); - } - - /// Return 0 if *this is lexicographically equal to str, -1 if - /// *this is lexicographically earlier than str, 1 if *this is - /// lexicographically after str. - int compare (const std::string& str) const { - return strcmp (c_str() ? c_str() : "", str.c_str()); - } - - /// Return 0 if *this is lexicographically equal to str, -1 if - /// *this is lexicographically earlier than str, 1 if *this is - /// lexicographically after str. - int compare (string_view str) const { - return strncmp (c_str() ? c_str() : "", - str.data() ? str.data() : "", str.length()); - } - - /// Return 0 if *this is lexicographically equal to str, -1 if - /// *this is lexicographically earlier than str, 1 if *this is - /// lexicographically after str. - int compare (const char *str) const { - return strcmp (c_str() ? c_str() : "", str ? str : ""); - } - - /// Return 0 if a is lexicographically equal to b, -1 if a is - /// lexicographically earlier than b, 1 if a is lexicographically - /// after b. - friend int compare (const std::string& a, const ustring &b) { - return strcmp (a.c_str(), b.c_str() ? b.c_str() : ""); - } - - /// Test two ustrings for equality -- are they comprised of the same - /// sequence of characters. Note that because ustrings are unique, - /// this is a trivial pointer comparison, not a char-by-char loop as - /// would be the case with a char* or a std::string. - bool operator== (const ustring &str) const { - return c_str() == str.c_str(); - } - - /// Test two ustrings for inequality -- are they comprised of different - /// sequences of characters. Note that because ustrings are unique, - /// this is a trivial pointer comparison, not a char-by-char loop as - /// would be the case with a char* or a std::string. - bool operator!= (const ustring &str) const { - return c_str() != str.c_str(); - } - - /// Test a ustring (*this) for lexicographic equality with std::string - /// x. - bool operator== (const std::string &x) const { return compare(x) == 0; } - - /// Test a ustring (*this) for lexicographic equality with string_view - /// x. - bool operator== (string_view x) const { return compare(x) == 0; } - - /// Test a ustring (*this) for lexicographic equality with char* x. - bool operator== (const char *x) const { return compare(x) == 0; } - - /// Test for lexicographic equality between std::string a and ustring - /// b. - friend bool operator== (const std::string &a, const ustring &b) { - return b.compare(a) == 0; - } - - /// Test for lexicographic equality between string_view a and ustring - /// b. - friend bool operator== (string_view a, const ustring &b) { - return b.compare(a) == 0; - } - - /// Test for lexicographic equality between char* a and ustring - /// b. - friend bool operator== (const char *a, const ustring &b) { - return b.compare(a) == 0; - } - - /// Test a ustring (*this) for lexicographic inequality with - /// std::string x. - bool operator!= (const std::string &x) const { return compare(x) != 0; } - - /// Test a ustring (*this) for lexicographic inequality with - /// string_view x. - bool operator!= (string_view x) const { return compare(x) != 0; } - - /// Test a ustring (*this) for lexicographic inequality with - /// char* x. - bool operator!= (const char *x) const { return compare(x) != 0; } - - /// Test for lexicographic inequality between std::string a and - /// ustring b. - friend bool operator!= (const std::string &a, const ustring &b) { - return b.compare(a) != 0; - } - - /// Test for lexicographic inequality between string_view a and - /// ustring b. - friend bool operator!= (string_view a, const ustring &b) { - return b.compare(a) != 0; - } - - /// Test for lexicographic inequality between char* a and - /// ustring b. - friend bool operator!= (const char *a, const ustring &b) { - return b.compare(a) != 0; - } - - /// Test for lexicographic 'less', comes in handy for lots of STL - /// containers and algorithms. - bool operator< (const ustring &x) const { return compare(x) < 0; } - - /// Construct a ustring in a printf-like fashion. In other words, - /// something like: - /// ustring s = ustring::format ("blah %d %g", (int)foo, (float)bar); - /// - /// The printf argument list is fully typesafe via tinyformat; format - /// conceptually has the signature - /// - /// static ustring format (const char *fmt, ...); - TINYFORMAT_WRAP_FORMAT (static ustring, format, /**/, - std::ostringstream msg;, msg, return ustring(msg.str());) - - /// Generic stream output of a ustring. - /// - friend std::ostream & operator<< (std::ostream &out, const ustring &str) { - if (str.c_str() && out.good()) - out.write (str.c_str(), str.size()); - return out; - } - - /// Return the statistics output as a string. - /// - static std::string getstats (bool verbose = true); - - /// Return the amount of memory consumed by the ustring table. - /// - static size_t memory (); - - /// Given a string_view, return a pointer to the unique - /// version kept in the internal table (creating a new table entry - /// if we haven't seen this sequence of characters before). - /// N.B.: this is equivalent to ustring(str).c_str(). It's also the - /// routine that is used directly by ustring's internals to generate - /// the canonical unique copy of the characters. - static const char * make_unique (string_view str); - - /// Is this character pointer a unique ustring representation of - /// those characters? Useful for diagnostics and debugging. - static bool is_unique (const char *str) { - return str == NULL || make_unique(str) == str; - } - - /// Create a ustring from characters guaranteed to already be - /// ustring-clean, without having to run through the hash yet - /// again. Use with extreme caution!!! - static ustring from_unique (const char *unique) { - DASSERT (is_unique(unique)); // DEBUG builds -- check it! - ustring u; - u.m_chars = unique; - return u; - } - -private: - - // Individual ustring internal representation -- the unique characters. - // - const char *m_chars; - -public: - // Representation within the hidden string table -- DON'T EVER CREATE - // ONE OF THESE YOURSELF! - // The characters are found directly after the rep. So that means that - // if you know the rep, the chars are at (char *)(rep+1), and if you - // know the chars, the rep is at ((TableRep *)chars - 1). - struct TableRep { - size_t hashed; // precomputed Hash value - std::string str; // String representation - size_t length; // Length of the string; must be right before cap - size_t dummy_capacity; // Dummy field! must be right before refcount - int dummy_refcount; // Dummy field! must be right before chars - TableRep (string_view strref, size_t hash); - ~TableRep (); - const char *c_str () const { return (const char *)(this + 1); } - }; - -private: - static std::string empty_std_string; -}; - - - -/// Functor class to use as a hasher when you want to make a hash_map or -/// hash_set using ustring as a key. -class ustringHash -{ -public: - size_t operator() (const ustring &s) const { return s.hash(); } -}; - - - -/// Functor class to use for comparisons when sorting ustrings, if you -/// want the strings sorted lexicographically. -class ustringLess -{ -public: - size_t operator() (ustring a, ustring b) const {return a a, VaryingRef b, -/// float *result) { -/// for (int i = 0; i < n; ++i) -/// result[i] = a[i] + b[i]; -/// } -/// \endcode -/// -/// VaryingRef overloads operator [] to properly decode whether it is -/// uniform (point to the one value) or varying (index the right array -/// element). It also overloads the increment operator ++ and the pointer -/// indirection operator '*', so you could also write the function -/// equivalently as: -/// \code -/// void add (int n, VaryingRef a, VaryingRef b, -/// float *result) { -/// for (int i = 0; i < n; ++i, ++a, ++b) // note increments -/// result[i] = (*a) + (*b); -/// } -/// \endcode -/// -/// An example of calling this function would be: -/// \code -/// float a[n]; -/// float b; // just 1 value -/// float result[n]; -/// add (n, VaryingRef(a,sizeof(a[0])), -/// VaryingRef(b), result); -/// \endcode -/// -/// In this example, we're passing a truly varying 'a' (signified by -/// giving a step size from element to element), but a uniform 'b' (signified -/// by no step size, or a step size of zero). -/// -/// There are Varying() and Uniform() templated functions that provide -/// a helpful shorthand: -/// \code -/// add (n, Varying(a), Uniform(b), result); -/// \endcode -/// -/// Now let's take it a step further and fully optimize the 'add' function -/// for when both operands are uniform: -/// \code -/// void add (int n, VaryingRef a, VaryingRef b, -/// VaryingRef result) { -/// if (a.is_uniform() && b.is_uniform()) { -/// float r = (*a) + (*b); -/// for (int i = 0; i < n; ++i) -/// result[i] = r; -/// } else { -/// // One or both are varying -/// for (int i = 0; i < n; ++i, ++a, ++b) -/// result[i] = (*a) + (*b); -/// } -/// } -/// \endcode -/// This is the basis for handling uniform and varying values efficiently -/// inside a SIMD shading system. - -template -class VaryingRef { -public: - VaryingRef () { init (0, 0); } - - /// Construct a VaryingRef either of a single value pointed to by ptr - /// (if step == 0 or no step is provided), or of a varying set of - /// values beginning with ptr and with successive values every 'step' - /// bytes. - VaryingRef (void *ptr_, int step_=0) { init ((T *)ptr_,step_); } - - /// Construct a uniform VaryingRef from a single value. - /// - VaryingRef (T &ptr_) { init (&ptr_, 0); } - - /// Initialize this VaryingRef to either of a single value pointed - /// to by ptr (if step == 0 or no step is provided), or of a varying - /// set of values beginning with ptr and with successive values - /// every 'step' bytes. - void init (T *ptr_, int step_=0) { - m_ptr = ptr_; - m_step = step_; - } - - /// Initialize this VaryingRef to be uniform and point to a particular - /// value reference. - const VaryingRef & operator= (T &ptr_) { init (&ptr_); return *this; } - - /// Is this reference pointing nowhere? - /// - bool is_null () const { return (m_ptr == 0); } - - /// Cast to void* returns the pointer, but the real purpose is so - /// you can use a VaryingRef as if it were a 'bool' value in a test. - operator void*() const { return m_ptr; } - - /// Is this VaryingRef referring to a varying value, signified by - /// having a nonzero step size between elements? - bool is_varying () const { return (m_step != 0); } - - /// Is this VaryingRef referring to a uniform value, signified by - /// having a step size of zero between elements? - bool is_uniform () const { return (m_step == 0); } - - /// Pre-increment: If this VaryingRef is varying, increment its - /// pointer to the next element in the series, but don't change - /// anything if it's uniform. In either case, return a reference to - /// its new state. - VaryingRef & operator++ () { // Prefix form ++i - char *p = (char *)m_ptr; - p += m_step; - m_ptr = (T *) p; - return *this; - } - /// Post-increment: If this VaryingRef is varying, increment its - /// pointer to the next element in the series, but don't change - /// anything if it's uniform. No value is returned, so it's not - /// legal to do 'bar = foo++' if foo and bar are VaryingRef's. - void operator++ (int) { // Postfix form i++ : return nothing to avoid copy - // VaryingRef tmp = *this; - char *p = (char *)m_ptr; - p += m_step; - m_ptr = (T *) p; - // return tmp; - } - - /// Pointer indirection will return the first value currently - /// pointed to by this VaryingRef. - T & operator* () const { return *m_ptr; } - - /// Array indexing operator will return a reference to the single - /// element if *this is uniform, or to the i-th element of the - /// series if *this is varying. - T & operator[] (int i) const { return *(T *) ((char *)m_ptr + i*m_step); } - - /// Return the raw pointer underneath. - /// - T * ptr () const { return m_ptr; } - - /// Return the raw step underneath. - /// - int step () const { return m_step; } - -private: - T *m_ptr; ///< Pointer to value - int m_step; ///< Distance between successive values -- in BYTES! -}; - - - -/// Helper function wraps a varying reference with default step size. -/// -template -VaryingRef Varying (T *x) { return VaryingRef (x, sizeof(T)); } - -/// Helper function wraps a uniform reference. -/// -template -VaryingRef Uniform (T *x) { return VaryingRef (x, 0); } - -/// Helper function wraps a uniform reference. -/// -template -VaryingRef Uniform (T &x) { return VaryingRef (&x, 0); } - - -OIIO_NAMESPACE_END - -#endif // OPENIMAGEIO_VARYINGREF_H diff --git a/3rdparty/oiio16/include/OpenImageIO/version.h b/3rdparty/oiio16/include/OpenImageIO/version.h deleted file mode 100644 index 89579fcb..00000000 --- a/3rdparty/oiio16/include/OpenImageIO/version.h +++ /dev/null @@ -1,4 +0,0 @@ -// DEPRECATED header OpenImageIO/version.h -// For back compatibility, just include the new name, oiioversion.h. - -#include "oiioversion.h" diff --git a/3rdparty/tinyobjloader/include/tiny_obj_loader.h b/3rdparty/tinyobjloader/include/tiny_obj_loader.h new file mode 100644 index 00000000..b0aae897 --- /dev/null +++ b/3rdparty/tinyobjloader/include/tiny_obj_loader.h @@ -0,0 +1,2488 @@ +/* +The MIT License (MIT) + +Copyright (c) 2012-2018 Syoyo Fujita and many contributors. + +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. +*/ + +// +// version 1.2.2 : Parse multiple group names. +// version 1.2.1 : Added initial support for line('l') primitive(PR #178) +// version 1.2.0 : Hardened implementation(#175) +// version 1.1.1 : Support smoothing groups(#162) +// version 1.1.0 : Support parsing vertex color(#144) +// version 1.0.8 : Fix parsing `g` tag just after `usemtl`(#138) +// version 1.0.7 : Support multiple tex options(#126) +// version 1.0.6 : Add TINYOBJLOADER_USE_DOUBLE option(#124) +// version 1.0.5 : Ignore `Tr` when `d` exists in MTL(#43) +// version 1.0.4 : Support multiple filenames for 'mtllib'(#112) +// version 1.0.3 : Support parsing texture options(#85) +// version 1.0.2 : Improve parsing speed by about a factor of 2 for large +// files(#105) +// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104) +// version 1.0.0 : Change data structure. Change license from BSD to MIT. +// + +// +// Use this in *one* .cc + #define TINYOBJLOADER_IMPLEMENTATION +// #include "tiny_obj_loader.h" +// + +#ifndef TINY_OBJ_LOADER_H_ +#define TINY_OBJ_LOADER_H_ + +#include +#include +#include + +namespace tinyobj { + +#ifdef __clang__ +#pragma clang diagnostic push +#if __has_warning("-Wzero-as-null-pointer-constant") +#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" +#endif + +#pragma clang diagnostic ignored "-Wpadded" + +#endif + +// https://en.wikipedia.org/wiki/Wavefront_.obj_file says ... +// +// -blendu on | off # set horizontal texture blending +// (default on) +// -blendv on | off # set vertical texture blending +// (default on) +// -boost real_value # boost mip-map sharpness +// -mm base_value gain_value # modify texture map values (default +// 0 1) +// # base_value = brightness, +// gain_value = contrast +// -o u [v [w]] # Origin offset (default +// 0 0 0) +// -s u [v [w]] # Scale (default +// 1 1 1) +// -t u [v [w]] # Turbulence (default +// 0 0 0) +// -texres resolution # texture resolution to create +// -clamp on | off # only render texels in the clamped +// 0-1 range (default off) +// # When unclamped, textures are +// repeated across a surface, +// # when clamped, only texels which +// fall within the 0-1 +// # range are rendered. +// -bm mult_value # bump multiplier (for bump maps +// only) +// +// -imfchan r | g | b | m | l | z # specifies which channel of the file +// is used to +// # create a scalar or bump texture. +// r:red, g:green, +// # b:blue, m:matte, l:luminance, +// z:z-depth.. +// # (the default for bump is 'l' and +// for decal is 'm') +// bump -imfchan r bumpmap.tga # says to use the red channel of +// bumpmap.tga as the bumpmap +// +// For reflection maps... +// +// -type sphere # specifies a sphere for a "refl" +// reflection map +// -type cube_top | cube_bottom | # when using a cube map, the texture +// file for each +// cube_front | cube_back | # side of the cube is specified +// separately +// cube_left | cube_right + +#ifdef TINYOBJLOADER_USE_DOUBLE +//#pragma message "using double" +typedef double real_t; +#else +//#pragma message "using float" +typedef float real_t; +#endif + +typedef enum { + TEXTURE_TYPE_NONE, // default + TEXTURE_TYPE_SPHERE, + TEXTURE_TYPE_CUBE_TOP, + TEXTURE_TYPE_CUBE_BOTTOM, + TEXTURE_TYPE_CUBE_FRONT, + TEXTURE_TYPE_CUBE_BACK, + TEXTURE_TYPE_CUBE_LEFT, + TEXTURE_TYPE_CUBE_RIGHT +} texture_type_t; + +typedef struct { + texture_type_t type; // -type (default TEXTURE_TYPE_NONE) + real_t sharpness; // -boost (default 1.0?) + real_t brightness; // base_value in -mm option (default 0) + real_t contrast; // gain_value in -mm option (default 1) + real_t origin_offset[3]; // -o u [v [w]] (default 0 0 0) + real_t scale[3]; // -s u [v [w]] (default 1 1 1) + real_t turbulence[3]; // -t u [v [w]] (default 0 0 0) + // int texture_resolution; // -texres resolution (default = ?) TODO + bool clamp; // -clamp (default false) + char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm') + bool blendu; // -blendu (default on) + bool blendv; // -blendv (default on) + real_t bump_multiplier; // -bm (for bump maps only, default 1.0) +} texture_option_t; + +typedef struct { + std::string name; + + real_t ambient[3]; + real_t diffuse[3]; + real_t specular[3]; + real_t transmittance[3]; + real_t emission[3]; + real_t shininess; + real_t ior; // index of refraction + real_t dissolve; // 1 == opaque; 0 == fully transparent + // illumination model (see http://www.fileformat.info/format/material/) + int illum; + + int dummy; // Suppress padding warning. + + std::string ambient_texname; // map_Ka + std::string diffuse_texname; // map_Kd + std::string specular_texname; // map_Ks + std::string specular_highlight_texname; // map_Ns + std::string bump_texname; // map_bump, map_Bump, bump + std::string displacement_texname; // disp + std::string alpha_texname; // map_d + std::string reflection_texname; // refl + + texture_option_t ambient_texopt; + texture_option_t diffuse_texopt; + texture_option_t specular_texopt; + texture_option_t specular_highlight_texopt; + texture_option_t bump_texopt; + texture_option_t displacement_texopt; + texture_option_t alpha_texopt; + texture_option_t reflection_texopt; + + // PBR extension + // http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr + real_t roughness; // [0, 1] default 0 + real_t metallic; // [0, 1] default 0 + real_t sheen; // [0, 1] default 0 + real_t clearcoat_thickness; // [0, 1] default 0 + real_t clearcoat_roughness; // [0, 1] default 0 + real_t anisotropy; // aniso. [0, 1] default 0 + real_t anisotropy_rotation; // anisor. [0, 1] default 0 + real_t pad0; + std::string roughness_texname; // map_Pr + std::string metallic_texname; // map_Pm + std::string sheen_texname; // map_Ps + std::string emissive_texname; // map_Ke + std::string normal_texname; // norm. For normal mapping. + + texture_option_t roughness_texopt; + texture_option_t metallic_texopt; + texture_option_t sheen_texopt; + texture_option_t emissive_texopt; + texture_option_t normal_texopt; + + int pad2; + + std::map unknown_parameter; +} material_t; + +typedef struct { + std::string name; + + std::vector intValues; + std::vector floatValues; + std::vector stringValues; +} tag_t; + +// Index struct to support different indices for vtx/normal/texcoord. +// -1 means not used. +typedef struct { + int vertex_index; + int normal_index; + int texcoord_index; +} index_t; + +typedef struct { + std::vector indices; + std::vector num_face_vertices; // The number of vertices per + // face. 3 = polygon, 4 = quad, + // ... Up to 255. + std::vector material_ids; // per-face material ID + std::vector smoothing_group_ids; // per-face smoothing group + // ID(0 = off. positive value + // = group id) + std::vector tags; // SubD tag +} mesh_t; + +typedef struct { + std::vector indices; // pairs of indices for lines +} path_t; + +typedef struct { + std::string name; + mesh_t mesh; + path_t path; +} shape_t; + +// Vertex attributes +typedef struct { + std::vector vertices; // 'v' + std::vector normals; // 'vn' + std::vector texcoords; // 'vt' + std::vector colors; // extension: vertex colors +} attrib_t; + +typedef struct callback_t_ { + // W is optional and set to 1 if there is no `w` item in `v` line + void (*vertex_cb)(void *user_data, real_t x, real_t y, real_t z, real_t w); + void (*normal_cb)(void *user_data, real_t x, real_t y, real_t z); + + // y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in + // `vt` line. + void (*texcoord_cb)(void *user_data, real_t x, real_t y, real_t z); + + // called per 'f' line. num_indices is the number of face indices(e.g. 3 for + // triangle, 4 for quad) + // 0 will be passed for undefined index in index_t members. + void (*index_cb)(void *user_data, index_t *indices, int num_indices); + // `name` material name, `material_id` = the array index of material_t[]. -1 + // if + // a material not found in .mtl + void (*usemtl_cb)(void *user_data, const char *name, int material_id); + // `materials` = parsed material data. + void (*mtllib_cb)(void *user_data, const material_t *materials, + int num_materials); + // There may be multiple group names + void (*group_cb)(void *user_data, const char **names, int num_names); + void (*object_cb)(void *user_data, const char *name); + + callback_t_() + : vertex_cb(NULL), + normal_cb(NULL), + texcoord_cb(NULL), + index_cb(NULL), + usemtl_cb(NULL), + mtllib_cb(NULL), + group_cb(NULL), + object_cb(NULL) {} +} callback_t; + +class MaterialReader { + public: + MaterialReader() {} + virtual ~MaterialReader(); + + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) = 0; +}; + +class MaterialFileReader : public MaterialReader { + public: + explicit MaterialFileReader(const std::string &mtl_basedir) + : m_mtlBaseDir(mtl_basedir) {} + virtual ~MaterialFileReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::string m_mtlBaseDir; +}; + +class MaterialStreamReader : public MaterialReader { + public: + explicit MaterialStreamReader(std::istream &inStream) + : m_inStream(inStream) {} + virtual ~MaterialStreamReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::istream &m_inStream; +}; + +/// Loads .obj from a file. +/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data +/// 'shapes' will be filled with parsed shape data +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +/// 'mtl_basedir' is optional, and used for base directory for .mtl file. +/// In default(`NULL'), .mtl file is searched from an application's working +/// directory. +/// 'triangulate' is optional, and used whether triangulate polygon face in .obj +/// or not. +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir = NULL, + bool triangulate = true); + +/// Loads .obj from a file with custom user callback. +/// .mtl is loaded as usual and parsed material_t data will be passed to +/// `callback.mtllib_cb`. +/// Returns true when loading .obj/.mtl become success. +/// Returns warning and error message into `err` +/// See `examples/callback_api/` for how to use this function. +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data = NULL, + MaterialReader *readMatFn = NULL, + std::string *err = NULL); + +/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve +/// std::istream for materials. +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn = NULL, + bool triangulate = true); + +/// Loads materials into std::map +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream, + std::string *warning); + +} // namespace tinyobj + +#endif // TINY_OBJ_LOADER_H_ + +#ifdef TINYOBJLOADER_IMPLEMENTATION +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace tinyobj { + +MaterialReader::~MaterialReader() {} + +struct vertex_index_t { + int v_idx, vt_idx, vn_idx; + vertex_index_t() : v_idx(-1), vt_idx(-1), vn_idx(-1) {} + explicit vertex_index_t(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {} + vertex_index_t(int vidx, int vtidx, int vnidx) + : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {} +}; + +// Internal data structure for face representation +// index + smoothing group. +struct face_t { + unsigned int + smoothing_group_id; // smoothing group id. 0 = smoothing groupd is off. + int pad_; + std::vector vertex_indices; // face vertex indices. + + face_t() : smoothing_group_id(0) {} +}; + +struct line_t { + int idx0; + int idx1; +}; + +struct tag_sizes { + tag_sizes() : num_ints(0), num_reals(0), num_strings(0) {} + int num_ints; + int num_reals; + int num_strings; +}; + +struct obj_shape { + std::vector v; + std::vector vn; + std::vector vt; +}; + +// See +// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf +static std::istream &safeGetline(std::istream &is, std::string &t) { + t.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is, true); + std::streambuf *sb = is.rdbuf(); + + if (se) { + for (;;) { + int c = sb->sbumpc(); + switch (c) { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') sb->sbumpc(); + return is; + case EOF: + // Also handle the case when the last line has no line ending + if (t.empty()) is.setstate(std::ios::eofbit); + return is; + default: + t += static_cast(c); + } + } + } + + return is; +} + +#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) +#define IS_DIGIT(x) \ + (static_cast((x) - '0') < static_cast(10)) +#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) + +// Make index zero-base, and also support relative index. +static inline bool fixIndex(int idx, int n, int *ret) { + if (!ret) { + return false; + } + + if (idx > 0) { + (*ret) = idx - 1; + return true; + } + + if (idx == 0) { + // zero is not allowed according to the spec. + return false; + } + + if (idx < 0) { + (*ret) = n + idx; // negative value = relative + return true; + } + + return false; // never reach here. +} + +static inline std::string parseString(const char **token) { + std::string s; + (*token) += strspn((*token), " \t"); + size_t e = strcspn((*token), " \t\r"); + s = std::string((*token), &(*token)[e]); + (*token) += e; + return s; +} + +static inline int parseInt(const char **token) { + (*token) += strspn((*token), " \t"); + int i = atoi((*token)); + (*token) += strcspn((*token), " \t\r"); + return i; +} + +// Tries to parse a floating point number located at s. +// +// s_end should be a location in the string where reading should absolutely +// stop. For example at the end of the string, to prevent buffer overflows. +// +// Parses the following EBNF grammar: +// sign = "+" | "-" ; +// END = ? anything not in digit ? +// digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; +// integer = [sign] , digit , {digit} ; +// decimal = integer , ["." , integer] ; +// float = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ; +// +// Valid strings are for example: +// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 +// +// If the parsing is a success, result is set to the parsed value and true +// is returned. +// +// The function is greedy and will parse until any of the following happens: +// - a non-conforming character is encountered. +// - s_end is reached. +// +// The following situations triggers a failure: +// - s >= s_end. +// - parse failure. +// +static bool tryParseDouble(const char *s, const char *s_end, double *result) { + if (s >= s_end) { + return false; + } + + double mantissa = 0.0; + // This exponent is base 2 rather than 10. + // However the exponent we parse is supposed to be one of ten, + // thus we must take care to convert the exponent/and or the + // mantissa to a * 2^E, where a is the mantissa and E is the + // exponent. + // To get the final double we will use ldexp, it requires the + // exponent to be in base 2. + int exponent = 0; + + // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED + // TO JUMP OVER DEFINITIONS. + char sign = '+'; + char exp_sign = '+'; + char const *curr = s; + + // How many characters were read in a loop. + int read = 0; + // Tells whether a loop terminated due to reaching s_end. + bool end_not_reached = false; + + /* + BEGIN PARSING. + */ + + // Find out what sign we've got. + if (*curr == '+' || *curr == '-') { + sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + goto fail; + } + + // Read the integer part. + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + mantissa *= 10; + mantissa += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + + // We must make sure we actually got something. + if (read == 0) goto fail; + // We allow numbers of form "#", "###" etc. + if (!end_not_reached) goto assemble; + + // Read the decimal part. + if (*curr == '.') { + curr++; + read = 1; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + static const double pow_lut[] = { + 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, + }; + const int lut_entries = sizeof pow_lut / sizeof pow_lut[0]; + + // NOTE: Don't use powf here, it will absolutely murder precision. + mantissa += static_cast(*curr - 0x30) * + (read < lut_entries ? pow_lut[read] : std::pow(10.0, -read)); + read++; + curr++; + end_not_reached = (curr != s_end); + } + } else if (*curr == 'e' || *curr == 'E') { + } else { + goto assemble; + } + + if (!end_not_reached) goto assemble; + + // Read the exponent part. + if (*curr == 'e' || *curr == 'E') { + curr++; + // Figure out if a sign is present and if it is. + end_not_reached = (curr != s_end); + if (end_not_reached && (*curr == '+' || *curr == '-')) { + exp_sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + // Empty E is not allowed. + goto fail; + } + + read = 0; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + exponent *= 10; + exponent += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + exponent *= (exp_sign == '+' ? 1 : -1); + if (read == 0) goto fail; + } + +assemble: + *result = (sign == '+' ? 1 : -1) * + (exponent ? std::ldexp(mantissa * std::pow(5.0, exponent), exponent) + : mantissa); + return true; +fail: + return false; +} + +static inline real_t parseReal(const char **token, double default_value = 0.0) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + double val = default_value; + tryParseDouble((*token), end, &val); + real_t f = static_cast(val); + (*token) = end; + return f; +} + +static inline bool parseReal(const char **token, real_t *out) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + double val; + bool ret = tryParseDouble((*token), end, &val); + if (ret) { + real_t f = static_cast(val); + (*out) = f; + } + (*token) = end; + return ret; +} + +static inline void parseReal2(real_t *x, real_t *y, const char **token, + const double default_x = 0.0, + const double default_y = 0.0) { + (*x) = parseReal(token, default_x); + (*y) = parseReal(token, default_y); +} + +static inline void parseReal3(real_t *x, real_t *y, real_t *z, + const char **token, const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0) { + (*x) = parseReal(token, default_x); + (*y) = parseReal(token, default_y); + (*z) = parseReal(token, default_z); +} + +static inline void parseV(real_t *x, real_t *y, real_t *z, real_t *w, + const char **token, const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0, + const double default_w = 1.0) { + (*x) = parseReal(token, default_x); + (*y) = parseReal(token, default_y); + (*z) = parseReal(token, default_z); + (*w) = parseReal(token, default_w); +} + +// Extension: parse vertex with colors(6 items) +static inline bool parseVertexWithColor(real_t *x, real_t *y, real_t *z, + real_t *r, real_t *g, real_t *b, + const char **token, + const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0) { + (*x) = parseReal(token, default_x); + (*y) = parseReal(token, default_y); + (*z) = parseReal(token, default_z); + + (*r) = parseReal(token, 1.0); + (*g) = parseReal(token, 1.0); + (*b) = parseReal(token, 1.0); + + return true; +} + +static inline bool parseOnOff(const char **token, bool default_value = true) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + + bool ret = default_value; + if ((0 == strncmp((*token), "on", 2))) { + ret = true; + } else if ((0 == strncmp((*token), "off", 3))) { + ret = false; + } + + (*token) = end; + return ret; +} + +static inline texture_type_t parseTextureType( + const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + texture_type_t ty = default_value; + + if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) { + ty = TEXTURE_TYPE_CUBE_TOP; + } else if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) { + ty = TEXTURE_TYPE_CUBE_BOTTOM; + } else if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) { + ty = TEXTURE_TYPE_CUBE_LEFT; + } else if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) { + ty = TEXTURE_TYPE_CUBE_RIGHT; + } else if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) { + ty = TEXTURE_TYPE_CUBE_FRONT; + } else if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) { + ty = TEXTURE_TYPE_CUBE_BACK; + } else if ((0 == strncmp((*token), "sphere", strlen("sphere")))) { + ty = TEXTURE_TYPE_SPHERE; + } + + (*token) = end; + return ty; +} + +static tag_sizes parseTagTriple(const char **token) { + tag_sizes ts; + + (*token) += strspn((*token), " \t"); + ts.num_ints = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + + (*token)++; // Skip '/' + + (*token) += strspn((*token), " \t"); + ts.num_reals = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; // Skip '/' + + ts.num_strings = parseInt(token); + + return ts; +} + +// Parse triples with index offsets: i, i/j/k, i//k, i/j +static bool parseTriple(const char **token, int vsize, int vnsize, int vtsize, + vertex_index_t *ret) { + if (!ret) { + return false; + } + + vertex_index_t vi(-1); + + if (!fixIndex(atoi((*token)), vsize, &(vi.v_idx))) { + return false; + } + + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + (*ret) = vi; + return true; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + if (!fixIndex(atoi((*token)), vnsize, &(vi.vn_idx))) { + return false; + } + (*token) += strcspn((*token), "/ \t\r"); + (*ret) = vi; + return true; + } + + // i/j/k or i/j + if (!fixIndex(atoi((*token)), vtsize, &(vi.vt_idx))) { + return false; + } + + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + (*ret) = vi; + return true; + } + + // i/j/k + (*token)++; // skip '/' + if (!fixIndex(atoi((*token)), vnsize, &(vi.vn_idx))) { + return false; + } + (*token) += strcspn((*token), "/ \t\r"); + + (*ret) = vi; + + return true; +} + +// Parse raw triples: i, i/j/k, i//k, i/j +static vertex_index_t parseRawTriple(const char **token) { + vertex_index_t vi(static_cast(0)); // 0 is an invalid index in OBJ + + vi.v_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +static bool ParseTextureNameAndOption(std::string *texname, + texture_option_t *texopt, + const char *linebuf, const bool is_bump) { + // @todo { write more robust lexer and parser. } + bool found_texname = false; + std::string texture_name; + + // Fill with default value for texopt. + if (is_bump) { + texopt->imfchan = 'l'; + } else { + texopt->imfchan = 'm'; + } + texopt->bump_multiplier = static_cast(1.0); + texopt->clamp = false; + texopt->blendu = true; + texopt->blendv = true; + texopt->sharpness = static_cast(1.0); + texopt->brightness = static_cast(0.0); + texopt->contrast = static_cast(1.0); + texopt->origin_offset[0] = static_cast(0.0); + texopt->origin_offset[1] = static_cast(0.0); + texopt->origin_offset[2] = static_cast(0.0); + texopt->scale[0] = static_cast(1.0); + texopt->scale[1] = static_cast(1.0); + texopt->scale[2] = static_cast(1.0); + texopt->turbulence[0] = static_cast(0.0); + texopt->turbulence[1] = static_cast(0.0); + texopt->turbulence[2] = static_cast(0.0); + texopt->type = TEXTURE_TYPE_NONE; + + const char *token = linebuf; // Assume line ends with NULL + + while (!IS_NEW_LINE((*token))) { + token += strspn(token, " \t"); // skip space + if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendu = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendv = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->clamp = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->sharpness = parseReal(&token, 1.0); + } else if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) { + token += 4; + texopt->bump_multiplier = parseReal(&token, 1.0); + } else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseReal3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]), + &(texopt->origin_offset[2]), &token); + } else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseReal3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]), + &token, 1.0, 1.0, 1.0); + } else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseReal3(&(texopt->turbulence[0]), &(texopt->turbulence[1]), + &(texopt->turbulence[2]), &token); + } else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) { + token += 5; + texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE); + } else if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) { + token += 9; + token += strspn(token, " \t"); + const char *end = token + strcspn(token, " \t\r"); + if ((end - token) == 1) { // Assume one char for -imfchan + texopt->imfchan = (*token); + } + token = end; + } else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) { + token += 4; + parseReal2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0); + } else { + // Assume texture filename +#if 0 + size_t len = strcspn(token, " \t\r"); // untile next space + texture_name = std::string(token, token + len); + token += len; + + token += strspn(token, " \t"); // skip space +#else + // Read filename until line end to parse filename containing whitespace + // TODO(syoyo): Support parsing texture option flag after the filename. + texture_name = std::string(token); + token += texture_name.length(); +#endif + + found_texname = true; + } + } + + if (found_texname) { + (*texname) = texture_name; + return true; + } else { + return false; + } +} + +static void InitMaterial(material_t *material) { + material->name = ""; + material->ambient_texname = ""; + material->diffuse_texname = ""; + material->specular_texname = ""; + material->specular_highlight_texname = ""; + material->bump_texname = ""; + material->displacement_texname = ""; + material->reflection_texname = ""; + material->alpha_texname = ""; + for (int i = 0; i < 3; i++) { + material->ambient[i] = static_cast(0.0); + material->diffuse[i] = static_cast(0.0); + material->specular[i] = static_cast(0.0); + material->transmittance[i] = static_cast(0.0); + material->emission[i] = static_cast(0.0); + } + material->illum = 0; + material->dissolve = static_cast(1.0); + material->shininess = static_cast(1.0); + material->ior = static_cast(1.0); + + material->roughness = static_cast(0.0); + material->metallic = static_cast(0.0); + material->sheen = static_cast(0.0); + material->clearcoat_thickness = static_cast(0.0); + material->clearcoat_roughness = static_cast(0.0); + material->anisotropy_rotation = static_cast(0.0); + material->anisotropy = static_cast(0.0); + material->roughness_texname = ""; + material->metallic_texname = ""; + material->sheen_texname = ""; + material->emissive_texname = ""; + material->normal_texname = ""; + + material->unknown_parameter.clear(); +} + +// code from https://wrf.ecse.rpi.edu//Research/Short_Notes/pnpoly.html +template +static int pnpoly(int nvert, T *vertx, T *verty, T testx, T testy) { + int i, j, c = 0; + for (i = 0, j = nvert - 1; i < nvert; j = i++) { + if (((verty[i] > testy) != (verty[j] > testy)) && + (testx < + (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + + vertx[i])) + c = !c; + } + return c; +} + +// TODO(syoyo): refactor function. +static bool exportGroupsToShape(shape_t *shape, + const std::vector &faceGroup, + std::vector &lineGroup, + const std::vector &tags, + const int material_id, const std::string &name, + bool triangulate, + const std::vector &v) { + if (faceGroup.empty() && lineGroup.empty()) { + return false; + } + + if (!faceGroup.empty()) { + // Flatten vertices and indices + for (size_t i = 0; i < faceGroup.size(); i++) { + const face_t &face = faceGroup[i]; + + size_t npolys = face.vertex_indices.size(); + + if (npolys < 3) { + // Face must have 3+ vertices. + continue; + } + + vertex_index_t i0 = face.vertex_indices[0]; + vertex_index_t i1(-1); + vertex_index_t i2 = face.vertex_indices[1]; + + if (triangulate) { + // find the two axes to work in + size_t axes[2] = {1, 2}; + for (size_t k = 0; k < npolys; ++k) { + i0 = face.vertex_indices[(k + 0) % npolys]; + i1 = face.vertex_indices[(k + 1) % npolys]; + i2 = face.vertex_indices[(k + 2) % npolys]; + size_t vi0 = size_t(i0.v_idx); + size_t vi1 = size_t(i1.v_idx); + size_t vi2 = size_t(i2.v_idx); + + if (((3 * vi0 + 2) >= v.size()) || ((3 * vi1 + 2) >= v.size()) || + ((3 * vi2 + 2) >= v.size())) { + // Invalid triangle. + // FIXME(syoyo): Is it ok to simply skip this invalid triangle? + continue; + } + real_t v0x = v[vi0 * 3 + 0]; + real_t v0y = v[vi0 * 3 + 1]; + real_t v0z = v[vi0 * 3 + 2]; + real_t v1x = v[vi1 * 3 + 0]; + real_t v1y = v[vi1 * 3 + 1]; + real_t v1z = v[vi1 * 3 + 2]; + real_t v2x = v[vi2 * 3 + 0]; + real_t v2y = v[vi2 * 3 + 1]; + real_t v2z = v[vi2 * 3 + 2]; + real_t e0x = v1x - v0x; + real_t e0y = v1y - v0y; + real_t e0z = v1z - v0z; + real_t e1x = v2x - v1x; + real_t e1y = v2y - v1y; + real_t e1z = v2z - v1z; + real_t cx = std::fabs(e0y * e1z - e0z * e1y); + real_t cy = std::fabs(e0z * e1x - e0x * e1z); + real_t cz = std::fabs(e0x * e1y - e0y * e1x); + const real_t epsilon = std::numeric_limits::epsilon(); + if (cx > epsilon || cy > epsilon || cz > epsilon) { + // found a corner + if (cx > cy && cx > cz) { + } else { + axes[0] = 0; + if (cz > cx && cz > cy) axes[1] = 1; + } + break; + } + } + + real_t area = 0; + for (size_t k = 0; k < npolys; ++k) { + i0 = face.vertex_indices[(k + 0) % npolys]; + i1 = face.vertex_indices[(k + 1) % npolys]; + size_t vi0 = size_t(i0.v_idx); + size_t vi1 = size_t(i1.v_idx); + if (((vi0 * 3 + axes[0]) >= v.size()) || + ((vi0 * 3 + axes[1]) >= v.size()) || + ((vi1 * 3 + axes[0]) >= v.size()) || + ((vi1 * 3 + axes[1]) >= v.size())) { + // Invalid index. + continue; + } + real_t v0x = v[vi0 * 3 + axes[0]]; + real_t v0y = v[vi0 * 3 + axes[1]]; + real_t v1x = v[vi1 * 3 + axes[0]]; + real_t v1y = v[vi1 * 3 + axes[1]]; + area += (v0x * v1y - v0y * v1x) * static_cast(0.5); + } + + int maxRounds = 10; // arbitrary max loop count to protect against + // unexpected errors + + face_t remainingFace = face; // copy + size_t guess_vert = 0; + vertex_index_t ind[3]; + real_t vx[3]; + real_t vy[3]; + while (remainingFace.vertex_indices.size() > 3 && maxRounds > 0) { + npolys = remainingFace.vertex_indices.size(); + if (guess_vert >= npolys) { + maxRounds -= 1; + guess_vert -= npolys; + } + for (size_t k = 0; k < 3; k++) { + ind[k] = remainingFace.vertex_indices[(guess_vert + k) % npolys]; + size_t vi = size_t(ind[k].v_idx); + if (((vi * 3 + axes[0]) >= v.size()) || + ((vi * 3 + axes[1]) >= v.size())) { + // ??? + vx[k] = static_cast(0.0); + vy[k] = static_cast(0.0); + } else { + vx[k] = v[vi * 3 + axes[0]]; + vy[k] = v[vi * 3 + axes[1]]; + } + } + real_t e0x = vx[1] - vx[0]; + real_t e0y = vy[1] - vy[0]; + real_t e1x = vx[2] - vx[1]; + real_t e1y = vy[2] - vy[1]; + real_t cross = e0x * e1y - e0y * e1x; + // if an internal angle + if (cross * area < static_cast(0.0)) { + guess_vert += 1; + continue; + } + + // check all other verts in case they are inside this triangle + bool overlap = false; + for (size_t otherVert = 3; otherVert < npolys; ++otherVert) { + size_t idx = (guess_vert + otherVert) % npolys; + + if (idx >= remainingFace.vertex_indices.size()) { + // ??? + continue; + } + + size_t ovi = size_t(remainingFace.vertex_indices[idx].v_idx); + + if (((ovi * 3 + axes[0]) >= v.size()) || + ((ovi * 3 + axes[1]) >= v.size())) { + // ??? + continue; + } + real_t tx = v[ovi * 3 + axes[0]]; + real_t ty = v[ovi * 3 + axes[1]]; + if (pnpoly(3, vx, vy, tx, ty)) { + overlap = true; + break; + } + } + + if (overlap) { + guess_vert += 1; + continue; + } + + // this triangle is an ear + { + index_t idx0, idx1, idx2; + idx0.vertex_index = ind[0].v_idx; + idx0.normal_index = ind[0].vn_idx; + idx0.texcoord_index = ind[0].vt_idx; + idx1.vertex_index = ind[1].v_idx; + idx1.normal_index = ind[1].vn_idx; + idx1.texcoord_index = ind[1].vt_idx; + idx2.vertex_index = ind[2].v_idx; + idx2.normal_index = ind[2].vn_idx; + idx2.texcoord_index = ind[2].vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + shape->mesh.smoothing_group_ids.push_back(face.smoothing_group_id); + } + + // remove v1 from the list + size_t removed_vert_index = (guess_vert + 1) % npolys; + while (removed_vert_index + 1 < npolys) { + remainingFace.vertex_indices[removed_vert_index] = + remainingFace.vertex_indices[removed_vert_index + 1]; + removed_vert_index += 1; + } + remainingFace.vertex_indices.pop_back(); + } + + if (remainingFace.vertex_indices.size() == 3) { + i0 = remainingFace.vertex_indices[0]; + i1 = remainingFace.vertex_indices[1]; + i2 = remainingFace.vertex_indices[2]; + { + index_t idx0, idx1, idx2; + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + shape->mesh.smoothing_group_ids.push_back(face.smoothing_group_id); + } + } + } else { + for (size_t k = 0; k < npolys; k++) { + index_t idx; + idx.vertex_index = face.vertex_indices[k].v_idx; + idx.normal_index = face.vertex_indices[k].vn_idx; + idx.texcoord_index = face.vertex_indices[k].vt_idx; + shape->mesh.indices.push_back(idx); + } + + shape->mesh.num_face_vertices.push_back( + static_cast(npolys)); + shape->mesh.material_ids.push_back(material_id); // per face + shape->mesh.smoothing_group_ids.push_back( + face.smoothing_group_id); // per face + } + } + + shape->name = name; + shape->mesh.tags = tags; + } + + if (!lineGroup.empty()) { + shape->path.indices.swap(lineGroup); + } + + return true; +} + +// Split a string with specified delimiter character. +// http://stackoverflow.com/questions/236129/split-a-string-in-c +static void SplitString(const std::string &s, char delim, + std::vector &elems) { + std::stringstream ss; + ss.str(s); + std::string item; + while (std::getline(ss, item, delim)) { + elems.push_back(item); + } +} + +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream, + std::string *warning) { + // Create a default material anyway. + material_t material; + InitMaterial(&material); + + // Issue 43. `d` wins against `Tr` since `Tr` is not in the MTL specification. + bool has_d = false; + bool has_tr = false; + + std::stringstream ss; + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim trailing whitespace. + if (linebuf.size() > 0) { + linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1); + } + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // new mtl + if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { + // flush previous material. + if (!material.name.empty()) { + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); + } + + // initial temporary material + InitMaterial(&material); + + has_d = false; + has_tr = false; + + // set new mtl name + token += 7; + { + std::stringstream sstr; + sstr << token; + material.name = sstr.str(); + } + continue; + } + + // ambient + if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { + token += 2; + real_t r, g, b; + parseReal3(&r, &g, &b, &token); + material.ambient[0] = r; + material.ambient[1] = g; + material.ambient[2] = b; + continue; + } + + // diffuse + if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { + token += 2; + real_t r, g, b; + parseReal3(&r, &g, &b, &token); + material.diffuse[0] = r; + material.diffuse[1] = g; + material.diffuse[2] = b; + continue; + } + + // specular + if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { + token += 2; + real_t r, g, b; + parseReal3(&r, &g, &b, &token); + material.specular[0] = r; + material.specular[1] = g; + material.specular[2] = b; + continue; + } + + // transmittance + if (token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 2; + real_t r, g, b; + parseReal3(&r, &g, &b, &token); + material.transmittance[0] = r; + material.transmittance[1] = g; + material.transmittance[2] = b; + continue; + } + + // ior(index of refraction) + if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { + token += 2; + material.ior = parseReal(&token); + continue; + } + + // emission + if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { + token += 2; + real_t r, g, b; + parseReal3(&r, &g, &b, &token); + material.emission[0] = r; + material.emission[1] = g; + material.emission[2] = b; + continue; + } + + // shininess + if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.shininess = parseReal(&token); + continue; + } + + // illum model + if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { + token += 6; + material.illum = parseInt(&token); + continue; + } + + // dissolve + if ((token[0] == 'd' && IS_SPACE(token[1]))) { + token += 1; + material.dissolve = parseReal(&token); + + if (has_tr) { + ss << "WARN: Both `d` and `Tr` parameters defined for \"" + << material.name << "\". Use the value of `d` for dissolve." + << std::endl; + } + has_d = true; + continue; + } + if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + if (has_d) { + // `d` wins. Ignore `Tr` value. + ss << "WARN: Both `d` and `Tr` parameters defined for \"" + << material.name << "\". Use the value of `d` for dissolve." + << std::endl; + } else { + // We invert value of Tr(assume Tr is in range [0, 1]) + // NOTE: Interpretation of Tr is application(exporter) dependent. For + // some application(e.g. 3ds max obj exporter), Tr = d(Issue 43) + material.dissolve = static_cast(1.0) - parseReal(&token); + } + has_tr = true; + continue; + } + + // PBR: roughness + if (token[0] == 'P' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + material.roughness = parseReal(&token); + continue; + } + + // PBR: metallic + if (token[0] == 'P' && token[1] == 'm' && IS_SPACE(token[2])) { + token += 2; + material.metallic = parseReal(&token); + continue; + } + + // PBR: sheen + if (token[0] == 'P' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.sheen = parseReal(&token); + continue; + } + + // PBR: clearcoat thickness + if (token[0] == 'P' && token[1] == 'c' && IS_SPACE(token[2])) { + token += 2; + material.clearcoat_thickness = parseReal(&token); + continue; + } + + // PBR: clearcoat roughness + if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) { + token += 4; + material.clearcoat_roughness = parseReal(&token); + continue; + } + + // PBR: anisotropy + if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) { + token += 6; + material.anisotropy = parseReal(&token); + continue; + } + + // PBR: anisotropy rotation + if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) { + token += 7; + material.anisotropy_rotation = parseReal(&token); + continue; + } + + // ambient texture + if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.ambient_texname), + &(material.ambient_texopt), token, + /* is_bump */ false); + continue; + } + + // diffuse texture + if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.diffuse_texname), + &(material.diffuse_texopt), token, + /* is_bump */ false); + continue; + } + + // specular texture + if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_texname), + &(material.specular_texopt), token, + /* is_bump */ false); + continue; + } + + // specular highlight texture + if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_highlight_texname), + &(material.specular_highlight_texopt), token, + /* is_bump */ false); + continue; + } + + // bump texture + if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // bump texture + if ((0 == strncmp(token, "map_Bump", 8)) && IS_SPACE(token[8])) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // bump texture + if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // alpha texture + if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { + token += 6; + material.alpha_texname = token; + ParseTextureNameAndOption(&(material.alpha_texname), + &(material.alpha_texopt), token, + /* is_bump */ false); + continue; + } + + // displacement texture + if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.displacement_texname), + &(material.displacement_texopt), token, + /* is_bump */ false); + continue; + } + + // reflection map + if ((0 == strncmp(token, "refl", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.reflection_texname), + &(material.reflection_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: roughness texture + if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.roughness_texname), + &(material.roughness_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: metallic texture + if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.metallic_texname), + &(material.metallic_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: sheen texture + if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.sheen_texname), + &(material.sheen_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: emissive texture + if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.emissive_texname), + &(material.emissive_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: normal map texture + if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption( + &(material.normal_texname), &(material.normal_texopt), token, + /* is_bump */ false); // @fixme { is_bump will be true? } + continue; + } + + // unknown parameter + const char *_space = strchr(token, ' '); + if (!_space) { + _space = strchr(token, '\t'); + } + if (_space) { + std::ptrdiff_t len = _space - token; + std::string key(token, static_cast(len)); + std::string value = _space + 1; + material.unknown_parameter.insert( + std::pair(key, value)); + } + } + // flush last material. + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); + + if (warning) { + (*warning) = ss.str(); + } +} + +bool MaterialFileReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + std::string filepath; + + if (!m_mtlBaseDir.empty()) { + filepath = std::string(m_mtlBaseDir) + matId; + } else { + filepath = matId; + } + + std::ifstream matIStream(filepath.c_str()); + if (!matIStream) { + std::stringstream ss; + ss << "WARN: Material file [ " << filepath << " ] not found." << std::endl; + if (err) { + (*err) += ss.str(); + } + return false; + } + + std::string warning; + LoadMtl(matMap, materials, &matIStream, &warning); + + if (!warning.empty()) { + if (err) { + (*err) += warning; + } + } + + return true; +} + +bool MaterialStreamReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + (void)matId; + if (!m_inStream) { + std::stringstream ss; + ss << "WARN: Material stream in error state. " << std::endl; + if (err) { + (*err) += ss.str(); + } + return false; + } + + std::string warning; + LoadMtl(matMap, materials, &m_inStream, &warning); + + if (!warning.empty()) { + if (err) { + (*err) += warning; + } + } + + return true; +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir, bool trianglulate) { + attrib->vertices.clear(); + attrib->normals.clear(); + attrib->texcoords.clear(); + attrib->colors.clear(); + shapes->clear(); + + std::stringstream errss; + + std::ifstream ifs(filename); + if (!ifs) { + errss << "Cannot open file [" << filename << "]" << std::endl; + if (err) { + (*err) = errss.str(); + } + return false; + } + + std::string baseDir = mtl_basedir ? mtl_basedir : ""; + if (!baseDir.empty()) { +#ifndef _WIN32 + const char dirsep = '/'; +#else + const char dirsep = '\\'; +#endif + if (baseDir[baseDir.length() - 1] != dirsep) baseDir += dirsep; + } + MaterialFileReader matFileReader(baseDir); + + return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, + trianglulate); +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn /*= NULL*/, + bool triangulate) { + std::stringstream errss; + + std::vector v; + std::vector vn; + std::vector vt; + std::vector vc; + std::vector tags; + std::vector faceGroup; + std::vector lineGroup; + std::string name; + + // material + std::map material_map; + int material = -1; + + // smoothing group id + unsigned int current_smoothing_id = + 0; // Initial value. 0 means no smoothing. + + int greatest_v_idx = -1; + int greatest_vn_idx = -1; + int greatest_vt_idx = -1; + + shape_t shape; + + size_t line_num = 0; + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + line_num++; + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + real_t x, y, z; + real_t r, g, b; + parseVertexWithColor(&x, &y, &z, &r, &g, &b, &token); + v.push_back(x); + v.push_back(y); + v.push_back(z); + + vc.push_back(r); + vc.push_back(g); + vc.push_back(b); + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + real_t x, y, z; + parseReal3(&x, &y, &z, &token); + vn.push_back(x); + vn.push_back(y); + vn.push_back(z); + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + real_t x, y; + parseReal2(&x, &y, &token); + vt.push_back(x); + vt.push_back(y); + continue; + } + + // line + if (token[0] == 'l' && IS_SPACE((token[1]))) { + token += 2; + + line_t line_cache; + bool end_line_bit = 0; + while (!IS_NEW_LINE(token[0])) { + // get index from string + int idx = 0; + fixIndex(parseInt(&token), 0, &idx); + + size_t n = strspn(token, " \t\r"); + token += n; + + if (!end_line_bit) { + line_cache.idx0 = idx; + } else { + line_cache.idx1 = idx; + lineGroup.push_back(line_cache.idx0); + lineGroup.push_back(line_cache.idx1); + line_cache = line_t(); + } + end_line_bit = !end_line_bit; + } + + continue; + } + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + face_t face; + + face.smoothing_group_id = current_smoothing_id; + face.vertex_indices.reserve(3); + + while (!IS_NEW_LINE(token[0])) { + vertex_index_t vi; + if (!parseTriple(&token, static_cast(v.size() / 3), + static_cast(vn.size() / 3), + static_cast(vt.size() / 2), &vi)) { + if (err) { + (*err) = "Failed parse `f' line(e.g. zero value for face index).\n"; + } + return false; + } + + greatest_v_idx = greatest_v_idx > vi.v_idx ? greatest_v_idx : vi.v_idx; + greatest_vn_idx = greatest_vn_idx > vi.vn_idx ? greatest_vn_idx : vi.vn_idx; + greatest_vt_idx = greatest_vt_idx > vi.vt_idx ? greatest_vt_idx : vi.vt_idx; + + face.vertex_indices.push_back(vi); + size_t n = strspn(token, " \t\r"); + token += n; + } + + // replace with emplace_back + std::move on C++11 + faceGroup.push_back(face); + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + token += 7; + std::stringstream ss; + ss << token; + std::string namebuf = ss.str(); + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material) { + // Create per-face material. Thus we don't add `shape` to `shapes` at + // this time. + // just clear `faceGroup` after `exportGroupsToShape()` call. + exportGroupsToShape(&shape, faceGroup, lineGroup, tags, material, name, + triangulate, v); + faceGroup.clear(); + material = newMaterialId; + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + token += 7; + + std::vector filenames; + SplitString(std::string(token), ' ', filenames); + + if (filenames.empty()) { + if (err) { + (*err) += + "WARN: Looks like empty filename for mtllib. Use default " + "material. \n"; + } + } else { + bool found = false; + for (size_t s = 0; s < filenames.size(); s++) { + std::string err_mtl; + bool ok = (*readMatFn)(filenames[s].c_str(), materials, + &material_map, &err_mtl); + if (err && (!err_mtl.empty())) { + (*err) += err_mtl; // This should be warn message. + } + + if (ok) { + found = true; + break; + } + } + + if (!found) { + if (err) { + (*err) += + "WARN: Failed to load material file(s). Use default " + "material.\n"; + } + } + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportGroupsToShape(&shape, faceGroup, lineGroup, tags, + material, name, triangulate, v); + (void)ret; // return value not used. + + if (shape.mesh.indices.size() > 0) { + shapes->push_back(shape); + } + + shape = shape_t(); + + // material = -1; + faceGroup.clear(); + + std::vector names; + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + // names[0] must be 'g' + + if (names.size() < 2) { + // 'g' with empty names + if (err) { + std::stringstream ss; + ss << "WARN: Empty group name. line: " << line_num << "\n"; + (*err) += ss.str(); + name = ""; + } + } else { + + std::stringstream ss; + ss << names[1]; + + // tinyobjloader does not support multiple groups for a primitive. + // Currently we concatinate multiple group names with a space to get + // single group name. + + for (size_t i = 2; i < names.size(); i++) { + ss << " " << names[i]; + } + + name = ss.str(); + + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportGroupsToShape(&shape, faceGroup, lineGroup, tags, + material, name, triangulate, v); + if (ret) { + shapes->push_back(shape); + } + + // material = -1; + faceGroup.clear(); + shape = shape_t(); + + // @todo { multiple object name? } + token += 2; + std::stringstream ss; + ss << token; + name = ss.str(); + + continue; + } + + if (token[0] == 't' && IS_SPACE(token[1])) { + const int max_tag_nums = 8192; // FIXME(syoyo): Parameterize. + tag_t tag; + + token += 2; + + tag.name = parseString(&token); + + tag_sizes ts = parseTagTriple(&token); + + if (ts.num_ints < 0) { + ts.num_ints = 0; + } + if (ts.num_ints > max_tag_nums) { + ts.num_ints = max_tag_nums; + } + + if (ts.num_reals < 0) { + ts.num_reals = 0; + } + if (ts.num_reals > max_tag_nums) { + ts.num_reals = max_tag_nums; + } + + if (ts.num_strings < 0) { + ts.num_strings = 0; + } + if (ts.num_strings > max_tag_nums) { + ts.num_strings = max_tag_nums; + } + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = parseInt(&token); + } + + tag.floatValues.resize(static_cast(ts.num_reals)); + for (size_t i = 0; i < static_cast(ts.num_reals); ++i) { + tag.floatValues[i] = parseReal(&token); + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + tag.stringValues[i] = parseString(&token); + } + + tags.push_back(tag); + + continue; + } + + if (token[0] == 's' && IS_SPACE(token[1])) { + // smoothing group id + token += 2; + + // skip space. + token += strspn(token, " \t"); // skip space + + if (token[0] == '\0') { + continue; + } + + if (token[0] == '\r' || token[1] == '\n') { + continue; + } + + if (strlen(token) >= 3) { + if (token[0] == 'o' && token[1] == 'f' && token[2] == 'f') { + current_smoothing_id = 0; + } + } else { + // assume number + int smGroupId = parseInt(&token); + if (smGroupId < 0) { + // parse error. force set to 0. + // FIXME(syoyo): Report warning. + current_smoothing_id = 0; + } else { + current_smoothing_id = static_cast(smGroupId); + } + } + + continue; + } // smoothing group id + + // Ignore unknown command. + } + + if (greatest_v_idx >= static_cast(v.size() / 3)) + { + if (err) { + std::stringstream ss; + ss << "WARN: Vertex indices out of bounds.\n" << std::endl; + (*err) += ss.str(); + } + } + if (greatest_vn_idx >= static_cast(vn.size() / 3)) + { + if (err) { + std::stringstream ss; + ss << "WARN: Vertex normal indices out of bounds.\n" << std::endl; + (*err) += ss.str(); + } + } + if (greatest_vt_idx >= static_cast(vt.size() / 2)) + { + if (err) { + std::stringstream ss; + ss << "WARN: Vertex texcoord indices out of bounds.\n" << std::endl; + (*err) += ss.str(); + } + } + + bool ret = exportGroupsToShape(&shape, faceGroup, lineGroup, tags, material, + name, triangulate, v); + // exportGroupsToShape return false when `usemtl` is called in the last + // line. + // we also add `shape` to `shapes` when `shape.mesh` has already some + // faces(indices) + if (ret || shape.mesh.indices.size()) { + shapes->push_back(shape); + } + faceGroup.clear(); // for safety + + if (err) { + (*err) += errss.str(); + } + + attrib->vertices.swap(v); + attrib->normals.swap(vn); + attrib->texcoords.swap(vt); + attrib->colors.swap(vc); + + return true; +} + +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data /*= NULL*/, + MaterialReader *readMatFn /*= NULL*/, + std::string *err /*= NULL*/) { + std::stringstream errss; + + // material + std::map material_map; + int material_id = -1; // -1 = invalid + + std::vector indices; + std::vector materials; + std::vector names; + names.reserve(2); + std::vector names_out; + + std::string linebuf; + while (inStream.peek() != -1) { + safeGetline(inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + // TODO(syoyo): Support parsing vertex color extension. + real_t x, y, z, w; // w is optional. default = 1.0 + parseV(&x, &y, &z, &w, &token); + if (callback.vertex_cb) { + callback.vertex_cb(user_data, x, y, z, w); + } + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + real_t x, y, z; + parseReal3(&x, &y, &z, &token); + if (callback.normal_cb) { + callback.normal_cb(user_data, x, y, z); + } + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + real_t x, y, z; // y and z are optional. default = 0.0 + parseReal3(&x, &y, &z, &token); + if (callback.texcoord_cb) { + callback.texcoord_cb(user_data, x, y, z); + } + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + indices.clear(); + while (!IS_NEW_LINE(token[0])) { + vertex_index_t vi = parseRawTriple(&token); + + index_t idx; + idx.vertex_index = vi.v_idx; + idx.normal_index = vi.vn_idx; + idx.texcoord_index = vi.vt_idx; + + indices.push_back(idx); + size_t n = strspn(token, " \t\r"); + token += n; + } + + if (callback.index_cb && indices.size() > 0) { + callback.index_cb(user_data, &indices.at(0), + static_cast(indices.size())); + } + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + token += 7; + std::stringstream ss; + ss << token; + std::string namebuf = ss.str(); + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material_id) { + material_id = newMaterialId; + } + + if (callback.usemtl_cb) { + callback.usemtl_cb(user_data, namebuf.c_str(), material_id); + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + token += 7; + + std::vector filenames; + SplitString(std::string(token), ' ', filenames); + + if (filenames.empty()) { + if (err) { + (*err) += + "WARN: Looks like empty filename for mtllib. Use default " + "material. \n"; + } + } else { + bool found = false; + for (size_t s = 0; s < filenames.size(); s++) { + std::string err_mtl; + bool ok = (*readMatFn)(filenames[s].c_str(), &materials, + &material_map, &err_mtl); + if (err && (!err_mtl.empty())) { + (*err) += err_mtl; // This should be warn message. + } + + if (ok) { + found = true; + break; + } + } + + if (!found) { + if (err) { + (*err) += + "WARN: Failed to load material file(s). Use default " + "material.\n"; + } + } else { + if (callback.mtllib_cb) { + callback.mtllib_cb(user_data, &materials.at(0), + static_cast(materials.size())); + } + } + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + names.clear(); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + if (callback.group_cb) { + if (names.size() > 1) { + // create const char* array. + names_out.resize(names.size() - 1); + for (size_t j = 0; j < names_out.size(); j++) { + names_out[j] = names[j + 1].c_str(); + } + callback.group_cb(user_data, &names_out.at(0), + static_cast(names_out.size())); + + } else { + callback.group_cb(user_data, NULL, 0); + } + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // @todo { multiple object name? } + token += 2; + + std::stringstream ss; + ss << token; + std::string object_name = ss.str(); + + if (callback.object_cb) { + callback.object_cb(user_data, object_name.c_str()); + } + + continue; + } + +#if 0 // @todo + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + token += 2; + std::stringstream ss; + ss << token; + tag.name = ss.str(); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_reals)); + for (size_t i = 0; i < static_cast(ts.num_reals); ++i) { + tag.floatValues[i] = parseReal(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + std::stringstream ss; + ss << token; + tag.stringValues[i] = ss.str(); + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } +#endif + + // Ignore unknown command. + } + + if (err) { + (*err) += errss.str(); + } + + return true; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +} // namespace tinyobj + +#endif diff --git a/Baikal/Baikal.lua b/Baikal/Baikal.lua deleted file mode 100644 index 3be41863..00000000 --- a/Baikal/Baikal.lua +++ /dev/null @@ -1,107 +0,0 @@ -project "Baikal" - kind "ConsoleApp" - location "../Baikal" - links {"RadeonRays", "CLW", "Calc"} - files { "../Baikal/**.inl", "../Baikal/**.h", "../Baikal/**.cpp", "../Baikal/**.cl", "../Baikal/**.fsh", "../Baikal/**.vsh" } - - includedirs{ "../RadeonRays/RadeonRays/include", "../RadeonRays/CLW", "."} - - if os.is("macosx") then - sysincludedirs {"/usr/local/include"} - includedirs{"../3rdparty/glfw/include"} - libdirs {"/usr/local/lib", "../3rdparty/glfw/lib/x64"} - linkoptions{ "-framework OpenGL -framework CoreFoundation -framework CoreGraphics -framework IOKit -framework AppKit -framework QuartzCore" } - buildoptions "-std=c++11 -stdlib=libc++" - links {"OpenImageIO", "glfw3"} - end - - if os.is("windows") then - includedirs { "../3rdparty/glew/include", "../3rdparty/freeglut/include", - "../3rdparty/oiio/include", "../3rdparty/glfw/include"} - links {"RadeonRays", "glfw3"} - if not _OPTIONS["benchmark"] then - links {"glew", "OpenGL32", "glfw3"} - end - libdirs { "../3rdparty/glew/lib/%{cfg.platform}", - "../3rdparty/freeglut/lib/%{cfg.platform}", - "../3rdparty/embree/lib/%{cfg.platform}", - "../3rdparty/oiio/lib/%{cfg.platform}", - "../3rdparty/glfw/lib/%{cfg.platform}" } - - configuration {"Debug"} - links {"OpenImageIOD"} - configuration {"Release"} - links {"OpenImageIO"} - configuration {} - end - - if os.is("linux") then - buildoptions "-std=c++11" - links {"OpenImageIO", "pthread"} - if not _OPTIONS["benchmark"] then - links{"GLEW", "GL", "glfw"} - end - os.execute("rm -rf obj"); - end - - if _OPTIONS["use_vulkan"] then - local vulkanSDKPath = os.getenv( "VK_SDK_PATH" ); - if vulkanSDKPath == nil then - vulkanSDKPath = os.getenv( "VULKAN_SDK" ); - end - if vulkanSDKPath ~= nil then - configuration {"x32"} - libdirs { vulkanSDKPath .. "/Bin32" } - configuration {"x64"} - libdirs { vulkanSDKPath .. "/Bin" } - configuration {} - end - if os.is("macosx") then - --no Vulkan on macOs need to error out TODO - elseif os.is("linux") then - libdirs { vulkanSDKPath .. "/lib" } - links { "vulkan"} - elseif os.is("windows") then - links {"Anvil"} - links{"vulkan-1"} - end - end - - if _OPTIONS["benchmark"] then - defines{"APP_BENCHMARK"} - removefiles{"../App/main.cpp", - "../App/Utils/shader_manager.cpp",} - else - removefiles {"../App/main_benchmark.cpp"} - end - -- if _OPTIONS["embed_kernels"] then - -- configuration {} - -- defines {"FR_EMBED_KERNELS"} - -- os.execute("python ../Tools/scripts/stringify.py ./CL/ > ./CL/cache/kernels.h") --- print ">> App: CL kernels embedded" --- end - - if _OPTIONS["denoiser"] then - defines{"ENABLE_DENOISER"} - end - - configuration {"x32", "Debug"} - targetdir "../Bin/Debug/x86" - configuration {"x64", "Debug"} - targetdir "../Bin/Debug/x64" - configuration {"x32", "Release"} - targetdir "../Bin/Release/x86" - configuration {"x64", "Release"} - targetdir "../Bin/Release/x64" - configuration {} - - if os.is("windows") then - postbuildcommands { - 'copy "..\\3rdparty\\glew\\bin\\%{cfg.platform}\\glew32.dll" "%{cfg.buildtarget.directory}"', - 'copy "..\\3rdparty\\glfw\\bin\\%{cfg.platform}\\glfw3.dll" "%{cfg.buildtarget.directory}"', - 'copy "..\\3rdparty\\embree\\bin\\%{cfg.platform}\\embree.dll" "%{cfg.buildtarget.directory}"', - 'copy "..\\3rdparty\\embree\\bin\\%{cfg.platform}\\tbb.dll" "%{cfg.buildtarget.directory}"', - 'copy "..\\3rdparty\\oiio\\bin\\%{cfg.platform}\\OpenImageIO.dll" "%{cfg.buildtarget.directory}"', - 'copy "..\\3rdparty\\oiio\\bin\\%{cfg.platform}\\OpenImageIOD.dll" "%{cfg.buildtarget.directory}"' - } - end diff --git a/Baikal/CL/bxdf.cl b/Baikal/CL/bxdf.cl deleted file mode 100644 index a3caf011..00000000 --- a/Baikal/CL/bxdf.cl +++ /dev/null @@ -1,1187 +0,0 @@ -/********************************************************************** -Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. - -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 BXDF_CL -#define BXDF_CL - -#include <../Baikal/CL/utils.cl> -#include <../Baikal/CL/texture.cl> -#include <../Baikal/CL/payload.cl> - -#define DENOM_EPS 1e-8f -#define ROUGHNESS_EPS 0.0001f - - -enum BxdfFlags -{ - kReflection = (1 << 0), - kTransmission = (1 << 1), - kDiffuse = (1 << 2), - kSpecular = (1 << 3), - kGlossy = (1 << 4), - kAllReflection = kReflection | kDiffuse | kSpecular | kGlossy, - kAllTransmission = kTransmission | kDiffuse | kSpecular | kGlossy, - kAll = kReflection | kTransmission | kDiffuse | kSpecular | kGlossy -}; - - -/// Schlick's approximation of Fresnel equtions -float SchlickFresnel(float eta, float ndotw) -{ - const float f = ((1.f - eta) / (1.f + eta)) * ((1.f - eta) / (1.f + eta)); - const float m = 1.f - fabs(ndotw); - const float m2 = m*m; - return f + (1.f - f) * m2 * m2 * m; -} - -/// Full Fresnel equations -float FresnelDielectric(float etai, float etat, float ndotwi, float ndotwt) -{ - // Parallel and perpendicular polarization - float rparl = ((etat * ndotwi) - (etai * ndotwt)) / ((etat * ndotwi) + (etai * ndotwt)); - float rperp = ((etai * ndotwi) - (etat * ndotwt)) / ((etai * ndotwi) + (etat * ndotwt)); - return (rparl*rparl + rperp*rperp) * 0.5f; -} - -/* - Microfacet Beckmann - */ - - // Distribution fucntion -float MicrofacetDistribution_Beckmann_D(float roughness, float3 m) -{ - float ndotm = fabs(m.y); - float ndotm2 = ndotm * ndotm; - float sinmn = native_sqrt(1.f - clamp(ndotm * ndotm, 0.f, 1.f)); - float tanmn = sinmn / ndotm; - float a2 = roughness * roughness; - - return (1.f / (PI * a2 * ndotm2 * ndotm2)) * native_exp(-tanmn * tanmn / a2); -} - -// PDF of the given direction -float MicrofacetDistribution_Beckmann_GetPdf( - // Rougness - float roughness, - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - // We need to convert pdf(wh)->pdf(wo) - float3 m = normalize(wi + wo); - float wodotm = fabs(dot(wo, m)); - - float mpdf = MicrofacetDistribution_Beckmann_D(roughness, m) * fabs(m.y); - // See Humphreys and Pharr for derivation - return mpdf / (4.f * wodotm); -} - -// Sample the distribution -void MicrofacetDistribution_Beckmann_SampleNormal(// Roughness - float roughness, - // Geometry - DifferentialGeometry const* dg, - // Texture args - TEXTURE_ARG_LIST, - // Sample - float2 sample, - // Outgoing direction - float3* wh - ) -{ - float r1 = sample.x; - float r2 = sample.y; - - // Sample halfway vector first, then reflect wi around that - float theta = atan(native_sqrt(-roughness*roughness*native_log(1.f - r1*0.99f))); - float costheta = native_cos(theta); - float sintheta = native_sin(theta); - - // phi = 2*PI*ksi2 - float phi = 2.f*PI*r2; - float cosphi = native_cos(phi); - float sinphi = native_sin(phi); - - // Reflect wi around wh - *wh = make_float3(sintheta * cosphi, costheta, sintheta * sinphi); -} - -float MicrofacetDistribution_Beckmann_G1(float roughness, float3 v, float3 m) -{ - float ndotv = fabs(v.y); - float mdotv = fabs(dot(m, v)); - float sinnv = native_sqrt(1.f - clamp(ndotv * ndotv, 0.f, 1.f)); - float tannv = sinnv / ndotv; - float a = tannv > DENOM_EPS ? 1.f / (roughness * tannv) : 0.f; - float a2 = a * a; - - if (a < 1.6f) - return 1.f; - - return (3.535f * a + 2.181f * a2) / (1.f + 2.276f * a + 2.577f * a2); -} - -// Shadowing function also depends on microfacet distribution -float MicrofacetDistribution_Beckmann_G(float roughness, float3 wi, float3 wo, float3 wh) -{ - return MicrofacetDistribution_Beckmann_G1(roughness, wi, wh) * MicrofacetDistribution_Beckmann_G1(roughness, wo, wh); -} - - -float3 MicrofacetBeckmann_Evaluate( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - const float3 ks = Texture_GetValue3f(dg->mat.kx.xyz, dg->uv, TEXTURE_ARGS_IDX(dg->mat.kxmapidx)); - const float roughness = Texture_GetValue1f(dg->mat.ns, dg->uv, TEXTURE_ARGS_IDX(dg->mat.nsmapidx)); - const float eta = dg->mat.ni; - - // Incident and reflected zenith angles - float costhetao = fabs(wo.y); - float costhetai = fabs(wi.y); - - // Calc halfway vector - float3 wh = normalize(wi + wo); - - float F = dg->mat.fresnel; - - float denom = 4.f * costhetao * costhetai; - - // F(eta) * D * G * ks / (4 * cosa * cosi) - return denom > DENOM_EPS ? F * ks * MicrofacetDistribution_Beckmann_G(roughness, wi, wo, wh) * MicrofacetDistribution_Beckmann_D(roughness, wh) / denom : 0.f; -} - - -float MicrofacetBeckmann_GetPdf( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - const float roughness = Texture_GetValue1f(dg->mat.ns, dg->uv, TEXTURE_ARGS_IDX(dg->mat.nsmapidx)); - return MicrofacetDistribution_Beckmann_GetPdf(roughness, dg, wi, wo, TEXTURE_ARGS); -} - -float3 MicrofacetBeckmann_Sample( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Texture args - TEXTURE_ARG_LIST, - // Sample - float2 sample, - // Outgoing direction - float3* wo, - // PDF at wo - float* pdf - ) -{ - const float roughness = Texture_GetValue1f(dg->mat.ns, dg->uv, TEXTURE_ARGS_IDX(dg->mat.nsmapidx)); - - float3 wh; - MicrofacetDistribution_Beckmann_SampleNormal(roughness, dg, TEXTURE_ARGS, sample, &wh); - - *wo = -wi + 2.f*fabs(dot(wi, wh)) * wh; - - *pdf = MicrofacetDistribution_Beckmann_GetPdf(roughness, dg, wi, *wo, TEXTURE_ARGS); - - return MicrofacetBeckmann_Evaluate(dg, wi, *wo, TEXTURE_ARGS); -} - -/* - Microfacet GGX - */ - // Distribution fucntion -float MicrofacetDistribution_GGX_D(float roughness, float3 m) -{ - float ndotm = fabs(m.y); - float ndotm2 = ndotm * ndotm; - float sinmn = native_sqrt(1.f - clamp(ndotm * ndotm, 0.f, 1.f)); - float tanmn = sinmn / ndotm; - float a2 = roughness * roughness; - float denom = (PI * ndotm2 * ndotm2 * (a2 + tanmn * tanmn) * (a2 + tanmn * tanmn)); - return denom > DENOM_EPS ? (a2 / denom) : 0.f; -} - -// PDF of the given direction -float MicrofacetDistribution_GGX_GetPdf( - // Halfway vector - float3 m, - // Rougness - float roughness, - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - float mpdf = MicrofacetDistribution_GGX_D(roughness, m) * fabs(m.y); - // See Humphreys and Pharr for derivation - float denom = (4.f * fabs(dot(wo, m))); - - return denom > DENOM_EPS ? mpdf / denom : 0.f; -} - -// Sample the distribution -void MicrofacetDistribution_GGX_SampleNormal( - // Roughness - float roughness, - // Differential geometry - DifferentialGeometry const* dg, - // Texture args - TEXTURE_ARG_LIST, - // Sample - float2 sample, - // Outgoing direction - float3* wh - ) -{ - float r1 = sample.x; - float r2 = sample.y; - - // Sample halfway vector first, then reflect wi around that - float theta = atan2(roughness * native_sqrt(r1), native_sqrt(1.f - r1)); - float costheta = native_cos(theta); - float sintheta = native_sin(theta); - - // phi = 2*PI*ksi2 - float phi = 2.f * PI * r2; - float cosphi = native_cos(phi); - float sinphi = native_sin(phi); - - // Calculate wh - *wh = make_float3(sintheta * cosphi, costheta, sintheta * sinphi); -} - -// -float MicrofacetDistribution_GGX_G1(float roughness, float3 v, float3 m) -{ - float ndotv = fabs(v.y); - float mdotv = fabs(dot(m, v)); - - float sinnv = native_sqrt(1.f - clamp(ndotv * ndotv, 0.f, 1.f)); - float tannv = sinnv / ndotv; - float a2 = roughness * roughness; - return 2.f / (1.f + native_sqrt(1.f + a2 * tannv * tannv)); -} - -// Shadowing function also depends on microfacet distribution -float MicrofacetDistribution_GGX_G(float roughness, float3 wi, float3 wo, float3 wh) -{ - return MicrofacetDistribution_GGX_G1(roughness, wi, wh) * MicrofacetDistribution_GGX_G1(roughness, wo, wh); -} - -float3 MicrofacetGGX_Evaluate( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - const float3 ks = Texture_GetValue3f(dg->mat.kx.xyz, dg->uv, TEXTURE_ARGS_IDX(dg->mat.kxmapidx)); - const float roughness = Texture_GetValue1f(dg->mat.ns, dg->uv, TEXTURE_ARGS_IDX(dg->mat.nsmapidx)); - - // Incident and reflected zenith angles - float costhetao = fabs(wo.y); - float costhetai = fabs(wi.y); - - // Calc halfway vector - float3 wh = normalize(wi + wo); - - float F = dg->mat.fresnel; - - float denom = (4.f * costhetao * costhetai); - - // F(eta) * D * G * ks / (4 * cosa * cosi) - //return denom > 0.f ? F * ks * MicrofacetDistribution_GGX_G(roughness, wi, wo, wh) * MicrofacetDistribution_GGX_D(roughness, wh) / denom : 0.f; - - float3 res = denom > 0.f ? F * ks * MicrofacetDistribution_GGX_G(roughness, wi, wo, wh) * MicrofacetDistribution_GGX_D(roughness, wh) / denom : 0.f; - if (length(res) < 0.1f) - res = 0.f; - return res; -} - - -float MicrofacetGGX_GetPdf( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - const float roughness = Texture_GetValue1f(dg->mat.ns, dg->uv, TEXTURE_ARGS_IDX(dg->mat.nsmapidx)); - - float3 wh = normalize(wo + wi); - - return MicrofacetDistribution_GGX_GetPdf(wh, roughness, dg, wi, wo, TEXTURE_ARGS); -} - -float3 MicrofacetGGX_Sample( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Texture args - TEXTURE_ARG_LIST, - // Sample - float2 sample, - // Outgoing direction - float3* wo, - // PDF at wo - float* pdf - ) -{ - const float roughness = Texture_GetValue1f(dg->mat.ns, dg->uv, TEXTURE_ARGS_IDX(dg->mat.nsmapidx)); - - float3 wh; - MicrofacetDistribution_GGX_SampleNormal(roughness, dg, TEXTURE_ARGS, sample, &wh); - - *wo = -wi + 2.f*fabs(dot(wi, wh)) * wh; - - *pdf = MicrofacetDistribution_GGX_GetPdf(wh, roughness, dg, wi, *wo, TEXTURE_ARGS); - - return MicrofacetGGX_Evaluate(dg, wi, *wo, TEXTURE_ARGS); -} - - -/* - Lambert BRDF - */ - /// Lambert BRDF evaluation -float3 Lambert_Evaluate( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - const float3 kd = Texture_GetValue3f(dg->mat.kx.xyz, dg->uv, TEXTURE_ARGS_IDX(dg->mat.kxmapidx)); - - float F = dg->mat.fresnel; - - return F * kd / PI; -} - -/// Lambert BRDF PDF -float Lambert_GetPdf( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - return fabs(wo.y) / PI; -} - -/// Lambert BRDF sampling -float3 Lambert_Sample( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Texture args - TEXTURE_ARG_LIST, - // Sample - float2 sample, - // Outgoing direction - float3* wo, - // PDF at wo - float* pdf - ) -{ - const float3 kd = Texture_GetValue3f(dg->mat.kx.xyz, dg->uv, TEXTURE_ARGS_IDX(dg->mat.kxmapidx)); - - *wo = Sample_MapToHemisphere(sample, make_float3(0.f, 1.f, 0.f) , 1.f); - - float F = dg->mat.fresnel; - - *pdf = fabs(wo->y) / PI; - - return F * kd / PI; -} - -/* - Ideal reflection BRDF - */ -float3 IdealReflect_Evaluate( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - return 0.f; -} - -/// Lambert BRDF sampling -float3 Translucent_Sample( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Texture args - TEXTURE_ARG_LIST, - // Sample - float2 sample, - // Outgoing direction - float3* wo, - // PDF at wo - float* pdf - ) -{ - const float3 kd = Texture_GetValue3f(dg->mat.kx.xyz, dg->uv, TEXTURE_ARGS_IDX(dg->mat.kxmapidx)); - - float ndotwi = wi.y; - - float3 n = ndotwi > DENOM_EPS ? make_float3(0.f, -1.f, 0.f) : make_float3(0.f, 1.f, 0.f); - - *wo = normalize(Sample_MapToHemisphere(sample, n, 1.f)); - - *pdf = fabs(wo->y) / PI; - - return kd / PI; -} - -// Lambert BRDF evaluation -float3 Translucent_Evaluate( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - const float3 kd = Texture_GetValue3f(dg->mat.kx.xyz, dg->uv, TEXTURE_ARGS_IDX(dg->mat.kxmapidx)); - - float ndotwi = wi.y; - float ndotwo = wo.y; - - if (ndotwi * ndotwo > 0.f) - return 0.f; - - return kd / PI; -} - -/// Lambert BRDF PDF -float Translucent_GetPdf( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - float ndotwi = wi.y; - float ndotwo = wo.y; - - if (ndotwi * ndotwo > 0) - return 0.f; - - return fabs(ndotwo) / PI; -} - -float IdealReflect_GetPdf( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - return 0.f; -} - -float3 IdealReflect_Sample( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Texture args - TEXTURE_ARG_LIST, - // Sample - float2 sample, - // Outgoing direction - float3* wo, - // PDF at wo - float* pdf - ) -{ - const float3 ks = Texture_GetValue3f(dg->mat.kx.xyz, dg->uv, TEXTURE_ARGS_IDX(dg->mat.kxmapidx)); - const float eta = dg->mat.ni; - - // Mirror reflect wi - *wo = normalize(make_float3(-wi.x, wi.y, -wi.z)); - - // PDF is infinite at that point, but deltas are going to cancel out while evaluating - // so set it to 1.f - *pdf = 1.f; - - float F = dg->mat.fresnel; - - float coswo = fabs(wo->y); - - // Return reflectance value - return coswo > DENOM_EPS ? (F * ks * (1.f / coswo)) : 0.f; -} - -/* - Ideal refraction BTDF - */ - -float3 IdealRefract_Evaluate( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - return 0.f; -} - -float IdealRefract_GetPdf( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - return 0.f; -} - -float3 IdealRefract_Sample( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Texture args - TEXTURE_ARG_LIST, - // Sample - float2 sample, - // Outgoing direction - float3* wo, - // PDF at wo - float* pdf - ) -{ - const float3 ks = Texture_GetValue3f(dg->mat.kx.xyz, dg->uv, TEXTURE_ARGS_IDX(dg->mat.kxmapidx)); - - float etai = 1.f; - float etat = dg->mat.ni; - float cosi = wi.y; - - bool entering = cosi > 0.f; - - // Revert normal and eta if needed - if (!entering) - { - float tmp = etai; - etai = etat; - etat = tmp; - } - - float eta = etai / etat; - float sini2 = 1.f - cosi * cosi; - float sint2 = eta * eta * sini2; - - if (sint2 >= 1.f) - { - *pdf = 0.f; - return 0.f; - } - - float cost = native_sqrt(max(0.f, 1.f - sint2)); - - // Transmitted ray - float F = dg->mat.fresnel; - - *wo = normalize(make_float3(eta * -wi.x, entering ? -cost : cost, eta * -wi.z)); - - *pdf = 1.f; - - return cost > DENOM_EPS ? (F * eta * eta * ks / cost) : 0.f; -} - - -float3 MicrofacetRefractionGGX_Evaluate( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - const float3 ks = Texture_GetValue3f(dg->mat.kx.xyz, dg->uv, TEXTURE_ARGS_IDX(dg->mat.kxmapidx)); - const float roughness = max(Texture_GetValue1f(dg->mat.ns, dg->uv, TEXTURE_ARGS_IDX(dg->mat.nsmapidx)), ROUGHNESS_EPS); - - float ndotwi = wi.y; - float ndotwo = wo.y; - - if (ndotwi * ndotwo >= 0.f) - { - return 0.f; - } - - float etai = 1.f; - float etat = dg->mat.ni; - - // Revert normal and eta if needed - if (ndotwi < 0.f) - { - float tmp = etai; - etai = etat; - etat = tmp; - } - - // Calc halfway vector - float3 ht = -(etai * wi + etat * wo); - float3 wh = normalize(ht); - - float widotwh = fabs(dot(wh, wi)); - float wodotwh = fabs(dot(wh, wo)); - - float F = dg->mat.fresnel; - - float denom = dot(ht, ht); - denom *= (fabs(ndotwi) * fabs(ndotwo)); - - return denom > DENOM_EPS ? (F * ks * (widotwh * wodotwh) * (etat)* (etat)* - MicrofacetDistribution_GGX_G(roughness, wi, wo, wh) * MicrofacetDistribution_GGX_D(roughness, wh) / denom) : 0.f; -} - - - -float MicrofacetRefractionGGX_GetPdf( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - const float roughness = max(Texture_GetValue1f(dg->mat.ns, dg->uv, TEXTURE_ARGS_IDX(dg->mat.nsmapidx)), ROUGHNESS_EPS); - float ndotwi = wi.y; - float ndotwo = wo.y; - - float etai = 1.f; - float etat = dg->mat.ni; - - if (ndotwi * ndotwo >= 0.f) - { - return 0.f; - } - - // Revert normal and eta if needed - if (ndotwi < 0.f) - { - float tmp = etai; - etai = etat; - etat = tmp; - } - - // Calc halfway vector - float3 ht = -(etai * wi + etat * wo); - - float3 wh = normalize(ht); - - float wodotwh = fabs(dot(wo, wh)); - - float whpdf = MicrofacetDistribution_GGX_D(roughness, wh) * fabs(wh.y); - - float whwo = wodotwh * etat * etat; - - float denom = dot(ht, ht); - - return denom > DENOM_EPS ? whpdf * whwo / denom : 0.f; -} - -float3 MicrofacetRefractionGGX_Sample( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Texture args - TEXTURE_ARG_LIST, - // Sample - float2 sample, - // Outgoing direction - float3* wo, - // PDF at wo - float* pdf - ) -{ - const float3 ks = Texture_GetValue3f(dg->mat.kx.xyz, dg->uv, TEXTURE_ARGS_IDX(dg->mat.kxmapidx)); - const float roughness = max(Texture_GetValue1f(dg->mat.ns, dg->uv, TEXTURE_ARGS_IDX(dg->mat.nsmapidx)), ROUGHNESS_EPS); - - float ndotwi = wi.y; - - if (ndotwi == 0.f) - { - *pdf = 0.f; - return 0.f; - } - - float etai = 1.f; - float etat = dg->mat.ni; - float s = 1.f; - - // Revert normal and eta if needed - if (ndotwi < 0.f) - { - float tmp = etai; - etai = etat; - etat = tmp; - s = -s; - } - - float3 wh; - MicrofacetDistribution_GGX_SampleNormal(roughness, dg, TEXTURE_ARGS, sample, &wh); - - float c = dot(wi, wh); - float eta = etai / etat; - - float d = 1 + eta * (c * c - 1); - - if (d <= 0.f) - { - *pdf = 0.f; - return 0.f; - } - - *wo = normalize((eta * c - s * native_sqrt(d)) * wh - eta * wi); - - *pdf = MicrofacetRefractionGGX_GetPdf(dg, wi, *wo, TEXTURE_ARGS); - - return MicrofacetRefractionGGX_Evaluate(dg, wi, *wo, TEXTURE_ARGS); -} - - - -float3 MicrofacetRefractionBeckmann_Evaluate( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - const float3 ks = Texture_GetValue3f(dg->mat.kx.xyz, dg->uv, TEXTURE_ARGS_IDX(dg->mat.kxmapidx)); - const float roughness = max(Texture_GetValue1f(dg->mat.ns, dg->uv, TEXTURE_ARGS_IDX(dg->mat.nsmapidx)), ROUGHNESS_EPS); - - float ndotwi = wi.y; - float ndotwo = wo.y; - - float etai = 1.f; - float etat = dg->mat.ni; - - // Revert normal and eta if needed - if (ndotwi < 0.f) - { - float tmp = etai; - etai = etat; - etat = tmp; - } - - // Calc halfway vector - float3 ht = -(etai * wi + etat * wo); - float3 wh = normalize(ht); - - float widotwh = fabs(dot(wh, wi)); - float wodotwh = fabs(dot(wh, wo)); - - float F = dg->mat.fresnel; - - float denom = dot(ht, ht); - denom *= (fabs(ndotwi) * fabs(ndotwo)); - - return denom > DENOM_EPS ? (F * ks * (widotwh * wodotwh) * (etat)* (etat)* - MicrofacetDistribution_Beckmann_G(roughness, wi, wo, wh) * MicrofacetDistribution_Beckmann_D(roughness, wh) / denom) : 0.f; -} - - - -float MicrofacetRefractionBeckmann_GetPdf( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - const float roughness = Texture_GetValue1f(dg->mat.ns, dg->uv, TEXTURE_ARGS_IDX(dg->mat.nsmapidx)); - float ndotwi = wi.y; - float ndotwo = wo.y; - - float etai = 1.f; - float etat = dg->mat.ni; - - // Revert normal and eta if needed - if (ndotwi < 0.f) - { - float tmp = etai; - etai = etat; - etat = tmp; - } - - // Calc halfway vector - float3 ht = -(etai * wi + etat * wo); - - float3 wh = normalize(ht); - - float wodotwh = fabs(dot(wo, wh)); - - float whpdf = MicrofacetDistribution_Beckmann_D(roughness, wh) * fabs(wh.y); - - float whwo = wodotwh * etat * etat; - - float denom = dot(ht, ht); - - return denom > DENOM_EPS ? whpdf * whwo / denom : 0.f; -} - -float3 MicrofacetRefractionBeckmann_Sample( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Texture args - TEXTURE_ARG_LIST, - // Sample - float2 sample, - // Outgoing direction - float3* wo, - // PDF at wo - float* pdf - ) -{ - const float3 ks = Texture_GetValue3f(dg->mat.kx.xyz, dg->uv, TEXTURE_ARGS_IDX(dg->mat.kxmapidx)); - const float roughness = Texture_GetValue1f(dg->mat.ns, dg->uv, TEXTURE_ARGS_IDX(dg->mat.nsmapidx)); - - float ndotwi = wi.y; - - float etai = 1.f; - float etat = dg->mat.ni; - float s = 1.f; - - // Revert normal and eta if needed - if (ndotwi < 0.f) - { - float tmp = etai; - etai = etat; - etat = tmp; - s = -s; - } - - float3 wh; - MicrofacetDistribution_Beckmann_SampleNormal(roughness, dg, TEXTURE_ARGS, sample, &wh); - - float c = dot(wi, wh); - float eta = etai / etat; - - float d = 1 + eta * (c * c - 1); - - if (d <= 0) - { - *pdf = 0.f; - return 0.f; - } - - *wo = normalize((eta * c - s * native_sqrt(d)) * wh - eta * wi); - - *pdf = MicrofacetRefractionBeckmann_GetPdf(dg, wi, *wo, TEXTURE_ARGS); - - return MicrofacetRefractionBeckmann_Evaluate(dg, wi, *wo, TEXTURE_ARGS); -} - -float3 Passthrough_Sample( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Texture args - TEXTURE_ARG_LIST, - // Sample - float2 sample, - // Outgoing direction - float3* wo, - // PDF at wo - float* pdf - ) -{ - - *wo = -wi; - float coswo = fabs(wo->y); - - // PDF is infinite at that point, but deltas are going to cancel out while evaluating - // so set it to 1.f - *pdf = 1.f; - - // - return coswo > 0.0001f ? (1.f / coswo) : 0.f; -} - -/* - Dispatch functions - */ -float3 Bxdf_Evaluate( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - // Transform vectors into tangent space - float3 wi_t = matrix_mul_vector3(dg->world_to_tangent, wi); - float3 wo_t = matrix_mul_vector3(dg->world_to_tangent, wo); - - int mattype = dg->mat.type; - switch (mattype) - { - case kLambert: - return Lambert_Evaluate(dg, wi_t, wo_t, TEXTURE_ARGS); - case kMicrofacetGGX: - return MicrofacetGGX_Evaluate(dg, wi_t, wo_t, TEXTURE_ARGS); - case kMicrofacetBeckmann: - return MicrofacetBeckmann_Evaluate(dg, wi_t, wo_t, TEXTURE_ARGS); - case kIdealReflect: - return IdealReflect_Evaluate(dg, wi_t, wo_t, TEXTURE_ARGS); - case kIdealRefract: - return IdealRefract_Evaluate(dg, wi_t, wo_t, TEXTURE_ARGS); - case kTranslucent: - return Translucent_Evaluate(dg, wi_t, wo_t, TEXTURE_ARGS); - case kMicrofacetRefractionGGX: - return MicrofacetRefractionGGX_Evaluate(dg, wi_t, wo_t, TEXTURE_ARGS); - case kMicrofacetRefractionBeckmann: - return MicrofacetRefractionBeckmann_Evaluate(dg, wi_t, wo_t, TEXTURE_ARGS); - } - - return 0.f; -} - -float3 Bxdf_Sample( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Texture args - TEXTURE_ARG_LIST, - // RNG - float2 sample, - // Outgoing direction - float3* wo, - // PDF at w - float* pdf - ) -{ - // Transform vectors into tangent space - float3 wi_t = matrix_mul_vector3(dg->world_to_tangent, wi); - float3 wo_t; - - float3 res = 0.f; - - int mattype = dg->mat.type; - switch (mattype) - { - case kLambert: - res = Lambert_Sample(dg, wi_t, TEXTURE_ARGS, sample, &wo_t, pdf); - break; - case kMicrofacetGGX: - res = MicrofacetGGX_Sample(dg, wi_t, TEXTURE_ARGS, sample, &wo_t, pdf); - break; - case kMicrofacetBeckmann: - res = MicrofacetBeckmann_Sample(dg, wi_t, TEXTURE_ARGS, sample, &wo_t, pdf); - break; - case kIdealReflect: - res = IdealReflect_Sample(dg, wi_t, TEXTURE_ARGS, sample, &wo_t, pdf); - break; - case kIdealRefract: - res = IdealRefract_Sample(dg, wi_t, TEXTURE_ARGS, sample, &wo_t, pdf); - break; - case kTranslucent: - res = Translucent_Sample(dg, wi_t, TEXTURE_ARGS, sample, &wo_t, pdf); - break; - case kPassthrough: - res = Passthrough_Sample(dg, wi_t, TEXTURE_ARGS, sample, &wo_t, pdf); - break; - case kMicrofacetRefractionGGX: - res = MicrofacetRefractionGGX_Sample(dg, wi_t, TEXTURE_ARGS, sample, &wo_t, pdf); - break; - case kMicrofacetRefractionBeckmann: - res = MicrofacetRefractionBeckmann_Sample(dg, wi_t, TEXTURE_ARGS, sample, &wo_t, pdf); - break; - default: - *pdf = 0.f; - break; - } - - *wo = matrix_mul_vector3(dg->tangent_to_world, wo_t); - - return res; -} - -float Bxdf_GetPdf( - // Geometry - DifferentialGeometry const* dg, - // Incoming direction - float3 wi, - // Outgoing direction - float3 wo, - // Texture args - TEXTURE_ARG_LIST - ) -{ - // Transform vectors into tangent space - float3 wi_t = matrix_mul_vector3(dg->world_to_tangent, wi); - float3 wo_t = matrix_mul_vector3(dg->world_to_tangent, wo); - - int mattype = dg->mat.type; - switch (mattype) - { - case kLambert: - return Lambert_GetPdf(dg, wi_t, wo_t, TEXTURE_ARGS); - case kMicrofacetGGX: - return MicrofacetGGX_GetPdf(dg, wi_t, wo_t, TEXTURE_ARGS); - case kMicrofacetBeckmann: - return MicrofacetBeckmann_GetPdf(dg, wi_t, wo_t, TEXTURE_ARGS); - case kIdealReflect: - return IdealReflect_GetPdf(dg, wi_t, wo_t, TEXTURE_ARGS); - case kIdealRefract: - return IdealRefract_GetPdf(dg, wi_t, wo_t, TEXTURE_ARGS); - case kTranslucent: - return Translucent_GetPdf(dg, wi_t, wo_t, TEXTURE_ARGS); - case kPassthrough: - return 0.f; - case kMicrofacetRefractionGGX: - return MicrofacetRefractionGGX_GetPdf(dg, wi_t, wo_t, TEXTURE_ARGS); - case kMicrofacetRefractionBeckmann: - return MicrofacetRefractionBeckmann_GetPdf(dg, wi_t, wo_t, TEXTURE_ARGS); - } - - return 0.f; -} - -/// Emissive BRDF sampling -float3 Emissive_GetLe( - // Geometry - DifferentialGeometry const* dg, - // Texture args - TEXTURE_ARG_LIST) -{ - const float3 kd = Texture_GetValue3f(dg->mat.kx.xyz, dg->uv, TEXTURE_ARGS_IDX(dg->mat.kxmapidx)); - return kd; -} - - -/// BxDF singularity check -bool Bxdf_IsSingular(DifferentialGeometry const* dg) -{ - return dg->mat.type == kIdealReflect || dg->mat.type == kIdealRefract || dg->mat.type == kPassthrough; -} - -/// BxDF emission check -bool Bxdf_IsEmissive(DifferentialGeometry const* dg) -{ - return dg->mat.type == kEmissive; -} - -/// BxDF singularity check -bool Bxdf_IsBtdf(DifferentialGeometry const* dg) -{ - return dg->mat.type == kIdealRefract || dg->mat.type == kPassthrough || dg->mat.type == kTranslucent || - dg->mat.type == kMicrofacetRefractionGGX || dg->mat.type == kMicrofacetRefractionBeckmann; -} - -#endif // BXDF_CL diff --git a/Baikal/CL/cache/kernels.h b/Baikal/CL/cache/kernels.h deleted file mode 100644 index 767f4ffc..00000000 --- a/Baikal/CL/cache/kernels.h +++ /dev/null @@ -1,1701 +0,0 @@ -/********************************************************************** -Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. - -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. -********************************************************************/ - -static const char cl_sh[]= \ -" \n"\ -"#define MAX_BAND 2 \n"\ -"#define PI 3.14159265358979323846f \n"\ -" \n"\ -"enum TextureFormat \n"\ -"{ \n"\ -" UNKNOWN, \n"\ -" RGBA8, \n"\ -" RGBA16, \n"\ -" RGBA32 \n"\ -"}; \n"\ -" \n"\ -"// Texture description \n"\ -"typedef struct _Texture \n"\ -"{ \n"\ -" // Texture width, height and depth \n"\ -" int w; \n"\ -" int h; \n"\ -" int d; \n"\ -" // Offset in texture data array \n"\ -" int dataoffset; \n"\ -" int fmt; \n"\ -" int extra; \n"\ -"} Texture; \n"\ -" \n"\ -" \n"\ -"float3 make_float3(float x, float y, float z) \n"\ -"{ \n"\ -" float3 res; \n"\ -" res.x = x; \n"\ -" res.y = y; \n"\ -" res.z = z; \n"\ -" return res; \n"\ -"} \n"\ -" \n"\ -" \n"\ -"void CartesianToSpherical ( float3 cart, float* r, float* phi, float* theta ) \n"\ -"{ \n"\ -" float temp = atan2(cart.x, cart.z); \n"\ -" *r = sqrt(cart.x*cart.x + cart.y*cart.y + cart.z*cart.z); \n"\ -" *phi = (float)((temp >= 0)?temp:(temp + 2*PI)); \n"\ -" *theta = acos(cart.y/ *r); \n"\ -"} \n"\ -" \n"\ -" \n"\ -"/// Sample 2D texture described by texture in texturedata pool \n"\ -"float3 Sample2D(Texture const* texture, __global char const* texturedata, float2 uv) \n"\ -"{ \n"\ -" // Get width and height \n"\ -" int width = texture->w; \n"\ -" int height = texture->h; \n"\ -" \n"\ -" // Find the origin of the data in the pool \n"\ -" __global char const* mydata = texturedata + texture->dataoffset; \n"\ -" \n"\ -" // Handle wrap \n"\ -" uv -= floor(uv); \n"\ -" \n"\ -" // Reverse Y \n"\ -" // it is needed as textures are loaded with Y axis going top to down \n"\ -" // and our axis goes from down to top \n"\ -" uv.y = 1.f - uv.y; \n"\ -" \n"\ -" // Figure out integer coordinates \n"\ -" int x = floor(uv.x * width); \n"\ -" int y = floor(uv.y * height); \n"\ -" \n"\ -" // Calculate samples for linear filtering \n"\ -" int x1 = min(x + 1, width - 1); \n"\ -" int y1 = min(y + 1, height - 1); \n"\ -" \n"\ -" // Calculate weights for linear filtering \n"\ -" float wx = uv.x * width - floor(uv.x * width); \n"\ -" float wy = uv.y * height - floor(uv.y * height); \n"\ -" \n"\ -" if (texture->fmt == RGBA32) \n"\ -" { \n"\ -" __global float3 const* mydataf = (__global float3 const*)mydata; \n"\ -" \n"\ -" // Get 4 values \n"\ -" float3 valx = *(mydataf + width * y + x); \n"\ -" \n"\ -" // Filter and return the result \n"\ -" return valx; \n"\ -" } \n"\ -" else if (texture->fmt == RGBA16) \n"\ -" { \n"\ -" __global half const* mydatah = (__global half const*)mydata; \n"\ -" \n"\ -" float valx = vload_half(0, mydatah + 4*(width * y + x)); \n"\ -" float valy = vload_half(0, mydatah + 4*(width * y + x) + 1); \n"\ -" float valz = vload_half(0, mydatah + 4*(width * y + x) + 2); \n"\ -" \n"\ -" return make_float3(valx, valy, valz); \n"\ -" } \n"\ -" else \n"\ -" { \n"\ -" __global uchar4 const* mydatac = (__global uchar4 const*)mydata; \n"\ -" \n"\ -" // Get 4 values \n"\ -" uchar4 valx = *(mydatac + width * y + x); \n"\ -" \n"\ -" float3 valxf = make_float3((float)valx.x / 255.f, (float)valx.y / 255.f, (float)valx.z / 255.f); \n"\ -" \n"\ -" // Filter and return the result \n"\ -" return valxf; \n"\ -" } \n"\ -"} \n"\ -" \n"\ -" \n"\ -"void ShEvaluate(float3 p, float* coeffs) \n"\ -"{ \n"\ -" float fC0, fC1, fS0, fS1, fTmpA, fTmpB, fTmpC; \n"\ -" float pz2 = p.z * p.z; \n"\ -" coeffs[0] = 0.2820947917738781f; \n"\ -" coeffs[2] = 0.4886025119029199f * p.z; \n"\ -" coeffs[6] = 0.9461746957575601f * pz2 + -0.3153915652525201f; \n"\ -" fC0 = p.x; \n"\ -" fS0 = p.y; \n"\ -" fTmpA = -0.48860251190292f; \n"\ -" coeffs[3] = fTmpA * fC0; \n"\ -" coeffs[1] = fTmpA * fS0; \n"\ -" fTmpB = -1.092548430592079f * p.z; \n"\ -" coeffs[7] = fTmpB * fC0; \n"\ -" coeffs[5] = fTmpB * fS0; \n"\ -" fC1 = p.x*fC0 - p.y*fS0; \n"\ -" fS1 = p.x*fS0 + p.y*fC0; \n"\ -" fTmpC = 0.5462742152960395f; \n"\ -" coeffs[8] = fTmpC * fC1; \n"\ -" coeffs[4] = fTmpC * fS1; \n"\ -"} \n"\ -" \n"\ -"__attribute__((reqd_work_group_size(8, 8, 1))) \n"\ -"///< Project the function represented by lat-long map lmmap to Sh up to lmax band \n"\ -"__kernel void ShProject( \n"\ -" __global Texture const* textures, \n"\ -" // Texture data \n"\ -" __global char const* texturedata, \n"\ -" // Environment texture index \n"\ -" int envmapidx, \n"\ -" // Harmonic coefficients flattened: NumShTerms(lmax) * num_groups \n"\ -" __global float3* coeffs \n"\ -" ) \n"\ -"{ \n"\ -" // Temporary work area for trigonom results \n"\ -" __local float3 cx[64]; \n"\ -" \n"\ -" int x = get_global_id(0); \n"\ -" int y = get_global_id(1); \n"\ -" \n"\ -" int xl = get_local_id(0); \n"\ -" int yl = get_local_id(1); \n"\ -" int wl = get_local_size(0); \n"\ -" \n"\ -" int ngx = get_num_groups(0); \n"\ -" int gx = get_group_id(0); \n"\ -" int gy = get_group_id(1); \n"\ -" int g = gy * ngx + gx; \n"\ -" \n"\ -" int lid = yl * wl + xl; \n"\ -" \n"\ -" Texture envmap = textures[envmapidx]; \n"\ -" int w = envmap.w; \n"\ -" int h = envmap.h; \n"\ -" \n"\ -" if (x < w && y < h) \n"\ -" { \n"\ -" // Calculate spherical angles \n"\ -" float thetastep = PI / h; \n"\ -" float phistep = 2.f*PI / w; \n"\ -" float theta0 = 0;//PI / h / 2.f; \n"\ -" float phi0 = 0;//2.f*PI / w / 2.f; \n"\ -" \n"\ -" float phi = phi0 + x * phistep; \n"\ -" float theta = theta0 + y * thetastep; \n"\ -" \n"\ -" float2 uv; \n"\ -" uv.x = (float)x/w; \n"\ -" uv.y = 1.f - (float)y/h; \n"\ -" float3 le = 3.f * Sample2D(&envmap, texturedata, uv); \n"\ -" \n"\ -" float sinphi = sin(phi); \n"\ -" float cosphi = cos(phi); \n"\ -" float costheta = cos(theta); \n"\ -" float sintheta = sin(theta); \n"\ -" \n"\ -" // Construct point on unit sphere \n"\ -" float3 p = normalize(make_float3(sintheta * cosphi, costheta, sintheta * sinphi)); \n"\ -" \n"\ -" // Evaluate SH functions at w up to lmax band \n"\ -" float ylm[9]; \n"\ -" ShEvaluate(p, ylm); \n"\ -" \n"\ -" // Evaluate Riemann sum \n"\ -" for (int i = 0; i < 9; ++i) \n"\ -" { \n"\ -" // Calculate the coefficient into local memory \n"\ -" cx[lid] = le * ylm[i] * sintheta * (PI / h) * (2.f * PI / w); \n"\ -" \n"\ -" barrier(CLK_LOCAL_MEM_FENCE); \n"\ -" \n"\ -" // Reduce the coefficient to get the resulting one \n"\ -" for (int stride = 1; stride <= (64 >> 1); stride <<= 1) \n"\ -" { \n"\ -" if (lid < 64/(2*stride)) \n"\ -" { \n"\ -" cx[2*(lid + 1)*stride-1] = cx[2*(lid + 1)*stride-1] + cx[(2*lid + 1)*stride-1]; \n"\ -" } \n"\ -" \n"\ -" barrier(CLK_LOCAL_MEM_FENCE); \n"\ -" } \n"\ -" \n"\ -" // Put the coefficient into global memory \n"\ -" if (lid == 0) \n"\ -" { \n"\ -" coeffs[g * 9 + i] = cx[63]; \n"\ -" } \n"\ -" \n"\ -" barrier(CLK_LOCAL_MEM_FENCE); \n"\ -" } \n"\ -" } \n"\ -"} \n"\ -" \n"\ -"__attribute__((reqd_work_group_size(8, 8, 1))) \n"\ -"///< Project the function represented by lat-long map lmmap to Sh up to lmax band \n"\ -"__kernel void ShProjectHemisphericalProbe( \n"\ -" __global Texture const* textures, \n"\ -" // Texture data \n"\ -" __global char const* texturedata, \n"\ -" // Environment texture index \n"\ -" int envmapidx, \n"\ -" // Harmonic coefficients flattened: NumShTerms(lmax) * num_groups \n"\ -" __global float3* coeffs \n"\ -" ) \n"\ -"{ \n"\ -" // Temporary work area for trigonom results \n"\ -" __local float3 cx[64]; \n"\ -" \n"\ -" int x = get_global_id(0); \n"\ -" int y = get_global_id(1); \n"\ -" \n"\ -" int xl = get_local_id(0); \n"\ -" int yl = get_local_id(1); \n"\ -" int wl = get_local_size(0); \n"\ -" \n"\ -" int ngx = get_num_groups(0); \n"\ -" int gx = get_group_id(0); \n"\ -" int gy = get_group_id(1); \n"\ -" int g = gy * ngx + gx; \n"\ -" \n"\ -" int lid = yl * wl + xl; \n"\ -" \n"\ -" Texture envmap = textures[envmapidx]; \n"\ -" int w = envmap.w; \n"\ -" int h = envmap.h; \n"\ -" \n"\ -" if (x < w && y < h) \n"\ -" { \n"\ -" // Calculate spherical angles \n"\ -" float thetastep = PI / h; \n"\ -" float phistep = 2.f*PI / w; \n"\ -" float theta0 = 0;//PI / h / 2.f; \n"\ -" float phi0 = 0;//2.f*PI / w / 2.f; \n"\ -" \n"\ -" float phi = phi0 + x * phistep; \n"\ -" float theta = theta0 + y * thetastep; \n"\ -" \n"\ -" float sinphi = sin(phi); \n"\ -" float cosphi = cos(phi); \n"\ -" float costheta = cos(theta); \n"\ -" float sintheta = sin(theta); \n"\ -" \n"\ -" // Construct point on unit sphere \n"\ -" float3 p = normalize(make_float3(sintheta * cosphi, costheta, sintheta * sinphi)); \n"\ -" \n"\ -" float envmapaspect = (float)envmap.h / envmap.w; \n"\ -" float2 uv = p.xz; \n"\ -" uv.y = 0.5f*uv.y + 0.5f; \n"\ -" uv.x = 0.5f*uv.x + 0.5f; \n"\ -" uv.x = (1.f - envmapaspect) * 0.5f + uv.x * envmapaspect; \n"\ -" \n"\ -" //uv.x = (float)x/w; \n"\ -" //uv.y = 1.f - (float)y/h; \n"\ -" float3 le = Sample2D(&envmap, texturedata, uv); \n"\ -" \n"\ -" // Evaluate SH functions at w up to lmax band \n"\ -" float ylm[9]; \n"\ -" ShEvaluate(p, ylm); \n"\ -" \n"\ -" // Evaluate Riemann sum \n"\ -" for (int i = 0; i < 9; ++i) \n"\ -" { \n"\ -" // Calculate the coefficient into local memory \n"\ -" cx[lid] = le * ylm[i] * sintheta * (PI / h) * (2.f * PI / w); \n"\ -" \n"\ -" barrier(CLK_LOCAL_MEM_FENCE); \n"\ -" \n"\ -" // Reduce the coefficient to get the resulting one \n"\ -" for (int stride = 1; stride <= (64 >> 1); stride <<= 1) \n"\ -" { \n"\ -" if (lid < 64/(2*stride)) \n"\ -" { \n"\ -" cx[2*(lid + 1)*stride-1] = cx[2*(lid + 1)*stride-1] + cx[(2*lid + 1)*stride-1]; \n"\ -" } \n"\ -" \n"\ -" barrier(CLK_LOCAL_MEM_FENCE); \n"\ -" } \n"\ -" \n"\ -" // Put the coefficient into global memory \n"\ -" if (lid == 0) \n"\ -" { \n"\ -" coeffs[g * 9 + i] = cx[63]; \n"\ -" } \n"\ -" \n"\ -" barrier(CLK_LOCAL_MEM_FENCE); \n"\ -" } \n"\ -" } \n"\ -"} \n"\ -" \n"\ -" \n"\ -"#define GROUP_SIZE 256 \n"\ -"__attribute__((reqd_work_group_size(GROUP_SIZE, 1, 1))) \n"\ -"__kernel void ShReduce( \n"\ -" // Harmonic coefficients flattened: NumShTerms(lmax) * num_groups \n"\ -" const __global float3* coeffs, \n"\ -" // Number of sets \n"\ -" int numsets, \n"\ -" // Resulting coeffs \n"\ -" __global float3* result \n"\ -" ) \n"\ -"{ \n"\ -" __local float3 lds[GROUP_SIZE]; \n"\ -" \n"\ -" int gid = get_global_id(0); \n"\ -" int lid = get_global_id(0); \n"\ -" \n"\ -" // How many items to reduce for a single work item \n"\ -" int numprivate = numsets / GROUP_SIZE; \n"\ -" \n"\ -" for (int i=0;i<9;++i) \n"\ -" { \n"\ -" float3 res = {0,0,0}; \n"\ -" \n"\ -" // Private reduction \n"\ -" for (int j=0;j> 1); stride <<= 1) \n"\ -" { \n"\ -" if (lid < GROUP_SIZE/(2*stride)) \n"\ -" { \n"\ -" lds[2*(lid + 1)*stride-1] = lds[2*(lid + 1)*stride-1] + lds[(2*lid + 1)*stride-1]; \n"\ -" } \n"\ -" \n"\ -" barrier (CLK_LOCAL_MEM_FENCE); \n"\ -" } \n"\ -" \n"\ -" // Write final result \n"\ -" if (lid == 0) \n"\ -" { \n"\ -" result[i] = lds[GROUP_SIZE-1]; \n"\ -" } \n"\ -" \n"\ -" barrier (CLK_LOCAL_MEM_FENCE); \n"\ -" } \n"\ -"} \n"\ -"#undef GROUP_SIZE \n"\ -" \n"\ -" \n"\ -"__attribute__((reqd_work_group_size(8, 8, 1))) \n"\ -"__kernel void ShReconstructLmmap( \n"\ -" // SH coefficients: NumShTerms(lmax) items \n"\ -" const __global float3* coeffs, \n"\ -" // Resulting image width \n"\ -" int w, \n"\ -" // Resulting image height \n"\ -" int h, \n"\ -" // Resulting image \n"\ -" __global float3* lmmap \n"\ -" ) \n"\ -"{ \n"\ -" int x = get_global_id(0); \n"\ -" int y = get_global_id(1); \n"\ -" \n"\ -" int xl = get_local_id(0); \n"\ -" int yl = get_local_id(1); \n"\ -" int wl = get_local_size(0); \n"\ -" \n"\ -" int ngx = get_num_groups(0); \n"\ -" int gx = get_group_id(0); \n"\ -" int gy = get_group_id(1); \n"\ -" \n"\ -" if (x < w && y < h) \n"\ -" { \n"\ -" // Calculate spherical angles \n"\ -" float thetastep = M_PI / h; \n"\ -" float phistep = 2.f*M_PI / w; \n"\ -" float theta0 = 0;//M_PI / h / 2.f; \n"\ -" float phi0 = 0;//2.f*M_PI / w / 2.f; \n"\ -" \n"\ -" float phi = phi0 + x * phistep; \n"\ -" float theta = theta0 + y * thetastep; \n"\ -" \n"\ -" float2 uv; \n"\ -" uv.x = (float)x/w; \n"\ -" uv.y = (float)y/h; \n"\ -" \n"\ -" float sinphi = sin(phi); \n"\ -" float cosphi = cos(phi); \n"\ -" float costheta = cos(theta); \n"\ -" float sintheta = sin(theta); \n"\ -" \n"\ -" // Construct point on unit sphere \n"\ -" float3 p = normalize(make_float3(sintheta * cosphi, costheta, sintheta * sinphi)); \n"\ -" \n"\ -" // Evaluate SH functions at w up to lmax band \n"\ -" float ylm[9]; \n"\ -" ShEvaluate(p, ylm); \n"\ -" \n"\ -" // Evaluate Riemann sum \n"\ -" float3 val = {0, 0, 0}; \n"\ -" for (int i = 0; i < 9; ++i) \n"\ -" { \n"\ -" // Calculate the coefficient into local memory \n"\ -" val += ylm[i] * coeffs[i]; \n"\ -" } \n"\ -" \n"\ -" int x = floor(uv.x * w); \n"\ -" int y = floor(uv.y * h); \n"\ -" \n"\ -" lmmap[w * y + x] = val; \n"\ -" } \n"\ -"} \n"\ -; -static const char cl_app[]= \ -" \n"\ -"#define PI 3.14159265358979323846f \n"\ -" \n"\ -"typedef struct _ray \n"\ -"{ \n"\ -" float4 o; \n"\ -" float4 d; \n"\ -"} ray; \n"\ -" \n"\ -"typedef struct __attribute__ ((packed)) _Intersection \n"\ -"{ \n"\ -" float4 uvwt; \n"\ -" int shapeid; \n"\ -" int primid; \n"\ -"} Intersection; \n"\ -" \n"\ -"typedef struct _Camera \n"\ -"{ \n"\ -" // Camera coordinate frame \n"\ -" float3 forward; \n"\ -" float3 right; \n"\ -" float3 up; \n"\ -" float3 p; \n"\ -" \n"\ -" // Image plane width & height in scene units \n"\ -" float2 dim; \n"\ -" \n"\ -" // Near and far Z \n"\ -" float2 zcap; \n"\ -" float fovy; \n"\ -" float aspect; \n"\ -"} Camera; \n"\ -" \n"\ -"typedef struct _Rng \n"\ -"{ \n"\ -" uint val; \n"\ -"} Rng; \n"\ -" \n"\ -"typedef struct _Material \n"\ -"{ \n"\ -" float4 kd; \n"\ -" float4 ks; \n"\ -" float3 ke; \n"\ -" int kdmapidx; \n"\ -" int nmapidx; \n"\ -" float metallic; \n"\ -" float subsurface; \n"\ -" float specular; \n"\ -" float roughness; \n"\ -" float speculartint; \n"\ -" float anisotropic; \n"\ -" float sheen; \n"\ -" float sheentint; \n"\ -" float clearcoat; \n"\ -" float clearcoatgloss; \n"\ -"} Material; \n"\ -" \n"\ -"enum TextureFormat \n"\ -"{ \n"\ -" UNKNOWN, \n"\ -" RGBA8, \n"\ -" RGBA16, \n"\ -" RGBA32 \n"\ -"}; \n"\ -" \n"\ -"// Texture description \n"\ -"typedef struct _Texture \n"\ -"{ \n"\ -" // Texture width, height and depth \n"\ -" int w; \n"\ -" int h; \n"\ -" int d; \n"\ -" // Offset in texture data array \n"\ -" int dataoffset; \n"\ -" int fmt; \n"\ -" int extra; \n"\ -"} Texture; \n"\ -" \n"\ -"// Shape description \n"\ -"typedef struct _Shape \n"\ -"{ \n"\ -" // Shape starting index in indices_ array \n"\ -" int startidx; \n"\ -" // Number of primitives in the shape \n"\ -" int numprims; \n"\ -" // Start vertex \n"\ -" int startvtx; \n"\ -" // Number of vertices \n"\ -" int numvertices; \n"\ -" // Linear motion vector \n"\ -" float3 linearvelocity; \n"\ -" // Angular velocity \n"\ -" float4 angularvelocity; \n"\ -" // Transform \n"\ -" float4 m0; \n"\ -" float4 m1; \n"\ -" float4 m2; \n"\ -" float4 m3; \n"\ -"} Shape; \n"\ -" \n"\ -"// Emissive object \n"\ -"typedef struct _Emissive \n"\ -"{ \n"\ -" // Shape index \n"\ -" int shapeidx; \n"\ -" // Polygon index \n"\ -" int primidx; \n"\ -"} Emissive; \n"\ -" \n"\ -" \n"\ -"// Unitility functions \n"\ -"#ifndef APPLE \n"\ -" \n"\ -"float4 make_float4(float x, float y, float z, float w) \n"\ -"{ \n"\ -" float4 res; \n"\ -" res.x = x; \n"\ -" res.y = y; \n"\ -" res.z = z; \n"\ -" res.w = w; \n"\ -" return res; \n"\ -"} \n"\ -" \n"\ -"float3 make_float3(float x, float y, float z) \n"\ -"{ \n"\ -" float3 res; \n"\ -" res.x = x; \n"\ -" res.y = y; \n"\ -" res.z = z; \n"\ -" return res; \n"\ -"} \n"\ -" \n"\ -"float2 make_float2(float x, float y) \n"\ -"{ \n"\ -" float2 res; \n"\ -" res.x = x; \n"\ -" res.y = y; \n"\ -" return res; \n"\ -"} \n"\ -" \n"\ -"int2 make_int2(int x, int y) \n"\ -"{ \n"\ -" int2 res; \n"\ -" res.x = x; \n"\ -" res.y = y; \n"\ -" return res; \n"\ -"} \n"\ -" \n"\ -"#endif \n"\ -" \n"\ -"float3 transform_point(float3 p, float4 m0, float4 m1, float4 m2, float4 m3) \n"\ -"{ \n"\ -" float3 res; \n"\ -" res.x = m0.s0 * p.x + m0.s1 * p.y + m0.s2 * p.z + m0.s3; \n"\ -" res.y = m1.s0 * p.x + m1.s1 * p.y + m1.s2 * p.z + m1.s3; \n"\ -" res.z = m2.s0 * p.x + m2.s1 * p.y + m2.s2 * p.z + m2.s3; \n"\ -" return res; \n"\ -"} \n"\ -" \n"\ -"float3 transform_vector(float3 p, float4 m0, float4 m1, float4 m2, float4 m3) \n"\ -"{ \n"\ -" float3 res; \n"\ -" res.x = m0.s0 * p.x + m0.s1 * p.y + m0.s2 * p.z; \n"\ -" res.y = m1.s0 * p.x + m1.s1 * p.y + m1.s2 * p.z; \n"\ -" res.z = m2.s0 * p.x + m2.s1 * p.y + m2.s2 * p.z; \n"\ -" return res; \n"\ -"} \n"\ -" \n"\ -"float4 quaternion_mul(float4 q1, float4 q2) \n"\ -"{ \n"\ -" float4 res; \n"\ -" res.x = q1.y*q2.z - q1.z*q2.y + q2.w*q1.x + q1.w*q2.x; \n"\ -" res.y = q1.z*q2.x - q1.x*q2.z + q2.w*q1.y + q1.w*q2.y; \n"\ -" res.z = q1.x*q2.y - q2.x*q1.y + q2.w*q1.z + q1.w*q2.z; \n"\ -" res.w = q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z; \n"\ -" return res; \n"\ -"} \n"\ -" \n"\ -"float4 quaternion_conjugate(float4 q) \n"\ -"{ \n"\ -" return make_float4(-q.x, -q.y, -q.z, q.w); \n"\ -"} \n"\ -" \n"\ -"float4 quaternion_inverse(float4 q) \n"\ -"{ \n"\ -" float sqnorm = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w; \n"\ -" \n"\ -" if (sqnorm != 0.f) \n"\ -" { \n"\ -" return quaternion_conjugate(q) / sqnorm; \n"\ -" } \n"\ -" else \n"\ -" { \n"\ -" return make_float4(0.f, 0.f, 0.f, 1.f); \n"\ -" } \n"\ -"} \n"\ -" \n"\ -"float3 rotate_vector(float3 v, float4 q) \n"\ -"{ \n"\ -" float4 qinv = quaternion_inverse(q); \n"\ -" float4 vv = make_float4(v.x, v.y, v.z, 0); \n"\ -" return quaternion_mul(q, quaternion_mul(vv, qinv)).xyz; \n"\ -"} \n"\ -" \n"\ -"uint WangHash(uint seed) \n"\ -"{ \n"\ -" seed = (seed ^ 61) ^ (seed >> 16); \n"\ -" seed *= 9; \n"\ -" seed = seed ^ (seed >> 4); \n"\ -" seed *= 0x27d4eb2d; \n"\ -" seed = seed ^ (seed >> 15); \n"\ -" return seed; \n"\ -"} \n"\ -" \n"\ -"uint RandUint(Rng* rng) \n"\ -"{ \n"\ -" rng->val = WangHash(1664525U * rng->val + 1013904223U); \n"\ -" return rng->val; \n"\ -"} \n"\ -" \n"\ -"float RandFloat(Rng* rng) \n"\ -"{ \n"\ -" return ((float)RandUint(rng)) / 0xffffffffU; \n"\ -"} \n"\ -" \n"\ -"void InitRng(uint seed, Rng* rng) \n"\ -"{ \n"\ -" rng->val = WangHash(seed); \n"\ -" for (int i=0;i<100;++i) \n"\ -" RandFloat(rng); \n"\ -"} \n"\ -" \n"\ -"float3 lerp(float3 a, float3 b, float w) \n"\ -"{ \n"\ -" return a + w*(b-a); \n"\ -"} \n"\ -" \n"\ -"void CartesianToSpherical ( float3 cart, float* r, float* phi, float* theta ) \n"\ -"{ \n"\ -" float temp = atan2(cart.x, cart.z); \n"\ -" *r = sqrt(cart.x*cart.x + cart.y*cart.y + cart.z*cart.z); \n"\ -" *phi = (float)((temp >= 0)?temp:(temp + 2*PI)); \n"\ -" *theta = acos(cart.y/ *r); \n"\ -"} \n"\ -" \n"\ -"/// Uniformly sample a triangle \n"\ -"void SampleTriangleUniform( \n"\ -" // RNG to use \n"\ -" Rng* rng, \n"\ -" // Triangle vertices \n"\ -" float3 v0, \n"\ -" float3 v1, \n"\ -" float3 v2, \n"\ -" // Triangle normals \n"\ -" float3 n0, \n"\ -" float3 n1, \n"\ -" float3 n2, \n"\ -" // Point and normal \n"\ -" float3* p, \n"\ -" float3* n, \n"\ -" // PDF \n"\ -" float* pdf \n"\ -" ) \n"\ -"{ \n"\ -" // Sample 2D value \n"\ -" float a = RandFloat(rng); \n"\ -" float b = RandFloat(rng); \n"\ -" \n"\ -" // Calculate point \n"\ -" *p = (1.f - sqrt(a)) * v0.xyz + sqrt(a) * (1.f - b) * v1.xyz + sqrt(a) * b * v2.xyz; \n"\ -" // Calculate normal \n"\ -" *n = normalize((1.f - sqrt(a)) * n0.xyz + sqrt(a) * (1.f - b) * n1.xyz + sqrt(a) * b * n2.xyz); \n"\ -" // PDF \n"\ -" *pdf = 1.f / (length(cross((v2-v0), (v1-v0))) * 0.5f); \n"\ -"} \n"\ -" \n"\ -"/// Get vector orthogonal to a given one \n"\ -"float3 GetOrthoVector(float3 n) \n"\ -"{ \n"\ -" float3 p; \n"\ -" if (fabs(n.z) > 0.707106781186547524401f) { \n"\ -" float k = sqrt(n.y*n.y + n.z*n.z); \n"\ -" p.x = 0; p.y = -n.z/k; p.z = n.y/k; \n"\ -" } \n"\ -" else { \n"\ -" float k = sqrt(n.x*n.x + n.y*n.y); \n"\ -" p.x = -n.y/k; p.y = n.x/k; p.z = 0; \n"\ -" } \n"\ -" \n"\ -" return p; \n"\ -"} \n"\ -" \n"\ -"///< Power heuristic for multiple importance sampling \n"\ -"float PowerHeuristic(int nf, float fpdf, int ng, float gpdf) \n"\ -"{ \n"\ -" float f = nf * fpdf; \n"\ -" float g = ng * gpdf; \n"\ -" return (f*f) / (f*f + g*g); \n"\ -"} \n"\ -" \n"\ -"///< Sample hemisphere with cos weight \n"\ -"float3 SampleHemisphere( \n"\ -" // RNG to use \n"\ -" Rng* rng, \n"\ -" // Hemisphere normal \n"\ -" float3 n, \n"\ -" // Cos power \n"\ -" float e) \n"\ -"{ \n"\ -" // Construct basis \n"\ -" float3 u = GetOrthoVector(n); \n"\ -" float3 v = cross(u, n); \n"\ -" u = cross(n, v); \n"\ -" \n"\ -" // Calculate 2D sample \n"\ -" float r1 = RandFloat(rng); \n"\ -" float r2 = RandFloat(rng); \n"\ -" \n"\ -" // Transform to spherical coordinates \n"\ -" float sinpsi = sin(2*PI*r1); \n"\ -" float cospsi = cos(2*PI*r1); \n"\ -" float costheta = pow(1.f - r2, 1.f/(e + 1.f)); \n"\ -" float sintheta = sqrt(1.f - costheta * costheta); \n"\ -" \n"\ -" // Return the result \n"\ -" return normalize(u * sintheta * cospsi + v * sintheta * sinpsi + n * costheta); \n"\ -"} \n"\ -" \n"\ -"/// Sample 2D texture described by texture in texturedata pool \n"\ -"float3 Sample2D(Texture const* texture, __global char const* texturedata, float2 uv) \n"\ -"{ \n"\ -" // Get width and height \n"\ -" int width = texture->w; \n"\ -" int height = texture->h; \n"\ -" \n"\ -" // Find the origin of the data in the pool \n"\ -" __global char const* mydata = texturedata + texture->dataoffset; \n"\ -" \n"\ -" // Handle wrap \n"\ -" uv -= floor(uv); \n"\ -" \n"\ -" // Reverse Y \n"\ -" // it is needed as textures are loaded with Y axis going top to down \n"\ -" // and our axis goes from down to top \n"\ -" uv.y = 1.f - uv.y; \n"\ -" \n"\ -" // Figure out integer coordinates \n"\ -" int x = floor(uv.x * width); \n"\ -" int y = floor(uv.y * height); \n"\ -" \n"\ -" // Calculate samples for linear filtering \n"\ -" int x1 = min(x + 1, width - 1); \n"\ -" int y1 = min(y + 1, height - 1); \n"\ -" \n"\ -" // Calculate weights for linear filtering \n"\ -" float wx = uv.x * width - floor(uv.x * width); \n"\ -" float wy = uv.y * height - floor(uv.y * height); \n"\ -" \n"\ -" if (texture->fmt == RGBA32) \n"\ -" { \n"\ -" __global float3 const* mydataf = (__global float3 const*)mydata; \n"\ -" \n"\ -" // Get 4 values \n"\ -" float3 valx = *(mydataf + width * y + x); \n"\ -" float3 valx1 = *(mydataf + width * y + x1); \n"\ -" float3 valy1 = *(mydataf + width * y1 + x); \n"\ -" float3 valx1y1 = *(mydataf + width * y1 + x1); \n"\ -" \n"\ -" // Filter and return the result \n"\ -" return lerp(lerp(valx, valx1, wx), lerp(valy1, valx1y1, wx), wy); \n"\ -" } \n"\ -" else if (texture->fmt == RGBA16) \n"\ -" { \n"\ -" __global half const* mydatah = (__global half const*)mydata; \n"\ -" \n"\ -" // Get 4 values \n"\ -" float3 valx = vload_half4(width * y + x, mydatah).xyz; \n"\ -" float3 valx1 = vload_half4(width * y + x1, mydatah).xyz; \n"\ -" float3 valy1 = vload_half4(width * y1 + x, mydatah).xyz; \n"\ -" float3 valx1y1 = vload_half4(width * y1 + x1, mydatah).xyz; \n"\ -" \n"\ -" // Filter and return the result \n"\ -" return lerp(lerp(valx, valx1, wx), lerp(valy1, valx1y1, wx), wy); \n"\ -" } \n"\ -" else \n"\ -" { \n"\ -" __global uchar4 const* mydatac = (__global uchar4 const*)mydata; \n"\ -" \n"\ -" // Get 4 values \n"\ -" uchar4 valx = *(mydatac + width * y + x); \n"\ -" uchar4 valx1 = *(mydatac + width * y + x1); \n"\ -" uchar4 valy1 = *(mydatac + width * y1 + x); \n"\ -" uchar4 valx1y1 = *(mydatac + width * y1 + x1); \n"\ -" \n"\ -" float3 valxf = make_float3((float)valx.x / 255.f, (float)valx.y / 255.f, (float)valx.z / 255.f); \n"\ -" float3 valx1f = make_float3((float)valx1.x / 255.f, (float)valx1.y / 255.f, (float)valx1.z / 255.f); \n"\ -" float3 valy1f = make_float3((float)valy1.x / 255.f, (float)valy1.y / 255.f, (float)valy1.z / 255.f); \n"\ -" float3 valx1y1f = make_float3((float)valx1y1.x / 255.f, (float)valx1y1.y / 255.f, (float)valx1y1.z / 255.f); \n"\ -" \n"\ -" // Filter and return the result \n"\ -" return lerp(lerp(valxf, valx1f, wx), lerp(valy1f, valx1y1f, wx), wy); \n"\ -" } \n"\ -"} \n"\ -" \n"\ -"/// Sample 2D lat-long IBL map \n"\ -"float3 SampleEnvMap(Texture const* texture, __global char const* texturedata, float3 d) \n"\ -"{ \n"\ -" // Transform to spherical coords \n"\ -" float r, phi, theta; \n"\ -" CartesianToSpherical(d, &r, &phi, &theta); \n"\ -" \n"\ -" // Map to [0,1]x[0,1] range and reverse Y axis \n"\ -" float2 uv; \n"\ -" uv.x = phi / (2*PI); \n"\ -" uv.y = 1.f - theta / PI; \n"\ -" \n"\ -" // Sample the texture \n"\ -" return Sample2D(texture, texturedata, uv); \n"\ -"} \n"\ -" \n"\ -"/// Get material data from hardcoded value or texture \n"\ -"float3 GetValue( \n"\ -" // Value \n"\ -" float3 v, \n"\ -" // Texture index (can be -1 whihc means no texture) \n"\ -" int texidx, \n"\ -" // Texture coordinate \n"\ -" float2 uv, \n"\ -" // Texture data \n"\ -" __global Texture const* textures, \n"\ -" __global char const* texturedata) \n"\ -"{ \n"\ -" // If texture present sample from texture \n"\ -" if (texidx != -1) \n"\ -" { \n"\ -" // Get texture desc \n"\ -" Texture texture = textures[texidx]; \n"\ -" // Sample diffuse texture \n"\ -" return Sample2D(&texture, texturedata, uv); \n"\ -" } \n"\ -" \n"\ -" // Return fixed color otherwise \n"\ -" return v; \n"\ -"} \n"\ -" \n"\ -" \n"\ -"/// Construct tangent basis on the fly and apply normal map \n"\ -"float3 ApplyNormalMap(Texture* normalmap, __global char const* texturedata, float2 uv, float3 n, float3 v0, float3 v1, float3 v2, float2 uv0, float2 uv1, float2 uv2) \n"\ -"{ \n"\ -" /// From PBRT book \n"\ -" float du1 = uv0.x - uv2.x; \n"\ -" float du2 = uv1.x - uv2.x; \n"\ -" float dv1 = uv0.y - uv2.y; \n"\ -" float dv2 = uv1.y - uv2.y; \n"\ -" \n"\ -" float3 dp1 = v0 - v2; \n"\ -" float3 dp2 = v1 - v2; \n"\ -" \n"\ -" float det = du1 * dv2 - dv1 * du2; \n"\ -" \n"\ -" \n"\ -" float3 dpdu, dpdv; \n"\ -" \n"\ -" if (det != 0.f) \n"\ -" { \n"\ -" float invdet = 1.f / det; \n"\ -" dpdu = normalize(( dv2 * dp1 - dv1 * dp2) * invdet); \n"\ -" dpdv = normalize((-du2 * dp1 + du1 * dp2) * invdet); \n"\ -" } \n"\ -" else \n"\ -" { \n"\ -" dpdu = GetOrthoVector(n); \n"\ -" dpdv = cross(n, dpdu); \n"\ -" } \n"\ -" \n"\ -" float3 newnormal = cross(dpdv, dpdu); \n"\ -" \n"\ -" // Now n, dpdu, dpdv is orthonormal basis \n"\ -" float3 mappednormal = 2.f * Sample2D(normalmap, texturedata, uv) - make_float3(1.f, 1.f, 1.f); \n"\ -" \n"\ -" // Return mapped version \n"\ -" return normalize(mappednormal.z * n + mappednormal.x * dpdu + mappednormal.y * dpdv); \n"\ -"} \n"\ -" \n"\ -"///< Shlick Fresnel term approx for Disney BRDF \n"\ -"float SchlickFresnel(const float u) \n"\ -"{ \n"\ -" const float m = clamp(1.f - u, 0.f, 1.f); \n"\ -" const float m2 = m * m; \n"\ -" return m2 * m2 * m; \n"\ -"} \n"\ -" \n"\ -"float SchlickFresnelEta(float eta, float cosi) \n"\ -"{ \n"\ -" const float f = ((1.f - eta) / (1.f + eta)) * ((1.f - eta) / (1.f + eta)); \n"\ -" const float m = 1.f - fabs(cosi); \n"\ -" const float m2 = m*m; \n"\ -" return f + (1.f - f) * m2 * m2 * m; \n"\ -"} \n"\ -" \n"\ -"float Gtr1(const float ndoth, const float a) \n"\ -"{ \n"\ -" if (a >= 1.f) \n"\ -" return 1.f / PI; \n"\ -" \n"\ -" const float a2 = a * a; \n"\ -" const float t = 1.f + (a2 - 1.f) * ndoth * ndoth; \n"\ -" \n"\ -" return (a2 - 1.f) / (PI * log(a2) * t); \n"\ -"} \n"\ -" \n"\ -"float Gtr2Aniso( \n"\ -" const float ndoth, \n"\ -" const float hdotx, \n"\ -" const float hdoty, \n"\ -" const float ax, \n"\ -" const float ay \n"\ -" ) \n"\ -"{ \n"\ -" return clamp( \n"\ -" 1.f / (PI * ax * ay * \n"\ -" ((hdotx / ax)*(hdotx / ax) + (hdoty / ay)*(hdoty / ay) + ndoth * ndoth) * \n"\ -" ((hdotx / ax)*(hdotx / ax) + (hdoty / ay)*(hdoty / ay) + ndoth * ndoth)), \n"\ -" 0.f, 10.f); // A trick to avoid fireflies \n"\ -"} \n"\ -" \n"\ -"float SmithGggx(const float ndotv, const float alphag) \n"\ -"{ \n"\ -" float a = alphag * alphag; \n"\ -" float b = ndotv * ndotv; \n"\ -" return 1.f / (ndotv + sqrt(a + b - a * b)); \n"\ -"} \n"\ -" \n"\ -"///< Evaluate actual layers \n"\ -"float3 DisneyEvaluateLayers( \n"\ -" Material *material, \n"\ -" const float3 n, \n"\ -" const float3 v, \n"\ -" const float3 l, \n"\ -" const float3 h, \n"\ -" const float ds, \n"\ -" const float2 uv, \n"\ -" __global Texture const* textures, \n"\ -" __global char const* texturedata \n"\ -" ) \n"\ -"{ \n"\ -" // Read material parameters \n"\ -" const float3 basecolor = GetValue(material->kd.xyz, material->kdmapidx, uv, textures, texturedata); \n"\ -" const float metallic = material->metallic; \n"\ -" const float subsurface = material->subsurface; \n"\ -" const float specular = material->specular; \n"\ -" const float roughness = material->roughness; \n"\ -" const float speculartint = material->speculartint; \n"\ -" const float sheen = material->sheen; \n"\ -" const float sheentint = material->sheentint; \n"\ -" const float clearcoat = material->clearcoat; \n"\ -" const float clearcoatgloss = material->clearcoatgloss; \n"\ -" \n"\ -" const float ndotv = dot(n, v); \n"\ -" const float ndotl = dot(n, l); \n"\ -" \n"\ -" const float ndoth = dot(n, h); \n"\ -" const float ldoth = dot(l, h); \n"\ -" \n"\ -" const float3 cdlin = basecolor; \n"\ -" const float cdlum = .3f * cdlin.x + .6f * cdlin.y + .1f * cdlin.z; // luminance approx. \n"\ -" \n"\ -" const float3 ctint = (cdlum > 0.f) ? (cdlin / cdlum) : make_float3(1.f,1.f,1.f); // normalize lum. to isolate hue+sat \n"\ -" const float3 cspec0 = mix(specular * .08f * mix(1.f, ctint, speculartint), cdlin, metallic); \n"\ -" const float3 csheen = mix(1.f, ctint, sheentint); \n"\ -" \n"\ -" // Diffuse fresnel - go from 1 at normal incidence to .5 at grazing \n"\ -" // and mix in diffuse retro-reflection based on roughness \n"\ -" const float fl = SchlickFresnel(ndotl); \n"\ -" const float fv = SchlickFresnel(ndotv); \n"\ -" const float fd90 = .5f + 2.f * ldoth * ldoth * roughness; \n"\ -" const float fd = mix(1.f, fd90, fl) * mix(1.f, fd90, fv); \n"\ -" \n"\ -" // Based on Hanrahan-Krueger brdf approximation of isotropic bssrdf \n"\ -" // 1.25 scale is used to (roughly) preserve albedo \n"\ -" // fss90 used to flatten retroreflection based on roughness \n"\ -" const float fss90 = ldoth * ldoth * roughness; \n"\ -" const float fss = mix(1.f, fss90, fl) * mix(1.f, fss90, fv); \n"\ -" const float ss = 1.25f * (fss * (1.f / (ndotl + ndotv) - .5f) + .5f); \n"\ -" \n"\ -" // Specular \n"\ -" // The original implementation uses ldoth (i.e. the micro-facets normal) but \n"\ -" // the effect of many parameters is hardly noticeable in this case. \n"\ -" const float fh = SchlickFresnel(ndotl); \n"\ -" const float3 fs = mix(cspec0, 1.f, fh); \n"\ -" const float roughg = (roughness * .5f + .5f) * (roughness * .5f + .5f); \n"\ -" const float gs = SmithGggx(ndotl, roughg) * SmithGggx(ndotv, roughg); \n"\ -" \n"\ -" // Sheen \n"\ -" const float3 fsheen = fh * sheen * csheen; \n"\ -" \n"\ -" // Clearcoat (ior = 1.5 -> f0 = 0.04) \n"\ -" const float dr = Gtr1(ndoth, mix(.1f, .001f, clearcoatgloss)); \n"\ -" const float fr = mix(.04f, 1.f, fh); \n"\ -" const float gr = SmithGggx(ndotl, .25f) * SmithGggx(ndotv, .25f); \n"\ -" \n"\ -" float f = 1.f; \n"\ -" const float et = material->kd.w; \n"\ -" if (et != 0.f) \n"\ -" { \n"\ -" const float3 wo = -v; \n"\ -" const float cosi = dot(n, wo); \n"\ -" f = 1.f - SchlickFresnelEta(et, cosi); \n"\ -" } \n"\ -" \n"\ -" return f * ( \n"\ -" // Diffuse layer \n"\ -" ((1.f / PI) * mix(fd, ss, subsurface) * cdlin + fsheen) * (1.f - metallic) \n"\ -" + \n"\ -" // 1st Specular lobe \n"\ -" gs * fs * ds \n"\ -" + \n"\ -" // 2nd Specular lobe \n"\ -" // \n"\ -" // The original paper us a .25 scale but is not well visible in \n"\ -" // my opinion. I'm also clamping to reduce fireflies. \n"\ -" clamp(clearcoat * gr * fr * dr, 0.f, .5f) \n"\ -" ); \n"\ -"} \n"\ -" \n"\ -" \n"\ -" \n"\ -"///< Evaluate Disney principled BRDF \n"\ -"float3 DisneyEvaluate(Material *mat, \n"\ -" float3 n, \n"\ -" float3 wi, \n"\ -" float3 wo, \n"\ -" float2 uv, \n"\ -" __global Texture const* textures, \n"\ -" __global char const* texturedata \n"\ -") \n"\ -"{ \n"\ -" const float3 v = wi; \n"\ -" const float3 l = wo; \n"\ -" \n"\ -" if (dot(v, n) < 0.f) \n"\ -" return 0.f; \n"\ -" if (dot(l, n) <= 0.f) \n"\ -" return 0.f; \n"\ -" \n"\ -" const float anisotropic = mat->anisotropic; \n"\ -" const float roughness = mat->roughness; \n"\ -" \n"\ -" const float aspect = sqrt(1.f - anisotropic * .9f); \n"\ -" const float ax = max(.001f, roughness * roughness / aspect); \n"\ -" const float ay = max(.001f, roughness * roughness * aspect); \n"\ -" \n"\ -" float3 x, y; \n"\ -" x = GetOrthoVector(n); \n"\ -" y = normalize(cross(n, x)); \n"\ -" \n"\ -" const float3 h = normalize(l + v); \n"\ -" \n"\ -" const float ndoth = dot(n, h); \n"\ -" const float hdotx = dot(h, x); \n"\ -" const float hdoty = dot(h, y); \n"\ -" const float ds = Gtr2Aniso(ndoth, hdotx, hdoty, ax, ay); \n"\ -" \n"\ -" return DisneyEvaluateLayers(mat, n, v, l, h, ds, uv, textures, texturedata); \n"\ -"} \n"\ -" \n"\ -" \n"\ -"///< Sample Disney BRDF \n"\ -"float3 DisneySample( \n"\ -" Rng* rng, \n"\ -" Material *mat, \n"\ -" float3 n, \n"\ -" float3 wi, \n"\ -" float2 uv, \n"\ -" __global Texture const* textures, \n"\ -" __global char const* texturedata, \n"\ -" float3* wo, \n"\ -" float* pdf \n"\ -") \n"\ -"{ \n"\ -" const float weight2 = mat->metallic; \n"\ -" const float weight1 = 1.f - weight2; \n"\ -" \n"\ -" const float3 v = wi; \n"\ -" if (dot(v, n) < 0.f) \n"\ -" n = -n; \n"\ -" \n"\ -" const float anisotropic = mat->anisotropic; \n"\ -" const float roughness = mat->roughness; \n"\ -" \n"\ -" const float aspect = sqrt(1.f - anisotropic * .9f); \n"\ -" const float ax = max(.001f, roughness * roughness / aspect); \n"\ -" const float ay = max(.001f, roughness * roughness * aspect); \n"\ -" \n"\ -" float3 x, y; \n"\ -" x = GetOrthoVector(n); \n"\ -" y = normalize(cross(n, x)); \n"\ -" \n"\ -" const float u = RandFloat(rng); \n"\ -" const bool samplediffuse = (u < weight1); \n"\ -" \n"\ -" float ds; \n"\ -" float3 h, l; \n"\ -" float diffusepdf, specularpdf; \n"\ -" if (samplediffuse) \n"\ -" { \n"\ -" // Sample the diffuse layer \n"\ -" l = SampleHemisphere(rng, n, 0.f); \n"\ -" \n"\ -" h = normalize(l + v); \n"\ -" \n"\ -" const float ndoth = dot(n, h); \n"\ -" const float hdotx = dot(h, x); \n"\ -" const float hdoty = dot(h, y); \n"\ -" ds = Gtr2Aniso(ndoth, hdotx, hdoty, ax, ay); \n"\ -" \n"\ -" const float ldoth = dot(l, h); \n"\ -" diffusepdf = dot(l, n) / PI; \n"\ -" specularpdf = (ds * ndoth) / (4.f * ldoth); \n"\ -" } \n"\ -" else { \n"\ -" // Sample the specular layer \n"\ -" const float u1 = RandFloat(rng); \n"\ -" const float u2 = RandFloat(rng); \n"\ -" \n"\ -" h = normalize(sqrt(u2 / (1.f - u2)) * (ax * cos(2.f * PI * u1) + ay * sin(2.f * PI * u1)) + n); \n"\ -" l = 2.f * dot(v, h) * h - v; \n"\ -" \n"\ -" const float ndoth = dot(n, h); \n"\ -" const float hdotx = dot(h, x); \n"\ -" const float hdoty = dot(h, y); \n"\ -" ds = Gtr2Aniso(ndoth, hdotx, hdoty, ax, ay); \n"\ -" \n"\ -" const float ldoth = dot(l, h); \n"\ -" if (ldoth < .01f) \n"\ -" { \n"\ -" *pdf = 0.f; \n"\ -" return make_float3(0.f, 0.f, 0.f); \n"\ -" } \n"\ -" \n"\ -" diffusepdf = dot(l, n) / PI; \n"\ -" specularpdf = (ds * ndoth) / (4.f * ldoth); \n"\ -" \n"\ -" // A trick to avoid fireflies \n"\ -" if (specularpdf < 1.f) \n"\ -" { \n"\ -" *pdf = 0.f; \n"\ -" return make_float3(0.f, 0.f, 0.f); \n"\ -" } \n"\ -" } \n"\ -" \n"\ -" *wo = l; \n"\ -" *pdf = weight1 * diffusepdf + weight2 * specularpdf; \n"\ -" \n"\ -" return DisneyEvaluateLayers(mat, n, v, l, h, ds, uv, textures, texturedata); \n"\ -"} \n"\ -" \n"\ -"float DisneyGetPdf( \n"\ -" Material *mat, \n"\ -" float3 n, \n"\ -" float3 wi, \n"\ -" float3 wo, \n"\ -" float2 uv, \n"\ -" __global Texture const* textures, \n"\ -" __global char const* texturedata \n"\ -" ) \n"\ -"{ \n"\ -" const float3 v = wi; \n"\ -" const float3 l = wo; \n"\ -" \n"\ -" if (dot(v, n) < 0.f) \n"\ -" return 0.f; \n"\ -" if (dot(l, n) <= 0.f) \n"\ -" return 0.f; \n"\ -" \n"\ -" const float weight2 = mat->metallic; \n"\ -" //const float weight2 = .25f * .5f * material->m_disney_principled.m_metallic; \n"\ -" //const float weight2 = .5f; \n"\ -" const float weight1 = 1.f - weight2; \n"\ -" \n"\ -" // Diffuse pdf \n"\ -" const float diffusepdf = dot(l, n) / PI; \n"\ -" \n"\ -" // Specular pdf \n"\ -" const float anisotropic = mat->anisotropic; \n"\ -" const float roughness = mat->roughness; \n"\ -" \n"\ -" const float aspect = sqrt(1.f - anisotropic * .9f); \n"\ -" const float ax = max(.001f, roughness * roughness / aspect); \n"\ -" const float ay = max(.001f, roughness * roughness * aspect); \n"\ -" \n"\ -" float3 x, y; \n"\ -" x = GetOrthoVector(n); \n"\ -" y = normalize(cross(n, x)); \n"\ -" \n"\ -" const float3 h = normalize(l + v); \n"\ -" \n"\ -" const float ndoth = dot(n, h); \n"\ -" const float hdotx = dot(h, x); \n"\ -" const float hdoty = dot(h, y); \n"\ -" const float ldoth = dot(l, h); \n"\ -" const float ds = Gtr2Aniso(ndoth, hdotx, hdoty, ax, ay); \n"\ -" \n"\ -" const float specularpdf = (ds * ndoth) / (4.f * ldoth); \n"\ -" \n"\ -" return weight1 * diffusepdf + weight2 * specularpdf; \n"\ -"} \n"\ -" \n"\ -" \n"\ -" \n"\ -" \n"\ -"///< Evaluate material at shading point \n"\ -"float3 EvaluateBxdf(Material* mat, float3 wi, float3 wo, float3 n, float2 uv, __global Texture const* textures, __global char const* texturedata) \n"\ -"{ \n"\ -" return DisneyEvaluate(mat, n, wi, wo, uv, textures, texturedata); \n"\ -"} \n"\ -" \n"\ -"float3 SampleBxdf(Rng* rng, Material* mat, float3 wi, float3 n, float2 uv, __global Texture const* textures, __global char const* texturedata, float3* wo, float* pdf) \n"\ -"{ \n"\ -" return DisneySample(rng, mat, n, wi, uv, textures, texturedata, wo, pdf); \n"\ -"} \n"\ -" \n"\ -"float GetPdfBxfd(Material* mat, float3 wi, float3 wo, float3 n, float2 uv, __global Texture const* textures, __global char const* texturedata) \n"\ -"{ \n"\ -" return DisneyGetPdf(mat, n, wi, wo, uv, textures, texturedata); \n"\ -"} \n"\ -" \n"\ -"///< Light sampling \n"\ -" \n"\ -"float3 EvaluateLight(float3 p, float3 n, float3 wo, int envmapidx, float envmapmul, __global Texture const* textures, __global char const* texturedata) \n"\ -"{ \n"\ -" // Sample envmap \n"\ -" Texture envtexture = textures[envmapidx]; \n"\ -" return envmapmul * SampleEnvMap(&envtexture, texturedata, wo); \n"\ -"} \n"\ -" \n"\ -"float3 SampleLight(Rng* rng, float3 p, float3 n, int envmapidx, float envmapmul, __global Texture const* textures, __global char const* texturedata, float3* wo, float* pdf) \n"\ -"{ \n"\ -" // Generate direction \n"\ -" *wo = SampleHemisphere(rng, n, 1.f); \n"\ -" \n"\ -" // Envmap PDF \n"\ -" *pdf = dot(n, *wo) / PI; \n"\ -" \n"\ -" // Sample envmap \n"\ -" Texture envtexture = textures[envmapidx]; \n"\ -" return envmapmul * SampleEnvMap(&envtexture, texturedata, *wo); \n"\ -"} \n"\ -" \n"\ -"float GetPdfLight(float3 p, float3 n, float3 wo) \n"\ -"{ \n"\ -" return dot(n, wo) > 0 ? (dot(n, wo) / PI) : 0.f; \n"\ -"} \n"\ -" \n"\ -" \n"\ -"/// Ray generation kernel \n"\ -"/// Rays are generated from camera position to viewing plane \n"\ -"/// using random sample distribution within the pixel \n"\ -"/// \n"\ -"__kernel void GenerateRays2D( \n"\ -" // Camera buffer \n"\ -" __global Camera const* camera, \n"\ -" // Image resolution \n"\ -" int imgwidth, \n"\ -" int imgheight, \n"\ -" // RNG seed value \n"\ -" int randseed, \n"\ -" // Output rays \n"\ -" __global ray* rays) \n"\ -"{ \n"\ -" int2 global_id; \n"\ -" global_id.x = get_global_id(0); \n"\ -" global_id.y = get_global_id(1); \n"\ -" \n"\ -" // Handle only working subset \n"\ -" if (global_id.x < imgwidth && global_id.y < imgheight) \n"\ -" { \n"\ -" __global ray* myray = rays + global_id.y * imgwidth + global_id.x; \n"\ -" \n"\ -" Rng rng; \n"\ -" InitRng(randseed + global_id.x * 157 - 33 * global_id.y, &rng); \n"\ -" \n"\ -" // Calculate [0..1] image plane sample \n"\ -" float2 imgsample; \n"\ -" imgsample.x = (float)global_id.x / imgwidth + RandFloat(&rng) / imgwidth; \n"\ -" imgsample.y = (float)global_id.y / imgheight + RandFloat(&rng) / imgheight; \n"\ -" \n"\ -" // Transform into [-0.5,0.5] \n"\ -" float2 hsample = imgsample - make_float2(0.5f, 0.5f); \n"\ -" // Transform into [-dim/2, dim/2] \n"\ -" float2 csample = hsample * camera->dim; \n"\ -" \n"\ -" // Direction to image plane \n"\ -" myray->d.xyz = normalize(camera->zcap.x * camera->forward + csample.x * camera->right + csample.y * camera->up); \n"\ -" // Origin == camera position \n"\ -" myray->o.xyz = camera->p + camera->zcap.x * myray->d.xyz; \n"\ -" // Zcap == (znear, zfar) \n"\ -" myray->o.w = camera->zcap.y; \n"\ -" // Generate random time from 0 to 1 \n"\ -" myray->d.w = RandFloat(&rng); \n"\ -" } \n"\ -"} \n"\ -" \n"\ -"///< Sample environemnt light and produce light samples and shadow rays into separate buffer \n"\ -"__kernel void SampleEnvironment( \n"\ -" // Ray batch \n"\ -" __global ray const* rays, \n"\ -" // Intersection data \n"\ -" __global Intersection const* isects, \n"\ -" // Hit indices \n"\ -" __global int const* hitindices, \n"\ -" // Pixel indices \n"\ -" __global int const* pixelindices, \n"\ -" // Number of rays \n"\ -" int numhits, \n"\ -" // Vertices \n"\ -" __global float3 const* vertices, \n"\ -" // Normals \n"\ -" __global float3 const* normals, \n"\ -" // UVs \n"\ -" __global float2 const* uvs, \n"\ -" // Indices \n"\ -" __global int const* indices, \n"\ -" // Shapes \n"\ -" __global Shape const* shapes, \n"\ -" // Material IDs \n"\ -" __global int const* materialids, \n"\ -" // Materials \n"\ -" __global Material const* materials, \n"\ -" // Textures \n"\ -" __global Texture const* textures, \n"\ -" // Texture data \n"\ -" __global char const* texturedata, \n"\ -" // Environment texture index \n"\ -" int envmapidx, \n"\ -" // Envmap multiplier \n"\ -" float envmapmul, \n"\ -" // Emissives \n"\ -" __global Emissive const* emissives, \n"\ -" // Number of emissive objects \n"\ -" int numemissives, \n"\ -" // RNG seed \n"\ -" int rngseed, \n"\ -" // Shadow rays \n"\ -" __global ray* shadowrays, \n"\ -" // Light samples \n"\ -" __global float3* lightsamples, \n"\ -" // Number of shadow rays to spawn \n"\ -" int numlightsamples, \n"\ -" // Path throughput \n"\ -" __global float3* throughput, \n"\ -" // Indirect rays \n"\ -" __global ray* indirectrays \n"\ -" ) \n"\ -"{ \n"\ -" int globalid = get_global_id(0); \n"\ -" \n"\ -" if (globalid < numhits) \n"\ -" { \n"\ -" // Fetch index \n"\ -" int hitidx = hitindices[globalid]; \n"\ -" int pixelidx = pixelindices[globalid]; \n"\ -" \n"\ -" // Fetch incoming ray \n"\ -" float3 wi = -normalize(rays[hitidx].d.xyz); \n"\ -" float time = rays[hitidx].d.w; \n"\ -" \n"\ -" // Determine shape and polygon \n"\ -" int shapeid = isects[hitidx].shapeid - 1; \n"\ -" int primid = isects[hitidx].primid; \n"\ -" float2 uv = isects[hitidx].uvwt.xy; \n"\ -" \n"\ -" // Extract shape data \n"\ -" Shape shape = shapes[shapeid]; \n"\ -" float3 linearvelocity = shape.linearvelocity; \n"\ -" float4 angularvelocity = shape.angularvelocity; \n"\ -" \n"\ -" // Fetch indices starting from startidx and offset by primid \n"\ -" int i0 = indices[shape.startidx + 3*primid]; \n"\ -" int i1 = indices[shape.startidx + 3*primid + 1]; \n"\ -" int i2 = indices[shape.startidx + 3*primid + 2]; \n"\ -" \n"\ -" // Fetch normals \n"\ -" float3 n0 = normals[shape.startvtx + i0]; \n"\ -" float3 n1 = normals[shape.startvtx + i1]; \n"\ -" float3 n2 = normals[shape.startvtx + i2]; \n"\ -" \n"\ -" // Fetch positions \n"\ -" float3 v0 = vertices[shape.startvtx + i0]; \n"\ -" float3 v1 = vertices[shape.startvtx + i1]; \n"\ -" float3 v2 = vertices[shape.startvtx + i2]; \n"\ -" \n"\ -" // Fetch UVs \n"\ -" float2 uv0 = uvs[shape.startvtx + i0]; \n"\ -" float2 uv1 = uvs[shape.startvtx + i1]; \n"\ -" float2 uv2 = uvs[shape.startvtx + i2]; \n"\ -" \n"\ -" // Calculate barycentric position and normal \n"\ -" float3 n = normalize((1.f - uv.x - uv.y) * n0 + uv.x * n1 + uv.y * n2); \n"\ -" float3 v = (1.f - uv.x - uv.y) * v0 + uv.x * v1 + uv.y * v2; \n"\ -" float2 t = (1.f - uv.x - uv.y) * uv0 + uv.x * uv1 + uv.y * uv2; \n"\ -" \n"\ -" // Bail out if opposite facing normal \n"\ -" if (dot(wi, n) < 0.f) \n"\ -" { \n"\ -" //throughput[pixelidx] = 0; \n"\ -" //return; \n"\ -" } \n"\ -" \n"\ -" // Get material at shading point \n"\ -" int matidx = materialids[shape.startidx / 3 + primid]; \n"\ -" Material mat = materials[matidx]; \n"\ -" \n"\ -" \n"\ -" // Apply transform & linear motion blur \n"\ -" v = rotate_vector(v, angularvelocity); \n"\ -" v = transform_point(v, shape.m0, shape.m1, shape.m2, shape.m3); \n"\ -" v += (linearvelocity * time); \n"\ -" // MT^-1 should be used if scale is present \n"\ -" n = rotate_vector(n, angularvelocity); \n"\ -" n = transform_vector(n, shape.m0, shape.m1, shape.m2, shape.m3); \n"\ -" \n"\ -" // Apply normal map if needed \n"\ -" if (mat.nmapidx != -1) \n"\ -" { \n"\ -" Texture normalmap = textures[mat.nmapidx]; \n"\ -" n = ApplyNormalMap(&normalmap, texturedata, t, n, v0, v1, v2, uv0, uv1, uv2); \n"\ -" } \n"\ -" \n"\ -" if (dot(wi, n) < 0.f) \n"\ -" { \n"\ -" n = -n; \n"\ -" } \n"\ -" \n"\ -" // Prepare RNG for light sampling \n"\ -" Rng rng; \n"\ -" InitRng(rngseed + globalid * 157, &rng); \n"\ -" \n"\ -" float lightpdf = 0.f; \n"\ -" float bxdfpdf = 0.f; \n"\ -" float3 wo; \n"\ -" float3 le; \n"\ -" \n"\ -" // Generate shadow rays and light samples \n"\ -" for (int i=0; i 0.f) \n"\ -" { \n"\ -" // Generate light sample \n"\ -" radiance = lightsampling_weight * le * EvaluateBxdf(&mat, wi, wo, n, t, textures, texturedata) * throughput[pixelidx] * max(0.f, dot(n, wo)) / lightpdf; \n"\ -" } \n"\ -" \n"\ -" // Generate ray \n"\ -" shadowrays[globalid * numlightsamples + 2*i].d.xyz = wo; \n"\ -" shadowrays[globalid * numlightsamples + 2*i].o.xyz = v + 0.001f * wo; \n"\ -" shadowrays[globalid * numlightsamples + 2*i].o.w = 100000000.f; \n"\ -" shadowrays[globalid * numlightsamples + 2*i].d.w = rays[hitidx].d.w; \n"\ -" lightsamples[globalid * numlightsamples + 2*i] = clamp(radiance, 0.f, 10.f); \n"\ -" \n"\ -" radiance = 0.f; \n"\ -" { \n"\ -" // Sample BxDF \n"\ -" float3 bxdf = SampleBxdf(&rng, &mat, wi, n, t, textures, texturedata, &wo, &bxdfpdf); \n"\ -" lightpdf = GetPdfLight(v, n, wo); \n"\ -" float bxdfsampling_weight = PowerHeuristic(1, bxdfpdf, 1, lightpdf); \n"\ -" le = EvaluateLight(v, n, wo, envmapidx, envmapmul, textures, texturedata); \n"\ -" \n"\ -" if (bxdfpdf > 0.f) \n"\ -" { \n"\ -" radiance = bxdfsampling_weight * le * bxdf * throughput[pixelidx] * max(0.f, dot(n, wo)) / bxdfpdf; \n"\ -" } \n"\ -" } \n"\ -" \n"\ -" // Generate ray \n"\ -" shadowrays[globalid * numlightsamples + 2 * i + 1].d.xyz = wo; \n"\ -" shadowrays[globalid * numlightsamples + 2 * i + 1].o.xyz = v + 0.001f * wo; \n"\ -" shadowrays[globalid * numlightsamples + 2 * i + 1].o.w = 100000000.f; \n"\ -" shadowrays[globalid * numlightsamples + 2 * i + 1].d.w = rays[hitidx].d.w; \n"\ -" lightsamples[globalid * numlightsamples + 2 * i + 1] = clamp(radiance, 0.f, 10.f); \n"\ -" } \n"\ -" \n"\ -" // Generate indirect ray and update throughput \n"\ -" \n"\ -" float pdf; \n"\ -" float3 bxdf = SampleBxdf(&rng, &mat, wi, n, t, textures, texturedata, &wo, &pdf); \n"\ -" \n"\ -" if (pdf > 0.001f && dot(n, wo) > 0.001f) \n"\ -" throughput[pixelidx] *= (bxdf * max(0.f, dot(n, wo)) / pdf); \n"\ -" else \n"\ -" throughput[pixelidx] = 0.f; \n"\ -" \n"\ -" indirectrays[globalid].d.xyz = normalize(wo); \n"\ -" indirectrays[globalid].o.xyz = v + 0.001f * normalize(wo); \n"\ -" indirectrays[globalid].o.w = 100000000.f; \n"\ -" indirectrays[globalid].d.w = rays[hitidx].d.w; \n"\ -" } \n"\ -"} \n"\ -" \n"\ -"///< Illuminate missing rays \n"\ -"__kernel void ShadeMiss( \n"\ -" // Ray batch \n"\ -" __global ray const* rays, \n"\ -" // Intersection data \n"\ -" __global Intersection const* isects, \n"\ -" // Pixel indices \n"\ -" __global int const* pixelindices, \n"\ -" // Number of rays \n"\ -" int numrays, \n"\ -" // Textures \n"\ -" __global Texture const* textures, \n"\ -" // Texture data \n"\ -" __global char const* texturedata, \n"\ -" // Environment texture index \n"\ -" int envmapidx, \n"\ -" // Througput \n"\ -" __global float3 const* througput, \n"\ -" // Output values \n"\ -" __global float4* output \n"\ -" ) \n"\ -"{ \n"\ -" int globalid = get_global_id(0); \n"\ -" \n"\ -" if (globalid < numrays) \n"\ -" { \n"\ -" int pixelidx = pixelindices[globalid]; \n"\ -" \n"\ -" // In case of a miss \n"\ -" if (isects[globalid].shapeid < 0) \n"\ -" { \n"\ -" // Sample IBL for that ray \n"\ -" Texture texture = textures[envmapidx]; \n"\ -" // Multiply by througput \n"\ -" output[pixelidx].xyz += SampleEnvMap(&texture, texturedata, rays[globalid].d.xyz) * througput[pixelidx]; \n"\ -" } \n"\ -" \n"\ -" output[pixelidx].w += 1.f; \n"\ -" } \n"\ -"} \n"\ -" \n"\ -"///< Handle light samples and visibility info and add contribution to final buffer \n"\ -"__kernel void GatherLightSamples( \n"\ -" // Pixel indices \n"\ -" __global int const* pixelindices, \n"\ -" // Number of rays \n"\ -" int numrays, \n"\ -" // Number of light samples per ray \n"\ -" int numlightsamples, \n"\ -" // Shadow rays hits \n"\ -" __global int const* shadowhits, \n"\ -" // Light samples \n"\ -" __global float3 const* lightsamples, \n"\ -" // Througput \n"\ -" __global float3 const* throughput, \n"\ -" // Radiance sample buffer \n"\ -" __global float4* output \n"\ -" ) \n"\ -"{ \n"\ -" int globalid = get_global_id(0); \n"\ -" \n"\ -" if (globalid < numrays) \n"\ -" { \n"\ -" // Prepare accumulator variable \n"\ -" float3 radiance = make_float3(0.f, 0.f, 0.f); \n"\ -" \n"\ -" // Get pixel id for this sample set \n"\ -" int pixelidx = pixelindices[globalid]; \n"\ -" \n"\ -" // Start collecting samples \n"\ -" for (int i=0; i= 0 ? 1 : 0; \n"\ -" } \n"\ -"} \n"\ -" \n"\ -" \n"\ -; diff --git a/Baikal/CL/camera.cl b/Baikal/CL/camera.cl deleted file mode 100644 index f641053d..00000000 --- a/Baikal/CL/camera.cl +++ /dev/null @@ -1,462 +0,0 @@ -/********************************************************************** -Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. - -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 CAMERA_CL -#define CAMERA_CL - -#include <../Baikal/CL/common.cl> -#include <../Baikal/CL/payload.cl> -#include <../Baikal/CL/sampling.cl> -#include <../Baikal/CL/utils.cl> -#include <../Baikal/CL/path.cl> -#include <../Baikal/CL/vertex.cl> - -// Pinhole camera implementation. -// This kernel is being used if aperture value = 0. -KERNEL -void PerspectiveCamera_GeneratePaths( - // Camera - GLOBAL Camera const* restrict camera, - // Image resolution - int output_width, - int output_height, - // Pixel domain buffer - GLOBAL int const* restrict pixel_idx, - // Size of pixel domain buffer - GLOBAL int const* restrict num_pixels, - // RNG seed value - uint rng_seed, - // Current frame - uint frame, - // Rays to generate - GLOBAL ray* restrict rays, - // RNG data - GLOBAL uint* restrict random, - GLOBAL uint const* restrict sobolmat, - // Path buffer - GLOBAL Path* restrict paths -) -{ - int global_id = get_global_id(0); - - // Check borders - if (global_id < *num_pixels) - { - int idx = pixel_idx[global_id]; - int y = idx / output_width; - int x = idx % output_width; - - // Get pointer to ray & path handles - GLOBAL ray* my_ray = rays + global_id; - GLOBAL Path* my_path = paths + y * output_width + x; - - // Initialize sampler - Sampler sampler; -#if SAMPLER == SOBOL - uint scramble = random[x + output_width * y] * 0x1fe3434f; - - if (frame & 0xF) - { - random[x + output_width * y] = WangHash(scramble); - } - - Sampler_Init(&sampler, frame, SAMPLE_DIM_CAMERA_OFFSET, scramble); -#elif SAMPLER == RANDOM - uint scramble = x + output_width * y * rng_seed; - Sampler_Init(&sampler, scramble); -#elif SAMPLER == CMJ - uint rnd = random[x + output_width * y]; - uint scramble = rnd * 0x1fe3434f * ((frame + 133 * rnd) / (CMJ_DIM * CMJ_DIM)); - Sampler_Init(&sampler, frame % (CMJ_DIM * CMJ_DIM), SAMPLE_DIM_CAMERA_OFFSET, scramble); -#endif - - // Generate sample - float2 sample0 = Sampler_Sample2D(&sampler, SAMPLER_ARGS); - - // Calculate [0..1] image plane sample - float2 img_sample; - img_sample.x = (float)x / output_width + sample0.x / output_width; - img_sample.y = (float)y / output_height + sample0.y / output_height; - - // Transform into [-0.5, 0.5] - float2 h_sample = img_sample - make_float2(0.5f, 0.5f); - // Transform into [-dim/2, dim/2] - float2 c_sample = h_sample * camera->dim; - - // Calculate direction to image plane - my_ray->d.xyz = normalize(camera->focal_length * camera->forward + c_sample.x * camera->right + c_sample.y * camera->up); - // Origin == camera position + nearz * d - my_ray->o.xyz = camera->p + camera->zcap.x * my_ray->d.xyz; - // Max T value = zfar - znear since we moved origin to znear - my_ray->o.w = camera->zcap.y - camera->zcap.x; - // Generate random time from 0 to 1 - my_ray->d.w = sample0.x; - // Set ray max - my_ray->extra.x = 0xFFFFFFFF; - my_ray->extra.y = 0xFFFFFFFF; - Ray_SetExtra(my_ray, 1.f); - - // Initalize path data - my_path->throughput = make_float3(1.f, 1.f, 1.f); - my_path->volume = INVALID_IDX; - my_path->flags = 0; - my_path->active = 0xFF; - } -} - -// Physical camera implemenation. -// This kernel is being used if aperture > 0. -KERNEL void PerspectiveCameraDof_GeneratePaths( - // Camera - GLOBAL Camera const* restrict camera, - // Image resolution - int output_width, - int output_height, - // Pixel domain buffer - GLOBAL int const* restrict pixel_idx, - // Size of pixel domain buffer - GLOBAL int const* restrict num_pixels, - // RNG seed value - uint rng_seed, - // Current frame - uint frame, - // Rays to generate - GLOBAL ray* restrict rays, - // RNG data - GLOBAL uint* restrict random, - GLOBAL uint const* restrict sobolmat, - // Path buffer - GLOBAL Path* restrict paths -) -{ - int global_id = get_global_id(0); - - // Check borders - if (global_id < *num_pixels) - { - int idx = pixel_idx[global_id]; - int y = idx / output_width; - int x = idx % output_width; - - // Get pointer to ray & path handles - GLOBAL ray* my_ray = rays + global_id; - GLOBAL Path* my_path = paths + y * output_width + x; - - // Initialize sampler - Sampler sampler; -#if SAMPLER == SOBOL - uint scramble = random[x + output_width * y] * 0x1fe3434f; - - if (frame & 0xF) - { - random[x + output_width * y] = WangHash(scramble); - } - - Sampler_Init(&sampler, frame, SAMPLE_DIM_CAMERA_OFFSET, scramble); -#elif SAMPLER == RANDOM - uint scramble = x + output_width * y * rng_seed; - Sampler_Init(&sampler, scramble); -#elif SAMPLER == CMJ - uint rnd = random[x + output_width * y]; - uint scramble = rnd * 0x1fe3434f * ((frame + 133 * rnd) / (CMJ_DIM * CMJ_DIM)); - Sampler_Init(&sampler, frame % (CMJ_DIM * CMJ_DIM), SAMPLE_DIM_CAMERA_OFFSET, scramble); -#endif - - // Generate pixel and lens samples - float2 sample0 = Sampler_Sample2D(&sampler, SAMPLER_ARGS); - float2 sample1 = Sampler_Sample2D(&sampler, SAMPLER_ARGS); - - // Calculate [0..1] image plane sample - float2 img_sample; - img_sample.x = (float)x / output_width + sample0.x / output_width; - img_sample.y = (float)y / output_height + sample0.y / output_height; - - // Transform into [-0.5, 0.5] - float2 h_sample = img_sample - make_float2(0.5f, 0.5f); - // Transform into [-dim/2, dim/2] - float2 c_sample = h_sample * camera->dim; - - // Generate sample on the lens - float2 lens_sample = camera->aperture * Sample_MapToDiskConcentric(sample1); - // Calculate position on focal plane - float2 focal_plane_sample = c_sample * camera->focus_distance / camera->focal_length; - // Calculate ray direction - float2 camera_dir = focal_plane_sample - lens_sample; - - // Calculate direction to image plane - my_ray->d.xyz = normalize(camera->forward * camera->focus_distance + camera->right * camera_dir.x + camera->up * camera_dir.y); - // Origin == camera position + nearz * d - my_ray->o.xyz = camera->p + lens_sample.x * camera->right + lens_sample.y * camera->up; - // Max T value = zfar - znear since we moved origin to znear - my_ray->o.w = camera->zcap.y - camera->zcap.x; - // Generate random time from 0 to 1 - my_ray->d.w = sample0.x; - // Set ray max - my_ray->extra.x = 0xFFFFFFFF; - my_ray->extra.y = 0xFFFFFFFF; - Ray_SetExtra(my_ray, 1.f); - - // Initlize path data - my_path->throughput = make_float3(1.f, 1.f, 1.f); - my_path->volume = -1; - my_path->flags = 0; - my_path->active = 0xFF; - } -} - - -KERNEL -void PerspectiveCamera_GenerateVertices( - // Camera - GLOBAL Camera const* restrict camera, - // Image resolution - int output_width, - int output_height, - // Pixel domain buffer - GLOBAL int const* restrict pixel_idx, - // Size of pixel domain buffer - GLOBAL int const* restrict num_pixels, - // RNG seed value - uint rng_seed, - // Current frame - uint frame, - // RNG data - GLOBAL uint* restrict random, - GLOBAL uint const* restrict sobolmat, - // Rays to generate - GLOBAL ray* restrict rays, - // Eye subpath vertices - GLOBAL PathVertex* restrict eye_subpath, - // Eye subpath length - GLOBAL int* restrict eye_subpath_length, - // Path buffer - GLOBAL Path* restrict paths -) - -{ - int global_id = get_global_id(0); - - // Check borders - if (global_id < *num_pixels) - { - int idx = pixel_idx[global_id]; - int y = idx / output_width; - int x = idx % output_width; - - // Get pointer to ray & path handles - GLOBAL ray* my_ray = rays + global_id; - - GLOBAL PathVertex* my_vertex = eye_subpath + BDPT_MAX_SUBPATH_LEN * idx; - GLOBAL int* my_count = eye_subpath_length + idx; - GLOBAL Path* my_path = paths + idx; - - // Initialize sampler - Sampler sampler; -#if SAMPLER == SOBOL - uint scramble = random[x + output_width * y] * 0x1fe3434f; - - if (frame & 0xF) - { - random[x + output_width * y] = WangHash(scramble); - } - - Sampler_Init(&sampler, frame, SAMPLE_DIM_CAMERA_OFFSET, scramble); -#elif SAMPLER == RANDOM - uint scramble = x + output_width * y * rng_seed; - Sampler_Init(&sampler, scramble); -#elif SAMPLER == CMJ - uint rnd = random[x + output_width * y]; - uint scramble = rnd * 0x1fe3434f * ((frame + 133 * rnd) / (CMJ_DIM * CMJ_DIM)); - Sampler_Init(&sampler, frame % (CMJ_DIM * CMJ_DIM), SAMPLE_DIM_CAMERA_OFFSET, scramble); -#endif - - // Generate sample - float2 sample0 = Sampler_Sample2D(&sampler, SAMPLER_ARGS); - - // Calculate [0..1] image plane sample - float2 img_sample; - img_sample.x = (float)x / output_width + sample0.x / output_width; - img_sample.y = (float)y / output_height + sample0.y / output_height; - - // Transform into [-0.5, 0.5] - float2 h_sample = img_sample - make_float2(0.5f, 0.5f); - // Transform into [-dim/2, dim/2] - float2 c_sample = h_sample * camera->dim; - - // Calculate direction to image plane - my_ray->d.xyz = normalize(camera->focal_length * camera->forward + c_sample.x * camera->right + c_sample.y * camera->up); - // Origin == camera position + nearz * d - my_ray->o.xyz = camera->p + camera->zcap.x * my_ray->d.xyz; - // Max T value = zfar - znear since we moved origin to znear - my_ray->o.w = camera->zcap.y - camera->zcap.x; - // Generate random time from 0 to 1 - my_ray->d.w = sample0.x; - // Set ray max - my_ray->extra.x = 0xFFFFFFFF; - my_ray->extra.y = 0xFFFFFFFF; - Ray_SetExtra(my_ray, 1.f); - - PathVertex v; - PathVertex_Init(&v, - camera->p, - camera->forward, - camera->forward, - 0.f, - 1.f, - 1.f, - 1.f, - kCamera, - -1); - - *my_count = 1; - *my_vertex = v; - - // Initlize path data - my_path->throughput = make_float3(1.f, 1.f, 1.f); - my_path->volume = -1; - my_path->flags = 0; - my_path->active = 0xFF; - } -} - -KERNEL -void PerspectiveCameraDof_GenerateVertices( - // Camera - GLOBAL Camera const* restrict camera, - // Image resolution - int output_width, - int output_height, - // Pixel domain buffer - GLOBAL int const* restrict pixel_idx, - // Size of pixel domain buffer - GLOBAL int const* restrict num_pixels, - // RNG seed value - uint rng_seed, - // Current frame - uint frame, - // RNG data - GLOBAL uint* restrict random, - GLOBAL uint const* restrict sobolmat, - // Rays to generate - GLOBAL ray* restrict rays, - // Eye subpath vertices - GLOBAL PathVertex* restrict eye_subpath, - // Eye subpath length - GLOBAL int* restrict eye_subpath_length, - // Path buffer - GLOBAL Path* restrict paths -) - -{ - int global_id = get_global_id(0); - - // Check borders - if (global_id < *num_pixels) - { - int idx = pixel_idx[global_id]; - int y = idx / output_width; - int x = idx % output_width; - - // Get pointer to ray & path handles - GLOBAL ray* my_ray = rays + global_id; - GLOBAL PathVertex* my_vertex = eye_subpath + BDPT_MAX_SUBPATH_LEN * (y * output_width + x); - GLOBAL int* my_count = eye_subpath_length + y * output_width + x; - GLOBAL Path* my_path = paths + y * output_width + x; - - // Initialize sampler - Sampler sampler; -#if SAMPLER == SOBOL - uint scramble = random[x + output_width * y] * 0x1fe3434f; - - if (frame & 0xF) - { - random[x + output_width * y] = WangHash(scramble); - } - - Sampler_Init(&sampler, frame, SAMPLE_DIM_CAMERA_OFFSET, scramble); -#elif SAMPLER == RANDOM - uint scramble = x + output_width * y * rng_seed; - Sampler_Init(&sampler, scramble); -#elif SAMPLER == CMJ - uint rnd = random[x + output_width * y]; - uint scramble = rnd * 0x1fe3434f * ((frame + 133 * rnd) / (CMJ_DIM * CMJ_DIM)); - Sampler_Init(&sampler, frame % (CMJ_DIM * CMJ_DIM), SAMPLE_DIM_CAMERA_OFFSET, scramble); -#endif - - // Generate pixel and lens samples - float2 sample0 = Sampler_Sample2D(&sampler, SAMPLER_ARGS); - float2 sample1 = Sampler_Sample2D(&sampler, SAMPLER_ARGS); - - // Calculate [0..1] image plane sample - float2 img_sample; - img_sample.x = (float)x / output_width + sample0.x / output_width; - img_sample.y = (float)y / output_height + sample0.y / output_height; - - // Transform into [-0.5, 0.5] - float2 h_sample = img_sample - make_float2(0.5f, 0.5f); - // Transform into [-dim/2, dim/2] - float2 c_sample = h_sample * camera->dim; - - // Generate sample on the lens - float2 lens_sample = camera->aperture * Sample_MapToDiskConcentric(sample1); - // Calculate position on focal plane - float2 focal_plane_sample = c_sample * camera->focus_distance / camera->focal_length; - // Calculate ray direction - float2 camera_dir = focal_plane_sample - lens_sample; - - // Calculate direction to image plane - my_ray->d.xyz = normalize(camera->forward * camera->focus_distance + camera->right * camera_dir.x + camera->up * camera_dir.y); - // Origin == camera position + nearz * d - my_ray->o.xyz = camera->p + lens_sample.x * camera->right + lens_sample.y * camera->up; - // Max T value = zfar - znear since we moved origin to znear - my_ray->o.w = camera->zcap.y - camera->zcap.x; - // Generate random time from 0 to 1 - my_ray->d.w = sample0.x; - // Set ray max - my_ray->extra.x = 0xFFFFFFFF; - my_ray->extra.y = 0xFFFFFFFF; - Ray_SetExtra(my_ray, 1.f); - - PathVertex v; - PathVertex_Init(&v, - camera->p, - camera->forward, - camera->forward, - 0.f, - 1.f, - 1.f, - 1.f, - kCamera, - -1); - - *my_count = 1; - *my_vertex = v; - - // Initlize path data - my_path->throughput = make_float3(1.f, 1.f, 1.f); - my_path->volume = -1; - my_path->flags = 0; - my_path->active = 0xFF; - } -} - - -#endif // CAMERA_CL diff --git a/Baikal/CL/integrator_pt.cl b/Baikal/CL/integrator_pt.cl deleted file mode 100644 index 8e29858e..00000000 --- a/Baikal/CL/integrator_pt.cl +++ /dev/null @@ -1,979 +0,0 @@ - -/********************************************************************** -Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. - -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 <../Baikal/CL/common.cl> -#include <../Baikal/CL/ray.cl> -#include <../Baikal/CL/isect.cl> -#include <../Baikal/CL/utils.cl> -#include <../Baikal/CL/payload.cl> -#include <../Baikal/CL/texture.cl> -#include <../Baikal/CL/sampling.cl> -#include <../Baikal/CL/normalmap.cl> -#include <../Baikal/CL/bxdf.cl> -#include <../Baikal/CL/light.cl> -#include <../Baikal/CL/camera.cl> -#include <../Baikal/CL/scene.cl> -#include <../Baikal/CL/material.cl> -#include <../Baikal/CL/volumetrics.cl> -#include <../Baikal/CL/path.cl> - - -// This kernel only handles scattered paths. -// It applies direct illumination and generates -// path continuation if multiscattering is enabled. -__kernel void ShadeVolume( - // Ray batch - __global ray const* rays, - // Intersection data - __global Intersection const* isects, - // Hit indices - __global int const* hitindices, - // Pixel indices - __global int const* pixelindices, - // Number of rays - __global int const* numhits, - // Vertices - __global float3 const* vertices, - // Normals - __global float3 const* normals, - // UVs - __global float2 const* uvs, - // Indices - __global int const* indices, - // Shapes - __global Shape const* shapes, - // Material IDs - __global int const* materialids, - // Materials - __global Material const* materials, - // Textures - TEXTURE_ARG_LIST, - // Environment texture index - int env_light_idx, - // Emissives - __global Light const* lights, - // Number of emissive objects - int num_lights, - // RNG seed - uint rngseed, - // Sampler state - __global uint* random, - // Sobol matrices - __global uint const* sobolmat, - // Current bounce - int bounce, - // Current frame - int frame, - // Volume data - __global Volume const* volumes, - // Shadow rays - __global ray* shadowrays, - // Light samples - __global float3* lightsamples, - // Path throughput - __global Path* paths, - // Indirect rays (next path segment) - __global ray* indirectrays, - // Radiance - __global float3* output -) -{ - int globalid = get_global_id(0); - - Scene scene = - { - vertices, - normals, - uvs, - indices, - shapes, - materialids, - materials, - lights, - env_light_idx, - num_lights - }; - - if (globalid < *numhits) - { - // Fetch index - int hitidx = hitindices[globalid]; - int pixelidx = pixelindices[globalid]; - Intersection isect = isects[hitidx]; - - __global Path* path = paths + pixelidx; - - // Only apply to scattered paths - if (!Path_IsScattered(path)) - { - return; - } - - // Fetch incoming ray - float3 o = rays[hitidx].o.xyz; - float3 wi = rays[hitidx].d.xyz; - - Sampler sampler; -#if SAMPLER == SOBOL - uint scramble = random[pixelidx] * 0x1fe3434f; - Sampler_Init(&sampler, frame, SAMPLE_DIM_SURFACE_OFFSET + bounce * SAMPLE_DIMS_PER_BOUNCE + SAMPLE_DIM_VOLUME_EVALUATE_OFFSET, scramble); -#elif SAMPLER == RANDOM - uint scramble = pixelidx * rngseed; - Sampler_Init(&sampler, scramble); -#elif SAMPLER == CMJ - uint rnd = random[pixelidx]; - uint scramble = rnd * 0x1fe3434f * ((frame + 13 * rnd) / (CMJ_DIM * CMJ_DIM)); - Sampler_Init(&sampler, frame % (CMJ_DIM * CMJ_DIM), SAMPLE_DIM_SURFACE_OFFSET + bounce * SAMPLE_DIMS_PER_BOUNCE + SAMPLE_DIM_VOLUME_EVALUATE_OFFSET, scramble); -#endif - - - // Here we know that volidx != -1 since this is a precondition - // for scattering event - int volidx = Path_GetVolumeIdx(path); - - // Sample light source - float pdf = 0.f; - float selection_pdf = 0.f; - float3 wo; - - int light_idx = Scene_SampleLight(&scene, Sampler_Sample1D(&sampler, SAMPLER_ARGS), &selection_pdf); - - // Here we need fake differential geometry for light sampling procedure - DifferentialGeometry dg; - // put scattering position in there (it is along the current ray at isect.distance - // since EvaluateVolume has put it there - dg.p = o + wi * Intersection_GetDistance(isects + hitidx); - // Get light sample intencity - float3 le = Light_Sample (light_idx, &scene, &dg, TEXTURE_ARGS, Sampler_Sample2D(&sampler, SAMPLER_ARGS), &wo, &pdf); - - // Generate shadow ray - float shadow_ray_length = length(wo); - Ray_Init(shadowrays + globalid, dg.p, normalize(wo), shadow_ray_length, 0.f, 0xFFFFFFFF); - - // Evaluate volume transmittion along the shadow ray (it is incorrect if the light source is outside of the - // current volume, but in this case it will be discarded anyway since the intersection at the outer bound - // of a current volume), so the result is fully correct. - float3 tr = Volume_Transmittance(&volumes[volidx], &shadowrays[globalid], shadow_ray_length); - - // Volume emission is applied only if the light source is in the current volume(this is incorrect since the light source might be - // outside of a volume and we have to compute fraction of ray in this case, but need to figure out how) - float3 r = Volume_Emission(&volumes[volidx], &shadowrays[globalid], shadow_ray_length); - - // This is the estimate coming from a light source - // TODO: remove hardcoded phase func and sigma - r += tr * le * volumes[volidx].sigma_s * PhaseFunction_Uniform(wi, normalize(wo)) / pdf / selection_pdf; - - // Only if we have some radiance compute the visibility ray - if (NON_BLACK(tr) && NON_BLACK(r) && pdf > 0.f) - { - // Put lightsample result - lightsamples[globalid] = REASONABLE_RADIANCE(r * Path_GetThroughput(path)); - } - else - { - // Nothing to compute - lightsamples[globalid] = 0.f; - // Otherwise make it incative to save intersector cycles (hopefully) - Ray_SetInactive(shadowrays + globalid); - } - -#ifdef MULTISCATTER - // This is highly brute-force - // TODO: investigate importance sampling techniques here - wo = Sample_MapToSphere(Sampler_Sample2D(&sampler, SAMPLER_ARGS)); - pdf = 1.f / (4.f * PI); - - // Generate new path segment - Ray_Init(indirectrays + globalid, dg.p, normalize(wo), CRAZY_HIGH_DISTANCE, 0.f, 0xFFFFFFFF); - - // Update path throughput multiplying by phase function. - Path_MulThroughput(path, volumes[volidx].sigma_s * PhaseFunction_Uniform(wi, normalize(wo)) / pdf); -#else - // Single-scattering mode only, - // kill the path and compact away on next iteration - Path_Kill(path); - Ray_SetInactive(indirectrays + globalid); -#endif - } -} - - - -// Handle ray-surface interaction possibly generating path continuation. -// This is only applied to non-scattered paths. -__kernel void ShadeSurface( - // Ray batch - __global ray const* rays, - // Intersection data - __global Intersection const* isects, - // Hit indices - __global int const* hitindices, - // Pixel indices - __global int const* pixelindices, - // Number of rays - __global int const* numhits, - // Vertices - __global float3 const* vertices, - // Normals - __global float3 const* normals, - // UVs - __global float2 const* uvs, - // Indices - __global int const* indices, - // Shapes - __global Shape const* shapes, - // Material IDs - __global int const* materialids, - // Materials - __global Material const* materials, - // Textures - TEXTURE_ARG_LIST, - // Environment texture index - int env_light_idx, - // Emissives - __global Light const* lights, - // Number of emissive objects - int num_lights, - // RNG seed - uint rngseed, - // Sampler states - __global uint* random, - // Sobol matrices - __global uint const* sobolmat, - // Current bounce - int bounce, - // Frame - int frame, - // Volume data - __global Volume const* volumes, - // Shadow rays - __global ray* shadowrays, - // Light samples - __global float3* lightsamples, - // Path throughput - __global Path* paths, - // Indirect rays - __global ray* indirectrays, - // Radiance - __global float3* output -) -{ - int globalid = get_global_id(0); - - Scene scene = - { - vertices, - normals, - uvs, - indices, - shapes, - materialids, - materials, - lights, - env_light_idx, - num_lights - }; - - // Only applied to active rays after compaction - if (globalid < *numhits) - { - // Fetch index - int hitidx = hitindices[globalid]; - int pixelidx = pixelindices[globalid]; - Intersection isect = isects[hitidx]; - - __global Path* path = paths + pixelidx; - - // Early exit for scattered paths - if (Path_IsScattered(path)) - { - return; - } - - // Fetch incoming ray direction - float3 wi = -normalize(rays[hitidx].d.xyz); - - Sampler sampler; -#if SAMPLER == SOBOL - uint scramble = random[pixelidx] * 0x1fe3434f; - Sampler_Init(&sampler, frame, SAMPLE_DIM_SURFACE_OFFSET + bounce * SAMPLE_DIMS_PER_BOUNCE, scramble); -#elif SAMPLER == RANDOM - uint scramble = pixelidx * rngseed; - Sampler_Init(&sampler, scramble); -#elif SAMPLER == CMJ - uint rnd = random[pixelidx]; - uint scramble = rnd * 0x1fe3434f * ((frame + 331 * rnd) / (CMJ_DIM * CMJ_DIM)); - Sampler_Init(&sampler, frame % (CMJ_DIM * CMJ_DIM), SAMPLE_DIM_SURFACE_OFFSET + bounce * SAMPLE_DIMS_PER_BOUNCE, scramble); -#endif - - // Fill surface data - DifferentialGeometry diffgeo; - Scene_FillDifferentialGeometry(&scene, &isect,&diffgeo); - - // Check if we are hitting from the inside - float ngdotwi = dot(diffgeo.ng, wi); - bool backfacing = ngdotwi < 0.f; - - // Select BxDF - Material_Select(&scene, wi, &sampler, TEXTURE_ARGS, SAMPLER_ARGS, &diffgeo); - - // Terminate if emissive - if (Bxdf_IsEmissive(&diffgeo)) - { - if (!backfacing) - { - float weight = 1.f; - - if (bounce > 0 && !Path_IsSpecular(path)) - { - float2 extra = Ray_GetExtra(&rays[hitidx]); - float ld = isect.uvwt.w; - float denom = fabs(dot(diffgeo.n, wi)) * diffgeo.area; - // TODO: num_lights should be num_emissies instead, presence of analytical lights breaks this code - float bxdflightpdf = denom > 0.f ? (ld * ld / denom / num_lights) : 0.f; - weight = BalanceHeuristic(1, extra.x, 1, bxdflightpdf); - } - - // In this case we hit after an application of MIS process at previous step. - // That means BRDF weight has been already applied. - output[pixelidx] += Path_GetThroughput(path) * Emissive_GetLe(&diffgeo, TEXTURE_ARGS) * weight; - } - - Path_Kill(path); - Ray_SetInactive(shadowrays + globalid); - Ray_SetInactive(indirectrays + globalid); - - lightsamples[globalid] = 0.f; - return; - } - - - float s = Bxdf_IsBtdf(&diffgeo) ? (-sign(ngdotwi)) : 1.f; - if (backfacing && !Bxdf_IsBtdf(&diffgeo)) - { - //Reverse normal and tangents in this case - //but not for BTDFs, since BTDFs rely - //on normal direction in order to arrange - //indices of refraction - diffgeo.n = -diffgeo.n; - diffgeo.dpdu = -diffgeo.dpdu; - diffgeo.dpdv = -diffgeo.dpdv; - s = -s; - } - - - DifferentialGeometry_ApplyBumpNormalMap(&diffgeo, TEXTURE_ARGS); - DifferentialGeometry_CalculateTangentTransforms(&diffgeo); - - float ndotwi = fabs(dot(diffgeo.n, wi)); - - float lightpdf = 0.f; - float bxdflightpdf = 0.f; - float bxdfpdf = 0.f; - float lightbxdfpdf = 0.f; - float selection_pdf = 0.f; - float3 radiance = 0.f; - float3 lightwo; - float3 bxdfwo; - float3 wo; - float bxdfweight = 1.f; - float lightweight = 1.f; - - int light_idx = Scene_SampleLight(&scene, Sampler_Sample1D(&sampler, SAMPLER_ARGS), &selection_pdf); - - float3 throughput = Path_GetThroughput(path); - - // Sample bxdf - float3 bxdf = Bxdf_Sample(&diffgeo, wi, TEXTURE_ARGS, Sampler_Sample2D(&sampler, SAMPLER_ARGS), &bxdfwo, &bxdfpdf); - - // If we have light to sample we can hopefully do mis - if (light_idx > -1) - { - // Sample light - float3 le = Light_Sample(light_idx, &scene, &diffgeo, TEXTURE_ARGS, Sampler_Sample2D(&sampler, SAMPLER_ARGS), &lightwo, &lightpdf); - lightbxdfpdf = Bxdf_GetPdf(&diffgeo, wi, normalize(lightwo), TEXTURE_ARGS); - lightweight = Light_IsSingular(&scene.lights[light_idx]) ? 1.f : BalanceHeuristic(1, lightpdf / selection_pdf, 1, lightbxdfpdf); - - // Apply MIS to account for both - if (NON_BLACK(le) && lightpdf > 0.0f && !Bxdf_IsSingular(&diffgeo)) - { - wo = lightwo; - float ndotwo = fabs(dot(diffgeo.n, normalize(wo))); - radiance = le * ndotwo * Bxdf_Evaluate(&diffgeo, wi, normalize(wo), TEXTURE_ARGS) * throughput * lightweight / lightpdf / selection_pdf; - } - } - - // If we have some light here generate a shadow ray - if (NON_BLACK(radiance)) - { - // Generate shadow ray - float3 shadow_ray_o = diffgeo.p + CRAZY_LOW_DISTANCE * s * diffgeo.ng; - float3 temp = diffgeo.p + wo - shadow_ray_o; - float3 shadow_ray_dir = normalize(temp); - float shadow_ray_length = length(temp); - int shadow_ray_mask = 0xFFFFFFFF; - - Ray_Init(shadowrays + globalid, shadow_ray_o, shadow_ray_dir, shadow_ray_length, 0.f, shadow_ray_mask); - - // Apply the volume to shadow ray if needed - int volidx = Path_GetVolumeIdx(path); - if (volidx != -1) - { - radiance *= Volume_Transmittance(&volumes[volidx], &shadowrays[globalid], shadow_ray_length); - radiance += Volume_Emission(&volumes[volidx], &shadowrays[globalid], shadow_ray_length) * throughput; - } - - // And write the light sample - lightsamples[globalid] = REASONABLE_RADIANCE(radiance); - } - else - { - // Otherwise save some intersector cycles - Ray_SetInactive(shadowrays + globalid); - lightsamples[globalid] = 0; - } - - // Apply Russian roulette - float q = max(min(0.5f, - // Luminance - 0.2126f * throughput.x + 0.7152f * throughput.y + 0.0722f * throughput.z), 0.01f); - // Only if it is 3+ bounce - bool rr_apply = bounce > 3; - bool rr_stop = Sampler_Sample1D(&sampler, SAMPLER_ARGS) > q && rr_apply; - - if (rr_apply) - { - Path_MulThroughput(path, 1.f / q); - } - - if (Bxdf_IsSingular(&diffgeo)) - { - Path_SetSpecularFlag(path); - } - - bxdfwo = normalize(bxdfwo); - float3 t = bxdf * fabs(dot(diffgeo.n, bxdfwo)); - - // Only continue if we have non-zero throughput & pdf - if (NON_BLACK(t) && bxdfpdf > 0.f && !rr_stop) - { - // Update the throughput - Path_MulThroughput(path, t / bxdfpdf); - - // Generate ray - float3 indirect_ray_dir = bxdfwo; - float3 indirect_ray_o = diffgeo.p + CRAZY_LOW_DISTANCE * s * diffgeo.ng; - - Ray_Init(indirectrays + globalid, indirect_ray_o, indirect_ray_dir, CRAZY_HIGH_DISTANCE, 0.f, 0xFFFFFFFF); - Ray_SetExtra(indirectrays + globalid, make_float2(bxdfpdf, 0.f)); - } - else - { - // Otherwise kill the path - Path_Kill(path); - Ray_SetInactive(indirectrays + globalid); - } - } -} - -///< Illuminate missing rays -__kernel void ShadeBackgroundEnvMap( - // Ray batch - __global ray const* rays, - // Intersection data - __global Intersection const* isects, - // Pixel indices - __global int const* pixelindices, - // Number of rays - int numrays, - __global Light const* lights, - int env_light_idx, - // Textures - TEXTURE_ARG_LIST, - // Environment texture index - __global Path const* paths, - __global Volume const* volumes, - // Output values - __global float4* output -) -{ - int globalid = get_global_id(0); - - if (globalid < numrays) - { - int pixelidx = pixelindices[globalid]; - - // In case of a miss - if (isects[globalid].shapeid < 0 && env_light_idx != -1) - { - // Multiply by throughput - int volidx = paths[pixelidx].volume; - - Light light = lights[env_light_idx]; - - if (volidx == -1) - output[pixelidx].xyz += light.multiplier * Texture_SampleEnvMap(rays[globalid].d.xyz, TEXTURE_ARGS_IDX(light.tex)); - else - { - output[pixelidx].xyz += light.multiplier * Texture_SampleEnvMap(rays[globalid].d.xyz, TEXTURE_ARGS_IDX(light.tex)) * - Volume_Transmittance(&volumes[volidx], &rays[globalid], rays[globalid].o.w); - - output[pixelidx].xyz += Volume_Emission(&volumes[volidx], &rays[globalid], rays[globalid].o.w); - } - } - - if (isnan(output[pixelidx].x) || isnan(output[pixelidx].y) || isnan(output[pixelidx].z)) - { - output[pixelidx] = make_float4(100.f, 0.f, 0.f, 1.f); - } - - output[pixelidx].w += 1.f; - } -} - -///< Handle light samples and visibility info and add contribution to final buffer -__kernel void GatherLightSamples( - // Pixel indices - __global int const* pixelindices, - // Number of rays - __global int* numrays, - // Shadow rays hits - __global int const* shadowhits, - // Light samples - __global float3 const* lightsamples, - // throughput - __global Path const* paths, - // Radiance sample buffer - __global float4* output -) -{ - int globalid = get_global_id(0); - - if (globalid < *numrays) - { - // Get pixel id for this sample set - int pixelidx = pixelindices[globalid]; - - - // Prepare accumulator variable - float3 radiance = make_float3(0.f, 0.f, 0.f); - - // Start collecting samples - { - // If shadow ray didn't hit anything and reached skydome - if (shadowhits[globalid] == -1) - { - // Add its contribution to radiance accumulator - radiance += lightsamples[globalid]; - } - } - - // Divide by number of light samples (samples already have built-in throughput) - output[pixelidx].xyz += radiance; - } -} - - -///< Handle light samples and visibility info and add contribution to final buffer -__kernel void GatherOcclusion( - // Pixel indices - __global int const* pixelindices, - // Number of rays - __global int const* numrays, - // Shadow rays hits - __global int const* shadowhits, - // Light samples - __global float3 const* lightsamples, - // throughput - __global float3 const* throughput, - // Radiance sample buffer - __global float4* output -) -{ - int globalid = get_global_id(0); - - if (globalid < *numrays) - { - // Get pixel id for this sample set - int pixelidx = pixelindices[globalid]; - - float visibility = (shadowhits[globalid] == 1) ? 0.f : 1.f; - - output[pixelidx].xyz += visibility; - output[pixelidx].w += 1.f; - } -} - -///< Restore pixel indices after compaction -__kernel void RestorePixelIndices( - // Compacted indices - __global int const* compacted_indices, - // Number of compacted indices - __global int* numitems, - // Previous pixel indices - __global int const* previndices, - // New pixel indices - __global int* newindices -) -{ - int globalid = get_global_id(0); - - // Handle only working subset - if (globalid < *numitems) - { - newindices[globalid] = previndices[compacted_indices[globalid]]; - } -} - -///< Restore pixel indices after compaction -__kernel void FilterPathStream( - // Intersections - __global Intersection const* isects, - // Number of compacted indices - __global int const* numitems, - // Pixel indices - __global int const* pixelindices, - // Paths - __global Path* paths, - // Predicate - __global int* predicate -) -{ - int globalid = get_global_id(0); - - // Handle only working subset - if (globalid < *numitems) - { - int pixelidx = pixelindices[globalid]; - - __global Path* path = paths + pixelidx; - - if (Path_IsAlive(path)) - { - bool kill = (length(Path_GetThroughput(path)) < CRAZY_LOW_THROUGHPUT); - - if (!kill) - { - predicate[globalid] = isects[globalid].shapeid >= 0 ? 1 : 0; - } - else - { - Path_Kill(path); - predicate[globalid] = 0; - } - } - else - { - predicate[globalid] = 0; - } - } -} - -///< Illuminate missing rays -__kernel void ShadeMiss( - // Ray batch - __global ray const* rays, - // Intersection data - __global Intersection const* isects, - // Pixel indices - __global int const* pixelindices, - // Number of rays - __global int const* numrays, - __global Light const* lights, - int env_light_idx, - // Textures - TEXTURE_ARG_LIST, - __global Path const* paths, - __global Volume const* volumes, - // Output values - __global float4* output -) -{ - int globalid = get_global_id(0); - - if (globalid < *numrays) - { - int pixelidx = pixelindices[globalid]; - - __global Path const* path = paths + pixelidx; - - // In case of a miss - if (isects[globalid].shapeid < 0 && Path_IsAlive(path)) - { - Light light = lights[env_light_idx]; - - float3 t = Path_GetThroughput(path); - output[pixelidx].xyz += REASONABLE_RADIANCE(light.multiplier * Texture_SampleEnvMap(rays[globalid].d.xyz, TEXTURE_ARGS_IDX(light.tex)) * t); - } - } -} - - -// Copy data to interop texture if supported -__kernel void AccumulateData( - __global float4 const* srcdata, - int numelems, - __global float4* dstdata -) -{ - int gid = get_global_id(0); - - if (gid < numelems) - { - float4 v = srcdata[gid]; - dstdata[gid] += v; - } -} - -// Copy data to interop texture if supported -__kernel void ApplyGammaAndCopyData( - __global float4 const* data, - int imgwidth, - int imgheight, - float gamma, - write_only image2d_t img -) -{ - int gid = get_global_id(0); - - int gidx = gid % imgwidth; - int gidy = gid / imgwidth; - - if (gidx < imgwidth && gidy < imgheight) - { - float4 v = data[gid]; - float4 val = clamp(native_powr(v / v.w, 1.f / gamma), 0.f, 1.f); - write_imagef(img, make_int2(gidx, gidy), val); - } -} - -// Fill AOVs -__kernel void FillAOVs( - // Ray batch - __global ray const* rays, - // Intersection data - __global Intersection const* isects, - // Pixel indices - __global int const* pixel_idx, - // Number of pixels - __global int const* num_items, - // Vertices - __global float3 const* vertices, - // Normals - __global float3 const* normals, - // UVs - __global float2 const* uvs, - // Indices - __global int const* indices, - // Shapes - __global Shape const* shapes, - // Material IDs - __global int const* materialids, - // Materials - __global Material const* materials, - // Textures - TEXTURE_ARG_LIST, - // Environment texture index - int env_light_idx, - // Emissives - __global Light const* lights, - // Number of emissive objects - int num_lights, - // RNG seed - uint rngseed, - // Sampler states - __global uint* random, - // Sobol matrices - __global uint const* sobolmat, - // Frame - int frame, - // World position flag - int world_position_enabled, - // World position AOV - __global float4* aov_world_position, - // World normal flag - int world_shading_normal_enabled, - // World normal AOV - __global float4* aov_world_shading_normal, - // World true normal flag - int world_geometric_normal_enabled, - // World true normal AOV - __global float4* aov_world_geometric_normal, - // UV flag - int uv_enabled, - // UV AOV - __global float4* aov_uv, - // Wireframe flag - int wireframe_enabled, - // Wireframe AOV - __global float4* aov_wireframe, - // Albedo flag - int albedo_enabled, - // Wireframe AOV - __global float4* aov_albedo -) -{ - int globalid = get_global_id(0); - - Scene scene = - { - vertices, - normals, - uvs, - indices, - shapes, - materialids, - materials, - lights, - env_light_idx, - num_lights - }; - - // Only applied to active rays after compaction - if (globalid < *num_items) - { - Intersection isect = isects[globalid]; - int idx = pixel_idx[globalid]; - - if (isect.shapeid > -1) - { - // Fetch incoming ray direction - float3 wi = -normalize(rays[globalid].d.xyz); - - Sampler sampler; -#if SAMPLER == SOBOL - uint scramble = random[globalid] * 0x1fe3434f; - Sampler_Init(&sampler, frame, SAMPLE_DIM_SURFACE_OFFSET, scramble); -#elif SAMPLER == RANDOM - uint scramble = globalid * rngseed; - Sampler_Init(&sampler, scramble); -#elif SAMPLER == CMJ - uint rnd = random[globalid]; - uint scramble = rnd * 0x1fe3434f * ((frame + 331 * rnd) / (CMJ_DIM * CMJ_DIM)); - Sampler_Init(&sampler, frame % (CMJ_DIM * CMJ_DIM), SAMPLE_DIM_SURFACE_OFFSET, scramble); -#endif - - // Fill surface data - DifferentialGeometry diffgeo; - Scene_FillDifferentialGeometry(&scene, &isect, &diffgeo); - - if (world_position_enabled) - { - aov_world_position[idx].xyz += diffgeo.p; - aov_world_position[idx].w += 1.f; - } - - if (world_shading_normal_enabled) - { - float ngdotwi = dot(diffgeo.ng, wi); - bool backfacing = ngdotwi < 0.f; - - // Select BxDF - Material_Select(&scene, wi, &sampler, TEXTURE_ARGS, SAMPLER_ARGS, &diffgeo); - - float s = Bxdf_IsBtdf(&diffgeo) ? (-sign(ngdotwi)) : 1.f; - if (backfacing && !Bxdf_IsBtdf(&diffgeo)) - { - //Reverse normal and tangents in this case - //but not for BTDFs, since BTDFs rely - //on normal direction in order to arrange - //indices of refraction - diffgeo.n = -diffgeo.n; - diffgeo.dpdu = -diffgeo.dpdu; - diffgeo.dpdv = -diffgeo.dpdv; - } - - DifferentialGeometry_ApplyBumpNormalMap(&diffgeo, TEXTURE_ARGS); - DifferentialGeometry_CalculateTangentTransforms(&diffgeo); - - aov_world_shading_normal[idx].xyz += diffgeo.n; - aov_world_shading_normal[idx].w += 1.f; - } - - if (world_geometric_normal_enabled) - { - aov_world_geometric_normal[idx].xyz += diffgeo.ng; - aov_world_geometric_normal[idx].w += 1.f; - } - - if (wireframe_enabled) - { - bool hit = (isect.uvwt.x < 1e-3) || (isect.uvwt.y < 1e-3) || (1.f - isect.uvwt.x - isect.uvwt.y < 1e-3); - float3 value = hit ? make_float3(1.f, 1.f, 1.f) : make_float3(0.f, 0.f, 0.f); - aov_wireframe[idx].xyz += value; - aov_wireframe[idx].w += 1.f; - } - - if (uv_enabled) - { - aov_uv[idx].xyz += diffgeo.uv.xyy; - aov_uv[idx].w += 1.f; - } - - if (albedo_enabled) - { - float ngdotwi = dot(diffgeo.ng, wi); - bool backfacing = ngdotwi < 0.f; - - // Select BxDF - Material_Select(&scene, wi, &sampler, TEXTURE_ARGS, SAMPLER_ARGS, &diffgeo); - - const float3 kd = Texture_GetValue3f(diffgeo.mat.kx.xyz, diffgeo.uv, TEXTURE_ARGS_IDX(diffgeo.mat.kxmapidx)); - - aov_albedo[idx].xyz += kd; - aov_albedo[idx].w += 1.f; - } - } - } -} - -__kernel void GenerateTileDomain( - int output_width, - int output_height, - int tile_offset_x, - int tile_offset_y, - int tile_width, - int tile_height, - int subtile_width, - int subtile_height, - __global int* pixelidx0, - __global int* pixelidx1, - __global int* count -) -{ - int tile_x = get_global_id(0); - int tile_y = get_global_id(1); - int tile_start_idx = output_width * tile_offset_y + tile_offset_x; - - if (tile_x < tile_width && tile_y < tile_height) - { - // TODO: implement subtile support - int idx = tile_start_idx + tile_y * output_width + tile_x; - pixelidx0[tile_y * tile_width + tile_x] = idx; - pixelidx1[tile_y * tile_width + tile_x] = idx; - } - - if (tile_x == 0 && tile_y == 0) - { - *count = tile_width * tile_height; - } -} diff --git a/Baikal/CL/material.cl b/Baikal/CL/material.cl deleted file mode 100644 index 148b43de..00000000 --- a/Baikal/CL/material.cl +++ /dev/null @@ -1,175 +0,0 @@ -/********************************************************************** -Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. - -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 MATERIAL_CL -#define MATERIAL_CL - -#include <../Baikal/CL/common.cl> -#include <../Baikal/CL/utils.cl> -#include <../Baikal/CL/texture.cl> -#include <../Baikal/CL/payload.cl> -#include <../Baikal/CL/bxdf.cl> - -void Material_Select( - // Scene data - Scene const* scene, - // Incoming direction - float3 wi, - // Sampler - Sampler* sampler, - // Texture args - TEXTURE_ARG_LIST, - // Sampler args - SAMPLER_ARG_LIST, - // Geometry - DifferentialGeometry* dg -) -{ - // Check material type - int type = dg->mat.type; - int idx = dg->material_index; - - // If material is regular BxDF we do not have to sample it - if (type != kFresnelBlend && type != kMix) - { - // If fresnel > 0 here we need to calculate Frensle factor (remove this workaround) - if (dg->mat.fresnel > 0.f) - { - float etai = 1.f; - float etat = dg->mat.ni; - float cosi = dot(dg->n, wi); - - // Revert normal and eta if needed - if (cosi < 0.f) - { - float tmp = etai; - etai = etat; - etat = tmp; - cosi = -cosi; - } - - float eta = etai / etat; - float sini2 = 1.f - cosi * cosi; - float sint2 = eta * eta * sini2; - - float fresnel = 1.f; - - if (sint2 < 1.f) - { - float cost = native_sqrt(max(0.f, 1.f - sint2)); - fresnel = FresnelDielectric(etai, etat, cosi, cost); - } - - dg->mat.fresnel = Bxdf_IsBtdf(dg) ? (1.f - fresnel) : fresnel; - } - else - { - // Otherwise set multiplier to 1 - dg->mat.fresnel = 1.f; - } - } - // Here we deal with combined material and we have to sample - else - { - // Prefetch current material - Material mat = dg->mat; - int iter = 0; - - // Might need several passes of sampling - while (mat.type == kFresnelBlend || mat.type == kMix) - { - if (mat.type == kFresnelBlend) - { - float etai = 1.f; - float etat = mat.ni; - float cosi = dot(dg->n, wi); - - // Revert normal and eta if needed - if (cosi < 0.f) - { - float tmp = etai; - etai = etat; - etat = tmp; - cosi = -cosi; - } - - float eta = etai / etat; - float sini2 = 1.f - cosi * cosi; - float sint2 = eta * eta * sini2; - float fresnel = 1.f; - - if (sint2 < 1.f) - { - float cost = native_sqrt(max(0.f, 1.f - sint2)); - fresnel = FresnelDielectric(etai, etat, cosi, cost); - } - - float sample = Sampler_Sample1D(sampler, SAMPLER_ARGS); - - if (sample < fresnel) - { - // Sample top - idx = mat.brdftopidx; - // - mat = scene->materials[idx]; - mat.fresnel = 1.f; - } - else - { - // Sample base - idx = mat.brdfbaseidx; - // - mat = scene->materials[idx]; - mat.fresnel = 1.f; - } - } - else - { - float sample = Sampler_Sample1D(sampler, SAMPLER_ARGS); - - float weight = Texture_GetValue1f(mat.ns, dg->uv, TEXTURE_ARGS_IDX(mat.nsmapidx)); - - if (sample < weight) - { - // Sample top - idx = mat.brdftopidx; - // - mat = scene->materials[idx]; - mat.fresnel = 1.f; - } - else - { - // Sample base - idx = mat.brdfbaseidx; - // - mat = scene->materials[idx]; - mat.fresnel = 1.f; - } - } - } - - dg->material_index = idx; - dg->mat = mat; - } -} - - -#endif // MATERIAL_CL \ No newline at end of file diff --git a/Baikal/CLW/clw_scene_controller.cpp b/Baikal/CLW/clw_scene_controller.cpp deleted file mode 100644 index 877875b9..00000000 --- a/Baikal/CLW/clw_scene_controller.cpp +++ /dev/null @@ -1,1078 +0,0 @@ -#include "CLW/clw_scene_controller.h" -#include "SceneGraph/scene1.h" -#include "SceneGraph/camera.h" -#include "SceneGraph/light.h" -#include "SceneGraph/shape.h" -#include "SceneGraph/material.h" -#include "SceneGraph/texture.h" -#include "SceneGraph/Collector/collector.h" -#include "SceneGraph/iterator.h" - -#include -#include -#include -#include -#include - -using namespace RadeonRays; - -namespace Baikal -{ - ClwSceneController::ClwSceneController(CLWContext context, int devidx) - : m_default_material(new SingleBxdf(SingleBxdf::BxdfType::kLambert)), - m_context(context) - { - // Get raw CL data out of CLW context - cl_device_id id = m_context.GetDevice(devidx).GetID(); - cl_command_queue queue = m_context.GetCommandQueue(devidx); - - // Create intersection API - m_api = CreateFromOpenClContext(m_context, id, queue); - - m_api->SetOption("acc.type", "fatbvh"); - m_api->SetOption("bvh.builder", "sah"); - m_api->SetOption("bvh.sah.num_bins", 64.f); - } - - Material const* ClwSceneController::GetDefaultMaterial() const - { - return m_default_material.get(); - } - - ClwSceneController::~ClwSceneController() - { - // Delete API - IntersectionApi::Delete(m_api); - } - - static void SplitMeshesAndInstances(Iterator* shape_iter, std::set& meshes, std::set& instances, std::set& excluded_meshes) - { - // Clear all sets - meshes.clear(); - instances.clear(); - excluded_meshes.clear(); - - // Prepare instance check lambda - auto is_instance = [](Shape const* shape) - { - if (dynamic_cast(shape)) - { - return true; - } - else - { - return false; - } - }; - - for (; shape_iter->IsValid(); shape_iter->Next()) - { - auto shape = shape_iter->ItemAs(); - - if (!is_instance(shape)) - { - meshes.emplace(static_cast(shape)); - } - else - { - instances.emplace(static_cast(shape)); - } - } - - for (auto& i : instances) - { - auto base_mesh = static_cast(i->GetBaseShape()); - if (meshes.find(base_mesh) == meshes.cend()) - { - excluded_meshes.emplace(base_mesh); - } - } - } - - static std::size_t GetShapeIdx(Iterator* shape_iter, Shape const* shape) - { - std::set meshes; - std::set excluded_meshes; - std::set instances; - SplitMeshesAndInstances(shape_iter, meshes, instances, excluded_meshes); - - std::size_t idx = 0; - for (auto& i : meshes) - { - if (i == shape) - { - return idx; - } - - ++idx; - } - - for (auto& i : excluded_meshes) - { - if (i == shape) - { - return idx; - } - - ++idx; - } - - for (auto& i : instances) - { - if (i == shape) - { - return idx; - } - - ++idx; - } - - return -1; - } - - void ClwSceneController::UpdateIntersector(Scene1 const& scene, ClwScene& out) const - { - // Detach and delete all shapes - for (auto& shape : out.isect_shapes) - { - m_api->DetachShape(shape); - m_api->DeleteShape(shape); - } - - // Clear shapes cache - out.isect_shapes.clear(); - // Only visible shapes are attached to the API. - // So excluded meshes are pushed into isect_shapes, but - // not to visible_shapes. - out.visible_shapes.clear(); - - // Create new shapes - std::unique_ptr shape_iter(scene.CreateShapeIterator()); - - if (!shape_iter->IsValid()) - { - throw std::runtime_error("No shapes in the scene"); - } - - // Split all shapes into meshes and instances sets. - std::set meshes; - // Excluded shapes are shapes which are not in the scene, - // but references by at least one instance. - std::set excluded_meshes; - std::set instances; - SplitMeshesAndInstances(shape_iter.get(), meshes, instances, excluded_meshes); - - // Keep shape->rr shape association for - // instance base shape lookup. - std::map rr_shapes; - - // Start from ID 1 - // Handle meshes - int id = 1; - for (auto& iter : meshes) - { - auto mesh = iter; - - auto shape = m_api->CreateMesh( - // Vertices starting from the first one - (float*)mesh->GetVertices(), - // Number of vertices - static_cast(mesh->GetNumVertices()), - // Stride - sizeof(float3), - // TODO: make API signature const - reinterpret_cast(mesh->GetIndices()), - // Index stride - 0, - // All triangles - nullptr, - // Number of primitives - static_cast(mesh->GetNumIndices() / 3) - ); - - auto transform = mesh->GetTransform(); - shape->SetTransform(transform, inverse(transform)); - shape->SetId(id++); - out.isect_shapes.push_back(shape); - out.visible_shapes.push_back(shape); - rr_shapes[mesh] = shape; - } - - // Handle excluded meshes - for (auto& iter : excluded_meshes) - { - auto mesh = iter; - - auto shape = m_api->CreateMesh( - // Vertices starting from the first one - (float*)mesh->GetVertices(), - // Number of vertices - static_cast(mesh->GetNumVertices()), - // Stride - sizeof(float3), - // TODO: make API signature const - reinterpret_cast(mesh->GetIndices()), - // Index stride - 0, - // All triangles - nullptr, - // Number of primitives - static_cast(mesh->GetNumIndices() / 3) - ); - - auto transform = mesh->GetTransform(); - shape->SetTransform(transform, inverse(transform)); - shape->SetId(id++); - out.isect_shapes.push_back(shape); - rr_shapes[mesh] = shape; - } - - // Handle instances - for (auto& iter: instances) - { - auto instance = iter; - auto rr_mesh = rr_shapes[instance->GetBaseShape()]; - auto shape = m_api->CreateInstance(rr_mesh); - - auto transform = instance->GetTransform(); - shape->SetTransform(transform, inverse(transform)); - shape->SetId(id++); - out.isect_shapes.push_back(shape); - out.visible_shapes.push_back(shape); - } - } - - void ClwSceneController::UpdateCamera(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, ClwScene& out) const - { - // TODO: support different camera types here - auto camera = static_cast(scene.GetCamera()); - - // Create light buffer if needed - if (out.camera.GetElementCount() == 0) - { - out.camera = m_context.CreateBuffer(1, CL_MEM_READ_ONLY); - } - - // TODO: remove this - out.camera_type = camera->GetAperture() > 0.f ? CameraType::kPhysical : CameraType::kDefault; - - // Update camera data - ClwScene::Camera* data = nullptr; - - // Map GPU camera buffer - m_context.MapBuffer(0, out.camera, CL_MAP_WRITE, &data).Wait(); - - // Copy camera parameters - data->forward = camera->GetForwardVector(); - data->up = camera->GetUpVector(); - data->right = camera->GetRightVector(); - data->p = camera->GetPosition(); - data->aperture = camera->GetAperture(); - data->aspect_ratio = camera->GetAspectRatio(); - data->dim = camera->GetSensorSize(); - data->focal_length = camera->GetFocalLength(); - data->focus_distance = camera->GetFocusDistance(); - data->zcap = camera->GetDepthRange(); - - // Unmap camera buffer - m_context.UnmapBuffer(0, out.camera, data); - - // Drop camera dirty flag - camera->SetDirty(false); - } - - void ClwSceneController::UpdateShapes(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, ClwScene& out) const - { - std::size_t num_vertices = 0; - std::size_t num_normals = 0; - std::size_t num_uvs = 0; - std::size_t num_indices = 0; - std::size_t num_material_ids = 0; - - std::size_t num_vertices_written = 0; - std::size_t num_normals_written = 0; - std::size_t num_uvs_written = 0; - std::size_t num_indices_written = 0; - std::size_t num_matids_written = 0; - std::size_t num_shapes_written = 0; - - std::unique_ptr shape_iter(scene.CreateShapeIterator()); - - // Sort shapes into meshes and instances sets. - std::set meshes; - // Excluded meshes are meshes which are not in the scene, - // but are references by at least one instance. - std::set excluded_meshes; - std::set instances; - SplitMeshesAndInstances(shape_iter.get(), meshes, instances, excluded_meshes); - - // Calculate GPU array sizes. Do that only for meshes, - // since instances do not occupy space in vertex buffers. - // However instances still have their own material ids. - for (auto& iter : meshes) - { - auto mesh = iter; - - num_vertices += mesh->GetNumVertices(); - num_normals += mesh->GetNumNormals(); - num_uvs += mesh->GetNumUVs(); - num_indices += mesh->GetNumIndices(); - num_material_ids += mesh->GetNumIndices() / 3; - } - - // Excluded meshes still occupy space in vertex buffers. - for (auto& iter : excluded_meshes) - { - auto mesh = iter; - - num_vertices += mesh->GetNumVertices(); - num_normals += mesh->GetNumNormals(); - num_uvs += mesh->GetNumUVs(); - num_indices += mesh->GetNumIndices(); - num_material_ids += mesh->GetNumIndices() / 3; - } - - // Instances only occupy material IDs space. - for (auto& iter : instances) - { - auto instance = iter; - auto mesh = static_cast(instance->GetBaseShape()); - num_material_ids += mesh->GetNumIndices() / 3; - } - - // Create CL arrays - out.vertices = m_context.CreateBuffer(num_vertices, CL_MEM_READ_ONLY); - out.normals = m_context.CreateBuffer(num_normals, CL_MEM_READ_ONLY); - out.uvs = m_context.CreateBuffer(num_uvs, CL_MEM_READ_ONLY); - out.indices = m_context.CreateBuffer(num_indices, CL_MEM_READ_ONLY); - - // Total number of entries in shapes GPU array - auto num_shapes = meshes.size() + excluded_meshes.size() + instances.size(); - out.shapes = m_context.CreateBuffer(num_shapes, CL_MEM_READ_ONLY); - out.materialids = m_context.CreateBuffer(num_material_ids, CL_MEM_READ_ONLY); - - float3* vertices = nullptr; - float3* normals = nullptr; - float2* uvs = nullptr; - int* indices = nullptr; - int* matids = nullptr; - ClwScene::Shape* shapes = nullptr; - - // Map arrays and prepare to write data - m_context.MapBuffer(0, out.vertices, CL_MAP_WRITE, &vertices); - m_context.MapBuffer(0, out.normals, CL_MAP_WRITE, &normals); - m_context.MapBuffer(0, out.uvs, CL_MAP_WRITE, &uvs); - m_context.MapBuffer(0, out.indices, CL_MAP_WRITE, &indices); - m_context.MapBuffer(0, out.materialids, CL_MAP_WRITE, &matids); - m_context.MapBuffer(0, out.shapes, CL_MAP_WRITE, &shapes).Wait(); - - // Keep associated shapes data for instance look up. - // We retrieve data from here while serializing instances, - // using base shape lookup. - std::map shape_data; - // Handle meshes - for (auto& iter : meshes) - { - auto mesh = iter; - - // Get pointers data - auto mesh_vertex_array = mesh->GetVertices(); - auto mesh_num_vertices = mesh->GetNumVertices(); - - auto mesh_normal_array = mesh->GetNormals(); - auto mesh_num_normals = mesh->GetNumNormals(); - - auto mesh_uv_array = mesh->GetUVs(); - auto mesh_num_uvs = mesh->GetNumUVs(); - - auto mesh_index_array = mesh->GetIndices(); - auto mesh_num_indices = mesh->GetNumIndices(); - - // Prepare shape descriptor - ClwScene::Shape shape; - shape.numprims = static_cast(mesh_num_indices / 3); - shape.startvtx = static_cast(num_vertices_written); - shape.startidx = static_cast(num_indices_written); - shape.start_material_idx = static_cast(num_matids_written); - - auto transform = mesh->GetTransform(); - shape.transform.m0 = { transform.m00, transform.m01, transform.m02, transform.m03 }; - shape.transform.m1 = { transform.m10, transform.m11, transform.m12, transform.m13 }; - shape.transform.m2 = { transform.m20, transform.m21, transform.m22, transform.m23 }; - shape.transform.m3 = { transform.m30, transform.m31, transform.m32, transform.m33 }; - - shape.linearvelocity = float3(0.0f, 0.f, 0.f); - shape.angularvelocity = float3(0.f, 0.f, 0.f, 1.f); - - shape_data[mesh] = shape; - - std::copy(mesh_vertex_array, mesh_vertex_array + mesh_num_vertices, vertices + num_vertices_written); - num_vertices_written += mesh_num_vertices; - - std::copy(mesh_normal_array, mesh_normal_array + mesh_num_normals, normals + num_normals_written); - num_normals_written += mesh_num_normals; - - std::copy(mesh_uv_array, mesh_uv_array + mesh_num_uvs, uvs + num_uvs_written); - num_uvs_written += mesh_num_uvs; - - std::copy(mesh_index_array, mesh_index_array + mesh_num_indices, indices + num_indices_written); - num_indices_written += mesh_num_indices; - - shapes[num_shapes_written++] = shape; - - // Check if mesh has a material and use default if not - auto material = mesh->GetMaterial(); - if (!material) - { - material = m_default_material.get(); - } - - auto matidx = mat_collector.GetItemIndex(material); - std::fill(matids + num_matids_written, matids + num_matids_written + mesh_num_indices / 3, matidx); - - num_matids_written += mesh_num_indices / 3; - - // Drop dirty flag - mesh->SetDirty(false); - } - - // Excluded shapes are handled in almost the same way - // except materials. - for (auto& iter : excluded_meshes) - { - auto mesh = iter; - - // Get pointers data - auto mesh_vertex_array = mesh->GetVertices(); - auto mesh_num_vertices = mesh->GetNumVertices(); - - auto mesh_normal_array = mesh->GetNormals(); - auto mesh_num_normals = mesh->GetNumNormals(); - - auto mesh_uv_array = mesh->GetUVs(); - auto mesh_num_uvs = mesh->GetNumUVs(); - - auto mesh_index_array = mesh->GetIndices(); - auto mesh_num_indices = mesh->GetNumIndices(); - - // Prepare shape descriptor - ClwScene::Shape shape; - shape.numprims = static_cast(mesh_num_indices / 3); - shape.startvtx = static_cast(num_vertices_written); - shape.startidx = static_cast(num_indices_written); - shape.start_material_idx = static_cast(num_matids_written); - - auto transform = mesh->GetTransform(); - shape.transform.m0 = { transform.m00, transform.m01, transform.m02, transform.m03 }; - shape.transform.m1 = { transform.m10, transform.m11, transform.m12, transform.m13 }; - shape.transform.m2 = { transform.m20, transform.m21, transform.m22, transform.m23 }; - shape.transform.m3 = { transform.m30, transform.m31, transform.m32, transform.m33 }; - - shape.linearvelocity = float3(0.0f, 0.f, 0.f); - shape.angularvelocity = float3(0.f, 0.f, 0.f, 1.f); - - shape_data[mesh] = shape; - - std::copy(mesh_vertex_array, mesh_vertex_array + mesh_num_vertices, vertices + num_vertices_written); - num_vertices_written += mesh_num_vertices; - - std::copy(mesh_normal_array, mesh_normal_array + mesh_num_normals, normals + num_normals_written); - num_normals_written += mesh_num_normals; - - std::copy(mesh_uv_array, mesh_uv_array + mesh_num_uvs, uvs + num_uvs_written); - num_uvs_written += mesh_num_uvs; - - std::copy(mesh_index_array, mesh_index_array + mesh_num_indices, indices + num_indices_written); - num_indices_written += mesh_num_indices; - - shapes[num_shapes_written++] = shape; - - // We do not need materials for excluded shapes, we never shade them. - std::fill(matids + num_matids_written, matids + num_matids_written + mesh_num_indices / 3, -1); - - num_matids_written += mesh_num_indices / 3; - - // Drop dirty flag - mesh->SetDirty(false); - } - - // Handle instances - for (auto& iter : instances) - { - auto instance = iter; - auto base_shape = static_cast(instance->GetBaseShape()); - auto material = instance->GetMaterial(); - auto transform = instance->GetTransform(); - auto mesh_num_indices = base_shape->GetNumIndices(); - - // Here shape_data is guaranteed to contain - // info for base_shape since we have serialized it - // above in a different pass. - ClwScene::Shape shape = shape_data[base_shape]; - // Instance has its own material part. - shape.start_material_idx = static_cast(num_matids_written); - - // Instance has its own transform. - shape.transform.m0 = { transform.m00, transform.m01, transform.m02, transform.m03 }; - shape.transform.m1 = { transform.m10, transform.m11, transform.m12, transform.m13 }; - shape.transform.m2 = { transform.m20, transform.m21, transform.m22, transform.m23 }; - shape.transform.m3 = { transform.m30, transform.m31, transform.m32, transform.m33 }; - - shape.linearvelocity = float3(0.0f, 0.f, 0.f); - shape.angularvelocity = float3(0.f, 0.f, 0.f, 1.f); - - shapes[num_shapes_written++] = shape; - - // If instance do not have a material, use default one. - if (!material) - { - material = m_default_material.get(); - } - - auto mat_idx = mat_collector.GetItemIndex(material); - std::fill(matids + num_matids_written, matids + num_matids_written + mesh_num_indices / 3, mat_idx); - - num_matids_written += mesh_num_indices / 3; - - // Drop dirty flag - instance->SetDirty(false); - } - - m_context.UnmapBuffer(0, out.vertices, vertices); - m_context.UnmapBuffer(0, out.normals, normals); - m_context.UnmapBuffer(0, out.uvs, uvs); - m_context.UnmapBuffer(0, out.indices, indices); - m_context.UnmapBuffer(0, out.materialids, matids); - m_context.UnmapBuffer(0, out.shapes, shapes).Wait(); - - UpdateIntersector(scene, out); - - ReloadIntersector(scene, out); - } - - void ClwSceneController::UpdateCurrentScene(Scene1 const& scene, ClwScene& out) const - { - ReloadIntersector(scene, out); - } - - void ClwSceneController::UpdateMaterials(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, ClwScene& out) const - { - // Get new buffer size - std::size_t mat_buffer_size = mat_collector.GetNumItems(); - - // Recreate material buffer if it needs resize - if (mat_buffer_size > out.materials.GetElementCount()) - { - // Create material buffer - out.materials = m_context.CreateBuffer(mat_buffer_size, CL_MEM_READ_ONLY); - } - - ClwScene::Material* materials = nullptr; - std::size_t num_materials_written = 0; - - // Map GPU materials buffer - m_context.MapBuffer(0, out.materials, CL_MAP_WRITE, &materials).Wait(); - - // Serialize - { - // Update material bundle first to be able to track differences - out.material_bundle.reset(mat_collector.CreateBundle()); - - // Create material iterator - std::unique_ptr mat_iter(mat_collector.CreateIterator()); - - // Iterate and serialize - for (; mat_iter->IsValid(); mat_iter->Next()) - { - WriteMaterial(mat_iter->ItemAs(), mat_collector, tex_collector, materials + num_materials_written); - ++num_materials_written; - } - } - - // Unmap material buffer - m_context.UnmapBuffer(0, out.materials, materials); - } - - void ClwSceneController::ReloadIntersector(Scene1 const& scene, ClwScene& inout) const - { - m_api->DetachAll(); - - for (auto& s : inout.visible_shapes) - { - m_api->AttachShape(s); - } - - m_api->Commit(); - } - - void ClwSceneController::UpdateTextures(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, ClwScene& out) const - { - // Get new buffer size - std::size_t tex_buffer_size = tex_collector.GetNumItems(); - std::size_t tex_data_buffer_size = 0; - - if (tex_buffer_size == 0) - { - out.textures = m_context.CreateBuffer(1, CL_MEM_READ_ONLY); - out.texturedata = m_context.CreateBuffer(1, CL_MEM_READ_ONLY); - return; - } - - // Recreate material buffer if it needs resize - if (tex_buffer_size > out.textures.GetElementCount()) - { - // Create material buffer - out.textures = m_context.CreateBuffer(tex_buffer_size, CL_MEM_READ_ONLY); - } - - ClwScene::Texture* textures = nullptr; - std::size_t num_textures_written = 0; - - // Map GPU materials buffer - m_context.MapBuffer(0, out.textures, CL_MAP_WRITE, &textures).Wait(); - - // Update material bundle first to be able to track differences - out.texture_bundle.reset(tex_collector.CreateBundle()); - - // Create material iterator - std::unique_ptr tex_iter(tex_collector.CreateIterator()); - - // Iterate and serialize - for (; tex_iter->IsValid(); tex_iter->Next()) - { - auto tex = tex_iter->ItemAs(); - - WriteTexture(tex, tex_data_buffer_size, textures + num_textures_written); - - ++num_textures_written; - - tex_data_buffer_size += tex->GetSizeInBytes(); - } - - // Unmap material buffer - m_context.UnmapBuffer(0, out.textures, textures); - - // Recreate material buffer if it needs resize - if (tex_data_buffer_size > out.texturedata.GetElementCount()) - { - // Create material buffer - out.texturedata = m_context.CreateBuffer(tex_data_buffer_size, CL_MEM_READ_ONLY); - } - - char* data = nullptr; - std::size_t num_bytes_written = 0; - - tex_iter->Reset(); - - // Map GPU materials buffer - m_context.MapBuffer(0, out.texturedata, CL_MAP_WRITE, &data).Wait(); - - // Write texture data for all textures - for (; tex_iter->IsValid(); tex_iter->Next()) - { - auto tex = tex_iter->ItemAs(); - - WriteTextureData(tex, data + num_bytes_written); - - num_bytes_written += tex->GetSizeInBytes(); - } - - // Unmap material buffer - m_context.UnmapBuffer(0, out.texturedata, data); - } - - // Convert Material:: types to ClwScene:: types - static ClwScene::Bxdf GetMaterialType(Material const* material) - { - // Distinguish between single bxdf materials and compound ones - if (auto bxdf = dynamic_cast(material)) - { - switch (bxdf->GetBxdfType()) - { - case SingleBxdf::BxdfType::kZero: return ClwScene::Bxdf::kZero; - case SingleBxdf::BxdfType::kLambert: return ClwScene::Bxdf::kLambert; - case SingleBxdf::BxdfType::kEmissive: return ClwScene::Bxdf::kEmissive; - case SingleBxdf::BxdfType::kPassthrough: return ClwScene::Bxdf::kPassthrough; - case SingleBxdf::BxdfType::kTranslucent: return ClwScene::Bxdf::kTranslucent; - case SingleBxdf::BxdfType::kIdealReflect: return ClwScene::Bxdf::kIdealReflect; - case SingleBxdf::BxdfType::kIdealRefract: return ClwScene::Bxdf::kIdealRefract; - case SingleBxdf::BxdfType::kMicrofacetGGX: return ClwScene::Bxdf::kMicrofacetGGX; - case SingleBxdf::BxdfType::kMicrofacetBeckmann: return ClwScene::Bxdf::kMicrofacetBeckmann; - case SingleBxdf::BxdfType::kMicrofacetRefractionGGX: return ClwScene::Bxdf::kMicrofacetRefractionGGX; - case SingleBxdf::BxdfType::kMicrofacetRefractionBeckmann: return ClwScene::Bxdf::kMicrofacetRefractionBeckmann; - } - } - else if (auto mat = dynamic_cast(material)) - { - switch (mat->GetType()) - { - case MultiBxdf::Type::kMix: return ClwScene::Bxdf::kMix; - case MultiBxdf::Type::kLayered: return ClwScene::Bxdf::kLayered; - case MultiBxdf::Type::kFresnelBlend: return ClwScene::Bxdf::kFresnelBlend; - } - } - else - { - return ClwScene::Bxdf::kZero; - } - - return ClwScene::Bxdf::kZero; - } - - void ClwSceneController::WriteMaterial(Material const* material, Collector& mat_collector, Collector& tex_collector, void* data) const - { - auto clw_material = reinterpret_cast(data); - - // Convert material type and sidedness - auto type = GetMaterialType(material); - - clw_material->type = type; - clw_material->thin = material->IsThin() ? 1 : 0; - - switch (type) - { - case ClwScene::Bxdf::kZero: - clw_material->kx = RadeonRays::float4(); - break; - - // We need to convert roughness for the following materials - case ClwScene::Bxdf::kMicrofacetGGX: - case ClwScene::Bxdf::kMicrofacetBeckmann: - case ClwScene::Bxdf::kMicrofacetRefractionGGX: - case ClwScene::Bxdf::kMicrofacetRefractionBeckmann: - { - Material::InputValue value = material->GetInputValue("roughness"); - - if (value.type == Material::InputType::kFloat4) - { - clw_material->ns = value.float_value.x; - clw_material->nsmapidx = -1; - } - else if (value.type == Material::InputType::kTexture) - { - clw_material->nsmapidx = value.tex_value ? tex_collector.GetItemIndex(value.tex_value) : -1; - } - else - { - // TODO: should not happen - assert(false); - } - - // Intentionally missing break here - } - - // For the rest we need to conver albedo, normal map, fresnel factor, ior - case ClwScene::Bxdf::kLambert: - case ClwScene::Bxdf::kEmissive: - case ClwScene::Bxdf::kPassthrough: - case ClwScene::Bxdf::kTranslucent: - case ClwScene::Bxdf::kIdealRefract: - case ClwScene::Bxdf::kIdealReflect: - { - Material::InputValue value = material->GetInputValue("albedo"); - - if (value.type == Material::InputType::kFloat4) - { - clw_material->kx = value.float_value; - clw_material->kxmapidx = -1; - } - else if (value.type == Material::InputType::kTexture) - { - clw_material->kxmapidx = value.tex_value ? tex_collector.GetItemIndex(value.tex_value) : -1; - } - else - { - // TODO: should not happen - assert(false); - } - - value = material->GetInputValue("normal"); - - if (value.type == Material::InputType::kTexture && value.tex_value) - { - clw_material->nmapidx = tex_collector.GetItemIndex(value.tex_value); - clw_material->bump_flag = 0; - } - else - { - value = material->GetInputValue("bump"); - - if (value.type == Material::InputType::kTexture && value.tex_value) - { - clw_material->nmapidx = tex_collector.GetItemIndex(value.tex_value); - clw_material->bump_flag = 1; - } - else - { - clw_material->nmapidx = -1; - clw_material->bump_flag = 0; - } - } - - value = material->GetInputValue("fresnel"); - - if (value.type == Material::InputType::kFloat4) - { - clw_material->fresnel = value.float_value.x > 0 ? 1.f : 0.f; - } - else - { - clw_material->fresnel = 0.f; - } - - value = material->GetInputValue("ior"); - - if (value.type == Material::InputType::kFloat4) - { - clw_material->ni = value.float_value.x; - } - else - { - clw_material->ni = 1.f; - } - - value = material->GetInputValue("roughness"); - - if (value.type == Material::InputType::kFloat4) - { - clw_material->ns = value.float_value.x; - } - else - { - clw_material->ns = 0.99f; - } - - break; - } - - // For compound materials we need to convert dependencies - // and weights. - case ClwScene::Bxdf::kMix: - case ClwScene::Bxdf::kFresnelBlend: - { - Material::InputValue value0 = material->GetInputValue("base_material"); - Material::InputValue value1 = material->GetInputValue("top_material"); - - if (value0.type == Material::InputType::kMaterial && - value1.type == Material::InputType::kMaterial) - { - clw_material->brdfbaseidx = mat_collector.GetItemIndex(value0.mat_value); - clw_material->brdftopidx = mat_collector.GetItemIndex(value1.mat_value); - } - else - { - // Should not happen - assert(false); - } - - if (type == ClwScene::Bxdf::kMix) - { - clw_material->fresnel = 0.f; - - Material::InputValue value = material->GetInputValue("weight"); - - if (value.type == Material::InputType::kTexture) - { - clw_material->nsmapidx = tex_collector.GetItemIndex(value.tex_value); - } - else - { - clw_material->nsmapidx = -1; - clw_material->ns = value.float_value.x; - } - } - else - { - clw_material->fresnel = 1.f; - - Material::InputValue value = material->GetInputValue("ior"); - - if (value.type == Material::InputType::kFloat4) - { - clw_material->ni = value.float_value.x; - } - else - { - // Should not happen - assert(false); - } - } - } - - default: - break; - } - - material->SetDirty(false); - } - - // Convert Light:: types to ClwScene:: types - static int GetLightType(Light const* light) - { - - if (dynamic_cast(light)) - { - return ClwScene::kPoint; - } - else if (dynamic_cast(light)) - { - return ClwScene::kDirectional; - } - else if (dynamic_cast(light)) - { - return ClwScene::kSpot; - } - else if (dynamic_cast(light)) - { - return ClwScene::kIbl; - } - else - { - return ClwScene::LightType::kArea; - } - } - - void ClwSceneController::WriteLight(Scene1 const& scene, Light const* light, Collector& tex_collector, void* data) const - { - auto clw_light = reinterpret_cast(data); - - auto type = GetLightType(light); - - clw_light->type = type; - - switch (type) - { - case ClwScene::kPoint: - { - clw_light->p = light->GetPosition(); - clw_light->intensity = light->GetEmittedRadiance(); - break; - } - - case ClwScene::kDirectional: - { - clw_light->d = light->GetDirection(); - clw_light->intensity = light->GetEmittedRadiance(); - break; - } - - case ClwScene::kSpot: - { - clw_light->p = light->GetPosition(); - clw_light->d = light->GetDirection(); - clw_light->intensity = light->GetEmittedRadiance(); - - auto cone_shape = static_cast(light)->GetConeShape(); - clw_light->ia = cone_shape.x; - clw_light->oa = cone_shape.y; - break; - } - - case ClwScene::kIbl: - { - // TODO: support this - clw_light->multiplier = static_cast(light)->GetMultiplier(); - auto tex = static_cast(light)->GetTexture(); - clw_light->tex = tex_collector.GetItemIndex(tex); - clw_light->texdiffuse = clw_light->tex; - break; - } - - case ClwScene::kArea: - { - // TODO: optimize this linear search - auto shape = static_cast(light)->GetShape(); - - std::unique_ptr shape_iter(scene.CreateShapeIterator()); - - auto idx = GetShapeIdx(shape_iter.get(), shape); - - clw_light->shapeidx = static_cast(idx); - clw_light->primidx = static_cast(static_cast(light)->GetPrimitiveIdx()); - break; - } - - - default: - assert(false); - break; - } - } - - void ClwSceneController::UpdateLights(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, ClwScene& out) const - { - std::size_t num_lights_written = 0; - - auto num_lights = scene.GetNumLights(); - - // Create light buffer if needed - if (num_lights > out.lights.GetElementCount()) - { - out.lights = m_context.CreateBuffer(num_lights, CL_MEM_READ_ONLY); - } - - ClwScene::Light* lights = nullptr; - - m_context.MapBuffer(0, out.lights, CL_MAP_WRITE, &lights).Wait(); - - std::unique_ptr light_iter(scene.CreateLightIterator()); - - // Disable IBL by default - out.envmapidx = -1; - - // Serialize - { - for (; light_iter->IsValid(); light_iter->Next()) - { - auto light = light_iter->ItemAs(); - WriteLight(scene, light, tex_collector, lights + num_lights_written); - ++num_lights_written; - - // Find and update IBL idx - auto ibl = dynamic_cast(light_iter->ItemAs()); - if (ibl) - { - out.envmapidx = static_cast(num_lights_written - 1); - } - - light->SetDirty(false); - } - } - - m_context.UnmapBuffer(0, out.lights, lights); - - out.num_lights = static_cast(num_lights_written); - } - - - // Convert texture format into ClwScene:: types - static ClwScene::TextureFormat GetTextureFormat(Texture const* texture) - { - switch (texture->GetFormat()) - { - case Texture::Format::kRgba8: return ClwScene::TextureFormat::RGBA8; - case Texture::Format::kRgba16: return ClwScene::TextureFormat::RGBA16; - case Texture::Format::kRgba32: return ClwScene::TextureFormat::RGBA32; - default: return ClwScene::TextureFormat::RGBA8; - } - } - - void ClwSceneController::WriteTexture(Texture const* texture, std::size_t data_offset, void* data) const - { - auto clw_texture = reinterpret_cast(data); - - auto dim = texture->GetSize(); - - clw_texture->w = dim.x; - clw_texture->h = dim.y; - clw_texture->fmt = GetTextureFormat(texture); - clw_texture->dataoffset = static_cast(data_offset); - } - - void ClwSceneController::WriteTextureData(Texture const* texture, void* data) const - { - auto begin = texture->GetData(); - auto end = begin + texture->GetSizeInBytes(); - std::copy(begin, end, static_cast(data)); - } -} diff --git a/Baikal/CMakeLists.txt b/Baikal/CMakeLists.txt new file mode 100644 index 00000000..ca9b60a1 --- /dev/null +++ b/Baikal/CMakeLists.txt @@ -0,0 +1,226 @@ +set(CONTROLLERS_SOURCES + Controllers/clw_scene_controller.cpp + Controllers/clw_scene_controller.h + Controllers/scene_controller.h + Controllers/scene_controller.inl + Controllers/scene_controller.cpp) + +set(ESTIMATORS_SOURCES + Estimators/estimator.h + Estimators/path_tracing_estimator.cpp + Estimators/path_tracing_estimator.h) + +set(OUTPUT_SOURCES + Output/clwoutput.h + Output/output.h) + +set(POSTEFFECT_SOURCES + PostEffects/clw_post_effect.h + PostEffects/post_effect.h + PostEffects/bilateral_denoiser.h + PostEffects/wavelet_denoiser.h + PostEffects/AreaMap33.h + ) + +set(RENDERERS_SOURCES + Renderers/adaptive_renderer.cpp + Renderers/adaptive_renderer.h + Renderers/monte_carlo_renderer.cpp + Renderers/monte_carlo_renderer.h + Renderers/renderer.h) + +set(RENDERFACTORY_SOURCES + RenderFactory/clw_render_factory.cpp + RenderFactory/clw_render_factory.h + RenderFactory/render_factory.h) + +set(UTILS_SOURCES + Utils/clw_class.h + Utils/distribution1d.cpp + Utils/distribution1d.h + Utils/eLut.h + Utils/half.cpp + Utils/half.h + Utils/log.h + Utils/sh.cpp + Utils/sh.h + Utils/shproject.cpp + Utils/shproject.h + Utils/sobol.h + Utils/toFloat.h + Utils/version.h + Utils/mkpath.cpp + Utils/mkpath.h + Utils/cl_inputmap_generator.cpp + Utils/cl_inputmap_generator.h + Utils/cl_program.cpp + Utils/cl_program.h + Utils/cl_program_manager.cpp + Utils/cl_program_manager.h + Utils/cl_uberv2_generator.h + Utils/cl_uberv2_generator.cpp + Utils/cmd_parser.h + Utils/cmd_parser.cpp +) + +set(SCENEGRAPH_SOURCES + SceneGraph/camera.cpp + SceneGraph/camera.h + SceneGraph/clwscene.h + SceneGraph/iterator.h + SceneGraph/light.cpp + SceneGraph/light.h + SceneGraph/material.cpp + SceneGraph/material.h + SceneGraph/scene1.cpp + SceneGraph/scene1.h + SceneGraph/scene_object.cpp + SceneGraph/scene_object.h + SceneGraph/shape.cpp + SceneGraph/shape.h + SceneGraph/texture.cpp + SceneGraph/texture.h + SceneGraph/uberv2material.cpp + SceneGraph/uberv2material.h + SceneGraph/inputmap.h + SceneGraph/inputmaps.h) + +set(SCENEGRAPH_COLLECTOR_SOURCES + SceneGraph/Collector/collector.cpp + SceneGraph/Collector/collector.h) + +set(XML_SOURCES + XML/tinyxml2.cpp + XML/tinyxml2.h) + +set(KERNELS_SOURCES + Kernels/CL/bxdf.cl + Kernels/CL/bxdf_uberv2.cl + Kernels/CL/bxdf_uberv2_bricks.cl + Kernels/CL/common.cl + Kernels/CL/denoise.cl + Kernels/CL/disney.cl + Kernels/CL/integrator_bdpt.cl + Kernels/CL/isect.cl + Kernels/CL/light.cl + Kernels/CL/monte_carlo_renderer.cl + Kernels/CL/normalmap.cl + Kernels/CL/path.cl + Kernels/CL/path_tracing_estimator.cl + Kernels/CL/payload.cl + Kernels/CL/ray.cl + Kernels/CL/sampling.cl + Kernels/CL/scene.cl + Kernels/CL/sh.cl + Kernels/CL/texture.cl + Kernels/CL/utils.cl + Kernels/CL/vertex.cl + Kernels/CL/volumetrics.cl + Kernels/CL/wavelet_denoise.cl + Kernels/CL/path_tracing_estimator_uberv2.cl + Kernels/CL/fill_aovs_uberv2.cl + ) + +set(SOURCES + ${CONTROLLERS_SOURCES} + ${ESTIMATORS_SOURCES} + ${OUTPUT_SOURCES} + ${POSTEFFECT_SOURCES} + ${RENDERERS_SOURCES} + ${RENDERFACTORY_SOURCES} + ${UTILS_SOURCES} + ${SCENEGRAPH_SOURCES} + ${SCENEGRAPH_COLLECTOR_SOURCES} + ${SCENEGRAPH_IO_SOURCES} + ${XML_SOURCES} + ${KERNELS_SOURCES} + ) + +source_group("Controllers" FILES ${CONTROLLERS_SOURCES}) +source_group("Estimators" FILES ${ESTIMATORS_SOURCES}) +source_group("Output" FILES ${OUTPUT_SOURCES}) +source_group("Posteffect" FILES ${POSTEFFECT_SOURCES}) +source_group("Renderers" FILES ${RENDERERS_SOURCES}) +source_group("RenderFactory" FILES ${RENDERFACTORY_SOURCES}) +source_group("Utils" FILES ${UTILS_SOURCES}) +source_group("SceneGraph" FILES ${SCENEGRAPH_SOURCES}) +source_group("SceneGraph\\Collector" FILES ${SCENEGRAPH_COLLECTOR_SOURCES}) +source_group("XML" FILES ${XML_SOURCES}) +source_group("Kernels\\CL" FILES ${KERNELS_SOURCES}) + +# Set CMAKE_EXPORT_ALL_SYMBOLS flag for exporting dll +# symbols without __declspec(dllimport / dllexport) specifier +if (WIN32) + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) +elseif (UNIX) + add_definitions(-fvisibility=default) +endif (WIN32) + +add_library(Baikal SHARED ${SOURCES}) + +# We need to use this definition because CMAKE_EXPORT_ALL_SYMBOLS +# actually doesn't export data symbols +target_compile_definitions(Baikal PRIVATE BAIKAL_EXPORT_DATA_SYMBOLS) + +if (BAIKAL_ENABLE_DENOISER) + target_compile_definitions(Baikal PUBLIC ENABLE_DENOISER) +endif(BAIKAL_ENABLE_DENOISER) + +if (BAIKAL_ENABLE_RAYMASK) + target_compile_definitions(Baikal PUBLIC ENABLE_RAYMASK) +endif (BAIKAL_ENABLE_RAYMASK) + +if (BAIKAL_EMBED_KERNELS) + target_compile_definitions(Baikal PRIVATE BAIKAL_EMBED_KERNELS) + set(KERNEL_HEADER "${Baikal_BINARY_DIR}/Baikal/embed_kernels.h") + set(STRINGIFY_SCRIPT "${CMAKE_SOURCE_DIR}/Tools/scripts/baikal_stringify.py") + add_custom_command( + OUTPUT ${KERNEL_HEADER} + COMMAND ${PYTHON_EXECUTABLE} ${STRINGIFY_SCRIPT} ../Baikal/Kernels/CL/ .cl opencl > ${KERNEL_HEADER} + DEPENDS ${KERNELS_SOURCES} + WORKING_DIRECTORY ${Baikal_SOURCE_DIR}/Baikal + COMMENT "Generating Baikal kernel cache" + VERBATIM) + add_custom_target(BaikalKernelCache DEPENDS ${KERNEL_HEADER}) + add_dependencies(Baikal BaikalKernelCache) + # Add directory where embed_kernels.h lies + target_include_directories(Baikal PRIVATE ${Baikal_BINARY_DIR}/Baikal) +endif (BAIKAL_EMBED_KERNELS) + +target_compile_features(Baikal PRIVATE cxx_std_14) +target_include_directories(Baikal PUBLIC "${Baikal_SOURCE_DIR}/Baikal") +target_link_libraries(Baikal PUBLIC RadeonRays) + +# Add 'treat warnings as errors' flag and 'Wall' flag on Unix +if (WIN32) + target_compile_options(Baikal PUBLIC /WX) +elseif (UNIX) + target_compile_options(Baikal PUBLIC -Wall -Werror) +endif (WIN32) + +# Add symbolic link from binary to Baikal/Kernels directory +set(BAIKAL_KERNELS_DIR Baikal/Kernels) +file(TO_NATIVE_PATH ${Baikal_SOURCE_DIR}/${BAIKAL_KERNELS_DIR} BAIKAL_KERNELS_SRC) +file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR}/${BAIKAL_KERNELS_DIR} BAIKAL_KERNELS_DST) + +if (WIN32) + add_custom_target(BaikalKernelsDir ALL + COMMAND IF NOT EXIST ${BAIKAL_KERNELS_DST} mklink /D ${BAIKAL_KERNELS_DST} ${BAIKAL_KERNELS_SRC} + ) +else () + add_custom_target(BaikalKernelsDir ALL + COMMAND ${CMAKE_COMMAND} -E create_symlink ${BAIKAL_KERNELS_SRC} ${BAIKAL_KERNELS_DST} + ) +endif () + +add_dependencies(Baikal BaikalKernelsDir ResourcesDir) + +# Install target +if (WIN32) + install(TARGETS Baikal RUNTIME DESTINATION bin) +else () + install(TARGETS Baikal LIBRARY DESTINATION lib) +endif () + +file(TO_CMAKE_PATH ${BAIKAL_KERNELS_SRC} BAIKAL_KERNELS_SRC_CMAKE) +install(DIRECTORY ${BAIKAL_KERNELS_SRC_CMAKE} DESTINATION Baikal) diff --git a/Baikal/Controllers/clw_scene_controller.cpp b/Baikal/Controllers/clw_scene_controller.cpp new file mode 100644 index 00000000..9ac09f04 --- /dev/null +++ b/Baikal/Controllers/clw_scene_controller.cpp @@ -0,0 +1,1399 @@ +#include "Controllers/clw_scene_controller.h" +#include "SceneGraph/scene1.h" +#include "SceneGraph/camera.h" +#include "SceneGraph/light.h" +#include "SceneGraph/shape.h" +#include "SceneGraph/material.h" +#include "SceneGraph/texture.h" +#include "SceneGraph/Collector/collector.h" +#include "SceneGraph/iterator.h" +#include "SceneGraph/uberv2material.h" +#include "SceneGraph/inputmaps.h" +#include "Utils/distribution1d.h" +#include "Utils/log.h" +#include "Utils/cl_inputmap_generator.h" +#include "Utils/cl_program_manager.h" +#include "Utils/cl_uberv2_generator.h" + + +#include +#include +#include +#include +#include + +using namespace RadeonRays; + +namespace Baikal +{ + static std::size_t align16(std::size_t value) + { + return (value + 0xF) / 0x10 * 0x10; + } + + static CameraType GetCameraType(Camera& camera) + { + auto perspective = dynamic_cast(&camera); + + if (perspective) + { + return perspective->GetAperture() > 0.f ? CameraType::kPhysicalPerspective : CameraType::kPerspective; + } + + auto ortho = dynamic_cast(&camera); + + if (ortho) + { + return CameraType::kOrthographic; + } + + return CameraType::kPerspective; + } + + + ClwSceneController::ClwSceneController(CLWContext context, RadeonRays::IntersectionApi* api, const CLProgramManager *program_manager) + : m_context(context) + , m_api(api) + , m_default_material(UberV2Material::Create()) + , m_program_manager(program_manager) + { + auto acc_type = "fatbvh"; + auto builder_type = "sah"; + LogInfo("Configuring acceleration structure: ", acc_type, " with ", builder_type, " builder\n"); + m_api->SetOption("acc.type", acc_type); + +#ifdef ENABLE_RAYMASK + m_api->SetOption("bvh.force2level", 1.f); +#endif + + m_api->SetOption("bvh.builder", builder_type); + m_api->SetOption("bvh.sah.num_bins", 16.f); + } + + Material::Ptr ClwSceneController::GetDefaultMaterial() const + { + return m_default_material; + } + + ClwSceneController::~ClwSceneController() + { + } + + static void SplitMeshesAndInstances(Iterator& shape_iter, std::set& meshes, std::set& instances, std::set& excluded_meshes) + { + // Clear all sets + meshes.clear(); + instances.clear(); + excluded_meshes.clear(); + + // Prepare instance check lambda + auto is_instance = [](Shape::Ptr shape) + { + if (std::dynamic_pointer_cast(shape)) + { + return true; + } + else + { + return false; + } + }; + + for (; shape_iter.IsValid(); shape_iter.Next()) + { + auto shape = shape_iter.ItemAs(); + + if (!is_instance(shape)) + { + meshes.emplace(std::static_pointer_cast(shape)); + } + else + { + instances.emplace(std::static_pointer_cast(shape)); + } + } + + for (auto& i : instances) + { + auto base_mesh = std::static_pointer_cast(i->GetBaseShape()); + if (meshes.find(base_mesh) == meshes.cend()) + { + excluded_meshes.emplace(base_mesh); + } + } + } + + static std::size_t GetShapeIdx(Iterator& shape_iter, Shape::Ptr shape) + { + std::set meshes; + std::set excluded_meshes; + std::set instances; + SplitMeshesAndInstances(shape_iter, meshes, instances, excluded_meshes); + + std::size_t idx = 0; + for (auto& i : meshes) + { + if (i == shape) + { + return idx; + } + + ++idx; + } + + for (auto& i : excluded_meshes) + { + if (i == shape) + { + return idx; + } + + ++idx; + } + + for (auto& i : instances) + { + if (i == shape) + { + return idx; + } + + ++idx; + } + + return -1; + } + + void ClwSceneController::UpdateIntersector(Scene1 const& scene, ClwScene& out) const + { + // Detach and delete all shapes + for (auto& shape : out.isect_shapes) + { + m_api->DetachShape(shape); + m_api->DeleteShape(shape); + } + + // Clear shapes cache + out.isect_shapes.clear(); + // Only visible shapes are attached to the API. + // So excluded meshes are pushed into isect_shapes, but + // not to visible_shapes. + out.visible_shapes.clear(); + + // Create new shapes + auto shape_iter = scene.CreateShapeIterator(); + + if (!shape_iter->IsValid()) + { + throw std::runtime_error("No shapes in the scene"); + } + + // Split all shapes into meshes and instances sets. + std::set meshes; + // Excluded shapes are shapes which are not in the scene, + // but references by at least one instance. + std::set excluded_meshes; + std::set instances; + SplitMeshesAndInstances(*shape_iter, meshes, instances, excluded_meshes); + + // Keep shape->rr shape association for + // instance base shape lookup. + std::map rr_shapes; + + // Start from ID 1 + // Handle meshes + int id = 1; + for (auto& iter : meshes) + { + auto mesh = iter; + + auto shape = m_api->CreateMesh( + // Vertices starting from the first one + (float*)mesh->GetVertices(), + // Number of vertices + static_cast(mesh->GetNumVertices()), + // Stride + sizeof(float3), + // TODO: make API signature const + reinterpret_cast(mesh->GetIndices()), + // Index stride + 0, + // All triangles + nullptr, + // Number of primitives + static_cast(mesh->GetNumIndices() / 3) + ); + + auto transform = mesh->GetTransform(); + shape->SetTransform(transform, inverse(transform)); + shape->SetId(id++); + // shape->SetMask(iter->GetVisibilityMask()); + + out.isect_shapes.push_back(shape); + out.visible_shapes.push_back(shape); + rr_shapes[mesh] = shape; + } + + // Handle excluded meshes + for (auto& iter : excluded_meshes) + { + auto mesh = iter; + + auto shape = m_api->CreateMesh( + // Vertices starting from the first one + (float*)mesh->GetVertices(), + // Number of vertices + static_cast(mesh->GetNumVertices()), + // Stride + sizeof(float3), + // TODO: make API signature const + reinterpret_cast(mesh->GetIndices()), + // Index stride + 0, + // All triangles + nullptr, + // Number of primitives + static_cast(mesh->GetNumIndices() / 3) + ); + + auto transform = mesh->GetTransform(); + shape->SetTransform(transform, inverse(transform)); + shape->SetId(id++); + out.isect_shapes.push_back(shape); + rr_shapes[mesh] = shape; + } + + // Handle instances + for (auto& iter: instances) + { + auto instance = iter; + auto rr_mesh = rr_shapes[instance->GetBaseShape()]; + auto shape = m_api->CreateInstance(rr_mesh); + + auto transform = instance->GetTransform(); + shape->SetTransform(transform, inverse(transform)); + shape->SetId(id++); + out.isect_shapes.push_back(shape); + out.visible_shapes.push_back(shape); + } + } + + void ClwSceneController::UpdateIntersectorTransforms(Scene1 const& scene, ClwScene& out) const + { + // Create new shapes + auto shape_iter = scene.CreateShapeIterator(); + + if (!shape_iter->IsValid()) + { + throw std::runtime_error("No shapes in the scene"); + } + + // Split all shapes into meshes and instances sets. + std::set meshes; + // Excluded shapes are shapes which are not in the scene, + // but references by at least one instance. + std::set excluded_meshes; + std::set instances; + SplitMeshesAndInstances(*shape_iter, meshes, instances, excluded_meshes); + + auto rr_iter = out.isect_shapes.begin(); + + // Start from ID 1 + // Handle meshes + for (auto& iter : meshes) + { + auto mesh = iter; + auto transform = mesh->GetTransform(); + (*rr_iter)->SetTransform(transform, inverse(transform)); + ++rr_iter; + } + + // Handle excluded meshes + for (auto& iter : excluded_meshes) + { + auto mesh = iter; + auto transform = mesh->GetTransform(); + (*rr_iter)->SetTransform(transform, inverse(transform)); + ++rr_iter; + } + + // Handle instances + for (auto& iter : instances) + { + auto instance = iter; + auto transform = instance->GetTransform(); + (*rr_iter)->SetTransform(transform, inverse(transform)); + ++rr_iter; + } + + m_api->Commit(); + } + + void ClwSceneController::UpdateCamera(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, Collector& vol_collector, ClwScene& out) const + { + // TODO: support different camera types here + auto camera = scene.GetCamera(); + + // Create light buffer if needed + if (out.camera.GetElementCount() == 0) + { + out.camera = m_context.CreateBuffer(1, CL_MEM_READ_ONLY); + } + + // TODO: remove this + out.camera_type = GetCameraType(*camera); + + // Update camera data + ClwScene::Camera* data = nullptr; + + // Map GPU camera buffer + m_context.MapBuffer(0, out.camera, CL_MAP_WRITE, &data).Wait(); + + // Copy camera parameters + data->forward = camera->GetForwardVector(); + data->up = camera->GetUpVector(); + data->right = camera->GetRightVector(); + data->p = camera->GetPosition(); + data->aspect_ratio = camera->GetAspectRatio(); + data->dim = camera->GetSensorSize(); + data->zcap = camera->GetDepthRange(); + + if (out.camera_type == CameraType::kPerspective || + out.camera_type == CameraType::kPhysicalPerspective) + { + auto physical_camera = std::static_pointer_cast(camera); + data->aperture = physical_camera->GetAperture(); + data->focal_length = physical_camera->GetFocalLength(); + data->focus_distance = physical_camera->GetFocusDistance(); + } + + // Unmap camera buffer + m_context.UnmapBuffer(0, out.camera, data); + + // Update volume index + out.camera_volume_index = GetVolumeIndex(vol_collector, camera->GetVolume()); + } + + void ClwSceneController::UpdateShapes(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, Collector& vol_collector, ClwScene& out) const + { + std::size_t num_vertices = 0; + std::size_t num_normals = 0; + std::size_t num_uvs = 0; + std::size_t num_indices = 0; + + std::size_t num_vertices_written = 0; + std::size_t num_normals_written = 0; + std::size_t num_uvs_written = 0; + std::size_t num_indices_written = 0; + std::size_t num_shapes_written = 0; + + auto shape_iter = scene.CreateShapeIterator(); + + // Sort shapes into meshes and instances sets. + std::set meshes; + // Excluded meshes are meshes which are not in the scene, + // but are references by at least one instance. + std::set excluded_meshes; + std::set instances; + SplitMeshesAndInstances(*shape_iter, meshes, instances, excluded_meshes); + + // Calculate GPU array sizes. Do that only for meshes, + // since instances do not occupy space in vertex buffers. + // However instances still have their own material ids. + for (auto& iter : meshes) + { + auto mesh = iter; + + num_vertices += mesh->GetNumVertices(); + num_normals += mesh->GetNumNormals(); + num_uvs += mesh->GetNumUVs(); + num_indices += mesh->GetNumIndices(); + } + + // Excluded meshes still occupy space in vertex buffers. + for (auto& iter : excluded_meshes) + { + auto mesh = iter; + + num_vertices += mesh->GetNumVertices(); + num_normals += mesh->GetNumNormals(); + num_uvs += mesh->GetNumUVs(); + num_indices += mesh->GetNumIndices(); + } + + // Instances only occupy material IDs space. + for (auto& iter : instances) + { + auto instance = iter; + auto mesh = std::static_pointer_cast(instance->GetBaseShape()); + } + + LogInfo("Creating vertex buffer...\n"); + // Create CL arrays + out.vertices = m_context.CreateBuffer(num_vertices, CL_MEM_READ_ONLY); + + LogInfo("Creating normal buffer...\n"); + out.normals = m_context.CreateBuffer(num_normals, CL_MEM_READ_ONLY); + + LogInfo("Creating UV buffer...\n"); + out.uvs = m_context.CreateBuffer(num_uvs, CL_MEM_READ_ONLY); + + LogInfo("Creating index buffer...\n"); + out.indices = m_context.CreateBuffer(num_indices, CL_MEM_READ_ONLY); + + // Total number of entries in shapes GPU array + auto num_shapes = meshes.size() + excluded_meshes.size() + instances.size(); + out.shapes = m_context.CreateBuffer(num_shapes, CL_MEM_READ_ONLY); + out.shapes_additional = m_context.CreateBuffer(num_shapes, CL_MEM_READ_ONLY); + + float3* vertices = nullptr; + float3* normals = nullptr; + float2* uvs = nullptr; + int* indices = nullptr; + ClwScene::Shape* shapes = nullptr; + ClwScene::ShapeAdditionalData* shapes_additional = nullptr; + + // Map arrays and prepare to write data + LogInfo("Mapping buffers...\n"); + m_context.MapBuffer(0, out.vertices, CL_MAP_WRITE, &vertices); + m_context.MapBuffer(0, out.normals, CL_MAP_WRITE, &normals); + m_context.MapBuffer(0, out.uvs, CL_MAP_WRITE, &uvs); + m_context.MapBuffer(0, out.indices, CL_MAP_WRITE, &indices); + m_context.MapBuffer(0, out.shapes, CL_MAP_WRITE, &shapes).Wait(); + m_context.MapBuffer(0, out.shapes_additional, CL_MAP_WRITE, &shapes_additional).Wait(); + + // Keep associated shapes data for instance look up. + // We retrieve data from here while serializing instances, + // using base shape lookup. + std::map shape_data; + + // Handle meshes + //int shape_id = 0; + for (auto& iter : meshes) + { + auto mesh = iter; + + // Get pointers data + auto mesh_vertex_array = mesh->GetVertices(); + auto mesh_num_vertices = mesh->GetNumVertices(); + + auto mesh_normal_array = mesh->GetNormals(); + auto mesh_num_normals = mesh->GetNumNormals(); + + auto mesh_uv_array = mesh->GetUVs(); + auto mesh_num_uvs = mesh->GetNumUVs(); + + auto mesh_index_array = mesh->GetIndices(); + auto mesh_num_indices = mesh->GetNumIndices(); + + // Prepare shape descriptor + ClwScene::Shape shape; + + shape.id = iter->GetId(); + + shape.startvtx = static_cast(num_vertices_written); + shape.startidx = static_cast(num_indices_written); + + auto transform = mesh->GetTransform(); + shape.transform.m0 = { transform.m00, transform.m01, transform.m02, transform.m03 }; + shape.transform.m1 = { transform.m10, transform.m11, transform.m12, transform.m13 }; + shape.transform.m2 = { transform.m20, transform.m21, transform.m22, transform.m23 }; + shape.transform.m3 = { transform.m30, transform.m31, transform.m32, transform.m33 }; + + shape.linearvelocity = float3(0.0f, 0.f, 0.f); + shape.angularvelocity = float3(0.f, 0.f, 0.f, 1.f); + shape.material.offset = GetMaterialIndex(mat_collector, mesh->GetMaterial()); + shape.material.layers = GetMaterialLayers(mesh->GetMaterial()); + + shape.volume_idx = GetVolumeIndex(vol_collector, mesh->GetVolumeMaterial()); + + shape_data[mesh] = shape; + + std::copy(mesh_vertex_array, mesh_vertex_array + mesh_num_vertices, vertices + num_vertices_written); + num_vertices_written += mesh_num_vertices; + + std::copy(mesh_normal_array, mesh_normal_array + mesh_num_normals, normals + num_normals_written); + num_normals_written += mesh_num_normals; + + std::copy(mesh_uv_array, mesh_uv_array + mesh_num_uvs, uvs + num_uvs_written); + num_uvs_written += mesh_num_uvs; + + std::copy(mesh_index_array, mesh_index_array + mesh_num_indices, indices + num_indices_written); + num_indices_written += mesh_num_indices; + + shapes[num_shapes_written] = shape; + + ClwScene::ShapeAdditionalData shape_additional; + shape_additional.group_id = mesh->GetGroupId(); + shapes_additional[num_shapes_written++] = shape_additional; + } + + // Excluded shapes are handled in almost the same way + // except materials. + for (auto& iter : excluded_meshes) + { + auto mesh = iter; + + // Get pointers data + auto mesh_vertex_array = mesh->GetVertices(); + auto mesh_num_vertices = mesh->GetNumVertices(); + + auto mesh_normal_array = mesh->GetNormals(); + auto mesh_num_normals = mesh->GetNumNormals(); + + auto mesh_uv_array = mesh->GetUVs(); + auto mesh_num_uvs = mesh->GetNumUVs(); + + auto mesh_index_array = mesh->GetIndices(); + auto mesh_num_indices = mesh->GetNumIndices(); + + // Prepare shape descriptor + ClwScene::Shape shape; + + shape.id = mesh->GetId(); + + shape.startvtx = static_cast(num_vertices_written); + shape.startidx = static_cast(num_indices_written); + + auto transform = mesh->GetTransform(); + shape.transform.m0 = { transform.m00, transform.m01, transform.m02, transform.m03 }; + shape.transform.m1 = { transform.m10, transform.m11, transform.m12, transform.m13 }; + shape.transform.m2 = { transform.m20, transform.m21, transform.m22, transform.m23 }; + shape.transform.m3 = { transform.m30, transform.m31, transform.m32, transform.m33 }; + + shape.linearvelocity = float3(0.0f, 0.f, 0.f); + shape.angularvelocity = float3(0.f, 0.f, 0.f, 1.f); + shape.material.offset = GetMaterialIndex(mat_collector, mesh->GetMaterial()); + shape.material.layers = GetMaterialLayers(mesh->GetMaterial()); + + shape.volume_idx = GetVolumeIndex(vol_collector, mesh->GetVolumeMaterial()); + + shape_data[mesh] = shape; + + std::copy(mesh_vertex_array, mesh_vertex_array + mesh_num_vertices, vertices + num_vertices_written); + num_vertices_written += mesh_num_vertices; + + std::copy(mesh_normal_array, mesh_normal_array + mesh_num_normals, normals + num_normals_written); + num_normals_written += mesh_num_normals; + + std::copy(mesh_uv_array, mesh_uv_array + mesh_num_uvs, uvs + num_uvs_written); + num_uvs_written += mesh_num_uvs; + + std::copy(mesh_index_array, mesh_index_array + mesh_num_indices, indices + num_indices_written); + num_indices_written += mesh_num_indices; + + shapes[num_shapes_written] = shape; + + ClwScene::ShapeAdditionalData shape_additional; + shape_additional.group_id = mesh->GetGroupId(); + shapes_additional[num_shapes_written++] = shape_additional; + } + + // Handle instances + for (auto& iter : instances) + { + auto instance = iter; + auto base_shape = std::static_pointer_cast(instance->GetBaseShape()); + auto transform = instance->GetTransform(); + + // Here shape_data is guaranteed to contain + // info for base_shape since we have serialized it + // above in a different pass. + ClwScene::Shape shape = shape_data[base_shape]; + + shape.id = iter->GetId(); + + // Instance has its own transform. + shape.transform.m0 = { transform.m00, transform.m01, transform.m02, transform.m03 }; + shape.transform.m1 = { transform.m10, transform.m11, transform.m12, transform.m13 }; + shape.transform.m2 = { transform.m20, transform.m21, transform.m22, transform.m23 }; + shape.transform.m3 = { transform.m30, transform.m31, transform.m32, transform.m33 }; + + shape.linearvelocity = float3(0.0f, 0.f, 0.f); + shape.angularvelocity = float3(0.f, 0.f, 0.f, 1.f); + shape.material.offset = GetMaterialIndex(mat_collector, instance->GetMaterial()); + shape.material.layers = std::static_pointer_cast(instance->GetMaterial())->GetLayers(); + + shape.volume_idx = GetVolumeIndex(vol_collector, instance->GetVolumeMaterial()); + + shapes[num_shapes_written] = shape; + + ClwScene::ShapeAdditionalData shape_additional; + shape_additional.group_id = iter->GetGroupId(); + shapes_additional[num_shapes_written++] = shape_additional; + } + + LogInfo("Unmapping buffers...\n"); + m_context.UnmapBuffer(0, out.vertices, vertices); + m_context.UnmapBuffer(0, out.normals, normals); + m_context.UnmapBuffer(0, out.uvs, uvs); + m_context.UnmapBuffer(0, out.indices, indices); + m_context.UnmapBuffer(0, out.shapes, shapes).Wait(); + m_context.UnmapBuffer(0, out.shapes_additional, shapes_additional).Wait(); + + LogInfo("Updating intersector...\n"); + + UpdateIntersector(scene, out); + + ReloadIntersector(scene, out); + } + + void ClwSceneController::UpdateShapeProperties(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, Collector& volume_collector, ClwScene& out) const + { + auto shape_iter = scene.CreateShapeIterator(); + + // Sort shapes into meshes and instances sets. + std::set meshes; + // Excluded meshes are meshes which are not in the scene, + // but are references by at least one instance. + std::set excluded_meshes; + std::set instances; + SplitMeshesAndInstances(*shape_iter, meshes, instances, excluded_meshes); + + ClwScene::Shape* shapes = nullptr; + ClwScene::ShapeAdditionalData* shapes_additional = nullptr; + + // Map arrays and prepare to write data + m_context.MapBuffer(0, out.shapes, CL_MAP_READ | CL_MAP_WRITE, &shapes).Wait(); + m_context.MapBuffer(0, out.shapes_additional, CL_MAP_READ | CL_MAP_WRITE, &shapes_additional).Wait(); + + auto current_shape = shapes; + auto current_shape_additional = shapes_additional; + for (auto& iter : meshes) + { + auto mesh = iter; + + auto transform = mesh->GetTransform(); + current_shape->transform.m0 = { transform.m00, transform.m01, transform.m02, transform.m03 }; + current_shape->transform.m1 = { transform.m10, transform.m11, transform.m12, transform.m13 }; + current_shape->transform.m2 = { transform.m20, transform.m21, transform.m22, transform.m23 }; + current_shape->transform.m3 = { transform.m30, transform.m31, transform.m32, transform.m33 }; + current_shape->material.offset = GetMaterialIndex(mat_collector, mesh->GetMaterial()); + current_shape->material.layers = GetMaterialLayers(mesh->GetMaterial()); + + current_shape->volume_idx = GetVolumeIndex(volume_collector, mesh->GetVolumeMaterial()); + + current_shape->id = iter->GetId(); + current_shape_additional->group_id = iter->GetGroupId(); + + ++current_shape; + ++current_shape_additional; + } + + // Excluded shapes are handled in almost the same way + // except materials. + for (auto& iter : excluded_meshes) + { + auto mesh = iter; + + auto transform = mesh->GetTransform(); + current_shape->transform.m0 = { transform.m00, transform.m01, transform.m02, transform.m03 }; + current_shape->transform.m1 = { transform.m10, transform.m11, transform.m12, transform.m13 }; + current_shape->transform.m2 = { transform.m20, transform.m21, transform.m22, transform.m23 }; + current_shape->transform.m3 = { transform.m30, transform.m31, transform.m32, transform.m33 }; + current_shape->material.offset = GetMaterialIndex(mat_collector, mesh->GetMaterial()); + current_shape->material.layers = GetMaterialLayers(mesh->GetMaterial()); + + current_shape->volume_idx = GetVolumeIndex(volume_collector, mesh->GetVolumeMaterial()); + + current_shape->id = iter->GetId(); + current_shape_additional->group_id = iter->GetGroupId(); + + ++current_shape; + ++current_shape_additional; + } + + // Handle instances + for (auto& iter : instances) + { + auto instance = iter; + auto base_shape = std::static_pointer_cast(instance->GetBaseShape()); + auto transform = instance->GetTransform(); + + current_shape->transform.m0 = { transform.m00, transform.m01, transform.m02, transform.m03 }; + current_shape->transform.m1 = { transform.m10, transform.m11, transform.m12, transform.m13 }; + current_shape->transform.m2 = { transform.m20, transform.m21, transform.m22, transform.m23 }; + current_shape->transform.m3 = { transform.m30, transform.m31, transform.m32, transform.m33 }; + current_shape->material.offset = GetMaterialIndex(mat_collector, instance->GetMaterial()); + current_shape->material.layers = GetMaterialLayers(std::static_pointer_cast(instance->GetMaterial())); + + current_shape->volume_idx = GetVolumeIndex(volume_collector, instance->GetVolumeMaterial()); + + current_shape->id = iter->GetId(); + current_shape_additional->group_id = iter->GetGroupId(); + + ++current_shape; + ++current_shape_additional; + } + + m_context.UnmapBuffer(0, out.shapes, shapes).Wait(); + m_context.UnmapBuffer(0, out.shapes_additional, shapes_additional).Wait(); + } + + void ClwSceneController::UpdateCurrentScene(Scene1 const& scene, ClwScene& out) const + { + ReloadIntersector(scene, out); + } + + void ClwSceneController::UpdateMaterials(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, ClwScene& out) const + { + // Get new buffer size + std::vector mat_buffer; + mat_buffer.reserve(1024 * 1024); //Reserv 1M of ints for material buffer. + + // Cleanup material mapping + m_materialid_to_offset.clear(); + + CLUberV2Generator uberv2_generator; + + // Serialize materials + { + // Update material bundle first to be able to track differences + out.material_bundle.reset(mat_collector.CreateBundle()); + + // Create material iterator + auto mat_iter = mat_collector.CreateIterator(); + + // Iterate and serialize + for (; mat_iter->IsValid(); mat_iter->Next()) + { + WriteMaterial(*mat_iter->ItemAs(), mat_collector, tex_collector, mat_buffer); + + uberv2_generator.AddMaterial(mat_iter->ItemAs()); + } + + } + + std::string uberv2_source = uberv2_generator.BuildSource(); + m_program_manager->AddHeader("uberv2_generated.cl", uberv2_source); + + + // Recreate material buffer if it needs resize + if (mat_buffer.size() > out.material_attributes.GetElementCount()) + { + // Create material buffer + out.material_attributes = m_context.CreateBuffer(mat_buffer.size(), CL_MEM_READ_ONLY); + } + + int32_t *materials = nullptr; + + // Map GPU materials buffer + m_context.MapBuffer(0, out.material_attributes, CL_MAP_WRITE, &materials).Wait(); + + memcpy(materials, mat_buffer.data(), mat_buffer.size() * sizeof(int32_t)); + + // Unmap material buffer + m_context.UnmapBuffer(0, out.material_attributes, materials); + } + + void ClwSceneController::UpdateVolumes(Scene1 const& scene, Collector& volume_collector, Collector& tex_collector, ClwScene& out) const + { + if (!volume_collector.GetNumItems()) + return; + + // Get new buffer size + std::size_t vol_buffer_size = volume_collector.GetNumItems(); + + // Recreate material buffer if it needs resize + if (vol_buffer_size > out.volumes.GetElementCount()) + { + // Create material buffer + out.volumes = m_context.CreateBuffer(vol_buffer_size, CL_MEM_READ_ONLY); + } + + ClwScene::Volume* volumes = nullptr; + + // Map GPU materials buffer + m_context.MapBuffer(0, out.volumes, CL_MAP_WRITE, &volumes).Wait(); + + // Create volume iterator + auto volume_iter = volume_collector.CreateIterator(); + + out.volume_bundle.reset(volume_collector.CreateBundle()); + // Serialize + size_t num_volumes_copied = 0; + for (; volume_iter->IsValid(); volume_iter->Next()) + { + WriteVolume(*volume_iter->ItemAs(), tex_collector, volumes + num_volumes_copied); + ++num_volumes_copied; + } + + // Unmap serial buffer + m_context.UnmapBuffer(0, out.volumes, volumes); + + // Update number of volumes + out.num_volumes = static_cast(num_volumes_copied); + } + + void ClwSceneController::ReloadIntersector(Scene1 const& scene, ClwScene& inout) const + { + m_api->DetachAll(); + + for (auto& s : inout.visible_shapes) + { + m_api->AttachShape(s); + } + + m_api->Commit(); + } + + void ClwSceneController::UpdateTextures(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, ClwScene& out) const + { + // Get new buffer size + std::size_t tex_buffer_size = tex_collector.GetNumItems(); + std::size_t tex_data_buffer_size = 0; + + if (tex_buffer_size == 0) + { + out.textures = m_context.CreateBuffer(1, CL_MEM_READ_ONLY); + out.texturedata = m_context.CreateBuffer(1, CL_MEM_READ_ONLY); + return; + } + + // Recreate material buffer if it needs resize + if (tex_buffer_size > out.textures.GetElementCount()) + { + // Create material buffer + out.textures = m_context.CreateBuffer(tex_buffer_size, CL_MEM_READ_ONLY); + } + + ClwScene::Texture* textures = nullptr; + std::size_t num_textures_written = 0; + + // Map GPU materials buffer + m_context.MapBuffer(0, out.textures, CL_MAP_WRITE, &textures).Wait(); + + // Update material bundle first to be able to track differences + out.texture_bundle.reset(tex_collector.CreateBundle()); + + // Create material iterator + std::unique_ptr tex_iter(tex_collector.CreateIterator()); + + // Iterate and serialize + for (; tex_iter->IsValid(); tex_iter->Next()) + { + auto tex = tex_iter->ItemAs(); + + WriteTexture(*tex, tex_data_buffer_size, textures + num_textures_written); + + ++num_textures_written; + + tex_data_buffer_size += align16(tex->GetSizeInBytes()); + } + + // Unmap material buffer + m_context.UnmapBuffer(0, out.textures, textures); + + // Recreate material buffer if it needs resize + if (tex_data_buffer_size > out.texturedata.GetElementCount()) + { + // Create material buffer + out.texturedata = m_context.CreateBuffer(tex_data_buffer_size, CL_MEM_READ_ONLY); + } + + char* data = nullptr; + std::size_t num_bytes_written = 0; + + tex_iter->Reset(); + + // Map GPU materials buffer + m_context.MapBuffer(0, out.texturedata, CL_MAP_WRITE, &data).Wait(); + + // Write texture data for all textures + for (; tex_iter->IsValid(); tex_iter->Next()) + { + auto tex = tex_iter->ItemAs(); + + WriteTextureData(*tex, data + num_bytes_written); + + num_bytes_written += align16(tex->GetSizeInBytes()); + } + + // Unmap material buffer + m_context.UnmapBuffer(0, out.texturedata, data); + } + +#ifndef NDEBUG + // We're not using this function on release + // Convert Material:: types to ClwScene:: types + static ClwScene::Bxdf GetMaterialType(Material const& material) + { + // Distinguish between single bxdf materials and compound ones + if (dynamic_cast(&material)) + { + return ClwScene::Bxdf::kUberV2; + } + + return ClwScene::Bxdf::kZero; + } +#endif + + void ClwSceneController::WriteMaterial(Material const& material, Collector& mat_collector, Collector& tex_collector, std::vector &material_data) const + { + assert(GetMaterialType(material) == ClwScene::Bxdf::kUberV2); + const UberV2Material &uber_material = static_cast(material); + + std::uint32_t layers = uber_material.GetLayers(); + + m_materialid_to_offset[material.GetId()] = static_cast(material_data.size()); + + // Pack material parameters + std::int32_t params = 0; + params |= ((uber_material.IsLinkRefractionIOR()) ? 1 : 0) << 0; + params |= ((uber_material.IsThin()) ? 1 : 0) << 1; + params |= ((uber_material.isDoubleSided()) ? 1 : 0) << 2; + params |= ((uber_material.IsMultiscatter()) ? 1 : 0) << 3; + material_data.push_back(params); + + // Describe order of fields and layers + static const std::vector>> uberv2_ordered_fields = + { + { + UberV2Material::Layers::kEmissionLayer, + { "uberv2.emission.color" } + }, + { + UberV2Material::Layers::kCoatingLayer, + { "uberv2.coating.color", "uberv2.coating.ior"} + }, + { + UberV2Material::Layers::kReflectionLayer, + { + "uberv2.reflection.color", + "uberv2.reflection.roughness", + "uberv2.reflection.anisotropy", + "uberv2.reflection.anisotropy_rotation", + "uberv2.reflection.ior", + "uberv2.reflection.metalness", + } + }, + { + UberV2Material::Layers::kDiffuseLayer, + { "uberv2.diffuse.color"} + }, + { + UberV2Material::Layers::kRefractionLayer, + { + "uberv2.refraction.color", + "uberv2.refraction.roughness", + "uberv2.refraction.ior" + } + }, + { + UberV2Material::Layers::kTransparencyLayer, + { "uberv2.transparency" } + }, + { + UberV2Material::Layers::kShadingNormalLayer, + { "uberv2.shading_normal" } + }, + { + UberV2Material::Layers::kSSSLayer, + { + "uberv2.sss.absorption_color", + "uberv2.sss.scatter_color", + "uberv2.sss.subsurface_color", + "uberv2.sss.absorption_distance", + "uberv2.sss.scatter_distance", + "uberv2.sss.scatter_direction" + } + }, + }; + + // Write material layers. Order matters. + for (auto &layer_info : uberv2_ordered_fields) + { + if ((layers & layer_info.first) == layer_info.first) + { + for (auto &layer_param : layer_info.second) + { + auto value = material.GetInputValue(layer_param); + assert(value.type == Material::InputType::kInputMap); + material_data.push_back(value.input_map_value ? value.input_map_value->GetId() : -1); + } + } + } + } + + // Convert Light:: types to ClwScene:: types + static int GetLightType(Light const& light) + { + + if (dynamic_cast(&light)) + { + return ClwScene::kPoint; + } + else if (dynamic_cast(&light)) + { + return ClwScene::kDirectional; + } + else if (dynamic_cast(&light)) + { + return ClwScene::kSpot; + } + else if (dynamic_cast(&light)) + { + return ClwScene::kIbl; + } + else + { + return ClwScene::LightType::kArea; + } + } + + void ClwSceneController::WriteLight(Scene1 const& scene, Light const& light, Collector& tex_collector, void* data) const + { + auto clw_light = reinterpret_cast(data); + + auto type = GetLightType(light); + + clw_light->type = type; + + switch (type) + { + case ClwScene::kPoint: + { + clw_light->p = light.GetPosition(); + clw_light->intensity = light.GetEmittedRadiance(); + break; + } + + case ClwScene::kDirectional: + { + clw_light->d = light.GetDirection(); + clw_light->intensity = light.GetEmittedRadiance(); + break; + } + + case ClwScene::kSpot: + { + clw_light->p = light.GetPosition(); + clw_light->d = light.GetDirection(); + clw_light->intensity = light.GetEmittedRadiance(); + + auto cone_shape = static_cast(light).GetConeShape(); + clw_light->ia = cone_shape.x; + clw_light->oa = cone_shape.y; + break; + } + + case ClwScene::kIbl: + { + auto& ibl = static_cast(light); + clw_light->multiplier = ibl.GetMultiplier(); + auto main_tex = ibl.GetTexture(); + clw_light->tex = main_tex ? tex_collector.GetItemIndex(main_tex) : -1; + auto reflection_tex = ibl.GetReflectionTexture(); + clw_light->tex_reflection = reflection_tex ? tex_collector.GetItemIndex(reflection_tex) : -1; + auto refraction_tex = ibl.GetRefractionTexture(); + clw_light->tex_refraction = refraction_tex ? tex_collector.GetItemIndex(refraction_tex) : -1; + auto transparency_tex = ibl.GetTransparencyTexture(); + clw_light->tex_transparency = transparency_tex ? tex_collector.GetItemIndex(transparency_tex) : -1; + auto background_tex = ibl.GetBackgroundTexture(); + clw_light->tex_background = background_tex ? tex_collector.GetItemIndex(background_tex) : -1; + clw_light->ibl_mirror_x = ibl.GetMirrorX(); + break; + } + + case ClwScene::kArea: + { + // TODO: optimize this linear search + auto shape = static_cast(light).GetShape(); + + auto shape_iter = scene.CreateShapeIterator(); + + auto idx = GetShapeIdx(*shape_iter, shape); + + clw_light->id = shape->GetId(); + clw_light->shapeidx = static_cast(idx); + clw_light->primidx = static_cast(static_cast(light).GetPrimitiveIdx()); + break; + } + + default: + assert(false); + break; + } + } + + void ClwSceneController::UpdateLights(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, ClwScene& out) const + { + std::size_t num_lights_written = 0; + + auto env_override = scene.GetEnvironmentOverride(); + + auto num_lights = scene.GetNumLights(); + auto distribution_buffer_size = (1 + 1 + num_lights + num_lights); + + // Create light buffer if needed + if (num_lights > out.lights.GetElementCount()) + { + out.lights = m_context.CreateBuffer(num_lights, CL_MEM_READ_ONLY); + out.light_distributions = m_context.CreateBuffer(distribution_buffer_size, CL_MEM_READ_ONLY); + } + + ClwScene::Light* lights = nullptr; + + m_context.MapBuffer(0, out.lights, CL_MAP_WRITE, &lights).Wait(); + std::unique_ptr light_iter(scene.CreateLightIterator()); + + // Disable IBL by default + out.envmapidx = -1; + + // Allocate intermediate storage for lights power distribution + std::vector light_power(num_lights); + std::uint32_t k = 0; + + // Serialize + { + for (; light_iter->IsValid(); light_iter->Next()) + { + auto light = light_iter->ItemAs(); + WriteLight(scene, *light, tex_collector, lights + num_lights_written); + + + // Find and update IBL idx + auto ibl = std::dynamic_pointer_cast(light_iter->ItemAs()); + if (ibl) + { + out.envmapidx = static_cast(num_lights_written); + } + + ++num_lights_written; + + auto power = light->GetPower(scene); + + // TODO: move luminance calculation into utility function + light_power[k++] = 0.2126f * power.x + 0.7152f * power.y + 0.0722f * power.z; + } + } + + m_context.UnmapBuffer(0, out.lights, lights); + + // Create distribution over light sources based on their power + Distribution1D light_distribution(&light_power[0], (std::uint32_t)light_power.size()); + + // Write distribution data + int* distribution_ptr = nullptr; + m_context.MapBuffer(0, out.light_distributions, CL_MAP_WRITE, &distribution_ptr).Wait(); + auto current = distribution_ptr; + + // Write the number of segments first + *current++ = (int)light_distribution.m_num_segments; + + // Then write num_segments + 1 CDF values + auto values = reinterpret_cast(current); + for (auto i = 0u; i < light_distribution.m_num_segments + 1; ++i) + { + values[i] = light_distribution.m_cdf[i]; + } + + // Then write num_segments PDF values + values += light_distribution.m_num_segments + 1; + + for (auto i = 0u; i < light_distribution.m_num_segments; ++i) + { + values[i] = light_distribution.m_func_values[i] / light_distribution.m_func_sum; + } + + m_context.UnmapBuffer(0, out.light_distributions, distribution_ptr); + + out.num_lights = static_cast(num_lights_written); + } + + + // Convert texture format into ClwScene:: types + static ClwScene::TextureFormat GetTextureFormat(Texture const& texture) + { + switch (texture.GetFormat()) + { + case Texture::Format::kRgba8: return ClwScene::TextureFormat::RGBA8; + case Texture::Format::kRgba16: return ClwScene::TextureFormat::RGBA16; + case Texture::Format::kRgba32: return ClwScene::TextureFormat::RGBA32; + default: return ClwScene::TextureFormat::RGBA8; + } + } + + void ClwSceneController::WriteTexture(Texture const& texture, std::size_t data_offset, void* data) const + { + auto clw_texture = reinterpret_cast(data); + + auto dim = texture.GetSize(); + + clw_texture->w = dim.x; + clw_texture->h = dim.y; + clw_texture->d = dim.z; + clw_texture->fmt = GetTextureFormat(texture); + clw_texture->dataoffset = static_cast(data_offset); + } + + void ClwSceneController::WriteTextureData(Texture const& texture, void* data) const + { + auto begin = texture.GetData(); + auto end = begin + texture.GetSizeInBytes(); + std::copy(begin, end, static_cast(data)); + } + + void ClwSceneController::WriteVolume(VolumeMaterial const& volume, Collector& tex_collector, void* data) const + { + auto clw_volume = reinterpret_cast(data); + + clw_volume->type = ClwScene::VolumeType::kHomogeneous; + clw_volume->data = -1; + clw_volume->extra = -1; + + auto absorption_value = volume.GetInputValue("absorption"); + + if (absorption_value.type == Material::InputType::kFloat4) + { + clw_volume->sigma_a.float_value.value = absorption_value.float_value; + clw_volume->sigma_a.int_value.value[3] = -1; + } + else if (absorption_value.type == Material::InputType::kTexture) + { + clw_volume->sigma_a.float_value.value = absorption_value.float_value; + clw_volume->sigma_a.int_value.value[3] = tex_collector.GetItemIndex(absorption_value.tex_value); + } + else + { + // TODO: should not happen + assert(false); + } + + + clw_volume->sigma_e.float_value.value = volume.GetInputValue("emission").float_value; + clw_volume->sigma_e.int_value.value[3] = -1; + clw_volume->sigma_s.float_value.value = volume.GetInputValue("scattering").float_value; + clw_volume->sigma_s.int_value.value[3] = -1; + clw_volume->g = volume.GetInputValue("g").float_value.x; + } + + int ClwSceneController::GetTextureIndex(Collector const& collector, Texture::Ptr texture) const + { + return texture ? collector.GetItemIndex(texture) : (-1); + } + + int ClwSceneController::GetMaterialIndex(Collector const& collector, Material::Ptr material) const + { + auto m = material ? material : m_default_material; + return ResolveMaterialPtr(m); + } + + int ClwSceneController::GetVolumeIndex(Collector const& collector, VolumeMaterial::Ptr volume) const + { + return volume ? collector.GetItemIndex(volume) : (-1); + } + + void ClwSceneController::UpdateSceneAttributes(Scene1 const& scene, Collector& tex_collector, ClwScene& out) const + { + auto bg_image = scene.GetBackgroundImage(); + out.background_idx = (bg_image) ? tex_collector.GetItemIndex(bg_image) : -1; + } + + void Baikal::ClwSceneController::UpdateInputMaps(const Baikal::Scene1& scene, Baikal::Collector& input_map_collector, Collector& input_map_leafs_collector, ClwScene& out) const + { + CLInputMapGenerator generator; + generator.Generate(input_map_collector, input_map_leafs_collector); + std::string source = generator.GetGeneratedSource(); + m_program_manager->AddHeader("inputmaps.cl", source); + } + + void Baikal::ClwSceneController::UpdateLeafsData(Scene1 const& scene, Collector& input_map_leafs_collector, Collector& tex_collector, ClwScene& out) const + { + // Get new buffer size + std::size_t buffer_size = input_map_leafs_collector.GetNumItems(); + + // Recreate input map leafs buffer if it needs resize + if (buffer_size > out.input_map_data.GetElementCount()) + { + // Create material buffer + out.input_map_data = m_context.CreateBuffer(buffer_size, CL_MEM_READ_ONLY); + } + + if (buffer_size > 0) + { + ClwScene::InputMapData *input_map_data = nullptr; + + // Map GPU input map buffer + m_context.MapBuffer(0, out.input_map_data, CL_MAP_WRITE, &input_map_data).Wait(); + + // Update input map leafs bundle to be able to track differences + out.input_map_leafs_bundle.reset(input_map_leafs_collector.CreateBundle()); + + // leaf iterator + auto iter = input_map_leafs_collector.CreateIterator(); + std::size_t num_inputmap_leafs_written = 0; + + // Iterate and serialize + for (; iter->IsValid(); iter->Next()) + { + WriteInputMapLeaf(*iter->ItemAs(), tex_collector, input_map_data + num_inputmap_leafs_written); + ++num_inputmap_leafs_written; + } + + //Unmap buffer + m_context.UnmapBuffer(0, out.input_map_data, input_map_data); + } + } + + void Baikal::ClwSceneController::WriteInputMapLeaf(InputMap const& leaf, Collector& tex_collector, void* data) const + { + ClwScene::InputMapData *data_pointer = static_cast(data); + if (!leaf.IsLeaf()) + { + //Shouldn't happen + assert(false); + return; + } + + switch (leaf.m_type) + { + case InputMap::InputMapType::kConstantFloat3: + { + const InputMap_ConstantFloat3 &i = static_cast(leaf); + data_pointer->float_value.value = i.GetValue(); + data_pointer->int_values.type = ClwScene::InputMapDataType::kFloat3; + break; + } + case InputMap::InputMapType::kConstantFloat: + { + const InputMap_ConstantFloat &i = static_cast(leaf); + data_pointer->float_value.value.x = i.GetValue(); + data_pointer->float_value.value.y = i.GetValue(); + data_pointer->float_value.value.z = i.GetValue(); + data_pointer->int_values.type = ClwScene::InputMapDataType::kFloat; + break; + } + case InputMap::InputMapType::kSampler: + { + const InputMap_Sampler &i = static_cast(leaf); + data_pointer->int_values.idx = tex_collector.GetItemIndex(i.GetTexture()); + data_pointer->int_values.type = ClwScene::InputMapDataType::kInt; + break; + } + case InputMap::InputMapType::kSamplerBumpmap: + { + const InputMap_SamplerBumpMap &i = static_cast(leaf); + data_pointer->int_values.idx = tex_collector.GetItemIndex(i.GetTexture()); + data_pointer->int_values.type = ClwScene::InputMapDataType::kInt; + break; + } + default: + //Shouldn't happen + assert(false); + } + } + + std::int32_t ClwSceneController::ResolveMaterialPtr(Material::Ptr material) const + { + auto it = m_materialid_to_offset.find(material->GetId()); + return (it == m_materialid_to_offset.end()) ? -1 : it->second; + } + + int ClwSceneController::GetMaterialLayers(Material::Ptr material) const + { + auto m = material ? material : m_default_material; + return std::static_pointer_cast(m)->GetLayers(); + } + +} diff --git a/Baikal/CLW/clw_scene_controller.h b/Baikal/Controllers/clw_scene_controller.h similarity index 57% rename from Baikal/CLW/clw_scene_controller.h rename to Baikal/Controllers/clw_scene_controller.h index 89b89f6f..ac02e40a 100644 --- a/Baikal/CLW/clw_scene_controller.h +++ b/Baikal/Controllers/clw_scene_controller.h @@ -1,16 +1,16 @@ /********************************************************************** Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. - + 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 @@ -28,10 +28,10 @@ */ #pragma once -#include "SceneGraph/scene_controller.h" +#include "scene_controller.h" #include "CLW.h" -#include "CLW/clwscene.h" +#include "SceneGraph/clwscene.h" #include "radeon_rays_cl.h" @@ -43,24 +43,25 @@ namespace Baikal class Material; class Light; class Texture; + class CLProgramManager; /** \brief Tracks changes of a scene and serialized data into GPU memory when needed. - + ClwSceneController class is intended to keep track of CPU side scene changes and update all - necessary GPU buffers. It essentially establishes a mapping between Scene class and - corresponding ClwScene class. It also pre-caches ClwScenes and speeds up loading for + necessary GPU buffers. It essentially establishes a mapping between Scene class and + corresponding ClwScene class. It also pre-caches ClwScenes and speeds up loading for already compiled scenes. */ class ClwSceneController : public SceneController { public: // Constructor - ClwSceneController(CLWContext context, int devidx); + ClwSceneController(CLWContext context, RadeonRays::IntersectionApi* api, const CLProgramManager *program_manager); // Destructor virtual ~ClwSceneController(); - + // Get underlying intersection API. RadeonRays::IntersectionApi* GetIntersectionApi() { return m_api; } @@ -68,42 +69,70 @@ namespace Baikal // Clear intersector and load meshes into it. void ReloadIntersector(Scene1 const& scene, ClwScene& inout) const; - private: + public: // Update camera data only. - void UpdateCamera(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, ClwScene& out) const override; + void UpdateCamera(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, Collector& vol_collector, ClwScene& out) const override; // Update shape data only. - void UpdateShapes(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, ClwScene& out) const override; + void UpdateShapes(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, Collector& vol_collector, ClwScene& out) const override; + // Update transform data only + void UpdateShapeProperties(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, Collector& volume_collector, ClwScene& out) const override; // Update lights data only. void UpdateLights(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, ClwScene& out) const override; // Update material data. void UpdateMaterials(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, ClwScene& out) const override; // Update texture data only. void UpdateTextures(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, ClwScene& out) const override; + // Update input maps only + void UpdateInputMaps(Scene1 const& scene, Collector& input_map_collector, Collector& input_map_leafs_collector, ClwScene& out) const override; + // Update input map leafs only + void UpdateLeafsData(Scene1 const& scene, Collector& input_map_leafs_collector, Collector& tex_collector, ClwScene& out) const override; // Get default material - Material const* GetDefaultMaterial() const override; + Material::Ptr GetDefaultMaterial() const override; // If m_current_scene changes void UpdateCurrentScene(Scene1 const& scene, ClwScene& out) const override; - + // Update volume materiuals + void UpdateVolumes(Scene1 const& scene, Collector& volume_collector, Collector& tex_collector, ClwScene& out) const override; + // If scene attributes changed + void UpdateSceneAttributes(Scene1 const& scene, Collector& tex_collector, ClwScene& out) const override; + // Update intersection API void UpdateIntersector(Scene1 const& scene, ClwScene& out) const; + void UpdateIntersectorTransforms(Scene1 const& scene, ClwScene& out) const; // Write out single material at data pointer. // Collectors are required to convert texture and material pointers into indices. - void WriteMaterial(Material const* material, Collector& mat_collector, Collector& tex_collector, void* data) const; + void WriteMaterial(Material const& material, Collector& mat_collector, Collector& tex_collector, std::vector &material_data) const; // Write out single light at data pointer. // Collector is required to convert texture pointers into indices. - void WriteLight(Scene1 const& scene, Light const* light, Collector& tex_collector, void* data) const; + void WriteLight(Scene1 const& scene, Light const& light, Collector& tex_collector, void* data) const; // Write out single texture header at data pointer. // Header requires texture data offset, so it is passed in. - void WriteTexture(Texture const* texture, std::size_t data_offset, void* data) const; + void WriteTexture(Texture const& texture, std::size_t data_offset, void* data) const; // Write out texture data at data pointer. - void WriteTextureData(Texture const* texture, void* data) const; + void WriteTextureData(Texture const& texture, void* data) const; + // Write single volume at data pointer + void WriteVolume(VolumeMaterial const& volume, Collector& tex_collector, void* data) const; + // Write single input map leaf at data pointer + // Collectore is required to convert texture pointers into indices. + void WriteInputMapLeaf(InputMap const& leaf, Collector& tex_collector, void* data) const; + + // Resolves host material pointer to device offset + std::int32_t ResolveMaterialPtr(Material::Ptr material) const; private: + int GetMaterialIndex(Collector const& collector, Material::Ptr material) const; + int GetTextureIndex(Collector const& collector, Texture::Ptr material) const; + int GetVolumeIndex(Collector const& collector, VolumeMaterial::Ptr volume) const; + int GetMaterialLayers(Material::Ptr material) const; + // Context CLWContext m_context; // Intersection API RadeonRays::IntersectionApi* m_api; // Default material - std::unique_ptr m_default_material; + Material::Ptr m_default_material; + // CL Program manager + const CLProgramManager *m_program_manager; + // Material to device material map + mutable std::unordered_map m_materialid_to_offset; }; } diff --git a/Baikal/Controllers/scene_controller.cpp b/Baikal/Controllers/scene_controller.cpp new file mode 100644 index 00000000..d4937136 --- /dev/null +++ b/Baikal/Controllers/scene_controller.cpp @@ -0,0 +1,17 @@ +#include + +namespace Baikal +{ + static std::uint32_t g_next_id = 0; + + std::uint32_t GetNextControllerId() + { + return g_next_id++; + } + + void ResetControllerId() + { + g_next_id = 0; + } + +} diff --git a/Baikal/SceneGraph/scene_controller.h b/Baikal/Controllers/scene_controller.h similarity index 57% rename from Baikal/SceneGraph/scene_controller.h rename to Baikal/Controllers/scene_controller.h index 1f17d654..7e830870 100644 --- a/Baikal/SceneGraph/scene_controller.h +++ b/Baikal/Controllers/scene_controller.h @@ -1,16 +1,16 @@ /********************************************************************** Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. - + 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 @@ -28,22 +28,25 @@ */ #pragma once +#include "SceneGraph/Collector/collector.h" +#include "SceneGraph/material.h" +#include "SceneGraph/scene1.h" + #include #include namespace Baikal { class Scene1; - class Collector; class Bundle; class Material; class Light; class Texture; - - + class VolumeMaterial; + /** \brief Tracks changes of a scene and serialized data if needed. - + SceneTracker class is intended to keep track of CPU side scene changes and update all necessary renderer buffers. */ @@ -54,35 +57,65 @@ namespace Baikal SceneController(); // Destructor virtual ~SceneController() = default; - + // Given a scene this method produces (or loads from cache) corresponding GPU representation. - CompiledScene& CompileScene(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector) const; - + CompiledScene& CompileScene(Scene1::Ptr scene) const; + + CompiledScene& GetCachedScene(Scene1::Ptr scene) const; + + static void ResetId(); + protected: // Recompile the scene from scratch, i.e. not loading from cache. // All the buffers are recreated and reloaded. - void RecompileFull(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, CompiledScene& out) const; - - private: + void RecompileFull(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, + Collector& vol_collector, Collector& input_maps_collector, + Collector& input_map_leafs_collector, CompiledScene& out) const; + + // set dirty flag to false for camera object + void DropCameraDirty(Scene1 const& scene) const; + // set dirty flag to false for iterator + void DropDirty(Iterator& light_iterator) const; + public: // Update camera data only. - virtual void UpdateCamera(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, CompiledScene& out) const = 0; + virtual void UpdateCamera(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, Collector& vol_collector, CompiledScene& out) const = 0; // Update shape data only. - virtual void UpdateShapes(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, CompiledScene& out) const = 0; + virtual void UpdateShapes(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, Collector& volume_collector, CompiledScene& out) const = 0; + // Update shape transforms + virtual void UpdateShapeProperties(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, Collector& volume_collector, CompiledScene& out) const = 0; // Update lights data only. virtual void UpdateLights(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, CompiledScene& out) const = 0; // Update material data. virtual void UpdateMaterials(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, CompiledScene& out) const = 0; // Update texture data only. virtual void UpdateTextures(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, CompiledScene& out) const = 0; + // Update input maps only + virtual void UpdateInputMaps(Scene1 const& scene, Collector& input_map_collector, Collector& input_map_leafs_collector, CompiledScene& out) const = 0; + // Update input map leafs only + virtual void UpdateLeafsData(Scene1 const& scene, Collector& input_map_leafs_collector, Collector& tex_collector, CompiledScene& out) const = 0; // Default material - virtual Material const* GetDefaultMaterial() const = 0; + virtual Material::Ptr GetDefaultMaterial() const = 0; // If m_current_scene changes virtual void UpdateCurrentScene(Scene1 const& scene, CompiledScene& out) const = 0; - + // Update volume materials only + virtual void UpdateVolumes(Scene1 const& scene, Collector& volume_collector, Collector& tex_collector, CompiledScene& out) const = 0; + // If scene attributes changed + virtual void UpdateSceneAttributes(Scene1 const& scene, Collector& tex_collector, CompiledScene& out) const = 0; + + private: - mutable Scene1 const* m_current_scene; + mutable Scene1::Ptr m_current_scene; // Scene cache map (CPU scene -> GPU scene mapping) - mutable std::map m_scene_cache; + mutable std::map m_scene_cache; + + mutable Collector m_material_collector; + mutable Collector m_volume_collector; + mutable Collector m_texture_collector; + mutable Collector m_input_maps_collector; + mutable Collector m_input_map_leafs_collector; + + // Scene controller id + std::uint32_t m_id; }; } diff --git a/Baikal/Controllers/scene_controller.inl b/Baikal/Controllers/scene_controller.inl new file mode 100644 index 00000000..14541a20 --- /dev/null +++ b/Baikal/Controllers/scene_controller.inl @@ -0,0 +1,585 @@ +#include "SceneGraph/scene1.h" +#include "SceneGraph/camera.h" +#include "SceneGraph/light.h" +#include "SceneGraph/shape.h" +#include "SceneGraph/material.h" +#include "SceneGraph/texture.h" +#include "SceneGraph/Collector/collector.h" +#include "SceneGraph/iterator.h" +#include "SceneGraph/uberv2material.h" + +#include +#include +#include +#include +#include + +namespace Baikal +{ + // Defined in scene_controller.cpp + std::uint32_t GetNextControllerId(); + void ResetControllerId(); + + template + SceneController::SceneController() + : m_id(GetNextControllerId()) + { + } + + template + void SceneController::ResetId() + { + ResetControllerId(); + } + + template + inline + CompiledScene& SceneController::GetCachedScene(Scene1::Ptr scene) const { + // Try to find scene in cache first + auto iter = m_scene_cache.find(scene); + + if (iter != m_scene_cache.cend()) { + return iter->second; + } else { + throw std::runtime_error("Scene has not been compiled"); + } + } + + template + inline + CompiledScene& SceneController::CompileScene( + Scene1::Ptr scene + ) const { + + scene->Acquire(m_id); + + // The overall approach is: + // 1) Check if materials have changed, update collector if yes + // 2) Check if textures have changed, update collector if yes + // Note, that material are collected from shapes (potentially recursively). + // Textures are collected from materials and lights. + // As soon as we updated both collectors we have established + // correct pointer to buffer index mapping for both materials and textures. + // As soon as we have this mapping we are analyzing dirty flags and + // updating necessary parts. + + // We need to make sure collectors are empty before proceeding + m_material_collector.Clear(); + m_texture_collector.Clear(); + m_volume_collector.Clear(); + m_input_maps_collector.Clear(); + m_input_map_leafs_collector.Clear(); + + // Create shape and light iterators + auto shape_iter = scene->CreateShapeIterator(); + auto light_iter = scene->CreateLightIterator(); + + auto default_material = GetDefaultMaterial(); + // Collect materials from shapes first + m_material_collector.Collect(*shape_iter, + // This function adds all materials to resulting map + // recursively via Material dependency API + [default_material](SceneObject::Ptr item) -> + std::set + { + // Resulting material set + std::set mats; + // Material stack + std::stack material_stack; + + // Get material from current shape + auto shape = std::static_pointer_cast(item); + auto material = shape->GetMaterial(); + + // If shape does not have a material, use default one + if (!material) + { + material = default_material; + } + + // Push to stack as an initializer + material_stack.push(material); + + // Drain the stack + while (!material_stack.empty()) + { + // Get current material + auto m = material_stack.top(); + material_stack.pop(); + + // Emplace into the set + mats.emplace(m); + + // Create dependency iterator + auto mat_iter = m->CreateMaterialIterator(); + + // Push all dependencies into the stack + for (; mat_iter->IsValid(); mat_iter->Next()) + { + material_stack.push( + mat_iter->ItemAs() + ); + } + } + + // Return resulting set + return mats; + }); + + // Commit stuff (we can iterate over it after commit has happened) + m_material_collector.Commit(); + + // set iterator position at begin + shape_iter->Reset(); + // Collect volume materials from shapes first + m_volume_collector.Collect(*shape_iter, + [](SceneObject::Ptr item) -> std::set + { + // Resulting material set + std::set vol_mats; + + // Get volume material from current shape + auto shape = std::static_pointer_cast(item); + auto volume_material = shape->GetVolumeMaterial(); + + if (volume_material) + vol_mats.emplace(volume_material); + + return vol_mats; + }); + + // Commit stuff + m_volume_collector.Commit(); + + // Now we need to collect textures from our materials + // Create material iterator + auto mat_iter = m_material_collector.CreateIterator(); + + // Collect textures from materials + m_texture_collector.Collect(*mat_iter, + [](SceneObject::Ptr item) -> std::set + { + // Texture set + std::set textures; + + auto material = std::static_pointer_cast(item); + + // Create texture dependency iterator + auto tex_iter = material->CreateTextureIterator(); + + // Emplace all dependent textures + for (; tex_iter->IsValid(); tex_iter->Next()) + { + textures.emplace(tex_iter->ItemAs()); + } + + // Return resulting set + return textures; + }); + + // Now we need to collect textures from volumes + // Create volume iterator + auto vol_iter = m_volume_collector.CreateIterator(); + + // Collect textures from materials + m_texture_collector.Collect(*vol_iter, + [](SceneObject::Ptr item) -> std::set + { + // Texture set + std::set textures; + + auto volume = std::static_pointer_cast(item); + + // Create texture dependency iterator + auto tex_iter = volume->CreateTextureIterator(); + + // Emplace all dependent textures + for (; tex_iter->IsValid(); tex_iter->Next()) + { + textures.emplace(tex_iter->ItemAs()); + } + + // Return resulting set + return textures; + }); + + // Collect textures from lights + m_texture_collector.Collect(*light_iter, + [](SceneObject::Ptr item) -> std::set + { + // Resulting set + std::set textures; + + auto light = std::static_pointer_cast(item); + + // Create texture dependency iterator + auto tex_iter = light->CreateTextureIterator(); + + // Emplace all dependent textures + for (; tex_iter->IsValid(); tex_iter->Next()) + { + textures.emplace(tex_iter->ItemAs()); + } + + // Return resulting set + return textures; + }); + + mat_iter->Reset(); + m_input_maps_collector.Collect(*mat_iter, + [](SceneObject::Ptr item) -> std::set + { + // Texture set + std::set input_maps; + + auto material = std::static_pointer_cast(item); + + // Create texture dependency iterator + auto input_map_iter = material->CreateInputMapsIterator(); + + // Emplace all dependent textures + for (; input_map_iter->IsValid(); input_map_iter->Next()) + { + input_maps.emplace(input_map_iter->ItemAs()); + } + + // Return resulting set + return input_maps; + }); + m_input_maps_collector.Commit(); + + mat_iter->Reset(); + m_input_map_leafs_collector.Collect(*mat_iter, + [](SceneObject::Ptr item) -> std::set + { + // Texture set + std::set input_maps; + + auto material = std::static_pointer_cast(item); + + // Create texture dependency iterator + auto input_map_iter = material->CreateInputMapLeafsIterator(); + + // Emplace all dependent textures + for (; input_map_iter->IsValid(); input_map_iter->Next()) + { + input_maps.emplace(input_map_iter->ItemAs()); + } + + // Return resulting set + return input_maps; + }); + m_input_map_leafs_collector.Commit(); + + + // Add background texture from scene into texture collector + auto background_texture = scene->GetBackgroundImage(); + if (background_texture) + m_texture_collector.Collect(background_texture); + + // Commit textures + m_texture_collector.Commit(); + + // Try to find scene in cache first + auto iter = m_scene_cache.find(scene); + + if (iter == m_scene_cache.cend()) + { + // If not found create scene entry in cache + auto res = m_scene_cache.emplace(std::make_pair(scene, CompiledScene())); + + // Recompile all the stuff into cached scene + RecompileFull(*scene, m_material_collector, m_texture_collector, m_volume_collector, + m_input_maps_collector, m_input_map_leafs_collector, res.first->second); + + // Set scene as current + m_current_scene = scene; + + // Drop all dirty flags for the scene + scene->ClearDirtyFlags(); + + // Drop dirty flags for materials + m_material_collector.Finalize([](SceneObject::Ptr item) + { + auto material = std::static_pointer_cast(item); + material->SetDirty(false); + }); + + m_volume_collector.Finalize([](SceneObject::Ptr item) + { + auto volume = std::static_pointer_cast(item); + volume->SetDirty(false); + }); + + // It will mark entire hierarchy as not dirty + m_input_maps_collector.Finalize([](SceneObject::Ptr item) + { + auto input_map = std::static_pointer_cast(item); + input_map->SetDirty(false); + }); + + // Return the scene + scene->Release(); + return res.first->second; + } + else + { + // Exctract cached scene entry + auto& out = iter->second; + auto dirty = scene->GetDirtyFlags(); + + bool should_update_materials = !out.material_bundle || + m_material_collector.NeedsUpdate(out.material_bundle.get(), + [](SceneObject::Ptr ptr)->bool + { + auto mat = std::static_pointer_cast(ptr); + return mat->IsDirty(); + }); + + bool should_update_volumes = !out.volume_bundle || + m_volume_collector.NeedsUpdate(out.volume_bundle.get(), + [](SceneObject::Ptr ptr)->bool + { + auto volume = std::static_pointer_cast(ptr); + return volume->IsDirty(); + }); + + bool should_update_textures = m_texture_collector.GetNumItems() > 0 && ( + !out.texture_bundle || + m_texture_collector.NeedsUpdate(out.texture_bundle.get(), [](SceneObject::Ptr ptr) { + auto tex = std::static_pointer_cast(ptr); + return tex->IsDirty(); })); + + bool should_update_leafs_data = (m_input_map_leafs_collector.GetNumItems() > 0) && ( + !out.input_map_leafs_bundle || + m_input_map_leafs_collector.NeedsUpdate(out.input_map_leafs_bundle.get(), [](SceneObject::Ptr ptr) + { + return ptr->IsDirty(); + })); + + bool should_update_input_maps = (m_input_maps_collector.GetNumItems() > 0) && ( + !out.input_map_bundle || + m_input_maps_collector.NeedsUpdate(out.input_map_bundle.get(), [](SceneObject::Ptr ptr) + { + return ptr->IsDirty(); + })); + + // Check if we have valid camera + auto camera = scene->GetCamera(); + + if (!camera) + { + throw std::runtime_error("No camera in the scene"); + } + + // Check if camera parameters have been changed + auto camera_changed = camera->IsDirty(); + + // Update camera if needed + if (dirty & Scene1::kCamera || camera_changed) + { + UpdateCamera(*scene, m_material_collector, m_texture_collector, m_volume_collector, out); + DropCameraDirty(*scene); + } + + // If materials need an update, do it. + // We are passing material dirty state detection function in there. + // We update materials before lights and shapes since they depends on it. + if (should_update_materials) + { + UpdateMaterials(*scene, m_material_collector, m_texture_collector, out); + } + + { + // Check if we have lights in the scene + auto light_iter = scene->CreateLightIterator(); + + if (!light_iter->IsValid()) + { + throw std::runtime_error("No lights in the scene"); + } + + + // Check if light parameters have been changed + bool lights_changed = false; + + for (; light_iter->IsValid(); light_iter->Next()) + { + auto light = light_iter->ItemAs(); + + if (light->IsDirty()) + { + lights_changed = true; + break; + } + } + + + // Update lights if needed + if (dirty & Scene1::kLights || lights_changed || + should_update_textures || should_update_materials) + { + UpdateLights(*scene, m_material_collector, m_texture_collector, out); + light_iter->Reset(); + DropDirty(*light_iter); + } + } + + { + // Check if we have shapes in the scene + auto shape_iter = scene->CreateShapeIterator(); + + if (!shape_iter->IsValid()) + { + throw std::runtime_error("No shapes in the scene"); + } + + // Check if shape parameters have been changed + bool shapes_changed = false; + + for (; shape_iter->IsValid(); shape_iter->Next()) + { + auto shape = shape_iter->ItemAs(); + + if (shape->IsDirty()) + { + shapes_changed = true; + break; + } + } + + // Update shapes if needed + if (dirty & Scene1::kShapes) + { + UpdateShapes(*scene, m_material_collector, m_texture_collector, m_volume_collector, out); + shape_iter->Reset(); + DropDirty(*shape_iter); + } + else if (shapes_changed) + { + UpdateShapeProperties(*scene, m_material_collector, m_texture_collector, m_volume_collector, out); + } + } + + // If textures need an update, do it. + if (should_update_textures) + { + UpdateTextures(*scene, m_material_collector, m_texture_collector, out); + } + + // If volumes need an update, do it. + if (should_update_volumes) + { + UpdateVolumes(*scene, m_volume_collector, m_texture_collector, out); + } + + if (should_update_leafs_data) + { + UpdateLeafsData(*scene, m_input_map_leafs_collector, m_texture_collector, out); + } + + if (should_update_input_maps) + { + UpdateInputMaps(*scene, m_input_maps_collector, m_input_map_leafs_collector, out); + } + + // Set current scene + if (m_current_scene != scene) + { + m_current_scene = scene; + + UpdateCurrentScene(*scene, out); + } + + // If background image need an update, do it. + if ((scene->GetDirtyFlags() & Scene1::kBackground) == Scene1::kBackground) + { + UpdateSceneAttributes(*scene, m_texture_collector, out); + } + + // Make sure to clear dirty flags + scene->ClearDirtyFlags(); + + // Clear material dirty flags + m_material_collector.Finalize([](SceneObject::Ptr item) + { + auto material = std::static_pointer_cast(item); + material->SetDirty(false); + }); + + m_texture_collector.Finalize([](SceneObject::Ptr item) + { + auto tex = std::static_pointer_cast(item); + tex->SetDirty(false); + }); + + m_volume_collector.Finalize([](SceneObject::Ptr item) + { + auto volume = std::static_pointer_cast(item); + volume->SetDirty(false); + }); + + // It will mark entire hierarchy as not dirty + m_input_maps_collector.Finalize([](SceneObject::Ptr item) + { + auto input_map = std::static_pointer_cast(item); + input_map->SetDirty(false); + }); + + // Return the scene + scene->Release(); + return out; + } + } + + template + inline + void SceneController::RecompileFull( + Scene1 const& scene, Collector& m_material_collector, Collector& m_texture_collector, Collector& vol_collector, + Collector& input_maps_collector, Collector& input_map_leafs_collector, CompiledScene& out) const + { + UpdateCamera(scene, m_material_collector, m_texture_collector, m_volume_collector, out); + DropCameraDirty(scene); + + //Lights and Shapes depends on Materials + UpdateMaterials(scene, m_material_collector, m_texture_collector, out); + + UpdateLights(scene, m_material_collector, m_texture_collector, out); + auto light_iterator = scene.CreateLightIterator(); + DropDirty(*light_iterator); + + UpdateShapes(scene, m_material_collector, m_texture_collector, vol_collector, out); + auto shape_iterator = scene.CreateShapeIterator(); + DropDirty(*shape_iterator); + + UpdateTextures(scene, m_material_collector, m_texture_collector, out); + + UpdateLeafsData(scene, m_input_map_leafs_collector, m_texture_collector, out); + + UpdateInputMaps(scene, m_input_maps_collector, m_input_map_leafs_collector, out); + + UpdateVolumes(scene, vol_collector, m_texture_collector, out); + + UpdateSceneAttributes(scene, m_texture_collector, out); + } + + template + inline + void SceneController::DropCameraDirty(Scene1 const& scene) const + { + auto camera = scene.GetCamera(); + + if (!camera) + throw std::runtime_error("SceneController::RecompileFull(...): camera was not set"); + + camera->SetDirty(false); + } + + template + inline + void SceneController::DropDirty(Iterator& iterator) const + { + for (; iterator.IsValid(); iterator.Next()) + iterator.ItemAs()->SetDirty(false); + } +} diff --git a/Baikal/Estimators/estimator.h b/Baikal/Estimators/estimator.h new file mode 100644 index 00000000..6ac9ee09 --- /dev/null +++ b/Baikal/Estimators/estimator.h @@ -0,0 +1,302 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once + +#include "radeon_rays.h" +#include "SceneGraph/clwscene.h" +#include "Utils/clw_class.h" + +#include "CLW.h" + +#include +#include + +namespace Baikal +{ + /** + \brief Estimator calculates radiance estimates for a given set of directions in the scene. + + Given a ray buffer and an output buffer, estimator calculates single sample estimate of an + incoming radiance and adds it into an output buffer. + */ + class Estimator + { + public: + enum class QualityLevel + { + kRough, + kStandard, + kPrecise + }; + + enum class IntermediateValue + { + kDirectRadiance, + kIndirectRadiance, + kVisibility, + kOpacity, + kMax + }; + + enum class RandomBufferType + { + kRandomSeed, + kSobolLUT + }; + + struct RayTracingStats + { + float primary_throughput; + float secondary_throughput; + float shadow_throughput; + }; + + using MissedPrimaryRaysHandler = std::function rays, CLWBuffer intersections, CLWBuffer pixel_indices, + CLWBuffer output_indices, std::size_t size, CLWBuffer output)>; + + Estimator(std::shared_ptr api) + : m_intersector(api) + , m_max_bounces(5u) + , m_max_shadow_ray_transmission_steps(2u) + { + } + + virtual ~Estimator() = default; + + /** + \brief Tells estimator about memory requirements (max number of entries in ray buffer). + + Estimators allocate internal buffers to store rays and output index mappings. Clients + set the size of internal buffers and then query them and fill them up with the data. + */ + virtual void SetWorkBufferSize(std::size_t size) = 0; + + /** + \brief Returns internal ray buffer size in elements. + */ + virtual std::size_t GetWorkBufferSize() const = 0; + + /** + \brief Set random seed value for the renderer. Renders + with the same random seed are guaranteed to be the same. + + \param seed Seed value + */ + virtual void SetRandomSeed(std::uint32_t seed) = 0; + + /** + \brief Get ray buffer handle. + + Clients generate ray workload directly into internal memory of an estimator to + save memory bandwidth. This method allows to get CLW handle of a buffer and fill it up + on the client side. + + IMPORTANT: SetWorkBufferSize should be called prior to calling this method. + Returned buffer size is exacly the size set via SetWorkBufferSize. + */ + virtual CLWBuffer GetRayBuffer() const = 0; + + /** + \brief Get output index buffer handle. + + Clients generate ray workload directly into internal memory of an estimator to + save memory bandwidth. This method allows to get CLW handle of a buffer and fill it up + on the client side. Output index establishes ray index -> output index mapping. + Output data for ray index i is scattered into output[output_index[i]]. + + IMPORTANT: SetWorkBufferSize should be called prior to calling this method. + Returned buffer size is exacly the size set via SetWorkBufferSize. + */ + virtual CLWBuffer GetOutputIndexBuffer() const = 0; + + /** + \brief Get ray count buffer handle. + + This buffer is used by the clients to tell how many rays are in ray buffer. + This is GPU buffer, which helps to avoid unnecessary CPU->GPU copies. + + IMPORTANT: SetWorkBufferSize should be called prior to calling this method. + */ + virtual CLWBuffer GetRayCountBuffer() const = 0; + + /** + \brief Returns first hit buffer + + IMPORTANT: SetWorkBufferSize should be called prior to calling this method. + Returned buffer size is exacly the size set via SetWorkBufferSize. + */ + virtual CLWBuffer GetFirstHitBuffer() const = 0;; + + /** + \brief General buffer access function (hack to avoid vidmem duplication). + + IMPORTANT: SetWorkBufferSize should be called prior to calling this method. + Returned buffer size is exacly the size set via SetWorkBufferSize. + */ + virtual bool HasRandomBuffer(RandomBufferType buffer) const { return false; } + + /** + \brief General buffer access function (hack to avoid vidmem duplication). + + IMPORTANT: SetWorkBufferSize should be called prior to calling this method. + Returned buffer size is exacly the size set via SetWorkBufferSize. + */ + virtual CLWBuffer GetRandomBuffer(RandomBufferType buffer) const { + return CLWBuffer(); + } + + /** + \brief Check if an estimator supports intermediate value. + + Estimators can support output of various intermidate quantities. + */ + virtual bool SupportsIntermediateValue(IntermediateValue value) const { return false; } + + /** + \brief Set intermediate value buffer. + + Estimators can support output of various intermidate quantities. The size of the buffer + should be >= working buffer size. + */ + void SetIntermediateValueBuffer(IntermediateValue value, CLWBuffer buffer) { m_intermediate_value[static_cast(value)] = buffer; } + + /** + \brief Get intermediate value buffer. + + Estimators can support output of various intermidate quantities. The size of the buffer + should be >= working buffer size. + */ + CLWBuffer GetIntermediateValueBuffer(IntermediateValue value) const { return m_intermediate_value[static_cast(value)]; } + + /** + \brief Check whether intermediate buffer is set. + + Estimators can support output of various intermidate quantities. The size of the buffer + should be >= working buffer size. + */ + bool HasIntermediateValueBuffer(IntermediateValue value) const { return m_intermediate_value[static_cast(value)].GetElementCount() > 0; } + + + /** + \brief Evaluate single sample radiance estimate for a given direction. + + Estimators usually utilize some internal structures where the size depends on input ray + buffer size. This method allows an estimator to pre-allocate internal structures upfront. + + \param scene Scene description. + \param num_estimates Number of items in ray buffer. + \param quality Quality of the estimate. + \param output Output buffer. + \param use_output_indices If set to false assumes 1 to 1 correspondence between the ray and the output + \param atomic_update Tells an estimator that indices might contain duplicate elements and + hence atomic update is required while updating output buffer. + */ + virtual void Estimate( + ClwScene const& scene, + std::size_t num_estimates, + QualityLevel quality, + CLWBuffer output, + bool use_output_indices = true, + bool atomic_update = false, + MissedPrimaryRaysHandler missedPrimaryRaysHandler = nullptr + ) = 0; + + /** + \brief Find intersection points for the rays in ray buffer. + + Intersection are calculated and written to intersection buffer. + + \param scene Scene description. + \param num_estimates Number of items in ray buffer. + */ + virtual void TraceFirstHit( + ClwScene const& scene, + std::size_t num_estimates + ) = 0; + + /** + \brief Run internal ray tracing benchmark. + + Intersection are calculated and written to intersection buffer. + + \param scene Scene description. + \param num_estimates Number of items in ray buffer. + */ + virtual void Benchmark( + ClwScene const& scene, + std::size_t num_estimates, + RayTracingStats& stats + ) = 0; + + /** + \brief Get underlying intersector. + + Estimators rely on intersection API for geometric queries. + */ + std::shared_ptr GetIntersector() const { + return m_intersector; + } + + /** + \brief Set max number of light bounces. + + \param num_bounces + */ + void SetMaxBounces(std::uint32_t num_bounces) { + m_max_bounces = num_bounces; + } + + /** + \brief Get max number of light bounces. + */ + std::uint32_t GetMaxBounces() const { + return m_max_bounces; + } + + /** + \brief Set max number of shadow ray steps through volumes (Transparent shadow). + + \param num_steps + */ + void SetMaxShadowRayTransmissionSteps(std::uint32_t num_steps) { + m_max_shadow_ray_transmission_steps = num_steps; + } + + /** + \brief Get max number of shadow ray transmission steps. + */ + std::uint32_t GetMaxShadowRayTransmissionSteps() const { + return m_max_shadow_ray_transmission_steps; + } + + Estimator(Estimator const&) = delete; + Estimator& operator = (Estimator const&) = delete; + + private: + std::shared_ptr m_intersector; + std::uint32_t m_max_bounces; + std::uint32_t m_max_shadow_ray_transmission_steps; + std::array, + static_cast(IntermediateValue::kMax)> m_intermediate_value; + }; +} \ No newline at end of file diff --git a/Baikal/Estimators/path_tracing_estimator.cpp b/Baikal/Estimators/path_tracing_estimator.cpp new file mode 100644 index 00000000..d88ded7e --- /dev/null +++ b/Baikal/Estimators/path_tracing_estimator.cpp @@ -0,0 +1,918 @@ +#include "path_tracing_estimator.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "Utils/sobol.h" + +#ifdef BAIKAL_EMBED_KERNELS +#include "embed_kernels.h" +#endif + +namespace Baikal +{ + struct PathTracingEstimator::PathState + { + float4 throughput; + int volume; + int flags; + int extra0; + int extra1; + }; + + struct PathTracingEstimator::RenderData + { + // OpenCL stuff + CLWBuffer rays[2]; + CLWBuffer hits; + + CLWBuffer shadowrays; + CLWBuffer shadowhits; + + CLWBuffer intersections; + CLWBuffer compacted_indices; + CLWBuffer pixelindices[2]; + CLWBuffer output_indices; + CLWBuffer iota; + + CLWBuffer lightsamples; + CLWBuffer paths; + CLWBuffer random; + CLWBuffer sobolmat; + CLWBuffer hitcount; + CLWParallelPrimitives pp; + + // RadeonRays stuff + Buffer* fr_rays[2]; + Buffer* fr_shadowrays; + Buffer* fr_shadowhits; + Buffer* fr_hits; + Buffer* fr_intersections; + Buffer* fr_hitcount; + + Collector mat_collector; + Collector tex_collector; + + RenderData() + : fr_shadowrays(nullptr) + , fr_shadowhits(nullptr) + , fr_hits(nullptr) + , fr_intersections(nullptr) + , fr_hitcount(nullptr) + { + fr_rays[0] = nullptr; + fr_rays[1] = nullptr; + } + }; + + PathTracingEstimator::PathTracingEstimator( + CLWContext context, + std::shared_ptr api, + const CLProgramManager *program_manager + ) : + Estimator(api) +#ifdef BAIKAL_EMBED_KERNELS + , ClwClass(context, program_manager, "path_tracing_estimator", g_path_tracing_estimator_opencl, g_path_tracing_estimator_opencl_headers, "") +#else + , ClwClass(context, program_manager, "../Baikal/Kernels/CL/path_tracing_estimator.cl", "") +#endif + , m_render_data(new RenderData) + , m_sample_counter(0) +#ifdef BAIKAL_EMBED_KERNELS + , m_uberv2_kernels(context, program_manager, "path_tracing_estimator_uberv2", g_path_tracing_estimator_uberv2_opencl, g_path_tracing_estimator_uberv2_opencl_headers, "") +#else + , m_uberv2_kernels(context, program_manager, "../Baikal/Kernels/CL/path_tracing_estimator_uberv2.cl", "") +#endif + { + // Create parallel primitives + m_render_data->pp = CLWParallelPrimitives(context, GetFullBuildOpts().c_str()); + m_render_data->sobolmat = context.CreateBuffer(1024 * 52, CL_MEM_READ_ONLY, &g_SobolMatrices[0]); + } + + PathTracingEstimator::~PathTracingEstimator() + { + // Recreate FR buffers + GetIntersector()->DeleteBuffer(m_render_data->fr_rays[0]); + GetIntersector()->DeleteBuffer(m_render_data->fr_rays[1]); + GetIntersector()->DeleteBuffer(m_render_data->fr_shadowrays); + GetIntersector()->DeleteBuffer(m_render_data->fr_hits); + GetIntersector()->DeleteBuffer(m_render_data->fr_shadowhits); + GetIntersector()->DeleteBuffer(m_render_data->fr_intersections); + GetIntersector()->DeleteBuffer(m_render_data->fr_hitcount); + } + + std::size_t PathTracingEstimator::GetWorkBufferSize() const + { + return m_render_data->rays[0].GetElementCount(); + } + + void PathTracingEstimator::SetWorkBufferSize(std::size_t size) + { + m_render_data->rays[0] = GetContext().CreateBuffer(size, CL_MEM_READ_WRITE); + m_render_data->rays[1] = GetContext().CreateBuffer(size, CL_MEM_READ_WRITE); + m_render_data->hits = GetContext().CreateBuffer(size, CL_MEM_READ_WRITE); + m_render_data->intersections = GetContext().CreateBuffer(size, CL_MEM_READ_WRITE); + m_render_data->shadowrays = GetContext().CreateBuffer(size, CL_MEM_READ_WRITE); + m_render_data->shadowhits = GetContext().CreateBuffer(size, CL_MEM_READ_WRITE); + m_render_data->lightsamples = GetContext().CreateBuffer(size, CL_MEM_READ_WRITE); + m_render_data->paths = GetContext().CreateBuffer(size, CL_MEM_READ_WRITE); + + std::vector random_buffer(size); + std::generate(random_buffer.begin(), random_buffer.end(), [](){return std::rand() + 3;}); + + m_render_data->random = GetContext().CreateBuffer(size, CL_MEM_READ_WRITE, &random_buffer[0]); + + std::vector initdata(size); + std::iota(initdata.begin(), initdata.end(), 0); + + m_render_data->iota = GetContext().CreateBuffer(size, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, &initdata[0]); + m_render_data->compacted_indices = GetContext().CreateBuffer(size, CL_MEM_READ_WRITE); + m_render_data->pixelindices[0] = GetContext().CreateBuffer(size, CL_MEM_READ_WRITE); + m_render_data->pixelindices[1] = GetContext().CreateBuffer(size, CL_MEM_READ_WRITE); + m_render_data->output_indices = GetContext().CreateBuffer(size, CL_MEM_READ_WRITE); + m_render_data->hitcount = GetContext().CreateBuffer(1, CL_MEM_READ_WRITE); + + // Recreate FR buffers + GetIntersector()->DeleteBuffer(m_render_data->fr_rays[0]); + GetIntersector()->DeleteBuffer(m_render_data->fr_rays[1]); + GetIntersector()->DeleteBuffer(m_render_data->fr_shadowrays); + GetIntersector()->DeleteBuffer(m_render_data->fr_hits); + GetIntersector()->DeleteBuffer(m_render_data->fr_shadowhits); + GetIntersector()->DeleteBuffer(m_render_data->fr_intersections); + GetIntersector()->DeleteBuffer(m_render_data->fr_hitcount); + + auto intersector = GetIntersector().get(); + m_render_data->fr_rays[0] = CreateFromOpenClBuffer(intersector, m_render_data->rays[0]); + m_render_data->fr_rays[1] = CreateFromOpenClBuffer(intersector, m_render_data->rays[1]); + m_render_data->fr_shadowrays = CreateFromOpenClBuffer(intersector, m_render_data->shadowrays); + m_render_data->fr_hits = CreateFromOpenClBuffer(intersector, m_render_data->hits); + m_render_data->fr_shadowhits = CreateFromOpenClBuffer(intersector, m_render_data->shadowhits); + m_render_data->fr_intersections = CreateFromOpenClBuffer(intersector, m_render_data->intersections); + m_render_data->fr_hitcount = CreateFromOpenClBuffer(intersector, m_render_data->hitcount); + } + + CLWBuffer PathTracingEstimator::GetRayBuffer() const + { + return m_render_data->rays[0]; + } + + CLWBuffer PathTracingEstimator::GetOutputIndexBuffer() const + { + return m_render_data->output_indices; + } + + CLWBuffer PathTracingEstimator::GetRayCountBuffer() const + { + return m_render_data->hitcount; + } + + void PathTracingEstimator::Estimate( + ClwScene const& scene, + std::size_t num_estimates, + QualityLevel quality, + CLWBuffer output, + bool use_output_indices, + bool atomic_update, + MissedPrimaryRaysHandler missedPrimaryRaysHandler + ) + { + if (atomic_update) + { + SetDefaultBuildOptions(" -D BAIKAL_ATOMIC_RESOLVE "); + } + + auto has_visibility_buffer = HasIntermediateValueBuffer(IntermediateValue::kVisibility); + auto visibility_buffer = GetIntermediateValueBuffer(IntermediateValue::kVisibility); + + auto has_opacity_buffer = HasIntermediateValueBuffer(IntermediateValue::kOpacity); + auto opacity_buffer = GetIntermediateValueBuffer(IntermediateValue::kOpacity); + + InitPathData(num_estimates, scene.camera_volume_index); + + GetContext().CopyBuffer(0u, m_render_data->iota, m_render_data->pixelindices[0], 0, 0, num_estimates); + GetContext().CopyBuffer(0u, m_render_data->iota, m_render_data->pixelindices[1], 0, 0, num_estimates); + + // Initialize first pass + for (auto pass = 0u; pass < GetMaxBounces(); ++pass) + { + // Clear ray hits buffer + // TODO: make it a kernel + GetContext().FillBuffer( + 0, + m_render_data->hits, + 0, + m_render_data->hits.GetElementCount() + ); + + // Intersect ray batch + GetIntersector()->QueryIntersection( + m_render_data->fr_rays[pass & 0x1], + m_render_data->fr_hitcount, (std::uint32_t)num_estimates, + m_render_data->fr_intersections, + nullptr, + nullptr + ); + + + // Apply scattering only if we have volumes + bool has_some_volume = scene.num_volumes > 0; + + if (has_some_volume) + { + SampleVolume(scene, pass, num_estimates, output, use_output_indices); + } + + bool has_some_environment = scene.envmapidx > -1; + + if ((pass > 0) && has_some_environment) + { + ShadeMiss(scene, pass, num_estimates, output, use_output_indices); + } + + // Convert intersections to predicates + FilterPathStream(pass, num_estimates); + + // Gather opacity if we have opacity buffer + if ((pass > 0) && has_opacity_buffer) + { + GatherOpacity(scene, pass, num_estimates, opacity_buffer, use_output_indices); + } + + // Compact batch + m_render_data->pp.Compact( + 0, + m_render_data->hits, + m_render_data->iota, + m_render_data->compacted_indices, + (std::uint32_t)num_estimates, + m_render_data->hitcount + ); + + // Advance indices to keep pixel indices up to date + RestorePixelIndices(pass, num_estimates); + + // Shade missing rays + if (pass == 0) + { + if (missedPrimaryRaysHandler) + missedPrimaryRaysHandler( + m_render_data->rays[0], + m_render_data->intersections, + m_render_data->pixelindices[1], + use_output_indices ? m_render_data->output_indices : m_render_data->iota, + num_estimates, output); + else if (scene.envmapidx > -1) + ShadeBackground(scene, 0, num_estimates, output, use_output_indices); + else + AdvanceIterationCount(0, num_estimates, output, use_output_indices); + } + + if (has_some_volume) + { + // Shade hits + ShadeVolume(scene, pass, num_estimates, output, use_output_indices); + } + + // Shade hits + ShadeSurface(scene, pass, num_estimates, output, use_output_indices); + + + if (has_some_volume && GetMaxShadowRayTransmissionSteps() > 0) + { + for (auto i = 0u; i < GetMaxShadowRayTransmissionSteps(); ++i) + { + // Intersect ray batch + GetIntersector()->QueryIntersection(m_render_data->fr_shadowrays, + m_render_data->fr_hitcount, + (std::uint32_t)num_estimates, + m_render_data->fr_intersections, + nullptr, + nullptr); + + ApplyVolumeTransmission(scene, pass, num_estimates, output, use_output_indices); + } + } + + // Intersect shadow rays + GetIntersector()->QueryOcclusion( + m_render_data->fr_shadowrays, + m_render_data->fr_hitcount, + (std::uint32_t)num_estimates, + m_render_data->fr_shadowhits, + nullptr, + nullptr + ); + + // Gather light samples and account for visibility + GatherLightSamples(scene, pass, num_estimates, output, use_output_indices); + + if (pass == 0 && has_visibility_buffer) + { + // Run visibility resolve kernel + GatherVisibility(scene, pass, num_estimates, visibility_buffer, use_output_indices); + } + + GetContext().Flush(0); + } + // Gather opacity if we have opacity buffer + if (has_opacity_buffer) + { + // Convert intersections to predicates + FilterPathStream(GetMaxBounces(), num_estimates); + GatherOpacity(scene, GetMaxBounces(), num_estimates, opacity_buffer, use_output_indices); + GetContext().Flush(0); + } + ++m_sample_counter; + } + + void PathTracingEstimator::InitPathData(std::size_t size, int volume_idx) + { + auto init_kernel = GetKernel("InitPathData"); + + int argc = 0; + init_kernel.SetArg(argc++, m_render_data->pixelindices[0]); + init_kernel.SetArg(argc++, m_render_data->pixelindices[1]); + init_kernel.SetArg(argc++, m_render_data->hitcount); + init_kernel.SetArg(argc++, (cl_int)volume_idx); + init_kernel.SetArg(argc++, m_render_data->paths); + + { + GetContext().Launch1D(0, ((size + 63) / 64) * 64, 64, init_kernel); + } + } + + void PathTracingEstimator::ShadeSurface( + ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ) + { + // Fetch kernel + auto shadekernel = m_uberv2_kernels.GetKernel("ShadeSurfaceUberV2"); + + auto output_indices = use_output_indices ? m_render_data->output_indices : m_render_data->iota; + + // Set kernel parameters + int argc = 0; + shadekernel.SetArg(argc++, m_render_data->rays[pass & 0x1]); + shadekernel.SetArg(argc++, m_render_data->intersections); + shadekernel.SetArg(argc++, m_render_data->compacted_indices); + shadekernel.SetArg(argc++, m_render_data->pixelindices[pass & 0x1]); + shadekernel.SetArg(argc++, output_indices); + shadekernel.SetArg(argc++, m_render_data->hitcount); + shadekernel.SetArg(argc++, scene.vertices); + shadekernel.SetArg(argc++, scene.normals); + shadekernel.SetArg(argc++, scene.uvs); + shadekernel.SetArg(argc++, scene.indices); + shadekernel.SetArg(argc++, scene.shapes); + shadekernel.SetArg(argc++, scene.material_attributes); + shadekernel.SetArg(argc++, scene.textures); + shadekernel.SetArg(argc++, scene.texturedata); + shadekernel.SetArg(argc++, scene.envmapidx); + shadekernel.SetArg(argc++, scene.lights); + shadekernel.SetArg(argc++, scene.light_distributions); + shadekernel.SetArg(argc++, scene.num_lights); + shadekernel.SetArg(argc++, rand_uint()); + shadekernel.SetArg(argc++, m_render_data->random); + shadekernel.SetArg(argc++, m_render_data->sobolmat); + shadekernel.SetArg(argc++, pass); + shadekernel.SetArg(argc++, m_sample_counter); + shadekernel.SetArg(argc++, scene.volumes); + shadekernel.SetArg(argc++, m_render_data->shadowrays); + shadekernel.SetArg(argc++, m_render_data->lightsamples); + shadekernel.SetArg(argc++, m_render_data->paths); + shadekernel.SetArg(argc++, m_render_data->rays[(pass + 1) & 0x1]); + shadekernel.SetArg(argc++, output); + shadekernel.SetArg(argc++, scene.input_map_data); + + // Run shading kernel + { + GetContext().Launch1D(0, ((size + 63) / 64) * 64, 64, shadekernel); + } + } + + void PathTracingEstimator::ShadeVolume( + ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ) + { + // Fetch kernel + auto shadekernel = m_uberv2_kernels.GetKernel("ShadeVolumeUberV2"); + + auto output_indices = use_output_indices ? m_render_data->output_indices : m_render_data->iota; + + // Set kernel parameters + int argc = 0; + shadekernel.SetArg(argc++, m_render_data->rays[pass & 0x1]); + shadekernel.SetArg(argc++, m_render_data->intersections); + shadekernel.SetArg(argc++, m_render_data->compacted_indices); + shadekernel.SetArg(argc++, m_render_data->pixelindices[pass & 0x1]); + shadekernel.SetArg(argc++, output_indices); + shadekernel.SetArg(argc++, m_render_data->hitcount); + shadekernel.SetArg(argc++, scene.vertices); + shadekernel.SetArg(argc++, scene.normals); + shadekernel.SetArg(argc++, scene.uvs); + shadekernel.SetArg(argc++, scene.indices); + shadekernel.SetArg(argc++, scene.shapes); + shadekernel.SetArg(argc++, scene.material_attributes); + shadekernel.SetArg(argc++, scene.textures); + shadekernel.SetArg(argc++, scene.texturedata); + shadekernel.SetArg(argc++, scene.envmapidx); + shadekernel.SetArg(argc++, scene.lights); + shadekernel.SetArg(argc++, scene.light_distributions); + shadekernel.SetArg(argc++, scene.num_lights); + shadekernel.SetArg(argc++, rand_uint()); + shadekernel.SetArg(argc++, m_render_data->random); + shadekernel.SetArg(argc++, m_render_data->sobolmat); + shadekernel.SetArg(argc++, pass); + shadekernel.SetArg(argc++, m_sample_counter); + shadekernel.SetArg(argc++, scene.volumes); + shadekernel.SetArg(argc++, m_render_data->shadowrays); + shadekernel.SetArg(argc++, m_render_data->lightsamples); + shadekernel.SetArg(argc++, m_render_data->paths); + shadekernel.SetArg(argc++, m_render_data->rays[(pass + 1) & 0x1]); + shadekernel.SetArg(argc++, output); + shadekernel.SetArg(argc++, scene.input_map_data); + + // Run shading kernel + { + GetContext().Launch1D(0, ((size + 63) / 64) * 64, 64, shadekernel); + } + } + + void PathTracingEstimator::SampleVolume( + ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ) + { + // Fetch kernel + auto sample_kernel = GetKernel("SampleVolume"); + + auto output_indices = use_output_indices ? m_render_data->output_indices : m_render_data->iota; + + // Set kernel parameters + int argc = 0; + sample_kernel.SetArg(argc++, m_render_data->rays[pass & 0x1]); + sample_kernel.SetArg(argc++, m_render_data->pixelindices[(pass + 1) & 0x1]); + sample_kernel.SetArg(argc++, output_indices); + sample_kernel.SetArg(argc++, m_render_data->hitcount); + sample_kernel.SetArg(argc++, scene.volumes); + sample_kernel.SetArg(argc++, scene.textures); + sample_kernel.SetArg(argc++, scene.texturedata); + sample_kernel.SetArg(argc++, rand_uint()); + sample_kernel.SetArg(argc++, m_render_data->random); + sample_kernel.SetArg(argc++, m_render_data->sobolmat); + sample_kernel.SetArg(argc++, pass); + sample_kernel.SetArg(argc++, m_sample_counter); + sample_kernel.SetArg(argc++, m_render_data->intersections); + sample_kernel.SetArg(argc++, m_render_data->paths); + sample_kernel.SetArg(argc++, output); + + // Run shading kernel + { + GetContext().Launch1D(0, ((size + 63) / 64) * 64, 64, sample_kernel); + } + } + + void PathTracingEstimator::ShadeBackground( + ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ) + { + // Fetch kernel + auto misskernel = GetKernel("ShadeBackgroundEnvMap"); + + auto output_indices = use_output_indices ? m_render_data->output_indices : m_render_data->iota; + + // Set kernel parameters + int argc = 0; + misskernel.SetArg(argc++, m_render_data->rays[pass & 0x1]); + misskernel.SetArg(argc++, m_render_data->intersections); + misskernel.SetArg(argc++, m_render_data->pixelindices[(pass + 1) & 0x1]); + misskernel.SetArg(argc++, output_indices); + misskernel.SetArg(argc++, (cl_int)size); + misskernel.SetArg(argc++, scene.lights); + misskernel.SetArg(argc++, scene.envmapidx); + misskernel.SetArg(argc++, scene.textures); + misskernel.SetArg(argc++, scene.texturedata); + misskernel.SetArg(argc++, m_render_data->paths); + misskernel.SetArg(argc++, scene.volumes); + misskernel.SetArg(argc++, output); + + { + GetContext().Launch1D(0, ((size + 63) / 64) * 64, 64, misskernel); + } + } + + void PathTracingEstimator::GatherLightSamples( + ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ) + { + // Fetch kernel + auto gatherkernel = GetKernel("GatherLightSamples"); + + auto output_indices = use_output_indices ? m_render_data->output_indices : m_render_data->iota; + + // Set kernel parameters + int argc = 0; + gatherkernel.SetArg(argc++, m_render_data->pixelindices[pass & 0x1]); + gatherkernel.SetArg(argc++, output_indices); + gatherkernel.SetArg(argc++, m_render_data->hitcount); + gatherkernel.SetArg(argc++, m_render_data->shadowhits); + gatherkernel.SetArg(argc++, m_render_data->lightsamples); + gatherkernel.SetArg(argc++, m_render_data->paths); + gatherkernel.SetArg(argc++, output); + + // Run shading kernel + { + GetContext().Launch1D(0, ((size + 63) / 64) * 64, 64, gatherkernel); + } + } + + void PathTracingEstimator::ApplyVolumeTransmission( + ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ) + { + // Fetch kernel + auto volumekernel = m_uberv2_kernels.GetKernel("ApplyVolumeTransmissionUberV2"); + + auto output_indices = use_output_indices ? m_render_data->output_indices : m_render_data->iota; + + // Set kernel parameters + int argc = 0; + volumekernel.SetArg(argc++, m_render_data->pixelindices[pass & 0x1]); + volumekernel.SetArg(argc++, output_indices); + volumekernel.SetArg(argc++, m_render_data->shadowrays); + volumekernel.SetArg(argc++, m_render_data->hitcount); + volumekernel.SetArg(argc++, m_render_data->intersections); + volumekernel.SetArg(argc++, m_render_data->paths); + volumekernel.SetArg(argc++, scene.vertices); + volumekernel.SetArg(argc++, scene.normals); + volumekernel.SetArg(argc++, scene.uvs); + volumekernel.SetArg(argc++, scene.indices); + volumekernel.SetArg(argc++, scene.shapes); + volumekernel.SetArg(argc++, scene.material_attributes); + volumekernel.SetArg(argc++, scene.volumes); + volumekernel.SetArg(argc++, m_render_data->lightsamples); + volumekernel.SetArg(argc++, m_render_data->shadowhits); + volumekernel.SetArg(argc++, output); + volumekernel.SetArg(argc++, scene.input_map_data); + + // Run shading kernel + { + GetContext().Launch1D(0, ((size + 63) / 64) * 64, 64, volumekernel); + } + } + + void PathTracingEstimator::GatherVisibility( + ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ) + { + // Fetch kernel + auto gatherkernel = GetKernel("GatherVisibility"); + + auto output_indices = use_output_indices ? m_render_data->output_indices : m_render_data->iota; + + // Set kernel parameters + int argc = 0; + gatherkernel.SetArg(argc++, m_render_data->pixelindices[pass & 0x1]); + gatherkernel.SetArg(argc++, output_indices); + gatherkernel.SetArg(argc++, m_render_data->hitcount); + gatherkernel.SetArg(argc++, m_render_data->shadowhits); + gatherkernel.SetArg(argc++, output); + + // Run shading kernel + { + GetContext().Launch1D(0, ((size + 63) / 64) * 64, 64, gatherkernel); + } + } + + void PathTracingEstimator::GatherOpacity(ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ) + { + // Fetch kernel + auto gatherkernel = GetKernel("GatherOpacity"); + + auto output_indices = use_output_indices ? m_render_data->output_indices : m_render_data->iota; + + // Set kernel parameters + int argc = 0; + gatherkernel.SetArg(argc++, m_render_data->pixelindices[(pass + 1) & 0x1]); + gatherkernel.SetArg(argc++, output_indices); + gatherkernel.SetArg(argc++, m_render_data->hitcount); + gatherkernel.SetArg(argc++, m_render_data->paths); + gatherkernel.SetArg(argc++, (pass == (int)GetMaxBounces())); + gatherkernel.SetArg(argc++, output); + + // Run shading kernel + { + GetContext().Launch1D(0, ((size + 63) / 64) * 64, 64, gatherkernel); + } + } + + void PathTracingEstimator::RestorePixelIndices(int pass, std::size_t size) + { + // Fetch kernel + CLWKernel restorekernel = GetKernel("RestorePixelIndices"); + + // Set kernel parameters + int argc = 0; + restorekernel.SetArg(argc++, m_render_data->compacted_indices); + restorekernel.SetArg(argc++, m_render_data->hitcount); + restorekernel.SetArg(argc++, m_render_data->pixelindices[(pass + 1) & 0x1]); + restorekernel.SetArg(argc++, m_render_data->pixelindices[pass & 0x1]); + + // Run shading kernel + { + GetContext().Launch1D(0, ((size + 63) / 64) * 64, 64, restorekernel); + } + } + + void PathTracingEstimator::FilterPathStream(int pass, std::size_t size) + { + auto restorekernel = GetKernel("FilterPathStream"); + + int argc = 0; + restorekernel.SetArg(argc++, m_render_data->intersections); + restorekernel.SetArg(argc++, m_render_data->hitcount); + restorekernel.SetArg(argc++, m_render_data->pixelindices[(pass + 1) & 0x1]); + restorekernel.SetArg(argc++, m_render_data->paths); + restorekernel.SetArg(argc++, m_render_data->hits); + + { + GetContext().Launch1D(0, ((size + 63) / 64) * 64, 64, restorekernel); + } + } + + void PathTracingEstimator::ShadeMiss( + ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ) + { + auto misskernel = GetKernel("ShadeMiss"); + + auto output_indices = use_output_indices ? m_render_data->output_indices : m_render_data->iota; + + int argc = 0; + misskernel.SetArg(argc++, m_render_data->rays[pass & 0x1]); + misskernel.SetArg(argc++, m_render_data->intersections); + misskernel.SetArg(argc++, m_render_data->pixelindices[(pass + 1) & 0x1]); + misskernel.SetArg(argc++, output_indices); + misskernel.SetArg(argc++, m_render_data->hitcount); + misskernel.SetArg(argc++, scene.lights); + misskernel.SetArg(argc++, scene.light_distributions); + misskernel.SetArg(argc++, scene.num_lights); + misskernel.SetArg(argc++, scene.envmapidx); + misskernel.SetArg(argc++, scene.textures); + misskernel.SetArg(argc++, scene.texturedata); + misskernel.SetArg(argc++, m_render_data->paths); + misskernel.SetArg(argc++, scene.volumes); + misskernel.SetArg(argc++, output); + + { + GetContext().Launch1D(0, ((size + 63) / 64) * 64, 64, misskernel); + } + } + + void PathTracingEstimator::SetRandomSeed(std::uint32_t seed) + { + std::srand(seed); + + auto size = m_render_data->random.GetElementCount(); + + if (size != 0) + { + std::vector random_buffer(size); + std::generate(random_buffer.begin(), random_buffer.end(), []() {return std::rand() + 3; }); + GetContext().WriteBuffer(0, m_render_data->random, random_buffer.data(), size).Wait(); + } + } + + bool PathTracingEstimator::HasRandomBuffer(RandomBufferType buffer) const + { + switch (buffer) + { + case RandomBufferType::kRandomSeed: + case RandomBufferType::kSobolLUT: + return true; + } + + return false; + } + + CLWBuffer PathTracingEstimator::GetRandomBuffer(RandomBufferType buffer) const + { + switch (buffer) + { + case RandomBufferType::kRandomSeed: + return m_render_data->random; + case RandomBufferType::kSobolLUT: + return m_render_data->sobolmat; + } + + return CLWBuffer(); + } + + CLWBuffer PathTracingEstimator::GetFirstHitBuffer() const + { + return m_render_data->intersections; + } + + void PathTracingEstimator::TraceFirstHit( + ClwScene const& scene, + std::size_t num_estimates + ) + { + // Intersect ray batch + GetIntersector()->QueryIntersection( + m_render_data->fr_rays[0], + m_render_data->fr_hitcount, + (std::uint32_t)num_estimates, + m_render_data->fr_intersections, + nullptr, + nullptr + ); + } + + void PathTracingEstimator::Benchmark( + ClwScene const& scene, + std::size_t num_estimates, + RayTracingStats& stats + ) + { + auto temporary = GetContext().CreateBuffer(num_estimates, CL_MEM_WRITE_ONLY); + + auto num_passes = 100u; + // Clear ray hits buffer + GetContext().FillBuffer(0, m_render_data->hits, 0, num_estimates); + + // Intersect ray batch + auto start = std::chrono::high_resolution_clock::now(); + + for (auto i = 0u; i < num_passes; ++i) + { + GetIntersector()->QueryIntersection( + m_render_data->fr_rays[0], + m_render_data->fr_hitcount, + (std::uint32_t)num_estimates, + m_render_data->fr_intersections, + nullptr, + nullptr + ); + } + + GetContext().Finish(0); + + auto delta = std::chrono::high_resolution_clock::now() - start; + + stats.primary_throughput = + num_estimates / (((float)std::chrono::duration_cast(delta).count() + / num_passes) + / 1000.f); + + // Convert intersections to predicates + FilterPathStream(0, num_estimates); + + // Compact batch + m_render_data->pp.Compact( + 0, + m_render_data->hits, + m_render_data->iota, + m_render_data->compacted_indices, + (std::uint32_t)num_estimates, + m_render_data->hitcount); + + // Advance indices to keep pixel indices up to date + RestorePixelIndices(0, num_estimates); + + // Shade hits + ShadeSurface(scene, 0, num_estimates, temporary, false); + + // Shade missing rays + ShadeMiss(scene, 0, num_estimates, temporary, false); + + // Intersect ray batch + start = std::chrono::high_resolution_clock::now(); + + for (auto i = 0U; i < num_passes; ++i) + { + GetIntersector()->QueryOcclusion( + m_render_data->fr_shadowrays, + m_render_data->fr_hitcount, + (std::uint32_t)num_estimates, + m_render_data->fr_shadowhits, + nullptr, + nullptr); + } + + GetContext().Finish(0); + + delta = std::chrono::high_resolution_clock::now() - start; + + stats.shadow_throughput = + num_estimates / (((float)std::chrono::duration_cast(delta).count() + / num_passes) + / 1000.f); + + // Gather light samples and account for visibility + GatherLightSamples(scene, 0, num_estimates, temporary, false); + + // + GetContext().Flush(0); + + // Clear ray hits buffer + GetContext().FillBuffer(0, m_render_data->hits, 0, m_render_data->hits.GetElementCount()); + + // Intersect ray batch + start = std::chrono::high_resolution_clock::now(); + + for (auto i = 0U; i < num_passes; ++i) + { + GetIntersector()->QueryIntersection( + m_render_data->fr_rays[1], + m_render_data->fr_hitcount, + (std::uint32_t)num_estimates, + m_render_data->fr_intersections, + nullptr, + nullptr + ); + } + + GetContext().Finish(0); + + delta = std::chrono::high_resolution_clock::now() - start; + + stats.secondary_throughput = + num_estimates / (((float)std::chrono::duration_cast(delta).count() + / num_passes) + / 1000.f); + } + + bool PathTracingEstimator::SupportsIntermediateValue(IntermediateValue value) const + { + if (value == IntermediateValue::kVisibility || value == IntermediateValue::kOpacity) + { + return true; + } + else + { + return false; + } + } + + void PathTracingEstimator::AdvanceIterationCount( + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices) + { + auto misskernel = GetKernel("AdvanceIterationCount"); + + auto output_indices = use_output_indices ? m_render_data->output_indices : m_render_data->iota; + + int argc = 0; + misskernel.SetArg(argc++, m_render_data->pixelindices[(pass + 1) & 0x1]); + misskernel.SetArg(argc++, output_indices); + misskernel.SetArg(argc++, (cl_int)size); + misskernel.SetArg(argc++, output); + + { + GetContext().Launch1D(0, ((size + 63) / 64) * 64, 64, misskernel); + } + } +} diff --git a/Baikal/Estimators/path_tracing_estimator.h b/Baikal/Estimators/path_tracing_estimator.h new file mode 100644 index 00000000..ec73e252 --- /dev/null +++ b/Baikal/Estimators/path_tracing_estimator.h @@ -0,0 +1,278 @@ +#pragma once +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once + +#include "estimator.h" +#include "radeon_rays_cl.h" +#include "Utils/cl_program_manager.h" + +#include + +namespace Baikal +{ + /** + \brief Estimator calculates radiance estimates for a given set of directions in the scene. + + Given a ray buffer and an output buffer, estimator calculates single sample estimate of an + incoming radiance and adds it into an output buffer. + */ + class PathTracingEstimator : public Estimator, protected ClwClass + { + public: + PathTracingEstimator( + CLWContext context, + std::shared_ptr api, + const CLProgramManager *program_manager + ); + + ~PathTracingEstimator() override; + + /** + \brief Tells estimator about memory requirements (max number of entries in ray buffer). + + Estimators allocate internal buffers to store rays and output index mappings. Clients + set the size of internal buffers and then query them and fill them up with the data. + */ + void SetWorkBufferSize(std::size_t size) override; + + /** + \brief Returns internal ray buffer size in elements. + */ + std::size_t GetWorkBufferSize() const override; + + /** + \brief Set random seed value for the estimator. Renders + with the same random seed are guaranteed to be the same. + + \param seed Seed value + */ + void SetRandomSeed(std::uint32_t seed) override; + + /** + \brief Get ray buffer handle. + + Clients generate ray workload directly into internal memory of an estimator to + save memory bandwidth. This method allows to get CLW handle of a buffer and fill it up + on the client side. + + IMPORTANT: SetWorkBufferSize should be called prior to calling this method. + Returned buffer size is exacly the size set via SetWorkBufferSize. + */ + CLWBuffer GetRayBuffer() const override; + + /** + \brief Get output index buffer handle. + + Clients generate ray workload directly into internal memory of an estimator to + save memory bandwidth. This method allows to get CLW handle of a buffer and fill it up + on the client side. Output index establishes ray index -> output index mapping. + Output data for ray index i is scattered into output[output_index[i]]. + + IMPORTANT: SetWorkBufferSize should be called prior to calling this method. + Returned buffer size is exacly the size set via SetWorkBufferSize. + */ + CLWBuffer GetOutputIndexBuffer() const override; + + /** + \brief Get ray count buffer handle. + + This buffer is used by the clients to tell how many rays are in ray buffer. + This is GPU buffer, which helps to avoid unnecessary CPU->GPU copies. + + IMPORTANT: SetWorkBufferSize should be called prior to calling this method. + */ + CLWBuffer GetRayCountBuffer() const override; + + /** + \brief Returns first hit buffer + + IMPORTANT: SetWorkBufferSize should be called prior to calling this method. + Returned buffer size is exacly the size set via SetWorkBufferSize. + */ + CLWBuffer GetFirstHitBuffer() const override; + + /** + \brief Evaluate single sample radiance estimate for a given direction. + + Estimators usually utilize some internal structures where the size depends on input ray + buffer size. This method allows an estimator to pre-allocate internal structures upfront. + + \param scene Scene description. + \param rays Ray buffer to estimate radiance for. + \param indices Rays to output indices correspondence. + \param quality Quality of the estimate. + \param output Output buffer. + \param atomic_update Tells an estimator that indices might contain duplicate elements and + hence atomic update is required while updating output buffer. + */ + void Estimate( + ClwScene const& scene, + std::size_t num_estimates, + QualityLevel quality, + CLWBuffer output, + bool use_output_indices = true, + bool atomic_update = false, + MissedPrimaryRaysHandler missedPrimaryRaysHandler = nullptr + ) override; + + /** + \brief Find intersection points for the rays in ray buffer. + + Intersection are calculated and written to intersection buffer. + + \param scene Scene description. + \param num_estimates Number of items in ray buffer. + */ + void TraceFirstHit( + ClwScene const& scene, + std::size_t num_estimates + ) override; + + /** + \brief Run internal ray tracing benchmark. + + Intersection are calculated and written to intersection buffer. + + \param scene Scene description. + \param num_estimates Number of items in ray buffer. + */ + void Benchmark( + ClwScene const& scene, + std::size_t num_estimates, + RayTracingStats& stats + ) override; + + /** + \brief General buffer access function (hack to avoid vidmem duplication). + + IMPORTANT: SetWorkBufferSize should be called prior to calling this method. + Returned buffer size is exacly the size set via SetWorkBufferSize. + */ + bool HasRandomBuffer(RandomBufferType buffer) const override; + + /** + \brief General buffer access function (hack to avoid vidmem duplication). + + IMPORTANT: SetWorkBufferSize should be called prior to calling this method. + Returned buffer size is exacly the size set via SetWorkBufferSize. + */ + CLWBuffer GetRandomBuffer(RandomBufferType buffer) const override; + + /** + \brief Check if an estimator supports intermediate value. + + Estimators can support output of various intermidate quantities. + */ + bool SupportsIntermediateValue(IntermediateValue value) const override; + + private: + void InitPathData(std::size_t size, int volume_idx); + + void ShadeSurface( + ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ); + + void SampleVolume( + ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ); + + void ShadeMiss( + ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ); + + void GatherLightSamples( + ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ); + + void GatherVisibility( + ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ); + + void GatherOpacity(ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ); + + void ShadeVolume( + ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ); + + void ShadeBackground( + ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ); + + void ApplyVolumeTransmission( + ClwScene const& scene, + int pass, + std::size_t size, + CLWBuffer output, + bool use_output_indices + ); + + + void AdvanceIterationCount(int pass, std::size_t size, CLWBuffer output, bool use_output_indices); + + // Restore pixel indices after compaction + void RestorePixelIndices(int pass, std::size_t size); + + // Convert intersection info to compaction predicate + void FilterPathStream(int pass, std::size_t size); + + struct PathState; + struct RenderData; + + std::unique_ptr m_render_data; + mutable std::uint32_t m_sample_counter; + ClwClass m_uberv2_kernels; + }; +} diff --git a/Baikal/ImGUI/imconfig.h b/Baikal/ImGUI/imconfig.h deleted file mode 100644 index 2a956d37..00000000 --- a/Baikal/ImGUI/imconfig.h +++ /dev/null @@ -1,54 +0,0 @@ -//----------------------------------------------------------------------------- -// USER IMPLEMENTATION -// This file contains compile-time options for ImGui. -// Other options (memory allocation overrides, callbacks, etc.) can be set at runtime via the ImGuiIO structure - ImGui::GetIO(). -//----------------------------------------------------------------------------- - -#pragma once - -//---- Define assertion handler. Defaults to calling assert(). -//#define IM_ASSERT(_EXPR) MyAssert(_EXPR) - -//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows. -//#define IMGUI_API __declspec( dllexport ) -//#define IMGUI_API __declspec( dllimport ) - -//---- Include imgui_user.h at the end of imgui.h -//#define IMGUI_INCLUDE_IMGUI_USER_H - -//---- Don't implement default handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions) -//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS -//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS - -//---- Don't implement help and test window functionality (ShowUserGuide()/ShowStyleEditor()/ShowTestWindow() methods will be empty) -//#define IMGUI_DISABLE_TEST_WINDOWS - -//---- Don't define obsolete functions names -//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS - -//---- Pack colors to BGRA instead of RGBA (remove need to post process vertex buffer in back ends) -//#define IMGUI_USE_BGRA_PACKED_COLOR - -//---- Implement STB libraries in a namespace to avoid conflicts -//#define IMGUI_STB_NAMESPACE ImGuiStb - -//---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4. -/* -#define IM_VEC2_CLASS_EXTRA \ - ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ - operator MyVec2() const { return MyVec2(x,y); } - -#define IM_VEC4_CLASS_EXTRA \ - ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ - operator MyVec4() const { return MyVec4(x,y,z,w); } -*/ - -//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. -//---- e.g. create variants of the ImGui::Value() helper for your low-level math types, or your own widgets/helpers. -/* -namespace ImGui -{ - void Value(const char* prefix, const MyMatrix44& v, const char* float_format = NULL); -} -*/ - diff --git a/Baikal/ImGUI/imgui.cpp b/Baikal/ImGUI/imgui.cpp deleted file mode 100644 index ff4617ba..00000000 --- a/Baikal/ImGUI/imgui.cpp +++ /dev/null @@ -1,9857 +0,0 @@ -// dear imgui, v1.50 WIP -// (main code and documentation) - -// See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code. -// Newcomers, read 'Programmer guide' below for notes on how to setup ImGui in your codebase. -// Get latest version at https://github.com/ocornut/imgui -// Releases change-log at https://github.com/ocornut/imgui/releases -// Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/772 -// Developed by Omar Cornut and every direct or indirect contributors to the GitHub. -// This library is free but I need your support to sustain development and maintenance. -// If you work for a company, please consider financial support, e.g: https://www.patreon.com/imgui - -/* - - Index - - MISSION STATEMENT - - END-USER GUIDE - - PROGRAMMER GUIDE (read me!) - - API BREAKING CHANGES (read me when you update!) - - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS - - How can I help? - - How do I update to a newer version of ImGui? - - What is ImTextureID and how do I display an image? - - I integrated ImGui in my engine and the text or lines are blurry.. - - I integrated ImGui in my engine and some elements are clipping or disappearing when I move windows around.. - - How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs. - - How can I tell when ImGui wants my mouse/keyboard inputs and when I can pass them to my application? - - How can I load a different font than the default? - - How can I easily use icons in my application? - - How can I load multiple fonts? - - How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic? - - How can I use the drawing facilities without an ImGui window? (using ImDrawList API) - - ISSUES & TODO-LIST - - CODE - - - MISSION STATEMENT - ================= - - - easy to use to create code-driven and data-driven tools - - easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools - - easy to hack and improve - - minimize screen real-estate usage - - minimize setup and maintenance - - minimize state storage on user side - - portable, minimize dependencies, run on target (consoles, phones, etc.) - - efficient runtime (NB- we do allocate when "growing" content - creating a window / opening a tree node for the first time, etc. - but a typical frame won't allocate anything) - - read about immediate-mode gui principles @ http://mollyrocket.com/861, http://mollyrocket.com/forums/index.html - - Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes: - - doesn't look fancy, doesn't animate - - limited layout features, intricate layouts are typically crafted in code - - occasionally uses statically sized buffers for string manipulations - won't crash, but some very long pieces of text may be clipped. functions like ImGui::TextUnformatted() don't have such restriction. - - - END-USER GUIDE - ============== - - - double-click title bar to collapse window - - click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin() - - click and drag on lower right corner to resize window - - click and drag on any empty space to move window - - double-click/double-tap on lower right corner grip to auto-fit to content - - TAB/SHIFT+TAB to cycle through keyboard editable fields - - use mouse wheel to scroll - - use CTRL+mouse wheel to zoom window contents (if IO.FontAllowScaling is true) - - CTRL+Click on a slider or drag box to input value as text - - text editor: - - Hold SHIFT or use mouse to select text. - - CTRL+Left/Right to word jump - - CTRL+Shift+Left/Right to select words - - CTRL+A our Double-Click to select all - - CTRL+X,CTRL+C,CTRL+V to use OS clipboard - - CTRL+Z,CTRL+Y to undo/redo - - ESCAPE to revert text to its original value - - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!) - - - PROGRAMMER GUIDE - ================ - - - read the FAQ below this section! - - your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention on your side, no state duplication, less sync, less bugs. - - call and read ImGui::ShowTestWindow() for demo code demonstrating most features. - - see examples/ folder for standalone sample applications. Prefer reading examples/opengl2_example/ first as it is the simplest. - you may be able to grab and copy a ready made imgui_impl_*** file from the examples/. - - customization: PushStyleColor()/PushStyleVar() or the style editor to tweak the look of the interface (e.g. if you want a more compact UI or a different color scheme). - - - getting started: - - init: call ImGui::GetIO() to retrieve the ImGuiIO structure and fill the fields marked 'Settings'. - - init: call io.Fonts->GetTexDataAsRGBA32(...) and load the font texture pixels into graphics memory. - - every frame: - 1/ in your mainloop or right after you got your keyboard/mouse info, call ImGui::GetIO() and fill the fields marked 'Input' - 2/ call ImGui::NewFrame() as early as you can! - 3/ use any ImGui function you want between NewFrame() and Render() - 4/ call ImGui::Render() as late as you can to end the frame and finalize render data. it will call your RenderDrawListFn handler that you set in the IO structure. - (if you don't need to render, you still need to call Render() and ignore the callback, or call EndFrame() instead. if you call neither some aspects of windows focusing/moving will appear broken.) - - all rendering information are stored into command-lists until ImGui::Render() is called. - - ImGui never touches or know about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you provide. - - effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases of your own application. - - refer to the examples applications in the examples/ folder for instruction on how to setup your code. - - a typical application skeleton may be: - - // Application init - ImGuiIO& io = ImGui::GetIO(); - io.DisplaySize.x = 1920.0f; - io.DisplaySize.y = 1280.0f; - io.IniFilename = "imgui.ini"; - io.RenderDrawListsFn = my_render_function; // Setup a render function, or set to NULL and call GetDrawData() after Render() to access the render data. - // TODO: Fill others settings of the io structure - - // Load texture atlas - // There is a default font so you don't need to care about choosing a font yet - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(pixels, &width, &height); - // TODO: At this points you've got a texture pointed to by 'pixels' and you need to upload that your your graphic system - // TODO: Store your texture pointer/identifier (whatever your engine uses) in 'io.Fonts->TexID' - - // Application main loop - while (true) - { - // 1) get low-level inputs (e.g. on Win32, GetKeyboardState(), or poll your events, etc.) - // TODO: fill all fields of IO structure and call NewFrame - ImGuiIO& io = ImGui::GetIO(); - io.DeltaTime = 1.0f/60.0f; - io.MousePos = mouse_pos; - io.MouseDown[0] = mouse_button_0; - io.MouseDown[1] = mouse_button_1; - io.KeysDown[i] = ... - - // 2) call NewFrame(), after this point you can use ImGui::* functions anytime - ImGui::NewFrame(); - - // 3) most of your application code here - MyGameUpdate(); // may use any ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End(); - MyGameRender(); // may use any ImGui functions - - // 4) render & swap video buffers - ImGui::Render(); - SwapBuffers(); - } - - - You can read back 'io.WantCaptureMouse', 'io.WantCaptureKeybord' etc. flags from the IO structure to tell how ImGui intends to use your - inputs and to know if you should share them or hide them from the rest of your application. Read the FAQ below for more information. - - - API BREAKING CHANGES - ==================== - - Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix. - Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. - Also read releases logs https://github.com/ocornut/imgui/releases for more details. - - - 2016/11/06 (1.50) - BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple times to a same child from different locations of the stack id. If that's the case, generate an id with GetId() and use it instead of passing string to BeginChild(). - - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass io.ClipboardUserData to it. - - 2016/09/25 (1.50) - style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc. - - 2016/07/30 (1.50) - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully breakage should be minimal. - - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore. - If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you. - However if your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar. - This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color. - ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col) - { - float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a; - return ImVec4((win_bg_col.x * win_bg_col.w + title_bg_col.x) * k, (win_bg_col.y * win_bg_col.w + title_bg_col.y) * k, (win_bg_col.z * win_bg_col.w + title_bg_col.z) * k, new_a); - } - If this is confusing, pick the RGB value from title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color. - - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext(). - - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection. - - 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the "default_open = true" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen). - - 2016/04/26 (1.49) - changed ImDrawList::PushClipRect(ImVec4 rect) to ImDraw::PushClipRect(Imvec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false). Note that higher-level ImGui::PushClipRect() is preferable because it will clip at logic/widget level, whereas ImDrawList::PushClipRect() only affect your renderer. - - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337). - - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337) - - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete). - - 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert. - - 2016/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. if you had manual pixel-perfect alignment in place it might affect you. - - 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis. - - 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete. - - 2015/08/29 (1.45) - with the addition of horizontal scrollbar we made various fixes to inconsistencies with dealing with cursor position. - GetCursorPos()/SetCursorPos() functions now include the scrolled amount. It shouldn't affect the majority of users, but take note that SetCursorPosX(100.0f) puts you at +100 from the starting x position which may include scrolling, not at +100 from the window left side. - GetContentRegionMax()/GetWindowContentRegionMin()/GetWindowContentRegionMax() functions allow include the scrolled amount. Typically those were used in cases where no scrolling would happen so it may not be a problem, but watch out! - - 2015/08/29 (1.45) - renamed style.ScrollbarWidth to style.ScrollbarSize - - 2015/08/05 (1.44) - split imgui.cpp into extra files: imgui_demo.cpp imgui_draw.cpp imgui_internal.h that you need to add to your project. - - 2015/07/18 (1.44) - fixed angles in ImDrawList::PathArcTo(), PathArcToFast() (introduced in 1.43) being off by an extra PI for no justifiable reason - - 2015/07/14 (1.43) - add new ImFontAtlas::AddFont() API. For the old AddFont***, moved the 'font_no' parameter of ImFontAtlas::AddFont** functions to the ImFontConfig structure. - you need to render your textured triangles with bilinear filtering to benefit from sub-pixel positioning of text. - - 2015/07/08 (1.43) - switched rendering data to use indexed rendering. this is saving a fair amount of CPU/GPU and enables us to get anti-aliasing for a marginal cost. - this necessary change will break your rendering function! the fix should be very easy. sorry for that :( - - if you are using a vanilla copy of one of the imgui_impl_XXXX.cpp provided in the example, you just need to update your copy and you can ignore the rest. - - the signature of the io.RenderDrawListsFn handler has changed! - ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count) - became: - ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data). - argument 'cmd_lists' -> 'draw_data->CmdLists' - argument 'cmd_lists_count' -> 'draw_data->CmdListsCount' - ImDrawList 'commands' -> 'CmdBuffer' - ImDrawList 'vtx_buffer' -> 'VtxBuffer' - ImDrawList n/a -> 'IdxBuffer' (new) - ImDrawCmd 'vtx_count' -> 'ElemCount' - ImDrawCmd 'clip_rect' -> 'ClipRect' - ImDrawCmd 'user_callback' -> 'UserCallback' - ImDrawCmd 'texture_id' -> 'TextureId' - - each ImDrawList now contains both a vertex buffer and an index buffer. For each command, render ElemCount/3 triangles using indices from the index buffer. - - if you REALLY cannot render indexed primitives, you can call the draw_data->DeIndexAllBuffers() method to de-index the buffers. This is slow and a waste of CPU/GPU. Prefer using indexed rendering! - - refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. please upgrade! - - 2015/07/10 (1.43) - changed SameLine() parameters from int to float. - - 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete). - - 2015/07/02 (1.42) - renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion along with other scrolling functions, because positions (e.g. cursor position) are not equivalent to scrolling amount. - - 2015/06/14 (1.41) - changed ImageButton() default bg_col parameter from (0,0,0,1) (black) to (0,0,0,0) (transparent) - makes a difference when texture have transparence - - 2015/06/14 (1.41) - changed Selectable() API from (label, selected, size) to (label, selected, flags, size). Size override should have been rarely be used. Sorry! - - 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will obsolete). - - 2015/05/31 (1.40) - renamed IsRectClipped() to IsRectVisible() for consistency. Note that return value is opposite! Kept inline redirection function (will obsolete). - - 2015/05/27 (1.40) - removed the third 'repeat_if_held' parameter from Button() - sorry! it was rarely used and inconsistent. Use PushButtonRepeat(true) / PopButtonRepeat() to enable repeat on desired buttons. - - 2015/05/11 (1.40) - changed BeginPopup() API, takes a string identifier instead of a bool. ImGui needs to manage the open/closed state of popups. Call OpenPopup() to actually set the "open" state of a popup. BeginPopup() returns true if the popup is opened. - - 2015/05/03 (1.40) - removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same). - - 2015/04/13 (1.38) - renamed IsClipped() to IsRectClipped(). Kept inline redirection function until 1.50. - - 2015/04/09 (1.38) - renamed ImDrawList::AddArc() to ImDrawList::AddArcFast() for compatibility with future API - - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive. - - 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or Inputfloat() instead. - - 2015/03/17 (1.36) - renamed GetItemBoxMin()/GetItemBoxMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function until 1.50. - - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing - - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function until 1.50. - - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth (casing) - - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function until 1.50. - - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once. - - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now. - - 2015/02/10 (1.32) - renamed GetItemWidth() to CalcItemWidth() to clarify its evolving behavior - - 2015/02/08 (1.31) - renamed GetTextLineSpacing() to GetTextLineHeightWithSpacing() - - 2015/02/01 (1.31) - removed IO.MemReallocFn (unused) - - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions. - - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader. - (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels. - this sequence: - const void* png_data; - unsigned int png_size; - ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); - // - became: - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - // - io.Fonts->TexID = (your_texture_identifier); - you now have much more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs. - it is now recommended that you sample the font texture with bilinear interpolation. - (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID. - (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix) - (1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets - - 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, ImGuiSetCondition_FirstUseEver) - - 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, FontFallbackGlyph) - - 2014/11/26 (1.17) - reworked syntax of IMGUI_ONCE_UPON_A_FRAME helper macro to increase compiler compatibility - - 2014/11/07 (1.15) - renamed IsHovered() to IsItemHovered() - - 2014/10/02 (1.14) - renamed IMGUI_INCLUDE_IMGUI_USER_CPP to IMGUI_INCLUDE_IMGUI_USER_INL and imgui_user.cpp to imgui_user.inl (more IDE friendly) - - 2014/09/25 (1.13) - removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for simplicity) - - 2014/09/24 (1.12) - renamed SetFontScale() to SetWindowFontScale() - - 2014/09/24 (1.12) - moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn - - 2014/08/30 (1.09) - removed IO.FontHeight (now computed automatically) - - 2014/08/30 (1.09) - moved IMGUI_FONT_TEX_UV_FOR_WHITE preprocessor define to IO.FontTexUvForWhite - - 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes - - - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS - ====================================== - - Q: How can I help? - A: - If you are experienced enough with ImGui and with C/C++, look at the todo list and see how you want/can help! - - Become a Patron/donate. Convince your company to become a Patron or provide serious funding for development time. - - Q: How do I update to a newer version of ImGui? - A: Overwrite the following files: - imgui.cpp - imgui.h - imgui_demo.cpp - imgui_draw.cpp - imgui_internal.h - stb_rect_pack.h - stb_textedit.h - stb_truetype.h - Don't overwrite imconfig.h if you have made modification to your copy. - Check the "API BREAKING CHANGES" sections for a list of occasional API breaking changes. If you have a problem with a function, search for its name - in the code, there will likely be a comment about it. Please report any issue to the GitHub page! - - Q: What is ImTextureID and how do I display an image? - A: ImTextureID is a void* used to pass renderer-agnostic texture references around until it hits your render function. - ImGui knows nothing about what those bits represent, it just passes them around. It is up to you to decide what you want the void* to carry! - It could be an identifier to your OpenGL texture (cast GLuint to void*), a pointer to your custom engine material (cast MyMaterial* to void*), etc. - At the end of the chain, your renderer takes this void* to cast it back into whatever it needs to select a current texture to render. - Refer to examples applications, where each renderer (in a imgui_impl_xxxx.cpp file) is treating ImTextureID as a different thing. - (c++ tip: OpenGL uses integers to identify textures. You can safely store an integer into a void*, just cast it to void*, don't take it's address!) - To display a custom image/texture within an ImGui window, you may use ImGui::Image(), ImGui::ImageButton(), ImDrawList::AddImage() functions. - ImGui will generate the geometry and draw calls using the ImTextureID that you passed and which your renderer can use. - It is your responsibility to get textures uploaded to your GPU. - - Q: I integrated ImGui in my engine and the text or lines are blurry.. - A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f). - Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension. - - Q: I integrated ImGui in my engine and some elements are clipping or disappearing when I move windows around.. - A: Most likely you are mishandling the clipping rectangles in your render function. Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height). - - Q: Can I have multiple widgets with the same label? Can I have widget without a label? (Yes) - A: Yes. A primer on the use of labels/IDs in ImGui.. - - - Elements that are not clickable, such as Text() items don't need an ID. - - - Interactive widgets require state to be carried over multiple frames (most typically ImGui often needs to remember what is the "active" widget). - to do so they need a unique ID. unique ID are typically derived from a string label, an integer index or a pointer. - - Button("OK"); // Label = "OK", ID = hash of "OK" - Button("Cancel"); // Label = "Cancel", ID = hash of "Cancel" - - - ID are uniquely scoped within windows, tree nodes, etc. so no conflict can happen if you have two buttons called "OK" in two different windows - or in two different locations of a tree. - - - If you have a same ID twice in the same location, you'll have a conflict: - - Button("OK"); - Button("OK"); // ID collision! Both buttons will be treated as the same. - - Fear not! this is easy to solve and there are many ways to solve it! - - - When passing a label you can optionally specify extra unique ID information within string itself. This helps solving the simpler collision cases. - use "##" to pass a complement to the ID that won't be visible to the end-user: - - Button("Play"); // Label = "Play", ID = hash of "Play" - Button("Play##foo1"); // Label = "Play", ID = hash of "Play##foo1" (different from above) - Button("Play##foo2"); // Label = "Play", ID = hash of "Play##foo2" (different from above) - - - If you want to completely hide the label, but still need an ID: - - Checkbox("##On", &b); // Label = "", ID = hash of "##On" (no label!) - - - Occasionally/rarely you might want change a label while preserving a constant ID. This allows you to animate labels. - For example you may want to include varying information in a window title bar (and windows are uniquely identified by their ID.. obviously) - Use "###" to pass a label that isn't part of ID: - - Button("Hello###ID"; // Label = "Hello", ID = hash of "ID" - Button("World###ID"; // Label = "World", ID = hash of "ID" (same as above) - - sprintf(buf, "My game (%f FPS)###MyGame"); - Begin(buf); // Variable label, ID = hash of "MyGame" - - - Use PushID() / PopID() to create scopes and avoid ID conflicts within the same Window. - This is the most convenient way of distinguishing ID if you are iterating and creating many UI elements. - You can push a pointer, a string or an integer value. Remember that ID are formed from the concatenation of everything in the ID stack! - - for (int i = 0; i < 100; i++) - { - PushID(i); - Button("Click"); // Label = "Click", ID = hash of integer + "label" (unique) - PopID(); - } - - for (int i = 0; i < 100; i++) - { - MyObject* obj = Objects[i]; - PushID(obj); - Button("Click"); // Label = "Click", ID = hash of pointer + "label" (unique) - PopID(); - } - - for (int i = 0; i < 100; i++) - { - MyObject* obj = Objects[i]; - PushID(obj->Name); - Button("Click"); // Label = "Click", ID = hash of string + "label" (unique) - PopID(); - } - - - More example showing that you can stack multiple prefixes into the ID stack: - - Button("Click"); // Label = "Click", ID = hash of "Click" - PushID("node"); - Button("Click"); // Label = "Click", ID = hash of "node" + "Click" - PushID(my_ptr); - Button("Click"); // Label = "Click", ID = hash of "node" + ptr + "Click" - PopID(); - PopID(); - - - Tree nodes implicitly creates a scope for you by calling PushID(). - - Button("Click"); // Label = "Click", ID = hash of "Click" - if (TreeNode("node")) - { - Button("Click"); // Label = "Click", ID = hash of "node" + "Click" - TreePop(); - } - - - When working with trees, ID are used to preserve the open/close state of each tree node. - Depending on your use cases you may want to use strings, indices or pointers as ID. - e.g. when displaying a single object that may change over time (1-1 relationship), using a static string as ID will preserve your node open/closed state when the targeted object change. - e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. experiment and see what makes more sense! - - Q: How can I tell when ImGui wants my mouse/keyboard inputs and when I can pass them to my application? - A: You can read the 'io.WantCaptureXXX' flags in the ImGuiIO structure. Preferably read them after calling ImGui::NewFrame() to avoid those flags lagging by one frame, but either should be fine. - When 'io.WantCaptureMouse' or 'io.WantCaptureKeyboard' flags are set you may want to discard/hide the inputs from the rest of your application. - When 'io.WantInputsCharacters' is set to may want to notify your OS to popup an on-screen keyboard, if available. - ImGui is tracking dragging and widget activity that may occur outside the boundary of a window, so 'io.WantCaptureMouse' is a more accurate and complete than testing for ImGui::IsMouseHoveringAnyWindow(). - (Advanced note: text input releases focus on Return 'KeyDown', so the following Return 'KeyUp' event that your application receive will typically have 'io.WantcaptureKeyboard=false'. - Depending on your application logic it may or not be inconvenient. You might want to track which key-downs were for ImGui (e.g. with an array of bool) and filter out the corresponding key-ups.) - - Q: How can I load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13) - A: Use the font atlas to load the TTF file you want: - - ImGuiIO& io = ImGui::GetIO(); - io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels); - io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() - - Q: How can I easily use icons in my application? - A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you main font. Then you can refer to icons within your strings. - Read 'How can I load multiple fonts?' and the file 'extra_fonts/README.txt' for instructions. - - Q: How can I load multiple fonts? - A: Use the font atlas to pack them into a single texture: - (Read extra_fonts/README.txt and the code in ImFontAtlas for more details.) - - ImGuiIO& io = ImGui::GetIO(); - ImFont* font0 = io.Fonts->AddFontDefault(); - ImFont* font1 = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels); - ImFont* font2 = io.Fonts->AddFontFromFileTTF("myfontfile2.ttf", size_in_pixels); - io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() - // the first loaded font gets used by default - // use ImGui::PushFont()/ImGui::PopFont() to change the font at runtime - - // Options - ImFontConfig config; - config.OversampleH = 3; - config.OversampleV = 1; - config.GlyphExtraSpacing.x = 1.0f; - io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, &config); - - // Combine multiple fonts into one (e.g. for icon fonts) - ImWchar ranges[] = { 0xf000, 0xf3ff, 0 }; - ImFontConfig config; - config.MergeMode = true; - io.Fonts->AddFontDefault(); - io.Fonts->LoadFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); // Merge icon font - io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs - - Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic? - A: When loading a font, pass custom Unicode ranges to specify the glyphs to load. - All your strings needs to use UTF-8 encoding. Specifying literal in your source code using a local code page (such as CP-923 for Japanese or CP-1251 for Cyrillic) will not work. - In C++11 you can encode a string literal in UTF-8 by using the u8"hello" syntax. Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. - You can also try to remap your local codepage characters to their Unicode codepoint using font->AddRemapChar(), but international users may have problems reading/editing your source code. - - io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese()); // Load Japanese characters - io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() - io.ImeWindowHandle = MY_HWND; // To input using Microsoft IME, give ImGui the hwnd of your application - - As for text input, depends on you passing the right character code to io.AddInputCharacter(). The example applications do that. - - Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API) - A: The easiest way is to create a dummy window. Call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flag, zero background alpha, - then retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like. - - - tip: the construct 'IMGUI_ONCE_UPON_A_FRAME { ... }' will run the block of code only once a frame. You can use it to quickly add custom UI in the middle of a deep nested inner loop in your code. - - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug" - - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window. this is also useful to set yourself in the context of another window (to get/set other settings) - - tip: you can call Render() multiple times (e.g for VR renders). - - tip: call and read the ShowTestWindow() code in imgui_demo.cpp for more example of how to use ImGui! - - - ISSUES & TODO-LIST - ================== - Issue numbers (#) refer to github issues listed at https://github.com/ocornut/imgui/issues - The list below consist mostly of ideas noted down before they are requested/discussed by users (at which point it usually moves to the github) - - - doc: add a proper documentation+regression testing system (#435) - - window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list. perhaps a lightweight explicit cleanup pass. - - window: calling SetNextWindowSize() every frame with <= 0 doesn't do anything, may be useful to allow (particularly when used for a single axis) (#690) - - window: auto-fit feedback loop when user relies on any dynamic layout (window width multiplier, column) appears weird to end-user. clarify. - - window: allow resizing of child windows (possibly given min/max for each axis?) - - window: background options for child windows, border option (disable rounding) - - window: add a way to clear an existing window instead of appending (e.g. for tooltip override using a consistent api rather than the deferred tooltip) - - window: resizing from any sides? + mouse cursor directives for app. -!- window: begin with *p_open == false should return false. - - window: get size/pos helpers given names (see discussion in #249) - - window: a collapsed window can be stuck behind the main menu bar? - - window: when window is small, prioritize resize button over close button. - - window: detect extra End() call that pop the "Debug" window out and assert at call site instead of later. - - window/tooltip: allow to set the width of a tooltip to allow TextWrapped() etc. while keeping the height automatic. - - window: increase minimum size of a window with menus or fix the menu rendering so that it doesn't look odd. - - draw-list: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command). -!- scrolling: allow immediately effective change of scroll if we haven't appended items yet - - splitter/separator: formalize the splitter idiom into an official api (we want to handle n-way split) (#319) - - widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc. - - widgets: clean up widgets internal toward exposing everything. - - widgets: add disabled and read-only modes (#211) - - main: considering adding an Init() function? some constructs are awkward in the implementation because of the lack of them. -!- main: make it so that a frame with no window registered won't refocus every window on subsequent frames (~bump LastFrameActive of all windows). - - main: IsItemHovered() make it more consistent for various type of widgets, widgets with multiple components, etc. also effectively IsHovered() region sometimes differs from hot region, e.g tree nodes - - main: IsItemHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of the TreeNode? - - input text: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now and super fragile. - - input text: reorganize event handling, allow CharFilter to modify buffers, allow multiple events? (#541) - - input text: expose CursorPos in char filter event (#816) - - input text: flag to disable live update of the user buffer (also applies to float/int text input) - - input text: resize behavior - field could stretch when being edited? hover tooltip shows more text? - - input text: add ImGuiInputTextFlags_EnterToApply? (off #218) - - input text: add discard flag (e.g. ImGuiInputTextFlags_DiscardActiveBuffer) or make it easier to clear active focus for text replacement during edition (#725) - - input text multi-line: don't directly call AddText() which does an unnecessary vertex reserve for character count prior to clipping. and/or more line-based clipping to AddText(). and/or reorganize TextUnformatted/RenderText for more efficiency for large text (e.g TextUnformatted could clip and log separately, etc). - - input text multi-line: way to dynamically grow the buffer without forcing the user to initially allocate for worse case (follow up on #200) - - input text multi-line: line numbers? status bar? (follow up on #200) - - input text multi-line: behave better when user changes input buffer while editing is active (even though it is illegal behavior). namely, the change of buffer can create a scrollbar glitch (#725) - - input text: allow centering/positioning text so that ctrl+clicking Drag or Slider keeps the textual value at the same pixel position. - - input number: optional range min/max for Input*() functions - - input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled) - - input number: use mouse wheel to step up/down - - input number: applying arithmetics ops (+,-,*,/) messes up with text edit undo stack. - - button: provide a button that looks framed. - - text: proper alignment options - - image/image button: misalignment on padded/bordered button? - - image/image button: parameters are confusing, image() has tint_col,border_col whereas imagebutton() has bg_col/tint_col. Even thou they are different parameters ordering could be more consistent. can we fix that? - - layout: horizontal layout helper (#97) - - layout: horizontal flow until no space left (#404) - - layout: more generic alignment state (left/right/centered) for single items? - - layout: clean up the InputFloatN/SliderFloatN/ColorEdit4 layout code. item width should include frame padding. - - layout: BeginGroup() needs a border option. - - columns: declare column set (each column: fixed size, %, fill, distribute default size among fills) (#513, #125) - - columns: add a conditional parameter to SetColumnOffset() (#513, #125) - - columns: separator function or parameter that works within the column (currently Separator() bypass all columns) (#125) - - columns: columns header to act as button (~sort op) and allow resize/reorder (#513, #125) - - columns: user specify columns size (#513, #125) - - columns: flag to add horizontal separator above/below? - - columns/layout: setup minimum line height (equivalent of automatically calling AlignFirstTextHeightToWidgets) - - combo: sparse combo boxes (via function call?) / iterators - - combo: contents should extends to fit label if combo widget is small - - combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203) - - listbox: multiple selection - - listbox: user may want to initial scroll to focus on the one selected value? - - listbox: keyboard navigation. - - listbox: scrolling should track modified selection. -!- popups/menus: clarify usage of popups id, how MenuItem/Selectable closing parent popups affects the ID, etc. this is quite fishy needs improvement! (#331, #402) - - popups: add variant using global identifier similar to Begin/End (#402) - - popups: border options. richer api like BeginChild() perhaps? (#197) - - tooltip: tooltip that doesn't fit in entire screen seems to lose their "last preferred button" and may teleport when moving mouse - - menus: local shortcuts, global shortcuts (#456, #126) - - menus: icons - - menus: menubars: some sort of priority / effect of main menu-bar on desktop size? - - menus: calling BeginMenu() twice with a same name doesn't seem to append nicely - - statusbar: add a per-window status bar helper similar to what menubar does. - - tabs (#261, #351) - - separator: separator on the initial position of a window is not visible (cursorpos.y <= clippos.y) -!- color: the color helpers/typing is a mess and needs sorting out. - - color: add a better color picker (#346) - - node/graph editor (#306) - - pie menus patterns (#434) - - drag'n drop, dragging helpers (carry dragging info, visualize drag source before clicking, drop target, etc.) (#143, #479) - - plot: PlotLines() should use the polygon-stroke facilities (currently issues with averaging normals) - - plot: make it easier for user to draw extra stuff into the graph (e.g: draw basis, highlight certain points, 2d plots, multiple plots) - - plot: "smooth" automatic scale over time, user give an input 0.0(full user scale) 1.0(full derived from value) - - plot: add a helper e.g. Plot(char* label, float value, float time_span=2.0f) that stores values and Plot them for you - probably another function name. and/or automatically allow to plot ANY displayed value (more reliance on stable ID) - - slider: allow using the [-]/[+] buttons used by InputFloat()/InputInt() - - slider: initial absolute click is imprecise. change to relative movement slider (same as scrollbar). - - slider: add dragging-based widgets to edit values with mouse (on 2 axises), saving screen real-estate. - - slider: tint background based on value (e.g. v_min -> v_max, or use 0.0f either side of the sign) - - slider & drag: int data passing through a float - - drag float: up/down axis - - drag float: added leeway on edge (e.g. a few invisible steps past the clamp limits) - - tree node / optimization: avoid formatting when clipped. - - tree node: tree-node/header right-most side doesn't take account of horizontal scrolling. - - tree node: add treenode/treepush int variants? not there because (void*) cast from int warns on some platforms/settings? - - tree node: try to apply scrolling at time of TreePop() if node was just opened and end of node is past scrolling limits? - - tree node / selectable render mismatch which is visible if you use them both next to each other (e.g. cf. property viewer) - - tree node: tweak color scheme to distinguish headers from selected tree node (#581) - - textwrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (#249) - - settings: write more decent code to allow saving/loading new fields - - settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file - - style: add window shadows. - - style/optimization: store rounded corners in texture to use 1 quad per corner (filled and wireframe) to lower the cost of rounding. - - style: color-box not always square? - - style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps to other settings? avoid implementing duplicate helpers such as SmallCheckbox(), etc. - - style: try to make PushStyleVar() more robust to incorrect parameters (to be more friendly to edit & continues situation). - - style: global scale setting. - - style: WindowPadding needs to be EVEN needs the 0.5 multiplier probably have a subtle effect on clip rectangle - - text: simple markup language for color change? - - font: dynamic font atlas to avoid baking huge ranges into bitmap and make scaling easier. - - font: small opt: for monospace font (like the defalt one) we can trim IndexXAdvance as long as trailing value is == FallbackXAdvance - - font: add support for kerning, probably optional. perhaps default to (32..128)^2 matrix ~ 36KB then hash fallback. - - font: add a simpler CalcTextSizeA() api? current one ok but not welcome if user needs to call it directly (without going through ImGui::CalcTextSize) - - font: fix AddRemapChar() to work before font has been built. - - log: LogButtons() options for specifying depth and/or hiding depth slider - - log: have more control over the log scope (e.g. stop logging when leaving current tree node scope) - - log: be able to log anything (e.g. right-click on a window/tree-node, shows context menu? log into tty/file/clipboard) - - log: let user copy any window content to clipboard easily (CTRL+C on windows? while moving it? context menu?). code is commented because it fails with multiple Begin/End pairs. - - filters: set a current filter that tree node can automatically query to hide themselves - - filters: handle wildcards (with implicit leading/trailing *), regexps - - shortcuts: add a shortcut api, e.g. parse "&Save" and/or "Save (CTRL+S)", pass in to widgets or provide simple ways to use (button=activate, input=focus) -!- keyboard: tooltip & combo boxes are messing up / not honoring keyboard tabbing - - keyboard: full keyboard navigation and focus. (#323) - - focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622) - - focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame) - - input: rework IO system to be able to pass actual ordered/timestamped events. (~#335, #71) - - input: allow to decide and pass explicit double-clicks (e.g. for windows by the CS_DBLCLKS style). - - input: support track pad style scrolling & slider edit. - - misc: provide a way to compile out the entire implementation while providing a dummy API (e.g. #define IMGUI_DUMMY_IMPL) - - misc: double-clicking on title bar to minimize isn't consistent, perhaps move to single-click on left-most collapse icon? - - misc: provide HoveredTime and ActivatedTime to ease the creation of animations. - - style editor: have a more global HSV setter (e.g. alter hue on all elements). consider replacing active/hovered by offset in HSV space? (#438) - - style editor: color child window height expressed in multiple of line height. - - remote: make a system like RemoteImGui first-class citizen/project (#75) - - drawlist: move Font, FontSize, FontTexUvWhitePixel inside ImDrawList and make it self-contained (apart from drawing settings?) - - drawlist: end-user probably can't call Clear() directly because we expect a texture to be pushed in the stack. - - examples: directx9: save/restore device state more thoroughly. - - examples: window minimize, maximize (#583) - - optimization: add a flag to disable most of rendering, for the case where the user expect to skip it (#335) - - optimization: use another hash function than crc32, e.g. FNV1a - - optimization/render: merge command-lists with same clip-rect into one even if they aren't sequential? (as long as in-between clip rectangle don't overlap)? - - optimization: turn some the various stack vectors into statically-sized arrays - - optimization: better clipping for multi-component widgets -*/ - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include "imgui.h" -#define IMGUI_DEFINE_MATH_OPERATORS -#define IMGUI_DEFINE_PLACEMENT_NEW -#include "imgui_internal.h" - -#include // toupper, isprint -#include // NULL, malloc, free, qsort, atoi -#include // vsnprintf, sscanf, printf -#include // INT_MIN, INT_MAX -#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier -#include // intptr_t -#else -#include // intptr_t -#endif - -#ifdef _MSC_VER -#pragma warning (disable: 4127) // condition expression is constant -#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) -#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen -#endif - -// Clang warnings with -Weverything -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse. -#pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants ok. -#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning : format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code. -#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals. -#pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it. -#pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // -#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' // -#elif defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used -#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size -#pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*' -#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function -#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value -#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers -#endif - -//------------------------------------------------------------------------- -// Forward Declarations -//------------------------------------------------------------------------- - -static void LogRenderedText(const ImVec2& ref_pos, const char* text, const char* text_end = NULL); - -static void PushMultiItemsWidths(int components, float w_full = 0.0f); -static float GetDraggedColumnOffset(int column_index); - -static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true); - -static ImFont* GetDefaultFont(); -static void SetCurrentFont(ImFont* font); -static void SetCurrentWindow(ImGuiWindow* window); -static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y); -static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiSetCond cond); -static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiSetCond cond); -static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiSetCond cond); -static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs); -static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags); -static inline bool IsWindowContentHoverable(ImGuiWindow* window); -static void ClearSetNextWindowData(); -static void CheckStacksSize(ImGuiWindow* window, bool write); -static void Scrollbar(ImGuiWindow* window, bool horizontal); - -static void AddDrawListToRenderList(ImVector& out_render_list, ImDrawList* draw_list); -static void AddWindowToRenderList(ImVector& out_render_list, ImGuiWindow* window); -static void AddWindowToSortedBuffer(ImVector& out_sorted_windows, ImGuiWindow* window); - -static ImGuiIniData* FindWindowSettings(const char* name); -static ImGuiIniData* AddWindowSettings(const char* name); -static void LoadIniSettingsFromDisk(const char* ini_filename); -static void SaveIniSettingsToDisk(const char* ini_filename); -static void MarkIniSettingsDirty(); - -static void PushColumnClipRect(int column_index = -1); -static ImRect GetVisibleRect(); - -static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags); -static void CloseInactivePopups(); -static void ClosePopupToLevel(int remaining); -static void ClosePopup(ImGuiID id); -static bool IsPopupOpen(ImGuiID id); -static ImGuiWindow* GetFrontMostModalRootWindow(); -static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, int* last_dir, const ImRect& rect_to_avoid); - -static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data); -static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end); -static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false); - -static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, const char* display_format, char* buf, int buf_size); -static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, int decimal_precision, char* buf, int buf_size); -static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* value1, const void* value2); -static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format); - -//----------------------------------------------------------------------------- -// Platform dependent default implementations -//----------------------------------------------------------------------------- - -static const char* GetClipboardTextFn_DefaultImpl(void* user_data); -static void SetClipboardTextFn_DefaultImpl(void* user_data, const char* text); -static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y); - -//----------------------------------------------------------------------------- -// Context -//----------------------------------------------------------------------------- - -// Default font atlas storage . -// New contexts always point by default to this font atlas. It can be changed by reassigning the GetIO().Fonts variable. -static ImFontAtlas GImDefaultFontAtlas; - -// Default context storage + current context pointer. -// Implicitely used by all ImGui functions. Always assumed to be != NULL. Change to a different context by calling ImGui::SetCurrentContext() -// ImGui is currently not thread-safe because of this variable. If you want thread-safety to allow N threads to access N different contexts, you might work around it by: -// - Having multiple instances of the ImGui code compiled inside different namespace (easiest/safest, if you have a finite number of contexts) -// - or: Changing this variable to be TLS. You may #define GImGui in imconfig.h for further custom hackery. Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586 -#ifndef GImGui -static ImGuiContext GImDefaultContext; -ImGuiContext* GImGui = &GImDefaultContext; -#endif - -//----------------------------------------------------------------------------- -// User facing structures -//----------------------------------------------------------------------------- - -ImGuiStyle::ImGuiStyle() -{ - Alpha = 1.0f; // Global alpha applies to everything in ImGui - WindowPadding = ImVec2(8,8); // Padding within a window - WindowMinSize = ImVec2(32,32); // Minimum window size - WindowRounding = 9.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows - WindowTitleAlign = ImVec2(0.0f,0.5f);// Alignment for title bar text - ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows - FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets) - FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets). - ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines - ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) - TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! - IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). - ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns - ScrollbarSize = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar - ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar - GrabMinSize = 10.0f; // Minimum width/height of a grab box for slider/scrollbar - GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. - ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text. - DisplayWindowPadding = ImVec2(22,22); // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows. - DisplaySafeAreaPadding = ImVec2(4,4); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. - AntiAliasedLines = true; // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU. - AntiAliasedShapes = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) - CurveTessellationTol = 1.25f; // Tessellation tolerance. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. - - Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); - Colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f); - Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - Colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f); - Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.65f); - Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input - Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.90f, 0.80f, 0.80f, 0.40f); - Colors[ImGuiCol_FrameBgActive] = ImVec4(0.90f, 0.65f, 0.65f, 0.45f); - Colors[ImGuiCol_TitleBg] = ImVec4(0.27f, 0.27f, 0.54f, 0.83f); - Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f); - Colors[ImGuiCol_TitleBgActive] = ImVec4(0.32f, 0.32f, 0.63f, 0.87f); - Colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.80f); - Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.25f, 0.30f, 0.60f); - Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f); - Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f); - Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 0.40f); - Colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f); - Colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f); - Colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f); - Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f); - Colors[ImGuiCol_Button] = ImVec4(0.67f, 0.40f, 0.40f, 0.60f); - Colors[ImGuiCol_ButtonHovered] = ImVec4(0.67f, 0.40f, 0.40f, 1.00f); - Colors[ImGuiCol_ButtonActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f); - Colors[ImGuiCol_Header] = ImVec4(0.40f, 0.40f, 0.90f, 0.45f); - Colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.90f, 0.80f); - Colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.87f, 0.80f); - Colors[ImGuiCol_Column] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); - Colors[ImGuiCol_ColumnHovered] = ImVec4(0.70f, 0.60f, 0.60f, 1.00f); - Colors[ImGuiCol_ColumnActive] = ImVec4(0.90f, 0.70f, 0.70f, 1.00f); - Colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f); - Colors[ImGuiCol_ResizeGripHovered] = ImVec4(1.00f, 1.00f, 1.00f, 0.60f); - Colors[ImGuiCol_ResizeGripActive] = ImVec4(1.00f, 1.00f, 1.00f, 0.90f); - Colors[ImGuiCol_CloseButton] = ImVec4(0.50f, 0.50f, 0.90f, 0.50f); - Colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.70f, 0.70f, 0.90f, 0.60f); - Colors[ImGuiCol_CloseButtonActive] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f); - Colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); - Colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); - Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); - Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); - Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); - Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); -} - -ImGuiIO::ImGuiIO() -{ - // Most fields are initialized with zero - memset(this, 0, sizeof(*this)); - - DisplaySize = ImVec2(-1.0f, -1.0f); - DeltaTime = 1.0f/60.0f; - IniSavingRate = 5.0f; - IniFilename = "imgui.ini"; - LogFilename = "imgui_log.txt"; - Fonts = &GImDefaultFontAtlas; - FontGlobalScale = 1.0f; - FontDefault = NULL; - DisplayFramebufferScale = ImVec2(1.0f, 1.0f); - MousePos = ImVec2(-1,-1); - MousePosPrev = ImVec2(-1,-1); - MouseDoubleClickTime = 0.30f; - MouseDoubleClickMaxDist = 6.0f; - MouseDragThreshold = 6.0f; - for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) - MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f; - for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) - KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f; - for (int i = 0; i < ImGuiKey_COUNT; i++) - KeyMap[i] = -1; - KeyRepeatDelay = 0.250f; - KeyRepeatRate = 0.050f; - UserData = NULL; - - // User functions - RenderDrawListsFn = NULL; - MemAllocFn = malloc; - MemFreeFn = free; - GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations - SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; - ClipboardUserData = NULL; - ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl; - - // Set OS X style defaults based on __APPLE__ compile time flag -#ifdef __APPLE__ - OSXBehaviors = true; -#endif -} - -// Pass in translated ASCII characters for text input. -// - with glfw you can get those from the callback set in glfwSetCharCallback() -// - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message -void ImGuiIO::AddInputCharacter(ImWchar c) -{ - const int n = ImStrlenW(InputCharacters); - if (n + 1 < IM_ARRAYSIZE(InputCharacters)) - { - InputCharacters[n] = c; - InputCharacters[n+1] = '\0'; - } -} - -void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars) -{ - // We can't pass more wchars than ImGuiIO::InputCharacters[] can hold so don't convert more - const int wchars_buf_len = sizeof(ImGuiIO::InputCharacters) / sizeof(ImWchar); - ImWchar wchars[wchars_buf_len]; - ImTextStrFromUtf8(wchars, wchars_buf_len, utf8_chars, NULL); - for (int i = 0; i < wchars_buf_len && wchars[i] != 0; i++) - AddInputCharacter(wchars[i]); -} - -//----------------------------------------------------------------------------- -// HELPERS -//----------------------------------------------------------------------------- - -#define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose -#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255 - -// Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n. -#ifdef _WIN32 -#define IM_NEWLINE "\r\n" -#else -#define IM_NEWLINE "\n" -#endif - -bool ImIsPointInTriangle(const ImVec2& p, const ImVec2& a, const ImVec2& b, const ImVec2& c) -{ - bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f; - bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f; - bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f; - return ((b1 == b2) && (b2 == b3)); -} - -int ImStricmp(const char* str1, const char* str2) -{ - int d; - while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } - return d; -} - -int ImStrnicmp(const char* str1, const char* str2, int count) -{ - int d = 0; - while (count > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; count--; } - return d; -} - -void ImStrncpy(char* dst, const char* src, int count) -{ - if (count < 1) return; - strncpy(dst, src, (size_t)count); - dst[count-1] = 0; -} - -char* ImStrdup(const char *str) -{ - size_t len = strlen(str) + 1; - void* buff = ImGui::MemAlloc(len); - return (char*)memcpy(buff, (const void*)str, len); -} - -int ImStrlenW(const ImWchar* str) -{ - int n = 0; - while (*str++) n++; - return n; -} - -const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line -{ - while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n') - buf_mid_line--; - return buf_mid_line; -} - -const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end) -{ - if (!needle_end) - needle_end = needle + strlen(needle); - - const char un0 = (char)toupper(*needle); - while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end)) - { - if (toupper(*haystack) == un0) - { - const char* b = needle + 1; - for (const char* a = haystack + 1; b < needle_end; a++, b++) - if (toupper(*a) != toupper(*b)) - break; - if (b == needle_end) - return haystack; - } - haystack++; - } - return NULL; -} - - -// MSVC version appears to return -1 on overflow, whereas glibc appears to return total count (which may be >= buf_size). -// Ideally we would test for only one of those limits at runtime depending on the behavior the vsnprintf(), but trying to deduct it at compile time sounds like a pandora can of worm. -int ImFormatString(char* buf, int buf_size, const char* fmt, ...) -{ - IM_ASSERT(buf_size > 0); - va_list args; - va_start(args, fmt); - int w = vsnprintf(buf, buf_size, fmt, args); - va_end(args); - if (w == -1 || w >= buf_size) - w = buf_size - 1; - buf[w] = 0; - return w; -} - -int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args) -{ - IM_ASSERT(buf_size > 0); - int w = vsnprintf(buf, buf_size, fmt, args); - if (w == -1 || w >= buf_size) - w = buf_size - 1; - buf[w] = 0; - return w; -} - -// Pass data_size==0 for zero-terminated strings -// FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements. -ImU32 ImHash(const void* data, int data_size, ImU32 seed) -{ - static ImU32 crc32_lut[256] = { 0 }; - if (!crc32_lut[1]) - { - const ImU32 polynomial = 0xEDB88320; - for (ImU32 i = 0; i < 256; i++) - { - ImU32 crc = i; - for (ImU32 j = 0; j < 8; j++) - crc = (crc >> 1) ^ (ImU32(-int(crc & 1)) & polynomial); - crc32_lut[i] = crc; - } - } - - seed = ~seed; - ImU32 crc = seed; - const unsigned char* current = (const unsigned char*)data; - - if (data_size > 0) - { - // Known size - while (data_size--) - crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *current++]; - } - else - { - // Zero-terminated string - while (unsigned char c = *current++) - { - // We support a syntax of "label###id" where only "###id" is included in the hash, and only "label" gets displayed. - // Because this syntax is rarely used we are optimizing for the common case. - // - If we reach ### in the string we discard the hash so far and reset to the seed. - // - We don't do 'current += 2; continue;' after handling ### to keep the code smaller. - if (c == '#' && current[0] == '#' && current[1] == '#') - crc = seed; - crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c]; - } - } - return ~crc; -} - -//----------------------------------------------------------------------------- -// ImText* helpers -//----------------------------------------------------------------------------- - -// Convert UTF-8 to 32-bits character, process single character input. -// Based on stb_from_utf8() from github.com/nothings/stb/ -// We handle UTF-8 decoding error by skipping forward. -int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end) -{ - unsigned int c = (unsigned int)-1; - const unsigned char* str = (const unsigned char*)in_text; - if (!(*str & 0x80)) - { - c = (unsigned int)(*str++); - *out_char = c; - return 1; - } - if ((*str & 0xe0) == 0xc0) - { - *out_char = 0xFFFD; // will be invalid but not end of string - if (in_text_end && in_text_end - (const char*)str < 2) return 1; - if (*str < 0xc2) return 2; - c = (unsigned int)((*str++ & 0x1f) << 6); - if ((*str & 0xc0) != 0x80) return 2; - c += (*str++ & 0x3f); - *out_char = c; - return 2; - } - if ((*str & 0xf0) == 0xe0) - { - *out_char = 0xFFFD; // will be invalid but not end of string - if (in_text_end && in_text_end - (const char*)str < 3) return 1; - if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 3; - if (*str == 0xed && str[1] > 0x9f) return 3; // str[1] < 0x80 is checked below - c = (unsigned int)((*str++ & 0x0f) << 12); - if ((*str & 0xc0) != 0x80) return 3; - c += (unsigned int)((*str++ & 0x3f) << 6); - if ((*str & 0xc0) != 0x80) return 3; - c += (*str++ & 0x3f); - *out_char = c; - return 3; - } - if ((*str & 0xf8) == 0xf0) - { - *out_char = 0xFFFD; // will be invalid but not end of string - if (in_text_end && in_text_end - (const char*)str < 4) return 1; - if (*str > 0xf4) return 4; - if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 4; - if (*str == 0xf4 && str[1] > 0x8f) return 4; // str[1] < 0x80 is checked below - c = (unsigned int)((*str++ & 0x07) << 18); - if ((*str & 0xc0) != 0x80) return 4; - c += (unsigned int)((*str++ & 0x3f) << 12); - if ((*str & 0xc0) != 0x80) return 4; - c += (unsigned int)((*str++ & 0x3f) << 6); - if ((*str & 0xc0) != 0x80) return 4; - c += (*str++ & 0x3f); - // utf-8 encodings of values used in surrogate pairs are invalid - if ((c & 0xFFFFF800) == 0xD800) return 4; - *out_char = c; - return 4; - } - *out_char = 0; - return 0; -} - -int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining) -{ - ImWchar* buf_out = buf; - ImWchar* buf_end = buf + buf_size; - while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text) - { - unsigned int c; - in_text += ImTextCharFromUtf8(&c, in_text, in_text_end); - if (c == 0) - break; - if (c < 0x10000) // FIXME: Losing characters that don't fit in 2 bytes - *buf_out++ = (ImWchar)c; - } - *buf_out = 0; - if (in_text_remaining) - *in_text_remaining = in_text; - return (int)(buf_out - buf); -} - -int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end) -{ - int char_count = 0; - while ((!in_text_end || in_text < in_text_end) && *in_text) - { - unsigned int c; - in_text += ImTextCharFromUtf8(&c, in_text, in_text_end); - if (c == 0) - break; - if (c < 0x10000) - char_count++; - } - return char_count; -} - -// Based on stb_to_utf8() from github.com/nothings/stb/ -static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c) -{ - if (c < 0x80) - { - buf[0] = (char)c; - return 1; - } - if (c < 0x800) - { - if (buf_size < 2) return 0; - buf[0] = (char)(0xc0 + (c >> 6)); - buf[1] = (char)(0x80 + (c & 0x3f)); - return 2; - } - if (c >= 0xdc00 && c < 0xe000) - { - return 0; - } - if (c >= 0xd800 && c < 0xdc00) - { - if (buf_size < 4) return 0; - buf[0] = (char)(0xf0 + (c >> 18)); - buf[1] = (char)(0x80 + ((c >> 12) & 0x3f)); - buf[2] = (char)(0x80 + ((c >> 6) & 0x3f)); - buf[3] = (char)(0x80 + ((c ) & 0x3f)); - return 4; - } - //else if (c < 0x10000) - { - if (buf_size < 3) return 0; - buf[0] = (char)(0xe0 + (c >> 12)); - buf[1] = (char)(0x80 + ((c>> 6) & 0x3f)); - buf[2] = (char)(0x80 + ((c ) & 0x3f)); - return 3; - } -} - -static inline int ImTextCountUtf8BytesFromChar(unsigned int c) -{ - if (c < 0x80) return 1; - if (c < 0x800) return 2; - if (c >= 0xdc00 && c < 0xe000) return 0; - if (c >= 0xd800 && c < 0xdc00) return 4; - return 3; -} - -int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end) -{ - char* buf_out = buf; - const char* buf_end = buf + buf_size; - while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text) - { - unsigned int c = (unsigned int)(*in_text++); - if (c < 0x80) - *buf_out++ = (char)c; - else - buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end-buf_out-1), c); - } - *buf_out = 0; - return (int)(buf_out - buf); -} - -int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end) -{ - int bytes_count = 0; - while ((!in_text_end || in_text < in_text_end) && *in_text) - { - unsigned int c = (unsigned int)(*in_text++); - if (c < 0x80) - bytes_count++; - else - bytes_count += ImTextCountUtf8BytesFromChar(c); - } - return bytes_count; -} - -ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in) -{ - float s = 1.0f/255.0f; - return ImVec4( - ((in >> IM_COL32_R_SHIFT) & 0xFF) * s, - ((in >> IM_COL32_G_SHIFT) & 0xFF) * s, - ((in >> IM_COL32_B_SHIFT) & 0xFF) * s, - ((in >> IM_COL32_A_SHIFT) & 0xFF) * s); -} - -ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in) -{ - ImU32 out; - out = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT; - out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT; - out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT; - out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT; - return out; -} - -ImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul) -{ - ImVec4 c = GImGui->Style.Colors[idx]; - c.w *= GImGui->Style.Alpha * alpha_mul; - return ColorConvertFloat4ToU32(c); -} - -ImU32 ImGui::GetColorU32(const ImVec4& col) -{ - ImVec4 c = col; - c.w *= GImGui->Style.Alpha; - return ColorConvertFloat4ToU32(c); -} - -// Convert rgb floats ([0-1],[0-1],[0-1]) to hsv floats ([0-1],[0-1],[0-1]), from Foley & van Dam p592 -// Optimized http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv -void ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v) -{ - float K = 0.f; - if (g < b) - { - const float tmp = g; g = b; b = tmp; - K = -1.f; - } - if (r < g) - { - const float tmp = r; r = g; g = tmp; - K = -2.f / 6.f - K; - } - - const float chroma = r - (g < b ? g : b); - out_h = fabsf(K + (g - b) / (6.f * chroma + 1e-20f)); - out_s = chroma / (r + 1e-20f); - out_v = r; -} - -// Convert hsv floats ([0-1],[0-1],[0-1]) to rgb floats ([0-1],[0-1],[0-1]), from Foley & van Dam p593 -// also http://en.wikipedia.org/wiki/HSL_and_HSV -void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b) -{ - if (s == 0.0f) - { - // gray - out_r = out_g = out_b = v; - return; - } - - h = fmodf(h, 1.0f) / (60.0f/360.0f); - int i = (int)h; - float f = h - (float)i; - float p = v * (1.0f - s); - float q = v * (1.0f - s * f); - float t = v * (1.0f - s * (1.0f - f)); - - switch (i) - { - case 0: out_r = v; out_g = t; out_b = p; break; - case 1: out_r = q; out_g = v; out_b = p; break; - case 2: out_r = p; out_g = v; out_b = t; break; - case 3: out_r = p; out_g = q; out_b = v; break; - case 4: out_r = t; out_g = p; out_b = v; break; - case 5: default: out_r = v; out_g = p; out_b = q; break; - } -} - -FILE* ImFileOpen(const char* filename, const char* mode) -{ -#if defined(_WIN32) && !defined(__CYGWIN__) - // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. Converting both strings from UTF-8 to wchar format (using a single allocation, because we can) - const int filename_wsize = ImTextCountCharsFromUtf8(filename, NULL) + 1; - const int mode_wsize = ImTextCountCharsFromUtf8(mode, NULL) + 1; - ImVector buf; - buf.resize(filename_wsize + mode_wsize); - ImTextStrFromUtf8(&buf[0], filename_wsize, filename, NULL); - ImTextStrFromUtf8(&buf[filename_wsize], mode_wsize, mode, NULL); - return _wfopen((wchar_t*)&buf[0], (wchar_t*)&buf[filename_wsize]); -#else - return fopen(filename, mode); -#endif -} - -// Load file content into memory -// Memory allocated with ImGui::MemAlloc(), must be freed by user using ImGui::MemFree() -void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* out_file_size, int padding_bytes) -{ - IM_ASSERT(filename && file_open_mode); - if (out_file_size) - *out_file_size = 0; - - FILE* f; - if ((f = ImFileOpen(filename, file_open_mode)) == NULL) - return NULL; - - long file_size_signed; - if (fseek(f, 0, SEEK_END) || (file_size_signed = ftell(f)) == -1 || fseek(f, 0, SEEK_SET)) - { - fclose(f); - return NULL; - } - - int file_size = (int)file_size_signed; - void* file_data = ImGui::MemAlloc(file_size + padding_bytes); - if (file_data == NULL) - { - fclose(f); - return NULL; - } - if (fread(file_data, 1, (size_t)file_size, f) != (size_t)file_size) - { - fclose(f); - ImGui::MemFree(file_data); - return NULL; - } - if (padding_bytes > 0) - memset((void *)(((char*)file_data) + file_size), 0, padding_bytes); - - fclose(f); - if (out_file_size) - *out_file_size = file_size; - - return file_data; -} - -//----------------------------------------------------------------------------- -// ImGuiStorage -//----------------------------------------------------------------------------- - -// Helper: Key->value storage -void ImGuiStorage::Clear() -{ - Data.clear(); -} - -// std::lower_bound but without the bullshit -static ImVector::iterator LowerBound(ImVector& data, ImGuiID key) -{ - ImVector::iterator first = data.begin(); - ImVector::iterator last = data.end(); - int count = (int)(last - first); - while (count > 0) - { - int count2 = count / 2; - ImVector::iterator mid = first + count2; - if (mid->key < key) - { - first = ++mid; - count -= count2 + 1; - } - else - { - count = count2; - } - } - return first; -} - -int ImGuiStorage::GetInt(ImGuiID key, int default_val) const -{ - ImVector::iterator it = LowerBound(const_cast&>(Data), key); - if (it == Data.end() || it->key != key) - return default_val; - return it->val_i; -} - -bool ImGuiStorage::GetBool(ImGuiID key, bool default_val) const -{ - return GetInt(key, default_val ? 1 : 0) != 0; -} - -float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const -{ - ImVector::iterator it = LowerBound(const_cast&>(Data), key); - if (it == Data.end() || it->key != key) - return default_val; - return it->val_f; -} - -void* ImGuiStorage::GetVoidPtr(ImGuiID key) const -{ - ImVector::iterator it = LowerBound(const_cast&>(Data), key); - if (it == Data.end() || it->key != key) - return NULL; - return it->val_p; -} - -// References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer. -int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val) -{ - ImVector::iterator it = LowerBound(Data, key); - if (it == Data.end() || it->key != key) - it = Data.insert(it, Pair(key, default_val)); - return &it->val_i; -} - -bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val) -{ - return (bool*)GetIntRef(key, default_val ? 1 : 0); -} - -float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val) -{ - ImVector::iterator it = LowerBound(Data, key); - if (it == Data.end() || it->key != key) - it = Data.insert(it, Pair(key, default_val)); - return &it->val_f; -} - -void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val) -{ - ImVector::iterator it = LowerBound(Data, key); - if (it == Data.end() || it->key != key) - it = Data.insert(it, Pair(key, default_val)); - return &it->val_p; -} - -// FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on explicit interaction (maximum one a frame) -void ImGuiStorage::SetInt(ImGuiID key, int val) -{ - ImVector::iterator it = LowerBound(Data, key); - if (it == Data.end() || it->key != key) - { - Data.insert(it, Pair(key, val)); - return; - } - it->val_i = val; -} - -void ImGuiStorage::SetBool(ImGuiID key, bool val) -{ - SetInt(key, val ? 1 : 0); -} - -void ImGuiStorage::SetFloat(ImGuiID key, float val) -{ - ImVector::iterator it = LowerBound(Data, key); - if (it == Data.end() || it->key != key) - { - Data.insert(it, Pair(key, val)); - return; - } - it->val_f = val; -} - -void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val) -{ - ImVector::iterator it = LowerBound(Data, key); - if (it == Data.end() || it->key != key) - { - Data.insert(it, Pair(key, val)); - return; - } - it->val_p = val; -} - -void ImGuiStorage::SetAllInt(int v) -{ - for (int i = 0; i < Data.Size; i++) - Data[i].val_i = v; -} - -//----------------------------------------------------------------------------- -// ImGuiTextFilter -//----------------------------------------------------------------------------- - -// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" -ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) -{ - if (default_filter) - { - ImStrncpy(InputBuf, default_filter, IM_ARRAYSIZE(InputBuf)); - Build(); - } - else - { - InputBuf[0] = 0; - CountGrep = 0; - } -} - -bool ImGuiTextFilter::Draw(const char* label, float width) -{ - if (width != 0.0f) - ImGui::PushItemWidth(width); - bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf)); - if (width != 0.0f) - ImGui::PopItemWidth(); - if (value_changed) - Build(); - return value_changed; -} - -void ImGuiTextFilter::TextRange::split(char separator, ImVector& out) -{ - out.resize(0); - const char* wb = b; - const char* we = wb; - while (we < e) - { - if (*we == separator) - { - out.push_back(TextRange(wb, we)); - wb = we + 1; - } - we++; - } - if (wb != we) - out.push_back(TextRange(wb, we)); -} - -void ImGuiTextFilter::Build() -{ - Filters.resize(0); - TextRange input_range(InputBuf, InputBuf+strlen(InputBuf)); - input_range.split(',', Filters); - - CountGrep = 0; - for (int i = 0; i != Filters.Size; i++) - { - Filters[i].trim_blanks(); - if (Filters[i].empty()) - continue; - if (Filters[i].front() != '-') - CountGrep += 1; - } -} - -bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const -{ - if (Filters.empty()) - return true; - - if (text == NULL) - text = ""; - - for (int i = 0; i != Filters.Size; i++) - { - const TextRange& f = Filters[i]; - if (f.empty()) - continue; - if (f.front() == '-') - { - // Subtract - if (ImStristr(text, text_end, f.begin()+1, f.end()) != NULL) - return false; - } - else - { - // Grep - if (ImStristr(text, text_end, f.begin(), f.end()) != NULL) - return true; - } - } - - // Implicit * grep - if (CountGrep == 0) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// ImGuiTextBuffer -//----------------------------------------------------------------------------- - -// On some platform vsnprintf() takes va_list by reference and modifies it. -// va_copy is the 'correct' way to copy a va_list but Visual Studio prior to 2013 doesn't have it. -#ifndef va_copy -#define va_copy(dest, src) (dest = src) -#endif - -// Helper: Text buffer for logging/accumulating text -void ImGuiTextBuffer::appendv(const char* fmt, va_list args) -{ - va_list args_copy; - va_copy(args_copy, args); - - int len = vsnprintf(NULL, 0, fmt, args); // FIXME-OPT: could do a first pass write attempt, likely successful on first pass. - if (len <= 0) - return; - - const int write_off = Buf.Size; - const int needed_sz = write_off + len; - if (write_off + len >= Buf.Capacity) - { - int double_capacity = Buf.Capacity * 2; - Buf.reserve(needed_sz > double_capacity ? needed_sz : double_capacity); - } - - Buf.resize(needed_sz); - ImFormatStringV(&Buf[write_off] - 1, len+1, fmt, args_copy); -} - -void ImGuiTextBuffer::append(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - appendv(fmt, args); - va_end(args); -} - -//----------------------------------------------------------------------------- -// ImGuiSimpleColumns -//----------------------------------------------------------------------------- - -ImGuiSimpleColumns::ImGuiSimpleColumns() -{ - Count = 0; - Spacing = Width = NextWidth = 0.0f; - memset(Pos, 0, sizeof(Pos)); - memset(NextWidths, 0, sizeof(NextWidths)); -} - -void ImGuiSimpleColumns::Update(int count, float spacing, bool clear) -{ - IM_ASSERT(Count <= IM_ARRAYSIZE(Pos)); - Count = count; - Width = NextWidth = 0.0f; - Spacing = spacing; - if (clear) memset(NextWidths, 0, sizeof(NextWidths)); - for (int i = 0; i < Count; i++) - { - if (i > 0 && NextWidths[i] > 0.0f) - Width += Spacing; - Pos[i] = (float)(int)Width; - Width += NextWidths[i]; - NextWidths[i] = 0.0f; - } -} - -float ImGuiSimpleColumns::DeclColumns(float w0, float w1, float w2) // not using va_arg because they promote float to double -{ - NextWidth = 0.0f; - NextWidths[0] = ImMax(NextWidths[0], w0); - NextWidths[1] = ImMax(NextWidths[1], w1); - NextWidths[2] = ImMax(NextWidths[2], w2); - for (int i = 0; i < 3; i++) - NextWidth += NextWidths[i] + ((i > 0 && NextWidths[i] > 0.0f) ? Spacing : 0.0f); - return ImMax(Width, NextWidth); -} - -float ImGuiSimpleColumns::CalcExtraSpace(float avail_w) -{ - return ImMax(0.0f, avail_w - Width); -} - -//----------------------------------------------------------------------------- -// ImGuiListClipper -//----------------------------------------------------------------------------- - -static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) -{ - // Set cursor position and a few other things so that SetScrollHere() and Columns() can work when seeking cursor. - // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue. Consider moving within SetCursorXXX functions? - ImGui::SetCursorPosY(pos_y); - ImGuiWindow* window = ImGui::GetCurrentWindow(); - window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHere() can properly function after the end of our clipper usage. - window->DC.PrevLineHeight = (line_height - GImGui->Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. - if (window->DC.ColumnsCount > 1) - window->DC.ColumnsCellMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly -} - -// Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1 -// Use case B: Begin() called from constructor with items_height>0 -// FIXME-LEGACY: Ideally we should remove the Begin/End functions but they are part of the legacy API we still support. This is why some of the code in Step() calling Begin() and reassign some fields, spaghetti style. -void ImGuiListClipper::Begin(int count, float items_height) -{ - StartPosY = ImGui::GetCursorPosY(); - ItemsHeight = items_height; - ItemsCount = count; - StepNo = 0; - DisplayEnd = DisplayStart = -1; - if (ItemsHeight > 0.0f) - { - ImGui::CalcListClipping(ItemsCount, ItemsHeight, &DisplayStart, &DisplayEnd); // calculate how many to clip/display - if (DisplayStart > 0) - SetCursorPosYAndSetupDummyPrevLine(StartPosY + DisplayStart * ItemsHeight, ItemsHeight); // advance cursor - StepNo = 2; - } -} - -void ImGuiListClipper::End() -{ - if (ItemsCount < 0) - return; - // In theory here we should assert that ImGui::GetCursorPosY() == StartPosY + DisplayEnd * ItemsHeight, but it feels saner to just seek at the end and not assert/crash the user. - if (ItemsCount < INT_MAX) - SetCursorPosYAndSetupDummyPrevLine(StartPosY + ItemsCount * ItemsHeight, ItemsHeight); // advance cursor - ItemsCount = -1; - StepNo = 3; -} - -bool ImGuiListClipper::Step() -{ - if (ItemsCount == 0 || ImGui::GetCurrentWindowRead()->SkipItems) - { - ItemsCount = -1; - return false; - } - if (StepNo == 0) // Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height. - { - DisplayStart = 0; - DisplayEnd = 1; - StartPosY = ImGui::GetCursorPosY(); - StepNo = 1; - return true; - } - if (StepNo == 1) // Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element. - { - if (ItemsCount == 1) { ItemsCount = -1; return false; } - float items_height = ImGui::GetCursorPosY() - StartPosY; - IM_ASSERT(items_height > 0.0f); // If this triggers, it means Item 0 hasn't moved the cursor vertically - Begin(ItemsCount-1, items_height); - DisplayStart++; - DisplayEnd++; - StepNo = 3; - return true; - } - if (StepNo == 2) // Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user still call Step(). Does nothing and switch to Step 3. - { - IM_ASSERT(DisplayStart >= 0 && DisplayEnd >= 0); - StepNo = 3; - return true; - } - if (StepNo == 3) // Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop. - End(); - return false; -} - -//----------------------------------------------------------------------------- -// ImGuiWindow -//----------------------------------------------------------------------------- - -ImGuiWindow::ImGuiWindow(const char* name) -{ - Name = ImStrdup(name); - ID = ImHash(name, 0); - IDStack.push_back(ID); - MoveId = GetID("#MOVE"); - - Flags = 0; - IndexWithinParent = 0; - PosFloat = Pos = ImVec2(0.0f, 0.0f); - Size = SizeFull = ImVec2(0.0f, 0.0f); - SizeContents = SizeContentsExplicit = ImVec2(0.0f, 0.0f); - WindowPadding = ImVec2(0.0f, 0.0f); - Scroll = ImVec2(0.0f, 0.0f); - ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); - ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f); - ScrollbarX = ScrollbarY = false; - ScrollbarSizes = ImVec2(0.0f, 0.0f); - BorderSize = 0.0f; - Active = WasActive = false; - Accessed = false; - Collapsed = false; - SkipItems = false; - BeginCount = 0; - PopupId = 0; - AutoFitFramesX = AutoFitFramesY = -1; - AutoFitOnlyGrows = false; - AutoPosLastDirection = -1; - HiddenFrames = 0; - SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiSetCond_Always | ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing; - SetWindowPosCenterWanted = false; - - LastFrameActive = -1; - ItemWidthDefault = 0.0f; - FontWindowScale = 1.0f; - - DrawList = (ImDrawList*)ImGui::MemAlloc(sizeof(ImDrawList)); - IM_PLACEMENT_NEW(DrawList) ImDrawList(); - DrawList->_OwnerName = Name; - RootWindow = NULL; - RootNonPopupWindow = NULL; - ParentWindow = NULL; - - FocusIdxAllCounter = FocusIdxTabCounter = -1; - FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX; - FocusIdxAllRequestNext = FocusIdxTabRequestNext = INT_MAX; -} - -ImGuiWindow::~ImGuiWindow() -{ - DrawList->~ImDrawList(); - ImGui::MemFree(DrawList); - DrawList = NULL; - ImGui::MemFree(Name); - Name = NULL; -} - -ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end) -{ - ImGuiID seed = IDStack.back(); - ImGuiID id = ImHash(str, str_end ? (int)(str_end - str) : 0, seed); - ImGui::KeepAliveID(id); - return id; -} - -ImGuiID ImGuiWindow::GetID(const void* ptr) -{ - ImGuiID seed = IDStack.back(); - ImGuiID id = ImHash(&ptr, sizeof(void*), seed); - ImGui::KeepAliveID(id); - return id; -} - -ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end) -{ - ImGuiID seed = IDStack.back(); - return ImHash(str, str_end ? (int)(str_end - str) : 0, seed); -} - -//----------------------------------------------------------------------------- -// Internal API exposed in imgui_internal.h -//----------------------------------------------------------------------------- - -static void SetCurrentWindow(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - g.CurrentWindow = window; - if (window) - g.FontSize = window->CalcFontSize(); -} - -ImGuiWindow* ImGui::GetParentWindow() -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.CurrentWindowStack.Size >= 2); - return g.CurrentWindowStack[(unsigned int)g.CurrentWindowStack.Size - 2]; -} - -void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - g.ActiveId = id; - g.ActiveIdAllowOverlap = false; - g.ActiveIdIsJustActivated = true; - if (id) - g.ActiveIdIsAlive = true; - g.ActiveIdWindow = window; -} - -void ImGui::ClearActiveID() -{ - SetActiveID(0, NULL); -} - -void ImGui::SetHoveredID(ImGuiID id) -{ - ImGuiContext& g = *GImGui; - g.HoveredId = id; - g.HoveredIdAllowOverlap = false; -} - -void ImGui::KeepAliveID(ImGuiID id) -{ - ImGuiContext& g = *GImGui; - if (g.ActiveId == id) - g.ActiveIdIsAlive = true; -} - -// Advance cursor given item size for layout. -void ImGui::ItemSize(const ImVec2& size, float text_offset_y) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - // Always align ourselves on pixel boundaries - ImGuiContext& g = *GImGui; - const float line_height = ImMax(window->DC.CurrentLineHeight, size.y); - const float text_base_offset = ImMax(window->DC.CurrentLineTextBaseOffset, text_offset_y); - window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y); - window->DC.CursorPos = ImVec2((float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX), (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y)); - window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x); - window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y); - - //window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // Debug - - window->DC.PrevLineHeight = line_height; - window->DC.PrevLineTextBaseOffset = text_base_offset; - window->DC.CurrentLineHeight = window->DC.CurrentLineTextBaseOffset = 0.0f; -} - -void ImGui::ItemSize(const ImRect& bb, float text_offset_y) -{ - ItemSize(bb.GetSize(), text_offset_y); -} - -// Declare item bounding box for clipping and interaction. -// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface -// declares their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd(). -bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.LastItemId = id ? *id : 0; - window->DC.LastItemRect = bb; - window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false; - if (IsClippedEx(bb, id, false)) - return false; - - // This is a sensible default, but widgets are free to override it after calling ItemAdd() - ImGuiContext& g = *GImGui; - if (IsMouseHoveringRect(bb.Min, bb.Max)) - { - // Matching the behavior of IsHovered() but allow if ActiveId==window->MoveID (we clicked on the window background) - // So that clicking on items with no active id such as Text() still returns true with IsItemHovered() - window->DC.LastItemHoveredRect = true; - if (g.HoveredRootWindow == window->RootWindow) - if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowOverlap || (g.ActiveId == window->MoveId)) - if (IsWindowContentHoverable(window)) - window->DC.LastItemHoveredAndUsable = true; - } - - return true; -} - -bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindowRead(); - - if (!bb.Overlaps(window->ClipRect)) - if (!id || *id != GImGui->ActiveId) - if (clip_even_when_logged || !g.LogEnabled) - return true; - return false; -} - -// NB: This is an internal helper. The user-facing IsItemHovered() is using data emitted from ItemAdd(), with a slightly different logic. -bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs) -{ - ImGuiContext& g = *GImGui; - if (g.HoveredId == 0 || g.HoveredId == id || g.HoveredIdAllowOverlap) - { - ImGuiWindow* window = GetCurrentWindowRead(); - if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow)) - if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) && IsMouseHoveringRect(bb.Min, bb.Max)) - if (IsWindowContentHoverable(g.HoveredRootWindow)) - return true; - } - return false; -} - -bool ImGui::FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_stop) -{ - ImGuiContext& g = *GImGui; - - const bool allow_keyboard_focus = window->DC.AllowKeyboardFocus; - window->FocusIdxAllCounter++; - if (allow_keyboard_focus) - window->FocusIdxTabCounter++; - - // Process keyboard input at this point: TAB, Shift-TAB switch focus - // We can always TAB out of a widget that doesn't allow tabbing in. - if (tab_stop && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && is_active && IsKeyPressedMap(ImGuiKey_Tab)) - { - // Modulo on index will be applied at the end of frame once we've got the total counter of items. - window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (allow_keyboard_focus ? -1 : 0) : +1); - } - - if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent) - return true; - - if (allow_keyboard_focus) - if (window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent) - return true; - - return false; -} - -void ImGui::FocusableItemUnregister(ImGuiWindow* window) -{ - window->FocusIdxAllCounter--; - window->FocusIdxTabCounter--; -} - -ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y) -{ - ImGuiContext& g = *GImGui; - ImVec2 content_max; - if (size.x < 0.0f || size.y < 0.0f) - content_max = g.CurrentWindow->Pos + GetContentRegionMax(); - if (size.x <= 0.0f) - size.x = (size.x == 0.0f) ? default_x : ImMax(content_max.x - g.CurrentWindow->DC.CursorPos.x, 4.0f) + size.x; - if (size.y <= 0.0f) - size.y = (size.y == 0.0f) ? default_y : ImMax(content_max.y - g.CurrentWindow->DC.CursorPos.y, 4.0f) + size.y; - return size; -} - -float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x) -{ - if (wrap_pos_x < 0.0f) - return 0.0f; - - ImGuiWindow* window = GetCurrentWindowRead(); - if (wrap_pos_x == 0.0f) - wrap_pos_x = GetContentRegionMax().x + window->Pos.x; - else if (wrap_pos_x > 0.0f) - wrap_pos_x += window->Pos.x - window->Scroll.x; // wrap_pos_x is provided is window local space - - return ImMax(wrap_pos_x - pos.x, 1.0f); -} - -//----------------------------------------------------------------------------- - -void* ImGui::MemAlloc(size_t sz) -{ - GImGui->IO.MetricsAllocs++; - return GImGui->IO.MemAllocFn(sz); -} - -void ImGui::MemFree(void* ptr) -{ - if (ptr) GImGui->IO.MetricsAllocs--; - return GImGui->IO.MemFreeFn(ptr); -} - -const char* ImGui::GetClipboardText() -{ - return GImGui->IO.GetClipboardTextFn ? GImGui->IO.GetClipboardTextFn(GImGui->IO.ClipboardUserData) : ""; -} - -void ImGui::SetClipboardText(const char* text) -{ - if (GImGui->IO.SetClipboardTextFn) - GImGui->IO.SetClipboardTextFn(GImGui->IO.ClipboardUserData, text); -} - -const char* ImGui::GetVersion() -{ - return IMGUI_VERSION; -} - -// Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself -// Note that we still point to some static data and members (such as GFontAtlas), so the state instance you end up using will point to the static data within its module -ImGuiContext* ImGui::GetCurrentContext() -{ - return GImGui; -} - -void ImGui::SetCurrentContext(ImGuiContext* ctx) -{ -#ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC - IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx); // For custom thread-based hackery you may want to have control over this. -#else - GImGui = ctx; -#endif -} - -ImGuiContext* ImGui::CreateContext(void* (*malloc_fn)(size_t), void (*free_fn)(void*)) -{ - if (!malloc_fn) malloc_fn = malloc; - ImGuiContext* ctx = (ImGuiContext*)malloc_fn(sizeof(ImGuiContext)); - IM_PLACEMENT_NEW(ctx) ImGuiContext(); - ctx->IO.MemAllocFn = malloc_fn; - ctx->IO.MemFreeFn = free_fn ? free_fn : free; - return ctx; -} - -void ImGui::DestroyContext(ImGuiContext* ctx) -{ - void (*free_fn)(void*) = ctx->IO.MemFreeFn; - ctx->~ImGuiContext(); - free_fn(ctx); - if (GImGui == ctx) - SetCurrentContext(NULL); -} - -ImGuiIO& ImGui::GetIO() -{ - return GImGui->IO; -} - -ImGuiStyle& ImGui::GetStyle() -{ - return GImGui->Style; -} - -// Same value as passed to your RenderDrawListsFn() function. valid after Render() and until the next call to NewFrame() -ImDrawData* ImGui::GetDrawData() -{ - return GImGui->RenderDrawData.Valid ? &GImGui->RenderDrawData : NULL; -} - -float ImGui::GetTime() -{ - return GImGui->Time; -} - -int ImGui::GetFrameCount() -{ - return GImGui->FrameCount; -} - -void ImGui::NewFrame() -{ - ImGuiContext& g = *GImGui; - - // Check user data - IM_ASSERT(g.IO.DeltaTime >= 0.0f); // Need a positive DeltaTime (zero is tolerated but will cause some timing issues) - IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f); - IM_ASSERT(g.IO.Fonts->Fonts.Size > 0); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? - IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? - IM_ASSERT(g.Style.CurveTessellationTol > 0.0f); // Invalid style setting - - if (!g.Initialized) - { - // Initialize on first frame - g.LogClipboard = (ImGuiTextBuffer*)ImGui::MemAlloc(sizeof(ImGuiTextBuffer)); - IM_PLACEMENT_NEW(g.LogClipboard) ImGuiTextBuffer(); - - IM_ASSERT(g.Settings.empty()); - LoadIniSettingsFromDisk(g.IO.IniFilename); - g.Initialized = true; - } - - SetCurrentFont(GetDefaultFont()); - IM_ASSERT(g.Font->IsLoaded()); - - g.Time += g.IO.DeltaTime; - g.FrameCount += 1; - g.Tooltip[0] = '\0'; - g.OverlayDrawList.Clear(); - g.OverlayDrawList.PushTextureID(g.IO.Fonts->TexID); - g.OverlayDrawList.PushClipRectFullScreen(); - - // Mark rendering data as invalid to prevent user who may have a handle on it to use it - g.RenderDrawData.Valid = false; - g.RenderDrawData.CmdLists = NULL; - g.RenderDrawData.CmdListsCount = g.RenderDrawData.TotalVtxCount = g.RenderDrawData.TotalIdxCount = 0; - - // Update inputs state - if (g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0) - g.IO.MousePos = ImVec2(-9999.0f, -9999.0f); - if ((g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0) || (g.IO.MousePosPrev.x < 0 && g.IO.MousePosPrev.y < 0)) // if mouse just appeared or disappeared (negative coordinate) we cancel out movement in MouseDelta - g.IO.MouseDelta = ImVec2(0.0f, 0.0f); - else - g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev; - g.IO.MousePosPrev = g.IO.MousePos; - for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) - { - g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f; - g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] >= 0.0f; - g.IO.MouseDownDurationPrev[i] = g.IO.MouseDownDuration[i]; - g.IO.MouseDownDuration[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f; - g.IO.MouseDoubleClicked[i] = false; - if (g.IO.MouseClicked[i]) - { - if (g.Time - g.IO.MouseClickedTime[i] < g.IO.MouseDoubleClickTime) - { - if (ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i]) < g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist) - g.IO.MouseDoubleClicked[i] = true; - g.IO.MouseClickedTime[i] = -FLT_MAX; // so the third click isn't turned into a double-click - } - else - { - g.IO.MouseClickedTime[i] = g.Time; - } - g.IO.MouseClickedPos[i] = g.IO.MousePos; - g.IO.MouseDragMaxDistanceSqr[i] = 0.0f; - } - else if (g.IO.MouseDown[i]) - { - g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i])); - } - } - memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); - for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) - g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f; - - // Calculate frame-rate for the user, as a purely luxurious feature - g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx]; - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime; - g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame); - g.IO.Framerate = 1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame)); - - // Clear reference to active widget if the widget isn't alive anymore - g.HoveredIdPreviousFrame = g.HoveredId; - g.HoveredId = 0; - g.HoveredIdAllowOverlap = false; - if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0) - ClearActiveID(); - g.ActiveIdPreviousFrame = g.ActiveId; - g.ActiveIdIsAlive = false; - g.ActiveIdIsJustActivated = false; - - // Handle user moving window (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows. - if (g.MovedWindowMoveId && g.MovedWindowMoveId == g.ActiveId) - { - KeepAliveID(g.MovedWindowMoveId); - IM_ASSERT(g.MovedWindow && g.MovedWindow->RootWindow); - IM_ASSERT(g.MovedWindow->RootWindow->MoveId == g.MovedWindowMoveId); - if (g.IO.MouseDown[0]) - { - if (!(g.MovedWindow->Flags & ImGuiWindowFlags_NoMove)) - { - g.MovedWindow->PosFloat += g.IO.MouseDelta; - if (!(g.MovedWindow->Flags & ImGuiWindowFlags_NoSavedSettings) && (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)) - MarkIniSettingsDirty(); - } - FocusWindow(g.MovedWindow); - } - else - { - ClearActiveID(); - g.MovedWindow = NULL; - g.MovedWindowMoveId = 0; - } - } - else - { - g.MovedWindow = NULL; - g.MovedWindowMoveId = 0; - } - - // Delay saving settings so we don't spam disk too much - if (g.SettingsDirtyTimer > 0.0f) - { - g.SettingsDirtyTimer -= g.IO.DeltaTime; - if (g.SettingsDirtyTimer <= 0.0f) - SaveIniSettingsToDisk(g.IO.IniFilename); - } - - // Find the window we are hovering. Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow - g.HoveredWindow = g.MovedWindow ? g.MovedWindow : FindHoveredWindow(g.IO.MousePos, false); - if (g.HoveredWindow && (g.HoveredWindow->Flags & ImGuiWindowFlags_ChildWindow)) - g.HoveredRootWindow = g.HoveredWindow->RootWindow; - else - g.HoveredRootWindow = g.MovedWindow ? g.MovedWindow->RootWindow : FindHoveredWindow(g.IO.MousePos, true); - - if (ImGuiWindow* modal_window = GetFrontMostModalRootWindow()) - { - g.ModalWindowDarkeningRatio = ImMin(g.ModalWindowDarkeningRatio + g.IO.DeltaTime * 6.0f, 1.0f); - ImGuiWindow* window = g.HoveredRootWindow; - while (window && window != modal_window) - window = window->ParentWindow; - if (!window) - g.HoveredRootWindow = g.HoveredWindow = NULL; - } - else - { - g.ModalWindowDarkeningRatio = 0.0f; - } - - // Are we using inputs? Tell user so they can capture/discard the inputs away from the rest of their application. - // When clicking outside of a window we assume the click is owned by the application and won't request capture. We need to track click ownership. - int mouse_earliest_button_down = -1; - bool mouse_any_down = false; - for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) - { - if (g.IO.MouseClicked[i]) - g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenPopupStack.empty()); - mouse_any_down |= g.IO.MouseDown[i]; - if (g.IO.MouseDown[i]) - if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[mouse_earliest_button_down] > g.IO.MouseClickedTime[i]) - mouse_earliest_button_down = i; - } - bool mouse_avail_to_imgui = (mouse_earliest_button_down == -1) || g.IO.MouseDownOwned[mouse_earliest_button_down]; - if (g.CaptureMouseNextFrame != -1) - g.IO.WantCaptureMouse = (g.CaptureMouseNextFrame != 0); - else - g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (g.ActiveId != 0) || (!g.OpenPopupStack.empty()); - g.IO.WantCaptureKeyboard = (g.CaptureKeyboardNextFrame != -1) ? (g.CaptureKeyboardNextFrame != 0) : (g.ActiveId != 0); - g.IO.WantTextInput = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId); - g.MouseCursor = ImGuiMouseCursor_Arrow; - g.CaptureMouseNextFrame = g.CaptureKeyboardNextFrame = -1; - g.OsImePosRequest = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default - - // If mouse was first clicked outside of ImGui bounds we also cancel out hovering. - if (!mouse_avail_to_imgui) - g.HoveredWindow = g.HoveredRootWindow = NULL; - - // Scale & Scrolling - if (g.HoveredWindow && g.IO.MouseWheel != 0.0f && !g.HoveredWindow->Collapsed) - { - ImGuiWindow* window = g.HoveredWindow; - if (g.IO.KeyCtrl) - { - if (g.IO.FontAllowUserScaling) - { - // Zoom / Scale window - float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); - float scale = new_font_scale / window->FontWindowScale; - window->FontWindowScale = new_font_scale; - - const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size; - window->Pos += offset; - window->PosFloat += offset; - window->Size *= scale; - window->SizeFull *= scale; - } - } - else if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse)) - { - // Scroll - const int scroll_lines = (window->Flags & ImGuiWindowFlags_ComboBox) ? 3 : 5; - SetWindowScrollY(window, window->Scroll.y - g.IO.MouseWheel * window->CalcFontSize() * scroll_lines); - } - } - - // Pressing TAB activate widget focus - // NB: Don't discard FocusedWindow if it isn't active, so that a window that go on/off programatically won't lose its keyboard focus. - if (g.ActiveId == 0 && g.FocusedWindow != NULL && g.FocusedWindow->Active && IsKeyPressedMap(ImGuiKey_Tab, false)) - g.FocusedWindow->FocusIdxTabRequestNext = 0; - - // Mark all windows as not visible - for (int i = 0; i != g.Windows.Size; i++) - { - ImGuiWindow* window = g.Windows[i]; - window->WasActive = window->Active; - window->Active = false; - window->Accessed = false; - } - - // Closing the focused window restore focus to the first active root window in descending z-order - if (g.FocusedWindow && !g.FocusedWindow->WasActive) - for (int i = g.Windows.Size-1; i >= 0; i--) - if (g.Windows[i]->WasActive && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow)) - { - FocusWindow(g.Windows[i]); - break; - } - - // No window should be open at the beginning of the frame. - // But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear. - g.CurrentWindowStack.resize(0); - g.CurrentPopupStack.resize(0); - CloseInactivePopups(); - - // Create implicit window - we will only render it if the user has added something to it. - ImGui::SetNextWindowSize(ImVec2(400,400), ImGuiSetCond_FirstUseEver); - ImGui::Begin("Debug"); -} - -// NB: behavior of ImGui after Shutdown() is not tested/guaranteed at the moment. This function is merely here to free heap allocations. -void ImGui::Shutdown() -{ - ImGuiContext& g = *GImGui; - - // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame) - if (g.IO.Fonts) // Testing for NULL to allow user to NULLify in case of running Shutdown() on multiple contexts. Bit hacky. - g.IO.Fonts->Clear(); - - // Cleanup of other data are conditional on actually having used ImGui. - if (!g.Initialized) - return; - - SaveIniSettingsToDisk(g.IO.IniFilename); - - for (int i = 0; i < g.Windows.Size; i++) - { - g.Windows[i]->~ImGuiWindow(); - ImGui::MemFree(g.Windows[i]); - } - g.Windows.clear(); - g.WindowsSortBuffer.clear(); - g.CurrentWindow = NULL; - g.CurrentWindowStack.clear(); - g.FocusedWindow = NULL; - g.HoveredWindow = NULL; - g.HoveredRootWindow = NULL; - g.ActiveIdWindow = NULL; - g.MovedWindow = NULL; - for (int i = 0; i < g.Settings.Size; i++) - ImGui::MemFree(g.Settings[i].Name); - g.Settings.clear(); - g.ColorModifiers.clear(); - g.StyleModifiers.clear(); - g.FontStack.clear(); - g.OpenPopupStack.clear(); - g.CurrentPopupStack.clear(); - g.SetNextWindowSizeConstraintCallback = NULL; - g.SetNextWindowSizeConstraintCallbackUserData = NULL; - for (int i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) - g.RenderDrawLists[i].clear(); - g.OverlayDrawList.ClearFreeMemory(); - g.ColorEditModeStorage.Clear(); - if (g.PrivateClipboard) - { - ImGui::MemFree(g.PrivateClipboard); - g.PrivateClipboard = NULL; - } - g.InputTextState.Text.clear(); - g.InputTextState.InitialText.clear(); - g.InputTextState.TempTextBuffer.clear(); - - if (g.LogFile && g.LogFile != stdout) - { - fclose(g.LogFile); - g.LogFile = NULL; - } - if (g.LogClipboard) - { - g.LogClipboard->~ImGuiTextBuffer(); - ImGui::MemFree(g.LogClipboard); - } - - g.Initialized = false; -} - -static ImGuiIniData* FindWindowSettings(const char* name) -{ - ImGuiContext& g = *GImGui; - ImGuiID id = ImHash(name, 0); - for (int i = 0; i != g.Settings.Size; i++) - { - ImGuiIniData* ini = &g.Settings[i]; - if (ini->Id == id) - return ini; - } - return NULL; -} - -static ImGuiIniData* AddWindowSettings(const char* name) -{ - GImGui->Settings.resize(GImGui->Settings.Size + 1); - ImGuiIniData* ini = &GImGui->Settings.back(); - ini->Name = ImStrdup(name); - ini->Id = ImHash(name, 0); - ini->Collapsed = false; - ini->Pos = ImVec2(FLT_MAX,FLT_MAX); - ini->Size = ImVec2(0,0); - return ini; -} - -// Zero-tolerance, poor-man .ini parsing -// FIXME: Write something less rubbish -static void LoadIniSettingsFromDisk(const char* ini_filename) -{ - ImGuiContext& g = *GImGui; - if (!ini_filename) - return; - - int file_size; - char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", &file_size, 1); - if (!file_data) - return; - - ImGuiIniData* settings = NULL; - const char* buf_end = file_data + file_size; - for (const char* line_start = file_data; line_start < buf_end; ) - { - const char* line_end = line_start; - while (line_end < buf_end && *line_end != '\n' && *line_end != '\r') - line_end++; - - if (line_start[0] == '[' && line_end > line_start && line_end[-1] == ']') - { - char name[64]; - ImFormatString(name, IM_ARRAYSIZE(name), "%.*s", (int)(line_end-line_start-2), line_start+1); - settings = FindWindowSettings(name); - if (!settings) - settings = AddWindowSettings(name); - } - else if (settings) - { - float x, y; - int i; - if (sscanf(line_start, "Pos=%f,%f", &x, &y) == 2) - settings->Pos = ImVec2(x, y); - else if (sscanf(line_start, "Size=%f,%f", &x, &y) == 2) - settings->Size = ImMax(ImVec2(x, y), g.Style.WindowMinSize); - else if (sscanf(line_start, "Collapsed=%d", &i) == 1) - settings->Collapsed = (i != 0); - } - - line_start = line_end+1; - } - - ImGui::MemFree(file_data); -} - -static void SaveIniSettingsToDisk(const char* ini_filename) -{ - ImGuiContext& g = *GImGui; - g.SettingsDirtyTimer = 0.0f; - if (!ini_filename) - return; - - // Gather data from windows that were active during this session - for (int i = 0; i != g.Windows.Size; i++) - { - ImGuiWindow* window = g.Windows[i]; - if (window->Flags & ImGuiWindowFlags_NoSavedSettings) - continue; - ImGuiIniData* settings = FindWindowSettings(window->Name); - settings->Pos = window->Pos; - settings->Size = window->SizeFull; - settings->Collapsed = window->Collapsed; - } - - // Write .ini file - // If a window wasn't opened in this session we preserve its settings - FILE* f = ImFileOpen(ini_filename, "wt"); - if (!f) - return; - for (int i = 0; i != g.Settings.Size; i++) - { - const ImGuiIniData* settings = &g.Settings[i]; - if (settings->Pos.x == FLT_MAX) - continue; - const char* name = settings->Name; - if (const char* p = strstr(name, "###")) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID() - name = p; - fprintf(f, "[%s]\n", name); - fprintf(f, "Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y); - fprintf(f, "Size=%d,%d\n", (int)settings->Size.x, (int)settings->Size.y); - fprintf(f, "Collapsed=%d\n", settings->Collapsed); - fprintf(f, "\n"); - } - - fclose(f); -} - -static void MarkIniSettingsDirty() -{ - ImGuiContext& g = *GImGui; - if (g.SettingsDirtyTimer <= 0.0f) - g.SettingsDirtyTimer = g.IO.IniSavingRate; -} - -// FIXME: Add a more explicit sort order in the window structure. -static int ChildWindowComparer(const void* lhs, const void* rhs) -{ - const ImGuiWindow* a = *(const ImGuiWindow**)lhs; - const ImGuiWindow* b = *(const ImGuiWindow**)rhs; - if (int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup)) - return d; - if (int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip)) - return d; - if (int d = (a->Flags & ImGuiWindowFlags_ComboBox) - (b->Flags & ImGuiWindowFlags_ComboBox)) - return d; - return (a->IndexWithinParent - b->IndexWithinParent); -} - -static void AddWindowToSortedBuffer(ImVector& out_sorted_windows, ImGuiWindow* window) -{ - out_sorted_windows.push_back(window); - if (window->Active) - { - int count = window->DC.ChildWindows.Size; - if (count > 1) - qsort(window->DC.ChildWindows.begin(), (size_t)count, sizeof(ImGuiWindow*), ChildWindowComparer); - for (int i = 0; i < count; i++) - { - ImGuiWindow* child = window->DC.ChildWindows[i]; - if (child->Active) - AddWindowToSortedBuffer(out_sorted_windows, child); - } - } -} - -static void AddDrawListToRenderList(ImVector& out_render_list, ImDrawList* draw_list) -{ - if (draw_list->CmdBuffer.empty()) - return; - - // Remove trailing command if unused - ImDrawCmd& last_cmd = draw_list->CmdBuffer.back(); - if (last_cmd.ElemCount == 0 && last_cmd.UserCallback == NULL) - { - draw_list->CmdBuffer.pop_back(); - if (draw_list->CmdBuffer.empty()) - return; - } - - // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. - IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size); - IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size); - IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); - - // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = 2 bytes = 64K vertices) - // If this assert triggers because you are drawing lots of stuff manually, A) workaround by calling BeginChild()/EndChild() to put your draw commands in multiple draw lists, B) #define ImDrawIdx to a 'unsigned int' in imconfig.h and render accordingly. - IM_ASSERT((int64_t)draw_list->_VtxCurrentIdx <= ((int64_t)1L << (sizeof(ImDrawIdx)*8))); // Too many vertices in same ImDrawList. See comment above. - - out_render_list.push_back(draw_list); - GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size; - GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size; -} - -static void AddWindowToRenderList(ImVector& out_render_list, ImGuiWindow* window) -{ - AddDrawListToRenderList(out_render_list, window->DrawList); - for (int i = 0; i < window->DC.ChildWindows.Size; i++) - { - ImGuiWindow* child = window->DC.ChildWindows[i]; - if (!child->Active) // clipped children may have been marked not active - continue; - if ((child->Flags & ImGuiWindowFlags_Popup) && child->HiddenFrames > 0) - continue; - AddWindowToRenderList(out_render_list, child); - } -} - -// When using this function it is sane to ensure that float are perfectly rounded to integer values, to that e.g. (int)(max.x-min.x) in user's render produce correct result. -void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DrawList->PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect); - window->ClipRect = window->DrawList->_ClipRectStack.back(); -} - -void ImGui::PopClipRect() -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DrawList->PopClipRect(); - window->ClipRect = window->DrawList->_ClipRectStack.back(); -} - -// This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal. -void ImGui::EndFrame() -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() - IM_ASSERT(g.FrameCountEnded != g.FrameCount); // ImGui::EndFrame() called multiple times, or forgot to call ImGui::NewFrame() again - - // Render tooltip - if (g.Tooltip[0]) - { - ImGui::BeginTooltip(); - ImGui::TextUnformatted(g.Tooltip); - ImGui::EndTooltip(); - } - - // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME) - if (g.IO.ImeSetInputScreenPosFn && ImLengthSqr(g.OsImePosRequest - g.OsImePosSet) > 0.0001f) - { - g.IO.ImeSetInputScreenPosFn((int)g.OsImePosRequest.x, (int)g.OsImePosRequest.y); - g.OsImePosSet = g.OsImePosRequest; - } - - // Hide implicit "Debug" window if it hasn't been used - IM_ASSERT(g.CurrentWindowStack.Size == 1); // Mismatched Begin()/End() calls - if (g.CurrentWindow && !g.CurrentWindow->Accessed) - g.CurrentWindow->Active = false; - ImGui::End(); - - // Click to focus window and start moving (after we're done with all our widgets) - if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0]) - { - if (!(g.FocusedWindow && !g.FocusedWindow->WasActive && g.FocusedWindow->Active)) // Unless we just made a popup appear - { - if (g.HoveredRootWindow != NULL) - { - FocusWindow(g.HoveredWindow); - if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove)) - { - g.MovedWindow = g.HoveredWindow; - g.MovedWindowMoveId = g.HoveredRootWindow->MoveId; - SetActiveID(g.MovedWindowMoveId, g.HoveredRootWindow); - } - } - else if (g.FocusedWindow != NULL && GetFrontMostModalRootWindow() == NULL) - { - // Clicking on void disable focus - FocusWindow(NULL); - } - } - } - - // Sort the window list so that all child windows are after their parent - // We cannot do that on FocusWindow() because childs may not exist yet - g.WindowsSortBuffer.resize(0); - g.WindowsSortBuffer.reserve(g.Windows.Size); - for (int i = 0; i != g.Windows.Size; i++) - { - ImGuiWindow* window = g.Windows[i]; - if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow)) // if a child is active its parent will add it - continue; - AddWindowToSortedBuffer(g.WindowsSortBuffer, window); - } - IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size); // we done something wrong - g.Windows.swap(g.WindowsSortBuffer); - - // Clear Input data for next frame - g.IO.MouseWheel = 0.0f; - memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters)); - - g.FrameCountEnded = g.FrameCount; -} - -void ImGui::Render() -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() - - if (g.FrameCountEnded != g.FrameCount) - ImGui::EndFrame(); - g.FrameCountRendered = g.FrameCount; - - // Skip render altogether if alpha is 0.0 - // Note that vertex buffers have been created and are wasted, so it is best practice that you don't create windows in the first place, or consistently respond to Begin() returning false. - if (g.Style.Alpha > 0.0f) - { - // Gather windows to render - g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = g.IO.MetricsActiveWindows = 0; - for (int i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) - g.RenderDrawLists[i].resize(0); - for (int i = 0; i != g.Windows.Size; i++) - { - ImGuiWindow* window = g.Windows[i]; - if (window->Active && window->HiddenFrames <= 0 && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0) - { - // FIXME: Generalize this with a proper layering system so e.g. user can draw in specific layers, below text, .. - g.IO.MetricsActiveWindows++; - if (window->Flags & ImGuiWindowFlags_Popup) - AddWindowToRenderList(g.RenderDrawLists[1], window); - else if (window->Flags & ImGuiWindowFlags_Tooltip) - AddWindowToRenderList(g.RenderDrawLists[2], window); - else - AddWindowToRenderList(g.RenderDrawLists[0], window); - } - } - - // Flatten layers - int n = g.RenderDrawLists[0].Size; - int flattened_size = n; - for (int i = 1; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) - flattened_size += g.RenderDrawLists[i].Size; - g.RenderDrawLists[0].resize(flattened_size); - for (int i = 1; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) - { - ImVector& layer = g.RenderDrawLists[i]; - if (layer.empty()) - continue; - memcpy(&g.RenderDrawLists[0][n], &layer[0], layer.Size * sizeof(ImDrawList*)); - n += layer.Size; - } - - // Draw software mouse cursor if requested - if (g.IO.MouseDrawCursor) - { - const ImGuiMouseCursorData& cursor_data = g.MouseCursorData[g.MouseCursor]; - const ImVec2 pos = g.IO.MousePos - cursor_data.HotOffset; - const ImVec2 size = cursor_data.Size; - const ImTextureID tex_id = g.IO.Fonts->TexID; - g.OverlayDrawList.PushTextureID(tex_id); - g.OverlayDrawList.AddImage(tex_id, pos+ImVec2(1,0), pos+ImVec2(1,0) + size, cursor_data.TexUvMin[1], cursor_data.TexUvMax[1], IM_COL32(0,0,0,48)); // Shadow - g.OverlayDrawList.AddImage(tex_id, pos+ImVec2(2,0), pos+ImVec2(2,0) + size, cursor_data.TexUvMin[1], cursor_data.TexUvMax[1], IM_COL32(0,0,0,48)); // Shadow - g.OverlayDrawList.AddImage(tex_id, pos, pos + size, cursor_data.TexUvMin[1], cursor_data.TexUvMax[1], IM_COL32(0,0,0,255)); // Black border - g.OverlayDrawList.AddImage(tex_id, pos, pos + size, cursor_data.TexUvMin[0], cursor_data.TexUvMax[0], IM_COL32(255,255,255,255)); // White fill - g.OverlayDrawList.PopTextureID(); - } - if (!g.OverlayDrawList.VtxBuffer.empty()) - AddDrawListToRenderList(g.RenderDrawLists[0], &g.OverlayDrawList); - - // Setup draw data - g.RenderDrawData.Valid = true; - g.RenderDrawData.CmdLists = (g.RenderDrawLists[0].Size > 0) ? &g.RenderDrawLists[0][0] : NULL; - g.RenderDrawData.CmdListsCount = g.RenderDrawLists[0].Size; - g.RenderDrawData.TotalVtxCount = g.IO.MetricsRenderVertices; - g.RenderDrawData.TotalIdxCount = g.IO.MetricsRenderIndices; - - // Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData() - if (g.RenderDrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL) - g.IO.RenderDrawListsFn(&g.RenderDrawData); - } -} - -const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end) -{ - const char* text_display_end = text; - if (!text_end) - text_end = (const char*)-1; - - while (text_display_end < text_end && *text_display_end != '\0' && (text_display_end[0] != '#' || text_display_end[1] != '#')) - text_display_end++; - return text_display_end; -} - -// Pass text data straight to log (without being displayed) -void ImGui::LogText(const char* fmt, ...) -{ - ImGuiContext& g = *GImGui; - if (!g.LogEnabled) - return; - - va_list args; - va_start(args, fmt); - if (g.LogFile) - { - vfprintf(g.LogFile, fmt, args); - } - else - { - g.LogClipboard->appendv(fmt, args); - } - va_end(args); -} - -// Internal version that takes a position to decide on newline placement and pad items according to their depth. -// We split text into individual lines to add current tree level padding -static void LogRenderedText(const ImVec2& ref_pos, const char* text, const char* text_end) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = ImGui::GetCurrentWindowRead(); - - if (!text_end) - text_end = ImGui::FindRenderedTextEnd(text, text_end); - - const bool log_new_line = ref_pos.y > window->DC.LogLinePosY+1; - window->DC.LogLinePosY = ref_pos.y; - - const char* text_remaining = text; - if (g.LogStartDepth > window->DC.TreeDepth) // Re-adjust padding if we have popped out of our starting depth - g.LogStartDepth = window->DC.TreeDepth; - const int tree_depth = (window->DC.TreeDepth - g.LogStartDepth); - for (;;) - { - // Split the string. Each new line (after a '\n') is followed by spacing corresponding to the current depth of our log entry. - const char* line_end = text_remaining; - while (line_end < text_end) - if (*line_end == '\n') - break; - else - line_end++; - if (line_end >= text_end) - line_end = NULL; - - const bool is_first_line = (text == text_remaining); - bool is_last_line = false; - if (line_end == NULL) - { - is_last_line = true; - line_end = text_end; - } - if (line_end != NULL && !(is_last_line && (line_end - text_remaining)==0)) - { - const int char_count = (int)(line_end - text_remaining); - if (log_new_line || !is_first_line) - ImGui::LogText(IM_NEWLINE "%*s%.*s", tree_depth*4, "", char_count, text_remaining); - else - ImGui::LogText(" %.*s", char_count, text_remaining); - } - - if (is_last_line) - break; - text_remaining = line_end + 1; - } -} - -// Internal ImGui functions to render text -// RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText() -void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - - // Hide anything after a '##' string - const char* text_display_end; - if (hide_text_after_hash) - { - text_display_end = FindRenderedTextEnd(text, text_end); - } - else - { - if (!text_end) - text_end = text + strlen(text); // FIXME-OPT - text_display_end = text_end; - } - - const int text_len = (int)(text_display_end - text); - if (text_len > 0) - { - window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end); - if (g.LogEnabled) - LogRenderedText(pos, text, text_display_end); - } -} - -void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - - if (!text_end) - text_end = text + strlen(text); // FIXME-OPT - - const int text_len = (int)(text_end - text); - if (text_len > 0) - { - window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width); - if (g.LogEnabled) - LogRenderedText(pos, text, text_end); - } -} - -// Default clip_rect uses (pos_min,pos_max) -// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges) -void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect) -{ - // Hide anything after a '##' string - const char* text_display_end = FindRenderedTextEnd(text, text_end); - const int text_len = (int)(text_display_end - text); - if (text_len == 0) - return; - - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - - // Perform CPU side clipping for single clipped element to avoid using scissor state - ImVec2 pos = pos_min; - const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_display_end, false, 0.0f); - - const ImVec2* clip_min = clip_rect ? &clip_rect->Min : &pos_min; - const ImVec2* clip_max = clip_rect ? &clip_rect->Max : &pos_max; - bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y); - if (clip_rect) // If we had no explicit clipping rectangle then pos==clip_min - need_clipping |= (pos.x < clip_min->x) || (pos.y < clip_min->y); - - // Align whole block. We should defer that to the better rendering function when we'll have support for individual line alignment. - if (align.x > 0.0f) pos.x = ImMax(pos.x, pos.x + (pos_max.x - pos.x - text_size.x) * align.x); - if (align.y > 0.0f) pos.y = ImMax(pos.y, pos.y + (pos_max.y - pos.y - text_size.y) * align.y); - - // Render - if (need_clipping) - { - ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y); - window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect); - } - else - { - window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL); - } - if (g.LogEnabled) - LogRenderedText(pos, text, text_display_end); -} - -// Render a rectangle shaped with optional rounding and borders -void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, float rounding) -{ - ImGuiWindow* window = GetCurrentWindow(); - - window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding); - if (border && (window->Flags & ImGuiWindowFlags_ShowBorders)) - { - window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding); - window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding); - } -} - -// Render a triangle to denote expanded/collapsed state -void ImGui::RenderCollapseTriangle(ImVec2 p_min, bool is_open, float scale) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - - const float h = g.FontSize * 1.00f; - const float r = h * 0.40f * scale; - ImVec2 center = p_min + ImVec2(h*0.50f, h*0.50f*scale); - - ImVec2 a, b, c; - if (is_open) - { - center.y -= r*0.25f; - a = center + ImVec2(0,1)*r; - b = center + ImVec2(-0.866f,-0.5f)*r; - c = center + ImVec2(0.866f,-0.5f)*r; - } - else - { - a = center + ImVec2(1,0)*r; - b = center + ImVec2(-0.500f,0.866f)*r; - c = center + ImVec2(-0.500f,-0.866f)*r; - } - - window->DrawList->AddTriangleFilled(a, b, c, GetColorU32(ImGuiCol_Text)); -} - -void ImGui::RenderBullet(ImVec2 pos) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DrawList->AddCircleFilled(pos, GImGui->FontSize*0.20f, GetColorU32(ImGuiCol_Text), 8); -} - -void ImGui::RenderCheckMark(ImVec2 pos, ImU32 col) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - - ImVec2 a, b, c; - float start_x = (float)(int)(g.FontSize * 0.307f + 0.5f); - float rem_third = (float)(int)((g.FontSize - start_x) / 3.0f); - a.x = pos.x + 0.5f + start_x; - b.x = a.x + rem_third; - c.x = a.x + rem_third * 3.0f; - b.y = pos.y - 1.0f + (float)(int)(g.Font->Ascent * (g.FontSize / g.Font->FontSize) + 0.5f) + (float)(int)(g.Font->DisplayOffset.y); - a.y = b.y - rem_third; - c.y = b.y - rem_third * 2.0f; - - window->DrawList->PathLineTo(a); - window->DrawList->PathLineTo(b); - window->DrawList->PathLineTo(c); - window->DrawList->PathStroke(col, false); -} - -// Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker. -// CalcTextSize("") should return ImVec2(0.0f, GImGui->FontSize) -ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width) -{ - ImGuiContext& g = *GImGui; - - const char* text_display_end; - if (hide_text_after_double_hash) - text_display_end = FindRenderedTextEnd(text, text_end); // Hide anything after a '##' string - else - text_display_end = text_end; - - ImFont* font = g.Font; - const float font_size = g.FontSize; - if (text == text_display_end) - return ImVec2(0.0f, font_size); - ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL); - - // Cancel out character spacing for the last character of a line (it is baked into glyph->XAdvance field) - const float font_scale = font_size / font->FontSize; - const float character_spacing_x = 1.0f * font_scale; - if (text_size.x > 0.0f) - text_size.x -= character_spacing_x; - text_size.x = (float)(int)(text_size.x + 0.95f); - - return text_size; -} - -// Helper to calculate coarse clipping of large list of evenly sized items. -// NB: Prefer using the ImGuiListClipper higher-level helper if you can! Read comments and instructions there on how those use this sort of pattern. -// NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX -void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindowRead(); - if (g.LogEnabled) - { - // If logging is active, do not perform any clipping - *out_items_display_start = 0; - *out_items_display_end = items_count; - return; - } - if (window->SkipItems) - { - *out_items_display_start = *out_items_display_end = 0; - return; - } - - const ImVec2 pos = window->DC.CursorPos; - int start = (int)((window->ClipRect.Min.y - pos.y) / items_height); - int end = (int)((window->ClipRect.Max.y - pos.y) / items_height); - start = ImClamp(start, 0, items_count); - end = ImClamp(end + 1, start, items_count); - *out_items_display_start = start; - *out_items_display_end = end; -} - -// Find window given position, search front-to-back -// FIXME: Note that we have a lag here because WindowRectClipped is updated in Begin() so windows moved by user via SetWindowPos() and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is called, aka before the next Begin(). Moving window thankfully isn't affected. -static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs) -{ - ImGuiContext& g = *GImGui; - for (int i = g.Windows.Size-1; i >= 0; i--) - { - ImGuiWindow* window = g.Windows[i]; - if (!window->Active) - continue; - if (window->Flags & ImGuiWindowFlags_NoInputs) - continue; - if (excluding_childs && (window->Flags & ImGuiWindowFlags_ChildWindow) != 0) - continue; - - // Using the clipped AABB so a child window will typically be clipped by its parent. - ImRect bb(window->WindowRectClipped.Min - g.Style.TouchExtraPadding, window->WindowRectClipped.Max + g.Style.TouchExtraPadding); - if (bb.Contains(pos)) - return window; - } - return NULL; -} - -// Test if mouse cursor is hovering given rectangle -// NB- Rectangle is clipped by our current clip setting -// NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style.TouchExtraPadding) -bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindowRead(); - - // Clip - ImRect rect_clipped(r_min, r_max); - if (clip) - rect_clipped.Clip(window->ClipRect); - - // Expand for touch input - const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, rect_clipped.Max + g.Style.TouchExtraPadding); - return rect_for_touch.Contains(g.IO.MousePos); -} - -bool ImGui::IsMouseHoveringWindow() -{ - ImGuiContext& g = *GImGui; - return g.HoveredWindow == g.CurrentWindow; -} - -bool ImGui::IsMouseHoveringAnyWindow() -{ - ImGuiContext& g = *GImGui; - return g.HoveredWindow != NULL; -} - -bool ImGui::IsPosHoveringAnyWindow(const ImVec2& pos) -{ - return FindHoveredWindow(pos, false) != NULL; -} - -static bool IsKeyPressedMap(ImGuiKey key, bool repeat) -{ - const int key_index = GImGui->IO.KeyMap[key]; - return ImGui::IsKeyPressed(key_index, repeat); -} - -int ImGui::GetKeyIndex(ImGuiKey key) -{ - IM_ASSERT(key >= 0 && key < ImGuiKey_COUNT); - return GImGui->IO.KeyMap[key]; -} - -bool ImGui::IsKeyDown(int key_index) -{ - if (key_index < 0) return false; - IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(GImGui->IO.KeysDown)); - return GImGui->IO.KeysDown[key_index]; -} - -bool ImGui::IsKeyPressed(int key_index, bool repeat) -{ - ImGuiContext& g = *GImGui; - if (key_index < 0) return false; - IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown)); - const float t = g.IO.KeysDownDuration[key_index]; - if (t == 0.0f) - return true; - - if (repeat && t > g.IO.KeyRepeatDelay) - { - float delay = g.IO.KeyRepeatDelay, rate = g.IO.KeyRepeatRate; - if ((fmodf(t - delay, rate) > rate*0.5f) != (fmodf(t - delay - g.IO.DeltaTime, rate) > rate*0.5f)) - return true; - } - return false; -} - -bool ImGui::IsKeyReleased(int key_index) -{ - ImGuiContext& g = *GImGui; - if (key_index < 0) return false; - IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown)); - if (g.IO.KeysDownDurationPrev[key_index] >= 0.0f && !g.IO.KeysDown[key_index]) - return true; - return false; -} - -bool ImGui::IsMouseDown(int button) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - return g.IO.MouseDown[button]; -} - -bool ImGui::IsMouseClicked(int button, bool repeat) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - const float t = g.IO.MouseDownDuration[button]; - if (t == 0.0f) - return true; - - if (repeat && t > g.IO.KeyRepeatDelay) - { - float delay = g.IO.KeyRepeatDelay, rate = g.IO.KeyRepeatRate; - if ((fmodf(t - delay, rate) > rate*0.5f) != (fmodf(t - delay - g.IO.DeltaTime, rate) > rate*0.5f)) - return true; - } - - return false; -} - -bool ImGui::IsMouseReleased(int button) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - return g.IO.MouseReleased[button]; -} - -bool ImGui::IsMouseDoubleClicked(int button) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - return g.IO.MouseDoubleClicked[button]; -} - -bool ImGui::IsMouseDragging(int button, float lock_threshold) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - if (!g.IO.MouseDown[button]) - return false; - if (lock_threshold < 0.0f) - lock_threshold = g.IO.MouseDragThreshold; - return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold; -} - -ImVec2 ImGui::GetMousePos() -{ - return GImGui->IO.MousePos; -} - -// NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed! -ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup() -{ - ImGuiContext& g = *GImGui; - if (g.CurrentPopupStack.Size > 0) - return g.OpenPopupStack[g.CurrentPopupStack.Size-1].MousePosOnOpen; - return g.IO.MousePos; -} - -ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - if (lock_threshold < 0.0f) - lock_threshold = g.IO.MouseDragThreshold; - if (g.IO.MouseDown[button]) - if (g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold) - return g.IO.MousePos - g.IO.MouseClickedPos[button]; // Assume we can only get active with left-mouse button (at the moment). - return ImVec2(0.0f, 0.0f); -} - -void ImGui::ResetMouseDragDelta(int button) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - // NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr - g.IO.MouseClickedPos[button] = g.IO.MousePos; -} - -ImGuiMouseCursor ImGui::GetMouseCursor() -{ - return GImGui->MouseCursor; -} - -void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type) -{ - GImGui->MouseCursor = cursor_type; -} - -void ImGui::CaptureKeyboardFromApp(bool capture) -{ - GImGui->CaptureKeyboardNextFrame = capture ? 1 : 0; -} - -void ImGui::CaptureMouseFromApp(bool capture) -{ - GImGui->CaptureMouseNextFrame = capture ? 1 : 0; -} - -bool ImGui::IsItemHovered() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.LastItemHoveredAndUsable; -} - -bool ImGui::IsItemHoveredRect() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.LastItemHoveredRect; -} - -bool ImGui::IsItemActive() -{ - ImGuiContext& g = *GImGui; - if (g.ActiveId) - { - ImGuiWindow* window = GetCurrentWindowRead(); - return g.ActiveId == window->DC.LastItemId; - } - return false; -} - -bool ImGui::IsItemClicked(int mouse_button) -{ - return IsMouseClicked(mouse_button) && IsItemHovered(); -} - -bool ImGui::IsAnyItemHovered() -{ - return GImGui->HoveredId != 0 || GImGui->HoveredIdPreviousFrame != 0; -} - -bool ImGui::IsAnyItemActive() -{ - return GImGui->ActiveId != 0; -} - -bool ImGui::IsItemVisible() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - ImRect r(window->ClipRect); - return r.Overlaps(window->DC.LastItemRect); -} - -// Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority. -void ImGui::SetItemAllowOverlap() -{ - ImGuiContext& g = *GImGui; - if (g.HoveredId == g.CurrentWindow->DC.LastItemId) - g.HoveredIdAllowOverlap = true; - if (g.ActiveId == g.CurrentWindow->DC.LastItemId) - g.ActiveIdAllowOverlap = true; -} - -ImVec2 ImGui::GetItemRectMin() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.LastItemRect.Min; -} - -ImVec2 ImGui::GetItemRectMax() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.LastItemRect.Max; -} - -ImVec2 ImGui::GetItemRectSize() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.LastItemRect.GetSize(); -} - -ImVec2 ImGui::CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge, float outward) -{ - ImGuiWindow* window = GetCurrentWindowRead(); - ImRect rect = window->DC.LastItemRect; - rect.Expand(outward); - return rect.GetClosestPoint(pos, on_edge); -} - -// Tooltip is stored and turned into a BeginTooltip()/EndTooltip() sequence at the end of the frame. Each call override previous value. -void ImGui::SetTooltipV(const char* fmt, va_list args) -{ - ImGuiContext& g = *GImGui; - ImFormatStringV(g.Tooltip, IM_ARRAYSIZE(g.Tooltip), fmt, args); -} - -void ImGui::SetTooltip(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - SetTooltipV(fmt, args); - va_end(args); -} - -static ImRect GetVisibleRect() -{ - ImGuiContext& g = *GImGui; - if (g.IO.DisplayVisibleMin.x != g.IO.DisplayVisibleMax.x && g.IO.DisplayVisibleMin.y != g.IO.DisplayVisibleMax.y) - return ImRect(g.IO.DisplayVisibleMin, g.IO.DisplayVisibleMax); - return ImRect(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y); -} - -void ImGui::BeginTooltip() -{ - ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize; - ImGui::Begin("##Tooltip", NULL, flags); -} - -void ImGui::EndTooltip() -{ - IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip); // Mismatched BeginTooltip()/EndTooltip() calls - ImGui::End(); -} - -static bool IsPopupOpen(ImGuiID id) -{ - ImGuiContext& g = *GImGui; - return g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].PopupId == id; -} - -// Mark popup as open (toggle toward open state). -// Popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. -// Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). -// One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL) -void ImGui::OpenPopupEx(const char* str_id, bool reopen_existing) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImGuiID id = window->GetID(str_id); - int current_stack_size = g.CurrentPopupStack.Size; - ImGuiPopupRef popup_ref = ImGuiPopupRef(id, window, window->GetID("##menus"), g.IO.MousePos); // Tagged as new ref because constructor sets Window to NULL (we are passing the ParentWindow info here) - if (g.OpenPopupStack.Size < current_stack_size + 1) - g.OpenPopupStack.push_back(popup_ref); - else if (reopen_existing || g.OpenPopupStack[current_stack_size].PopupId != id) - { - g.OpenPopupStack.resize(current_stack_size+1); - g.OpenPopupStack[current_stack_size] = popup_ref; - } -} - -void ImGui::OpenPopup(const char* str_id) -{ - ImGui::OpenPopupEx(str_id, false); -} - -static void CloseInactivePopups() -{ - ImGuiContext& g = *GImGui; - if (g.OpenPopupStack.empty()) - return; - - // When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it. - // Don't close our own child popup windows - int n = 0; - if (g.FocusedWindow) - { - for (n = 0; n < g.OpenPopupStack.Size; n++) - { - ImGuiPopupRef& popup = g.OpenPopupStack[n]; - if (!popup.Window) - continue; - IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0); - if (popup.Window->Flags & ImGuiWindowFlags_ChildWindow) - continue; - - bool has_focus = false; - for (int m = n; m < g.OpenPopupStack.Size && !has_focus; m++) - has_focus = (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == g.FocusedWindow->RootWindow); - if (!has_focus) - break; - } - } - if (n < g.OpenPopupStack.Size) // This test is not required but it allows to set a useful breakpoint on the line below - g.OpenPopupStack.resize(n); -} - -static ImGuiWindow* GetFrontMostModalRootWindow() -{ - ImGuiContext& g = *GImGui; - for (int n = g.OpenPopupStack.Size-1; n >= 0; n--) - if (ImGuiWindow* front_most_popup = g.OpenPopupStack.Data[n].Window) - if (front_most_popup->Flags & ImGuiWindowFlags_Modal) - return front_most_popup; - return NULL; -} - -static void ClosePopupToLevel(int remaining) -{ - ImGuiContext& g = *GImGui; - if (remaining > 0) - ImGui::FocusWindow(g.OpenPopupStack[remaining-1].Window); - else - ImGui::FocusWindow(g.OpenPopupStack[0].ParentWindow); - g.OpenPopupStack.resize(remaining); -} - -static void ClosePopup(ImGuiID id) -{ - if (!IsPopupOpen(id)) - return; - ImGuiContext& g = *GImGui; - ClosePopupToLevel(g.OpenPopupStack.Size - 1); -} - -// Close the popup we have begin-ed into. -void ImGui::CloseCurrentPopup() -{ - ImGuiContext& g = *GImGui; - int popup_idx = g.CurrentPopupStack.Size - 1; - if (popup_idx < 0 || popup_idx > g.OpenPopupStack.Size || g.CurrentPopupStack[popup_idx].PopupId != g.OpenPopupStack[popup_idx].PopupId) - return; - while (popup_idx > 0 && g.OpenPopupStack[popup_idx].Window && (g.OpenPopupStack[popup_idx].Window->Flags & ImGuiWindowFlags_ChildMenu)) - popup_idx--; - ClosePopupToLevel(popup_idx); -} - -static inline void ClearSetNextWindowData() -{ - ImGuiContext& g = *GImGui; - g.SetNextWindowPosCond = g.SetNextWindowSizeCond = g.SetNextWindowContentSizeCond = g.SetNextWindowCollapsedCond = 0; - g.SetNextWindowSizeConstraint = g.SetNextWindowFocus = false; -} - -static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - const ImGuiID id = window->GetID(str_id); - if (!IsPopupOpen(id)) - { - ClearSetNextWindowData(); // We behave like Begin() and need to consume those values - return false; - } - - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); - ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize; - - char name[20]; - if (flags & ImGuiWindowFlags_ChildMenu) - ImFormatString(name, IM_ARRAYSIZE(name), "##menu_%d", g.CurrentPopupStack.Size); // Recycle windows based on depth - else - ImFormatString(name, IM_ARRAYSIZE(name), "##popup_%08x", id); // Not recycling, so we can close/open during the same frame - - bool is_open = ImGui::Begin(name, NULL, flags); - if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) - g.CurrentWindow->Flags &= ~ImGuiWindowFlags_ShowBorders; - if (!is_open) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display) - ImGui::EndPopup(); - - return is_open; -} - -bool ImGui::BeginPopup(const char* str_id) -{ - if (GImGui->OpenPopupStack.Size <= GImGui->CurrentPopupStack.Size) // Early out for performance - { - ClearSetNextWindowData(); // We behave like Begin() and need to consume those values - return false; - } - return BeginPopupEx(str_id, ImGuiWindowFlags_ShowBorders); -} - -bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags extra_flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - const ImGuiID id = window->GetID(name); - if (!IsPopupOpen(id)) - { - ClearSetNextWindowData(); // We behave like Begin() and need to consume those values - return false; - } - - ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings; - bool is_open = ImGui::Begin(name, p_open, flags); - if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display) - { - ImGui::EndPopup(); - if (is_open) - ClosePopup(id); - return false; - } - - return is_open; -} - -void ImGui::EndPopup() -{ - ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginPopup()/EndPopup() calls - IM_ASSERT(GImGui->CurrentPopupStack.Size > 0); - ImGui::End(); - if (!(window->Flags & ImGuiWindowFlags_Modal)) - ImGui::PopStyleVar(); -} - -// This is a helper to handle the most simple case of associating one named popup to one given widget. -// 1. If you have many possible popups (for different "instances" of a same widget, or for wholly different widgets), you may be better off handling -// this yourself so you can store data relative to the widget that opened the popup instead of choosing different popup identifiers. -// 2. If you want right-clicking on the same item to reopen the popup at new location, use the same code replacing IsItemHovered() with IsItemHoveredRect() -// and passing true to the OpenPopupEx(). -// Because: hovering an item in a window below the popup won't normally trigger is hovering behavior/coloring. The pattern of ignoring the fact that -// the item isn't interactable (because it is blocked by the active popup) may useful in some situation when e.g. large canvas as one item, content of menu -// driven by click position. -bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button) -{ - if (IsItemHovered() && IsMouseClicked(mouse_button)) - OpenPopupEx(str_id, false); - return BeginPopup(str_id); -} - -bool ImGui::BeginPopupContextWindow(bool also_over_items, const char* str_id, int mouse_button) -{ - if (!str_id) str_id = "window_context_menu"; - if (IsMouseHoveringWindow() && IsMouseClicked(mouse_button)) - if (also_over_items || !IsAnyItemHovered()) - OpenPopupEx(str_id, true); - return BeginPopup(str_id); -} - -bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) -{ - if (!str_id) str_id = "void_context_menu"; - if (!IsMouseHoveringAnyWindow() && IsMouseClicked(mouse_button)) - OpenPopupEx(str_id, true); - return BeginPopup(str_id); -} - -static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) -{ - ImGuiWindow* window = ImGui::GetCurrentWindow(); - ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow; - - const ImVec2 content_avail = ImGui::GetContentRegionAvail(); - ImVec2 size = ImFloor(size_arg); - if (size.x <= 0.0f) - { - if (size.x == 0.0f) - flags |= ImGuiWindowFlags_ChildWindowAutoFitX; - size.x = ImMax(content_avail.x, 4.0f) - fabsf(size.x); // Arbitrary minimum zero-ish child size of 4.0f (0.0f causing too much issues) - } - if (size.y <= 0.0f) - { - if (size.y == 0.0f) - flags |= ImGuiWindowFlags_ChildWindowAutoFitY; - size.y = ImMax(content_avail.y, 4.0f) - fabsf(size.y); - } - if (border) - flags |= ImGuiWindowFlags_ShowBorders; - flags |= extra_flags; - - char title[256]; - if (name) - ImFormatString(title, IM_ARRAYSIZE(title), "%s.%s.%08X", window->Name, name, id); - else - ImFormatString(title, IM_ARRAYSIZE(title), "%s.%08X", window->Name, id); - - bool ret = ImGui::Begin(title, NULL, size, -1.0f, flags); - - if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) - ImGui::GetCurrentWindow()->Flags &= ~ImGuiWindowFlags_ShowBorders; - - return ret; -} - -bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - return BeginChildEx(str_id, window->GetID(str_id), size_arg, border, extra_flags); -} - -bool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) -{ - return BeginChildEx(NULL, id, size_arg, border, extra_flags); -} - -void ImGui::EndChild() -{ - ImGuiWindow* window = GetCurrentWindow(); - - IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() callss - if ((window->Flags & ImGuiWindowFlags_ComboBox) || window->BeginCount > 1) - { - ImGui::End(); - } - else - { - // When using auto-filling child window, we don't provide full width/height to ItemSize so that it doesn't feed back into automatic size-fitting. - ImVec2 sz = GetWindowSize(); - if (window->Flags & ImGuiWindowFlags_ChildWindowAutoFitX) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f - sz.x = ImMax(4.0f, sz.x); - if (window->Flags & ImGuiWindowFlags_ChildWindowAutoFitY) - sz.y = ImMax(4.0f, sz.y); - - ImGui::End(); - - window = GetCurrentWindow(); - ImRect bb(window->DC.CursorPos, window->DC.CursorPos + sz); - ItemSize(sz); - ItemAdd(bb, NULL); - } -} - -// Helper to create a child window / scrolling region that looks like a normal widget frame. -bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags) -{ - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, style.Colors[ImGuiCol_FrameBg]); - ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, style.FrameRounding); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); - return ImGui::BeginChild(id, size, (g.CurrentWindow->Flags & ImGuiWindowFlags_ShowBorders) ? true : false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding | extra_flags); -} - -void ImGui::EndChildFrame() -{ - ImGui::EndChild(); - ImGui::PopStyleVar(2); - ImGui::PopStyleColor(); -} - -// Save and compare stack sizes on Begin()/End() to detect usage errors -static void CheckStacksSize(ImGuiWindow* window, bool write) -{ - // NOT checking: DC.ItemWidth, DC.AllowKeyboardFocus, DC.ButtonRepeat, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin) - ImGuiContext& g = *GImGui; - int* p_backup = &window->DC.StackSizesBackup[0]; - { int current = window->IDStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "PushID/PopID Mismatch!"); p_backup++; } // User forgot PopID() - { int current = window->DC.GroupStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "BeginGroup/EndGroup Mismatch!"); p_backup++; } // User forgot EndGroup() - { int current = g.CurrentPopupStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "BeginMenu/EndMenu or BeginPopup/EndPopup Mismatch"); p_backup++; }// User forgot EndPopup()/EndMenu() - { int current = g.ColorModifiers.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "PushStyleColor/PopStyleColor Mismatch!"); p_backup++; } // User forgot PopStyleColor() - { int current = g.StyleModifiers.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "PushStyleVar/PopStyleVar Mismatch!"); p_backup++; } // User forgot PopStyleVar() - { int current = g.FontStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "PushFont/PopFont Mismatch!"); p_backup++; } // User forgot PopFont() - IM_ASSERT(p_backup == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup)); -} - -static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, int* last_dir, const ImRect& r_inner) -{ - const ImGuiStyle& style = GImGui->Style; - - // Clamp into visible area while not overlapping the cursor. Safety padding is optional if our popup size won't fit without it. - ImVec2 safe_padding = style.DisplaySafeAreaPadding; - ImRect r_outer(GetVisibleRect()); - r_outer.Reduce(ImVec2((size.x - r_outer.GetWidth() > safe_padding.x*2) ? safe_padding.x : 0.0f, (size.y - r_outer.GetHeight() > safe_padding.y*2) ? safe_padding.y : 0.0f)); - ImVec2 base_pos_clamped = ImClamp(base_pos, r_outer.Min, r_outer.Max - size); - - for (int n = (*last_dir != -1) ? -1 : 0; n < 4; n++) // Last, Right, down, up, left. (Favor last used direction). - { - const int dir = (n == -1) ? *last_dir : n; - ImRect rect(dir == 0 ? r_inner.Max.x : r_outer.Min.x, dir == 1 ? r_inner.Max.y : r_outer.Min.y, dir == 3 ? r_inner.Min.x : r_outer.Max.x, dir == 2 ? r_inner.Min.y : r_outer.Max.y); - if (rect.GetWidth() < size.x || rect.GetHeight() < size.y) - continue; - *last_dir = dir; - return ImVec2(dir == 0 ? r_inner.Max.x : dir == 3 ? r_inner.Min.x - size.x : base_pos_clamped.x, dir == 1 ? r_inner.Max.y : dir == 2 ? r_inner.Min.y - size.y : base_pos_clamped.y); - } - - // Fallback, try to keep within display - *last_dir = -1; - ImVec2 pos = base_pos; - pos.x = ImMax(ImMin(pos.x + size.x, r_outer.Max.x) - size.x, r_outer.Min.x); - pos.y = ImMax(ImMin(pos.y + size.y, r_outer.Max.y) - size.y, r_outer.Min.y); - return pos; -} - -ImGuiWindow* ImGui::FindWindowByName(const char* name) -{ - // FIXME-OPT: Store sorted hashes -> pointers so we can do a bissection in a contiguous block - ImGuiContext& g = *GImGui; - ImGuiID id = ImHash(name, 0); - for (int i = 0; i < g.Windows.Size; i++) - if (g.Windows[i]->ID == id) - return g.Windows[i]; - return NULL; -} - -static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags) -{ - ImGuiContext& g = *GImGui; - - // Create window the first time - ImGuiWindow* window = (ImGuiWindow*)ImGui::MemAlloc(sizeof(ImGuiWindow)); - IM_PLACEMENT_NEW(window) ImGuiWindow(name); - window->Flags = flags; - - if (flags & ImGuiWindowFlags_NoSavedSettings) - { - // User can disable loading and saving of settings. Tooltip and child windows also don't store settings. - window->Size = window->SizeFull = size; - } - else - { - // Retrieve settings from .ini file - // Use SetWindowPos() or SetNextWindowPos() with the appropriate condition flag to change the initial position of a window. - window->PosFloat = ImVec2(60, 60); - window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y); - - ImGuiIniData* settings = FindWindowSettings(name); - if (!settings) - { - settings = AddWindowSettings(name); - } - else - { - window->SetWindowPosAllowFlags &= ~ImGuiSetCond_FirstUseEver; - window->SetWindowSizeAllowFlags &= ~ImGuiSetCond_FirstUseEver; - window->SetWindowCollapsedAllowFlags &= ~ImGuiSetCond_FirstUseEver; - } - - if (settings->Pos.x != FLT_MAX) - { - window->PosFloat = settings->Pos; - window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y); - window->Collapsed = settings->Collapsed; - } - - if (ImLengthSqr(settings->Size) > 0.00001f && !(flags & ImGuiWindowFlags_NoResize)) - size = settings->Size; - window->Size = window->SizeFull = size; - } - - if ((flags & ImGuiWindowFlags_AlwaysAutoResize) != 0) - { - window->AutoFitFramesX = window->AutoFitFramesY = 2; - window->AutoFitOnlyGrows = false; - } - else - { - if (window->Size.x <= 0.0f) - window->AutoFitFramesX = 2; - if (window->Size.y <= 0.0f) - window->AutoFitFramesY = 2; - window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0); - } - - if (flags & ImGuiWindowFlags_NoBringToFrontOnFocus) - g.Windows.insert(g.Windows.begin(), window); // Quite slow but rare and only once - else - g.Windows.push_back(window); - return window; -} - -static void ApplySizeFullWithConstraint(ImGuiWindow* window, ImVec2 new_size) -{ - ImGuiContext& g = *GImGui; - if (g.SetNextWindowSizeConstraint) - { - // Using -1,-1 on either X/Y axis to preserve the current size. - ImRect cr = g.SetNextWindowSizeConstraintRect; - new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x; - new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y; - if (g.SetNextWindowSizeConstraintCallback) - { - ImGuiSizeConstraintCallbackData data; - data.UserData = g.SetNextWindowSizeConstraintCallbackUserData; - data.Pos = window->Pos; - data.CurrentSize = window->SizeFull; - data.DesiredSize = new_size; - g.SetNextWindowSizeConstraintCallback(&data); - new_size = data.DesiredSize; - } - } - if (!(window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysAutoResize))) - new_size = ImMax(new_size, g.Style.WindowMinSize); - window->SizeFull = new_size; -} - -// Push a new ImGui window to add widgets to. -// - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair. -// - Begin/End can be called multiple times during the frame with the same window name to append content. -// - 'size_on_first_use' for a regular window denote the initial size for first-time creation (no saved data) and isn't that useful. Use SetNextWindowSize() prior to calling Begin() for more flexible window manipulation. -// - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file). -// You can use the "##" or "###" markers to use the same label with different id, or same id with different label. See documentation at the top of this file. -// - Return false when window is collapsed, so you can early out in your code. You always need to call ImGui::End() even if false is returned. -// - Passing 'bool* p_open' displays a Close button on the upper-right corner of the window, the pointed value will be set to false when the button is pressed. -// - Passing non-zero 'size' is roughly equivalent to calling SetNextWindowSize(size, ImGuiSetCond_FirstUseEver) prior to calling Begin(). -bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) -{ - return ImGui::Begin(name, p_open, ImVec2(0.f, 0.f), -1.0f, flags); -} - -bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha, ImGuiWindowFlags flags) -{ - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - IM_ASSERT(name != NULL); // Window name required - IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() - IM_ASSERT(g.FrameCountEnded != g.FrameCount); // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet - - if (flags & ImGuiWindowFlags_NoInputs) - flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; - - // Find or create - bool window_is_new = false; - ImGuiWindow* window = FindWindowByName(name); - if (!window) - { - window = CreateNewWindow(name, size_on_first_use, flags); - window_is_new = true; - } - - const int current_frame = ImGui::GetFrameCount(); - const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame); - if (first_begin_of_the_frame) - window->Flags = (ImGuiWindowFlags)flags; - else - flags = window->Flags; - - // Add to stack - ImGuiWindow* parent_window = !g.CurrentWindowStack.empty() ? g.CurrentWindowStack.back() : NULL; - g.CurrentWindowStack.push_back(window); - SetCurrentWindow(window); - CheckStacksSize(window, true); - IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); - - bool window_was_active = (window->LastFrameActive == current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on - if (flags & ImGuiWindowFlags_Popup) - { - ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.CurrentPopupStack.Size]; - window_was_active &= (window->PopupId == popup_ref.PopupId); - window_was_active &= (window == popup_ref.Window); - popup_ref.Window = window; - g.CurrentPopupStack.push_back(popup_ref); - window->PopupId = popup_ref.PopupId; - } - - const bool window_appearing_after_being_hidden = (window->HiddenFrames == 1); - - // Process SetNextWindow***() calls - bool window_pos_set_by_api = false, window_size_set_by_api = false; - if (g.SetNextWindowPosCond) - { - const ImVec2 backup_cursor_pos = window->DC.CursorPos; // FIXME: not sure of the exact reason of this saving/restore anymore :( need to look into that. - if (!window_was_active || window_appearing_after_being_hidden) window->SetWindowPosAllowFlags |= ImGuiSetCond_Appearing; - window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) != 0; - if (window_pos_set_by_api && ImLengthSqr(g.SetNextWindowPosVal - ImVec2(-FLT_MAX,-FLT_MAX)) < 0.001f) - { - window->SetWindowPosCenterWanted = true; // May be processed on the next frame if this is our first frame and we are measuring size - window->SetWindowPosAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing); - } - else - { - SetWindowPos(window, g.SetNextWindowPosVal, g.SetNextWindowPosCond); - } - window->DC.CursorPos = backup_cursor_pos; - g.SetNextWindowPosCond = 0; - } - if (g.SetNextWindowSizeCond) - { - if (!window_was_active || window_appearing_after_being_hidden) window->SetWindowSizeAllowFlags |= ImGuiSetCond_Appearing; - window_size_set_by_api = (window->SetWindowSizeAllowFlags & g.SetNextWindowSizeCond) != 0; - SetWindowSize(window, g.SetNextWindowSizeVal, g.SetNextWindowSizeCond); - g.SetNextWindowSizeCond = 0; - } - if (g.SetNextWindowContentSizeCond) - { - window->SizeContentsExplicit = g.SetNextWindowContentSizeVal; - g.SetNextWindowContentSizeCond = 0; - } - else if (first_begin_of_the_frame) - { - window->SizeContentsExplicit = ImVec2(0.0f, 0.0f); - } - if (g.SetNextWindowCollapsedCond) - { - if (!window_was_active || window_appearing_after_being_hidden) window->SetWindowCollapsedAllowFlags |= ImGuiSetCond_Appearing; - SetWindowCollapsed(window, g.SetNextWindowCollapsedVal, g.SetNextWindowCollapsedCond); - g.SetNextWindowCollapsedCond = 0; - } - if (g.SetNextWindowFocus) - { - ImGui::SetWindowFocus(); - g.SetNextWindowFocus = false; - } - - // Update known root window (if we are a child window, otherwise window == window->RootWindow) - int root_idx, root_non_popup_idx; - for (root_idx = g.CurrentWindowStack.Size - 1; root_idx > 0; root_idx--) - if (!(g.CurrentWindowStack[root_idx]->Flags & ImGuiWindowFlags_ChildWindow)) - break; - for (root_non_popup_idx = root_idx; root_non_popup_idx > 0; root_non_popup_idx--) - if (!(g.CurrentWindowStack[root_non_popup_idx]->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) - break; - window->ParentWindow = parent_window; - window->RootWindow = g.CurrentWindowStack[root_idx]; - window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // This is merely for displaying the TitleBgActive color. - - // When reusing window again multiple times a frame, just append content (don't need to setup again) - if (first_begin_of_the_frame) - { - window->Active = true; - window->IndexWithinParent = 0; - window->BeginCount = 0; - window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX); - window->LastFrameActive = current_frame; - window->IDStack.resize(1); - - // Clear draw list, setup texture, outer clipping rectangle - window->DrawList->Clear(); - window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID); - ImRect fullscreen_rect(GetVisibleRect()); - if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_ComboBox|ImGuiWindowFlags_Popup))) - PushClipRect(parent_window->ClipRect.Min, parent_window->ClipRect.Max, true); - else - PushClipRect(fullscreen_rect.Min, fullscreen_rect.Max, true); - - if (!window_was_active) - { - // Popup first latch mouse position, will position itself when it appears next frame - window->AutoPosLastDirection = -1; - if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api) - window->PosFloat = g.IO.MousePos; - } - - // Collapse window by double-clicking on title bar - // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing - if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse)) - { - ImRect title_bar_rect = window->TitleBarRect(); - if (g.HoveredWindow == window && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseDoubleClicked[0]) - { - window->Collapsed = !window->Collapsed; - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - MarkIniSettingsDirty(); - FocusWindow(window); - } - } - else - { - window->Collapsed = false; - } - - // SIZE - - // Save contents size from last frame for auto-fitting (unless explicitly specified) - window->SizeContents.x = (float)(int)((window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : ((window_is_new ? 0.0f : window->DC.CursorMaxPos.x - window->Pos.x) + window->Scroll.x)); - window->SizeContents.y = (float)(int)((window->SizeContentsExplicit.y != 0.0f) ? window->SizeContentsExplicit.y : ((window_is_new ? 0.0f : window->DC.CursorMaxPos.y - window->Pos.y) + window->Scroll.y)); - - // Hide popup/tooltip window when first appearing while we measure size (because we recycle them) - if (window->HiddenFrames > 0) - window->HiddenFrames--; - if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && !window_was_active) - { - window->HiddenFrames = 1; - if (flags & ImGuiWindowFlags_AlwaysAutoResize) - { - if (!window_size_set_by_api) - window->Size = window->SizeFull = ImVec2(0.f, 0.f); - window->SizeContents = ImVec2(0.f, 0.f); - } - } - - // Lock window padding so that altering the ShowBorders flag for children doesn't have side-effects. - window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) ? ImVec2(0,0) : style.WindowPadding; - - // Calculate auto-fit size - ImVec2 size_auto_fit; - if ((flags & ImGuiWindowFlags_Tooltip) != 0) - { - // Tooltip always resize. We keep the spacing symmetric on both axises for aesthetic purpose. - size_auto_fit = window->SizeContents + window->WindowPadding - ImVec2(0.0f, style.ItemSpacing.y); - } - else - { - size_auto_fit = ImClamp(window->SizeContents + window->WindowPadding, style.WindowMinSize, ImMax(style.WindowMinSize, g.IO.DisplaySize - g.Style.DisplaySafeAreaPadding)); - - // Handling case of auto fit window not fitting in screen on one axis, we are growing auto fit size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than DisplaySize-WindowPadding. - if (size_auto_fit.x < window->SizeContents.x && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)) - size_auto_fit.y += style.ScrollbarSize; - if (size_auto_fit.y < window->SizeContents.y && !(flags & ImGuiWindowFlags_NoScrollbar)) - size_auto_fit.x += style.ScrollbarSize; - size_auto_fit.y = ImMax(size_auto_fit.y - style.ItemSpacing.y, 0.0f); - } - - // Handle automatic resize - if (window->Collapsed) - { - // We still process initial auto-fit on collapsed windows to get a window width, - // But otherwise we don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed. - if (window->AutoFitFramesX > 0) - window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x; - if (window->AutoFitFramesY > 0) - window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y; - } - else - { - if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window_size_set_by_api) - { - window->SizeFull = size_auto_fit; - } - else if ((window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) && !window_size_set_by_api) - { - // Auto-fit only grows during the first few frames - if (window->AutoFitFramesX > 0) - window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x; - if (window->AutoFitFramesY > 0) - window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y; - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - MarkIniSettingsDirty(); - } - } - - // Apply minimum/maximum window size constraints and final size - ApplySizeFullWithConstraint(window, window->SizeFull); - window->Size = window->Collapsed ? window->TitleBarRect().GetSize() : window->SizeFull; - - // POSITION - - // Position child window - if (flags & ImGuiWindowFlags_ChildWindow) - { - window->IndexWithinParent = parent_window->DC.ChildWindows.Size; - parent_window->DC.ChildWindows.push_back(window); - } - if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) - { - window->Pos = window->PosFloat = parent_window->DC.CursorPos; - window->Size = window->SizeFull = size_on_first_use; // NB: argument name 'size_on_first_use' misleading here, it's really just 'size' as provided by user passed via BeginChild()->Begin(). - } - - bool window_pos_center = false; - window_pos_center |= (window->SetWindowPosCenterWanted && window->HiddenFrames == 0); - window_pos_center |= ((flags & ImGuiWindowFlags_Modal) && !window_pos_set_by_api && window_appearing_after_being_hidden); - if (window_pos_center) - { - // Center (any sort of window) - SetWindowPos(window, ImMax(style.DisplaySafeAreaPadding, fullscreen_rect.GetCenter() - window->SizeFull * 0.5f), 0); - } - else if (flags & ImGuiWindowFlags_ChildMenu) - { - // Child menus typically request _any_ position within the parent menu item, and then our FindBestPopupWindowPos() function will move the new menu outside the parent bounds. - // This is how we end up with child menus appearing (most-commonly) on the right of the parent menu. - IM_ASSERT(window_pos_set_by_api); - float horizontal_overlap = style.ItemSpacing.x; // We want some overlap to convey the relative depth of each popup (currently the amount of overlap it is hard-coded to style.ItemSpacing.x, may need to introduce another style value). - ImRect rect_to_avoid; - if (parent_window->DC.MenuBarAppending) - rect_to_avoid = ImRect(-FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight(), FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight() + parent_window->MenuBarHeight()); - else - rect_to_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX); - window->PosFloat = FindBestPopupWindowPos(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid); - } - else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_appearing_after_being_hidden) - { - ImRect rect_to_avoid(window->PosFloat.x - 1, window->PosFloat.y - 1, window->PosFloat.x + 1, window->PosFloat.y + 1); - window->PosFloat = FindBestPopupWindowPos(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid); - } - - // Position tooltip (always follows mouse) - if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api) - { - ImRect rect_to_avoid(g.IO.MousePos.x - 16, g.IO.MousePos.y - 8, g.IO.MousePos.x + 24, g.IO.MousePos.y + 24); // FIXME: Completely hard-coded. Perhaps center on cursor hit-point instead? - window->PosFloat = FindBestPopupWindowPos(g.IO.MousePos, window->Size, &window->AutoPosLastDirection, rect_to_avoid); - if (window->AutoPosLastDirection == -1) - window->PosFloat = g.IO.MousePos + ImVec2(2,2); // If there's not enough room, for tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible. - } - - // Clamp position so it stays visible - if (!(flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip)) - { - if (!window_pos_set_by_api && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing. - { - ImVec2 padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding); - window->PosFloat = ImMax(window->PosFloat + window->Size, padding) - window->Size; - window->PosFloat = ImMin(window->PosFloat, g.IO.DisplaySize - padding); - } - } - window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y); - - // Default item width. Make it proportional to window size if window manually resizes - if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize)) - window->ItemWidthDefault = (float)(int)(window->Size.x * 0.65f); - else - window->ItemWidthDefault = (float)(int)(g.FontSize * 16.0f); - - // Prepare for focus requests - window->FocusIdxAllRequestCurrent = (window->FocusIdxAllRequestNext == INT_MAX || window->FocusIdxAllCounter == -1) ? INT_MAX : (window->FocusIdxAllRequestNext + (window->FocusIdxAllCounter+1)) % (window->FocusIdxAllCounter+1); - window->FocusIdxTabRequestCurrent = (window->FocusIdxTabRequestNext == INT_MAX || window->FocusIdxTabCounter == -1) ? INT_MAX : (window->FocusIdxTabRequestNext + (window->FocusIdxTabCounter+1)) % (window->FocusIdxTabCounter+1); - window->FocusIdxAllCounter = window->FocusIdxTabCounter = -1; - window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = INT_MAX; - - // Apply scrolling - if (window->ScrollTarget.x < FLT_MAX) - { - window->Scroll.x = window->ScrollTarget.x; - window->ScrollTarget.x = FLT_MAX; - } - if (window->ScrollTarget.y < FLT_MAX) - { - float center_ratio = window->ScrollTargetCenterRatio.y; - window->Scroll.y = window->ScrollTarget.y - ((1.0f - center_ratio) * (window->TitleBarHeight() + window->MenuBarHeight())) - (center_ratio * window->SizeFull.y); - window->ScrollTarget.y = FLT_MAX; - } - window->Scroll = ImMax(window->Scroll, ImVec2(0.0f, 0.0f)); - if (!window->Collapsed && !window->SkipItems) - window->Scroll = ImMin(window->Scroll, ImMax(ImVec2(0.0f, 0.0f), window->SizeContents - window->SizeFull + window->ScrollbarSizes)); - - // Modal window darkens what is behind them - if ((flags & ImGuiWindowFlags_Modal) != 0 && window == GetFrontMostModalRootWindow()) - window->DrawList->AddRectFilled(fullscreen_rect.Min, fullscreen_rect.Max, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); - - // Draw window + handle manual resize - ImRect title_bar_rect = window->TitleBarRect(); - const float window_rounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding; - if (window->Collapsed) - { - // Draw title bar only - RenderFrame(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(ImGuiCol_TitleBgCollapsed), true, window_rounding); - } - else - { - ImU32 resize_col = 0; - const float resize_corner_size = ImMax(g.FontSize * 1.35f, window_rounding + 1.0f + g.FontSize * 0.2f); - if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && !(flags & ImGuiWindowFlags_NoResize)) - { - // Manual resize - const ImVec2 br = window->Rect().GetBR(); - const ImRect resize_rect(br - ImVec2(resize_corner_size * 0.75f, resize_corner_size * 0.75f), br); - const ImGuiID resize_id = window->GetID("#RESIZE"); - bool hovered, held; - ButtonBehavior(resize_rect, resize_id, &hovered, &held, ImGuiButtonFlags_FlattenChilds); - resize_col = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); - - if (hovered || held) - g.MouseCursor = ImGuiMouseCursor_ResizeNWSE; - - if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0]) - { - // Manual auto-fit when double-clicking - ApplySizeFullWithConstraint(window, size_auto_fit); - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - MarkIniSettingsDirty(); - ClearActiveID(); - } - else if (held) - { - // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position - ApplySizeFullWithConstraint(window, (g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize()) - window->Pos); - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - MarkIniSettingsDirty(); - } - - window->Size = window->SizeFull; - title_bar_rect = window->TitleBarRect(); - } - - // Scrollbars - window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); - window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); - window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); - window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; - - // Window background, Default Alpha - ImGuiCol bg_color_idx = ImGuiCol_WindowBg; - if ((flags & ImGuiWindowFlags_ComboBox) != 0) - bg_color_idx = ImGuiCol_ComboBg; - else if ((flags & ImGuiWindowFlags_Tooltip) != 0 || (flags & ImGuiWindowFlags_Popup) != 0) - bg_color_idx = ImGuiCol_PopupBg; - else if ((flags & ImGuiWindowFlags_ChildWindow) != 0) - bg_color_idx = ImGuiCol_ChildWindowBg; - ImVec4 bg_color = style.Colors[bg_color_idx]; - if (bg_alpha >= 0.0f) - bg_color.w = bg_alpha; - bg_color.w *= style.Alpha; - if (bg_color.w > 0.0f) - window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImGuiCorner_All : ImGuiCorner_BottomLeft|ImGuiCorner_BottomRight); - - // Title bar - if (!(flags & ImGuiWindowFlags_NoTitleBar)) - window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32((g.FocusedWindow && window->RootNonPopupWindow == g.FocusedWindow->RootNonPopupWindow) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, ImGuiCorner_TopLeft|ImGuiCorner_TopRight); - - // Menu bar - if (flags & ImGuiWindowFlags_MenuBar) - { - ImRect menu_bar_rect = window->MenuBarRect(); - if (flags & ImGuiWindowFlags_ShowBorders) - window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border)); - window->DrawList->AddRectFilled(menu_bar_rect.GetTL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImGuiCorner_TopLeft|ImGuiCorner_TopRight); - } - - // Scrollbars - if (window->ScrollbarX) - Scrollbar(window, true); - if (window->ScrollbarY) - Scrollbar(window, false); - - // Render resize grip - // (after the input handling so we don't have a frame of latency) - if (!(flags & ImGuiWindowFlags_NoResize)) - { - const ImVec2 br = window->Rect().GetBR(); - window->DrawList->PathLineTo(br + ImVec2(-resize_corner_size, -window->BorderSize)); - window->DrawList->PathLineTo(br + ImVec2(-window->BorderSize, -resize_corner_size)); - window->DrawList->PathArcToFast(ImVec2(br.x - window_rounding - window->BorderSize, br.y - window_rounding - window->BorderSize), window_rounding, 0, 3); - window->DrawList->PathFill(resize_col); - } - - // Borders - if (flags & ImGuiWindowFlags_ShowBorders) - { - window->DrawList->AddRect(window->Pos+ImVec2(1,1), window->Pos+window->Size+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), window_rounding); - window->DrawList->AddRect(window->Pos, window->Pos+window->Size, GetColorU32(ImGuiCol_Border), window_rounding); - if (!(flags & ImGuiWindowFlags_NoTitleBar)) - window->DrawList->AddLine(title_bar_rect.GetBL()+ImVec2(1,0), title_bar_rect.GetBR()-ImVec2(1,0), GetColorU32(ImGuiCol_Border)); - } - } - - // Update ContentsRegionMax. All the variable it depends on are set above in this function. - window->ContentsRegionRect.Min.x = -window->Scroll.x + window->WindowPadding.x; - window->ContentsRegionRect.Min.y = -window->Scroll.y + window->WindowPadding.y + window->TitleBarHeight() + window->MenuBarHeight(); - window->ContentsRegionRect.Max.x = -window->Scroll.x - window->WindowPadding.x + (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : (window->Size.x - window->ScrollbarSizes.x)); - window->ContentsRegionRect.Max.y = -window->Scroll.y - window->WindowPadding.y + (window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : (window->Size.y - window->ScrollbarSizes.y)); - - // Setup drawing context - window->DC.IndentX = 0.0f + window->WindowPadding.x - window->Scroll.x; - window->DC.GroupOffsetX = 0.0f; - window->DC.ColumnsOffsetX = 0.0f; - window->DC.CursorStartPos = window->Pos + ImVec2(window->DC.IndentX + window->DC.ColumnsOffsetX, window->TitleBarHeight() + window->MenuBarHeight() + window->WindowPadding.y - window->Scroll.y); - window->DC.CursorPos = window->DC.CursorStartPos; - window->DC.CursorPosPrevLine = window->DC.CursorPos; - window->DC.CursorMaxPos = window->DC.CursorStartPos; - window->DC.CurrentLineHeight = window->DC.PrevLineHeight = 0.0f; - window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f; - window->DC.MenuBarAppending = false; - window->DC.MenuBarOffsetX = ImMax(window->WindowPadding.x, style.ItemSpacing.x); - window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; - window->DC.ChildWindows.resize(0); - window->DC.LayoutType = ImGuiLayoutType_Vertical; - window->DC.ItemWidth = window->ItemWidthDefault; - window->DC.TextWrapPos = -1.0f; // disabled - window->DC.AllowKeyboardFocus = true; - window->DC.ButtonRepeat = false; - window->DC.ItemWidthStack.resize(0); - window->DC.AllowKeyboardFocusStack.resize(0); - window->DC.ButtonRepeatStack.resize(0); - window->DC.TextWrapPosStack.resize(0); - window->DC.ColumnsCurrent = 0; - window->DC.ColumnsCount = 1; - window->DC.ColumnsStartPosY = window->DC.CursorPos.y; - window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.ColumnsStartPosY; - window->DC.TreeDepth = 0; - window->DC.StateStorage = &window->StateStorage; - window->DC.GroupStack.resize(0); - window->DC.ColorEditMode = ImGuiColorEditMode_UserSelect; - window->MenuColumns.Update(3, style.ItemSpacing.x, !window_was_active); - - if (window->AutoFitFramesX > 0) - window->AutoFitFramesX--; - if (window->AutoFitFramesY > 0) - window->AutoFitFramesY--; - - // New windows appears in front (we need to do that AFTER setting DC.CursorStartPos so our initial navigation reference rectangle can start around there) - if (!window_was_active && !(flags & ImGuiWindowFlags_NoFocusOnAppearing)) - if (!(flags & (ImGuiWindowFlags_ChildWindow|ImGuiWindowFlags_Tooltip)) || (flags & ImGuiWindowFlags_Popup)) - FocusWindow(window); - - // Title bar - if (!(flags & ImGuiWindowFlags_NoTitleBar)) - { - if (p_open != NULL) - { - const float pad = 2.0f; - const float rad = (window->TitleBarHeight() - pad*2.0f) * 0.5f; - if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-pad - rad, pad + rad), rad)) - *p_open = false; - } - - const ImVec2 text_size = CalcTextSize(name, NULL, true); - if (!(flags & ImGuiWindowFlags_NoCollapse)) - RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f); - - ImVec2 text_min = window->Pos; - ImVec2 text_max = window->Pos + ImVec2(window->Size.x, style.FramePadding.y*2 + text_size.y); - ImRect clip_rect; - clip_rect.Max = ImVec2(window->Pos.x + window->Size.x - (p_open ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x), text_max.y); // Match the size of CloseWindowButton() - float pad_left = (flags & ImGuiWindowFlags_NoCollapse) == 0 ? (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x) : style.FramePadding.x; - float pad_right = (p_open != NULL) ? (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x) : style.FramePadding.x; - if (style.WindowTitleAlign.x > 0.0f) pad_right = ImLerp(pad_right, pad_left, style.WindowTitleAlign.x); - text_min.x += pad_left; - text_max.x -= pad_right; - clip_rect.Min = ImVec2(text_min.x, window->Pos.y); - RenderTextClipped(text_min, text_max, name, NULL, &text_size, style.WindowTitleAlign, &clip_rect); - } - - // Save clipped aabb so we can access it in constant-time in FindHoveredWindow() - window->WindowRectClipped = window->Rect(); - window->WindowRectClipped.Clip(window->ClipRect); - - // Pressing CTRL+C while holding on a window copy its content to the clipboard - // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope. - // Maybe we can support CTRL+C on every element? - /* - if (g.ActiveId == move_id) - if (g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_C)) - ImGui::LogToClipboard(); - */ - } - - // Inner clipping rectangle - // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame - // Note that if our window is collapsed we will end up with a null clipping rectangle which is the correct behavior. - const ImRect title_bar_rect = window->TitleBarRect(); - const float border_size = window->BorderSize; - ImRect clip_rect; // Force round to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. - clip_rect.Min.x = ImFloor(0.5f + title_bar_rect.Min.x + ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); - clip_rect.Min.y = ImFloor(0.5f + title_bar_rect.Max.y + window->MenuBarHeight() + border_size); - clip_rect.Max.x = ImFloor(0.5f + window->Pos.x + window->Size.x - window->ScrollbarSizes.x - ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); - clip_rect.Max.y = ImFloor(0.5f + window->Pos.y + window->Size.y - window->ScrollbarSizes.y - border_size); - PushClipRect(clip_rect.Min, clip_rect.Max, true); - - // Clear 'accessed' flag last thing - if (first_begin_of_the_frame) - window->Accessed = false; - window->BeginCount++; - g.SetNextWindowSizeConstraint = false; - - // Child window can be out of sight and have "negative" clip windows. - // Mark them as collapsed so commands are skipped earlier (we can't manually collapse because they have no title bar). - if (flags & ImGuiWindowFlags_ChildWindow) - { - IM_ASSERT((flags & ImGuiWindowFlags_NoTitleBar) != 0); - window->Collapsed = parent_window && parent_window->Collapsed; - - if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) - window->Collapsed |= (window->WindowRectClipped.Min.x >= window->WindowRectClipped.Max.x || window->WindowRectClipped.Min.y >= window->WindowRectClipped.Max.y); - - // We also hide the window from rendering because we've already added its border to the command list. - // (we could perform the check earlier in the function but it is simpler at this point) - if (window->Collapsed) - window->Active = false; - } - if (style.Alpha <= 0.0f) - window->Active = false; - - // Return false if we don't intend to display anything to allow user to perform an early out optimization - window->SkipItems = (window->Collapsed || !window->Active) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0; - return !window->SkipItems; -} - -void ImGui::End() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - Columns(1, "#CloseColumns"); - PopClipRect(); // inner window clip rectangle - - // Stop logging - if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging - LogFinish(); - - // Pop - // NB: we don't clear 'window->RootWindow'. The pointer is allowed to live until the next call to Begin(). - g.CurrentWindowStack.pop_back(); - if (window->Flags & ImGuiWindowFlags_Popup) - g.CurrentPopupStack.pop_back(); - CheckStacksSize(window, false); - SetCurrentWindow(g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back()); -} - -// Vertical scrollbar -// The entire piece of code below is rather confusing because: -// - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab) -// - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar -// - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal. -static void Scrollbar(ImGuiWindow* window, bool horizontal) -{ - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(horizontal ? "#SCROLLX" : "#SCROLLY"); - - // Render background - bool other_scrollbar = (horizontal ? window->ScrollbarY : window->ScrollbarX); - float other_scrollbar_size_w = other_scrollbar ? style.ScrollbarSize : 0.0f; - const ImRect window_rect = window->Rect(); - const float border_size = window->BorderSize; - ImRect bb = horizontal - ? ImRect(window->Pos.x + border_size, window_rect.Max.y - style.ScrollbarSize, window_rect.Max.x - other_scrollbar_size_w - border_size, window_rect.Max.y - border_size) - : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + border_size, window_rect.Max.x - border_size, window_rect.Max.y - other_scrollbar_size_w - border_size); - if (!horizontal) - bb.Min.y += window->TitleBarHeight() + ((window->Flags & ImGuiWindowFlags_MenuBar) ? window->MenuBarHeight() : 0.0f); - - float window_rounding = (window->Flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding; - int window_rounding_corners; - if (horizontal) - window_rounding_corners = ImGuiCorner_BottomLeft | (other_scrollbar ? 0 : ImGuiCorner_BottomRight); - else - window_rounding_corners = (((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImGuiCorner_TopRight : 0) | (other_scrollbar ? 0 : ImGuiCorner_BottomRight); - window->DrawList->AddRectFilled(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_ScrollbarBg), window_rounding, window_rounding_corners); - bb.Reduce(ImVec2(ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f))); - - // V denote the main axis of the scrollbar - float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight(); - float scroll_v = horizontal ? window->Scroll.x : window->Scroll.y; - float win_size_avail_v = (horizontal ? window->Size.x : window->Size.y) - other_scrollbar_size_w; - float win_size_contents_v = horizontal ? window->SizeContents.x : window->SizeContents.y; - - // The grabable box size generally represent the amount visible (vs the total scrollable amount) - // But we maintain a minimum size in pixel to allow for the user to still aim inside. - const float grab_h_pixels = ImMin(ImMax(scrollbar_size_v * ImSaturate(win_size_avail_v / ImMax(win_size_contents_v, win_size_avail_v)), style.GrabMinSize), scrollbar_size_v); - const float grab_h_norm = grab_h_pixels / scrollbar_size_v; - - // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar(). - bool held = false; - bool hovered = false; - const bool previously_held = (g.ActiveId == id); - ImGui::ButtonBehavior(bb, id, &hovered, &held); - - float scroll_max = ImMax(1.0f, win_size_contents_v - win_size_avail_v); - float scroll_ratio = ImSaturate(scroll_v / scroll_max); - float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; - if (held && grab_h_norm < 1.0f) - { - float scrollbar_pos_v = horizontal ? bb.Min.x : bb.Min.y; - float mouse_pos_v = horizontal ? g.IO.MousePos.x : g.IO.MousePos.y; - float* click_delta_to_grab_center_v = horizontal ? &g.ScrollbarClickDeltaToGrabCenter.x : &g.ScrollbarClickDeltaToGrabCenter.y; - - // Click position in scrollbar normalized space (0.0f->1.0f) - const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v); - ImGui::SetHoveredID(id); - - bool seek_absolute = false; - if (!previously_held) - { - // On initial click calculate the distance between mouse and the center of the grab - if (clicked_v_norm >= grab_v_norm && clicked_v_norm <= grab_v_norm + grab_h_norm) - { - *click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm*0.5f; - } - else - { - seek_absolute = true; - *click_delta_to_grab_center_v = 0.0f; - } - } - - // Apply scroll - // It is ok to modify Scroll here because we are being called in Begin() after the calculation of SizeContents and before setting up our starting position - const float scroll_v_norm = ImSaturate((clicked_v_norm - *click_delta_to_grab_center_v - grab_h_norm*0.5f) / (1.0f - grab_h_norm)); - scroll_v = (float)(int)(0.5f + scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v)); - if (horizontal) - window->Scroll.x = scroll_v; - else - window->Scroll.y = scroll_v; - - // Update values for rendering - scroll_ratio = ImSaturate(scroll_v / scroll_max); - grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; - - // Update distance to grab now that we have seeked and saturated - if (seek_absolute) - *click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm*0.5f; - } - - // Render - const ImU32 grab_col = ImGui::GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab); - if (horizontal) - window->DrawList->AddRectFilled(ImVec2(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y), ImVec2(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, bb.Max.y), grab_col, style.ScrollbarRounding); - else - window->DrawList->AddRectFilled(ImVec2(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm)), ImVec2(bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels), grab_col, style.ScrollbarRounding); -} - -// Moving window to front of display (which happens to be back of our sorted list) -void ImGui::FocusWindow(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - - // Always mark the window we passed as focused. This is used for keyboard interactions such as tabbing. - g.FocusedWindow = window; - - // Passing NULL allow to disable keyboard focus - if (!window) - return; - - // And move its root window to the top of the pile - if (window->RootWindow) - window = window->RootWindow; - - // Steal focus on active widgets - if (window->Flags & ImGuiWindowFlags_Popup) // FIXME: This statement should be unnecessary. Need further testing before removing it.. - if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != window) - ClearActiveID(); - - // Bring to front - if ((window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) || g.Windows.back() == window) - return; - for (int i = 0; i < g.Windows.Size; i++) - if (g.Windows[i] == window) - { - g.Windows.erase(g.Windows.begin() + i); - break; - } - g.Windows.push_back(window); -} - -void ImGui::PushItemWidth(float item_width) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width); - window->DC.ItemWidthStack.push_back(window->DC.ItemWidth); -} - -static void PushMultiItemsWidths(int components, float w_full) -{ - ImGuiWindow* window = ImGui::GetCurrentWindow(); - const ImGuiStyle& style = GImGui->Style; - if (w_full <= 0.0f) - w_full = ImGui::CalcItemWidth(); - const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); - const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); - window->DC.ItemWidthStack.push_back(w_item_last); - for (int i = 0; i < components-1; i++) - window->DC.ItemWidthStack.push_back(w_item_one); - window->DC.ItemWidth = window->DC.ItemWidthStack.back(); -} - -void ImGui::PopItemWidth() -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.ItemWidthStack.pop_back(); - window->DC.ItemWidth = window->DC.ItemWidthStack.empty() ? window->ItemWidthDefault : window->DC.ItemWidthStack.back(); -} - -float ImGui::CalcItemWidth() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - float w = window->DC.ItemWidth; - if (w < 0.0f) - { - // Align to a right-side limit. We include 1 frame padding in the calculation because this is how the width is always used (we add 2 frame padding to it), but we could move that responsibility to the widget as well. - float width_to_right_edge = GetContentRegionAvail().x; - w = ImMax(1.0f, width_to_right_edge + w); - } - w = (float)(int)w; - return w; -} - -static ImFont* GetDefaultFont() -{ - ImGuiContext& g = *GImGui; - return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; -} - -static void SetCurrentFont(ImFont* font) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(font && font->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? - IM_ASSERT(font->Scale > 0.0f); - g.Font = font; - g.FontBaseSize = g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale; - g.FontSize = g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f; - g.FontTexUvWhitePixel = g.Font->ContainerAtlas->TexUvWhitePixel; -} - -void ImGui::PushFont(ImFont* font) -{ - ImGuiContext& g = *GImGui; - if (!font) - font = GetDefaultFont(); - SetCurrentFont(font); - g.FontStack.push_back(font); - g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID); -} - -void ImGui::PopFont() -{ - ImGuiContext& g = *GImGui; - g.CurrentWindow->DrawList->PopTextureID(); - g.FontStack.pop_back(); - SetCurrentFont(g.FontStack.empty() ? GetDefaultFont() : g.FontStack.back()); -} - -void ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.AllowKeyboardFocus = allow_keyboard_focus; - window->DC.AllowKeyboardFocusStack.push_back(allow_keyboard_focus); -} - -void ImGui::PopAllowKeyboardFocus() -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.AllowKeyboardFocusStack.pop_back(); - window->DC.AllowKeyboardFocus = window->DC.AllowKeyboardFocusStack.empty() ? true : window->DC.AllowKeyboardFocusStack.back(); -} - -void ImGui::PushButtonRepeat(bool repeat) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.ButtonRepeat = repeat; - window->DC.ButtonRepeatStack.push_back(repeat); -} - -void ImGui::PopButtonRepeat() -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.ButtonRepeatStack.pop_back(); - window->DC.ButtonRepeat = window->DC.ButtonRepeatStack.empty() ? false : window->DC.ButtonRepeatStack.back(); -} - -void ImGui::PushTextWrapPos(float wrap_pos_x) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.TextWrapPos = wrap_pos_x; - window->DC.TextWrapPosStack.push_back(wrap_pos_x); -} - -void ImGui::PopTextWrapPos() -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.TextWrapPosStack.pop_back(); - window->DC.TextWrapPos = window->DC.TextWrapPosStack.empty() ? -1.0f : window->DC.TextWrapPosStack.back(); -} - -void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col) -{ - ImGuiContext& g = *GImGui; - ImGuiColMod backup; - backup.Col = idx; - backup.BackupValue = g.Style.Colors[idx]; - g.ColorModifiers.push_back(backup); - g.Style.Colors[idx] = col; -} - -void ImGui::PopStyleColor(int count) -{ - ImGuiContext& g = *GImGui; - while (count > 0) - { - ImGuiColMod& backup = g.ColorModifiers.back(); - g.Style.Colors[backup.Col] = backup.BackupValue; - g.ColorModifiers.pop_back(); - count--; - } -} - -struct ImGuiStyleVarInfo -{ - ImGuiDataType Type; - ImU32 Offset; - void* GetVarPtr() const { return (void*)((unsigned char*)&GImGui->Style + Offset); } -}; - -static const ImGuiStyleVarInfo GStyleVarInfo[ImGuiStyleVar_Count_] = -{ - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) }, - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) }, - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) }, - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) }, - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildWindowRounding) }, - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding) }, - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding) }, - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) }, - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) }, - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) }, - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) }, - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) }, -}; - -static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx) -{ - IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_Count_); - return &GStyleVarInfo[idx]; -} - -void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) -{ - const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); - if (var_info->Type == ImGuiDataType_Float) - { - float* pvar = (float*)var_info->GetVarPtr(); - GImGui->StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar)); - *pvar = val; - return; - } - IM_ASSERT(0); // Called function with wrong-type? Variable is not a float. -} - -void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) -{ - const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); - if (var_info->Type == ImGuiDataType_Float2) - { - ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(); - GImGui->StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar)); - *pvar = val; - return; - } - IM_ASSERT(0); // Called function with wrong-type? Variable is not a ImVec2. -} - -void ImGui::PopStyleVar(int count) -{ - ImGuiContext& g = *GImGui; - while (count > 0) - { - ImGuiStyleMod& backup = g.StyleModifiers.back(); - const ImGuiStyleVarInfo* info = GetStyleVarInfo(backup.VarIdx); - if (info->Type == ImGuiDataType_Float) (*(float*)info->GetVarPtr()) = backup.BackupFloat[0]; - else if (info->Type == ImGuiDataType_Float2) (*(ImVec2*)info->GetVarPtr()) = ImVec2(backup.BackupFloat[0], backup.BackupFloat[1]); - else if (info->Type == ImGuiDataType_Int) (*(int*)info->GetVarPtr()) = backup.BackupInt[0]; - g.StyleModifiers.pop_back(); - count--; - } -} - -const char* ImGui::GetStyleColName(ImGuiCol idx) -{ - // Create switch-case from enum with regexp: ImGuiCol_{.*}, --> case ImGuiCol_\1: return "\1"; - switch (idx) - { - case ImGuiCol_Text: return "Text"; - case ImGuiCol_TextDisabled: return "TextDisabled"; - case ImGuiCol_WindowBg: return "WindowBg"; - case ImGuiCol_ChildWindowBg: return "ChildWindowBg"; - case ImGuiCol_PopupBg: return "PopupBg"; - case ImGuiCol_Border: return "Border"; - case ImGuiCol_BorderShadow: return "BorderShadow"; - case ImGuiCol_FrameBg: return "FrameBg"; - case ImGuiCol_FrameBgHovered: return "FrameBgHovered"; - case ImGuiCol_FrameBgActive: return "FrameBgActive"; - case ImGuiCol_TitleBg: return "TitleBg"; - case ImGuiCol_TitleBgCollapsed: return "TitleBgCollapsed"; - case ImGuiCol_TitleBgActive: return "TitleBgActive"; - case ImGuiCol_MenuBarBg: return "MenuBarBg"; - case ImGuiCol_ScrollbarBg: return "ScrollbarBg"; - case ImGuiCol_ScrollbarGrab: return "ScrollbarGrab"; - case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered"; - case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive"; - case ImGuiCol_ComboBg: return "ComboBg"; - case ImGuiCol_CheckMark: return "CheckMark"; - case ImGuiCol_SliderGrab: return "SliderGrab"; - case ImGuiCol_SliderGrabActive: return "SliderGrabActive"; - case ImGuiCol_Button: return "Button"; - case ImGuiCol_ButtonHovered: return "ButtonHovered"; - case ImGuiCol_ButtonActive: return "ButtonActive"; - case ImGuiCol_Header: return "Header"; - case ImGuiCol_HeaderHovered: return "HeaderHovered"; - case ImGuiCol_HeaderActive: return "HeaderActive"; - case ImGuiCol_Column: return "Column"; - case ImGuiCol_ColumnHovered: return "ColumnHovered"; - case ImGuiCol_ColumnActive: return "ColumnActive"; - case ImGuiCol_ResizeGrip: return "ResizeGrip"; - case ImGuiCol_ResizeGripHovered: return "ResizeGripHovered"; - case ImGuiCol_ResizeGripActive: return "ResizeGripActive"; - case ImGuiCol_CloseButton: return "CloseButton"; - case ImGuiCol_CloseButtonHovered: return "CloseButtonHovered"; - case ImGuiCol_CloseButtonActive: return "CloseButtonActive"; - case ImGuiCol_PlotLines: return "PlotLines"; - case ImGuiCol_PlotLinesHovered: return "PlotLinesHovered"; - case ImGuiCol_PlotHistogram: return "PlotHistogram"; - case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered"; - case ImGuiCol_TextSelectedBg: return "TextSelectedBg"; - case ImGuiCol_ModalWindowDarkening: return "ModalWindowDarkening"; - } - IM_ASSERT(0); - return "Unknown"; -} - -bool ImGui::IsWindowHovered() -{ - ImGuiContext& g = *GImGui; - return g.HoveredWindow == g.CurrentWindow && IsWindowContentHoverable(g.HoveredRootWindow); -} - -bool ImGui::IsWindowFocused() -{ - ImGuiContext& g = *GImGui; - return g.FocusedWindow == g.CurrentWindow; -} - -bool ImGui::IsRootWindowFocused() -{ - ImGuiContext& g = *GImGui; - return g.FocusedWindow == g.CurrentWindow->RootWindow; -} - -bool ImGui::IsRootWindowOrAnyChildFocused() -{ - ImGuiContext& g = *GImGui; - return g.FocusedWindow && g.FocusedWindow->RootWindow == g.CurrentWindow->RootWindow; -} - -bool ImGui::IsRootWindowOrAnyChildHovered() -{ - ImGuiContext& g = *GImGui; - return g.HoveredRootWindow && (g.HoveredRootWindow == g.CurrentWindow->RootWindow) && IsWindowContentHoverable(g.HoveredRootWindow); -} - -float ImGui::GetWindowWidth() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->Size.x; -} - -float ImGui::GetWindowHeight() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->Size.y; -} - -ImVec2 ImGui::GetWindowPos() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - return window->Pos; -} - -static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y) -{ - window->DC.CursorMaxPos.y += window->Scroll.y; - window->Scroll.y = new_scroll_y; - window->DC.CursorMaxPos.y -= window->Scroll.y; -} - -static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiSetCond cond) -{ - // Test condition (NB: bit 0 is always true) and clear flags for next time - if (cond && (window->SetWindowPosAllowFlags & cond) == 0) - return; - window->SetWindowPosAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing); - window->SetWindowPosCenterWanted = false; - - // Set - const ImVec2 old_pos = window->Pos; - window->PosFloat = pos; - window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y); - window->DC.CursorPos += (window->Pos - old_pos); // As we happen to move the window while it is being appended to (which is a bad idea - will smear) let's at least offset the cursor - window->DC.CursorMaxPos += (window->Pos - old_pos); // And more importantly we need to adjust this so size calculation doesn't get affected. -} - -void ImGui::SetWindowPos(const ImVec2& pos, ImGuiSetCond cond) -{ - ImGuiWindow* window = GetCurrentWindowRead(); - SetWindowPos(window, pos, cond); -} - -void ImGui::SetWindowPos(const char* name, const ImVec2& pos, ImGuiSetCond cond) -{ - if (ImGuiWindow* window = FindWindowByName(name)) - SetWindowPos(window, pos, cond); -} - -ImVec2 ImGui::GetWindowSize() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->Size; -} - -static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiSetCond cond) -{ - // Test condition (NB: bit 0 is always true) and clear flags for next time - if (cond && (window->SetWindowSizeAllowFlags & cond) == 0) - return; - window->SetWindowSizeAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing); - - // Set - if (size.x > 0.0f) - { - window->AutoFitFramesX = 0; - window->SizeFull.x = size.x; - } - else - { - window->AutoFitFramesX = 2; - window->AutoFitOnlyGrows = false; - } - if (size.y > 0.0f) - { - window->AutoFitFramesY = 0; - window->SizeFull.y = size.y; - } - else - { - window->AutoFitFramesY = 2; - window->AutoFitOnlyGrows = false; - } -} - -void ImGui::SetWindowSize(const ImVec2& size, ImGuiSetCond cond) -{ - SetWindowSize(GImGui->CurrentWindow, size, cond); -} - -void ImGui::SetWindowSize(const char* name, const ImVec2& size, ImGuiSetCond cond) -{ - ImGuiWindow* window = FindWindowByName(name); - if (window) - SetWindowSize(window, size, cond); -} - -static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiSetCond cond) -{ - // Test condition (NB: bit 0 is always true) and clear flags for next time - if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0) - return; - window->SetWindowCollapsedAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing); - - // Set - window->Collapsed = collapsed; -} - -void ImGui::SetWindowCollapsed(bool collapsed, ImGuiSetCond cond) -{ - SetWindowCollapsed(GImGui->CurrentWindow, collapsed, cond); -} - -bool ImGui::IsWindowCollapsed() -{ - return GImGui->CurrentWindow->Collapsed; -} - -void ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiSetCond cond) -{ - ImGuiWindow* window = FindWindowByName(name); - if (window) - SetWindowCollapsed(window, collapsed, cond); -} - -void ImGui::SetWindowFocus() -{ - FocusWindow(GImGui->CurrentWindow); -} - -void ImGui::SetWindowFocus(const char* name) -{ - if (name) - { - if (ImGuiWindow* window = FindWindowByName(name)) - FocusWindow(window); - } - else - { - FocusWindow(NULL); - } -} - -void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiSetCond cond) -{ - ImGuiContext& g = *GImGui; - g.SetNextWindowPosVal = pos; - g.SetNextWindowPosCond = cond ? cond : ImGuiSetCond_Always; -} - -void ImGui::SetNextWindowPosCenter(ImGuiSetCond cond) -{ - ImGuiContext& g = *GImGui; - g.SetNextWindowPosVal = ImVec2(-FLT_MAX, -FLT_MAX); - g.SetNextWindowPosCond = cond ? cond : ImGuiSetCond_Always; -} - -void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiSetCond cond) -{ - ImGuiContext& g = *GImGui; - g.SetNextWindowSizeVal = size; - g.SetNextWindowSizeCond = cond ? cond : ImGuiSetCond_Always; -} - -void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback, void* custom_callback_user_data) -{ - ImGuiContext& g = *GImGui; - g.SetNextWindowSizeConstraint = true; - g.SetNextWindowSizeConstraintRect = ImRect(size_min, size_max); - g.SetNextWindowSizeConstraintCallback = custom_callback; - g.SetNextWindowSizeConstraintCallbackUserData = custom_callback_user_data; -} - -void ImGui::SetNextWindowContentSize(const ImVec2& size) -{ - ImGuiContext& g = *GImGui; - g.SetNextWindowContentSizeVal = size; - g.SetNextWindowContentSizeCond = ImGuiSetCond_Always; -} - -void ImGui::SetNextWindowContentWidth(float width) -{ - ImGuiContext& g = *GImGui; - g.SetNextWindowContentSizeVal = ImVec2(width, g.SetNextWindowContentSizeCond ? g.SetNextWindowContentSizeVal.y : 0.0f); - g.SetNextWindowContentSizeCond = ImGuiSetCond_Always; -} - -void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiSetCond cond) -{ - ImGuiContext& g = *GImGui; - g.SetNextWindowCollapsedVal = collapsed; - g.SetNextWindowCollapsedCond = cond ? cond : ImGuiSetCond_Always; -} - -void ImGui::SetNextWindowFocus() -{ - ImGuiContext& g = *GImGui; - g.SetNextWindowFocus = true; -} - -// In window space (not screen space!) -ImVec2 ImGui::GetContentRegionMax() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - ImVec2 mx = window->ContentsRegionRect.Max; - if (window->DC.ColumnsCount != 1) - mx.x = GetColumnOffset(window->DC.ColumnsCurrent + 1) - window->WindowPadding.x; - return mx; -} - -ImVec2 ImGui::GetContentRegionAvail() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return GetContentRegionMax() - (window->DC.CursorPos - window->Pos); -} - -float ImGui::GetContentRegionAvailWidth() -{ - return GetContentRegionAvail().x; -} - -// In window space (not screen space!) -ImVec2 ImGui::GetWindowContentRegionMin() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->ContentsRegionRect.Min; -} - -ImVec2 ImGui::GetWindowContentRegionMax() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->ContentsRegionRect.Max; -} - -float ImGui::GetWindowContentRegionWidth() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->ContentsRegionRect.Max.x - window->ContentsRegionRect.Min.x; -} - -float ImGui::GetTextLineHeight() -{ - ImGuiContext& g = *GImGui; - return g.FontSize; -} - -float ImGui::GetTextLineHeightWithSpacing() -{ - ImGuiContext& g = *GImGui; - return g.FontSize + g.Style.ItemSpacing.y; -} - -float ImGui::GetItemsLineHeightWithSpacing() -{ - ImGuiContext& g = *GImGui; - return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y; -} - -ImDrawList* ImGui::GetWindowDrawList() -{ - ImGuiWindow* window = GetCurrentWindow(); - return window->DrawList; -} - -ImFont* ImGui::GetFont() -{ - return GImGui->Font; -} - -float ImGui::GetFontSize() -{ - return GImGui->FontSize; -} - -ImVec2 ImGui::GetFontTexUvWhitePixel() -{ - return GImGui->FontTexUvWhitePixel; -} - -void ImGui::SetWindowFontScale(float scale) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - window->FontWindowScale = scale; - g.FontSize = window->CalcFontSize(); -} - -// User generally sees positions in window coordinates. Internally we store CursorPos in absolute screen coordinates because it is more convenient. -// Conversion happens as we pass the value to user, but it makes our naming convention confusing because GetCursorPos() == (DC.CursorPos - window.Pos). May want to rename 'DC.CursorPos'. -ImVec2 ImGui::GetCursorPos() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.CursorPos - window->Pos + window->Scroll; -} - -float ImGui::GetCursorPosX() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.CursorPos.x - window->Pos.x + window->Scroll.x; -} - -float ImGui::GetCursorPosY() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.CursorPos.y - window->Pos.y + window->Scroll.y; -} - -void ImGui::SetCursorPos(const ImVec2& local_pos) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.CursorPos = window->Pos - window->Scroll + local_pos; - window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos); -} - -void ImGui::SetCursorPosX(float x) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x; - window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPos.x); -} - -void ImGui::SetCursorPosY(float y) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y; - window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y); -} - -ImVec2 ImGui::GetCursorStartPos() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.CursorStartPos - window->Pos; -} - -ImVec2 ImGui::GetCursorScreenPos() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.CursorPos; -} - -void ImGui::SetCursorScreenPos(const ImVec2& screen_pos) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.CursorPos = screen_pos; - window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos); -} - -float ImGui::GetScrollX() -{ - return GImGui->CurrentWindow->Scroll.x; -} - -float ImGui::GetScrollY() -{ - return GImGui->CurrentWindow->Scroll.y; -} - -float ImGui::GetScrollMaxX() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->SizeContents.x - window->SizeFull.x - window->ScrollbarSizes.x; -} - -float ImGui::GetScrollMaxY() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->SizeContents.y - window->SizeFull.y - window->ScrollbarSizes.y; -} - -void ImGui::SetScrollX(float scroll_x) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->ScrollTarget.x = scroll_x; - window->ScrollTargetCenterRatio.x = 0.0f; -} - -void ImGui::SetScrollY(float scroll_y) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->ScrollTarget.y = scroll_y + window->TitleBarHeight() + window->MenuBarHeight(); // title bar height canceled out when using ScrollTargetRelY - window->ScrollTargetCenterRatio.y = 0.0f; -} - -void ImGui::SetScrollFromPosY(float pos_y, float center_y_ratio) -{ - // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size - ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); - window->ScrollTarget.y = (float)(int)(pos_y + window->Scroll.y); - if (center_y_ratio <= 0.0f && window->ScrollTarget.y <= window->WindowPadding.y) // Minor hack to make "scroll to top" take account of WindowPadding, else it would scroll to (WindowPadding.y - ItemSpacing.y) - window->ScrollTarget.y = 0.0f; - window->ScrollTargetCenterRatio.y = center_y_ratio; -} - -// center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item. -void ImGui::SetScrollHere(float center_y_ratio) -{ - ImGuiWindow* window = GetCurrentWindow(); - float target_y = window->DC.CursorPosPrevLine.y + (window->DC.PrevLineHeight * center_y_ratio) + (GImGui->Style.ItemSpacing.y * (center_y_ratio - 0.5f) * 2.0f); // Precisely aim above, in the middle or below the last line. - SetScrollFromPosY(target_y - window->Pos.y, center_y_ratio); -} - -void ImGui::SetKeyboardFocusHere(int offset) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->FocusIdxAllRequestNext = window->FocusIdxAllCounter + 1 + offset; - window->FocusIdxTabRequestNext = INT_MAX; -} - -void ImGui::SetStateStorage(ImGuiStorage* tree) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.StateStorage = tree ? tree : &window->StateStorage; -} - -ImGuiStorage* ImGui::GetStateStorage() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.StateStorage; -} - -void ImGui::TextV(const char* fmt, va_list args) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); - TextUnformatted(g.TempBuffer, text_end); -} - -void ImGui::Text(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - TextV(fmt, args); - va_end(args); -} - -void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args) -{ - PushStyleColor(ImGuiCol_Text, col); - TextV(fmt, args); - PopStyleColor(); -} - -void ImGui::TextColored(const ImVec4& col, const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - TextColoredV(col, fmt, args); - va_end(args); -} - -void ImGui::TextDisabledV(const char* fmt, va_list args) -{ - PushStyleColor(ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled]); - TextV(fmt, args); - PopStyleColor(); -} - -void ImGui::TextDisabled(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - TextDisabledV(fmt, args); - va_end(args); -} - -void ImGui::TextWrappedV(const char* fmt, va_list args) -{ - bool need_wrap = (GImGui->CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position is one ia already set - if (need_wrap) PushTextWrapPos(0.0f); - TextV(fmt, args); - if (need_wrap) PopTextWrapPos(); -} - -void ImGui::TextWrapped(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - TextWrappedV(fmt, args); - va_end(args); -} - -void ImGui::TextUnformatted(const char* text, const char* text_end) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - IM_ASSERT(text != NULL); - const char* text_begin = text; - if (text_end == NULL) - text_end = text + strlen(text); // FIXME-OPT - - const float wrap_pos_x = window->DC.TextWrapPos; - const bool wrap_enabled = wrap_pos_x >= 0.0f; - if (text_end - text > 2000 && !wrap_enabled) - { - // Long text! - // Perform manual coarse clipping to optimize for long multi-line text - // From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled. - // We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line. - const char* line = text; - const float line_height = GetTextLineHeight(); - const ImVec2 text_pos = window->DC.CursorPos + ImVec2(0.0f, window->DC.CurrentLineTextBaseOffset); - const ImRect clip_rect = window->ClipRect; - ImVec2 text_size(0,0); - - if (text_pos.y <= clip_rect.Max.y) - { - ImVec2 pos = text_pos; - - // Lines to skip (can't skip when logging text) - if (!g.LogEnabled) - { - int lines_skippable = (int)((clip_rect.Min.y - text_pos.y) / line_height); - if (lines_skippable > 0) - { - int lines_skipped = 0; - while (line < text_end && lines_skipped < lines_skippable) - { - const char* line_end = strchr(line, '\n'); - if (!line_end) - line_end = text_end; - line = line_end + 1; - lines_skipped++; - } - pos.y += lines_skipped * line_height; - } - } - - // Lines to render - if (line < text_end) - { - ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height)); - while (line < text_end) - { - const char* line_end = strchr(line, '\n'); - if (IsClippedEx(line_rect, NULL, false)) - break; - - const ImVec2 line_size = CalcTextSize(line, line_end, false); - text_size.x = ImMax(text_size.x, line_size.x); - RenderText(pos, line, line_end, false); - if (!line_end) - line_end = text_end; - line = line_end + 1; - line_rect.Min.y += line_height; - line_rect.Max.y += line_height; - pos.y += line_height; - } - - // Count remaining lines - int lines_skipped = 0; - while (line < text_end) - { - const char* line_end = strchr(line, '\n'); - if (!line_end) - line_end = text_end; - line = line_end + 1; - lines_skipped++; - } - pos.y += lines_skipped * line_height; - } - - text_size.y += (pos - text_pos).y; - } - - ImRect bb(text_pos, text_pos + text_size); - ItemSize(bb); - ItemAdd(bb, NULL); - } - else - { - const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f; - const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width); - - // Account of baseline offset - ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrentLineTextBaseOffset); - ImRect bb(text_pos, text_pos + text_size); - ItemSize(text_size); - if (!ItemAdd(bb, NULL)) - return; - - // Render (we don't hide text after ## in this end-user function) - RenderTextWrapped(bb.Min, text_begin, text_end, wrap_width); - } -} - -void ImGui::AlignFirstTextHeightToWidgets() -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - // Declare a dummy item size to that upcoming items that are smaller will center-align on the newly expanded line height. - ImGuiContext& g = *GImGui; - ItemSize(ImVec2(0, g.FontSize + g.Style.FramePadding.y*2), g.Style.FramePadding.y); - SameLine(0, 0); -} - -// Add a label+text combo aligned to other label+value widgets -void ImGui::LabelTextV(const char* label, const char* fmt, va_list args) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const float w = CalcItemWidth(); - - const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2)); - const ImRect total_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y*2) + label_size); - ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, NULL)) - return; - - // Render - const char* value_text_begin = &g.TempBuffer[0]; - const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); - RenderTextClipped(value_bb.Min, value_bb.Max, value_text_begin, value_text_end, NULL, ImVec2(0.0f,0.5f)); - if (label_size.x > 0.0f) - RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label); -} - -void ImGui::LabelText(const char* label, const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - LabelTextV(label, fmt, args); - va_end(args); -} - -static inline bool IsWindowContentHoverable(ImGuiWindow* window) -{ - // An active popup disable hovering on other windows (apart from its own children) - ImGuiContext& g = *GImGui; - if (ImGuiWindow* focused_window = g.FocusedWindow) - if (ImGuiWindow* focused_root_window = focused_window->RootWindow) - if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) != 0 && focused_root_window->WasActive && focused_root_window != window->RootWindow) - return false; - - return true; -} - -bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - - if (flags & ImGuiButtonFlags_Disabled) - { - if (out_hovered) *out_hovered = false; - if (out_held) *out_held = false; - if (g.ActiveId == id) ClearActiveID(); - return false; - } - - if ((flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick)) == 0) - flags |= ImGuiButtonFlags_PressedOnClickRelease; - - bool pressed = false; - bool hovered = IsHovered(bb, id, (flags & ImGuiButtonFlags_FlattenChilds) != 0); - if (hovered) - { - SetHoveredID(id); - if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt)) - { - // | CLICKING | HOLDING with ImGuiButtonFlags_Repeat - // PressedOnClickRelease | * | .. (NOT on release) <-- MOST COMMON! (*) only if both click/release were over bounds - // PressedOnClick | | .. - // PressedOnRelease | | .. (NOT on release) - // PressedOnDoubleClick | | .. - if ((flags & ImGuiButtonFlags_PressedOnClickRelease) && g.IO.MouseClicked[0]) - { - SetActiveID(id, window); // Hold on ID - FocusWindow(window); - g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; - } - if (((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0])) - { - pressed = true; - ClearActiveID(); - FocusWindow(window); - } - if ((flags & ImGuiButtonFlags_PressedOnRelease) && g.IO.MouseReleased[0]) - { - if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps - pressed = true; - ClearActiveID(); - } - - // 'Repeat' mode acts when held regardless of _PressedOn flags (see table above). - // Relies on repeat logic of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings. - if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && g.IO.MouseDownDuration[0] > 0.0f && IsMouseClicked(0, true)) - pressed = true; - } - } - - bool held = false; - if (g.ActiveId == id) - { - if (g.IO.MouseDown[0]) - { - held = true; - } - else - { - if (hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease)) - if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps - pressed = true; - ClearActiveID(); - } - } - - // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one. - if (hovered && (flags & ImGuiButtonFlags_AllowOverlapMode) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) - hovered = pressed = held = false; - - if (out_hovered) *out_hovered = hovered; - if (out_held) *out_held = held; - - return pressed; -} - -bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const ImVec2 label_size = CalcTextSize(label, NULL, true); - - ImVec2 pos = window->DC.CursorPos; - if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrentLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag) - pos.y += window->DC.CurrentLineTextBaseOffset - style.FramePadding.y; - ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f); - - const ImRect bb(pos, pos + size); - ItemSize(bb, style.FramePadding.y); - if (!ItemAdd(bb, &id)) - return false; - - if (window->DC.ButtonRepeat) flags |= ImGuiButtonFlags_Repeat; - bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); - - // Render - const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); - RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); - RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb); - - // Automatically close popups - //if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup)) - // CloseCurrentPopup(); - - return pressed; -} - -bool ImGui::Button(const char* label, const ImVec2& size_arg) -{ - return ButtonEx(label, size_arg, 0); -} - -// Small buttons fits within text without additional vertical spacing. -bool ImGui::SmallButton(const char* label) -{ - ImGuiContext& g = *GImGui; - float backup_padding_y = g.Style.FramePadding.y; - g.Style.FramePadding.y = 0.0f; - bool pressed = ButtonEx(label, ImVec2(0,0), ImGuiButtonFlags_AlignTextBaseLine); - g.Style.FramePadding.y = backup_padding_y; - return pressed; -} - -// Tip: use ImGui::PushID()/PopID() to push indices or pointers in the ID stack. -// Then you can keep 'str_id' empty or the same for all your buttons (instead of creating a string based on a non-string id) -bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - const ImGuiID id = window->GetID(str_id); - ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f); - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); - ItemSize(bb); - if (!ItemAdd(bb, &id)) - return false; - - bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held); - - return pressed; -} - -// Upper-right button to close a window. -bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) -{ - ImGuiWindow* window = GetCurrentWindow(); - - const ImRect bb(pos - ImVec2(radius,radius), pos + ImVec2(radius,radius)); - - bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held); - - // Render - const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton); - const ImVec2 center = bb.GetCenter(); - window->DrawList->AddCircleFilled(center, ImMax(2.0f, radius), col, 12); - - const float cross_extent = (radius * 0.7071f) - 1.0f; - if (hovered) - { - window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), GetColorU32(ImGuiCol_Text)); - window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), GetColorU32(ImGuiCol_Text)); - } - - return pressed; -} - -void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); - if (border_col.w > 0.0f) - bb.Max += ImVec2(2,2); - ItemSize(bb); - if (!ItemAdd(bb, NULL)) - return; - - if (border_col.w > 0.0f) - { - window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(border_col), 0.0f); - window->DrawList->AddImage(user_texture_id, bb.Min+ImVec2(1,1), bb.Max-ImVec2(1,1), uv0, uv1, GetColorU32(tint_col)); - } - else - { - window->DrawList->AddImage(user_texture_id, bb.Min, bb.Max, uv0, uv1, GetColorU32(tint_col)); - } -} - -// frame_padding < 0: uses FramePadding from style (default) -// frame_padding = 0: no framing -// frame_padding > 0: set framing size -// The color used are the button colors. -bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - - // Default to using texture ID as ID. User can still push string/integer prefixes. - // We could hash the size/uv to create a unique ID but that would prevent the user from animating UV. - PushID((void *)user_texture_id); - const ImGuiID id = window->GetID("#image"); - PopID(); - - const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : style.FramePadding; - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding*2); - const ImRect image_bb(window->DC.CursorPos + padding, window->DC.CursorPos + padding + size); - ItemSize(bb); - if (!ItemAdd(bb, &id)) - return false; - - bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held); - - // Render - const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); - RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, style.FrameRounding)); - if (bg_col.w > 0.0f) - window->DrawList->AddRectFilled(image_bb.Min, image_bb.Max, GetColorU32(bg_col)); - window->DrawList->AddImage(user_texture_id, image_bb.Min, image_bb.Max, uv0, uv1, GetColorU32(tint_col)); - - return pressed; -} - -// Start logging ImGui output to TTY -void ImGui::LogToTTY(int max_depth) -{ - ImGuiContext& g = *GImGui; - if (g.LogEnabled) - return; - ImGuiWindow* window = GetCurrentWindowRead(); - - g.LogEnabled = true; - g.LogFile = stdout; - g.LogStartDepth = window->DC.TreeDepth; - if (max_depth >= 0) - g.LogAutoExpandMaxDepth = max_depth; -} - -// Start logging ImGui output to given file -void ImGui::LogToFile(int max_depth, const char* filename) -{ - ImGuiContext& g = *GImGui; - if (g.LogEnabled) - return; - ImGuiWindow* window = GetCurrentWindowRead(); - - if (!filename) - { - filename = g.IO.LogFilename; - if (!filename) - return; - } - - g.LogFile = ImFileOpen(filename, "ab"); - if (!g.LogFile) - { - IM_ASSERT(g.LogFile != NULL); // Consider this an error - return; - } - g.LogEnabled = true; - g.LogStartDepth = window->DC.TreeDepth; - if (max_depth >= 0) - g.LogAutoExpandMaxDepth = max_depth; -} - -// Start logging ImGui output to clipboard -void ImGui::LogToClipboard(int max_depth) -{ - ImGuiContext& g = *GImGui; - if (g.LogEnabled) - return; - ImGuiWindow* window = GetCurrentWindowRead(); - - g.LogEnabled = true; - g.LogFile = NULL; - g.LogStartDepth = window->DC.TreeDepth; - if (max_depth >= 0) - g.LogAutoExpandMaxDepth = max_depth; -} - -void ImGui::LogFinish() -{ - ImGuiContext& g = *GImGui; - if (!g.LogEnabled) - return; - - LogText(IM_NEWLINE); - g.LogEnabled = false; - if (g.LogFile != NULL) - { - if (g.LogFile == stdout) - fflush(g.LogFile); - else - fclose(g.LogFile); - g.LogFile = NULL; - } - if (g.LogClipboard->size() > 1) - { - SetClipboardText(g.LogClipboard->begin()); - g.LogClipboard->clear(); - } -} - -// Helper to display logging buttons -void ImGui::LogButtons() -{ - ImGuiContext& g = *GImGui; - - PushID("LogButtons"); - const bool log_to_tty = Button("Log To TTY"); SameLine(); - const bool log_to_file = Button("Log To File"); SameLine(); - const bool log_to_clipboard = Button("Log To Clipboard"); SameLine(); - PushItemWidth(80.0f); - PushAllowKeyboardFocus(false); - SliderInt("Depth", &g.LogAutoExpandMaxDepth, 0, 9, NULL); - PopAllowKeyboardFocus(); - PopItemWidth(); - PopID(); - - // Start logging at the end of the function so that the buttons don't appear in the log - if (log_to_tty) - LogToTTY(g.LogAutoExpandMaxDepth); - if (log_to_file) - LogToFile(g.LogAutoExpandMaxDepth, g.IO.LogFilename); - if (log_to_clipboard) - LogToClipboard(g.LogAutoExpandMaxDepth); -} - -bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) -{ - if (flags & ImGuiTreeNodeFlags_Leaf) - return true; - - // We only write to the tree storage if the user clicks (or explicitely use SetNextTreeNode*** functions) - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImGuiStorage* storage = window->DC.StateStorage; - - bool is_open; - if (g.SetNextTreeNodeOpenCond != 0) - { - if (g.SetNextTreeNodeOpenCond & ImGuiSetCond_Always) - { - is_open = g.SetNextTreeNodeOpenVal; - storage->SetInt(id, is_open); - } - else - { - // We treat ImGuiSetCondition_Once and ImGuiSetCondition_FirstUseEver the same because tree node state are not saved persistently. - const int stored_value = storage->GetInt(id, -1); - if (stored_value == -1) - { - is_open = g.SetNextTreeNodeOpenVal; - storage->SetInt(id, is_open); - } - else - { - is_open = stored_value != 0; - } - } - g.SetNextTreeNodeOpenCond = 0; - } - else - { - is_open = storage->GetInt(id, (flags & ImGuiTreeNodeFlags_DefaultOpen) ? 1 : 0) != 0; - } - - // When logging is enabled, we automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior). - // NB- If we are above max depth we still allow manually opened nodes to be logged. - if (g.LogEnabled && !(flags & ImGuiTreeNodeFlags_NoAutoOpenOnLog) && window->DC.TreeDepth < g.LogAutoExpandMaxDepth) - is_open = true; - - return is_open; -} - -bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0; - const ImVec2 padding = display_frame ? style.FramePadding : ImVec2(style.FramePadding.x, 0.0f); - - if (!label_end) - label_end = FindRenderedTextEnd(label); - const ImVec2 label_size = CalcTextSize(label, label_end, false); - - // We vertically grow up to current line height up the typical widget height. - const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset - padding.y); // Latch before ItemSize changes it - const float frame_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2); - ImRect bb = ImRect(window->DC.CursorPos, ImVec2(window->Pos.x + GetContentRegionMax().x, window->DC.CursorPos.y + frame_height)); - if (display_frame) - { - // Framed header expand a little outside the default padding - bb.Min.x -= (float)(int)(window->WindowPadding.x*0.5f) - 1; - bb.Max.x += (float)(int)(window->WindowPadding.x*0.5f) - 1; - } - - const float text_offset_x = (g.FontSize + (display_frame ? padding.x*3 : padding.x*2)); // Collapser arrow width + Spacing - const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser - ItemSize(ImVec2(text_width, frame_height), text_base_offset_y); - - // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing - // (Ideally we'd want to add a flag for the user to specify we want want the hit test to be done up to the right side of the content or not) - const ImRect interact_bb = display_frame ? bb : ImRect(bb.Min.x, bb.Min.y, bb.Min.x + text_width + style.ItemSpacing.x*2, bb.Max.y); - bool is_open = TreeNodeBehaviorIsOpen(id, flags); - if (!ItemAdd(interact_bb, &id)) - { - if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) - TreePushRawID(id); - return is_open; - } - - // Flags that affects opening behavior: - // - 0(default) ..................... single-click anywhere to open - // - OpenOnDoubleClick .............. double-click anywhere to open - // - OpenOnArrow .................... single-click on arrow to open - // - OpenOnDoubleClick|OpenOnArrow .. single-click on arrow or double-click anywhere to open - ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowOverlapMode : 0); - if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) - button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); - bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); - if (pressed && !(flags & ImGuiTreeNodeFlags_Leaf)) - { - bool toggled = !(flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)); - if (flags & ImGuiTreeNodeFlags_OpenOnArrow) - toggled |= IsMouseHoveringRect(interact_bb.Min, ImVec2(interact_bb.Min.x + text_offset_x, interact_bb.Max.y)); - if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) - toggled |= g.IO.MouseDoubleClicked[0]; - if (toggled) - { - is_open = !is_open; - window->DC.StateStorage->SetInt(id, is_open); - } - } - if (flags & ImGuiTreeNodeFlags_AllowOverlapMode) - SetItemAllowOverlap(); - - // Render - const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - const ImVec2 text_pos = bb.Min + ImVec2(text_offset_x, padding.y + text_base_offset_y); - if (display_frame) - { - // Framed type - RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); - RenderCollapseTriangle(bb.Min + padding + ImVec2(0.0f, text_base_offset_y), is_open, 1.0f); - if (g.LogEnabled) - { - // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here. - const char log_prefix[] = "\n##"; - const char log_suffix[] = "##"; - LogRenderedText(text_pos, log_prefix, log_prefix+3); - RenderTextClipped(text_pos, bb.Max, label, label_end, &label_size); - LogRenderedText(text_pos, log_suffix+1, log_suffix+3); - } - else - { - RenderTextClipped(text_pos, bb.Max, label, label_end, &label_size); - } - } - else - { - // Unframed typed for tree nodes - if (hovered || (flags & ImGuiTreeNodeFlags_Selected)) - RenderFrame(bb.Min, bb.Max, col, false); - - if (flags & ImGuiTreeNodeFlags_Bullet) - RenderBullet(bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y)); - else if (!(flags & ImGuiTreeNodeFlags_Leaf)) - RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open, 0.70f); - if (g.LogEnabled) - LogRenderedText(text_pos, ">"); - RenderText(text_pos, label, label_end, false); - } - - if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) - TreePushRawID(id); - return is_open; -} - -// CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag). -// This is basically the same as calling TreeNodeEx(label, ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen). You can remove the _NoTreePushOnOpen flag if you want behavior closer to normal TreeNode(). -bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - return TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen, label); -} - -bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - if (p_open && !*p_open) - return false; - - ImGuiID id = window->GetID(label); - bool is_open = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen | (p_open ? ImGuiTreeNodeFlags_AllowOverlapMode : 0), label); - if (p_open) - { - // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. - ImGuiContext& g = *GImGui; - float button_sz = g.FontSize * 0.5f; - if (CloseButton(window->GetID((void*)(intptr_t)(id+1)), ImVec2(ImMin(window->DC.LastItemRect.Max.x, window->ClipRect.Max.x) - g.Style.FramePadding.x - button_sz, window->DC.LastItemRect.Min.y + g.Style.FramePadding.y + button_sz), button_sz)) - *p_open = false; - } - - return is_open; -} - -bool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - return TreeNodeBehavior(window->GetID(label), flags, label, NULL); -} - -bool ImGui::TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); - return TreeNodeBehavior(window->GetID(str_id), flags, g.TempBuffer, label_end); -} - -bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); - return TreeNodeBehavior(window->GetID(ptr_id), flags, g.TempBuffer, label_end); -} - -bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args) -{ - return TreeNodeExV(str_id, 0, fmt, args); -} - -bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args) -{ - return TreeNodeExV(ptr_id, 0, fmt, args); -} - -bool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - bool is_open = TreeNodeExV(str_id, flags, fmt, args); - va_end(args); - return is_open; -} - -bool ImGui::TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - bool is_open = TreeNodeExV(ptr_id, flags, fmt, args); - va_end(args); - return is_open; -} - -bool ImGui::TreeNode(const char* str_id, const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - bool is_open = TreeNodeExV(str_id, 0, fmt, args); - va_end(args); - return is_open; -} - -bool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - bool is_open = TreeNodeExV(ptr_id, 0, fmt, args); - va_end(args); - return is_open; -} - -bool ImGui::TreeNode(const char* label) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - return TreeNodeBehavior(window->GetID(label), 0, label, NULL); -} - -void ImGui::TreeAdvanceToLabelPos() -{ - ImGuiContext& g = *GImGui; - g.CurrentWindow->DC.CursorPos.x += GetTreeNodeToLabelSpacing(); -} - -// Horizontal distance preceding label when using TreeNode() or Bullet() -float ImGui::GetTreeNodeToLabelSpacing() -{ - ImGuiContext& g = *GImGui; - return g.FontSize + (g.Style.FramePadding.x * 2.0f); -} - -void ImGui::SetNextTreeNodeOpen(bool is_open, ImGuiSetCond cond) -{ - ImGuiContext& g = *GImGui; - g.SetNextTreeNodeOpenVal = is_open; - g.SetNextTreeNodeOpenCond = cond ? cond : ImGuiSetCond_Always; -} - -void ImGui::PushID(const char* str_id) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->IDStack.push_back(window->GetID(str_id)); -} - -void ImGui::PushID(const char* str_id_begin, const char* str_id_end) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->IDStack.push_back(window->GetID(str_id_begin, str_id_end)); -} - -void ImGui::PushID(const void* ptr_id) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->IDStack.push_back(window->GetID(ptr_id)); -} - -void ImGui::PushID(int int_id) -{ - const void* ptr_id = (void*)(intptr_t)int_id; - ImGuiWindow* window = GetCurrentWindow(); - window->IDStack.push_back(window->GetID(ptr_id)); -} - -void ImGui::PopID() -{ - ImGuiWindow* window = GetCurrentWindow(); - window->IDStack.pop_back(); -} - -ImGuiID ImGui::GetID(const char* str_id) -{ - return GImGui->CurrentWindow->GetID(str_id); -} - -ImGuiID ImGui::GetID(const char* str_id_begin, const char* str_id_end) -{ - return GImGui->CurrentWindow->GetID(str_id_begin, str_id_end); -} - -ImGuiID ImGui::GetID(const void* ptr_id) -{ - return GImGui->CurrentWindow->GetID(ptr_id); -} - -void ImGui::Bullet() -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const float line_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + g.Style.FramePadding.y*2), g.FontSize); - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize, line_height)); - ItemSize(bb); - if (!ItemAdd(bb, NULL)) - { - SameLine(0, style.FramePadding.x*2); - return; - } - - // Render and stay on same line - RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f)); - SameLine(0, style.FramePadding.x*2); -} - -// Text with a little bullet aligned to the typical tree node. -void ImGui::BulletTextV(const char* fmt, va_list args) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - - const char* text_begin = g.TempBuffer; - const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); - const ImVec2 label_size = CalcTextSize(text_begin, text_end, false); - const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it - const float line_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + g.Style.FramePadding.y*2), g.FontSize); - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x*2) : 0.0f), ImMax(line_height, label_size.y))); // Empty text doesn't add padding - ItemSize(bb); - if (!ItemAdd(bb, NULL)) - return; - - // Render - RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f)); - RenderText(bb.Min+ImVec2(g.FontSize + style.FramePadding.x*2, text_base_offset_y), text_begin, text_end, false); -} - -void ImGui::BulletText(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - BulletTextV(fmt, args); - va_end(args); -} - -static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, const char* display_format, char* buf, int buf_size) -{ - if (data_type == ImGuiDataType_Int) - ImFormatString(buf, buf_size, display_format, *(int*)data_ptr); - else if (data_type == ImGuiDataType_Float) - ImFormatString(buf, buf_size, display_format, *(float*)data_ptr); -} - -static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, int decimal_precision, char* buf, int buf_size) -{ - if (data_type == ImGuiDataType_Int) - { - if (decimal_precision < 0) - ImFormatString(buf, buf_size, "%d", *(int*)data_ptr); - else - ImFormatString(buf, buf_size, "%.*d", decimal_precision, *(int*)data_ptr); - } - else if (data_type == ImGuiDataType_Float) - { - if (decimal_precision < 0) - ImFormatString(buf, buf_size, "%f", *(float*)data_ptr); // Ideally we'd have a minimum decimal precision of 1 to visually denote that it is a float, while hiding non-significant digits? - else - ImFormatString(buf, buf_size, "%.*f", decimal_precision, *(float*)data_ptr); - } -} - -static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* value1, const void* value2)// Store into value1 -{ - if (data_type == ImGuiDataType_Int) - { - if (op == '+') - *(int*)value1 = *(int*)value1 + *(const int*)value2; - else if (op == '-') - *(int*)value1 = *(int*)value1 - *(const int*)value2; - } - else if (data_type == ImGuiDataType_Float) - { - if (op == '+') - *(float*)value1 = *(float*)value1 + *(const float*)value2; - else if (op == '-') - *(float*)value1 = *(float*)value1 - *(const float*)value2; - } -} - -// User can input math operators (e.g. +100) to edit a numerical values. -static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format) -{ - while (ImCharIsSpace(*buf)) - buf++; - - // We don't support '-' op because it would conflict with inputing negative value. - // Instead you can use +-100 to subtract from an existing value - char op = buf[0]; - if (op == '+' || op == '*' || op == '/') - { - buf++; - while (ImCharIsSpace(*buf)) - buf++; - } - else - { - op = 0; - } - if (!buf[0]) - return false; - - if (data_type == ImGuiDataType_Int) - { - if (!scalar_format) - scalar_format = "%d"; - int* v = (int*)data_ptr; - const int old_v = *v; - int arg0 = *v; - if (op && sscanf(initial_value_buf, scalar_format, &arg0) < 1) - return false; - - // Store operand in a float so we can use fractional value for multipliers (*1.1), but constant always parsed as integer so we can fit big integers (e.g. 2000000003) past float precision - float arg1 = 0.0f; - if (op == '+') { if (sscanf(buf, "%f", &arg1) == 1) *v = (int)(arg0 + arg1); } // Add (use "+-" to subtract) - else if (op == '*') { if (sscanf(buf, "%f", &arg1) == 1) *v = (int)(arg0 * arg1); } // Multiply - else if (op == '/') { if (sscanf(buf, "%f", &arg1) == 1 && arg1 != 0.0f) *v = (int)(arg0 / arg1); }// Divide - else { if (sscanf(buf, scalar_format, &arg0) == 1) *v = arg0; } // Assign constant - return (old_v != *v); - } - else if (data_type == ImGuiDataType_Float) - { - // For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in - scalar_format = "%f"; - float* v = (float*)data_ptr; - const float old_v = *v; - float arg0 = *v; - if (op && sscanf(initial_value_buf, scalar_format, &arg0) < 1) - return false; - - float arg1 = 0.0f; - if (sscanf(buf, scalar_format, &arg1) < 1) - return false; - if (op == '+') { *v = arg0 + arg1; } // Add (use "+-" to subtract) - else if (op == '*') { *v = arg0 * arg1; } // Multiply - else if (op == '/') { if (arg1 != 0.0f) *v = arg0 / arg1; } // Divide - else { *v = arg1; } // Assign constant - return (old_v != *v); - } - - return false; -} - -// Create text input in place of a slider (when CTRL+Clicking on slider) -bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - - // Our replacement widget will override the focus ID (registered previously to allow for a TAB focus to happen) - SetActiveID(g.ScalarAsInputTextId, window); - SetHoveredID(0); - FocusableItemUnregister(window); - - char buf[32]; - DataTypeFormatString(data_type, data_ptr, decimal_precision, buf, IM_ARRAYSIZE(buf)); - bool text_value_changed = InputTextEx(label, buf, IM_ARRAYSIZE(buf), aabb.GetSize(), ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_AutoSelectAll); - if (g.ScalarAsInputTextId == 0) - { - // First frame - IM_ASSERT(g.ActiveId == id); // InputText ID expected to match the Slider ID (else we'd need to store them both, which is also possible) - g.ScalarAsInputTextId = g.ActiveId; - SetHoveredID(id); - } - else if (g.ActiveId != g.ScalarAsInputTextId) - { - // Release - g.ScalarAsInputTextId = 0; - } - if (text_value_changed) - return DataTypeApplyOpFromText(buf, GImGui->InputTextState.InitialText.begin(), data_type, data_ptr, NULL); - return false; -} - -// Parse display precision back from the display format string -int ImGui::ParseFormatPrecision(const char* fmt, int default_precision) -{ - int precision = default_precision; - while ((fmt = strchr(fmt, '%')) != NULL) - { - fmt++; - if (fmt[0] == '%') { fmt++; continue; } // Ignore "%%" - while (*fmt >= '0' && *fmt <= '9') - fmt++; - if (*fmt == '.') - { - precision = atoi(fmt + 1); - if (precision < 0 || precision > 10) - precision = default_precision; - } - break; - } - return precision; -} - -float ImGui::RoundScalar(float value, int decimal_precision) -{ - // Round past decimal precision - // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0 - // FIXME: Investigate better rounding methods - static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f }; - float min_step = (decimal_precision >= 0 && decimal_precision < 10) ? min_steps[decimal_precision] : powf(10.0f, (float)-decimal_precision); - bool negative = value < 0.0f; - value = fabsf(value); - float remainder = fmodf(value, min_step); - if (remainder <= min_step*0.5f) - value -= remainder; - else - value += (min_step - remainder); - return negative ? -value : value; -} - -static inline float SliderBehaviorCalcRatioFromValue(float v, float v_min, float v_max, float power, float linear_zero_pos) -{ - if (v_min == v_max) - return 0.0f; - - const bool is_non_linear = (power < 1.0f-0.00001f) || (power > 1.0f+0.00001f); - const float v_clamped = (v_min < v_max) ? ImClamp(v, v_min, v_max) : ImClamp(v, v_max, v_min); - if (is_non_linear) - { - if (v_clamped < 0.0f) - { - const float f = 1.0f - (v_clamped - v_min) / (ImMin(0.0f,v_max) - v_min); - return (1.0f - powf(f, 1.0f/power)) * linear_zero_pos; - } - else - { - const float f = (v_clamped - ImMax(0.0f,v_min)) / (v_max - ImMax(0.0f,v_min)); - return linear_zero_pos + powf(f, 1.0f/power) * (1.0f - linear_zero_pos); - } - } - - // Linear slider - return (v_clamped - v_min) / (v_max - v_min); -} - -bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - const ImGuiStyle& style = g.Style; - - // Draw frame - RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - - const bool is_non_linear = (power < 1.0f-0.00001f) || (power > 1.0f+0.00001f); - const bool is_horizontal = (flags & ImGuiSliderFlags_Vertical) == 0; - - const float grab_padding = 2.0f; - const float slider_sz = is_horizontal ? (frame_bb.GetWidth() - grab_padding * 2.0f) : (frame_bb.GetHeight() - grab_padding * 2.0f); - float grab_sz; - if (decimal_precision > 0) - grab_sz = ImMin(style.GrabMinSize, slider_sz); - else - grab_sz = ImMin(ImMax(1.0f * (slider_sz / ((v_min < v_max ? v_max - v_min : v_min - v_max) + 1.0f)), style.GrabMinSize), slider_sz); // Integer sliders, if possible have the grab size represent 1 unit - const float slider_usable_sz = slider_sz - grab_sz; - const float slider_usable_pos_min = (is_horizontal ? frame_bb.Min.x : frame_bb.Min.y) + grab_padding + grab_sz*0.5f; - const float slider_usable_pos_max = (is_horizontal ? frame_bb.Max.x : frame_bb.Max.y) - grab_padding - grab_sz*0.5f; - - // For logarithmic sliders that cross over sign boundary we want the exponential increase to be symmetric around 0.0f - float linear_zero_pos = 0.0f; // 0.0->1.0f - if (v_min * v_max < 0.0f) - { - // Different sign - const float linear_dist_min_to_0 = powf(fabsf(0.0f - v_min), 1.0f/power); - const float linear_dist_max_to_0 = powf(fabsf(v_max - 0.0f), 1.0f/power); - linear_zero_pos = linear_dist_min_to_0 / (linear_dist_min_to_0+linear_dist_max_to_0); - } - else - { - // Same sign - linear_zero_pos = v_min < 0.0f ? 1.0f : 0.0f; - } - - // Process clicking on the slider - bool value_changed = false; - if (g.ActiveId == id) - { - if (g.IO.MouseDown[0]) - { - const float mouse_abs_pos = is_horizontal ? g.IO.MousePos.x : g.IO.MousePos.y; - float clicked_t = (slider_usable_sz > 0.0f) ? ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) : 0.0f; - if (!is_horizontal) - clicked_t = 1.0f - clicked_t; - - float new_value; - if (is_non_linear) - { - // Account for logarithmic scale on both sides of the zero - if (clicked_t < linear_zero_pos) - { - // Negative: rescale to the negative range before powering - float a = 1.0f - (clicked_t / linear_zero_pos); - a = powf(a, power); - new_value = ImLerp(ImMin(v_max,0.0f), v_min, a); - } - else - { - // Positive: rescale to the positive range before powering - float a; - if (fabsf(linear_zero_pos - 1.0f) > 1.e-6f) - a = (clicked_t - linear_zero_pos) / (1.0f - linear_zero_pos); - else - a = clicked_t; - a = powf(a, power); - new_value = ImLerp(ImMax(v_min,0.0f), v_max, a); - } - } - else - { - // Linear slider - new_value = ImLerp(v_min, v_max, clicked_t); - } - - // Round past decimal precision - new_value = RoundScalar(new_value, decimal_precision); - if (*v != new_value) - { - *v = new_value; - value_changed = true; - } - } - else - { - ClearActiveID(); - } - } - - // Calculate slider grab positioning - float grab_t = SliderBehaviorCalcRatioFromValue(*v, v_min, v_max, power, linear_zero_pos); - - // Draw - if (!is_horizontal) - grab_t = 1.0f - grab_t; - const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); - ImRect grab_bb; - if (is_horizontal) - grab_bb = ImRect(ImVec2(grab_pos - grab_sz*0.5f, frame_bb.Min.y + grab_padding), ImVec2(grab_pos + grab_sz*0.5f, frame_bb.Max.y - grab_padding)); - else - grab_bb = ImRect(ImVec2(frame_bb.Min.x + grab_padding, grab_pos - grab_sz*0.5f), ImVec2(frame_bb.Max.x - grab_padding, grab_pos + grab_sz*0.5f)); - window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding); - - return value_changed; -} - -// Use power!=1.0 for logarithmic sliders. -// Adjust display_format to decorate the value with a prefix or a suffix. -// "%.3f" 1.234 -// "%5.2f secs" 01.23 secs -// "Gold: %.0f" Gold: 1 -bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format, float power) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const float w = CalcItemWidth(); - - const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); - const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); - - // NB- we don't call ItemSize() yet because we may turn into a text edit box below - if (!ItemAdd(total_bb, &id)) - { - ItemSize(total_bb, style.FramePadding.y); - return false; - } - - const bool hovered = IsHovered(frame_bb, id); - if (hovered) - SetHoveredID(id); - - if (!display_format) - display_format = "%.3f"; - int decimal_precision = ParseFormatPrecision(display_format, 3); - - // Tabbing or CTRL-clicking on Slider turns it into an input box - bool start_text_input = false; - const bool tab_focus_requested = FocusableItemRegister(window, g.ActiveId == id); - if (tab_focus_requested || (hovered && g.IO.MouseClicked[0])) - { - SetActiveID(id, window); - FocusWindow(window); - - if (tab_focus_requested || g.IO.KeyCtrl) - { - start_text_input = true; - g.ScalarAsInputTextId = 0; - } - } - if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id)) - return InputScalarAsWidgetReplacement(frame_bb, label, ImGuiDataType_Float, v, id, decimal_precision); - - ItemSize(total_bb, style.FramePadding.y); - - // Actual slider behavior + render grab - const bool value_changed = SliderBehavior(frame_bb, id, v, v_min, v_max, power, decimal_precision); - - // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. - char value_buf[64]; - const char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); - RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.5f)); - - if (label_size.x > 0.0f) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); - - return value_changed; -} - -bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* display_format, float power) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - - const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size); - const ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); - - ItemSize(bb, style.FramePadding.y); - if (!ItemAdd(frame_bb, &id)) - return false; - - const bool hovered = IsHovered(frame_bb, id); - if (hovered) - SetHoveredID(id); - - if (!display_format) - display_format = "%.3f"; - int decimal_precision = ParseFormatPrecision(display_format, 3); - - if (hovered && g.IO.MouseClicked[0]) - { - SetActiveID(id, window); - FocusWindow(window); - } - - // Actual slider behavior + render grab - bool value_changed = SliderBehavior(frame_bb, id, v, v_min, v_max, power, decimal_precision, ImGuiSliderFlags_Vertical); - - // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. - // For the vertical slider we allow centered text to overlap the frame padding - char value_buf[64]; - char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); - RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.0f)); - if (label_size.x > 0.0f) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); - - return value_changed; -} - -bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, float v_degrees_max) -{ - float v_deg = (*v_rad) * 360.0f / (2*IM_PI); - bool value_changed = SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, "%.0f deg", 1.0f); - *v_rad = v_deg * (2*IM_PI) / 360.0f; - return value_changed; -} - -bool ImGui::SliderInt(const char* label, int* v, int v_min, int v_max, const char* display_format) -{ - if (!display_format) - display_format = "%.0f"; - float v_f = (float)*v; - bool value_changed = SliderFloat(label, &v_f, (float)v_min, (float)v_max, display_format, 1.0f); - *v = (int)v_f; - return value_changed; -} - -bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* display_format) -{ - if (!display_format) - display_format = "%.0f"; - float v_f = (float)*v; - bool value_changed = VSliderFloat(label, size, &v_f, (float)v_min, (float)v_max, display_format, 1.0f); - *v = (int)v_f; - return value_changed; -} - -// Add multiple sliders on 1 line for compact edition of multiple components -bool ImGui::SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* display_format, float power) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - bool value_changed = false; - BeginGroup(); - PushID(label); - PushMultiItemsWidths(components); - for (int i = 0; i < components; i++) - { - PushID(i); - value_changed |= SliderFloat("##v", &v[i], v_min, v_max, display_format, power); - SameLine(0, g.Style.ItemInnerSpacing.x); - PopID(); - PopItemWidth(); - } - PopID(); - - TextUnformatted(label, FindRenderedTextEnd(label)); - EndGroup(); - - return value_changed; -} - -bool ImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format, float power) -{ - return SliderFloatN(label, v, 2, v_min, v_max, display_format, power); -} - -bool ImGui::SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* display_format, float power) -{ - return SliderFloatN(label, v, 3, v_min, v_max, display_format, power); -} - -bool ImGui::SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* display_format, float power) -{ - return SliderFloatN(label, v, 4, v_min, v_max, display_format, power); -} - -bool ImGui::SliderIntN(const char* label, int* v, int components, int v_min, int v_max, const char* display_format) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - bool value_changed = false; - BeginGroup(); - PushID(label); - PushMultiItemsWidths(components); - for (int i = 0; i < components; i++) - { - PushID(i); - value_changed |= SliderInt("##v", &v[i], v_min, v_max, display_format); - SameLine(0, g.Style.ItemInnerSpacing.x); - PopID(); - PopItemWidth(); - } - PopID(); - - TextUnformatted(label, FindRenderedTextEnd(label)); - EndGroup(); - - return value_changed; -} - -bool ImGui::SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* display_format) -{ - return SliderIntN(label, v, 2, v_min, v_max, display_format); -} - -bool ImGui::SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* display_format) -{ - return SliderIntN(label, v, 3, v_min, v_max, display_format); -} - -bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* display_format) -{ - return SliderIntN(label, v, 4, v_min, v_max, display_format); -} - -bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power) -{ - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - - // Draw frame - const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); - RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); - - bool value_changed = false; - - // Process clicking on the drag - if (g.ActiveId == id) - { - if (g.IO.MouseDown[0]) - { - if (g.ActiveIdIsJustActivated) - { - // Lock current value on click - g.DragCurrentValue = *v; - g.DragLastMouseDelta = ImVec2(0.f, 0.f); - } - - float v_cur = g.DragCurrentValue; - const ImVec2 mouse_drag_delta = GetMouseDragDelta(0, 1.0f); - if (fabsf(mouse_drag_delta.x - g.DragLastMouseDelta.x) > 0.0f) - { - float speed = v_speed; - if (speed == 0.0f && (v_max - v_min) != 0.0f && (v_max - v_min) < FLT_MAX) - speed = (v_max - v_min) * g.DragSpeedDefaultRatio; - if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) - speed = speed * g.DragSpeedScaleFast; - if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) - speed = speed * g.DragSpeedScaleSlow; - - float delta = (mouse_drag_delta.x - g.DragLastMouseDelta.x) * speed; - if (fabsf(power - 1.0f) > 0.001f) - { - // Logarithmic curve on both side of 0.0 - float v0_abs = v_cur >= 0.0f ? v_cur : -v_cur; - float v0_sign = v_cur >= 0.0f ? 1.0f : -1.0f; - float v1 = powf(v0_abs, 1.0f / power) + (delta * v0_sign); - float v1_abs = v1 >= 0.0f ? v1 : -v1; - float v1_sign = v1 >= 0.0f ? 1.0f : -1.0f; // Crossed sign line - v_cur = powf(v1_abs, power) * v0_sign * v1_sign; // Reapply sign - } - else - { - v_cur += delta; - } - g.DragLastMouseDelta.x = mouse_drag_delta.x; - - // Clamp - if (v_min < v_max) - v_cur = ImClamp(v_cur, v_min, v_max); - g.DragCurrentValue = v_cur; - } - - // Round to user desired precision, then apply - v_cur = RoundScalar(v_cur, decimal_precision); - if (*v != v_cur) - { - *v = v_cur; - value_changed = true; - } - } - else - { - ClearActiveID(); - } - } - - return value_changed; -} - -bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* display_format, float power) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const float w = CalcItemWidth(); - - const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); - const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); - const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); - - // NB- we don't call ItemSize() yet because we may turn into a text edit box below - if (!ItemAdd(total_bb, &id)) - { - ItemSize(total_bb, style.FramePadding.y); - return false; - } - - const bool hovered = IsHovered(frame_bb, id); - if (hovered) - SetHoveredID(id); - - if (!display_format) - display_format = "%.3f"; - int decimal_precision = ParseFormatPrecision(display_format, 3); - - // Tabbing or CTRL-clicking on Drag turns it into an input box - bool start_text_input = false; - const bool tab_focus_requested = FocusableItemRegister(window, g.ActiveId == id); - if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] | g.IO.MouseDoubleClicked[0]))) - { - SetActiveID(id, window); - FocusWindow(window); - - if (tab_focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0]) - { - start_text_input = true; - g.ScalarAsInputTextId = 0; - } - } - if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id)) - return InputScalarAsWidgetReplacement(frame_bb, label, ImGuiDataType_Float, v, id, decimal_precision); - - // Actual drag behavior - ItemSize(total_bb, style.FramePadding.y); - const bool value_changed = DragBehavior(frame_bb, id, v, v_speed, v_min, v_max, decimal_precision, power); - - // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. - char value_buf[64]; - const char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); - RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.5f)); - - if (label_size.x > 0.0f) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label); - - return value_changed; -} - -bool ImGui::DragFloatN(const char* label, float* v, int components, float v_speed, float v_min, float v_max, const char* display_format, float power) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - bool value_changed = false; - BeginGroup(); - PushID(label); - PushMultiItemsWidths(components); - for (int i = 0; i < components; i++) - { - PushID(i); - value_changed |= DragFloat("##v", &v[i], v_speed, v_min, v_max, display_format, power); - SameLine(0, g.Style.ItemInnerSpacing.x); - PopID(); - PopItemWidth(); - } - PopID(); - - TextUnformatted(label, FindRenderedTextEnd(label)); - EndGroup(); - - return value_changed; -} - -bool ImGui::DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* display_format, float power) -{ - return DragFloatN(label, v, 2, v_speed, v_min, v_max, display_format, power); -} - -bool ImGui::DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* display_format, float power) -{ - return DragFloatN(label, v, 3, v_speed, v_min, v_max, display_format, power); -} - -bool ImGui::DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* display_format, float power) -{ - return DragFloatN(label, v, 4, v_speed, v_min, v_max, display_format, power); -} - -bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed, float v_min, float v_max, const char* display_format, const char* display_format_max, float power) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - PushID(label); - BeginGroup(); - PushMultiItemsWidths(2); - - bool value_changed = DragFloat("##min", v_current_min, v_speed, (v_min >= v_max) ? -FLT_MAX : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format, power); - PopItemWidth(); - SameLine(0, g.Style.ItemInnerSpacing.x); - value_changed |= DragFloat("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? FLT_MAX : v_max, display_format_max ? display_format_max : display_format, power); - PopItemWidth(); - SameLine(0, g.Style.ItemInnerSpacing.x); - - TextUnformatted(label, FindRenderedTextEnd(label)); - EndGroup(); - PopID(); - - return value_changed; -} - -// NB: v_speed is float to allow adjusting the drag speed with more precision -bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_max, const char* display_format) -{ - if (!display_format) - display_format = "%.0f"; - float v_f = (float)*v; - bool value_changed = DragFloat(label, &v_f, v_speed, (float)v_min, (float)v_max, display_format); - *v = (int)v_f; - return value_changed; -} - -bool ImGui::DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* display_format) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - bool value_changed = false; - BeginGroup(); - PushID(label); - PushMultiItemsWidths(components); - for (int i = 0; i < components; i++) - { - PushID(i); - value_changed |= DragInt("##v", &v[i], v_speed, v_min, v_max, display_format); - SameLine(0, g.Style.ItemInnerSpacing.x); - PopID(); - PopItemWidth(); - } - PopID(); - - TextUnformatted(label, FindRenderedTextEnd(label)); - EndGroup(); - - return value_changed; -} - -bool ImGui::DragInt2(const char* label, int v[2], float v_speed, int v_min, int v_max, const char* display_format) -{ - return DragIntN(label, v, 2, v_speed, v_min, v_max, display_format); -} - -bool ImGui::DragInt3(const char* label, int v[3], float v_speed, int v_min, int v_max, const char* display_format) -{ - return DragIntN(label, v, 3, v_speed, v_min, v_max, display_format); -} - -bool ImGui::DragInt4(const char* label, int v[4], float v_speed, int v_min, int v_max, const char* display_format) -{ - return DragIntN(label, v, 4, v_speed, v_min, v_max, display_format); -} - -bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed, int v_min, int v_max, const char* display_format, const char* display_format_max) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - PushID(label); - BeginGroup(); - PushMultiItemsWidths(2); - - bool value_changed = DragInt("##min", v_current_min, v_speed, (v_min >= v_max) ? INT_MIN : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format); - PopItemWidth(); - SameLine(0, g.Style.ItemInnerSpacing.x); - value_changed |= DragInt("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? INT_MAX : v_max, display_format_max ? display_format_max : display_format); - PopItemWidth(); - SameLine(0, g.Style.ItemInnerSpacing.x); - - TextUnformatted(label, FindRenderedTextEnd(label)); - EndGroup(); - PopID(); - - return value_changed; -} - -void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - - const ImVec2 label_size = CalcTextSize(label, NULL, true); - if (graph_size.x == 0.0f) - graph_size.x = CalcItemWidth(); - if (graph_size.y == 0.0f) - graph_size.y = label_size.y + (style.FramePadding.y * 2); - - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(graph_size.x, graph_size.y)); - const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); - const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0)); - ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, NULL)) - return; - - // Determine scale from values if not specified - if (scale_min == FLT_MAX || scale_max == FLT_MAX) - { - float v_min = FLT_MAX; - float v_max = -FLT_MAX; - for (int i = 0; i < values_count; i++) - { - const float v = values_getter(data, i); - v_min = ImMin(v_min, v); - v_max = ImMax(v_max, v); - } - if (scale_min == FLT_MAX) - scale_min = v_min; - if (scale_max == FLT_MAX) - scale_max = v_max; - } - - RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - - if (values_count > 0) - { - int res_w = ImMin((int)graph_size.x, values_count) + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0); - int item_count = values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0); - - // Tooltip on hover - int v_hovered = -1; - if (IsHovered(inner_bb, 0)) - { - const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f); - const int v_idx = (int)(t * item_count); - IM_ASSERT(v_idx >= 0 && v_idx < values_count); - - const float v0 = values_getter(data, (v_idx + values_offset) % values_count); - const float v1 = values_getter(data, (v_idx + 1 + values_offset) % values_count); - if (plot_type == ImGuiPlotType_Lines) - SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx+1, v1); - else if (plot_type == ImGuiPlotType_Histogram) - SetTooltip("%d: %8.4g", v_idx, v0); - v_hovered = v_idx; - } - - const float t_step = 1.0f / (float)res_w; - - float v0 = values_getter(data, (0 + values_offset) % values_count); - float t0 = 0.0f; - ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) / (scale_max - scale_min)) ); // Point in the normalized space of our target rectangle - - const ImU32 col_base = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram); - const ImU32 col_hovered = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered); - - for (int n = 0; n < res_w; n++) - { - const float t1 = t0 + t_step; - const int v1_idx = (int)(t0 * item_count + 0.5f); - IM_ASSERT(v1_idx >= 0 && v1_idx < values_count); - const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count); - const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) / (scale_max - scale_min)) ); - - // NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU. - ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0); - ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, 1.0f)); - if (plot_type == ImGuiPlotType_Lines) - { - window->DrawList->AddLine(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base); - } - else if (plot_type == ImGuiPlotType_Histogram) - { - if (pos1.x >= pos0.x + 2.0f) - pos1.x -= 1.0f; - window->DrawList->AddRectFilled(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base); - } - - t0 = t1; - tp0 = tp1; - } - } - - // Text overlay - if (overlay_text) - RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, overlay_text, NULL, NULL, ImVec2(0.5f,0.0f)); - - if (label_size.x > 0.0f) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label); -} - -struct ImGuiPlotArrayGetterData -{ - const float* Values; - int Stride; - - ImGuiPlotArrayGetterData(const float* values, int stride) { Values = values; Stride = stride; } -}; - -static float Plot_ArrayGetter(void* data, int idx) -{ - ImGuiPlotArrayGetterData* plot_data = (ImGuiPlotArrayGetterData*)data; - const float v = *(float*)(void*)((unsigned char*)plot_data->Values + (size_t)idx * plot_data->Stride); - return v; -} - -void ImGui::PlotLines(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride) -{ - ImGuiPlotArrayGetterData data(values, stride); - PlotEx(ImGuiPlotType_Lines, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); -} - -void ImGui::PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size) -{ - PlotEx(ImGuiPlotType_Lines, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); -} - -void ImGui::PlotHistogram(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride) -{ - ImGuiPlotArrayGetterData data(values, stride); - PlotEx(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); -} - -void ImGui::PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size) -{ - PlotEx(ImGuiPlotType_Histogram, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); -} - -// size_arg (for each axis) < 0.0f: align to end, 0.0f: auto, > 0.0f: specified size -void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* overlay) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - - ImVec2 pos = window->DC.CursorPos; - ImRect bb(pos, pos + CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y*2.0f)); - ItemSize(bb, style.FramePadding.y); - if (!ItemAdd(bb, NULL)) - return; - - // Render - fraction = ImSaturate(fraction); - RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - bb.Reduce(ImVec2(window->BorderSize, window->BorderSize)); - const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y); - RenderFrame(bb.Min, fill_br, GetColorU32(ImGuiCol_PlotHistogram), false, style.FrameRounding); - - // Default displaying the fraction as percentage string, but user can override it - char overlay_buf[32]; - if (!overlay) - { - ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%.0f%%", fraction*100+0.01f); - overlay = overlay_buf; - } - - ImVec2 overlay_size = CalcTextSize(overlay, NULL); - if (overlay_size.x > 0.0f) - RenderTextClipped(ImVec2(ImClamp(fill_br.x + style.ItemSpacing.x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), bb.Min.y), bb.Max, overlay, NULL, &overlay_size, ImVec2(0.0f,0.5f), &bb); -} - -bool ImGui::Checkbox(const char* label, bool* v) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const ImVec2 label_size = CalcTextSize(label, NULL, true); - - const ImRect check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y*2, label_size.y + style.FramePadding.y*2)); - ItemSize(check_bb, style.FramePadding.y); - - ImRect total_bb = check_bb; - if (label_size.x > 0) - SameLine(0, style.ItemInnerSpacing.x); - const ImRect text_bb(window->DC.CursorPos + ImVec2(0,style.FramePadding.y), window->DC.CursorPos + ImVec2(0,style.FramePadding.y) + label_size); - if (label_size.x > 0) - { - ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()), style.FramePadding.y); - total_bb = ImRect(ImMin(check_bb.Min, text_bb.Min), ImMax(check_bb.Max, text_bb.Max)); - } - - if (!ItemAdd(total_bb, &id)) - return false; - - bool hovered, held; - bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); - if (pressed) - *v = !(*v); - - RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); - if (*v) - { - const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight()); - const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f)); - window->DrawList->AddRectFilled(check_bb.Min+ImVec2(pad,pad), check_bb.Max-ImVec2(pad,pad), GetColorU32(ImGuiCol_CheckMark), style.FrameRounding); - } - - if (g.LogEnabled) - LogRenderedText(text_bb.GetTL(), *v ? "[x]" : "[ ]"); - if (label_size.x > 0.0f) - RenderText(text_bb.GetTL(), label); - - return pressed; -} - -bool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value) -{ - bool v = ((*flags & flags_value) == flags_value); - bool pressed = Checkbox(label, &v); - if (pressed) - { - if (v) - *flags |= flags_value; - else - *flags &= ~flags_value; - } - - return pressed; -} - -bool ImGui::RadioButton(const char* label, bool active) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const ImVec2 label_size = CalcTextSize(label, NULL, true); - - const ImRect check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y*2-1, label_size.y + style.FramePadding.y*2-1)); - ItemSize(check_bb, style.FramePadding.y); - - ImRect total_bb = check_bb; - if (label_size.x > 0) - SameLine(0, style.ItemInnerSpacing.x); - const ImRect text_bb(window->DC.CursorPos + ImVec2(0, style.FramePadding.y), window->DC.CursorPos + ImVec2(0, style.FramePadding.y) + label_size); - if (label_size.x > 0) - { - ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()), style.FramePadding.y); - total_bb.Add(text_bb); - } - - if (!ItemAdd(total_bb, &id)) - return false; - - ImVec2 center = check_bb.GetCenter(); - center.x = (float)(int)center.x + 0.5f; - center.y = (float)(int)center.y + 0.5f; - const float radius = check_bb.GetHeight() * 0.5f; - - bool hovered, held; - bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); - - window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16); - if (active) - { - const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight()); - const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f)); - window->DrawList->AddCircleFilled(center, radius-pad, GetColorU32(ImGuiCol_CheckMark), 16); - } - - if (window->Flags & ImGuiWindowFlags_ShowBorders) - { - window->DrawList->AddCircle(center+ImVec2(1,1), radius, GetColorU32(ImGuiCol_BorderShadow), 16); - window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), 16); - } - - if (g.LogEnabled) - LogRenderedText(text_bb.GetTL(), active ? "(x)" : "( )"); - if (label_size.x > 0.0f) - RenderText(text_bb.GetTL(), label); - - return pressed; -} - -bool ImGui::RadioButton(const char* label, int* v, int v_button) -{ - const bool pressed = RadioButton(label, *v == v_button); - if (pressed) - { - *v = v_button; - } - return pressed; -} - -static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end) -{ - int line_count = 0; - const char* s = text_begin; - while (char c = *s++) // We are only matching for \n so we can ignore UTF-8 decoding - if (c == '\n') - line_count++; - s--; - if (s[0] != '\n' && s[0] != '\r') - line_count++; - *out_text_end = s; - return line_count; -} - -static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining, ImVec2* out_offset, bool stop_on_new_line) -{ - ImFont* font = GImGui->Font; - const float line_height = GImGui->FontSize; - const float scale = line_height / font->FontSize; - - ImVec2 text_size = ImVec2(0,0); - float line_width = 0.0f; - - const ImWchar* s = text_begin; - while (s < text_end) - { - unsigned int c = (unsigned int)(*s++); - if (c == '\n') - { - text_size.x = ImMax(text_size.x, line_width); - text_size.y += line_height; - line_width = 0.0f; - if (stop_on_new_line) - break; - continue; - } - if (c == '\r') - continue; - - const float char_width = font->GetCharAdvance((unsigned short)c) * scale; - line_width += char_width; - } - - if (text_size.x < line_width) - text_size.x = line_width; - - if (out_offset) - *out_offset = ImVec2(line_width, text_size.y + line_height); // offset allow for the possibility of sitting after a trailing \n - - if (line_width > 0 || text_size.y == 0.0f) // whereas size.y will ignore the trailing \n - text_size.y += line_height; - - if (remaining) - *remaining = s; - - return text_size; -} - -// Wrapper for stb_textedit.h to edit text (our wrapper is for: statically sized buffer, single-line, wchar characters. InputText converts between UTF-8 and wchar) -namespace ImGuiStb -{ - -static int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING* obj) { return obj->CurLenW; } -static ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING* obj, int idx) { return obj->Text[idx]; } -static float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING* obj, int line_start_idx, int char_idx) { ImWchar c = obj->Text[line_start_idx+char_idx]; if (c == '\n') return STB_TEXTEDIT_GETWIDTH_NEWLINE; return GImGui->Font->GetCharAdvance(c) * (GImGui->FontSize / GImGui->Font->FontSize); } -static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x10000 ? 0 : key; } -static ImWchar STB_TEXTEDIT_NEWLINE = '\n'; -static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* obj, int line_start_idx) -{ - const ImWchar* text = obj->Text.Data; - const ImWchar* text_remaining = NULL; - const ImVec2 size = InputTextCalcTextSizeW(text + line_start_idx, text + obj->CurLenW, &text_remaining, NULL, true); - r->x0 = 0.0f; - r->x1 = size.x; - r->baseline_y_delta = size.y; - r->ymin = 0.0f; - r->ymax = size.y; - r->num_chars = (int)(text_remaining - (text + line_start_idx)); -} - -static bool is_separator(unsigned int c) { return ImCharIsSpace(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; } -static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator( obj->Text[idx-1] ) && !is_separator( obj->Text[idx] ) ) : 1; } -static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; } -#ifdef __APPLE__ // FIXME: Move setting to IO structure -static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; } -static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; } -#else -static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; } -#endif -#define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h -#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_IMPL - -static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n) -{ - ImWchar* dst = obj->Text.Data + pos; - - // We maintain our buffer length in both UTF-8 and wchar formats - obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n); - obj->CurLenW -= n; - - // Offset remaining text - const ImWchar* src = obj->Text.Data + pos + n; - while (ImWchar c = *src++) - *dst++ = c; - *dst = '\0'; -} - -static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const ImWchar* new_text, int new_text_len) -{ - const int text_len = obj->CurLenW; - IM_ASSERT(pos <= text_len); - if (new_text_len + text_len + 1 > obj->Text.Size) - return false; - - const int new_text_len_utf8 = ImTextCountUtf8BytesFromStr(new_text, new_text + new_text_len); - if (new_text_len_utf8 + obj->CurLenA + 1 > obj->BufSizeA) - return false; - - ImWchar* text = obj->Text.Data; - if (pos != text_len) - memmove(text + pos + new_text_len, text + pos, (size_t)(text_len - pos) * sizeof(ImWchar)); - memcpy(text + pos, new_text, (size_t)new_text_len * sizeof(ImWchar)); - - obj->CurLenW += new_text_len; - obj->CurLenA += new_text_len_utf8; - obj->Text[obj->CurLenW] = '\0'; - - return true; -} - -// We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols) -#define STB_TEXTEDIT_K_LEFT 0x10000 // keyboard input to move cursor left -#define STB_TEXTEDIT_K_RIGHT 0x10001 // keyboard input to move cursor right -#define STB_TEXTEDIT_K_UP 0x10002 // keyboard input to move cursor up -#define STB_TEXTEDIT_K_DOWN 0x10003 // keyboard input to move cursor down -#define STB_TEXTEDIT_K_LINESTART 0x10004 // keyboard input to move cursor to start of line -#define STB_TEXTEDIT_K_LINEEND 0x10005 // keyboard input to move cursor to end of line -#define STB_TEXTEDIT_K_TEXTSTART 0x10006 // keyboard input to move cursor to start of text -#define STB_TEXTEDIT_K_TEXTEND 0x10007 // keyboard input to move cursor to end of text -#define STB_TEXTEDIT_K_DELETE 0x10008 // keyboard input to delete selection or character under cursor -#define STB_TEXTEDIT_K_BACKSPACE 0x10009 // keyboard input to delete selection or character left of cursor -#define STB_TEXTEDIT_K_UNDO 0x1000A // keyboard input to perform undo -#define STB_TEXTEDIT_K_REDO 0x1000B // keyboard input to perform redo -#define STB_TEXTEDIT_K_WORDLEFT 0x1000C // keyboard input to move cursor left one word -#define STB_TEXTEDIT_K_WORDRIGHT 0x1000D // keyboard input to move cursor right one word -#define STB_TEXTEDIT_K_SHIFT 0x20000 - -#define STB_TEXTEDIT_IMPLEMENTATION -#include "stb_textedit.h" - -} - -void ImGuiTextEditState::OnKeyPressed(int key) -{ - stb_textedit_key(this, &StbState, key); - CursorFollow = true; - CursorAnimReset(); -} - -// Public API to manipulate UTF-8 text -// We expose UTF-8 to the user (unlike the STB_TEXTEDIT_* functions which are manipulating wchar) -// FIXME: The existence of this rarely exercised code path is a bit of a nuisance. -void ImGuiTextEditCallbackData::DeleteChars(int pos, int bytes_count) -{ - IM_ASSERT(pos + bytes_count <= BufTextLen); - char* dst = Buf + pos; - const char* src = Buf + pos + bytes_count; - while (char c = *src++) - *dst++ = c; - *dst = '\0'; - - if (CursorPos + bytes_count >= pos) - CursorPos -= bytes_count; - else if (CursorPos >= pos) - CursorPos = pos; - SelectionStart = SelectionEnd = CursorPos; - BufDirty = true; - BufTextLen -= bytes_count; -} - -void ImGuiTextEditCallbackData::InsertChars(int pos, const char* new_text, const char* new_text_end) -{ - const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)strlen(new_text); - if (new_text_len + BufTextLen + 1 >= BufSize) - return; - - if (BufTextLen != pos) - memmove(Buf + pos + new_text_len, Buf + pos, (size_t)(BufTextLen - pos)); - memcpy(Buf + pos, new_text, (size_t)new_text_len * sizeof(char)); - Buf[BufTextLen + new_text_len] = '\0'; - - if (CursorPos >= pos) - CursorPos += new_text_len; - SelectionStart = SelectionEnd = CursorPos; - BufDirty = true; - BufTextLen += new_text_len; -} - -// Return false to discard a character. -static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data) -{ - unsigned int c = *p_char; - - if (c < 128 && c != ' ' && !isprint((int)(c & 0xFF))) - { - bool pass = false; - pass |= (c == '\n' && (flags & ImGuiInputTextFlags_Multiline)); - pass |= (c == '\t' && (flags & ImGuiInputTextFlags_AllowTabInput)); - if (!pass) - return false; - } - - if (c >= 0xE000 && c <= 0xF8FF) // Filter private Unicode range. I don't imagine anybody would want to input them. GLFW on OSX seems to send private characters for special keys like arrow keys. - return false; - - if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank)) - { - if (flags & ImGuiInputTextFlags_CharsDecimal) - if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/')) - return false; - - if (flags & ImGuiInputTextFlags_CharsHexadecimal) - if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F')) - return false; - - if (flags & ImGuiInputTextFlags_CharsUppercase) - if (c >= 'a' && c <= 'z') - *p_char = (c += (unsigned int)('A'-'a')); - - if (flags & ImGuiInputTextFlags_CharsNoBlank) - if (ImCharIsSpace(c)) - return false; - } - - if (flags & ImGuiInputTextFlags_CallbackCharFilter) - { - ImGuiTextEditCallbackData callback_data; - memset(&callback_data, 0, sizeof(ImGuiTextEditCallbackData)); - callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter; - callback_data.EventChar = (ImWchar)c; - callback_data.Flags = flags; - callback_data.UserData = user_data; - if (callback(&callback_data) != 0) - return false; - *p_char = callback_data.EventChar; - if (!callback_data.EventChar) - return false; - } - - return true; -} - -// Edit a string of text -// NB: when active, hold on a privately held copy of the text (and apply back to 'buf'). So changing 'buf' while active has no effect. -// FIXME: Rather messy function partly because we are doing UTF8 > u16 > UTF8 conversions on the go to more easily handle stb_textedit calls. Ideally we should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188 -bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackHistory) && (flags & ImGuiInputTextFlags_Multiline))); // Can't use both together (they both use up/down keys) - IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackCompletion) && (flags & ImGuiInputTextFlags_AllowTabInput))); // Can't use both together (they both use tab key) - - ImGuiContext& g = *GImGui; - const ImGuiIO& io = g.IO; - const ImGuiStyle& style = g.Style; - - const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0; - const bool is_editable = (flags & ImGuiInputTextFlags_ReadOnly) == 0; - const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0; - - if (is_multiline) // Open group before calling GetID() because groups tracks id created during their spawn - BeginGroup(); - const ImGuiID id = window->GetID(label); - const ImVec2 label_size = CalcTextSize(label, NULL, true); - ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? GetTextLineHeight() * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size); - const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f)); - - ImGuiWindow* draw_window = window; - if (is_multiline) - { - if (!BeginChildFrame(id, frame_bb.GetSize())) - { - EndChildFrame(); - EndGroup(); - return false; - } - draw_window = GetCurrentWindow(); - size.x -= draw_window->ScrollbarSizes.x; - } - else - { - ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, &id)) - return false; - } - - // Password pushes a temporary font with only a fallback glyph - if (is_password) - { - const ImFont::Glyph* glyph = g.Font->FindGlyph('*'); - ImFont* password_font = &g.InputTextPasswordFont; - password_font->FontSize = g.Font->FontSize; - password_font->Scale = g.Font->Scale; - password_font->DisplayOffset = g.Font->DisplayOffset; - password_font->Ascent = g.Font->Ascent; - password_font->Descent = g.Font->Descent; - password_font->ContainerAtlas = g.Font->ContainerAtlas; - password_font->FallbackGlyph = glyph; - password_font->FallbackXAdvance = glyph->XAdvance; - IM_ASSERT(password_font->Glyphs.empty() && password_font->IndexXAdvance.empty() && password_font->IndexLookup.empty()); - PushFont(password_font); - } - - // NB: we are only allowed to access 'edit_state' if we are the active widget. - ImGuiTextEditState& edit_state = g.InputTextState; - - const bool focus_requested = FocusableItemRegister(window, g.ActiveId == id, (flags & (ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_AllowTabInput)) == 0); // Using completion callback disable keyboard tabbing - const bool focus_requested_by_code = focus_requested && (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent); - const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code; - - const bool hovered = IsHovered(frame_bb, id); - if (hovered) - { - SetHoveredID(id); - g.MouseCursor = ImGuiMouseCursor_TextInput; - } - const bool user_clicked = hovered && io.MouseClicked[0]; - const bool user_scrolled = is_multiline && g.ActiveId == 0 && edit_state.Id == id && g.ActiveIdPreviousFrame == draw_window->GetIDNoKeepAlive("#SCROLLY"); - - bool select_all = (g.ActiveId != id) && (flags & ImGuiInputTextFlags_AutoSelectAll) != 0; - if (focus_requested || user_clicked || user_scrolled) - { - if (g.ActiveId != id) - { - // Start edition - // Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar) - // From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode) - const int prev_len_w = edit_state.CurLenW; - edit_state.Text.resize(buf_size+1); // wchar count <= UTF-8 count. we use +1 to make sure that .Data isn't NULL so it doesn't crash. - edit_state.InitialText.resize(buf_size+1); // UTF-8. we use +1 to make sure that .Data isn't NULL so it doesn't crash. - ImStrncpy(edit_state.InitialText.Data, buf, edit_state.InitialText.Size); - const char* buf_end = NULL; - edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end); - edit_state.CurLenA = (int)(buf_end - buf); // We can't get the result from ImFormatString() above because it is not UTF-8 aware. Here we'll cut off malformed UTF-8. - edit_state.CursorAnimReset(); - - // Preserve cursor position and undo/redo stack if we come back to same widget - // FIXME: We should probably compare the whole buffer to be on the safety side. Comparing buf (utf8) and edit_state.Text (wchar). - const bool recycle_state = (edit_state.Id == id) && (prev_len_w == edit_state.CurLenW); - if (recycle_state) - { - // Recycle existing cursor/selection/undo stack but clamp position - // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler. - edit_state.CursorClamp(); - } - else - { - edit_state.Id = id; - edit_state.ScrollX = 0.0f; - stb_textedit_initialize_state(&edit_state.StbState, !is_multiline); - if (!is_multiline && focus_requested_by_code) - select_all = true; - } - if (flags & ImGuiInputTextFlags_AlwaysInsertMode) - edit_state.StbState.insert_mode = true; - if (!is_multiline && (focus_requested_by_tab || (user_clicked && io.KeyCtrl))) - select_all = true; - } - SetActiveID(id, window); - FocusWindow(window); - } - else if (io.MouseClicked[0]) - { - // Release focus when we click outside - if (g.ActiveId == id) - ClearActiveID(); - } - - bool value_changed = false; - bool enter_pressed = false; - - if (g.ActiveId == id) - { - if (!is_editable && !g.ActiveIdIsJustActivated) - { - // When read-only we always use the live data passed to the function - edit_state.Text.resize(buf_size+1); - const char* buf_end = NULL; - edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end); - edit_state.CurLenA = (int)(buf_end - buf); - edit_state.CursorClamp(); - } - - edit_state.BufSizeA = buf_size; - - // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget. - // Down the line we should have a cleaner library-wide concept of Selected vs Active. - g.ActiveIdAllowOverlap = !io.MouseDown[0]; - - // Edit in progress - const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX; - const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y - style.FramePadding.y) : (g.FontSize*0.5f)); - - const bool osx_double_click_selects_words = io.OSXBehaviors; // OS X style: Double click selects by word instead of selecting whole text - if (select_all || (hovered && !osx_double_click_selects_words && io.MouseDoubleClicked[0])) - { - edit_state.SelectAll(); - edit_state.SelectedAllMouseLock = true; - } - else if (hovered && osx_double_click_selects_words && io.MouseDoubleClicked[0]) - { - // Select a word only, OS X style (by simulating keystrokes) - edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT); - edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT); - } - else if (io.MouseClicked[0] && !edit_state.SelectedAllMouseLock) - { - stb_textedit_click(&edit_state, &edit_state.StbState, mouse_x, mouse_y); - edit_state.CursorAnimReset(); - } - else if (io.MouseDown[0] && !edit_state.SelectedAllMouseLock && (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)) - { - stb_textedit_drag(&edit_state, &edit_state.StbState, mouse_x, mouse_y); - edit_state.CursorAnimReset(); - edit_state.CursorFollow = true; - } - if (edit_state.SelectedAllMouseLock && !io.MouseDown[0]) - edit_state.SelectedAllMouseLock = false; - - if (io.InputCharacters[0]) - { - // Process text input (before we check for Return because using some IME will effectively send a Return?) - // We ignore CTRL inputs, but need to allow CTRL+ALT as some keyboards (e.g. German) use AltGR - which is Alt+Ctrl - to input certain characters. - if (!(io.KeyCtrl && !io.KeyAlt) && is_editable) - { - for (int n = 0; n < IM_ARRAYSIZE(io.InputCharacters) && io.InputCharacters[n]; n++) - if (unsigned int c = (unsigned int)io.InputCharacters[n]) - { - // Insert character if they pass filtering - if (!InputTextFilterCharacter(&c, flags, callback, user_data)) - continue; - edit_state.OnKeyPressed((int)c); - } - } - - // Consume characters - memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters)); - } - - // Handle various key-presses - bool cancel_edit = false; - const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0); - const bool is_shortcut_key_only = (io.OSXBehaviors ? (io.KeySuper && !io.KeyCtrl) : (io.KeyCtrl && !io.KeySuper)) && !io.KeyAlt && !io.KeyShift; // OS X style: Shortcuts using Cmd/Super instead of Ctrl - const bool is_wordmove_key_down = io.OSXBehaviors ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl - const bool is_startend_key_down = io.OSXBehaviors && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End - - if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetWindowScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetWindowScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_Home)) { edit_state.OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_End)) { edit_state.OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_Delete) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_Backspace) && is_editable) - { - if (!edit_state.HasSelection()) - { - if (is_wordmove_key_down) edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT|STB_TEXTEDIT_K_SHIFT); - else if (io.OSXBehaviors && io.KeySuper && !io.KeyAlt && !io.KeyCtrl) edit_state.OnKeyPressed(STB_TEXTEDIT_K_LINESTART|STB_TEXTEDIT_K_SHIFT); - } - edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); - } - else if (IsKeyPressedMap(ImGuiKey_Enter)) - { - bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0; - if (!is_multiline || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl)) - { - ClearActiveID(); - enter_pressed = true; - } - else if (is_editable) - { - unsigned int c = '\n'; // Insert new line - if (InputTextFilterCharacter(&c, flags, callback, user_data)) - edit_state.OnKeyPressed((int)c); - } - } - else if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressedMap(ImGuiKey_Tab) && !io.KeyCtrl && !io.KeyShift && !io.KeyAlt && is_editable) - { - unsigned int c = '\t'; // Insert TAB - if (InputTextFilterCharacter(&c, flags, callback, user_data)) - edit_state.OnKeyPressed((int)c); - } - else if (IsKeyPressedMap(ImGuiKey_Escape)) { ClearActiveID(); cancel_edit = true; } - else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Z) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); edit_state.ClearSelection(); } - else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Y) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); edit_state.ClearSelection(); } - else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); edit_state.CursorFollow = true; } - else if (is_shortcut_key_only && !is_password && ((IsKeyPressedMap(ImGuiKey_X) && is_editable) || IsKeyPressedMap(ImGuiKey_C)) && (!is_multiline || edit_state.HasSelection())) - { - // Cut, Copy - const bool cut = IsKeyPressedMap(ImGuiKey_X); - if (cut && !edit_state.HasSelection()) - edit_state.SelectAll(); - - if (io.SetClipboardTextFn) - { - const int ib = edit_state.HasSelection() ? ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end) : 0; - const int ie = edit_state.HasSelection() ? ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end) : edit_state.CurLenW; - edit_state.TempTextBuffer.resize((ie-ib) * 4 + 1); - ImTextStrToUtf8(edit_state.TempTextBuffer.Data, edit_state.TempTextBuffer.Size, edit_state.Text.Data+ib, edit_state.Text.Data+ie); - SetClipboardText(edit_state.TempTextBuffer.Data); - } - - if (cut) - { - edit_state.CursorFollow = true; - stb_textedit_cut(&edit_state, &edit_state.StbState); - } - } - else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_V) && is_editable) - { - // Paste - if (const char* clipboard = GetClipboardText()) - { - // Filter pasted buffer - const int clipboard_len = (int)strlen(clipboard); - ImWchar* clipboard_filtered = (ImWchar*)ImGui::MemAlloc((clipboard_len+1) * sizeof(ImWchar)); - int clipboard_filtered_len = 0; - for (const char* s = clipboard; *s; ) - { - unsigned int c; - s += ImTextCharFromUtf8(&c, s, NULL); - if (c == 0) - break; - if (c >= 0x10000 || !InputTextFilterCharacter(&c, flags, callback, user_data)) - continue; - clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c; - } - clipboard_filtered[clipboard_filtered_len] = 0; - if (clipboard_filtered_len > 0) // If everything was filtered, ignore the pasting operation - { - stb_textedit_paste(&edit_state, &edit_state.StbState, clipboard_filtered, clipboard_filtered_len); - edit_state.CursorFollow = true; - } - ImGui::MemFree(clipboard_filtered); - } - } - - if (cancel_edit) - { - // Restore initial value - if (is_editable) - { - ImStrncpy(buf, edit_state.InitialText.Data, buf_size); - value_changed = true; - } - } - else - { - // Apply new value immediately - copy modified buffer back - // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer - // FIXME: We actually always render 'buf' when calling DrawList->AddText, making the comment above incorrect. - // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks. - if (is_editable) - { - edit_state.TempTextBuffer.resize(edit_state.Text.Size * 4); - ImTextStrToUtf8(edit_state.TempTextBuffer.Data, edit_state.TempTextBuffer.Size, edit_state.Text.Data, NULL); - } - - // User callback - if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackAlways)) != 0) - { - IM_ASSERT(callback != NULL); - - // The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard TABBING at the moment. - ImGuiInputTextFlags event_flag = 0; - ImGuiKey event_key = ImGuiKey_COUNT; - if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && IsKeyPressedMap(ImGuiKey_Tab)) - { - event_flag = ImGuiInputTextFlags_CallbackCompletion; - event_key = ImGuiKey_Tab; - } - else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_UpArrow)) - { - event_flag = ImGuiInputTextFlags_CallbackHistory; - event_key = ImGuiKey_UpArrow; - } - else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_DownArrow)) - { - event_flag = ImGuiInputTextFlags_CallbackHistory; - event_key = ImGuiKey_DownArrow; - } - else if (flags & ImGuiInputTextFlags_CallbackAlways) - event_flag = ImGuiInputTextFlags_CallbackAlways; - - if (event_flag) - { - ImGuiTextEditCallbackData callback_data; - memset(&callback_data, 0, sizeof(ImGuiTextEditCallbackData)); - callback_data.EventFlag = event_flag; - callback_data.Flags = flags; - callback_data.UserData = user_data; - callback_data.ReadOnly = !is_editable; - - callback_data.EventKey = event_key; - callback_data.Buf = edit_state.TempTextBuffer.Data; - callback_data.BufTextLen = edit_state.CurLenA; - callback_data.BufSize = edit_state.BufSizeA; - callback_data.BufDirty = false; - - // We have to convert from wchar-positions to UTF-8-positions, which can be pretty slow (an incentive to ditch the ImWchar buffer, see https://github.com/nothings/stb/issues/188) - ImWchar* text = edit_state.Text.Data; - const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.cursor); - const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.select_start); - const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.select_end); - - // Call user code - callback(&callback_data); - - // Read back what user may have modified - IM_ASSERT(callback_data.Buf == edit_state.TempTextBuffer.Data); // Invalid to modify those fields - IM_ASSERT(callback_data.BufSize == edit_state.BufSizeA); - IM_ASSERT(callback_data.Flags == flags); - if (callback_data.CursorPos != utf8_cursor_pos) edit_state.StbState.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); - if (callback_data.SelectionStart != utf8_selection_start) edit_state.StbState.select_start = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); - if (callback_data.SelectionEnd != utf8_selection_end) edit_state.StbState.select_end = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); - if (callback_data.BufDirty) - { - IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text! - edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, callback_data.Buf, NULL); - edit_state.CurLenA = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen() - edit_state.CursorAnimReset(); - } - } - } - - // Copy back to user buffer - if (is_editable && strcmp(edit_state.TempTextBuffer.Data, buf) != 0) - { - ImStrncpy(buf, edit_state.TempTextBuffer.Data, buf_size); - value_changed = true; - } - } - } - - // Render - // Select which buffer we are going to display. When ImGuiInputTextFlags_NoLiveEdit is set 'buf' might still be the old value. We set buf to NULL to prevent accidental usage from now on. - const char* buf_display = (g.ActiveId == id && is_editable) ? edit_state.TempTextBuffer.Data : buf; buf = NULL; - - if (!is_multiline) - RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - - const ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + size.x, frame_bb.Min.y + size.y); // Not using frame_bb.Max because we have adjusted size - ImVec2 render_pos = is_multiline ? draw_window->DC.CursorPos : frame_bb.Min + style.FramePadding; - ImVec2 text_size(0.f, 0.f); - const bool is_currently_scrolling = (edit_state.Id == id && is_multiline && g.ActiveId == draw_window->GetIDNoKeepAlive("#SCROLLY")); - if (g.ActiveId == id || is_currently_scrolling) - { - edit_state.CursorAnim += io.DeltaTime; - - // This is going to be messy. We need to: - // - Display the text (this alone can be more easily clipped) - // - Handle scrolling, highlight selection, display cursor (those all requires some form of 1d->2d cursor position calculation) - // - Measure text height (for scrollbar) - // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort) - // FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8. - const ImWchar* text_begin = edit_state.Text.Data; - ImVec2 cursor_offset, select_start_offset; - - { - // Count lines + find lines numbers straddling 'cursor' and 'select_start' position. - const ImWchar* searches_input_ptr[2]; - searches_input_ptr[0] = text_begin + edit_state.StbState.cursor; - searches_input_ptr[1] = NULL; - int searches_remaining = 1; - int searches_result_line_number[2] = { -1, -999 }; - if (edit_state.StbState.select_start != edit_state.StbState.select_end) - { - searches_input_ptr[1] = text_begin + ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end); - searches_result_line_number[1] = -1; - searches_remaining++; - } - - // Iterate all lines to find our line numbers - // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter. - searches_remaining += is_multiline ? 1 : 0; - int line_count = 0; - for (const ImWchar* s = text_begin; *s != 0; s++) - if (*s == '\n') - { - line_count++; - if (searches_result_line_number[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_number[0] = line_count; if (--searches_remaining <= 0) break; } - if (searches_result_line_number[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_number[1] = line_count; if (--searches_remaining <= 0) break; } - } - line_count++; - if (searches_result_line_number[0] == -1) searches_result_line_number[0] = line_count; - if (searches_result_line_number[1] == -1) searches_result_line_number[1] = line_count; - - // Calculate 2d position by finding the beginning of the line and measuring distance - cursor_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x; - cursor_offset.y = searches_result_line_number[0] * g.FontSize; - if (searches_result_line_number[1] >= 0) - { - select_start_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x; - select_start_offset.y = searches_result_line_number[1] * g.FontSize; - } - - // Calculate text height - if (is_multiline) - text_size = ImVec2(size.x, line_count * g.FontSize); - } - - // Scroll - if (edit_state.CursorFollow) - { - // Horizontal scroll in chunks of quarter width - if (!(flags & ImGuiInputTextFlags_NoHorizontalScroll)) - { - const float scroll_increment_x = size.x * 0.25f; - if (cursor_offset.x < edit_state.ScrollX) - edit_state.ScrollX = (float)(int)ImMax(0.0f, cursor_offset.x - scroll_increment_x); - else if (cursor_offset.x - size.x >= edit_state.ScrollX) - edit_state.ScrollX = (float)(int)(cursor_offset.x - size.x + scroll_increment_x); - } - else - { - edit_state.ScrollX = 0.0f; - } - - // Vertical scroll - if (is_multiline) - { - float scroll_y = draw_window->Scroll.y; - if (cursor_offset.y - g.FontSize < scroll_y) - scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize); - else if (cursor_offset.y - size.y >= scroll_y) - scroll_y = cursor_offset.y - size.y; - draw_window->DC.CursorPos.y += (draw_window->Scroll.y - scroll_y); // To avoid a frame of lag - draw_window->Scroll.y = scroll_y; - render_pos.y = draw_window->DC.CursorPos.y; - } - } - edit_state.CursorFollow = false; - const ImVec2 render_scroll = ImVec2(edit_state.ScrollX, 0.0f); - - // Draw selection - if (edit_state.StbState.select_start != edit_state.StbState.select_end) - { - const ImWchar* text_selected_begin = text_begin + ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end); - const ImWchar* text_selected_end = text_begin + ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end); - - float bg_offy_up = is_multiline ? 0.0f : -1.0f; // FIXME: those offsets should be part of the style? they don't play so well with multi-line selection. - float bg_offy_dn = is_multiline ? 0.0f : 2.0f; - ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg); - ImVec2 rect_pos = render_pos + select_start_offset - render_scroll; - for (const ImWchar* p = text_selected_begin; p < text_selected_end; ) - { - if (rect_pos.y > clip_rect.w + g.FontSize) - break; - if (rect_pos.y < clip_rect.y) - { - while (p < text_selected_end) - if (*p++ == '\n') - break; - } - else - { - ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true); - if (rect_size.x <= 0.0f) rect_size.x = (float)(int)(g.Font->GetCharAdvance((unsigned short)' ') * 0.50f); // So we can see selected empty lines - ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos +ImVec2(rect_size.x, bg_offy_dn)); - rect.Clip(clip_rect); - if (rect.Overlaps(clip_rect)) - draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color); - } - rect_pos.x = render_pos.x - render_scroll.x; - rect_pos.y += g.FontSize; - } - } - - draw_window->DrawList->AddText(g.Font, g.FontSize, render_pos - render_scroll, GetColorU32(ImGuiCol_Text), buf_display, buf_display + edit_state.CurLenA, 0.0f, is_multiline ? NULL : &clip_rect); - - // Draw blinking cursor - bool cursor_is_visible = (g.InputTextState.CursorAnim <= 0.0f) || fmodf(g.InputTextState.CursorAnim, 1.20f) <= 0.80f; - ImVec2 cursor_screen_pos = render_pos + cursor_offset - render_scroll; - ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y-g.FontSize+0.5f, cursor_screen_pos.x+1.0f, cursor_screen_pos.y-1.5f); - if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect)) - draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text)); - - // Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.) - if (is_editable) - g.OsImePosRequest = ImVec2(cursor_screen_pos.x - 1, cursor_screen_pos.y - g.FontSize); - } - else - { - // Render text only - const char* buf_end = NULL; - if (is_multiline) - text_size = ImVec2(size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_end) * g.FontSize); // We don't need width - draw_window->DrawList->AddText(g.Font, g.FontSize, render_pos, GetColorU32(ImGuiCol_Text), buf_display, buf_end, 0.0f, is_multiline ? NULL : &clip_rect); - } - - if (is_multiline) - { - Dummy(text_size + ImVec2(0.0f, g.FontSize)); // Always add room to scroll an extra line - EndChildFrame(); - EndGroup(); - } - - if (is_password) - PopFont(); - - // Log as text - if (g.LogEnabled && !is_password) - LogRenderedText(render_pos, buf_display, NULL); - - if (label_size.x > 0) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); - - if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0) - return enter_pressed; - else - return value_changed; -} - -bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data) -{ - IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline() - return InputTextEx(label, buf, (int)buf_size, ImVec2(0,0), flags, callback, user_data); -} - -bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data) -{ - return InputTextEx(label, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data); -} - -// NB: scalar_format here must be a simple "%xx" format string with no prefix/suffix (unlike the Drag/Slider functions "display_format" argument) -bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImVec2 label_size = CalcTextSize(label, NULL, true); - - BeginGroup(); - PushID(label); - const ImVec2 button_sz = ImVec2(g.FontSize, g.FontSize) + style.FramePadding*2.0f; - if (step_ptr) - PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_sz.x + style.ItemInnerSpacing.x)*2)); - - char buf[64]; - DataTypeFormatString(data_type, data_ptr, scalar_format, buf, IM_ARRAYSIZE(buf)); - - bool value_changed = false; - if (!(extra_flags & ImGuiInputTextFlags_CharsHexadecimal)) - extra_flags |= ImGuiInputTextFlags_CharsDecimal; - extra_flags |= ImGuiInputTextFlags_AutoSelectAll; - if (InputText("", buf, IM_ARRAYSIZE(buf), extra_flags)) // PushId(label) + "" gives us the expected ID from outside point of view - value_changed = DataTypeApplyOpFromText(buf, GImGui->InputTextState.InitialText.begin(), data_type, data_ptr, scalar_format); - - // Step buttons - if (step_ptr) - { - PopItemWidth(); - SameLine(0, style.ItemInnerSpacing.x); - if (ButtonEx("-", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) - { - DataTypeApplyOp(data_type, '-', data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr); - value_changed = true; - } - SameLine(0, style.ItemInnerSpacing.x); - if (ButtonEx("+", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) - { - DataTypeApplyOp(data_type, '+', data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr); - value_changed = true; - } - } - PopID(); - - if (label_size.x > 0) - { - SameLine(0, style.ItemInnerSpacing.x); - RenderText(ImVec2(window->DC.CursorPos.x, window->DC.CursorPos.y + style.FramePadding.y), label); - ItemSize(label_size, style.FramePadding.y); - } - EndGroup(); - - return value_changed; -} - -bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags extra_flags) -{ - char display_format[16]; - if (decimal_precision < 0) - strcpy(display_format, "%f"); // Ideally we'd have a minimum decimal precision of 1 to visually denote that this is a float, while hiding non-significant digits? %f doesn't have a minimum of 1 - else - ImFormatString(display_format, IM_ARRAYSIZE(display_format), "%%.%df", decimal_precision); - return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), display_format, extra_flags); -} - -bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags extra_flags) -{ - // Hexadecimal input provided as a convenience but the flag name is awkward. Typically you'd use InputText() to parse your own data, if you want to handle prefixes. - const char* scalar_format = (extra_flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d"; - return InputScalarEx(label, ImGuiDataType_Int, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), scalar_format, extra_flags); -} - -bool ImGui::InputFloatN(const char* label, float* v, int components, int decimal_precision, ImGuiInputTextFlags extra_flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - bool value_changed = false; - BeginGroup(); - PushID(label); - PushMultiItemsWidths(components); - for (int i = 0; i < components; i++) - { - PushID(i); - value_changed |= InputFloat("##v", &v[i], 0, 0, decimal_precision, extra_flags); - SameLine(0, g.Style.ItemInnerSpacing.x); - PopID(); - PopItemWidth(); - } - PopID(); - - window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y); - TextUnformatted(label, FindRenderedTextEnd(label)); - EndGroup(); - - return value_changed; -} - -bool ImGui::InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags extra_flags) -{ - return InputFloatN(label, v, 2, decimal_precision, extra_flags); -} - -bool ImGui::InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags extra_flags) -{ - return InputFloatN(label, v, 3, decimal_precision, extra_flags); -} - -bool ImGui::InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags extra_flags) -{ - return InputFloatN(label, v, 4, decimal_precision, extra_flags); -} - -bool ImGui::InputIntN(const char* label, int* v, int components, ImGuiInputTextFlags extra_flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - bool value_changed = false; - BeginGroup(); - PushID(label); - PushMultiItemsWidths(components); - for (int i = 0; i < components; i++) - { - PushID(i); - value_changed |= InputInt("##v", &v[i], 0, 0, extra_flags); - SameLine(0, g.Style.ItemInnerSpacing.x); - PopID(); - PopItemWidth(); - } - PopID(); - - window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y); - TextUnformatted(label, FindRenderedTextEnd(label)); - EndGroup(); - - return value_changed; -} - -bool ImGui::InputInt2(const char* label, int v[2], ImGuiInputTextFlags extra_flags) -{ - return InputIntN(label, v, 2, extra_flags); -} - -bool ImGui::InputInt3(const char* label, int v[3], ImGuiInputTextFlags extra_flags) -{ - return InputIntN(label, v, 3, extra_flags); -} - -bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags extra_flags) -{ - return InputIntN(label, v, 4, extra_flags); -} - -static bool Items_ArrayGetter(void* data, int idx, const char** out_text) -{ - const char* const* items = (const char* const*)data; - if (out_text) - *out_text = items[idx]; - return true; -} - -static bool Items_SingleStringGetter(void* data, int idx, const char** out_text) -{ - // FIXME-OPT: we could pre-compute the indices to fasten this. But only 1 active combo means the waste is limited. - const char* items_separated_by_zeros = (const char*)data; - int items_count = 0; - const char* p = items_separated_by_zeros; - while (*p) - { - if (idx == items_count) - break; - p += strlen(p) + 1; - items_count++; - } - if (!*p) - return false; - if (out_text) - *out_text = p; - return true; -} - -// Combo box helper allowing to pass an array of strings. -bool ImGui::Combo(const char* label, int* current_item, const char* const* items, int items_count, int height_in_items) -{ - const bool value_changed = Combo(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_in_items); - return value_changed; -} - -// Combo box helper allowing to pass all items in a single string. -bool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items) -{ - int items_count = 0; - const char* p = items_separated_by_zeros; // FIXME-OPT: Avoid computing this, or at least only when combo is open - while (*p) - { - p += strlen(p) + 1; - items_count++; - } - bool value_changed = Combo(label, current_item, Items_SingleStringGetter, (void*)items_separated_by_zeros, items_count, height_in_items); - return value_changed; -} - -// Combo box function. -bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const float w = CalcItemWidth(); - - const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); - const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); - ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, &id)) - return false; - - const float arrow_size = (g.FontSize + style.FramePadding.x * 2.0f); - const bool hovered = IsHovered(frame_bb, id); - bool popup_open = IsPopupOpen(id); - bool popup_opened_now = false; - - const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f)); - RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING - RenderCollapseTriangle(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y) + style.FramePadding, true); - - if (*current_item >= 0 && *current_item < items_count) - { - const char* item_text; - if (items_getter(data, *current_item, &item_text)) - RenderTextClipped(frame_bb.Min + style.FramePadding, value_bb.Max, item_text, NULL, NULL, ImVec2(0.0f,0.0f)); - } - - if (label_size.x > 0) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); - - if (hovered) - { - SetHoveredID(id); - if (g.IO.MouseClicked[0]) - { - ClearActiveID(); - if (IsPopupOpen(id)) - { - ClosePopup(id); - } - else - { - FocusWindow(window); - OpenPopup(label); - popup_open = popup_opened_now = true; - } - } - } - - bool value_changed = false; - if (IsPopupOpen(id)) - { - // Size default to hold ~7 items - if (height_in_items < 0) - height_in_items = 7; - - float popup_height = (label_size.y + style.ItemSpacing.y) * ImMin(items_count, height_in_items) + (style.FramePadding.y * 3); - float popup_y1 = frame_bb.Max.y; - float popup_y2 = ImClamp(popup_y1 + popup_height, popup_y1, g.IO.DisplaySize.y - style.DisplaySafeAreaPadding.y); - if ((popup_y2 - popup_y1) < ImMin(popup_height, frame_bb.Min.y - style.DisplaySafeAreaPadding.y)) - { - // Position our combo ABOVE because there's more space to fit! (FIXME: Handle in Begin() or use a shared helper. We have similar code in Begin() for popup placement) - popup_y1 = ImClamp(frame_bb.Min.y - popup_height, style.DisplaySafeAreaPadding.y, frame_bb.Min.y); - popup_y2 = frame_bb.Min.y; - } - ImRect popup_rect(ImVec2(frame_bb.Min.x, popup_y1), ImVec2(frame_bb.Max.x, popup_y2)); - SetNextWindowPos(popup_rect.Min); - SetNextWindowSize(popup_rect.GetSize()); - PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); - - const ImGuiWindowFlags flags = ImGuiWindowFlags_ComboBox | ((window->Flags & ImGuiWindowFlags_ShowBorders) ? ImGuiWindowFlags_ShowBorders : 0); - if (BeginPopupEx(label, flags)) - { - // Display items - Spacing(); - for (int i = 0; i < items_count; i++) - { - PushID((void*)(intptr_t)i); - const bool item_selected = (i == *current_item); - const char* item_text; - if (!items_getter(data, i, &item_text)) - item_text = "*Unknown item*"; - if (Selectable(item_text, item_selected)) - { - ClearActiveID(); - value_changed = true; - *current_item = i; - } - if (item_selected && popup_opened_now) - SetScrollHere(); - PopID(); - } - EndPopup(); - } - PopStyleVar(); - } - return value_changed; -} - -// Tip: pass an empty label (e.g. "##dummy") then you can use the space to draw other text or image. -// But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID. -bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) - PopClipRect(); - - ImGuiID id = window->GetID(label); - ImVec2 label_size = CalcTextSize(label, NULL, true); - ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y); - ImVec2 pos = window->DC.CursorPos; - pos.y += window->DC.CurrentLineTextBaseOffset; - ImRect bb(pos, pos + size); - ItemSize(bb); - - // Fill horizontal space. - ImVec2 window_padding = window->WindowPadding; - float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? GetWindowContentRegionMax().x : GetContentRegionMax().x; - float w_draw = ImMax(label_size.x, window->Pos.x + max_x - window_padding.x - window->DC.CursorPos.x); - ImVec2 size_draw((size_arg.x != 0 && !(flags & ImGuiSelectableFlags_DrawFillAvailWidth)) ? size_arg.x : w_draw, size_arg.y != 0.0f ? size_arg.y : size.y); - ImRect bb_with_spacing(pos, pos + size_draw); - if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_DrawFillAvailWidth)) - bb_with_spacing.Max.x += window_padding.x; - - // Selectables are tightly packed together, we extend the box to cover spacing between selectable. - float spacing_L = (float)(int)(style.ItemSpacing.x * 0.5f); - float spacing_U = (float)(int)(style.ItemSpacing.y * 0.5f); - float spacing_R = style.ItemSpacing.x - spacing_L; - float spacing_D = style.ItemSpacing.y - spacing_U; - bb_with_spacing.Min.x -= spacing_L; - bb_with_spacing.Min.y -= spacing_U; - bb_with_spacing.Max.x += spacing_R; - bb_with_spacing.Max.y += spacing_D; - if (!ItemAdd(bb_with_spacing, &id)) - { - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) - PushColumnClipRect(); - return false; - } - - ImGuiButtonFlags button_flags = 0; - if (flags & ImGuiSelectableFlags_Menu) button_flags |= ImGuiButtonFlags_PressedOnClick; - if (flags & ImGuiSelectableFlags_MenuItem) button_flags |= ImGuiButtonFlags_PressedOnClick|ImGuiButtonFlags_PressedOnRelease; - if (flags & ImGuiSelectableFlags_Disabled) button_flags |= ImGuiButtonFlags_Disabled; - if (flags & ImGuiSelectableFlags_AllowDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; - bool hovered, held; - bool pressed = ButtonBehavior(bb_with_spacing, id, &hovered, &held, button_flags); - if (flags & ImGuiSelectableFlags_Disabled) - selected = false; - - // Render - if (hovered || selected) - { - const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - RenderFrame(bb_with_spacing.Min, bb_with_spacing.Max, col, false, 0.0f); - } - - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) - { - PushColumnClipRect(); - bb_with_spacing.Max.x -= (GetContentRegionMax().x - max_x); - } - - if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); - RenderTextClipped(bb.Min, bb_with_spacing.Max, label, NULL, &label_size, ImVec2(0.0f,0.0f)); - if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor(); - - // Automatically close popups - if (pressed && !(flags & ImGuiSelectableFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup)) - CloseCurrentPopup(); - return pressed; -} - -bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) -{ - if (Selectable(label, *p_selected, flags, size_arg)) - { - *p_selected = !*p_selected; - return true; - } - return false; -} - -// Helper to calculate the size of a listbox and display a label on the right. -// Tip: To have a list filling the entire window width, PushItemWidth(-1) and pass an empty label "##empty" -bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - const ImGuiStyle& style = GetStyle(); - const ImGuiID id = GetID(label); - const ImVec2 label_size = CalcTextSize(label, NULL, true); - - // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar. - ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y); - ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y)); - ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); - ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); - window->DC.LastItemRect = bb; - - BeginGroup(); - if (label_size.x > 0) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); - - BeginChildFrame(id, frame_bb.GetSize()); - return true; -} - -bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_items) -{ - // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar. - // However we don't add +0.40f if items_count <= height_in_items. It is slightly dodgy, because it means a dynamic list of items will make the widget resize occasionally when it crosses that size. - // I am expecting that someone will come and complain about this behavior in a remote future, then we can advise on a better solution. - if (height_in_items < 0) - height_in_items = ImMin(items_count, 7); - float height_in_items_f = height_in_items < items_count ? (height_in_items + 0.40f) : (height_in_items + 0.00f); - - // We include ItemSpacing.y so that a list sized for the exact number of items doesn't make a scrollbar appears. We could also enforce that by passing a flag to BeginChild(). - ImVec2 size; - size.x = 0.0f; - size.y = GetTextLineHeightWithSpacing() * height_in_items_f + GetStyle().ItemSpacing.y; - return ListBoxHeader(label, size); -} - -void ImGui::ListBoxFooter() -{ - ImGuiWindow* parent_window = GetParentWindow(); - const ImRect bb = parent_window->DC.LastItemRect; - const ImGuiStyle& style = GetStyle(); - - EndChildFrame(); - - // Redeclare item size so that it includes the label (we have stored the full size in LastItemRect) - // We call SameLine() to restore DC.CurrentLine* data - SameLine(); - parent_window->DC.CursorPos = bb.Min; - ItemSize(bb, style.FramePadding.y); - EndGroup(); -} - -bool ImGui::ListBox(const char* label, int* current_item, const char* const* items, int items_count, int height_items) -{ - const bool value_changed = ListBox(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_items); - return value_changed; -} - -bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items) -{ - if (!ListBoxHeader(label, items_count, height_in_items)) - return false; - - // Assume all items have even height (= 1 line of text). If you need items of different or variable sizes you can create a custom version of ListBox() in your code without using the clipper. - bool value_changed = false; - ImGuiListClipper clipper(items_count, GetTextLineHeightWithSpacing()); - while (clipper.Step()) - for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) - { - const bool item_selected = (i == *current_item); - const char* item_text; - if (!items_getter(data, i, &item_text)) - item_text = "*Unknown item*"; - - PushID(i); - if (Selectable(item_text, item_selected)) - { - *current_item = i; - value_changed = true; - } - PopID(); - } - ListBoxFooter(); - return value_changed; -} - -bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, bool enabled) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - ImVec2 pos = window->DC.CursorPos; - ImVec2 label_size = CalcTextSize(label, NULL, true); - ImVec2 shortcut_size = shortcut ? CalcTextSize(shortcut, NULL) : ImVec2(0.0f, 0.0f); - float w = window->MenuColumns.DeclColumns(label_size.x, shortcut_size.x, (float)(int)(g.FontSize * 1.20f)); // Feedback for next frame - float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); - - bool pressed = Selectable(label, false, ImGuiSelectableFlags_MenuItem | ImGuiSelectableFlags_DrawFillAvailWidth | (enabled ? 0 : ImGuiSelectableFlags_Disabled), ImVec2(w, 0.0f)); - if (shortcut_size.x > 0.0f) - { - PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); - RenderText(pos + ImVec2(window->MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false); - PopStyleColor(); - } - - if (selected) - RenderCheckMark(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.20f, 0.0f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled)); - - return pressed; -} - -bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled) -{ - if (MenuItem(label, shortcut, p_selected ? *p_selected : false, enabled)) - { - if (p_selected) - *p_selected = !*p_selected; - return true; - } - return false; -} - -bool ImGui::BeginMainMenuBar() -{ - ImGuiContext& g = *GImGui; - SetNextWindowPos(ImVec2(0.0f, 0.0f)); - SetNextWindowSize(ImVec2(g.IO.DisplaySize.x, g.FontBaseSize + g.Style.FramePadding.y * 2.0f)); - PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); - PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0,0)); - if (!Begin("##MainMenuBar", NULL, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_MenuBar) - || !BeginMenuBar()) - { - End(); - PopStyleVar(2); - return false; - } - g.CurrentWindow->DC.MenuBarOffsetX += g.Style.DisplaySafeAreaPadding.x; - return true; -} - -void ImGui::EndMainMenuBar() -{ - EndMenuBar(); - End(); - PopStyleVar(2); -} - -bool ImGui::BeginMenuBar() -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - if (!(window->Flags & ImGuiWindowFlags_MenuBar)) - return false; - - IM_ASSERT(!window->DC.MenuBarAppending); - BeginGroup(); // Save position - PushID("##menubar"); - ImRect rect = window->MenuBarRect(); - PushClipRect(ImVec2(ImFloor(rect.Min.x+0.5f), ImFloor(rect.Min.y + window->BorderSize + 0.5f)), ImVec2(ImFloor(rect.Max.x+0.5f), ImFloor(rect.Max.y+0.5f)), false); - window->DC.CursorPos = ImVec2(rect.Min.x + window->DC.MenuBarOffsetX, rect.Min.y);// + g.Style.FramePadding.y); - window->DC.LayoutType = ImGuiLayoutType_Horizontal; - window->DC.MenuBarAppending = true; - AlignFirstTextHeightToWidgets(); - return true; -} - -void ImGui::EndMenuBar() -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar); - IM_ASSERT(window->DC.MenuBarAppending); - PopClipRect(); - PopID(); - window->DC.MenuBarOffsetX = window->DC.CursorPos.x - window->MenuBarRect().Min.x; - window->DC.GroupStack.back().AdvanceCursor = false; - EndGroup(); - window->DC.LayoutType = ImGuiLayoutType_Vertical; - window->DC.MenuBarAppending = false; -} - -bool ImGui::BeginMenu(const char* label, bool enabled) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - - ImVec2 label_size = CalcTextSize(label, NULL, true); - ImGuiWindow* backed_focused_window = g.FocusedWindow; - - bool pressed; - bool menu_is_open = IsPopupOpen(id); - bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentMenuSet == window->GetID("##menus")); - if (menuset_is_open) - g.FocusedWindow = window; - - // The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu (using FindBestPopupWindowPos). - ImVec2 popup_pos, pos = window->DC.CursorPos; - if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) - { - popup_pos = ImVec2(pos.x - window->WindowPadding.x, pos.y - style.FramePadding.y + window->MenuBarHeight()); - window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); - PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f); - float w = label_size.x; - pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); - PopStyleVar(); - SameLine(); - window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); - } - else - { - popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y); - float w = window->MenuColumns.DeclColumns(label_size.x, 0.0f, (float)(int)(g.FontSize * 1.20f)); // Feedback to next frame - float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); - pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); - if (!enabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); - RenderCollapseTriangle(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.20f, 0.0f), false); - if (!enabled) PopStyleColor(); - } - - bool hovered = enabled && IsHovered(window->DC.LastItemRect, id); - if (menuset_is_open) - g.FocusedWindow = backed_focused_window; - - bool want_open = false, want_close = false; - if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) - { - // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive. - bool moving_within_opened_triangle = false; - if (g.HoveredWindow == window && g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentWindow == window) - { - if (ImGuiWindow* next_window = g.OpenPopupStack[g.CurrentPopupStack.Size].Window) - { - ImRect next_window_rect = next_window->Rect(); - ImVec2 ta = g.IO.MousePos - g.IO.MouseDelta; - ImVec2 tb = (window->Pos.x < next_window->Pos.x) ? next_window_rect.GetTL() : next_window_rect.GetTR(); - ImVec2 tc = (window->Pos.x < next_window->Pos.x) ? next_window_rect.GetBL() : next_window_rect.GetBR(); - float extra = ImClamp(fabsf(ta.x - tb.x) * 0.30f, 5.0f, 30.0f); // add a bit of extra slack. - ta.x += (window->Pos.x < next_window->Pos.x) ? -0.5f : +0.5f; // to avoid numerical issues - tb.y = ta.y + ImMax((tb.y - extra) - ta.y, -100.0f); // triangle is maximum 200 high to limit the slope and the bias toward large sub-menus // FIXME: Multiply by fb_scale? - tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +100.0f); - moving_within_opened_triangle = ImIsPointInTriangle(g.IO.MousePos, ta, tb, tc); - //window->DrawList->PushClipRectFullScreen(); window->DrawList->AddTriangleFilled(ta, tb, tc, moving_within_opened_triangle ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); window->DrawList->PopClipRect(); // Debug - } - } - - want_close = (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_within_opened_triangle); - want_open = (!menu_is_open && hovered && !moving_within_opened_triangle) || (!menu_is_open && hovered && pressed); - } - else if (menu_is_open && pressed && menuset_is_open) // menu-bar: click open menu to close - { - want_close = true; - want_open = menu_is_open = false; - } - else if (pressed || (hovered && menuset_is_open && !menu_is_open)) // menu-bar: first click to open, then hover to open others - want_open = true; - if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }' - want_close = true; - if (want_close && IsPopupOpen(id)) - ClosePopupToLevel(GImGui->CurrentPopupStack.Size); - - if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.CurrentPopupStack.Size) - { - // Don't recycle same menu level in the same frame, first close the other menu and yield for a frame. - OpenPopup(label); - return false; - } - - menu_is_open |= want_open; - if (want_open) - OpenPopup(label); - - if (menu_is_open) - { - SetNextWindowPos(popup_pos, ImGuiSetCond_Always); - ImGuiWindowFlags flags = ImGuiWindowFlags_ShowBorders | ((window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) ? ImGuiWindowFlags_ChildMenu|ImGuiWindowFlags_ChildWindow : ImGuiWindowFlags_ChildMenu); - menu_is_open = BeginPopupEx(label, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) - } - - return menu_is_open; -} - -void ImGui::EndMenu() -{ - EndPopup(); -} - -// A little colored square. Return true when clicked. -// FIXME: May want to display/ignore the alpha component in the color display? Yet show it in the tooltip. -bool ImGui::ColorButton(const ImVec4& col, bool small_height, bool outline_border) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID("#colorbutton"); - const float square_size = g.FontSize; - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(square_size + style.FramePadding.y*2, square_size + (small_height ? 0 : style.FramePadding.y*2))); - ItemSize(bb, small_height ? 0.0f : style.FramePadding.y); - if (!ItemAdd(bb, &id)) - return false; - - bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held); - RenderFrame(bb.Min, bb.Max, GetColorU32(col), outline_border, style.FrameRounding); - - if (hovered) - SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col.x, col.y, col.z, col.w, IM_F32_TO_INT8_SAT(col.x), IM_F32_TO_INT8_SAT(col.y), IM_F32_TO_INT8_SAT(col.z), IM_F32_TO_INT8_SAT(col.w)); - - return pressed; -} - -bool ImGui::ColorEdit3(const char* label, float col[3]) -{ - float col4[4]; - col4[0] = col[0]; - col4[1] = col[1]; - col4[2] = col[2]; - col4[3] = 1.0f; - const bool value_changed = ColorEdit4(label, col4, false); - col[0] = col4[0]; - col[1] = col4[1]; - col[2] = col4[2]; - return value_changed; -} - -// Edit colors components (each component in 0.0f..1.0f range -// Use CTRL-Click to input value and TAB to go to next item. -bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const float w_full = CalcItemWidth(); - const float square_sz = (g.FontSize + style.FramePadding.y * 2.0f); - - ImGuiColorEditMode edit_mode = window->DC.ColorEditMode; - if (edit_mode == ImGuiColorEditMode_UserSelect || edit_mode == ImGuiColorEditMode_UserSelectShowButton) - edit_mode = g.ColorEditModeStorage.GetInt(id, 0) % 3; - - float f[4] = { col[0], col[1], col[2], col[3] }; - if (edit_mode == ImGuiColorEditMode_HSV) - ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); - - int i[4] = { IM_F32_TO_INT8_UNBOUND(f[0]), IM_F32_TO_INT8_UNBOUND(f[1]), IM_F32_TO_INT8_UNBOUND(f[2]), IM_F32_TO_INT8_UNBOUND(f[3]) }; - - int components = alpha ? 4 : 3; - bool value_changed = false; - - BeginGroup(); - PushID(label); - - const bool hsv = (edit_mode == 1); - switch (edit_mode) - { - case ImGuiColorEditMode_RGB: - case ImGuiColorEditMode_HSV: - { - // RGB/HSV 0..255 Sliders - const float w_items_all = w_full - (square_sz + style.ItemInnerSpacing.x); - const float w_item_one = ImMax(1.0f, (float)(int)((w_items_all - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); - const float w_item_last = ImMax(1.0f, (float)(int)(w_items_all - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); - - const bool hide_prefix = (w_item_one <= CalcTextSize("M:999").x); - const char* ids[4] = { "##X", "##Y", "##Z", "##W" }; - const char* fmt_table[3][4] = - { - { "%3.0f", "%3.0f", "%3.0f", "%3.0f" }, - { "R:%3.0f", "G:%3.0f", "B:%3.0f", "A:%3.0f" }, - { "H:%3.0f", "S:%3.0f", "V:%3.0f", "A:%3.0f" } - }; - const char** fmt = hide_prefix ? fmt_table[0] : hsv ? fmt_table[2] : fmt_table[1]; - - PushItemWidth(w_item_one); - for (int n = 0; n < components; n++) - { - if (n > 0) - SameLine(0, style.ItemInnerSpacing.x); - if (n + 1 == components) - PushItemWidth(w_item_last); - value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, 255, fmt[n]); - } - PopItemWidth(); - PopItemWidth(); - } - break; - case ImGuiColorEditMode_HEX: - { - // RGB Hexadecimal Input - const float w_slider_all = w_full - square_sz; - char buf[64]; - if (alpha) - ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", i[0], i[1], i[2], i[3]); - else - ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", i[0], i[1], i[2]); - PushItemWidth(w_slider_all - style.ItemInnerSpacing.x); - if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase)) - { - value_changed |= true; - char* p = buf; - while (*p == '#' || ImCharIsSpace(*p)) - p++; - i[0] = i[1] = i[2] = i[3] = 0; - if (alpha) - sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); // Treat at unsigned (%X is unsigned) - else - sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]); - } - PopItemWidth(); - } - break; - } - - SameLine(0, style.ItemInnerSpacing.x); - - const ImVec4 col_display(col[0], col[1], col[2], 1.0f); - if (ColorButton(col_display)) - g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); // Don't set local copy of 'edit_mode' right away! - - // Recreate our own tooltip over's ColorButton() one because we want to display correct alpha here - if (IsItemHovered()) - SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col[0], col[1], col[2], col[3], IM_F32_TO_INT8_SAT(col[0]), IM_F32_TO_INT8_SAT(col[1]), IM_F32_TO_INT8_SAT(col[2]), IM_F32_TO_INT8_SAT(col[3])); - - if (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton) - { - SameLine(0, style.ItemInnerSpacing.x); - const char* button_titles[3] = { "RGB", "HSV", "HEX" }; - if (ButtonEx(button_titles[edit_mode], ImVec2(0,0), ImGuiButtonFlags_DontClosePopups)) - g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); // Don't set local copy of 'edit_mode' right away! - } - - const char* label_display_end = FindRenderedTextEnd(label); - if (label != label_display_end) - { - SameLine(0, (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton) ? -1.0f : style.ItemInnerSpacing.x); - TextUnformatted(label, label_display_end); - } - - // Convert back - for (int n = 0; n < 4; n++) - f[n] = i[n] / 255.0f; - if (edit_mode == 1) - ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); - - if (value_changed) - { - col[0] = f[0]; - col[1] = f[1]; - col[2] = f[2]; - if (alpha) - col[3] = f[3]; - } - - PopID(); - EndGroup(); - - return value_changed; -} - -void ImGui::ColorEditMode(ImGuiColorEditMode mode) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.ColorEditMode = mode; -} - -// Horizontal separating line. -void ImGui::Separator() -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - if (window->DC.ColumnsCount > 1) - PopClipRect(); - - float x1 = window->Pos.x; - float x2 = window->Pos.x + window->Size.x; - if (!window->DC.GroupStack.empty()) - x1 += window->DC.IndentX; - - const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y+1.0f)); - ItemSize(ImVec2(0.0f, 0.0f)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit, we don't provide height to not alter layout. - if (!ItemAdd(bb, NULL)) - { - if (window->DC.ColumnsCount > 1) - PushColumnClipRect(); - return; - } - - window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x,bb.Min.y), GetColorU32(ImGuiCol_Border)); - - ImGuiContext& g = *GImGui; - if (g.LogEnabled) - LogText(IM_NEWLINE "--------------------------------"); - - if (window->DC.ColumnsCount > 1) - { - PushColumnClipRect(); - window->DC.ColumnsCellMinY = window->DC.CursorPos.y; - } -} - -void ImGui::Spacing() -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - ItemSize(ImVec2(0,0)); -} - -void ImGui::Dummy(const ImVec2& size) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); - ItemSize(bb); - ItemAdd(bb, NULL); -} - -bool ImGui::IsRectVisible(const ImVec2& size) -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size)); -} - -bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max) -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->ClipRect.Overlaps(ImRect(rect_min, rect_max)); -} - -// Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) -void ImGui::BeginGroup() -{ - ImGuiWindow* window = GetCurrentWindow(); - - window->DC.GroupStack.resize(window->DC.GroupStack.Size + 1); - ImGuiGroupData& group_data = window->DC.GroupStack.back(); - group_data.BackupCursorPos = window->DC.CursorPos; - group_data.BackupCursorMaxPos = window->DC.CursorMaxPos; - group_data.BackupIndentX = window->DC.IndentX; - group_data.BackupGroupOffsetX = window->DC.GroupOffsetX; - group_data.BackupCurrentLineHeight = window->DC.CurrentLineHeight; - group_data.BackupCurrentLineTextBaseOffset = window->DC.CurrentLineTextBaseOffset; - group_data.BackupLogLinePosY = window->DC.LogLinePosY; - group_data.BackupActiveIdIsAlive = GImGui->ActiveIdIsAlive; - group_data.AdvanceCursor = true; - - window->DC.GroupOffsetX = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffsetX; - window->DC.IndentX = window->DC.GroupOffsetX; - window->DC.CursorMaxPos = window->DC.CursorPos; - window->DC.CurrentLineHeight = 0.0f; - window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; -} - -void ImGui::EndGroup() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - - IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls - - ImGuiGroupData& group_data = window->DC.GroupStack.back(); - - ImRect group_bb(group_data.BackupCursorPos, window->DC.CursorMaxPos); - group_bb.Max.y -= g.Style.ItemSpacing.y; // Cancel out last vertical spacing because we are adding one ourselves. - group_bb.Max = ImMax(group_bb.Min, group_bb.Max); - - window->DC.CursorPos = group_data.BackupCursorPos; - window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos); - window->DC.CurrentLineHeight = group_data.BackupCurrentLineHeight; - window->DC.CurrentLineTextBaseOffset = group_data.BackupCurrentLineTextBaseOffset; - window->DC.IndentX = group_data.BackupIndentX; - window->DC.GroupOffsetX = group_data.BackupGroupOffsetX; - window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; - - if (group_data.AdvanceCursor) - { - window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrentLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now. - ItemSize(group_bb.GetSize(), group_data.BackupCurrentLineTextBaseOffset); - ItemAdd(group_bb, NULL); - } - - // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive() will function on the entire group. - // It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but if you search for LastItemId you'll notice it is only used in that context. - const bool active_id_within_group = (!group_data.BackupActiveIdIsAlive && g.ActiveIdIsAlive && g.ActiveId && g.ActiveIdWindow->RootWindow == window->RootWindow); - if (active_id_within_group) - window->DC.LastItemId = g.ActiveId; - if (active_id_within_group && g.HoveredId == g.ActiveId) - window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = true; - - window->DC.GroupStack.pop_back(); - - //window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // Debug -} - -// Gets back to previous line and continue with horizontal layout -// pos_x == 0 : follow right after previous item -// pos_x != 0 : align to specified x position (relative to window/group left) -// spacing_w < 0 : use default spacing if pos_x == 0, no spacing if pos_x != 0 -// spacing_w >= 0 : enforce spacing amount -void ImGui::SameLine(float pos_x, float spacing_w) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - if (pos_x != 0.0f) - { - if (spacing_w < 0.0f) spacing_w = 0.0f; - window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + pos_x + spacing_w + window->DC.GroupOffsetX + window->DC.ColumnsOffsetX; - window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y; - } - else - { - if (spacing_w < 0.0f) spacing_w = g.Style.ItemSpacing.x; - window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w; - window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y; - } - window->DC.CurrentLineHeight = window->DC.PrevLineHeight; - window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset; -} - -void ImGui::NewLine() -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - if (window->DC.CurrentLineHeight > 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height. - ItemSize(ImVec2(0,0)); - else - ItemSize(ImVec2(0.0f, GImGui->FontSize)); -} - -void ImGui::NextColumn() -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems || window->DC.ColumnsCount <= 1) - return; - - ImGuiContext& g = *GImGui; - PopItemWidth(); - PopClipRect(); - - window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); - if (++window->DC.ColumnsCurrent < window->DC.ColumnsCount) - { - // Columns 1+ cancel out IndentX - window->DC.ColumnsOffsetX = GetColumnOffset(window->DC.ColumnsCurrent) - window->DC.IndentX + g.Style.ItemSpacing.x; - window->DrawList->ChannelsSetCurrent(window->DC.ColumnsCurrent); - } - else - { - window->DC.ColumnsCurrent = 0; - window->DC.ColumnsOffsetX = 0.0f; - window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY; - window->DrawList->ChannelsSetCurrent(0); - } - window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); - window->DC.CursorPos.y = window->DC.ColumnsCellMinY; - window->DC.CurrentLineHeight = 0.0f; - window->DC.CurrentLineTextBaseOffset = 0.0f; - - PushColumnClipRect(); - PushItemWidth(GetColumnWidth() * 0.65f); // FIXME: Move on columns setup -} - -int ImGui::GetColumnIndex() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.ColumnsCurrent; -} - -int ImGui::GetColumnsCount() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.ColumnsCount; -} - -static float GetDraggedColumnOffset(int column_index) -{ - // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing - // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning. - ImGuiContext& g = *GImGui; - ImGuiWindow* window = ImGui::GetCurrentWindowRead(); - IM_ASSERT(column_index > 0); // We cannot drag column 0. If you get this assert you may have a conflict between the ID of your columns and another widgets. - IM_ASSERT(g.ActiveId == window->DC.ColumnsSetId + ImGuiID(column_index)); - - float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x - window->Pos.x; - x = ImClamp(x, ImGui::GetColumnOffset(column_index-1)+g.Style.ColumnsMinSpacing, ImGui::GetColumnOffset(column_index+1)-g.Style.ColumnsMinSpacing); - - return (float)(int)x; -} - -float ImGui::GetColumnOffset(int column_index) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindowRead(); - if (column_index < 0) - column_index = window->DC.ColumnsCurrent; - - if (g.ActiveId) - { - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); - if (g.ActiveId == column_id) - return GetDraggedColumnOffset(column_index); - } - - IM_ASSERT(column_index < window->DC.ColumnsData.Size); - const float t = window->DC.ColumnsData[column_index].OffsetNorm; - const float x_offset = window->DC.ColumnsMinX + t * (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); - return (float)(int)x_offset; -} - -void ImGui::SetColumnOffset(int column_index, float offset) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (column_index < 0) - column_index = window->DC.ColumnsCurrent; - - IM_ASSERT(column_index < window->DC.ColumnsData.Size); - const float t = (offset - window->DC.ColumnsMinX) / (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); - window->DC.ColumnsData[column_index].OffsetNorm = t; - - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); - window->DC.StateStorage->SetFloat(column_id, t); -} - -float ImGui::GetColumnWidth(int column_index) -{ - ImGuiWindow* window = GetCurrentWindowRead(); - if (column_index < 0) - column_index = window->DC.ColumnsCurrent; - - float w = GetColumnOffset(column_index+1) - GetColumnOffset(column_index); - return w; -} - -static void PushColumnClipRect(int column_index) -{ - ImGuiWindow* window = ImGui::GetCurrentWindow(); - if (column_index < 0) - column_index = window->DC.ColumnsCurrent; - - float x1 = ImFloor(0.5f + window->Pos.x + ImGui::GetColumnOffset(column_index) - 1.0f); - float x2 = ImFloor(0.5f + window->Pos.x + ImGui::GetColumnOffset(column_index+1) - 1.0f); - ImGui::PushClipRect(ImVec2(x1,-FLT_MAX), ImVec2(x2,+FLT_MAX), true); -} - -void ImGui::Columns(int columns_count, const char* id, bool border) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(columns_count >= 1); - - if (window->DC.ColumnsCount != 1) - { - if (window->DC.ColumnsCurrent != 0) - ItemSize(ImVec2(0,0)); // Advance to column 0 - PopItemWidth(); - PopClipRect(); - window->DrawList->ChannelsMerge(); - - window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); - window->DC.CursorPos.y = window->DC.ColumnsCellMaxY; - } - - // Draw columns borders and handle resize at the time of "closing" a columns set - if (window->DC.ColumnsCount != columns_count && window->DC.ColumnsCount != 1 && window->DC.ColumnsShowBorders && !window->SkipItems) - { - const float y1 = window->DC.ColumnsStartPosY; - const float y2 = window->DC.CursorPos.y; - for (int i = 1; i < window->DC.ColumnsCount; i++) - { - float x = window->Pos.x + GetColumnOffset(i); - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i); - const ImRect column_rect(ImVec2(x-4,y1),ImVec2(x+4,y2)); - if (IsClippedEx(column_rect, &column_id, false)) - continue; - - bool hovered, held; - ButtonBehavior(column_rect, column_id, &hovered, &held); - if (hovered || held) - g.MouseCursor = ImGuiMouseCursor_ResizeEW; - - // Draw before resize so our items positioning are in sync with the line being drawn - const ImU32 col = GetColorU32(held ? ImGuiCol_ColumnActive : hovered ? ImGuiCol_ColumnHovered : ImGuiCol_Column); - const float xi = (float)(int)x; - window->DrawList->AddLine(ImVec2(xi, y1+1.0f), ImVec2(xi, y2), col); - - if (held) - { - if (g.ActiveIdIsJustActivated) - g.ActiveIdClickOffset.x -= 4; // Store from center of column line (we used a 8 wide rect for columns clicking) - x = GetDraggedColumnOffset(i); - SetColumnOffset(i, x); - } - } - } - - // Differentiate column ID with an arbitrary prefix for cases where users name their columns set the same as another widget. - // In addition, when an identifier isn't explicitly provided we include the number of columns in the hash to make it uniquer. - PushID(0x11223347 + (id ? 0 : columns_count)); - window->DC.ColumnsSetId = window->GetID(id ? id : "columns"); - PopID(); - - // Set state for first column - window->DC.ColumnsCurrent = 0; - window->DC.ColumnsCount = columns_count; - window->DC.ColumnsShowBorders = border; - - const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : window->Size.x; - window->DC.ColumnsMinX = window->DC.IndentX; // Lock our horizontal range - window->DC.ColumnsMaxX = content_region_width - window->Scroll.x - ((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; - window->DC.ColumnsStartPosY = window->DC.CursorPos.y; - window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.CursorPos.y; - window->DC.ColumnsOffsetX = 0.0f; - window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); - - if (window->DC.ColumnsCount != 1) - { - // Cache column offsets - window->DC.ColumnsData.resize(columns_count + 1); - for (int column_index = 0; column_index < columns_count + 1; column_index++) - { - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); - KeepAliveID(column_id); - const float default_t = column_index / (float)window->DC.ColumnsCount; - const float t = window->DC.StateStorage->GetFloat(column_id, default_t); // Cheaply store our floating point value inside the integer (could store a union into the map?) - window->DC.ColumnsData[column_index].OffsetNorm = t; - } - window->DrawList->ChannelsSplit(window->DC.ColumnsCount); - PushColumnClipRect(); - PushItemWidth(GetColumnWidth() * 0.65f); - } - else - { - window->DC.ColumnsData.resize(0); - } -} - -void ImGui::Indent(float indent_w) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - window->DC.IndentX += (indent_w > 0.0f) ? indent_w : g.Style.IndentSpacing; - window->DC.CursorPos.x = window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX; -} - -void ImGui::Unindent(float indent_w) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - window->DC.IndentX -= (indent_w > 0.0f) ? indent_w : g.Style.IndentSpacing; - window->DC.CursorPos.x = window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX; -} - -void ImGui::TreePush(const char* str_id) -{ - ImGuiWindow* window = GetCurrentWindow(); - Indent(); - window->DC.TreeDepth++; - PushID(str_id ? str_id : "#TreePush"); -} - -void ImGui::TreePush(const void* ptr_id) -{ - ImGuiWindow* window = GetCurrentWindow(); - Indent(); - window->DC.TreeDepth++; - PushID(ptr_id ? ptr_id : (const void*)"#TreePush"); -} - -void ImGui::TreePushRawID(ImGuiID id) -{ - ImGuiWindow* window = GetCurrentWindow(); - Indent(); - window->DC.TreeDepth++; - window->IDStack.push_back(id); -} - -void ImGui::TreePop() -{ - ImGuiWindow* window = GetCurrentWindow(); - Unindent(); - window->DC.TreeDepth--; - PopID(); -} - -void ImGui::Value(const char* prefix, bool b) -{ - Text("%s: %s", prefix, (b ? "true" : "false")); -} - -void ImGui::Value(const char* prefix, int v) -{ - Text("%s: %d", prefix, v); -} - -void ImGui::Value(const char* prefix, unsigned int v) -{ - Text("%s: %d", prefix, v); -} - -void ImGui::Value(const char* prefix, float v, const char* float_format) -{ - if (float_format) - { - char fmt[64]; - ImFormatString(fmt, IM_ARRAYSIZE(fmt), "%%s: %s", float_format); - Text(fmt, prefix, v); - } - else - { - Text("%s: %.3f", prefix, v); - } -} - -// FIXME: May want to remove those helpers? -void ImGui::ValueColor(const char* prefix, const ImVec4& v) -{ - Text("%s: (%.2f,%.2f,%.2f,%.2f)", prefix, v.x, v.y, v.z, v.w); - SameLine(); - ColorButton(v, true); -} - -void ImGui::ValueColor(const char* prefix, ImU32 v) -{ - Text("%s: %08X", prefix, v); - SameLine(); - ColorButton(ColorConvertU32ToFloat4(v), true); -} - -//----------------------------------------------------------------------------- -// PLATFORM DEPENDENT HELPERS -//----------------------------------------------------------------------------- - -#if defined(_WIN32) && !defined(_WINDOWS_) && (!defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS) || !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS)) -#undef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#include -#endif - -// Win32 API clipboard implementation -#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS) - -#ifdef _MSC_VER -#pragma comment(lib, "user32") -#endif - -static const char* GetClipboardTextFn_DefaultImpl(void*) -{ - static ImVector buf_local; - buf_local.clear(); - if (!OpenClipboard(NULL)) - return NULL; - HANDLE wbuf_handle = GetClipboardData(CF_UNICODETEXT); - if (wbuf_handle == NULL) - return NULL; - if (ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle)) - { - int buf_len = ImTextCountUtf8BytesFromStr(wbuf_global, NULL) + 1; - buf_local.resize(buf_len); - ImTextStrToUtf8(buf_local.Data, buf_len, wbuf_global, NULL); - } - GlobalUnlock(wbuf_handle); - CloseClipboard(); - return buf_local.Data; -} - -static void SetClipboardTextFn_DefaultImpl(void*, const char* text) -{ - if (!OpenClipboard(NULL)) - return; - const int wbuf_length = ImTextCountCharsFromUtf8(text, NULL) + 1; - HGLOBAL wbuf_handle = GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar)); - if (wbuf_handle == NULL) - return; - ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle); - ImTextStrFromUtf8(wbuf_global, wbuf_length, text, NULL); - GlobalUnlock(wbuf_handle); - EmptyClipboard(); - SetClipboardData(CF_UNICODETEXT, wbuf_handle); - CloseClipboard(); -} - -#else - -// Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers -static const char* GetClipboardTextFn_DefaultImpl(void*) -{ - return GImGui->PrivateClipboard; -} - -// Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers -static void SetClipboardTextFn_DefaultImpl(void*, const char* text) -{ - ImGuiContext& g = *GImGui; - if (g.PrivateClipboard) - { - ImGui::MemFree(g.PrivateClipboard); - g.PrivateClipboard = NULL; - } - const char* text_end = text + strlen(text); - g.PrivateClipboard = (char*)ImGui::MemAlloc((size_t)(text_end - text) + 1); - memcpy(g.PrivateClipboard, text, (size_t)(text_end - text)); - g.PrivateClipboard[(int)(text_end - text)] = 0; -} - -#endif - -// Win32 API IME support (for Asian languages, etc.) -#if defined(_WIN32) && !defined(__GNUC__) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS) - -#include -#ifdef _MSC_VER -#pragma comment(lib, "imm32") -#endif - -static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y) -{ - // Notify OS Input Method Editor of text input position - if (HWND hwnd = (HWND)GImGui->IO.ImeWindowHandle) - if (HIMC himc = ImmGetContext(hwnd)) - { - COMPOSITIONFORM cf; - cf.ptCurrentPos.x = x; - cf.ptCurrentPos.y = y; - cf.dwStyle = CFS_FORCE_POSITION; - ImmSetCompositionWindow(himc, &cf); - } -} - -#else - -static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {} - -#endif - -//----------------------------------------------------------------------------- -// HELP -//----------------------------------------------------------------------------- - -void ImGui::ShowMetricsWindow(bool* p_open) -{ - if (ImGui::Begin("ImGui Metrics", p_open)) - { - ImGui::Text("ImGui %s", ImGui::GetVersion()); - ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); - ImGui::Text("%d vertices, %d indices (%d triangles)", ImGui::GetIO().MetricsRenderVertices, ImGui::GetIO().MetricsRenderIndices, ImGui::GetIO().MetricsRenderIndices / 3); - ImGui::Text("%d allocations", ImGui::GetIO().MetricsAllocs); - static bool show_clip_rects = true; - ImGui::Checkbox("Show clipping rectangles when hovering a ImDrawCmd", &show_clip_rects); - ImGui::Separator(); - - struct Funcs - { - static void NodeDrawList(ImDrawList* draw_list, const char* label) - { - bool node_open = ImGui::TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, draw_list->CmdBuffer.Size); - if (draw_list == ImGui::GetWindowDrawList()) - { - ImGui::SameLine(); - ImGui::TextColored(ImColor(255,100,100), "CURRENTLY APPENDING"); // Can't display stats for active draw list! (we don't have the data double-buffered) - if (node_open) ImGui::TreePop(); - return; - } - if (!node_open) - return; - - ImDrawList* overlay_draw_list = &GImGui->OverlayDrawList; // Render additional visuals into the top-most draw list - overlay_draw_list->PushClipRectFullScreen(); - int elem_offset = 0; - for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.begin(); pcmd < draw_list->CmdBuffer.end(); elem_offset += pcmd->ElemCount, pcmd++) - { - if (pcmd->UserCallback) - { - ImGui::BulletText("Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData); - continue; - } - ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; - bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %-4d %s vtx, tex = %p, clip_rect = (%.0f,%.0f)..(%.0f,%.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); - if (show_clip_rects && ImGui::IsItemHovered()) - { - ImRect clip_rect = pcmd->ClipRect; - ImRect vtxs_rect; - for (int i = elem_offset; i < elem_offset + (int)pcmd->ElemCount; i++) - vtxs_rect.Add(draw_list->VtxBuffer[idx_buffer ? idx_buffer[i] : i].pos); - clip_rect.Floor(); overlay_draw_list->AddRect(clip_rect.Min, clip_rect.Max, IM_COL32(255,255,0,255)); - vtxs_rect.Floor(); overlay_draw_list->AddRect(vtxs_rect.Min, vtxs_rect.Max, IM_COL32(255,0,255,255)); - } - if (!pcmd_node_open) - continue; - ImGuiListClipper clipper(pcmd->ElemCount/3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible. - while (clipper.Step()) - for (int prim = clipper.DisplayStart, vtx_i = elem_offset + clipper.DisplayStart*3; prim < clipper.DisplayEnd; prim++) - { - char buf[300], *buf_p = buf; - ImVec2 triangles_pos[3]; - for (int n = 0; n < 3; n++, vtx_i++) - { - ImDrawVert& v = draw_list->VtxBuffer[idx_buffer ? idx_buffer[vtx_i] : vtx_i]; - triangles_pos[n] = v.pos; - buf_p += sprintf(buf_p, "%s %04d { pos = (%8.2f,%8.2f), uv = (%.6f,%.6f), col = %08X }\n", (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); - } - ImGui::Selectable(buf, false); - if (ImGui::IsItemHovered()) - overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f, false); // Add triangle without AA, more readable for large-thin triangle - } - ImGui::TreePop(); - } - overlay_draw_list->PopClipRect(); - ImGui::TreePop(); - } - - static void NodeWindows(ImVector& windows, const char* label) - { - if (!ImGui::TreeNode(label, "%s (%d)", label, windows.Size)) - return; - for (int i = 0; i < windows.Size; i++) - Funcs::NodeWindow(windows[i], "Window"); - ImGui::TreePop(); - } - - static void NodeWindow(ImGuiWindow* window, const char* label) - { - if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, window->Active || window->WasActive, window)) - return; - NodeDrawList(window->DrawList, "DrawList"); - ImGui::BulletText("Pos: (%.1f,%.1f)", window->Pos.x, window->Pos.y); - ImGui::BulletText("Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)", window->Size.x, window->Size.y, window->SizeContents.x, window->SizeContents.y); - ImGui::BulletText("Scroll: (%.2f,%.2f)", window->Scroll.x, window->Scroll.y); - if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); - if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows"); - ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair)); - ImGui::TreePop(); - } - }; - - ImGuiContext& g = *GImGui; // Access private state - Funcs::NodeWindows(g.Windows, "Windows"); - if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.RenderDrawLists[0].Size)) - { - for (int i = 0; i < g.RenderDrawLists[0].Size; i++) - Funcs::NodeDrawList(g.RenderDrawLists[0][i], "DrawList"); - ImGui::TreePop(); - } - if (ImGui::TreeNode("Popups", "Open Popups Stack (%d)", g.OpenPopupStack.Size)) - { - for (int i = 0; i < g.OpenPopupStack.Size; i++) - { - ImGuiWindow* window = g.OpenPopupStack[i].Window; - ImGui::BulletText("PopupID: %08x, Window: '%s'%s%s", g.OpenPopupStack[i].PopupId, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? " ChildWindow" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? " ChildMenu" : ""); - } - ImGui::TreePop(); - } - if (ImGui::TreeNode("Basic state")) - { - ImGui::Text("FocusedWindow: '%s'", g.FocusedWindow ? g.FocusedWindow->Name : "NULL"); - ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); - ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); - ImGui::Text("HoveredID: 0x%08X/0x%08X", g.HoveredId, g.HoveredIdPreviousFrame); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not - ImGui::Text("ActiveID: 0x%08X/0x%08X", g.ActiveId, g.ActiveIdPreviousFrame); - ImGui::TreePop(); - } - } - ImGui::End(); -} - -//----------------------------------------------------------------------------- - -// Include imgui_user.inl at the end of imgui.cpp to access private data/functions that aren't exposed. -// Prefer just including imgui_internal.h from your code rather than using this define. If a declaration is missing from imgui_internal.h add it or request it on the github. -#ifdef IMGUI_INCLUDE_IMGUI_USER_INL -#include "imgui_user.inl" -#endif - -//----------------------------------------------------------------------------- diff --git a/Baikal/ImGUI/imgui.h b/Baikal/ImGUI/imgui.h deleted file mode 100644 index bf687178..00000000 --- a/Baikal/ImGUI/imgui.h +++ /dev/null @@ -1,1401 +0,0 @@ -// dear imgui, v1.50 WIP -// (headers) - -// See imgui.cpp file for documentation. -// See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code. -// Read 'Programmer guide' in imgui.cpp for notes on how to setup ImGui in your codebase. -// Get latest version at https://github.com/ocornut/imgui - -#pragma once - -#if !defined(IMGUI_DISABLE_INCLUDE_IMCONFIG_H) || defined(IMGUI_INCLUDE_IMCONFIG_H) -#include "imconfig.h" // User-editable configuration file -#endif -#include // FLT_MAX -#include // va_list -#include // ptrdiff_t, NULL -#include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp - -#define IMGUI_VERSION "1.50 WIP" - -// Define attributes of all API symbols declarations, e.g. for DLL under Windows. -#ifndef IMGUI_API -#define IMGUI_API -#endif - -// Define assertion handler. -#ifndef IM_ASSERT -#include -#define IM_ASSERT(_EXPR) assert(_EXPR) -#endif - -// Some compilers support applying printf-style warnings to user functions. -#if defined(__clang__) || defined(__GNUC__) -#define IM_PRINTFARGS(FMT) __attribute__((format(printf, FMT, (FMT+1)))) -#else -#define IM_PRINTFARGS(FMT) -#endif - -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wold-style-cast" -#endif - -// Forward declarations -struct ImDrawChannel; // Temporary storage for outputting drawing commands out of order, used by ImDrawList::ChannelsSplit() -struct ImDrawCmd; // A single draw command within a parent ImDrawList (generally maps to 1 GPU draw call) -struct ImDrawData; // All draw command lists required to render the frame -struct ImDrawList; // A single draw command list (generally one per window) -struct ImDrawVert; // A single vertex (20 bytes by default, override layout with IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT) -struct ImFont; // Runtime data for a single font within a parent ImFontAtlas -struct ImFontAtlas; // Runtime data for multiple fonts, bake multiple fonts into a single texture, TTF font loader -struct ImFontConfig; // Configuration data when adding a font or merging fonts -struct ImColor; // Helper functions to create a color that can be converted to either u32 or float4 -struct ImGuiIO; // Main configuration and I/O between your application and ImGui -struct ImGuiOnceUponAFrame; // Simple helper for running a block of code not more than once a frame, used by IMGUI_ONCE_UPON_A_FRAME macro -struct ImGuiStorage; // Simple custom key value storage -struct ImGuiStyle; // Runtime data for styling/colors -struct ImGuiTextFilter; // Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" -struct ImGuiTextBuffer; // Text buffer for logging/accumulating text -struct ImGuiTextEditCallbackData; // Shared state of ImGui::InputText() when using custom ImGuiTextEditCallback (rare/advanced use) -struct ImGuiSizeConstraintCallbackData;// Structure used to constraint window size in custom ways when using custom ImGuiSizeConstraintCallback (rare/advanced use) -struct ImGuiListClipper; // Helper to manually clip large list of items -struct ImGuiContext; // ImGui context (opaque) - -// Typedefs and Enumerations (declared as int for compatibility and to not pollute the top of this file) -typedef unsigned int ImU32; // 32-bit unsigned integer (typically used to store packed colors) -typedef unsigned int ImGuiID; // unique ID used by widgets (typically hashed from a stack of string) -typedef unsigned short ImWchar; // character for keyboard input/display -typedef void* ImTextureID; // user data to identify a texture (this is whatever to you want it to be! read the FAQ about ImTextureID in imgui.cpp) -typedef int ImGuiCol; // a color identifier for styling // enum ImGuiCol_ -typedef int ImGuiStyleVar; // a variable identifier for styling // enum ImGuiStyleVar_ -typedef int ImGuiKey; // a key identifier (ImGui-side enum) // enum ImGuiKey_ -typedef int ImGuiColorEditMode; // color edit mode for ColorEdit*() // enum ImGuiColorEditMode_ -typedef int ImGuiMouseCursor; // a mouse cursor identifier // enum ImGuiMouseCursor_ -typedef int ImGuiWindowFlags; // window flags for Begin*() // enum ImGuiWindowFlags_ -typedef int ImGuiSetCond; // condition flags for Set*() // enum ImGuiSetCond_ -typedef int ImGuiInputTextFlags; // flags for InputText*() // enum ImGuiInputTextFlags_ -typedef int ImGuiSelectableFlags; // flags for Selectable() // enum ImGuiSelectableFlags_ -typedef int ImGuiTreeNodeFlags; // flags for TreeNode*(), Collapsing*() // enum ImGuiTreeNodeFlags_ -typedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data); -typedef void (*ImGuiSizeConstraintCallback)(ImGuiSizeConstraintCallbackData* data); - -// Others helpers at bottom of the file: -// class ImVector<> // Lightweight std::vector like class. -// IMGUI_ONCE_UPON_A_FRAME // Execute a block of code once per frame only (convenient for creating UI within deep-nested code that runs multiple times) - -struct ImVec2 -{ - float x, y; - ImVec2() { x = y = 0.0f; } - ImVec2(float _x, float _y) { x = _x; y = _y; } -#ifdef IM_VEC2_CLASS_EXTRA // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math types and ImVec2. - IM_VEC2_CLASS_EXTRA -#endif -}; - -struct ImVec4 -{ - float x, y, z, w; - ImVec4() { x = y = z = w = 0.0f; } - ImVec4(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; } -#ifdef IM_VEC4_CLASS_EXTRA // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math types and ImVec4. - IM_VEC4_CLASS_EXTRA -#endif -}; - -// ImGui end-user API -// In a namespace so that user can add extra functions in a separate file (e.g. Value() helpers for your vector or common types) -namespace ImGui -{ - // Main - IMGUI_API ImGuiIO& GetIO(); - IMGUI_API ImGuiStyle& GetStyle(); - IMGUI_API ImDrawData* GetDrawData(); // same value as passed to your io.RenderDrawListsFn() function. valid after Render() and until the next call to NewFrame() - IMGUI_API void NewFrame(); // start a new ImGui frame, you can submit any command from this point until NewFrame()/Render(). - IMGUI_API void Render(); // ends the ImGui frame, finalize rendering data, then call your io.RenderDrawListsFn() function if set. - IMGUI_API void Shutdown(); - IMGUI_API void ShowUserGuide(); // help block - IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // style editor block. you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style) - IMGUI_API void ShowTestWindow(bool* p_open = NULL); // test window demonstrating ImGui features - IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // metrics window for debugging ImGui (browse draw commands, individual vertices, window list, etc.) - - // Window - IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_open' creates a widget on the upper-right to close the window (which sets your bool to false). - IMGUI_API bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE. this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! might obsolete this API eventually. - IMGUI_API void End(); // finish appending to current window, pop it off the window stack. - IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400). - IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // " - IMGUI_API void EndChild(); - IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates - IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos() - IMGUI_API float GetContentRegionAvailWidth(); // - IMGUI_API ImVec2 GetWindowContentRegionMin(); // content boundaries min (roughly (0,0)-Scroll), in window coordinates - IMGUI_API ImVec2 GetWindowContentRegionMax(); // content boundaries max (roughly (0,0)+Size-Scroll) where Size can be override with SetNextWindowContentSize(), in window coordinates - IMGUI_API float GetWindowContentRegionWidth(); // - IMGUI_API ImDrawList* GetWindowDrawList(); // get rendering command-list if you want to append your own draw primitives - IMGUI_API ImVec2 GetWindowPos(); // get current window position in screen space (useful if you want to do your own drawing via the DrawList api) - IMGUI_API ImVec2 GetWindowSize(); // get current window size - IMGUI_API float GetWindowWidth(); - IMGUI_API float GetWindowHeight(); - IMGUI_API bool IsWindowCollapsed(); - IMGUI_API void SetWindowFontScale(float scale); // per-window font scale. Adjust IO.FontGlobalScale if you want to scale all windows - - IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiSetCond cond = 0); // set next window position. call before Begin() - IMGUI_API void SetNextWindowPosCenter(ImGuiSetCond cond = 0); // set next window position to be centered on screen. call before Begin() - IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiSetCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin() - IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Use callback to apply non-trivial programmatic constraints. - IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (enforce the range of scrollbars). set axis to 0.0f to leave it automatic. call before Begin() - IMGUI_API void SetNextWindowContentWidth(float width); // set next window content width (enforce the range of horizontal scrollbar). call before Begin() - IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiSetCond cond = 0); // set next window collapsed state. call before Begin() - IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most. call before Begin() - IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiSetCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects. - IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiSetCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0,0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. - IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiSetCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). - IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / front-most. prefer using SetNextWindowFocus(). - IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiSetCond cond = 0); // set named window position. - IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiSetCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis. - IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiSetCond cond = 0); // set named window collapsed state - IMGUI_API void SetWindowFocus(const char* name); // set named window to be focused / front-most. use NULL to remove focus. - - IMGUI_API float GetScrollX(); // get scrolling amount [0..GetScrollMaxX()] - IMGUI_API float GetScrollY(); // get scrolling amount [0..GetScrollMaxY()] - IMGUI_API float GetScrollMaxX(); // get maximum scrolling amount ~~ ContentSize.X - WindowSize.X - IMGUI_API float GetScrollMaxY(); // get maximum scrolling amount ~~ ContentSize.Y - WindowSize.Y - IMGUI_API void SetScrollX(float scroll_x); // set scrolling amount [0..GetScrollMaxX()] - IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0..GetScrollMaxY()] - IMGUI_API void SetScrollHere(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. - IMGUI_API void SetScrollFromPosY(float pos_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position valid. use GetCursorPos() or GetCursorStartPos()+offset to get valid positions. - IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use negative 'offset' to access previous widgets. - IMGUI_API void SetStateStorage(ImGuiStorage* tree); // replace tree state storage with our own (if you want to manipulate it yourself, typically clear subsection of it) - IMGUI_API ImGuiStorage* GetStateStorage(); - - // Parameters stacks (shared) - IMGUI_API void PushFont(ImFont* font); // use NULL as a shortcut to push default font - IMGUI_API void PopFont(); - IMGUI_API void PushStyleColor(ImGuiCol idx, const ImVec4& col); - IMGUI_API void PopStyleColor(int count = 1); - IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); - IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val); - IMGUI_API void PopStyleVar(int count = 1); - IMGUI_API ImFont* GetFont(); // get current font - IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied - IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API - IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul = 1.0f); // retrieve given style color with style alpha applied and optional extra alpha multiplier - IMGUI_API ImU32 GetColorU32(const ImVec4& col); // retrieve given color with style alpha applied - - // Parameters stacks (current window) - IMGUI_API void PushItemWidth(float item_width); // width of items for the common item+label case, pixels. 0.0f = default to ~2/3 of windows width, >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side) - IMGUI_API void PopItemWidth(); - IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position - IMGUI_API void PushTextWrapPos(float wrap_pos_x = 0.0f); // word-wrapping for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space - IMGUI_API void PopTextWrapPos(); - IMGUI_API void PushAllowKeyboardFocus(bool v); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets - IMGUI_API void PopAllowKeyboardFocus(); - IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (uses io.KeyRepeatDelay/io.KeyRepeatRate for now). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame. - IMGUI_API void PopButtonRepeat(); - - // Cursor / Layout - IMGUI_API void Separator(); // horizontal line - IMGUI_API void SameLine(float pos_x = 0.0f, float spacing_w = -1.0f); // call between widgets or groups to layout them horizontally - IMGUI_API void NewLine(); // undo a SameLine() - IMGUI_API void Spacing(); // add vertical spacing - IMGUI_API void Dummy(const ImVec2& size); // add a dummy item of given size - IMGUI_API void Indent(float indent_w = 0.0f); // move content position toward the right, by style.IndentSpacing or indent_w if >0 - IMGUI_API void Unindent(float indent_w = 0.0f); // move content position back to the left, by style.IndentSpacing or indent_w if >0 - IMGUI_API void BeginGroup(); // lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) - IMGUI_API void EndGroup(); - IMGUI_API ImVec2 GetCursorPos(); // cursor position is relative to window position - IMGUI_API float GetCursorPosX(); // " - IMGUI_API float GetCursorPosY(); // " - IMGUI_API void SetCursorPos(const ImVec2& local_pos); // " - IMGUI_API void SetCursorPosX(float x); // " - IMGUI_API void SetCursorPosY(float y); // " - IMGUI_API ImVec2 GetCursorStartPos(); // initial cursor position - IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute screen coordinates [0..io.DisplaySize] (useful to work with ImDrawList API) - IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute screen coordinates [0..io.DisplaySize] - IMGUI_API void AlignFirstTextHeightToWidgets(); // call once if the first item on the line is a Text() item and you want to vertically lower it to match subsequent (bigger) widgets - IMGUI_API float GetTextLineHeight(); // height of font == GetWindowFontSize() - IMGUI_API float GetTextLineHeightWithSpacing(); // distance (in pixels) between 2 consecutive lines of text == GetWindowFontSize() + GetStyle().ItemSpacing.y - IMGUI_API float GetItemsLineHeightWithSpacing(); // distance (in pixels) between 2 consecutive lines of standard height widgets == GetWindowFontSize() + GetStyle().FramePadding.y*2 + GetStyle().ItemSpacing.y - - // Columns - // You can also use SameLine(pos_x) for simplified columning. The columns API is still work-in-progress and rather lacking. - IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); // setup number of columns. use an identifier to distinguish multiple column sets. close with Columns(1). - IMGUI_API void NextColumn(); // next column - IMGUI_API int GetColumnIndex(); // get current column index - IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetcolumnsCount() inclusive. column 0 is usually 0.0f and not resizable unless you call this - IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column - IMGUI_API float GetColumnWidth(int column_index = -1); // column width (== GetColumnOffset(GetColumnIndex()+1) - GetColumnOffset(GetColumnOffset()) - IMGUI_API int GetColumnsCount(); // number of columns (what was passed to Columns()) - - // ID scopes - // If you are creating widgets in a loop you most likely want to push a unique identifier so ImGui can differentiate them. - // You can also use the "##foobar" syntax within widget label to distinguish them from each others. Read "A primer on the use of labels/IDs" in the FAQ for more details. - IMGUI_API void PushID(const char* str_id); // push identifier into the ID stack. IDs are hash of the *entire* stack! - IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end); - IMGUI_API void PushID(const void* ptr_id); - IMGUI_API void PushID(int int_id); - IMGUI_API void PopID(); - IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). useful if you want to query into ImGuiStorage yourself. otherwise rarely needed - IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end); - IMGUI_API ImGuiID GetID(const void* ptr_id); - - // Widgets - IMGUI_API void Text(const char* fmt, ...) IM_PRINTFARGS(1); - IMGUI_API void TextV(const char* fmt, va_list args); - IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_PRINTFARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor(); - IMGUI_API void TextColoredV(const ImVec4& col, const char* fmt, va_list args); - IMGUI_API void TextDisabled(const char* fmt, ...) IM_PRINTFARGS(1); // shortcut for PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); Text(fmt, ...); PopStyleColor(); - IMGUI_API void TextDisabledV(const char* fmt, va_list args); - IMGUI_API void TextWrapped(const char* fmt, ...) IM_PRINTFARGS(1); // shortcut for PushTextWrapPos(0.0f); Text(fmt, ...); PopTextWrapPos();. Note that this won't work on an auto-resizing window if there's no other widgets to extend the window width, yoy may need to set a size using SetNextWindowSize(). - IMGUI_API void TextWrappedV(const char* fmt, va_list args); - IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // doesn't require null terminated string if 'text_end' is specified. no copy done to any bounded stack buffer, recommended for long chunks of text - IMGUI_API void LabelText(const char* label, const char* fmt, ...) IM_PRINTFARGS(2); // display text+label aligned the same way as value+label widgets - IMGUI_API void LabelTextV(const char* label, const char* fmt, va_list args); - IMGUI_API void Bullet(); // draw a small circle and keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses - IMGUI_API void BulletText(const char* fmt, ...) IM_PRINTFARGS(1); // shortcut for Bullet()+Text() - IMGUI_API void BulletTextV(const char* fmt, va_list args); - IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0)); // button - IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) - IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size); - IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0)); - IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1)); // <0 frame_padding uses default frame padding settings. 0 for no padding - IMGUI_API bool Checkbox(const char* label, bool* v); - IMGUI_API bool CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value); - IMGUI_API bool RadioButton(const char* label, bool active); - IMGUI_API bool RadioButton(const char* label, int* v, int v_button); - IMGUI_API bool Combo(const char* label, int* current_item, const char* const* items, int items_count, int height_in_items = -1); - IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items = -1); // separate items with \0, end item-list with \0\0 - IMGUI_API bool Combo(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); - IMGUI_API bool ColorButton(const ImVec4& col, bool small_height = false, bool outline_border = true); - IMGUI_API bool ColorEdit3(const char* label, float col[3]); // Hint: 'float col[3]' function argument is same as 'float* col'. You can pass address of first element out of a contiguous set, e.g. &myvector.x - IMGUI_API bool ColorEdit4(const char* label, float col[4], bool show_alpha = true); // " - IMGUI_API void ColorEditMode(ImGuiColorEditMode mode); // FIXME-OBSOLETE: This is inconsistent with most of the API and will be obsoleted/replaced. - IMGUI_API void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float)); - IMGUI_API void PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0)); - IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float)); - IMGUI_API void PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0)); - IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-1,0), const char* overlay = NULL); - - // Widgets: Drags (tip: ctrl+click on a drag box to input with keyboard. manually input values aren't clamped, can go off-bounds) - // For all the Float2/Float3/Float4/Int2/Int3/Int4 versions of every functions, remember than a 'float v[3]' function argument is the same as 'float* v'. You can pass address of your first element out of a contiguous set, e.g. &myvector.x - IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); // If v_min >= v_max we have no bound - IMGUI_API bool DragFloat2(const char* label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool DragFloat3(const char* label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool DragFloat4(const char* label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", const char* display_format_max = NULL, float power = 1.0f); - IMGUI_API bool DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); // If v_min >= v_max we have no bound - IMGUI_API bool DragInt2(const char* label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); - IMGUI_API bool DragInt3(const char* label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); - IMGUI_API bool DragInt4(const char* label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); - IMGUI_API bool DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f", const char* display_format_max = NULL); - - // Widgets: Input with Keyboard - IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0,0), ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputFloat2(const char* label, float v[2], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputFloat3(const char* label, float v[3], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputFloat4(const char* label, float v[4], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputInt2(const char* label, int v[2], ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags extra_flags = 0); - - // Widgets: Sliders (tip: ctrl+click on a slider to input with keyboard. manually input values aren't clamped, can go off-bounds) - IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); // adjust display_format to decorate the value with a prefix or a suffix. Use power!=1.0 for logarithmic sliders - IMGUI_API bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool SliderAngle(const char* label, float* v_rad, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f); - IMGUI_API bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* display_format = "%.0f"); - IMGUI_API bool SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* display_format = "%.0f"); - IMGUI_API bool SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* display_format = "%.0f"); - IMGUI_API bool SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* display_format = "%.0f"); - IMGUI_API bool VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* display_format = "%.0f"); - - // Widgets: Trees - IMGUI_API bool TreeNode(const char* label); // if returning 'true' the node is open and the tree id is pushed into the id stack. user is responsible for calling TreePop(). - IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_PRINTFARGS(2); // read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet(). - IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_PRINTFARGS(2); // " - IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args); // " - IMGUI_API bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args); // " - IMGUI_API bool TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags = 0); - IMGUI_API bool TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_PRINTFARGS(3); - IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_PRINTFARGS(3); - IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args); - IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args); - IMGUI_API void TreePush(const char* str_id = NULL); // ~ Indent()+PushId(). Already called by TreeNode() when returning true, but you can call Push/Pop yourself for layout purpose - IMGUI_API void TreePush(const void* ptr_id = NULL); // " - IMGUI_API void TreePop(); // ~ Unindent()+PopId() - IMGUI_API void TreeAdvanceToLabelPos(); // advance cursor x position by GetTreeNodeToLabelSpacing() - IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode - IMGUI_API void SetNextTreeNodeOpen(bool is_open, ImGuiSetCond cond = 0); // set next TreeNode/CollapsingHeader open state. - IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop(). - IMGUI_API bool CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close button on upper right of the header - - // Widgets: Selectable / Lists - IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height - IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); - IMGUI_API bool ListBox(const char* label, int* current_item, const char* const* items, int items_count, int height_in_items = -1); - IMGUI_API bool ListBox(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); - IMGUI_API bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0,0)); // use if you want to reimplement ListBox() will custom data or interactions. make sure to call ListBoxFooter() afterwards. - IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // " - IMGUI_API void ListBoxFooter(); // terminate the scrolling region - - // Widgets: Value() Helpers. Output single value in "name: value" format (tip: freely declare more in your code to handle your types. you can add functions to the ImGui namespace) - IMGUI_API void Value(const char* prefix, bool b); - IMGUI_API void Value(const char* prefix, int v); - IMGUI_API void Value(const char* prefix, unsigned int v); - IMGUI_API void Value(const char* prefix, float v, const char* float_format = NULL); - IMGUI_API void ValueColor(const char* prefix, const ImVec4& v); - IMGUI_API void ValueColor(const char* prefix, ImU32 v); - - // Tooltips - IMGUI_API void SetTooltip(const char* fmt, ...) IM_PRINTFARGS(1); // set tooltip under mouse-cursor, typically use with ImGui::IsHovered(). last call wins - IMGUI_API void SetTooltipV(const char* fmt, va_list args); - IMGUI_API void BeginTooltip(); // use to create full-featured tooltip windows that aren't just text - IMGUI_API void EndTooltip(); - - // Menus - IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar. only call EndMainMenuBar() if this returns true! - IMGUI_API void EndMainMenuBar(); - IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set). only call EndMenuBar() if this returns true! - IMGUI_API void EndMenuBar(); - IMGUI_API bool BeginMenu(const char* label, bool enabled = true); // create a sub-menu entry. only call EndMenu() if this returns true! - IMGUI_API void EndMenu(); - IMGUI_API bool MenuItem(const char* label, const char* shortcut = NULL, bool selected = false, bool enabled = true); // return true when activated. shortcuts are displayed for convenience but not processed by ImGui at the moment - IMGUI_API bool MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL - - // Popups - IMGUI_API void OpenPopup(const char* str_id); // mark popup as open. popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). - IMGUI_API bool BeginPopup(const char* str_id); // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returned true! - IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags extra_flags = 0); // modal dialog (block interactions behind the modal window, can't close the modal window by clicking outside) - IMGUI_API bool BeginPopupContextItem(const char* str_id, int mouse_button = 1); // helper to open and begin popup when clicked on last item. read comments in .cpp! - IMGUI_API bool BeginPopupContextWindow(bool also_over_items = true, const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked on current window. - IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked in void (no window). - IMGUI_API void EndPopup(); - IMGUI_API void CloseCurrentPopup(); // close the popup we have begin-ed into. clicking on a MenuItem or Selectable automatically close the current popup. - - // Logging: all text output from interface is redirected to tty/file/clipboard. By default, tree nodes are automatically opened during logging. - IMGUI_API void LogToTTY(int max_depth = -1); // start logging to tty - IMGUI_API void LogToFile(int max_depth = -1, const char* filename = NULL); // start logging to file - IMGUI_API void LogToClipboard(int max_depth = -1); // start logging to OS clipboard - IMGUI_API void LogFinish(); // stop logging (close file, etc.) - IMGUI_API void LogButtons(); // helper to display buttons for logging to tty/file/clipboard - IMGUI_API void LogText(const char* fmt, ...) IM_PRINTFARGS(1); // pass text data straight to log (without being displayed) - - // Clipping - IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect); - IMGUI_API void PopClipRect(); - - // Utilities - IMGUI_API bool IsItemHovered(); // was the last item hovered by mouse? - IMGUI_API bool IsItemHoveredRect(); // was the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this - IMGUI_API bool IsItemActive(); // was the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) - IMGUI_API bool IsItemClicked(int mouse_button = 0); // was the last item clicked? (e.g. button/node just clicked on) - IMGUI_API bool IsItemVisible(); // was the last item visible? (aka not out of sight due to clipping/scrolling.) - IMGUI_API bool IsAnyItemHovered(); - IMGUI_API bool IsAnyItemActive(); - IMGUI_API ImVec2 GetItemRectMin(); // get bounding rect of last item in screen space - IMGUI_API ImVec2 GetItemRectMax(); // " - IMGUI_API ImVec2 GetItemRectSize(); // " - IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. - IMGUI_API bool IsWindowHovered(); // is current window hovered and hoverable (not blocked by a popup) (differentiate child windows from each others) - IMGUI_API bool IsWindowFocused(); // is current window focused - IMGUI_API bool IsRootWindowFocused(); // is current root window focused (root = top-most parent of a child, otherwise self) - IMGUI_API bool IsRootWindowOrAnyChildFocused(); // is current root window or any of its child (including current window) focused - IMGUI_API bool IsRootWindowOrAnyChildHovered(); // is current root window or any of its child (including current window) hovered and hoverable (not blocked by a popup) - IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped. - IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side. - IMGUI_API bool IsPosHoveringAnyWindow(const ImVec2& pos); // is given position hovering any active imgui window - IMGUI_API float GetTime(); - IMGUI_API int GetFrameCount(); - IMGUI_API const char* GetStyleColName(ImGuiCol idx); - IMGUI_API ImVec2 CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge = false, float outward = +0.0f); // utility to find the closest point the last item bounding rectangle edge. useful to visually link items - IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); - IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can. - - IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame - IMGUI_API void EndChildFrame(); - - IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in); - IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4& in); - IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v); - IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b); - - // Inputs - IMGUI_API int GetKeyIndex(ImGuiKey key); // map ImGuiKey_* values into user's key index. == io.KeyMap[key] - IMGUI_API bool IsKeyDown(int key_index); // key_index into the keys_down[] array, imgui doesn't know the semantic of each entry, uses your own indices! - IMGUI_API bool IsKeyPressed(int key_index, bool repeat = true); // uses user's key indices as stored in the keys_down[] array. if repeat=true. uses io.KeyRepeatDelay / KeyRepeatRate - IMGUI_API bool IsKeyReleased(int key_index); // " - IMGUI_API bool IsMouseDown(int button); // is mouse button held - IMGUI_API bool IsMouseClicked(int button, bool repeat = false); // did mouse button clicked (went from !Down to Down) - IMGUI_API bool IsMouseDoubleClicked(int button); // did mouse button double-clicked. a double-click returns false in IsMouseClicked(). uses io.MouseDoubleClickTime. - IMGUI_API bool IsMouseReleased(int button); // did mouse button released (went from Down to !Down) - IMGUI_API bool IsMouseHoveringWindow(); // is mouse hovering current window ("window" in API names always refer to current window). disregarding of any consideration of being blocked by a popup. (unlike IsWindowHovered() this will return true even if the window is blocked because of a popup) - IMGUI_API bool IsMouseHoveringAnyWindow(); // is mouse hovering any visible window - IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true); // is mouse hovering given bounding rect (in screen space). clipped by current clipping settings. disregarding of consideration of focus/window ordering/blocked by a popup. - IMGUI_API bool IsMouseDragging(int button = 0, float lock_threshold = -1.0f); // is mouse dragging. if lock_threshold < -1.0f uses io.MouseDraggingThreshold - IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls - IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve backup of mouse positioning at the time of opening popup we have BeginPopup() into - IMGUI_API ImVec2 GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f); // dragging amount since clicking. if lock_threshold < -1.0f uses io.MouseDraggingThreshold - IMGUI_API void ResetMouseDragDelta(int button = 0); // - IMGUI_API ImGuiMouseCursor GetMouseCursor(); // get desired cursor type, reset in ImGui::NewFrame(), this updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you - IMGUI_API void SetMouseCursor(ImGuiMouseCursor type); // set desired cursor type - IMGUI_API void CaptureKeyboardFromApp(bool capture = true); // manually override io.WantCaptureKeyboard flag next frame (said flag is entirely left for your application handle). e.g. force capture keyboard when your widget is being hovered. - IMGUI_API void CaptureMouseFromApp(bool capture = true); // manually override io.WantCaptureMouse flag next frame (said flag is entirely left for your application handle). - - // Helpers functions to access functions pointers in ImGui::GetIO() - IMGUI_API void* MemAlloc(size_t sz); - IMGUI_API void MemFree(void* ptr); - IMGUI_API const char* GetClipboardText(); - IMGUI_API void SetClipboardText(const char* text); - - // Internal context access - if you want to use multiple context, share context between modules (e.g. DLL). There is a default context created and active by default. - // All contexts share a same ImFontAtlas by default. If you want different font atlas, you can new() them and overwrite the GetIO().Fonts variable of an ImGui context. - IMGUI_API const char* GetVersion(); - IMGUI_API ImGuiContext* CreateContext(void* (*malloc_fn)(size_t) = NULL, void (*free_fn)(void*) = NULL); - IMGUI_API void DestroyContext(ImGuiContext* ctx); - IMGUI_API ImGuiContext* GetCurrentContext(); - IMGUI_API void SetCurrentContext(ImGuiContext* ctx); - - // Obsolete (will be removed) -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - static inline bool CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1<<5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+ - static inline ImFont* GetWindowFont() { return GetFont(); } // OBSOLETE 1.48+ - static inline float GetWindowFontSize() { return GetFontSize(); } // OBSOLETE 1.48+ - static inline void SetScrollPosHere() { SetScrollHere(); } // OBSOLETE 1.42+ - static inline bool GetWindowCollapsed() { return ImGui::IsWindowCollapsed(); } // OBSOLETE 1.39+ - static inline bool IsRectClipped(const ImVec2& size) { return !IsRectVisible(size); } // OBSOLETE 1.39+ -#endif - -} // namespace ImGui - -// Flags for ImGui::Begin() -enum ImGuiWindowFlags_ -{ - // Default: 0 - ImGuiWindowFlags_NoTitleBar = 1 << 0, // Disable title-bar - ImGuiWindowFlags_NoResize = 1 << 1, // Disable user resizing with the lower-right grip - ImGuiWindowFlags_NoMove = 1 << 2, // Disable user moving the window - ImGuiWindowFlags_NoScrollbar = 1 << 3, // Disable scrollbars (window can still scroll with mouse or programatically) - ImGuiWindowFlags_NoScrollWithMouse = 1 << 4, // Disable user vertically scrolling with mouse wheel - ImGuiWindowFlags_NoCollapse = 1 << 5, // Disable user collapsing window by double-clicking on it - ImGuiWindowFlags_AlwaysAutoResize = 1 << 6, // Resize every window to its content every frame - ImGuiWindowFlags_ShowBorders = 1 << 7, // Show borders around windows and items - ImGuiWindowFlags_NoSavedSettings = 1 << 8, // Never load/save settings in .ini file - ImGuiWindowFlags_NoInputs = 1 << 9, // Disable catching mouse or keyboard inputs - ImGuiWindowFlags_MenuBar = 1 << 10, // Has a menu-bar - ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You may use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section. - ImGuiWindowFlags_NoFocusOnAppearing = 1 << 12, // Disable taking focus when transitioning from hidden to visible state - ImGuiWindowFlags_NoBringToFrontOnFocus = 1 << 13, // Disable bringing window to front when taking focus (e.g. clicking on it or programatically giving it focus) - ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) - ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) - ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) - // [Internal] - ImGuiWindowFlags_ChildWindow = 1 << 20, // Don't use! For internal use by BeginChild() - ImGuiWindowFlags_ChildWindowAutoFitX = 1 << 21, // Don't use! For internal use by BeginChild() - ImGuiWindowFlags_ChildWindowAutoFitY = 1 << 22, // Don't use! For internal use by BeginChild() - ImGuiWindowFlags_ComboBox = 1 << 23, // Don't use! For internal use by ComboBox() - ImGuiWindowFlags_Tooltip = 1 << 24, // Don't use! For internal use by BeginTooltip() - ImGuiWindowFlags_Popup = 1 << 25, // Don't use! For internal use by BeginPopup() - ImGuiWindowFlags_Modal = 1 << 26, // Don't use! For internal use by BeginPopupModal() - ImGuiWindowFlags_ChildMenu = 1 << 27 // Don't use! For internal use by BeginMenu() -}; - -// Flags for ImGui::InputText() -enum ImGuiInputTextFlags_ -{ - // Default: 0 - ImGuiInputTextFlags_CharsDecimal = 1 << 0, // Allow 0123456789.+-*/ - ImGuiInputTextFlags_CharsHexadecimal = 1 << 1, // Allow 0123456789ABCDEFabcdef - ImGuiInputTextFlags_CharsUppercase = 1 << 2, // Turn a..z into A..Z - ImGuiInputTextFlags_CharsNoBlank = 1 << 3, // Filter out spaces, tabs - ImGuiInputTextFlags_AutoSelectAll = 1 << 4, // Select entire text when first taking mouse focus - ImGuiInputTextFlags_EnterReturnsTrue = 1 << 5, // Return 'true' when Enter is pressed (as opposed to when the value was modified) - ImGuiInputTextFlags_CallbackCompletion = 1 << 6, // Call user function on pressing TAB (for completion handling) - ImGuiInputTextFlags_CallbackHistory = 1 << 7, // Call user function on pressing Up/Down arrows (for history handling) - ImGuiInputTextFlags_CallbackAlways = 1 << 8, // Call user function every time. User code may query cursor position, modify text buffer. - ImGuiInputTextFlags_CallbackCharFilter = 1 << 9, // Call user function to filter character. Modify data->EventChar to replace/filter input, or return 1 to discard character. - ImGuiInputTextFlags_AllowTabInput = 1 << 10, // Pressing TAB input a '\t' character into the text field - ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 11, // In multi-line mode, unfocus with Enter, add new line with Ctrl+Enter (default is opposite: unfocus with Ctrl+Enter, add line with Enter). - ImGuiInputTextFlags_NoHorizontalScroll = 1 << 12, // Disable following the cursor horizontally - ImGuiInputTextFlags_AlwaysInsertMode = 1 << 13, // Insert mode - ImGuiInputTextFlags_ReadOnly = 1 << 14, // Read-only mode - ImGuiInputTextFlags_Password = 1 << 15, // Password mode, display all characters as '*' - // [Internal] - ImGuiInputTextFlags_Multiline = 1 << 20 // For internal use by InputTextMultiline() -}; - -// Flags for ImGui::TreeNodeEx(), ImGui::CollapsingHeader*() -enum ImGuiTreeNodeFlags_ -{ - ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected - ImGuiTreeNodeFlags_Framed = 1 << 1, // Full colored frame (e.g. for CollapsingHeader) - ImGuiTreeNodeFlags_AllowOverlapMode = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one - ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack - ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes) - ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open - ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Need double-click to open node - ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open. - ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). - ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow - //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 10, // FIXME: TODO: Extend hit box horizontally even if not framed - //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 11, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible - ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog -}; - -// Flags for ImGui::Selectable() -enum ImGuiSelectableFlags_ -{ - // Default: 0 - ImGuiSelectableFlags_DontClosePopups = 1 << 0, // Clicking this don't close parent popup window - ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Selectable frame can span all columns (text will still fit in current column) - ImGuiSelectableFlags_AllowDoubleClick = 1 << 2 // Generate press events on double clicks too -}; - -// User fill ImGuiIO.KeyMap[] array with indices into the ImGuiIO.KeysDown[512] array -enum ImGuiKey_ -{ - ImGuiKey_Tab, // for tabbing through fields - ImGuiKey_LeftArrow, // for text edit - ImGuiKey_RightArrow,// for text edit - ImGuiKey_UpArrow, // for text edit - ImGuiKey_DownArrow, // for text edit - ImGuiKey_PageUp, - ImGuiKey_PageDown, - ImGuiKey_Home, // for text edit - ImGuiKey_End, // for text edit - ImGuiKey_Delete, // for text edit - ImGuiKey_Backspace, // for text edit - ImGuiKey_Enter, // for text edit - ImGuiKey_Escape, // for text edit - ImGuiKey_A, // for text edit CTRL+A: select all - ImGuiKey_C, // for text edit CTRL+C: copy - ImGuiKey_V, // for text edit CTRL+V: paste - ImGuiKey_X, // for text edit CTRL+X: cut - ImGuiKey_Y, // for text edit CTRL+Y: redo - ImGuiKey_Z, // for text edit CTRL+Z: undo - ImGuiKey_COUNT -}; - -// Enumeration for PushStyleColor() / PopStyleColor() -enum ImGuiCol_ -{ - ImGuiCol_Text, - ImGuiCol_TextDisabled, - ImGuiCol_WindowBg, // Background of normal windows - ImGuiCol_ChildWindowBg, // Background of child windows - ImGuiCol_PopupBg, // Background of popups, menus, tooltips windows - ImGuiCol_Border, - ImGuiCol_BorderShadow, - ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input - ImGuiCol_FrameBgHovered, - ImGuiCol_FrameBgActive, - ImGuiCol_TitleBg, - ImGuiCol_TitleBgCollapsed, - ImGuiCol_TitleBgActive, - ImGuiCol_MenuBarBg, - ImGuiCol_ScrollbarBg, - ImGuiCol_ScrollbarGrab, - ImGuiCol_ScrollbarGrabHovered, - ImGuiCol_ScrollbarGrabActive, - ImGuiCol_ComboBg, - ImGuiCol_CheckMark, - ImGuiCol_SliderGrab, - ImGuiCol_SliderGrabActive, - ImGuiCol_Button, - ImGuiCol_ButtonHovered, - ImGuiCol_ButtonActive, - ImGuiCol_Header, - ImGuiCol_HeaderHovered, - ImGuiCol_HeaderActive, - ImGuiCol_Column, - ImGuiCol_ColumnHovered, - ImGuiCol_ColumnActive, - ImGuiCol_ResizeGrip, - ImGuiCol_ResizeGripHovered, - ImGuiCol_ResizeGripActive, - ImGuiCol_CloseButton, - ImGuiCol_CloseButtonHovered, - ImGuiCol_CloseButtonActive, - ImGuiCol_PlotLines, - ImGuiCol_PlotLinesHovered, - ImGuiCol_PlotHistogram, - ImGuiCol_PlotHistogramHovered, - ImGuiCol_TextSelectedBg, - ImGuiCol_ModalWindowDarkening, // darken entire screen when a modal window is active - ImGuiCol_COUNT -}; - -// Enumeration for PushStyleVar() / PopStyleVar() -// NB: the enum only refers to fields of ImGuiStyle() which makes sense to be pushed/poped in UI code. Feel free to add others. -enum ImGuiStyleVar_ -{ - ImGuiStyleVar_Alpha, // float - ImGuiStyleVar_WindowPadding, // ImVec2 - ImGuiStyleVar_WindowRounding, // float - ImGuiStyleVar_WindowMinSize, // ImVec2 - ImGuiStyleVar_ChildWindowRounding, // float - ImGuiStyleVar_FramePadding, // ImVec2 - ImGuiStyleVar_FrameRounding, // float - ImGuiStyleVar_ItemSpacing, // ImVec2 - ImGuiStyleVar_ItemInnerSpacing, // ImVec2 - ImGuiStyleVar_IndentSpacing, // float - ImGuiStyleVar_GrabMinSize, // float - ImGuiStyleVar_ButtonTextAlign, // flags ImGuiAlign_* - ImGuiStyleVar_Count_ -}; - -// Enumeration for ColorEditMode() -// FIXME-OBSOLETE: Will be replaced by future color/picker api -enum ImGuiColorEditMode_ -{ - ImGuiColorEditMode_UserSelect = -2, - ImGuiColorEditMode_UserSelectShowButton = -1, - ImGuiColorEditMode_RGB = 0, - ImGuiColorEditMode_HSV = 1, - ImGuiColorEditMode_HEX = 2 -}; - -// Enumeration for GetMouseCursor() -enum ImGuiMouseCursor_ -{ - ImGuiMouseCursor_None = -1, - ImGuiMouseCursor_Arrow = 0, - ImGuiMouseCursor_TextInput, // When hovering over InputText, etc. - ImGuiMouseCursor_Move, // Unused - ImGuiMouseCursor_ResizeNS, // Unused - ImGuiMouseCursor_ResizeEW, // When hovering over a column - ImGuiMouseCursor_ResizeNESW, // Unused - ImGuiMouseCursor_ResizeNWSE, // When hovering over the bottom-right corner of a window - ImGuiMouseCursor_Count_ -}; - -// Condition flags for ImGui::SetWindow***(), SetNextWindow***(), SetNextTreeNode***() functions -// All those functions treat 0 as a shortcut to ImGuiSetCond_Always -enum ImGuiSetCond_ -{ - ImGuiSetCond_Always = 1 << 0, // Set the variable - ImGuiSetCond_Once = 1 << 1, // Set the variable once per runtime session (only the first call with succeed) - ImGuiSetCond_FirstUseEver = 1 << 2, // Set the variable if the window has no saved data (if doesn't exist in the .ini file) - ImGuiSetCond_Appearing = 1 << 3 // Set the variable if the window is appearing after being hidden/inactive (or the first time) -}; - -struct ImGuiStyle -{ - float Alpha; // Global alpha applies to everything in ImGui - ImVec2 WindowPadding; // Padding within a window - ImVec2 WindowMinSize; // Minimum window size - float WindowRounding; // Radius of window corners rounding. Set to 0.0f to have rectangular windows - ImVec2 WindowTitleAlign; // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered. - float ChildWindowRounding; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows - ImVec2 FramePadding; // Padding within a framed rectangle (used by most widgets) - float FrameRounding; // Radius of frame corners rounding. Set to 0.0f to have rectangular frame (used by most widgets). - ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines - ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) - ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! - float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). - float ColumnsMinSpacing; // Minimum horizontal spacing between two columns - float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar - float ScrollbarRounding; // Radius of grab corners for scrollbar - float GrabMinSize; // Minimum width/height of a grab box for slider/scrollbar. - float GrabRounding; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. - ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f,0.5f) for horizontally+vertically centered. - ImVec2 DisplayWindowPadding; // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows. - ImVec2 DisplaySafeAreaPadding; // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. - bool AntiAliasedLines; // Enable anti-aliasing on lines/borders. Disable if you are really tight on CPU/GPU. - bool AntiAliasedShapes; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) - float CurveTessellationTol; // Tessellation tolerance. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. - ImVec4 Colors[ImGuiCol_COUNT]; - - IMGUI_API ImGuiStyle(); -}; - -// This is where your app communicate with ImGui. Access via ImGui::GetIO(). -// Read 'Programmer guide' section in .cpp file for general usage. -struct ImGuiIO -{ - //------------------------------------------------------------------ - // Settings (fill once) // Default value: - //------------------------------------------------------------------ - - ImVec2 DisplaySize; // // Display size, in pixels. For clamping windows positions. - float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. - float IniSavingRate; // = 5.0f // Maximum time between saving positions/sizes to .ini file, in seconds. - const char* IniFilename; // = "imgui.ini" // Path to .ini file. NULL to disable .ini saving. - const char* LogFilename; // = "imgui_log.txt" // Path to .log file (default parameter to ImGui::LogToFile when no file is specified). - float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds. - float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels. - float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging - int KeyMap[ImGuiKey_COUNT]; // // Map of indices into the KeysDown[512] entries array - float KeyRepeatDelay; // = 0.250f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.). - float KeyRepeatRate; // = 0.020f // When holding a key/button, rate at which it repeats, in seconds. - void* UserData; // = NULL // Store your own data for retrieval by callbacks. - - ImFontAtlas* Fonts; // // Load and assemble one or more fonts into a single tightly packed texture. Output to Fonts array. - float FontGlobalScale; // = 1.0f // Global scale all fonts - bool FontAllowUserScaling; // = false // Allow user scaling text of individual window with CTRL+Wheel. - ImFont* FontDefault; // = NULL // Font to use on NewFrame(). Use NULL to uses Fonts->Fonts[0]. - ImVec2 DisplayFramebufferScale; // = (1.0f,1.0f) // For retina display or other situations where window coordinates are different from framebuffer coordinates. User storage only, presently not used by ImGui. - ImVec2 DisplayVisibleMin; // (0.0f,0.0f) // If you use DisplaySize as a virtual space larger than your screen, set DisplayVisibleMin/Max to the visible area. - ImVec2 DisplayVisibleMax; // (0.0f,0.0f) // If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize - - // Advanced/subtle behaviors - bool OSXBehaviors; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl - - //------------------------------------------------------------------ - // User Functions - //------------------------------------------------------------------ - - // Rendering function, will be called in Render(). - // Alternatively you can keep this to NULL and call GetDrawData() after Render() to get the same pointer. - // See example applications if you are unsure of how to implement this. - void (*RenderDrawListsFn)(ImDrawData* data); - - // Optional: access OS clipboard - // (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures) - const char* (*GetClipboardTextFn)(void* user_data); - void (*SetClipboardTextFn)(void* user_data, const char* text); - void* ClipboardUserData; - - // Optional: override memory allocations. MemFreeFn() may be called with a NULL pointer. - // (default to posix malloc/free) - void* (*MemAllocFn)(size_t sz); - void (*MemFreeFn)(void* ptr); - - // Optional: notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME in Windows) - // (default to use native imm32 api on Windows) - void (*ImeSetInputScreenPosFn)(int x, int y); - void* ImeWindowHandle; // (Windows) Set this to your HWND to get automatic IME cursor positioning. - - //------------------------------------------------------------------ - // Input - Fill before calling NewFrame() - //------------------------------------------------------------------ - - ImVec2 MousePos; // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) - bool MouseDown[5]; // Mouse buttons: left, right, middle + extras. ImGui itself mostly only uses left button (BeginPopupContext** are using right button). Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. - float MouseWheel; // Mouse wheel: 1 unit scrolls about 5 lines text. - bool MouseDrawCursor; // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). - bool KeyCtrl; // Keyboard modifier pressed: Control - bool KeyShift; // Keyboard modifier pressed: Shift - bool KeyAlt; // Keyboard modifier pressed: Alt - bool KeySuper; // Keyboard modifier pressed: Cmd/Super/Windows - bool KeysDown[512]; // Keyboard keys that are pressed (in whatever storage order you naturally have access to keyboard data) - ImWchar InputCharacters[16+1]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper. - - // Functions - IMGUI_API void AddInputCharacter(ImWchar c); // Add new character into InputCharacters[] - IMGUI_API void AddInputCharactersUTF8(const char* utf8_chars); // Add new characters into InputCharacters[] from an UTF-8 string - inline void ClearInputCharacters() { InputCharacters[0] = 0; } // Clear the text input buffer manually - - //------------------------------------------------------------------ - // Output - Retrieve after calling NewFrame() - //------------------------------------------------------------------ - - bool WantCaptureMouse; // Mouse is hovering a window or widget is active (= ImGui will use your mouse input). Use to hide mouse from the rest of your application - bool WantCaptureKeyboard; // Widget is active (= ImGui will use your keyboard input). Use to hide keyboard from the rest of your application - bool WantTextInput; // Some text input widget is active, which will read input characters from the InputCharacters array. Use to activate on screen keyboard if your system needs one - float Framerate; // Application framerate estimation, in frame per second. Solely for convenience. Rolling average estimation based on IO.DeltaTime over 120 frames - int MetricsAllocs; // Number of active memory allocations - int MetricsRenderVertices; // Vertices output during last call to Render() - int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3 - int MetricsActiveWindows; // Number of visible root windows (exclude child windows) - ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are negative, so a disappearing/reappearing mouse won't have a huge delta for one frame. - - //------------------------------------------------------------------ - // [Private] ImGui will maintain those fields. Forward compatibility not guaranteed! - //------------------------------------------------------------------ - - ImVec2 MousePosPrev; // Previous mouse position temporary storage (nb: not for public use, set to MousePos in NewFrame()) - bool MouseClicked[5]; // Mouse button went from !Down to Down - ImVec2 MouseClickedPos[5]; // Position at time of clicking - float MouseClickedTime[5]; // Time of last click (used to figure out double-click) - bool MouseDoubleClicked[5]; // Has mouse button been double-clicked? - bool MouseReleased[5]; // Mouse button went from Down to !Down - bool MouseDownOwned[5]; // Track if button was clicked inside a window. We don't request mouse capture from the application if click started outside ImGui bounds. - float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked) - float MouseDownDurationPrev[5]; // Previous time the mouse button has been down - float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the click point - float KeysDownDuration[512]; // Duration the keyboard key has been down (0.0f == just pressed) - float KeysDownDurationPrev[512]; // Previous duration the key has been down - - IMGUI_API ImGuiIO(); -}; - -//----------------------------------------------------------------------------- -// Helpers -//----------------------------------------------------------------------------- - -// Lightweight std::vector<> like class to avoid dragging dependencies (also: windows implementation of STL with debug enabled is absurdly slow, so let's bypass it so our code runs fast in debug). -// Our implementation does NOT call c++ constructors because we don't use them in ImGui. Don't use this class as a straight std::vector replacement in your code! -template -class ImVector -{ -public: - int Size; - int Capacity; - T* Data; - - typedef T value_type; - typedef value_type* iterator; - typedef const value_type* const_iterator; - - ImVector() { Size = Capacity = 0; Data = NULL; } - ~ImVector() { if (Data) ImGui::MemFree(Data); } - - inline bool empty() const { return Size == 0; } - inline int size() const { return Size; } - inline int capacity() const { return Capacity; } - - inline value_type& operator[](int i) { IM_ASSERT(i < Size); return Data[i]; } - inline const value_type& operator[](int i) const { IM_ASSERT(i < Size); return Data[i]; } - - inline void clear() { if (Data) { Size = Capacity = 0; ImGui::MemFree(Data); Data = NULL; } } - inline iterator begin() { return Data; } - inline const_iterator begin() const { return Data; } - inline iterator end() { return Data + Size; } - inline const_iterator end() const { return Data + Size; } - inline value_type& front() { IM_ASSERT(Size > 0); return Data[0]; } - inline const value_type& front() const { IM_ASSERT(Size > 0); return Data[0]; } - inline value_type& back() { IM_ASSERT(Size > 0); return Data[Size-1]; } - inline const value_type& back() const { IM_ASSERT(Size > 0); return Data[Size-1]; } - inline void swap(ImVector& rhs) { int rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; int rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; } - - inline int _grow_capacity(int new_size) { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > new_size ? new_capacity : new_size; } - - inline void resize(int new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; } - inline void reserve(int new_capacity) - { - if (new_capacity <= Capacity) return; - T* new_data = (value_type*)ImGui::MemAlloc((size_t)new_capacity * sizeof(value_type)); - if (Data) - memcpy(new_data, Data, (size_t)Size * sizeof(value_type)); - ImGui::MemFree(Data); - Data = new_data; - Capacity = new_capacity; - } - - inline void push_back(const value_type& v) { if (Size == Capacity) reserve(_grow_capacity(Size+1)); Data[Size++] = v; } - inline void pop_back() { IM_ASSERT(Size > 0); Size--; } - - inline iterator erase(const_iterator it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(value_type)); Size--; return Data + off; } - inline iterator insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; } -}; - -// Helper: execute a block of code at maximum once a frame -// Convenient if you want to quickly create an UI within deep-nested code that runs multiple times every frame. -// Usage: -// IMGUI_ONCE_UPON_A_FRAME -// { -// // code block will be executed one per frame -// } -// Attention! the macro expands into 2 statement so make sure you don't use it within e.g. an if() statement without curly braces. -#define IMGUI_ONCE_UPON_A_FRAME static ImGuiOnceUponAFrame imgui_oaf##__LINE__; if (imgui_oaf##__LINE__) -struct ImGuiOnceUponAFrame -{ - ImGuiOnceUponAFrame() { RefFrame = -1; } - mutable int RefFrame; - operator bool() const { int current_frame = ImGui::GetFrameCount(); if (RefFrame == current_frame) return false; RefFrame = current_frame; return true; } -}; - -// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" -struct ImGuiTextFilter -{ - struct TextRange - { - const char* b; - const char* e; - - TextRange() { b = e = NULL; } - TextRange(const char* _b, const char* _e) { b = _b; e = _e; } - const char* begin() const { return b; } - const char* end() const { return e; } - bool empty() const { return b == e; } - char front() const { return *b; } - static bool is_blank(char c) { return c == ' ' || c == '\t'; } - void trim_blanks() { while (b < e && is_blank(*b)) b++; while (e > b && is_blank(*(e-1))) e--; } - IMGUI_API void split(char separator, ImVector& out); - }; - - char InputBuf[256]; - ImVector Filters; - int CountGrep; - - ImGuiTextFilter(const char* default_filter = ""); - ~ImGuiTextFilter() {} - void Clear() { InputBuf[0] = 0; Build(); } - bool Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build - bool PassFilter(const char* text, const char* text_end = NULL) const; - bool IsActive() const { return !Filters.empty(); } - IMGUI_API void Build(); -}; - -// Helper: Text buffer for logging/accumulating text -struct ImGuiTextBuffer -{ - ImVector Buf; - - ImGuiTextBuffer() { Buf.push_back(0); } - inline char operator[](int i) { return Buf.Data[i]; } - const char* begin() const { return &Buf.front(); } - const char* end() const { return &Buf.back(); } // Buf is zero-terminated, so end() will point on the zero-terminator - int size() const { return Buf.Size - 1; } - bool empty() { return Buf.Size <= 1; } - void clear() { Buf.clear(); Buf.push_back(0); } - const char* c_str() const { return Buf.Data; } - IMGUI_API void append(const char* fmt, ...) IM_PRINTFARGS(2); - IMGUI_API void appendv(const char* fmt, va_list args); -}; - -// Helper: Simple Key->value storage -// Typically you don't have to worry about this since a storage is held within each Window. -// We use it to e.g. store collapse state for a tree (Int 0/1), store color edit options. -// You can use it as custom user storage for temporary values. -// Declare your own storage if: -// - You want to manipulate the open/close state of a particular sub-tree in your interface (tree node uses Int 0/1 to store their state). -// - You want to store custom debug data easily without adding or editing structures in your code. -// Types are NOT stored, so it is up to you to make sure your Key don't collide with different types. -struct ImGuiStorage -{ - struct Pair - { - ImGuiID key; - union { int val_i; float val_f; void* val_p; }; - Pair(ImGuiID _key, int _val_i) { key = _key; val_i = _val_i; } - Pair(ImGuiID _key, float _val_f) { key = _key; val_f = _val_f; } - Pair(ImGuiID _key, void* _val_p) { key = _key; val_p = _val_p; } - }; - ImVector Data; - - // - Get***() functions find pair, never add/allocate. Pairs are sorted so a query is O(log N) - // - Set***() functions find pair, insertion on demand if missing. - // - Sorted insertion is costly, paid once. A typical frame shouldn't need to insert any new pair. - IMGUI_API void Clear(); - IMGUI_API int GetInt(ImGuiID key, int default_val = 0) const; - IMGUI_API void SetInt(ImGuiID key, int val); - IMGUI_API bool GetBool(ImGuiID key, bool default_val = false) const; - IMGUI_API void SetBool(ImGuiID key, bool val); - IMGUI_API float GetFloat(ImGuiID key, float default_val = 0.0f) const; - IMGUI_API void SetFloat(ImGuiID key, float val); - IMGUI_API void* GetVoidPtr(ImGuiID key) const; // default_val is NULL - IMGUI_API void SetVoidPtr(ImGuiID key, void* val); - - // - Get***Ref() functions finds pair, insert on demand if missing, return pointer. Useful if you intend to do Get+Set. - // - References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer. - // - A typical use case where this is convenient for quick hacking (e.g. add storage during a live Edit&Continue session if you can't modify existing struct) - // float* pvar = ImGui::GetFloatRef(key); ImGui::SliderFloat("var", pvar, 0, 100.0f); some_var += *pvar; - IMGUI_API int* GetIntRef(ImGuiID key, int default_val = 0); - IMGUI_API bool* GetBoolRef(ImGuiID key, bool default_val = false); - IMGUI_API float* GetFloatRef(ImGuiID key, float default_val = 0.0f); - IMGUI_API void** GetVoidPtrRef(ImGuiID key, void* default_val = NULL); - - // Use on your own storage if you know only integer are being stored (open/close all tree nodes) - IMGUI_API void SetAllInt(int val); -}; - -// Shared state of InputText(), passed to callback when a ImGuiInputTextFlags_Callback* flag is used and the corresponding callback is triggered. -struct ImGuiTextEditCallbackData -{ - ImGuiInputTextFlags EventFlag; // One of ImGuiInputTextFlags_Callback* // Read-only - ImGuiInputTextFlags Flags; // What user passed to InputText() // Read-only - void* UserData; // What user passed to InputText() // Read-only - bool ReadOnly; // Read-only mode // Read-only - - // CharFilter event: - ImWchar EventChar; // Character input // Read-write (replace character or set to zero) - - // Completion,History,Always events: - // If you modify the buffer contents make sure you update 'BufTextLen' and set 'BufDirty' to true. - ImGuiKey EventKey; // Key pressed (Up/Down/TAB) // Read-only - char* Buf; // Current text buffer // Read-write (pointed data only, can't replace the actual pointer) - int BufTextLen; // Current text length in bytes // Read-write - int BufSize; // Maximum text length in bytes // Read-only - bool BufDirty; // Set if you modify Buf/BufTextLen!! // Write - int CursorPos; // // Read-write - int SelectionStart; // // Read-write (== to SelectionEnd when no selection) - int SelectionEnd; // // Read-write - - // NB: Helper functions for text manipulation. Calling those function loses selection. - IMGUI_API void DeleteChars(int pos, int bytes_count); - IMGUI_API void InsertChars(int pos, const char* text, const char* text_end = NULL); - bool HasSelection() const { return SelectionStart != SelectionEnd; } -}; - -// Resizing callback data to apply custom constraint. As enabled by SetNextWindowSizeConstraints(). Callback is called during the next Begin(). -// NB: For basic min/max size constraint on each axis you don't need to use the callback! The SetNextWindowSizeConstraints() parameters are enough. -struct ImGuiSizeConstraintCallbackData -{ - void* UserData; // Read-only. What user passed to SetNextWindowSizeConstraints() - ImVec2 Pos; // Read-only. Window position, for reference. - ImVec2 CurrentSize; // Read-only. Current window size. - ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing. -}; - -// Helpers macros to generate 32-bits encoded colors -#ifdef IMGUI_USE_BGRA_PACKED_COLOR -#define IM_COL32_R_SHIFT 16 -#define IM_COL32_G_SHIFT 8 -#define IM_COL32_B_SHIFT 0 -#define IM_COL32_A_SHIFT 24 -#define IM_COL32_A_MASK 0xFF000000 -#else -#define IM_COL32_R_SHIFT 0 -#define IM_COL32_G_SHIFT 8 -#define IM_COL32_B_SHIFT 16 -#define IM_COL32_A_SHIFT 24 -#define IM_COL32_A_MASK 0xFF000000 -#endif -#define IM_COL32(R,G,B,A) (((ImU32)(A)<>IM_COL32_R_SHIFT)&0xFF) * sc; Value.y = (float)((rgba>>IM_COL32_G_SHIFT)&0xFF) * sc; Value.z = (float)((rgba>>IM_COL32_B_SHIFT)&0xFF) * sc; Value.w = (float)((rgba>>IM_COL32_A_SHIFT)&0xFF) * sc; } - ImColor(float r, float g, float b, float a = 1.0f) { Value.x = r; Value.y = g; Value.z = b; Value.w = a; } - ImColor(const ImVec4& col) { Value = col; } - inline operator ImU32() const { return ImGui::ColorConvertFloat4ToU32(Value); } - inline operator ImVec4() const { return Value; } - - inline void SetHSV(float h, float s, float v, float a = 1.0f){ ImGui::ColorConvertHSVtoRGB(h, s, v, Value.x, Value.y, Value.z); Value.w = a; } - - static ImColor HSV(float h, float s, float v, float a = 1.0f) { float r,g,b; ImGui::ColorConvertHSVtoRGB(h, s, v, r, g, b); return ImColor(r,g,b,a); } -}; - -// Helper: Manually clip large list of items. -// If you are submitting lots of evenly spaced items and you have a random access to the list, you can perform coarse clipping based on visibility to save yourself from processing those items at all. -// The clipper calculates the range of visible items and advance the cursor to compensate for the non-visible items we have skipped. -// ImGui already clip items based on their bounds but it needs to measure text size to do so. Coarse clipping before submission makes this cost and your own data fetching/submission cost null. -// Usage: -// ImGuiListClipper clipper(1000); // we have 1000 elements, evenly spaced. -// while (clipper.Step()) -// for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) -// ImGui::Text("line number %d", i); -// - Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height (step skipped if we passed a known height as second arg to constructor). -// - Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element. -// - (Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user call Step(). Does nothing and switch to Step 3.) -// - Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop. -struct ImGuiListClipper -{ - float StartPosY; - float ItemsHeight; - int ItemsCount, StepNo, DisplayStart, DisplayEnd; - - // items_count: Use -1 to ignore (you can call Begin later). Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step). - // items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetItemsLineHeightWithSpacing(). - // If you don't specify an items_height, you NEED to call Step(). If you specify items_height you may call the old Begin()/End() api directly, but prefer calling Step(). - ImGuiListClipper(int items_count = -1, float items_height = -1.0f) { Begin(items_count, items_height); } // NB: Begin() initialize every fields (as we allow user to call Begin/End multiple times on a same instance if they want). - ~ImGuiListClipper() { IM_ASSERT(ItemsCount == -1); } // Assert if user forgot to call End() or Step() until false. - - IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items. - IMGUI_API void Begin(int items_count, float items_height = -1.0f); // Automatically called by constructor if you passed 'items_count' or by Step() in Step 1. - IMGUI_API void End(); // Automatically called on the last call of Step() that returns false. -}; - -//----------------------------------------------------------------------------- -// Draw List -// Hold a series of drawing commands. The user provides a renderer for ImDrawData which essentially contains an array of ImDrawList. -//----------------------------------------------------------------------------- - -// Draw callbacks for advanced uses. -// NB- You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering (you can poke into the draw list for that) -// Draw callback may be useful for example, A) Change your GPU render state, B) render a complex 3D scene inside a UI element (without an intermediate texture/render target), etc. -// The expected behavior from your rendering function is 'if (cmd.UserCallback != NULL) cmd.UserCallback(parent_list, cmd); else RenderTriangles()' -typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd); - -// Typically, 1 command = 1 gpu draw call (unless command is a callback) -struct ImDrawCmd -{ - unsigned int ElemCount; // Number of indices (multiple of 3) to be rendered as triangles. Vertices are stored in the callee ImDrawList's vtx_buffer[] array, indices in idx_buffer[]. - ImVec4 ClipRect; // Clipping rectangle (x1, y1, x2, y2) - ImTextureID TextureId; // User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() functions. Ignore if never using images or multiple fonts atlas. - ImDrawCallback UserCallback; // If != NULL, call the function instead of rendering the vertices. clip_rect and texture_id will be set normally. - void* UserCallbackData; // The draw callback code can access this. - - ImDrawCmd() { ElemCount = 0; ClipRect.x = ClipRect.y = -8192.0f; ClipRect.z = ClipRect.w = +8192.0f; TextureId = NULL; UserCallback = NULL; UserCallbackData = NULL; } -}; - -// Vertex index (override with '#define ImDrawIdx unsigned int' inside in imconfig.h) -#ifndef ImDrawIdx -typedef unsigned short ImDrawIdx; -#endif - -// Vertex layout -#ifndef IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT -struct ImDrawVert -{ - ImVec2 pos; - ImVec2 uv; - ImU32 col; -}; -#else -// You can override the vertex format layout by defining IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT in imconfig.h -// The code expect ImVec2 pos (8 bytes), ImVec2 uv (8 bytes), ImU32 col (4 bytes), but you can re-order them or add other fields as needed to simplify integration in your engine. -// The type has to be described within the macro (you can either declare the struct or use a typedef) -IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT; -#endif - -// Draw channels are used by the Columns API to "split" the render list into different channels while building, so items of each column can be batched together. -// You can also use them to simulate drawing layers and submit primitives in a different order than how they will be rendered. -struct ImDrawChannel -{ - ImVector CmdBuffer; - ImVector IdxBuffer; -}; - -// Draw command list -// This is the low-level list of polygons that ImGui functions are filling. At the end of the frame, all command lists are passed to your ImGuiIO::RenderDrawListFn function for rendering. -// At the moment, each ImGui window contains its own ImDrawList but they could potentially be merged in the future. -// If you want to add custom rendering within a window, you can use ImGui::GetWindowDrawList() to access the current draw list and add your own primitives. -// You can interleave normal ImGui:: calls and adding primitives to the current draw list. -// All positions are in screen coordinates (0,0=top-left, 1 pixel per unit). Primitives are always added to the list and not culled (culling is done at render time and at a higher-level by ImGui:: functions). -struct ImDrawList -{ - // This is what you have to render - ImVector CmdBuffer; // Commands. Typically 1 command = 1 gpu draw call. - ImVector IdxBuffer; // Index buffer. Each command consume ImDrawCmd::ElemCount of those - ImVector VtxBuffer; // Vertex buffer. - - // [Internal, used while building lists] - const char* _OwnerName; // Pointer to owner window's name for debugging - unsigned int _VtxCurrentIdx; // [Internal] == VtxBuffer.Size - ImDrawVert* _VtxWritePtr; // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> operators too much) - ImDrawIdx* _IdxWritePtr; // [Internal] point within IdxBuffer.Data after each add command (to avoid using the ImVector<> operators too much) - ImVector _ClipRectStack; // [Internal] - ImVector _TextureIdStack; // [Internal] - ImVector _Path; // [Internal] current path building - int _ChannelsCurrent; // [Internal] current channel number (0) - int _ChannelsCount; // [Internal] number of active channels (1+) - ImVector _Channels; // [Internal] draw channels for columns API (not resized down so _ChannelsCount may be smaller than _Channels.Size) - - ImDrawList() { _OwnerName = NULL; Clear(); } - ~ImDrawList() { ClearFreeMemory(); } - IMGUI_API void PushClipRect(ImVec2 clip_rect_min, ImVec2 clip_rect_max, bool intersect_with_current_clip_rect = false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) - IMGUI_API void PushClipRectFullScreen(); - IMGUI_API void PopClipRect(); - IMGUI_API void PushTextureID(const ImTextureID& texture_id); - IMGUI_API void PopTextureID(); - - // Primitives - IMGUI_API void AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness = 1.0f); - IMGUI_API void AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners_flags = ~0, float thickness = 1.0f); // a: upper-left, b: lower-right, rounding_corners_flags: 4-bits corresponding to which corner to round - IMGUI_API void AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners_flags = ~0); // a: upper-left, b: lower-right - IMGUI_API void AddRectFilledMultiColor(const ImVec2& a, const ImVec2& b, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left); - IMGUI_API void AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col, float thickness = 1.0f); - IMGUI_API void AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col); - IMGUI_API void AddTriangle(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col, float thickness = 1.0f); - IMGUI_API void AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col); - IMGUI_API void AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments = 12, float thickness = 1.0f); - IMGUI_API void AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments = 12); - IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL); - IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); - IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), ImU32 col = 0xFFFFFFFF); - IMGUI_API void AddPolyline(const ImVec2* points, const int num_points, ImU32 col, bool closed, float thickness, bool anti_aliased); - IMGUI_API void AddConvexPolyFilled(const ImVec2* points, const int num_points, ImU32 col, bool anti_aliased); - IMGUI_API void AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments = 0); - - // Stateful path API, add points then finish with PathFill() or PathStroke() - inline void PathClear() { _Path.resize(0); } - inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } - inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path[_Path.Size-1], &pos, 8) != 0) _Path.push_back(pos); } - inline void PathFill(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col, true); PathClear(); } - inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); PathClear(); } - IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10); - IMGUI_API void PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle - IMGUI_API void PathBezierCurveTo(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, int num_segments = 0); - IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, int rounding_corners_flags = ~0); // rounding_corners_flags: 4-bits corresponding to which corner to round - - // Channels - // - Use to simulate layers. By switching channels to can render out-of-order (e.g. submit foreground primitives before background primitives) - // - Use to minimize draw calls (e.g. if going back-and-forth between multiple non-overlapping clipping rectangles, prefer to append into separate channels then merge at the end) - IMGUI_API void ChannelsSplit(int channels_count); - IMGUI_API void ChannelsMerge(); - IMGUI_API void ChannelsSetCurrent(int channel_index); - - // Advanced - IMGUI_API void AddCallback(ImDrawCallback callback, void* callback_data); // Your rendering function must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles. - IMGUI_API void AddDrawCmd(); // This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending). Otherwise primitives are merged into the same draw-call as much as possible - - // Internal helpers - // NB: all primitives needs to be reserved via PrimReserve() beforehand! - IMGUI_API void Clear(); - IMGUI_API void ClearFreeMemory(); - IMGUI_API void PrimReserve(int idx_count, int vtx_count); - IMGUI_API void PrimRect(const ImVec2& a, const ImVec2& b, ImU32 col); // Axis aligned rectangle (composed of two triangles) - IMGUI_API void PrimRectUV(const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col); - IMGUI_API void PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col); - inline void PrimWriteVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col){ _VtxWritePtr->pos = pos; _VtxWritePtr->uv = uv; _VtxWritePtr->col = col; _VtxWritePtr++; _VtxCurrentIdx++; } - inline void PrimWriteIdx(ImDrawIdx idx) { *_IdxWritePtr = idx; _IdxWritePtr++; } - inline void PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); PrimWriteVtx(pos, uv, col); } - IMGUI_API void UpdateClipRect(); - IMGUI_API void UpdateTextureID(); -}; - -// All draw data to render an ImGui frame -struct ImDrawData -{ - bool Valid; // Only valid after Render() is called and before the next NewFrame() is called. - ImDrawList** CmdLists; - int CmdListsCount; - int TotalVtxCount; // For convenience, sum of all cmd_lists vtx_buffer.Size - int TotalIdxCount; // For convenience, sum of all cmd_lists idx_buffer.Size - - // Functions - ImDrawData() { Valid = false; CmdLists = NULL; CmdListsCount = TotalVtxCount = TotalIdxCount = 0; } - IMGUI_API void DeIndexAllBuffers(); // For backward compatibility: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering! - IMGUI_API void ScaleClipRects(const ImVec2& sc); // Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution. -}; - -struct ImFontConfig -{ - void* FontData; // // TTF data - int FontDataSize; // // TTF data size - bool FontDataOwnedByAtlas; // true // TTF data ownership taken by the container ImFontAtlas (will delete memory itself). Set to true - int FontNo; // 0 // Index of font within TTF file - float SizePixels; // // Size in pixels for rasterizer - int OversampleH, OversampleV; // 3, 1 // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel positions on the Y axis. - bool PixelSnapH; // false // Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1. - ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs - const ImWchar* GlyphRanges; // // Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. - bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). - bool MergeGlyphCenterV; // false // When merging (multiple ImFontInput for one ImFont), vertically center new glyphs instead of aligning their baseline - - // [Internal] - char Name[32]; // Name (strictly for debugging) - ImFont* DstFont; - - IMGUI_API ImFontConfig(); -}; - -// Load and rasterize multiple TTF fonts into a same texture. -// Sharing a texture for multiple fonts allows us to reduce the number of draw calls during rendering. -// We also add custom graphic data into the texture that serves for ImGui. -// 1. (Optional) Call AddFont*** functions. If you don't call any, the default font will be loaded for you. -// 2. Call GetTexDataAsAlpha8() or GetTexDataAsRGBA32() to build and retrieve pixels data. -// 3. Upload the pixels data into a texture within your graphics system. -// 4. Call SetTexID(my_tex_id); and pass the pointer/identifier to your texture. This value will be passed back to you during rendering to identify the texture. -// 5. Call ClearTexData() to free textures memory on the heap. -// NB: If you use a 'glyph_ranges' array you need to make sure that your array persist up until the ImFont is cleared. We only copy the pointer, not the data. -struct ImFontAtlas -{ - IMGUI_API ImFontAtlas(); - IMGUI_API ~ImFontAtlas(); - IMGUI_API ImFont* AddFont(const ImFontConfig* font_cfg); - IMGUI_API ImFont* AddFontDefault(const ImFontConfig* font_cfg = NULL); - IMGUI_API ImFont* AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); - IMGUI_API ImFont* AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Transfer ownership of 'ttf_data' to ImFontAtlas, will be deleted after Build() - IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_ttf_data' still owned by caller. Compress with binary_to_compressed_c.cpp - IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_ttf_data_base85, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_ttf_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 paramaeter - IMGUI_API void ClearTexData(); // Clear the CPU-side texture data. Saves RAM once the texture has been copied to graphics memory. - IMGUI_API void ClearInputData(); // Clear the input TTF data (inc sizes, glyph ranges) - IMGUI_API void ClearFonts(); // Clear the ImGui-side font data (glyphs storage, UV coordinates) - IMGUI_API void Clear(); // Clear all - - // Retrieve texture data - // User is in charge of copying the pixels into graphics memory, then call SetTextureUserID() - // After loading the texture into your graphic system, store your texture handle in 'TexID' (ignore if you aren't using multiple fonts nor images) - // RGBA32 format is provided for convenience and high compatibility, but note that all RGB pixels are white, so 75% of the memory is wasted. - // Pitch = Width * BytesPerPixels - IMGUI_API void GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 1 byte per-pixel - IMGUI_API void GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 4 bytes-per-pixel - void SetTexID(void* id) { TexID = id; } - - // Helpers to retrieve list of common Unicode ranges (2 value per range, values are inclusive, zero-terminated list) - // NB: Make sure that your string are UTF-8 and NOT in your local code page. See FAQ for details. - IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin - IMGUI_API const ImWchar* GetGlyphRangesKorean(); // Default + Korean characters - IMGUI_API const ImWchar* GetGlyphRangesJapanese(); // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs - IMGUI_API const ImWchar* GetGlyphRangesChinese(); // Japanese + full set of about 21000 CJK Unified Ideographs - IMGUI_API const ImWchar* GetGlyphRangesCyrillic(); // Default + about 400 Cyrillic characters - IMGUI_API const ImWchar* GetGlyphRangesThai(); // Default + Thai characters - - // Members - // (Access texture data via GetTexData*() calls which will setup a default font for you.) - void* TexID; // User data to refer to the texture once it has been uploaded to user's graphic systems. It ia passed back to you during rendering. - unsigned char* TexPixelsAlpha8; // 1 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight - unsigned int* TexPixelsRGBA32; // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4 - int TexWidth; // Texture width calculated during Build(). - int TexHeight; // Texture height calculated during Build(). - int TexDesiredWidth; // Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height. - ImVec2 TexUvWhitePixel; // Texture coordinates to a white pixel - ImVector Fonts; // Hold all the fonts returned by AddFont*. Fonts[0] is the default font upon calling ImGui::NewFrame(), use ImGui::PushFont()/PopFont() to change the current font. - - // Private - ImVector ConfigData; // Internal data - IMGUI_API bool Build(); // Build pixels data. This is automatically for you by the GetTexData*** functions. - IMGUI_API void RenderCustomTexData(int pass, void* rects); -}; - -// Font runtime data and rendering -// ImFontAtlas automatically loads a default embedded font for you when you call GetTexDataAsAlpha8() or GetTexDataAsRGBA32(). -struct ImFont -{ - struct Glyph - { - ImWchar Codepoint; - float XAdvance; - float X0, Y0, X1, Y1; - float U0, V0, U1, V1; // Texture coordinates - }; - - // Members: Hot ~62/78 bytes - float FontSize; // // Height of characters, set during loading (don't change after loading) - float Scale; // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetFontScale() - ImVec2 DisplayOffset; // = (0.f,1.f) // Offset font rendering by xx pixels - ImVector Glyphs; // // All glyphs. - ImVector IndexXAdvance; // // Sparse. Glyphs->XAdvance in a directly indexable way (more cache-friendly, for CalcTextSize functions which are often bottleneck in large UI). - ImVector IndexLookup; // // Sparse. Index glyphs by Unicode code-point. - const Glyph* FallbackGlyph; // == FindGlyph(FontFallbackChar) - float FallbackXAdvance; // == FallbackGlyph->XAdvance - ImWchar FallbackChar; // = '?' // Replacement glyph if one isn't found. Only set via SetFallbackChar() - - // Members: Cold ~18/26 bytes - short ConfigDataCount; // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont. - ImFontConfig* ConfigData; // // Pointer within ContainerAtlas->ConfigData - ImFontAtlas* ContainerAtlas; // // What we has been loaded into - float Ascent, Descent; // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] - int MetricsTotalSurface;// // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) - - // Methods - IMGUI_API ImFont(); - IMGUI_API ~ImFont(); - IMGUI_API void Clear(); - IMGUI_API void BuildLookupTable(); - IMGUI_API const Glyph* FindGlyph(ImWchar c) const; - IMGUI_API void SetFallbackChar(ImWchar c); - float GetCharAdvance(ImWchar c) const { return ((int)c < IndexXAdvance.Size) ? IndexXAdvance[(int)c] : FallbackXAdvance; } - bool IsLoaded() const { return ContainerAtlas != NULL; } - - // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable. - // 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable. - IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end = NULL, const char** remaining = NULL) const; // utf8 - IMGUI_API const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const; - IMGUI_API void RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, unsigned short c) const; - IMGUI_API void RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, bool cpu_fine_clip = false) const; - - // Private - IMGUI_API void GrowIndex(int new_size); - IMGUI_API void AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built. -}; - -#if defined(__clang__) -#pragma clang diagnostic pop -#endif - -// Include imgui_user.h at the end of imgui.h (convenient for user to only explicitly include vanilla imgui.h) -#ifdef IMGUI_INCLUDE_IMGUI_USER_H -#include "imgui_user.h" -#endif diff --git a/Baikal/ImGUI/imgui_demo.cpp b/Baikal/ImGUI/imgui_demo.cpp deleted file mode 100644 index 58f7a795..00000000 --- a/Baikal/ImGUI/imgui_demo.cpp +++ /dev/null @@ -1,2639 +0,0 @@ -// dear imgui, v1.50 WIP -// (demo code) - -// Don't remove this file from your project! It is useful reference code that you can execute. -// You can call ImGui::ShowTestWindow() in your code to learn about various features of ImGui. -// Everything in this file will be stripped out by the linker if you don't call ImGui::ShowTestWindow(). - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include "imgui.h" -#include // toupper, isprint -#include // sqrtf, powf, cosf, sinf, floorf, ceilf -#include // vsnprintf, sscanf, printf -#include // NULL, malloc, free, qsort, atoi -#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier -#include // intptr_t -#else -#include // intptr_t -#endif - -#ifdef _MSC_VER -#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen -#define snprintf _snprintf -#endif -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse. -#pragma clang diagnostic ignored "-Wdeprecated-declarations" // warning : 'xx' is deprecated: The POSIX name for this item.. // for strdup used in demo code (so user can copy & paste the code) -#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' -#pragma clang diagnostic ignored "-Wformat-security" // warning : warning: format string is not a string literal -#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals. -#if __has_warning("-Wreserved-id-macro") -#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier // -#endif -#elif defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size -#pragma GCC diagnostic ignored "-Wformat-security" // warning : format string is not a string literal (potentially insecure) -#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function -#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value -#if (__GNUC__ >= 6) -#pragma GCC diagnostic ignored "-Wmisleading-indentation" // warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on github. -#endif -#endif - -// Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n. -#ifdef _WIN32 -#define IM_NEWLINE "\r\n" -#else -#define IM_NEWLINE "\n" -#endif - -#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) -#define IM_MAX(_A,_B) (((_A) >= (_B)) ? (_A) : (_B)) - -//----------------------------------------------------------------------------- -// DEMO CODE -//----------------------------------------------------------------------------- - -#ifndef IMGUI_DISABLE_TEST_WINDOWS - -static void ShowExampleAppConsole(bool* p_open); -static void ShowExampleAppLog(bool* p_open); -static void ShowExampleAppLayout(bool* p_open); -static void ShowExampleAppPropertyEditor(bool* p_open); -static void ShowExampleAppLongText(bool* p_open); -static void ShowExampleAppAutoResize(bool* p_open); -static void ShowExampleAppConstrainedResize(bool* p_open); -static void ShowExampleAppFixedOverlay(bool* p_open); -static void ShowExampleAppManipulatingWindowTitle(bool* p_open); -static void ShowExampleAppCustomRendering(bool* p_open); -static void ShowExampleAppMainMenuBar(); -static void ShowExampleMenuFile(); - -static void ShowHelpMarker(const char* desc) -{ - ImGui::TextDisabled("(?)"); - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(450.0f); - ImGui::TextUnformatted(desc); - ImGui::PopTextWrapPos(); - ImGui::EndTooltip(); - } -} - -void ImGui::ShowUserGuide() -{ - ImGui::BulletText("Double-click on title bar to collapse window."); - ImGui::BulletText("Click and drag on lower right corner to resize window."); - ImGui::BulletText("Click and drag on any empty space to move window."); - ImGui::BulletText("Mouse Wheel to scroll."); - if (ImGui::GetIO().FontAllowUserScaling) - ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents."); - ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields."); - ImGui::BulletText("CTRL+Click on a slider or drag box to input text."); - ImGui::BulletText( - "While editing text:\n" - "- Hold SHIFT or use mouse to select text\n" - "- CTRL+Left/Right to word jump\n" - "- CTRL+A or double-click to select all\n" - "- CTRL+X,CTRL+C,CTRL+V clipboard\n" - "- CTRL+Z,CTRL+Y undo/redo\n" - "- ESCAPE to revert\n" - "- You can apply arithmetic operators +,*,/ on numerical values.\n" - " Use +- to subtract.\n"); -} - -// Demonstrate most ImGui features (big function!) -void ImGui::ShowTestWindow(bool* p_open) -{ - // Examples apps - static bool show_app_main_menu_bar = false; - static bool show_app_console = false; - static bool show_app_log = false; - static bool show_app_layout = false; - static bool show_app_property_editor = false; - static bool show_app_long_text = false; - static bool show_app_auto_resize = false; - static bool show_app_constrained_resize = false; - static bool show_app_fixed_overlay = false; - static bool show_app_manipulating_window_title = false; - static bool show_app_custom_rendering = false; - static bool show_app_style_editor = false; - - static bool show_app_metrics = false; - static bool show_app_about = false; - - if (show_app_main_menu_bar) ShowExampleAppMainMenuBar(); - if (show_app_console) ShowExampleAppConsole(&show_app_console); - if (show_app_log) ShowExampleAppLog(&show_app_log); - if (show_app_layout) ShowExampleAppLayout(&show_app_layout); - if (show_app_property_editor) ShowExampleAppPropertyEditor(&show_app_property_editor); - if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text); - if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize); - if (show_app_constrained_resize) ShowExampleAppConstrainedResize(&show_app_constrained_resize); - if (show_app_fixed_overlay) ShowExampleAppFixedOverlay(&show_app_fixed_overlay); - if (show_app_manipulating_window_title) ShowExampleAppManipulatingWindowTitle(&show_app_manipulating_window_title); - if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering); - - if (show_app_metrics) ImGui::ShowMetricsWindow(&show_app_metrics); - if (show_app_style_editor) { ImGui::Begin("Style Editor", &show_app_style_editor); ImGui::ShowStyleEditor(); ImGui::End(); } - if (show_app_about) - { - ImGui::Begin("About ImGui", &show_app_about, ImGuiWindowFlags_AlwaysAutoResize); - ImGui::Text("dear imgui, %s", ImGui::GetVersion()); - ImGui::Separator(); - ImGui::Text("By Omar Cornut and all github contributors."); - ImGui::Text("ImGui is licensed under the MIT License, see LICENSE for more information."); - ImGui::End(); - } - - static bool no_titlebar = false; - static bool no_border = true; - static bool no_resize = false; - static bool no_move = false; - static bool no_scrollbar = false; - static bool no_collapse = false; - static bool no_menu = false; - - // Demonstrate the various window flags. Typically you would just use the default. - ImGuiWindowFlags window_flags = 0; - if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar; - if (!no_border) window_flags |= ImGuiWindowFlags_ShowBorders; - if (no_resize) window_flags |= ImGuiWindowFlags_NoResize; - if (no_move) window_flags |= ImGuiWindowFlags_NoMove; - if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar; - if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse; - if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar; - ImGui::SetNextWindowSize(ImVec2(550,680), ImGuiSetCond_FirstUseEver); - if (!ImGui::Begin("ImGui Demo", p_open, window_flags)) - { - // Early out if the window is collapsed, as an optimization. - ImGui::End(); - return; - } - - //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f); // 2/3 of the space for widget and 1/3 for labels - ImGui::PushItemWidth(-140); // Right align, keep 140 pixels for labels - - ImGui::Text("Dear ImGui says hello."); - - // Menu - if (ImGui::BeginMenuBar()) - { - if (ImGui::BeginMenu("Menu")) - { - ShowExampleMenuFile(); - ImGui::EndMenu(); - } - if (ImGui::BeginMenu("Examples")) - { - ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar); - ImGui::MenuItem("Console", NULL, &show_app_console); - ImGui::MenuItem("Log", NULL, &show_app_log); - ImGui::MenuItem("Simple layout", NULL, &show_app_layout); - ImGui::MenuItem("Property editor", NULL, &show_app_property_editor); - ImGui::MenuItem("Long text display", NULL, &show_app_long_text); - ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize); - ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize); - ImGui::MenuItem("Simple overlay", NULL, &show_app_fixed_overlay); - ImGui::MenuItem("Manipulating window title", NULL, &show_app_manipulating_window_title); - ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering); - ImGui::EndMenu(); - } - if (ImGui::BeginMenu("Help")) - { - ImGui::MenuItem("Metrics", NULL, &show_app_metrics); - ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor); - ImGui::MenuItem("About ImGui", NULL, &show_app_about); - ImGui::EndMenu(); - } - ImGui::EndMenuBar(); - } - - ImGui::Spacing(); - if (ImGui::CollapsingHeader("Help")) - { - ImGui::TextWrapped("This window is being created by the ShowTestWindow() function. Please refer to the code for programming reference.\n\nUser Guide:"); - ImGui::ShowUserGuide(); - } - - if (ImGui::CollapsingHeader("Window options")) - { - ImGui::Checkbox("No titlebar", &no_titlebar); ImGui::SameLine(150); - ImGui::Checkbox("No border", &no_border); ImGui::SameLine(300); - ImGui::Checkbox("No resize", &no_resize); - ImGui::Checkbox("No move", &no_move); ImGui::SameLine(150); - ImGui::Checkbox("No scrollbar", &no_scrollbar); ImGui::SameLine(300); - ImGui::Checkbox("No collapse", &no_collapse); - ImGui::Checkbox("No menu", &no_menu); - - if (ImGui::TreeNode("Style")) - { - ImGui::ShowStyleEditor(); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Logging")) - { - ImGui::TextWrapped("The logging API redirects all text output so you can easily capture the content of a window or a block. Tree nodes can be automatically expanded. You can also call ImGui::LogText() to output directly to the log without a visual output."); - ImGui::LogButtons(); - ImGui::TreePop(); - } - } - - if (ImGui::CollapsingHeader("Widgets")) - { - if (ImGui::TreeNode("Trees")) - { - if (ImGui::TreeNode("Basic trees")) - { - for (int i = 0; i < 5; i++) - if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i)) - { - ImGui::Text("blah blah"); - ImGui::SameLine(); - if (ImGui::SmallButton("print")) printf("Child %d pressed", i); - ImGui::TreePop(); - } - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Advanced, with Selectable nodes")) - { - ShowHelpMarker("This is a more standard looking tree with selectable nodes.\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open."); - static bool align_label_with_current_x_position = false; - ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position); - ImGui::Text("Hello!"); - if (align_label_with_current_x_position) - ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing()); - - static int selection_mask = (1 << 2); // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit. - int node_clicked = -1; // Temporary storage of what node we have clicked to process selection at the end of the loop. May be a pointer to your own node type, etc. - ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize()*3); // Increase spacing to differentiate leaves from expanded contents. - for (int i = 0; i < 6; i++) - { - // Disable the default open on single-click behavior and pass in Selected flag according to our selection state. - ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0); - if (i < 3) - { - // Node - bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i); - if (ImGui::IsItemClicked()) - node_clicked = i; - if (node_open) - { - ImGui::Text("Blah blah\nBlah Blah"); - ImGui::TreePop(); - } - } - else - { - // Leaf: The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use BulletText() or TreeAdvanceToLabelPos()+Text(). - ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen, "Selectable Leaf %d", i); - if (ImGui::IsItemClicked()) - node_clicked = i; - } - } - if (node_clicked != -1) - { - // Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame. - if (ImGui::GetIO().KeyCtrl) - selection_mask ^= (1 << node_clicked); // CTRL+click to toggle - else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, this commented bit preserve selection when clicking on item that is part of the selection - selection_mask = (1 << node_clicked); // Click to single-select - } - ImGui::PopStyleVar(); - if (align_label_with_current_x_position) - ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing()); - ImGui::TreePop(); - } - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Collapsing Headers")) - { - static bool closable_group = true; - if (ImGui::CollapsingHeader("Header")) - { - ImGui::Checkbox("Enable extra group", &closable_group); - for (int i = 0; i < 5; i++) - ImGui::Text("Some content %d", i); - } - if (ImGui::CollapsingHeader("Header with a close button", &closable_group)) - { - for (int i = 0; i < 5; i++) - ImGui::Text("More content %d", i); - } - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Bullets")) - { - ImGui::BulletText("Bullet point 1"); - ImGui::BulletText("Bullet point 2\nOn multiple lines"); - ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)"); - ImGui::Bullet(); ImGui::SmallButton("Button"); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Colored Text")) - { - // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility. - ImGui::TextColored(ImVec4(1.0f,0.0f,1.0f,1.0f), "Pink"); - ImGui::TextColored(ImVec4(1.0f,1.0f,0.0f,1.0f), "Yellow"); - ImGui::TextDisabled("Disabled"); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Word Wrapping")) - { - // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility. - ImGui::TextWrapped("This text should automatically wrap on the edge of the window. The current implementation for text wrapping follows simple rules suitable for English and possibly other languages."); - ImGui::Spacing(); - - static float wrap_width = 200.0f; - ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f"); - - ImGui::Text("Test paragraph 1:"); - ImVec2 pos = ImGui::GetCursorScreenPos(); - ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255,0,255,255)); - ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width); - ImGui::Text("The lazy dog is a good dog. This paragraph is made to fit within %.0f pixels. Testing a 1 character word. The quick brown fox jumps over the lazy dog.", wrap_width); - ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255)); - ImGui::PopTextWrapPos(); - - ImGui::Text("Test paragraph 2:"); - pos = ImGui::GetCursorScreenPos(); - ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255,0,255,255)); - ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width); - ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee ffffffff. gggggggg!hhhhhhhh"); - ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255)); - ImGui::PopTextWrapPos(); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("UTF-8 Text")) - { - // UTF-8 test with Japanese characters - // (needs a suitable font, try Arial Unicode or M+ fonts http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html) - // Most compiler appears to support UTF-8 in source code (with Visual Studio you need to save your file as 'UTF-8 without signature') - // However for the sake for maximum portability here we are *not* including raw UTF-8 character in this source file, instead we encode the string with hexadecimal constants. - // In your own application be reasonable and use UTF-8 in source or retrieve the data from file system! - // Note that characters values are preserved even if the font cannot be displayed, so you can safely copy & paste garbled characters into another application. - ImGui::TextWrapped("CJK text will only appears if the font was loaded with the appropriate CJK character ranges. Call io.Font->LoadFromFileTTF() manually to load extra character ranges."); - ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)"); - ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)"); - static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"; - ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf)); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Images")) - { - ImGui::TextWrapped("Below we are displaying the font texture (which is the only texture we have access to in this demo). Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. Hover the texture for a zoomed view!"); - ImVec2 tex_screen_pos = ImGui::GetCursorScreenPos(); - float tex_w = (float)ImGui::GetIO().Fonts->TexWidth; - float tex_h = (float)ImGui::GetIO().Fonts->TexHeight; - ImTextureID tex_id = ImGui::GetIO().Fonts->TexID; - ImGui::Text("%.0fx%.0f", tex_w, tex_h); - ImGui::Image(tex_id, ImVec2(tex_w, tex_h), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128)); - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - float focus_sz = 32.0f; - float focus_x = ImGui::GetMousePos().x - tex_screen_pos.x - focus_sz * 0.5f; if (focus_x < 0.0f) focus_x = 0.0f; else if (focus_x > tex_w - focus_sz) focus_x = tex_w - focus_sz; - float focus_y = ImGui::GetMousePos().y - tex_screen_pos.y - focus_sz * 0.5f; if (focus_y < 0.0f) focus_y = 0.0f; else if (focus_y > tex_h - focus_sz) focus_y = tex_h - focus_sz; - ImGui::Text("Min: (%.2f, %.2f)", focus_x, focus_y); - ImGui::Text("Max: (%.2f, %.2f)", focus_x + focus_sz, focus_y + focus_sz); - ImVec2 uv0 = ImVec2((focus_x) / tex_w, (focus_y) / tex_h); - ImVec2 uv1 = ImVec2((focus_x + focus_sz) / tex_w, (focus_y + focus_sz) / tex_h); - ImGui::Image(tex_id, ImVec2(128,128), uv0, uv1, ImColor(255,255,255,255), ImColor(255,255,255,128)); - ImGui::EndTooltip(); - } - ImGui::TextWrapped("And now some textured buttons.."); - static int pressed_count = 0; - for (int i = 0; i < 8; i++) - { - ImGui::PushID(i); - int frame_padding = -1 + i; // -1 = uses default padding - if (ImGui::ImageButton(tex_id, ImVec2(32,32), ImVec2(0,0), ImVec2(32.0f/tex_w,32/tex_h), frame_padding, ImColor(0,0,0,255))) - pressed_count += 1; - ImGui::PopID(); - ImGui::SameLine(); - } - ImGui::NewLine(); - ImGui::Text("Pressed %d times.", pressed_count); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Selectables")) - { - if (ImGui::TreeNode("Basic")) - { - static bool selected[4] = { false, true, false, false }; - ImGui::Selectable("1. I am selectable", &selected[0]); - ImGui::Selectable("2. I am selectable", &selected[1]); - ImGui::Text("3. I am not selectable"); - ImGui::Selectable("4. I am selectable", &selected[2]); - if (ImGui::Selectable("5. I am double clickable", selected[3], ImGuiSelectableFlags_AllowDoubleClick)) - if (ImGui::IsMouseDoubleClicked(0)) - selected[3] = !selected[3]; - ImGui::TreePop(); - } - if (ImGui::TreeNode("Rendering more text into the same block")) - { - static bool selected[3] = { false, false, false }; - ImGui::Selectable("main.c", &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes"); - ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(300); ImGui::Text("12,345 bytes"); - ImGui::Selectable("Hello.h", &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes"); - ImGui::TreePop(); - } - if (ImGui::TreeNode("In columns")) - { - ImGui::Columns(3, NULL, false); - static bool selected[16] = { 0 }; - for (int i = 0; i < 16; i++) - { - char label[32]; sprintf(label, "Item %d", i); - if (ImGui::Selectable(label, &selected[i])) {} - ImGui::NextColumn(); - } - ImGui::Columns(1); - ImGui::TreePop(); - } - if (ImGui::TreeNode("Grid")) - { - static bool selected[16] = { true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true }; - for (int i = 0; i < 16; i++) - { - ImGui::PushID(i); - if (ImGui::Selectable("Sailor", &selected[i], 0, ImVec2(50,50))) - { - int x = i % 4, y = i / 4; - if (x > 0) selected[i - 1] ^= 1; - if (x < 3) selected[i + 1] ^= 1; - if (y > 0) selected[i - 4] ^= 1; - if (y < 3) selected[i + 4] ^= 1; - } - if ((i % 4) < 3) ImGui::SameLine(); - ImGui::PopID(); - } - ImGui::TreePop(); - } - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Filtered Text Input")) - { - static char buf1[64] = ""; ImGui::InputText("default", buf1, 64); - static char buf2[64] = ""; ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal); - static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase); - static char buf4[64] = ""; ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase); - static char buf5[64] = ""; ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank); - struct TextFilters { static int FilterImGuiLetters(ImGuiTextEditCallbackData* data) { if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) return 0; return 1; } }; - static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters); - - ImGui::Text("Password input"); - static char bufpass[64] = "password123"; - ImGui::InputText("password", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank); - ImGui::SameLine(); ShowHelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n"); - ImGui::InputText("password (clear)", bufpass, 64, ImGuiInputTextFlags_CharsNoBlank); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Multi-line Text Input")) - { - static bool read_only = false; - static char text[1024*16] = - "/*\n" - " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n" - " the hexadecimal encoding of one offending instruction,\n" - " more formally, the invalid operand with locked CMPXCHG8B\n" - " instruction bug, is a design flaw in the majority of\n" - " Intel Pentium, Pentium MMX, and Pentium OverDrive\n" - " processors (all in the P5 microarchitecture).\n" - "*/\n\n" - "label:\n" - "\tlock cmpxchg8b eax\n"; - - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0)); - ImGui::Checkbox("Read-only", &read_only); - ImGui::PopStyleVar(); - ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), ImGuiInputTextFlags_AllowTabInput | (read_only ? ImGuiInputTextFlags_ReadOnly : 0)); - ImGui::TreePop(); - } - - static bool a=false; - if (ImGui::Button("Button")) { printf("Clicked\n"); a ^= 1; } - if (a) - { - ImGui::SameLine(); - ImGui::Text("Thanks for clicking me!"); - } - - static bool check = true; - ImGui::Checkbox("checkbox", &check); - - static int e = 0; - ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine(); - ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine(); - ImGui::RadioButton("radio c", &e, 2); - - // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style. - for (int i = 0; i < 7; i++) - { - if (i > 0) ImGui::SameLine(); - ImGui::PushID(i); - ImGui::PushStyleColor(ImGuiCol_Button, ImColor::HSV(i/7.0f, 0.6f, 0.6f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImColor::HSV(i/7.0f, 0.7f, 0.7f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImColor::HSV(i/7.0f, 0.8f, 0.8f)); - ImGui::Button("Click"); - ImGui::PopStyleColor(3); - ImGui::PopID(); - } - - ImGui::Text("Hover over me"); - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("I am a tooltip"); - - ImGui::SameLine(); - ImGui::Text("- or me"); - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::Text("I am a fancy tooltip"); - static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f }; - ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr)); - ImGui::EndTooltip(); - } - - // Testing IMGUI_ONCE_UPON_A_FRAME macro - //for (int i = 0; i < 5; i++) - //{ - // IMGUI_ONCE_UPON_A_FRAME - // { - // ImGui::Text("This will be displayed only once."); - // } - //} - - ImGui::Separator(); - - ImGui::LabelText("label", "Value"); - - static int item = 1; - ImGui::Combo("combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); // Combo using values packed in a single constant string (for really quick combo) - - const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK" }; - static int item2 = -1; - ImGui::Combo("combo scroll", &item2, items, IM_ARRAYSIZE(items)); // Combo using proper array. You can also pass a callback to retrieve array value, no need to create/copy an array just for that. - - { - static char str0[128] = "Hello, world!"; - static int i0=123; - static float f0=0.001f; - ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0)); - ImGui::SameLine(); ShowHelpMarker("Hold SHIFT or use mouse to select text.\n" "CTRL+Left/Right to word jump.\n" "CTRL+A or double-click to select all.\n" "CTRL+X,CTRL+C,CTRL+V clipboard.\n" "CTRL+Z,CTRL+Y undo/redo.\n" "ESCAPE to revert.\n"); - - ImGui::InputInt("input int", &i0); - ImGui::SameLine(); ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n"); - - ImGui::InputFloat("input float", &f0, 0.01f, 1.0f); - - static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f }; - ImGui::InputFloat3("input float3", vec4a); - } - - { - static int i1=50, i2=42; - ImGui::DragInt("drag int", &i1, 1); - ImGui::SameLine(); ShowHelpMarker("Click and drag to edit value.\nHold SHIFT/ALT for faster/slower edit.\nDouble-click or CTRL+click to input value."); - - ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%.0f%%"); - - static float f1=1.00f, f2=0.0067f; - ImGui::DragFloat("drag float", &f1, 0.005f); - ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns"); - } - - { - static int i1=0; - ImGui::SliderInt("slider int", &i1, -1, 3); - ImGui::SameLine(); ShowHelpMarker("CTRL+click to input value."); - - static float f1=0.123f, f2=0.0f; - ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f"); - ImGui::SliderFloat("slider log float", &f2, -10.0f, 10.0f, "%.4f", 3.0f); - static float angle = 0.0f; - ImGui::SliderAngle("slider angle", &angle); - } - - static float col1[3] = { 1.0f,0.0f,0.2f }; - static float col2[4] = { 0.4f,0.7f,0.0f,0.5f }; - ImGui::ColorEdit3("color 1", col1); - ImGui::SameLine(); ShowHelpMarker("Click on the colored square to change edit mode.\nCTRL+click on individual component to input value.\n"); - - ImGui::ColorEdit4("color 2", col2); - - const char* listbox_items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" }; - static int listbox_item_current = 1; - ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4); - - //static int listbox_item_current2 = 2; - //ImGui::PushItemWidth(-1); - //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4); - //ImGui::PopItemWidth(); - - if (ImGui::TreeNode("Range Widgets")) - { - ImGui::Unindent(); - - static float begin = 10, end = 90; - static int begin_i = 100, end_i = 1000; - ImGui::DragFloatRange2("range", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%"); - ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %.0f units", "Max: %.0f units"); - - ImGui::Indent(); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Multi-component Widgets")) - { - ImGui::Unindent(); - - static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f }; - static int vec4i[4] = { 1, 5, 100, 255 }; - - ImGui::InputFloat2("input float2", vec4f); - ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f); - ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f); - ImGui::DragInt2("drag int2", vec4i, 1, 0, 255); - ImGui::InputInt2("input int2", vec4i); - ImGui::SliderInt2("slider int2", vec4i, 0, 255); - ImGui::Spacing(); - - ImGui::InputFloat3("input float3", vec4f); - ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f); - ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f); - ImGui::DragInt3("drag int3", vec4i, 1, 0, 255); - ImGui::InputInt3("input int3", vec4i); - ImGui::SliderInt3("slider int3", vec4i, 0, 255); - ImGui::Spacing(); - - ImGui::InputFloat4("input float4", vec4f); - ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f); - ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f); - ImGui::InputInt4("input int4", vec4i); - ImGui::DragInt4("drag int4", vec4i, 1, 0, 255); - ImGui::SliderInt4("slider int4", vec4i, 0, 255); - - ImGui::Indent(); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Vertical Sliders")) - { - ImGui::Unindent(); - const float spacing = 4; - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing)); - - static int int_value = 0; - ImGui::VSliderInt("##int", ImVec2(18,160), &int_value, 0, 5); - ImGui::SameLine(); - - static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f }; - ImGui::PushID("set1"); - for (int i = 0; i < 7; i++) - { - if (i > 0) ImGui::SameLine(); - ImGui::PushID(i); - ImGui::PushStyleColor(ImGuiCol_FrameBg, ImColor::HSV(i/7.0f, 0.5f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImColor::HSV(i/7.0f, 0.6f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImColor::HSV(i/7.0f, 0.7f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImColor::HSV(i/7.0f, 0.9f, 0.9f)); - ImGui::VSliderFloat("##v", ImVec2(18,160), &values[i], 0.0f, 1.0f, ""); - if (ImGui::IsItemActive() || ImGui::IsItemHovered()) - ImGui::SetTooltip("%.3f", values[i]); - ImGui::PopStyleColor(4); - ImGui::PopID(); - } - ImGui::PopID(); - - ImGui::SameLine(); - ImGui::PushID("set2"); - static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f }; - const int rows = 3; - const ImVec2 small_slider_size(18, (160.0f-(rows-1)*spacing)/rows); - for (int nx = 0; nx < 4; nx++) - { - if (nx > 0) ImGui::SameLine(); - ImGui::BeginGroup(); - for (int ny = 0; ny < rows; ny++) - { - ImGui::PushID(nx*rows+ny); - ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, ""); - if (ImGui::IsItemActive() || ImGui::IsItemHovered()) - ImGui::SetTooltip("%.3f", values2[nx]); - ImGui::PopID(); - } - ImGui::EndGroup(); - } - ImGui::PopID(); - - ImGui::SameLine(); - ImGui::PushID("set3"); - for (int i = 0; i < 4; i++) - { - if (i > 0) ImGui::SameLine(); - ImGui::PushID(i); - ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40); - ImGui::VSliderFloat("##v", ImVec2(40,160), &values[i], 0.0f, 1.0f, "%.2f\nsec"); - ImGui::PopStyleVar(); - ImGui::PopID(); - } - ImGui::PopID(); - ImGui::PopStyleVar(); - - ImGui::Indent(); - ImGui::TreePop(); - } - } - - if (ImGui::CollapsingHeader("Graphs widgets")) - { - static bool animate = true; - ImGui::Checkbox("Animate", &animate); - - static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f }; - ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr)); - - // Create a dummy array of contiguous float values to plot - // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float and the sizeof() of your structure in the Stride parameter. - static float values[90] = { 0 }; - static int values_offset = 0; - if (animate) - { - static float refresh_time = ImGui::GetTime(); // Create dummy data at fixed 60 hz rate for the demo - for (; ImGui::GetTime() > refresh_time + 1.0f/60.0f; refresh_time += 1.0f/60.0f) - { - static float phase = 0.0f; - values[values_offset] = cosf(phase); - values_offset = (values_offset+1) % IM_ARRAYSIZE(values); - phase += 0.10f*values_offset; - } - } - ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,80)); - ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,80)); - - // Use functions to generate output - // FIXME: This is rather awkward because current plot API only pass in indices. We probably want an API passing floats and user provide sample rate/count. - struct Funcs - { - static float Sin(void*, int i) { return sinf(i * 0.1f); } - static float Saw(void*, int i) { return (i & 1) ? 1.0f : 0.0f; } - }; - static int func_type = 0, display_count = 70; - ImGui::Separator(); - ImGui::PushItemWidth(100); ImGui::Combo("func", &func_type, "Sin\0Saw\0"); ImGui::PopItemWidth(); - ImGui::SameLine(); - ImGui::SliderInt("Sample count", &display_count, 1, 400); - float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw; - ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80)); - ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80)); - ImGui::Separator(); - - // Animate a simple progress bar - static float progress = 0.0f, progress_dir = 1.0f; - if (animate) - { - progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime; - if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; } - if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; } - } - - // Typically we would use ImVec2(-1.0f,0.0f) to use all available width, or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth. - ImGui::ProgressBar(progress, ImVec2(0.0f,0.0f)); - ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); - ImGui::Text("Progress Bar"); - - float progress_saturated = (progress < 0.0f) ? 0.0f : (progress > 1.0f) ? 1.0f : progress; - char buf[32]; - sprintf(buf, "%d/%d", (int)(progress_saturated*1753), 1753); - ImGui::ProgressBar(progress, ImVec2(0.f,0.f), buf); - } - - if (ImGui::CollapsingHeader("Layout")) - { - if (ImGui::TreeNode("Child regions")) - { - ImGui::Text("Without border"); - static int line = 50; - bool goto_line = ImGui::Button("Goto"); - ImGui::SameLine(); - ImGui::PushItemWidth(100); - goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue); - ImGui::PopItemWidth(); - ImGui::BeginChild("Sub1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f,300), false, ImGuiWindowFlags_HorizontalScrollbar); - for (int i = 0; i < 100; i++) - { - ImGui::Text("%04d: scrollable region", i); - if (goto_line && line == i) - ImGui::SetScrollHere(); - } - if (goto_line && line >= 100) - ImGui::SetScrollHere(); - ImGui::EndChild(); - - ImGui::SameLine(); - - ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, 5.0f); - ImGui::BeginChild("Sub2", ImVec2(0,300), true); - ImGui::Text("With border"); - ImGui::Columns(2); - for (int i = 0; i < 100; i++) - { - if (i == 50) - ImGui::NextColumn(); - char buf[32]; - sprintf(buf, "%08x", i*5731); - ImGui::Button(buf, ImVec2(-1.0f, 0.0f)); - } - ImGui::EndChild(); - ImGui::PopStyleVar(); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Widgets Width")) - { - static float f = 0.0f; - ImGui::Text("PushItemWidth(100)"); - ImGui::SameLine(); ShowHelpMarker("Fixed width."); - ImGui::PushItemWidth(100); - ImGui::DragFloat("float##1", &f); - ImGui::PopItemWidth(); - - ImGui::Text("PushItemWidth(GetWindowWidth() * 0.5f)"); - ImGui::SameLine(); ShowHelpMarker("Half of window width."); - ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f); - ImGui::DragFloat("float##2", &f); - ImGui::PopItemWidth(); - - ImGui::Text("PushItemWidth(GetContentRegionAvailWidth() * 0.5f)"); - ImGui::SameLine(); ShowHelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)"); - ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() * 0.5f); - ImGui::DragFloat("float##3", &f); - ImGui::PopItemWidth(); - - ImGui::Text("PushItemWidth(-100)"); - ImGui::SameLine(); ShowHelpMarker("Align to right edge minus 100"); - ImGui::PushItemWidth(-100); - ImGui::DragFloat("float##4", &f); - ImGui::PopItemWidth(); - - ImGui::Text("PushItemWidth(-1)"); - ImGui::SameLine(); ShowHelpMarker("Align to right edge"); - ImGui::PushItemWidth(-1); - ImGui::DragFloat("float##5", &f); - ImGui::PopItemWidth(); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Basic Horizontal Layout")) - { - ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)"); - - // Text - ImGui::Text("Two items: Hello"); ImGui::SameLine(); - ImGui::TextColored(ImVec4(1,1,0,1), "Sailor"); - - // Adjust spacing - ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20); - ImGui::TextColored(ImVec4(1,1,0,1), "Sailor"); - - // Button - ImGui::AlignFirstTextHeightToWidgets(); - ImGui::Text("Normal buttons"); ImGui::SameLine(); - ImGui::Button("Banana"); ImGui::SameLine(); - ImGui::Button("Apple"); ImGui::SameLine(); - ImGui::Button("Corniflower"); - - // Button - ImGui::Text("Small buttons"); ImGui::SameLine(); - ImGui::SmallButton("Like this one"); ImGui::SameLine(); - ImGui::Text("can fit within a text block."); - - // Aligned to arbitrary position. Easy/cheap column. - ImGui::Text("Aligned"); - ImGui::SameLine(150); ImGui::Text("x=150"); - ImGui::SameLine(300); ImGui::Text("x=300"); - ImGui::Text("Aligned"); - ImGui::SameLine(150); ImGui::SmallButton("x=150"); - ImGui::SameLine(300); ImGui::SmallButton("x=300"); - - // Checkbox - static bool c1=false,c2=false,c3=false,c4=false; - ImGui::Checkbox("My", &c1); ImGui::SameLine(); - ImGui::Checkbox("Tailor", &c2); ImGui::SameLine(); - ImGui::Checkbox("Is", &c3); ImGui::SameLine(); - ImGui::Checkbox("Rich", &c4); - - // Various - static float f0=1.0f, f1=2.0f, f2=3.0f; - ImGui::PushItemWidth(80); - const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" }; - static int item = -1; - ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine(); - ImGui::SliderFloat("X", &f0, 0.0f,5.0f); ImGui::SameLine(); - ImGui::SliderFloat("Y", &f1, 0.0f,5.0f); ImGui::SameLine(); - ImGui::SliderFloat("Z", &f2, 0.0f,5.0f); - ImGui::PopItemWidth(); - - ImGui::PushItemWidth(80); - ImGui::Text("Lists:"); - static int selection[4] = { 0, 1, 2, 3 }; - for (int i = 0; i < 4; i++) - { - if (i > 0) ImGui::SameLine(); - ImGui::PushID(i); - ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items)); - ImGui::PopID(); - //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i); - } - ImGui::PopItemWidth(); - - // Dummy - ImVec2 sz(30,30); - ImGui::Button("A", sz); ImGui::SameLine(); - ImGui::Dummy(sz); ImGui::SameLine(); - ImGui::Button("B", sz); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Groups")) - { - ImGui::TextWrapped("(Using ImGui::BeginGroup()/EndGroup() to layout items. BeginGroup() basically locks the horizontal position. EndGroup() bundles the whole group so that you can use functions such as IsItemHovered() on it.)"); - ImGui::BeginGroup(); - { - ImGui::BeginGroup(); - ImGui::Button("AAA"); - ImGui::SameLine(); - ImGui::Button("BBB"); - ImGui::SameLine(); - ImGui::BeginGroup(); - ImGui::Button("CCC"); - ImGui::Button("DDD"); - ImGui::EndGroup(); - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("Group hovered"); - ImGui::SameLine(); - ImGui::Button("EEE"); - ImGui::EndGroup(); - } - // Capture the group size and create widgets using the same size - ImVec2 size = ImGui::GetItemRectSize(); - const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f }; - ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size); - - ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y)); - ImGui::SameLine(); - ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y)); - ImGui::EndGroup(); - ImGui::SameLine(); - - ImGui::Button("LEVERAGE\nBUZZWORD", size); - ImGui::SameLine(); - - ImGui::ListBoxHeader("List", size); - ImGui::Selectable("Selected", true); - ImGui::Selectable("Not Selected", false); - ImGui::ListBoxFooter(); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Text Baseline Alignment")) - { - ImGui::TextWrapped("(This is testing the vertical alignment that occurs on text to keep it at the same baseline as widgets. Lines only composed of text or \"small\" widgets fit in less vertical spaces than lines with normal widgets)"); - - ImGui::Text("One\nTwo\nThree"); ImGui::SameLine(); - ImGui::Text("Hello\nWorld"); ImGui::SameLine(); - ImGui::Text("Banana"); - - ImGui::Text("Banana"); ImGui::SameLine(); - ImGui::Text("Hello\nWorld"); ImGui::SameLine(); - ImGui::Text("One\nTwo\nThree"); - - ImGui::Button("HOP##1"); ImGui::SameLine(); - ImGui::Text("Banana"); ImGui::SameLine(); - ImGui::Text("Hello\nWorld"); ImGui::SameLine(); - ImGui::Text("Banana"); - - ImGui::Button("HOP##2"); ImGui::SameLine(); - ImGui::Text("Hello\nWorld"); ImGui::SameLine(); - ImGui::Text("Banana"); - - ImGui::Button("TEST##1"); ImGui::SameLine(); - ImGui::Text("TEST"); ImGui::SameLine(); - ImGui::SmallButton("TEST##2"); - - ImGui::AlignFirstTextHeightToWidgets(); // If your line starts with text, call this to align it to upcoming widgets. - ImGui::Text("Text aligned to Widget"); ImGui::SameLine(); - ImGui::Button("Widget##1"); ImGui::SameLine(); - ImGui::Text("Widget"); ImGui::SameLine(); - ImGui::SmallButton("Widget##2"); - - // Tree - const float spacing = ImGui::GetStyle().ItemInnerSpacing.x; - ImGui::Button("Button##1"); - ImGui::SameLine(0.0f, spacing); - if (ImGui::TreeNode("Node##1")) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data - - ImGui::AlignFirstTextHeightToWidgets(); // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. Otherwise you can use SmallButton (smaller fit). - bool node_open = ImGui::TreeNode("Node##2"); // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add child content. - ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2"); - if (node_open) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data - - // Bullet - ImGui::Button("Button##3"); - ImGui::SameLine(0.0f, spacing); - ImGui::BulletText("Bullet text"); - - ImGui::AlignFirstTextHeightToWidgets(); - ImGui::BulletText("Node"); - ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4"); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Scrolling")) - { - ImGui::TextWrapped("(Use SetScrollHere() or SetScrollFromPosY() to scroll to a given position.)"); - static bool track = true; - static int track_line = 50, scroll_to_px = 200; - ImGui::Checkbox("Track", &track); - ImGui::PushItemWidth(100); - ImGui::SameLine(130); track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 99, "Line %.0f"); - bool scroll_to = ImGui::Button("Scroll To"); - ImGui::SameLine(130); scroll_to |= ImGui::DragInt("##pos_y", &scroll_to_px, 1.00f, 0, 9999, "y = %.0f px"); - ImGui::PopItemWidth(); - if (scroll_to) track = false; - - for (int i = 0; i < 5; i++) - { - if (i > 0) ImGui::SameLine(); - ImGui::BeginGroup(); - ImGui::Text("%s", i == 0 ? "Top" : i == 1 ? "25%" : i == 2 ? "Center" : i == 3 ? "75%" : "Bottom"); - ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true); - if (scroll_to) - ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f); - for (int line = 0; line < 100; line++) - { - if (track && line == track_line) - { - ImGui::TextColored(ImColor(255,255,0), "Line %d", line); - ImGui::SetScrollHere(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom - } - else - { - ImGui::Text("Line %d", line); - } - } - ImGui::EndChild(); - ImGui::EndGroup(); - } - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Horizontal Scrolling")) - { - ImGui::Bullet(); ImGui::TextWrapped("Horizontal scrolling for a window has to be enabled explicitly via the ImGuiWindowFlags_HorizontalScrollbar flag."); - ImGui::Bullet(); ImGui::TextWrapped("You may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin()."); - static int lines = 7; - ImGui::SliderInt("Lines", &lines, 1, 15); - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f)); - ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetItemsLineHeightWithSpacing()*7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar); - for (int line = 0; line < lines; line++) - { - // Display random stuff (for the sake of this trivial demo we are using basic Button+SameLine. If you want to create your own time line for a real application you may be better off - // manipulating the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets yourself. You may also want to use the lower-level ImDrawList API) - int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3); - for (int n = 0; n < num_buttons; n++) - { - if (n > 0) ImGui::SameLine(); - ImGui::PushID(n + line * 1000); - char num_buf[16]; - const char* label = (!(n%15)) ? "FizzBuzz" : (!(n%3)) ? "Fizz" : (!(n%5)) ? "Buzz" : (sprintf(num_buf, "%d", n), num_buf); - float hue = n*0.05f; - ImGui::PushStyleColor(ImGuiCol_Button, ImColor::HSV(hue, 0.6f, 0.6f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImColor::HSV(hue, 0.7f, 0.7f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImColor::HSV(hue, 0.8f, 0.8f)); - ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f)); - ImGui::PopStyleColor(3); - ImGui::PopID(); - } - } - ImGui::EndChild(); - ImGui::PopStyleVar(2); - float scroll_x_delta = 0.0f; - ImGui::SmallButton("<<"); if (ImGui::IsItemActive()) scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f; - ImGui::SameLine(); ImGui::Text("Scroll from code"); ImGui::SameLine(); - ImGui::SmallButton(">>"); if (ImGui::IsItemActive()) scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f; - if (scroll_x_delta != 0.0f) - { - ImGui::BeginChild("scrolling"); // Demonstrate a trick: you can use Begin to set yourself in the context of another window (here we are already out of your child window) - ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta); - ImGui::End(); - } - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Clipping")) - { - static ImVec2 size(100, 100), offset(50, 20); - ImGui::TextWrapped("On a per-widget basis we are occasionally clipping text CPU-side if it won't fit in its frame. Otherwise we are doing coarser clipping + passing a scissor rectangle to the renderer. The system is designed to try minimizing both execution and CPU/GPU rendering cost."); - ImGui::DragFloat2("size", (float*)&size, 0.5f, 0.0f, 200.0f, "%.0f"); - ImGui::TextWrapped("(Click and drag)"); - ImVec2 pos = ImGui::GetCursorScreenPos(); - ImVec4 clip_rect(pos.x, pos.y, pos.x+size.x, pos.y+size.y); - ImGui::InvisibleButton("##dummy", size); - if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; } - ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x+size.x,pos.y+size.y), ImColor(90,90,120,255)); - ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize()*2.0f, ImVec2(pos.x+offset.x,pos.y+offset.y), ImColor(255,255,255,255), "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect); - ImGui::TreePop(); - } - } - - if (ImGui::CollapsingHeader("Popups & Modal windows")) - { - if (ImGui::TreeNode("Popups")) - { - ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it."); - - static int selected_fish = -1; - const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" }; - static bool toggles[] = { true, false, false, false, false }; - - // Simple selection popup - // (If you want to show the current selection inside the Button itself, you may want to build a string using the "###" operator to preserve a constant ID with a variable label) - if (ImGui::Button("Select..")) - ImGui::OpenPopup("select"); - ImGui::SameLine(); - ImGui::Text(selected_fish == -1 ? "" : names[selected_fish]); - if (ImGui::BeginPopup("select")) - { - ImGui::Text("Aquarium"); - ImGui::Separator(); - for (int i = 0; i < IM_ARRAYSIZE(names); i++) - if (ImGui::Selectable(names[i])) - selected_fish = i; - ImGui::EndPopup(); - } - - // Showing a menu with toggles - if (ImGui::Button("Toggle..")) - ImGui::OpenPopup("toggle"); - if (ImGui::BeginPopup("toggle")) - { - for (int i = 0; i < IM_ARRAYSIZE(names); i++) - ImGui::MenuItem(names[i], "", &toggles[i]); - if (ImGui::BeginMenu("Sub-menu")) - { - ImGui::MenuItem("Click me"); - ImGui::EndMenu(); - } - - ImGui::Separator(); - ImGui::Text("Tooltip here"); - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("I am a tooltip over a popup"); - - if (ImGui::Button("Stacked Popup")) - ImGui::OpenPopup("another popup"); - if (ImGui::BeginPopup("another popup")) - { - for (int i = 0; i < IM_ARRAYSIZE(names); i++) - ImGui::MenuItem(names[i], "", &toggles[i]); - if (ImGui::BeginMenu("Sub-menu")) - { - ImGui::MenuItem("Click me"); - ImGui::EndMenu(); - } - ImGui::EndPopup(); - } - ImGui::EndPopup(); - } - - if (ImGui::Button("Popup Menu..")) - ImGui::OpenPopup("FilePopup"); - if (ImGui::BeginPopup("FilePopup")) - { - ShowExampleMenuFile(); - ImGui::EndPopup(); - } - - ImGui::Spacing(); - ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!"); - ImGui::Separator(); - // NB: As a quirk in this very specific example, we want to differentiate the parent of this menu from the parent of the various popup menus above. - // To do so we are encloding the items in a PushID()/PopID() block to make them two different menusets. If we don't, opening any popup above and hovering our menu here - // would open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it, which is the desired behavior for regular menus. - ImGui::PushID("foo"); - ImGui::MenuItem("Menu item", "CTRL+M"); - if (ImGui::BeginMenu("Menu inside a regular window")) - { - ShowExampleMenuFile(); - ImGui::EndMenu(); - } - ImGui::PopID(); - ImGui::Separator(); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Context menus")) - { - static float value = 0.5f; - ImGui::Text("Value = %.3f (<-- right-click here)", value); - if (ImGui::BeginPopupContextItem("item context menu")) - { - if (ImGui::Selectable("Set to zero")) value = 0.0f; - if (ImGui::Selectable("Set to PI")) value = 3.1415f; - ImGui::EndPopup(); - } - - static ImVec4 color = ImColor(0.8f, 0.5f, 1.0f, 1.0f); - ImGui::ColorButton(color); - if (ImGui::BeginPopupContextItem("color context menu")) - { - ImGui::Text("Edit color"); - ImGui::ColorEdit3("##edit", (float*)&color); - if (ImGui::Button("Close")) - ImGui::CloseCurrentPopup(); - ImGui::EndPopup(); - } - ImGui::SameLine(); ImGui::Text("(<-- right-click here)"); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Modals")) - { - ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside the window."); - - if (ImGui::Button("Delete..")) - ImGui::OpenPopup("Delete?"); - if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize)) - { - ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n"); - ImGui::Separator(); - - //static int dummy_i = 0; - //ImGui::Combo("Combo", &dummy_i, "Delete\0Delete harder\0"); - - static bool dont_ask_me_next_time = false; - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0)); - ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time); - ImGui::PopStyleVar(); - - if (ImGui::Button("OK", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); } - ImGui::SameLine(); - if (ImGui::Button("Cancel", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); } - ImGui::EndPopup(); - } - - if (ImGui::Button("Stacked modals..")) - ImGui::OpenPopup("Stacked 1"); - if (ImGui::BeginPopupModal("Stacked 1")) - { - ImGui::Text("Hello from Stacked The First"); - - if (ImGui::Button("Another one..")) - ImGui::OpenPopup("Stacked 2"); - if (ImGui::BeginPopupModal("Stacked 2")) - { - ImGui::Text("Hello from Stacked The Second"); - if (ImGui::Button("Close")) - ImGui::CloseCurrentPopup(); - ImGui::EndPopup(); - } - - if (ImGui::Button("Close")) - ImGui::CloseCurrentPopup(); - ImGui::EndPopup(); - } - - ImGui::TreePop(); - } - } - - if (ImGui::CollapsingHeader("Columns")) - { - // Basic columns - if (ImGui::TreeNode("Basic")) - { - ImGui::Text("Without border:"); - ImGui::Columns(3, "mycolumns3", false); // 3-ways, no border - ImGui::Separator(); - for (int n = 0; n < 14; n++) - { - char label[32]; - sprintf(label, "Item %d", n); - if (ImGui::Selectable(label)) {} - //if (ImGui::Button(label, ImVec2(-1,0))) {} - ImGui::NextColumn(); - } - ImGui::Columns(1); - ImGui::Separator(); - - ImGui::Text("With border:"); - ImGui::Columns(4, "mycolumns"); // 4-ways, with border - ImGui::Separator(); - ImGui::Text("ID"); ImGui::NextColumn(); - ImGui::Text("Name"); ImGui::NextColumn(); - ImGui::Text("Path"); ImGui::NextColumn(); - ImGui::Text("Flags"); ImGui::NextColumn(); - ImGui::Separator(); - const char* names[3] = { "One", "Two", "Three" }; - const char* paths[3] = { "/path/one", "/path/two", "/path/three" }; - static int selected = -1; - for (int i = 0; i < 3; i++) - { - char label[32]; - sprintf(label, "%04d", i); - if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns)) - selected = i; - ImGui::NextColumn(); - ImGui::Text(names[i]); ImGui::NextColumn(); - ImGui::Text(paths[i]); ImGui::NextColumn(); - ImGui::Text("...."); ImGui::NextColumn(); - } - ImGui::Columns(1); - ImGui::Separator(); - ImGui::TreePop(); - } - - // Scrolling columns - /* - if (ImGui::TreeNode("Scrolling")) - { - ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y)); - ImGui::Columns(3); - ImGui::Text("ID"); ImGui::NextColumn(); - ImGui::Text("Name"); ImGui::NextColumn(); - ImGui::Text("Path"); ImGui::NextColumn(); - ImGui::Columns(1); - ImGui::Separator(); - ImGui::EndChild(); - ImGui::BeginChild("##scrollingregion", ImVec2(0, 60)); - ImGui::Columns(3); - for (int i = 0; i < 10; i++) - { - ImGui::Text("%04d", i); ImGui::NextColumn(); - ImGui::Text("Foobar"); ImGui::NextColumn(); - ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn(); - } - ImGui::Columns(1); - ImGui::EndChild(); - ImGui::TreePop(); - } - */ - - // Create multiple items in a same cell before switching to next column - if (ImGui::TreeNode("Mixed items")) - { - ImGui::Columns(3, "mixed"); - ImGui::Separator(); - - ImGui::Text("Hello"); - ImGui::Button("Banana"); - ImGui::NextColumn(); - - ImGui::Text("ImGui"); - ImGui::Button("Apple"); - static float foo = 1.0f; - ImGui::InputFloat("red", &foo, 0.05f, 0, 3); - ImGui::Text("An extra line here."); - ImGui::NextColumn(); - - ImGui::Text("Sailor"); - ImGui::Button("Corniflower"); - static float bar = 1.0f; - ImGui::InputFloat("blue", &bar, 0.05f, 0, 3); - ImGui::NextColumn(); - - if (ImGui::CollapsingHeader("Category A")) ImGui::Text("Blah blah blah"); ImGui::NextColumn(); - if (ImGui::CollapsingHeader("Category B")) ImGui::Text("Blah blah blah"); ImGui::NextColumn(); - if (ImGui::CollapsingHeader("Category C")) ImGui::Text("Blah blah blah"); ImGui::NextColumn(); - ImGui::Columns(1); - ImGui::Separator(); - ImGui::TreePop(); - } - - // Word wrapping - if (ImGui::TreeNode("Word-wrapping")) - { - ImGui::Columns(2, "word-wrapping"); - ImGui::Separator(); - ImGui::TextWrapped("The quick brown fox jumps over the lazy dog."); - ImGui::TextWrapped("Hello Left"); - ImGui::NextColumn(); - ImGui::TextWrapped("The quick brown fox jumps over the lazy dog."); - ImGui::TextWrapped("Hello Right"); - ImGui::Columns(1); - ImGui::Separator(); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Borders")) - { - static bool h_borders = true; - static bool v_borders = true; - ImGui::Checkbox("horizontal", &h_borders); - ImGui::SameLine(); - ImGui::Checkbox("vertical", &v_borders); - ImGui::Columns(4, NULL, v_borders); - if (h_borders) ImGui::Separator(); - for (int i = 0; i < 8; i++) - { - ImGui::Text("%c%c%c", 'a'+i, 'a'+i, 'a'+i); - ImGui::NextColumn(); - } - ImGui::Columns(1); - if (h_borders) ImGui::Separator(); - ImGui::TreePop(); - } - - bool node_open = ImGui::TreeNode("Tree within single cell"); - ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell.\nThere's no storage of state per-cell."); - if (node_open) - { - ImGui::Columns(2, "tree items"); - ImGui::Separator(); - if (ImGui::TreeNode("Hello")) { ImGui::BulletText("Sailor"); ImGui::TreePop(); } ImGui::NextColumn(); - if (ImGui::TreeNode("Bonjour")) { ImGui::BulletText("Marin"); ImGui::TreePop(); } ImGui::NextColumn(); - ImGui::Columns(1); - ImGui::Separator(); - ImGui::TreePop(); - } - } - - if (ImGui::CollapsingHeader("Filtering")) - { - static ImGuiTextFilter filter; - ImGui::Text("Filter usage:\n" - " \"\" display all lines\n" - " \"xxx\" display lines containing \"xxx\"\n" - " \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n" - " \"-xxx\" hide lines containing \"xxx\""); - filter.Draw(); - const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" }; - for (int i = 0; i < IM_ARRAYSIZE(lines); i++) - if (filter.PassFilter(lines[i])) - ImGui::BulletText("%s", lines[i]); - } - - if (ImGui::CollapsingHeader("Keyboard, Mouse & Focus")) - { - if (ImGui::TreeNode("Tabbing")) - { - ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields."); - static char buf[32] = "dummy"; - ImGui::InputText("1", buf, IM_ARRAYSIZE(buf)); - ImGui::InputText("2", buf, IM_ARRAYSIZE(buf)); - ImGui::InputText("3", buf, IM_ARRAYSIZE(buf)); - ImGui::PushAllowKeyboardFocus(false); - ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf)); - //ImGui::SameLine(); ShowHelperMarker("Use ImGui::PushAllowKeyboardFocus(bool)\nto disable tabbing through certain widgets."); - ImGui::PopAllowKeyboardFocus(); - ImGui::InputText("5", buf, IM_ARRAYSIZE(buf)); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Focus from code")) - { - bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine(); - bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine(); - bool focus_3 = ImGui::Button("Focus on 3"); - int has_focus = 0; - static char buf[128] = "click on a button to set focus"; - - if (focus_1) ImGui::SetKeyboardFocusHere(); - ImGui::InputText("1", buf, IM_ARRAYSIZE(buf)); - if (ImGui::IsItemActive()) has_focus = 1; - - if (focus_2) ImGui::SetKeyboardFocusHere(); - ImGui::InputText("2", buf, IM_ARRAYSIZE(buf)); - if (ImGui::IsItemActive()) has_focus = 2; - - ImGui::PushAllowKeyboardFocus(false); - if (focus_3) ImGui::SetKeyboardFocusHere(); - ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf)); - if (ImGui::IsItemActive()) has_focus = 3; - ImGui::PopAllowKeyboardFocus(); - if (has_focus) - ImGui::Text("Item with focus: %d", has_focus); - else - ImGui::Text("Item with focus: "); - ImGui::TextWrapped("Cursor & selection are preserved when refocusing last used item in code."); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Dragging")) - { - ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget."); - ImGui::Button("Drag Me"); - if (ImGui::IsItemActive()) - { - // Draw a line between the button and the mouse cursor - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - draw_list->PushClipRectFullScreen(); - draw_list->AddLine(ImGui::CalcItemRectClosestPoint(ImGui::GetIO().MousePos, true, -2.0f), ImGui::GetIO().MousePos, ImColor(ImGui::GetStyle().Colors[ImGuiCol_Button]), 4.0f); - draw_list->PopClipRect(); - ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f); - ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0); - ImVec2 mouse_delta = ImGui::GetIO().MouseDelta; - ImGui::SameLine(); ImGui::Text("Raw (%.1f, %.1f), WithLockThresold (%.1f, %.1f), MouseDelta (%.1f, %.1f)", value_raw.x, value_raw.y, value_with_lock_threshold.x, value_with_lock_threshold.y, mouse_delta.x, mouse_delta.y); - } - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Keyboard & Mouse State")) - { - ImGuiIO& io = ImGui::GetIO(); - - ImGui::Text("MousePos: (%g, %g)", io.MousePos.x, io.MousePos.y); - ImGui::Text("Mouse down:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); } - ImGui::Text("Mouse clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } - ImGui::Text("Mouse dbl-clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } - ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } - ImGui::Text("MouseWheel: %.1f", io.MouseWheel); - - ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]); } - ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } - ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } - ImGui::Text("KeyMods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); - - ImGui::Text("WantCaptureMouse: %s", io.WantCaptureMouse ? "true" : "false"); - ImGui::Text("WantCaptureKeyboard: %s", io.WantCaptureKeyboard ? "true" : "false"); - ImGui::Text("WantTextInput: %s", io.WantTextInput ? "true" : "false"); - - ImGui::Button("Hovering me sets the\nkeyboard capture flag"); - if (ImGui::IsItemHovered()) - ImGui::CaptureKeyboardFromApp(true); - ImGui::SameLine(); - ImGui::Button("Holding me clears the\nthe keyboard capture flag"); - if (ImGui::IsItemActive()) - ImGui::CaptureKeyboardFromApp(false); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Mouse cursors")) - { - ImGui::TextWrapped("Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. You can also set io.MouseDrawCursor to ask ImGui to render the cursor for you in software."); - ImGui::Checkbox("io.MouseDrawCursor", &ImGui::GetIO().MouseDrawCursor); - ImGui::Text("Hover to see mouse cursors:"); - for (int i = 0; i < ImGuiMouseCursor_Count_; i++) - { - char label[32]; - sprintf(label, "Mouse cursor %d", i); - ImGui::Bullet(); ImGui::Selectable(label, false); - if (ImGui::IsItemHovered()) - ImGui::SetMouseCursor(i); - } - ImGui::TreePop(); - } - } - - ImGui::End(); -} - -void ImGui::ShowStyleEditor(ImGuiStyle* ref) -{ - ImGuiStyle& style = ImGui::GetStyle(); - - // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to the default style) - const ImGuiStyle default_style; // Default style - if (ImGui::Button("Revert Style")) - style = ref ? *ref : default_style; - - if (ref) - { - ImGui::SameLine(); - if (ImGui::Button("Save Style")) - *ref = style; - } - - ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.55f); - - if (ImGui::TreeNode("Rendering")) - { - ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines); - ImGui::Checkbox("Anti-aliased shapes", &style.AntiAliasedShapes); - ImGui::PushItemWidth(100); - ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, NULL, 2.0f); - if (style.CurveTessellationTol < 0.0f) style.CurveTessellationTol = 0.10f; - ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero. - ImGui::PopItemWidth(); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Settings")) - { - ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f"); - ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 16.0f, "%.0f"); - ImGui::SliderFloat("ChildWindowRounding", &style.ChildWindowRounding, 0.0f, 16.0f, "%.0f"); - ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f"); - ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 16.0f, "%.0f"); - ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f"); - ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f"); - ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f"); - ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f"); - ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f"); - ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 16.0f, "%.0f"); - ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f"); - ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 16.0f, "%.0f"); - ImGui::Text("Alignment"); - ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f"); - ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); ShowHelpMarker("Alignment applies when a button is larger than its text content."); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Colors")) - { - static int output_dest = 0; - static bool output_only_modified = false; - if (ImGui::Button("Copy Colors")) - { - if (output_dest == 0) - ImGui::LogToClipboard(); - else - ImGui::LogToTTY(); - ImGui::LogText("ImGuiStyle& style = ImGui::GetStyle();" IM_NEWLINE); - for (int i = 0; i < ImGuiCol_COUNT; i++) - { - const ImVec4& col = style.Colors[i]; - const char* name = ImGui::GetStyleColName(i); - if (!output_only_modified || memcmp(&col, (ref ? &ref->Colors[i] : &default_style.Colors[i]), sizeof(ImVec4)) != 0) - ImGui::LogText("style.Colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE, name, 22 - (int)strlen(name), "", col.x, col.y, col.z, col.w); - } - ImGui::LogFinish(); - } - ImGui::SameLine(); ImGui::PushItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0"); ImGui::PopItemWidth(); - ImGui::SameLine(); ImGui::Checkbox("Only Modified Fields", &output_only_modified); - - static ImGuiColorEditMode edit_mode = ImGuiColorEditMode_RGB; - ImGui::RadioButton("RGB", &edit_mode, ImGuiColorEditMode_RGB); - ImGui::SameLine(); - ImGui::RadioButton("HSV", &edit_mode, ImGuiColorEditMode_HSV); - ImGui::SameLine(); - ImGui::RadioButton("HEX", &edit_mode, ImGuiColorEditMode_HEX); - //ImGui::Text("Tip: Click on colored square to change edit mode."); - - static ImGuiTextFilter filter; - filter.Draw("Filter colors", 200); - - ImGui::BeginChild("#colors", ImVec2(0, 300), true, ImGuiWindowFlags_AlwaysVerticalScrollbar); - ImGui::PushItemWidth(-160); - ImGui::ColorEditMode(edit_mode); - for (int i = 0; i < ImGuiCol_COUNT; i++) - { - const char* name = ImGui::GetStyleColName(i); - if (!filter.PassFilter(name)) - continue; - ImGui::PushID(i); - ImGui::ColorEdit4(name, (float*)&style.Colors[i], true); - if (memcmp(&style.Colors[i], (ref ? &ref->Colors[i] : &default_style.Colors[i]), sizeof(ImVec4)) != 0) - { - ImGui::SameLine(); if (ImGui::Button("Revert")) style.Colors[i] = ref ? ref->Colors[i] : default_style.Colors[i]; - if (ref) { ImGui::SameLine(); if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i]; } - } - ImGui::PopID(); - } - ImGui::PopItemWidth(); - ImGui::EndChild(); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Fonts", "Fonts (%d)", ImGui::GetIO().Fonts->Fonts.Size)) - { - ImGui::SameLine(); ShowHelpMarker("Tip: Load fonts with io.Fonts->AddFontFromFileTTF()\nbefore calling io.Fonts->GetTex* functions."); - ImFontAtlas* atlas = ImGui::GetIO().Fonts; - if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight)) - { - ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128)); - ImGui::TreePop(); - } - ImGui::PushItemWidth(100); - for (int i = 0; i < atlas->Fonts.Size; i++) - { - ImFont* font = atlas->Fonts[i]; - ImGui::BulletText("Font %d: \'%s\', %.2f px, %d glyphs", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size); - ImGui::TreePush((void*)(intptr_t)i); - ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) ImGui::GetIO().FontDefault = font; - ImGui::PushFont(font); - ImGui::Text("The quick brown fox jumps over the lazy dog"); - ImGui::PopFont(); - if (ImGui::TreeNode("Details")) - { - ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); // Scale only this font - ImGui::SameLine(); ShowHelpMarker("Note than the default embedded font is NOT meant to be scaled.\n\nFont are currently rendered into bitmaps at a given size at the time of building the atlas. You may oversample them to get some flexibility with scaling. You can also render at multiple sizes and select which one to use at runtime.\n\n(Glimmer of hope: the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)"); - ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent); - ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar); - ImGui::Text("Texture surface: %d pixels (approx)", font->MetricsTotalSurface); - for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) - { - ImFontConfig* cfg = &font->ConfigData[config_i]; - ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH); - } - if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size)) - { - // Display all glyphs of the fonts in separate pages of 256 characters - const ImFont::Glyph* glyph_fallback = font->FallbackGlyph; // Forcefully/dodgily make FindGlyph() return NULL on fallback, which isn't the default behavior. - font->FallbackGlyph = NULL; - for (int base = 0; base < 0x10000; base += 256) - { - int count = 0; - for (int n = 0; n < 256; n++) - count += font->FindGlyph((ImWchar)(base + n)) ? 1 : 0; - if (count > 0 && ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base+255, count, count > 1 ? "glyphs" : "glyph")) - { - float cell_spacing = style.ItemSpacing.y; - ImVec2 cell_size(font->FontSize * 1, font->FontSize * 1); - ImVec2 base_pos = ImGui::GetCursorScreenPos(); - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - for (int n = 0; n < 256; n++) - { - ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size.x + cell_spacing), base_pos.y + (n / 16) * (cell_size.y + cell_spacing)); - ImVec2 cell_p2(cell_p1.x + cell_size.x, cell_p1.y + cell_size.y); - const ImFont::Glyph* glyph = font->FindGlyph((ImWchar)(base+n));; - draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255,255,255,100) : IM_COL32(255,255,255,50)); - font->RenderChar(draw_list, cell_size.x, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), (ImWchar)(base+n)); // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions available to generate a string. - if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2)) - { - ImGui::BeginTooltip(); - ImGui::Text("Codepoint: U+%04X", base+n); - ImGui::Separator(); - ImGui::Text("XAdvance+1: %.1f", glyph->XAdvance); - ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1); - ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1); - ImGui::EndTooltip(); - } - } - ImGui::Dummy(ImVec2((cell_size.x + cell_spacing) * 16, (cell_size.y + cell_spacing) * 16)); - ImGui::TreePop(); - } - } - font->FallbackGlyph = glyph_fallback; - ImGui::TreePop(); - } - ImGui::TreePop(); - } - ImGui::TreePop(); - } - static float window_scale = 1.0f; - ImGui::DragFloat("this window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale only this window - ImGui::DragFloat("global scale", &ImGui::GetIO().FontGlobalScale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale everything - ImGui::PopItemWidth(); - ImGui::SetWindowFontScale(window_scale); - ImGui::TreePop(); - } - - ImGui::PopItemWidth(); -} - -// Demonstrate creating a fullscreen menu bar and populating it. -static void ShowExampleAppMainMenuBar() -{ - if (ImGui::BeginMainMenuBar()) - { - if (ImGui::BeginMenu("File")) - { - ShowExampleMenuFile(); - ImGui::EndMenu(); - } - if (ImGui::BeginMenu("Edit")) - { - if (ImGui::MenuItem("Undo", "CTRL+Z")) {} - if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item - ImGui::Separator(); - if (ImGui::MenuItem("Cut", "CTRL+X")) {} - if (ImGui::MenuItem("Copy", "CTRL+C")) {} - if (ImGui::MenuItem("Paste", "CTRL+V")) {} - ImGui::EndMenu(); - } - ImGui::EndMainMenuBar(); - } -} - -static void ShowExampleMenuFile() -{ - ImGui::MenuItem("(dummy menu)", NULL, false, false); - if (ImGui::MenuItem("New")) {} - if (ImGui::MenuItem("Open", "Ctrl+O")) {} - if (ImGui::BeginMenu("Open Recent")) - { - ImGui::MenuItem("fish_hat.c"); - ImGui::MenuItem("fish_hat.inl"); - ImGui::MenuItem("fish_hat.h"); - if (ImGui::BeginMenu("More..")) - { - ImGui::MenuItem("Hello"); - ImGui::MenuItem("Sailor"); - if (ImGui::BeginMenu("Recurse..")) - { - ShowExampleMenuFile(); - ImGui::EndMenu(); - } - ImGui::EndMenu(); - } - ImGui::EndMenu(); - } - if (ImGui::MenuItem("Save", "Ctrl+S")) {} - if (ImGui::MenuItem("Save As..")) {} - ImGui::Separator(); - if (ImGui::BeginMenu("Options")) - { - static bool enabled = true; - ImGui::MenuItem("Enabled", "", &enabled); - ImGui::BeginChild("child", ImVec2(0, 60), true); - for (int i = 0; i < 10; i++) - ImGui::Text("Scrolling Text %d", i); - ImGui::EndChild(); - static float f = 0.5f; - static int n = 0; - ImGui::SliderFloat("Value", &f, 0.0f, 1.0f); - ImGui::InputFloat("Input", &f, 0.1f); - ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0"); - ImGui::EndMenu(); - } - if (ImGui::BeginMenu("Colors")) - { - for (int i = 0; i < ImGuiCol_COUNT; i++) - ImGui::MenuItem(ImGui::GetStyleColName((ImGuiCol)i)); - ImGui::EndMenu(); - } - if (ImGui::BeginMenu("Disabled", false)) // Disabled - { - IM_ASSERT(0); - } - if (ImGui::MenuItem("Checked", NULL, true)) {} - if (ImGui::MenuItem("Quit", "Alt+F4")) {} -} - -// Demonstrate creating a window which gets auto-resized according to its content. -static void ShowExampleAppAutoResize(bool* p_open) -{ - if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize)) - { - ImGui::End(); - return; - } - - static int lines = 10; - ImGui::Text("Window will resize every-frame to the size of its content.\nNote that you probably don't want to query the window size to\noutput your content because that would create a feedback loop."); - ImGui::SliderInt("Number of lines", &lines, 1, 20); - for (int i = 0; i < lines; i++) - ImGui::Text("%*sThis is line %d", i*4, "", i); // Pad with space to extend size horizontally - ImGui::End(); -} - -// Demonstrate creating a window with custom resize constraints. -static void ShowExampleAppConstrainedResize(bool* p_open) -{ - struct CustomConstraints // Helper functions to demonstrate programmatic constraints - { - static void Square(ImGuiSizeConstraintCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); } - static void Step(ImGuiSizeConstraintCallbackData* data) { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); } - }; - - static int type = 0; - if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Vertical only - if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Horizontal only - if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100 - if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(300, 0), ImVec2(400, FLT_MAX)); // Width 300-400 - if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square - if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);// Fixed Step - - if (ImGui::Begin("Example: Constrained Resize", p_open)) - { - const char* desc[] = - { - "Resize vertical only", - "Resize horizontal only", - "Width > 100, Height > 100", - "Width 300-400", - "Custom: Always Square", - "Custom: Fixed Steps (100)", - }; - ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc)); - if (ImGui::Button("200x200")) ImGui::SetWindowSize(ImVec2(200,200)); ImGui::SameLine(); - if (ImGui::Button("500x500")) ImGui::SetWindowSize(ImVec2(500,500)); ImGui::SameLine(); - if (ImGui::Button("800x200")) ImGui::SetWindowSize(ImVec2(800,200)); - for (int i = 0; i < 10; i++) - ImGui::Text("Hello, sailor! Making this line long enough for the example."); - } - ImGui::End(); -} - -// Demonstrate creating a simple static window with no decoration. -static void ShowExampleAppFixedOverlay(bool* p_open) -{ - ImGui::SetNextWindowPos(ImVec2(10,10)); - if (!ImGui::Begin("Example: Fixed Overlay", p_open, ImVec2(0,0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings)) - { - ImGui::End(); - return; - } - ImGui::Text("Simple overlay\non the top-left side of the screen."); - ImGui::Separator(); - ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y); - ImGui::End(); -} - -// Demonstrate using "##" and "###" in identifiers to manipulate ID generation. -// Read section "How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs." about ID. -static void ShowExampleAppManipulatingWindowTitle(bool*) -{ - // By default, Windows are uniquely identified by their title. - // You can use the "##" and "###" markers to manipulate the display/ID. - - // Using "##" to display same title but have unique identifier. - ImGui::SetNextWindowPos(ImVec2(100,100), ImGuiSetCond_FirstUseEver); - ImGui::Begin("Same title as another window##1"); - ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique."); - ImGui::End(); - - ImGui::SetNextWindowPos(ImVec2(100,200), ImGuiSetCond_FirstUseEver); - ImGui::Begin("Same title as another window##2"); - ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique."); - ImGui::End(); - - // Using "###" to display a changing title but keep a static identifier "AnimatedTitle" - char buf[128]; - sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime()/0.25f)&3], rand()); - ImGui::SetNextWindowPos(ImVec2(100,300), ImGuiSetCond_FirstUseEver); - ImGui::Begin(buf); - ImGui::Text("This window has a changing title."); - ImGui::End(); -} - -// Demonstrate using the low-level ImDrawList to draw custom shapes. -static void ShowExampleAppCustomRendering(bool* p_open) -{ - ImGui::SetNextWindowSize(ImVec2(350,560), ImGuiSetCond_FirstUseEver); - if (!ImGui::Begin("Example: Custom rendering", p_open)) - { - ImGui::End(); - return; - } - - // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of overloaded operators, etc. - // Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your types and ImVec2/ImVec4. - // ImGui defines overloaded operators but they are internal to imgui.cpp and not exposed outside (to avoid messing with your types) - // In this example we are not using the maths operators! - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - - // Primitives - ImGui::Text("Primitives"); - static float sz = 36.0f; - static ImVec4 col = ImVec4(1.0f,1.0f,0.4f,1.0f); - ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f"); - ImGui::ColorEdit3("Color", &col.x); - { - const ImVec2 p = ImGui::GetCursorScreenPos(); - const ImU32 col32 = ImColor(col); - float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f; - for (int n = 0; n < 2; n++) - { - float thickness = (n == 0) ? 1.0f : 4.0f; - draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 20, thickness); x += sz+spacing; - draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 0.0f, ~0, thickness); x += sz+spacing; - draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ~0, thickness); x += sz+spacing; - draw_list->AddTriangle(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32, thickness); x += sz+spacing; - draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y ), col32, thickness); x += sz+spacing; - draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, thickness); x += sz+spacing; - draw_list->AddLine(ImVec2(x, y), ImVec2(x, y+sz), col32, thickness); x += spacing; - draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x+sz*1.3f,y+sz*0.3f), ImVec2(x+sz-sz*1.3f,y+sz-sz*0.3f), ImVec2(x+sz, y+sz), col32, thickness); - x = p.x + 4; - y += sz+spacing; - } - draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 32); x += sz+spacing; - draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32); x += sz+spacing; - draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f); x += sz+spacing; - draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32); x += sz+spacing; - draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x+sz, y+sz), ImColor(0,0,0), ImColor(255,0,0), ImColor(255,255,0), ImColor(0,255,0)); - ImGui::Dummy(ImVec2((sz+spacing)*8, (sz+spacing)*3)); - } - ImGui::Separator(); - { - static ImVector points; - static bool adding_line = false; - ImGui::Text("Canvas example"); - if (ImGui::Button("Clear")) points.clear(); - if (points.Size >= 2) { ImGui::SameLine(); if (ImGui::Button("Undo")) { points.pop_back(); points.pop_back(); } } - ImGui::Text("Left-click and drag to add lines,\nRight-click to undo"); - - // Here we are using InvisibleButton() as a convenience to 1) advance the cursor and 2) allows us to use IsItemHovered() - // However you can draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() and SetCursorPos(). - // If you only use the ImDrawList API, you can notify the owner window of its extends by using SetCursorPos(max). - ImVec2 canvas_pos = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates! - ImVec2 canvas_size = ImGui::GetContentRegionAvail(); // Resize canvas to what's available - if (canvas_size.x < 50.0f) canvas_size.x = 50.0f; - if (canvas_size.y < 50.0f) canvas_size.y = 50.0f; - draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), ImColor(50,50,50), ImColor(50,50,60), ImColor(60,60,70), ImColor(50,50,60)); - draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), ImColor(255,255,255)); - - bool adding_preview = false; - ImGui::InvisibleButton("canvas", canvas_size); - ImVec2 mouse_pos_in_canvas = ImVec2(ImGui::GetIO().MousePos.x - canvas_pos.x, ImGui::GetIO().MousePos.y - canvas_pos.y); - if (adding_line) - { - adding_preview = true; - points.push_back(mouse_pos_in_canvas); - if (!ImGui::GetIO().MouseDown[0]) - adding_line = adding_preview = false; - } - if (ImGui::IsItemHovered()) - { - if (!adding_line && ImGui::IsMouseClicked(0)) - { - points.push_back(mouse_pos_in_canvas); - adding_line = true; - } - if (ImGui::IsMouseClicked(1) && !points.empty()) - { - adding_line = adding_preview = false; - points.pop_back(); - points.pop_back(); - } - } - draw_list->PushClipRect(canvas_pos, ImVec2(canvas_pos.x+canvas_size.x, canvas_pos.y+canvas_size.y)); // clip lines within the canvas (if we resize it, etc.) - for (int i = 0; i < points.Size - 1; i += 2) - draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), ImVec2(canvas_pos.x + points[i+1].x, canvas_pos.y + points[i+1].y), IM_COL32(255,255,0,255), 2.0f); - draw_list->PopClipRect(); - if (adding_preview) - points.pop_back(); - } - ImGui::End(); -} - -// Demonstrating creating a simple console window, with scrolling, filtering, completion and history. -// For the console example, here we are using a more C++ like approach of declaring a class to hold the data and the functions. -struct ExampleAppConsole -{ - char InputBuf[256]; - ImVector Items; - bool ScrollToBottom; - ImVector History; - int HistoryPos; // -1: new line, 0..History.Size-1 browsing history. - ImVector Commands; - - ExampleAppConsole() - { - ClearLog(); - memset(InputBuf, 0, sizeof(InputBuf)); - HistoryPos = -1; - Commands.push_back("HELP"); - Commands.push_back("HISTORY"); - Commands.push_back("CLEAR"); - Commands.push_back("CLASSIFY"); // "classify" is here to provide an example of "C"+[tab] completing to "CL" and displaying matches. - AddLog("Welcome to ImGui!"); - } - ~ExampleAppConsole() - { - ClearLog(); - for (int i = 0; i < History.Size; i++) - free(History[i]); - } - - // Portable helpers - static int Stricmp(const char* str1, const char* str2) { int d; while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } return d; } - static int Strnicmp(const char* str1, const char* str2, int n) { int d = 0; while (n > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; n--; } return d; } - static char* Strdup(const char *str) { size_t len = strlen(str) + 1; void* buff = malloc(len); return (char*)memcpy(buff, (const void*)str, len); } - - void ClearLog() - { - for (int i = 0; i < Items.Size; i++) - free(Items[i]); - Items.clear(); - ScrollToBottom = true; - } - - void AddLog(const char* fmt, ...) IM_PRINTFARGS(2) - { - char buf[1024]; - va_list args; - va_start(args, fmt); - vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args); - buf[IM_ARRAYSIZE(buf)-1] = 0; - va_end(args); - Items.push_back(Strdup(buf)); - ScrollToBottom = true; - } - - void Draw(const char* title, bool* p_open) - { - ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiSetCond_FirstUseEver); - if (!ImGui::Begin(title, p_open)) - { - ImGui::End(); - return; - } - - ImGui::TextWrapped("This example implements a console with basic coloring, completion and history. A more elaborate implementation may want to store entries along with extra data such as timestamp, emitter, etc."); - ImGui::TextWrapped("Enter 'HELP' for help, press TAB to use text completion."); - - // TODO: display items starting from the bottom - - if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine(); - if (ImGui::SmallButton("Add Dummy Error")) AddLog("[error] something went wrong"); ImGui::SameLine(); - if (ImGui::SmallButton("Clear")) ClearLog(); ImGui::SameLine(); - if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom = true; - //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); } - - ImGui::Separator(); - - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0)); - static ImGuiTextFilter filter; - filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180); - ImGui::PopStyleVar(); - ImGui::Separator(); - - ImGui::BeginChild("ScrollingRegion", ImVec2(0,-ImGui::GetItemsLineHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar); - if (ImGui::BeginPopupContextWindow()) - { - if (ImGui::Selectable("Clear")) ClearLog(); - ImGui::EndPopup(); - } - - // Display every line as a separate entry so we can change their color or add custom widgets. If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end()); - // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping to only process visible items. - // You can seek and display only the lines that are visible using the ImGuiListClipper helper, if your elements are evenly spaced and you have cheap random access to the elements. - // To use the clipper we could replace the 'for (int i = 0; i < Items.Size; i++)' loop with: - // ImGuiListClipper clipper(Items.Size); - // while (clipper.Step()) - // for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) - // However take note that you can not use this code as is if a filter is active because it breaks the 'cheap random-access' property. We would need random-access on the post-filtered list. - // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices that passed the filtering test, recomputing this array when user changes the filter, - // and appending newly elements as they are inserted. This is left as a task to the user until we can manage to improve this example code! - // If your items are of variable size you may want to implement code similar to what ImGuiListClipper does. Or split your data into fixed height items to allow random-seeking into your list. - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing - for (int i = 0; i < Items.Size; i++) - { - const char* item = Items[i]; - if (!filter.PassFilter(item)) - continue; - ImVec4 col = ImVec4(1.0f,1.0f,1.0f,1.0f); // A better implementation may store a type per-item. For the sample let's just parse the text. - if (strstr(item, "[error]")) col = ImColor(1.0f,0.4f,0.4f,1.0f); - else if (strncmp(item, "# ", 2) == 0) col = ImColor(1.0f,0.78f,0.58f,1.0f); - ImGui::PushStyleColor(ImGuiCol_Text, col); - ImGui::TextUnformatted(item); - ImGui::PopStyleColor(); - } - if (ScrollToBottom) - ImGui::SetScrollHere(); - ScrollToBottom = false; - ImGui::PopStyleVar(); - ImGui::EndChild(); - ImGui::Separator(); - - // Command-line - if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this)) - { - char* input_end = InputBuf+strlen(InputBuf); - while (input_end > InputBuf && input_end[-1] == ' ') input_end--; *input_end = 0; - if (InputBuf[0]) - ExecCommand(InputBuf); - strcpy(InputBuf, ""); - } - - // Demonstrate keeping auto focus on the input box - if (ImGui::IsItemHovered() || (ImGui::IsRootWindowOrAnyChildFocused() && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0))) - ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget - - ImGui::End(); - } - - void ExecCommand(const char* command_line) - { - AddLog("# %s\n", command_line); - - // Insert into history. First find match and delete it so it can be pushed to the back. This isn't trying to be smart or optimal. - HistoryPos = -1; - for (int i = History.Size-1; i >= 0; i--) - if (Stricmp(History[i], command_line) == 0) - { - free(History[i]); - History.erase(History.begin() + i); - break; - } - History.push_back(Strdup(command_line)); - - // Process command - if (Stricmp(command_line, "CLEAR") == 0) - { - ClearLog(); - } - else if (Stricmp(command_line, "HELP") == 0) - { - AddLog("Commands:"); - for (int i = 0; i < Commands.Size; i++) - AddLog("- %s", Commands[i]); - } - else if (Stricmp(command_line, "HISTORY") == 0) - { - for (int i = History.Size >= 10 ? History.Size - 10 : 0; i < History.Size; i++) - AddLog("%3d: %s\n", i, History[i]); - } - else - { - AddLog("Unknown command: '%s'\n", command_line); - } - } - - static int TextEditCallbackStub(ImGuiTextEditCallbackData* data) // In C++11 you are better off using lambdas for this sort of forwarding callbacks - { - ExampleAppConsole* console = (ExampleAppConsole*)data->UserData; - return console->TextEditCallback(data); - } - - int TextEditCallback(ImGuiTextEditCallbackData* data) - { - //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd); - switch (data->EventFlag) - { - case ImGuiInputTextFlags_CallbackCompletion: - { - // Example of TEXT COMPLETION - - // Locate beginning of current word - const char* word_end = data->Buf + data->CursorPos; - const char* word_start = word_end; - while (word_start > data->Buf) - { - const char c = word_start[-1]; - if (c == ' ' || c == '\t' || c == ',' || c == ';') - break; - word_start--; - } - - // Build a list of candidates - ImVector candidates; - for (int i = 0; i < Commands.Size; i++) - if (Strnicmp(Commands[i], word_start, (int)(word_end-word_start)) == 0) - candidates.push_back(Commands[i]); - - if (candidates.Size == 0) - { - // No match - AddLog("No match for \"%.*s\"!\n", (int)(word_end-word_start), word_start); - } - else if (candidates.Size == 1) - { - // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing - data->DeleteChars((int)(word_start-data->Buf), (int)(word_end-word_start)); - data->InsertChars(data->CursorPos, candidates[0]); - data->InsertChars(data->CursorPos, " "); - } - else - { - // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY" - int match_len = (int)(word_end - word_start); - for (;;) - { - int c = 0; - bool all_candidates_matches = true; - for (int i = 0; i < candidates.Size && all_candidates_matches; i++) - if (i == 0) - c = toupper(candidates[i][match_len]); - else if (c == 0 || c != toupper(candidates[i][match_len])) - all_candidates_matches = false; - if (!all_candidates_matches) - break; - match_len++; - } - - if (match_len > 0) - { - data->DeleteChars((int)(word_start - data->Buf), (int)(word_end-word_start)); - data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len); - } - - // List matches - AddLog("Possible matches:\n"); - for (int i = 0; i < candidates.Size; i++) - AddLog("- %s\n", candidates[i]); - } - - break; - } - case ImGuiInputTextFlags_CallbackHistory: - { - // Example of HISTORY - const int prev_history_pos = HistoryPos; - if (data->EventKey == ImGuiKey_UpArrow) - { - if (HistoryPos == -1) - HistoryPos = History.Size - 1; - else if (HistoryPos > 0) - HistoryPos--; - } - else if (data->EventKey == ImGuiKey_DownArrow) - { - if (HistoryPos != -1) - if (++HistoryPos >= History.Size) - HistoryPos = -1; - } - - // A better implementation would preserve the data on the current input line along with cursor position. - if (prev_history_pos != HistoryPos) - { - data->CursorPos = data->SelectionStart = data->SelectionEnd = data->BufTextLen = (int)snprintf(data->Buf, (size_t)data->BufSize, "%s", (HistoryPos >= 0) ? History[HistoryPos] : ""); - data->BufDirty = true; - } - } - } - return 0; - } -}; - -static void ShowExampleAppConsole(bool* p_open) -{ - static ExampleAppConsole console; - console.Draw("Example: Console", p_open); -} - -// Usage: -// static ExampleAppLog my_log; -// my_log.AddLog("Hello %d world\n", 123); -// my_log.Draw("title"); -struct ExampleAppLog -{ - ImGuiTextBuffer Buf; - ImGuiTextFilter Filter; - ImVector LineOffsets; // Index to lines offset - bool ScrollToBottom; - - void Clear() { Buf.clear(); LineOffsets.clear(); } - - void AddLog(const char* fmt, ...) IM_PRINTFARGS(2) - { - int old_size = Buf.size(); - va_list args; - va_start(args, fmt); - Buf.appendv(fmt, args); - va_end(args); - for (int new_size = Buf.size(); old_size < new_size; old_size++) - if (Buf[old_size] == '\n') - LineOffsets.push_back(old_size); - ScrollToBottom = true; - } - - void Draw(const char* title, bool* p_open = NULL) - { - ImGui::SetNextWindowSize(ImVec2(500,400), ImGuiSetCond_FirstUseEver); - ImGui::Begin(title, p_open); - if (ImGui::Button("Clear")) Clear(); - ImGui::SameLine(); - bool copy = ImGui::Button("Copy"); - ImGui::SameLine(); - Filter.Draw("Filter", -100.0f); - ImGui::Separator(); - ImGui::BeginChild("scrolling", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar); - if (copy) ImGui::LogToClipboard(); - - if (Filter.IsActive()) - { - const char* buf_begin = Buf.begin(); - const char* line = buf_begin; - for (int line_no = 0; line != NULL; line_no++) - { - const char* line_end = (line_no < LineOffsets.Size) ? buf_begin + LineOffsets[line_no] : NULL; - if (Filter.PassFilter(line, line_end)) - ImGui::TextUnformatted(line, line_end); - line = line_end && line_end[1] ? line_end + 1 : NULL; - } - } - else - { - ImGui::TextUnformatted(Buf.begin()); - } - - if (ScrollToBottom) - ImGui::SetScrollHere(1.0f); - ScrollToBottom = false; - ImGui::EndChild(); - ImGui::End(); - } -}; - -// Demonstrate creating a simple log window with basic filtering. -static void ShowExampleAppLog(bool* p_open) -{ - static ExampleAppLog log; - - // Demo fill - static float last_time = -1.0f; - float time = ImGui::GetTime(); - if (time - last_time >= 0.3f) - { - const char* random_words[] = { "system", "info", "warning", "error", "fatal", "notice", "log" }; - log.AddLog("[%s] Hello, time is %.1f, rand() %d\n", random_words[rand() % IM_ARRAYSIZE(random_words)], time, (int)rand()); - last_time = time; - } - - log.Draw("Example: Log", p_open); -} - -// Demonstrate create a window with multiple child windows. -static void ShowExampleAppLayout(bool* p_open) -{ - ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiSetCond_FirstUseEver); - if (ImGui::Begin("Example: Layout", p_open, ImGuiWindowFlags_MenuBar)) - { - if (ImGui::BeginMenuBar()) - { - if (ImGui::BeginMenu("File")) - { - if (ImGui::MenuItem("Close")) *p_open = false; - ImGui::EndMenu(); - } - ImGui::EndMenuBar(); - } - - // left - static int selected = 0; - ImGui::BeginChild("left pane", ImVec2(150, 0), true); - for (int i = 0; i < 100; i++) - { - char label[128]; - sprintf(label, "MyObject %d", i); - if (ImGui::Selectable(label, selected == i)) - selected = i; - } - ImGui::EndChild(); - ImGui::SameLine(); - - // right - ImGui::BeginGroup(); - ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetItemsLineHeightWithSpacing())); // Leave room for 1 line below us - ImGui::Text("MyObject: %d", selected); - ImGui::Separator(); - ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "); - ImGui::EndChild(); - ImGui::BeginChild("buttons"); - if (ImGui::Button("Revert")) {} - ImGui::SameLine(); - if (ImGui::Button("Save")) {} - ImGui::EndChild(); - ImGui::EndGroup(); - } - ImGui::End(); -} - -// Demonstrate create a simple property editor. -static void ShowExampleAppPropertyEditor(bool* p_open) -{ - ImGui::SetNextWindowSize(ImVec2(430,450), ImGuiSetCond_FirstUseEver); - if (!ImGui::Begin("Example: Property editor", p_open)) - { - ImGui::End(); - return; - } - - ShowHelpMarker("This example shows how you may implement a property editor using two columns.\nAll objects/fields data are dummies here.\nRemember that in many simple cases, you can use ImGui::SameLine(xxx) to position\nyour cursor horizontally instead of using the Columns() API."); - - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2,2)); - ImGui::Columns(2); - ImGui::Separator(); - - struct funcs - { - static void ShowDummyObject(const char* prefix, int uid) - { - ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID. - ImGui::AlignFirstTextHeightToWidgets(); // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high. - bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid); - ImGui::NextColumn(); - ImGui::AlignFirstTextHeightToWidgets(); - ImGui::Text("my sailor is rich"); - ImGui::NextColumn(); - if (node_open) - { - static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f }; - for (int i = 0; i < 8; i++) - { - ImGui::PushID(i); // Use field index as identifier. - if (i < 2) - { - ShowDummyObject("Child", 424242); - } - else - { - ImGui::AlignFirstTextHeightToWidgets(); - // Here we use a Selectable (instead of Text) to highlight on hover - //ImGui::Text("Field_%d", i); - char label[32]; - sprintf(label, "Field_%d", i); - ImGui::Bullet(); - ImGui::Selectable(label); - ImGui::NextColumn(); - ImGui::PushItemWidth(-1); - if (i >= 5) - ImGui::InputFloat("##value", &dummy_members[i], 1.0f); - else - ImGui::DragFloat("##value", &dummy_members[i], 0.01f); - ImGui::PopItemWidth(); - ImGui::NextColumn(); - } - ImGui::PopID(); - } - ImGui::TreePop(); - } - ImGui::PopID(); - } - }; - - // Iterate dummy objects with dummy members (all the same data) - for (int obj_i = 0; obj_i < 3; obj_i++) - funcs::ShowDummyObject("Object", obj_i); - - ImGui::Columns(1); - ImGui::Separator(); - ImGui::PopStyleVar(); - ImGui::End(); -} - -// Demonstrate/test rendering huge amount of text, and the incidence of clipping. -static void ShowExampleAppLongText(bool* p_open) -{ - ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiSetCond_FirstUseEver); - if (!ImGui::Begin("Example: Long text display", p_open)) - { - ImGui::End(); - return; - } - - static int test_type = 0; - static ImGuiTextBuffer log; - static int lines = 0; - ImGui::Text("Printing unusually long amount of text."); - ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped\0"); - ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size()); - if (ImGui::Button("Clear")) { log.clear(); lines = 0; } - ImGui::SameLine(); - if (ImGui::Button("Add 1000 lines")) - { - for (int i = 0; i < 1000; i++) - log.append("%i The quick brown fox jumps over the lazy dog\n", lines+i); - lines += 1000; - } - ImGui::BeginChild("Log"); - switch (test_type) - { - case 0: - // Single call to TextUnformatted() with a big buffer - ImGui::TextUnformatted(log.begin(), log.end()); - break; - case 1: - { - // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper. - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0)); - ImGuiListClipper clipper(lines); - while (clipper.Step()) - for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) - ImGui::Text("%i The quick brown fox jumps over the lazy dog", i); - ImGui::PopStyleVar(); - break; - } - case 2: - // Multiple calls to Text(), not clipped (slow) - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0)); - for (int i = 0; i < lines; i++) - ImGui::Text("%i The quick brown fox jumps over the lazy dog", i); - ImGui::PopStyleVar(); - break; - } - ImGui::EndChild(); - ImGui::End(); -} - -// End of Demo code -#else - -void ImGui::ShowTestWindow(bool*) {} -void ImGui::ShowUserGuide() {} -void ImGui::ShowStyleEditor(ImGuiStyle*) {} - -#endif diff --git a/Baikal/ImGUI/imgui_internal.h b/Baikal/ImGUI/imgui_internal.h deleted file mode 100644 index effc5ce7..00000000 --- a/Baikal/ImGUI/imgui_internal.h +++ /dev/null @@ -1,776 +0,0 @@ -// dear imgui, v1.50 WIP -// (internals) - -// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! -// Implement maths operators for ImVec2 (disabled by default to not collide with using IM_VEC2_CLASS_EXTRA along with your own math types+operators) -// #define IMGUI_DEFINE_MATH_OPERATORS - -#pragma once - -#ifndef IMGUI_VERSION -#error Must include imgui.h before imgui_internal.h -#endif - -#include // FILE* -#include // sqrtf, fabsf, fmodf, powf, floorf, ceilf, cosf, sinf - -#ifdef _MSC_VER -#pragma warning (push) -#pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport) -#endif - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-function" // for stb_textedit.h -#pragma clang diagnostic ignored "-Wmissing-prototypes" // for stb_textedit.h -#pragma clang diagnostic ignored "-Wold-style-cast" -#endif - -//----------------------------------------------------------------------------- -// Forward Declarations -//----------------------------------------------------------------------------- - -struct ImRect; -struct ImGuiColMod; -struct ImGuiStyleMod; -struct ImGuiGroupData; -struct ImGuiSimpleColumns; -struct ImGuiDrawContext; -struct ImGuiTextEditState; -struct ImGuiIniData; -struct ImGuiMouseCursorData; -struct ImGuiPopupRef; -struct ImGuiWindow; - -typedef int ImGuiLayoutType; // enum ImGuiLayoutType_ -typedef int ImGuiButtonFlags; // enum ImGuiButtonFlags_ -typedef int ImGuiTreeNodeFlags; // enum ImGuiTreeNodeFlags_ -typedef int ImGuiSliderFlags; // enum ImGuiSliderFlags_ - -//------------------------------------------------------------------------- -// STB libraries -//------------------------------------------------------------------------- - -namespace ImGuiStb -{ - -#undef STB_TEXTEDIT_STRING -#undef STB_TEXTEDIT_CHARTYPE -#define STB_TEXTEDIT_STRING ImGuiTextEditState -#define STB_TEXTEDIT_CHARTYPE ImWchar -#define STB_TEXTEDIT_GETWIDTH_NEWLINE -1.0f -#include "stb_textedit.h" - -} // namespace ImGuiStb - -//----------------------------------------------------------------------------- -// Context -//----------------------------------------------------------------------------- - -#ifndef GImGui -extern IMGUI_API ImGuiContext* GImGui; // Current implicit ImGui context pointer -#endif - -//----------------------------------------------------------------------------- -// Helpers -//----------------------------------------------------------------------------- - -#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) -#define IM_PI 3.14159265358979323846f -#define IM_OFFSETOF(_TYPE,_ELM) ((size_t)&(((_TYPE*)0)->_ELM)) - -// Helpers: UTF-8 <> wchar -IMGUI_API int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count -IMGUI_API int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // return input UTF-8 bytes count -IMGUI_API int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL); // return input UTF-8 bytes count -IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count) -IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string as UTF-8 code-points - -// Helpers: Misc -IMGUI_API ImU32 ImHash(const void* data, int data_size, ImU32 seed = 0); // Pass data_size==0 for zero-terminated strings -IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* out_file_size = NULL, int padding_bytes = 0); -IMGUI_API FILE* ImFileOpen(const char* filename, const char* file_open_mode); -IMGUI_API bool ImIsPointInTriangle(const ImVec2& p, const ImVec2& a, const ImVec2& b, const ImVec2& c); -static inline bool ImCharIsSpace(int c) { return c == ' ' || c == '\t' || c == 0x3000; } -static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; } - -// Helpers: String -IMGUI_API int ImStricmp(const char* str1, const char* str2); -IMGUI_API int ImStrnicmp(const char* str1, const char* str2, int count); -IMGUI_API char* ImStrdup(const char* str); -IMGUI_API int ImStrlenW(const ImWchar* str); -IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line -IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end); -IMGUI_API int ImFormatString(char* buf, int buf_size, const char* fmt, ...) IM_PRINTFARGS(3); -IMGUI_API int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args); - -// Helpers: Math -// We are keeping those not leaking to the user by default, in the case the user has implicit cast operators between ImVec2 and its own types (when IM_VEC2_CLASS_EXTRA is defined) -#ifdef IMGUI_DEFINE_MATH_OPERATORS -static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x*rhs, lhs.y*rhs); } -static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x/rhs, lhs.y/rhs); } -static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x+rhs.x, lhs.y+rhs.y); } -static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x-rhs.x, lhs.y-rhs.y); } -static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x*rhs.x, lhs.y*rhs.y); } -static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x/rhs.x, lhs.y/rhs.y); } -static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; } -static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; } -static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; } -static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; } -static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z, lhs.w-rhs.w); } -#endif - -static inline int ImMin(int lhs, int rhs) { return lhs < rhs ? lhs : rhs; } -static inline int ImMax(int lhs, int rhs) { return lhs >= rhs ? lhs : rhs; } -static inline float ImMin(float lhs, float rhs) { return lhs < rhs ? lhs : rhs; } -static inline float ImMax(float lhs, float rhs) { return lhs >= rhs ? lhs : rhs; } -static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMin(lhs.x,rhs.x), ImMin(lhs.y,rhs.y)); } -static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMax(lhs.x,rhs.x), ImMax(lhs.y,rhs.y)); } -static inline int ImClamp(int v, int mn, int mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } -static inline float ImClamp(float v, float mn, float mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } -static inline ImVec2 ImClamp(const ImVec2& f, const ImVec2& mn, ImVec2 mx) { return ImVec2(ImClamp(f.x,mn.x,mx.x), ImClamp(f.y,mn.y,mx.y)); } -static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; } -static inline float ImLerp(float a, float b, float t) { return a + (b - a) * t; } -static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); } -static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; } -static inline float ImLengthSqr(const ImVec4& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y + lhs.z*lhs.z + lhs.w*lhs.w; } -static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / sqrtf(d); return fail_value; } -static inline float ImFloor(float f) { return (float)(int)f; } -static inline ImVec2 ImFloor(ImVec2 v) { return ImVec2((float)(int)v.x, (float)(int)v.y); } - -// We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax. -// Defining a custom placement new() with a dummy parameter allows us to bypass including which on some platforms complains when user has disabled exceptions. -#ifdef IMGUI_DEFINE_PLACEMENT_NEW -struct ImPlacementNewDummy {}; -inline void* operator new(size_t, ImPlacementNewDummy, void* ptr) { return ptr; } -inline void operator delete(void*, ImPlacementNewDummy, void*) {} -#define IM_PLACEMENT_NEW(_PTR) new(ImPlacementNewDummy(), _PTR) -#endif - -//----------------------------------------------------------------------------- -// Types -//----------------------------------------------------------------------------- - -enum ImGuiButtonFlags_ -{ - ImGuiButtonFlags_Repeat = 1 << 0, // hold to repeat - ImGuiButtonFlags_PressedOnClickRelease = 1 << 1, // (default) return pressed on click+release on same item (default if no PressedOn** flag is set) - ImGuiButtonFlags_PressedOnClick = 1 << 2, // return pressed on click (default requires click+release) - ImGuiButtonFlags_PressedOnRelease = 1 << 3, // return pressed on release (default requires click+release) - ImGuiButtonFlags_PressedOnDoubleClick = 1 << 4, // return pressed on double-click (default requires click+release) - ImGuiButtonFlags_FlattenChilds = 1 << 5, // allow interaction even if a child window is overlapping - ImGuiButtonFlags_DontClosePopups = 1 << 6, // disable automatically closing parent popup on press - ImGuiButtonFlags_Disabled = 1 << 7, // disable interaction - ImGuiButtonFlags_AlignTextBaseLine = 1 << 8, // vertically align button to match text baseline - ButtonEx() only - ImGuiButtonFlags_NoKeyModifiers = 1 << 9, // disable interaction if a key modifier is held - ImGuiButtonFlags_AllowOverlapMode = 1 << 10 // require previous frame HoveredId to either match id or be null before being usable -}; - -enum ImGuiSliderFlags_ -{ - ImGuiSliderFlags_Vertical = 1 << 0 -}; - -enum ImGuiSelectableFlagsPrivate_ -{ - // NB: need to be in sync with last value of ImGuiSelectableFlags_ - ImGuiSelectableFlags_Menu = 1 << 3, - ImGuiSelectableFlags_MenuItem = 1 << 4, - ImGuiSelectableFlags_Disabled = 1 << 5, - ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 6 -}; - -// FIXME: this is in development, not exposed/functional as a generic feature yet. -enum ImGuiLayoutType_ -{ - ImGuiLayoutType_Vertical, - ImGuiLayoutType_Horizontal -}; - -enum ImGuiPlotType -{ - ImGuiPlotType_Lines, - ImGuiPlotType_Histogram -}; - -enum ImGuiDataType -{ - ImGuiDataType_Int, - ImGuiDataType_Float, - ImGuiDataType_Float2, -}; - -enum ImGuiCorner -{ - ImGuiCorner_TopLeft = 1 << 0, // 1 - ImGuiCorner_TopRight = 1 << 1, // 2 - ImGuiCorner_BottomRight = 1 << 2, // 4 - ImGuiCorner_BottomLeft = 1 << 3, // 8 - ImGuiCorner_All = 0x0F -}; - -// 2D axis aligned bounding-box -// NB: we can't rely on ImVec2 math operators being available here -struct IMGUI_API ImRect -{ - ImVec2 Min; // Upper-left - ImVec2 Max; // Lower-right - - ImRect() : Min(FLT_MAX,FLT_MAX), Max(-FLT_MAX,-FLT_MAX) {} - ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {} - ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {} - ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {} - - ImVec2 GetCenter() const { return ImVec2((Min.x+Max.x)*0.5f, (Min.y+Max.y)*0.5f); } - ImVec2 GetSize() const { return ImVec2(Max.x-Min.x, Max.y-Min.y); } - float GetWidth() const { return Max.x-Min.x; } - float GetHeight() const { return Max.y-Min.y; } - ImVec2 GetTL() const { return Min; } // Top-left - ImVec2 GetTR() const { return ImVec2(Max.x, Min.y); } // Top-right - ImVec2 GetBL() const { return ImVec2(Min.x, Max.y); } // Bottom-left - ImVec2 GetBR() const { return Max; } // Bottom-right - bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; } - bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x < Max.x && r.Max.y < Max.y; } - bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; } - void Add(const ImVec2& rhs) { if (Min.x > rhs.x) Min.x = rhs.x; if (Min.y > rhs.y) Min.y = rhs.y; if (Max.x < rhs.x) Max.x = rhs.x; if (Max.y < rhs.y) Max.y = rhs.y; } - void Add(const ImRect& rhs) { if (Min.x > rhs.Min.x) Min.x = rhs.Min.x; if (Min.y > rhs.Min.y) Min.y = rhs.Min.y; if (Max.x < rhs.Max.x) Max.x = rhs.Max.x; if (Max.y < rhs.Max.y) Max.y = rhs.Max.y; } - void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; } - void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; } - void Reduce(const ImVec2& amount) { Min.x += amount.x; Min.y += amount.y; Max.x -= amount.x; Max.y -= amount.y; } - void Clip(const ImRect& clip) { if (Min.x < clip.Min.x) Min.x = clip.Min.x; if (Min.y < clip.Min.y) Min.y = clip.Min.y; if (Max.x > clip.Max.x) Max.x = clip.Max.x; if (Max.y > clip.Max.y) Max.y = clip.Max.y; } - void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } - ImVec2 GetClosestPoint(ImVec2 p, bool on_edge) const - { - if (!on_edge && Contains(p)) - return p; - if (p.x > Max.x) p.x = Max.x; - else if (p.x < Min.x) p.x = Min.x; - if (p.y > Max.y) p.y = Max.y; - else if (p.y < Min.y) p.y = Min.y; - return p; - } -}; - -// Stacked color modifier, backup of modified data so we can restore it -struct ImGuiColMod -{ - ImGuiCol Col; - ImVec4 BackupValue; -}; - -// Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable. -struct ImGuiStyleMod -{ - ImGuiStyleVar VarIdx; - union { int BackupInt[2]; float BackupFloat[2]; }; - ImGuiStyleMod(ImGuiStyleVar idx, int v) { VarIdx = idx; BackupInt[0] = v; } - ImGuiStyleMod(ImGuiStyleVar idx, float v) { VarIdx = idx; BackupFloat[0] = v; } - ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v) { VarIdx = idx; BackupFloat[0] = v.x; BackupFloat[1] = v.y; } -}; - -// Stacked data for BeginGroup()/EndGroup() -struct ImGuiGroupData -{ - ImVec2 BackupCursorPos; - ImVec2 BackupCursorMaxPos; - float BackupIndentX; - float BackupGroupOffsetX; - float BackupCurrentLineHeight; - float BackupCurrentLineTextBaseOffset; - float BackupLogLinePosY; - bool BackupActiveIdIsAlive; - bool AdvanceCursor; -}; - -// Per column data for Columns() -struct ImGuiColumnData -{ - float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) - //float IndentX; -}; - -// Simple column measurement currently used for MenuItem() only. This is very short-sighted/throw-away code and NOT a generic helper. -struct IMGUI_API ImGuiSimpleColumns -{ - int Count; - float Spacing; - float Width, NextWidth; - float Pos[8], NextWidths[8]; - - ImGuiSimpleColumns(); - void Update(int count, float spacing, bool clear); - float DeclColumns(float w0, float w1, float w2); - float CalcExtraSpace(float avail_w); -}; - -// Internal state of the currently focused/edited text input box -struct IMGUI_API ImGuiTextEditState -{ - ImGuiID Id; // widget id owning the text state - ImVector Text; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer. - ImVector InitialText; // backup of end-user buffer at the time of focus (in UTF-8, unaltered) - ImVector TempTextBuffer; - int CurLenA, CurLenW; // we need to maintain our buffer length in both UTF-8 and wchar format. - int BufSizeA; // end-user buffer size - float ScrollX; - ImGuiStb::STB_TexteditState StbState; - float CursorAnim; - bool CursorFollow; - bool SelectedAllMouseLock; - - ImGuiTextEditState() { memset(this, 0, sizeof(*this)); } - void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking - void CursorClamp() { StbState.cursor = ImMin(StbState.cursor, CurLenW); StbState.select_start = ImMin(StbState.select_start, CurLenW); StbState.select_end = ImMin(StbState.select_end, CurLenW); } - bool HasSelection() const { return StbState.select_start != StbState.select_end; } - void ClearSelection() { StbState.select_start = StbState.select_end = StbState.cursor; } - void SelectAll() { StbState.select_start = 0; StbState.select_end = CurLenW; StbState.cursor = StbState.select_end; StbState.has_preferred_x = false; } - void OnKeyPressed(int key); -}; - -// Data saved in imgui.ini file -struct ImGuiIniData -{ - char* Name; - ImGuiID Id; - ImVec2 Pos; - ImVec2 Size; - bool Collapsed; -}; - -// Mouse cursor data (used when io.MouseDrawCursor is set) -struct ImGuiMouseCursorData -{ - ImGuiMouseCursor Type; - ImVec2 HotOffset; - ImVec2 Size; - ImVec2 TexUvMin[2]; - ImVec2 TexUvMax[2]; -}; - -// Storage for current popup stack -struct ImGuiPopupRef -{ - ImGuiID PopupId; // Set on OpenPopup() - ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() - ImGuiWindow* ParentWindow; // Set on OpenPopup() - ImGuiID ParentMenuSet; // Set on OpenPopup() - ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup - - ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; } -}; - -// Main state for ImGui -struct ImGuiContext -{ - bool Initialized; - ImGuiIO IO; - ImGuiStyle Style; - ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() - float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize() - float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Size of characters. - ImVec2 FontTexUvWhitePixel; // (Shortcut) == Font->TexUvWhitePixel - - float Time; - int FrameCount; - int FrameCountEnded; - int FrameCountRendered; - ImVector Windows; - ImVector WindowsSortBuffer; - ImGuiWindow* CurrentWindow; // Being drawn into - ImVector CurrentWindowStack; - ImGuiWindow* FocusedWindow; // Will catch keyboard inputs - ImGuiWindow* HoveredWindow; // Will catch mouse inputs - ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only) - ImGuiID HoveredId; // Hovered widget - bool HoveredIdAllowOverlap; - ImGuiID HoveredIdPreviousFrame; - ImGuiID ActiveId; // Active widget - ImGuiID ActiveIdPreviousFrame; - bool ActiveIdIsAlive; - bool ActiveIdIsJustActivated; // Set at the time of activation for one frame - bool ActiveIdAllowOverlap; // Set only by active widget - ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) - ImGuiWindow* ActiveIdWindow; - ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. - ImGuiID MovedWindowMoveId; // == MovedWindow->RootWindow->MoveId - ImVector Settings; // .ini Settings - float SettingsDirtyTimer; // Save .ini Settings on disk when time reaches zero - ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() - ImVector StyleModifiers; // Stack for PushStyleVar()/PopStyleVar() - ImVector FontStack; // Stack for PushFont()/PopFont() - ImVector OpenPopupStack; // Which popups are open (persistent) - ImVector CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame) - - // Storage for SetNexWindow** and SetNextTreeNode*** functions - ImVec2 SetNextWindowPosVal; - ImVec2 SetNextWindowSizeVal; - ImVec2 SetNextWindowContentSizeVal; - bool SetNextWindowCollapsedVal; - ImGuiSetCond SetNextWindowPosCond; - ImGuiSetCond SetNextWindowSizeCond; - ImGuiSetCond SetNextWindowContentSizeCond; - ImGuiSetCond SetNextWindowCollapsedCond; - ImRect SetNextWindowSizeConstraintRect; // Valid if 'SetNextWindowSizeConstraint' is true - ImGuiSizeConstraintCallback SetNextWindowSizeConstraintCallback; - void* SetNextWindowSizeConstraintCallbackUserData; - bool SetNextWindowSizeConstraint; - bool SetNextWindowFocus; - bool SetNextTreeNodeOpenVal; - ImGuiSetCond SetNextTreeNodeOpenCond; - - // Render - ImDrawData RenderDrawData; // Main ImDrawData instance to pass render information to the user - ImVector RenderDrawLists[3]; - float ModalWindowDarkeningRatio; - ImDrawList OverlayDrawList; // Optional software render of mouse cursors, if io.MouseDrawCursor is set + a few debug overlays - ImGuiMouseCursor MouseCursor; - ImGuiMouseCursorData MouseCursorData[ImGuiMouseCursor_Count_]; - - // Widget state - ImGuiTextEditState InputTextState; - ImFont InputTextPasswordFont; - ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. - ImGuiStorage ColorEditModeStorage; // Store user selection of color edit mode - float DragCurrentValue; // Currently dragged value, always float, not rounded by end-user precision settings - ImVec2 DragLastMouseDelta; - float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio - float DragSpeedScaleSlow; - float DragSpeedScaleFast; - ImVec2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage? - char Tooltip[1024]; - char* PrivateClipboard; // If no custom clipboard handler is defined - ImVec2 OsImePosRequest, OsImePosSet; // Cursor position request & last passed to the OS Input Method Editor - - // Logging - bool LogEnabled; - FILE* LogFile; // If != NULL log to stdout/ file - ImGuiTextBuffer* LogClipboard; // Else log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators. - int LogStartDepth; - int LogAutoExpandMaxDepth; - - // Misc - float FramerateSecPerFrame[120]; // calculate estimate of framerate for user - int FramerateSecPerFrameIdx; - float FramerateSecPerFrameAccum; - int CaptureMouseNextFrame; // explicit capture via CaptureInputs() sets those flags - int CaptureKeyboardNextFrame; - char TempBuffer[1024*3+1]; // temporary text buffer - - ImGuiContext() - { - Initialized = false; - Font = NULL; - FontSize = FontBaseSize = 0.0f; - FontTexUvWhitePixel = ImVec2(0.0f, 0.0f); - - Time = 0.0f; - FrameCount = 0; - FrameCountEnded = FrameCountRendered = -1; - CurrentWindow = NULL; - FocusedWindow = NULL; - HoveredWindow = NULL; - HoveredRootWindow = NULL; - HoveredId = 0; - HoveredIdAllowOverlap = false; - HoveredIdPreviousFrame = 0; - ActiveId = 0; - ActiveIdPreviousFrame = 0; - ActiveIdIsAlive = false; - ActiveIdIsJustActivated = false; - ActiveIdAllowOverlap = false; - ActiveIdClickOffset = ImVec2(-1,-1); - ActiveIdWindow = NULL; - MovedWindow = NULL; - MovedWindowMoveId = 0; - SettingsDirtyTimer = 0.0f; - - SetNextWindowPosVal = ImVec2(0.0f, 0.0f); - SetNextWindowSizeVal = ImVec2(0.0f, 0.0f); - SetNextWindowCollapsedVal = false; - SetNextWindowPosCond = 0; - SetNextWindowSizeCond = 0; - SetNextWindowContentSizeCond = 0; - SetNextWindowCollapsedCond = 0; - SetNextWindowSizeConstraintRect = ImRect(); - SetNextWindowSizeConstraintCallback = NULL; - SetNextWindowSizeConstraintCallbackUserData = NULL; - SetNextWindowSizeConstraint = false; - SetNextWindowFocus = false; - SetNextTreeNodeOpenVal = false; - SetNextTreeNodeOpenCond = 0; - - ScalarAsInputTextId = 0; - DragCurrentValue = 0.0f; - DragLastMouseDelta = ImVec2(0.0f, 0.0f); - DragSpeedDefaultRatio = 1.0f / 100.0f; - DragSpeedScaleSlow = 0.01f; - DragSpeedScaleFast = 10.0f; - ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f); - memset(Tooltip, 0, sizeof(Tooltip)); - PrivateClipboard = NULL; - OsImePosRequest = OsImePosSet = ImVec2(-1.0f, -1.0f); - - ModalWindowDarkeningRatio = 0.0f; - OverlayDrawList._OwnerName = "##Overlay"; // Give it a name for debugging - MouseCursor = ImGuiMouseCursor_Arrow; - memset(MouseCursorData, 0, sizeof(MouseCursorData)); - - LogEnabled = false; - LogFile = NULL; - LogClipboard = NULL; - LogStartDepth = 0; - LogAutoExpandMaxDepth = 2; - - memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame)); - FramerateSecPerFrameIdx = 0; - FramerateSecPerFrameAccum = 0.0f; - CaptureMouseNextFrame = CaptureKeyboardNextFrame = -1; - memset(TempBuffer, 0, sizeof(TempBuffer)); - } -}; - -// Transient per-window data, reset at the beginning of the frame -// FIXME: That's theory, in practice the delimitation between ImGuiWindow and ImGuiDrawContext is quite tenuous and could be reconsidered. -struct IMGUI_API ImGuiDrawContext -{ - ImVec2 CursorPos; - ImVec2 CursorPosPrevLine; - ImVec2 CursorStartPos; - ImVec2 CursorMaxPos; // Implicitly calculate the size of our contents, always extending. Saved into window->SizeContents at the end of the frame - float CurrentLineHeight; - float CurrentLineTextBaseOffset; - float PrevLineHeight; - float PrevLineTextBaseOffset; - float LogLinePosY; - int TreeDepth; - ImGuiID LastItemId; - ImRect LastItemRect; - bool LastItemHoveredAndUsable; // Item rectangle is hovered, and its window is currently interactable with (not blocked by a popup preventing access to the window) - bool LastItemHoveredRect; // Item rectangle is hovered, but its window may or not be currently interactable with (might be blocked by a popup preventing access to the window) - bool MenuBarAppending; - float MenuBarOffsetX; - ImVector ChildWindows; - ImGuiStorage* StateStorage; - ImGuiLayoutType LayoutType; - - // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. - float ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window - float TextWrapPos; // == TextWrapPosStack.back() [empty == -1.0f] - bool AllowKeyboardFocus; // == AllowKeyboardFocusStack.back() [empty == true] - bool ButtonRepeat; // == ButtonRepeatStack.back() [empty == false] - ImVector ItemWidthStack; - ImVector TextWrapPosStack; - ImVector AllowKeyboardFocusStack; - ImVector ButtonRepeatStack; - ImVectorGroupStack; - ImGuiColorEditMode ColorEditMode; - int StackSizesBackup[6]; // Store size of various stacks for asserting - - float IndentX; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) - float GroupOffsetX; - float ColumnsOffsetX; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. - int ColumnsCurrent; - int ColumnsCount; - float ColumnsMinX; - float ColumnsMaxX; - float ColumnsStartPosY; - float ColumnsCellMinY; - float ColumnsCellMaxY; - bool ColumnsShowBorders; - ImGuiID ColumnsSetId; - ImVector ColumnsData; - - ImGuiDrawContext() - { - CursorPos = CursorPosPrevLine = CursorStartPos = CursorMaxPos = ImVec2(0.0f, 0.0f); - CurrentLineHeight = PrevLineHeight = 0.0f; - CurrentLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f; - LogLinePosY = -1.0f; - TreeDepth = 0; - LastItemId = 0; - LastItemRect = ImRect(0.0f,0.0f,0.0f,0.0f); - LastItemHoveredAndUsable = LastItemHoveredRect = false; - MenuBarAppending = false; - MenuBarOffsetX = 0.0f; - StateStorage = NULL; - LayoutType = ImGuiLayoutType_Vertical; - ItemWidth = 0.0f; - ButtonRepeat = false; - AllowKeyboardFocus = true; - TextWrapPos = -1.0f; - ColorEditMode = ImGuiColorEditMode_RGB; - memset(StackSizesBackup, 0, sizeof(StackSizesBackup)); - - IndentX = 0.0f; - GroupOffsetX = 0.0f; - ColumnsOffsetX = 0.0f; - ColumnsCurrent = 0; - ColumnsCount = 1; - ColumnsMinX = ColumnsMaxX = 0.0f; - ColumnsStartPosY = 0.0f; - ColumnsCellMinY = ColumnsCellMaxY = 0.0f; - ColumnsShowBorders = true; - ColumnsSetId = 0; - } -}; - -// Windows data -struct IMGUI_API ImGuiWindow -{ - char* Name; - ImGuiID ID; // == ImHash(Name) - ImGuiWindowFlags Flags; // See enum ImGuiWindowFlags_ - int IndexWithinParent; // Order within immediate parent window, if we are a child window. Otherwise 0. - ImVec2 PosFloat; - ImVec2 Pos; // Position rounded-up to nearest pixel - ImVec2 Size; // Current size (==SizeFull or collapsed title bar size) - ImVec2 SizeFull; // Size when non collapsed - ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame - ImVec2 SizeContentsExplicit; // Size of contents explicitly set by the user via SetNextWindowContentSize() - ImRect ContentsRegionRect; // Maximum visible content position in window coordinates. ~~ (SizeContentsExplicit ? SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis - ImVec2 WindowPadding; // Window padding at the time of begin. We need to lock it, in particular manipulation of the ShowBorder would have an effect - ImGuiID MoveId; // == window->GetID("#MOVE") - ImVec2 Scroll; - ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change) - ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered - bool ScrollbarX, ScrollbarY; - ImVec2 ScrollbarSizes; - float BorderSize; - bool Active; // Set to true on Begin() - bool WasActive; - bool Accessed; // Set to true when any widget access the current window - bool Collapsed; // Set when collapsing window to become only title-bar - bool SkipItems; // == Visible && !Collapsed - int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) - ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) - int AutoFitFramesX, AutoFitFramesY; - bool AutoFitOnlyGrows; - int AutoPosLastDirection; - int HiddenFrames; - int SetWindowPosAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowPos() call will succeed with this particular flag. - int SetWindowSizeAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowSize() call will succeed with this particular flag. - int SetWindowCollapsedAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowCollapsed() call will succeed with this particular flag. - bool SetWindowPosCenterWanted; - - ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame - ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack - ImRect ClipRect; // = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2. - ImRect WindowRectClipped; // = WindowRect just after setup in Begin(). == window->Rect() for root window. - int LastFrameActive; - float ItemWidthDefault; - ImGuiSimpleColumns MenuColumns; // Simplified columns storage for menu items - ImGuiStorage StateStorage; - float FontWindowScale; // Scale multiplier per-window - ImDrawList* DrawList; - ImGuiWindow* RootWindow; // If we are a child window, this is pointing to the first non-child parent window. Else point to ourself. - ImGuiWindow* RootNonPopupWindow; // If we are a child window, this is pointing to the first non-child non-popup parent window. Else point to ourself. - ImGuiWindow* ParentWindow; // If we are a child window, this is pointing to our parent window. Else point to NULL. - - // Navigation / Focus - int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister() - int FocusIdxTabCounter; // (same, but only count widgets which you can Tab through) - int FocusIdxAllRequestCurrent; // Item being requested for focus - int FocusIdxTabRequestCurrent; // Tab-able item being requested for focus - int FocusIdxAllRequestNext; // Item being requested for focus, for next update (relies on layout to be stable between the frame pressing TAB and the next frame) - int FocusIdxTabRequestNext; // " - -public: - ImGuiWindow(const char* name); - ~ImGuiWindow(); - - ImGuiID GetID(const char* str, const char* str_end = NULL); - ImGuiID GetID(const void* ptr); - ImGuiID GetIDNoKeepAlive(const char* str, const char* str_end = NULL); - - ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); } - float CalcFontSize() const { return GImGui->FontBaseSize * FontWindowScale; } - float TitleBarHeight() const { return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f; } - ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); } - float MenuBarHeight() const { return (Flags & ImGuiWindowFlags_MenuBar) ? CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f : 0.0f; } - ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); } -}; - -//----------------------------------------------------------------------------- -// Internal API -// No guarantee of forward compatibility here. -//----------------------------------------------------------------------------- - -namespace ImGui -{ - // We should always have a CurrentWindow in the stack (there is an implicit "Debug" window) - // If this ever crash because g.CurrentWindow is NULL it means that either - // - ImGui::NewFrame() has never been called, which is illegal. - // - You are calling ImGui functions after ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal. - inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; } - inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->Accessed = true; return g.CurrentWindow; } - IMGUI_API ImGuiWindow* GetParentWindow(); - IMGUI_API ImGuiWindow* FindWindowByName(const char* name); - IMGUI_API void FocusWindow(ImGuiWindow* window); - - IMGUI_API void EndFrame(); // Ends the ImGui frame. Automatically called by Render()! you most likely don't need to ever call that yourself directly. If you don't need to render you can call EndFrame() but you'll have wasted CPU already. If you don't need to render, don't create any windows instead! - - IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); - IMGUI_API void ClearActiveID(); - IMGUI_API void SetHoveredID(ImGuiID id); - IMGUI_API void KeepAliveID(ImGuiID id); - - IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f); - IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f); - IMGUI_API bool ItemAdd(const ImRect& bb, const ImGuiID* id); - IMGUI_API bool IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged); - IMGUI_API bool IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs = false); - IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_stop = true); // Return true if focus is requested - IMGUI_API void FocusableItemUnregister(ImGuiWindow* window); - IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y); - IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); - - IMGUI_API void OpenPopupEx(const char* str_id, bool reopen_existing); - - // NB: All position are in absolute pixels coordinates (not window coordinates) - // FIXME: All those functions are a mess and needs to be refactored into something decent. AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. - // We need: a sort of symbol library, preferably baked into font atlas when possible + decent text rendering helpers. - IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); - IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width); - IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0,0), const ImRect* clip_rect = NULL); - IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); - IMGUI_API void RenderCollapseTriangle(ImVec2 pos, bool is_open, float scale = 1.0f); - IMGUI_API void RenderBullet(ImVec2 pos); - IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col); - IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. - - IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0); - IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0); - IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos, float radius); - - IMGUI_API bool SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* display_format, float power); - IMGUI_API bool SliderIntN(const char* label, int* v, int components, int v_min, int v_max, const char* display_format); - - IMGUI_API bool DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power); - IMGUI_API bool DragFloatN(const char* label, float* v, int components, float v_speed, float v_min, float v_max, const char* display_format, float power); - IMGUI_API bool DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* display_format); - - IMGUI_API bool InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputFloatN(const char* label, float* v, int components, int decimal_precision, ImGuiInputTextFlags extra_flags); - IMGUI_API bool InputIntN(const char* label, int* v, int components, ImGuiInputTextFlags extra_flags); - IMGUI_API bool InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags); - IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision); - - IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); - IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging - IMGUI_API void TreePushRawID(ImGuiID id); - - IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size); - - IMGUI_API int ParseFormatPrecision(const char* fmt, int default_value); - IMGUI_API float RoundScalar(float value, int decimal_precision); - -} // namespace ImGui - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#ifdef _MSC_VER -#pragma warning (pop) -#endif diff --git a/Baikal/Kernels/CL/bxdf.cl b/Baikal/Kernels/CL/bxdf.cl new file mode 100644 index 00000000..fe7b2179 --- /dev/null +++ b/Baikal/Kernels/CL/bxdf.cl @@ -0,0 +1,95 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 BXDF_CL +#define BXDF_CL + +#include <../Baikal/Kernels/CL/bxdf_flags.cl> + +/// Schlick's approximation of Fresnel equtions +float SchlickFresnel(float eta, float ndotw) +{ + const float f = ((1.f - eta) / (1.f + eta)) * ((1.f - eta) / (1.f + eta)); + const float m = 1.f - fabs(ndotw); + const float m2 = m*m; + return f + (1.f - f) * m2 * m2 * m; +} + +/// Full Fresnel equations +float FresnelDielectric(float etai, float etat, float ndotwi, float ndotwt) +{ + // Parallel and perpendicular polarization + float rparl = ((etat * ndotwi) - (etai * ndotwt)) / ((etat * ndotwi) + (etai * ndotwt)); + float rperp = ((etai * ndotwi) - (etat * ndotwt)) / ((etai * ndotwi) + (etat * ndotwt)); + return (rparl*rparl + rperp*rperp) * 0.5f; +} + +#include <../Baikal/Kernels/CL/utils.cl> +#include <../Baikal/Kernels/CL/texture.cl> +#include <../Baikal/Kernels/CL/payload.cl> +#include <../Baikal/Kernels/CL/bxdf_uberv2.cl> + +/// Emissive BRDF sampling +float3 Emissive_GetLe( + // Geometry + DifferentialGeometry const* dg, + // Texture args + TEXTURE_ARG_LIST, + UberV2ShaderData const* shader_data) +{ + return shader_data->emission_color.xyz; +} + +/// BxDF singularity check +bool Bxdf_IsSingular(DifferentialGeometry const* dg) +{ + return (dg->mat.flags & kBxdfFlagsSingular) == kBxdfFlagsSingular; +} + +/// BxDF emission check +bool Bxdf_IsEmissive(DifferentialGeometry const* dg) +{ + return (dg->mat.flags & kBxdfFlagsEmissive) == kBxdfFlagsEmissive; +} + +bool Bxdf_IsBtdf(DifferentialGeometry const* dg) +{ + return (dg->mat.flags & kBxdfFlagsBrdf) == 0; +} + +bool Bxdf_IsReflection(DifferentialGeometry const* dg) +{ + return ((dg->mat.flags & kBxdfFlagsBrdf) == kBxdfFlagsBrdf) && ((dg->mat.flags & kBxdfFlagsDiffuse) == kBxdfFlagsDiffuse); +} + +bool Bxdf_IsTransparency(DifferentialGeometry const* dg) +{ + return (dg->mat.flags & kBxdfFlagsTransparency) == kBxdfFlagsTransparency; +} + +bool Bxdf_IsRefraction(DifferentialGeometry const* dg) +{ + return Bxdf_IsBtdf(dg) && !Bxdf_IsTransparency(dg); +} + +#include + +#endif // BXDF_CL diff --git a/Baikal/Kernels/CL/bxdf_flags.cl b/Baikal/Kernels/CL/bxdf_flags.cl new file mode 100644 index 00000000..2410f679 --- /dev/null +++ b/Baikal/Kernels/CL/bxdf_flags.cl @@ -0,0 +1,75 @@ +/********************************************************************** + * Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + * + * 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 BXDF_FLAGS_CL +#define BXDF_FLAGS_CL + +#define DENOM_EPS 1e-8f +#define ROUGHNESS_EPS 0.0001f + +enum BxdfFlags +{ + kBxdfFlagsSingular = (1 << 0), + kBxdfFlagsBrdf = (1 << 1), + kBxdfFlagsEmissive = (1 << 2), + kBxdfFlagsTransparency = (1 << 3), + kBxdfFlagsDiffuse = (1 << 4), + + //Used to mask value from bxdf_flags + kBxdfFlagsAll = (kBxdfFlagsSingular | kBxdfFlagsBrdf | kBxdfFlagsEmissive | kBxdfFlagsTransparency | kBxdfFlagsDiffuse) +}; + +enum BxdfUberV2SampledComponent +{ + kBxdfUberV2SampleTransparency = 0, + kBxdfUberV2SampleCoating = 1, + kBxdfUberV2SampleReflection = 2, + kBxdfUberV2SampleRefraction = 3, + kBxdfUberV2SampleDiffuse = 4 +}; + +/// Returns BxDF flags. Flags stored in first byte of bxdf_flags +int Bxdf_GetFlags(DifferentialGeometry const* dg) +{ + return (dg->mat.flags & kBxdfFlagsAll); +} + +/// Sets BxDF flags. Flags stored in first byte of bxdf_flags +void Bxdf_SetFlags(DifferentialGeometry *dg, int flags) +{ + dg->mat.flags &= 0xffffff00; //Reset flags + dg->mat.flags |= flags; //Set new flags +} + +/// Return BxDF sampled component. Sampled component stored in second byte of bxdf_flags +int Bxdf_UberV2_GetSampledComponent(DifferentialGeometry const* dg) +{ + return (dg->mat.flags >> 8) & 0xff; +} + +/// Sets BxDF sampled component. Sampled component stored in second byte of bxdf_flags +void Bxdf_UberV2_SetSampledComponent(DifferentialGeometry *dg, int sampledComponent) +{ + dg->mat.flags &= 0xffff00ff; //Reset sampled component + dg->mat.flags |= (sampledComponent << 8); //Set new component +} + +#endif diff --git a/Baikal/Kernels/CL/bxdf_uberv2.cl b/Baikal/Kernels/CL/bxdf_uberv2.cl new file mode 100644 index 00000000..216323bd --- /dev/null +++ b/Baikal/Kernels/CL/bxdf_uberv2.cl @@ -0,0 +1,79 @@ +#ifndef BXDF_UBERV2_CL +#define BXDF_UBERV2_CL + +#include + +typedef struct _UberV2ShaderData +{ + float4 diffuse_color; + float4 reflection_color; + float4 coating_color; + float4 refraction_color; + float4 emission_color; + float4 sss_absorption_color; + float4 sss_scatter_color; + float4 sss_subsurface_color; + float4 shading_normal; + + float reflection_roughness; + float reflection_anisotropy; + float reflection_anisotropy_rotation; + float reflection_ior; + + float reflection_metalness; + float coating_ior; + float refraction_roughness; + float refraction_ior; + + float transparency; + float sss_absorption_distance; + float sss_scatter_distance; + float sss_scatter_direction; + +} UberV2ShaderData; + +bool UberV2IsTransmissive( + // Layers + int layers + ) +{ + return (layers & (kTransparencyLayer | kRefractionLayer)) != 0; +} + +float4 GetUberV2EmissionColor( + // Material offset + int offset, + // Geometry + DifferentialGeometry const* dg, + // Values for input maps + GLOBAL InputMapData const* restrict input_map_values, + // Material attributes + GLOBAL int const* restrict material_attributes, + // Texture args + TEXTURE_ARG_LIST +) +{ + return GetInputMapFloat4(material_attributes[offset+1], dg, input_map_values, TEXTURE_ARGS); +} + + +#include <../Baikal/Kernels/CL/bxdf_uberv2_bricks.cl> + +void UberV2_ApplyShadingNormal( + // Geometry + DifferentialGeometry* dg, + // Prepared UberV2 shader inputs + UberV2ShaderData const* shader_data +) +{ + const int layers = dg->mat.layers; + + if ((layers & kShadingNormalLayer) == kShadingNormalLayer) + { + dg->n = normalize(shader_data->shading_normal.z * dg->n + shader_data->shading_normal.x * dg->dpdu + shader_data->shading_normal.y * dg->dpdv); + dg->dpdv = normalize(cross(dg->n, dg->dpdu)); + dg->dpdu = normalize(cross(dg->dpdv, dg->n)); + } +} + +#endif diff --git a/Baikal/Kernels/CL/bxdf_uberv2_bricks.cl b/Baikal/Kernels/CL/bxdf_uberv2_bricks.cl new file mode 100644 index 00000000..ccc59545 --- /dev/null +++ b/Baikal/Kernels/CL/bxdf_uberv2_bricks.cl @@ -0,0 +1,749 @@ +#ifndef BXDF_UBERV2_BRICKS +#define BXDF_UBERV2_BRICKS + +// Utility functions for Uberv2 +/// Calculates Fresnel for provided parameters. Swaps IORs if needed +float CalculateFresnel( + // IORs + float top_ior, + float bottom_ior, + // Angle between normal and incoming ray + float ndotwi +) +{ + float etai = top_ior; + float etat = bottom_ior; + float cosi = ndotwi; + + // Revert normal and eta if needed + if (cosi < 0.f) + { + float tmp = etai; + etai = etat; + etat = tmp; + cosi = -cosi; + } + + float eta = etai / etat; + float sini2 = 1.f - cosi * cosi; + float sint2 = eta * eta * sini2; + float fresnel = 1.f; + + if (sint2 < 1.f) + { + float cost = native_sqrt(max(0.f, 1.f - sint2)); + fresnel = FresnelDielectric(etai, etat, cosi, cost); + } + + return fresnel; +} + +// Calucates Fresnel blend for two float3 values. +// F(top_ior, bottom_ior) * top_value + (1 - F(top_ior, bottom_ior) * bottom_value) +float3 Fresnel_Blend( + // IORs + float top_ior, + float bottom_ior, + // Values to blend + float3 top_value, + float3 bottom_value, + // Incoming direction + float3 wi +) +{ + float fresnel = CalculateFresnel(top_ior, bottom_ior, wi.y); + return fresnel * top_value + (1.f - fresnel) * bottom_value; +} + +// Calucates Fresnel blend for two float values. +// F(top_ior, bottom_ior) * top_value + (1 - F(top_ior, bottom_ior) * bottom_value) +float Fresnel_Blend_F( + // IORs + float top_ior, + float bottom_ior, + // Values to blend + float top_value, + float bottom_value, + // Incoming direction + float3 wi +) +{ + float fresnel = CalculateFresnel(top_ior, bottom_ior, wi.y); + return fresnel * top_value + (1.f - fresnel) * bottom_value; +} + +// Diffuse layer +float3 UberV2_Lambert_Evaluate( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Outgoing direction + float3 wo, + // Texture args + TEXTURE_ARG_LIST +) +{ + return shader_data->diffuse_color.xyz / PI; +} + +float UberV2_Lambert_GetPdf( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Outgoing direction + float3 wo, + // Texture args + TEXTURE_ARG_LIST +) +{ + return fabs(wo.y) / PI; +} + +/// Lambert BRDF sampling +float3 UberV2_Lambert_Sample( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Texture args + TEXTURE_ARG_LIST, + // Sample + float2 sample, + // Outgoing direction + float3* wo, + // PDF at wo + float* pdf +) +{ + const float3 kd = UberV2_Lambert_Evaluate(shader_data, wi, *wo, TEXTURE_ARGS); + + *wo = Sample_MapToHemisphere(sample, make_float3(0.f, 1.f, 0.f), 1.f); + + *pdf = fabs((*wo).y) / PI; + + return kd; +} + +// Reflection/Coating +/* +Microfacet GGX +*/ +// Distribution fucntion +float UberV2_MicrofacetDistribution_GGX_D(float roughness, float3 m) +{ + float ndotm = fabs(m.y); + float ndotm2 = ndotm * ndotm; + float sinmn = native_sqrt(1.f - clamp(ndotm * ndotm, 0.f, 1.f)); + float tanmn = ndotm > DENOM_EPS ? sinmn / ndotm : 0.f; + float a2 = roughness * roughness; + float denom = (PI * ndotm2 * ndotm2 * (a2 + tanmn * tanmn) * (a2 + tanmn * tanmn)); + return denom > DENOM_EPS ? (a2 / denom) : 1.f; +} + +// PDF of the given direction +float UberV2_MicrofacetDistribution_GGX_GetPdf( + // Halfway vector + float3 m, + // Rougness + float roughness, + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Outgoing direction + float3 wo, + // Texture args + TEXTURE_ARG_LIST +) +{ + float mpdf = UberV2_MicrofacetDistribution_GGX_D(roughness, m) * fabs(m.y); + // See Humphreys and Pharr for derivation + float denom = (4.f * fabs(dot(wo, m))); + + return denom > DENOM_EPS ? mpdf / denom : 0.f; +} + +// Sample the distribution +void UberV2_MicrofacetDistribution_GGX_SampleNormal( + // Roughness + float roughness, + // Differential geometry + UberV2ShaderData const* shader_data, + // Texture args + TEXTURE_ARG_LIST, + // Sample + float2 sample, + // Outgoing direction + float3* wh +) +{ + float r1 = sample.x; + float r2 = sample.y; + + // Sample halfway vector first, then reflect wi around that + float theta = atan2(roughness * native_sqrt(r1), native_sqrt(1.f - r1)); + float costheta = native_cos(theta); + float sintheta = native_sin(theta); + + // phi = 2*PI*ksi2 + float phi = 2.f * PI * r2; + float cosphi = native_cos(phi); + float sinphi = native_sin(phi); + + // Calculate wh + *wh = make_float3(sintheta * cosphi, costheta, sintheta * sinphi); +} + +// +float UberV2_MicrofacetDistribution_GGX_G1(float roughness, float3 v, float3 m) +{ + float ndotv = fabs(v.y); + float mdotv = fabs(dot(m, v)); + + float sinnv = native_sqrt(1.f - clamp(ndotv * ndotv, 0.f, 1.f)); + float tannv = ndotv > DENOM_EPS ? sinnv / ndotv : 0.f; + float a2 = roughness * roughness; + return 2.f / (1.f + native_sqrt(1.f + a2 * tannv * tannv)); +} + +// Shadowing function also depends on microfacet distribution +float UberV2_MicrofacetDistribution_GGX_G(float roughness, float3 wi, float3 wo, float3 wh) +{ + return UberV2_MicrofacetDistribution_GGX_G1(roughness, wi, wh) * UberV2_MicrofacetDistribution_GGX_G1(roughness, wo, wh); +} + +float3 UberV2_MicrofacetGGX_Evaluate( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Outgoing direction + float3 wo, + // Texture args + TEXTURE_ARG_LIST, + float3 ks +) +{ + // Incident and reflected zenith angles + float costhetao = fabs(wo.y); + float costhetai = fabs(wi.y); + + // Calc halfway vector + float3 wh = normalize(wi + wo); + + float denom = (4.f * costhetao * costhetai); + + return denom > DENOM_EPS ? ks * UberV2_MicrofacetDistribution_GGX_G(shader_data->reflection_roughness, wi, wo, wh) * UberV2_MicrofacetDistribution_GGX_D(shader_data->reflection_roughness, wh) / denom : 0.f; +} + + +float UberV2_MicrofacetGGX_GetPdf( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Outgoing direction + float3 wo, + // Texture args + TEXTURE_ARG_LIST +) +{ + float3 wh = normalize(wo + wi); + + return UberV2_MicrofacetDistribution_GGX_GetPdf(wh, shader_data->reflection_roughness, shader_data, wi, wo, TEXTURE_ARGS); +} + +float3 UberV2_MicrofacetGGX_Sample( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Texture args + TEXTURE_ARG_LIST, + // Sample + float2 sample, + // Outgoing direction + float3* wo, + // PDF at wo + float* pdf, + float3 ks +) +{ + float3 wh; + UberV2_MicrofacetDistribution_GGX_SampleNormal(shader_data->reflection_roughness, shader_data, TEXTURE_ARGS, sample, &wh); + + *wo = -wi + 2.f*fabs(dot(wi, wh)) * wh; + + *pdf = UberV2_MicrofacetDistribution_GGX_GetPdf(wh, shader_data->reflection_roughness, shader_data, wi, *wo, TEXTURE_ARGS); + + return UberV2_MicrofacetGGX_Evaluate(shader_data, wi, *wo, TEXTURE_ARGS, ks); +} + +/* +Ideal reflection BRDF +*/ +float3 UberV2_IdealReflect_Evaluate( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Outgoing direction + float3 wo, + // Texture args + TEXTURE_ARG_LIST +) +{ + return 0.f; +} + +float UberV2_IdealReflect_GetPdf( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Outgoing direction + float3 wo, + // Texture args + TEXTURE_ARG_LIST +) +{ + return 0.f; +} + +float3 UberV2_IdealReflect_Sample( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Texture args + TEXTURE_ARG_LIST, + // Outgoing direction + float3* wo, + // PDF at wo + float* pdf, + float3 ks) +{ + // Mirror reflect wi + *wo = normalize(make_float3(-wi.x, wi.y, -wi.z)); + + // PDF is infinite at that point, but deltas are going to cancel out while evaluating + // so set it to 1.f + *pdf = 1.f; + + float coswo = fabs((*wo).y); + + // Return reflectance value + return coswo > DENOM_EPS ? (ks * (1.f / coswo)) : 0.f; +} + +// Refraction +/* +Ideal refraction BTDF +*/ + +float3 UberV2_IdealRefract_Evaluate( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Outgoing direction + float3 wo, + // Texture args + TEXTURE_ARG_LIST +) +{ + return 0.f; +} + +float UberV2_IdealRefract_GetPdf( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Outgoing direction + float3 wo, + // Texture args + TEXTURE_ARG_LIST +) +{ + return 0.f; +} + +float3 UberV2_IdealRefract_Sample( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Texture args + TEXTURE_ARG_LIST, + // Sample + float2 sample, + // Outgoing direction + float3* wo, + // PDF at wo + float* pdf +) +{ + const float3 ks = shader_data->refraction_color.xyz; + + float etai = 1.f; + float etat = shader_data->refraction_ior; + float cosi = wi.y; + + bool entering = cosi > 0.f; + + // Revert normal and eta if needed + if (!entering) + { + float tmp = etai; + etai = etat; + etat = tmp; + } + + float eta = etai / etat; + float sini2 = 1.f - cosi * cosi; + float sint2 = eta * eta * sini2; + + if (sint2 >= 1.f) + { + *pdf = 0.f; + return 0.f; + } + + float cost = native_sqrt(max(0.f, 1.f - sint2)); + + // Transmitted ray + *wo = normalize(make_float3(eta * -wi.x, entering ? -cost : cost, eta * -wi.z)); + + *pdf = 1.f; + + return cost > DENOM_EPS ? (eta * eta * ks / cost) : 0.f; +} + + +float3 UberV2_MicrofacetRefractionGGX_Evaluate( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Outgoing direction + float3 wo, + // Texture args + TEXTURE_ARG_LIST +) +{ + const float3 ks = shader_data->refraction_color.xyz; + const float roughness = max(shader_data->refraction_roughness, ROUGHNESS_EPS); + + float ndotwi = wi.y; + float ndotwo = wo.y; + + if (ndotwi * ndotwo >= 0.f) + { + return 0.f; + } + + float etai = 1.f; + float etat = shader_data->refraction_ior; + + // Revert normal and eta if needed + if (ndotwi < 0.f) + { + float tmp = etai; + etai = etat; + etat = tmp; + } + + // Calc halfway vector + float3 ht = -(etai * wi + etat * wo); + float3 wh = normalize(ht); + + float widotwh = fabs(dot(wh, wi)); + float wodotwh = fabs(dot(wh, wo)); + + float denom = dot(ht, ht); + denom *= (fabs(ndotwi) * fabs(ndotwo)); + + return denom > DENOM_EPS ? (ks * (widotwh * wodotwh) * (etat)* (etat)* + UberV2_MicrofacetDistribution_GGX_G(roughness, wi, wo, wh) * UberV2_MicrofacetDistribution_GGX_D(roughness, wh) / denom) : 0.f; +} + +float UberV2_MicrofacetRefractionGGX_GetPdf( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Outgoing direction + float3 wo, + // Texture args + TEXTURE_ARG_LIST +) +{ + const float roughness = max(shader_data->refraction_roughness, ROUGHNESS_EPS); + + float ndotwi = wi.y; + float ndotwo = wo.y; + + if (ndotwi * ndotwo >= 0.f) + { + return 0.f; + } + + float etai = 1.f; + float etat = shader_data->refraction_ior; + + // Revert normal and eta if needed + if (ndotwi < 0.f) + { + float tmp = etai; + etai = etat; + etat = tmp; + } + + // Calc halfway vector + float3 ht = -(etai * wi + etat * wo); + + float3 wh = normalize(ht); + + float wodotwh = fabs(dot(wo, wh)); + + float whpdf = UberV2_MicrofacetDistribution_GGX_D(roughness, wh) * fabs(wh.y); + + float whwo = wodotwh * etat * etat; + + float denom = dot(ht, ht); + + return denom > DENOM_EPS ? whpdf * whwo / denom : 0.f; +} + +float3 UberV2_MicrofacetRefractionGGX_Sample( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Texture args + TEXTURE_ARG_LIST, + // Sample + float2 sample, + // Outgoing direction + float3* wo, + // PDF at wo + float* pdf +) +{ + const float3 ks = shader_data->refraction_color.xyz; + const float roughness = max(shader_data->refraction_roughness, ROUGHNESS_EPS); + + float ndotwi = wi.y; + + if (ndotwi == 0.f) + { + *pdf = 0.f; + return 0.f; + } + + float etai = 1.f; + float etat = shader_data->refraction_ior; + float s = 1.f; + + // Revert normal and eta if needed + if (ndotwi < 0.f) + { + float tmp = etai; + etai = etat; + etat = tmp; + s = -s; + } + + float3 wh; + UberV2_MicrofacetDistribution_GGX_SampleNormal(roughness, shader_data, TEXTURE_ARGS, sample, &wh); + + float c = dot(wi, wh); + float eta = etai / etat; + + float d = 1 + eta * (c * c - 1); + + if (d <= 0.f) + { + *pdf = 0.f; + return 0.f; + } + + *wo = normalize((eta * c - s * native_sqrt(d)) * wh - eta * wi); + + *pdf = UberV2_MicrofacetRefractionGGX_GetPdf(shader_data, wi, *wo, TEXTURE_ARGS); + + return UberV2_MicrofacetRefractionGGX_Evaluate(shader_data, wi, *wo, TEXTURE_ARGS); +} + +float3 UberV2_Passthrough_Sample( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Texture args + TEXTURE_ARG_LIST, + // Sample + float2 sample, + // Outgoing direction + float3* wo, + // PDF at wo + float* pdf +) +{ + *wo = -wi; + float coswo = fabs((*wo).y); + + // PDF is infinite at that point, but deltas are going to cancel out while evaluating + // so set it to 1.f + *pdf = 1.f; + + return coswo > 1e-5f ? (1.f / coswo) : 0.f; +} + +float3 UberV2_Reflection_Evaluate( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Outgoing direction + float3 wo, + // Texture args + TEXTURE_ARG_LIST +) +{ + const bool is_singular = (shader_data->reflection_roughness < ROUGHNESS_EPS); + const float metalness = shader_data->reflection_metalness; + + const float3 ks = shader_data->reflection_color.xyz; + + float3 color = mix((float3)(1.0f, 1.0f, 1.0f), ks, metalness); + + return is_singular ? + UberV2_IdealReflect_Evaluate(shader_data, wi, wo, TEXTURE_ARGS) : + UberV2_MicrofacetGGX_Evaluate(shader_data, wi, wo, TEXTURE_ARGS, color); +} + +float3 UberV2_Refraction_Evaluate( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Outgoing direction + float3 wo, + // Texture args + TEXTURE_ARG_LIST +) +{ + const bool is_singular = (shader_data->refraction_roughness < ROUGHNESS_EPS); + + return is_singular ? + UberV2_IdealRefract_Evaluate(shader_data, wi, wo, TEXTURE_ARGS) : + UberV2_MicrofacetRefractionGGX_Evaluate(shader_data, wi, wo, TEXTURE_ARGS); +} + +float UberV2_Reflection_GetPdf( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Outgoing direction + float3 wo, + // Texture args + TEXTURE_ARG_LIST +) +{ + const bool is_singular = (shader_data->reflection_roughness < ROUGHNESS_EPS); + + return is_singular ? + UberV2_IdealReflect_GetPdf(shader_data, wi, wo, TEXTURE_ARGS) : + UberV2_MicrofacetGGX_GetPdf(shader_data, wi, wo, TEXTURE_ARGS); +} + +float UberV2_Refraction_GetPdf( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Outgoing direction + float3 wo, + // Texture args + TEXTURE_ARG_LIST +) +{ + const bool is_singular = (shader_data->refraction_roughness < ROUGHNESS_EPS); + + return is_singular ? + UberV2_IdealRefract_GetPdf(shader_data, wi, wo, TEXTURE_ARGS) : + UberV2_MicrofacetRefractionGGX_GetPdf(shader_data, wi, wo, TEXTURE_ARGS); +} + +float3 UberV2_Reflection_Sample( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Texture args + TEXTURE_ARG_LIST, + // Sample + float2 sample, + // Outgoing direction + float3* wo, + // PDF at wo + float* pdf +) +{ + const float3 ks = shader_data->reflection_color.xyz; + const bool is_singular = (shader_data->reflection_roughness < ROUGHNESS_EPS); + const float metalness = shader_data->reflection_metalness; + + float3 color = mix((float3)(1.0f, 1.0f, 1.0f), ks, metalness); + + return is_singular ? + UberV2_IdealReflect_Sample(shader_data, wi, TEXTURE_ARGS, wo, pdf, color) : + UberV2_MicrofacetGGX_Sample(shader_data, wi, TEXTURE_ARGS, sample, wo, pdf, color); +} + +float3 UberV2_Refraction_Sample( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Texture args + TEXTURE_ARG_LIST, + // Sample + float2 sample, + // Outgoing direction + float3* wo, + // PDF at wo + float* pdf +) +{ + const bool is_singular = (shader_data->refraction_roughness < ROUGHNESS_EPS); + + return is_singular ? + UberV2_IdealRefract_Sample(shader_data, wi, TEXTURE_ARGS, sample, wo, pdf) : + UberV2_MicrofacetRefractionGGX_Sample(shader_data, wi, TEXTURE_ARGS, sample, wo, pdf); +} + +float3 UberV2_Coating_Sample( + // Preprocessed shader input data + UberV2ShaderData const* shader_data, + // Incoming direction + float3 wi, + // Texture args + TEXTURE_ARG_LIST, + // Outgoing direction + float3* wo, + // PDF at wo + float* pdf +) +{ + const float3 ks = shader_data->coating_color.xyz; + + return UberV2_IdealReflect_Sample(shader_data, wi, TEXTURE_ARGS, wo, pdf, ks); +} + +#endif diff --git a/Baikal/CL/common.cl b/Baikal/Kernels/CL/common.cl similarity index 75% rename from Baikal/CL/common.cl rename to Baikal/Kernels/CL/common.cl index 8ff900b4..90a1224f 100644 --- a/Baikal/CL/common.cl +++ b/Baikal/Kernels/CL/common.cl @@ -35,9 +35,10 @@ THE SOFTWARE. #define INVALID_IDX -1 #define CRAZY_LOW_THROUGHPUT 0.0f -#define CRAZY_HIGH_RADIANCE 3.f +#define CRAZY_HIGH_RADIANCE 10.f #define CRAZY_HIGH_DISTANCE 1000000.f #define CRAZY_LOW_DISTANCE 0.001f +#define CRAZY_HIGH_DISTANCE_IN_VOLUME 1000000.f #define REASONABLE_RADIANCE(x) (clamp((x), 0.f, CRAZY_HIGH_RADIANCE)) #define NON_BLACK(x) (length(x) > 0.f) @@ -53,4 +54,19 @@ THE SOFTWARE. #define BDPT_MAX_SUBPATH_LEN 3 +#ifdef BAIKAL_ATOMIC_RESOLVE +#define ADD_FLOAT3(x,y) atomic_add_float3((x),(y)) +#define ADD_FLOAT4(x,y) atomic_add_float4((x),(y)) +#else +#define ADD_FLOAT3(x,y) add_float3((x),(y)) +#define ADD_FLOAT4(x,y) add_float4((x),(y)) +#endif + +#define VISIBILITY_MASK_PRIMARY (0x1) +#define VISIBILITY_MASK_SHADOW (0x1 << 15) +#define VISIBILITY_MASK_ALL (0xffffffffu) +#define VISIBILITY_MASK_NONE (0x0u) +#define VISIBILITY_MASK_BOUNCE(i) (VISIBILITY_MASK_PRIMARY << (i)) +#define VISIBILITY_MASK_BOUNCE_SHADOW(i) (VISIBILITY_MASK_SHADOW << (i)) + #endif // COMMON_CL diff --git a/Baikal/CL/denoise.cl b/Baikal/Kernels/CL/denoise.cl similarity index 80% rename from Baikal/CL/denoise.cl rename to Baikal/Kernels/CL/denoise.cl index 1884e39a..88bf8697 100644 --- a/Baikal/CL/denoise.cl +++ b/Baikal/Kernels/CL/denoise.cl @@ -22,7 +22,7 @@ THE SOFTWARE. #ifndef DENOISE_CL #define DENOISE_CL -#include <../Baikal/CL/common.cl> +#include <../Baikal/Kernels/CL/common.cl> // Similarity function inline float C(float3 x1, float3 x2, float sigma) @@ -66,14 +66,14 @@ void BilateralDenoise_main( { int idx = global_id.y * width + global_id.x; - float3 color = colors[idx].xyz / colors[idx].w; - float3 normal = normals[idx].xyz / normals[idx].w; - float3 position = positions[idx].xyz / positions[idx].w; - float3 albedo = albedos[idx].xyz / albedos[idx].w; + float3 color = colors[idx].w > 1 ? (colors[idx].xyz / colors[idx].w) : colors[idx].xyz; + float3 normal = normals[idx].w > 1 ? (normals[idx].xyz / normals[idx].w) : normals[idx].xyz; + float3 position = positions[idx].w > 1 ? (positions[idx].xyz / positions[idx].w) : positions[idx].xyz; + float3 albedo = albedos[idx].w > 1 ? (albedos[idx].xyz / albedos[idx].w) : albedos[idx].xyz; float3 filtered_color = 0.f; float sum = 0.f; - if (length(normal) > 0.f && radius > 0) + if (length(position) > 0.f) { for (int i = -radius; i <= radius; ++i) { @@ -88,20 +88,20 @@ void BilateralDenoise_main( float3 p = positions[ci].xyz / positions[ci].w; float3 a = albedos[ci].xyz / albedos[ci].w; - if (length(n) > 0.f) + if (length(p) > 0.f) { filtered_color += c * C(p, position, sigma_position) * - C(c, color, sigma_color) * - C(n, normal, sigma_normal) * - C(a, albedo, sigma_albedo); + C(c, color, sigma_color) * + C(n, normal, sigma_normal) * + C(a, albedo, sigma_albedo); sum += C(p, position, sigma_position) * C(c, color, sigma_color) * - C(n, normal, sigma_normal) * - C(a, albedo, sigma_albedo); + C(n, normal, sigma_normal) * + C(a, albedo, sigma_albedo); } } } - out_colors[idx].xyz = sum > 0 ? filtered_color / sum : 0.f; + out_colors[idx].xyz = sum > 0 ? filtered_color / sum : color; out_colors[idx].w = 1.f; } else diff --git a/Baikal/Kernels/CL/disney.cl b/Baikal/Kernels/CL/disney.cl new file mode 100644 index 00000000..c252517d --- /dev/null +++ b/Baikal/Kernels/CL/disney.cl @@ -0,0 +1,297 @@ +#ifndef DISNEY_CL +#define DISNEY_CL + +#include <../Baikal/Kernels/CL/utils.cl> +#include <../Baikal/Kernels/CL/texture.cl> +#include <../Baikal/Kernels/CL/payload.cl> + +#define DENOM_EPS 1e-8f +#define ROUGHNESS_EPS 0.0001f + +#define WHITE make_float3(1.f, 1.f, 1.f) + +INLINE float SchlickFresnelReflectance(float u) +{ + float m = clamp(1.f - u, 0.f, 1.f); + float m2 = m * m; + return m2 * m2 * m; +} + +float GTR1(float ndoth, float a) +{ + if (a >= 1.f) return 1.f / PI; + + float a2 = a * a; + float t = 1.f + (a2 - 1.f) * ndoth * ndoth; + return (a2 - 1.f) / (PI * log(a2) * t); +} + +float GTR2(float ndoth, float a) +{ + float a2 = a * a; + float t = 1.f + (a2 - 1.f) * ndoth * ndoth; + return a2 / (PI * t * t); +} + +float GTR2_Aniso(float ndoth, float hdotx, float hdoty, float ax, float ay) +{ + float hdotxa2 = (hdotx / ax); + hdotxa2 *= hdotxa2; + float hdotya2 = (hdoty / ay); + hdotya2 *= hdotya2; + float denom = hdotxa2 + hdotya2 + ndoth * ndoth; + return denom > 1e-5 ? (1.f / (PI * ax * ay * denom * denom)) : 0.f; +} + + +float SmithGGX_G(float ndotv, float a) +{ + float a2 = a * a; + float b = ndotv * ndotv; + return 1.f / (ndotv + native_sqrt(a2 + b - a2 * b)); +} + +float SmithGGX_G_Aniso(float ndotv, float vdotx, float vdoty, float ax, float ay) +{ + float vdotxax2 = (vdotx * ax) * (vdotx * ax); + float vdotyay2 = (vdoty * ay) * (vdoty * ay); + return 1.f / (ndotv + native_sqrt( vdotxax2 + vdotyay2 + ndotv * ndotv)); +} + + +INLINE float Disney_GetPdf( + // Geometry + DifferentialGeometry const* dg, + // Incoming direction + float3 wi, + // Outgoing direction + float3 wo, + // Texture args + TEXTURE_ARG_LIST + ) +{ + float3 base_color = Texture_GetValue3f(dg->mat.disney.base_color.xyz, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.base_color_map_idx)); + float metallic = Texture_GetValue1f(dg->mat.disney.metallic, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.metallic_map_idx)); + float specular = Texture_GetValue1f(dg->mat.disney.specular, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.specular_map_idx)); + float anisotropy = Texture_GetValue1f(dg->mat.disney.anisotropy, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.anisotropy_map_idx)); + float roughness = Texture_GetValue1f(dg->mat.disney.roughness, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.roughness_map_idx)); + float specular_tint = Texture_GetValue1f(dg->mat.disney.specular_tint, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.specular_tint_map_idx)); + float sheen_tint = Texture_GetValue1f(dg->mat.disney.sheen_tint, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.sheen_tint_map_idx)); + float sheen = Texture_GetValue1f(dg->mat.disney.sheen, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.sheen_map_idx)); + float clearcoat_gloss = Texture_GetValue1f(dg->mat.disney.clearcoat_gloss, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.clearcoat_gloss_map_idx)); + float clearcoat = Texture_GetValue1f(dg->mat.disney.clearcoat, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.clearcoat_map_idx)); + float subsurface = dg->mat.disney.subsurface; + + float aspect = native_sqrt(1.f - anisotropy * 0.9f); + + float ax = max(0.001f, roughness * roughness * ( 1.f + anisotropy)); + float ay = max(0.001f, roughness * roughness * ( 1.f - anisotropy)); + float3 wh = normalize(wo + wi); + float ndotwh = fabs(wh.y); + float hdotwo = fabs(dot(wh, wo)); + + + float d_pdf = fabs(wo.y) / PI; + float r_pdf = GTR2_Aniso(ndotwh, wh.x, wh.z, ax, ay) * ndotwh / (4.f * hdotwo); + float c_pdf = GTR1(ndotwh, mix(0.1f,0.001f, clearcoat_gloss)) * ndotwh / (4.f * hdotwo); + + float3 cd_lin = native_powr(base_color, 2.2f); + // Luminance approximmation + float cd_lum = dot(cd_lin, make_float3(0.3f, 0.6f, 0.1f)); + + // Normalize lum. to isolate hue+sat + float3 c_tint = cd_lum > 0.f ? (cd_lin / cd_lum) : WHITE; + + float3 c_spec0 = mix(specular * 0.1f * mix(WHITE, + c_tint, specular_tint), + cd_lin, metallic); + + float cs_lum = dot(c_spec0, make_float3(0.3f, 0.6f, 0.1f)); + + float cs_w = cs_lum / (cs_lum + (1.f - metallic) * cd_lum); + + return c_pdf * clearcoat + (1.f - clearcoat) * (cs_w * r_pdf + (1.f - cs_w) * d_pdf); +} + + +INLINE float3 Disney_Evaluate( + // Geometry + DifferentialGeometry const* dg, + // Incoming direction + float3 wi, + // Outgoing direction + float3 wo, + // Texture args + TEXTURE_ARG_LIST + ) +{ + float3 base_color = Texture_GetValue3f(dg->mat.disney.base_color.xyz, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.base_color_map_idx)); + float metallic = Texture_GetValue1f(dg->mat.disney.metallic, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.metallic_map_idx)); + float specular = Texture_GetValue1f(dg->mat.disney.specular, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.specular_map_idx)); + float anisotropy = Texture_GetValue1f(dg->mat.disney.anisotropy, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.anisotropy_map_idx)); + float roughness = Texture_GetValue1f(dg->mat.disney.roughness, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.roughness_map_idx)); + float specular_tint = Texture_GetValue1f(dg->mat.disney.specular_tint, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.specular_tint_map_idx)); + float sheen_tint = Texture_GetValue1f(dg->mat.disney.sheen_tint, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.sheen_tint_map_idx)); + float sheen = Texture_GetValue1f(dg->mat.disney.sheen, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.sheen_map_idx)); + float clearcoat_gloss = Texture_GetValue1f(dg->mat.disney.clearcoat_gloss, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.clearcoat_gloss_map_idx)); + float clearcoat = Texture_GetValue1f(dg->mat.disney.clearcoat, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.clearcoat_map_idx)); + float subsurface = dg->mat.disney.subsurface; + + float ndotwi = fabs(wi.y); + float ndotwo = fabs(wo.y); + + float3 h = normalize(wi + wo); + float ndoth = fabs(h.y); + float hdotwo = fabs(dot(h, wo)); + + float3 cd_lin = native_powr(base_color, 2.2f); + // Luminance approximmation + float cd_lum = dot(cd_lin, make_float3(0.3f, 0.6f, 0.1f)); + + // Normalize lum. to isolate hue+sat + float3 c_tint = cd_lum > 0.f ? (cd_lin / cd_lum) : WHITE; + + float3 c_spec0 = mix(specular * 0.1f * mix(WHITE, + c_tint, specular_tint), + cd_lin, metallic); + + float3 c_sheen = mix(WHITE, c_tint, sheen_tint); + + // Diffuse fresnel - go from 1 at normal incidence to 0.5 at grazing + // and mix in diffuse retro-reflection based on roughness + float f_wo = SchlickFresnelReflectance(ndotwo); + float f_wi = SchlickFresnelReflectance(ndotwi); + + float fd90 = 0.5f + 2 * hdotwo * hdotwo * roughness; + float fd = mix(1.f, fd90, f_wo) * mix(1.f, fd90, f_wi); + + // Based on Hanrahan-Krueger brdf approximation of isotropic bssrdf + // 1.25 scale is used to (roughly) preserve albedo + // fss90 used to "flatten" retroreflection based on roughness + float fss90 = hdotwo * hdotwo * roughness; + float fss = mix(1.f, fss90, f_wo) * mix(1.f, fss90, f_wi); + float ss = 1.25f * (fss * (1.f / (ndotwo + ndotwi) - 0.5f) + 0.5f); + + // Specular + float ax = max(0.001f, roughness * roughness * ( 1.f + anisotropy)); + float ay = max(0.001f, roughness * roughness * ( 1.f - anisotropy)); + float ds = GTR2_Aniso(ndoth, h.x, h.z, ax, ay); + float fh = SchlickFresnelReflectance(hdotwo); + float3 fs = mix(c_spec0, WHITE, fh); + + float gs; + gs = SmithGGX_G_Aniso(ndotwo, wo.x, wo.z, ax, ay); + gs *= SmithGGX_G_Aniso(ndotwi, wi.x, wi.z, ax, ay); + + // Sheen + float3 f_sheen = fh * sheen * c_sheen; + + // clearcoat (ior = 1.5 -> F0 = 0.04) + float dr = GTR1(ndoth, mix(0.1f,0.001f, clearcoat_gloss)); + float fr = mix(0.04f, 1.f, fh); + float gr = SmithGGX_G(ndotwo, 0.25f) * SmithGGX_G(ndotwi, 0.25f); + + return ((1.f / PI) * mix(fd, ss, subsurface) * cd_lin + f_sheen) * + (1.f - metallic) + gs * fs * ds + clearcoat * gr * fr * dr; +} + +INLINE float3 Disney_Sample( + // Geometry + DifferentialGeometry const* dg, + // Incoming direction + float3 wi, + // Texture args + TEXTURE_ARG_LIST, + // Sample + float2 sample, + // Outgoing direction + float3* wo, + // PDF at wo + float* pdf + ) +{ + float3 base_color = Texture_GetValue3f(dg->mat.disney.base_color.xyz, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.base_color_map_idx)); + float metallic = Texture_GetValue1f(dg->mat.disney.metallic, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.metallic_map_idx)); + float specular = Texture_GetValue1f(dg->mat.disney.specular, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.specular_map_idx)); + float anisotropy = Texture_GetValue1f(dg->mat.disney.anisotropy, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.anisotropy_map_idx)); + float roughness = Texture_GetValue1f(dg->mat.disney.roughness, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.roughness_map_idx)); + float specular_tint = Texture_GetValue1f(dg->mat.disney.specular_tint, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.specular_tint_map_idx)); + float sheen_tint = Texture_GetValue1f(dg->mat.disney.sheen_tint, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.sheen_tint_map_idx)); + float sheen = Texture_GetValue1f(dg->mat.disney.sheen, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.sheen_map_idx)); + float clearcoat_gloss = Texture_GetValue1f(dg->mat.disney.clearcoat_gloss, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.clearcoat_gloss_map_idx)); + float clearcoat = Texture_GetValue1f(dg->mat.disney.clearcoat, dg->uv, TEXTURE_ARGS_IDX(dg->mat.disney.clearcoat_map_idx)); + float subsurface = dg->mat.disney.subsurface; + + float ax = max(0.001f, roughness * roughness * ( 1.f + anisotropy)); + float ay = max(0.001f, roughness * roughness * ( 1.f - anisotropy)); + + float mis_weight = 1.f; + float3 wh; + + + if (sample.x < clearcoat) + { + sample.x /= (clearcoat); + + float a = mix(0.1f,0.001f, clearcoat_gloss); + float ndotwh = native_sqrt((1.f - native_powr(a*a, 1.f - sample.y)) / (1.f - a*a)); + float sintheta = native_sqrt(1.f - ndotwh * ndotwh); + wh = normalize(make_float3(native_cos(2.f * PI * sample.x) * sintheta, + ndotwh, + native_sin(2.f * PI * sample.x) * sintheta)); + + *wo = -wi + 2.f*fabs(dot(wi, wh)) * wh; + + } + else + { + sample.x -= (clearcoat); + sample.x /= (1.f - clearcoat); + + float3 cd_lin = native_powr(base_color, 2.2f); + // Luminance approximmation + float cd_lum = dot(cd_lin, make_float3(0.3f, 0.6f, 0.1f)); + + // Normalize lum. to isolate hue+sat + float3 c_tint = cd_lum > 0.f ? (cd_lin / cd_lum) : WHITE; + + float3 c_spec0 = mix(specular * 0.3f * mix(WHITE, + c_tint, specular_tint), + cd_lin, metallic); + + float cs_lum = dot(c_spec0, make_float3(0.3f, 0.6f, 0.1f)); + + float cs_w = cs_lum / (cs_lum + (1.f - metallic) * cd_lum); + + if (sample.y < cs_w) + { + sample.y /= cs_w; + + float t = native_sqrt(sample.y / (1.f - sample.y)); + wh = normalize(make_float3(t * ax * native_cos(2.f * PI * sample.x), + 1.f, + t * ay * native_sin(2.f * PI * sample.x))); + + *wo = -wi + 2.f*fabs(dot(wi, wh)) * wh; + } + else + { + sample.y -= cs_w; + sample.y /= (1.f - cs_w); + + *wo = Sample_MapToHemisphere(sample, make_float3(0.f, 1.f, 0.f) , 1.f); + + wh = normalize(*wo + wi); + } + } + + //float ndotwh = fabs(wh.y); + //float hdotwo = fabs(dot(wh, *wo)); + + *pdf = Disney_GetPdf(dg, wi, *wo, TEXTURE_ARGS); + + return Disney_Evaluate(dg, wi, *wo, TEXTURE_ARGS); +} + +#endif + diff --git a/Baikal/Kernels/CL/fill_aovs_uberv2.cl b/Baikal/Kernels/CL/fill_aovs_uberv2.cl new file mode 100644 index 00000000..9cfbafb5 --- /dev/null +++ b/Baikal/Kernels/CL/fill_aovs_uberv2.cl @@ -0,0 +1,452 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 MONTE_CARLO_RENDERER_CL +#define MONTE_CARLO_RENDERER_CL + +#include <../Baikal/Kernels/CL/common.cl> +#include <../Baikal/Kernels/CL/ray.cl> +#include <../Baikal/Kernels/CL/isect.cl> +#include <../Baikal/Kernels/CL/utils.cl> +#include <../Baikal/Kernels/CL/payload.cl> +#include <../Baikal/Kernels/CL/texture.cl> +#include <../Baikal/Kernels/CL/sampling.cl> +#include <../Baikal/Kernels/CL/bxdf.cl> +#include <../Baikal/Kernels/CL/light.cl> +#include <../Baikal/Kernels/CL/scene.cl> +#include <../Baikal/Kernels/CL/volumetrics.cl> +#include <../Baikal/Kernels/CL/path.cl> +#include <../Baikal/Kernels/CL/vertex.cl> + +#define CORRECT_VALUE(value)\ + if (any(isnan(value)) || (value.w == 0))\ + {\ + value = make_float4(0.f, 0.f, 0.f, 1.f);\ + } + +// Fill AOVs +KERNEL void FillAOVsUberV2( + // Ray batch + GLOBAL ray const* restrict rays, + // Intersection data + GLOBAL Intersection const* restrict isects, + // Pixel indices + GLOBAL int const* restrict pixel_idx, + // Number of pixels + GLOBAL int const* restrict num_items, + // Vertices + GLOBAL float3 const*restrict vertices, + // Normals + GLOBAL float3 const* restrict normals, + // UVs + GLOBAL float2 const* restrict uvs, + // Indices + GLOBAL int const* restrict indices, + // Shapes + GLOBAL Shape const* restrict shapes, + GLOBAL ShapeAdditionalData const* restrict shapes_additional, + // Materials + GLOBAL int const* restrict material_attributes, + // Textures + TEXTURE_ARG_LIST, + // Environment texture index + int env_light_idx, + // Background texture index + int background_idx, + // Output size + int width, + int height, + // Emissives + GLOBAL Light const* restrict lights, + // Number of emissive objects + int num_lights, + // camera + GLOBAL Camera const* restrict camera, + // RNG seed + uint rngseed, + // Sampler states + GLOBAL uint* restrict random, + // Sobol matrices + GLOBAL uint const* restrict sobol_mat, + // Frame + int frame, + // World position flag + int world_position_enabled, + // World position AOV + GLOBAL float4* restrict aov_world_position, + // World normal flag + int world_shading_normal_enabled, + // World normal AOV + GLOBAL float4* restrict aov_world_shading_normal, + // View normal flag + int view_shading_normal_enabled, + // View normal AOV + GLOBAL float4* restrict aov_view_shading_normal, + // World true normal flag + int world_geometric_normal_enabled, + // World true normal AOV + GLOBAL float4* restrict aov_world_geometric_normal, + // UV flag + int uv_enabled, + // UV AOV + GLOBAL float4* restrict aov_uv, + // Wireframe flag + int wireframe_enabled, + // Wireframe AOV + GLOBAL float4* restrict aov_wireframe, + // Albedo flag + int albedo_enabled, + // Wireframe AOV + GLOBAL float4* restrict aov_albedo, + // World tangent flag + int world_tangent_enabled, + // World tangent AOV + GLOBAL float4* restrict aov_world_tangent, + // World bitangent flag + int world_bitangent_enabled, + // World bitangent AOV + GLOBAL float4* restrict aov_world_bitangent, + // Gloss enabled flag + int gloss_enabled, + // Specularity map + GLOBAL float4* restrict aov_gloss, + // Mesh_id enabled flag + int mesh_id_enabled, + // Mesh_id AOV + GLOBAL float4* restrict mesh_id, + // Group id enabled flag + int group_id_enabled, + // Group id AOV + GLOBAL float4* restrict group_id, + // Background enabled flag + int background_enabled, + // Background aov + GLOBAL float4* restrict aov_background, + // Depth enabled flag + int depth_enabled, + // Depth map + GLOBAL float4* restrict aov_depth, + // Shape id map enabled flag + int shape_ids_enabled, + // Shape id map stores shape id in every pixel + // And negative number if there is no any shape in the pixel + GLOBAL float4* restrict aov_shape_ids, + GLOBAL InputMapData const* restrict input_map_values +) +{ + int global_id = get_global_id(0); + + Scene scene = + { + vertices, + normals, + uvs, + indices, + shapes, + material_attributes, + input_map_values, + lights, + env_light_idx, + num_lights + }; + + // Only applied to active rays after compaction + if (global_id < *num_items) + { + Intersection isect = isects[global_id]; + int idx = pixel_idx[global_id]; + + if (shape_ids_enabled) + aov_shape_ids[idx].x = -1; + + if (background_enabled) + { + if (background_idx != -1) + { + float x = (float)(idx % width) / (float)width; + float y = (float)(idx / width) / (float)height; + float2 uv = make_float2(x, y); + aov_background[idx].xyz += Texture_Sample2D(uv, TEXTURE_ARGS_IDX(background_idx)).xyz; + } + else if (env_light_idx != -1) + { + Light light = lights[env_light_idx]; + int tex = EnvironmentLight_GetBackgroundTexture(&light); + if (tex != -1) + { + aov_background[idx].xyz += light.multiplier * Texture_SampleEnvMap(rays[global_id].d.xyz, TEXTURE_ARGS_IDX(tex), light.ibl_mirror_x); + } + } + aov_background[idx].w += 1.0f; + CORRECT_VALUE(aov_background[idx]) + } + + if (isect.shapeid > -1) + { + // Fetch incoming ray direction + float3 wi = -normalize(rays[global_id].d.xyz); + + Sampler sampler; +#if SAMPLER == SOBOL + uint scramble = random[global_id] * 0x1fe3434f; + Sampler_Init(&sampler, frame, SAMPLE_DIM_SURFACE_OFFSET, scramble); +#elif SAMPLER == RANDOM + uint scramble = global_id * rngseed; + Sampler_Init(&sampler, scramble); +#elif SAMPLER == CMJ + uint rnd = random[global_id]; + uint scramble = rnd * 0x1fe3434f * ((frame + 331 * rnd) / (CMJ_DIM * CMJ_DIM)); + Sampler_Init(&sampler, frame % (CMJ_DIM * CMJ_DIM), SAMPLE_DIM_SURFACE_OFFSET, scramble); +#endif + + // Fill surface data + DifferentialGeometry diffgeo; + Scene_FillDifferentialGeometry(&scene, &isect, &diffgeo); + + if (world_position_enabled) + { + aov_world_position[idx].xyz += diffgeo.p; + aov_world_position[idx].w += 1.f; + CORRECT_VALUE(aov_world_position[idx]) + } + + if (world_shading_normal_enabled) + { + float ngdotwi = dot(diffgeo.ng, wi); + bool backfacing = ngdotwi < 0.f; + + // Select BxDF + UberV2ShaderData uber_shader_data; + UberV2PrepareInputs(&diffgeo, input_map_values, material_attributes, TEXTURE_ARGS, &uber_shader_data); + GetMaterialBxDFType(wi, &sampler, SAMPLER_ARGS, &diffgeo, &uber_shader_data); + + float s = Bxdf_IsBtdf(&diffgeo) ? (-sign(ngdotwi)) : 1.f; + if (backfacing && !Bxdf_IsBtdf(&diffgeo)) + { + //Reverse normal and tangents in this case + //but not for BTDFs, since BTDFs rely + //on normal direction in order to arrange + //indices of refraction + diffgeo.n = -diffgeo.n; + diffgeo.dpdu = -diffgeo.dpdu; + diffgeo.dpdv = -diffgeo.dpdv; + } + UberV2_ApplyShadingNormal(&diffgeo, &uber_shader_data); + DifferentialGeometry_CalculateTangentTransforms(&diffgeo); + + aov_world_shading_normal[idx].xyz += diffgeo.n; + aov_world_shading_normal[idx].w += 1.f; + CORRECT_VALUE(aov_world_shading_normal[idx]) + } + + if (world_geometric_normal_enabled) + { + aov_world_geometric_normal[idx].xyz += diffgeo.ng; + aov_world_geometric_normal[idx].w += 1.f; + CORRECT_VALUE(aov_world_geometric_normal[idx]) + } + + if (wireframe_enabled) + { + bool hit = (isect.uvwt.x < 1e-3) || (isect.uvwt.y < 1e-3) || (1.f - isect.uvwt.x - isect.uvwt.y < 1e-3); + float3 value = hit ? make_float3(1.f, 1.f, 1.f) : make_float3(0.f, 0.f, 0.f); + aov_wireframe[idx].xyz += value; + aov_wireframe[idx].w += 1.f; + CORRECT_VALUE(aov_wireframe[idx]) + } + + if (uv_enabled) + { + aov_uv[idx].xy += diffgeo.uv.xy; + aov_uv[idx].w += 1.f; + CORRECT_VALUE(aov_uv[idx]) + } + + if (albedo_enabled) + { + float ngdotwi = dot(diffgeo.ng, wi); + bool backfacing = ngdotwi < 0.f; + + // Select BxDF + UberV2ShaderData uber_shader_data; + UberV2PrepareInputs(&diffgeo, input_map_values, material_attributes, TEXTURE_ARGS, &uber_shader_data); + + const float3 kd = ((diffgeo.mat.layers & kDiffuseLayer) == kDiffuseLayer) ? + uber_shader_data.diffuse_color.xyz : (float3)(0.0f); + + aov_albedo[idx].xyz += kd; + aov_albedo[idx].w += 1.f; + CORRECT_VALUE(aov_albedo[idx]) + } + + if (world_tangent_enabled) + { + float ngdotwi = dot(diffgeo.ng, wi); + bool backfacing = ngdotwi < 0.f; + + // Select BxDF + UberV2ShaderData uber_shader_data; + UberV2PrepareInputs(&diffgeo, input_map_values, material_attributes, TEXTURE_ARGS, &uber_shader_data); + GetMaterialBxDFType(wi, &sampler, SAMPLER_ARGS, &diffgeo, &uber_shader_data); + + float s = Bxdf_IsBtdf(&diffgeo) ? (-sign(ngdotwi)) : 1.f; + if (backfacing && !Bxdf_IsBtdf(&diffgeo)) + { + //Reverse normal and tangents in this case + //but not for BTDFs, since BTDFs rely + //on normal direction in order to arrange + //indices of refraction + diffgeo.n = -diffgeo.n; + diffgeo.dpdu = -diffgeo.dpdu; + diffgeo.dpdv = -diffgeo.dpdv; + } + + UberV2_ApplyShadingNormal(&diffgeo, &uber_shader_data); + DifferentialGeometry_CalculateTangentTransforms(&diffgeo); + + aov_world_tangent[idx].xyz += diffgeo.dpdu; + aov_world_tangent[idx].w += 1.f; + CORRECT_VALUE(aov_world_tangent[idx]) + } + + if (world_bitangent_enabled) + { + float ngdotwi = dot(diffgeo.ng, wi); + bool backfacing = ngdotwi < 0.f; + + // Select BxDF + UberV2ShaderData uber_shader_data; + UberV2PrepareInputs(&diffgeo, input_map_values, material_attributes, TEXTURE_ARGS, &uber_shader_data); + GetMaterialBxDFType(wi, &sampler, SAMPLER_ARGS, &diffgeo, &uber_shader_data); + + float s = Bxdf_IsBtdf(&diffgeo) ? (-sign(ngdotwi)) : 1.f; + if (backfacing && !Bxdf_IsBtdf(&diffgeo)) + { + //Reverse normal and tangents in this case + //but not for BTDFs, since BTDFs rely + //on normal direction in order to arrange + //indices of refraction + diffgeo.n = -diffgeo.n; + diffgeo.dpdu = -diffgeo.dpdu; + diffgeo.dpdv = -diffgeo.dpdv; + } + + UberV2_ApplyShadingNormal(&diffgeo, &uber_shader_data); + DifferentialGeometry_CalculateTangentTransforms(&diffgeo); + + aov_world_bitangent[idx].xyz += diffgeo.dpdv; + aov_world_bitangent[idx].w += 1.f; + CORRECT_VALUE(aov_world_bitangent[idx]) + } + + if (gloss_enabled) + { + float ngdotwi = dot(diffgeo.ng, wi); + bool backfacing = ngdotwi < 0.f; + + // Select BxDF + UberV2ShaderData uber_shader_data; + UberV2PrepareInputs(&diffgeo, input_map_values, material_attributes, TEXTURE_ARGS, &uber_shader_data); + GetMaterialBxDFType(wi, &sampler, SAMPLER_ARGS, &diffgeo, &uber_shader_data); + + int sampled_component = Bxdf_UberV2_GetSampledComponent(&diffgeo); + + float gloss = 0.f; + if (sampled_component == kBxdfUberV2SampleCoating) + { + gloss = 1.0f; + } + else if (sampled_component == kBxdfUberV2SampleReflection) + { + gloss = 1.0f - uber_shader_data.reflection_roughness; + } + else if (sampled_component == kBxdfUberV2SampleRefraction) + { + gloss = 1.0f - uber_shader_data.refraction_roughness; + } + + aov_gloss[idx].xyz += gloss; + aov_gloss[idx].w += 1.f; + CORRECT_VALUE(aov_gloss[idx]) + } + + if (mesh_id_enabled) + { + Sampler shapeid_sampler; + shapeid_sampler.index = shapes[isect.shapeid - 1].id; + mesh_id[idx].xyz += clamp(make_float3(UniformSampler_Sample1D(&shapeid_sampler), + UniformSampler_Sample1D(&shapeid_sampler), + UniformSampler_Sample1D(&shapeid_sampler)), 0.0f, 1.0f); + mesh_id[idx].w += 1.0f; + CORRECT_VALUE(mesh_id[idx]) + } + + if (group_id_enabled) + { + Sampler groupid_sampler; + groupid_sampler.index = shapes_additional[isect.shapeid - 1].group_id; + group_id[idx].xyz += clamp(make_float3(UniformSampler_Sample1D(&groupid_sampler), + UniformSampler_Sample1D(&groupid_sampler), + UniformSampler_Sample1D(&groupid_sampler)), 0.0f, 1.0f); + group_id[idx].w += 1.0f; + CORRECT_VALUE(group_id[idx]) + } + + if (depth_enabled) + { + float w = aov_depth[idx].w; + if (w == 0.f) + { + aov_depth[idx].xyz = isect.uvwt.w; + aov_depth[idx].w = 1.f; + } + else + { + aov_depth[idx].xyz += isect.uvwt.w; + aov_depth[idx].w += 1.f; + } + CORRECT_VALUE(aov_depth[idx]) + } + + if (shape_ids_enabled) + { + aov_shape_ids[idx].x = shapes[isect.shapeid - 1].id; + } + + if (view_shading_normal_enabled) + { + float3 res = make_float3(dot(camera->right, diffgeo.n), + dot(camera->up, diffgeo.n), + dot(camera->forward, diffgeo.n)); + res = normalize(res); + + aov_view_shading_normal[idx].xyz += res; + aov_view_shading_normal[idx].w += 1.f; + + CORRECT_VALUE(aov_view_shading_normal[idx]) + } + } + } +} + + + +#endif // MONTE_CARLO_RENDERER_CL diff --git a/Baikal/CL/integrator_bdpt.cl b/Baikal/Kernels/CL/integrator_bdpt.cl similarity index 98% rename from Baikal/CL/integrator_bdpt.cl rename to Baikal/Kernels/CL/integrator_bdpt.cl index 5bc8aa32..0f105757 100644 --- a/Baikal/CL/integrator_bdpt.cl +++ b/Baikal/Kernels/CL/integrator_bdpt.cl @@ -19,22 +19,22 @@ 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 <../Baikal/CL/common.cl> -#include <../Baikal/CL/ray.cl> -#include <../Baikal/CL/isect.cl> -#include <../Baikal/CL/utils.cl> -#include <../Baikal/CL/payload.cl> -#include <../Baikal/CL/texture.cl> -#include <../Baikal/CL/sampling.cl> -#include <../Baikal/CL/normalmap.cl> -#include <../Baikal/CL/bxdf.cl> -#include <../Baikal/CL/light.cl> -#include <../Baikal/CL/camera.cl> -#include <../Baikal/CL/scene.cl> -#include <../Baikal/CL/material.cl> -#include <../Baikal/CL/volumetrics.cl> -#include <../Baikal/CL/path.cl> -#include <../Baikal/CL/vertex.cl> +#ifndef INTEGRATOR_BDPT_CL +#define INTEGRATOR_BDPT_CL + +#include <../Baikal/Kernels/CL/common.cl> +#include <../Baikal/Kernels/CL/ray.cl> +#include <../Baikal/Kernels/CL/isect.cl> +#include <../Baikal/Kernels/CL/utils.cl> +#include <../Baikal/Kernels/CL/payload.cl> +#include <../Baikal/Kernels/CL/texture.cl> +#include <../Baikal/Kernels/CL/sampling.cl> +#include <../Baikal/Kernels/CL/bxdf.cl> +#include <../Baikal/Kernels/CL/light.cl> +#include <../Baikal/Kernels/CL/scene.cl> +#include <../Baikal/Kernels/CL/volumetrics.cl> +#include <../Baikal/Kernels/CL/path.cl> +#include <../Baikal/Kernels/CL/vertex.cl> // Convert PDF of sampling point po from point p from solid angle measure to area measure INLINE @@ -100,7 +100,7 @@ KERNEL void GenerateLightVertices( num_lights }; - int global_id = get_global_id(0); + int global_id = get_global_id(0); // Check borders if (global_id < num_subpaths) @@ -1059,5 +1059,5 @@ KERNEL void ConnectCaustics( image_plane_positions[global_id] = impuv; } - +#endif diff --git a/Baikal/CL/isect.cl b/Baikal/Kernels/CL/isect.cl similarity index 100% rename from Baikal/CL/isect.cl rename to Baikal/Kernels/CL/isect.cl diff --git a/Baikal/CL/light.cl b/Baikal/Kernels/CL/light.cl similarity index 81% rename from Baikal/CL/light.cl rename to Baikal/Kernels/CL/light.cl index 67bcaf92..a6fe8a81 100644 --- a/Baikal/CL/light.cl +++ b/Baikal/Kernels/CL/light.cl @@ -22,11 +22,19 @@ THE SOFTWARE. #ifndef LIGHT_CL #define LIGHT_CL -#include <../Baikal/CL/utils.cl> -#include <../Baikal/CL/payload.cl> -#include <../Baikal/CL/texture.cl> -#include <../Baikal/CL/scene.cl> - +#include <../Baikal/Kernels/CL/utils.cl> +#include <../Baikal/Kernels/CL/payload.cl> +#include <../Baikal/Kernels/CL/texture.cl> +#include <../Baikal/Kernels/CL/scene.cl> +#include <../Baikal/Kernels/CL/path.cl> +#include <../Baikal/Kernels/CL/bxdf.cl> + +enum LightInteractionType +{ + kLightInteractionUnknown, + kLightInteractionSurface, + kLightInteractionVolume +}; INLINE bool IntersectTriangle(ray const* r, float3 v1, float3 v2, float3 v3, float* a, float* b) @@ -53,6 +61,27 @@ bool IntersectTriangle(ray const* r, float3 v1, float3 v2, float3 v3, float* a, } } +INLINE int EnvironmentLight_GetTexture(Light const* light, int bxdf_flags) +{ + int tex = light->tex; + + if ((bxdf_flags & kBxdfFlagsBrdf) && (light->tex_reflection != -1) && ((bxdf_flags & kBxdfFlagsDiffuse) != kBxdfFlagsDiffuse)) + tex = light->tex_reflection; + + if (((bxdf_flags & kBxdfFlagsBrdf) == 0) && light->tex_refraction != -1) + tex = light->tex_refraction; + + if ((bxdf_flags & kBxdfFlagsTransparency) && light->tex_transparency != -1) + tex = light->tex_transparency; + + return tex; +} + +INLINE int EnvironmentLight_GetBackgroundTexture(Light const* light) +{ + return light->tex_background == -1 ? light->tex : light->tex_background; +} + /* Environment light */ @@ -63,6 +92,10 @@ float3 EnvironmentLight_GetLe(// Light Scene const* scene, // Geometry DifferentialGeometry const* dg, + // Path flags + int bxdf_flags, + // Light inteaction type + int interaction_type, // Direction to light source float3* wo, // Textures @@ -70,9 +103,16 @@ float3 EnvironmentLight_GetLe(// Light ) { // Sample envmap - *wo *= 100000.f; - // - return light->multiplier * Texture_SampleEnvMap(normalize(*wo), TEXTURE_ARGS_IDX(light->multiplier)); + *wo *= CRAZY_HIGH_DISTANCE; + + int tex = EnvironmentLight_GetTexture(light, bxdf_flags); + + if (tex == -1) + { + return 0.f; + } + + return light->multiplier * Texture_SampleEnvMap(normalize(*wo), TEXTURE_ARGS_IDX(tex), light->ibl_mirror_x); } /// Sample direction to the light @@ -86,22 +126,42 @@ float3 EnvironmentLight_Sample(// Light TEXTURE_ARG_LIST, // Sample float2 sample, + // Path flags + int bxdf_flags, + // Light inteaction type + int interaction_type, // Direction to light source float3* wo, // PDF float* pdf ) { - float3 d = Sample_MapToHemisphere(sample, dg->n, 1.f); + float3 d; + + if (interaction_type != kLightInteractionVolume) + { + d = Sample_MapToHemisphere(sample, dg->n, 0.f); + *pdf = 1.f / (2.f * PI); + } + else + { + d = Sample_MapToSphere(sample); + *pdf = 1.f / (4.f * PI); + } // Generate direction - *wo = 100000.f * d; + *wo = CRAZY_HIGH_DISTANCE * d; + + int tex = EnvironmentLight_GetTexture(light, bxdf_flags); - // Envmap PDF - *pdf = fabs(dot(dg->n, normalize(d))) / PI; + if (tex == -1) + { + *pdf = 0.f; + return 0.f; + } // Sample envmap - return light->multiplier * Texture_SampleEnvMap(d, TEXTURE_ARGS_IDX(light->multiplier)); + return light->multiplier * Texture_SampleEnvMap(d, TEXTURE_ARGS_IDX(tex), light->ibl_mirror_x); } /// Get PDF for a given direction @@ -112,13 +172,24 @@ float EnvironmentLight_GetPdf( Scene const* scene, // Geometry DifferentialGeometry const* dg, + // Path flags + int bxdf_flags, + // Light inteaction type + int interaction_type, // Direction to light source float3 wo, // Textures TEXTURE_ARG_LIST ) { - return max(0.f, fabs(dot(dg->n, normalize(wo)))/ PI); + if (interaction_type != kLightInteractionVolume) + { + return 1.f / (2.f * PI); + } + else + { + return 1.f / (4.f * PI); + } } @@ -160,10 +231,10 @@ float3 AreaLight_GetLe(// Emissive object float3 d = p - dg->p; *wo = d; - int mat_idx = Scene_GetMaterialIndex(scene, shapeidx, primidx); - Material mat = scene->materials[mat_idx]; + int material_offset = scene->shapes[shapeidx].material.offset; - const float3 ke = Texture_GetValue3f(mat.kx.xyz, tx, TEXTURE_ARGS_IDX(mat.kxmapidx)); + const float3 ke = GetUberV2EmissionColor(material_offset, dg, scene->input_map_values, scene->material_attributes, TEXTURE_ARGS).xyz; + return ke; } else @@ -197,7 +268,8 @@ float3 AreaLight_Sample(// Emissive object // Convert random to barycentric coords float2 uv; - uv.x = native_sqrt(r0) * (1.f - r1); + + uv.x = 1.f - native_sqrt(r0); uv.y = native_sqrt(r0) * r1; float3 n; @@ -208,11 +280,9 @@ float3 AreaLight_Sample(// Emissive object *wo = p - dg->p; - int mat_idx = Scene_GetMaterialIndex(scene, shapeidx, primidx); - Material mat = scene->materials[mat_idx]; - - const float3 ke = Texture_GetValue3f(mat.kx.xyz, tx, TEXTURE_ARGS_IDX(mat.kxmapidx)); + int material_offset = scene->shapes[shapeidx].material.offset; + const float3 ke = GetUberV2EmissionColor(material_offset, dg, scene->input_map_values, scene->material_attributes, TEXTURE_ARGS).xyz; float3 v = -normalize(*wo); float ndotv = dot(n, v); @@ -222,7 +292,7 @@ float3 AreaLight_Sample(// Emissive object float dist2 = dot(*wo, *wo); float denom = fabs(ndotv) * area; *pdf = denom > 0.f ? dist2 / denom : 0.f; - return dist2 > 0.f ? ke * ndotv / dist2 : 0.f; + return ke; } else { @@ -309,11 +379,10 @@ float3 AreaLight_SampleVertex( float area; Scene_InterpolateAttributes(scene, shapeidx, primidx, uv, p, n, &tx, &area); - int mat_idx = Scene_GetMaterialIndex(scene, shapeidx, primidx); - Material mat = scene->materials[mat_idx]; - - const float3 ke = Texture_GetValue3f(mat.kx.xyz, tx, TEXTURE_ARGS_IDX(mat.kxmapidx)); + int material_offset = scene->shapes[shapeidx].material.offset; + /*const float3 ke = GetUberV2EmissionColor(material_offset, dg, scene->input_map_values, scene->material_attributes, TEXTURE_ARGS).xyz;*/ + const float3 ke = make_float3(0.f, 0.f, 0.f); *wo = Sample_MapToHemisphere(sample1, *n, 1.f); *pdf = (1.f / area) * fabs(dot(*n, *wo)) / PI; @@ -355,7 +424,7 @@ float3 DirectionalLight_Sample(// Emissive object // PDF float* pdf) { - *wo = 100000.f * -light->d; + *wo = CRAZY_HIGH_DISTANCE * -light->d; *pdf = 1.f; return light->intensity; } @@ -536,6 +605,10 @@ float3 Light_GetLe(// Light index Scene const* scene, // Geometry DifferentialGeometry const* dg, + // Path flags + int bxdf_flags, + // Light inteaction type + int interaction_type, // Direction to light source float3* wo, // Textures @@ -547,7 +620,7 @@ float3 Light_GetLe(// Light index switch(light.type) { case kIbl: - return EnvironmentLight_GetLe(&light, scene, dg, wo, TEXTURE_ARGS); + return EnvironmentLight_GetLe(&light, scene, dg, bxdf_flags, interaction_type, wo, TEXTURE_ARGS); case kArea: return AreaLight_GetLe(&light, scene, dg, wo, TEXTURE_ARGS); case kDirectional: @@ -572,6 +645,10 @@ float3 Light_Sample(// Light index TEXTURE_ARG_LIST, // Sample float2 sample, + // Path flags + int bxdf_flags, + // Light inteaction type + int interaction_type, // Direction to light source float3* wo, // PDF @@ -582,7 +659,7 @@ float3 Light_Sample(// Light index switch(light.type) { case kIbl: - return EnvironmentLight_Sample(&light, scene, dg, TEXTURE_ARGS, sample, wo, pdf); + return EnvironmentLight_Sample(&light, scene, dg, TEXTURE_ARGS, sample, bxdf_flags, interaction_type, wo, pdf); case kArea: return AreaLight_Sample(&light, scene, dg, TEXTURE_ARGS, sample, wo, pdf); case kDirectional: @@ -604,6 +681,10 @@ float Light_GetPdf(// Light index Scene const* scene, // Geometry DifferentialGeometry const* dg, + // Path flags + int bxdf_flags, + // Light inteaction type + int interaction_type, // Direction to light source float3 wo, // Textures @@ -615,7 +696,7 @@ float Light_GetPdf(// Light index switch(light.type) { case kIbl: - return EnvironmentLight_GetPdf(&light, scene, dg, wo, TEXTURE_ARGS); + return EnvironmentLight_GetPdf(&light, scene, dg, bxdf_flags, interaction_type, wo, TEXTURE_ARGS); case kArea: return AreaLight_GetPdf(&light, scene, dg, wo, TEXTURE_ARGS); case kDirectional: diff --git a/Baikal/Kernels/CL/monte_carlo_renderer.cl b/Baikal/Kernels/CL/monte_carlo_renderer.cl new file mode 100644 index 00000000..07c07b33 --- /dev/null +++ b/Baikal/Kernels/CL/monte_carlo_renderer.cl @@ -0,0 +1,908 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 MONTE_CARLO_RENDERER_CL +#define MONTE_CARLO_RENDERER_CL + +#include <../Baikal/Kernels/CL/common.cl> +#include <../Baikal/Kernels/CL/ray.cl> +#include <../Baikal/Kernels/CL/isect.cl> +#include <../Baikal/Kernels/CL/utils.cl> +#include <../Baikal/Kernels/CL/payload.cl> +#include <../Baikal/Kernels/CL/texture.cl> +#include <../Baikal/Kernels/CL/sampling.cl> +#include <../Baikal/Kernels/CL/scene.cl> +#include <../Baikal/Kernels/CL/volumetrics.cl> +#include <../Baikal/Kernels/CL/path.cl> +#include <../Baikal/Kernels/CL/vertex.cl> + +// Pinhole camera implementation. +// This kernel is being used if aperture value = 0. +KERNEL +void PerspectiveCamera_GeneratePaths( + // Camera + GLOBAL Camera const* restrict camera, + // Image resolution + int output_width, + int output_height, + // Pixel domain buffer + GLOBAL int const* restrict pixel_idx, + // Size of pixel domain buffer + GLOBAL int const* restrict num_pixels, + // RNG seed value + uint rng_seed, + // Current frame + uint frame, + // Rays to generate + GLOBAL ray* restrict rays, + // RNG data + GLOBAL uint* restrict random, + GLOBAL uint const* restrict sobol_mat +) +{ + int global_id = get_global_id(0); + + // Check borders + if (global_id < *num_pixels) + { + int idx = pixel_idx[global_id]; + int y = idx / output_width; + int x = idx % output_width; + + // Get pointer to ray & path handles + GLOBAL ray* my_ray = rays + global_id; + + // Initialize sampler + Sampler sampler; +#if SAMPLER == SOBOL + uint scramble = random[x + output_width * y] * 0x1fe3434f; + + if (frame & 0xF) + { + random[x + output_width * y] = WangHash(scramble); + } + + Sampler_Init(&sampler, frame, SAMPLE_DIM_CAMERA_OFFSET, scramble); +#elif SAMPLER == RANDOM + uint scramble = x + output_width * y * rng_seed; + Sampler_Init(&sampler, scramble); +#elif SAMPLER == CMJ + uint rnd = random[x + output_width * y]; + uint scramble = rnd * 0x1fe3434f * ((frame + 133 * rnd) / (CMJ_DIM * CMJ_DIM)); + Sampler_Init(&sampler, frame % (CMJ_DIM * CMJ_DIM), SAMPLE_DIM_CAMERA_OFFSET, scramble); +#endif + + // Generate sample +#ifndef BAIKAL_GENERATE_SAMPLE_AT_PIXEL_CENTER + float2 sample0 = Sampler_Sample2D(&sampler, SAMPLER_ARGS); +#else + float2 sample0 = make_float2(0.5f, 0.5f); +#endif + + // Calculate [0..1] image plane sample + float2 img_sample; + img_sample.x = (float)x / output_width + sample0.x / output_width; + img_sample.y = (float)y / output_height + sample0.y / output_height; + + // Transform into [-0.5, 0.5] + float2 h_sample = img_sample - make_float2(0.5f, 0.5f); + // Transform into [-dim/2, dim/2] + float2 c_sample = h_sample * camera->dim; + + // Calculate direction to image plane + my_ray->d.xyz = normalize(camera->focal_length * camera->forward + c_sample.x * camera->right + c_sample.y * camera->up); + // Origin == camera position + nearz * d + my_ray->o.xyz = camera->p + camera->zcap.x * my_ray->d.xyz; + // Max T value = zfar - znear since we moved origin to znear + my_ray->o.w = camera->zcap.y - camera->zcap.x; + // Generate random time from 0 to 1 + my_ray->d.w = sample0.x; + // Set ray max + my_ray->extra.x = 0xFFFFFFFF; + my_ray->extra.y = 0xFFFFFFFF; + Ray_SetExtra(my_ray, 1.f); + Ray_SetMask(my_ray, VISIBILITY_MASK_PRIMARY); + } +} + +// Physical camera implemenation. +// This kernel is being used if aperture > 0. +KERNEL void PerspectiveCameraDof_GeneratePaths( + // Camera + GLOBAL Camera const* restrict camera, + // Image resolution + int output_width, + int output_height, + // Pixel domain buffer + GLOBAL int const* restrict pixel_idx, + // Size of pixel domain buffer + GLOBAL int const* restrict num_pixels, + // RNG seed value + uint rng_seed, + // Current frame + uint frame, + // Rays to generate + GLOBAL ray* restrict rays, + // RNG data + GLOBAL uint* restrict random, + GLOBAL uint const* restrict sobol_mat +) +{ + int global_id = get_global_id(0); + + // Check borders + if (global_id < *num_pixels) + { + int idx = pixel_idx[global_id]; + int y = idx / output_width; + int x = idx % output_width; + + // Get pointer to ray & path handles + GLOBAL ray* my_ray = rays + global_id; + + // Initialize sampler + Sampler sampler; +#if SAMPLER == SOBOL + uint scramble = random[x + output_width * y] * 0x1fe3434f; + + if (frame & 0xF) + { + random[x + output_width * y] = WangHash(scramble); + } + + Sampler_Init(&sampler, frame, SAMPLE_DIM_CAMERA_OFFSET, scramble); +#elif SAMPLER == RANDOM + uint scramble = x + output_width * y * rng_seed; + Sampler_Init(&sampler, scramble); +#elif SAMPLER == CMJ + uint rnd = random[x + output_width * y]; + uint scramble = rnd * 0x1fe3434f * ((frame + 133 * rnd) / (CMJ_DIM * CMJ_DIM)); + Sampler_Init(&sampler, frame % (CMJ_DIM * CMJ_DIM), SAMPLE_DIM_CAMERA_OFFSET, scramble); +#endif + + // Generate pixel and lens samples +#ifndef BAIKAL_GENERATE_SAMPLE_AT_PIXEL_CENTER + float2 sample0 = Sampler_Sample2D(&sampler, SAMPLER_ARGS); +#else + float2 sample0 = make_float2(0.5f, 0.5f); +#endif + float2 sample1 = Sampler_Sample2D(&sampler, SAMPLER_ARGS); + + // Calculate [0..1] image plane sample + float2 img_sample; + img_sample.x = (float)x / output_width + sample0.x / output_width; + img_sample.y = (float)y / output_height + sample0.y / output_height; + + // Transform into [-0.5, 0.5] + float2 h_sample = img_sample - make_float2(0.5f, 0.5f); + // Transform into [-dim/2, dim/2] + float2 c_sample = h_sample * camera->dim; + + // Generate sample on the lens + float2 lens_sample = camera->aperture * Sample_MapToDiskConcentric(sample1); + // Calculate position on focal plane + float2 focal_plane_sample = c_sample * camera->focus_distance / camera->focal_length; + // Calculate ray direction + float2 camera_dir = focal_plane_sample - lens_sample; + + // Calculate direction to image plane + my_ray->d.xyz = normalize(camera->forward * camera->focus_distance + camera->right * camera_dir.x + camera->up * camera_dir.y); + // Origin == camera position + nearz * d + my_ray->o.xyz = camera->p + lens_sample.x * camera->right + lens_sample.y * camera->up; + // Max T value = zfar - znear since we moved origin to znear + my_ray->o.w = camera->zcap.y - camera->zcap.x; + // Generate random time from 0 to 1 + my_ray->d.w = sample0.x; + // Set ray max + my_ray->extra.x = 0xFFFFFFFF; + my_ray->extra.y = 0xFFFFFFFF; + Ray_SetExtra(my_ray, 1.f); + Ray_SetMask(my_ray, VISIBILITY_MASK_PRIMARY); + } +} + + +KERNEL +void PerspectiveCamera_GenerateVertices( + // Camera + GLOBAL Camera const* restrict camera, + // Image resolution + int output_width, + int output_height, + // Pixel domain buffer + GLOBAL int const* restrict pixel_idx, + // Size of pixel domain buffer + GLOBAL int const* restrict num_pixels, + // RNG seed value + uint rng_seed, + // Current frame + uint frame, + // RNG data + GLOBAL uint* restrict random, + GLOBAL uint const* restrict sobol_mat, + // Rays to generate + GLOBAL ray* restrict rays, + // Eye subpath vertices + GLOBAL PathVertex* restrict eye_subpath, + // Eye subpath length + GLOBAL int* restrict eye_subpath_length, + // Path buffer + GLOBAL Path* restrict paths +) + +{ + int global_id = get_global_id(0); + + // Check borders + if (global_id < *num_pixels) + { + int idx = pixel_idx[global_id]; + int y = idx / output_width; + int x = idx % output_width; + + // Get pointer to ray & path handles + GLOBAL ray* my_ray = rays + global_id; + + GLOBAL PathVertex* my_vertex = eye_subpath + BDPT_MAX_SUBPATH_LEN * idx; + GLOBAL int* my_count = eye_subpath_length + idx; + GLOBAL Path* my_path = paths + idx; + + // Initialize sampler + Sampler sampler; +#if SAMPLER == SOBOL + uint scramble = random[x + output_width * y] * 0x1fe3434f; + + if (frame & 0xF) + { + random[x + output_width * y] = WangHash(scramble); + } + + Sampler_Init(&sampler, frame, SAMPLE_DIM_CAMERA_OFFSET, scramble); +#elif SAMPLER == RANDOM + uint scramble = x + output_width * y * rng_seed; + Sampler_Init(&sampler, scramble); +#elif SAMPLER == CMJ + uint rnd = random[x + output_width * y]; + uint scramble = rnd * 0x1fe3434f * ((frame + 133 * rnd) / (CMJ_DIM * CMJ_DIM)); + Sampler_Init(&sampler, frame % (CMJ_DIM * CMJ_DIM), SAMPLE_DIM_CAMERA_OFFSET, scramble); +#endif + + // Generate sample + float2 sample0 = Sampler_Sample2D(&sampler, SAMPLER_ARGS); + + // Calculate [0..1] image plane sample + float2 img_sample; + img_sample.x = (float)x / output_width + sample0.x / output_width; + img_sample.y = (float)y / output_height + sample0.y / output_height; + + // Transform into [-0.5, 0.5] + float2 h_sample = img_sample - make_float2(0.5f, 0.5f); + // Transform into [-dim/2, dim/2] + float2 c_sample = h_sample * camera->dim; + + // Calculate direction to image plane + my_ray->d.xyz = normalize(camera->focal_length * camera->forward + c_sample.x * camera->right + c_sample.y * camera->up); + // Origin == camera position + nearz * d + my_ray->o.xyz = camera->p + camera->zcap.x * my_ray->d.xyz; + // Max T value = zfar - znear since we moved origin to znear + my_ray->o.w = camera->zcap.y - camera->zcap.x; + // Generate random time from 0 to 1 + my_ray->d.w = sample0.x; + // Set ray max + my_ray->extra.x = 0xFFFFFFFF; + my_ray->extra.y = 0xFFFFFFFF; + Ray_SetExtra(my_ray, 1.f); + + PathVertex v; + PathVertex_Init(&v, + camera->p, + camera->forward, + camera->forward, + 0.f, + 1.f, + 1.f, + 1.f, + kCamera, + -1); + + *my_count = 1; + *my_vertex = v; + + // Initlize path data + my_path->throughput = make_float3(1.f, 1.f, 1.f); + my_path->volume = -1; + my_path->flags = 0; + my_path->active = 0xFF; + } +} + +KERNEL +void PerspectiveCameraDof_GenerateVertices( + // Camera + GLOBAL Camera const* restrict camera, + // Image resolution + int output_width, + int output_height, + // Pixel domain buffer + GLOBAL int const* restrict pixel_idx, + // Size of pixel domain buffer + GLOBAL int const* restrict num_pixels, + // RNG seed value + uint rng_seed, + // Current frame + uint frame, + // RNG data + GLOBAL uint* restrict random, + GLOBAL uint const* restrict sobol_mat, + // Rays to generate + GLOBAL ray* restrict rays, + // Eye subpath vertices + GLOBAL PathVertex* restrict eye_subpath, + // Eye subpath length + GLOBAL int* restrict eye_subpath_length, + // Path buffer + GLOBAL Path* restrict paths +) + +{ + int global_id = get_global_id(0); + + // Check borders + if (global_id < *num_pixels) + { + int idx = pixel_idx[global_id]; + int y = idx / output_width; + int x = idx % output_width; + + // Get pointer to ray & path handles + GLOBAL ray* my_ray = rays + global_id; + GLOBAL PathVertex* my_vertex = eye_subpath + BDPT_MAX_SUBPATH_LEN * (y * output_width + x); + GLOBAL int* my_count = eye_subpath_length + y * output_width + x; + GLOBAL Path* my_path = paths + y * output_width + x; + + // Initialize sampler + Sampler sampler; +#if SAMPLER == SOBOL + uint scramble = random[x + output_width * y] * 0x1fe3434f; + + if (frame & 0xF) + { + random[x + output_width * y] = WangHash(scramble); + } + + Sampler_Init(&sampler, frame, SAMPLE_DIM_CAMERA_OFFSET, scramble); +#elif SAMPLER == RANDOM + uint scramble = x + output_width * y * rng_seed; + Sampler_Init(&sampler, scramble); +#elif SAMPLER == CMJ + uint rnd = random[x + output_width * y]; + uint scramble = rnd * 0x1fe3434f * ((frame + 133 * rnd) / (CMJ_DIM * CMJ_DIM)); + Sampler_Init(&sampler, frame % (CMJ_DIM * CMJ_DIM), SAMPLE_DIM_CAMERA_OFFSET, scramble); +#endif + + // Generate pixel and lens samples + float2 sample0 = Sampler_Sample2D(&sampler, SAMPLER_ARGS); + float2 sample1 = Sampler_Sample2D(&sampler, SAMPLER_ARGS); + + // Calculate [0..1] image plane sample + float2 img_sample; + img_sample.x = (float)x / output_width + sample0.x / output_width; + img_sample.y = (float)y / output_height + sample0.y / output_height; + + // Transform into [-0.5, 0.5] + float2 h_sample = img_sample - make_float2(0.5f, 0.5f); + // Transform into [-dim/2, dim/2] + float2 c_sample = h_sample * camera->dim; + + // Generate sample on the lens + float2 lens_sample = camera->aperture * Sample_MapToDiskConcentric(sample1); + // Calculate position on focal plane + float2 focal_plane_sample = c_sample * camera->focus_distance / camera->focal_length; + // Calculate ray direction + float2 camera_dir = focal_plane_sample - lens_sample; + + // Calculate direction to image plane + my_ray->d.xyz = normalize(camera->forward * camera->focus_distance + camera->right * camera_dir.x + camera->up * camera_dir.y); + // Origin == camera position + nearz * d + my_ray->o.xyz = camera->p + lens_sample.x * camera->right + lens_sample.y * camera->up; + // Max T value = zfar - znear since we moved origin to znear + my_ray->o.w = camera->zcap.y - camera->zcap.x; + // Generate random time from 0 to 1 + my_ray->d.w = sample0.x; + // Set ray max + my_ray->extra.x = 0xFFFFFFFF; + my_ray->extra.y = 0xFFFFFFFF; + Ray_SetExtra(my_ray, 1.f); + + PathVertex v; + PathVertex_Init(&v, + camera->p, + camera->forward, + camera->forward, + 0.f, + 1.f, + 1.f, + 1.f, + kCamera, + -1); + + *my_count = 1; + *my_vertex = v; + + // Initlize path data + my_path->throughput = make_float3(1.f, 1.f, 1.f); + my_path->volume = -1; + my_path->flags = 0; + my_path->active = 0xFF; + } +} + +uint Part1By1(uint x) +{ + x &= 0x0000ffff; // x = ---- ---- ---- ---- fedc ba98 7654 3210 + x = (x ^ (x << 8)) & 0x00ff00ff; // x = ---- ---- fedc ba98 ---- ---- 7654 3210 + x = (x ^ (x << 4)) & 0x0f0f0f0f; // x = ---- fedc ---- ba98 ---- 7654 ---- 3210 + x = (x ^ (x << 2)) & 0x33333333; // x = --fe --dc --ba --98 --76 --54 --32 --10 + x = (x ^ (x << 1)) & 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0 + return x; +} + +uint Morton2D(uint x, uint y) +{ + return (Part1By1(y) << 1) + Part1By1(x); +} + +KERNEL void GenerateTileDomain( + int output_width, + int output_height, + int offset_x, + int offset_y, + int width, + int height, + uint rng_seed, + uint frame, + GLOBAL uint* restrict random, + GLOBAL uint const* restrict sobol_mat, + GLOBAL int* restrict indices, + GLOBAL int* restrict count +) +{ + int2 global_id; + global_id.x = get_global_id(0); + global_id.y = get_global_id(1); + + int2 local_id; + local_id.x = get_local_id(0); + local_id.y = get_local_id(1); + + int2 group_id; + group_id.x = get_group_id(0); + group_id.y = get_group_id(1); + + int2 tile_size; + tile_size.x = get_local_size(0); + tile_size.y = get_local_size(1); + + int num_tiles_x = output_width / tile_size.x; + int num_tiles_y = output_height / tile_size.y; + + int start_idx = output_width * offset_y + offset_x; + + if (global_id.x < width && global_id.y < height) + { + int idx = start_idx + + (group_id.y * tile_size.y + local_id.y) * output_width + + (group_id.x * tile_size.x + local_id.x); + + indices[global_id.y * width + global_id.x] = idx; + } + + if (global_id.x == 0 && global_id.y == 0) + { + *count = width * height; + } +} + +KERNEL void GenerateTileDomain_Adaptive( + int output_width, + int output_height, + int offset_x, + int offset_y, + int width, + int height, + uint rng_seed, + uint frame, + GLOBAL uint* restrict random, + GLOBAL uint const* restrict sobol_mat, + GLOBAL int const* restrict tile_distribution, + GLOBAL int* restrict indices, + GLOBAL int* restrict count +) +{ + int2 global_id; + global_id.x = get_global_id(0); + global_id.y = get_global_id(1); + + int2 local_id; + local_id.x = get_local_id(0); + local_id.y = get_local_id(1); + + int2 group_id; + group_id.x = get_group_id(0); + group_id.y = get_group_id(1); + + int2 tile_size; + tile_size.x = get_local_size(0); + tile_size.y = get_local_size(1); + + + // Initialize sampler + Sampler sampler; + int x = global_id.x; + int y = global_id.y; +#if SAMPLER == SOBOL + uint scramble = random[x + output_width * y] * 0x1fe3434f; + + if (frame & 0xF) + { + random[x + output_width * y] = WangHash(scramble); + } + + Sampler_Init(&sampler, frame, SAMPLE_DIM_IMG_PLANE_EVALUATE_OFFSET, scramble); +#elif SAMPLER == RANDOM + uint scramble = x + output_width * y * rng_seed; + Sampler_Init(&sampler, scramble); +#elif SAMPLER == CMJ + uint rnd = random[group_id.x + output_width *group_id.y]; + uint scramble = rnd * 0x1fe3434f * ((frame + 133 * rnd) / (CMJ_DIM * CMJ_DIM)); + Sampler_Init(&sampler, frame % (CMJ_DIM * CMJ_DIM), SAMPLE_DIM_IMG_PLANE_EVALUATE_OFFSET, scramble); +#endif + + float2 sample = Sampler_Sample2D(&sampler, SAMPLER_ARGS); + + float pdf; + int tile = Distribution1D_SampleDiscrete(sample.x, tile_distribution, &pdf); + + int num_tiles_x = output_width / tile_size.x; + int num_tiles_y = output_height / tile_size.y; + + int tile_y = clamp(tile / num_tiles_x , 0, num_tiles_y - 1); + int tile_x = clamp(tile % num_tiles_x, 0, num_tiles_x - 1); + + int start_idx = output_width * offset_y + offset_x; + + if (global_id.x < width && global_id.y < height) + { + int idx = start_idx + + (tile_y * tile_size.y + local_id.y) * output_width + + (tile_x * tile_size.x + local_id.x); + + indices[global_id.y * width + global_id.x] = idx; + } + + if (global_id.x == 0 && global_id.y == 0) + { + *count = width * height; + } +} + +// Copy data to interop texture if supported +KERNEL void AccumulateData( + GLOBAL float4 const* src_data, + int num_elements, + GLOBAL float4* dst_data +) +{ + int global_id = get_global_id(0); + + if (global_id < num_elements) + { + float4 v = src_data[global_id]; + dst_data[global_id] += v; + } +} + +//#define ADAPTIVITY_DEBUG +// Copy data to interop texture if supported +KERNEL void ApplyGammaAndCopyData( + GLOBAL float4 const* data, + int img_width, + int img_height, + float gamma, + write_only image2d_t img +) +{ + int global_id = get_global_id(0); + + int global_idx = global_id % img_width; + int global_idy = global_id / img_width; + + if (global_idx < img_width && global_idy < img_height) + { + float4 v = data[global_id]; +#ifdef ADAPTIVITY_DEBUG + float a = v.w < 1024 ? min(1.f, v.w / 1024.f) : 0.f; + float4 mul_color = make_float4(1.f, 1.f - a, 1.f - a, 1.f); + v *= mul_color; +#endif + + float4 val = clamp(native_powr(v / v.w, 1.f / gamma), 0.f, 1.f); + write_imagef(img, make_int2(global_idx, global_idy), val); + } +} + +KERNEL void AccumulateSingleSample( + GLOBAL float4 const* restrict src_sample_data, + GLOBAL float4* restrict dst_accumulation_data, + GLOBAL int* restrict scatter_indices, + int num_elements +) +{ + int global_id = get_global_id(0); + + if (global_id < num_elements) + { + int idx = scatter_indices[global_id]; + float4 sample = src_sample_data[global_id]; + dst_accumulation_data[idx].xyz += sample.xyz; + dst_accumulation_data[idx].w += 1.f; + } +} + +INLINE void group_reduce_add(__local float* lds, int size, int lid) +{ + for (int offset = (size >> 1); offset > 0; offset >>= 1) + { + if (lid < offset) + { + lds[lid] += lds[lid + offset]; + } + barrier(CLK_LOCAL_MEM_FENCE); + } +} + +INLINE void group_reduce_min(__local float* lds, int size, int lid) +{ + for (int offset = (size >> 1); offset > 0; offset >>= 1) + { + if (lid < offset) + { + lds[lid] = min(lds[lid], lds[lid + offset]); + } + barrier(CLK_LOCAL_MEM_FENCE); + } +} + + +INLINE void group_reduce_max(__local float* lds, int size, int lid) +{ + for (int offset = (size >> 1); offset > 0; offset >>= 1) + { + if (lid < offset) + { + lds[lid] = max(lds[lid], lds[lid + offset]); + } + barrier(CLK_LOCAL_MEM_FENCE); + } +} + + +KERNEL void EstimateVariance( + GLOBAL float4 const* restrict image_buffer, + GLOBAL float* restrict variance_buffer, + int width, + int height +) +{ + __local float lds[256]; + + int x = get_global_id(0); + int y = get_global_id(1); + int lx = get_local_id(0); + int ly = get_local_id(1); + int gx = get_group_id(0); + int gy = get_group_id(1); + int wx = get_local_size(0); + int wy = get_local_size(1); + int num_tiles = (width + wx - 1) / wx; + int lid = ly * wx + lx; + + float value = 0.f; + if (x < width && y < height) + { + float4 rw = image_buffer[y * width + x]; rw /= rw.w; + value = 4*luminance(clamp(rw.xyz, 0.f, 1.f)); + rw = y + 1 < height ? image_buffer[(y + 1) * width + x] : image_buffer[y * width + x]; rw /= rw.w; + value -= luminance(clamp(rw.xyz, 0.f, 1.f)); + rw = y - 1 >= 0 ? image_buffer[(y - 1) * width + x] : image_buffer[y * width + x]; rw /= rw.w; + value -= luminance(clamp(rw.xyz, 0.f, 1.f)); + rw = x + 1 < width ? image_buffer[y * width + x + 1] : image_buffer[y * width + x]; rw /= rw.w; + value -= luminance(clamp(rw.xyz, 0.f, 1.f)); + rw = x - 1 >= 0 ? image_buffer[y * width + x - 1] : image_buffer[y * width + x]; rw /= rw.w; + value -= luminance(clamp(rw.xyz, 0.f, 1.f)); + //rw = y + 1 < height && x + 1 < width ? image_buffer[(y + 1) * width + x + 1] : image_buffer[y * width + x]; rw /= rw.w; + //value -= luminance(clamp(rw.xyz, 0.f, 1.f)); + //rw = y - 1 >= 0 && x - 1 >= 0 ? image_buffer[(y - 1) * width + x - 1] : image_buffer[y * width + x]; rw /= rw.w; + //value -= luminance(clamp(rw.xyz, 0.f, 1.f)); + //rw = y + 1 < height && x - 1 >= 0 ? image_buffer[(y + 1) * width + x - 1] : image_buffer[y * width + x]; rw /= rw.w; + //value -= luminance(clamp(rw.xyz, 0.f, 1.f)); + //rw = y - 1 >= 0 && x + 1 < width ? image_buffer[(y - 1) * width + x + 1] : image_buffer[y * width + x]; rw /= rw.w; + //value -= luminance(clamp(rw.xyz, 0.f, 1.f)); + } + + value = fabs(value); + lds[lid] = value; + barrier(CLK_LOCAL_MEM_FENCE); + + group_reduce_add(lds, 256, lid); + + float mean = lds[0] / (wx * wy); + barrier(CLK_LOCAL_MEM_FENCE); + + /*lds[lid] = (mean - value) * (mean - value); + barrier(CLK_LOCAL_MEM_FENCE); + + group_reduce_add(lds, 256, lid);*/ + + if (x < width && y < height) + { + if (lx == 0 && ly == 0) + { + //float dev = lds[0] / (wx * wy - 1); + variance_buffer[gy * num_tiles + gx] = mean; + } + } +} + +KERNEL +void OrthographicCamera_GeneratePaths( + // Camera + GLOBAL Camera const* restrict camera, + // Image resolution + int output_width, + int output_height, + // Pixel domain buffer + GLOBAL int const* restrict pixel_idx, + // Size of pixel domain buffer + GLOBAL int const* restrict num_pixels, + // RNG seed value + uint rng_seed, + // Current frame + uint frame, + // Rays to generate + GLOBAL ray* restrict rays, + // RNG data + GLOBAL uint* restrict random, + GLOBAL uint const* restrict sobol_mat + ) +{ + int global_id = get_global_id(0); + + // Check borders + if (global_id < *num_pixels) + { + int idx = pixel_idx[global_id]; + int y = idx / output_width; + int x = idx % output_width; + + // Get pointer to ray & path handles + GLOBAL ray* my_ray = rays + global_id; + + // Initialize sampler + Sampler sampler; +#if SAMPLER == SOBOL + uint scramble = random[x + output_width * y] * 0x1fe3434f; + + if (frame & 0xF) + { + random[x + output_width * y] = WangHash(scramble); + } + + Sampler_Init(&sampler, frame, SAMPLE_DIM_CAMERA_OFFSET, scramble); +#elif SAMPLER == RANDOM + uint scramble = x + output_width * y * rng_seed; + Sampler_Init(&sampler, scramble); +#elif SAMPLER == CMJ + uint rnd = random[x + output_width * y]; + uint scramble = rnd * 0x1fe3434f * ((frame + 133 * rnd) / (CMJ_DIM * CMJ_DIM)); + Sampler_Init(&sampler, frame % (CMJ_DIM * CMJ_DIM), SAMPLE_DIM_CAMERA_OFFSET, scramble); +#endif + + // Generate sample +#ifndef BAIKAL_GENERATE_SAMPLE_AT_PIXEL_CENTER + float2 sample0 = Sampler_Sample2D(&sampler, SAMPLER_ARGS); +#else + float2 sample0 = make_float2(0.5f, 0.5f); +#endif + + // Calculate [0..1] image plane sample + float2 img_sample; + img_sample.x = (float)x / output_width + sample0.x / output_width; + img_sample.y = (float)y / output_height + sample0.y / output_height; + + // Transform into [-0.5, 0.5] + float2 h_sample = img_sample - make_float2(0.5f, 0.5f); + // Transform into [-dim/2, dim/2] + float2 c_sample = h_sample * camera->dim; + + // Calculate direction to image plane + my_ray->d.xyz = normalize(camera->forward); + // Origin == camera position + nearz * d + my_ray->o.xyz = camera->p + c_sample.x * camera->right + c_sample.y * camera->up; + // Max T value = zfar - znear since we moved origin to znear + my_ray->o.w = camera->zcap.y - camera->zcap.x; + // Generate random time from 0 to 1 + my_ray->d.w = sample0.x; + // Set ray max + my_ray->extra.x = 0xFFFFFFFF; + my_ray->extra.y = 0xFFFFFFFF; + Ray_SetExtra(my_ray, 1.f); + Ray_SetMask(my_ray, VISIBILITY_MASK_PRIMARY); + } +} + +///< Illuminate missing rays +KERNEL void ShadeBackgroundImage( + // Ray batch + GLOBAL ray const* restrict rays, + // Intersection data + GLOBAL Intersection const* restrict isects, + // Pixel indices + GLOBAL int const* restrict pixel_indices, + // Output indices + GLOBAL int const* restrict output_indices, + // Number of rays + int num_rays, + int background_idx, + // Output size + int width, + int height, + // Textures + TEXTURE_ARG_LIST, + // Output values + GLOBAL float4* restrict output +) +{ + int global_id = get_global_id(0); + + if (global_id < num_rays) + { + int pixel_idx = pixel_indices[global_id]; + int output_index = output_indices[pixel_idx]; + + float x = (float)(output_index % width) / (float)width; + float y = (float)(output_index / width) / (float)height; + + float4 v = make_float4(0.f, 0.f, 0.f, 1.f); + + // In case of a miss + if (isects[global_id].shapeid < 0) + { + float2 uv = make_float2(x, y); + v.xyz = Texture_Sample2D(uv, TEXTURE_ARGS_IDX(background_idx)).xyz; + } + + ADD_FLOAT4(&output[output_index], v); + } +} + + +#endif // MONTE_CARLO_RENDERER_CL diff --git a/Baikal/CL/normalmap.cl b/Baikal/Kernels/CL/normalmap.cl similarity index 95% rename from Baikal/CL/normalmap.cl rename to Baikal/Kernels/CL/normalmap.cl index a3920fca..529e6f6a 100644 --- a/Baikal/CL/normalmap.cl +++ b/Baikal/Kernels/CL/normalmap.cl @@ -22,9 +22,9 @@ THE SOFTWARE. #ifndef NORMALMAP_CL #define NORMALMAP_CL -#include <../Baikal/CL/utils.cl> -#include <../Baikal/CL/texture.cl> -#include <../Baikal/CL/payload.cl> +#include <../Baikal/Kernels/CL/utils.cl> +#include <../Baikal/Kernels/CL/texture.cl> +#include <../Baikal/Kernels/CL/payload.cl> void DifferentialGeometry_ApplyNormalMap(DifferentialGeometry* diffgeo, TEXTURE_ARG_LIST) { diff --git a/Baikal/CL/path.cl b/Baikal/Kernels/CL/path.cl similarity index 53% rename from Baikal/CL/path.cl rename to Baikal/Kernels/CL/path.cl index e9703383..a8597d8e 100644 --- a/Baikal/CL/path.cl +++ b/Baikal/Kernels/CL/path.cl @@ -22,7 +22,9 @@ THE SOFTWARE. #ifndef PATH_CL #define PATH_CL -#include <../Baikal/CL/payload.cl> +#include <../Baikal/Kernels/CL/common.cl> +#include <../Baikal/Kernels/CL/payload.cl> +#include <../Baikal/Kernels/CL/bxdf_flags.cl> typedef struct _Path { @@ -38,76 +40,100 @@ typedef enum _PathFlags kNone = 0x0, kKilled = 0x1, kScattered = 0x2, - kSpecularBounce = 0x4 + kOpaque = 0x4 } PathFlags; -bool Path_IsScattered(__global Path const* path) +INLINE bool Path_IsScattered(__global Path const* path) { return path->flags & kScattered; } -bool Path_IsSpecular(__global Path const* path) +INLINE bool Path_IsAlive(__global Path const* path) { - return path->flags & kSpecularBounce; + return ((path->flags & kKilled) == 0); } -bool Path_IsAlive(__global Path const* path) +INLINE bool Path_ContainsOpacity(__global Path const* path) { - return ((path->flags & kKilled) == 0); + return path->flags & kOpaque; } -void Path_ClearScatterFlag(__global Path* path) +INLINE void Path_ClearScatterFlag(__global Path* path) { path->flags &= ~kScattered; } -void Path_SetScatterFlag(__global Path* path) +INLINE void Path_SetScatterFlag(__global Path* path) { path->flags |= kScattered; } +INLINE void Path_SetOpacityFlag(__global Path* path) +{ + path->flags |= kOpaque; +} + +INLINE void Path_ClearBxdfFlags(__global Path* path) +{ + path->flags &= (kKilled | kScattered | kOpaque); +} -void Path_ClearSpecularFlag(__global Path* path) +INLINE int Path_GetBxdfFlags(__global Path const* path) { - path->flags &= ~kSpecularBounce; + return path->flags >> 8; } -void Path_SetSpecularFlag(__global Path* path) +INLINE int Path_SetBxdfFlags(__global Path* path, int flags) { - path->flags |= kSpecularBounce; + return path->flags |= (flags << 8); } -void Path_Restart(__global Path* path) +INLINE void Path_Restart(__global Path* path) { path->flags = 0; } -int Path_GetVolumeIdx(__global Path const* path) +INLINE int Path_GetVolumeIdx(__global Path const* path) { return path->volume; } -float3 Path_GetThroughput(__global Path const* path) +INLINE void Path_SetVolumeIdx(__global Path* path, int volume_idx) +{ + path->volume = volume_idx; +} + +INLINE float3 Path_GetThroughput(__global Path const* path) { float3 t = path->throughput; return t; } -void Path_MulThroughput(__global Path* path, float3 mul) +INLINE void Path_MulThroughput(__global Path* path, float3 mul) { path->throughput *= mul; } -void Path_Kill(__global Path* path) +INLINE void Path_Kill(__global Path* path) { path->flags |= kKilled; } -void Path_AddContribution(__global Path* path, __global float3* output, int idx, float3 val) +INLINE void Path_AddContribution(__global Path* path, __global float3* output, int idx, float3 val) { output[idx] += Path_GetThroughput(path) * val; } +INLINE bool Path_IsSpecular(__global Path const* path) +{ + int flags = Path_GetBxdfFlags(path); + return (flags & kBxdfFlagsSingular) == kBxdfFlagsSingular; +} +INLINE void Path_SetFlags(DifferentialGeometry* diffgeo, GLOBAL Path* restrict path) +{ + Path_ClearBxdfFlags(path); + Path_SetBxdfFlags(path, Bxdf_GetFlags(diffgeo)); +} #endif diff --git a/Baikal/Kernels/CL/path_tracing_estimator.cl b/Baikal/Kernels/CL/path_tracing_estimator.cl new file mode 100644 index 00000000..19b358f8 --- /dev/null +++ b/Baikal/Kernels/CL/path_tracing_estimator.cl @@ -0,0 +1,384 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 PATH_TRACING_ESTIMATOR_CL +#define PATH_TRACING_ESTIMATOR_CL + +#include <../Baikal/Kernels/CL/common.cl> +#include <../Baikal/Kernels/CL/ray.cl> +#include <../Baikal/Kernels/CL/isect.cl> +#include <../Baikal/Kernels/CL/utils.cl> +#include <../Baikal/Kernels/CL/payload.cl> +#include <../Baikal/Kernels/CL/texture.cl> +#include <../Baikal/Kernels/CL/sampling.cl> +#include <../Baikal/Kernels/CL/light.cl> +#include <../Baikal/Kernels/CL/scene.cl> +#include <../Baikal/Kernels/CL/volumetrics.cl> +#include <../Baikal/Kernels/CL/path.cl> + + +KERNEL +void InitPathData( + GLOBAL int const* restrict src_index, + GLOBAL int* restrict dst_index, + GLOBAL int const* restrict num_elements, + int world_volume_idx, + GLOBAL Path* restrict paths +) +{ + int global_id = get_global_id(0); + + // Check borders + if (global_id < *num_elements) + { + GLOBAL Path* my_path = paths + global_id; + dst_index[global_id] = src_index[global_id]; + + // Initalize path data + my_path->throughput = make_float3(1.f, 1.f, 1.f); + my_path->volume = world_volume_idx; + my_path->flags = 0; + my_path->active = 0xFF; + } +} + +///< Illuminate missing rays +KERNEL void ShadeBackgroundEnvMap( + // Ray batch + GLOBAL ray const* restrict rays, + // Intersection data + GLOBAL Intersection const* restrict isects, + // Pixel indices + GLOBAL int const* restrict pixel_indices, + // Output indices + GLOBAL int const* restrict output_indices, + // Number of rays + int num_rays, + GLOBAL Light const* restrict lights, + int env_light_idx, + // Textures + TEXTURE_ARG_LIST, + // Environment texture index + GLOBAL Path const* restrict paths, + GLOBAL Volume const* restrict volumes, + // Output values + GLOBAL float4* restrict output +) +{ + int global_id = get_global_id(0); + + if (global_id < num_rays) + { + int pixel_idx = pixel_indices[global_id]; + int output_index = output_indices[pixel_idx]; + + float4 v = make_float4(0.f, 0.f, 0.f, 1.f); + + // In case of a miss + if (isects[global_id].shapeid < 0 && env_light_idx != -1) + { + // Multiply by throughput + int volume_idx = paths[pixel_idx].volume; + + Light light = lights[env_light_idx]; + + int tex = EnvironmentLight_GetBackgroundTexture(&light); + + if (tex != -1) + { + v.xyz = light.multiplier * Texture_SampleEnvMap(rays[global_id].d.xyz, TEXTURE_ARGS_IDX(tex), light.ibl_mirror_x); + } + } + + ADD_FLOAT4(&output[output_index], v); + } +} + +///< Handle light samples and visibility info and add contribution to final buffer +KERNEL void GatherLightSamples( + // Pixel indices + GLOBAL int const* restrict pixel_indices, + // Output indices + GLOBAL int const* restrict output_indices, + // Number of rays + GLOBAL int* restrict num_rays, + // Shadow rays hits + GLOBAL int const* restrict shadow_hits, + // Light samples + GLOBAL float3 const* restrict light_samples, + // throughput + GLOBAL Path const* restrict paths, + // Radiance sample buffer + GLOBAL float4* restrict output +) +{ + int global_id = get_global_id(0); + + if (global_id < *num_rays) + { + // Get pixel id for this sample set + int pixel_idx = pixel_indices[global_id]; + int output_index = output_indices[pixel_idx]; + + // Prepare accumulator variable + float4 radiance = 0.f; + + // Start collecting samples + { + // If shadow ray didn't hit anything and reached skydome + if (shadow_hits[global_id] == -1) + { + // Add its contribution to radiance accumulator + radiance.xyz += light_samples[global_id]; + } + } + + // Divide by number of light samples (samples already have built-in throughput) + ADD_FLOAT4(&output[output_index], radiance); + } +} + +///< Handle light samples and visibility info and add contribution to final buffer +KERNEL void GatherVisibility( + // Pixel indices + GLOBAL int const* restrict pixel_indices, + // Output indices + GLOBAL int const* restrict output_indices, + // Number of rays + GLOBAL int* restrict num_rays, + // Shadow rays hits + GLOBAL int const* restrict shadow_hits, + // Radiance sample buffer + GLOBAL float4* restrict output +) +{ + int global_id = get_global_id(0); + + if (global_id < *num_rays) + { + // Get pixel id for this sample set + int pixel_idx = pixel_indices[global_id]; + int output_index = output_indices[pixel_idx]; + + // Prepare accumulator variable + float4 visibility = make_float4(0.f, 0.f, 0.f, 1.f); + + // Start collecting samples + { + // If shadow ray didn't hit anything and reached skydome + if (shadow_hits[global_id] == -1) + { + // Add its contribution to radiance accumulator + visibility.xyz += 1.f; + } + } + + // Divide by number of light samples (samples already have built-in throughput) + ADD_FLOAT4(&output[output_index], visibility); + } +} + +///< Gather opacity information and store it in opacity buffer +KERNEL void GatherOpacity( + // Pixel indices + GLOBAL int const* restrict pixel_indices, + // Output indices + GLOBAL int const* restrict output_indices, + // Number of rays + GLOBAL int* restrict num_rays, + // Paths + GLOBAL Path const* restrict paths, + int last_bounce, + // Radiance sample buffer + GLOBAL float4* restrict output +) +{ + int global_id = get_global_id(0); + if (global_id < *num_rays) + { + int pixel_idx = pixel_indices[global_id]; + int output_index = output_indices[pixel_idx]; + GLOBAL Path* path = paths + pixel_idx; + + if (!Path_IsAlive(path) || last_bounce) + { + float4 v = make_float4(0.f, 0.f, 0.f, 1.f); + if (Path_ContainsOpacity(path)) + { + v.xyz = 1.0f; + } + ADD_FLOAT4(&output[output_index], v); + } + } +} + +///< Restore pixel indices after compaction +KERNEL void RestorePixelIndices( + // Compacted indices + GLOBAL int const* restrict compacted_indices, + // Number of compacted indices + GLOBAL int* restrict num_elements, + // Previous pixel indices + GLOBAL int const* restrict prev_indices, + // New pixel indices + GLOBAL int* restrict new_indices +) +{ + int global_id = get_global_id(0); + + // Handle only working subset + if (global_id < *num_elements) + { + new_indices[global_id] = prev_indices[compacted_indices[global_id]]; + } +} + +///< Restore pixel indices after compaction +KERNEL void FilterPathStream( + // Intersections + GLOBAL Intersection const* restrict isects, + // Number of compacted indices + GLOBAL int const* restrict num_elements, + // Pixel indices + GLOBAL int const* restrict pixel_indices, + // Paths + GLOBAL Path* restrict paths, + // Predicate + GLOBAL int* restrict predicate +) +{ + int global_id = get_global_id(0); + + // Handle only working subset + if (global_id < *num_elements) + { + int pixel_idx = pixel_indices[global_id]; + + GLOBAL Path* path = paths + pixel_idx; + + if (Path_IsAlive(path)) + { + bool kill = (length(Path_GetThroughput(path)) < CRAZY_LOW_THROUGHPUT) || (isects[global_id].shapeid < 0); + + if (!kill) + { + predicate[global_id] = 1; + } + else + { + Path_Kill(path); + predicate[global_id] = 0; + } + } + else + { + predicate[global_id] = 0; + } + } +} + +///< Illuminate missing rays +KERNEL void ShadeMiss( + // Ray batch + GLOBAL ray const* restrict rays, + // Intersection data + GLOBAL Intersection const* restrict isects, + // Pixel indices + GLOBAL int const* restrict pixel_indices, + // Output indices + GLOBAL int const* restrict output_indices, + // Number of rays + GLOBAL int const* restrict num_rays, + GLOBAL Light const* restrict lights, + // Light distribution + GLOBAL int const* restrict light_distribution, + // Number of emissive objects + int num_lights, + int env_light_idx, + // Textures + TEXTURE_ARG_LIST, + GLOBAL Path const* restrict paths, + GLOBAL Volume const* restrict volumes, + // Output values + GLOBAL float4* restrict output +) +{ + int global_id = get_global_id(0); + + if (global_id < *num_rays) + { + int pixel_idx = pixel_indices[global_id]; + int output_index = output_indices[pixel_idx]; + + GLOBAL Path const* path = paths + pixel_idx; + + // In case of a miss + if (isects[global_id].shapeid < 0 && Path_IsAlive(path)) + { + Light light = lights[env_light_idx]; + + // Apply MIS + int bxdf_flags = Path_GetBxdfFlags(path); + float selection_pdf = Distribution1D_GetPdfDiscreet(env_light_idx, light_distribution); + float light_pdf = EnvironmentLight_GetPdf(&light, 0, 0, bxdf_flags, kLightInteractionSurface, rays[global_id].d.xyz, TEXTURE_ARGS); + float2 extra = Ray_GetExtra(&rays[global_id]); + float weight = extra.x > 0.f ? BalanceHeuristic(1, extra.x, 1, light_pdf * selection_pdf) : 1.f; + + float3 t = Path_GetThroughput(path); + float4 v = 0.f; + + int tex = EnvironmentLight_GetTexture(&light, bxdf_flags); + if (tex != -1) + { + v.xyz = weight * light.multiplier * Texture_SampleEnvMap(rays[global_id].d.xyz, TEXTURE_ARGS_IDX(tex), light.ibl_mirror_x) * t; + v.xyz = REASONABLE_RADIANCE(v.xyz); + } + + ADD_FLOAT4(&output[output_index], v); + } + } +} + +///< Advance iteration count. Used on missed rays +KERNEL void AdvanceIterationCount( + // Pixel indices + GLOBAL int const* restrict pixel_indices, + // Output indices + GLOBAL int const* restrict output_indices, + // Number of rays + int num_rays, + // Output values + GLOBAL float4* restrict output +) +{ + int global_id = get_global_id(0); + if (global_id < num_rays) + { + int pixel_idx = pixel_indices[global_id]; + int output_index = output_indices[pixel_idx]; + + float4 v = make_float4(0.f, 0.f, 0.f, 1.f); + ADD_FLOAT4(&output[output_index], v); + } +} + +#endif + diff --git a/Baikal/Kernels/CL/path_tracing_estimator_uberv2.cl b/Baikal/Kernels/CL/path_tracing_estimator_uberv2.cl new file mode 100644 index 00000000..dcf79ae0 --- /dev/null +++ b/Baikal/Kernels/CL/path_tracing_estimator_uberv2.cl @@ -0,0 +1,673 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 PATH_TRACING_ESTIMATOR_UBERV2_CL +#define PATH_TRACING_ESTIMATOR_UBERV2_CL + +#include <../Baikal/Kernels/CL/common.cl> +#include <../Baikal/Kernels/CL/ray.cl> +#include <../Baikal/Kernels/CL/isect.cl> +#include <../Baikal/Kernels/CL/utils.cl> +#include <../Baikal/Kernels/CL/payload.cl> +#include <../Baikal/Kernels/CL/texture.cl> +#include <../Baikal/Kernels/CL/sampling.cl> +#include <../Baikal/Kernels/CL/bxdf.cl> +#include <../Baikal/Kernels/CL/light.cl> +#include <../Baikal/Kernels/CL/scene.cl> +#include <../Baikal/Kernels/CL/volumetrics.cl> +#include <../Baikal/Kernels/CL/path.cl> + +// This kernel only handles scattered paths. +// It applies direct illumination and generates +// path continuation if multiscattering is enabled. +KERNEL void ShadeVolumeUberV2( + // Ray batch + GLOBAL ray const* restrict rays, + // Intersection data + GLOBAL Intersection const* restrict isects, + // Hit indices + GLOBAL int const* restrict hit_indices, + // Pixel indices + GLOBAL int const* restrict pixel_indices, + // Output indices + GLOBAL int const* restrict output_indices, + // Number of rays + GLOBAL int const* restrict num_hits, + // Vertices + GLOBAL float3 const* restrict vertices, + // Normals + GLOBAL float3 const* restrict normals, + // UVs + GLOBAL float2 const* restrict uvs, + // Indices + GLOBAL int const* restrict indices, + // Shapes + GLOBAL Shape const* restrict shapes, + // Material parameters + GLOBAL int const* restrict material_attributes, + // Textures + TEXTURE_ARG_LIST, + // Environment texture index + int env_light_idx, + // Emissives + GLOBAL Light const* restrict lights, + // Light distribution + GLOBAL int const* restrict light_distribution, + // Number of emissive objects + int num_lights, + // RNG seed + uint rng_seed, + // Sampler state + GLOBAL uint* restrict random, + // Sobol matrices + GLOBAL uint const* restrict sobol_mat, + // Current bounce + int bounce, + // Current frame + int frame, + // Volume data + GLOBAL Volume const* restrict volumes, + // Shadow rays + GLOBAL ray* restrict shadow_rays, + // Light samples + GLOBAL float3* restrict light_samples, + // Path throughput + GLOBAL Path* restrict paths, + // Indirect rays (next path segment) + GLOBAL ray* restrict indirect_rays, + // Radiance + GLOBAL float3* restrict output, + GLOBAL InputMapData const* restrict input_map_values +) +{ + int global_id = get_global_id(0); + + Scene scene = + { + vertices, + normals, + uvs, + indices, + shapes, + material_attributes, + input_map_values, + lights, + env_light_idx, + num_lights, + light_distribution + }; + + if (global_id < *num_hits) + { + // Fetch index + int hit_idx = hit_indices[global_id]; + int pixel_idx = pixel_indices[global_id]; + Intersection isect = isects[hit_idx]; + + GLOBAL Path* path = paths + pixel_idx; + + // Only apply to scattered paths + if (!Path_IsScattered(path)) + { + return; + } + + // Fetch incoming ray + float3 o = rays[hit_idx].o.xyz; + float3 wi = -rays[hit_idx].d.xyz; + + Sampler sampler; +#if SAMPLER == SOBOL + uint scramble = random[pixel_idx] * 0x1fe3434f; + Sampler_Init(&sampler, frame, SAMPLE_DIM_SURFACE_OFFSET + bounce * SAMPLE_DIMS_PER_BOUNCE + SAMPLE_DIM_VOLUME_EVALUATE_OFFSET, scramble); +#elif SAMPLER == RANDOM + uint scramble = pixel_idx * rng_seed; + Sampler_Init(&sampler, scramble); +#elif SAMPLER == CMJ + uint rnd = random[pixel_idx]; + uint scramble = rnd * 0x1fe3434f * ((frame + 13 * rnd) / (CMJ_DIM * CMJ_DIM)); + Sampler_Init(&sampler, frame % (CMJ_DIM * CMJ_DIM), SAMPLE_DIM_SURFACE_OFFSET + bounce * SAMPLE_DIMS_PER_BOUNCE + SAMPLE_DIM_VOLUME_EVALUATE_OFFSET, scramble); +#endif + + + // Here we know that volume_idx != -1 since this is a precondition + // for scattering event + int volume_idx = Path_GetVolumeIdx(path); + + // Sample light source + float pdf = 0.f; + float selection_pdf = 0.f; + float3 wo; + + int light_idx = Scene_SampleLight(&scene, Sampler_Sample1D(&sampler, SAMPLER_ARGS), &selection_pdf); + + // Here we need fake differential geometry for light sampling procedure + DifferentialGeometry dg; + // put scattering position in there (it is along the current ray at isect.distance + // since EvaluateVolume has put it there + dg.p = o - wi * Intersection_GetDistance(isects + hit_idx); + // Get light sample intencity + int bxdf_flags = Path_GetBxdfFlags(path); + float3 le = Light_Sample(light_idx, &scene, &dg, TEXTURE_ARGS, Sampler_Sample2D(&sampler, SAMPLER_ARGS), bxdf_flags, kLightInteractionVolume, &wo, &pdf); + + // Generate shadow ray + float shadow_ray_length = length(wo); + Ray_Init(shadow_rays + global_id, dg.p, normalize(wo), shadow_ray_length, 0.f, 0xFFFFFFFF); + Ray_SetExtra(shadow_rays + global_id, make_float2(1.f, 0.f)); + + // Evaluate volume transmittion along the shadow ray (it is incorrect if the light source is outside of the + // current volume, but in this case it will be discarded anyway since the intersection at the outer bound + // of a current volume), so the result is fully correct. + float3 tr = 1.f;// Volume_Transmittance(&volumes[volume_idx], &shadow_rays[global_id], shadow_ray_length); + float3 emission = 0.f;// Volume_Emission(&volumes[volume_idx], &shadow_rays[global_id], shadow_ray_length); + + // Volume emission is applied only if the light source is in the current volume(this is incorrect since the light source might be + // outside of a volume and we have to compute fraction of ray in this case, but need to figure out how) + // float3 r = Volume_Emission(&volumes[volume_idx], &shadow_rays[global_id], shadow_ray_length); + float3 r = 0.f; + float g = volumes[volume_idx].g; + // This is the estimate coming from a light source + // TODO: remove hardcoded phase func and sigma + r += tr * le * PhaseFunctionHG(wi, normalize(wo), g) / pdf / selection_pdf; + r += tr * emission; + + // Only if we have some radiance compute the visibility ray + if (NON_BLACK(tr) && NON_BLACK(r) && pdf > 0.f) + { + // Put lightsample result + light_samples[global_id] = REASONABLE_RADIANCE(r * Path_GetThroughput(path)); + } + else + { + // Nothing to compute + light_samples[global_id] = 0.f; + // Otherwise make it incative to save intersector cycles (hopefully) + Ray_SetInactive(shadow_rays + global_id); + } + +#ifdef MULTISCATTER + // This is highly brute-force + float phase = PhaseFunctionHG_Sample(wi, g, Sampler_Sample2D(&sampler, SAMPLER_ARGS), &wo); + + // Generate new path segment + Ray_Init(indirect_rays + global_id, dg.p, normalize(wo), CRAZY_HIGH_DISTANCE, 0.f, 0xFFFFFFFF); + + + // Update path throughput multiplying by phase function. + Path_MulThroughput(path, phase); +#else + // Single-scattering mode only, + // kill the path and compact away on next iteration + Path_Kill(path); + Ray_SetInactive(indirect_rays + global_id); +#endif + } +} + + +// Handle ray-surface interaction possibly generating path continuation. +// This is only applied to non-scattered paths. +KERNEL void ShadeSurfaceUberV2( + // Ray batch + GLOBAL ray const* restrict rays, + // Intersection data + GLOBAL Intersection const* restrict isects, + // Hit indices + GLOBAL int const* restrict hit_indices, + // Pixel indices + GLOBAL int const* restrict pixel_indices, + // Output indices + GLOBAL int const* restrict output_indices, + // Number of rays + GLOBAL int const* restrict num_hits, + // Vertices + GLOBAL float3 const* restrict vertices, + // Normals + GLOBAL float3 const* restrict normals, + // UVs + GLOBAL float2 const* restrict uvs, + // Indices + GLOBAL int const* restrict indices, + // Shapes + GLOBAL Shape const* restrict shapes, + // Materials + GLOBAL int const* restrict material_attributes, + // Textures + TEXTURE_ARG_LIST, + // Environment texture index + int env_light_idx, + // Emissives + GLOBAL Light const* restrict lights, + // Light distribution + GLOBAL int const* restrict light_distribution, + // Number of emissive objects + int num_lights, + // RNG seed + uint rng_seed, + // Sampler states + GLOBAL uint* restrict random, + // Sobol matrices + GLOBAL uint const* restrict sobol_mat, + // Current bounce + int bounce, + // Frame + int frame, + // Volume data + GLOBAL Volume const* restrict volumes, + // Shadow rays + GLOBAL ray* restrict shadow_rays, + // Light samples + GLOBAL float3* restrict light_samples, + // Path throughput + GLOBAL Path* restrict paths, + // Indirect rays + GLOBAL ray* restrict indirect_rays, + // Radiance + GLOBAL float3* restrict output, + GLOBAL InputMapData const* restrict input_map_values +) +{ + int global_id = get_global_id(0); + + Scene scene = + { + vertices, + normals, + uvs, + indices, + shapes, + material_attributes, + input_map_values, + lights, + env_light_idx, + num_lights, + light_distribution + }; + + // Only applied to active rays after compaction + if (global_id < *num_hits) + { + // Fetch index + int hit_idx = hit_indices[global_id]; + int pixel_idx = pixel_indices[global_id]; + Intersection isect = isects[hit_idx]; + + GLOBAL Path* path = paths + pixel_idx; + + // Early exit for scattered paths + if (Path_IsScattered(path)) + { + return; + } + + // Fetch incoming ray direction + float3 wi = -normalize(rays[hit_idx].d.xyz); + + Sampler sampler; +#if SAMPLER == SOBOL + uint scramble = random[pixel_idx] * 0x1fe3434f; + Sampler_Init(&sampler, frame, SAMPLE_DIM_SURFACE_OFFSET + bounce * SAMPLE_DIMS_PER_BOUNCE, scramble); +#elif SAMPLER == RANDOM + uint scramble = pixel_idx * rng_seed; + Sampler_Init(&sampler, scramble); +#elif SAMPLER == CMJ + uint rnd = random[pixel_idx]; + uint scramble = rnd * 0x1fe3434f * ((frame + 331 * rnd) / (CMJ_DIM * CMJ_DIM)); + Sampler_Init(&sampler, frame % (CMJ_DIM * CMJ_DIM), SAMPLE_DIM_SURFACE_OFFSET + bounce * SAMPLE_DIMS_PER_BOUNCE, scramble); +#endif + + // Fill surface data + DifferentialGeometry diffgeo; + Scene_FillDifferentialGeometry(&scene, &isect, &diffgeo); + + // Check if we are hitting from the inside + float ngdotwi = dot(diffgeo.ng, wi); + bool backfacing = ngdotwi < 0.f; + + // Select BxDF + UberV2ShaderData uber_shader_data; + UberV2PrepareInputs(&diffgeo, input_map_values, material_attributes, TEXTURE_ARGS, &uber_shader_data); + + UberV2_ApplyShadingNormal(&diffgeo, &uber_shader_data); + DifferentialGeometry_CalculateTangentTransforms(&diffgeo); + + GetMaterialBxDFType(wi, &sampler, SAMPLER_ARGS, &diffgeo, &uber_shader_data); + + // Set surface interaction flags + Path_SetFlags(&diffgeo, path); + + // Opacity flag for opacity AOV + if (!Bxdf_IsTransparency(&diffgeo)) + { + Path_SetOpacityFlag(path); + } + + // Terminate if emissive + if (Bxdf_IsEmissive(&diffgeo)) + { + if (!backfacing) + { + float weight = 1.f; + + if (bounce > 0 && !Path_IsSpecular(path)) + { + float2 extra = Ray_GetExtra(&rays[hit_idx]); + float ld = isect.uvwt.w; + float denom = fabs(dot(diffgeo.n, wi)) * diffgeo.area; + // TODO: num_lights should be num_emissies instead, presence of analytical lights breaks this code + float bxdf_light_pdf = denom > 0.f ? (ld * ld / denom / num_lights) : 0.f; + weight = extra.x > 0.f ? BalanceHeuristic(1, extra.x, 1, bxdf_light_pdf) : 1.f; + } + + // In this case we hit after an application of MIS process at previous step. + // That means BRDF weight has been already applied. + float3 v = REASONABLE_RADIANCE(Path_GetThroughput(path) * Emissive_GetLe(&diffgeo, TEXTURE_ARGS, &uber_shader_data) * weight); + + int output_index = output_indices[pixel_idx]; + ADD_FLOAT3(&output[output_index], v); + } + + Path_Kill(path); + Ray_SetInactive(shadow_rays + global_id); + Ray_SetInactive(indirect_rays + global_id); + + light_samples[global_id] = 0.f; + return; + } + + float s = Bxdf_IsBtdf(&diffgeo) ? (-sign(ngdotwi)) : 1.f; + if (backfacing && !Bxdf_IsBtdf(&diffgeo)) + { + //Reverse normal and tangents in this case + //but not for BTDFs, since BTDFs rely + //on normal direction in order to arrange + //indices of refraction + diffgeo.n = -diffgeo.n; + diffgeo.dpdu = -diffgeo.dpdu; + diffgeo.dpdv = -diffgeo.dpdv; + s = -s; + } + + float ndotwi = fabs(dot(diffgeo.n, wi)); + + float light_pdf = 0.f; + float bxdf_light_pdf = 0.f; + float bxdf_pdf = 0.f; + float light_bxdf_pdf = 0.f; + float selection_pdf = 0.f; + float3 radiance = 0.f; + float3 lightwo; + float3 bxdfwo; + float3 wo; + float bxdf_weight = 1.f; + float light_weight = 1.f; + + int light_idx = Scene_SampleLight(&scene, Sampler_Sample1D(&sampler, SAMPLER_ARGS), &selection_pdf); + + float3 throughput = Path_GetThroughput(path); + + // Sample bxdf + const float2 sample = Sampler_Sample2D(&sampler, SAMPLER_ARGS); + float3 bxdf = UberV2_Sample(&diffgeo, wi, TEXTURE_ARGS, sample, &bxdfwo, &bxdf_pdf, &uber_shader_data); + + // If we have light to sample we can hopefully do mis + if (light_idx > -1) + { + // Sample light + int bxdf_flags = Path_GetBxdfFlags(path); + float3 le = Light_Sample(light_idx, &scene, &diffgeo, TEXTURE_ARGS, Sampler_Sample2D(&sampler, SAMPLER_ARGS), bxdf_flags, kLightInteractionSurface, &lightwo, &light_pdf); + light_bxdf_pdf = UberV2_GetPdf(&diffgeo, wi, normalize(lightwo), TEXTURE_ARGS, &uber_shader_data); + light_weight = Light_IsSingular(&scene.lights[light_idx]) ? 1.f : BalanceHeuristic(1, light_pdf * selection_pdf, 1, light_bxdf_pdf); + + // Apply MIS to account for both + if (NON_BLACK(le) && (light_pdf > 0.0f) && (selection_pdf > 0.0f) && !Bxdf_IsSingular(&diffgeo)) + { + wo = lightwo; + float ndotwo = fabs(dot(diffgeo.n, normalize(wo))); + radiance = le * ndotwo * UberV2_Evaluate(&diffgeo, wi, normalize(wo), TEXTURE_ARGS, &uber_shader_data) * throughput * light_weight / light_pdf / selection_pdf; + } + } + + // If we have some light here generate a shadow ray + if (NON_BLACK(radiance)) + { + // Generate shadow ray + float3 shadow_ray_o = diffgeo.p + CRAZY_LOW_DISTANCE * s * diffgeo.ng; + float3 temp = diffgeo.p + wo - shadow_ray_o; + float3 shadow_ray_dir = normalize(temp); + float shadow_ray_length = length(temp); + int shadow_ray_mask = VISIBILITY_MASK_BOUNCE_SHADOW(bounce); + + Ray_Init(shadow_rays + global_id, shadow_ray_o, shadow_ray_dir, shadow_ray_length, 0.f, shadow_ray_mask); + Ray_SetExtra(shadow_rays + global_id, make_float2(1.f, 0.f)); + + light_samples[global_id] = REASONABLE_RADIANCE(radiance); + } + else + { + // Otherwise save some intersector cycles + Ray_SetInactive(shadow_rays + global_id); + light_samples[global_id] = 0; + } + + // Apply Russian roulette + float q = max(min(0.5f, + // Luminance + 0.2126f * throughput.x + 0.7152f * throughput.y + 0.0722f * throughput.z), 0.01f); + // Only if it is 3+ bounce + bool rr_apply = bounce > 3; + bool rr_stop = Sampler_Sample1D(&sampler, SAMPLER_ARGS) > q && rr_apply; + + if (rr_apply) + { + Path_MulThroughput(path, 1.f / q); + } + + bxdfwo = normalize(bxdfwo); + float3 t = bxdf * fabs(dot(diffgeo.n, bxdfwo)); + + // Only continue if we have non-zero throughput & pdf + if (NON_BLACK(t) && bxdf_pdf > 0.f && !rr_stop) + { + // Update the throughput + Path_MulThroughput(path, t / bxdf_pdf); + + // Generate ray + float3 indirect_ray_dir = bxdfwo; + float3 indirect_ray_o = diffgeo.p + CRAZY_LOW_DISTANCE * s * diffgeo.ng; + int indirect_ray_mask = VISIBILITY_MASK_BOUNCE(bounce + 1); + + Ray_Init(indirect_rays + global_id, indirect_ray_o, indirect_ray_dir, CRAZY_HIGH_DISTANCE, 0.f, indirect_ray_mask); + Ray_SetExtra(indirect_rays + global_id, make_float2(Bxdf_IsSingular(&diffgeo) ? 0.f : bxdf_pdf, 0.f)); + + if (Bxdf_IsBtdf(&diffgeo)) + { + if (backfacing) + { + Path_SetVolumeIdx(path, INVALID_IDX); + } + else + { + Path_SetVolumeIdx(path, Scene_GetVolumeIndex(&scene, isect.shapeid - 1)); + } + } + } + else + { + // Otherwise kill the path + Path_Kill(path); + Ray_SetInactive(indirect_rays + global_id); + } + } +} + +///< Handle light samples and visibility info and add contribution to final buffer +KERNEL void ApplyVolumeTransmissionUberV2( + // Pixel indices + GLOBAL int const* restrict pixel_indices, + // Output indices + GLOBAL int const* restrict output_indices, + // Shadow rays batch + GLOBAL ray* restrict shadow_rays, + // Number of rays + GLOBAL int* restrict num_rays, + // Shadow rays hits + GLOBAL Intersection const* restrict isects, + // throughput + GLOBAL Path const* restrict paths, + // Vertices + GLOBAL float3 const* restrict vertices, + // Normals + GLOBAL float3 const* restrict normals, + // UVs + GLOBAL float2 const* restrict uvs, + // Indices + GLOBAL int const* restrict indices, + // Shapes + GLOBAL Shape const* restrict shapes, + // Materials + GLOBAL int const* restrict material_attributes, + // Volumes + GLOBAL Volume const* restrict volumes, + // Light samples + GLOBAL float3* restrict light_samples, + // Shadow predicates + GLOBAL int* restrict shadow_hits, + // Radiance sample buffer + GLOBAL float4* restrict output, + GLOBAL InputMapData const* restrict input_map_values +) +{ + int global_id = get_global_id(0); + + if (global_id < *num_rays) + { + int pixel_idx = pixel_indices[global_id]; + + // Ray might be inactive, in this case we just + // fail an intersection test, nothing has been added for this ray. + if (Ray_IsActive(&shadow_rays[global_id])) + { + Scene scene = + { + vertices, + normals, + uvs, + indices, + shapes, + material_attributes, + input_map_values, + 0, + 0, + 0, + 0 + }; + + // Get pixel id for this sample set + int pixel_idx = pixel_indices[global_id]; + GLOBAL Path* path = &paths[pixel_idx]; + int path_volume_idx = Path_GetVolumeIdx(path); + + // Here we do not have any intersections, + // so we mark the test passed. + // OPTIMIZATION: this ray is going to be tested again + // on the next iteration, we can make it inactive, but + // in this case inactive rays need special handling and + // we can't fail the test for them like condition above does. + if (isects[global_id].shapeid < 0) + { + Ray_SetInactive(&shadow_rays[global_id]); + shadow_hits[global_id] = -1; + return; + } + + // Now we have a hit + // FIXME: this should be scene functions + Intersection isect = isects[global_id]; + int shape_idx = isect.shapeid - 1; + int prim_idx = isect.primid; + float t = isect.uvwt.w; + + int volume_idx = Scene_GetVolumeIndex(&scene, shape_idx); + /// @FIXME need to get material params from material_attributes + int layers = scene.shapes[shape_idx].material.layers; + + // If shape does not have volume, it is a surface intersection + // and we fail a shadow test and bail out. + if ((volume_idx == -1) || (!UberV2IsTransmissive(layers) && volume_idx != path_volume_idx)) + { + shadow_hits[global_id] = 1; + Ray_SetInactive(&shadow_rays[global_id]); + return; + } + + // Here we know volume intersection occured and we need to + // interpolate normal to figure out if we are entering or exiting volume + float3 n; + Scene_InterpolateNormalsFromIntersection(&scene, &isect, &n); + + ray shadow_ray = shadow_rays[global_id]; + float shadow_ray_throughput = Ray_GetExtra(&shadow_rays[global_id]).x; + // Now we determine if we are exiting or entering. On exit + // we need to apply transmittance and emission, on enter we simply update the ray origin. + if (dot(shadow_ray.d.xyz, n) > 0.f) + { + // Old target point is needed to update t_max + float3 old_target = shadow_ray.o.xyz + (shadow_ray.o.w) * shadow_ray.d.xyz; + // This is new ray origin after media boundary intersection + float3 p = shadow_ray.o.xyz + (t + CRAZY_LOW_DISTANCE) * shadow_ray.d.xyz; + + // Calculate volume transmittance up to this point + float3 tr = Volume_Transmittance(&volumes[volume_idx], &shadow_rays[global_id], t); + // Calculat volume emission up to this point + float3 emission = Volume_Emission(&volumes[volume_idx], &shadow_rays[global_id], t); + + // Multiply light sample by the transmittance of this segment + light_samples[global_id] *= tr; + + // TODO: this goes directly to output, not affected by a shadow ray, fix me + if (length(emission) > 0.f) + { + int output_index = output_indices[pixel_idx]; + float3 v = Path_GetThroughput(path) * emission * tr * shadow_ray_throughput; + ADD_FLOAT3(&output[output_index], v); + } + + shadow_rays[global_id].o.xyz = p; + shadow_rays[global_id].o.w = length(old_target - p); + // TODO: we keep average throughput here since we do not have float3 available + float tr_avg = (tr.x + tr.y + tr.z) / 3.f; + Ray_SetExtra(&shadow_rays[global_id], make_float2(shadow_ray_throughput * tr_avg, 0.f)); + } + else + { + float3 old_target = shadow_ray.o.xyz + (shadow_ray.o.w) * shadow_ray.d.xyz; + float3 p = shadow_ray.o.xyz + (t + CRAZY_LOW_DISTANCE) * shadow_ray.d.xyz; + + shadow_rays[global_id].o.xyz = p; + shadow_rays[global_id].o.w = length(old_target - p); + } + } + } +} + + +#endif diff --git a/Baikal/CL/payload.cl b/Baikal/Kernels/CL/payload.cl similarity index 58% rename from Baikal/CL/payload.cl rename to Baikal/Kernels/CL/payload.cl index 2a142c5c..7ff9c09b 100644 --- a/Baikal/CL/payload.cl +++ b/Baikal/Kernels/CL/payload.cl @@ -22,6 +22,10 @@ THE SOFTWARE. #ifndef PAYLOAD_CL #define PAYLOAD_CL +#define TEXTURED_INPUT(x) union { struct { float4 value; } float_value; struct { int value[4]; } int_value; } x +#define TEXTURED_INPUT_HAS_TEXTURE(x) ((x).int_value.value[3] != -1) +#define TEXTURED_INPUT_GET_COLOR(x) ((x).float_value.value.xyz) + // Matrix typedef struct { @@ -33,111 +37,102 @@ typedef struct // Camera typedef struct - { - // Coordinate frame - float3 forward; - float3 right; - float3 up; - // Position - float3 p; - - // Image plane width & height in current units - float2 dim; - // Near and far Z - float2 zcap; - // Focal lenght - float focal_length; - // Camera aspect_ratio ratio - float aspect_ratio; - float focus_distance; - float aperture; - } Camera; +{ + // Coordinate frame + float3 forward; + float3 right; + float3 up; + // Position + float3 p; + + // Image plane width & height in current units + float2 dim; + // Near and far Z + float2 zcap; + // Focal lenght + float focal_length; + // Camera aspect_ratio ratio + float aspect_ratio; + float focus_distance; + float aperture; +} Camera; + +enum UberMaterialLayers +{ + kEmissionLayer = 0x1, + kTransparencyLayer = 0x2, + kCoatingLayer = 0x4, + kReflectionLayer = 0x8, + kDiffuseLayer = 0x10, + kRefractionLayer = 0x20, + kSSSLayer = 0x40, + kShadingNormalLayer = 0x80 +}; + +typedef struct +{ + int offset; + int layers; + int flags; + int padding; +} Material; // Shape description typedef struct { // Shape starting index int startidx; - // Number of primitives in the shape - int numprims; // Start vertex int startvtx; - // Start material idx - int start_material_idx; + // Number of primitives in the shape + int volume_idx; + // unique shape id + int id; // Linear motion vector float3 linearvelocity; // Angular velocity float4 angularvelocity; // Transform in row major format matrix4x4 transform; + Material material; } Shape; - -enum Bxdf +typedef struct { - kZero, - kLambert, - kIdealReflect, - kIdealRefract, - kMicrofacetBeckmann, - kMicrofacetGGX, - kLayered, - kFresnelBlend, - kMix, - kEmissive, - kPassthrough, - kTranslucent, - kMicrofacetRefractionGGX, - kMicrofacetRefractionBeckmann -}; + int group_id; + int padding[3]; +} ShapeAdditionalData; -// Material description -typedef struct _Material +typedef enum { - // Color: can be diffuse, specular, whatever... - float4 kx; - // Refractive index - float ni; - // Context dependent parameter: glossiness, etc - float ns; - - union - { - // Color map index - int kxmapidx; - int brdftopidx; - }; - - union - { - // Normal map index - int nmapidx; - int brdfbaseidx; - }; - - union - { - // Parameter map idx - int nsmapidx; - }; - - union - { - // PDF - float fresnel; - }; + kFloat3 = 0, + kFloat = 1, + kInt = 2 +} InputMapDataType; +// Input data for input maps +typedef struct _InputMapData +{ union { - int type; - int num_materials; + struct + { + float3 value; + } float_value; + struct + { + int idx; + int placeholder[2]; + int type; //We can use it since float3 is actually float4 + } int_values; }; +} InputMapData; - int bump_flag; - int thin; - int padding[3]; -} Material; - +enum Bxdf +{ + kZero, + kUberV2 +}; enum LightType { @@ -150,24 +145,24 @@ enum LightType typedef struct { - int type; - union { // Area light struct { + int id; int shapeidx; int primidx; - int matidx; + int padding0; }; // IBL struct { int tex; - int texdiffuse; - float multiplier; + int tex_reflection; + int tex_refraction; + int tex_transparency; }; // Spot @@ -176,12 +171,17 @@ typedef struct float ia; float oa; float f; + int padding1; }; }; float3 p; float3 d; float3 intensity; + int type; + float multiplier; + int tex_background; + bool ibl_mirror_x; } Light; typedef enum @@ -191,31 +191,23 @@ typedef enum kHeterogeneous } VolumeType; -typedef enum - { - kUniform, - kRayleigh, - kMieMurky, - kMieHazy, - kHG // this one requires one extra coeff - } PhaseFunction; typedef struct _Volume - { - VolumeType type; - PhaseFunction phase_func; +{ + VolumeType type; + float g; - // Id of volume data if present - int data; - int extra; + // Id of volume data if present + int data; + int extra; - // Absorbtion - float3 sigma_a; - // Scattering - float3 sigma_s; - // Emission - float3 sigma_e; - } Volume; + // Absorbtion + TEXTURED_INPUT(sigma_a); + // Scattering + TEXTURED_INPUT(sigma_s); + // Emission + TEXTURED_INPUT(sigma_e); +} Volume; /// Supported formats enum TextureFormat @@ -228,19 +220,18 @@ enum TextureFormat /// Texture description typedef - struct _Texture - { - // Width, height and depth - int w; - int h; - int d; - // Offset in texture data array - int dataoffset; - // Format - int fmt; - int extra; - } Texture; - +struct _Texture +{ + // Width, height and depth + int w; + int h; + int d; + // Offset in texture data array + int dataoffset; + // Format + int fmt; + int extra; +} Texture; // Hit data typedef struct _DifferentialGeometry @@ -256,15 +247,15 @@ typedef struct _DifferentialGeometry // Derivatives float3 dpdu; float3 dpdv; - float area; matrix4x4 world_to_tangent; matrix4x4 tangent_to_world; // Material Material mat; - int material_index; + float area; int transfer_mode; + int padding[2]; } DifferentialGeometry; diff --git a/Baikal/CL/ray.cl b/Baikal/Kernels/CL/ray.cl similarity index 88% rename from Baikal/CL/ray.cl rename to Baikal/Kernels/CL/ray.cl index 310e9271..dbeb1049 100644 --- a/Baikal/CL/ray.cl +++ b/Baikal/Kernels/CL/ray.cl @@ -22,7 +22,7 @@ #ifndef RAY_CL #define RAY_CL -#include "../Baikal/CL/common.cl" +#include <../Baikal/Kernels/CL/common.cl> // Ray descriptor typedef struct @@ -43,12 +43,28 @@ INLINE void Ray_SetInactive(GLOBAL ray* r) r->extra.y = 0; } +INLINE bool Ray_IsActive(GLOBAL ray* r) +{ + return r->extra.y != 0; +} + // Set extra data for ray INLINE void Ray_SetExtra(GLOBAL ray* r, float2 extra) { r->padding = extra; } +// Set mask +INLINE void Ray_SetMask(GLOBAL ray* r, int mask) +{ + r->extra.x = mask; +} + +INLINE int Ray_GetMask(GLOBAL ray* r) +{ + return r->extra.x; +} + // Get extra data for ray INLINE float2 Ray_GetExtra(GLOBAL ray const* r) { diff --git a/Baikal/CL/sampling.cl b/Baikal/Kernels/CL/sampling.cl similarity index 76% rename from Baikal/CL/sampling.cl rename to Baikal/Kernels/CL/sampling.cl index 367ddefd..779b95f9 100644 --- a/Baikal/CL/sampling.cl +++ b/Baikal/Kernels/CL/sampling.cl @@ -22,14 +22,14 @@ THE SOFTWARE. #ifndef SAMPLING_CL #define SAMPLING_CL -#include <../Baikal/CL/utils.cl> - +#include <../Baikal/Kernels/CL/utils.cl> #define SAMPLE_DIMS_PER_BOUNCE 300 -#define SAMPLE_DIM_CAMERA_OFFSET 0 -#define SAMPLE_DIM_SURFACE_OFFSET 4 -#define SAMPLE_DIM_VOLUME_APPLY_OFFSET 100 -#define SAMPLE_DIM_VOLUME_EVALUATE_OFFSET 200 +#define SAMPLE_DIM_CAMERA_OFFSET 1 +#define SAMPLE_DIM_SURFACE_OFFSET 5 +#define SAMPLE_DIM_VOLUME_APPLY_OFFSET 101 +#define SAMPLE_DIM_VOLUME_EVALUATE_OFFSET 201 +#define SAMPLE_DIM_IMG_PLANE_EVALUATE_OFFSET 401 typedef struct { @@ -48,8 +48,8 @@ typedef struct _Sampler } Sampler; #if SAMPLER == SOBOL -#define SAMPLER_ARG_LIST __global uint const* sobolmat -#define SAMPLER_ARGS sobolmat +#define SAMPLER_ARG_LIST __global uint const* sobol_mat +#define SAMPLER_ARGS sobol_mat #elif SAMPLER == RANDOM #define SAMPLER_ARG_LIST int unused #define SAMPLER_ARGS 0 @@ -346,5 +346,93 @@ float BalanceHeuristic(int nf, float fpdf, int ng, float gpdf) return (f) / (f + g); } +int lower_bound(GLOBAL float const* values, int n, float value) +{ + int count = n; + int b = 0; + int it = 0; + int step = 0; + + while (count > 0) + { + it = b; + step = count / 2; + it += step; + if (values[it] < value) + { + b = ++it; + count -= step + 1; + } + else + { + count = step; + } + } + + return b; +} +/// Sample 1D distribution +float Distribution1D_Sample(float s, GLOBAL int const* data, float* pdf) +{ + int num_segments = data[0]; + + GLOBAL float const* cdf_data = (GLOBAL float const*)&data[1]; + GLOBAL float const* pdf_data = cdf_data + num_segments + 1; + + int segment_idx = max(lower_bound(cdf_data, num_segments + 1, s), 1); + + // Find lerp coefficient + float du = (s - cdf_data[segment_idx - 1]) / (cdf_data[segment_idx] - cdf_data[segment_idx - 1]); + + // Calc pdf + *pdf = pdf_data[segment_idx - 1]; + + return (segment_idx - 1 + du) / num_segments;; +} + +/// Sample 1D distribution +int Distribution1D_SampleDiscrete(float s, GLOBAL int const* data, float* pdf) +{ + int num_segments = data[0]; + + GLOBAL float const* cdf_data = (GLOBAL float const*)&data[1]; + GLOBAL float const* pdf_data = cdf_data + num_segments + 1; + + int segment_idx = max(lower_bound(cdf_data, num_segments + 1, s), 1); + + // Find lerp coefficient + float du = (s - cdf_data[segment_idx - 1]) / (cdf_data[segment_idx] - cdf_data[segment_idx - 1]); + + // Calc pdf + *pdf = pdf_data[segment_idx - 1] / num_segments; + + return segment_idx - 1; +} + +/// PDF of 1D distribution +float Distribution1D_GetPdf(float s, GLOBAL int const* data) +{ + int num_segments = data[0]; + GLOBAL float const* cdf_data = (GLOBAL float const*)&data[1]; + GLOBAL float const* pdf_data = cdf_data + num_segments + 1; + + int segment_idx = max(lower_bound(cdf_data, num_segments + 1, s), 1); + + // Calc pdf + return pdf_data[segment_idx - 1]; +} + +/// PDF of 1D distribution +float Distribution1D_GetPdfDiscreet(int d, GLOBAL int const* data) +{ + int num_segments = data[0]; + GLOBAL float const* cdf_data = (GLOBAL float const*)&data[1]; + GLOBAL float const* pdf_data = cdf_data + num_segments + 1; + + // Calc pdf + return pdf_data[d] / num_segments; +} + + #endif // SAMPLING_CL diff --git a/Baikal/CL/scene.cl b/Baikal/Kernels/CL/scene.cl similarity index 69% rename from Baikal/CL/scene.cl rename to Baikal/Kernels/CL/scene.cl index b83204db..ad89fc84 100644 --- a/Baikal/CL/scene.cl +++ b/Baikal/Kernels/CL/scene.cl @@ -22,9 +22,9 @@ THE SOFTWARE. #ifndef SCENE_CL #define SCENE_CL -#include "../Baikal/CL/common.cl" -#include "../Baikal/CL/utils.cl" -#include "../Baikal/CL/payload.cl" +#include <../Baikal/Kernels/CL/common.cl> +#include <../Baikal/Kernels/CL/utils.cl> +#include <../Baikal/Kernels/CL/payload.cl> typedef struct { @@ -38,16 +38,18 @@ typedef struct GLOBAL int const* restrict indices; // Shapes GLOBAL Shape const* restrict shapes; - // Material IDs - GLOBAL int const* restrict materialids; - // Materials - GLOBAL Material const* restrict materials; + // Material attributes + GLOBAL int const* restrict material_attributes; + // Input map values + GLOBAL InputMapData const* restrict input_map_values; // Emissive objects GLOBAL Light const* restrict lights; // Envmap idx int env_light_idx; // Number of emissive objects int num_lights; + // Light distribution + GLOBAL int const* restrict light_distribution; } Scene; // Get triangle vertices given scene, shape index and prim index @@ -118,11 +120,78 @@ INLINE void Scene_InterpolateAttributes(Scene const* scene, int shape_idx, int p *area = 0.5f * length(cross(v2 - v0, v1 - v0)); } -// Get material index of a shape face -INLINE int Scene_GetMaterialIndex(Scene const* scene, int shape_idx, int prim_idx) +// Interpolate position, normal and uv +INLINE void Scene_InterpolateVertices(Scene const* scene, int shape_idx, int prim_idx, float2 barycentrics, float3* p) +{ + // Extract shape data + Shape shape = scene->shapes[shape_idx]; + + // Fetch indices starting from startidx and offset by prim_idx + int i0 = scene->indices[shape.startidx + 3 * prim_idx]; + int i1 = scene->indices[shape.startidx + 3 * prim_idx + 1]; + int i2 = scene->indices[shape.startidx + 3 * prim_idx + 2]; + + // Fetch positions and transform to world space + float3 v0 = matrix_mul_point3(shape.transform, scene->vertices[shape.startvtx + i0]); + float3 v1 = matrix_mul_point3(shape.transform, scene->vertices[shape.startvtx + i1]); + float3 v2 = matrix_mul_point3(shape.transform, scene->vertices[shape.startvtx + i2]); + + // Calculate barycentric position and normal + *p = (1.f - barycentrics.x - barycentrics.y) * v0 + barycentrics.x * v1 + barycentrics.y * v2; +} + +// Interpolate position, normal and uv +INLINE void Scene_InterpolateVerticesFromIntersection(Scene const* scene, Intersection const* isect, float3* p) +{ + // Extract shape data + int shape_idx = isect->shapeid - 1; + int prim_idx = isect->primid; + float2 barycentrics = isect->uvwt.xy; + + Shape shape = scene->shapes[shape_idx]; + + // Fetch indices starting from startidx and offset by prim_idx + int i0 = scene->indices[shape.startidx + 3 * prim_idx]; + int i1 = scene->indices[shape.startidx + 3 * prim_idx + 1]; + int i2 = scene->indices[shape.startidx + 3 * prim_idx + 2]; + + // Fetch positions and transform to world space + float3 v0 = matrix_mul_point3(shape.transform, scene->vertices[shape.startvtx + i0]); + float3 v1 = matrix_mul_point3(shape.transform, scene->vertices[shape.startvtx + i1]); + float3 v2 = matrix_mul_point3(shape.transform, scene->vertices[shape.startvtx + i2]); + + // Calculate barycentric position and normal + *p = (1.f - barycentrics.x - barycentrics.y) * v0 + barycentrics.x * v1 + barycentrics.y * v2; +} + +// Interpolate position, normal and uv +INLINE void Scene_InterpolateNormalsFromIntersection(Scene const* scene, Intersection const* isect, float3* n) { + // Extract shape data + int shape_idx = isect->shapeid - 1; + int prim_idx = isect->primid; + float2 barycentrics = isect->uvwt.xy; + Shape shape = scene->shapes[shape_idx]; - return scene->materialids[shape.start_material_idx + prim_idx]; + + // Fetch indices starting from startidx and offset by prim_idx + int i0 = scene->indices[shape.startidx + 3 * prim_idx]; + int i1 = scene->indices[shape.startidx + 3 * prim_idx + 1]; + int i2 = scene->indices[shape.startidx + 3 * prim_idx + 2]; + + // Fetch normals + float3 n0 = scene->normals[shape.startvtx + i0]; + float3 n1 = scene->normals[shape.startvtx + i1]; + float3 n2 = scene->normals[shape.startvtx + i2]; + + // Calculate barycentric position and normal + *n = normalize(matrix_mul_vector3(shape.transform, (1.f - barycentrics.x - barycentrics.y) * n0 + barycentrics.x * n1 + barycentrics.y * n2)); +} + +INLINE int Scene_GetVolumeIndex(Scene const* scene, int shape_idx) +{ + Shape shape = scene->shapes[shape_idx]; + return shape.volume_idx; } /// Fill DifferentialGeometry structure based on intersection info from RadeonRays @@ -165,18 +234,19 @@ void Scene_FillDifferentialGeometry(// Scene // Calculate true normal diffgeo->ng = normalize(cross(v1 - v0, v2 - v0)); - // Reverse geometric normal if shading normal points to different side - if (dot(diffgeo->ng, diffgeo->n) < 0.f) - diffgeo->ng = -diffgeo->ng; - // Get material at shading point - int material_idx = Scene_GetMaterialIndex(scene, shape_idx, prim_idx); - diffgeo->mat = scene->materials[material_idx]; + diffgeo->mat = shape.material; // Get UVs float2 uv0, uv1, uv2; Scene_GetTriangleUVs(scene, shape_idx, prim_idx, &uv0, &uv1, &uv2); + // Reverse geometric normal if shading normal points to different side + if (dot(diffgeo->ng, diffgeo->n) < 0.f) + { + diffgeo->ng = -diffgeo->ng; + } + /// Calculate tangent basis /// From PBRT book float du1 = uv0.x - uv2.x; @@ -193,9 +263,10 @@ void Scene_FillDifferentialGeometry(// Scene diffgeo->dpdu = normalize( (dv2 * dp1 - dv1 * dp2) * invdet ); diffgeo->dpdv = normalize( (-du2 * dp1 + du1 * dp2) * invdet ); diffgeo->dpdu -= dot(diffgeo->n, diffgeo->dpdu) * diffgeo->n; + diffgeo->dpdu = normalize(diffgeo->dpdu); + diffgeo->dpdv -= dot(diffgeo->n, diffgeo->dpdv) * diffgeo->n; diffgeo->dpdv -= dot(diffgeo->dpdu, diffgeo->dpdv) * diffgeo->dpdu; - diffgeo->dpdu = normalize(diffgeo->dpdu); diffgeo->dpdv = normalize(diffgeo->dpdv); } else @@ -203,8 +274,6 @@ void Scene_FillDifferentialGeometry(// Scene diffgeo->dpdu = normalize(GetOrthoVector(diffgeo->n)); diffgeo->dpdv = normalize(cross(diffgeo->n, diffgeo->dpdu)); } - - diffgeo->material_index = material_idx; } @@ -225,13 +294,21 @@ INLINE void DifferentialGeometry_CalculateTangentTransforms(DifferentialGeometry diffgeo->tangent_to_world.m2.w = diffgeo->p.z; } +#define POWER_SAMPLING + // Sample light index INLINE int Scene_SampleLight(Scene const* scene, float sample, float* pdf) { +#ifndef POWER_SAMPLING int num_lights = scene->num_lights; int light_idx = clamp((int)(sample * num_lights), 0, num_lights - 1); *pdf = 1.f / num_lights; return light_idx; +#else + int num_lights = scene->num_lights; + int light_idx = Distribution1D_SampleDiscrete(sample, scene->light_distribution, pdf); + return light_idx; +#endif } #endif diff --git a/Baikal/CL/sh.cl b/Baikal/Kernels/CL/sh.cl similarity index 99% rename from Baikal/CL/sh.cl rename to Baikal/Kernels/CL/sh.cl index 0972906c..46008465 100644 --- a/Baikal/CL/sh.cl +++ b/Baikal/Kernels/CL/sh.cl @@ -19,6 +19,8 @@ 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 SH_CL +#define SH_CL #define MAX_BAND 2 #define PI 3.14159265358979323846f @@ -459,4 +461,6 @@ __kernel void ShReconstructLmmap( lmmap[w * y + x] = val; } -} \ No newline at end of file +} + +#endif diff --git a/Baikal/CL/texture.cl b/Baikal/Kernels/CL/texture.cl similarity index 98% rename from Baikal/CL/texture.cl rename to Baikal/Kernels/CL/texture.cl index 57270d2f..efab861f 100644 --- a/Baikal/CL/texture.cl +++ b/Baikal/Kernels/CL/texture.cl @@ -23,8 +23,8 @@ THE SOFTWARE. #define TEXTURE_CL -#include <../Baikal/CL/payload.cl> -#include <../Baikal/CL/utils.cl> +#include <../Baikal/Kernels/CL/payload.cl> +#include <../Baikal/Kernels/CL/utils.cl> /// To simplify a bit @@ -123,7 +123,7 @@ float4 Texture_Sample2D(float2 uv, TEXTURE_ARG_LIST_IDX(texidx)) /// Sample lattitue-longitude environment map using 3d vector inline -float3 Texture_SampleEnvMap(float3 d, TEXTURE_ARG_LIST_IDX(texidx)) +float3 Texture_SampleEnvMap(float3 d, TEXTURE_ARG_LIST_IDX(texidx), bool mirror_x) { // Transform to spherical coords float r, phi, theta; @@ -131,7 +131,7 @@ float3 Texture_SampleEnvMap(float3 d, TEXTURE_ARG_LIST_IDX(texidx)) // Map to [0,1]x[0,1] range and reverse Y axis float2 uv; - uv.x = phi / (2*PI); + uv.x = (mirror_x) ? (1.f - phi / (2 * PI)) : phi / (2 * PI); uv.y = 1.f - theta / PI; // Sample the texture diff --git a/Baikal/CL/utils.cl b/Baikal/Kernels/CL/utils.cl similarity index 78% rename from Baikal/CL/utils.cl rename to Baikal/Kernels/CL/utils.cl index 531e4dff..dcc6baf9 100644 --- a/Baikal/CL/utils.cl +++ b/Baikal/Kernels/CL/utils.cl @@ -24,7 +24,7 @@ THE SOFTWARE. #define PI 3.14159265358979323846f -#include <../Baikal/CL/payload.cl> +#include <../Baikal/Kernels/CL/payload.cl> #ifndef APPLE /// These functions are defined on OSX already @@ -176,6 +176,12 @@ float3 GetOrthoVector(float3 n) return normalize(p); } +float luminance(float3 v) +{ + // Luminance + return 0.2126f * v.x + 0.7152f * v.y + 0.0722f * v.z; +} + uint upper_power_of_two(uint v) { v--; @@ -188,5 +194,48 @@ uint upper_power_of_two(uint v) return v; } +INLINE +void atomic_add_float(volatile __global float* addr, float value) +{ + union { + unsigned int u32; + float f32; + } next, expected, current; + current.f32 = *addr; + do { + expected.f32 = current.f32; + next.f32 = expected.f32 + value; + current.u32 = atomic_cmpxchg((volatile __global unsigned int *)addr, + expected.u32, next.u32); + } while (current.u32 != expected.u32); +} + +void atomic_add_float3(volatile __global float3* ptr, float3 value) +{ + volatile __global float* p = (volatile __global float*)ptr; + atomic_add_float(p, value.x); + atomic_add_float(p + 1, value.y); + atomic_add_float(p + 2, value.z); +} + +void atomic_add_float4(volatile __global float4* ptr, float4 value) +{ + volatile __global float* p = (volatile __global float*)ptr; + atomic_add_float(p, value.x); + atomic_add_float(p + 1, value.y); + atomic_add_float(p + 2, value.z); + atomic_add_float(p + 3, value.w); +} + +void add_float3(__global float3* ptr, float3 value) +{ + *ptr += value; +} + +void add_float4(__global float4* ptr, float4 value) +{ + *ptr += value; +} + #endif // UTILS_CL diff --git a/Baikal/CL/vertex.cl b/Baikal/Kernels/CL/vertex.cl similarity index 100% rename from Baikal/CL/vertex.cl rename to Baikal/Kernels/CL/vertex.cl diff --git a/Baikal/CL/volumetrics.cl b/Baikal/Kernels/CL/volumetrics.cl similarity index 61% rename from Baikal/CL/volumetrics.cl rename to Baikal/Kernels/CL/volumetrics.cl index d6a4ba72..c2de5123 100644 --- a/Baikal/CL/volumetrics.cl +++ b/Baikal/Kernels/CL/volumetrics.cl @@ -22,52 +22,52 @@ THE SOFTWARE. #ifndef VOLUMETRICS_CL #define VOLUMETRICS_CL -#include <../Baikal/CL/common.cl> -#include <../Baikal/CL/payload.cl> -#include <../Baikal/CL/path.cl> +#include <../Baikal/Kernels/CL/common.cl> +#include <../Baikal/Kernels/CL/payload.cl> +#include <../Baikal/Kernels/CL/path.cl> #define FAKE_SHAPE_SENTINEL 0xFFFFFF -// The following functions are taken from PBRT -float PhaseFunction_Uniform(float3 wi, float3 wo) -{ - return 1.f / (4.f * PI); -} - -float PhaseFunction_Rayleigh(float3 wi, float3 wo) +float PhaseFunctionHG(float3 wi, float3 wo, float g) { float costheta = dot(wi, wo); - return 3.f / (16.f*PI) * (1 + costheta * costheta); + return 1.f / (4.f * PI) * + (1.f - g*g) / native_powr(1.f + g*g - 2.f * g * costheta, 1.5f); } -float PhaseFunction_MieHazy(float3 wi, float3 wo) +// See PBRT for derivation +float PhaseFunctionHG_Sample(float3 wi, float g, float2 sample, float3* wo) { - float costheta = dot(wi, wo); - return (0.5f + 4.5f * native_powr(0.5f * (1.f + costheta), 8.f)) / (4.f*PI); -} + float costheta = 0.f; + if (fabs(g) < 1e-5) + { + costheta = 1.f - 2.f * sample.x; + } + else + { + float temp = (1.f - g * g) / (1.f - g + 2.f * g * sample.x); + costheta = (1 + g * g - temp * temp) / (2.f * g); + } -float PhaseFunction_MieMurky(float3 wi, float3 wo) -{ - float costheta = dot(wi, wo); - return (0.5f + 16.5f * native_powr(0.5f * (1.f + costheta), 32.f)) / (4.f*PI); -} + float phi = 2.f * PI * sample.y; -float PhaseFunction_HG(float3 wi, float3 wo, float g) -{ - float costheta = dot(wi, wo); - return 1.f / (4.f * PI) * - (1.f - g*g) / native_powr(1.f + g*g - 2.f * g * costheta, 1.5f); + float3 u = GetOrthoVector(-wi); + float3 v = normalize(cross(-wi, u)); + *wo = u * native_cos(phi) + v * native_sin(phi) - wi * costheta; + + return PhaseFunctionHG(wi, *wo, g); } // Evaluate volume transmittance along the ray [0, dist] segment -float3 Volume_Transmittance(__global Volume const* volume, __global ray const* ray, float dist) +float3 Volume_Transmittance(GLOBAL Volume const* volume, GLOBAL ray const* ray, float dist) { switch (volume->type) { case kHomogeneous: { // For homogeneous it is e(-sigma * dist) - float3 sigma_t = volume->sigma_a + volume->sigma_s; + float3 sigma_t = TEXTURED_INPUT_GET_COLOR(volume->sigma_a) + + TEXTURED_INPUT_GET_COLOR(volume->sigma_s); return native_exp(-sigma_t * dist); } } @@ -76,14 +76,13 @@ float3 Volume_Transmittance(__global Volume const* volume, __global ray const* r } // Evaluate volume selfemission along the ray [0, dist] segment -float3 Volume_Emission(__global Volume const* volume, __global ray const* ray, float dist) +float3 Volume_Emission(GLOBAL Volume const* volume, GLOBAL ray const* ray, float dist) { switch (volume->type) { case kHomogeneous: { - // For homogeneous it is simply Tr * Ev (since sigma_e is constant) - return Volume_Transmittance(volume, ray, dist) * volume->sigma_e; + return TEXTURED_INPUT_GET_COLOR(volume->sigma_e) * dist; } } @@ -91,16 +90,23 @@ float3 Volume_Emission(__global Volume const* volume, __global ray const* ray, f } // Sample volume in order to find next scattering event -float Volume_SampleDistance(__global Volume const* volume, __global ray const* ray, float maxdist, float sample, float* pdf) +float Volume_SampleDistance(GLOBAL Volume const* volume, GLOBAL ray const* ray, float maxdist, float2 sample, float* pdf) { + // Sample component + float3 sigma_s = TEXTURED_INPUT_GET_COLOR(volume->sigma_s); + float sigma = sample.x < 0.33f ? sigma_s.x : + sample.x < 0.66f ? sigma_s.y : sigma_s.z; + switch (volume->type) { case kHomogeneous: { - // The PDF = sigma * e(-sigma * x), so the larger sigma the closer we scatter - float sigma = (volume->sigma_s.x + volume->sigma_s.y + volume->sigma_s.z) / 3; - float d = sigma > 0.f ? (-native_log(sample) / sigma) : -1.f; - *pdf = sigma > 0.f ? (sigma * native_exp(-sigma * d)) : 0.f; + + float d = sigma > 0.f ? (-native_log(sample.y) / sigma) : -1.f; + float temp = (1.f / 3.f) * (sigma_s.x * native_exp(-sigma_s.x * d) + + sigma_s.y * native_exp(-sigma_s.y * d) + + sigma_s.z * native_exp(-sigma_s.z * d)); + *pdf = sigma > 0.f ? temp : 0.f; return d; } } @@ -108,6 +114,23 @@ float Volume_SampleDistance(__global Volume const* volume, __global ray const* r return -1.f; } +// Sample volume in order to find next scattering event +float Volume_GetDistancePdf(GLOBAL Volume const* volume, float dist) +{ + switch (volume->type) + { + case kHomogeneous: + { + float3 sigma_s = TEXTURED_INPUT_GET_COLOR(volume->sigma_s); + return (1.f / 3.f) * (native_exp(-sigma_s.x * dist) + + native_exp(-sigma_s.y * dist) + + native_exp(-sigma_s.z * dist)); + } + } + + return 0.f; +} + // Apply volume effects (absorbtion and emission) and scatter if needed. // The rays we handling here might intersect something or miss, // since scattering can happen even for missed rays. @@ -115,43 +138,45 @@ float Volume_SampleDistance(__global Volume const* volume, __global ray const* r // In case ray has missed geometry (has shapeid < 0) and has been scattered, // we put FAKE_SHAPE_SENTINEL into shapeid to prevent ray from being compacted away. // -__kernel void EvaluateVolume( +KERNEL void SampleVolume( // Ray batch - __global ray const* rays, + GLOBAL ray const* rays, // Pixel indices - __global int const* pixelindices, + GLOBAL int const* pixelindices, + // Output indices + GLOBAL int const* output_indices, // Number of rays - __global int const* numrays, + GLOBAL int const* numrays, // Volumes - __global Volume const* volumes, + GLOBAL Volume const* volumes, // Textures TEXTURE_ARG_LIST, // RNG seed uint rngseed, // Sampler state - __global uint* random, + GLOBAL uint* random, // Sobol matrices - __global uint const* sobolmat, + GLOBAL uint const* sobol_mat, // Current bounce int bounce, // Current frame int frame, // Intersection data - __global Intersection* isects, + GLOBAL Intersection* isects, // Current paths - __global Path* paths, + GLOBAL Path* paths, // Output - __global float3* output + GLOBAL float3* output ) { int globalid = get_global_id(0); - + // Only handle active rays if (globalid < *numrays) { int pixelidx = pixelindices[globalid]; - __global Path* path = paths + pixelidx; + GLOBAL Path* path = paths + pixelidx; // Path can be dead here since compaction step has not // yet been applied @@ -179,7 +204,9 @@ __kernel void EvaluateVolume( // Try sampling volume for a next scattering event float pdf = 0.f; float maxdist = Intersection_GetDistance(isects + globalid); - float d = Volume_SampleDistance(&volumes[volidx], &rays[globalid], maxdist, Sampler_Sample1D(&sampler, SAMPLER_ARGS), &pdf); + float2 sample = Sampler_Sample2D(&sampler, SAMPLER_ARGS); + float2 sample1 = Sampler_Sample2D(&sampler, SAMPLER_ARGS); + float d = Volume_SampleDistance(&volumes[volidx], &rays[globalid], maxdist, make_float2(sample.x, sample1.y), &pdf); // Check if we shall skip the event (it is either outside of a volume or not happened at all) bool skip = d < 0 || d > maxdist || pdf <= 0.f; @@ -189,19 +216,20 @@ __kernel void EvaluateVolume( // In case we skip we just need to apply volume absorbtion and emission for the segment we went through // and clear scatter flag Path_ClearScatterFlag(path); - // Emission contribution accounting for a throughput we have so far - Path_AddContribution(path, output, pixelidx, Volume_Emission(&volumes[volidx], &rays[globalid], maxdist)); // And finally update the throughput - Path_MulThroughput(path, Volume_Transmittance(&volumes[volidx], &rays[globalid], maxdist)); + Path_MulThroughput(path, Volume_Transmittance(&volumes[volidx], &rays[globalid], maxdist) * Volume_GetDistancePdf(&volumes[volidx], maxdist)); + // Emission contribution accounting for a throughput we have so far + Path_AddContribution(path, output, output_indices[pixelidx], Volume_Emission(&volumes[volidx], &rays[globalid], maxdist)); } else { // Set scattering flag to notify ShadeVolume kernel to handle this path Path_SetScatterFlag(path); - // Emission contribution accounting for a throughput we have so far - Path_AddContribution(path, output, pixelidx, Volume_Emission(&volumes[volidx], &rays[globalid], d) / pdf); // Update the throughput - Path_MulThroughput(path, (Volume_Transmittance(&volumes[volidx], &rays[globalid], d) / pdf)); + float3 sigma_s = TEXTURED_INPUT_GET_COLOR(volumes[volidx].sigma_s); + Path_MulThroughput(path, sigma_s * (Volume_Transmittance(&volumes[volidx], &rays[globalid], d) / pdf)); + // Emission contribution accounting for a throughput we have so far + Path_AddContribution(path, output, output_indices[pixelidx], Volume_Emission(&volumes[volidx], &rays[globalid], d) / pdf); // Put fake shape to prevent from being compacted away isects[globalid].shapeid = FAKE_SHAPE_SENTINEL; // And keep scattering distance around as well diff --git a/Baikal/Kernels/CL/wavelet_denoise.cl b/Baikal/Kernels/CL/wavelet_denoise.cl new file mode 100644 index 00000000..193ee2bb --- /dev/null +++ b/Baikal/Kernels/CL/wavelet_denoise.cl @@ -0,0 +1,922 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 WAVELETDENOISE_CL +#define WAVELETDENOISE_CL + +#include <../Baikal/Kernels/CL/common.cl> +#include <../Baikal/Kernels/CL/utils.cl> + +#define WAVELET_KERNEL_SIZE 25 +#define GAUSS_KERNEL_SIZE 9 +#define DENOM_EPS 1e-8f +#define FRAME_BLEND_ALPHA 0.2f +#define MLAA_MAX_SEARCH_STEPS 15 + +// Gauss filter 3x3 for variance prefiltering on first wavelet pass +float4 GaussFilter3x3( + GLOBAL float4 const* restrict buffer, + int2 buffer_size, + int2 uv) +{ + const int2 kernel_offsets[GAUSS_KERNEL_SIZE] = { + make_int2(-1, -1), make_int2(0, -1), make_int2(1, -1), + make_int2(-1, 0), make_int2(0, 0), make_int2(1, 0), + make_int2(-1, 1), make_int2(0, 1), make_int2(1, 1), + }; + + const float kernel_weights[GAUSS_KERNEL_SIZE] = { + 1.0 / 16.0, 1.0 / 8.0, 1.0 / 16.0, + 1.0 / 8.0, 1.0 / 4.0, 1.0 / 8.0, + 1.0 / 16.0, 1.0 / 8.0, 1.0 / 16.0 + }; + + float4 sample_out = make_float4(0.f, 0.f, 0.f, 0.f); + + for (int i = 0; i < GAUSS_KERNEL_SIZE; i++) + { + const int cx = clamp(uv.x + kernel_offsets[i].x, 0, buffer_size.x - 1); + const int cy = clamp(uv.y + kernel_offsets[i].y, 0, buffer_size.y - 1); + const int ci = cy * buffer_size.x + cx; + + sample_out += kernel_weights[i] * buffer[ci]; + } + + return sample_out; +} + +// Convertor to linear address with out of bounds clamp +int ConvertToLinearAddress(int address_x, int address_y, int2 buffer_size) +{ + int max_buffer_size = buffer_size.x * buffer_size.y; + return clamp(address_y * buffer_size.x + address_x, 0, max_buffer_size - 1); +} + +int ConvertToLinearAddressInt2(int2 address, int2 buffer_size) +{ + return ConvertToLinearAddress(address.x, address.y, buffer_size); +} + +// Bilinear sampler +float4 Sampler2DBilinear(GLOBAL float4 const* restrict buffer, int2 buffer_size, float2 uv) +{ + uv = uv * make_float2(buffer_size.x, buffer_size.y) - make_float2(0.5f, 0.5f); + + int x = floor(uv.x); + int y = floor(uv.y); + + float2 uv_ratio = uv - make_float2(x, y); + float2 uv_inv = make_float2(1.f, 1.f) - uv_ratio; + + int x1 = clamp(x + 1, 0, buffer_size.x - 1); + int y1 = clamp(y + 1, 0, buffer_size.y - 1); + + float4 r = (buffer[ConvertToLinearAddress(x, y, buffer_size)] * uv_inv.x + buffer[ConvertToLinearAddress(x1, y, buffer_size)] * uv_ratio.x) * uv_inv.y + + (buffer[ConvertToLinearAddress(x, y1, buffer_size)] * uv_inv.x + buffer[ConvertToLinearAddress(x1, y1, buffer_size)] * uv_ratio.x) * uv_ratio.y; + + return r; +} + + +// Derivatives with subpixel values +float4 dFdx(GLOBAL float4 const* restrict buffer, float2 uv, int2 buffer_size) +{ + const float2 uv_x = uv + make_float2(1.0f / (float)buffer_size.x, 0.0); + + return Sampler2DBilinear(buffer, buffer_size, uv_x) - Sampler2DBilinear(buffer, buffer_size, uv); +} + +float4 dFdy(GLOBAL float4 const* restrict buffer, float2 uv, int2 buffer_size) +{ + const float2 uv_y = uv + make_float2(0.0, 1.0f / (float)buffer_size.y); + + return Sampler2DBilinear(buffer, buffer_size, uv_y) - Sampler2DBilinear(buffer, buffer_size, uv); +} + + +KERNEL +void WaveletFilter_main( + // Color data + GLOBAL float4 const* restrict colors, + // Normal data + GLOBAL float4 const* restrict normals, + // Positional data + GLOBAL float4 const* restrict positions, + // Variance + GLOBAL float4 const* restrict variances, + // Albedo + GLOBAL float4 const* restrict albedo, + // Image resolution + int width, + int height, + // Filter width + int step_width, + // Filter kernel parameters + float sigma_color, + float sigma_position, + // Resulting color + GLOBAL float4* restrict out_colors +) +{ + int2 global_id; + global_id.x = get_global_id(0); + global_id.y = get_global_id(1); + + const float kernel_weights[WAVELET_KERNEL_SIZE] = { + 1.0 / 256.0, 1.0 / 64.0, 3.0 / 128.0, 1.0 / 64.0, 1.0 / 256.0, + 1.0 / 64.0, 1.0 / 16.0, 3.0 / 32.0, 1.0 / 16.0, 1.0 / 64.0, + 3.0 / 128.0, 3.0 / 32.0, 9.0 / 64.0, 3.0 / 32.0, 3.0 / 128.0, + 1.0 / 64.0, 1.0 / 16.0, 3.0 / 32.0, 1.0 / 16.0, 1.0 / 64.0, + 1.0 / 256.0, 1.0 / 64.0, 3.0 / 128.0, 1.0 / 64.0, 1.0 / 256.0 }; + + const int2 kernel_offsets[WAVELET_KERNEL_SIZE] = { + make_int2(-2, -2), make_int2(-1, -2), make_int2(0, -2), make_int2(1, -2), make_int2(2, -2), + make_int2(-2, -1), make_int2(-1, -1), make_int2(0, -2), make_int2(1, -1), make_int2(2, -1), + make_int2(-2, 0), make_int2(-1, 0), make_int2(0, 0), make_int2(1, 0), make_int2(2, 0), + make_int2(-2, 1), make_int2(-1, 1), make_int2(0, 1), make_int2(1, 1), make_int2(2, 1), + make_int2(-2, 2), make_int2(-1, 2), make_int2(0, 2), make_int2(1, 2), make_int2(2, 2) }; + + const int2 buffer_size = make_int2(width, height); + const float2 uv = make_float2(global_id.x + 0.5f, global_id.y + 0.5f) / make_float2(width, height); + + // Check borders + if (global_id.x < width && global_id.y < height) + { + const int idx = global_id.y * width + global_id.x; + + const float3 color = colors[idx].xyz; + const float3 position = positions[idx].xyz; + const float3 normal = normals[idx].xyz; + const float3 calbedo = albedo[idx].xyz / max(albedo[idx].w, 1.f); + + const float variance = step_width == 1 ? sqrt(GaussFilter3x3(variances, buffer_size, global_id).z) : sqrt(variances[idx].z); + const float step_width_2 = (float)(step_width * step_width); + + float3 color_sum = make_float3(0.0f, 0.0f, 0.0f); + float weight_sum = 0.f; + + const float3 luminance = make_float3(0.2126f, 0.7152f, 0.0722f); + const float lum_color = dot(color, luminance); + + const float max_sigma_variance = 8.0f; + const float min_sigma_variance = 1.0f; + const float sigma_adaptation_samples = 100.0f; + const float sigma_variance = max(max_sigma_variance * exp(-albedo[idx].w / sigma_adaptation_samples), min_sigma_variance); + + if (length(position) > 0.f && !any(isnan(color))) + { + for (int i = 0; i < WAVELET_KERNEL_SIZE; i++) + { + const int cx = clamp(global_id.x + step_width * kernel_offsets[i].x, 0, width - 1); + const int cy = clamp(global_id.y + step_width * kernel_offsets[i].y, 0, height - 1); + const int ci = cy * width + cx; + + const float3 sample_color = colors[ci].xyz; + const float3 sample_normal = normals[ci].xyz; + const float3 sample_position = positions[ci].xyz; + const float3 sample_albedo = albedo[ci].xyz / max(albedo[ci].w, 1.f); + + const float3 delta_position = position - sample_position; + const float3 delta_color = calbedo - sample_albedo; + + const float position_dist2 = dot(delta_position, delta_position); + const float color_dist2 = dot(delta_color, delta_color); + + const float position_value = exp(-position_dist2 / (sigma_position * 20.f)); + const float color_value = exp(-color_dist2 / sigma_color); + + const float position_weight = isnan(position_value) ? 1.f : position_value; + const float color_weight = isnan(color_value) ? 1.f : color_value; + const float normal_weight = pow(max(0.f, dot(sample_normal, normal)), 128.f); + + const float lum_value = exp(-fabs((lum_color - dot(luminance, sample_color))) / (sigma_variance * variance + DENOM_EPS)); + const float luminance_weight = isnan(lum_value) ? 1.f : lum_value; + + const float final_weight = color_weight * luminance_weight * normal_weight * position_weight * kernel_weights[i]; + + color_sum += final_weight * sample_color; + weight_sum += final_weight; + } + + out_colors[idx].xyz = color_sum / max(weight_sum, DENOM_EPS); + out_colors[idx].w = 1.f; + } + else + { + out_colors[idx].xyz = color; + out_colors[idx].w = 1.f; + } + } +} + +KERNEL +void WaveletGenerateMotionBuffer_main( + GLOBAL float4 const* restrict positions, + // Image resolution + int width, + int height, + // View-projection matrix of current frame + GLOBAL matrix4x4* restrict view_projection, + // View-projection matrix of previous frame + GLOBAL matrix4x4* restrict prev_view_projection, + // Resulting motion and depth + GLOBAL float4* restrict out_motion +) +{ + int2 global_id; + global_id.x = get_global_id(0); + global_id.y = get_global_id(1); + + // Check borders + if (global_id.x < width && global_id.y < height) + { + const int idx = global_id.y * width + global_id.x; + + const float3 position_xyz = positions[idx].xyz / max(positions[idx].w, 1.f); + + if (length(position_xyz) > 0) + { + const float4 position = make_float4(position_xyz.x, position_xyz.y, position_xyz.z, 1.0f); + + float4 position_ps = matrix_mul_vector4(*view_projection, position); + float3 position_cs = position_ps.xyz / position_ps.w; + float2 position_ss = position_cs.xy * make_float2(0.5f, -0.5f) + make_float2(0.5f, 0.5f); + + float4 prev_position_ps = matrix_mul_vector4(*prev_view_projection, position); + float2 prev_position_cs = prev_position_ps.xy / prev_position_ps.w; + float2 prev_position_ss = prev_position_cs * make_float2(0.5f, -0.5f) + make_float2(0.5f, 0.5f); + + out_motion[idx] = (float4)(prev_position_ss - position_ss, 0.0f, 1.0f); + } + else + { + out_motion[idx] = make_float4(0.f, 0.f, 0.f, 1.f); + } + } +} + +KERNEL +void CopyBuffers_main( + // Input buffers + GLOBAL float4 const* restrict colors, + GLOBAL float4 const* restrict positions, + GLOBAL float4 const* restrict normals, + GLOBAL float4 const* restrict mesh_ids, + // Image resolution + int width, + int height, + // Output buffers + GLOBAL float4* restrict out_colors, + GLOBAL float4* restrict out_positions, + GLOBAL float4* restrict out_normals, + GLOBAL float4* restrict out_mesh_ids +) +{ + int2 global_id; + global_id.x = get_global_id(0); + global_id.y = get_global_id(1); + + // Check borders + if (global_id.x < width && global_id.y < height) + { + const int idx = global_id.y * width + global_id.x; + + out_colors[idx] = (float4)(colors[idx].xyz / max(colors[idx].w, 1.f), 1.f); + out_positions[idx] = (float4)(positions[idx].xyz / max(positions[idx].w, 1.f), 1.f); + out_normals[idx] = (float4)(normals[idx].xyz / max(normals[idx].w, 1.f), 1.f); + out_mesh_ids[idx] = mesh_ids[idx]; + } +} + +KERNEL +void CopyBuffer_main( + GLOBAL float4 const* restrict in_buffer, + GLOBAL float4* restrict out_buffer, + // Image resolution + int width, + int height +) +{ + int2 global_id; + global_id.x = get_global_id(0); + global_id.y = get_global_id(1); + + // Check borders + if (global_id.x < width && global_id.y < height) + { + const int idx = global_id.y * width + global_id.x; + out_buffer[idx] = in_buffer[idx]; + } +} + +// Geometry consistency term - normal alignment test +bool IsNormalConsistent(float3 nq, float3 np) +{ + const float cos_pi_div_4 = cos(PI / 4.f); + return dot(nq, np) > cos_pi_div_4; +} + +// Geometry consistency term - position consistency +bool IsPositionConsistent( + GLOBAL float4 const* restrict buffer, + GLOBAL float4 const* restrict prev_buffer, + float2 uv, + float2 motion, + int2 buffer_size) +{ + float2 uv_prev = uv + motion; + + float3 ddx = dFdx(buffer, uv, buffer_size).xyz * 4.f; + float3 ddy = dFdy(buffer, uv, buffer_size).xyz * 4.f; + + float3 p0 = Sampler2DBilinear(buffer, buffer_size, uv).xyz; + float3 p1 = Sampler2DBilinear(prev_buffer, buffer_size, uv_prev).xyz; + + return length(p1 - p0) < length(ddx) + length(ddy); +} + +// Bilinear filtering with geometry test on each tap (resampling of previous color buffer) +// TODO: Add depth test consistency +float4 SampleWithGeometryTest(GLOBAL float4 const* restrict buffer, + float4 current_color, + float3 current_positions, + float3 current_normal, + int current_mesh_id, + GLOBAL float4 const* restrict positions, + GLOBAL float4 const* restrict normals, + GLOBAL float4 const* restrict mesh_ids, + GLOBAL float4 const* restrict prev_positions, + GLOBAL float4 const* restrict prev_normals, + GLOBAL float4 const* restrict prev_mesh_ids, + int2 buffer_size, + float2 uv, + float2 uv_prev) +{ + uv_prev.x = clamp(uv_prev.x, 0.f, 1.f); + uv_prev.y = clamp(uv_prev.y, 0.f, 1.f); + + float2 scaled_uv = uv_prev * make_float2(buffer_size.x, buffer_size.y) - make_float2(0.5f, 0.5f); + + int x = floor(scaled_uv.x); + int y = floor(scaled_uv.y); + + const int2 offsets[4] = { + make_int2(x + 0, y + 0), + make_int2(x + 1, y + 0), + make_int2(x + 1, y + 1), + make_int2(x + 0, y + 1) + }; + + const float3 normal_samples[4] = { + prev_normals[ConvertToLinearAddressInt2(offsets[0], buffer_size)].xyz, + prev_normals[ConvertToLinearAddressInt2(offsets[1], buffer_size)].xyz, + prev_normals[ConvertToLinearAddressInt2(offsets[2], buffer_size)].xyz, + prev_normals[ConvertToLinearAddressInt2(offsets[3], buffer_size)].xyz + }; + + const bool is_normal_consistent[4] = { + IsNormalConsistent(current_normal, normal_samples[0]), + IsNormalConsistent(current_normal, normal_samples[1]), + IsNormalConsistent(current_normal, normal_samples[2]), + IsNormalConsistent(current_normal, normal_samples[3]) + }; + + const int mesh_id_samples[4] = { + (int)prev_mesh_ids[ConvertToLinearAddressInt2(offsets[0], buffer_size)].x, + (int)prev_mesh_ids[ConvertToLinearAddressInt2(offsets[1], buffer_size)].x, + (int)prev_mesh_ids[ConvertToLinearAddressInt2(offsets[2], buffer_size)].x, + (int)prev_mesh_ids[ConvertToLinearAddressInt2(offsets[3], buffer_size)].x + }; + + const bool is_mesh_id_consistent[4] = { + current_mesh_id == mesh_id_samples[0], + current_mesh_id == mesh_id_samples[1], + current_mesh_id == mesh_id_samples[2], + current_mesh_id == mesh_id_samples[3] + }; + + int num_consistent_samples = 0; + + for (int i = 0; i < 4; i++) num_consistent_samples += is_normal_consistent[i] && is_mesh_id_consistent[i] ? 1 : 0; + + // Bilinear resample if all samples are consistent + if (num_consistent_samples == 4) + { + return Sampler2DBilinear(buffer, buffer_size, uv_prev); + } + + // Box filter otherwise + const float4 buffer_samples[4] = { + buffer[ConvertToLinearAddressInt2(offsets[0], buffer_size)], + buffer[ConvertToLinearAddressInt2(offsets[1], buffer_size)], + buffer[ConvertToLinearAddressInt2(offsets[2], buffer_size)], + buffer[ConvertToLinearAddressInt2(offsets[3], buffer_size)] + }; + + float weight = 1; + float4 sample = current_color; + + for (int i = 0; i < 4; i++) + { + if (is_normal_consistent[i] && is_mesh_id_consistent[i]) + { + sample += buffer_samples[i]; + weight += 1.f; + } + } + + return sample / max(weight, 1.f); +} + +// Similarity function +inline float C(float3 x1, float3 x2, float sigma) +{ + float a = length(x1 - x2) / sigma; + a *= a; + return native_exp(-0.5f * a); +} + +// Spatial bilateral variance estimation +float4 BilateralVariance( + GLOBAL float4 const* restrict colors, + GLOBAL float4 const* restrict positions, + GLOBAL float4 const* restrict normals, + int2 global_id, + int2 buffer_size, + int kernel_size +) +{ + const float3 luminance_weight = make_float3(0.2126f, 0.7152f, 0.0722f); + + float local_mean = 0.f; + float local_mean_2 = 0.f; + float sum_weight = 0.0f; + + const int idx = global_id.y * buffer_size.x + global_id.x; + + float3 normal = normals[idx].w > 1 ? (normals[idx].xyz / normals[idx].w) : normals[idx].xyz; + float3 position = positions[idx].w > 1 ? (positions[idx].xyz / positions[idx].w) : positions[idx].xyz; + + const int borders = kernel_size >> 1; + + for (int i = -borders; i <= borders; ++i) + { + for (int j = -borders; j <= borders; ++j) + { + int cx = clamp(global_id.x + i, 0, buffer_size.x - 1); + int cy = clamp(global_id.y + j, 0, buffer_size.y - 1); + int ci = cy * buffer_size.x + cx; + + float3 c = colors[ci].xyz / colors[ci].w; + float3 n = normals[ci].xyz / normals[ci].w; + float3 p = positions[ci].xyz / positions[ci].w; + + float sigma_position = 0.1f; + float sigma_normal = 0.1f; + + if (length(p) > 0.f && !any(isnan(c))) + { + const float weight = C(p, position, sigma_position) * C(n, normal, sigma_normal); + const float luminance = dot(c, luminance_weight); + + local_mean += luminance * weight; + local_mean_2 += luminance * luminance * weight; + sum_weight += weight; + } + } + } + + local_mean = local_mean / max(DENOM_EPS, sum_weight); + local_mean_2 = local_mean_2 / max(DENOM_EPS, sum_weight);; + + const float variance = local_mean_2 - local_mean * local_mean; + + return make_float4( local_mean, local_mean_2, variance, 1.f); +} + +// Temporal accumulation of path tracer results and moments, spatio-temporal variance estimation +KERNEL +void TemporalAccumulation_main( + GLOBAL float4 const* restrict prev_colors, + GLOBAL float4 const* restrict prev_positions, + GLOBAL float4 const* restrict prev_normals, + GLOBAL float4* restrict in_out_colors, + GLOBAL float4 const* restrict positions, + GLOBAL float4 const* restrict normals, + GLOBAL float4 const* restrict motions, + GLOBAL float4 const* restrict prev_moments_and_variance, + GLOBAL float4* restrict moments_and_variance, + GLOBAL float4* restrict mesh_ids, + GLOBAL float4* restrict prev_mesh_ids, + // Image resolution + int width, + int height +) +{ + int2 global_id; + global_id.x = get_global_id(0); + global_id.y = get_global_id(1); + + // Check borders + if (global_id.x < width && global_id.y < height) + { + const int idx = global_id.y * width + global_id.x; + const int mesh_id = (int)mesh_ids[idx].x; + + const float3 position_xyz = positions[idx].xyz; + const float3 normal = normals[idx].xyz; + const float3 color = in_out_colors[idx].xyz; + + const int bilateral_filter_kernel_size = 7; + + if (length(position_xyz) > 0 && !any(isnan(color))) + { + const float2 motion = motions[idx].xy; + const int2 buffer_size = make_int2(width, height); + + const float2 uv = make_float2(global_id.x + 0.5f, global_id.y + 0.5f) / make_float2(width, height); + const float2 prev_uv = clamp(uv + motion, make_float2(0.f, 0.f), make_float2(1.f, 1.f)); + + const float sample_prev_mesh_id = (float)Sampler2DBilinear(prev_mesh_ids, buffer_size, prev_uv).x; + const int prev_mesh_id = (sample_prev_mesh_id - floor(sample_prev_mesh_id)) > 0.f ? -1 : (int)sample_prev_mesh_id; + + const float3 prev_position_xyz = Sampler2DBilinear(prev_positions, buffer_size, prev_uv).xyz; + const float3 prev_normal = normalize(Sampler2DBilinear(prev_normals, buffer_size, prev_uv).xyz); + + // Test for geometry consistency + if (length(prev_position_xyz) > 0 && mesh_id == prev_mesh_id && IsNormalConsistent(prev_normal, normal) && IsPositionConsistent(positions, prev_positions, uv, motion, buffer_size)) + { + // Temporal accumulation of moments + float4 prev_moments_and_variance_sample = Sampler2DBilinear(prev_moments_and_variance, buffer_size, prev_uv); + + const bool prev_moments_is_nan = any(isnan(prev_moments_and_variance_sample)); + + float4 current_moments_and_variance_sample; + + current_moments_and_variance_sample.w = prev_moments_and_variance_sample.w + 1.f; + + if (prev_moments_and_variance_sample.w < 4 || prev_moments_is_nan) + { + // Not enought accumulated samples - get bilateral estimate + current_moments_and_variance_sample.xyz = BilateralVariance(in_out_colors, positions, normals, global_id, buffer_size, bilateral_filter_kernel_size).xyz; + } + else + { + // Otherwise calculate moments for current color + const float3 luminance_weight = make_float3(0.2126f, 0.7152f, 0.0722f); + + const float first_moment = dot(color, luminance_weight); + const float second_moment = first_moment * first_moment; + + current_moments_and_variance_sample.xy += make_float2(first_moment, second_moment); + current_moments_and_variance_sample.z = (second_moment - first_moment * first_moment) / current_moments_and_variance_sample.w; + } + + // Nan avoidance + if (any(isnan(prev_moments_and_variance_sample))) + { + prev_moments_and_variance_sample = make_float4(0,0,0,1); + } + + float2 moments = mix(prev_moments_and_variance_sample.xy, current_moments_and_variance_sample.xy, FRAME_BLEND_ALPHA); + float variance = moments.y - moments.x * moments.x; + + moments_and_variance[idx] = make_float4(moments.x, moments.y, variance, current_moments_and_variance_sample.w); + + // Temporal accumulation of color + float3 prev_color = SampleWithGeometryTest(prev_colors, (float4)(color, 1.f), position_xyz, normal, mesh_id, positions, normals, mesh_ids, prev_positions, prev_normals, prev_mesh_ids, buffer_size, uv, prev_uv).xyz; + + in_out_colors[idx].xyz = (dot(motion, motion) != 0.f) ? mix(prev_color, color, FRAME_BLEND_ALPHA) : in_out_colors[idx].xyz; + in_out_colors[idx].w = 1.0f; + } + else + { + // In case of disoclussion - calclulate variance by bilateral estimate + moments_and_variance[idx] = BilateralVariance(in_out_colors, positions, normals, global_id, buffer_size, bilateral_filter_kernel_size); + } + } + } +} + +KERNEL +void UpdateVariance_main( + // Color data + GLOBAL float4 const* restrict colors, + GLOBAL float4 const* restrict positions, + GLOBAL float4 const* restrict normals, + // Image resolution + int width, + int height, + GLOBAL float4* restrict out_variance +) +{ + int2 global_id; + global_id.x = get_global_id(0); + global_id.y = get_global_id(1); + + const int bilateral_filter_kernel_size = 3; + const int2 buffer_size = make_int2(width, height); + + // Check borders + if (global_id.x < width && global_id.y < height) + { + const int idx = global_id.y * width + global_id.x; + out_variance[idx] = BilateralVariance(colors, positions, normals, global_id, buffer_size, bilateral_filter_kernel_size); + } +} + +// Jimenez MLAA. Implementation was adapted to OpenCL + +/** + * Copyright (C) 2010 Jorge Jimenez (jorge@iryoku.com) + * Copyright (C) 2010 Belen Masia (bmasia@unizar.es) + * Copyright (C) 2010 Jose I. Echevarria (joseignacioechevarria@gmail.com) + * Copyright (C) 2010 Fernando Navarro (fernandn@microsoft.com) + * Copyright (C) 2010 Diego Gutierrez (diegog@unizar.es) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the following statement: + * + * "Uses Jimenez's MLAA. Copyright (C) 2010 by Jorge Jimenez, Belen Masia, + * Jose I. Echevarria, Fernando Navarro and Diego Gutierrez." + * + * 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 COPYRIGHT HOLDERS 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. + * + * The views and conclusions contained in the software and documentation are + * those of the authors and should not be interpreted as representing official + * policies, either expressed or implied, of the copyright holders. + */ + +float4 texture2D(GLOBAL float4 const* restrict buffer, float2 uv, int2 buffer_size) +{ + return buffer[ConvertToLinearAddressInt2(make_int2(uv.x * buffer_size.x, uv.y * buffer_size.y), buffer_size)]; +} + +float4 texture2DOffset(GLOBAL float4 const* restrict buffer, float2 uv, int2 offset, int2 buffer_size, float2 rcp_buffer) +{ + uv = uv + make_float2(offset.x * rcp_buffer.x, offset.y * rcp_buffer.y); + + return buffer[ConvertToLinearAddressInt2(make_int2(uv.x * buffer_size.x, uv.y * buffer_size.y), buffer_size)]; +} + +float4 texture2DOffsetInt2(GLOBAL float4 const* restrict buffer, int2 uv, int2 offset, int2 buffer_size) +{ + uv = uv + offset; + + return buffer[ConvertToLinearAddressInt2(make_int2(uv.x, uv.y), buffer_size)]; +} + +KERNEL +void EdgeDetectionMLAA(GLOBAL float4 const* restrict mesh_id, + GLOBAL float4 const* restrict normal, + int width, + int height, + GLOBAL float4* restrict out_buffer) +{ + int2 global_id; + global_id.x = get_global_id(0); + global_id.y = get_global_id(1); + + const int max_pixels = width * height; + const int idx = clamp(global_id.y * width + global_id.x, 0, max_pixels); + const int2 buffer_size = make_int2(width, height); + + const float3 weights = make_float3(0.2126,0.7152, 0.0722); + + int2 edges = make_int2(0,0); + + float id = mesh_id[ConvertToLinearAddressInt2(global_id, buffer_size)].x; + float id_left = texture2DOffsetInt2(mesh_id, global_id, make_int2(-1, 0), buffer_size).x; + float id_top = texture2DOffsetInt2(mesh_id, global_id, make_int2(0, -1), buffer_size).x; + + edges.x = id != id_left ? 1 : 0; + edges.y = id != id_top ? 1 : 0; + + float3 N = normalize(normal[ConvertToLinearAddressInt2(global_id, buffer_size)].xyz); + + if (length(N) > 0) + { + float3 Nleft = normalize(texture2DOffsetInt2(normal, global_id, make_int2(-1, 0), buffer_size).xyz); + float3 Ntop = normalize(texture2DOffsetInt2(normal, global_id, make_int2(0, -1), buffer_size).xyz); + + const float threshold = cos(PI / 8.f); + float2 delta = make_float2(dot(N, Nleft), dot(N, Ntop)); + + edges.x |= delta.x < threshold ? 1 : 0; + edges.y |= delta.y < threshold ? 1 : 0; + } + + out_buffer[idx] = make_float4((float)edges.x, (float)edges.y, 0.f, 0.f); +} + +float SearchXLeft(GLOBAL float4 const* restrict edgesTex, float2 texcoord, int2 buffer_size, float2 rcp_frame) { + texcoord -= make_float2(1.5f, 0.0f) * rcp_frame; + + float e = 0.0f; + int i = 0; + + for (i = 0; i < MLAA_MAX_SEARCH_STEPS; i++) { + e = Sampler2DBilinear(edgesTex, buffer_size, texcoord).y; + if (e < 0.9) break; + texcoord -= make_float2(2.0f, 0.0f) * rcp_frame; + } + + return max(-2.0f * i - 2.0f * e, -2.0f * MLAA_MAX_SEARCH_STEPS); +} + +float SearchXRight(GLOBAL float4 const* restrict edgesTex, float2 texcoord, int2 buffer_size, float2 rcp_frame) { + texcoord += make_float2(1.5f, 0.0f) * rcp_frame; + + float e = 0.0f; + int i = 0; + + for (i = 0; i < MLAA_MAX_SEARCH_STEPS; i++) { + e = Sampler2DBilinear(edgesTex, buffer_size, texcoord).y; + if (e < 0.9) break; + texcoord += make_float2(2.0f, 0.0f) * rcp_frame; + } + + return min(2.0f * i + 2.0f * e, 2.0f * MLAA_MAX_SEARCH_STEPS); +} + +float SearchYUp(GLOBAL float4 const* restrict edgesTex, float2 texcoord, int2 buffer_size, float2 rcp_frame) { + texcoord += make_float2(0.0, -1.5) * rcp_frame; + + float e = 0.0; + int i = 0; + + for (i = 0; i < MLAA_MAX_SEARCH_STEPS; i++) { + e = Sampler2DBilinear(edgesTex, buffer_size, texcoord).x; + if (e < 0.9) break; + texcoord += make_float2(0.0f, -2.0f) * rcp_frame; + } + + return fmax(-2.0f * i - 2.0f * e, -2.0f * MLAA_MAX_SEARCH_STEPS); +} + +float SearchYDown(GLOBAL float4 const* restrict edgesTex, float2 texcoord, int2 buffer_size, float2 rcp_frame) { + texcoord -= make_float2(0.0, -1.5) * rcp_frame; + + float e = 0.0; + int i = 0; + + for (i = 0; i < MLAA_MAX_SEARCH_STEPS; i++) { + e = Sampler2DBilinear(edgesTex, buffer_size, texcoord).x; + if (e < 0.9) break; + texcoord -= make_float2(0.0f, -2.0f) * rcp_frame; + } + return fmin(2.0f * i + 2.0f * e, 2.0f * MLAA_MAX_SEARCH_STEPS); +} + +#define MAX_DISTANCE 33 + +float2 Area(GLOBAL float4 const* restrict areaTex, float2 distance, float e1, float e2) { + // * By dividing by areaSize - 1.0 below we are implicitely offsetting to + // always fall inside of a pixel + // * Rounding prevents bilinear access precision problems + float areaSize = MAX_DISTANCE * 5.0f; + float2 pixcoord = MAX_DISTANCE * round(4.0f * make_float2(e1, e2)) + distance; + float2 texcoord = pixcoord / (areaSize - 1.0f); + return texture2D(areaTex, texcoord, make_int2(areaSize, areaSize)).xy; +} + +KERNEL +void BlendingWeightCalculationMLAA( GLOBAL float4 const* restrict edgesTex, + GLOBAL float4 const* restrict areaTex, + int width, + int height, + GLOBAL float4* restrict out_buffer) +{ + int2 global_id; + global_id.x = get_global_id(0); + global_id.y = get_global_id(1); + + const float2 rcp_frame = make_float2(1.f / (float)width, 1.f / (float)height); + const int max_pixels = width * height; + const int idx = clamp(global_id.y * width + global_id.x, 0, max_pixels); + const int2 buffer_size = make_int2(width, height); + const float2 texcoord = make_float2((float)global_id.x / (float)width, (float)global_id.y / (float)height) + make_float2(0.5f, 0.5f) * rcp_frame; + + float4 weights = make_float4(0.f, 0.f, 0.f, 0.f); + + float2 e = texture2D(edgesTex, texcoord, buffer_size).xy; + + if (e.y) { // Edge at north + // Search distances to the left and to the right: + float2 d = make_float2(SearchXLeft(edgesTex, texcoord, buffer_size, rcp_frame), SearchXRight(edgesTex, texcoord, buffer_size, rcp_frame)); + + // Now fetch the crossing edges. Instead of sampling between edgels, we + // sample at -0.25, to be able to discern what value has each edgel: + float4 coords = mad(make_float4(d.x, -0.25f, d.y + 1.0f, -0.25f), rcp_frame.xyxy, texcoord.xyxy); + float e1 = Sampler2DBilinear(edgesTex, buffer_size, coords.xy).x; + float e2 = Sampler2DBilinear(edgesTex, buffer_size, coords.zw).x; + + // Ok, we know how this pattern looks like, now it is time for getting + // the actual area: + weights.xy = Area(areaTex, fabs(d), e1, e2); + } + + if (e.x) { // Edge at west + // Search distances to the top and to the bottom: + float2 d = make_float2(SearchYUp(edgesTex, texcoord, buffer_size, rcp_frame), SearchYDown(edgesTex, texcoord, buffer_size, rcp_frame)); + + // Now fetch the crossing edges (yet again): + float4 coords = mad(make_float4(-0.25f, d.x, -0.25f, (d.y + 1.0f)), rcp_frame.xyxy, texcoord.xyxy); + float e1 = Sampler2DBilinear(edgesTex, buffer_size, coords.xy).y; + float e2 = Sampler2DBilinear(edgesTex, buffer_size, coords.zw).y; + + // Get the area for this direction: + weights.zw = Area(areaTex, fabs(d), e1, e2); + } + + out_buffer[idx] = weights; +} + +KERNEL +void NeighborhoodBlendingMLAA( GLOBAL float4 const* restrict colorTex, + GLOBAL float4 const* restrict blendTex, + int width, + int height, + GLOBAL float4* restrict out_buffer) +{ + int2 global_id; + global_id.x = get_global_id(0); + global_id.y = get_global_id(1); + + const float2 rcp_frame = make_float2(1.f / (float)width, 1.f / (float)height); + const int max_pixels = width * height; + const int idx = clamp(global_id.y * width + global_id.x, 0, max_pixels); + const int2 buffer_size = make_int2(width, height); + const float2 texcoord = make_float2((float)global_id.x / (float)width, (float)global_id.y / (float)height) + make_float2(0.5f, 0.5f) * rcp_frame; + + // Fetch the blending weights for current pixel: + float4 topLeft = blendTex[ConvertToLinearAddressInt2(global_id, buffer_size)]; + float bottom = texture2DOffsetInt2(blendTex, global_id, make_int2(0, 1), buffer_size).y; + float right = texture2DOffsetInt2(blendTex, global_id, make_int2(1, 0), buffer_size).w; + float4 a = make_float4(topLeft.x, bottom, topLeft.z, right); + + // Up to 4 lines can be crossing a pixel (one in each edge). So, we perform + // a weighted average, where the weight of each line is 'a' cubed, which + // favors blending and works well in practice. + float4 w = a * a * a; + + // There is some blending weight with a value greater than 0.0? + float sum = dot(w, 1.0); + + if (sum < 1e-5) + { + out_buffer[idx] = colorTex[idx]; + return; + } + + float4 color = make_float4(0.f, 0.f, 0.f, 0.f); + + // Add the contributions of the possible 4 lines that can cross this + // pixel: + float4 coords = mad(make_float4( 0.0, -a.x, 0.0, +a.y), rcp_frame.yyyy, texcoord.xyxy); + color = mad(Sampler2DBilinear(colorTex, buffer_size, coords.xy), w.x, color); + color = mad(Sampler2DBilinear(colorTex, buffer_size, coords.zw), w.y, color); + + coords = mad(make_float4(-a.z, 0.0, a.w, 0.0), rcp_frame.xxxx, texcoord.xyxy); + color = mad(Sampler2DBilinear(colorTex, buffer_size, coords.xy), w.z, color); + color = mad(Sampler2DBilinear(colorTex, buffer_size, coords.zw), w.w, color); + + // Normalize the resulting color and we are finished! + out_buffer[idx] = color / sum; +} + +#endif \ No newline at end of file diff --git a/Baikal/CLW/clwoutput.h b/Baikal/Output/clwoutput.h similarity index 54% rename from Baikal/CLW/clwoutput.h rename to Baikal/Output/clwoutput.h index 7ea7a852..0ca49556 100644 --- a/Baikal/CLW/clwoutput.h +++ b/Baikal/Output/clwoutput.h @@ -1,6 +1,6 @@ #pragma once -#include "Core/output.h" +#include "output.h" #include "CLW.h" namespace Baikal @@ -8,19 +8,29 @@ namespace Baikal class ClwOutput : public Output { public: - ClwOutput(std::uint32_t w, std::uint32_t h, CLWContext context) + ClwOutput(CLWContext context, std::uint32_t w, std::uint32_t h) : Output(w, h) , m_context(context) , m_data(context.CreateBuffer(w*h, CL_MEM_READ_WRITE)) { } - void GetData(RadeonRays::float3* data) const + void GetData(RadeonRays::float3* data) const override { m_context.ReadBuffer(0, m_data, data, m_data.GetElementCount()).Wait(); } - void Clear(RadeonRays::float3 const& val) + void GetData(RadeonRays::float3* data, /* offset in elems */ size_t offset, /* read elems */size_t elems_count) const override + { + m_context.ReadBuffer( + 0, + m_data, + data, + offset, + elems_count).Wait(); + } + + void Clear(RadeonRays::float3 const& val) override { m_context.FillBuffer(0, m_data, val, m_data.GetElementCount()).Wait(); } @@ -28,7 +38,7 @@ namespace Baikal CLWBuffer data() const { return m_data; } private: - CLWBuffer m_data; CLWContext m_context; + CLWBuffer m_data; }; } diff --git a/Baikal/Core/output.h b/Baikal/Output/output.h similarity index 92% rename from Baikal/Core/output.h rename to Baikal/Output/output.h index c69a1534..1cd561a9 100644 --- a/Baikal/Core/output.h +++ b/Baikal/Output/output.h @@ -64,6 +64,9 @@ namespace Baikal Represents discrete 2D surface with [0..w]x[0..h] coordinate ranges. */ virtual void GetData(RadeonRays::float3* data) const = 0; + virtual void GetData(RadeonRays::float3* data, /* offset in elems */ size_t offset, /* read elems */size_t elems_count) const = 0; + + virtual void Clear(RadeonRays::float3 const& val) = 0; // Get surface width std::uint32_t width() const; diff --git a/Baikal/PostEffects/AreaMap33.h b/Baikal/PostEffects/AreaMap33.h new file mode 100644 index 00000000..ab2be959 --- /dev/null +++ b/Baikal/PostEffects/AreaMap33.h @@ -0,0 +1,9083 @@ +#ifndef AREA_MAP_H +#define AREA_MAP_H + +static const unsigned char area_map_33[] = { + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x66, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x66, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x6a, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x6d, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, + 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x6f, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, + 0x2e, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x71, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x71, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x72, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x01, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x72, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x01, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x73, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x73, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x74, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x74, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x0c, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x75, 0x00, 0xcd, 0x00, 0x64, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x47, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x31, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x01, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x75, 0x00, 0x00, 0xcd, 0x64, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x47, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, 0x31, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x01, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x76, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, + 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, + 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x76, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, + 0x4b, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, + 0x2c, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x77, 0x00, 0xcd, 0x00, 0x67, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x30, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, + 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x77, 0x00, 0x00, 0xcd, 0x67, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x30, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, + 0x1a, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x77, 0x00, 0xcd, 0x00, 0x69, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x34, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x01, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x77, 0x00, 0x00, 0xcd, 0x69, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x34, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x01, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, + 0x00, 0x52, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, + 0x00, 0x37, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, + 0x00, 0x22, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, + 0x52, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, + 0x37, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, + 0x22, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x42, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x42, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x61, 0x00, 0xcd, + 0x00, 0x56, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, 0x61, 0x00, 0x00, 0xcd, + 0x56, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, + 0x00, 0x58, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, + 0x58, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x1b, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0e, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6e, 0x00, 0xcd, 0x00, 0x63, 0x00, 0xcd, + 0x00, 0x5a, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, + 0x00, 0x42, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6e, 0x00, 0x00, 0xcd, 0x63, 0x00, 0x00, 0xcd, + 0x5a, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, + 0x42, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x2e, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6e, 0x00, 0xcd, 0x00, 0x64, 0x00, 0xcd, + 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6e, 0x00, 0x00, 0xcd, 0x64, 0x00, 0x00, 0xcd, + 0x5b, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x3d, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, + 0x00, 0x46, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x24, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6f, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x5d, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, + 0x46, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x24, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x0c, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x70, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x5e, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, + 0x00, 0x48, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x36, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x70, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x5e, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, + 0x48, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x36, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x1a, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x70, 0x00, 0xcd, 0x00, 0x67, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, 0x00, 0x50, 0x00, 0xcd, + 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, 0x00, 0x3d, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x70, 0x00, 0x00, 0xcd, 0x67, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, 0x50, 0x00, 0x00, 0xcd, + 0x4a, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, 0x3d, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, 0x00, 0x68, 0x00, 0xcd, + 0x00, 0x60, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x52, 0x00, 0xcd, + 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, 0x68, 0x00, 0x00, 0xcd, + 0x60, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x52, 0x00, 0x00, 0xcd, + 0x4b, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, 0x00, 0x69, 0x00, 0xcd, + 0x00, 0x61, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, 0x69, 0x00, 0x00, 0xcd, + 0x61, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x3c, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x72, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, + 0x00, 0x62, 0x00, 0xcd, 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, + 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x72, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, + 0x62, 0x00, 0x00, 0xcd, 0x5b, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x4e, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, + 0x3e, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x2f, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x72, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, + 0x00, 0x63, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x36, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x72, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, + 0x63, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, 0x36, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x1b, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, + 0x00, 0x64, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, + 0x00, 0x51, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, + 0x00, 0x41, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x27, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, + 0x64, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, + 0x51, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, + 0x41, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x27, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x1d, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, + 0x00, 0x65, 0x00, 0xcd, 0x00, 0x5e, 0x00, 0xcd, 0x00, 0x58, 0x00, 0xcd, + 0x00, 0x52, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, + 0x00, 0x42, 0x00, 0xcd, 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x31, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x19, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, + 0x65, 0x00, 0x00, 0xcd, 0x5e, 0x00, 0x00, 0xcd, 0x58, 0x00, 0x00, 0xcd, + 0x52, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, + 0x42, 0x00, 0x00, 0xcd, 0x3e, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x31, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x19, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, + 0x00, 0x66, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x53, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x37, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, + 0x66, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x53, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x37, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x74, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, + 0x00, 0x66, 0x00, 0xcd, 0x00, 0x60, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, + 0x00, 0x45, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x19, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x74, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, + 0x66, 0x00, 0x00, 0xcd, 0x60, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, + 0x45, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x19, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, + 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, + 0x00, 0x72, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x74, 0x00, 0xcd, + 0x00, 0x75, 0x00, 0xcd, 0x00, 0x76, 0x00, 0xcd, 0x00, 0x77, 0x00, 0xcd, + 0x00, 0x77, 0x00, 0xcd, 0x00, 0x78, 0x00, 0xcd, 0x00, 0x78, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x79, 0x00, 0xcd, 0x00, 0x79, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x79, 0x00, 0xcd, 0x00, 0x7a, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x7a, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, + 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, + 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, + 0x00, 0x72, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x74, 0x00, 0xcd, + 0x00, 0x75, 0x00, 0xcd, 0x00, 0x76, 0x00, 0xcd, 0x00, 0x77, 0x00, 0xcd, + 0x00, 0x77, 0x00, 0xcd, 0x00, 0x78, 0x00, 0xcd, 0x00, 0x78, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x79, 0x00, 0xcd, 0x00, 0x79, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x79, 0x00, 0xcd, 0x00, 0x7a, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x7a, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x1f, 0x1f, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, + 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, + 0x00, 0x72, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x74, 0x00, 0xcd, + 0x00, 0x75, 0x00, 0xcd, 0x00, 0x76, 0x00, 0xcd, 0x00, 0x77, 0x00, 0xcd, + 0x00, 0x77, 0x00, 0xcd, 0x00, 0x78, 0x00, 0xcd, 0x00, 0x78, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x79, 0x00, 0xcd, 0x00, 0x79, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x79, 0x00, 0xcd, 0x00, 0x7a, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x7a, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, + 0x1f, 0x1f, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, + 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, + 0x00, 0x72, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x74, 0x00, 0xcd, + 0x00, 0x75, 0x00, 0xcd, 0x00, 0x76, 0x00, 0xcd, 0x00, 0x77, 0x00, 0xcd, + 0x00, 0x77, 0x00, 0xcd, 0x00, 0x78, 0x00, 0xcd, 0x00, 0x78, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x79, 0x00, 0xcd, 0x00, 0x79, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x79, 0x00, 0xcd, 0x00, 0x7a, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x7a, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, + 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, + 0x00, 0x64, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x67, 0x00, 0xcd, + 0x00, 0x69, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, + 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x6e, 0x00, 0xcd, + 0x00, 0x6e, 0x00, 0xcd, 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x70, 0x00, 0xcd, + 0x00, 0x70, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, + 0x00, 0x72, 0x00, 0xcd, 0x00, 0x72, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, + 0x00, 0x73, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x74, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, + 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, + 0x00, 0x64, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x67, 0x00, 0xcd, + 0x00, 0x69, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, + 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x6e, 0x00, 0xcd, + 0x00, 0x6e, 0x00, 0xcd, 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x70, 0x00, 0xcd, + 0x00, 0x70, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, + 0x00, 0x72, 0x00, 0xcd, 0x00, 0x72, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, + 0x00, 0x73, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x74, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x0a, 0x0a, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, + 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, + 0x00, 0x64, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x67, 0x00, 0xcd, + 0x00, 0x69, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, + 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x6e, 0x00, 0xcd, + 0x00, 0x6e, 0x00, 0xcd, 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x70, 0x00, 0xcd, + 0x00, 0x70, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, + 0x00, 0x72, 0x00, 0xcd, 0x00, 0x72, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, + 0x00, 0x73, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x74, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x0a, 0x0a, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, + 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, + 0x00, 0x64, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x67, 0x00, 0xcd, + 0x00, 0x69, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, + 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x6e, 0x00, 0xcd, + 0x00, 0x6e, 0x00, 0xcd, 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x70, 0x00, 0xcd, + 0x00, 0x70, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, + 0x00, 0x72, 0x00, 0xcd, 0x00, 0x72, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, + 0x00, 0x73, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x74, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, + 0x00, 0x61, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, 0x00, 0x63, 0x00, 0xcd, + 0x00, 0x64, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x67, 0x00, 0xcd, 0x00, 0x68, 0x00, 0xcd, 0x00, 0x69, 0x00, 0xcd, + 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, + 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, + 0x00, 0x61, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, 0x00, 0x63, 0x00, 0xcd, + 0x00, 0x64, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x67, 0x00, 0xcd, 0x00, 0x68, 0x00, 0xcd, 0x00, 0x69, 0x00, 0xcd, + 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, + 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x06, 0x06, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, + 0x00, 0x61, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, 0x00, 0x63, 0x00, 0xcd, + 0x00, 0x64, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x67, 0x00, 0xcd, 0x00, 0x68, 0x00, 0xcd, 0x00, 0x69, 0x00, 0xcd, + 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, + 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x06, 0x06, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, + 0x00, 0x61, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, 0x00, 0x63, 0x00, 0xcd, + 0x00, 0x64, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x67, 0x00, 0xcd, 0x00, 0x68, 0x00, 0xcd, 0x00, 0x69, 0x00, 0xcd, + 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, + 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, + 0x00, 0x47, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x52, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x56, 0x00, 0xcd, 0x00, 0x58, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x5e, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x60, 0x00, 0xcd, 0x00, 0x61, 0x00, 0xcd, + 0x00, 0x62, 0x00, 0xcd, 0x00, 0x63, 0x00, 0xcd, 0x00, 0x64, 0x00, 0xcd, + 0x00, 0x65, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, + 0x00, 0x47, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x52, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x56, 0x00, 0xcd, 0x00, 0x58, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x5e, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x60, 0x00, 0xcd, 0x00, 0x61, 0x00, 0xcd, + 0x00, 0x62, 0x00, 0xcd, 0x00, 0x63, 0x00, 0xcd, 0x00, 0x64, 0x00, 0xcd, + 0x00, 0x65, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x04, 0x04, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, + 0x00, 0x47, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x52, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x56, 0x00, 0xcd, 0x00, 0x58, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x5e, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x60, 0x00, 0xcd, 0x00, 0x61, 0x00, 0xcd, + 0x00, 0x62, 0x00, 0xcd, 0x00, 0x63, 0x00, 0xcd, 0x00, 0x64, 0x00, 0xcd, + 0x00, 0x65, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x04, 0x04, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, + 0x00, 0x47, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x52, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x56, 0x00, 0xcd, 0x00, 0x58, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x5e, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x60, 0x00, 0xcd, 0x00, 0x61, 0x00, 0xcd, + 0x00, 0x62, 0x00, 0xcd, 0x00, 0x63, 0x00, 0xcd, 0x00, 0x64, 0x00, 0xcd, + 0x00, 0x65, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, + 0x00, 0x46, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x53, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, + 0x00, 0x57, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, + 0x00, 0x5e, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x60, 0x00, 0xcd, + 0x00, 0x66, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, + 0x00, 0x46, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x53, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, + 0x00, 0x57, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, + 0x00, 0x5e, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x60, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x66, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x03, 0x03, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, + 0x00, 0x46, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x53, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, + 0x00, 0x57, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, + 0x00, 0x5e, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x60, 0x00, 0xcd, + 0x66, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x03, 0x03, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, + 0x00, 0x46, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x53, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, + 0x00, 0x57, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, + 0x00, 0x5e, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x60, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, + 0x00, 0x22, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x42, 0x00, 0xcd, + 0x00, 0x45, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, + 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x52, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, + 0x00, 0x58, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, + 0x00, 0x22, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x42, 0x00, 0xcd, + 0x00, 0x45, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, + 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x52, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, + 0x00, 0x58, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x6a, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x02, 0x02, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, + 0x00, 0x22, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x42, 0x00, 0xcd, + 0x00, 0x45, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, + 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x52, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, + 0x00, 0x58, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x6a, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x02, 0x02, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, + 0x00, 0x22, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x42, 0x00, 0xcd, + 0x00, 0x45, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, + 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x52, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, + 0x00, 0x58, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x34, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x42, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, + 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, + 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x50, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x52, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x34, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x42, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, + 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, + 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x50, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x52, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x6d, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x02, 0x02, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x34, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x42, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, + 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, + 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x50, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x52, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x6d, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x02, 0x02, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x34, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x42, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, + 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, + 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x50, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x52, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, + 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x43, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, + 0x00, 0x48, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, + 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, + 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, + 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x43, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, + 0x00, 0x48, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x6f, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, + 0x2e, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x02, 0x02, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, + 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x43, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, + 0x00, 0x48, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, + 0x6f, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, + 0x2e, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x02, 0x02, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, + 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x43, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, + 0x00, 0x48, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x37, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x43, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, + 0x00, 0x47, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, + 0x00, 0x71, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x37, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x43, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, + 0x00, 0x47, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x71, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x37, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x43, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, + 0x00, 0x47, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, + 0x71, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x37, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x43, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, + 0x00, 0x47, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x01, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x36, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x42, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x72, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x36, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x42, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x72, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x36, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x42, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x72, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x36, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x42, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x39, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x73, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x39, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x73, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x39, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x73, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x39, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x12, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, + 0x00, 0x34, 0x00, 0xcd, 0x00, 0x36, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x39, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x74, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x12, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, + 0x00, 0x34, 0x00, 0xcd, 0x00, 0x36, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x39, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x74, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x0c, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x12, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, + 0x00, 0x34, 0x00, 0xcd, 0x00, 0x36, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x39, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x74, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x0c, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x12, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, + 0x00, 0x34, 0x00, 0xcd, 0x00, 0x36, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x39, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x01, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, + 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x31, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, + 0x00, 0x75, 0x00, 0xcd, 0x00, 0x64, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x47, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x31, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, + 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x31, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x75, 0x00, 0x00, 0xcd, 0x64, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x47, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, 0x31, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, + 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x31, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, + 0x75, 0x00, 0x00, 0xcd, 0x64, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x47, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, 0x31, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, + 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x31, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x13, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, + 0x00, 0x24, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x76, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, + 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, + 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x13, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, + 0x00, 0x24, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x76, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, + 0x4b, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, + 0x2c, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x13, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, + 0x00, 0x24, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x76, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, + 0x4b, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, + 0x2c, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x13, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, + 0x00, 0x24, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x20, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x27, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x77, 0x00, 0xcd, 0x00, 0x67, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x30, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, + 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x20, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x27, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x77, 0x00, 0x00, 0xcd, 0x67, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x30, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, + 0x1a, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x20, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x27, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x77, 0x00, 0x00, 0xcd, 0x67, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x30, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, + 0x1a, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x20, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x27, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x01, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, + 0x00, 0x77, 0x00, 0xcd, 0x00, 0x69, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x34, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x77, 0x00, 0x00, 0xcd, 0x69, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x34, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, + 0x77, 0x00, 0x00, 0xcd, 0x69, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x34, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x10, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, + 0x00, 0x52, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, + 0x00, 0x37, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, + 0x00, 0x22, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x10, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, + 0x52, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, + 0x37, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, + 0x22, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x10, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, + 0x52, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, + 0x37, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, + 0x22, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x10, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x22, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x42, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x22, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x42, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x22, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x42, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x22, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x61, 0x00, 0xcd, + 0x00, 0x56, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, 0x61, 0x00, 0x00, 0xcd, + 0x56, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, 0x61, 0x00, 0x00, 0xcd, + 0x56, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, + 0x00, 0x58, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, + 0x58, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x1b, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0e, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, + 0x58, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x1b, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0e, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x12, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x19, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6e, 0x00, 0xcd, 0x00, 0x63, 0x00, 0xcd, + 0x00, 0x5a, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, + 0x00, 0x42, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x12, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x19, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6e, 0x00, 0x00, 0xcd, 0x63, 0x00, 0x00, 0xcd, + 0x5a, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, + 0x42, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x2e, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x12, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x19, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6e, 0x00, 0x00, 0xcd, 0x63, 0x00, 0x00, 0xcd, + 0x5a, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, + 0x42, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x2e, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x12, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x19, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, 0x00, 0x19, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6e, 0x00, 0xcd, 0x00, 0x64, 0x00, 0xcd, + 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, 0x00, 0x19, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6e, 0x00, 0x00, 0xcd, 0x64, 0x00, 0x00, 0xcd, + 0x5b, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x3d, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, 0x00, 0x19, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6e, 0x00, 0x00, 0xcd, 0x64, 0x00, 0x00, 0xcd, + 0x5b, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x3d, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, 0x00, 0x19, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x13, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, + 0x00, 0x46, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x24, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x13, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6f, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x5d, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, + 0x46, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x24, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x0c, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x13, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6f, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x5d, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, + 0x46, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x24, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x0c, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x13, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x10, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x70, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x5e, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, + 0x00, 0x48, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x36, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x10, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x70, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x5e, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, + 0x48, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x36, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x1a, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x10, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x70, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x5e, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, + 0x48, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x36, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x1a, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x10, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x70, 0x00, 0xcd, 0x00, 0x67, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, 0x00, 0x50, 0x00, 0xcd, + 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, 0x00, 0x3d, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x70, 0x00, 0x00, 0xcd, 0x67, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, 0x50, 0x00, 0x00, 0xcd, + 0x4a, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, 0x3d, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x70, 0x00, 0x00, 0xcd, 0x67, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, 0x50, 0x00, 0x00, 0xcd, + 0x4a, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, 0x3d, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, 0x00, 0x68, 0x00, 0xcd, + 0x00, 0x60, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x52, 0x00, 0xcd, + 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, 0x68, 0x00, 0x00, 0xcd, + 0x60, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x52, 0x00, 0x00, 0xcd, + 0x4b, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, 0x68, 0x00, 0x00, 0xcd, + 0x60, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x52, 0x00, 0x00, 0xcd, + 0x4b, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, 0x00, 0x69, 0x00, 0xcd, + 0x00, 0x61, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, 0x69, 0x00, 0x00, 0xcd, + 0x61, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x3c, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, 0x69, 0x00, 0x00, 0xcd, + 0x61, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x3c, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x72, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, + 0x00, 0x62, 0x00, 0xcd, 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, + 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x72, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, + 0x62, 0x00, 0x00, 0xcd, 0x5b, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x4e, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, + 0x3e, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x2f, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x72, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, + 0x62, 0x00, 0x00, 0xcd, 0x5b, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x4e, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, + 0x3e, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x2f, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x72, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, + 0x00, 0x63, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x36, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x72, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, + 0x63, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, 0x36, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x1b, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x72, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, + 0x63, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, 0x36, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x1b, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, + 0x00, 0x64, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, + 0x00, 0x51, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, + 0x00, 0x41, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x27, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, + 0x64, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, + 0x51, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, + 0x41, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x27, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x1d, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, + 0x64, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, + 0x51, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, + 0x41, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x27, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x1d, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, + 0x00, 0x65, 0x00, 0xcd, 0x00, 0x5e, 0x00, 0xcd, 0x00, 0x58, 0x00, 0xcd, + 0x00, 0x52, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, + 0x00, 0x42, 0x00, 0xcd, 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x31, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x19, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, + 0x65, 0x00, 0x00, 0xcd, 0x5e, 0x00, 0x00, 0xcd, 0x58, 0x00, 0x00, 0xcd, + 0x52, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, + 0x42, 0x00, 0x00, 0xcd, 0x3e, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x31, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x19, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, + 0x65, 0x00, 0x00, 0xcd, 0x5e, 0x00, 0x00, 0xcd, 0x58, 0x00, 0x00, 0xcd, + 0x52, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, + 0x42, 0x00, 0x00, 0xcd, 0x3e, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x31, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x19, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, + 0x00, 0x66, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x53, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x37, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, + 0x66, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x53, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x37, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, + 0x66, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x53, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x37, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x74, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, + 0x00, 0x66, 0x00, 0xcd, 0x00, 0x60, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, + 0x00, 0x45, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x19, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x74, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, + 0x66, 0x00, 0x00, 0xcd, 0x60, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, + 0x45, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x19, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x74, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, + 0x66, 0x00, 0x00, 0xcd, 0x60, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, + 0x45, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x19, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, + 0x6d, 0x00, 0x00, 0xcd, 0x6f, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, + 0x72, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x74, 0x00, 0x00, 0xcd, + 0x75, 0x00, 0x00, 0xcd, 0x76, 0x00, 0x00, 0xcd, 0x77, 0x00, 0x00, 0xcd, + 0x77, 0x00, 0x00, 0xcd, 0x78, 0x00, 0x00, 0xcd, 0x78, 0x00, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x79, 0x00, 0x00, 0xcd, 0x79, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x79, 0x00, 0x00, 0xcd, 0x7a, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x7a, 0x00, 0x00, 0xcd, 0x7a, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, + 0x1f, 0x1f, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, + 0x6d, 0x00, 0x00, 0xcd, 0x6f, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, + 0x72, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x74, 0x00, 0x00, 0xcd, + 0x75, 0x00, 0x00, 0xcd, 0x76, 0x00, 0x00, 0xcd, 0x77, 0x00, 0x00, 0xcd, + 0x77, 0x00, 0x00, 0xcd, 0x78, 0x00, 0x00, 0xcd, 0x78, 0x00, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x79, 0x00, 0x00, 0xcd, 0x79, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x79, 0x00, 0x00, 0xcd, 0x7a, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x7a, 0x00, 0x00, 0xcd, 0x7a, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x3e, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, + 0x6d, 0x00, 0x00, 0xcd, 0x6f, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, + 0x72, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x74, 0x00, 0x00, 0xcd, + 0x75, 0x00, 0x00, 0xcd, 0x76, 0x00, 0x00, 0xcd, 0x77, 0x00, 0x00, 0xcd, + 0x77, 0x00, 0x00, 0xcd, 0x78, 0x00, 0x00, 0xcd, 0x78, 0x00, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x79, 0x00, 0x00, 0xcd, 0x79, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x79, 0x00, 0x00, 0xcd, 0x7a, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x7a, 0x00, 0x00, 0xcd, 0x7a, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, + 0x1f, 0x1f, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, + 0x6d, 0x00, 0x00, 0xcd, 0x6f, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, + 0x72, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x74, 0x00, 0x00, 0xcd, + 0x75, 0x00, 0x00, 0xcd, 0x76, 0x00, 0x00, 0xcd, 0x77, 0x00, 0x00, 0xcd, + 0x77, 0x00, 0x00, 0xcd, 0x78, 0x00, 0x00, 0xcd, 0x78, 0x00, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x79, 0x00, 0x00, 0xcd, 0x79, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x79, 0x00, 0x00, 0xcd, 0x7a, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x7a, 0x00, 0x00, 0xcd, 0x7a, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, + 0x4f, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x5c, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, + 0x64, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x67, 0x00, 0x00, 0xcd, + 0x69, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, + 0x6c, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, 0x6e, 0x00, 0x00, 0xcd, + 0x6e, 0x00, 0x00, 0xcd, 0x6f, 0x00, 0x00, 0xcd, 0x70, 0x00, 0x00, 0xcd, + 0x70, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, + 0x72, 0x00, 0x00, 0xcd, 0x72, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, + 0x73, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x74, 0x00, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x0a, 0x0a, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, + 0x4f, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x5c, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, + 0x64, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x67, 0x00, 0x00, 0xcd, + 0x69, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, + 0x6c, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, 0x6e, 0x00, 0x00, 0xcd, + 0x6e, 0x00, 0x00, 0xcd, 0x6f, 0x00, 0x00, 0xcd, 0x70, 0x00, 0x00, 0xcd, + 0x70, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, + 0x72, 0x00, 0x00, 0xcd, 0x72, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, + 0x73, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x74, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, + 0x4f, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x5c, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, + 0x64, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x67, 0x00, 0x00, 0xcd, + 0x69, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, + 0x6c, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, 0x6e, 0x00, 0x00, 0xcd, + 0x6e, 0x00, 0x00, 0xcd, 0x6f, 0x00, 0x00, 0xcd, 0x70, 0x00, 0x00, 0xcd, + 0x70, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, + 0x72, 0x00, 0x00, 0xcd, 0x72, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, + 0x73, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x74, 0x00, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x0a, 0x0a, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, + 0x4f, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x5c, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, + 0x64, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x67, 0x00, 0x00, 0xcd, + 0x69, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, + 0x6c, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, 0x6e, 0x00, 0x00, 0xcd, + 0x6e, 0x00, 0x00, 0xcd, 0x6f, 0x00, 0x00, 0xcd, 0x70, 0x00, 0x00, 0xcd, + 0x70, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, + 0x72, 0x00, 0x00, 0xcd, 0x72, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, + 0x73, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x74, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x4a, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x5c, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, + 0x61, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, 0x63, 0x00, 0x00, 0xcd, + 0x64, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x67, 0x00, 0x00, 0xcd, 0x68, 0x00, 0x00, 0xcd, 0x69, 0x00, 0x00, 0xcd, + 0x6a, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, + 0x6c, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x06, 0x06, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x4a, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x5c, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, + 0x61, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, 0x63, 0x00, 0x00, 0xcd, + 0x64, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x67, 0x00, 0x00, 0xcd, 0x68, 0x00, 0x00, 0xcd, 0x69, 0x00, 0x00, 0xcd, + 0x6a, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, + 0x6c, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x4a, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x5c, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, + 0x61, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, 0x63, 0x00, 0x00, 0xcd, + 0x64, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x67, 0x00, 0x00, 0xcd, 0x68, 0x00, 0x00, 0xcd, 0x69, 0x00, 0x00, 0xcd, + 0x6a, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, + 0x6c, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x06, 0x06, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x4a, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x5c, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, + 0x61, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, 0x63, 0x00, 0x00, 0xcd, + 0x64, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x67, 0x00, 0x00, 0xcd, 0x68, 0x00, 0x00, 0xcd, 0x69, 0x00, 0x00, 0xcd, + 0x6a, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, + 0x6c, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, + 0x47, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x52, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x56, 0x00, 0x00, 0xcd, 0x58, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x5b, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, 0x5e, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x60, 0x00, 0x00, 0xcd, 0x61, 0x00, 0x00, 0xcd, + 0x62, 0x00, 0x00, 0xcd, 0x63, 0x00, 0x00, 0xcd, 0x64, 0x00, 0x00, 0xcd, + 0x65, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x04, 0x04, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, + 0x47, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x52, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x56, 0x00, 0x00, 0xcd, 0x58, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x5b, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, 0x5e, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x60, 0x00, 0x00, 0xcd, 0x61, 0x00, 0x00, 0xcd, + 0x62, 0x00, 0x00, 0xcd, 0x63, 0x00, 0x00, 0xcd, 0x64, 0x00, 0x00, 0xcd, + 0x65, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, + 0x47, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x52, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x56, 0x00, 0x00, 0xcd, 0x58, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x5b, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, 0x5e, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x60, 0x00, 0x00, 0xcd, 0x61, 0x00, 0x00, 0xcd, + 0x62, 0x00, 0x00, 0xcd, 0x63, 0x00, 0x00, 0xcd, 0x64, 0x00, 0x00, 0xcd, + 0x65, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x04, 0x04, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, + 0x47, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x52, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x56, 0x00, 0x00, 0xcd, 0x58, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x5b, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, 0x5e, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x60, 0x00, 0x00, 0xcd, 0x61, 0x00, 0x00, 0xcd, + 0x62, 0x00, 0x00, 0xcd, 0x63, 0x00, 0x00, 0xcd, 0x64, 0x00, 0x00, 0xcd, + 0x65, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x3c, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, + 0x46, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x53, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, + 0x57, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x5b, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, + 0x5e, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x60, 0x00, 0x00, 0xcd, + 0x00, 0x66, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x03, 0x03, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x3c, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, + 0x46, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x53, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, + 0x57, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x5b, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, + 0x5e, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x60, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x66, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x3c, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, + 0x46, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x53, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, + 0x57, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x5b, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, + 0x5e, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x60, 0x00, 0x00, 0xcd, + 0x00, 0x66, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x03, 0x03, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x3c, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, + 0x46, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x53, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, + 0x57, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x5b, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, + 0x5e, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x60, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, + 0x22, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x3c, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x42, 0x00, 0x00, 0xcd, + 0x45, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, + 0x4b, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x52, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, + 0x58, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x02, 0x02, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, + 0x22, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x3c, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x42, 0x00, 0x00, 0xcd, + 0x45, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, + 0x4b, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x52, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, + 0x58, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x6a, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, + 0x22, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x3c, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x42, 0x00, 0x00, 0xcd, + 0x45, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, + 0x4b, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x52, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, + 0x58, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x02, 0x02, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, + 0x22, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x3c, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x42, 0x00, 0x00, 0xcd, + 0x45, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, + 0x4b, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x52, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, + 0x58, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x34, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x42, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, + 0x4a, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, + 0x4e, 0x00, 0x00, 0xcd, 0x50, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x52, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x02, 0x02, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x34, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x42, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, + 0x4a, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, + 0x4e, 0x00, 0x00, 0xcd, 0x50, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x52, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x6d, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x34, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x42, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, + 0x4a, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, + 0x4e, 0x00, 0x00, 0xcd, 0x50, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x52, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x02, 0x02, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x34, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x42, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, + 0x4a, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, + 0x4e, 0x00, 0x00, 0xcd, 0x50, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x52, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, + 0x2c, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x43, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, + 0x48, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, + 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, + 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x02, 0x02, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, + 0x2c, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x43, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, + 0x48, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x6f, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, + 0x2e, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, + 0x2c, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x43, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, + 0x48, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, + 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, + 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x02, 0x02, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, + 0x2c, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x43, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, + 0x48, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x2f, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x37, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x43, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, + 0x47, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, + 0x00, 0x71, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x2f, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x37, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x43, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, + 0x47, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x71, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x2f, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x37, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x43, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, + 0x47, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, + 0x00, 0x71, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x2f, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x37, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x43, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, + 0x47, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x01, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x36, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x3e, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x42, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x00, 0x72, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x36, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x3e, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x42, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x72, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x36, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x3e, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x42, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x00, 0x72, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x36, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x3e, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x42, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x39, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x3e, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x00, 0x73, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x39, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x3e, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x73, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x39, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x3e, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x00, 0x73, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x39, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x3e, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x12, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1d, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x2e, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, + 0x34, 0x00, 0x00, 0xcd, 0x36, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x39, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x00, 0x74, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x12, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1d, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x2e, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, + 0x34, 0x00, 0x00, 0xcd, 0x36, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x39, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x74, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x0c, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x12, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1d, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x2e, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, + 0x34, 0x00, 0x00, 0xcd, 0x36, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x39, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x00, 0x74, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x12, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1d, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x2e, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, + 0x34, 0x00, 0x00, 0xcd, 0x36, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x39, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x01, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, + 0x2f, 0x00, 0x00, 0xcd, 0x31, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, + 0x00, 0x75, 0x00, 0xcd, 0x00, 0x64, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x47, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x31, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, + 0x2f, 0x00, 0x00, 0xcd, 0x31, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x75, 0x00, 0x00, 0xcd, 0x64, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x47, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, 0x31, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, + 0x2f, 0x00, 0x00, 0xcd, 0x31, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, + 0x00, 0x75, 0x00, 0xcd, 0x00, 0x64, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x47, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x31, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, + 0x2f, 0x00, 0x00, 0xcd, 0x31, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x13, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1d, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, + 0x24, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x00, 0x76, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, + 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, + 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x13, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1d, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, + 0x24, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x76, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, + 0x4b, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, + 0x2c, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x13, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1d, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, + 0x24, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x00, 0x76, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, + 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, + 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x13, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1d, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, + 0x24, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x20, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x27, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x00, 0x77, 0x00, 0xcd, 0x00, 0x67, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x30, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, + 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x20, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x27, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x77, 0x00, 0x00, 0xcd, 0x67, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x30, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, + 0x1a, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x20, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x27, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x00, 0x77, 0x00, 0xcd, 0x00, 0x67, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x30, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, + 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x20, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x27, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x01, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, + 0x00, 0x77, 0x00, 0xcd, 0x00, 0x69, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x34, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x77, 0x00, 0x00, 0xcd, 0x69, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x34, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, + 0x00, 0x77, 0x00, 0xcd, 0x00, 0x69, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x34, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x10, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, + 0x00, 0x52, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, + 0x00, 0x37, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, + 0x00, 0x22, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x10, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, + 0x52, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, + 0x37, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, + 0x22, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x10, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, + 0x00, 0x52, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, + 0x00, 0x37, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, + 0x00, 0x22, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x10, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x22, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x42, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x22, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x42, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x22, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x42, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x22, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x61, 0x00, 0xcd, + 0x00, 0x56, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, 0x61, 0x00, 0x00, 0xcd, + 0x56, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x61, 0x00, 0xcd, + 0x00, 0x56, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x0e, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, + 0x00, 0x58, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x0e, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, + 0x58, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x1b, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0e, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x0e, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, + 0x00, 0x58, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x0e, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x12, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x19, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6e, 0x00, 0xcd, 0x00, 0x63, 0x00, 0xcd, + 0x00, 0x5a, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, + 0x00, 0x42, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x12, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x19, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6e, 0x00, 0x00, 0xcd, 0x63, 0x00, 0x00, 0xcd, + 0x5a, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, + 0x42, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x2e, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x12, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x19, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6e, 0x00, 0xcd, 0x00, 0x63, 0x00, 0xcd, + 0x00, 0x5a, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, + 0x00, 0x42, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x12, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x19, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, 0x19, 0x00, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6e, 0x00, 0xcd, 0x00, 0x64, 0x00, 0xcd, + 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, 0x19, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6e, 0x00, 0x00, 0xcd, 0x64, 0x00, 0x00, 0xcd, + 0x5b, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x3d, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, 0x19, 0x00, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6e, 0x00, 0xcd, 0x00, 0x64, 0x00, 0xcd, + 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, 0x19, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x0c, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x13, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, + 0x00, 0x46, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x24, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x0c, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x13, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6f, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x5d, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, + 0x46, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x24, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x0c, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x0c, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x13, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, + 0x00, 0x46, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x24, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x0c, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x13, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x10, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x70, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x5e, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, + 0x00, 0x48, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x36, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x10, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x70, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x5e, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, + 0x48, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x36, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x1a, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x10, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x70, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x5e, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, + 0x00, 0x48, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x36, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x10, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x70, 0x00, 0xcd, 0x00, 0x67, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, 0x00, 0x50, 0x00, 0xcd, + 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, 0x00, 0x3d, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x70, 0x00, 0x00, 0xcd, 0x67, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, 0x50, 0x00, 0x00, 0xcd, + 0x4a, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, 0x3d, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x70, 0x00, 0xcd, 0x00, 0x67, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, 0x00, 0x50, 0x00, 0xcd, + 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, 0x00, 0x3d, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, 0x00, 0x68, 0x00, 0xcd, + 0x00, 0x60, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x52, 0x00, 0xcd, + 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, 0x68, 0x00, 0x00, 0xcd, + 0x60, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x52, 0x00, 0x00, 0xcd, + 0x4b, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, 0x00, 0x68, 0x00, 0xcd, + 0x00, 0x60, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x52, 0x00, 0xcd, + 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, 0x00, 0x69, 0x00, 0xcd, + 0x00, 0x61, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, 0x69, 0x00, 0x00, 0xcd, + 0x61, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x3c, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, 0x00, 0x69, 0x00, 0xcd, + 0x00, 0x61, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x72, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, + 0x00, 0x62, 0x00, 0xcd, 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, + 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x72, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, + 0x62, 0x00, 0x00, 0xcd, 0x5b, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x4e, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, + 0x3e, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x2f, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x72, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, + 0x00, 0x62, 0x00, 0xcd, 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, + 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x72, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, + 0x00, 0x63, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x36, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x72, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, + 0x63, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, 0x36, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x1b, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x72, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, + 0x00, 0x63, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x36, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, + 0x00, 0x64, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, + 0x00, 0x51, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, + 0x00, 0x41, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x27, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, + 0x64, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, + 0x51, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, + 0x41, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x27, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x1d, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, + 0x00, 0x64, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, + 0x00, 0x51, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, + 0x00, 0x41, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x27, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, + 0x00, 0x65, 0x00, 0xcd, 0x00, 0x5e, 0x00, 0xcd, 0x00, 0x58, 0x00, 0xcd, + 0x00, 0x52, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, + 0x00, 0x42, 0x00, 0xcd, 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x31, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x19, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, + 0x65, 0x00, 0x00, 0xcd, 0x5e, 0x00, 0x00, 0xcd, 0x58, 0x00, 0x00, 0xcd, + 0x52, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, + 0x42, 0x00, 0x00, 0xcd, 0x3e, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x31, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x19, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, + 0x00, 0x65, 0x00, 0xcd, 0x00, 0x5e, 0x00, 0xcd, 0x00, 0x58, 0x00, 0xcd, + 0x00, 0x52, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, + 0x00, 0x42, 0x00, 0xcd, 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x31, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x19, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, + 0x00, 0x66, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x53, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x37, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, + 0x66, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x53, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x37, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, + 0x00, 0x66, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x53, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x37, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x74, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, + 0x00, 0x66, 0x00, 0xcd, 0x00, 0x60, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, + 0x00, 0x45, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x19, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x74, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, + 0x66, 0x00, 0x00, 0xcd, 0x60, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, + 0x45, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x19, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x74, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, + 0x00, 0x66, 0x00, 0xcd, 0x00, 0x60, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, + 0x00, 0x45, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x19, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x1f, 0x1f, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, + 0x6d, 0x00, 0x00, 0xcd, 0x6f, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, + 0x72, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x74, 0x00, 0x00, 0xcd, + 0x75, 0x00, 0x00, 0xcd, 0x76, 0x00, 0x00, 0xcd, 0x77, 0x00, 0x00, 0xcd, + 0x77, 0x00, 0x00, 0xcd, 0x78, 0x00, 0x00, 0xcd, 0x78, 0x00, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x79, 0x00, 0x00, 0xcd, 0x79, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x79, 0x00, 0x00, 0xcd, 0x7a, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x7a, 0x00, 0x00, 0xcd, 0x7a, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, 0x7b, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x1f, 0x1f, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, + 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, + 0x00, 0x72, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x74, 0x00, 0xcd, + 0x00, 0x75, 0x00, 0xcd, 0x00, 0x76, 0x00, 0xcd, 0x00, 0x77, 0x00, 0xcd, + 0x00, 0x77, 0x00, 0xcd, 0x00, 0x78, 0x00, 0xcd, 0x00, 0x78, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x79, 0x00, 0xcd, 0x00, 0x79, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x79, 0x00, 0xcd, 0x00, 0x7a, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x7a, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x7b, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x0a, 0x0a, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, + 0x4f, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x5c, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, + 0x64, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x67, 0x00, 0x00, 0xcd, + 0x69, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, + 0x6c, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, 0x6e, 0x00, 0x00, 0xcd, + 0x6e, 0x00, 0x00, 0xcd, 0x6f, 0x00, 0x00, 0xcd, 0x70, 0x00, 0x00, 0xcd, + 0x70, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, + 0x72, 0x00, 0x00, 0xcd, 0x72, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, + 0x73, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x74, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x0a, 0x0a, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, + 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, + 0x00, 0x64, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x67, 0x00, 0xcd, + 0x00, 0x69, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, + 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x6e, 0x00, 0xcd, + 0x00, 0x6e, 0x00, 0xcd, 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x70, 0x00, 0xcd, + 0x00, 0x70, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, + 0x00, 0x72, 0x00, 0xcd, 0x00, 0x72, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, + 0x00, 0x73, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x74, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x06, 0x06, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x4a, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x5c, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, + 0x61, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, 0x63, 0x00, 0x00, 0xcd, + 0x64, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x67, 0x00, 0x00, 0xcd, 0x68, 0x00, 0x00, 0xcd, 0x69, 0x00, 0x00, 0xcd, + 0x6a, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, + 0x6c, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x06, 0x06, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, + 0x00, 0x61, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, 0x00, 0x63, 0x00, 0xcd, + 0x00, 0x64, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x67, 0x00, 0xcd, 0x00, 0x68, 0x00, 0xcd, 0x00, 0x69, 0x00, 0xcd, + 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, + 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x04, 0x04, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, + 0x47, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x52, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x56, 0x00, 0x00, 0xcd, 0x58, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x5b, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, 0x5e, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x60, 0x00, 0x00, 0xcd, 0x61, 0x00, 0x00, 0xcd, + 0x62, 0x00, 0x00, 0xcd, 0x63, 0x00, 0x00, 0xcd, 0x64, 0x00, 0x00, 0xcd, + 0x65, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x04, 0x04, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, + 0x00, 0x47, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x52, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x56, 0x00, 0xcd, 0x00, 0x58, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x5e, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x60, 0x00, 0xcd, 0x00, 0x61, 0x00, 0xcd, + 0x00, 0x62, 0x00, 0xcd, 0x00, 0x63, 0x00, 0xcd, 0x00, 0x64, 0x00, 0xcd, + 0x00, 0x65, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x66, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x03, 0x03, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x3c, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, + 0x46, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x53, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, + 0x57, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x5b, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, + 0x5e, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x60, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x66, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x03, 0x03, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, + 0x00, 0x46, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x53, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, + 0x00, 0x57, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, + 0x00, 0x5e, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x60, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x02, 0x02, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, + 0x22, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x3c, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x42, 0x00, 0x00, 0xcd, + 0x45, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, + 0x4b, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x52, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, + 0x58, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x6a, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x02, 0x02, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, + 0x00, 0x22, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x42, 0x00, 0xcd, + 0x00, 0x45, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, + 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x52, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, + 0x00, 0x58, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x02, 0x02, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x34, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x42, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, + 0x4a, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, + 0x4e, 0x00, 0x00, 0xcd, 0x50, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x52, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x6d, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x02, 0x02, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x34, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x42, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, + 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, + 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x50, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x52, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, + 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x02, 0x02, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, + 0x2c, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x43, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, + 0x48, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x6f, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, + 0x2e, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x02, 0x02, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, + 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x43, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, + 0x00, 0x48, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x71, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x2f, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x37, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x43, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, + 0x47, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x71, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x37, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x43, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, + 0x00, 0x47, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x72, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x36, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x3e, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x42, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x72, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x36, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x42, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x73, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x39, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x3e, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x73, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x39, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x74, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x12, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1d, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x2e, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, + 0x34, 0x00, 0x00, 0xcd, 0x36, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x39, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x74, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x0c, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x12, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, + 0x00, 0x34, 0x00, 0xcd, 0x00, 0x36, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x39, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x75, 0x00, 0xcd, 0x00, 0x64, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x47, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x31, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, + 0x2f, 0x00, 0x00, 0xcd, 0x31, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x75, 0x00, 0x00, 0xcd, 0x64, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x47, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, 0x31, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, + 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x31, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x76, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, + 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, + 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x13, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1d, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, + 0x24, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x76, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, + 0x4b, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, + 0x2c, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x13, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, + 0x00, 0x24, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x77, 0x00, 0xcd, 0x00, 0x67, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x30, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, + 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x20, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x27, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x77, 0x00, 0x00, 0xcd, 0x67, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x30, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, + 0x1a, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x01, 0x01, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x20, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x27, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x77, 0x00, 0xcd, 0x00, 0x69, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x34, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x77, 0x00, 0x00, 0xcd, 0x69, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x34, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x01, 0x01, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, + 0x00, 0x52, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, + 0x00, 0x37, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x28, 0x00, 0xcd, + 0x00, 0x22, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x10, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, + 0x52, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, + 0x37, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, + 0x22, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x10, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x42, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2c, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x22, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x42, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x2c, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x22, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x78, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, 0x00, 0x61, 0x00, 0xcd, + 0x00, 0x56, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, + 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x28, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x21, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x78, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, 0x61, 0x00, 0x00, 0xcd, + 0x56, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, + 0x3d, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x28, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x21, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, 0x00, 0x62, 0x00, 0xcd, + 0x00, 0x58, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x38, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x0e, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, + 0x15, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, 0x62, 0x00, 0x00, 0xcd, + 0x58, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x1b, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0e, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, + 0x00, 0x15, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6e, 0x00, 0xcd, 0x00, 0x63, 0x00, 0xcd, + 0x00, 0x5a, 0x00, 0xcd, 0x00, 0x51, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, + 0x00, 0x42, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x03, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x12, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x19, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6e, 0x00, 0x00, 0xcd, 0x63, 0x00, 0x00, 0xcd, + 0x5a, 0x00, 0x00, 0xcd, 0x51, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, + 0x42, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x2e, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x1e, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x03, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x12, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x19, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6e, 0x00, 0xcd, 0x00, 0x64, 0x00, 0xcd, + 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x3d, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x03, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, 0x19, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6e, 0x00, 0x00, 0xcd, 0x64, 0x00, 0x00, 0xcd, + 0x5b, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x3d, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, 0x00, 0x19, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x79, 0x00, 0xcd, 0x00, 0x6f, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, + 0x00, 0x46, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x24, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, + 0x00, 0x17, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x0c, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x13, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x79, 0x00, 0x00, 0xcd, 0x6f, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x5d, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, + 0x46, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x24, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, + 0x17, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x0c, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x13, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x70, 0x00, 0xcd, 0x00, 0x66, 0x00, 0xcd, + 0x00, 0x5e, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, + 0x00, 0x48, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x36, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x26, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x10, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x70, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, 0xcd, + 0x5e, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, + 0x48, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x36, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x26, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x1a, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x10, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x70, 0x00, 0xcd, 0x00, 0x67, 0x00, 0xcd, + 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, 0x00, 0x50, 0x00, 0xcd, + 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, 0x00, 0x3d, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2e, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x18, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x70, 0x00, 0x00, 0xcd, 0x67, 0x00, 0x00, 0xcd, + 0x5f, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, 0x50, 0x00, 0x00, 0xcd, + 0x4a, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, 0x3d, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x2e, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x1c, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, 0x00, 0x68, 0x00, 0xcd, + 0x00, 0x60, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, 0x00, 0x52, 0x00, 0xcd, + 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x45, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, + 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x23, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x05, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, 0x68, 0x00, 0x00, 0xcd, + 0x60, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, 0x52, 0x00, 0x00, 0xcd, + 0x4b, 0x00, 0x00, 0xcd, 0x45, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, + 0x3a, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x23, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x1b, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x05, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x71, 0x00, 0xcd, 0x00, 0x69, 0x00, 0xcd, + 0x00, 0x61, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, 0x00, 0x53, 0x00, 0xcd, + 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, + 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, 0x00, 0x32, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, + 0x00, 0x05, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x71, 0x00, 0x00, 0xcd, 0x69, 0x00, 0x00, 0xcd, + 0x61, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, 0x53, 0x00, 0x00, 0xcd, + 0x4d, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, + 0x3c, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, 0x32, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x1d, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, + 0x05, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7a, 0x00, 0xcd, 0x00, 0x72, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, + 0x00, 0x62, 0x00, 0xcd, 0x00, 0x5b, 0x00, 0xcd, 0x00, 0x55, 0x00, 0xcd, + 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x48, 0x00, 0xcd, 0x00, 0x43, 0x00, 0xcd, + 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, + 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x07, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7a, 0x00, 0x00, 0xcd, 0x72, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, + 0x62, 0x00, 0x00, 0xcd, 0x5b, 0x00, 0x00, 0xcd, 0x55, 0x00, 0x00, 0xcd, + 0x4e, 0x00, 0x00, 0xcd, 0x48, 0x00, 0x00, 0xcd, 0x43, 0x00, 0x00, 0xcd, + 0x3e, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, + 0x2f, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x07, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x72, 0x00, 0xcd, 0x00, 0x6a, 0x00, 0xcd, + 0x00, 0x63, 0x00, 0xcd, 0x00, 0x5c, 0x00, 0xcd, 0x00, 0x56, 0x00, 0xcd, + 0x00, 0x50, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, 0x00, 0x44, 0x00, 0xcd, + 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x3a, 0x00, 0xcd, 0x00, 0x36, 0x00, 0xcd, + 0x00, 0x31, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, + 0x00, 0x25, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, + 0x00, 0x1b, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x09, 0x00, 0xcd, 0x00, 0x07, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x72, 0x00, 0x00, 0xcd, 0x6a, 0x00, 0x00, 0xcd, + 0x63, 0x00, 0x00, 0xcd, 0x5c, 0x00, 0x00, 0xcd, 0x56, 0x00, 0x00, 0xcd, + 0x50, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, 0x44, 0x00, 0x00, 0xcd, + 0x3f, 0x00, 0x00, 0xcd, 0x3a, 0x00, 0x00, 0xcd, 0x36, 0x00, 0x00, 0xcd, + 0x31, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, + 0x25, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, + 0x1b, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x09, 0x00, 0x00, 0xcd, 0x07, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x6b, 0x00, 0xcd, + 0x00, 0x64, 0x00, 0xcd, 0x00, 0x5d, 0x00, 0xcd, 0x00, 0x57, 0x00, 0xcd, + 0x00, 0x51, 0x00, 0xcd, 0x00, 0x4b, 0x00, 0xcd, 0x00, 0x46, 0x00, 0xcd, + 0x00, 0x41, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, 0x00, 0x37, 0x00, 0xcd, + 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, 0x00, 0x2b, 0x00, 0xcd, + 0x00, 0x27, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, 0x00, 0x20, 0x00, 0xcd, + 0x00, 0x1d, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, 0x00, 0x16, 0x00, 0xcd, + 0x00, 0x14, 0x00, 0xcd, 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0e, 0x00, 0xcd, + 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x09, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x6b, 0x00, 0x00, 0xcd, + 0x64, 0x00, 0x00, 0xcd, 0x5d, 0x00, 0x00, 0xcd, 0x57, 0x00, 0x00, 0xcd, + 0x51, 0x00, 0x00, 0xcd, 0x4b, 0x00, 0x00, 0xcd, 0x46, 0x00, 0x00, 0xcd, + 0x41, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, 0x37, 0x00, 0x00, 0xcd, + 0x33, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, 0x2b, 0x00, 0x00, 0xcd, + 0x27, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xcd, + 0x1d, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, 0x16, 0x00, 0x00, 0xcd, + 0x14, 0x00, 0x00, 0xcd, 0x11, 0x00, 0x00, 0xcd, 0x0e, 0x00, 0x00, 0xcd, + 0x0b, 0x00, 0x00, 0xcd, 0x09, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, + 0x00, 0x65, 0x00, 0xcd, 0x00, 0x5e, 0x00, 0xcd, 0x00, 0x58, 0x00, 0xcd, + 0x00, 0x52, 0x00, 0xcd, 0x00, 0x4d, 0x00, 0xcd, 0x00, 0x47, 0x00, 0xcd, + 0x00, 0x42, 0x00, 0xcd, 0x00, 0x3e, 0x00, 0xcd, 0x00, 0x39, 0x00, 0xcd, + 0x00, 0x35, 0x00, 0xcd, 0x00, 0x31, 0x00, 0xcd, 0x00, 0x2d, 0x00, 0xcd, + 0x00, 0x29, 0x00, 0xcd, 0x00, 0x25, 0x00, 0xcd, 0x00, 0x22, 0x00, 0xcd, + 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, 0x00, 0x19, 0x00, 0xcd, + 0x00, 0x16, 0x00, 0xcd, 0x00, 0x13, 0x00, 0xcd, 0x00, 0x10, 0x00, 0xcd, + 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0b, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, + 0x00, 0x06, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, + 0x65, 0x00, 0x00, 0xcd, 0x5e, 0x00, 0x00, 0xcd, 0x58, 0x00, 0x00, 0xcd, + 0x52, 0x00, 0x00, 0xcd, 0x4d, 0x00, 0x00, 0xcd, 0x47, 0x00, 0x00, 0xcd, + 0x42, 0x00, 0x00, 0xcd, 0x3e, 0x00, 0x00, 0xcd, 0x39, 0x00, 0x00, 0xcd, + 0x35, 0x00, 0x00, 0xcd, 0x31, 0x00, 0x00, 0xcd, 0x2d, 0x00, 0x00, 0xcd, + 0x29, 0x00, 0x00, 0xcd, 0x25, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xcd, + 0x1f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, 0x19, 0x00, 0x00, 0xcd, + 0x16, 0x00, 0x00, 0xcd, 0x13, 0x00, 0x00, 0xcd, 0x10, 0x00, 0x00, 0xcd, + 0x0d, 0x00, 0x00, 0xcd, 0x0b, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, + 0x06, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x73, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xcd, + 0x00, 0x66, 0x00, 0xcd, 0x00, 0x5f, 0x00, 0xcd, 0x00, 0x59, 0x00, 0xcd, + 0x00, 0x53, 0x00, 0xcd, 0x00, 0x4e, 0x00, 0xcd, 0x00, 0x49, 0x00, 0xcd, + 0x00, 0x44, 0x00, 0xcd, 0x00, 0x3f, 0x00, 0xcd, 0x00, 0x3b, 0x00, 0xcd, + 0x00, 0x37, 0x00, 0xcd, 0x00, 0x33, 0x00, 0xcd, 0x00, 0x2f, 0x00, 0xcd, + 0x00, 0x2b, 0x00, 0xcd, 0x00, 0x27, 0x00, 0xcd, 0x00, 0x24, 0x00, 0xcd, + 0x00, 0x21, 0x00, 0xcd, 0x00, 0x1e, 0x00, 0xcd, 0x00, 0x1a, 0x00, 0xcd, + 0x00, 0x18, 0x00, 0xcd, 0x00, 0x15, 0x00, 0xcd, 0x00, 0x12, 0x00, 0xcd, + 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0d, 0x00, 0xcd, 0x00, 0x0a, 0x00, 0xcd, + 0x00, 0x08, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, 0x00, 0x04, 0x00, 0xcd, + 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x73, 0x00, 0x00, 0xcd, 0x6c, 0x00, 0x00, 0xcd, + 0x66, 0x00, 0x00, 0xcd, 0x5f, 0x00, 0x00, 0xcd, 0x59, 0x00, 0x00, 0xcd, + 0x53, 0x00, 0x00, 0xcd, 0x4e, 0x00, 0x00, 0xcd, 0x49, 0x00, 0x00, 0xcd, + 0x44, 0x00, 0x00, 0xcd, 0x3f, 0x00, 0x00, 0xcd, 0x3b, 0x00, 0x00, 0xcd, + 0x37, 0x00, 0x00, 0xcd, 0x33, 0x00, 0x00, 0xcd, 0x2f, 0x00, 0x00, 0xcd, + 0x2b, 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0xcd, + 0x21, 0x00, 0x00, 0xcd, 0x1e, 0x00, 0x00, 0xcd, 0x1a, 0x00, 0x00, 0xcd, + 0x18, 0x00, 0x00, 0xcd, 0x15, 0x00, 0x00, 0xcd, 0x12, 0x00, 0x00, 0xcd, + 0x0f, 0x00, 0x00, 0xcd, 0x0d, 0x00, 0x00, 0xcd, 0x0a, 0x00, 0x00, 0xcd, + 0x08, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, 0x04, 0x00, 0x00, 0xcd, + 0x02, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x7b, 0x00, 0xcd, 0x00, 0x74, 0x00, 0xcd, 0x00, 0x6d, 0x00, 0xcd, + 0x00, 0x66, 0x00, 0xcd, 0x00, 0x60, 0x00, 0xcd, 0x00, 0x5a, 0x00, 0xcd, + 0x00, 0x55, 0x00, 0xcd, 0x00, 0x4f, 0x00, 0xcd, 0x00, 0x4a, 0x00, 0xcd, + 0x00, 0x45, 0x00, 0xcd, 0x00, 0x41, 0x00, 0xcd, 0x00, 0x3c, 0x00, 0xcd, + 0x00, 0x38, 0x00, 0xcd, 0x00, 0x34, 0x00, 0xcd, 0x00, 0x30, 0x00, 0xcd, + 0x00, 0x2d, 0x00, 0xcd, 0x00, 0x29, 0x00, 0xcd, 0x00, 0x26, 0x00, 0xcd, + 0x00, 0x23, 0x00, 0xcd, 0x00, 0x1f, 0x00, 0xcd, 0x00, 0x1c, 0x00, 0xcd, + 0x00, 0x19, 0x00, 0xcd, 0x00, 0x17, 0x00, 0xcd, 0x00, 0x14, 0x00, 0xcd, + 0x00, 0x11, 0x00, 0xcd, 0x00, 0x0f, 0x00, 0xcd, 0x00, 0x0c, 0x00, 0xcd, + 0x00, 0x0a, 0x00, 0xcd, 0x00, 0x08, 0x00, 0xcd, 0x00, 0x06, 0x00, 0xcd, + 0x00, 0x04, 0x00, 0xcd, 0x00, 0x01, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x7b, 0x00, 0x00, 0xcd, 0x74, 0x00, 0x00, 0xcd, 0x6d, 0x00, 0x00, 0xcd, + 0x66, 0x00, 0x00, 0xcd, 0x60, 0x00, 0x00, 0xcd, 0x5a, 0x00, 0x00, 0xcd, + 0x55, 0x00, 0x00, 0xcd, 0x4f, 0x00, 0x00, 0xcd, 0x4a, 0x00, 0x00, 0xcd, + 0x45, 0x00, 0x00, 0xcd, 0x41, 0x00, 0x00, 0xcd, 0x3c, 0x00, 0x00, 0xcd, + 0x38, 0x00, 0x00, 0xcd, 0x34, 0x00, 0x00, 0xcd, 0x30, 0x00, 0x00, 0xcd, + 0x2d, 0x00, 0x00, 0xcd, 0x29, 0x00, 0x00, 0xcd, 0x26, 0x00, 0x00, 0xcd, + 0x23, 0x00, 0x00, 0xcd, 0x1f, 0x00, 0x00, 0xcd, 0x1c, 0x00, 0x00, 0xcd, + 0x19, 0x00, 0x00, 0xcd, 0x17, 0x00, 0x00, 0xcd, 0x14, 0x00, 0x00, 0xcd, + 0x11, 0x00, 0x00, 0xcd, 0x0f, 0x00, 0x00, 0xcd, 0x0c, 0x00, 0x00, 0xcd, + 0x0a, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x06, 0x00, 0x00, 0xcd, + 0x04, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcd + +}; + +#endif diff --git a/Baikal/PostEffects/bilateral_denoiser.h b/Baikal/PostEffects/bilateral_denoiser.h index 2c63f3a0..595f6eee 100644 --- a/Baikal/PostEffects/bilateral_denoiser.h +++ b/Baikal/PostEffects/bilateral_denoiser.h @@ -20,10 +20,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ********************************************************************/ #pragma once -#include "post_effect_clw.h" +#include "clw_post_effect.h" -#include "CLW.h" -#include "../CLW/clwoutput.h" +#ifdef BAIKAL_EMBED_KERNELS +#include "embed_kernels.h" +#endif namespace Baikal { @@ -43,11 +44,11 @@ namespace Baikal * kWorldShadingNormal * kWorldPosition */ - class BilateralDenoiser : public PostEffectClw + class BilateralDenoiser : public ClwPostEffect { public: // Constructor - BilateralDenoiser(CLWContext context); + BilateralDenoiser(CLWContext context, const CLProgramManager *program_manager); // Apply filter void Apply(InputSet const& input_set, Output& output) override; @@ -58,28 +59,13 @@ namespace Baikal CLWProgram m_program; }; - inline BilateralDenoiser::BilateralDenoiser(CLWContext context) - : PostEffectClw(context) - { - std::string buildopts; - - buildopts.append(" -cl-mad-enable -cl-fast-relaxed-math -cl-std=CL1.2 -I . "); - - buildopts.append( -#if defined(__APPLE__) - "-D APPLE " -#elif defined(_WIN32) || defined (WIN32) - "-D WIN32 " -#elif defined(__linux__) - "-D __linux__ " + inline BilateralDenoiser::BilateralDenoiser(CLWContext context, const CLProgramManager *program_manager) +#ifdef BAIKAL_EMBED_KERNELS + : ClwPostEffect(context, program_manager, "denoise", g_denoise_opencl, g_denoise_opencl_headers) #else - "" + : ClwPostEffect(context, program_manager, "../Baikal/Kernels/CL/denoise.cl") #endif - ); - - // Compile kernels - m_program = CLWProgram::CreateFromFile("../Baikal/CL/denoise.cl", buildopts.c_str(), GetContext()); - + { // Add necessary params RegisterParameter("radius", RadeonRays::float4(5.f, 0.f, 0.f, 0.f)); RegisterParameter("color_sensitivity", RadeonRays::float4(5.f, 0.f, 0.f, 0.f)); @@ -114,9 +100,7 @@ namespace Baikal auto albedo = FindOutput(input_set, Renderer::OutputType::kAlbedo); auto out_color = static_cast(&output); - auto denoise_kernel = m_program.GetKernel("BilateralDenoise_main"); - - int num_pixels = color->width() * color->height(); + auto denoise_kernel = GetKernel("BilateralDenoise_main"); // Set kernel parameters int argc = 0; diff --git a/Baikal/PostEffects/clw_post_effect.h b/Baikal/PostEffects/clw_post_effect.h new file mode 100644 index 00000000..01d7be77 --- /dev/null +++ b/Baikal/PostEffects/clw_post_effect.h @@ -0,0 +1,63 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once + +#include "post_effect.h" + +#include "CLW.h" +#include "Output/clwoutput.h" +#include "Utils/clw_class.h" + +#include +#include + +namespace Baikal +{ + class CLProgramManager; + /** + \brief Post effects partial implementation based on CLW framework. + */ + class ClwPostEffect : public PostEffect, protected ClwClass + { + public: +#ifdef BAIKAL_EMBED_KERNELS + // Constructor, receives CLW context + ClwPostEffect(CLWContext context, const CLProgramManager *program_manager, std::string const& name, + std::string const& source, std::unordered_map const& headers); +#else + ClwPostEffect(CLWContext context, const CLProgramManager *program_manager, std::string const& file_name); +#endif + }; + +#ifdef BAIKAL_EMBED_KERNELS + inline ClwPostEffect::ClwPostEffect(CLWContext context, const CLProgramManager *program_manager, std::string const& name, + std::string const& source, std::unordered_map const& headers) + : ClwClass(context, program_manager, name, source, headers) + { + } +#else + inline ClwPostEffect::ClwPostEffect(CLWContext context, const CLProgramManager *program_manager, std::string const& file_name) + : ClwClass(context, program_manager, file_name) + { + } +#endif +} diff --git a/Baikal/PostEffects/post_effect.h b/Baikal/PostEffects/post_effect.h index 423b92fb..62becbd1 100644 --- a/Baikal/PostEffects/post_effect.h +++ b/Baikal/PostEffects/post_effect.h @@ -21,8 +21,8 @@ THE SOFTWARE. ********************************************************************/ #pragma once -#include "Core/renderer.h" -#include "Core/output.h" +#include "Renderers/renderer.h" +#include "Output/output.h" #include #include @@ -52,9 +52,6 @@ namespace Baikal PostEffect() = default; virtual ~PostEffect() = default; - // Check if the output is compatible with this effect - virtual bool IsCompatible(Output const& output) const = 0; - // Apply post effect and use output for the result virtual void Apply(InputSet const& input_set, Output& output) = 0; @@ -99,9 +96,7 @@ namespace Baikal inline void PostEffect::RegisterParameter(std::string const& name, RadeonRays::float4 const& initial_value) { - auto iter = m_parameters.find(name); - - assert(iter == m_parameters.cend()); + assert(m_parameters.find(name) == m_parameters.cend()); m_parameters.emplace(name, initial_value); } diff --git a/Baikal/PostEffects/wavelet_denoiser.h b/Baikal/PostEffects/wavelet_denoiser.h new file mode 100644 index 00000000..4c801271 --- /dev/null +++ b/Baikal/PostEffects/wavelet_denoiser.h @@ -0,0 +1,559 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once +#include "clw_post_effect.h" + +#include +#include +#include +#include "AreaMap33.h" + +#include + +#ifdef BAIKAL_EMBED_KERNELS +#include "embed_kernels.h" +#endif + +namespace Baikal +{ + /** + \brief SVGF wavelet denoiser. + + \details SVGF implements wavelet filter with edge-stopping function. Edge-stopping function is tuned + by spatio-temporal variance. Temporal component is presented by sample reconstruction from history frames. + Filter performs multiple passes, inserting pow(2, pass_index - 1) holes in + kernel on each pass. + Parameters: + * color_sensitivity - Higher the sensitivity the more it smoothes out depending on color difference. + * position_sensitivity - Higher the sensitivity the more it smoothes out depending on position difference. + Required AOVs in input set: + * kColor + * kAlbedo + * kMeshID + * kWorldShadingNormal + * kWorldPosition + */ + class WaveletDenoiser : public ClwPostEffect + { + public: + // Constructor + WaveletDenoiser(CLWContext context, const CLProgramManager *program_manager); + virtual ~WaveletDenoiser(); + // Apply filter + void Apply(InputSet const& input_set, Output& output) override; + void Update(PerspectiveCamera* camera); + + private: + // Find required output + ClwOutput* FindOutput(InputSet const& input_set, Renderer::OutputType type); + + CLWProgram m_program; + + // Ping-pong buffers for wavelet pass + const static uint32_t m_num_tmp_buffers = 2; + + uint32_t m_current_buffer_index; + + ClwOutput* m_motion_buffer; + + ClwOutput* m_colors[m_num_tmp_buffers]; + ClwOutput* m_positions[m_num_tmp_buffers]; + ClwOutput* m_normals[m_num_tmp_buffers]; + ClwOutput* m_mesh_ids[m_num_tmp_buffers]; + ClwOutput* m_tmp_buffers[m_num_tmp_buffers]; + ClwOutput* m_updated_variance; + ClwOutput* m_moments[m_num_tmp_buffers]; + + // MLAA buffers + ClwOutput* m_edge_detection; + ClwOutput* m_blending_weight_calculation; + + // Number of wavelet passes + uint32_t m_max_wavelet_passes; + + RadeonRays::matrix m_view_proj; + RadeonRays::matrix m_prev_view_proj; + + CLWBuffer m_view_proj_buffer; + CLWBuffer m_prev_view_proj_buffer; + CLWBuffer m_area_map_buffer; + + uint32_t m_buffers_width; + uint32_t m_buffers_height; + + bool m_buffers_initialized; + }; + + inline WaveletDenoiser::WaveletDenoiser(CLWContext context, const CLProgramManager *program_manager) +#ifdef BAIKAL_EMBED_KERNELS + : ClwPostEffect(context, program_manager, "wavelet_denoise", g_wavelet_denoise_opencl, g_wavelet_denoise_opencl_headers) +#else + : ClwPostEffect(context, program_manager, "../Baikal/Kernels/CL/wavelet_denoise.cl") +#endif + , m_current_buffer_index(0) + , m_max_wavelet_passes(5) + , m_buffers_width(0) + , m_buffers_height(0) + , m_buffers_initialized(false) + { + // Add necessary params + RegisterParameter("color_sensitivity", RadeonRays::float4(0.07f, 0.f, 0.f, 0.f)); + RegisterParameter("position_sensitivity", RadeonRays::float4(0.03f, 0.f, 0.f, 0.f)); + RegisterParameter("normal_sensitivity", RadeonRays::float4(0.01f, 0.f, 0.f, 0.f)); + + for (uint32_t buffer_index = 0; buffer_index < m_num_tmp_buffers; buffer_index++) + { + m_tmp_buffers[buffer_index] = nullptr; + m_colors[buffer_index] = nullptr; + } + + m_view_proj_buffer = context.CreateBuffer(16, CL_MEM_READ_WRITE); + m_prev_view_proj_buffer = context.CreateBuffer(16, CL_MEM_READ_WRITE); + + // Area map for MLAA weight coefficients + // Texture object takes ownership on texture data, so we need to copy area map into temporary buffer + char *buf = new char[sizeof(area_map_33)]; + memcpy(buf, area_map_33, sizeof(area_map_33)); + Texture::Ptr area_map = Texture::Create(buf, RadeonRays::int3(165, 165, 1), Texture::Format::kRgba8); + + if (area_map == nullptr) + throw std::runtime_error("AreaMap33.dds is missing"); + + std::vector area_map_values; + + const size_t area_map_buffer_size_in_bytes = area_map->GetSizeInBytes(); + const size_t pixels_num = area_map->GetSize().x * area_map->GetSize().y; + + area_map_values.reserve(pixels_num); + + const unsigned char* area_map_data = (const unsigned char*)area_map->GetData(); + + // Normalize area texture values + for (size_t i = 0; i < area_map_buffer_size_in_bytes; i += 4) + { + float r = static_cast(area_map_data[i]) / 255.0f; + float g = static_cast(area_map_data[i + 1]) / 255.0f; + float b = static_cast(area_map_data[i + 2]) / 255.0f; + float a = static_cast(area_map_data[i + 3]) / 255.0f; + + area_map_values.push_back(r); + area_map_values.push_back(g); + area_map_values.push_back(b); + area_map_values.push_back(a); + } + + m_area_map_buffer = context.CreateBuffer(area_map_values.size(), CL_MEM_READ_WRITE); + + context.WriteBuffer(0, m_area_map_buffer, &area_map_values[0], area_map_values.size()).Wait(); + } + + inline WaveletDenoiser::~WaveletDenoiser() + { + for (uint32_t i = 0; i < m_num_tmp_buffers; i++) + { + delete m_tmp_buffers[i]; + delete m_colors[i]; + delete m_positions[i]; + delete m_normals[i]; + delete m_mesh_ids[i]; + delete m_moments[i]; + } + + delete m_updated_variance; + delete m_motion_buffer; + + delete m_edge_detection; + delete m_blending_weight_calculation; + } + + inline ClwOutput* WaveletDenoiser::FindOutput(InputSet const& input_set, Renderer::OutputType type) + { + auto iter = input_set.find(type); + + if (iter == input_set.cend()) + { + return nullptr; + } + + return static_cast(iter->second); + } + + inline void WaveletDenoiser::Apply(InputSet const& input_set, Output& output) + { + uint32_t prev_buffer_index = m_current_buffer_index; + m_current_buffer_index = (m_current_buffer_index + 1) % m_num_tmp_buffers; + + auto sigma_color = GetParameter("color_sensitivity").x; + auto sigma_position = GetParameter("position_sensitivity").x; + + auto color = FindOutput(input_set, Renderer::OutputType::kColor); + auto normal = FindOutput(input_set, Renderer::OutputType::kWorldShadingNormal); + auto position = FindOutput(input_set, Renderer::OutputType::kWorldPosition); + auto albedo = FindOutput(input_set, Renderer::OutputType::kAlbedo); + auto mesh_id = FindOutput(input_set, Renderer::OutputType::kMeshID); + + auto out_color = static_cast(&output); + + auto color_width = color->width(); + auto color_height = color->height(); + + // Create ping pong buffers if they still need to be initialized + if (!m_buffers_initialized) + { + for (uint32_t buffer_index = 0; buffer_index < m_num_tmp_buffers; buffer_index++) + { + m_tmp_buffers[buffer_index] = new ClwOutput(GetContext(), color_width, color_height); + + m_colors[buffer_index] = new ClwOutput(GetContext(), color_width, color_height); + m_positions[buffer_index] = new ClwOutput(GetContext(), color_width, color_height); + m_normals[buffer_index] = new ClwOutput(GetContext(), color_width, color_height); + m_moments[buffer_index] = new ClwOutput(GetContext(), color_width, color_height); + m_mesh_ids[buffer_index] = new ClwOutput(GetContext(), color_width, color_height); + + m_tmp_buffers[buffer_index]->Clear(0.f); + m_colors[buffer_index]->Clear(0.f); + m_positions[buffer_index]->Clear(0.f); + m_normals[buffer_index]->Clear(0.f); + m_moments[buffer_index]->Clear(0.f); + m_mesh_ids[buffer_index]->Clear(0.f); + } + + m_motion_buffer = new ClwOutput(GetContext(), color_width, color_height); + m_updated_variance = new ClwOutput(GetContext(), color_width, color_height); + m_edge_detection = new ClwOutput(GetContext(), color_width, color_height); + m_blending_weight_calculation = new ClwOutput(GetContext(), color_width, color_height); + + m_motion_buffer->Clear(0.f); + m_updated_variance->Clear(0.f); + m_edge_detection->Clear(0.f); + m_blending_weight_calculation->Clear(0.f); + + m_buffers_width = color_width; + m_buffers_height = color_height; + m_buffers_initialized = true; + } + + // Resize AOV if main buffer size has changed + if (color_width != m_buffers_width || color_height != m_buffers_height) + { + for (uint32_t buffer_index = 0; buffer_index < m_num_tmp_buffers; buffer_index++) + { + delete m_tmp_buffers[buffer_index]; + m_tmp_buffers[buffer_index] = new ClwOutput(GetContext(), color_width, color_height); + m_tmp_buffers[buffer_index]->Clear(0.f); + + delete m_colors[buffer_index]; + m_colors[buffer_index] = new ClwOutput(GetContext(), color_width, color_height); + m_colors[buffer_index]->Clear(0.f); + + delete m_positions[buffer_index]; + m_positions[buffer_index] = new ClwOutput(GetContext(), color_width, color_height); + m_positions[buffer_index]->Clear(0.f); + + delete m_normals[buffer_index]; + m_normals[buffer_index] = new ClwOutput(GetContext(), color_width, color_height); + m_normals[buffer_index]->Clear(0.f); + + delete m_moments[buffer_index]; + m_moments[buffer_index] = new ClwOutput(GetContext(), color_width, color_height); + m_moments[buffer_index]->Clear(0.f); + + delete m_mesh_ids[buffer_index]; + m_mesh_ids[buffer_index] = new ClwOutput(GetContext(), color_width, color_height); + m_mesh_ids[buffer_index]->Clear(0.f); + } + + delete m_motion_buffer; + delete m_updated_variance; + delete m_edge_detection; + delete m_blending_weight_calculation; + + + m_motion_buffer = new ClwOutput(GetContext(), color_width, color_height); + m_updated_variance = new ClwOutput(GetContext(), color_width, color_height); + m_edge_detection = new ClwOutput(GetContext(), color_width, color_height); + m_blending_weight_calculation = new ClwOutput(GetContext(), color_width, color_height); + + m_motion_buffer->Clear(0.f); + m_updated_variance->Clear(0.f); + m_edge_detection->Clear(0.f); + m_blending_weight_calculation->Clear(0.f); + + m_buffers_width = color_width; + m_buffers_height = color_height; + } + + // Copy buffers + { + auto copy_buffers_kernel = GetKernel("CopyBuffers_main"); + + int argc = 0; + + // Set kernel parameters + copy_buffers_kernel.SetArg(argc++, color->data()); + copy_buffers_kernel.SetArg(argc++, position->data()); + copy_buffers_kernel.SetArg(argc++, normal->data()); + copy_buffers_kernel.SetArg(argc++, mesh_id->data()); + copy_buffers_kernel.SetArg(argc++, color->width()); + copy_buffers_kernel.SetArg(argc++, color->height()); + copy_buffers_kernel.SetArg(argc++, m_colors[m_current_buffer_index]->data()); + copy_buffers_kernel.SetArg(argc++, m_positions[m_current_buffer_index]->data()); + copy_buffers_kernel.SetArg(argc++, m_normals[m_current_buffer_index]->data()); + copy_buffers_kernel.SetArg(argc++, m_mesh_ids[m_current_buffer_index]->data()); + + // Run shading kernel + { + size_t gs[] = { static_cast((output.width() + 7) / 8 * 8), static_cast((output.height() + 7) / 8 * 8) }; + size_t ls[] = { 8, 8 }; + + GetContext().Launch2D(0, gs, ls, copy_buffers_kernel); + } + } + + // Generate screen space motion blur buffer + { + auto generate_motion_kernel = GetKernel("WaveletGenerateMotionBuffer_main"); + + int argc = 0; + + // Set kernel parameters + generate_motion_kernel.SetArg(argc++, m_positions[m_current_buffer_index]->data()); + generate_motion_kernel.SetArg(argc++, color->width()); + generate_motion_kernel.SetArg(argc++, color->height()); + generate_motion_kernel.SetArg(argc++, m_view_proj_buffer); + generate_motion_kernel.SetArg(argc++, m_prev_view_proj_buffer); + generate_motion_kernel.SetArg(argc++, m_motion_buffer->data()); + + // Run shading kernel + { + size_t gs[] = { static_cast((output.width() + 7) / 8 * 8), static_cast((output.height() + 7) / 8 * 8) }; + size_t ls[] = { 8, 8 }; + + GetContext().Launch2D(0, gs, ls, generate_motion_kernel); + } + } + + // Temporal accumulation of color and moments + { + auto accumulation_kernel = GetKernel("TemporalAccumulation_main"); + + int argc = 0; + + // Set kernel parameters + accumulation_kernel.SetArg(argc++, m_colors[prev_buffer_index]->data()); + accumulation_kernel.SetArg(argc++, m_positions[prev_buffer_index]->data()); + accumulation_kernel.SetArg(argc++, m_normals[prev_buffer_index]->data()); + accumulation_kernel.SetArg(argc++, m_colors[m_current_buffer_index]->data()); + accumulation_kernel.SetArg(argc++, m_positions[m_current_buffer_index]->data()); + accumulation_kernel.SetArg(argc++, m_normals[m_current_buffer_index]->data()); + accumulation_kernel.SetArg(argc++, m_motion_buffer->data()); + accumulation_kernel.SetArg(argc++, m_moments[prev_buffer_index]->data()); + accumulation_kernel.SetArg(argc++, m_moments[m_current_buffer_index]->data()); + accumulation_kernel.SetArg(argc++, m_mesh_ids[m_current_buffer_index]->data()); + accumulation_kernel.SetArg(argc++, m_mesh_ids[prev_buffer_index]->data()); + accumulation_kernel.SetArg(argc++, m_buffers_width); + accumulation_kernel.SetArg(argc++, m_buffers_height); + + // Run shading kernel + { + size_t gs[] = { static_cast((output.width() + 7) / 8 * 8), static_cast((output.height() + 7) / 8 * 8) }; + size_t ls[] = { 8, 8 }; + + GetContext().Launch2D(0, gs, ls, accumulation_kernel); + } + } + + { + auto copy_buffer_kernel = GetKernel("CopyBuffer_main"); + + int argc = 0; + + // Set kernel parameters + copy_buffer_kernel.SetArg(argc++, m_colors[m_current_buffer_index]->data()); + copy_buffer_kernel.SetArg(argc++, m_tmp_buffers[0]->data()); + copy_buffer_kernel.SetArg(argc++, m_buffers_width); + copy_buffer_kernel.SetArg(argc++, m_buffers_height); + + // Run shading kernel + { + size_t gs[] = { static_cast((output.width() + 7) / 8 * 8), static_cast((output.height() + 7) / 8 * 8) }; + size_t ls[] = { 8, 8 }; + + GetContext().Launch2D(0, gs, ls, copy_buffer_kernel); + } + } + + { + auto filter_kernel = GetKernel("WaveletFilter_main"); + auto update_variance_kernel = GetKernel("UpdateVariance_main"); + + Baikal::ClwOutput* current_input = nullptr; + Baikal::ClwOutput* current_output = nullptr; + Baikal::ClwOutput* current_variance = nullptr; + + for (uint32_t pass_index = 0; pass_index < m_max_wavelet_passes; pass_index++) + { + if (pass_index == 0) + { + // Result of first wavelet pass goes to color buffer for next frame + current_input = m_tmp_buffers[pass_index % m_num_tmp_buffers]; + current_output = m_max_wavelet_passes == 1 ? out_color : m_colors[m_current_buffer_index]; + current_variance = m_moments[m_current_buffer_index]; + } + else + { + // Last pass goes to output buffer + current_input = pass_index == 1 ? m_colors[m_current_buffer_index] : m_tmp_buffers[pass_index % m_num_tmp_buffers]; + current_output = m_tmp_buffers[(pass_index + 1) % m_num_tmp_buffers]; + current_variance = m_updated_variance; + } + + const int step_width = 1 << pass_index; + + int argc = 0; + + // Set kernel parameters + filter_kernel.SetArg(argc++, current_input->data()); + filter_kernel.SetArg(argc++, m_normals[m_current_buffer_index]->data()); + filter_kernel.SetArg(argc++, m_positions[m_current_buffer_index]->data()); + filter_kernel.SetArg(argc++, current_variance->data()); + filter_kernel.SetArg(argc++, albedo->data()); + + filter_kernel.SetArg(argc++, color->width()); + filter_kernel.SetArg(argc++, color->height()); + filter_kernel.SetArg(argc++, step_width); + filter_kernel.SetArg(argc++, sigma_color); + filter_kernel.SetArg(argc++, sigma_position); + filter_kernel.SetArg(argc++, current_output->data()); + + // Run wavelet filter kernel + { + size_t gs[] = { static_cast((output.width() + 7) / 8 * 8), static_cast((output.height() + 7) / 8 * 8) }; + size_t ls[] = { 8, 8 }; + + GetContext().Launch2D(0, gs, ls, filter_kernel); + } + + argc = 0; + + update_variance_kernel.SetArg(argc++, current_output->data()); + update_variance_kernel.SetArg(argc++, m_positions[m_current_buffer_index]->data()); + update_variance_kernel.SetArg(argc++, m_normals[m_current_buffer_index]->data()); + update_variance_kernel.SetArg(argc++, color->width()); + update_variance_kernel.SetArg(argc++, color->height()); + update_variance_kernel.SetArg(argc++, m_updated_variance->data()); + + // Run update variance kernel + { + size_t gs[] = { static_cast((output.width() + 7) / 8 * 8), static_cast((output.height() + 7) / 8 * 8) }; + size_t ls[] = { 8, 8 }; + + GetContext().Launch2D(0, gs, ls, update_variance_kernel); + } + } + + int argc = 0; + + auto edge_detection_kernel = GetKernel("EdgeDetectionMLAA"); + edge_detection_kernel.SetArg(argc++, m_mesh_ids[m_current_buffer_index]->data()); + edge_detection_kernel.SetArg(argc++, normal->data()); + edge_detection_kernel.SetArg(argc++, color->width()); + edge_detection_kernel.SetArg(argc++, color->height()); + edge_detection_kernel.SetArg(argc++, m_edge_detection->data()); + + // Run edge detection kernel + { + size_t gs[] = { static_cast((output.width() + 7) / 8 * 8), static_cast((output.height() + 7) / 8 * 8) }; + size_t ls[] = { 8, 8 }; + + GetContext().Launch2D(0, gs, ls, edge_detection_kernel); + } + + argc = 0; + + auto blending_weight_calclulation_kernel = GetKernel("BlendingWeightCalculationMLAA"); + blending_weight_calclulation_kernel.SetArg(argc++, m_edge_detection->data()); + blending_weight_calclulation_kernel.SetArg(argc++, m_area_map_buffer); + blending_weight_calclulation_kernel.SetArg(argc++, color->width()); + blending_weight_calclulation_kernel.SetArg(argc++, color->height()); + blending_weight_calclulation_kernel.SetArg(argc++, m_blending_weight_calculation->data()); + + // Run blending weight kernel + { + size_t gs[] = { static_cast((output.width() + 7) / 8 * 8), static_cast((output.height() + 7) / 8 * 8) }; + size_t ls[] = { 8, 8 }; + + GetContext().Launch2D(0, gs, ls, blending_weight_calclulation_kernel); + } + + argc = 0; + + auto neighborhood_blending_kernel = GetKernel("NeighborhoodBlendingMLAA"); + neighborhood_blending_kernel.SetArg(argc++, current_output->data()); + neighborhood_blending_kernel.SetArg(argc++, m_blending_weight_calculation->data()); + neighborhood_blending_kernel.SetArg(argc++, color->width()); + neighborhood_blending_kernel.SetArg(argc++, color->height()); + neighborhood_blending_kernel.SetArg(argc++, out_color->data()); + + // Run neighborhood blending kernel + { + size_t gs[] = { static_cast((output.width() + 7) / 8 * 8), static_cast((output.height() + 7) / 8 * 8) }; + size_t ls[] = { 8, 8 }; + + GetContext().Launch2D(0, gs, ls, neighborhood_blending_kernel); + } + } + } + + inline void WaveletDenoiser::Update(PerspectiveCamera* camera) + { + m_prev_view_proj = m_view_proj; + + const float focal_length = camera->GetFocalLength(); + const RadeonRays::float2 sensor_size = camera->GetSensorSize(); + + RadeonRays::float2 z_range = camera->GetDepthRange(); + + // Nan-avoidance in perspective matrix + z_range.x = std::max(z_range.x, std::numeric_limits::epsilon()); + + const float fovy = atan(sensor_size.y / (2.0f * focal_length)); + + const RadeonRays::float3 up = camera->GetUpVector(); + const RadeonRays::float3 right = -camera->GetRightVector(); + const RadeonRays::float3 forward = camera->GetForwardVector(); + const RadeonRays::float3 pos = camera->GetPosition(); + + const RadeonRays::matrix proj = RadeonRays::perspective_proj_fovy_rh_gl(fovy, camera->GetAspectRatio(), z_range.x, z_range.y); + const RadeonRays::float3 ip = RadeonRays::float3(-dot(right, pos), -dot(up, pos), -dot(forward, pos)); + + const RadeonRays::matrix view = RadeonRays::matrix(right.x, right.y, right.z, ip.x, + up.x, up.y, up.z, ip.y, + forward.x, forward.y, forward.z, ip.z, + 0.0f, 0.0f, 0.0f, 1.0f); + + m_view_proj = proj * view; + + GetContext().WriteBuffer(0, m_view_proj_buffer, &m_view_proj.m[0][0], 16).Wait(); + GetContext().WriteBuffer(0, m_prev_view_proj_buffer, &m_prev_view_proj.m[0][0], 16).Wait(); + } +} diff --git a/Baikal/RenderFactory/clw_render_factory.cpp b/Baikal/RenderFactory/clw_render_factory.cpp new file mode 100644 index 00000000..5c8b4d8c --- /dev/null +++ b/Baikal/RenderFactory/clw_render_factory.cpp @@ -0,0 +1,82 @@ +#include "clw_render_factory.h" + +#include "Output/clwoutput.h" +#include "Renderers/monte_carlo_renderer.h" +#include "Renderers/adaptive_renderer.h" +#include "Estimators/path_tracing_estimator.h" + +#ifdef ENABLE_DENOISER +#include "PostEffects/bilateral_denoiser.h" +#include "PostEffects/wavelet_denoiser.h" +#endif + +#include + +namespace Baikal +{ + ClwRenderFactory::ClwRenderFactory(CLWContext context, std::string const& cache_path) + : m_context(context) + , m_cache_path(cache_path) + , m_program_manager(cache_path) + , m_intersector( + CreateFromOpenClContext( + context, + context.GetDevice(0).GetID(), + context.GetCommandQueue(0) + ) + , RadeonRays::IntersectionApi::Delete + ) + + { + } + + // Create a renderer of specified type + std::unique_ptr ClwRenderFactory::CreateRenderer( + RendererType type) const + { + switch (type) + { + case RendererType::kUnidirectionalPathTracer: + return std::unique_ptr( + new MonteCarloRenderer( + m_context, + &m_program_manager, + std::make_unique(m_context, m_intersector, &m_program_manager) + )); + default: + throw std::runtime_error("Renderer not supported"); + } + } + + std::unique_ptr ClwRenderFactory::CreateOutput(std::uint32_t w, + std::uint32_t h) + const + { + return std::unique_ptr(new ClwOutput(m_context, w, h)); + } + + std::unique_ptr ClwRenderFactory::CreatePostEffect( + PostEffectType type) const + { +#ifdef ENABLE_DENOISER + switch (type) + { + case PostEffectType::kBilateralDenoiser: + return std::unique_ptr( + new BilateralDenoiser(m_context, &m_program_manager)); + case PostEffectType::kWaveletDenoiser: + return std::unique_ptr( + new WaveletDenoiser(m_context, &m_program_manager)); + default: + throw std::runtime_error("PostEffect is not supported"); + } +#else + throw std::runtime_error("PostEffect is not supported"); +#endif + } + + std::unique_ptr> ClwRenderFactory::CreateSceneController() const + { + return std::make_unique(m_context, m_intersector.get(), &m_program_manager); + } +} diff --git a/Baikal/RenderFactory/clw_render_factory.h b/Baikal/RenderFactory/clw_render_factory.h new file mode 100644 index 00000000..ef995b95 --- /dev/null +++ b/Baikal/RenderFactory/clw_render_factory.h @@ -0,0 +1,72 @@ + +/********************************************************************** + Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ +#pragma once + +#include "render_factory.h" +#include "radeon_rays_cl.h" +#include "CLW.h" + +#include "SceneGraph/clwscene.h" +#include "Utils/cl_program_manager.h" + +#include +#include + + +namespace Baikal +{ + /** + \brief RenderFactory class is in charge of render entities creation. + + \details RenderFactory makes sure renderer objects are compatible between + each other since many of them might use either CPU or GPU implementation. + Entities create via the same factory are known to be compatible. + */ + class ClwRenderFactory : public RenderFactory + { + public: + ClwRenderFactory(CLWContext context, std::string const& cache_path=""); + + // Create a renderer of specified type + std::unique_ptr + CreateRenderer(RendererType type) const override; + // Create an output of specified type + std::unique_ptr + CreateOutput(std::uint32_t w, std::uint32_t h) const override; + // Create post effect of specified type + std::unique_ptr + CreatePostEffect(PostEffectType type) const override; + + std::unique_ptr> + CreateSceneController() const override; + + private: + CLWContext m_context; + std::string m_cache_path; + CLProgramManager m_program_manager; + + using RadeonRaysInstanceDelete = decltype(RadeonRays::IntersectionApi::Delete); + + std::shared_ptr m_intersector; + }; +} diff --git a/Baikal/RenderFactory/render_factory.h b/Baikal/RenderFactory/render_factory.h new file mode 100644 index 00000000..29ebdbdc --- /dev/null +++ b/Baikal/RenderFactory/render_factory.h @@ -0,0 +1,77 @@ +/********************************************************************** + Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ +#pragma once + +#include + +#include "CLW.h" +#include "Controllers/scene_controller.h" + +namespace Baikal +{ + class Renderer; + class Output; + class PostEffect; + + /** + \brief RenderFactory class is in charge of render entities creation. + + \details RenderFactory makes sure renderer objects are compatible between + each other since many of them might use either CPU or GPU implementation. + Entities create via the same factory are known to be compatible. + */ + template + class RenderFactory + { + public: + enum class RendererType + { + kUnidirectionalPathTracer + }; + + enum class PostEffectType + { + kBilateralDenoiser, + kWaveletDenoiser + }; + + RenderFactory() = default; + virtual ~RenderFactory() = default; + + virtual + std::unique_ptr CreateRenderer(RendererType type) const = 0; + + virtual + std::unique_ptr CreateOutput(std::uint32_t w, std::uint32_t h) const = 0; + + virtual + std::unique_ptr CreatePostEffect(PostEffectType type) const = 0; + + virtual + std::unique_ptr> CreateSceneController() const = 0; + + RenderFactory(RenderFactory const&) = delete; + RenderFactory const& operator = (RenderFactory const&) = delete; + }; + + +} diff --git a/Baikal/Renderers/BDPT/bdptrenderer.cpp b/Baikal/Renderers/BDPT/bdptrenderer.cpp deleted file mode 100644 index c78c0d20..00000000 --- a/Baikal/Renderers/BDPT/bdptrenderer.cpp +++ /dev/null @@ -1,1169 +0,0 @@ -/********************************************************************** - Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. - - 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 "bdptrenderer.h" -#include "CLW/clwoutput.h" -#include "SceneGraph/scene1.h" -#include "SceneGraph/Collector/collector.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "Utils/sobol.h" - -#ifdef RR_EMBED_KERNELS -#include "./CL/cache/kernels.h" -#endif - -namespace Baikal -{ - using namespace RadeonRays; - - int constexpr kMaxLightSamples = 1; - int constexpr kTileSizeX = 1024; - int constexpr kTileSizeY = 1024; - - int constexpr kMaxRandomWalkLength = 3; - - // Path state description - struct BdptRenderer::PathState - { - float4 throughput; - int volume; - int flags; - int extra0; - int extra1; - }; - - // BDPT integrator keeps path vertices around, - // so it needs a structure to describe the vertex. - struct BdptRenderer::PathVertex - { - // Vertex position - float3 position; - // Shading normal - float3 shading_normal; - // True normal - float3 geometric_normal; - // UV coordinates - float2 uv; - // Pdf of sampling this vertex - // using forward transfer - float pdf_forward; - // Pdf of sampling this vertex - // using backward transfer - float pdf_backward; - // Value flow - //(importance or radiance) - float3 flow; - float3 unused; - int type; - int material_index; - int flags; - int padding; - }; - - struct BdptRenderer::RenderData - { - // OpenCL stuff - // Ray buffers for an intersector - CLWBuffer rays[2]; - // Hit predicates - CLWBuffer hits; - // Path data - CLWBuffer paths; - - // Shadow rays buffer - CLWBuffer shadowrays; - // Shadow hits (occluison) - CLWBuffer shadowhits; - - // Intersection data - CLWBuffer intersections; - // Compacted ray stream indices - CLWBuffer compacted_indices; - // Pixel indices - CLWBuffer pixelindices[2]; - // Constant range buffer - CLWBuffer iota; - - // Light samples collected - // after surface shading - CLWBuffer lightsamples; - // Image plane coordinates for splatting - CLWBuffer image_plane_positions; - // RNG data - CLWBuffer random; - CLWBuffer sobolmat; - // Hit counter - CLWBuffer hitcount; - - // Vertices stored during - // random walk from the eye - CLWBuffer eye_subpath; - // Vertices stored during - // random walk from the light - CLWBuffer light_subpath; - // Number of vertices in - // the corresponding subpaths - CLWBuffer eye_subpath_length; - CLWBuffer light_subpath_length; - - CLWProgram program; - CLWParallelPrimitives pp; - - // RadeonRays stuff - Buffer* fr_rays[2]; - Buffer* fr_shadowrays; - Buffer* fr_shadowhits; - Buffer* fr_hits; - Buffer* fr_intersections; - Buffer* fr_hitcount; - - Collector mat_collector; - Collector tex_collector; - - RenderData() - : fr_shadowrays(nullptr) - , fr_shadowhits(nullptr) - , fr_hits(nullptr) - , fr_intersections(nullptr) - , fr_hitcount(nullptr) - { - fr_rays[0] = nullptr; - fr_rays[1] = nullptr; - } - }; - - // Constructor - BdptRenderer::BdptRenderer(CLWContext context, int devidx, int num_bounces) - : m_context(context) - , m_render_data(new RenderData) - , m_vidmemws(0) - , m_scene_controller(context, devidx) - , m_num_bounces(num_bounces) - , m_framecnt(0) - { - std::string buildopts; - - buildopts.append(" -cl-mad-enable -cl-fast-relaxed-math -cl-std=CL1.2 -I . "); - - buildopts.append( -#if defined(__APPLE__) - "-D APPLE " -#elif defined(_WIN32) || defined (WIN32) - "-D WIN32 " -#elif defined(__linux__) - "-D __linux__ " -#else - "" -#endif - ); - - // Create parallel primitives - m_render_data->pp = CLWParallelPrimitives(m_context, buildopts.c_str()); - - // Load kernels -#ifndef RR_EMBED_KERNELS - m_render_data->program = CLWProgram::CreateFromFile("../Baikal/CL/integrator_bdpt.cl", buildopts.c_str(), m_context); -#else - m_render_data->program = CLWProgram::CreateFromSource(cl_app, std::strlen(cl_integrator_bdpt), buildopts.c_str(), context); -#endif - - m_render_data->sobolmat = m_context.CreateBuffer(1024 * 52, CL_MEM_READ_ONLY, &g_SobolMatrices[0]); - } - - BdptRenderer::~BdptRenderer() - { - } - - Output* BdptRenderer::CreateOutput(std::uint32_t w, std::uint32_t h) const - { - return new ClwOutput(w, h, m_context); - } - - void BdptRenderer::DeleteOutput(Output* output) const - { - delete output; - } - - void BdptRenderer::Clear(RadeonRays::float3 const& val, Output& output) const - { - static_cast(output).Clear(val); - m_framecnt = 0; - } - - void BdptRenderer::SetNumBounces(int num_bounces) - { - m_num_bounces = num_bounces; - } - - void BdptRenderer::GenerateCameraVertices(ClwScene const& scene, Output const& output, int2 const& tile_size) - { - // Fetch kernel - std::string kernel_name = (scene.camera_type == CameraType::kDefault) ? "PerspectiveCamera_GenerateVertices" : "PerspectiveCameraDof_GenerateVertices"; - - CLWKernel genkernel = m_render_data->program.GetKernel(kernel_name); - - // Set kernel parameters - int argc = 0; - genkernel.SetArg(argc++, scene.camera); - genkernel.SetArg(argc++, output.width()); - genkernel.SetArg(argc++, output.height()); - genkernel.SetArg(argc++, m_render_data->pixelindices[0]); - genkernel.SetArg(argc++, m_render_data->hitcount); - genkernel.SetArg(argc++, (int)rand_uint()); - genkernel.SetArg(argc++, m_framecnt); - genkernel.SetArg(argc++, m_render_data->random); - genkernel.SetArg(argc++, m_render_data->sobolmat); - genkernel.SetArg(argc++, m_render_data->rays[0]); - genkernel.SetArg(argc++, m_render_data->eye_subpath); - genkernel.SetArg(argc++, m_render_data->eye_subpath_length); - genkernel.SetArg(argc++, m_render_data->paths); - - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, genkernel); - } - } - - void BdptRenderer::GenerateLightVertices(ClwScene const& scene, Output const& output, int2 const& tile_size) - { - // Fetch kernel - CLWKernel genkernel = m_render_data->program.GetKernel("GenerateLightVertices"); - - // Set kernel parameters - int num_rays = tile_size.x * tile_size.y; - - int argc = 0; - genkernel.SetArg(argc++, num_rays); - genkernel.SetArg(argc++, scene.vertices); - genkernel.SetArg(argc++, scene.normals); - genkernel.SetArg(argc++, scene.uvs); - genkernel.SetArg(argc++, scene.indices); - genkernel.SetArg(argc++, scene.shapes); - genkernel.SetArg(argc++, scene.materialids); - genkernel.SetArg(argc++, scene.materials); - genkernel.SetArg(argc++, scene.textures); - genkernel.SetArg(argc++, scene.texturedata); - genkernel.SetArg(argc++, scene.envmapidx); - genkernel.SetArg(argc++, scene.lights); - genkernel.SetArg(argc++, scene.num_lights); - genkernel.SetArg(argc++, (int)rand_uint()); - genkernel.SetArg(argc++, m_framecnt); - genkernel.SetArg(argc++, m_render_data->random); - genkernel.SetArg(argc++, m_render_data->sobolmat); - genkernel.SetArg(argc++, m_render_data->rays[0]); - genkernel.SetArg(argc++, m_render_data->light_subpath); - genkernel.SetArg(argc++, m_render_data->light_subpath_length); - genkernel.SetArg(argc++, m_render_data->paths); - - // Run generation kernel - { - int globalsize = num_rays; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, genkernel); - } - } - - void BdptRenderer::Render(Scene1 const& scene) - { - auto output = FindFirstNonZeroOutput(); - auto output_size = int2(output->width(), output->height()); - - if (output_size.x > kTileSizeX || output_size.y > kTileSizeY) - { - auto num_tiles_x = (output_size.x + kTileSizeX - 1) / kTileSizeX; - auto num_tiles_y = (output_size.y + kTileSizeY - 1) / kTileSizeY; - - for (auto x = 0; x < num_tiles_x; ++x) - for (auto y = 0; y < num_tiles_y; ++y) - { - auto tile_offset = int2(x * kTileSizeX, y * kTileSizeY); - auto tile_size = int2(std::min(kTileSizeX, output_size.x - tile_offset.x), - std::min(kTileSizeY, output_size.y - tile_offset.y)); - - RenderTile(scene, tile_offset, tile_size); - } - } - else - { - RenderTile(scene, int2(), output_size); - } - } - - // Render the scene into the output - void BdptRenderer::RenderTile(Scene1 const& scene, int2 const& tile_origin, int2 const& tile_size) - { - auto& clwscene = m_scene_controller.CompileScene(scene, m_render_data->mat_collector, m_render_data->tex_collector); - - // Number of rays to generate - auto output = GetOutput(OutputType::kColor); - - if (output) - { - auto num_rays = tile_size.x * tile_size.y; - auto output_size = int2(output->width(), output->height()); - - // Generate tile domain - GenerateTileDomain(output_size, tile_origin, tile_size, tile_size); - // Generate camera vertices into eye_subpath array - GenerateCameraVertices(clwscene, *output, tile_size); - - //std::vector rays(num_rays); - //m_context.ReadBuffer(0, m_render_data->rays[0], &rays[0], num_rays).Wait(); - - // Perform random walk from camera - RandomWalk(clwscene, num_rays, m_render_data->eye_subpath, m_render_data->eye_subpath_length, 0, tile_size); - - //std::vector eye_vertices(num_rays); - //std::vector eye_length(num_rays); - //m_context.ReadBuffer(0, m_render_data->eye_subpath, &eye_vertices[0], num_rays).Wait(); - //m_context.ReadBuffer(0, m_render_data->eye_subpath_length, &eye_length[0], num_rays).Wait(); - - // Generate light vertices into light_subpath array - GenerateLightVertices(clwscene, *output, tile_size); - - // Need to update pixel indices - m_context.CopyBuffer(0, m_render_data->iota, m_render_data->pixelindices[0], 0, 0, num_rays); - m_context.CopyBuffer(0, m_render_data->iota, m_render_data->pixelindices[1], 0, 0, num_rays); - m_context.FillBuffer(0, m_render_data->hitcount, num_rays, 1); - - // Perform random walk from camera - RandomWalk(clwscene, num_rays, m_render_data->light_subpath, m_render_data->light_subpath_length, 0, tile_size); - - - // Generate tile domain - GenerateTileDomain(output_size, tile_origin, tile_size, tile_size); - std::vector light_vertices(num_rays); - std::vector light_length(num_rays); - m_context.ReadBuffer(0, m_render_data->light_subpath, &light_vertices[0], num_rays).Wait(); - m_context.ReadBuffer(0, m_render_data->light_subpath_length, &light_length[0], num_rays).Wait(); - - //for (int c = 1; c < kMaxRandomWalkLength; ++c) - { - //ConnectDirect(clwscene, c, tile_size); - } - - for (int c = 1; c < kMaxRandomWalkLength; ++c) - { - for (int l = 1; l < kMaxRandomWalkLength; ++l) - { - Connect(clwscene, c, l, tile_size); - } - } - - //for (int l = 1; l < 2; ++l) - //{ - // ConnectCaustic(clwscene, l, tile_size); - //} - - IncrementSampleCounter(clwscene, tile_size); - - m_context.Finish(0); - } - - // Check if we have other outputs, than color - bool aov_pass_needed = (FindFirstNonZeroOutput(false) != nullptr); - if (aov_pass_needed) - { - FillAOVs(clwscene, tile_origin, tile_size); - m_context.Flush(0); - } - - ++m_framecnt; - } - - void BdptRenderer::IncrementSampleCounter(ClwScene const& scene, int2 const& tile_size) - { - int num_rays = tile_size.x * tile_size.y; - auto output = static_cast(GetOutput(OutputType::kColor)); - - { - // Fetch kernel - CLWKernel increment_kernel = m_render_data->program.GetKernel("IncrementSampleCounter"); - - int argc = 0; - increment_kernel.SetArg(argc++, num_rays); - increment_kernel.SetArg(argc++, m_render_data->pixelindices[0]); - increment_kernel.SetArg(argc++, output->data()); - - // Run generation kernel - { - int globalsize = num_rays; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, increment_kernel); - } - } - } - - void BdptRenderer::Connect(ClwScene const& scene, int eye_vertex_index, int light_vertex_index, int2 const& tile_size) - { - m_context.FillBuffer(0, m_render_data->shadowhits, 1, m_render_data->shadowhits.GetElementCount()).Wait(); - - - int num_rays = tile_size.x * tile_size.y; - auto output = static_cast(GetOutput(OutputType::kColor)); - - { - // Fetch kernel - CLWKernel connect_kernel = m_render_data->program.GetKernel("Connect"); - - int argc = 0; - connect_kernel.SetArg(argc++, num_rays); - connect_kernel.SetArg(argc++, eye_vertex_index); - connect_kernel.SetArg(argc++, light_vertex_index); - connect_kernel.SetArg(argc++, m_render_data->pixelindices[0]); - connect_kernel.SetArg(argc++, m_render_data->eye_subpath); - connect_kernel.SetArg(argc++, m_render_data->eye_subpath_length); - connect_kernel.SetArg(argc++, m_render_data->light_subpath); - connect_kernel.SetArg(argc++, m_render_data->light_subpath_length); - connect_kernel.SetArg(argc++, scene.materials); - connect_kernel.SetArg(argc++, scene.textures); - connect_kernel.SetArg(argc++, scene.texturedata); - connect_kernel.SetArg(argc++, m_render_data->shadowrays); - connect_kernel.SetArg(argc++, m_render_data->lightsamples); - - // Run generation kernel - { - int globalsize = num_rays; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, connect_kernel); - } - } - - m_scene_controller.GetIntersectionApi() - ->QueryOcclusion(m_render_data->fr_shadowrays, num_rays, m_render_data->fr_shadowhits, nullptr, nullptr); - - { - CLWKernel gather_kernel = m_render_data->program.GetKernel("GatherContributions"); - - int argc = 0; - gather_kernel.SetArg(argc++, num_rays); - gather_kernel.SetArg(argc++, m_render_data->pixelindices[0]); - gather_kernel.SetArg(argc++, m_render_data->shadowhits); - gather_kernel.SetArg(argc++, m_render_data->lightsamples); - gather_kernel.SetArg(argc++, output->data()); - - // Run generation kernel - { - int globalsize = num_rays; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, gather_kernel); - } - } - } - - void BdptRenderer::ConnectDirect(ClwScene const& scene, int eye_vertex_index, int2 const& tile_size) - { - m_context.FillBuffer(0, m_render_data->shadowhits, 1, m_render_data->shadowhits.GetElementCount()); - - - int num_rays = tile_size.x * tile_size.y; - auto output = static_cast(GetOutput(OutputType::kColor)); - - { - // Fetch kernel - CLWKernel connect_kernel = m_render_data->program.GetKernel("ConnectDirect"); - - int argc = 0; - connect_kernel.SetArg(argc++, eye_vertex_index); - connect_kernel.SetArg(argc++, num_rays); - connect_kernel.SetArg(argc++, m_render_data->pixelindices[0]); - connect_kernel.SetArg(argc++, m_render_data->eye_subpath); - connect_kernel.SetArg(argc++, m_render_data->eye_subpath_length); - connect_kernel.SetArg(argc++, scene.vertices); - connect_kernel.SetArg(argc++, scene.normals); - connect_kernel.SetArg(argc++, scene.uvs); - connect_kernel.SetArg(argc++, scene.indices); - connect_kernel.SetArg(argc++, scene.shapes); - connect_kernel.SetArg(argc++, scene.materialids); - connect_kernel.SetArg(argc++, scene.materials); - connect_kernel.SetArg(argc++, scene.textures); - connect_kernel.SetArg(argc++, scene.texturedata); - connect_kernel.SetArg(argc++, scene.envmapidx); - connect_kernel.SetArg(argc++, scene.lights); - connect_kernel.SetArg(argc++, scene.num_lights); - connect_kernel.SetArg(argc++, rand_uint()); - connect_kernel.SetArg(argc++, m_render_data->random); - connect_kernel.SetArg(argc++, m_render_data->sobolmat); - connect_kernel.SetArg(argc++, m_framecnt); - connect_kernel.SetArg(argc++, m_render_data->shadowrays); - connect_kernel.SetArg(argc++, m_render_data->lightsamples); - - // Run generation kernel - { - int globalsize = num_rays; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, connect_kernel); - } - } - - m_scene_controller.GetIntersectionApi() - ->QueryOcclusion(m_render_data->fr_shadowrays, num_rays, m_render_data->fr_shadowhits, nullptr, nullptr); - - - { - CLWKernel gather_kernel = m_render_data->program.GetKernel("GatherContributions"); - - int argc = 0; - gather_kernel.SetArg(argc++, num_rays); - gather_kernel.SetArg(argc++, m_render_data->pixelindices[0]); - gather_kernel.SetArg(argc++, m_render_data->shadowhits); - gather_kernel.SetArg(argc++, m_render_data->lightsamples); - gather_kernel.SetArg(argc++, output->data()); - - // Run generation kernel - { - int globalsize = num_rays; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, gather_kernel); - } - } - } - - void BdptRenderer::ConnectCaustic(ClwScene const& scene, int light_vertex_index, int2 const& tile_size) - { - m_context.FillBuffer(0, m_render_data->shadowhits, 1, m_render_data->shadowhits.GetElementCount()); - - - int num_rays = tile_size.x * tile_size.y; - auto output = static_cast(GetOutput(OutputType::kColor)); - - { - // Fetch kernel - CLWKernel connect_kernel = m_render_data->program.GetKernel("ConnectCaustics"); - - int argc = 0; - connect_kernel.SetArg(argc++, num_rays); - connect_kernel.SetArg(argc++, light_vertex_index); - connect_kernel.SetArg(argc++, m_render_data->light_subpath); - connect_kernel.SetArg(argc++, m_render_data->light_subpath_length); - connect_kernel.SetArg(argc++, scene.camera); - connect_kernel.SetArg(argc++, scene.materials); - connect_kernel.SetArg(argc++, scene.textures); - connect_kernel.SetArg(argc++, scene.texturedata); - connect_kernel.SetArg(argc++, m_render_data->shadowrays); - connect_kernel.SetArg(argc++, m_render_data->lightsamples); - connect_kernel.SetArg(argc++, m_render_data->image_plane_positions); - - // Run generation kernel - { - int globalsize = num_rays; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, connect_kernel); - } - } - - m_scene_controller.GetIntersectionApi() - ->QueryOcclusion(m_render_data->fr_shadowrays, num_rays, m_render_data->fr_shadowhits, nullptr, nullptr); - - - { - CLWKernel gather_kernel = m_render_data->program.GetKernel("GatherCausticContributions"); - - int argc = 0; - gather_kernel.SetArg(argc++, num_rays); - gather_kernel.SetArg(argc++, output->width()); - gather_kernel.SetArg(argc++, output->height()); - gather_kernel.SetArg(argc++, m_render_data->shadowhits); - gather_kernel.SetArg(argc++, m_render_data->lightsamples); - gather_kernel.SetArg(argc++, m_render_data->image_plane_positions); - gather_kernel.SetArg(argc++, output->data()); - - // Run generation kernel - { - int globalsize = num_rays; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, gather_kernel); - } - } - } - - void BdptRenderer::GenerateTileDomain(int2 const& output_size, int2 const& tile_origin, - int2 const& tile_size, int2 const& subtile_size) - { - // Fetch kernel - CLWKernel generate_kernel = m_render_data->program.GetKernel("GenerateTileDomain"); - - // Set kernel parameters - int argc = 0; - generate_kernel.SetArg(argc++, output_size.x); - generate_kernel.SetArg(argc++, output_size.y); - generate_kernel.SetArg(argc++, tile_origin.x); - generate_kernel.SetArg(argc++, tile_origin.y); - generate_kernel.SetArg(argc++, tile_size.x); - generate_kernel.SetArg(argc++, tile_size.y); - generate_kernel.SetArg(argc++, subtile_size.x); - generate_kernel.SetArg(argc++, subtile_size.y); - generate_kernel.SetArg(argc++, m_render_data->pixelindices[0]); - generate_kernel.SetArg(argc++, m_render_data->pixelindices[1]); - generate_kernel.SetArg(argc++, m_render_data->hitcount); - - // Run shading kernel - { - size_t gs[] = { static_cast((tile_size.x + 7) / 8 * 8), static_cast((tile_size.y + 7) / 8 * 8) }; - size_t ls[] = { 8, 8 }; - - m_context.Launch2D(0, gs, ls, generate_kernel); - } - } - - void BdptRenderer::RandomWalk(ClwScene const& scene, int num_rays, CLWBuffer subpath, CLWBuffer subpath_length, int mode, int2 const& tile_size) - { - auto api = m_scene_controller.GetIntersectionApi(); - - // Initialize first pass - for (int pass = 0; pass < kMaxRandomWalkLength; ++pass) - { - // Clear ray hits buffer - m_context.FillBuffer(0, m_render_data->hits, 0, m_render_data->hits.GetElementCount()); - - // Intersect ray batch - api->QueryIntersection(m_render_data->fr_rays[pass & 0x1], m_render_data->fr_hitcount, num_rays, m_render_data->fr_intersections, nullptr, nullptr); - - // Convert intersections to predicates - FilterPathStream(pass, tile_size); - - // Compact batch - m_render_data->pp.Compact(0, m_render_data->hits, m_render_data->iota, m_render_data->compacted_indices, num_rays, m_render_data->hitcount); - - //int hitcount = 0; - //m_context.ReadBuffer(0, m_render_data->hitcount, &hitcount, 1).Wait(); - - //std::vector indices(num_rays); - //m_context.ReadBuffer(0, m_render_data->pixelindices[0], &indices[0], num_rays).Wait(); - - - // Advance indices to keep pixel indices up to date - RestorePixelIndices(pass, tile_size); - - //m_context.ReadBuffer(0, m_render_data->pixelindices[0], &indices[0], num_rays).Wait(); - - // Shade hits - SampleSurface(scene, pass, subpath, subpath_length, mode, tile_size); - - // - m_context.Flush(0); - } - } - - void BdptRenderer::SampleSurface(ClwScene const& scene, int pass, CLWBuffer subpath, CLWBuffer subpath_length, int mode, int2 const& tile_size) - { - // Fetch kernel - CLWKernel sample_kernel = m_render_data->program.GetKernel("SampleSurface"); - - // Set kernel parameters - int argc = 0; - sample_kernel.SetArg(argc++, m_render_data->rays[pass & 0x1]); - sample_kernel.SetArg(argc++, m_render_data->intersections); - sample_kernel.SetArg(argc++, m_render_data->compacted_indices); - sample_kernel.SetArg(argc++, m_render_data->pixelindices[pass & 0x1]); - sample_kernel.SetArg(argc++, m_render_data->hitcount); - sample_kernel.SetArg(argc++, scene.vertices); - sample_kernel.SetArg(argc++, scene.normals); - sample_kernel.SetArg(argc++, scene.uvs); - sample_kernel.SetArg(argc++, scene.indices); - sample_kernel.SetArg(argc++, scene.shapes); - sample_kernel.SetArg(argc++, scene.materialids); - sample_kernel.SetArg(argc++, scene.materials); - sample_kernel.SetArg(argc++, scene.textures); - sample_kernel.SetArg(argc++, scene.texturedata); - sample_kernel.SetArg(argc++, scene.envmapidx); - sample_kernel.SetArg(argc++, scene.lights); - sample_kernel.SetArg(argc++, scene.num_lights); - sample_kernel.SetArg(argc++, rand_uint()); - sample_kernel.SetArg(argc++, m_render_data->random); - sample_kernel.SetArg(argc++, m_render_data->sobolmat); - sample_kernel.SetArg(argc++, pass); - sample_kernel.SetArg(argc++, m_framecnt); - sample_kernel.SetArg(argc++, mode); - sample_kernel.SetArg(argc++, m_render_data->paths); - sample_kernel.SetArg(argc++, m_render_data->rays[(pass + 1) & 0x1]); - sample_kernel.SetArg(argc++, subpath); - sample_kernel.SetArg(argc++, subpath_length); - - // Run shading kernel - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, sample_kernel); - } - } - - Output* BdptRenderer::FindFirstNonZeroOutput(bool include_color) const - { - // Find first non-zero output - auto current_output = include_color ? GetOutput(Renderer::OutputType::kColor) : nullptr; - if (!current_output) - { - for (auto i = 1U; i < static_cast(Renderer::OutputType::kMax); ++i) - { - current_output = GetOutput(static_cast(i)); - - if (current_output) - { - break; - } - } - } - - return current_output; - } - - void BdptRenderer::SetOutput(OutputType type, Output* output) - { - if (output) - { - auto required_size = output->width() * output->height(); - - if (required_size > m_render_data->rays[0].GetElementCount()) - { - ResizeWorkingSet(*output); - } - } - - Renderer::SetOutput(type, output); - } - - void BdptRenderer::ResizeWorkingSet(Output const& output) - { - m_vidmemws = 0; - - // Create ray payloads - m_render_data->rays[0] = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(ray); - - m_render_data->rays[1] = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(ray); - - m_render_data->hits = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(int); - - m_render_data->intersections = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(Intersection); - - m_render_data->shadowrays = m_context.CreateBuffer(output.width() * output.height() * kMaxLightSamples, CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(ray)* kMaxLightSamples; - - m_render_data->shadowhits = m_context.CreateBuffer(output.width() * output.height() * kMaxLightSamples, CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(int)* kMaxLightSamples; - - m_render_data->lightsamples = m_context.CreateBuffer(output.width() * output.height() * kMaxLightSamples, CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(float3)* kMaxLightSamples; - - m_render_data->image_plane_positions = m_context.CreateBuffer(output.width() * output.height() * kMaxLightSamples, CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(float2)* kMaxLightSamples; - - m_render_data->paths = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(PathState); - - std::vector random_buffer(output.width() * output.height()); - std::generate(random_buffer.begin(), random_buffer.end(), std::rand); - - m_render_data->random = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE, &random_buffer[0]); - m_vidmemws += output.width() * output.height() * sizeof(std::uint32_t); - - std::vector initdata(output.width() * output.height()); - std::iota(initdata.begin(), initdata.end(), 0); - m_render_data->iota = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, &initdata[0]); - m_vidmemws += output.width() * output.height() * sizeof(int); - - m_render_data->compacted_indices = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(int); - - m_render_data->pixelindices[0] = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(int); - - m_render_data->pixelindices[1] = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(int); - - m_render_data->hitcount = m_context.CreateBuffer(1, CL_MEM_READ_WRITE); - - m_render_data->eye_subpath = m_context.CreateBuffer(output.width() * output.height() * kMaxRandomWalkLength, CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * kMaxRandomWalkLength * sizeof(PathVertex); - m_render_data->light_subpath = m_context.CreateBuffer(output.width() * output.height() * kMaxRandomWalkLength, CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * kMaxRandomWalkLength * sizeof(PathVertex); - - m_render_data->eye_subpath_length = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(int); - m_render_data->light_subpath_length = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(int); - - auto api = m_scene_controller.GetIntersectionApi(); - - // Recreate FR buffers - api->DeleteBuffer(m_render_data->fr_rays[0]); - api->DeleteBuffer(m_render_data->fr_rays[1]); - api->DeleteBuffer(m_render_data->fr_shadowrays); - api->DeleteBuffer(m_render_data->fr_hits); - api->DeleteBuffer(m_render_data->fr_shadowhits); - api->DeleteBuffer(m_render_data->fr_intersections); - api->DeleteBuffer(m_render_data->fr_hitcount); - - m_render_data->fr_rays[0] = CreateFromOpenClBuffer(api, m_render_data->rays[0]); - m_render_data->fr_rays[1] = CreateFromOpenClBuffer(api, m_render_data->rays[1]); - m_render_data->fr_shadowrays = CreateFromOpenClBuffer(api, m_render_data->shadowrays); - m_render_data->fr_hits = CreateFromOpenClBuffer(api, m_render_data->hits); - m_render_data->fr_shadowhits = CreateFromOpenClBuffer(api, m_render_data->shadowhits); - m_render_data->fr_intersections = CreateFromOpenClBuffer(api, m_render_data->intersections); - m_render_data->fr_hitcount = CreateFromOpenClBuffer(api, m_render_data->hitcount); - - std::cout << "Vidmem usage (working set): " << m_vidmemws / (1024 * 1024) << "Mb\n"; - } - - void BdptRenderer::FillAOVs(ClwScene const& scene, int2 const& tile_origin, int2 const& tile_size) - { - auto api = m_scene_controller.GetIntersectionApi(); - - // Find first non-zero AOV to get buffer dimensions - auto output = FindFirstNonZeroOutput(); - auto output_size = int2(output->width(), output->height()); - - // Generate tile domain - GenerateTileDomain(output_size, tile_origin, tile_size, tile_size); - - // Generate primary - GeneratePrimaryRays(scene, *output, tile_size); - - auto num_rays = tile_size.x * tile_size.y; - - // Intersect ray batch - api->QueryIntersection(m_render_data->fr_rays[0], m_render_data->fr_hitcount, num_rays, m_render_data->fr_intersections, nullptr, nullptr); - - CLWKernel fill_kernel = m_render_data->program.GetKernel("FillAOVs"); - - auto argc = 0U; - fill_kernel.SetArg(argc++, m_render_data->rays[0]); - fill_kernel.SetArg(argc++, m_render_data->intersections); - fill_kernel.SetArg(argc++, m_render_data->pixelindices[0]); - fill_kernel.SetArg(argc++, m_render_data->hitcount); - fill_kernel.SetArg(argc++, scene.vertices); - fill_kernel.SetArg(argc++, scene.normals); - fill_kernel.SetArg(argc++, scene.uvs); - fill_kernel.SetArg(argc++, scene.indices); - fill_kernel.SetArg(argc++, scene.shapes); - fill_kernel.SetArg(argc++, scene.materialids); - fill_kernel.SetArg(argc++, scene.materials); - fill_kernel.SetArg(argc++, scene.textures); - fill_kernel.SetArg(argc++, scene.texturedata); - fill_kernel.SetArg(argc++, scene.envmapidx); - fill_kernel.SetArg(argc++, scene.lights); - fill_kernel.SetArg(argc++, scene.num_lights); - fill_kernel.SetArg(argc++, rand_uint()); - fill_kernel.SetArg(argc++, m_render_data->random); - fill_kernel.SetArg(argc++, m_render_data->sobolmat); - fill_kernel.SetArg(argc++, m_framecnt); - for (auto i = 1U; i < static_cast(Renderer::OutputType::kMax); ++i) - { - if (auto aov = static_cast(GetOutput(static_cast(i)))) - { - fill_kernel.SetArg(argc++, 1); - fill_kernel.SetArg(argc++, aov->data()); - } - else - { - fill_kernel.SetArg(argc++, 0); - // This is simply a dummy buffer - fill_kernel.SetArg(argc++, m_render_data->hitcount); - } - } - - // Run AOV kernel - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, fill_kernel); - } - } - - - void BdptRenderer::GeneratePrimaryRays(ClwScene const& scene, Output const& output, int2 const& tile_size) - { - // Fetch kernel - std::string kernel_name = (scene.camera_type == CameraType::kDefault) ? "PerspectiveCamera_GeneratePaths" : "PerspectiveCameraDof_GeneratePaths"; - - CLWKernel genkernel = m_render_data->program.GetKernel(kernel_name); - - // Set kernel parameters - int argc = 0; - genkernel.SetArg(argc++, scene.camera); - genkernel.SetArg(argc++, output.width()); - genkernel.SetArg(argc++, output.height()); - genkernel.SetArg(argc++, m_render_data->pixelindices[0]); - genkernel.SetArg(argc++, m_render_data->hitcount); - genkernel.SetArg(argc++, (int)rand_uint()); - genkernel.SetArg(argc++, m_framecnt); - genkernel.SetArg(argc++, m_render_data->rays[0]); - genkernel.SetArg(argc++, m_render_data->random); - genkernel.SetArg(argc++, m_render_data->sobolmat); - - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, genkernel); - } - } - - void BdptRenderer::ShadeSurface(ClwScene const& scene, int pass, int2 const& tile_size) - { - // Fetch kernel - CLWKernel shadekernel = m_render_data->program.GetKernel("ShadeSurface"); - - auto output = static_cast(GetOutput(OutputType::kColor)); - - // Set kernel parameters - int argc = 0; - shadekernel.SetArg(argc++, m_render_data->rays[pass & 0x1]); - shadekernel.SetArg(argc++, m_render_data->intersections); - shadekernel.SetArg(argc++, m_render_data->compacted_indices); - shadekernel.SetArg(argc++, m_render_data->pixelindices[pass & 0x1]); - shadekernel.SetArg(argc++, m_render_data->hitcount); - shadekernel.SetArg(argc++, scene.vertices); - shadekernel.SetArg(argc++, scene.normals); - shadekernel.SetArg(argc++, scene.uvs); - shadekernel.SetArg(argc++, scene.indices); - shadekernel.SetArg(argc++, scene.shapes); - shadekernel.SetArg(argc++, scene.materialids); - shadekernel.SetArg(argc++, scene.materials); - shadekernel.SetArg(argc++, scene.textures); - shadekernel.SetArg(argc++, scene.texturedata); - shadekernel.SetArg(argc++, scene.envmapidx); - shadekernel.SetArg(argc++, scene.lights); - shadekernel.SetArg(argc++, scene.num_lights); - shadekernel.SetArg(argc++, rand_uint()); - shadekernel.SetArg(argc++, m_render_data->random); - shadekernel.SetArg(argc++, m_render_data->sobolmat); - shadekernel.SetArg(argc++, pass); - shadekernel.SetArg(argc++, m_framecnt); - shadekernel.SetArg(argc++, scene.volumes); - shadekernel.SetArg(argc++, m_render_data->shadowrays); - shadekernel.SetArg(argc++, m_render_data->lightsamples); - shadekernel.SetArg(argc++, m_render_data->rays[(pass + 1) & 0x1]); - shadekernel.SetArg(argc++, output->data()); - - // Run shading kernel - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, shadekernel); - } - } - - - void BdptRenderer::ShadeVolume(ClwScene const& scene, int pass, int2 const& tile_size) - { - // Fetch kernel - CLWKernel shadekernel = m_render_data->program.GetKernel("ShadeVolume"); - - auto output = static_cast(GetOutput(OutputType::kColor)); - - // Set kernel parameters - int argc = 0; - shadekernel.SetArg(argc++, m_render_data->rays[pass & 0x1]); - shadekernel.SetArg(argc++, m_render_data->intersections); - shadekernel.SetArg(argc++, m_render_data->compacted_indices); - shadekernel.SetArg(argc++, m_render_data->pixelindices[pass & 0x1]); - shadekernel.SetArg(argc++, m_render_data->hitcount); - shadekernel.SetArg(argc++, scene.vertices); - shadekernel.SetArg(argc++, scene.normals); - shadekernel.SetArg(argc++, scene.uvs); - shadekernel.SetArg(argc++, scene.indices); - shadekernel.SetArg(argc++, scene.shapes); - shadekernel.SetArg(argc++, scene.materialids); - shadekernel.SetArg(argc++, scene.materials); - shadekernel.SetArg(argc++, scene.textures); - shadekernel.SetArg(argc++, scene.texturedata); - shadekernel.SetArg(argc++, scene.envmapidx); - shadekernel.SetArg(argc++, scene.lights); - shadekernel.SetArg(argc++, scene.num_lights); - shadekernel.SetArg(argc++, rand_uint()); - shadekernel.SetArg(argc++, m_render_data->random); - shadekernel.SetArg(argc++, m_render_data->sobolmat); - shadekernel.SetArg(argc++, pass); - shadekernel.SetArg(argc++, m_framecnt); - shadekernel.SetArg(argc++, scene.volumes); - shadekernel.SetArg(argc++, m_render_data->shadowrays); - shadekernel.SetArg(argc++, m_render_data->lightsamples); - shadekernel.SetArg(argc++, m_render_data->rays[(pass + 1) & 0x1]); - shadekernel.SetArg(argc++, output->data()); - - // Run shading kernel - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, shadekernel); - } - } - - void BdptRenderer::EvaluateVolume(ClwScene const& scene, int pass, int2 const& tile_size) - { - // Fetch kernel - CLWKernel evalkernel = m_render_data->program.GetKernel("EvaluateVolume"); - - auto output = static_cast(GetOutput(OutputType::kColor)); - - // Set kernel parameters - int argc = 0; - evalkernel.SetArg(argc++, m_render_data->rays[pass & 0x1]); - evalkernel.SetArg(argc++, m_render_data->pixelindices[(pass + 1) & 0x1]); - evalkernel.SetArg(argc++, m_render_data->hitcount); - evalkernel.SetArg(argc++, scene.volumes); - evalkernel.SetArg(argc++, scene.textures); - evalkernel.SetArg(argc++, scene.texturedata); - evalkernel.SetArg(argc++, rand_uint()); - evalkernel.SetArg(argc++, m_render_data->random); - evalkernel.SetArg(argc++, m_render_data->sobolmat); - evalkernel.SetArg(argc++, pass); - evalkernel.SetArg(argc++, m_framecnt); - evalkernel.SetArg(argc++, m_render_data->intersections); - evalkernel.SetArg(argc++, output->data()); - - // Run shading kernel - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, evalkernel); - } - } - - - void BdptRenderer::ShadeBackground(ClwScene const& scene, int pass, int2 const& tile_size) - { - // Fetch kernel - CLWKernel misskernel = m_render_data->program.GetKernel("ShadeBackgroundEnvMap"); - - auto output = static_cast(GetOutput(OutputType::kColor)); - - // Set kernel parameters - int argc = 0; - misskernel.SetArg(argc++, m_render_data->rays[pass & 0x1]); - misskernel.SetArg(argc++, m_render_data->intersections); - misskernel.SetArg(argc++, m_render_data->pixelindices[(pass + 1) & 0x1]); - misskernel.SetArg(argc++, tile_size.x * tile_size.y); - misskernel.SetArg(argc++, scene.lights); - misskernel.SetArg(argc++, scene.envmapidx); - misskernel.SetArg(argc++, scene.textures); - misskernel.SetArg(argc++, scene.texturedata); - misskernel.SetArg(argc++, scene.volumes); - misskernel.SetArg(argc++, output->data()); - - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, misskernel); - } - } - - void BdptRenderer::GatherLightSamples(ClwScene const& scene, int pass, int2 const& tile_size) - { - // Fetch kernel - CLWKernel gatherkernel = m_render_data->program.GetKernel("GatherLightSamples"); - - auto output = static_cast(GetOutput(OutputType::kColor)); - - // Set kernel parameters - int argc = 0; - gatherkernel.SetArg(argc++, m_render_data->pixelindices[pass & 0x1]); - gatherkernel.SetArg(argc++, m_render_data->hitcount); - gatherkernel.SetArg(argc++, m_render_data->shadowhits); - gatherkernel.SetArg(argc++, m_render_data->lightsamples); - gatherkernel.SetArg(argc++, output->data()); - - // Run shading kernel - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, gatherkernel); - } - } - - - void BdptRenderer::RestorePixelIndices(int pass, int2 const& tile_size) - { - // Fetch kernel - CLWKernel restorekernel = m_render_data->program.GetKernel("RestorePixelIndices"); - - // Set kernel parameters - int argc = 0; - restorekernel.SetArg(argc++, m_render_data->compacted_indices); - restorekernel.SetArg(argc++, m_render_data->hitcount); - restorekernel.SetArg(argc++, m_render_data->pixelindices[(pass + 1) & 0x1]); - restorekernel.SetArg(argc++, m_render_data->pixelindices[pass & 0x1]); - - // Run shading kernel - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, restorekernel); - } - } - - void BdptRenderer::FilterPathStream(int pass, int2 const& tile_size) - { - // Fetch kernel - CLWKernel restorekernel = m_render_data->program.GetKernel("FilterPathStream"); - - // Set kernel parameters - int argc = 0; - restorekernel.SetArg(argc++, m_render_data->intersections); - restorekernel.SetArg(argc++, m_render_data->hitcount); - restorekernel.SetArg(argc++, m_render_data->pixelindices[(pass + 1) & 0x1]); - restorekernel.SetArg(argc++, m_render_data->paths); - restorekernel.SetArg(argc++, m_render_data->hits); - - // Run shading kernel - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, restorekernel); - } - } - - CLWKernel BdptRenderer::GetCopyKernel() - { - return m_render_data->program.GetKernel("ApplyGammaAndCopyData"); - } - - CLWKernel BdptRenderer::GetAccumulateKernel() - { - return m_render_data->program.GetKernel("AccumulateData"); - } - - // Shade background - void BdptRenderer::ShadeMiss(ClwScene const& scene, int pass, int2 const& tile_size) - { - // Fetch kernel - CLWKernel misskernel = m_render_data->program.GetKernel("ShadeMiss"); - - auto output = static_cast(GetOutput(OutputType::kColor)); - - // Set kernel parameters - int argc = 0; - misskernel.SetArg(argc++, m_render_data->rays[pass & 0x1]); - misskernel.SetArg(argc++, m_render_data->intersections); - misskernel.SetArg(argc++, m_render_data->pixelindices[(pass + 1) & 0x1]); - misskernel.SetArg(argc++, m_render_data->hitcount); - misskernel.SetArg(argc++, scene.lights); - misskernel.SetArg(argc++, scene.envmapidx); - misskernel.SetArg(argc++, scene.textures); - misskernel.SetArg(argc++, scene.texturedata); - misskernel.SetArg(argc++, scene.volumes); - misskernel.SetArg(argc++, output->data()); - - // Run shading kernel - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, misskernel); - } - } - - void BdptRenderer::RunBenchmark(Scene1 const& scene, std::uint32_t num_passes, BenchmarkStats& stats) - { - } -} diff --git a/Baikal/Renderers/BDPT/bdptrenderer.h b/Baikal/Renderers/BDPT/bdptrenderer.h deleted file mode 100644 index 5d797ca9..00000000 --- a/Baikal/Renderers/BDPT/bdptrenderer.h +++ /dev/null @@ -1,143 +0,0 @@ -/********************************************************************** -Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. - -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. -********************************************************************/ -#pragma once - -#include "math/int2.h" -#include "Core/renderer.h" -#include "CLW/clwscene.h" -#include "CLW/clw_scene_controller.h" - -#include "CLW.h" - - -namespace Baikal -{ - class ClwOutput; - struct ClwScene; - class SceneTracker; - - ///< Renderer implementation - class BdptRenderer : public Renderer - { - public: - // Constructor - BdptRenderer(CLWContext context, int devidx, int num_bounces); - // Destructor - ~BdptRenderer(); - - // Renderer overrides - // Create output - Output* CreateOutput(std::uint32_t w, std::uint32_t h) const override; - // Delete output - void DeleteOutput(Output* output) const override; - // Clear output - void Clear(RadeonRays::float3 const& val, Output& output) const override; - // Render the scene into the output - void Render(Scene1 const& scene) override; - // Render single tile - void RenderTile(Scene1 const& scene, RadeonRays::int2 const& tile_origin, RadeonRays::int2 const& tile_size) override; - // Set output - void SetOutput(OutputType type, Output* output) override; - // Set number of light bounces - void SetNumBounces(int num_bounces); - // Interop function - CLWKernel GetCopyKernel(); - // Add function - CLWKernel GetAccumulateKernel(); - // Run render benchmark - void RunBenchmark(Scene1 const& scene, std::uint32_t num_passes, BenchmarkStats& stats) override; - - protected: - // Resize output-dependent buffers - void ResizeWorkingSet(Output const& output); - // Generate rays - void GeneratePrimaryRays(ClwScene const& scene, Output const& output, int2 const& tile_size); - // Shade first hit - void ShadeSurface(ClwScene const& scene, int pass, int2 const& tile_size); - // Evaluate volume - void EvaluateVolume(ClwScene const& scene, int pass, int2 const& tile_size); - // Handle missing rays - void ShadeMiss(ClwScene const& scene, int pass, int2 const& tile_size); - // Gather light samples and account for visibility - void GatherLightSamples(ClwScene const& scene, int pass, int2 const& tile_size); - // Restore pixel indices after compaction - void RestorePixelIndices(int pass, int2 const& tile_size); - // Convert intersection info to compaction predicate - void FilterPathStream(int pass, int2 const& tile_size); - // Integrate volume - void ShadeVolume(ClwScene const& scene, int pass, int2 const& tile_size); - // Shade background - void ShadeBackground(ClwScene const& scene, int pass, int2 const& tile_size); - // Fill necessary AOVs - void FillAOVs(ClwScene const& scene, int2 const& tile_origin, int2 const& tile_size); - // Generate index domain - void GenerateTileDomain(int2 const& output_size, int2 const& tile_origin, int2 const& tile_size, int2 const& subtile_size); - // Find non-zero AOV - Output* FindFirstNonZeroOutput(bool include_color = true) const; - // Generate array of camera vertices for a given screen space tile - // into m_render_data->eye_subpath and initialize m_render_data->eye_subpath_length to 1. - void GenerateCameraVertices(ClwScene const& scene, Output const& output, int2 const& tile_size); - // Generate array of light vertices for a given screen space tile - // into m_render_data->light_subpath and initialize m_render_data->light_subpath_length to 1. - void GenerateLightVertices(ClwScene const& scene, Output const& output, int2 const& tile_size); - - struct PathVertex; - // Perform random walk collection vertices into subpath buffer and adjusting subpath length - // Mode stands for radiance or importance transfer modes - void RandomWalk(ClwScene const& scene, int num_rays, CLWBuffer subpath, CLWBuffer subpath_length, int mode, int2 const& tile_size); - // Sample surface and store vertex into subpath buffer adjusting subpath_length - void SampleSurface(ClwScene const& scene, int pass, CLWBuffer subpath, CLWBuffer subpath_length, int mode, int2 const& tile_size); - // Connect path segments - void Connect(ClwScene const& scene, int eye_vertex_index, int light_vertex_index, int2 const& tile_size); - // Connect eye vetices directly to light sources - void ConnectDirect(ClwScene const& scene, int eye_vertex_index, int2 const& tile_size); - // Connect light vetices directly to the eye - void ConnectCaustic(ClwScene const& scene, int light_vertex_index, int2 const& tile_size); - // Increment sample counter for a tile - void IncrementSampleCounter(ClwScene const& scene, int2 const& tile_size); - - - public: - // CL context - CLWContext m_context; - // Scene tracker - ClwSceneController m_scene_controller; - - // GPU data - struct RenderData; - struct PathState; - - std::unique_ptr m_render_data; - - // Intersector data - std::vector m_shapes; - - // Vidmem usage - // Working set - size_t m_vidmemws; - - private: - std::uint32_t m_num_bounces; - mutable std::uint32_t m_framecnt; - }; - -} diff --git a/Baikal/Renderers/PT/ptrenderer.cpp b/Baikal/Renderers/PT/ptrenderer.cpp deleted file mode 100644 index 17158d1a..00000000 --- a/Baikal/Renderers/PT/ptrenderer.cpp +++ /dev/null @@ -1,881 +0,0 @@ -/********************************************************************** - Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. - - 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 "Renderers/PT/ptrenderer.h" -#include "CLW/clwoutput.h" -#include "SceneGraph/scene1.h" -#include "SceneGraph/Collector/collector.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "Utils/sobol.h" - -#ifdef RR_EMBED_KERNELS -#include "./CL/cache/kernels.h" -#endif - -namespace Baikal -{ - using namespace RadeonRays; - - int constexpr kMaxLightSamples = 1; - int constexpr kTileSizeX = 1920; - int constexpr kTileSizeY = 1080; - - struct PtRenderer::PathState - { - float4 throughput; - int volume; - int flags; - int extra0; - int extra1; - }; - - struct PtRenderer::RenderData - { - // OpenCL stuff - CLWBuffer rays[2]; - CLWBuffer hits; - - CLWBuffer shadowrays; - CLWBuffer shadowhits; - - CLWBuffer intersections; - CLWBuffer compacted_indices; - CLWBuffer pixelindices[2]; - CLWBuffer iota; - - CLWBuffer lightsamples; - CLWBuffer paths; - CLWBuffer random; - CLWBuffer sobolmat; - CLWBuffer hitcount; - - CLWProgram program; - CLWParallelPrimitives pp; - - // RadeonRays stuff - Buffer* fr_rays[2]; - Buffer* fr_shadowrays; - Buffer* fr_shadowhits; - Buffer* fr_hits; - Buffer* fr_intersections; - Buffer* fr_hitcount; - - Collector mat_collector; - Collector tex_collector; - - RenderData() - : fr_shadowrays(nullptr) - , fr_shadowhits(nullptr) - , fr_hits(nullptr) - , fr_intersections(nullptr) - , fr_hitcount(nullptr) - { - fr_rays[0] = nullptr; - fr_rays[1] = nullptr; - } - }; - - // Constructor - PtRenderer::PtRenderer(CLWContext context, int devidx, int num_bounces) - : m_context(context) - , m_render_data(new RenderData) - , m_vidmemws(0) - , m_scene_controller(context, devidx) - , m_num_bounces(num_bounces) - , m_framecnt(0) - { - std::string buildopts; - - buildopts.append(" -cl-mad-enable -cl-fast-relaxed-math -cl-std=CL1.2 -I . "); - - buildopts.append( -#if defined(__APPLE__) - "-D APPLE " -#elif defined(_WIN32) || defined (WIN32) - "-D WIN32 " -#elif defined(__linux__) - "-D __linux__ " -#else - "" -#endif - ); - - // Create parallel primitives - m_render_data->pp = CLWParallelPrimitives(m_context, buildopts.c_str()); - - // Load kernels -#ifndef RR_EMBED_KERNELS - m_render_data->program = CLWProgram::CreateFromFile("../Baikal/CL/integrator_pt.cl", buildopts.c_str(), m_context); -#else - m_render_data->program = CLWProgram::CreateFromSource(cl_app, std::strlen(cl_integrator_pt), buildopts.c_str(), context); -#endif - - m_render_data->sobolmat = m_context.CreateBuffer(1024 * 52, CL_MEM_READ_ONLY, &g_SobolMatrices[0]); - } - - PtRenderer::~PtRenderer() - { - } - - Output* PtRenderer::CreateOutput(std::uint32_t w, std::uint32_t h) const - { - return new ClwOutput(w, h, m_context); - } - - void PtRenderer::DeleteOutput(Output* output) const - { - delete output; - } - - void PtRenderer::Clear(RadeonRays::float3 const& val, Output& output) const - { - static_cast(output).Clear(val); - m_framecnt = 0; - } - - void PtRenderer::SetNumBounces(int num_bounces) - { - m_num_bounces = num_bounces; - } - - void PtRenderer::Render(Scene1 const& scene) - { - auto output = FindFirstNonZeroOutput(); - auto output_size = int2(output->width(), output->height()); - - if (output_size.x > kTileSizeX || output_size.y > kTileSizeY) - { - auto num_tiles_x = (output_size.x + kTileSizeX - 1) / kTileSizeX; - auto num_tiles_y = (output_size.y + kTileSizeY - 1) / kTileSizeY; - - for (auto x = 0; x < num_tiles_x; ++x) - for (auto y = 0; y < num_tiles_y; ++y) - { - auto tile_offset = int2(x * kTileSizeX, y * kTileSizeY); - auto tile_size = int2(std::min(kTileSizeX, output_size.x - tile_offset.x), - std::min(kTileSizeY, output_size.y - tile_offset.y)); - - RenderTile(scene, tile_offset, tile_size); - } - } - else - { - RenderTile(scene, int2(), output_size); - } - } - - // Render the scene into the output - void PtRenderer::RenderTile(Scene1 const& scene, int2 const& tile_origin, int2 const& tile_size) - { - auto api = m_scene_controller.GetIntersectionApi(); - auto& clwscene = m_scene_controller.CompileScene(scene, m_render_data->mat_collector, m_render_data->tex_collector); - - // Number of rays to generate - auto output = GetOutput(OutputType::kColor); - - if (output) - { - auto num_rays = tile_size.x * tile_size.y; - auto output_size = int2(output->width(), output->height()); - - // Generate tile domain - GenerateTileDomain(output_size, tile_origin, tile_size, tile_size); - - // Generate primary - GeneratePrimaryRays(clwscene, *output, tile_size); - - // Initialize first pass - for (int pass = 0; pass < static_cast(m_num_bounces); ++pass) - { - // Clear ray hits buffer - m_context.FillBuffer(0, m_render_data->hits, 0, m_render_data->hits.GetElementCount()); - - // Intersect ray batch - api->QueryIntersection(m_render_data->fr_rays[pass & 0x1], m_render_data->fr_hitcount, num_rays, m_render_data->fr_intersections, nullptr, nullptr); - - // Apply scattering - EvaluateVolume(clwscene, pass, tile_size); - - if (pass > 0 && clwscene.envmapidx > -1) - { - ShadeMiss(clwscene, pass, tile_size); - } - - // Convert intersections to predicates - FilterPathStream(pass, tile_size); - - // Compact batch - m_render_data->pp.Compact(0, m_render_data->hits, m_render_data->iota, m_render_data->compacted_indices, num_rays, m_render_data->hitcount); - - // Advance indices to keep pixel indices up to date - RestorePixelIndices(pass, tile_size); - - // Shade hits - ShadeVolume(clwscene, pass, tile_size); - - // Shade hits - ShadeSurface(clwscene, pass, tile_size); - - // Shade missing rays - if (pass == 0) - ShadeBackground(clwscene, pass, tile_size); - - // Intersect shadow rays - api->QueryOcclusion(m_render_data->fr_shadowrays, m_render_data->fr_hitcount, num_rays, m_render_data->fr_shadowhits, nullptr, nullptr); - - // Gather light samples and account for visibility - GatherLightSamples(clwscene, pass, tile_size); - - // - m_context.Flush(0); - } - } - - // Check if we have other outputs, than color - bool aov_pass_needed = (FindFirstNonZeroOutput(false) != nullptr); - if (aov_pass_needed) - { - FillAOVs(clwscene, tile_origin, tile_size); - m_context.Flush(0); - } - - ++m_framecnt; - } - - void PtRenderer::GenerateTileDomain(int2 const& output_size, int2 const& tile_origin, - int2 const& tile_size, int2 const& subtile_size) - { - // Fetch kernel - CLWKernel generate_kernel = m_render_data->program.GetKernel("GenerateTileDomain"); - - // Set kernel parameters - int argc = 0; - generate_kernel.SetArg(argc++, output_size.x); - generate_kernel.SetArg(argc++, output_size.y); - generate_kernel.SetArg(argc++, tile_origin.x); - generate_kernel.SetArg(argc++, tile_origin.y); - generate_kernel.SetArg(argc++, tile_size.x); - generate_kernel.SetArg(argc++, tile_size.y); - generate_kernel.SetArg(argc++, subtile_size.x); - generate_kernel.SetArg(argc++, subtile_size.y); - generate_kernel.SetArg(argc++, m_render_data->pixelindices[0]); - generate_kernel.SetArg(argc++, m_render_data->pixelindices[1]); - generate_kernel.SetArg(argc++, m_render_data->hitcount); - - // Run shading kernel - { - size_t gs[] = { static_cast((tile_size.x + 7) / 8 * 8), static_cast((tile_size.y + 7) / 8 * 8) }; - size_t ls[] = { 8, 8 }; - - m_context.Launch2D(0, gs, ls, generate_kernel); - } - } - - Output* PtRenderer::FindFirstNonZeroOutput(bool include_color) const - { - // Find first non-zero output - auto current_output = include_color ? GetOutput(Renderer::OutputType::kColor) : nullptr; - if (!current_output) - { - for (auto i = 1U; i < static_cast(Renderer::OutputType::kMax); ++i) - { - current_output = GetOutput(static_cast(i)); - - if (current_output) - { - break; - } - } - } - - return current_output; - } - - void PtRenderer::SetOutput(OutputType type, Output* output) - { - if (output) - { - auto required_size = output->width() * output->height(); - - if (required_size > m_render_data->paths.GetElementCount()) - { - ResizeWorkingSet(*output); - } - } - - Renderer::SetOutput(type, output); - } - - void PtRenderer::ResizeWorkingSet(Output const& output) - { - m_vidmemws = 0; - - // Create ray payloads - m_render_data->rays[0] = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(ray); - - m_render_data->rays[1] = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(ray); - - m_render_data->hits = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(int); - - m_render_data->intersections = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(Intersection); - - m_render_data->shadowrays = m_context.CreateBuffer(output.width() * output.height() * kMaxLightSamples, CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(ray)* kMaxLightSamples; - - m_render_data->shadowhits = m_context.CreateBuffer(output.width() * output.height() * kMaxLightSamples, CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(int)* kMaxLightSamples; - - m_render_data->lightsamples = m_context.CreateBuffer(output.width() * output.height() * kMaxLightSamples, CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(float3)* kMaxLightSamples; - - m_render_data->paths = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(PathState); - - std::vector random_buffer(output.width() * output.height()); - std::generate(random_buffer.begin(), random_buffer.end(), std::rand); - - m_render_data->random = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE, &random_buffer[0]); - m_vidmemws += output.width() * output.height() * sizeof(std::uint32_t); - - std::vector initdata(output.width() * output.height()); - std::iota(initdata.begin(), initdata.end(), 0); - m_render_data->iota = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, &initdata[0]); - m_vidmemws += output.width() * output.height() * sizeof(int); - - m_render_data->compacted_indices = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(int); - - m_render_data->pixelindices[0] = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(int); - - m_render_data->pixelindices[1] = m_context.CreateBuffer(output.width() * output.height(), CL_MEM_READ_WRITE); - m_vidmemws += output.width() * output.height() * sizeof(int); - - m_render_data->hitcount = m_context.CreateBuffer(1, CL_MEM_READ_WRITE); - - auto api = m_scene_controller.GetIntersectionApi(); - - // Recreate FR buffers - api->DeleteBuffer(m_render_data->fr_rays[0]); - api->DeleteBuffer(m_render_data->fr_rays[1]); - api->DeleteBuffer(m_render_data->fr_shadowrays); - api->DeleteBuffer(m_render_data->fr_hits); - api->DeleteBuffer(m_render_data->fr_shadowhits); - api->DeleteBuffer(m_render_data->fr_intersections); - api->DeleteBuffer(m_render_data->fr_hitcount); - - m_render_data->fr_rays[0] = CreateFromOpenClBuffer(api, m_render_data->rays[0]); - m_render_data->fr_rays[1] = CreateFromOpenClBuffer(api, m_render_data->rays[1]); - m_render_data->fr_shadowrays = CreateFromOpenClBuffer(api, m_render_data->shadowrays); - m_render_data->fr_hits = CreateFromOpenClBuffer(api, m_render_data->hits); - m_render_data->fr_shadowhits = CreateFromOpenClBuffer(api, m_render_data->shadowhits); - m_render_data->fr_intersections = CreateFromOpenClBuffer(api, m_render_data->intersections); - m_render_data->fr_hitcount = CreateFromOpenClBuffer(api, m_render_data->hitcount); - - std::cout << "Vidmem usage (working set): " << m_vidmemws / (1024 * 1024) << "Mb\n"; - } - - void PtRenderer::FillAOVs(ClwScene const& scene, int2 const& tile_origin, int2 const& tile_size) - { - auto api = m_scene_controller.GetIntersectionApi(); - - // Find first non-zero AOV to get buffer dimensions - auto output = FindFirstNonZeroOutput(); - auto output_size = int2(output->width(), output->height()); - - // Generate tile domain - GenerateTileDomain(output_size, tile_origin, tile_size, tile_size); - - // Generate primary - GeneratePrimaryRays(scene, *output, tile_size); - - auto num_rays = tile_size.x * tile_size.y; - - // Intersect ray batch - api->QueryIntersection(m_render_data->fr_rays[0], m_render_data->fr_hitcount, num_rays, m_render_data->fr_intersections, nullptr, nullptr); - - CLWKernel fill_kernel = m_render_data->program.GetKernel("FillAOVs"); - - auto argc = 0U; - fill_kernel.SetArg(argc++, m_render_data->rays[0]); - fill_kernel.SetArg(argc++, m_render_data->intersections); - fill_kernel.SetArg(argc++, m_render_data->pixelindices[0]); - fill_kernel.SetArg(argc++, m_render_data->hitcount); - fill_kernel.SetArg(argc++, scene.vertices); - fill_kernel.SetArg(argc++, scene.normals); - fill_kernel.SetArg(argc++, scene.uvs); - fill_kernel.SetArg(argc++, scene.indices); - fill_kernel.SetArg(argc++, scene.shapes); - fill_kernel.SetArg(argc++, scene.materialids); - fill_kernel.SetArg(argc++, scene.materials); - fill_kernel.SetArg(argc++, scene.textures); - fill_kernel.SetArg(argc++, scene.texturedata); - fill_kernel.SetArg(argc++, scene.envmapidx); - fill_kernel.SetArg(argc++, scene.lights); - fill_kernel.SetArg(argc++, scene.num_lights); - fill_kernel.SetArg(argc++, rand_uint()); - fill_kernel.SetArg(argc++, m_render_data->random); - fill_kernel.SetArg(argc++, m_render_data->sobolmat); - fill_kernel.SetArg(argc++, m_framecnt); - for (auto i = 1U; i < static_cast(Renderer::OutputType::kMax); ++i) - { - if (auto aov = static_cast(GetOutput(static_cast(i)))) - { - fill_kernel.SetArg(argc++, 1); - fill_kernel.SetArg(argc++, aov->data()); - } - else - { - fill_kernel.SetArg(argc++, 0); - // This is simply a dummy buffer - fill_kernel.SetArg(argc++, m_render_data->hitcount); - } - } - - // Run AOV kernel - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, fill_kernel); - } - } - - - void PtRenderer::GeneratePrimaryRays(ClwScene const& scene, Output const& output, int2 const& tile_size) - { - // Fetch kernel - std::string kernel_name = (scene.camera_type == CameraType::kDefault) ? "PerspectiveCamera_GeneratePaths" : "PerspectiveCameraDof_GeneratePaths"; - - CLWKernel genkernel = m_render_data->program.GetKernel(kernel_name); - - // Set kernel parameters - int argc = 0; - genkernel.SetArg(argc++, scene.camera); - genkernel.SetArg(argc++, output.width()); - genkernel.SetArg(argc++, output.height()); - genkernel.SetArg(argc++, m_render_data->pixelindices[0]); - genkernel.SetArg(argc++, m_render_data->hitcount); - genkernel.SetArg(argc++, (int)rand_uint()); - genkernel.SetArg(argc++, m_framecnt); - genkernel.SetArg(argc++, m_render_data->rays[0]); - genkernel.SetArg(argc++, m_render_data->random); - genkernel.SetArg(argc++, m_render_data->sobolmat); - genkernel.SetArg(argc++, m_render_data->paths); - - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, genkernel); - } - } - - void PtRenderer::ShadeSurface(ClwScene const& scene, int pass, int2 const& tile_size) - { - // Fetch kernel - CLWKernel shadekernel = m_render_data->program.GetKernel("ShadeSurface"); - - auto output = static_cast(GetOutput(OutputType::kColor)); - - // Set kernel parameters - int argc = 0; - shadekernel.SetArg(argc++, m_render_data->rays[pass & 0x1]); - shadekernel.SetArg(argc++, m_render_data->intersections); - shadekernel.SetArg(argc++, m_render_data->compacted_indices); - shadekernel.SetArg(argc++, m_render_data->pixelindices[pass & 0x1]); - shadekernel.SetArg(argc++, m_render_data->hitcount); - shadekernel.SetArg(argc++, scene.vertices); - shadekernel.SetArg(argc++, scene.normals); - shadekernel.SetArg(argc++, scene.uvs); - shadekernel.SetArg(argc++, scene.indices); - shadekernel.SetArg(argc++, scene.shapes); - shadekernel.SetArg(argc++, scene.materialids); - shadekernel.SetArg(argc++, scene.materials); - shadekernel.SetArg(argc++, scene.textures); - shadekernel.SetArg(argc++, scene.texturedata); - shadekernel.SetArg(argc++, scene.envmapidx); - shadekernel.SetArg(argc++, scene.lights); - shadekernel.SetArg(argc++, scene.num_lights); - shadekernel.SetArg(argc++, rand_uint()); - shadekernel.SetArg(argc++, m_render_data->random); - shadekernel.SetArg(argc++, m_render_data->sobolmat); - shadekernel.SetArg(argc++, pass); - shadekernel.SetArg(argc++, m_framecnt); - shadekernel.SetArg(argc++, scene.volumes); - shadekernel.SetArg(argc++, m_render_data->shadowrays); - shadekernel.SetArg(argc++, m_render_data->lightsamples); - shadekernel.SetArg(argc++, m_render_data->paths); - shadekernel.SetArg(argc++, m_render_data->rays[(pass + 1) & 0x1]); - shadekernel.SetArg(argc++, output->data()); - - // Run shading kernel - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, shadekernel); - } - } - - - void PtRenderer::ShadeVolume(ClwScene const& scene, int pass, int2 const& tile_size) - { - // Fetch kernel - CLWKernel shadekernel = m_render_data->program.GetKernel("ShadeVolume"); - - auto output = static_cast(GetOutput(OutputType::kColor)); - - // Set kernel parameters - int argc = 0; - shadekernel.SetArg(argc++, m_render_data->rays[pass & 0x1]); - shadekernel.SetArg(argc++, m_render_data->intersections); - shadekernel.SetArg(argc++, m_render_data->compacted_indices); - shadekernel.SetArg(argc++, m_render_data->pixelindices[pass & 0x1]); - shadekernel.SetArg(argc++, m_render_data->hitcount); - shadekernel.SetArg(argc++, scene.vertices); - shadekernel.SetArg(argc++, scene.normals); - shadekernel.SetArg(argc++, scene.uvs); - shadekernel.SetArg(argc++, scene.indices); - shadekernel.SetArg(argc++, scene.shapes); - shadekernel.SetArg(argc++, scene.materialids); - shadekernel.SetArg(argc++, scene.materials); - shadekernel.SetArg(argc++, scene.textures); - shadekernel.SetArg(argc++, scene.texturedata); - shadekernel.SetArg(argc++, scene.envmapidx); - shadekernel.SetArg(argc++, scene.lights); - shadekernel.SetArg(argc++, scene.num_lights); - shadekernel.SetArg(argc++, rand_uint()); - shadekernel.SetArg(argc++, m_render_data->random); - shadekernel.SetArg(argc++, m_render_data->sobolmat); - shadekernel.SetArg(argc++, pass); - shadekernel.SetArg(argc++, m_framecnt); - shadekernel.SetArg(argc++, scene.volumes); - shadekernel.SetArg(argc++, m_render_data->shadowrays); - shadekernel.SetArg(argc++, m_render_data->lightsamples); - shadekernel.SetArg(argc++, m_render_data->paths); - shadekernel.SetArg(argc++, m_render_data->rays[(pass + 1) & 0x1]); - shadekernel.SetArg(argc++, output->data()); - - // Run shading kernel - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, shadekernel); - } - } - - void PtRenderer::EvaluateVolume(ClwScene const& scene, int pass, int2 const& tile_size) - { - // Fetch kernel - CLWKernel evalkernel = m_render_data->program.GetKernel("EvaluateVolume"); - - auto output = static_cast(GetOutput(OutputType::kColor)); - - // Set kernel parameters - int argc = 0; - evalkernel.SetArg(argc++, m_render_data->rays[pass & 0x1]); - evalkernel.SetArg(argc++, m_render_data->pixelindices[(pass + 1) & 0x1]); - evalkernel.SetArg(argc++, m_render_data->hitcount); - evalkernel.SetArg(argc++, scene.volumes); - evalkernel.SetArg(argc++, scene.textures); - evalkernel.SetArg(argc++, scene.texturedata); - evalkernel.SetArg(argc++, rand_uint()); - evalkernel.SetArg(argc++, m_render_data->random); - evalkernel.SetArg(argc++, m_render_data->sobolmat); - evalkernel.SetArg(argc++, pass); - evalkernel.SetArg(argc++, m_framecnt); - evalkernel.SetArg(argc++, m_render_data->intersections); - evalkernel.SetArg(argc++, m_render_data->paths); - evalkernel.SetArg(argc++, output->data()); - - // Run shading kernel - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, evalkernel); - } - } - - - void PtRenderer::ShadeBackground(ClwScene const& scene, int pass, int2 const& tile_size) - { - // Fetch kernel - CLWKernel misskernel = m_render_data->program.GetKernel("ShadeBackgroundEnvMap"); - - auto output = static_cast(GetOutput(OutputType::kColor)); - - // Set kernel parameters - int argc = 0; - misskernel.SetArg(argc++, m_render_data->rays[pass & 0x1]); - misskernel.SetArg(argc++, m_render_data->intersections); - misskernel.SetArg(argc++, m_render_data->pixelindices[(pass + 1) & 0x1]); - misskernel.SetArg(argc++, tile_size.x * tile_size.y); - misskernel.SetArg(argc++, scene.lights); - misskernel.SetArg(argc++, scene.envmapidx); - misskernel.SetArg(argc++, scene.textures); - misskernel.SetArg(argc++, scene.texturedata); - misskernel.SetArg(argc++, m_render_data->paths); - misskernel.SetArg(argc++, scene.volumes); - misskernel.SetArg(argc++, output->data()); - - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, misskernel); - } - } - - void PtRenderer::GatherLightSamples(ClwScene const& scene, int pass, int2 const& tile_size) - { - // Fetch kernel - CLWKernel gatherkernel = m_render_data->program.GetKernel("GatherLightSamples"); - - auto output = static_cast(GetOutput(OutputType::kColor)); - - // Set kernel parameters - int argc = 0; - gatherkernel.SetArg(argc++, m_render_data->pixelindices[pass & 0x1]); - gatherkernel.SetArg(argc++, m_render_data->hitcount); - gatherkernel.SetArg(argc++, m_render_data->shadowhits); - gatherkernel.SetArg(argc++, m_render_data->lightsamples); - gatherkernel.SetArg(argc++, m_render_data->paths); - gatherkernel.SetArg(argc++, output->data()); - - // Run shading kernel - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, gatherkernel); - } - } - - - void PtRenderer::RestorePixelIndices(int pass, int2 const& tile_size) - { - // Fetch kernel - CLWKernel restorekernel = m_render_data->program.GetKernel("RestorePixelIndices"); - - // Set kernel parameters - int argc = 0; - restorekernel.SetArg(argc++, m_render_data->compacted_indices); - restorekernel.SetArg(argc++, m_render_data->hitcount); - restorekernel.SetArg(argc++, m_render_data->pixelindices[(pass + 1) & 0x1]); - restorekernel.SetArg(argc++, m_render_data->pixelindices[pass & 0x1]); - - // Run shading kernel - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, restorekernel); - } - } - - void PtRenderer::FilterPathStream(int pass, int2 const& tile_size) - { - // Fetch kernel - CLWKernel restorekernel = m_render_data->program.GetKernel("FilterPathStream"); - - // Set kernel parameters - int argc = 0; - restorekernel.SetArg(argc++, m_render_data->intersections); - restorekernel.SetArg(argc++, m_render_data->hitcount); - restorekernel.SetArg(argc++, m_render_data->pixelindices[(pass + 1) & 0x1]); - restorekernel.SetArg(argc++, m_render_data->paths); - restorekernel.SetArg(argc++, m_render_data->hits); - - // Run shading kernel - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, restorekernel); - } - } - - CLWKernel PtRenderer::GetCopyKernel() - { - return m_render_data->program.GetKernel("ApplyGammaAndCopyData"); - } - - CLWKernel PtRenderer::GetAccumulateKernel() - { - return m_render_data->program.GetKernel("AccumulateData"); - } - - // Shade background - void PtRenderer::ShadeMiss(ClwScene const& scene, int pass, int2 const& tile_size) - { - // Fetch kernel - CLWKernel misskernel = m_render_data->program.GetKernel("ShadeMiss"); - - auto output = static_cast(GetOutput(OutputType::kColor)); - - // Set kernel parameters - int argc = 0; - misskernel.SetArg(argc++, m_render_data->rays[pass & 0x1]); - misskernel.SetArg(argc++, m_render_data->intersections); - misskernel.SetArg(argc++, m_render_data->pixelindices[(pass + 1) & 0x1]); - misskernel.SetArg(argc++, m_render_data->hitcount); - misskernel.SetArg(argc++, scene.lights); - misskernel.SetArg(argc++, scene.envmapidx); - misskernel.SetArg(argc++, scene.textures); - misskernel.SetArg(argc++, scene.texturedata); - misskernel.SetArg(argc++, m_render_data->paths); - misskernel.SetArg(argc++, scene.volumes); - misskernel.SetArg(argc++, output->data()); - - // Run shading kernel - { - int globalsize = tile_size.x * tile_size.y; - m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, misskernel); - } - - } - - void PtRenderer::RunBenchmark(Scene1 const& scene, std::uint32_t num_passes, BenchmarkStats& stats) - { - auto output = static_cast(GetOutput(OutputType::kColor)); - - stats.num_passes = num_passes; - stats.resolution = int2(output->width(), output->height()); - - auto api = m_scene_controller.GetIntersectionApi(); - auto& clwscene = m_scene_controller.CompileScene(scene, m_render_data->mat_collector, m_render_data->tex_collector); - - // Number of rays to generate - int maxrays = output->width() * output->height(); - int2 tile_size = int2(output->width(), output->height()); - - // Generate primary - GenerateTileDomain(tile_size, int2(), tile_size, int2()); - GeneratePrimaryRays(clwscene, *output, tile_size); - - // Copy compacted indices to track reverse indices - m_context.CopyBuffer(0, m_render_data->iota, m_render_data->pixelindices[0], 0, 0, m_render_data->iota.GetElementCount()); - m_context.CopyBuffer(0, m_render_data->iota, m_render_data->pixelindices[1], 0, 0, m_render_data->iota.GetElementCount()); - m_context.FillBuffer(0, m_render_data->hitcount, maxrays, 1); - - - // Clear ray hits buffer - m_context.FillBuffer(0, m_render_data->hits, 0, m_render_data->hits.GetElementCount()); - - // Intersect ray batch - auto start = std::chrono::high_resolution_clock::now(); - - for (auto i = 0U; i < num_passes; ++i) - { - api->QueryIntersection(m_render_data->fr_rays[0], m_render_data->fr_hitcount, maxrays, m_render_data->fr_intersections, nullptr, nullptr); - } - - m_context.Finish(0); - - auto delta = std::chrono::high_resolution_clock::now() - start; - - stats.primary_rays_time_in_ms = (float)std::chrono::duration_cast(delta).count() / num_passes; - - // Convert intersections to predicates - FilterPathStream(0, tile_size); - - // Compact batch - m_render_data->pp.Compact(0, m_render_data->hits, m_render_data->iota, m_render_data->compacted_indices, maxrays, m_render_data->hitcount); - - // Advance indices to keep pixel indices up to date - RestorePixelIndices(0, tile_size); - - // Shade hits - ShadeSurface(clwscene, 0, tile_size); - - // Shade missing rays - ShadeMiss(clwscene, 0, tile_size); - - // Intersect ray batch - start = std::chrono::high_resolution_clock::now(); - - for (auto i = 0U; i < num_passes; ++i) - { - api->QueryOcclusion(m_render_data->fr_shadowrays, m_render_data->fr_hitcount, maxrays, m_render_data->fr_shadowhits, nullptr, nullptr); - } - - m_context.Finish(0); - - delta = std::chrono::high_resolution_clock::now() - start; - - stats.shadow_rays_time_in_ms = (float)std::chrono::duration_cast(delta).count() / num_passes; - - // Gather light samples and account for visibility - GatherLightSamples(clwscene, 0, tile_size); - - // - m_context.Flush(0); - - // Clear ray hits buffer - m_context.FillBuffer(0, m_render_data->hits, 0, m_render_data->hits.GetElementCount()); - - // Intersect ray batch - start = std::chrono::high_resolution_clock::now(); - - for (auto i = 0U; i < num_passes; ++i) - { - api->QueryIntersection(m_render_data->fr_rays[1], m_render_data->fr_hitcount, maxrays, m_render_data->fr_intersections, nullptr, nullptr); - } - - m_context.Finish(0); - - delta = std::chrono::high_resolution_clock::now() - start; - - stats.secondary_rays_time_in_ms = (float)std::chrono::duration_cast(delta).count() / num_passes; - - // Convert intersections to predicates - FilterPathStream(1, tile_size); - - // Compact batch - m_render_data->pp.Compact(0, m_render_data->hits, m_render_data->iota, m_render_data->compacted_indices, maxrays, m_render_data->hitcount); - - // Advance indices to keep pixel indices up to date - RestorePixelIndices(1, tile_size); - - // Shade hits - ShadeSurface(clwscene, 1, tile_size); - - // Shade missing rays - ShadeMiss(clwscene, 1, tile_size); - - api->QueryOcclusion(m_render_data->fr_shadowrays, m_render_data->fr_hitcount, maxrays, m_render_data->fr_shadowhits, nullptr, nullptr); - - // Gather light samples and account for visibility - - GatherLightSamples(clwscene, 0, tile_size); - - // - m_context.Flush(0); - - //samples statisticks - output->Clear(0.f); - start = std::chrono::high_resolution_clock::now(); - for (auto i = 0U; i < num_passes; ++i) - { - Render(scene); - } - delta = std::chrono::high_resolution_clock::now() - start; - - stats.samples_pes_sec = output->width() * output->height() / ((float)std::chrono::duration_cast(delta).count() / num_passes) / 1000.f; - } -} diff --git a/Baikal/Renderers/PT/ptrenderer.h b/Baikal/Renderers/PT/ptrenderer.h deleted file mode 100644 index 23261418..00000000 --- a/Baikal/Renderers/PT/ptrenderer.h +++ /dev/null @@ -1,121 +0,0 @@ -/********************************************************************** -Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. - -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. -********************************************************************/ -#pragma once - -#include "math/int2.h" -#include "Core/renderer.h" -#include "CLW/clwscene.h" -#include "CLW/clw_scene_controller.h" - -#include "CLW.h" - - -namespace Baikal -{ - class ClwOutput; - struct ClwScene; - class SceneTracker; - - ///< Renderer implementation - class PtRenderer : public Renderer - { - public: - // Constructor - PtRenderer(CLWContext context, int devidx, int num_bounces); - // Destructor - ~PtRenderer(); - - // Renderer overrides - // Create output - Output* CreateOutput(std::uint32_t w, std::uint32_t h) const override; - // Delete output - void DeleteOutput(Output* output) const override; - // Clear output - void Clear(RadeonRays::float3 const& val, Output& output) const override; - // Render the scene into the output - void Render(Scene1 const& scene) override; - // Render single tile - void RenderTile(Scene1 const& scene, RadeonRays::int2 const& tile_origin, RadeonRays::int2 const& tile_size) override; - // Set output - void SetOutput(OutputType type, Output* output) override; - // Set number of light bounces - void SetNumBounces(int num_bounces); - // Interop function - CLWKernel GetCopyKernel(); - // Add function - CLWKernel GetAccumulateKernel(); - // Run render benchmark - void RunBenchmark(Scene1 const& scene, std::uint32_t num_passes, BenchmarkStats& stats) override; - - protected: - // Resize output-dependent buffers - void ResizeWorkingSet(Output const& output); - // Generate rays - void GeneratePrimaryRays(ClwScene const& scene, Output const& output, int2 const& tile_size); - // Shade first hit - void ShadeSurface(ClwScene const& scene, int pass, int2 const& tile_size); - // Evaluate volume - void EvaluateVolume(ClwScene const& scene, int pass, int2 const& tile_size); - // Handle missing rays - void ShadeMiss(ClwScene const& scene, int pass, int2 const& tile_size); - // Gather light samples and account for visibility - void GatherLightSamples(ClwScene const& scene, int pass, int2 const& tile_size); - // Restore pixel indices after compaction - void RestorePixelIndices(int pass, int2 const& tile_size); - // Convert intersection info to compaction predicate - void FilterPathStream(int pass, int2 const& tile_size); - // Integrate volume - void ShadeVolume(ClwScene const& scene, int pass, int2 const& tile_size); - // Shade background - void ShadeBackground(ClwScene const& scene, int pass, int2 const& tile_size); - // Fill necessary AOVs - void FillAOVs(ClwScene const& scene, int2 const& tile_origin, int2 const& tile_size); - // Generate index domain - void GenerateTileDomain(int2 const& output_size, int2 const& tile_origin, int2 const& tile_size, int2 const& subtile_size); - // Find non-zero AOV - Output* FindFirstNonZeroOutput(bool include_color = true) const; - - public: - // CL context - CLWContext m_context; - // Scene tracker - ClwSceneController m_scene_controller; - - // GPU data - struct PathState; - struct RenderData; - - std::unique_ptr m_render_data; - - // Intersector data - std::vector m_shapes; - - // Vidmem usage - // Working set - size_t m_vidmemws; - - private: - std::uint32_t m_num_bounces; - mutable std::uint32_t m_framecnt; - }; - -} diff --git a/Baikal/Renderers/adaptive_renderer.cpp b/Baikal/Renderers/adaptive_renderer.cpp new file mode 100644 index 00000000..ab7ff2ed --- /dev/null +++ b/Baikal/Renderers/adaptive_renderer.cpp @@ -0,0 +1,220 @@ +#include "adaptive_renderer.h" +#include "Output/clwoutput.h" + +namespace Baikal +{ + + AdaptiveRenderer::AdaptiveRenderer( + CLWContext context, + const CLProgramManager *program_manager, + std::unique_ptr estimator + ) : MonteCarloRenderer(context, program_manager, std::move(estimator)) + { + auto samples_buffer_size = GetEstimator().GetWorkBufferSize(); + m_sample_buffer = GetContext().CreateBuffer(samples_buffer_size, CL_MEM_READ_WRITE); + } + + void AdaptiveRenderer::Clear(RadeonRays::float3 const& val, + Output& output) const + { + MonteCarloRenderer::Clear(val, output); + + GetContext().FillBuffer(0u, m_variance_buffer, 0.f, m_variance_buffer.GetElementCount()).Wait(); + } + + // Render single tile + void AdaptiveRenderer::RenderTile(ClwScene const& scene, + RadeonRays::int2 const& tile_origin, + RadeonRays::int2 const& tile_size) + { + // Number of rays to generate + auto output = static_cast(GetOutput(OutputType::kColor)); + auto width = output->width(); + auto height = output->height(); + + GetContext().FillBuffer(0u, m_sample_buffer, float3(), m_sample_buffer.GetElementCount()).Wait(); + + if (output) + { + auto num_rays = tile_size.x * tile_size.y; + auto output_size = int2(width, height); + + if (m_sample_counter < 32) + { + MonteCarloRenderer::GenerateTileDomain(output_size, tile_origin, tile_size); + } + else + { + GenerateTileDomain(output_size, tile_origin, tile_size); + } + + GeneratePrimaryRays(scene, *output, tile_size); + + m_estimator->Estimate( + scene, + num_rays, + Estimator::QualityLevel::kStandard, + m_sample_buffer, + false, + true + ); + + AccumulateSamples(m_sample_buffer, output->data(), num_rays); + + if (m_sample_counter > 0 && m_sample_counter % 32 == 0) + { + auto variance_buffer_size = m_variance_buffer.GetElementCount(); + EstimateVariance(output->data(), output->width(), output->height()); + + std::vector probabilities(variance_buffer_size); + GetContext().ReadBuffer(0u, m_variance_buffer, &probabilities[0], variance_buffer_size).Wait(); + + m_tile_distribution.Set(&probabilities[0], + (std::uint32_t)variance_buffer_size); + + UpdateTileDistribution(); + } + + } + + // Check if we have other outputs, than color + bool aov_pass_needed = (FindFirstNonZeroOutput(false) != nullptr); + if (aov_pass_needed) + { + FillAOVs(scene, tile_origin, tile_size); + GetContext().Flush(0); + } + } + + void AdaptiveRenderer::AccumulateSamples( + CLWBuffer sample_buffer, + CLWBuffer accumulation_buffer, + std::uint32_t num_elements + ) + { + auto accumulate_kernel = GetKernel("AccumulateSingleSample"); + + int argc = 0; + accumulate_kernel.SetArg(argc++, sample_buffer); + accumulate_kernel.SetArg(argc++, accumulation_buffer); + accumulate_kernel.SetArg(argc++, m_estimator->GetOutputIndexBuffer()); + accumulate_kernel.SetArg(argc++, num_elements); + + { + GetContext().Launch1D(0, ((num_elements + 63) / 64) * 64, 64, accumulate_kernel); + } + } + + void AdaptiveRenderer::EstimateVariance( + CLWBuffer accumulation_buffer, + std::uint32_t width, + std::uint32_t height + ) + { + auto estimate_kernel = GetKernel("EstimateVariance"); + + int argc = 0; + estimate_kernel.SetArg(argc++, accumulation_buffer); + estimate_kernel.SetArg(argc++, m_variance_buffer); + estimate_kernel.SetArg(argc++, width); + estimate_kernel.SetArg(argc++, height); + + // Run shading kernel + { + size_t gs[] = { static_cast((width + 15) / 16 * 16), static_cast((width + 15) / 16 * 16) }; + size_t ls[] = { 16, 16 }; + + GetContext().Launch2D(0, gs, ls, estimate_kernel); + } + } + + void AdaptiveRenderer::SetOutput(OutputType type, Output* output) + { + // Intermediate variance buffer + MonteCarloRenderer::SetOutput(type, output); + + if (output) + { + auto width = output->width(); + auto height = output->height(); + + auto variance_buffer_size = ((width + 15) / 16) * ((height + 15) / 16); + m_variance_buffer = GetContext().CreateBuffer(variance_buffer_size, CL_MEM_READ_WRITE); + + std::vector probabilities(variance_buffer_size, 1.f); + m_tile_distribution.Set(&probabilities[0], variance_buffer_size); + + UpdateTileDistribution(); + } + } + + void AdaptiveRenderer::UpdateTileDistribution() + { + // Write distribution data + int* distribution_ptr = nullptr; + auto num_tiles = m_variance_buffer.GetElementCount(); + auto required_size = (1 + 1 + num_tiles + num_tiles); + if (m_tile_distribution_buffer.GetElementCount() < required_size) + { + m_tile_distribution_buffer = GetContext().CreateBuffer(required_size, CL_MEM_READ_ONLY); + } + + GetContext().MapBuffer(0, m_tile_distribution_buffer, CL_MAP_WRITE, &distribution_ptr).Wait(); + auto current = distribution_ptr; + + // Write the number of segments first + *current++ = (int)m_tile_distribution.m_num_segments; + + // Then write num_segments + 1 CDF values + auto values = reinterpret_cast(current); + for (auto i = 0u; i < m_tile_distribution.m_num_segments + 1; ++i) + { + values[i] = m_tile_distribution.m_cdf[i]; + } + + // Then write num_segments PDF values + values += m_tile_distribution.m_num_segments + 1; + + for (auto i = 0u; i < m_tile_distribution.m_num_segments; ++i) + { + values[i] = m_tile_distribution.m_func_values[i] / m_tile_distribution.m_func_sum; + } + + GetContext().UnmapBuffer(0, m_tile_distribution_buffer, distribution_ptr); + } + + void AdaptiveRenderer::GenerateTileDomain( + int2 const& output_size, + int2 const& tile_origin, + int2 const& tile_size + ) + { + // Fetch kernel + CLWKernel generate_kernel = GetKernel("GenerateTileDomain_Adaptive"); + + // Set kernel parameters + int argc = 0; + generate_kernel.SetArg(argc++, output_size.x); + generate_kernel.SetArg(argc++, output_size.y); + generate_kernel.SetArg(argc++, tile_origin.x); + generate_kernel.SetArg(argc++, tile_origin.y); + generate_kernel.SetArg(argc++, tile_size.x); + generate_kernel.SetArg(argc++, tile_size.y); + generate_kernel.SetArg(argc++, rand_uint()); + generate_kernel.SetArg(argc++, m_sample_counter); + generate_kernel.SetArg(argc++, m_estimator->GetRandomBuffer(Estimator::RandomBufferType::kRandomSeed)); + generate_kernel.SetArg(argc++, m_estimator->GetRandomBuffer(Estimator::RandomBufferType::kSobolLUT)); + generate_kernel.SetArg(argc++, m_tile_distribution_buffer); + generate_kernel.SetArg(argc++, m_estimator->GetOutputIndexBuffer()); + generate_kernel.SetArg(argc++, m_estimator->GetRayCountBuffer()); + + // Run shading kernel + { + size_t gs[] = { static_cast((tile_size.x + 15) / 16 * 16), static_cast((tile_size.y + 15) / 16 * 16) }; + size_t ls[] = { 16, 16 }; + + GetContext().Launch2D(0, gs, ls, generate_kernel); + } + } + +} diff --git a/Baikal/Renderers/adaptive_renderer.h b/Baikal/Renderers/adaptive_renderer.h new file mode 100644 index 00000000..d02e4ede --- /dev/null +++ b/Baikal/Renderers/adaptive_renderer.h @@ -0,0 +1,92 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once + +#include "math/int2.h" +#include "monte_carlo_renderer.h" +#include "CLW.h" +#include "Utils/distribution1d.h" + +#include + + + +namespace Baikal +{ + class ClwOutput; + struct ClwScene; + + ///< Renderer implementation + class AdaptiveRenderer : public MonteCarloRenderer + { + public: + AdaptiveRenderer( + CLWContext context, + const CLProgramManager *program_manager, + std::unique_ptr estimator + ); + + ~AdaptiveRenderer() = default; + + // Renderer overrides + void Clear(RadeonRays::float3 const& val, + Output& output) const override; + + // Render single tile + void RenderTile(ClwScene const& scene, + RadeonRays::int2 const& tile_origin, + RadeonRays::int2 const& tile_size) override; + + // Set output + void SetOutput(OutputType type, Output* output) override; + + // DEBUG STUFF + CLWBuffer GetVarianceBuffer() const { return m_variance_buffer; } + protected: + void AccumulateSamples( + CLWBuffer sample_buffer, + CLWBuffer accumulation_buffer, + std::uint32_t num_elements + ); + + void EstimateVariance( + CLWBuffer accumulation_buffer, + std::uint32_t width, + std::uint32_t height + ); + + void GenerateTileDomain( + int2 const& output_size, + int2 const& tile_origin, + int2 const& tile_size + ) override; + + void UpdateTileDistribution(); + + private: + mutable CLWBuffer m_variance_buffer; + mutable CLWBuffer m_sample_buffer; + CLWBuffer m_tile_distribution_buffer; + Distribution1D m_tile_distribution; + }; + +} diff --git a/Baikal/Renderers/monte_carlo_renderer.cpp b/Baikal/Renderers/monte_carlo_renderer.cpp new file mode 100644 index 00000000..3f99b0ba --- /dev/null +++ b/Baikal/Renderers/monte_carlo_renderer.cpp @@ -0,0 +1,426 @@ +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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 "monte_carlo_renderer.h" +#include "Output/clwoutput.h" +#include "Estimators/estimator.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "math/int2.h" + +#ifdef BAIKAL_EMBED_KERNELS +#include "embed_kernels.h" +#endif + +#include "Utils/cl_program_manager.h" + +namespace Baikal +{ + using namespace RadeonRays; + + int constexpr kTileSizeX = 1920; + int constexpr kTileSizeY = 1080; + + // Constructor + MonteCarloRenderer::MonteCarloRenderer( + CLWContext context, + const CLProgramManager *program_manager, + std::unique_ptr estimator + ) +#ifdef BAIKAL_EMBED_KERNELS + : Baikal::ClwClass(context, program_manager, "monte_carlo_renderer", g_monte_carlo_renderer_opencl, g_monte_carlo_renderer_opencl_headers, "") +#else + : Baikal::ClwClass(context, program_manager, "../Baikal/Kernels/CL/monte_carlo_renderer.cl", "") +#endif + , m_estimator(std::move(estimator)) + , m_sample_counter(0u) +#ifdef BAIKAL_EMBED_KERNELS + , m_uberv2_kernels(context, program_manager, "fill_aovs_uberv2", g_fill_aovs_uberv2_opencl, g_fill_aovs_uberv2_opencl_headers, "") +#else + , m_uberv2_kernels(context, program_manager, "../Baikal/Kernels/CL/fill_aovs_uberv2.cl", "") +#endif + { + m_estimator->SetWorkBufferSize(kTileSizeX * kTileSizeY); + } + + void MonteCarloRenderer::Clear(RadeonRays::float3 const& val, Output& output) const + { + static_cast(output).Clear(val); + m_sample_counter = 0u; + } + + void MonteCarloRenderer::Render(ClwScene const& scene) + { + auto output = FindFirstNonZeroOutput(true, true); + if (!output) + { + throw std::runtime_error("No outputs set"); + } + + auto output_size = int2(output->width(), output->height()); + + if (output_size.x > kTileSizeX || output_size.y > kTileSizeY) + { + auto num_tiles_x = (output_size.x + kTileSizeX - 1) / kTileSizeX; + auto num_tiles_y = (output_size.y + kTileSizeY - 1) / kTileSizeY; + + for (auto x = 0; x < num_tiles_x; ++x) + for (auto y = 0; y < num_tiles_y; ++y) + { + auto tile_offset = int2(x * kTileSizeX, y * kTileSizeY); + auto tile_size = int2(std::min(kTileSizeX, output_size.x - tile_offset.x), + std::min(kTileSizeY, output_size.y - tile_offset.y)); + + RenderTile(scene, tile_offset, tile_size); + } + } + else + { + RenderTile(scene, int2(), output_size); + } + + ++m_sample_counter; + } + + // Render the scene into the output + void MonteCarloRenderer::RenderTile(ClwScene const& scene, int2 const& tile_origin, int2 const& tile_size) + { + // Number of rays to generate + auto color_output = static_cast(GetOutput(OutputType::kColor)); + + if (color_output) + { + auto num_rays = tile_size.x * tile_size.y; + auto output_size = int2(color_output->width(), color_output->height()); + + GenerateTileDomain(output_size, tile_origin, tile_size); + GeneratePrimaryRays(scene, *color_output, tile_size); + + if (scene.background_idx > -1) + { + m_estimator->Estimate( + scene, + num_rays, + Estimator::QualityLevel::kStandard, + color_output->data(), + true, + false, + std::bind(&MonteCarloRenderer::HandleMissedRays, this, std::ref(scene), output_size.x, output_size.y, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, + std::placeholders::_5, std::placeholders::_6)); + } + else + m_estimator->Estimate( + scene, + num_rays, + Estimator::QualityLevel::kStandard, + color_output->data()); + + } + else + { + // Check if we set intermediate value output without enabled color output + for (std::size_t i = 0; i < static_cast(Estimator::IntermediateValue::kMax); ++i) + { + if (m_estimator->HasIntermediateValueBuffer(static_cast(i))) + { + throw std::runtime_error("IntermediateValue AOV require color AOV to be set"); + } + } + } + + // Check if we have outputs that we can render in single pass + bool aov_pass_needed = (FindFirstNonZeroOutput(false) != nullptr); + if (aov_pass_needed) + { + FillAOVs(scene, tile_origin, tile_size); + GetContext().Flush(0); + } + } + + void MonteCarloRenderer::GenerateTileDomain( + int2 const& output_size, + int2 const& tile_origin, + int2 const& tile_size + ) + { + // Fetch kernel + CLWKernel generate_kernel = GetKernel("GenerateTileDomain"); + + // Set kernel parameters + int argc = 0; + generate_kernel.SetArg(argc++, output_size.x); + generate_kernel.SetArg(argc++, output_size.y); + generate_kernel.SetArg(argc++, tile_origin.x); + generate_kernel.SetArg(argc++, tile_origin.y); + generate_kernel.SetArg(argc++, tile_size.x); + generate_kernel.SetArg(argc++, tile_size.y); + generate_kernel.SetArg(argc++, rand_uint()); + generate_kernel.SetArg(argc++, m_sample_counter); + generate_kernel.SetArg(argc++, m_estimator->GetRandomBuffer(Estimator::RandomBufferType::kRandomSeed)); + generate_kernel.SetArg(argc++, m_estimator->GetRandomBuffer(Estimator::RandomBufferType::kSobolLUT)); + generate_kernel.SetArg(argc++, m_estimator->GetOutputIndexBuffer()); + generate_kernel.SetArg(argc++, m_estimator->GetRayCountBuffer()); + + // Run shading kernel + { + size_t gs[] = { static_cast((tile_size.x + 15) / 16 * 16), static_cast((tile_size.y + 15) / 16 * 16) }; + size_t ls[] = { 16, 16 }; + + GetContext().Launch2D(0, gs, ls, generate_kernel); + } + } + + Output* MonteCarloRenderer::FindFirstNonZeroOutput(bool include_multipass, bool include_singlepass) const + { + // If we don't use anything, why are we calling this function? + assert(include_multipass || include_singlepass); + + std::uint32_t start_index = include_multipass ? 0 + : static_cast(Renderer::OutputType::kMaxMultiPassOutput) + 1; + std::uint32_t end_index = include_singlepass ? static_cast(Renderer::OutputType::kMax) + : static_cast(Renderer::OutputType::kMaxMultiPassOutput); + + Output* current_output = nullptr; + for (auto i = start_index; i < end_index; ++i) + { + current_output = GetOutput(static_cast(i)); + + if (current_output) + { + break; + } + } + return current_output; + } + + void MonteCarloRenderer::SetOutput(OutputType type, Output* output) + { + static const std::map kOutputTypeToIntermediateValue = + { + { OutputType::kOpacity, Estimator::IntermediateValue::kOpacity }, + { OutputType::kVisibility, Estimator::IntermediateValue::kVisibility }, + }; + + auto it = kOutputTypeToIntermediateValue.find(type); + if (it != kOutputTypeToIntermediateValue.end()) + { + if (!m_estimator->SupportsIntermediateValue(it->second)) + { + throw std::runtime_error("Visibility AOV is not supported by an underlying estimator"); + } + + if (output) + { + auto clw_output = static_cast(output); + m_estimator->SetIntermediateValueBuffer(it->second, clw_output->data()); + } + else + { + // Set empty buffer + m_estimator->SetIntermediateValueBuffer(it->second, CLWBuffer()); + } + } + + Renderer::SetOutput(type, output); + } + + + void MonteCarloRenderer::FillAOVs(ClwScene const& scene, int2 const& tile_origin, int2 const& tile_size) + { + // Find first non-zero AOV to get buffer dimensions + auto output = FindFirstNonZeroOutput(false); + auto output_size = int2(output->width(), output->height()); + + // Generate tile domain + GenerateTileDomain(output_size, tile_origin, tile_size); + + // Generate primary + GeneratePrimaryRays(scene, *output, tile_size, true); + + auto num_rays = tile_size.x * tile_size.y; + + // Intersect ray batch + m_estimator->TraceFirstHit(scene, num_rays); + + CLWKernel fill_kernel = m_uberv2_kernels.GetKernel("FillAOVsUberV2"); + + auto argc = 0U; + fill_kernel.SetArg(argc++, m_estimator->GetRayBuffer()); + fill_kernel.SetArg(argc++, m_estimator->GetFirstHitBuffer()); + fill_kernel.SetArg(argc++, m_estimator->GetOutputIndexBuffer()); + fill_kernel.SetArg(argc++, m_estimator->GetRayCountBuffer()); + fill_kernel.SetArg(argc++, scene.vertices); + fill_kernel.SetArg(argc++, scene.normals); + fill_kernel.SetArg(argc++, scene.uvs); + fill_kernel.SetArg(argc++, scene.indices); + fill_kernel.SetArg(argc++, scene.shapes); + fill_kernel.SetArg(argc++, scene.shapes_additional); + fill_kernel.SetArg(argc++, scene.material_attributes); + fill_kernel.SetArg(argc++, scene.textures); + fill_kernel.SetArg(argc++, scene.texturedata); + fill_kernel.SetArg(argc++, scene.envmapidx); + fill_kernel.SetArg(argc++, scene.background_idx); + fill_kernel.SetArg(argc++, output_size.x); + fill_kernel.SetArg(argc++, output_size.y); + fill_kernel.SetArg(argc++, scene.lights); + fill_kernel.SetArg(argc++, scene.num_lights); + fill_kernel.SetArg(argc++, scene.camera); + fill_kernel.SetArg(argc++, rand_uint()); + fill_kernel.SetArg(argc++, m_estimator->GetRandomBuffer(Estimator::RandomBufferType::kRandomSeed)); + fill_kernel.SetArg(argc++, m_estimator->GetRandomBuffer(Estimator::RandomBufferType::kSobolLUT)); + fill_kernel.SetArg(argc++, m_sample_counter); + for (auto i = static_cast(Renderer::OutputType::kMaxMultiPassOutput) + 1; + i < static_cast(Renderer::OutputType::kMax); ++i) + { + if (auto aov = static_cast(GetOutput(static_cast(i)))) + { + fill_kernel.SetArg(argc++, 1); + fill_kernel.SetArg(argc++, aov->data()); + } + else + { + fill_kernel.SetArg(argc++, 0); + // This is simply a dummy buffer + fill_kernel.SetArg(argc++, m_estimator->GetRayCountBuffer()); + } + } + fill_kernel.SetArg(argc++, scene.input_map_data); + + // Run AOV kernel + { + int globalsize = tile_size.x * tile_size.y; + GetContext().Launch1D(0, ((globalsize + 63) / 64) * 64, 64, fill_kernel); + } + } + + static std::string GetCameraKernelName(CameraType type) + { + switch (type) { + case CameraType::kPerspective: + return "PerspectiveCamera_GeneratePaths"; + case CameraType::kPhysicalPerspective: + return "PerspectiveCameraDof_GeneratePaths"; + case CameraType::kOrthographic: + return "OrthographicCamera_GeneratePaths"; + default: + assert(false); + return "none"; + } + } + + void MonteCarloRenderer::GeneratePrimaryRays( + ClwScene const& scene, + Output const& output, + int2 const& tile_size, + bool generate_at_pixel_center + ) + { + // Fetch kernel + auto kernel_name = GetCameraKernelName(scene.camera_type); + auto genkernel = GetKernel(kernel_name, generate_at_pixel_center ? "-D BAIKAL_GENERATE_SAMPLE_AT_PIXEL_CENTER " : ""); + + // Set kernel parameters + int argc = 0; + genkernel.SetArg(argc++, scene.camera); + genkernel.SetArg(argc++, output.width()); + genkernel.SetArg(argc++, output.height()); + genkernel.SetArg(argc++, m_estimator->GetOutputIndexBuffer()); + genkernel.SetArg(argc++, m_estimator->GetRayCountBuffer()); + genkernel.SetArg(argc++, (int)rand_uint()); + genkernel.SetArg(argc++, m_sample_counter); + genkernel.SetArg(argc++, m_estimator->GetRayBuffer()); + genkernel.SetArg(argc++, m_estimator->GetRandomBuffer(Estimator::RandomBufferType::kRandomSeed)); + genkernel.SetArg(argc++, m_estimator->GetRandomBuffer(Estimator::RandomBufferType::kSobolLUT)); + + { + int globalsize = tile_size.x * tile_size.y; + GetContext().Launch1D(0, ((globalsize + 63) / 64) * 64, 64, genkernel); + } + } + + CLWKernel MonteCarloRenderer::GetCopyKernel() + { + return GetKernel("ApplyGammaAndCopyData"); + } + + CLWKernel MonteCarloRenderer::GetAccumulateKernel() + { + return GetKernel("AccumulateData"); + } + + void MonteCarloRenderer::SetRandomSeed(std::uint32_t seed) + { + m_estimator->SetRandomSeed(seed); + } + + void MonteCarloRenderer::Benchmark(ClwScene const& scene, Estimator::RayTracingStats& stats) + { + auto output = static_cast(GetOutput(OutputType::kColor)); + + int num_rays = output->width() * output->height(); + int2 tile_size = int2(output->width(), output->height()); + + GenerateTileDomain(tile_size, int2(), tile_size); + GeneratePrimaryRays(scene, *output, tile_size); + + m_estimator->Benchmark(scene, num_rays, stats); + } + + void MonteCarloRenderer::SetMaxBounces(std::uint32_t max_bounces) + { + m_estimator->SetMaxBounces(max_bounces); + } + + void MonteCarloRenderer::HandleMissedRays(const ClwScene &scene , uint32_t w, uint32_t h, + CLWBuffer rays, CLWBuffer intersections, CLWBuffer pixel_indices, + CLWBuffer output_indices, std::size_t size, CLWBuffer output) + { + // Fetch kernel + auto misskernel = GetKernel("ShadeBackgroundImage") ; + + // Set kernel parameters + int argc = 0; + misskernel.SetArg(argc++, rays); + misskernel.SetArg(argc++, intersections); + misskernel.SetArg(argc++, pixel_indices); + misskernel.SetArg(argc++, output_indices); + misskernel.SetArg(argc++, (cl_int)size); + misskernel.SetArg(argc++, scene.background_idx); + misskernel.SetArg(argc++, w); + misskernel.SetArg(argc++, h); + misskernel.SetArg(argc++, scene.textures); + misskernel.SetArg(argc++, scene.texturedata); + misskernel.SetArg(argc++, output); + + { + GetContext().Launch1D(0, ((size + 63) / 64) * 64, 64, misskernel); + } + } + +} diff --git a/Baikal/Renderers/monte_carlo_renderer.h b/Baikal/Renderers/monte_carlo_renderer.h new file mode 100644 index 00000000..76792d83 --- /dev/null +++ b/Baikal/Renderers/monte_carlo_renderer.h @@ -0,0 +1,121 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once + +#include "math/int2.h" +#include "renderer.h" + +#include "SceneGraph/clwscene.h" +#include "Controllers/clw_scene_controller.h" +#include "Utils/clw_class.h" +#include "Estimators/estimator.h" + +#include "CLW.h" + +#include + + +namespace Baikal +{ + class ClwOutput; + struct ClwScene; + class CLProgramManager; + + ///< Renderer implementation + class MonteCarloRenderer : public Renderer, protected ClwClass + { + public: + + MonteCarloRenderer( + CLWContext context, + const CLProgramManager *program_manager, + std::unique_ptr estimator + ); + + ~MonteCarloRenderer() = default; + + // Renderer overrides + void Clear(RadeonRays::float3 const& val, + Output& output) const override; + + // Render the scene into the output + void Render(ClwScene const& scene) override; + + // Render single tile + void RenderTile(ClwScene const& scene, + RadeonRays::int2 const& tile_origin, + RadeonRays::int2 const& tile_size) override; + + // Set output + void SetOutput(OutputType type, Output* output) override; + + void SetRandomSeed(std::uint32_t seed) override; + + // Interop function + CLWKernel GetCopyKernel(); + // Add function + CLWKernel GetAccumulateKernel(); + // Run render benchmark + void Benchmark(ClwScene const& scene, Estimator::RayTracingStats& stats); + + // Set max number of light bounces + void SetMaxBounces(std::uint32_t max_bounces); + + protected: + void GeneratePrimaryRays( + ClwScene const& scene, + Output const& output, + int2 const& tile_size, + bool generate_at_pixel_center = false + ); + + void FillAOVs( + ClwScene const& scene, + int2 const& tile_origin, + int2 const& tile_size + ); + + virtual void GenerateTileDomain( + int2 const& output_size, + int2 const& tile_origin, + int2 const& tile_size + ); + + Estimator& GetEstimator() { return *m_estimator; } + + // Find non-zero AOV + Output* FindFirstNonZeroOutput(bool include_multipass = true, bool include_singlepass = true) const; + + // Handler for missed rays used when scene have background override with plain image + void HandleMissedRays(const ClwScene &scene, uint32_t w, uint32_t h, + CLWBuffer rays, CLWBuffer intersections, CLWBuffer pixel_indices, + CLWBuffer output_indices, std::size_t size, CLWBuffer output); + + public: + std::unique_ptr m_estimator; + mutable std::uint32_t m_sample_counter; + + private: + ClwClass m_uberv2_kernels; + }; + +} diff --git a/Baikal/Core/renderer.h b/Baikal/Renderers/renderer.h similarity index 74% rename from Baikal/Core/renderer.h rename to Baikal/Renderers/renderer.h index 7f0fa3bf..ca17272b 100644 --- a/Baikal/Core/renderer.h +++ b/Baikal/Renderers/renderer.h @@ -24,7 +24,8 @@ THE SOFTWARE. \file renderer.h \author Dmitry Kozlov \version 1.0 - \brief Contains declaration of Baikal::Renderer class, core interface representing representing the renderer. + \brief Contains declaration of Baikal::Renderer class, core interface + representing representing the renderer. */ #pragma once @@ -37,67 +38,74 @@ THE SOFTWARE. namespace Baikal { class Output; - class Scene1; + struct ClwScene; /** \brief Interface for the renderer. - Renderer implemenation is taking the scene and producing its image into an output surface. + Renderer implemenation is taking the scene and producing its image into + an output surface. */ class Renderer { public: enum class OutputType { - kColor, + // Multi-pass outputs that will + // be rendered in Estimator kernel + kColor = 0, + kOpacity, + kVisibility, + kMaxMultiPassOutput, + // Single-pass outputs that will + // be rendered in AOV kernel kWorldPosition, kWorldShadingNormal, + kViewShadingNormal, kWorldGeometricNormal, kUv, kWireframe, kAlbedo, + kWorldTangent, + kWorldBitangent, + kGloss, + kMeshID, + kGroupID, + kBackground, + kDepth, + kShapeId, kMax }; Renderer(); virtual ~Renderer() = default; - /** - \brief Create output of a given size. - - \param w Output surface width - \param h Output surface height - */ - virtual Output* CreateOutput(std::uint32_t w, std::uint32_t h) const = 0; - - /** - \brief Delete given output. - - \param output The output to delete - */ - virtual void DeleteOutput(Output* output) const = 0; - /** \brief Clear output surface using given value. \param val Value to clear to \param output Output to clear */ - virtual void Clear(RadeonRays::float3 const& val, Output& output) const = 0; + virtual + void Clear(RadeonRays::float3 const& val, Output& output) const = 0; /** \brief Render single iteration. \param scene Scene to render */ - virtual void Render(Scene1 const& scene) = 0; + virtual + void Render(ClwScene const& scene) = 0; /** \brief Render single iteration. \param scene Scene to render */ - virtual void RenderTile(Scene1 const& scene, RadeonRays::int2 const& tile_origin, RadeonRays::int2 const& tile_size) = 0; + virtual + void RenderTile(ClwScene const& scene, + RadeonRays::int2 const& tile_origin, + RadeonRays::int2 const& tile_size) = 0; /** \brief Set the output for rendering. @@ -113,29 +121,23 @@ namespace Baikal */ virtual Output* GetOutput(OutputType type) const; + /** + \brief Set random seed value for the renderer. Renders + with the same random seed are guaranteed to be the same. + + \param seed Seed value + */ + virtual void SetRandomSeed(std::uint32_t seed) = 0; + /** Disallow copies and moves. */ Renderer(Renderer const&) = delete; Renderer& operator = (Renderer const&) = delete; - // Temporary functionality - struct BenchmarkStats - { - std::uint32_t num_passes; - - RadeonRays::int2 resolution; - float primary_rays_time_in_ms; - float secondary_rays_time_in_ms; - float shadow_rays_time_in_ms; - //msamples per second - float samples_pes_sec; - }; - - virtual void RunBenchmark(Scene1 const& scene, std::uint32_t num_passes, BenchmarkStats& stats) {} - private: - std::array(OutputType::kMax)> m_outputs; + std::array(OutputType::kMax)> + m_outputs; }; inline Renderer::Renderer() @@ -148,6 +150,7 @@ namespace Baikal auto idx = static_cast(type); if (idx >= static_cast(OutputType::kMax)) throw std::out_of_range("Output type is out of supported range"); + m_outputs[idx] = output; } diff --git a/Baikal/SceneGraph/Collector/collector.cpp b/Baikal/SceneGraph/Collector/collector.cpp index b5220f13..bc8be38a 100644 --- a/Baikal/SceneGraph/Collector/collector.cpp +++ b/Baikal/SceneGraph/Collector/collector.cpp @@ -1,13 +1,21 @@ #include "collector.h" -#include "CLW/clwscene.h" +#include "SceneGraph/clwscene.h" #include "SceneGraph/iterator.h" #include #include +#include namespace Baikal { - using ItemMap = std::map; - using ItemSet = std::set; + struct IdCompare + { + bool operator() (const SceneObject::Ptr& lhs, const SceneObject::Ptr& rhs) const + { + return lhs->GetId() < rhs->GetId(); + } + }; + using ItemMap = std::unordered_map; + using ItemSet = std::set; class BundleImpl : public Bundle { @@ -41,23 +49,30 @@ namespace Baikal m_impl->m_set.clear(); } - Iterator* Collector::CreateIterator() const + std::unique_ptr Collector::CreateIterator() const { - return new IteratorImpl(m_impl->m_set.cbegin(), m_impl->m_set.cend()); + return std::unique_ptr( + new IteratorImpl(m_impl->m_set.cbegin(), + m_impl->m_set.cend())); } - void Collector::Collect(Iterator* shape_iter, ExpandFunc expand_func) + void Collector::Collect(Iterator& iter, ExpandFunc expand_func) { - for(;shape_iter->IsValid();shape_iter->Next()) + for(;iter.IsValid(); iter.Next()) { // Expand current item - auto cur_items = expand_func(shape_iter->Item()); + auto cur_items = expand_func(iter.Item()); // Insert items m_impl->m_set.insert(cur_items.cbegin(), cur_items.cend()); } } - + + void Collector::Collect(std::shared_ptr < Baikal::SceneObject > object) + { + m_impl->m_set.insert(object); + } + void Collector::Commit() { m_impl->m_map.clear(); @@ -65,7 +80,7 @@ namespace Baikal int idx = 0; for (auto& i : m_impl->m_set) { - m_impl->m_map[i] = idx++; + m_impl->m_map[i->GetId()] = idx++; } } @@ -123,9 +138,9 @@ namespace Baikal return new BundleImpl { m_impl->m_map, m_impl->m_set }; } - std::uint32_t Collector::GetItemIndex(void const* item) const + std::uint32_t Collector::GetItemIndex(SceneObject::Ptr item) const { - auto iter = m_impl->m_map.find(item); + auto iter = m_impl->m_map.find(item->GetId()); if (iter == m_impl->m_map.cend()) { diff --git a/Baikal/SceneGraph/Collector/collector.h b/Baikal/SceneGraph/Collector/collector.h index a5cfeb26..4fadb2b3 100644 --- a/Baikal/SceneGraph/Collector/collector.h +++ b/Baikal/SceneGraph/Collector/collector.h @@ -1,16 +1,16 @@ /********************************************************************** Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. - + 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 @@ -32,15 +32,17 @@ #include #include +#include "../scene_object.h" + namespace Baikal { class Material; class Iterator; - + /** \brief Serialized bundle. - + Bundle is a representation of a chunk of serialized memory keeping pointer to offset map. */ class Bundle @@ -51,30 +53,34 @@ namespace Baikal /** \brief Collector class. - + Collector iterates over collection of objects collecting objects and their dependecies into random access bundle. The engine uses collectors in order to resolve material-texture or shape-material dependecies for GPU serialization. */ class Collector { public: - using ExpandFunc = std::function(void const*)>; - using ChangedFunc = std::function; - using FinalizeFunc = std::function; - + using ExpandFunc = std::function(SceneObject::Ptr)>; + using ChangedFunc = std::function; + using FinalizeFunc = std::function; + // Constructor Collector(); // Destructor virtual ~Collector(); - + // Clear collector state (CreateIterator returns invalid iterator if the collector is empty) void Clear(); // Create an iterator of objects - Iterator* CreateIterator() const; + std::unique_ptr CreateIterator() const; // Collect objects and their dependencies - void Collect(Iterator* iter, ExpandFunc expand_func); + void Collect(Iterator& iter, ExpandFunc expand_func); + // Adds single object to collection + void Collect(std::shared_ptr object); // Commit collected objects void Commit(); + // Commit collected objects with order based on object id. + //void CommitOrderedById(); // Given a budnle check if all collected objects are in the bundle and do not require update bool NeedsUpdate(Bundle const* bundle, ChangedFunc cahnged_func) const; // Get number of objects in the collection @@ -82,19 +88,19 @@ namespace Baikal // Create serialised bundle (randomly accessible dump of objects) Bundle* CreateBundle() const; // Get item index within a collection - std::uint32_t GetItemIndex(void const* item) const; + std::uint32_t GetItemIndex(SceneObject::Ptr item) const; // Finalization function void Finalize(FinalizeFunc finalize_func); - + // Disallow copies and moves Collector(Collector const&) = delete; Collector& operator = (Collector const&) = delete; - + private: struct CollectorImpl; std::unique_ptr m_impl; }; - + inline Bundle::~Bundle() { } diff --git a/Baikal/SceneGraph/IO/scene_io.cpp b/Baikal/SceneGraph/IO/scene_io.cpp deleted file mode 100644 index a4745e7b..00000000 --- a/Baikal/SceneGraph/IO/scene_io.cpp +++ /dev/null @@ -1,269 +0,0 @@ -#include "scene_io.h" -#include "image_io.h" -#include "../scene1.h" -#include "../shape.h" -#include "../material.h" -#include "../light.h" -#include "../texture.h" - - -#include "Utils/tiny_obj_loader.h" - -namespace Baikal -{ - // Obj scene loader - class SceneIoObj : public SceneIo - { - public: - // Load scene from file - Scene1* LoadScene(std::string const& filename, std::string const& basepath) const override; - private: - Material const* TranslateMaterial(ImageIo const& image_io, tinyobj::material_t const& mat, std::string const& basepath, Scene1& scene) const; - - }; - - SceneIo* SceneIo::CreateSceneIoObj() - { - return new SceneIoObj(); - } - - - Material const* SceneIoObj::TranslateMaterial(ImageIo const& image_io, tinyobj::material_t const& mat, std::string const& basepath, Scene1& scene) const - { - RadeonRays::float3 emission(mat.emission[0], mat.emission[1], mat.emission[2]); - - Material* material = nullptr; - - // Check if this is emissive - if (emission.sqnorm() > 0) - { - // If yes create emissive brdf - material = new SingleBxdf(SingleBxdf::BxdfType::kEmissive); - - // Set albedo - if (!mat.diffuse_texname.empty()) - { - auto texture = image_io.LoadImage(basepath + mat.diffuse_texname); - material->SetInputValue("albedo", texture); - scene.AttachAutoreleaseObject(texture); - } - else - { - material->SetInputValue("albedo", emission); - } - } - else - { - auto s = RadeonRays::float3(mat.specular[0], mat.specular[1], mat.specular[2]); - - if ((s.sqnorm() > 0 || !mat.specular_texname.empty())) - { - // Otherwise create lambert - material = new MultiBxdf(MultiBxdf::Type::kFresnelBlend); - material->SetInputValue("ior", RadeonRays::float4(1.5f, 1.5f, 1.5f, 1.5f)); - - Material* diffuse = new SingleBxdf(SingleBxdf::BxdfType::kLambert); - Material* specular = new SingleBxdf(SingleBxdf::BxdfType::kMicrofacetGGX); - - specular->SetInputValue("roughness", 0.01f); - - // Set albedo - if (!mat.diffuse_texname.empty()) - { - auto texture = image_io.LoadImage(basepath + mat.diffuse_texname); - diffuse->SetInputValue("albedo", texture); - scene.AttachAutoreleaseObject(texture); - } - else - { - diffuse->SetInputValue("albedo", RadeonRays::float3(mat.diffuse[0], mat.diffuse[1], mat.diffuse[2])); - } - - // Set albedo - if (!mat.specular_texname.empty()) - { - auto texture = image_io.LoadImage(basepath + mat.specular_texname); - specular->SetInputValue("albedo", texture); - scene.AttachAutoreleaseObject(texture); - } - else - { - specular->SetInputValue("albedo", s); - } - - // Set normal - if (!mat.normal_texname.empty()) - { - auto texture = image_io.LoadImage(basepath + mat.normal_texname); - diffuse->SetInputValue("normal", texture); - specular->SetInputValue("normal", texture); - scene.AttachAutoreleaseObject(texture); - } - - diffuse->SetName(mat.name + "-diffuse"); - specular->SetName(mat.name + "-specular"); - - material->SetInputValue("base_material", diffuse); - material->SetInputValue("top_material", specular); - - scene.AttachAutoreleaseObject(diffuse); - scene.AttachAutoreleaseObject(specular); - } - else - { - // Otherwise create lambert - Material* diffuse = new SingleBxdf(SingleBxdf::BxdfType::kLambert); - - // Set albedo - if (!mat.diffuse_texname.empty()) - { - auto texture = image_io.LoadImage(basepath + mat.diffuse_texname); - diffuse->SetInputValue("albedo", texture); - scene.AttachAutoreleaseObject(texture); - } - else - { - diffuse->SetInputValue("albedo", RadeonRays::float3(mat.diffuse[0], mat.diffuse[1], mat.diffuse[2])); - } - - // Set normal - if (!mat.normal_texname.empty()) - { - auto texture = image_io.LoadImage(basepath + mat.normal_texname); - diffuse->SetInputValue("normal", texture); - scene.AttachAutoreleaseObject(texture); - } - - material = diffuse; - } - } - - // Set material name - material->SetName(mat.name); - - scene.AttachAutoreleaseObject(material); - - return material; - } - - Scene1* SceneIoObj::LoadScene(std::string const& filename, std::string const& basepath) const - { - using namespace tinyobj; - - auto image_io(ImageIo::CreateImageIo()); - - // Loader data - std::vector objshapes; - std::vector objmaterials; - - // Try loading file - std::string res = LoadObj(objshapes, objmaterials, filename.c_str(), basepath.c_str()); - if (res != "") - { - throw std::runtime_error(res); - } - - // Allocate scene - Scene1* scene(new Scene1); - - // Enumerate and translate materials - // Keep track of emissive subset - std::set emissives; - std::vector materials(objmaterials.size()); - for (int i = 0; i < (int)objmaterials.size(); ++i) - { - // Translate material - materials[i] = TranslateMaterial(*image_io, objmaterials[i], basepath, *scene); - - // Add to emissive subset if needed - if (materials[i]->HasEmission()) - { - emissives.insert(materials[i]); - } - } - - // Enumerate all shapes in the scene - for (int s = 0; s < (int)objshapes.size(); ++s) - { - // Create empty mesh - Mesh* mesh = new Mesh(); - - // Set vertex and index data - auto num_vertices = objshapes[s].mesh.positions.size() / 3; - mesh->SetVertices(&objshapes[s].mesh.positions[0], num_vertices); - - auto num_normals = objshapes[s].mesh.normals.size() / 3; - mesh->SetNormals(&objshapes[s].mesh.normals[0], num_normals); - - auto num_uvs = objshapes[s].mesh.texcoords.size() / 2; - - // If we do not have UVs, generate zeroes - if (num_uvs) - { - mesh->SetUVs(&objshapes[s].mesh.texcoords[0], num_uvs); - } - else - { - std::vector zero(num_vertices); - std::fill(zero.begin(), zero.end(), RadeonRays::float2(0, 0)); - mesh->SetUVs(&zero[0], num_vertices); - } - - // Set indices - auto num_indices = objshapes[s].mesh.indices.size(); - mesh->SetIndices(reinterpret_cast(&objshapes[s].mesh.indices[0]), num_indices); - - // Set material - auto idx = objshapes[s].mesh.material_ids[0]; - - if (idx > 0) - { - mesh->SetMaterial(materials[idx]); - } - - // Attach to the scene - scene->AttachShape(mesh); - - // Attach for autorelease - scene->AttachAutoreleaseObject(mesh); - - // If the mesh has emissive material we need to add area light for it - if (idx > 0 && emissives.find(materials[idx]) != emissives.cend()) - { - // Add area light for each polygon of emissive mesh - for (int l = 0; l < mesh->GetNumIndices() / 3 ;++l) - { - AreaLight* light = new AreaLight(mesh, l); - scene->AttachLight(light); - scene->AttachAutoreleaseObject(light); - } - } - } - - // TODO: temporary code, add IBL - Texture* ibl_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); - scene->AttachAutoreleaseObject(ibl_texture); - - ImageBasedLight* ibl = new ImageBasedLight(); - ibl->SetTexture(ibl_texture); - ibl->SetMultiplier(1.f); - scene->AttachAutoreleaseObject(ibl); - - // TODO: temporary code to add directional light - DirectionalLight* light = new DirectionalLight(); - light->SetDirection(RadeonRays::normalize(RadeonRays::float3(-1.1f, -0.6f, -0.2f))); - light->SetEmittedRadiance(3.5f * RadeonRays::float3(1.f, 1.f, 1.f)); - scene->AttachAutoreleaseObject(light); - - DirectionalLight* light1 = new DirectionalLight(); - light1->SetDirection(RadeonRays::float3(0.3f, -1.f, -0.5f)); - light1->SetEmittedRadiance(RadeonRays::float3(1.f, 0.8f, 0.65f)); - scene->AttachAutoreleaseObject(light1); - - //scene->AttachLight(light); - scene->AttachLight(light1); - scene->AttachLight(ibl); - - return scene; - } -} diff --git a/Baikal/SceneGraph/IO/scene_test_io.cpp b/Baikal/SceneGraph/IO/scene_test_io.cpp deleted file mode 100644 index 904595b1..00000000 --- a/Baikal/SceneGraph/IO/scene_test_io.cpp +++ /dev/null @@ -1,345 +0,0 @@ -#include "scene_io.h" -#include "image_io.h" -#include "../scene1.h" -#include "../shape.h" -#include "../material.h" -#include "../light.h" -#include "../texture.h" -#include "math/mathutils.h" - -#include - -#define _USE_MATH_DEFINES -#include - -namespace Baikal -{ - // Create fake test IO - class SceneIoTest : public SceneIo - { - public: - // Load scene (this class uses filename to determine what scene to generate) - Scene1* LoadScene(std::string const& filename, std::string const& basepath) const override; - }; - - // Create test IO - SceneIo* SceneIo::CreateSceneIoTest() - { - return new SceneIoTest(); - } - - - // Create spehere mesh - Mesh* CreateSphere(std::uint32_t lat, std::uint32_t lon, float r, RadeonRays::float3 const& c) - { - auto num_verts = (lat - 2) * lon + 2; - auto num_tris = (lat - 2) * (lon - 1 ) * 2; - - std::vector vertices(num_verts); - std::vector normals(num_verts); - std::vector uvs(num_verts); - std::vector indices (num_tris * 3); - - - auto t = 0U; - for(auto j = 1U; j < lat - 1; j++) - for(auto i = 0U; i < lon; i++) - { - float theta = float(j) / (lat - 1) * (float)M_PI; - float phi = float(i) / (lon - 1 ) * (float)M_PI * 2; - vertices[t].x = r * sinf(theta) * cosf(phi) + c.x; - vertices[t].y = r * cosf(theta) + c.y; - vertices[t].z = r * -sinf(theta) * sinf(phi) + c.z; - normals[t].x = sinf(theta) * cosf(phi); - normals[t].y = cosf(theta); - normals[t].z = -sinf(theta) * sinf(phi); - uvs[t].x = float(j) / (lat - 2); - uvs[t].y = float(i) / (lon - 1); - ++t; - } - - vertices[t].x=c.x; vertices[t].y = c.y + r; vertices[t].z = c.z; - normals[t].x=0; normals[t].y = 1; normals[t].z = 0; - uvs[t].x=0; uvs[t].y = 0; - ++t; - vertices[t].x=c.x; vertices[t].y = c.y-r; vertices[t].z = c.z; - normals[t].x=0; normals[t].y = -1; normals[t].z = 0; - uvs[t].x=1; uvs[t].y = 1; - ++t; - - t = 0U; - for(auto j = 0U; j < lat - 3; j++) - for(auto i = 0U; i < lon - 1; i++) - { - indices[t++] = j * lon + i; - indices[t++] = (j + 1) * lon + i + 1; - indices[t++] = j * lon + i + 1; - indices[t++] = j * lon + i; - indices[t++] = (j + 1) * lon + i; - indices[t++] = (j + 1) * lon + i + 1; - } - - for(auto i = 0U; i < lon - 1; i++) - { - indices[t++] = (lat - 2) * lon; - indices[t++] = i; - indices[t++] = i + 1; - indices[t++] = (lat - 2) * lon + 1; - indices[t++] = (lat - 3) * lon + i + 1; - indices[t++] = (lat - 3) * lon + i; - } - - auto mesh = new Mesh(); - mesh->SetVertices(&vertices[0], vertices.size()); - mesh->SetNormals(&normals[0], normals.size()); - mesh->SetUVs(&uvs[0], uvs.size()); - mesh->SetIndices(&indices[0], indices.size()); - - return mesh; - } - - - // Create quad - Mesh* CreateQuad(std::vector const& vertices, bool flip) - { - using namespace RadeonRays; - - auto u1 = normalize(vertices[1] - vertices[0]); - auto u2 = normalize(vertices[3] - vertices[0]); - auto n = -cross(u1, u2); - - if (flip) - { - n = -n; - } - - float3 normals[] = { n, n, n, n }; - - float2 uvs[] = - { - float2(0, 0), - float2(1, 0), - float2(1, 1), - float2(0, 1) - }; - - std::uint32_t indices[] = - { - 0, 1, 2, - 0, 2, 3 - }; - - auto mesh = new Mesh(); - mesh->SetVertices(&vertices[0], 4); - mesh->SetNormals(normals, 4); - mesh->SetUVs(uvs, 4); - mesh->SetIndices(indices, 6); - - return mesh; - } - - Scene1* SceneIoTest::LoadScene(std::string const& filename, std::string const& basepath) const - { - using namespace RadeonRays; - - Scene1* scene(new Scene1); - - auto image_io(ImageIo::CreateImageIo()); - - if (filename == "quad+ibl") - { - Mesh* quad = CreateQuad( - { - RadeonRays::float3(-5, 0, -5), - RadeonRays::float3(5, 0, -5), - RadeonRays::float3(5, 0, 5), - RadeonRays::float3(-5, 0, 5), - } - , false); - - scene->AttachShape(quad); - scene->AttachAutoreleaseObject(quad); - - Texture* ibl_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); - scene->AttachAutoreleaseObject(ibl_texture); - - ImageBasedLight* ibl = new ImageBasedLight(); - ibl->SetTexture(ibl_texture); - ibl->SetMultiplier(1.f); - scene->AttachLight(ibl); - scene->AttachAutoreleaseObject(ibl); - - SingleBxdf* green = new SingleBxdf(SingleBxdf::BxdfType::kLambert); - green->SetInputValue("albedo", float4(0.1f, 0.2f, 0.1f, 1.f)); - - SingleBxdf* spec = new SingleBxdf(SingleBxdf::BxdfType::kMicrofacetGGX); - spec->SetInputValue("albedo", float4(0.9f, 0.9f, 0.9f, 1.f)); - spec->SetInputValue("roughness", float4(0.002f, 0.002f, 0.002f, 1.f)); - - MultiBxdf* mix = new MultiBxdf(MultiBxdf::Type::kFresnelBlend); - mix->SetInputValue("base_material", green); - mix->SetInputValue("top_material", spec); - mix->SetInputValue("ior", float4(1.33f, 1.33f, 1.33f, 1.33f)); - - quad->SetMaterial(mix); - - scene->AttachAutoreleaseObject(green); - scene->AttachAutoreleaseObject(spec); - scene->AttachAutoreleaseObject(mix); - } - else if (filename == "sphere+ibl") - { - auto mesh = CreateSphere(64, 32, 2.f, float3()); - scene->AttachShape(mesh); - scene->AttachAutoreleaseObject(mesh); - - Texture* ibl_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); - scene->AttachAutoreleaseObject(ibl_texture); - - ImageBasedLight* ibl = new ImageBasedLight(); - ibl->SetTexture(ibl_texture); - ibl->SetMultiplier(1.f); - scene->AttachLight(ibl); - scene->AttachAutoreleaseObject(ibl); - - SingleBxdf* green = new SingleBxdf(SingleBxdf::BxdfType::kLambert); - green->SetInputValue("albedo", float4(0.1f, 0.2f, 0.1f, 1.f)); - - SingleBxdf* spec = new SingleBxdf(SingleBxdf::BxdfType::kMicrofacetGGX); - spec->SetInputValue("albedo", float4(0.9f, 0.9f, 0.9f, 1.f)); - spec->SetInputValue("roughness", float4(0.002f, 0.002f, 0.002f, 1.f)); - - MultiBxdf* mix = new MultiBxdf(MultiBxdf::Type::kFresnelBlend); - mix->SetInputValue("base_material", green); - mix->SetInputValue("top_material", spec); - mix->SetInputValue("ior", float4(1.33f, 1.33f, 1.33f, 1.33f)); - - mesh->SetMaterial(mix); - - scene->AttachAutoreleaseObject(green); - scene->AttachAutoreleaseObject(spec); - scene->AttachAutoreleaseObject(mix); - } - else if (filename == "sphere+plane+area") - { - auto mesh = CreateSphere(64, 32, 2.f, float3(0.f, 2.5f, 0.f)); - scene->AttachShape(mesh); - scene->AttachAutoreleaseObject(mesh); - - SingleBxdf* grey = new SingleBxdf(SingleBxdf::BxdfType::kMicrofacetGGX); - grey->SetInputValue("albedo", float4(0.99f, 0.99f, 0.99f, 1.f)); - grey->SetInputValue("roughness", float4(0.025f, 0.025f, 0.025f, 1.f)); - - Mesh* floor = CreateQuad( - { - RadeonRays::float3(-8, 0, -8), - RadeonRays::float3(8, 0, -8), - RadeonRays::float3(8, 0, 8), - RadeonRays::float3(-8, 0, 8), - } - , false); - scene->AttachShape(floor); - scene->AttachAutoreleaseObject(floor); - - floor->SetMaterial(grey); - mesh->SetMaterial(grey); - - SingleBxdf* emissive = new SingleBxdf(SingleBxdf::BxdfType::kEmissive); - emissive->SetInputValue("albedo", 1.f * float4(3.1f, 3.f, 2.8f, 1.f)); - - Mesh* light = CreateQuad( - { - RadeonRays::float3(-2, 6, -2), - RadeonRays::float3(2, 6, -2), - RadeonRays::float3(2, 6, 2), - RadeonRays::float3(-2, 6, 2), - } - , true); - scene->AttachShape(light); - scene->AttachAutoreleaseObject(light); - - light->SetMaterial(emissive); - - AreaLight* l1 = new AreaLight(light, 0); - AreaLight* l2 = new AreaLight(light, 1); - - scene->AttachLight(l1); - scene->AttachLight(l2); - scene->AttachAutoreleaseObject(l1); - scene->AttachAutoreleaseObject(l2); - - scene->AttachAutoreleaseObject(emissive); - scene->AttachAutoreleaseObject(grey); - } - else if (filename == "sphere+plane+ibl") - { - auto mesh = CreateSphere(64, 32, 2.f, float3(0.f, 2.2f, 0.f)); - scene->AttachShape(mesh); - scene->AttachAutoreleaseObject(mesh); - - auto instance = new Instance(mesh); - scene->AttachShape(instance); - scene->AttachAutoreleaseObject(instance); - - matrix t = RadeonRays::translation(float3(5.f, 0.f, 5.f)); - instance->SetTransform(t); - - SingleBxdf* green = new SingleBxdf(SingleBxdf::BxdfType::kLambert); - green->SetInputValue("albedo", 2.f * float4(0.1f, 0.2f, 0.1f, 1.f)); - - SingleBxdf* grey = new SingleBxdf(SingleBxdf::BxdfType::kLambert); - green->SetInputValue("albedo", 2.f * float4(0.2f, 0.2f, 0.2f, 0.2f)); - - SingleBxdf* spec = new SingleBxdf(SingleBxdf::BxdfType::kMicrofacetGGX); - spec->SetInputValue("albedo", float4(0.9f, 0.9f, 0.9f, 1.f)); - spec->SetInputValue("roughness", float4(0.2f, 0.2f, 0.2f, 1.f)); - - auto normal_map = image_io->LoadImage("../Resources/Textures/test_normal.jpg"); - auto bump_map = image_io->LoadImage("../Resources/Textures/test_bump.jpg"); - green->SetInputValue("normal", normal_map); - spec->SetInputValue("normal", normal_map); - grey->SetInputValue("bump", bump_map); - instance->SetMaterial(grey); - - MultiBxdf* mix = new MultiBxdf(MultiBxdf::Type::kFresnelBlend); - mix->SetInputValue("base_material", green); - mix->SetInputValue("top_material", spec); - mix->SetInputValue("ior", float4(3.33f, 3.33f, 3.33f, 3.33f)); - - mesh->SetMaterial(mix); - - Mesh* floor = CreateQuad( - { - RadeonRays::float3(-8, 0, -8), - RadeonRays::float3(8, 0, -8), - RadeonRays::float3(8, 0, 8), - RadeonRays::float3(-8, 0, 8), - } - , false); - scene->AttachShape(floor); - scene->AttachAutoreleaseObject(floor); - - floor->SetMaterial(green); - - Texture* ibl_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); - scene->AttachAutoreleaseObject(ibl_texture); - - ImageBasedLight* ibl = new ImageBasedLight(); - ibl->SetTexture(ibl_texture); - ibl->SetMultiplier(1.f); - scene->AttachLight(ibl); - scene->AttachAutoreleaseObject(ibl); - - scene->AttachAutoreleaseObject(green); - scene->AttachAutoreleaseObject(spec); - scene->AttachAutoreleaseObject(mix); - scene->AttachAutoreleaseObject(grey); - scene->AttachAutoreleaseObject(normal_map); - scene->AttachAutoreleaseObject(bump_map); - - } - - return scene; - } -} - diff --git a/Baikal/SceneGraph/camera.cpp b/Baikal/SceneGraph/camera.cpp index ca8a9819..c724c0aa 100644 --- a/Baikal/SceneGraph/camera.cpp +++ b/Baikal/SceneGraph/camera.cpp @@ -33,37 +33,41 @@ namespace Baikal { using namespace RadeonRays; + Camera::Camera(float3 const& eye, float3 const& at, float3 const& up) + : m_volume(nullptr) + { + LookAt(eye, at, up); + } + PerspectiveCamera::PerspectiveCamera(float3 const& eye, float3 const& at, float3 const& up) - : m_p(eye) - , m_aperture(0.f) - , m_focus_distance(0.f) + : Camera(eye, at, up) , m_focal_length(0.f) - , m_zcap(0.f, 0.f) - , m_aspect(0.f) + , m_focus_distance(0.f) + , m_aperture(0.f) { - // Construct camera frame - LookAt(eye, at, up); } - void PerspectiveCamera::LookAt(RadeonRays::float3 const& eye, - RadeonRays::float3 const& at, - RadeonRays::float3 const& up) + void Camera::LookAt(RadeonRays::float3 const& eye, + RadeonRays::float3 const& at, + RadeonRays::float3 const& up) { m_p = eye; m_forward = normalize(at - eye); - m_right = cross(m_forward, normalize(up)); + m_right = normalize(cross(m_forward, up)); m_up = cross(m_right, m_forward); + m_at = at; SetDirty(true); } // Rotate camera around world Z axis, use for FPS camera - void PerspectiveCamera::Rotate(float angle) + void Camera::Rotate(float angle) { - Rotate(float3(0.f, 1.f, 0.f), angle); + //Rotate(float3(0.f, 1.f, 0.f), angle); + RotateOnOrbit(float3(0.f, 1.f, 0.f), angle); SetDirty(true); } - void PerspectiveCamera::Rotate(float3 v, float angle) + void Camera::Rotate(float3 v, float angle) { /// matrix should have basis vectors in rows /// to be used for quaternion construction @@ -89,118 +93,115 @@ namespace Baikal m_forward = normalize(float3(cam_matrix.m20, cam_matrix.m21, cam_matrix.m22)); SetDirty(true); } + + void Camera::RotateOnOrbit(float3 v, float angle) + { + /// matrix should have basis vectors in rows + /// to be used for quaternion construction + /// would be good to add several options + /// to quaternion class + auto direction = m_p - m_at; + auto up = m_up; + + // Rotate camera frame around v + auto q = rotation_quaternion(v, angle); + auto new_direction = rotate_vector(direction, q); + auto new_up = rotate_vector(up, q); + + LookAt(m_at + new_direction, m_at, new_up); + + SetDirty(true); + } // Tilt camera - void PerspectiveCamera::Tilt(float angle) + void Camera::Tilt(float angle) { - Rotate(m_right, angle); + RotateOnOrbit(m_right, angle); + //Rotate(m_right, angle); SetDirty(true); } // Move along camera Z direction - void PerspectiveCamera::MoveForward(float distance) + void Camera::MoveForward(float distance) { m_p += distance * m_forward; + m_at += distance * m_forward; SetDirty(true); } + + void Camera::Zoom(float distance) + { + if (distance < 0.f || (m_p - m_at).sqnorm() > 1.f) + { + m_p += distance * m_forward; + LookAt(m_p, m_at, m_up); + SetDirty(true); + } + } // Move along camera X direction - void PerspectiveCamera::MoveRight(float distance) + void Camera::MoveRight(float distance) { m_p += distance * m_right; + m_at += distance * m_right; SetDirty(true); } // Move along camera Y direction - void PerspectiveCamera::MoveUp(float distance) + void Camera::MoveUp(float distance) { m_p += distance * m_up; + m_at += distance * m_up; SetDirty(true); } - RadeonRays::float3 PerspectiveCamera::GetForwardVector() const + RadeonRays::float3 Camera::GetForwardVector() const { return m_forward; } - RadeonRays::float3 PerspectiveCamera::GetUpVector() const + RadeonRays::float3 Camera::GetUpVector() const { return m_up; } - RadeonRays::float3 PerspectiveCamera::GetRightVector() const + RadeonRays::float3 Camera::GetRightVector() const { return m_right; } - RadeonRays::float3 PerspectiveCamera::GetPosition() const + RadeonRays::float3 Camera::GetPosition() const { return m_p; } - float PerspectiveCamera::GetAspectRatio() const + float Camera::GetAspectRatio() const { - return m_aspect; + return m_dim.x / m_dim.y; } - // Arcball rotation - void PerspectiveCamera::ArcballRotateHorizontally(float3 c, float angle) - { - // Build camera matrix - matrix cam_matrix = matrix( - m_up.x, m_up.y, m_up.z, 0, - m_right.x, m_right.y, m_right.z, 0, - m_forward.x, m_forward.y, m_forward.z, 0, - 0, 0, 0, 1); - - // Create camera orientation quaternion - quaternion q = normalize(quaternion(cam_matrix)); - - // Rotation of camera around the center of interest by a == rotation of the frame by -a and rotation of the position by a - q = q * rotation_quaternion(float3(0.f, 1.f, 0.f), -angle); - - // Rotate the frame - q.to_matrix(cam_matrix); - - m_up = normalize(float3(cam_matrix.m00, cam_matrix.m01, cam_matrix.m02)); - m_right = normalize(float3(cam_matrix.m10, cam_matrix.m11, cam_matrix.m12)); - m_forward = normalize(float3(cam_matrix.m20, cam_matrix.m21, cam_matrix.m22)); - - // Rotate the position - float3 dir = c - m_p; - dir = rotate_vector(dir, rotation_quaternion(float3(0.f, 1.f, 0.f), angle)); - - m_p = c - dir; - SetDirty(true); + namespace { + struct PerspectiveCameraConcrete : public PerspectiveCamera { + PerspectiveCameraConcrete(float3 const& eye, float3 const& at, float3 const& up) : + PerspectiveCamera(eye, at, up) {} + }; + + struct OrthographicCameraConcrete : public OrthographicCamera { + OrthographicCameraConcrete(float3 const& eye, float3 const& at, float3 const& up) : + OrthographicCamera(eye, at, up) {} + }; } - void PerspectiveCamera::ArcballRotateVertically(float3 c, float angle) - { - // Build camera matrix - matrix cam_matrix = matrix( - m_up.x, m_up.y, m_up.z, 0, - m_right.x, m_right.y, m_right.z, 0, - m_forward.x, m_forward.y, m_forward.z, 0, - 0, 0, 0, 1); + PerspectiveCamera::Ptr PerspectiveCamera::Create(RadeonRays::float3 const& eye, + RadeonRays::float3 const& at, + RadeonRays::float3 const& up) { + return std::make_shared(eye, at, up); - // Create camera orientation quaternion - quaternion q = normalize(quaternion(cam_matrix)); - - // Rotation of camera around the center of interest by a == rotation of the frame by -a and rotation of the position by a - q = q * rotation_quaternion(m_right, -angle); - - // Rotate the frame - q.to_matrix(cam_matrix); - - m_up = normalize(float3(cam_matrix.m00, cam_matrix.m01, cam_matrix.m02)); - m_right = normalize(float3(cam_matrix.m10, cam_matrix.m11, cam_matrix.m12)); - m_forward = normalize(float3(cam_matrix.m20, cam_matrix.m21, cam_matrix.m22)); - - // Rotate the position - float3 dir = c - m_p; - dir = rotate_vector(dir, rotation_quaternion(m_right, angle)); - - m_p = c - dir; - SetDirty(true); + } + + OrthographicCamera::Ptr OrthographicCamera::Create(RadeonRays::float3 const& eye, + RadeonRays::float3 const& at, + RadeonRays::float3 const& up) { + return std::make_shared(eye, at, up); } } diff --git a/Baikal/SceneGraph/camera.h b/Baikal/SceneGraph/camera.h index ab849dba..d5dc0289 100644 --- a/Baikal/SceneGraph/camera.h +++ b/Baikal/SceneGraph/camera.h @@ -32,104 +32,149 @@ #include "math/float2.h" #include "scene_object.h" +#include "material.h" namespace Baikal { class Camera : public SceneObject { public: + using Ptr = std::shared_ptr; + Camera() = default; - virtual ~Camera() = default; - }; - - class PerspectiveCamera : public Camera - { - public: - // Pass camera position, camera aim, camera up vector, depth limits, vertical field of view - // and image plane aspect ratio - PerspectiveCamera(RadeonRays::float3 const& eye, - RadeonRays::float3 const& at, - RadeonRays::float3 const& up); + virtual ~Camera() = 0; // Pass camera position, camera aim, camera up vector void LookAt(RadeonRays::float3 const& eye, RadeonRays::float3 const& at, RadeonRays::float3 const& up); - // Set camera focus distance in meters, - // this is essentially a distance from the lens to the focal plane. - // Altering this is similar to rotating the focus ring on real lens. - void SetFocusDistance(float distance); - float GetFocusDistance() const; - - // Set camera focal length in meters, - // this is essentially a distance between a camera sensor and a lens. - // Altering this is similar to rotating zoom ring on a lens. - void SetFocalLength(float length); - float GetFocalLength() const; - - // Set aperture value in meters. - // This is a radius of a lens. - void SetAperture(float aperture); - float GetAperture() const; - - // Set camera sensor size in meters. - // This distinguishes APC-S vs full-frame, etc - void SetSensorSize(RadeonRays::float2 const& size); - RadeonRays::float2 GetSensorSize() const; - - // Set camera depth range. - // Does not really make sence for physical camera - void SetDepthRange(RadeonRays::float2 const& range); - RadeonRays::float2 GetDepthRange() const; - - RadeonRays::float3 GetForwardVector() const; - RadeonRays::float3 GetUpVector() const; - RadeonRays::float3 GetRightVector() const; - RadeonRays::float3 GetPosition() const; - float GetAspectRatio() const; - // Rotate camera around world Z axis void Rotate(float angle); + // Tilt camera void Tilt(float angle); // Move along camera Z direction void MoveForward(float distance); + void Zoom(float distance); // Move along camera X direction void MoveRight(float distance); // Move along camera Y direction void MoveUp(float distance); - // - void ArcballRotateHorizontally(RadeonRays::float3 c, float angle); - // - void ArcballRotateVertically(RadeonRays::float3 c, float angle); + RadeonRays::float3 GetForwardVector() const; + RadeonRays::float3 GetUpVector() const; + RadeonRays::float3 GetRightVector() const; + RadeonRays::float3 GetPosition() const; + // Set camera depth range. + // Does not really make sence for physical camera + void SetDepthRange(RadeonRays::float2 const& range); + RadeonRays::float2 GetDepthRange() const; + + float GetAspectRatio() const; - private: + // Set camera sensor size in meters. + // This distinguishes APC-S vs full-frame, etc + void SetSensorSize(RadeonRays::float2 const& size); + RadeonRays::float2 GetSensorSize() const; + + // Get/Set camera volume index + void SetVolume(VolumeMaterial::Ptr shape); + VolumeMaterial::Ptr GetVolume() const; + + protected: // Rotate camera around world Z axis void Rotate(RadeonRays::float3, float angle); + void RotateOnOrbit(RadeonRays::float3, float angle); + + Camera(RadeonRays::float3 const& eye, + RadeonRays::float3 const& at, + RadeonRays::float3 const& up); // Camera coordinate frame RadeonRays::float3 m_forward; RadeonRays::float3 m_right; RadeonRays::float3 m_up; RadeonRays::float3 m_p; + RadeonRays::float3 m_at; // Image plane width & hight in scene units RadeonRays::float2 m_dim; // Near and far Z RadeonRays::float2 m_zcap; + + // Volume index + VolumeMaterial::Ptr m_volume; + }; + + class OrthographicCamera : public Camera + { + public: + using Ptr = std::shared_ptr; + + static Ptr Create(RadeonRays::float3 const& eye, + RadeonRays::float3 const& at, + RadeonRays::float3 const& up); + + ~OrthographicCamera() = default; + + + protected: + OrthographicCamera(RadeonRays::float3 const& eye, + RadeonRays::float3 const& at, + RadeonRays::float3 const& up) + : Camera(eye, at, up) + { + } + }; + + class PerspectiveCamera : public Camera + { + public: + using Ptr = std::shared_ptr; + static Ptr Create(RadeonRays::float3 const& eye, + RadeonRays::float3 const& at, + RadeonRays::float3 const& up); + + + // Set camera focus distance in meters, + // this is essentially a distance from the lens to the focal plane. + // Altering this is similar to rotating the focus ring on real lens. + void SetFocusDistance(float distance); + float GetFocusDistance() const; + // Set camera focal length in meters, + // this is essentially a distance between a camera sensor and a lens. + // Altering this is similar to rotating zoom ring on a lens. + void SetFocalLength(float length); + float GetFocalLength() const; + + // Set aperture value in meters. + // This is a radius of a lens. + void SetAperture(float aperture); + float GetAperture() const; + + protected: + // Pass camera position, camera aim, camera up vector, depth limits, vertical field of view + // and image plane aspect ratio + PerspectiveCamera(RadeonRays::float3 const& eye, + RadeonRays::float3 const& at, + RadeonRays::float3 const& up); + + private: float m_focal_length; - float m_aspect; float m_focus_distance; float m_aperture; friend std::ostream& operator << (std::ostream& o, PerspectiveCamera const& p); }; + inline Camera::~Camera() + { + } + inline void PerspectiveCamera::SetFocusDistance(float distance) { m_focus_distance = distance; @@ -163,26 +208,38 @@ namespace Baikal return m_aperture; } - inline RadeonRays::float2 PerspectiveCamera::GetSensorSize() const + inline RadeonRays::float2 Camera::GetSensorSize() const { return m_dim; } - inline void PerspectiveCamera::SetSensorSize(RadeonRays::float2 const& size) + inline void Camera::SetSensorSize(RadeonRays::float2 const& size) { m_dim = size; SetDirty(true); } - inline void PerspectiveCamera::SetDepthRange(RadeonRays::float2 const& range) + inline void Camera::SetDepthRange(RadeonRays::float2 const& range) { m_zcap = range; SetDirty(true); } - inline RadeonRays::float2 PerspectiveCamera::GetDepthRange() const + inline RadeonRays::float2 Camera::GetDepthRange() const { return m_zcap; } + + inline void Camera::SetVolume(VolumeMaterial::Ptr volume) + { + m_volume = volume; + SetDirty(true); + } + + inline VolumeMaterial::Ptr Camera::GetVolume() const + { + return m_volume; + } + } diff --git a/Baikal/CLW/clwscene.h b/Baikal/SceneGraph/clwscene.h similarity index 61% rename from Baikal/CLW/clwscene.h rename to Baikal/SceneGraph/clwscene.h index 1da424da..b9f07c89 100644 --- a/Baikal/CLW/clwscene.h +++ b/Baikal/SceneGraph/clwscene.h @@ -1,7 +1,7 @@ #pragma once #include "CLW.h" -#include "math/float3.h" +//#include "math/float3.h" #include "SceneGraph/scene1.h" #include "radeon_rays.h" #include "SceneGraph/Collector/collector.h" @@ -13,15 +13,16 @@ namespace Baikal enum class CameraType { - kDefault, - kPhysical, + kPerspective, + kPhysicalPerspective, kSpherical, - kFisheye + kFisheye, + kOrthographic }; struct ClwScene { - #include "CL/payload.cl" + #include "Kernels/CL/payload.cl" CLWBuffer vertices; CLWBuffer normals; @@ -29,21 +30,29 @@ namespace Baikal CLWBuffer indices; CLWBuffer shapes; + CLWBuffer shapes_additional; - CLWBuffer materials; + CLWBuffer material_attributes; CLWBuffer lights; - CLWBuffer materialids; CLWBuffer volumes; CLWBuffer textures; CLWBuffer texturedata; CLWBuffer camera; + CLWBuffer light_distributions; + CLWBuffer input_map_data; std::unique_ptr material_bundle; + std::unique_ptr volume_bundle; std::unique_ptr texture_bundle; + std::unique_ptr input_map_leafs_bundle; + std::unique_ptr input_map_bundle; int num_lights; + int num_volumes; int envmapidx; + int background_idx; + int camera_volume_index; CameraType camera_type; std::vector isect_shapes; diff --git a/Baikal/SceneGraph/inputmap.h b/Baikal/SceneGraph/inputmap.h new file mode 100644 index 00000000..2f83c936 --- /dev/null +++ b/Baikal/SceneGraph/inputmap.h @@ -0,0 +1,86 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ + +#pragma once + +#include +#include "SceneGraph/texture.h" +#include "scene_object.h" + +namespace Baikal +{ + /** + * @brief Base interface for InputMap + * + * Implementation details for each InputMap lays in inputmaps.h file + */ + class InputMap : public SceneObject + { + public: + using Ptr = std::shared_ptr; + enum class InputMapType + { + kConstantFloat3 = 0, // Holds constant float3 value. + kConstantFloat, // Holds constant float value + kSampler, // Samples value from provided texture + kAdd, // a + b + kSub, // a - b + kMul, // a * b + kDiv, // a / b + kSin, // sin(arg) + kCos, // cos(arg) + kTan, // tan(arg) + kSelect, // Selects single component from input arg + kDot3, // dot(a.xyz, b.xyz) + kCross3, // cross(a.xyz, b.xyz) + kLength3, // length(a.xyz) + kNormalize3, // normalize(a.xyz) + kPow, // pow(a, b) + kAcos, // acos(arg) + kAsin, // asin(arg) + kAtan, // atan(arg) + kLerp, // mix (a, b, control) + kMin, // min(a, b) + kMax, // max(a, b) + kFloor, // floor(arg) + kMod, // fmod(a, b) + kAbs, // fabs(arg) + kShuffle, // shuffle(arg, mask) + kShuffle2, // shuffle2(a, b, mask) + kDot4, // dot(a, b) + kCross4, // cross(a, b) + kMatMul, // arg * mat4 + kRemap, // remaps from source range (x->y) to destination range (x->y) + // calculated as mix(float3(dest.x), float3(dest.y), (val - src.x)/(src.y - src.x)) + kSamplerBumpmap // samples normal from bump map texture + }; + InputMapType m_type; + + InputMap(InputMapType t) : SceneObject(), m_type(t) {} + // Collects set of textures from this object and all its inputs + virtual void CollectTextures(std::set &textures) = 0; + // Collects set of leafs from this object and all its inputs + virtual void GetLeafs(std::set &leafs) {}; + // Checks if object is leaf or not + virtual bool IsLeaf() const { return false;} + }; +} diff --git a/Baikal/SceneGraph/inputmaps.h b/Baikal/SceneGraph/inputmaps.h new file mode 100644 index 00000000..13d58d33 --- /dev/null +++ b/Baikal/SceneGraph/inputmaps.h @@ -0,0 +1,625 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ + +#pragma once + +#include "inputmap.h" + +#include +#include + +#include "math/float3.h" +#include "math/matrix.h" + + +namespace Baikal +{ + class InputMap_ConstantFloat3 : public InputMap + { + public: + using Ptr = std::shared_ptr; + static Ptr Create(RadeonRays::float3 value) + { + return Ptr(new InputMap_ConstantFloat3(value)); + } + + void CollectTextures(std::set &textures) override + { + } + + void SetValue(RadeonRays::float3 value) + { + m_value = value; + SetDirty(true); + } + + RadeonRays::float3 GetValue() const + { + return m_value; + } + + bool IsLeaf() const override + { + return true; + } + + private: + RadeonRays::float3 m_value; + + explicit InputMap_ConstantFloat3(RadeonRays::float3 v) : + InputMap(InputMapType::kConstantFloat3), + m_value(v) + { + SetDirty(true); + } + }; + + class InputMap_ConstantFloat : public InputMap + { + public: + using Ptr = std::shared_ptr; + static Ptr Create(float value) + { + return Ptr(new InputMap_ConstantFloat(value)); + } + + void CollectTextures(std::set &textures) override + { + } + + void SetValue(float value) + { + m_value = value; + SetDirty(true); + } + + float GetValue() const + { + return m_value; + } + + bool IsLeaf() const override + { + return true; + } + + private: + float m_value; + + explicit InputMap_ConstantFloat(float v) : + InputMap(InputMapType::kConstantFloat), + m_value(v) + { + SetDirty(true); + } + }; + + class InputMap_Sampler : public InputMap + { + public: + using Ptr = std::shared_ptr; + static Ptr Create(Texture::Ptr texture) + { + return Ptr(new InputMap_Sampler(texture)); + } + + void CollectTextures(std::set &textures) override + { + textures.insert(m_texture); + } + + virtual void SetTexture(Texture::Ptr texture) + { + m_texture = texture; + assert(m_texture); + SetDirty(true); + } + + virtual Texture::Ptr GetTexture() const + { + return m_texture; + } + + bool IsDirty() const override + { + return InputMap::IsDirty() || m_texture->IsDirty(); + } + + bool IsLeaf() const override + { + return true; + } + + protected: + Texture::Ptr m_texture; + + explicit InputMap_Sampler(Texture::Ptr texture) : + InputMap(InputMapType::kSampler), + m_texture(texture) + { + SetDirty(true); + } + }; + + class InputMap_SamplerBumpMap : public InputMap_Sampler + { + public: + using Ptr = std::shared_ptr; + static Ptr Create(Texture::Ptr texture) + { + return Ptr(new InputMap_SamplerBumpMap(texture)); + } + + protected: + explicit InputMap_SamplerBumpMap(Texture::Ptr texture) : + InputMap_Sampler(texture) + { + SetDirty(true); + m_type = InputMapType::kSamplerBumpmap; + } + + }; + + template + class InputMap_TwoArg : public InputMap + { + public: + using Ptr = std::shared_ptr>; + static Ptr Create(InputMap::Ptr a, InputMap::Ptr b) + { + return Ptr(new InputMap_TwoArg(a, b)); + } + + void CollectTextures(std::set &textures) override + { + m_a->CollectTextures(textures); + m_b->CollectTextures(textures); + } + + void SetA(InputMap::Ptr a) + { + m_a = a; + assert(m_a); + SetDirty(true); + } + + void SetB(InputMap::Ptr b) + { + m_b = b; + assert(m_b); + SetDirty(true); + } + + InputMap::Ptr GetA() const + { + return m_a; + } + + InputMap::Ptr GetB() const + { + return m_b; + } + + bool IsDirty() const override + { + return InputMap::IsDirty() || m_a->IsDirty() || m_b->IsDirty(); + } + + void SetDirty(bool dirty) const override + { + SceneObject::SetDirty(dirty); + m_a->SetDirty(dirty); + m_b->SetDirty(dirty); + } + + void GetLeafs(std::set & leafs) override + { + if (m_a->IsLeaf()) leafs.insert(m_a); + else m_a->GetLeafs(leafs); + + if (m_b->IsLeaf()) leafs.insert(m_b); + else m_b->GetLeafs(leafs); + } + + + protected: + InputMap::Ptr m_a; + InputMap::Ptr m_b; + + InputMap_TwoArg(InputMap::Ptr a, InputMap::Ptr b) : + InputMap(type), + m_a(a), + m_b(b) + { + assert(m_a && m_b); + SetDirty(true); + } + }; + + typedef InputMap_TwoArg InputMap_Add; + typedef InputMap_TwoArg InputMap_Sub; + typedef InputMap_TwoArg InputMap_Mul; + typedef InputMap_TwoArg InputMap_Div; + typedef InputMap_TwoArg InputMap_Min; + typedef InputMap_TwoArg InputMap_Max; + typedef InputMap_TwoArg InputMap_Dot3; + typedef InputMap_TwoArg InputMap_Cross3; + typedef InputMap_TwoArg InputMap_Dot4; + typedef InputMap_TwoArg InputMap_Cross4; + typedef InputMap_TwoArg InputMap_Pow; + typedef InputMap_TwoArg InputMap_Mod; + + template + class InputMap_OneArg : public InputMap + { + public: + using Ptr = std::shared_ptr>; + static Ptr Create(InputMap::Ptr arg) + { + return Ptr(new InputMap_OneArg(arg)); + } + + void CollectTextures(std::set &textures) override + { + m_arg->CollectTextures(textures); + } + + void SetArg(InputMap::Ptr arg) + { + m_arg = arg; + assert(m_arg); + SetDirty(true); + } + + InputMap::Ptr GetArg() const + { + return m_arg; + } + + bool IsDirty() const override + { + return InputMap::IsDirty() || m_arg->IsDirty(); + } + + void GetLeafs(std::set & leafs) override + { + if (m_arg->IsLeaf()) leafs.insert(m_arg); + else m_arg->GetLeafs(leafs); + } + + void SetDirty(bool dirty) const override + { + SceneObject::SetDirty(dirty); + m_arg->SetDirty(dirty); + } + + protected: + InputMap::Ptr m_arg; + + InputMap_OneArg(InputMap::Ptr arg) : + InputMap(type), + m_arg(arg) + { + assert(m_arg); + SetDirty(true); + } + }; + + typedef InputMap_OneArg InputMap_Sin; + typedef InputMap_OneArg InputMap_Cos; + typedef InputMap_OneArg InputMap_Tan; + typedef InputMap_OneArg InputMap_Asin; + typedef InputMap_OneArg InputMap_Acos; + typedef InputMap_OneArg InputMap_Atan; + typedef InputMap_OneArg InputMap_Length3; + typedef InputMap_OneArg InputMap_Normalize3; + typedef InputMap_OneArg InputMap_Floor; + typedef InputMap_OneArg InputMap_Abs; + + class InputMap_Lerp : public InputMap_TwoArg + { + public: + using Ptr = std::shared_ptr; + static Ptr Create(InputMap::Ptr a, InputMap::Ptr b, InputMap::Ptr control) + { + return Ptr(new InputMap_Lerp(a, b, control)); + } + + void SetControl(InputMap::Ptr control) + { + m_control = control; + assert(m_control); + SetDirty(true); + } + + InputMap::Ptr GetControl() const + { + return m_control; + } + + void CollectTextures(std::set &textures) override + { + InputMap_TwoArg::CollectTextures(textures); + m_control->CollectTextures(textures); + } + + bool IsDirty() const override + { + return InputMap_TwoArg::IsDirty() || m_control->IsDirty(); + } + + void GetLeafs(std::set & leafs) override + { + InputMap_TwoArg::GetLeafs(leafs); + if (m_control->IsLeaf()) leafs.insert(m_control); + else m_control->GetLeafs(leafs); + } + + void SetDirty(bool dirty) const override + { + InputMap_TwoArg::SetDirty(dirty); + m_control->SetDirty(dirty); + } + + + private: + InputMap::Ptr m_control; + + InputMap_Lerp(InputMap::Ptr a, InputMap::Ptr b, InputMap::Ptr control) : + InputMap_TwoArg(a, b), + m_control(control) + { + assert(m_control); + SetDirty(true); + } + }; + + class InputMap_Select : public InputMap_OneArg + { + public: + using Ptr = std::shared_ptr; + enum class Selection + { + kX = 0, + kY = 1, + kZ = 2, + kW = 3 + }; + static Ptr Create(InputMap::Ptr arg, Selection selection) + { + return Ptr(new InputMap_Select(arg, selection)); + } + + void SetSelection(Selection selection) + { + m_selection = selection; + SetDirty(true); + } + + Selection GetSelection() const + { + return m_selection; + } + + private: + Selection m_selection; + + InputMap_Select(InputMap::Ptr arg, Selection selection) : + InputMap_OneArg(arg), + m_selection(selection) + { + SetDirty(true); + } + }; + + class InputMap_Shuffle : public InputMap_OneArg + { + public: + using Ptr = std::shared_ptr; + static Ptr Create(InputMap::Ptr arg, const std::array &mask) + { + return Ptr(new InputMap_Shuffle(arg, mask)); + } + + void SetMask(const std::array &mask) + { + m_mask = mask; + SetDirty(true); + } + + std::array GetMask() const + { + return m_mask; + } + + + private: + std::array m_mask; + + InputMap_Shuffle(InputMap::Ptr arg, const std::array &mask) : + InputMap_OneArg(arg), + m_mask(mask) + { + SetDirty(true); + } + }; + + class InputMap_Shuffle2 : public InputMap_TwoArg + { + public: + using Ptr = std::shared_ptr; + static Ptr Create(InputMap::Ptr a, InputMap::Ptr b, const std::array &mask) + { + return Ptr(new InputMap_Shuffle2(a, b, mask)); + } + + void SetMask(const std::array &mask) + { + m_mask = mask; + SetDirty(true); + } + + std::array GetMask() const + { + return m_mask; + } + + private: + std::array m_mask; + + InputMap_Shuffle2(InputMap::Ptr a, InputMap::Ptr b, const std::array &mask) : + InputMap_TwoArg(a, b), + m_mask(mask) + { + SetDirty(true); + } + }; + + class InputMap_MatMul : public InputMap_OneArg + { + public: + using Ptr = std::shared_ptr; + static Ptr Create(InputMap::Ptr arg, const RadeonRays::matrix &mat4) + { + return Ptr(new InputMap_MatMul(arg, mat4)); + } + + void SetMatrix(const RadeonRays::matrix &mat4) + { + m_mat4 = mat4; + SetDirty(true); + } + + RadeonRays::matrix GetMatrix() const + { + return m_mat4; + } + + private: + RadeonRays::matrix m_mat4; + + InputMap_MatMul(InputMap::Ptr arg, const RadeonRays::matrix &mat4) : + InputMap_OneArg(arg), + m_mat4(mat4) + { + SetDirty(true); + } + }; + + class InputMap_Remap : public InputMap + { + public: + using Ptr = std::shared_ptr; + static Ptr Create(InputMap::Ptr source_range, InputMap::Ptr destination_range, + InputMap::Ptr data) + { + return Ptr(new InputMap_Remap(source_range, destination_range, data)); + } + + void CollectTextures(std::set &textures) override + { + m_source_range->CollectTextures(textures); + m_destination_range->CollectTextures(textures); + m_data->CollectTextures(textures); + } + + void SetSourceRange(InputMap::Ptr source_range) + { + m_source_range = source_range; + assert(m_source_range); + SetDirty(true); + } + + void SetDestinationRange(InputMap::Ptr destination_range) + { + m_destination_range = destination_range; + assert(m_destination_range); + SetDirty(true); + } + + InputMap::Ptr GetSourceRange() const + { + return m_source_range; + } + + InputMap::Ptr GetDestinationRange() const + { + return m_destination_range; + } + + void SetData(InputMap::Ptr data) + { + m_data = data; + assert(m_data); + SetDirty(true); + } + + InputMap::Ptr GetData() const + { + return m_data; + } + + bool IsDirty() const override + { + return InputMap::IsDirty() || m_source_range->IsDirty() || + m_destination_range->IsDirty() || m_data->IsDirty(); + } + + void SetDirty(bool dirty) const override + { + SceneObject::SetDirty(dirty); + m_source_range->SetDirty(dirty); + m_destination_range->SetDirty(dirty); + m_data->SetDirty(dirty); + } + + void GetLeafs(std::set & leafs) override + { + if (m_source_range->IsLeaf()) leafs.insert(m_source_range); + else m_source_range->GetLeafs(leafs); + + if (m_destination_range->IsLeaf()) leafs.insert(m_destination_range); + else m_destination_range->GetLeafs(leafs); + + if (m_data->IsLeaf()) leafs.insert(m_data); + else m_data->GetLeafs(leafs); + } + + + private: + InputMap::Ptr m_source_range; + InputMap::Ptr m_destination_range; + InputMap::Ptr m_data; + + InputMap_Remap(InputMap::Ptr source_range, InputMap::Ptr destination_range, + InputMap::Ptr data) : + InputMap(InputMapType::kRemap), + m_source_range(source_range), + m_destination_range(destination_range), + m_data(data) + { + SetDirty(true); + assert(m_source_range && m_destination_range && m_data); + } + }; + +} diff --git a/Baikal/SceneGraph/iterator.h b/Baikal/SceneGraph/iterator.h index fbd48fe5..780c066c 100644 --- a/Baikal/SceneGraph/iterator.h +++ b/Baikal/SceneGraph/iterator.h @@ -27,6 +27,8 @@ \version 1.0 \brief Contains declaration of Baikal object iterators. */ +#include "scene_object.h" + namespace Baikal { /** @@ -49,13 +51,13 @@ namespace Baikal virtual void Next() = 0; // Retrieve underlying object - virtual void const* Item() const = 0; + virtual SceneObject::Ptr Item() const = 0; // Sets the iterator into its initial state (beginning of the sequence) virtual void Reset() = 0; // Retrieve with uncoditional cast: caller is responsible of all the implications, no type check here - template T* ItemAs() const { return reinterpret_cast(Item()); } + template typename T::Ptr ItemAs() const { return std::static_pointer_cast(Item()); } // Disable copies and moves Iterator(Iterator const&) = delete; @@ -80,7 +82,7 @@ namespace Baikal // Nothing to go to void Next() override {} // Dereferencing always returns nullptr - void const* Item() const override { return nullptr; } + SceneObject::Ptr Item() const override { return nullptr; } // Nothing to reset void Reset() override {} }; @@ -114,7 +116,7 @@ namespace Baikal } // Get underlying item - void const* Item() const override + SceneObject::Ptr Item() const override { return *m_cur; } @@ -155,7 +157,7 @@ namespace Baikal } // Get underlying item - void const* Item() const override + SceneObject::Ptr Item() const override { return *m_cur; } diff --git a/Baikal/SceneGraph/light.cpp b/Baikal/SceneGraph/light.cpp new file mode 100644 index 00000000..c6d1b228 --- /dev/null +++ b/Baikal/SceneGraph/light.cpp @@ -0,0 +1,296 @@ +#include "light.h" +#include "SceneGraph/scene1.h" +#include "SceneGraph/texture.h" + +namespace Baikal +{ + AreaLight::AreaLight(Shape::Ptr shape, std::size_t idx) + : m_shape(shape) + , m_prim_idx(idx) + { + } + + RadeonRays::float3 Light::GetPosition() const + { + return m_p; + } + + void Light::SetPosition(RadeonRays::float3 const& p) + { + m_p = p; + SetDirty(true); + } + + RadeonRays::float3 Light::GetDirection() const + { + return m_d; + } + + void Light::SetDirection(RadeonRays::float3 const& d) + { + m_d = normalize(d); + SetDirty(true); + } + + std::unique_ptr Light::CreateTextureIterator() const + { + return std::make_unique(); + } + + RadeonRays::float3 Light::GetEmittedRadiance() const + { + return m_e; + } + + void Light::SetEmittedRadiance(RadeonRays::float3 const& e) + { + m_e = e; + SetDirty(true); + } + + void SpotLight::SetConeShape(RadeonRays::float2 angles) + { + m_angles = angles; + SetDirty(true); + } + + RadeonRays::float2 SpotLight::GetConeShape() const + { + return m_angles; + } + + void ImageBasedLight::SetTexture(Texture::Ptr texture) + { + m_texture = texture; + SetDirty(true); + } + + Texture::Ptr ImageBasedLight::GetTexture() const + { + return m_texture; + } + + std::size_t AreaLight::GetPrimitiveIdx() const + { + return m_prim_idx; + } + + Shape::Ptr AreaLight::GetShape() const + { + return m_shape; + } + + ImageBasedLight::ImageBasedLight() + : m_texture(nullptr) + , m_reflection_texture(nullptr) + , m_refraction_texture(nullptr) + , m_transparency_texture(nullptr) + , m_background_texture(nullptr) + , m_multiplier(1.f) + , mirror_x_(false) + { + } + + float ImageBasedLight::GetMultiplier() const + { + return m_multiplier; + } + + void ImageBasedLight::SetMultiplier(float m) + { + m_multiplier = m; + SetDirty(true); + } + + + void ImageBasedLight::SetReflectionTexture(Texture::Ptr texture) + { + m_reflection_texture = texture; + SetDirty(true); + } + + Texture::Ptr ImageBasedLight::GetReflectionTexture() const + { + return m_reflection_texture; + } + + void ImageBasedLight::SetRefractionTexture(Texture::Ptr texture) + { + m_refraction_texture = texture; + SetDirty(true); + } + + Texture::Ptr ImageBasedLight::GetRefractionTexture() const + { + return m_refraction_texture; + } + + void ImageBasedLight::SetTransparencyTexture(Texture::Ptr texture) + { + m_transparency_texture = texture; + SetDirty(true); + } + + Texture::Ptr ImageBasedLight::GetTransparencyTexture() const + { + return m_transparency_texture; + } + + void ImageBasedLight::SetBackgroundTexture(Texture::Ptr texture) + { + m_background_texture = texture; + SetDirty(true); + } + + Texture::Ptr ImageBasedLight::GetBackgroundTexture() const + { + return m_background_texture; + } + + std::unique_ptr ImageBasedLight::CreateTextureIterator() const + { + std::set result; + + if (m_texture) + { + result.insert(m_texture); + } + + if (m_reflection_texture) + { + result.insert(m_reflection_texture); + } + + if (m_refraction_texture) + { + result.insert(m_refraction_texture); + } + + if (m_transparency_texture) + { + result.insert(m_transparency_texture); + } + + if (m_background_texture) + { + result.insert(m_background_texture); + } + + return std::make_unique>>(std::move(result)); + } + + + RadeonRays::float3 PointLight::GetPower(Scene1 const& scene) const + { + return 4.f * PI * GetEmittedRadiance(); + } + + RadeonRays::float3 SpotLight::GetPower(Scene1 const& scene) const + { + auto cone = GetConeShape(); + return 2.f * PI * GetEmittedRadiance() * (1.f - 0.5f * (cone.x + cone.y)); + } + + RadeonRays::float3 DirectionalLight::GetPower(Scene1 const& scene) const + { + auto scene_radius = scene.GetRadius(); + return PI * GetEmittedRadiance() * scene_radius * scene_radius; + } + + RadeonRays::float3 ImageBasedLight::GetPower(Scene1 const& scene) const + { + auto scene_radius = scene.GetRadius(); + auto avg = RadeonRays::float3(); + auto cnt = 0u; + if (m_texture) + { + avg += m_texture->ComputeAverageValue(); + ++cnt; + } + + if (m_reflection_texture) + { + avg += m_reflection_texture->ComputeAverageValue(); + ++cnt; + } + + if (m_refraction_texture) + { + avg += m_refraction_texture->ComputeAverageValue(); + ++cnt; + } + + if (m_transparency_texture) + { + avg += m_transparency_texture->ComputeAverageValue(); + ++cnt; + } + + // We do not count background texture here since it is only for missing primary rays + return PI * avg * (1.f / cnt) * scene_radius * scene_radius; + } + + void ImageBasedLight::SetMirrorX(bool mirror_x) + { + mirror_x_ = mirror_x; + } + + bool ImageBasedLight::GetMirrorX() const + { + return mirror_x_; + } + + + RadeonRays::float3 AreaLight::GetPower(Scene1 const& scene) const + { + auto mesh = std::static_pointer_cast(m_shape); + auto indices = mesh->GetIndices(); + auto vertices = mesh->GetVertices(); + + auto i0 = indices[m_prim_idx * 3]; + auto i1 = indices[m_prim_idx * 3 + 1]; + auto i2 = indices[m_prim_idx * 3 + 2]; + + auto v0 = vertices[i0]; + auto v1 = vertices[i1]; + auto v2 = vertices[i2]; + + float area = 0.5f * std::sqrt(cross(v2 - v0, v1 - v0).sqnorm()); + return PI * GetEmittedRadiance() * area; + } + + namespace { + struct PointLightConcrete : public PointLight { + }; + struct DirectionalLightConcrete : public DirectionalLight { + }; + struct SpotLightConcrete : public SpotLight { + }; + struct ImageBasedLightConcrete: public ImageBasedLight { + }; + struct AreaLightConcrete: public AreaLight { + AreaLightConcrete(Shape::Ptr shape, std::size_t idx) : + AreaLight(shape, idx) {} + }; + } + + PointLight::Ptr PointLight::Create() { + return std::make_shared(); + } + + DirectionalLight::Ptr DirectionalLight::Create() { + return std::make_shared(); + } + + SpotLight::Ptr SpotLight::Create() { + return std::make_shared(); + } + + ImageBasedLight::Ptr ImageBasedLight::Create() { + return std::make_shared(); + } + + AreaLight::Ptr AreaLight::Create(Shape::Ptr shape, std::size_t idx) { + return std::make_shared(shape, idx); + } +} diff --git a/Baikal/SceneGraph/light.h b/Baikal/SceneGraph/light.h index 04b9139c..9071d868 100644 --- a/Baikal/SceneGraph/light.h +++ b/Baikal/SceneGraph/light.h @@ -30,6 +30,7 @@ #include "math/float3.h" #include "math/float2.h" +#include "math/mathutils.h" #include #include #include @@ -38,11 +39,12 @@ #include "scene_object.h" #include "shape.h" +#include "texture.h" namespace Baikal { - class Texture; - + class Scene1; + /** \brief Light base interface. @@ -51,28 +53,34 @@ namespace Baikal class Light : public SceneObject { public: - // Constructor - Light(); + using Ptr = std::shared_ptr; + // Destructor virtual ~Light() = 0; - + // Get total radiant power (integral) //virtual RadeonRays::float3 GetRadiantPower() const = 0; - + // Set and get position RadeonRays::float3 GetPosition() const; void SetPosition(RadeonRays::float3 const& p); - + // Set and get direction RadeonRays::float3 GetDirection() const; void SetDirection(RadeonRays::float3 const& d); - + // Set and get emitted radiance (differential) RadeonRays::float3 GetEmittedRadiance() const; void SetEmittedRadiance(RadeonRays::float3 const& e); - + // Iterator for all the textures used by the light - virtual Iterator* CreateTextureIterator() const; + virtual std::unique_ptr CreateTextureIterator() const; + + virtual RadeonRays::float3 GetPower(Scene1 const& scene) const = 0; + + protected: + // Constructor + Light(); private: // Position @@ -101,6 +109,14 @@ namespace Baikal class PointLight: public Light { public: + using Ptr = std::shared_ptr; + static Ptr Create(); + + RadeonRays::float3 GetPower(Scene1 const& scene) const override; + + protected: + PointLight(){} + }; /** @@ -111,6 +127,13 @@ namespace Baikal class DirectionalLight: public Light { public: + using Ptr = std::shared_ptr; + static Ptr Create(); + + RadeonRays::float3 GetPower(Scene1 const& scene) const override; + + protected: + DirectionalLight(){} }; /** @@ -121,11 +144,18 @@ namespace Baikal class SpotLight: public Light { public: - SpotLight(); + using Ptr = std::shared_ptr; + static Ptr Create(); + // Get and set inner and outer falloff angles: they are set as cosines of angles between light direction // and cone opening. void SetConeShape(RadeonRays::float2 angles); RadeonRays::float2 GetConeShape() const; + + RadeonRays::float3 GetPower(Scene1 const& scene) const override; + + protected: + SpotLight(); private: // Opening angles (x - inner, y - outer) @@ -145,145 +175,74 @@ namespace Baikal class ImageBasedLight: public Light { public: - ImageBasedLight(); + using Ptr = std::shared_ptr; + static Ptr Create(); + // Get and set illuminant texture - void SetTexture(Texture const* texture); - Texture const* GetTexture() const; - + void SetTexture(Texture::Ptr texture); + Texture::Ptr GetTexture() const; + + void SetReflectionTexture(Texture::Ptr texture); + Texture::Ptr GetReflectionTexture() const; + + void SetRefractionTexture(Texture::Ptr texture); + Texture::Ptr GetRefractionTexture() const; + + void SetTransparencyTexture(Texture::Ptr texture); + Texture::Ptr GetTransparencyTexture() const; + + void SetBackgroundTexture(Texture::Ptr texture); + Texture::Ptr GetBackgroundTexture() const; + // Get and set multiplier. // Multiplier is used to adjust emissive power. float GetMultiplier() const; void SetMultiplier(float m); - + // Iterator for all the textures used by the light - Iterator* CreateTextureIterator() const override; + std::unique_ptr CreateTextureIterator() const override; + RadeonRays::float3 GetPower(Scene1 const& scene) const override; + + // Get and set mirror status for texture around Y axis. (switch X axis direction) + void SetMirrorX(bool mirror_x); + bool GetMirrorX() const; + protected: + ImageBasedLight(); + private: // Illuminant texture - Texture const* m_texture; + Texture::Ptr m_texture; + Texture::Ptr m_reflection_texture; + Texture::Ptr m_refraction_texture; + Texture::Ptr m_transparency_texture; + Texture::Ptr m_background_texture; // Emissive multiplier float m_multiplier; + bool mirror_x_; }; // Area light class AreaLight: public Light { public: - AreaLight(Shape const* shape, std::size_t idx); + using Ptr = std::shared_ptr; + static Ptr Create(Shape::Ptr shape, std::size_t idx); + // Get parent shape - Shape const* GetShape() const; + Shape::Ptr GetShape() const; // Get parent prim idx std::size_t GetPrimitiveIdx() const; - + + RadeonRays::float3 GetPower(Scene1 const& scene) const override; + + protected: + AreaLight(Shape::Ptr shape, std::size_t idx); + private: // Parent shape - Shape const* m_shape; + Shape::Ptr m_shape; // Parent primitive index std::size_t m_prim_idx; }; - - inline AreaLight::AreaLight(Shape const* shape, std::size_t idx) - : m_shape(shape) - , m_prim_idx(idx) - { - } - - inline RadeonRays::float3 Light::GetPosition() const - { - return m_p; - } - - inline void Light::SetPosition(RadeonRays::float3 const& p) - { - m_p = p; - SetDirty(true); - } - - inline RadeonRays::float3 Light::GetDirection() const - { - return m_d; - } - - inline void Light::SetDirection(RadeonRays::float3 const& d) - { - m_d = normalize(d); - SetDirty(true); - } - - inline Iterator* Light::CreateTextureIterator() const - { - return new EmptyIterator(); - } - - inline RadeonRays::float3 Light::GetEmittedRadiance() const - { - return m_e; - } - - inline void Light::SetEmittedRadiance(RadeonRays::float3 const& e) - { - m_e = e; - SetDirty(true); - } - - inline void SpotLight::SetConeShape(RadeonRays::float2 angles) - { - m_angles = angles; - SetDirty(true); - } - - inline RadeonRays::float2 SpotLight::GetConeShape() const - { - return m_angles; - } - - inline void ImageBasedLight::SetTexture(Texture const* texture) - { - m_texture = texture; - SetDirty(true); - } - - inline Texture const* ImageBasedLight::GetTexture() const - { - return m_texture; - } - - inline std::size_t AreaLight::GetPrimitiveIdx() const - { - return m_prim_idx; - } - - inline Shape const* AreaLight::GetShape() const - { - return m_shape; - } - - inline ImageBasedLight::ImageBasedLight() - : m_texture(nullptr) - , m_multiplier(1.f) - { - } - - inline float ImageBasedLight::GetMultiplier() const - { - return m_multiplier; - } - - inline void ImageBasedLight::SetMultiplier(float m) - { - m_multiplier = m; - SetDirty(true); - } - - inline Iterator* ImageBasedLight::CreateTextureIterator() const - { - std::set result; - - if (m_texture) - { - result.insert(m_texture); - } - - return new ContainerIterator>(std::move(result)); - } } diff --git a/Baikal/SceneGraph/material.cpp b/Baikal/SceneGraph/material.cpp index d3f46b95..5b1a1203 100644 --- a/Baikal/SceneGraph/material.cpp +++ b/Baikal/SceneGraph/material.cpp @@ -2,66 +2,25 @@ #include "iterator.h" #include +#include namespace Baikal { - class Material::InputIterator : public Iterator - { - public: - - InputIterator(InputMap::const_iterator begin, InputMap::const_iterator end) - : m_begin(begin) - , m_end(end) - { - Reset(); - } - - // Check if we reached end - bool IsValid() const override - { - return m_cur != m_end; - } - - // Advance by 1 - void Next() override - { - ++m_cur; - } - - // Set to starting iterator - void Reset() override - { - m_cur = m_begin; - } - - // Get underlying item - void const* Item() const override - { - return &m_cur->second; - } - - private: - InputMap::const_iterator m_begin; - InputMap::const_iterator m_end; - InputMap::const_iterator m_cur; - }; - - - - Material::Material() : m_thin(false) { } - - void Material::RegisterInput(std::string const& name, std::string const& desc, std::set&& supported_types) + + void Material::RegisterInput(std::string const& name, + std::string const& desc, + std::set&& supported_types) { - Input input = {{name, desc, std::move(supported_types)}}; - + Input input {{name, desc, std::move(supported_types)}, InputValue()}; + assert(input.info.supported_types.size() > 0); - + input.value.type = *input.info.supported_types.begin(); - + switch (input.value.type) { case InputType::kFloat4: @@ -73,24 +32,26 @@ namespace Baikal case InputType::kMaterial: input.value.mat_value = nullptr; break; + case InputType::kInputMap: + input.value.input_map_value = nullptr; default: break; } - + m_inputs.emplace(std::make_pair(name, input)); } - + void Material::ClearInputs() { m_inputs.clear(); } - + // Iterator of dependent materials (plugged as inputs) - Iterator* Material::CreateMaterialIterator() const + std::unique_ptr Material::CreateMaterialIterator() const { - std::set materials; - + std::set materials; + std::for_each(m_inputs.cbegin(), m_inputs.cend(), [&materials](std::pair const& map_entry) { @@ -101,15 +62,15 @@ namespace Baikal } } ); - - return new ContainerIterator>(std::move(materials)); + + return std::make_unique>>(std::move(materials)); } - + // Iterator of textures (plugged as inputs) - Iterator* Material::CreateTextureIterator() const + std::unique_ptr Material::CreateTextureIterator() const { - std::set textures; - + std::set textures; + std::for_each(m_inputs.cbegin(), m_inputs.cend(), [&textures](std::pair const& map_entry) { @@ -118,103 +79,123 @@ namespace Baikal { textures.insert(map_entry.second.value.tex_value); } + else if (map_entry.second.value.type == InputType::kInputMap) + { + map_entry.second.value.input_map_value->CollectTextures(textures); + } } ); - - return new ContainerIterator>(std::move(textures)); - } - - // Iterator of inputs - Iterator* Material::CreateInputIterator() const - { - return new InputIterator(m_inputs.cbegin(), m_inputs.cend()); + + return std::make_unique>>(std::move(textures)); } - - // Set input value - // If specific data type is not supported throws std::runtime_error - void Material::SetInputValue(std::string const& name, RadeonRays::float4 const& value) + + // Iterator of InputMaps + std::unique_ptr Material::CreateInputMapsIterator() const { - auto input_iter = m_inputs.find(name); - - if (input_iter != m_inputs.cend()) + std::set input_maps; + + for (auto &input : m_inputs) { - auto& input = input_iter->second; - - if (input.info.supported_types.find(InputType::kFloat4) != input.info.supported_types.cend()) + if (IsActive(input.second) && (input.second.value.type == InputType::kInputMap)) { - input.value.type = InputType::kFloat4; - input.value.float_value = value; - SetDirty(true); - } - else - { - throw std::runtime_error("Input type not supported"); + input_maps.insert(input.second.value.input_map_value); } } - else - { - throw std::runtime_error("No such input"); - } + + return std::make_unique>>(std::move(input_maps)); } - - void Material::SetInputValue(std::string const& name, Texture const* texture) + + // Iterator of InputMap leafs + std::unique_ptr Material::CreateInputMapLeafsIterator() const { - auto input_iter = m_inputs.find(name); - - if (input_iter != m_inputs.cend()) + std::set input_maps; + + for (auto &input : m_inputs) { - auto& input = input_iter->second; - - if (input.info.supported_types.find(InputType::kTexture) != input.info.supported_types.cend()) - { - input.value.type = InputType::kTexture; - input.value.tex_value = texture; - SetDirty(true); - } - else + if ((input.second.value.type == InputType::kInputMap) && IsActive(input.second)) { - throw std::runtime_error("Input type not supported"); + if (!input.second.value.input_map_value->IsLeaf()) + { + input.second.value.input_map_value->GetLeafs(input_maps); + } + else + { + input_maps.insert(input.second.value.input_map_value); + } } } - else - { - throw std::runtime_error("No such input"); - } + + return std::make_unique>>(std::move(input_maps)); } - - void Material::SetInputValue(std::string const& name, Material const* material) + + // Set input value + // If specific data type is not supported throws std::runtime_error + + Material::Input& Material::GetInput(const std::string& name, InputType type) { auto input_iter = m_inputs.find(name); - - if (input_iter != m_inputs.cend()) + if (input_iter == m_inputs.cend()) { - auto& input = input_iter->second; - - if (input.info.supported_types.find(InputType::kMaterial) != input.info.supported_types.cend()) - { - input.value.type = InputType::kMaterial; - input.value.mat_value = material; - SetDirty(true); - } - else - { - throw std::runtime_error("Input type not supported"); - } + throw std::runtime_error("No such input"); } - else + + auto& input = input_iter->second; + if (input.info.supported_types.find(type) == input.info.supported_types.cend()) { - throw std::runtime_error("No such input"); + throw std::runtime_error("Input type not supported"); } + + return input; + } + + void Material::SetInputValue(std::string const& name, uint32_t value) + { + auto& input = GetInput(name, InputType::kUint); + input.value.type = InputType::kUint; + input.value.uint_value = value; + SetDirty(true); + } + + void Material::SetInputValue(std::string const& name, RadeonRays::float4 const& value) + { + auto& input = GetInput(name, InputType::kFloat4); + input.value.type = InputType::kFloat4; + input.value.float_value = value; + SetDirty(true); + } + + void Material::SetInputValue(std::string const& name, Texture::Ptr texture) + { + auto& input = GetInput(name, InputType::kTexture); + input.value.type = InputType::kTexture; + input.value.tex_value = texture; + SetDirty(true); + } + + void Material::SetInputValue(std::string const& name, Material::Ptr material) + { + auto& input = GetInput(name, InputType::kMaterial); + input.value.type = InputType::kMaterial; + input.value.mat_value = material; + SetDirty(true); } - + + void Material::SetInputValue(std::string const& name, Baikal::InputMap::Ptr inputMap) + { + auto& input = GetInput(name, InputType::kInputMap); + input.value.type = InputType::kInputMap; + input.value.input_map_value = inputMap; + SetDirty(true); + } + Material::InputValue Material::GetInputValue(std::string const& name) const { auto input_iter = m_inputs.find(name); - + if (input_iter != m_inputs.cend()) { auto& input = input_iter->second; - + return input.value; } else @@ -227,76 +208,57 @@ namespace Baikal { return m_thin; } - + void Material::SetThin(bool thin) { m_thin = thin; SetDirty(true); } - SingleBxdf::SingleBxdf(BxdfType type) - : m_type(type) - { - RegisterInput("albedo", "Diffuse color", {InputType::kFloat4, InputType::kTexture}); - RegisterInput("normal", "Normal map", {InputType::kTexture}); - RegisterInput("bump", "Bump map", { InputType::kTexture }); - RegisterInput("ior", "Index of refraction", {InputType::kFloat4}); - RegisterInput("fresnel", "Fresnel flag", {InputType::kFloat4}); - RegisterInput("roughness", "Roughness", {InputType::kFloat4, InputType::kTexture}); - - SetInputValue("albedo", RadeonRays::float4(0.7f, 0.7f, 0.7f, 1.f)); - SetInputValue("normal", static_cast(nullptr)); - SetInputValue("bump", static_cast(nullptr)); - } - - SingleBxdf::BxdfType SingleBxdf::GetBxdfType() const - { - return m_type; - } - - void SingleBxdf::SetBxdfType(BxdfType type) + size_t Material::GetNumInputs() const { - m_type = type; - SetDirty(true); + return m_inputs.size(); } - bool SingleBxdf::HasEmission() const - { - return m_type == BxdfType::kEmissive; - } - - MultiBxdf::MultiBxdf(Type type) - : m_type(type) - { - RegisterInput("base_material", "Base material", {InputType::kMaterial}); - RegisterInput("top_material", "Top material", {InputType::kMaterial}); - RegisterInput("ior", "Index of refraction", {InputType::kFloat4}); - RegisterInput("weight", "Blend weight", {InputType::kFloat4, InputType::kTexture}); - } - - MultiBxdf::Type MultiBxdf::GetType() const - { - return m_type; - } - - void MultiBxdf::SetType(Type type) + Material::Input Material::GetInput(std::size_t idx) const { - m_type = type; - SetDirty(true); + if (idx >= GetNumInputs()) + throw std::logic_error( + "Material::GitInputByIndex(...): idx can not be bigger than number of inputs"); + + auto iter = m_inputs.begin(); + for (std::size_t i = 0; i < idx; i++) + ++iter; + + return iter->second; } - bool MultiBxdf::HasEmission() const + // VolumeMaterial implementation + VolumeMaterial::VolumeMaterial() { - InputValue base = GetInputValue("base_material"); - InputValue top = GetInputValue("base_material"); + RegisterInput("absorption", "Absorption of volume material", { InputType::kFloat4, InputType::kTexture }); + RegisterInput("scattering", "Scattering of light inside of volume material", { InputType::kFloat4, InputType::kTexture }); + RegisterInput("emission", "Emission of light inside of volume material", { InputType::kFloat4, InputType::kTexture }); + RegisterInput("g", "Phase function", { InputType::kFloat4 }); - if (base.mat_value && base.mat_value->HasEmission()) - return true; - if (top.mat_value && top.mat_value->HasEmission()) - return true; + SetInputValue("absorption", RadeonRays::float4(.0f, .0f, .0f, .0f)); + SetInputValue("scattering", RadeonRays::float4(.0f, .0f, .0f, .0f)); + SetInputValue("emission", RadeonRays::float4(.0f, .0f, .0f, .0f)); + SetInputValue("g", RadeonRays::float4(.0f, .0f, .0f, .0f)); + } - return false; + // Check if material has emissive components + bool VolumeMaterial::HasEmission() const + { + return (GetInputValue("emission").float_value.sqnorm() != 0); } + namespace { + struct VolumeMaterialConcrete : public VolumeMaterial { + }; + } + VolumeMaterial::Ptr VolumeMaterial::Create() { + return std::make_shared(); + } } diff --git a/Baikal/SceneGraph/material.h b/Baikal/SceneGraph/material.h index baebd82a..b0d6783d 100644 --- a/Baikal/SceneGraph/material.h +++ b/Baikal/SceneGraph/material.h @@ -1,16 +1,16 @@ /********************************************************************** Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. - + 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 @@ -29,13 +29,15 @@ #pragma once #include -#include +#include #include #include #include "math/float3.h" #include "scene_object.h" +#include "texture.h" +#include "inputmap.h" namespace Baikal { @@ -44,18 +46,24 @@ namespace Baikal /** \brief High level material interface - + \details Base class for all CPU side material supported by the renderer. */ class Material : public SceneObject { public: + using Ptr = std::shared_ptr; + + friend class MaterialAccessor; + // Material input type enum class InputType { + kUint = 0, kFloat4, kTexture, - kMaterial + kMaterial, + kInputMap }; // Input description @@ -70,18 +78,26 @@ namespace Baikal }; // Input value description - struct InputValue - { + struct InputValue { // Current type InputType type; - + // Possible values (use based on type) - union + uint32_t uint_value; + RadeonRays::float4 float_value; + Texture::Ptr tex_value; + Material::Ptr mat_value; + InputMap::Ptr input_map_value; + + InputValue() + : type(InputType::kMaterial) + , uint_value() + , float_value() + , tex_value(nullptr) + , mat_value(nullptr) + , input_map_value(nullptr) { - RadeonRays::float4 float_value; - Texture const* tex_value; - Material const* mat_value; - }; + } }; // Full input state @@ -91,47 +107,67 @@ namespace Baikal InputValue value; }; - // Constructor - Material(); + using InputMap = std::unordered_map; + // Destructor virtual ~Material() = 0; // Iterator of dependent materials (plugged as inputs) - virtual Iterator* CreateMaterialIterator() const; + virtual std::unique_ptr CreateMaterialIterator() const; // Iterator of textures (plugged as inputs) - virtual Iterator* CreateTextureIterator() const; - // Iterator of inputs - virtual Iterator* CreateInputIterator() const; + virtual std::unique_ptr CreateTextureIterator() const; + // Iterator of InputMaps + virtual std::unique_ptr CreateInputMapsIterator() const; + // Iterator of InputMap leafs + virtual std::unique_ptr CreateInputMapLeafsIterator() const; // Check if material has emissive components virtual bool HasEmission() const; // Set input value // If specific data type is not supported throws std::runtime_error - void SetInputValue(std::string const& name, RadeonRays::float4 const& value); - void SetInputValue(std::string const& name, Texture const* texture); - void SetInputValue(std::string const& name, Material const* material); + void SetInputValue(std::string const& name, uint32_t value); + void SetInputValue(std::string const& name, + RadeonRays::float4 const& value); + void SetInputValue(std::string const& name, Texture::Ptr texture); + void SetInputValue(std::string const& name, Material::Ptr material); + void SetInputValue(std::string const& name, Baikal::InputMap::Ptr inputMap); InputValue GetInputValue(std::string const& name) const; - // Check if material is thin (normal is always pointing in ray incidence direction) + // Check if material is thin (normal is always pointing in ray incidence + // direction) bool IsThin() const; // Set thin flag void SetThin(bool thin); + virtual bool IsActive(const Input &input) const + { + return true; + } + + size_t GetNumInputs() const; + Input GetInput(std::size_t idx) const; + Input& GetInput(const std::string& name, InputType type); + + Material(Material const&) = delete; + Material& operator = (Material const&) = delete; + protected: + + Material(); + // Register specific input - void RegisterInput(std::string const& name, std::string const& desc, std::set&& supported_types); + void RegisterInput(std::string const& name, std::string const& desc, + std::set&& supported_types); + // Wipe out all the inputs void ClearInputs(); private: - class InputIterator; - - using InputMap = std::map; // Input map InputMap m_inputs; // Thin material - bool m_thin;; + bool m_thin; }; inline Material::~Material() @@ -143,55 +179,16 @@ namespace Baikal return false; } - class SingleBxdf : public Material + class VolumeMaterial : public Material { public: - enum class BxdfType - { - kZero, - kLambert, - kIdealReflect, - kIdealRefract, - kMicrofacetBeckmann, - kMicrofacetGGX, - kEmissive, - kPassthrough, - kTranslucent, - kMicrofacetRefractionGGX, - kMicrofacetRefractionBeckmann - }; - - SingleBxdf(BxdfType type); - - BxdfType GetBxdfType() const; - void SetBxdfType(BxdfType type); + using Ptr = std::shared_ptr; + static Ptr Create(); // Check if material has emissive components bool HasEmission() const override; - private: - BxdfType m_type; - }; - - class MultiBxdf : public Material - { - public: - enum class Type - { - kLayered, - kFresnelBlend, - kMix - }; - - MultiBxdf(Type type); - - Type GetType() const; - void SetType(Type type); - - // Check if material has emissive components - bool HasEmission() const override; - - private: - Type m_type; + protected: + VolumeMaterial(); }; } diff --git a/Baikal/SceneGraph/scene1.cpp b/Baikal/SceneGraph/scene1.cpp index 9c2306a3..44e27134 100644 --- a/Baikal/SceneGraph/scene1.cpp +++ b/Baikal/SceneGraph/scene1.cpp @@ -7,24 +7,25 @@ #include #include #include +#include namespace Baikal { // Data structures for shapes and lights - using ShapeList = std::vector; - using LightList = std::vector; - using AutoreleasePool = std::set; + using ShapeList = std::vector; + using LightList = std::vector; // Internal data struct Scene1::SceneImpl { ShapeList m_shapes; LightList m_lights; - Camera const* m_camera; + Camera::Ptr m_camera; + Baikal::Texture::Ptr m_background_texture; + EnvironmentOverride m_environment_override; DirtyFlags m_dirty_flags; - - AutoreleasePool m_autorelease_pool; + std::mutex m_scene_mutex; }; Scene1::Scene1() @@ -34,13 +35,7 @@ namespace Baikal ClearDirtyFlags(); } - Scene1::~Scene1() - { - for(auto& i : m_impl->m_autorelease_pool) - { - delete i; - } - } + Scene1::~Scene1() = default; Scene1::DirtyFlags Scene1::GetDirtyFlags() const { @@ -57,23 +52,25 @@ namespace Baikal m_impl->m_dirty_flags = m_impl->m_dirty_flags | flag; } - void Scene1::SetCamera(Camera const* camera) + void Scene1::SetCamera(Camera::Ptr camera) { m_impl->m_camera = camera; SetDirtyFlag(kCamera); } - Camera const* Scene1::GetCamera() const + Camera::Ptr Scene1::GetCamera() const { return m_impl->m_camera; } - void Scene1::AttachLight(Light const* light) + void Scene1::AttachLight(Light::Ptr light) { assert(light); // Check if the light is already in the scene - LightList::const_iterator citer = std::find(m_impl->m_lights.cbegin(), m_impl->m_lights.cend(), light); + LightList::const_iterator citer = std::find(m_impl->m_lights.cbegin(), + m_impl->m_lights.cend(), + light); // And insert only if not if (citer == m_impl->m_lights.cend()) @@ -84,10 +81,12 @@ namespace Baikal } } - void Scene1::DetachLight(Light const* light) + void Scene1::DetachLight(Light::Ptr light) { // Check if the light is in the scene - LightList::const_iterator citer = std::find(m_impl->m_lights.cbegin(), m_impl->m_lights.cend(), light); + LightList::const_iterator citer = std::find(m_impl->m_lights.cbegin(), + m_impl->m_lights.cend(), + light); // And remove it if yes if (citer != m_impl->m_lights.cend()) @@ -103,17 +102,20 @@ namespace Baikal return m_impl->m_lights.size(); } - Iterator* Scene1::CreateShapeIterator() const + std::unique_ptr Scene1::CreateShapeIterator() const { - return new IteratorImpl(m_impl->m_shapes.begin(), m_impl->m_shapes.end()); + return std::make_unique> + (m_impl->m_shapes.begin(), m_impl->m_shapes.end()); } - void Scene1::AttachShape(Shape const* shape) + void Scene1::AttachShape(Shape::Ptr shape) { assert(shape); // Check if the shape is already in the scene - ShapeList::const_iterator citer = std::find(m_impl->m_shapes.cbegin(), m_impl->m_shapes.cend(), shape); + ShapeList::const_iterator citer = std::find(m_impl->m_shapes.cbegin(), + m_impl->m_shapes.cend(), + shape); // And attach it if not if (citer == m_impl->m_shapes.cend()) @@ -124,12 +126,14 @@ namespace Baikal } } - void Scene1::DetachShape(Shape const* shape) + void Scene1::DetachShape(Shape::Ptr shape) { assert(shape); // Check if the shape is in the scene - ShapeList::const_iterator citer = std::find(m_impl->m_shapes.cbegin(), m_impl->m_shapes.cend(), shape); + ShapeList::const_iterator citer = std::find(m_impl->m_shapes.cbegin(), + m_impl->m_shapes.cend(), + shape); // And detach if yes if (citer != m_impl->m_shapes.cend()) @@ -145,43 +149,95 @@ namespace Baikal return m_impl->m_shapes.size(); } - void Scene1::AttachAutoreleaseObject(SceneObject const* object) + std::unique_ptr Scene1::CreateLightIterator() const { - assert(object); - - // Check if the light is already in the scene - AutoreleasePool::const_iterator citer = std::find(m_impl->m_autorelease_pool.cbegin(), m_impl->m_autorelease_pool.cend(), object); - - // And insert only if not - if (citer == m_impl->m_autorelease_pool.cend()) - { - m_impl->m_autorelease_pool.insert(object); - } + return std::make_unique> + (m_impl->m_lights.begin(), m_impl->m_lights.end()); } - void Scene1::DetachAutoreleaseObject(SceneObject const* object) + bool Scene1::IsValid() const { - assert(object); - - // Check if the light is already in the scene - AutoreleasePool::const_iterator citer = std::find(m_impl->m_autorelease_pool.cbegin(), m_impl->m_autorelease_pool.cend(), object); - - // And insert only if not - if (citer != m_impl->m_autorelease_pool.cend()) + return GetCamera() && + GetNumLights() > 0 && + GetNumShapes() > 0; + } + + RadeonRays::bbox Scene1::GetWorldAABB() const + { + auto iter = CreateShapeIterator(); + + RadeonRays::bbox result; + for (; iter->IsValid(); iter->Next()) { - m_impl->m_autorelease_pool.erase(citer); + auto aabb = iter->ItemAs()->GetWorldAABB(); + result.grow(aabb); } + + return result; } - - Iterator* Scene1::CreateLightIterator() const + + float Scene1::GetRadius() const { - return new IteratorImpl(m_impl->m_lights.begin(), m_impl->m_lights.end()); + auto aabb = GetWorldAABB(); + + auto c = aabb.center(); + + return std::sqrt((aabb.pmax - c).sqnorm()); } - bool Scene1::IsValid() const + void Scene1::SetBackgroundImage(Baikal::Texture::Ptr texture) { - return GetCamera() && - GetNumLights() > 0 && - GetNumShapes() > 0; + m_impl->m_background_texture = texture; + SetDirtyFlag(kBackground); + } + + Baikal::Texture::Ptr Scene1::GetBackgroundImage() const + { + return m_impl->m_background_texture; + } + + void Scene1::SetEnvironmentOverride(const EnvironmentOverride& env_override) + { + auto check_and_set_light = [&](ImageBasedLight::Ptr current_light, ImageBasedLight::Ptr new_light) + { + if (current_light != new_light) + { + if (current_light) + DetachLight(current_light); + if (new_light) + AttachLight(new_light); + } + }; + + check_and_set_light(m_impl->m_environment_override.m_background, env_override.m_background); + check_and_set_light(m_impl->m_environment_override.m_reflection, env_override.m_reflection); + check_and_set_light(m_impl->m_environment_override.m_refraction, env_override.m_refraction); + check_and_set_light(m_impl->m_environment_override.m_transparency, env_override.m_transparency); + m_impl->m_environment_override = env_override; + } + const Scene1::EnvironmentOverride& Scene1::GetEnvironmentOverride() const + { + return m_impl->m_environment_override; + } + + void Scene1::Acquire(std::uint32_t controller_id) + { + m_impl->m_scene_mutex.lock(); + SceneObject::SetSceneControllerId(controller_id); + } + + void Scene1::Release() + { + SceneObject::ResetSceneControllerId(); + m_impl->m_scene_mutex.unlock(); + } + + namespace { + struct Scene1Concrete : public Scene1 { + }; + } + + Scene1::Ptr Scene1::Create() { + return std::make_shared(); } } diff --git a/Baikal/SceneGraph/scene1.h b/Baikal/SceneGraph/scene1.h index f9f461cc..16793eac 100644 --- a/Baikal/SceneGraph/scene1.h +++ b/Baikal/SceneGraph/scene1.h @@ -29,10 +29,14 @@ #pragma once #include +#include "math/bbox.h" + +#include "light.h" +#include "shape.h" +#include "camera.h" namespace Baikal { - class Light; class Shape; class Volume; class Camera; @@ -48,6 +52,8 @@ namespace Baikal class Scene1 { public: + using Ptr = std::shared_ptr; + static Ptr Create(); // Dirty flags are used to perform partial buffer updates to save traffic using DirtyFlags = std::uint32_t; @@ -57,53 +63,77 @@ namespace Baikal kLights, kShapes, kShapeTransforms, - kCamera + kCamera, + kBackground }; - - // Constructor - Scene1(); + + struct EnvironmentOverride + { + ImageBasedLight::Ptr m_reflection; + ImageBasedLight::Ptr m_refraction; + ImageBasedLight::Ptr m_transparency; + ImageBasedLight::Ptr m_background; + }; + // Destructor - ~Scene1(); - + virtual ~Scene1(); + // Add or remove lights - void AttachLight(Light const* light); - void DetachLight(Light const* light); + void AttachLight(Light::Ptr light); + void DetachLight(Light::Ptr light); // Get the number of lights in the scene std::size_t GetNumLights() const; // Get light iterator - Iterator* CreateLightIterator() const; + std::unique_ptr CreateLightIterator() const; // Add or remove shapes - void AttachShape(Shape const* shape); - void DetachShape(Shape const* shape); + void AttachShape(Shape::Ptr shape); + void DetachShape(Shape::Ptr shape); // Get number of shapes in the scene std::size_t GetNumShapes() const; // Get shape iterator - Iterator* CreateShapeIterator() const; - + std::unique_ptr CreateShapeIterator() const; + // Set and get camera - void SetCamera(Camera const* camera); - Camera const* GetCamera() const; - + void SetCamera(Camera::Ptr camera); + Camera::Ptr GetCamera() const; + // Get state change since last clear DirtyFlags GetDirtyFlags() const; // Set specified flag in dirty state void SetDirtyFlag(DirtyFlags flag) const; // Clear all flags void ClearDirtyFlags() const; - + // Check if the scene is ready for rendering bool IsValid() const; - - // Autorelase objects are deleted when scene is destroyed - void AttachAutoreleaseObject(SceneObject const* object); - void DetachAutoreleaseObject(SceneObject const* object); + + // World space AABB + RadeonRays::bbox GetWorldAABB() const; + + // World space bounding sphere radius + float GetRadius() const; + + // Background image override + void SetBackgroundImage(Baikal::Texture::Ptr texture); + Baikal::Texture::Ptr GetBackgroundImage() const; + + void SetEnvironmentOverride(const EnvironmentOverride& env_override); + const EnvironmentOverride& GetEnvironmentOverride() const; // Forbidden stuff Scene1(Scene1 const&) = delete; Scene1& operator = (Scene1 const&) = delete; + + // Acquire or release scene when scene controller compiles it + void Acquire(std::uint32_t controller_id); + void Release(); + + protected: + // Constructor + Scene1(); private: struct SceneImpl; diff --git a/Baikal/SceneGraph/scene_controller.inl b/Baikal/SceneGraph/scene_controller.inl deleted file mode 100644 index 67497a7c..00000000 --- a/Baikal/SceneGraph/scene_controller.inl +++ /dev/null @@ -1,323 +0,0 @@ -#include "SceneGraph/scene1.h" -#include "SceneGraph/camera.h" -#include "SceneGraph/light.h" -#include "SceneGraph/shape.h" -#include "SceneGraph/material.h" -#include "SceneGraph/texture.h" -#include "SceneGraph/Collector/collector.h" -#include "iterator.h" - -#include -#include -#include -#include -#include - -namespace Baikal -{ - template - inline - SceneController::SceneController() - { - } - - template - inline - CompiledScene& SceneController::CompileScene(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector) const - { - // The overall approach is: - // 1) Check if materials have changed, update collector if yes - // 2) Check if textures have changed, update collector if yes - // Note, that material are collected from shapes (potentially recursively). - // Textures are collected from materials and lights. - // As soon as we updated both collectors we have established - // correct pointer to buffer index mapping for both materials and textures. - // As soon as we have this mapping we are analyzing dirty flags and - // updating necessary parts. - - // We need to make sure collectors are empty before proceeding - mat_collector.Clear(); - tex_collector.Clear(); - - // Create shape and light iterators - std::unique_ptr shape_iter(scene.CreateShapeIterator()); - std::unique_ptr light_iter(scene.CreateLightIterator()); - - auto default_material = GetDefaultMaterial(); - // Collect materials from shapes first - mat_collector.Collect(shape_iter.get(), - // This function adds all materials to resulting map - // recursively via Material dependency API - [default_material](void const* item) -> std::set - { - // Resulting material set - std::set mats; - // Material stack - std::stack material_stack; - - // Get material from current shape - auto shape = reinterpret_cast(item); - auto material = shape->GetMaterial(); - - // If shape does not have a material, use default one - if (!material) - { - material = default_material; - } - - // Push to stack as an initializer - material_stack.push(material); - - // Drain the stack - while (!material_stack.empty()) - { - // Get current material - Material const* m = material_stack.top(); - material_stack.pop(); - - // Emplace into the set - mats.emplace(m); - - // Create dependency iterator - std::unique_ptr mat_iter(m->CreateMaterialIterator()); - - // Push all dependencies into the stack - for (; mat_iter->IsValid(); mat_iter->Next()) - { - material_stack.push(mat_iter->ItemAs()); - } - } - - // Return resulting set - return mats; - }); - - // Commit stuff (we can iterate over it after commit has happened) - mat_collector.Commit(); - - // Now we need to collect textures from our materials - // Create material iterator - std::unique_ptr mat_iter(mat_collector.CreateIterator()); - - // Collect textures from materials - tex_collector.Collect(mat_iter.get(), - [](void const* item) -> std::set - { - // Texture set - std::set textures; - - auto material = reinterpret_cast(item); - - // Create texture dependency iterator - std::unique_ptr tex_iter(material->CreateTextureIterator()); - - // Emplace all dependent textures - for (; tex_iter->IsValid(); tex_iter->Next()) - { - textures.emplace(tex_iter->ItemAs()); - } - - // Return resulting set - return textures; - }); - - - // Collect textures from lights - tex_collector.Collect(light_iter.get(), - [](void const* item) -> std::set - { - // Resulting set - std::set textures; - - auto light = reinterpret_cast(item); - - // Create texture dependency iterator - std::unique_ptr tex_iter(light->CreateTextureIterator()); - - // Emplace all dependent textures - for (; tex_iter->IsValid(); tex_iter->Next()) - { - textures.emplace(tex_iter->ItemAs()); - } - - // Return resulting set - return textures; - }); - - // Commit textures - tex_collector.Commit(); - - // Try to find scene in cache first - auto iter = m_scene_cache.find(&scene); - - if (iter == m_scene_cache.cend()) - { - // If not found create scene entry in cache - auto res = m_scene_cache.emplace(std::make_pair(&scene, CompiledScene())); - - // Recompile all the stuff into cached scene - RecompileFull(scene, mat_collector, tex_collector, res.first->second); - - // Set scene as current - m_current_scene = &scene; - - // Drop all dirty flags for the scene - scene.ClearDirtyFlags(); - - // Drop dirty flags for materials - mat_collector.Finalize([](void const* item) - { - auto material = reinterpret_cast(item); - material->SetDirty(false); - }); - - // Return the scene - return res.first->second; - } - else - { - // Exctract cached scene entry - auto& out = iter->second; - auto dirty = scene.GetDirtyFlags(); - - // Check if we have valid camera - auto camera = scene.GetCamera(); - - if (!camera) - { - throw std::runtime_error("No camera in the scene"); - } - - // Check if camera parameters have been changed - auto camera_changed = camera->IsDirty(); - - // Update camera if needed - if (dirty & Scene1::kCamera || camera_changed) - { - UpdateCamera(scene, mat_collector, tex_collector, out); - } - - { - // Check if we have lights in the scene - std::unique_ptr light_iter(scene.CreateLightIterator()); - - if (!light_iter->IsValid()) - { - throw std::runtime_error("No lights in the scene"); - } - - - // Check if light parameters have been changed - bool lights_changed = false; - - for (; light_iter->IsValid(); light_iter->Next()) - { - auto light = light_iter->ItemAs(); - - if (light->IsDirty()) - { - lights_changed = true; - break; - } - } - - - // Update lights if needed - if (dirty & Scene1::kLights || lights_changed) - { - UpdateLights(scene, mat_collector, tex_collector, out); - } - } - - { - // Check if we have shapes in the scene - std::unique_ptr shape_iter(scene.CreateShapeIterator()); - - if (!shape_iter->IsValid()) - { - throw std::runtime_error("No shapes in the scene"); - } - - // Check if shape parameters have been changed - bool shapes_changed = false; - - for (; shape_iter->IsValid(); shape_iter->Next()) - { - auto shape = shape_iter->ItemAs(); - - if (shape->IsDirty()) - { - shapes_changed = true; - break; - } - } - - // Update shapes if needed - if (dirty & Scene1::kShapes || shapes_changed) - { - UpdateShapes(scene, mat_collector, tex_collector, out); - } - } - - // If materials need an update, do it. - // We are passing material dirty state detection function in there. - if (!out.material_bundle || - mat_collector.NeedsUpdate(out.material_bundle.get(), - [](void const* ptr)->bool - { - auto mat = reinterpret_cast(ptr); - return mat->IsDirty(); - } - )) - { - UpdateMaterials(scene, mat_collector, tex_collector, out); - } - - // If textures need an update, do it. - if (tex_collector.GetNumItems() > 0 && ( - !out.texture_bundle || - tex_collector.NeedsUpdate(out.texture_bundle.get(), [](void const* ptr) { - auto tex = reinterpret_cast(ptr); - return tex->IsDirty(); }))) - { - UpdateTextures(scene, mat_collector, tex_collector, out); - } - - // Set current scene - if (m_current_scene != &scene) - { - m_current_scene = &scene; - - UpdateCurrentScene(scene, out); - } - - // Make sure to clear dirty flags - scene.ClearDirtyFlags(); - - // Clear material dirty flags - mat_collector.Finalize([](void const* item) - { - auto material = reinterpret_cast(item); - material->SetDirty(false); - }); - - // Return the scene - return out; - } - } - - template - inline - void SceneController::RecompileFull(Scene1 const& scene, Collector& mat_collector, Collector& tex_collector, CompiledScene& out) const - { - UpdateCamera(scene, mat_collector, tex_collector, out); - - UpdateLights(scene, mat_collector, tex_collector, out); - - UpdateShapes(scene, mat_collector, tex_collector, out); - - UpdateMaterials(scene, mat_collector, tex_collector, out); - - UpdateTextures(scene, mat_collector, tex_collector, out); - } -} diff --git a/Baikal/SceneGraph/scene_object.cpp b/Baikal/SceneGraph/scene_object.cpp new file mode 100644 index 00000000..4611240b --- /dev/null +++ b/Baikal/SceneGraph/scene_object.cpp @@ -0,0 +1,53 @@ +#include "scene_object.h" +#include + +namespace Baikal +{ + static std::uint32_t g_next_id = 0; + static int g_scene_controller_id = -1; + + SceneObject::SceneObject() + : m_dirty(), m_id(g_next_id++) + { + } + + bool SceneObject::IsDirty() const + { + assert(g_scene_controller_id >= 0); + + return m_dirty[g_scene_controller_id]; + + } + + void SceneObject::SetDirty(bool dirty) const + { + if (dirty) + { + // Set all bits to 1 + m_dirty.set(); + } + else + { + assert(g_scene_controller_id >= 0); + // Unset corresponging bit + m_dirty.set(g_scene_controller_id, false); + } + } + + void SceneObject::ResetId() + { + g_next_id = 0; + } + + void SceneObject::SetSceneControllerId(std::uint32_t controller_id) + { + assert(controller_id < kMaxDirtyBits); + g_scene_controller_id = static_cast(controller_id); + } + + void SceneObject::ResetSceneControllerId() + { + g_scene_controller_id = -1; + } + +} diff --git a/Baikal/SceneGraph/scene_object.h b/Baikal/SceneGraph/scene_object.h index b83c8891..c2139931 100644 --- a/Baikal/SceneGraph/scene_object.h +++ b/Baikal/SceneGraph/scene_object.h @@ -29,54 +29,57 @@ #pragma once #include +#include +#include +#include namespace Baikal { class SceneObject { public: - // Constructor - SceneObject(); + using Ptr = std::shared_ptr; + // Destructor virtual ~SceneObject() = 0; - + // Check if the object has been changed since last reset - bool IsDirty() const; + virtual bool IsDirty() const; // Set dirty flag - void SetDirty(bool dirty) const; - + virtual void SetDirty(bool dirty) const; + // Set & get name void SetName(std::string const& name); std::string GetName() const; SceneObject(SceneObject const&) = delete; SceneObject& operator = (SceneObject const&) = delete; + + inline std::uint32_t GetId() const + { return m_id; } + + static void ResetId(); + static void SetSceneControllerId(std::uint32_t controller_id); + static void ResetSceneControllerId(); + + protected: + // Constructor + SceneObject(); private: - mutable bool m_dirty; - + // Bit mask size, equals to bit count of std::uint32_t + static const int kMaxDirtyBits = 32; + mutable std::bitset m_dirty; + std::string m_name; + std::uint32_t m_id; + }; - - inline SceneObject::SceneObject() - : m_dirty(false) - { - } - + inline SceneObject::~SceneObject() { } - - inline bool SceneObject::IsDirty() const - { - return m_dirty; - } - - inline void SceneObject::SetDirty(bool dirty) const - { - m_dirty = dirty; - } - + inline std::string SceneObject::GetName() const { return m_name; diff --git a/Baikal/SceneGraph/shape.cpp b/Baikal/SceneGraph/shape.cpp index 6ed38fdb..fc7848e4 100644 --- a/Baikal/SceneGraph/shape.cpp +++ b/Baikal/SceneGraph/shape.cpp @@ -3,11 +3,8 @@ namespace Baikal { - Mesh::Mesh() - : m_num_indices(0) - , m_num_vertices(0) - , m_num_normals(0) - , m_num_uvs(0) + Mesh::Mesh() : + m_aabb_cached(false) { } @@ -17,23 +14,26 @@ namespace Baikal assert(num_indices != 0); // Resize internal array and copy data - m_indices.reset(new std::uint32_t[num_indices]); + m_indices.resize(num_indices); - std::copy(indices, indices + num_indices, m_indices.get()); - - m_num_indices = num_indices; + std::copy(indices, indices + num_indices, &m_indices[0]); SetDirty(true); } - + + void Mesh::SetIndices(std::vector&& indices) + { + m_indices = std::move(indices); + } + std::size_t Mesh::GetNumIndices() const { - return m_num_indices; + return m_indices.size(); } std::uint32_t const* Mesh::GetIndices() const { - return m_indices.get(); + return &m_indices[0]; } void Mesh::SetVertices(RadeonRays::float3 const* vertices, std::size_t num_vertices) @@ -42,12 +42,10 @@ namespace Baikal assert(num_vertices != 0); // Resize internal array and copy data - m_vertices.reset(new RadeonRays::float3[num_vertices]); - - std::copy(vertices, vertices + num_vertices, m_vertices.get()); - - m_num_vertices = num_vertices; - + m_vertices.resize(num_vertices); + + std::copy(vertices, vertices + num_vertices, &m_vertices[0]); + SetDirty(true); } @@ -57,7 +55,7 @@ namespace Baikal assert(num_vertices != 0); // Resize internal array and copy data - m_vertices.reset(new RadeonRays::float3[num_vertices]); + m_vertices.resize(num_vertices); for (std::size_t i = 0; i < num_vertices; ++i) { @@ -66,20 +64,24 @@ namespace Baikal m_vertices[i].z = vertices[3 * i + 2]; m_vertices[i].w = 1; } - - m_num_vertices = num_vertices; - + SetDirty(true); } + + void Mesh::SetVertices(std::vector&& vertices) + { + m_vertices = std::move(vertices); + } + std::size_t Mesh::GetNumVertices() const { - return m_num_vertices; + return m_vertices.size(); } RadeonRays::float3 const* Mesh::GetVertices() const { - return m_vertices.get(); + return &m_vertices[0]; } void Mesh::SetNormals(RadeonRays::float3 const* normals, std::size_t num_normals) @@ -88,11 +90,9 @@ namespace Baikal assert(num_normals != 0); // Resize internal array and copy data - m_normals.reset(new RadeonRays::float3[num_normals]); - - std::copy(normals, normals + num_normals, m_normals.get()); + m_normals.resize(num_normals); - m_num_normals = num_normals; + std::copy(normals, normals + num_normals, &m_normals[0]); SetDirty(true); } @@ -103,7 +103,7 @@ namespace Baikal assert(num_normals != 0); // Resize internal array and copy data - m_normals.reset(new RadeonRays::float3[num_normals]); + m_normals.resize(num_normals); for (std::size_t i = 0; i < num_normals; ++i) { @@ -112,34 +112,36 @@ namespace Baikal m_normals[i].z = normals[3 * i + 2]; m_normals[i].w = 0; } - - m_num_normals = num_normals; - + SetDirty(true); } + + void Mesh::SetNormals(std::vector&& normals) + { + m_normals = std::move(normals); + } + std::size_t Mesh::GetNumNormals() const { - return m_num_normals; + return m_normals.size(); } - + RadeonRays::float3 const* Mesh::GetNormals() const { - return m_normals.get(); + return &m_normals[0]; } - + void Mesh::SetUVs(RadeonRays::float2 const* uvs, std::size_t num_uvs) { assert(uvs); assert(num_uvs != 0); // Resize internal array and copy data - m_uvs.reset(new RadeonRays::float2[num_uvs]); - - std::copy(uvs, uvs + num_uvs, m_uvs.get()); - - m_num_uvs = num_uvs; - + m_uvs.resize(num_uvs); + + std::copy(uvs, uvs + num_uvs, &m_uvs[0]); + SetDirty(true); } @@ -149,26 +151,100 @@ namespace Baikal assert(num_uvs != 0); // Resize internal array and copy data - m_uvs.reset(new RadeonRays::float2[num_uvs]); + m_uvs.resize(num_uvs); for (std::size_t i = 0; i < num_uvs; ++i) { m_uvs[i].x = uvs[2 * i]; m_uvs[i].y = uvs[2 * i + 1]; } - - m_num_uvs = num_uvs; - + SetDirty(true); } - + + void Mesh::SetUVs(std::vector&& uvs) + { + m_uvs = std::move(uvs); + } + std::size_t Mesh::GetNumUVs() const { - return m_num_uvs; + return m_uvs.size(); } RadeonRays::float2 const* Mesh::GetUVs() const { - return m_uvs.get(); + return &m_uvs[0]; + } + + RadeonRays::bbox Shape::GetWorldAABB() const + { + RadeonRays::bbox result; + auto local_aabb = GetLocalAABB(); + auto transform = GetTransform(); + + auto p0 = local_aabb.pmin; + auto p1 = local_aabb.pmax; + auto p2 = RadeonRays::float3(p0.x, p0.y, p1.z); + auto p3 = RadeonRays::float3(p0.x, p1.y, p0.z); + auto p4 = RadeonRays::float3(p1.x, p0.y, p0.z); + auto p5 = RadeonRays::float3(p0.x, p1.y, p1.z); + auto p6 = RadeonRays::float3(p1.x, p1.y, p0.z); + auto p7 = RadeonRays::float3(p1.x, p0.y, p1.z); + + result.grow(transform * p0); + result.grow(transform * p1); + result.grow(transform * p2); + result.grow(transform * p3); + result.grow(transform * p4); + result.grow(transform * p5); + result.grow(transform * p6); + result.grow(transform * p7); + + return result; + } + + RadeonRays::bbox Mesh::GetLocalAABB() const + { + if (!m_aabb_cached) + { + m_aabb = RadeonRays::bbox(); + for (std::size_t i = 0; i < m_indices.size(); ++i) + { + m_aabb.grow(m_vertices[m_indices[i]]); + } + m_aabb_cached = true; + } + + return m_aabb; + } + + void Mesh::SetDirty(bool dirty) const + { + Shape::SetDirty(dirty); + m_aabb_cached = false; + } + + RadeonRays::bbox Instance::GetLocalAABB() const + { + return m_base_shape->GetLocalAABB(); + } + + namespace { + struct InstanceConcrete : public Instance { + InstanceConcrete(Shape::Ptr base_shape) : + Instance(base_shape) {} + }; + + struct MeshConcrete : public Mesh { + }; + } + + Mesh::Ptr Mesh::Create() { + return std::make_shared(); + } + + Instance::Ptr Instance::Create(Shape::Ptr base_shape) { + return std::make_shared(base_shape); } } diff --git a/Baikal/SceneGraph/shape.h b/Baikal/SceneGraph/shape.h index ec197693..7dd0cfb1 100644 --- a/Baikal/SceneGraph/shape.h +++ b/Baikal/SceneGraph/shape.h @@ -31,10 +31,13 @@ #include "math/float3.h" #include "math/float2.h" #include "math/matrix.h" +#include "math/bbox.h" #include #include +#include #include "scene_object.h" +#include "material.h" namespace Baikal { @@ -48,26 +51,74 @@ namespace Baikal class Shape : public SceneObject { public: - // Constructor - Shape(); + using Ptr = std::shared_ptr; + + struct Visibility + { + enum VisibilityFlags + { + kPrimary = 0x1, + kShadow = (0x1 << 15) + }; + + static VisibilityFlags VisibleForAll() { return (VisibilityFlags)0xffffffffu; } + static VisibilityFlags InvisibleForAll() { return (VisibilityFlags)0x0u; } + static VisibilityFlags VisibleForPrimary() { return kPrimary; } + static VisibilityFlags VisibleForPrimaryShadow() { return kShadow; } + static VisibilityFlags VisibleForBounce(int i) { return (VisibilityFlags)(kPrimary << i); } + static VisibilityFlags VisibleForBounceShadow(int i) { return (VisibilityFlags)(kShadow << i); } + }; + // Destructor virtual ~Shape() = 0; + // Set and get group id + void SetGroupId(std::uint32_t id); + std::uint32_t GetGroupId() const; + // Get and set material - void SetMaterial(Material const* material); - Material const* GetMaterial() const; + void SetMaterial(Material::Ptr material); + Material::Ptr GetMaterial() const; + + // Get and set volume material + void SetVolumeMaterial(VolumeMaterial::Ptr volume_mat); + VolumeMaterial::Ptr GetVolumeMaterial() const; // Get and set transform void SetTransform(RadeonRays::matrix const& t); RadeonRays::matrix GetTransform() const; + // Set whether a shape casts shadow or not + void SetShadow(bool shadow); + bool GetShadow() const; + + // Set visibility properties for a shape + void SetVisibilityMask(std::uint32_t mask); + std::uint32_t GetVisibilityMask() const; + + // Local AABB + virtual RadeonRays::bbox GetLocalAABB() const = 0; + RadeonRays::bbox GetWorldAABB() const; + // Forbidden stuff Shape(Shape const&) = delete; Shape& operator = (Shape const&) = delete; + + protected: + // Constructor + Shape(); + private: - Material const* m_material; - + // Material for the shape + Material::Ptr m_material; + // Volume material for the shape + VolumeMaterial::Ptr m_volume; + // Transform RadeonRays::matrix m_transform; + // Visibility mask + std::uint32_t m_visibility_mask; + // Group id + std::uint32_t m_group_id; }; /** @@ -78,68 +129,111 @@ namespace Baikal class Mesh : public Shape { public: - Mesh(); - + using Ptr = std::shared_ptr; + static Ptr Create(); + // Set and get index array void SetIndices(std::uint32_t const* indices, std::size_t num_indices); + void SetIndices(std::vector&& indices); std::size_t GetNumIndices() const; std::uint32_t const* GetIndices() const; - + // Set and get vertex array void SetVertices(RadeonRays::float3 const* vertices, std::size_t num_vertices); void SetVertices(float const* vertices, std::size_t num_vertices); + void SetVertices(std::vector&& vertices); + std::size_t GetNumVertices() const; RadeonRays::float3 const* GetVertices() const; - + // Set and get normal array void SetNormals(RadeonRays::float3 const* normals, std::size_t num_normals); void SetNormals(float const* normals, std::size_t num_normals); + void SetNormals(std::vector&& normals); + std::size_t GetNumNormals() const; RadeonRays::float3 const* GetNormals() const; // Set and get UV array void SetUVs(RadeonRays::float2 const* uvs, std::size_t num_uvs); void SetUVs(float const* uvs, std::size_t num_uvs); + void SetUVs(std::vector&& uvs); std::size_t GetNumUVs() const; RadeonRays::float2 const* GetUVs() const; + // Local space AABB + RadeonRays::bbox GetLocalAABB() const override; + + // We need to override it since mesh changes trigger + // m_aabb_cached flag reset + void SetDirty(bool dirty) const override; + // Forbidden stuff Mesh(Mesh const&) = delete; Mesh& operator = (Mesh const&) = delete; - private: - std::unique_ptr m_vertices; - std::unique_ptr m_normals; - std::unique_ptr m_uvs; - std::unique_ptr m_indices; + protected: + Mesh(); - std::size_t m_num_vertices; - std::size_t m_num_normals; - std::size_t m_num_uvs; - std::size_t m_num_indices; + private: + std::vector m_vertices; + std::vector m_normals; + std::vector m_uvs; + std::vector m_indices; + + mutable RadeonRays::bbox m_aabb; + mutable bool m_aabb_cached; }; inline Shape::~Shape() { } - inline Shape::Shape() : m_material(nullptr) + inline Shape::Shape() + : m_material(nullptr) + , m_volume(nullptr) + , m_visibility_mask(0xffffffffu) + , m_group_id(-1) { } - inline void Shape::SetMaterial(Material const* material) + inline void Shape::SetGroupId(std::uint32_t id) + { + m_group_id = id; + SetDirty(true); + } + + inline std::uint32_t Shape::GetGroupId() const + { + return m_group_id; + } + + inline void Shape::SetMaterial(Material::Ptr material) { m_material = material; + SetDirty(true); } - inline Material const* Shape::GetMaterial() const + inline Material::Ptr Shape::GetMaterial() const { return m_material; } + inline void Shape::SetVolumeMaterial(VolumeMaterial::Ptr volume_mat) + { + m_volume = volume_mat; + SetDirty(true); + } + + inline VolumeMaterial::Ptr Shape::GetVolumeMaterial() const + { + return m_volume; + } + inline void Shape::SetTransform(RadeonRays::matrix const& t) { m_transform = t; + SetDirty(true); } inline RadeonRays::matrix Shape::GetTransform() const @@ -147,6 +241,17 @@ namespace Baikal return m_transform; } + inline void Shape::SetVisibilityMask(std::uint32_t mask) + { + m_visibility_mask = mask; + SetDirty(true); + } + + inline std::uint32_t Shape::GetVisibilityMask() const + { + return m_visibility_mask; + } + /** \brief Instance class. @@ -155,31 +260,39 @@ namespace Baikal class Instance : public Shape { public: - Instance(Shape const* base_shape = nullptr); + using Ptr = std::shared_ptr; + static Ptr Create(Shape::Ptr base_shape); // Get and set base shape - void SetBaseShape(Shape const* base_shape); - Shape const* GetBaseShape() const; + void SetBaseShape(Shape::Ptr base_shape); + Shape::Ptr GetBaseShape() const; + + // Local space AABB + RadeonRays::bbox GetLocalAABB() const override; // Forbidden stuff Instance(Instance const&) = delete; Instance& operator = (Instance const&) = delete; + protected: + Instance(Shape::Ptr base_shape = nullptr); + private: - Shape const* m_base_shape; + Shape::Ptr m_base_shape; }; - inline Instance::Instance(Shape const* base_shape) + inline Instance::Instance(Shape::Ptr base_shape) : m_base_shape(base_shape) { } - inline void Instance::SetBaseShape(Shape const* base_shape) + inline void Instance::SetBaseShape(Shape::Ptr base_shape) { m_base_shape = base_shape; + SetDirty(true); } - inline Shape const* Instance::GetBaseShape() const + inline Shape::Ptr Instance::GetBaseShape() const { return m_base_shape; } diff --git a/Baikal/SceneGraph/texture.cpp b/Baikal/SceneGraph/texture.cpp new file mode 100644 index 00000000..c7c3af45 --- /dev/null +++ b/Baikal/SceneGraph/texture.cpp @@ -0,0 +1,90 @@ +#include "texture.h" + +#include "Utils/half.h" + +namespace Baikal +{ + RadeonRays::float3 Texture::ComputeAverageValue() const + { + auto avg = RadeonRays::float3(); + + switch (m_format) { + case Format::kRgba8: + { + auto data = reinterpret_cast(m_data.get()); + auto num_elements = m_size.x * m_size.y * m_size.z; + + + for (auto i = 0; i < num_elements; ++i) + { + float r = data[4 * i] / 255.f; + float g = data[4 * i + 1] / 255.f; + float b = data[4 * i + 2] / 255.f; + avg += RadeonRays::float3(r, g, b); + } + + avg *= (1.f / num_elements); + break; + } + case Format::kRgba16: + { + auto data = reinterpret_cast(m_data.get()); + auto num_elements = m_size.x * m_size.y * m_size.z; + + for (auto i = 0; i < num_elements; ++i) + { + auto r = data[4 * i]; + auto g = data[4 * i + 1]; + auto b = data[4 * i + 2]; + + half hr, hg, hb; + hr.setBits(r); + hg.setBits(g); + hb.setBits(b); + + avg += RadeonRays::float3(hr, hg, hb); + } + + avg *= (1.f / num_elements); + break; + } + case Format::kRgba32: + { + auto data = reinterpret_cast(m_data.get()); + auto num_elements = m_size.x * m_size.y * m_size.z; + + for (auto i = 0; i < num_elements; ++i) + { + auto r = data[4 * i]; + auto g = data[4 * i + 1]; + auto b = data[4 * i + 2]; + + avg += RadeonRays::float3(r, g, b); + } + + avg *= (1.f / num_elements); + break; + } + default: + break; + } + + return avg; + } + + namespace { + struct TextureConcrete : public Texture { + TextureConcrete() = default; + TextureConcrete(char* data, RadeonRays::int3 size, Format format) : + Texture(data, size, format) {} + }; + } + + Texture::Ptr Texture::Create() { + return std::make_shared(); + } + + Texture::Ptr Texture::Create(char* data, RadeonRays::int3 size, Format format) { + return std::make_shared(data, size, format); + } +} diff --git a/Baikal/SceneGraph/texture.h b/Baikal/SceneGraph/texture.h index ed20aa1d..dfbc6528 100644 --- a/Baikal/SceneGraph/texture.h +++ b/Baikal/SceneGraph/texture.h @@ -1,16 +1,16 @@ /********************************************************************** Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. - + 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 @@ -20,17 +20,17 @@ THE SOFTWARE. ********************************************************************/ -/** - \file texture.h - \author Dmitry Kozlov - \version 1.0 - \brief Contains declaration of a texture class. - */ + /** + \file texture.h + \author Dmitry Kozlov + \version 1.0 + \brief Contains declaration of a texture class. + */ #pragma once #include "math/float3.h" #include "math/float2.h" -#include "math/int2.h" +#include "math/int3.h" #include #include @@ -39,10 +39,10 @@ namespace Baikal { class Material; - + /** \brief Texture class. - + Texture is used to host CPU memory for image data. */ class Texture : public SceneObject @@ -55,18 +55,18 @@ namespace Baikal kRgba32 }; - // Constructor - Texture(); - // Note, that texture takes ownership of its data array - Texture(char* data, RadeonRays::int2 size, Format format); + using Ptr = std::shared_ptr; + static Ptr Create(char* data, RadeonRays::int3 size, Format format); + static Ptr Create(); + // Destructor (the data is destroyed as well) virtual ~Texture() = default; // Set data - void SetData(char* data, RadeonRays::int2 size, Format format); + void SetData(char* data, RadeonRays::int3 size, Format format); // Get texture dimensions - RadeonRays::int2 GetSize() const; + RadeonRays::int3 GetSize() const; // Get texture raw data char const* GetData() const; // Get texture format @@ -74,22 +74,31 @@ namespace Baikal // Get data size in bytes std::size_t GetSizeInBytes() const; + // Average normalized value + RadeonRays::float3 ComputeAverageValue() const; + // Disallow copying Texture(Texture const&) = delete; Texture& operator = (Texture const&) = delete; + protected: + // Constructor + Texture(); + // Note, that texture takes ownership of its data array + Texture(char* data, RadeonRays::int3 size, Format format); + private: // Image data std::unique_ptr m_data; // Image dimensions - RadeonRays::int2 m_size; + RadeonRays::int3 m_size; // Format Format m_format; }; inline Texture::Texture() : m_data(new char[16]) - , m_size(2,2) + , m_size(2, 2, 1) , m_format(Format::kRgba8) { // Create checkerboard by default @@ -99,54 +108,64 @@ namespace Baikal m_data[12] = m_data[13] = m_data[14] = m_data[15] = (char)0x00; } - inline Texture::Texture(char* data, RadeonRays::int2 size, Format format) - : m_data(data) - , m_size(size) - , m_format(format) + inline Texture::Texture(char* data, RadeonRays::int3 size, Format format) + : m_data(data) + , m_size(size) + , m_format(format) { + if (size.z == 0) + { + m_size.z = 1; + } } - inline void Texture::SetData(char* data, RadeonRays::int2 size, Format format) + inline void Texture::SetData(char* data, RadeonRays::int3 size, Format format) { m_data.reset(data); m_size = size; + + if (size.z == 0) + { + m_size.z = 1; + } + m_format = format; SetDirty(true); } - inline RadeonRays::int2 Texture::GetSize() const + inline RadeonRays::int3 Texture::GetSize() const { return m_size; } - + inline char const* Texture::GetData() const { return m_data.get(); } - + inline Texture::Format Texture::GetFormat() const { return m_format; } - + inline std::size_t Texture::GetSizeInBytes() const { std::uint32_t component_size = 1; - + switch (m_format) { - case Format::kRgba8: - component_size = 1; - break; - case Format::kRgba16: - component_size = 2; - break; - case Format::kRgba32: - component_size = 4; - break; - default: - break; + case Format::kRgba8: + component_size = 1; + break; + case Format::kRgba16: + component_size = 2; + break; + case Format::kRgba32: + component_size = 4; + break; + default: + break; } - - return 4 * component_size * m_size.x * m_size.y; + + return 4 * component_size * m_size.x * m_size.y * m_size.z; } } diff --git a/Baikal/SceneGraph/uberv2material.cpp b/Baikal/SceneGraph/uberv2material.cpp new file mode 100644 index 00000000..5758f5f4 --- /dev/null +++ b/Baikal/SceneGraph/uberv2material.cpp @@ -0,0 +1,186 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "uberv2material.h" +#include "inputmaps.h" + +using namespace Baikal; +using namespace RadeonRays; + +namespace +{ + struct UberV2MaterialConcrete : public UberV2Material { + }; +} + +UberV2Material::Ptr UberV2Material::Create() { + return std::make_shared(); +} + +UberV2Material::UberV2Material() +{ + using namespace RadeonRays; + + // Create several input maps that needed for default material parameters + auto f4_one = InputMap_ConstantFloat3::Create(float3(1.0f, 1.0f, 1.0f, 1.0f)); + auto f4_zero = InputMap_ConstantFloat3::Create(float3(0.0f, 0.0f, 0.0f, 0.0f)); + auto f_zero = InputMap_ConstantFloat::Create(0.0f); + auto def_ior = InputMap_ConstantFloat::Create(1.5f); + auto def_roughness = InputMap_ConstantFloat::Create(0.5f); + + //Diffuse + RegisterInput("uberv2.diffuse.color", "base diffuse albedo", { InputType::kInputMap }); + SetInputValue("uberv2.diffuse.color", f4_one); + + //Reflection + RegisterInput("uberv2.reflection.color", "base reflection albedo", { InputType::kInputMap }); + SetInputValue("uberv2.reflection.color", f4_one); + RegisterInput("uberv2.reflection.roughness", "reflection roughness", { InputType::kInputMap }); + SetInputValue("uberv2.reflection.roughness", def_roughness); + RegisterInput("uberv2.reflection.anisotropy", "level of anisotropy", { InputType::kInputMap }); + SetInputValue("uberv2.reflection.anisotropy", f_zero); + RegisterInput("uberv2.reflection.anisotropy_rotation", "orientation of anisotropic component", { InputType::kInputMap }); + SetInputValue("uberv2.reflection.anisotropy_rotation", f_zero); + RegisterInput("uberv2.reflection.ior", "index of refraction", { InputType::kInputMap }); + SetInputValue("uberv2.reflection.ior", def_ior); + RegisterInput("uberv2.reflection.metalness", "metalness of the material", { InputType::kInputMap }); + SetInputValue("uberv2.reflection.metalness", f_zero); + + //Coating + RegisterInput("uberv2.coating.color", "base coating albedo", { InputType::kInputMap }); + SetInputValue("uberv2.coating.color", f4_one); + RegisterInput("uberv2.coating.ior", "index of refraction", { InputType::kInputMap }); + SetInputValue("uberv2.coating.ior", def_ior); + + //Refraction + RegisterInput("uberv2.refraction.color", "base refraction albedo", { InputType::kInputMap }); + SetInputValue("uberv2.refraction.color", f4_one); + RegisterInput("uberv2.refraction.roughness", "refraction roughness", { InputType::kInputMap }); + SetInputValue("uberv2.refraction.roughness", def_roughness); + RegisterInput("uberv2.refraction.ior", "index of refraction", { InputType::kInputMap }); + SetInputValue("uberv2.refraction.ior", def_ior); + + //Emission + RegisterInput("uberv2.emission.color", "emission albedo", { InputType::kInputMap }); + SetInputValue("uberv2.emission.color", f4_one); + + //SSS + RegisterInput("uberv2.sss.absorption_color", "volume absorption color", { InputType::kInputMap }); + SetInputValue("uberv2.sss.absorption_color", f4_zero); + RegisterInput("uberv2.sss.scatter_color", "volume scattering color", { InputType::kInputMap }); + SetInputValue("uberv2.sss.scatter_color", f4_zero); + RegisterInput("uberv2.sss.absorption_distance", "maximum distance the light can travel before absorbed in meters", { InputType::kInputMap }); + SetInputValue("uberv2.sss.absorption_distance", f_zero); + RegisterInput("uberv2.sss.scatter_distance", "maximum distance the light can travel before scattered", { InputType::kInputMap }); + SetInputValue("uberv2.sss.scatter_distance", f_zero); + RegisterInput("uberv2.sss.scatter_direction", "scattering direction (G parameter of Henyey-Grenstein scattering function)", { InputType::kInputMap }); + SetInputValue("uberv2.sss.scatter_direction", f_zero); + RegisterInput("uberv2.sss.subsurface_color", "color of diffuse refraction BRDF", { InputType::kInputMap }); + SetInputValue("uberv2.sss.subsurface_color", f4_one); + + //Transparency + RegisterInput("uberv2.transparency", "level of transparency", { InputType::kInputMap }); + SetInputValue("uberv2.transparency", f_zero); + + //Normal mapping + RegisterInput("uberv2.shading_normal", "Shading normal", { InputType::kInputMap }); + SetInputValue("uberv2.shading_normal", f_zero); +} + +bool UberV2Material::HasEmission() const +{ + return (layers_ & Layers::kEmissionLayer) == Layers::kEmissionLayer; +} + +void UberV2Material::SetLayers(uint32_t layers) +{ + layers_ = layers; + + static const std::vector diffuse_inputs = {"uberv2.diffuse.color"}; + static const std::vector emission_inputs = {"uberv2.emission.color"}; + static const std::vector transparency_inputs = {"uberv2.transparency"}; + static const std::vector normalmap_inputs = {"uberv2.shading_normal"}; + + static const std::vector coating_inputs = + {"uberv2.coating.color", "uberv2.coating.ior"}; + + static const std::vector reflection_inputs = + {"uberv2.reflection.color", "uberv2.reflection.roughness", "uberv2.reflection.anisotropy", + "uberv2.reflection.anisotropy_rotation", "uberv2.reflection.ior", "uberv2.reflection.metalness"}; + + static const std::vector refraction_inputs = + {"uberv2.refraction.color", "uberv2.refraction.roughness", "uberv2.refraction.ior"}; + + static const std::vector sss_inputs = + {"uberv2.sss.absorption_color", "uberv2.sss.scatter_color", "uberv2.sss.absorption_distance", + "uberv2.sss.scatter_distance", "uberv2.sss.scatter_direction", "uberv2.sss.subsurface_color"}; + + auto add_inputs = [&](const std::vector inputs) + { + for (auto input_name : inputs) + { + m_active_inputs.insert(input_name); + } + }; + + m_active_inputs.clear(); + + if ((layers_ & Layers::kCoatingLayer) == Layers::kCoatingLayer) + { + add_inputs(coating_inputs); + } + if ((layers_ & Layers::kDiffuseLayer) == Layers::kDiffuseLayer) + { + add_inputs(diffuse_inputs); + } + if ((layers_ & Layers::kEmissionLayer) == Layers::kEmissionLayer) + { + add_inputs(emission_inputs); + } + if ((layers_ & Layers::kReflectionLayer) == Layers::kReflectionLayer) + { + add_inputs(reflection_inputs); + } + if ((layers_ & Layers::kRefractionLayer) == Layers::kRefractionLayer) + { + add_inputs(refraction_inputs); + } + if ((layers_ & Layers::kShadingNormalLayer) == Layers::kShadingNormalLayer) + { + add_inputs(normalmap_inputs); + } + if ((layers_ & Layers::kSSSLayer) == Layers::kSSSLayer) + { + add_inputs(sss_inputs); + } + if ((layers_ & Layers::kTransparencyLayer) == Layers::kTransparencyLayer) + { + add_inputs(transparency_inputs); + } + + +} + +bool UberV2Material::IsActive(const Input &input) const +{ + return (m_active_inputs.find(input.info.name) != m_active_inputs.end()); +} diff --git a/Baikal/SceneGraph/uberv2material.h b/Baikal/SceneGraph/uberv2material.h new file mode 100644 index 00000000..3b41fe5d --- /dev/null +++ b/Baikal/SceneGraph/uberv2material.h @@ -0,0 +1,120 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ + +#pragma once + +#include "material.h" + +namespace Baikal +{ + /** + \brief UberV2 material interface + + \details CPU side representation of UberV2 material + */ + class UberV2Material : public Material + { + public: + enum RefractionMode + { + kRefractionSeparate = 1U, + kRefractionLinked = 2U + }; + enum EmissionMode + { + kEmissionSinglesided = 1U, + kEmissionDoublesided = 2U + }; + + enum Layers + { + kEmissionLayer = 0x1, + kTransparencyLayer = 0x2, + kCoatingLayer = 0x4, + kReflectionLayer = 0x8, + kDiffuseLayer = 0x10, + kRefractionLayer = 0x20, + kSSSLayer = 0x40, + kShadingNormalLayer = 0x80 + }; + + using Ptr = std::shared_ptr; + static Ptr Create(); + + // Check if material has emissive components + bool HasEmission() const override; + + // Sets refraction IOR linked to reflection IOR + void LinkRefractionIOR(bool link_to_reflection) + { + is_link_to_reflection_ = link_to_reflection; + } + // Check if refraction IOR linked to reflection IOR + bool IsLinkRefractionIOR() const + { + return is_link_to_reflection_; + } + + // Sets double sided material + void SetDoubleSided(bool is_double_sided) + { + is_double_sided_ = is_double_sided; + } + // Check if material is double sided + bool isDoubleSided() const + { + return is_double_sided_; + } + + // Sets if multiscattering should be used or not + void SetMultiscatter(bool is_multiscatter) + { + is_multiscatter_ = is_multiscatter; + } + // Check if multiscattering used or not + bool IsMultiscatter() const + { + return is_multiscatter_; + } + + // Sets layers that should be enabled in material + void SetLayers(std::uint32_t layers); + + // Returns enabled material layers + std::uint32_t GetLayers() const + { + return layers_; + } + + bool IsActive(const Input &input) const override; + + protected: + UberV2Material(); + bool is_link_to_reflection_; + bool is_double_sided_; + bool is_multiscatter_; + std::uint32_t layers_; + std::set m_active_inputs; + + }; + +} diff --git a/Baikal/Utils/cl_inputmap_generator.cpp b/Baikal/Utils/cl_inputmap_generator.cpp new file mode 100644 index 00000000..7b827ea0 --- /dev/null +++ b/Baikal/Utils/cl_inputmap_generator.cpp @@ -0,0 +1,461 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "cl_inputmap_generator.h" +#include "SceneGraph/uberv2material.h" +#include "SceneGraph/inputmaps.h" + + +using namespace Baikal; + +const std::string header = "#ifndef INPUTMAPS_CL\n#define INPUTMAPS_CL\n\n"; +const std::string footer = "#endif\n\n"; + +const std::string float4_selector_header = + "float4 GetInputMapFloat4(uint input_id, DifferentialGeometry const* dg, GLOBAL InputMapData const* restrict input_map_values, TEXTURE_ARG_LIST)\n{\n" + "\tswitch(input_id)\n\t{\n"; +const std::string float4_selector_footer = "\t}\n\treturn 0.0f;\n}\n"; + +const std::string float_selector_header = + "float GetInputMapFloat(uint input_id, DifferentialGeometry const* dg, GLOBAL InputMapData const* restrict input_map_values, TEXTURE_ARG_LIST)\n{\n" + "\treturn GetInputMapFloat4(input_id, dg, input_map_values, TEXTURE_ARGS).x;\n" + "}\n"; + +void CLInputMapGenerator::Generate(const Collector& input_map_collector, const Collector& input_map_leaf_collector) +{ + m_source_code = header; + m_read_functions.clear(); + m_float4_selector = float4_selector_header; + m_float_selector = float_selector_header; + + m_generated_inputs.clear(); + + // We need to guarantee order. So sort it by id using map + std::map inputs; + + auto mat_iter = input_map_collector.CreateIterator(); + for (; mat_iter->IsValid(); mat_iter->Next()) + { + auto input = mat_iter->ItemAs(); + inputs.insert(std::make_pair(input->GetId(), input)); + } + + for (auto &input : inputs) + { + GenerateSingleInput(input.second, input_map_leaf_collector); + } + + m_source_code += m_read_functions; + m_source_code += m_float4_selector + float4_selector_footer; + m_source_code += float_selector_header; + m_source_code += footer; +} + +void CLInputMapGenerator::GenerateSingleInput(std::shared_ptr input, const Collector& input_map_leaf_collector) +{ + if (m_generated_inputs.find(input->GetId()) != m_generated_inputs.end()) return; + + std::string input_id = std::to_string(input->GetId()); + + //Generate code for selectors + m_float4_selector += "\t\tcase " + input_id + ": return ReadInputMap" + input_id + "(dg, input_map_values, TEXTURE_ARGS);\n"; + m_float_selector += "\t\tcase " + input_id + ": return ReadInputMap" + input_id + "(dg, input_map_values, TEXTURE_ARGS).x;\n"; + + m_read_functions += "float4 ReadInputMap" + input_id + "(DifferentialGeometry const* dg, GLOBAL InputMapData const* restrict input_map_values, TEXTURE_ARG_LIST)\n{\n" + "\treturn (float4)(\n\t"; + + GenerateInputSource(input, input_map_leaf_collector); + + m_read_functions += "\t);\n}\n"; + + m_generated_inputs.insert(input->GetId()); +} + +void CLInputMapGenerator::GenerateInputSource(std::shared_ptr input, const Collector& input_map_leaf_collector) +{ + switch (input->m_type) + { + + case InputMap::InputMapType::kConstantFloat: + { + int32_t index = input_map_leaf_collector.GetItemIndex(input); + + m_read_functions += "((float4)(input_map_values[" + std::to_string(index) + "].float_value.value, 0.0f))\n"; + break; + } + case InputMap::InputMapType::kConstantFloat3: + { + int32_t index = input_map_leaf_collector.GetItemIndex(input); + + m_read_functions += "((float4)(input_map_values[" + std::to_string(index) + "].float_value.value, 0.0f))\n"; + break; + } + case InputMap::InputMapType::kSampler: + { + int32_t index = input_map_leaf_collector.GetItemIndex(input); + + m_read_functions += "Texture_Sample2D(dg->uv, TEXTURE_ARGS_IDX(input_map_values[" + std::to_string(index) + "].int_values.idx))\n"; + break; + } + case InputMap::InputMapType::kSamplerBumpmap: + { + int32_t index = input_map_leaf_collector.GetItemIndex(input); + + m_read_functions += "(float4)(Texture_SampleBump(dg->uv, TEXTURE_ARGS_IDX(input_map_values[" + std::to_string(index) + "].int_values.idx)), 1.0f)\n"; + break; + } + // Two inputs + case InputMap::InputMapType::kAdd: + { + InputMap_Add *i = static_cast(input.get()); + + m_read_functions += "(\n\t\t"; + GenerateInputSource(i->GetA(), input_map_leaf_collector); + m_read_functions += "\t)\n\t + \n\t(\n\t\t"; + GenerateInputSource(i->GetB(), input_map_leaf_collector); + m_read_functions += "\t)\n"; + break; + } + case InputMap::InputMapType::kSub: + { + InputMap_Sub *i = static_cast(input.get()); + + m_read_functions += "(\n\t\t"; + GenerateInputSource(i->GetA(), input_map_leaf_collector); + m_read_functions += "\t)\n\t - \n\t(\n\t\t"; + GenerateInputSource(i->GetB(), input_map_leaf_collector); + m_read_functions += "\t)\n"; + break; + } + case InputMap::InputMapType::kMul: + { + InputMap_Mul *i = static_cast(input.get()); + + m_read_functions += "(\n\t\t"; + GenerateInputSource(i->GetA(), input_map_leaf_collector); + m_read_functions += "\t)\n\t * \n\t(\n\t\t"; + GenerateInputSource(i->GetB(), input_map_leaf_collector); + m_read_functions += "\t)\n"; + break; + } + case InputMap::InputMapType::kDiv: + { + InputMap_Div *i = static_cast(input.get()); + + m_read_functions += "(\n\t\t"; + GenerateInputSource(i->GetA(), input_map_leaf_collector); + m_read_functions += "\t)\n\t / \n\t(\n\t\t"; + GenerateInputSource(i->GetB(), input_map_leaf_collector); + m_read_functions += "\t)\n"; + break; + } + case InputMap::InputMapType::kMin: + { + InputMap_Min *i = static_cast(input.get()); + + m_read_functions += "min(\n\t\t"; + GenerateInputSource(i->GetA(), input_map_leaf_collector); + m_read_functions += "\t, \n\t\t"; + GenerateInputSource(i->GetB(), input_map_leaf_collector); + m_read_functions += "\t)\n"; + break; + } + case InputMap::InputMapType::kMax: + { + InputMap_Max *i = static_cast(input.get()); + + m_read_functions += "max(\n\t\t"; + GenerateInputSource(i->GetA(), input_map_leaf_collector); + m_read_functions += "\t, \n\t\t"; + GenerateInputSource(i->GetB(), input_map_leaf_collector); + m_read_functions += "\t)\n"; + break; + } + case InputMap::InputMapType::kDot3: + { + InputMap_Dot3 *i = static_cast(input.get()); + + m_read_functions += "((float4)(dot(\n\t\t"; + GenerateInputSource(i->GetA(), input_map_leaf_collector); + m_read_functions += ".xyz\t, \n\t\t"; + GenerateInputSource(i->GetB(), input_map_leaf_collector); + m_read_functions += ".xyz\t), 0.0f, 0.0f, 0.0f))\n"; + break; + } + case InputMap::InputMapType::kDot4: + { + InputMap_Dot4 *i = static_cast(input.get()); + + m_read_functions += "((float4)(dot(\n\t\t"; + GenerateInputSource(i->GetA(), input_map_leaf_collector); + m_read_functions += "\t, \n\t\t"; + GenerateInputSource(i->GetB(), input_map_leaf_collector); + m_read_functions += "\t), 0.0f, 0.0f, 0.0f))\n"; + break; + } + case InputMap::InputMapType::kCross3: + { + InputMap_Cross3 *i = static_cast(input.get()); + + m_read_functions += "((float4)(cross(\n\t\t"; + GenerateInputSource(i->GetA(), input_map_leaf_collector); + m_read_functions += ".xyz\t, \n\t\t"; + GenerateInputSource(i->GetB(), input_map_leaf_collector); + m_read_functions += ".xyz\t), 0.0f))\n"; + break; + } + case InputMap::InputMapType::kCross4: + { + InputMap_Cross4 *i = static_cast(input.get()); + + m_read_functions += "cross(\n\t\t"; + GenerateInputSource(i->GetA(), input_map_leaf_collector); + m_read_functions += "\t, \n\t\t"; + GenerateInputSource(i->GetB(), input_map_leaf_collector); + m_read_functions += "\t)\n"; + break; + } + case InputMap::InputMapType::kPow: + { + InputMap_Pow *i = static_cast(input.get()); + + m_read_functions += "pow(\n\t\t"; + GenerateInputSource(i->GetA(), input_map_leaf_collector); + m_read_functions += "\t, \n\t\t"; + GenerateInputSource(i->GetB(), input_map_leaf_collector); + m_read_functions += ".x\t)\n"; + break; + } + case InputMap::InputMapType::kMod: + { + InputMap_Mod *i = static_cast(input.get()); + + m_read_functions += "fmod(\n\t\t"; + GenerateInputSource(i->GetA(), input_map_leaf_collector); + m_read_functions += "\t, \n\t\t"; + GenerateInputSource(i->GetB(), input_map_leaf_collector); + m_read_functions += "\t)\n"; + break; + } + //Single input + case InputMap::InputMapType::kSin: + { + InputMap_Sin *i = static_cast(input.get()); + + m_read_functions += "sin(\n\t\t"; + GenerateInputSource(i->GetArg(), input_map_leaf_collector); + m_read_functions += "\t)\n"; + break; + } + case InputMap::InputMapType::kCos: + { + InputMap_Cos *i = static_cast(input.get()); + + m_read_functions += "cos(\n\t\t"; + GenerateInputSource(i->GetArg(), input_map_leaf_collector); + m_read_functions += "\t)\n"; + break; + } + case InputMap::InputMapType::kTan: + { + InputMap_Tan *i = static_cast(input.get()); + + m_read_functions += "tan(\n\t\t"; + GenerateInputSource(i->GetArg(), input_map_leaf_collector); + m_read_functions += "\t)\n"; + break; + } + case InputMap::InputMapType::kAsin: + { + InputMap_Asin *i = static_cast(input.get()); + + m_read_functions += "asin(\n\t\t"; + GenerateInputSource(i->GetArg(), input_map_leaf_collector); + m_read_functions += "\t)\n"; + break; + } + case InputMap::InputMapType::kAcos: + { + InputMap_Acos *i = static_cast(input.get()); + + m_read_functions += "acos(\n\t\t"; + GenerateInputSource(i->GetArg(), input_map_leaf_collector); + m_read_functions += "\t)\n"; + break; + } + case InputMap::InputMapType::kAtan: + { + InputMap_Atan *i = static_cast(input.get()); + + m_read_functions += "atan(\n\t\t"; + GenerateInputSource(i->GetArg(), input_map_leaf_collector); + m_read_functions += "\t)\n"; + break; + } + case InputMap::InputMapType::kLength3: + { + InputMap_Length3 *i = static_cast(input.get()); + + m_read_functions += "(float4)(length(\n\t\t"; + GenerateInputSource(i->GetArg(), input_map_leaf_collector); + m_read_functions += ".xyz\t), 0.0f, 0.0f, 0.0f)\n"; + break; + } + case InputMap::InputMapType::kNormalize3: + { + InputMap_Normalize3 *i = static_cast(input.get()); + + m_read_functions += "(float4)(normalize(\n\t\t"; + GenerateInputSource(i->GetArg(), input_map_leaf_collector); + m_read_functions += ".xyz\t), 0.0f)\n"; + break; + } + case InputMap::InputMapType::kFloor: + { + InputMap_Floor *i = static_cast(input.get()); + + m_read_functions += "floor(\n\t\t"; + GenerateInputSource(i->GetArg(), input_map_leaf_collector); + m_read_functions += "\t)\n"; + break; + } + case InputMap::InputMapType::kAbs: + { + InputMap_Abs *i = static_cast(input.get()); + + m_read_functions += "fabs(\n\t\t"; + GenerateInputSource(i->GetArg(), input_map_leaf_collector); + m_read_functions += "\t)\n"; + break; + } + // Specials + case InputMap::InputMapType::kLerp: + { + InputMap_Lerp *i = static_cast(input.get()); + + m_read_functions += "mix(\n\t\t"; + GenerateInputSource(i->GetA(), input_map_leaf_collector); + m_read_functions += "\t, \n\t\t"; + GenerateInputSource(i->GetB(), input_map_leaf_collector); + m_read_functions += "\t, \n\t\t"; + GenerateInputSource(i->GetControl(), input_map_leaf_collector); + m_read_functions += "\t)\n"; + break; + } + case InputMap::InputMapType::kSelect: + { + InputMap_Select *i = static_cast(input.get()); + static const std::vector selection_to_text = { ".x", ".y", ".z", ".w" }; + assert(static_cast(i->GetSelection()) < selection_to_text.size()); + + m_read_functions += "(\n\t\t"; + GenerateInputSource(i->GetArg(), input_map_leaf_collector); + m_read_functions += selection_to_text[static_cast(i->GetSelection())]; + m_read_functions += "\n\t)\n"; + break; + } + case InputMap::InputMapType::kShuffle: + { + InputMap_Shuffle *i = static_cast(input.get()); + auto mask = i->GetMask(); + + m_read_functions += "shuffle(\n\t\t"; + GenerateInputSource(i->GetArg(), input_map_leaf_collector); + m_read_functions += "\t, \n\t\t"; + m_read_functions += "(uint4)(" + std::to_string(mask[0]) + ", " + std::to_string(mask[1]) + ", " + std::to_string(mask[2]) + ", " + std::to_string(mask[3]) + ")\n"; + m_read_functions += "\t)\n"; + break; + } + case InputMap::InputMapType::kShuffle2: + { + InputMap_Shuffle2 *i = static_cast(input.get()); + auto mask = i->GetMask(); + + m_read_functions += "shuffle2(\n\t\t"; + GenerateInputSource(i->GetA(), input_map_leaf_collector); + m_read_functions += "\t, \n\t\t"; + GenerateInputSource(i->GetB(), input_map_leaf_collector); + m_read_functions += "\t, \n\t\t"; + m_read_functions += "(uint4)(" + std::to_string(mask[0]) + ", " + std::to_string(mask[1]) + ", " + std::to_string(mask[2]) + ", " + std::to_string(mask[3]) + ")\n"; + m_read_functions += "\t)\n"; + break; + } + case InputMap::InputMapType::kMatMul: + { + InputMap_MatMul *i = static_cast(input.get()); + + auto mat4 = i->GetMatrix(); + + m_read_functions += "matrix_mul_vector4(\n\t\t"; + //Generate matrix + m_read_functions += "matrix_from_rows(\n\t\t\t"; + m_read_functions += "make_float4(" + + std::to_string(mat4.m00) + ", " + + std::to_string(mat4.m01) + ", " + + std::to_string(mat4.m02) + ", " + + std::to_string(mat4.m03) + "), \n\t\t\t"; + m_read_functions += "make_float4(" + + std::to_string(mat4.m10) + ", " + + std::to_string(mat4.m11) + ", " + + std::to_string(mat4.m12) + ", " + + std::to_string(mat4.m13) + "), \n\t\t\t"; + m_read_functions += "make_float4(" + + std::to_string(mat4.m20) + ", " + + std::to_string(mat4.m21) + ", " + + std::to_string(mat4.m22) + ", " + + std::to_string(mat4.m23) + "), \n\t\t\t"; + m_read_functions += "make_float4(" + + std::to_string(mat4.m30) + ", " + + std::to_string(mat4.m31) + ", " + + std::to_string(mat4.m32) + ", " + + std::to_string(mat4.m33) + ")),\n\t\t("; + GenerateInputSource(i->GetArg(), input_map_leaf_collector); + m_read_functions += "\t)\n\t)"; + break; + } + case InputMap::InputMapType::kRemap: + { + InputMap_Remap *i = static_cast(input.get()); + //mix(float3(dest.x), float3(dest.y), (val - src.x) / (src.y - src.x)) + m_read_functions += "mix((float4)(\n\t\t"; + GenerateInputSource(i->GetDestinationRange(), input_map_leaf_collector); + m_read_functions += ".x)\t, \n\t\t(float4)(\n\t\t"; + GenerateInputSource(i->GetDestinationRange(), input_map_leaf_collector); + m_read_functions += ".y)\t, \n\t\t((\n\t\t"; + GenerateInputSource(i->GetData(), input_map_leaf_collector); + m_read_functions += ") - \n\t\t(\n\t\t"; + GenerateInputSource(i->GetSourceRange(), input_map_leaf_collector); + m_read_functions += ".x)) / \n\t\t((\n\t\t"; + GenerateInputSource(i->GetSourceRange(), input_map_leaf_collector); + m_read_functions += ".y) - \n\t\t(\n\t\t"; + GenerateInputSource(i->GetSourceRange(), input_map_leaf_collector); + m_read_functions += ".x)))\t\n"; + break; + } + + + } +} diff --git a/Baikal/Utils/cl_inputmap_generator.h b/Baikal/Utils/cl_inputmap_generator.h new file mode 100644 index 00000000..4fa6400f --- /dev/null +++ b/Baikal/Utils/cl_inputmap_generator.h @@ -0,0 +1,67 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ + + +#pragma once + +#include + +#include "SceneGraph/scene1.h" +#include "SceneGraph/Collector/collector.h" +#include "SceneGraph/clwscene.h" + +namespace Baikal +{ + class UberV2Material; + class CLInputMapGenerator + { + public: + /** + * @brief Generates source code for input maps. + * + * Code stored inside Generator object. + * Makes lookups into leaf collectors to get parameters + * Each input map will create single function that will output float4 value + * + * @param input_map_collector set of input maps for generation + * @param input_map_leaf_collector list of leaf nodes that holds values + */ + void Generate(const Collector& input_map_collector, const Collector& input_map_leaf_collector); + + // Returns generated source + const std::string& GetGeneratedSource() const + { + return m_source_code; + } + + private: + // Proceed single input, writes function header and function call + void GenerateSingleInput(std::shared_ptr input, const Collector& input_map_leaf_collector); + // Writes source code for single input map. Called recursively. + void GenerateInputSource(std::shared_ptr input, const Collector& input_map_leaf_collector); + std::string m_source_code; + std::string m_read_functions; + std::string m_float4_selector; + std::string m_float_selector; + std::set m_generated_inputs; + }; +} diff --git a/Baikal/Utils/cl_program.cpp b/Baikal/Utils/cl_program.cpp new file mode 100644 index 00000000..0970b6e3 --- /dev/null +++ b/Baikal/Utils/cl_program.cpp @@ -0,0 +1,305 @@ +/********************************************************************** +Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. + +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 "cl_program.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "cl_program_manager.h" +#include "version.h" +#include "Utils/mkpath.h" + +//#define DUMP_PROGRAM_SOURCE 1 + +using namespace Baikal; + +inline std::uint32_t jenkins_one_at_a_time_hash(char const *key, size_t len) +{ + std::uint32_t hash, i; + for (hash = i = 0; i < len; ++i) + { + hash += key[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + return hash; +} + +// Computting check sum algo +// Copy from here: https://codereview.stackexchange.com/questions/104948/32-bit-checksum-of-a-file +inline std::uint32_t CheckSum(const std::string &source) +{ + std::uint32_t check_sum = 0; + unsigned shift = 0; + for (uint32_t ch : source) + { + check_sum += (ch << shift); + shift += 8; + if (shift == 32) { + shift = 0; + } + } + return check_sum; +} + +inline bool LoadBinaries(std::string const& name, std::vector& data) +{ + std::ifstream in(name, std::ios::in | std::ios::binary); + if (in) + { + data.clear(); + std::streamoff beg = in.tellg(); + in.seekg(0, std::ios::end); + std::streamoff fileSize = in.tellg() - beg; + in.seekg(0, std::ios::beg); + data.resize(static_cast(fileSize)); + in.read((char*)&data[0], fileSize); + return true; + } + else + { + return false; + } +} + +inline void SaveBinaries(std::string const& name, std::vector& data) +{ + mkfilepath(name); + + std::ofstream out(name, std::ios::out | std::ios::binary); + + if (out) + { + out.write((char*)&data[0], data.size()); + } +} + + +CLProgram::CLProgram(const CLProgramManager *program_manager, uint32_t id, CLWContext context, + const std::string &program_name, const std::string &cache_path) : + m_program_manager(program_manager), + m_program_name(program_name), + m_cache_path(cache_path), + m_id(id), + m_context(context) +{ +}; + +void CLProgram::SetSource(const std::string &source) +{ + m_compiled_source.reserve(1024 * 1024); //Just reserve 1M for now + m_program_source = source; + ParseSource(m_program_source); +} + +void CLProgram::ParseSource(const std::string &source) +{ + std::string::size_type offset = 0; + std::string::size_type position = 0; + std::string find_str("#include"); + while ((position = source.find(find_str, offset)) != std::string::npos) + { + std::string::size_type end_position = source.find(">", position); + assert(end_position != std::string::npos); + std::string fname = source.substr(position, end_position - position); + position = fname.find("<"); + assert(position != std::string::npos); + fname = fname.substr(position + 1, fname.length() - position); + offset = end_position; + + m_program_manager->LoadHeader(fname); + m_required_headers.insert(fname); + std::string arr = m_program_manager->ReadHeader(fname); + ParseSource(arr); + } +} + +void CLProgram::BuildSource(const std::string &source) +{ + std::string::size_type offset = 0; + std::string::size_type position = 0; + std::string find_str("#include"); + while ((position = source.find(find_str, offset)) != std::string::npos) + { + // Append not-include part of source + if (position != offset) + m_compiled_source += source.substr(offset, position - offset - 1); + + // Get include file name + std::string::size_type end_position = source.find(">", position); + assert(end_position != std::string::npos); + std::string fname = source.substr(position, end_position - position); + position = fname.find("<"); + assert(position != std::string::npos); + fname = fname.substr(position + 1, fname.length() - position); + offset = end_position + 1; + + if (m_included_headers.find(fname) == m_included_headers.end()) + { + m_included_headers.insert(fname); + // Append included file to source + BuildSource(m_program_manager->ReadHeader(fname)); + } + } + + // Append rest of the file + m_compiled_source += source.substr(offset); +} + +CLWProgram CLProgram::Compile(const std::string &opts) +{ + std::chrono::time_point start, end; + start = std::chrono::high_resolution_clock::now(); + + CLWProgram compiled_program; + try + { + compiled_program = CLWProgram::CreateFromSource(m_compiled_source.c_str(), m_compiled_source.size(), opts.c_str(), m_context); + /* + * Code below usable for cache debugging + */ +#ifdef DUMP_PROGRAM_SOURCE + auto e = std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); + std::ofstream file(m_program_name + std::to_string(e) + ".cl"); + file << m_compiled_source; + file.close(); +#endif + } + catch (CLWException& ) + { + std::cerr << "Compilation failed!" << std::endl; + std::cerr << "Dumping source to file:" << m_program_name << ".cl.failed" << std::endl; + std::string fname = m_program_name + ".cl.failed"; + std::ofstream file(fname); + file << m_compiled_source; + file.close(); + throw; + } + + end = std::chrono::high_resolution_clock::now(); + int elapsed_ms = (int)std::chrono::duration_cast(end - start).count(); + std::cerr << "Program compilation time: " << elapsed_ms << " ms" << std::endl; + + m_is_dirty = false; + return compiled_program; +} + +bool CLProgram::IsHeaderNeeded(const std::string &header_name) const +{ + return (m_required_headers.find(header_name) != m_required_headers.end()); +} + +CLWProgram CLProgram::GetCLWProgram(const std::string &opts) +{ + // global dirty flag + if (m_is_dirty) + { + m_programs.clear(); + m_compiled_source.clear(); + m_included_headers.clear(); + BuildSource(m_program_source); + } + + auto it = m_programs.find(opts); + if (it != m_programs.end()) + { + return it->second; + } + + CLWProgram result; + //check if we can get it from cache + if (!m_cache_path.empty()) + { + std::string filename = GetFilenameHash(opts); + + auto cached_program_path = m_cache_path; + cached_program_path.append("/"); + cached_program_path.append(filename); + cached_program_path.append(".bin"); + + std::vector binary; + if (LoadBinaries(cached_program_path, binary)) + { + // Create from binary + std::size_t size = binary.size(); + auto binaries = &binary[0]; + result = CLWProgram::CreateFromBinary(&binaries, &size, m_context); + m_programs[opts] = result; + } + else + { + result = Compile(opts); + m_programs[opts] = result; + + // Save binaries + result.GetBinaries(0, binary); + SaveBinaries(cached_program_path, binary); + } + } + + m_is_dirty = false; + return result; +} + +std::string CLProgram::GetFilenameHash(std::string const& opts) const +{ + auto name = m_program_name; + auto device_name = m_context.GetDevice(0).GetName(); + + std::regex forbidden("(\\\\)|[\\./:<>\\\"\\|\\?\\*]"); + + device_name = std::regex_replace(device_name, forbidden, "_"); + device_name.erase( + std::remove_if(device_name.begin(), device_name.end(), isspace), + device_name.end()); + + name.append("_"); + name.append(device_name); + + auto extra = m_context.GetDevice(0).GetVersion(); + extra.append(opts); + + std::ostringstream oss; + oss << jenkins_one_at_a_time_hash(extra.c_str(), extra.size()); + + name.append("_"); + name.append(oss.str()); + + + std::uint32_t file_hash = CheckSum(m_compiled_source); + + name.append("_"); + name.append(std::to_string(file_hash)); + + name.append(BAIKAL_VERSION); + + return name; +} diff --git a/Baikal/Utils/cl_program.h b/Baikal/Utils/cl_program.h new file mode 100644 index 00000000..776bc880 --- /dev/null +++ b/Baikal/Utils/cl_program.h @@ -0,0 +1,99 @@ +/********************************************************************** +Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include +#include "CLWProgram.h" +#include "CLWContext.h" + +namespace Baikal +{ + class CLProgramManager; + class CLProgram + { + public: + CLProgram() = default; + // Constructs CLProgram empty object + CLProgram(const CLProgramManager *program_manager, uint32_t id, CLWContext context, const std::string &program_name, const std::string &cache_path); + // Check if program should be recompiled + bool IsDirty() const { return m_is_dirty; } + // Sets dirty flag on program + void SetDirty() { m_is_dirty = true; } + // Returns program id + uint32_t GetId() const { return m_id; } + /** + * @brief Sets program source + * + * Function parses provided source code and collect set of headers that + * required for program to compile. + * Each header added into CLProgramManager headers array and recursively parsed for headers. + */ + void SetSource(const std::string &source); + /** + * @brief returns CLWProgram object + * + * This function will build program and compile it if it's durty. + * This function respronsible for shader cache handling. If required program + * already exists in disk or in-memory cache returns it. + * For caching uses simple uint32 crc of source code. + */ + CLWProgram GetCLWProgram(const std::string &opts); + + // Checks if specified header required by program + bool IsHeaderNeeded(const std::string &header_name) const; + + // Compiles program. In case of error dumps source into current folder + CLWProgram Compile(const std::string &opts); + + private: + // Parses source + void ParseSource(const std::string &source); + /** + * This function builds full program source by replacing + * include directives with source code. + * Duplicate includes removed. + */ + void BuildSource(const std::string &source); + // Returns hash for file name + std::string GetFilenameHash(std::string const& opts) const; + + const CLProgramManager *m_program_manager; + std::string m_program_name; ///< Program name + std::string m_cache_path; ///< Cache folder path + std::string m_compiled_source; ///< Final program source with all headers + std::string m_program_source; ///< Program source code without modifications + std::unordered_set m_required_headers; ///< Set of required headers + + std::unordered_map m_programs; ///< In-memory cache for compiled programs + + bool m_is_dirty = true; + uint32_t m_id; + CLWContext m_context; + std::set m_included_headers; ///< Set of included headers + + }; +} diff --git a/Baikal/Utils/cl_program_manager.cpp b/Baikal/Utils/cl_program_manager.cpp new file mode 100644 index 00000000..92e09158 --- /dev/null +++ b/Baikal/Utils/cl_program_manager.cpp @@ -0,0 +1,123 @@ +/********************************************************************** +Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. + +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 "cl_program_manager.h" + +#include +#include + + +using namespace Baikal; + +uint32_t CLProgramManager::m_next_program_id = 0; + +std::string ReadFile(const std::string &fname) +{ + std::ifstream file(fname); + if (!file) + { + return ""; + } + std::string str; + + file.seekg(0, std::ios::end); + str.reserve(file.tellg()); + file.seekg(0, std::ios::beg); + + str.assign((std::istreambuf_iterator(file)), std::istreambuf_iterator()); + return str; +} +CLProgramManager::CLProgramManager(const std::string &cache_path) : + m_cache_path(cache_path) +{ + +} + +uint32_t CLProgramManager::CreateProgramFromFile(CLWContext context, const std::string &fname) const +{ + std::regex delimiter("\\\\"); + auto fullpath = std::regex_replace(fname, delimiter, "/"); + + auto filename_start = fullpath.find_last_of('/'); + + if (filename_start == std::string::npos) + filename_start = 0; + else + filename_start += 1; + + auto filename_end = fullpath.find_last_of('.'); + + if (filename_end == std::string::npos) + filename_end = fullpath.size(); + + auto name = fullpath.substr(filename_start, filename_end - filename_start); + + return CLProgramManager::CreateProgramFromSource(context, name, ReadFile(fname)); +} + +uint32_t CLProgramManager::CreateProgramFromSource(CLWContext context, const std::string &name, const std::string &source) const +{ + CLProgram prg(this, m_next_program_id++, context, name, m_cache_path); + prg.SetSource(source); + m_programs.insert(std::make_pair(prg.GetId(), prg)); + return prg.GetId(); +} + +void CLProgramManager::AddHeader(const std::string &header, const std::string &source) const +{ + std::string currect_header_code = m_headers[header]; + if (currect_header_code != source) + { + m_headers[header] = source; + + for (auto &program : m_programs) + { + if (program.second.IsHeaderNeeded(header)) + { + program.second.SetDirty(); + } + } + } +} + +void CLProgramManager::LoadHeader(const std::string &header) const +{ + std::string header_source = ReadFile(header); + AddHeader(header, header_source); +} + +const std::string& CLProgramManager::ReadHeader(const std::string &header) const +{ + return m_headers[header]; +} + +CLWProgram CLProgramManager::GetProgram(uint32_t id, const std::string &opts) const +{ + CLProgram &program = m_programs[id]; + return program.GetCLWProgram(opts); +} + +void CLProgramManager::CompileProgram(uint32_t id, const std::string &opts) const +{ + CLProgram &program = m_programs[id]; + program.Compile(opts); +} diff --git a/Baikal/Utils/cl_program_manager.h b/Baikal/Utils/cl_program_manager.h new file mode 100644 index 00000000..559a6dcd --- /dev/null +++ b/Baikal/Utils/cl_program_manager.h @@ -0,0 +1,63 @@ +/********************************************************************** +Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ + +#pragma once + +#include +#include +#include +#include + +#include "CLWProgram.h" +#include "CLWContext.h" +#include "cl_program.h" + + +namespace Baikal +{ + class CLProgramManager + { + public: + // Constructor + explicit CLProgramManager(const std::string &cache_path); + // Creates program from file and returns its id + uint32_t CreateProgramFromFile(CLWContext context, const std::string &fname) const; + // Creates program from source and returns its id + uint32_t CreateProgramFromSource(CLWContext context, const std::string &name, const std::string &source) const; + // Loads header from file into map of headers + void LoadHeader(const std::string &header) const; + // Adds header to map from source + void AddHeader(const std::string &header, const std::string &source) const; + // Reads header from disk and returns its source + const std::string& ReadHeader(const std::string &header) const; + // Returns compiled program + CLWProgram GetProgram(uint32_t id, const std::string &opts) const; + // Compiles program + void CompileProgram(uint32_t id, const std::string &opts) const; + + private: + mutable std::string m_cache_path; ///< Path to cache folder + mutable std::map m_programs; ///< Cache of programs by id + mutable std::map m_headers; ///< Headers map + static uint32_t m_next_program_id; + }; +} diff --git a/Baikal/Utils/cl_uberv2_generator.cpp b/Baikal/Utils/cl_uberv2_generator.cpp new file mode 100644 index 00000000..5a6004f5 --- /dev/null +++ b/Baikal/Utils/cl_uberv2_generator.cpp @@ -0,0 +1,647 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "cl_uberv2_generator.h" + +using namespace Baikal; + +inline int popcount(std::uint32_t value) +{ + int count = value ? 1 : 0; + while (value &= (value - 1)) + { + ++count; + } + return count; +} + +CLUberV2Generator::CLUberV2Generator() +{ + +} + +CLUberV2Generator::~CLUberV2Generator() +{ +} + +void CLUberV2Generator::AddMaterial(UberV2Material::Ptr material) +{ + std::uint32_t layers = material->GetLayers(); + // Check if we already have such material type processed + if (m_materials.find(layers) != m_materials.end()) + { + return; + } + + UberV2Sources src; + MaterialGeneratePrepareInputs(material, &src); + MaterialGenerateGetPdf(material, &src); + MaterialGenerateSample(material, &src); + MaterialGenerateGetBxDFType(material, &src); + MaterialGenerateEvaluate(material, &src); + m_materials[layers] = src; +} + +void CLUberV2Generator::MaterialGeneratePrepareInputs(UberV2Material::Ptr material, UberV2Sources *sources) +{ + static const std::string reader_function_arguments("material_attributes[offset++], dg, input_map_values, TEXTURE_ARGS"); + struct LayerReader + { + std::string variable; + std::string reader; + }; + // Should have same order as in ClwSceneController::WriteMaterial + static const std::vector>> readers = + { + { + UberV2Material::Layers::kEmissionLayer, + { + {"data->emission_color", "GetInputMapFloat4"} + } + }, + { + UberV2Material::Layers::kCoatingLayer, + { + {"data->coating_color", "GetInputMapFloat4"}, + {"data->coating_ior", "GetInputMapFloat"} + } + }, + { + UberV2Material::Layers::kReflectionLayer, + { + {"data->reflection_color", "GetInputMapFloat4"}, + {"data->reflection_roughness", "GetInputMapFloat"}, + {"data->reflection_anisotropy", "GetInputMapFloat"}, + {"data->reflection_anisotropy_rotation", "GetInputMapFloat"}, + {"data->reflection_ior", "GetInputMapFloat"}, + {"data->reflection_metalness", "GetInputMapFloat"} + } + }, + { + UberV2Material::Layers::kDiffuseLayer, + { + {"data->diffuse_color", "GetInputMapFloat4"} + } + }, + { + UberV2Material::Layers::kRefractionLayer, + { + {"data->refraction_color", "GetInputMapFloat4"}, + {"data->refraction_roughness", "GetInputMapFloat"}, + {"data->refraction_ior", "GetInputMapFloat"} + } + }, + { + UberV2Material::Layers::kTransparencyLayer, + { + {"data->transparency", "GetInputMapFloat"} + } + }, + { + UberV2Material::Layers::kShadingNormalLayer, + { + {"data->shading_normal", "GetInputMapFloat4"}, + } + }, + { + UberV2Material::Layers::kSSSLayer, + { + {"data->sss_absorption_color", "GetInputMapFloat4"}, + {"data->sss_scatter_color", "GetInputMapFloat4"}, + {"data->sss_subsurface_color", "GetInputMapFloat4"}, + {"data->sss_absorption_distance", "GetInputMapFloat"}, + {"data->sss_scatter_distance", "GetInputMapFloat"}, + {"data->sss_scatter_direction", "GetInputMapFloat"}, + } + } + }; + + + // Reserve 4k. This should be enought for maximum configuration + sources->m_prepare_inputs.reserve(4096); + // Write base code + std::uint32_t layers = material->GetLayers(); + sources->m_prepare_inputs = + "void UberV2PrepareInputs" + std::to_string(layers) + "(" + "DifferentialGeometry const* dg, GLOBAL InputMapData const* restrict input_map_values," + "GLOBAL int const* restrict material_attributes, TEXTURE_ARG_LIST, UberV2ShaderData *data)\n" + "{\n" + "\tint offset = dg->mat.offset + 1;\n"; + + // Write code for each layer + for (auto &reader: readers) + { + // If current layer exist in material - write it + if ((layers & reader.first) == reader.first) + { + for (auto &r : reader.second) + { + sources->m_prepare_inputs += std::string("\t") + r.variable + " = " + r.reader + "(" + reader_function_arguments + ");\n"; + } + } + } + + sources->m_prepare_inputs += "\n}"; +} + +std::string CLUberV2Generator::GenerateBlend(const BlendData &blend_data, bool is_float) +{ + std::string fresnel_function = is_float ? "Fresnel_Blend_F" : "Fresnel_Blend"; + + std::string result = is_float ? "0.0f" : "(float3)(0.0f)"; + result.reserve(1024); //1k should be enought + + std::string brdf; + brdf.reserve(1024); + + auto GenerateFresnelBlend = [&](const std::string &top_ior, const std::string &bottom_ior, + const std::string &top_value, const std::string &bottom_value) -> std::string + { + std::string value = fresnel_function; + value += "(" + top_ior + ", " + bottom_ior + ", " + top_value + ", " + bottom_value + ", wi)"; + return value; + }; + + // Generate BRDF first + if (!blend_data.m_brdf_values.empty()) + { + brdf = "(" + blend_data.m_brdf_values[blend_data.m_brdf_values.size() - 1] + ")"; + for (size_t a = blend_data.m_brdf_iors.size() - 1; a > 0 ; --a) + { + brdf = "(" + GenerateFresnelBlend(blend_data.m_brdf_iors[a - 1], blend_data.m_brdf_iors[a], + blend_data.m_brdf_values[a -1], brdf) + ")"; + } + } + + // Btdf + std::string bxdf(brdf); + if (!blend_data.m_btdf_ior.empty()) + { + if (brdf.empty()) + { + bxdf = "(" + blend_data.m_btdf_value + ")"; + } + else + { + bxdf = "(" + GenerateFresnelBlend("1.0f", blend_data.m_btdf_ior, brdf, blend_data.m_btdf_value) + ")"; + } + } + + if (!bxdf.empty()) + { + result = bxdf; + } + + // Mix for transparency + if (!blend_data.m_transparency_value.empty()) + { + if (!bxdf.empty()) + { + result = "mix(" + result + ", 0.f" + ", " + blend_data.m_transparency_value + ")"; + } + else if (!brdf.empty()) + { + result = "mix(" + result + ", 0.f" + ", " + blend_data.m_transparency_value + ")"; + } + else + { + result = "0.f"; + } + } + return result; +} + +void CLUberV2Generator::MaterialGenerateGetPdf(UberV2Material::Ptr material, UberV2Sources *sources) +{ + std::uint32_t layers = material->GetLayers(); + + sources->m_get_pdf = "float UberV2_GetPdf" + std::to_string(layers) + "(" + "DifferentialGeometry const* dg, float3 wi, float3 wo, TEXTURE_ARG_LIST, UberV2ShaderData const* shader_data)\n" + "{\n"; + + BlendData blend; + blend.m_brdf_iors.push_back("1.0f"); + + // BRDF layers + if ((layers & UberV2Material::Layers::kCoatingLayer) == UberV2Material::Layers::kCoatingLayer) + { + blend.m_brdf_iors.push_back("shader_data->coating_ior"); + blend.m_brdf_values.push_back("UberV2_IdealReflect_GetPdf(shader_data, wi, wo, TEXTURE_ARGS)"); + } + if ((layers & UberV2Material::Layers::kReflectionLayer) == UberV2Material::Layers::kReflectionLayer) + { + blend.m_brdf_iors.push_back("shader_data->reflection_ior"); + blend.m_brdf_values.push_back("UberV2_Reflection_GetPdf(shader_data, wi, wo, TEXTURE_ARGS)"); + } + if ((layers & UberV2Material::Layers::kDiffuseLayer) == UberV2Material::Layers::kDiffuseLayer) + { + blend.m_brdf_values.push_back("UberV2_Lambert_GetPdf(shader_data, wi, wo, TEXTURE_ARGS)"); + } + + // BTDF + if ((layers & UberV2Material::Layers::kRefractionLayer) == UberV2Material::Layers::kRefractionLayer) + { + blend.m_btdf_ior = "shader_data->refraction_ior"; + blend.m_btdf_value = "UberV2_Refraction_GetPdf(shader_data, wi, wo, TEXTURE_ARGS)"; + } + + //Transparency + if ((layers & UberV2Material::Layers::kTransparencyLayer) == UberV2Material::Layers::kTransparencyLayer) + { + blend.m_transparency_value = "shader_data->transparency"; + } + + sources->m_get_pdf += "\treturn " + GenerateBlend(blend, true) + ";\n}\n"; +} + +void CLUberV2Generator::MaterialGenerateSample(UberV2Material::Ptr material, UberV2Sources *sources) +{ + std::uint32_t layers = material->GetLayers(); + sources->m_sample = + "float3 UberV2_Sample" + std::to_string(layers) + "(DifferentialGeometry const* dg, float3 wi, TEXTURE_ARG_LIST, float2 sample, float3* wo, float* pdf," + "UberV2ShaderData const* shader_data)\n" + "{\n" + "\tconst int sampledComponent = Bxdf_UberV2_GetSampledComponent(dg);\n" + "\tfloat3 result;\n" + "\tswitch(sampledComponent)\n" + "\t{\n"; + + std::vector> component_sampling = + { + {UberV2Material::Layers::kTransparencyLayer, + "\t\tcase kBxdfUberV2SampleTransparency: result = UberV2_Passthrough_Sample(shader_data, wi, TEXTURE_ARGS, sample, wo, pdf);\n\t\t\tbreak;\n"}, + {UberV2Material::Layers::kCoatingLayer, + "\t\tcase kBxdfUberV2SampleCoating: result = UberV2_Coating_Sample(shader_data, wi, TEXTURE_ARGS, wo, pdf);\n\t\t\tbreak;\n"}, + {UberV2Material::Layers::kReflectionLayer, + "\t\tcase kBxdfUberV2SampleReflection: result = UberV2_Reflection_Sample(shader_data, wi, TEXTURE_ARGS, sample, wo, pdf);\n\t\t\tbreak;\n" + }, + {UberV2Material::Layers::kRefractionLayer, + "\t\tcase kBxdfUberV2SampleRefraction: result = UberV2_Refraction_Sample(shader_data, wi, TEXTURE_ARGS, sample, wo, pdf);\n\t\t\tbreak;\n"}, + {UberV2Material::Layers::kDiffuseLayer, + "\t\tcase kBxdfUberV2SampleDiffuse: result = UberV2_Lambert_Sample(shader_data, wi, TEXTURE_ARGS, sample, wo, pdf);\n\t\t\tbreak;\n" + } + }; + + for (auto &component : component_sampling) + { + if ((layers & component.first) == component.first) + { + sources->m_sample += component.second; + } + } + + sources->m_sample += + "\t}\n" +// Temporaty disable this code. It leads to incorrect work in UberV2Test +// "\tif (!Bxdf_IsSingular(dg))\n" + "\tif (false)\n" + "\t{\n" + "\t\t*pdf = UberV2_GetPdf" + std::to_string(layers) + "(dg, wi, *wo, TEXTURE_ARGS, shader_data);\n" + "\t\treturn UberV2_Evaluate" + std::to_string(layers) + "(dg, wi, *wo, TEXTURE_ARGS, shader_data);\n" + "\t}\n" + "\treturn result;\n" + "}\n"; +} +void CLUberV2Generator::MaterialGenerateGetBxDFType(UberV2Material::Ptr material, UberV2Sources *sources) +{ + std::uint32_t layers = material->GetLayers(); + sources->m_get_bxdf_type = "void GetMaterialBxDFType" + std::to_string(layers) + "(" + "float3 wi, Sampler* sampler, SAMPLER_ARG_LIST, DifferentialGeometry* dg, UberV2ShaderData const* shader_data)\n" + "{\n" + "\tint bxdf_flags = 0;\n"; + + // If we have layer that requires fresnel blend (reflection/refraction/coating) + if ((layers & + (UberV2Material::Layers::kReflectionLayer | UberV2Material::Layers::kRefractionLayer | UberV2Material::Layers::kCoatingLayer )) + != 0) + { + sources->m_get_bxdf_type += "\tconst float ndotwi = dot(dg->n, wi);\n"; + } + + if ((layers & UberV2Material::Layers::kEmissionLayer) == UberV2Material::Layers::kEmissionLayer) + { + sources->m_get_bxdf_type += "\tbxdf_flags |= kBxdfFlagsEmissive;\n"; + } + + //Check if blend layers have underlying layers + bool transparency_has_underlying_layer = popcount(layers & ( + UberV2Material::Layers::kRefractionLayer | + UberV2Material::Layers::kCoatingLayer | + UberV2Material::Layers::kReflectionLayer | + UberV2Material::Layers::kDiffuseLayer)) != 0; + + bool refraction_has_underlying_layer = popcount(layers & ( + UberV2Material::Layers::kCoatingLayer | + UberV2Material::Layers::kReflectionLayer | + UberV2Material::Layers::kDiffuseLayer)) != 0; + + bool coating_has_underlying_layer = popcount(layers & ( + UberV2Material::Layers::kReflectionLayer | + UberV2Material::Layers::kDiffuseLayer)) != 0; + + bool reflection_has_underlying_layer = popcount(layers & ( + UberV2Material::Layers::kDiffuseLayer)) != 0; + + if ((layers & UberV2Material::Layers::kTransparencyLayer) == UberV2Material::Layers::kTransparencyLayer) + { + // If layer have transparency check in OpenCL if we sample it and if we sample it - return + sources->m_get_bxdf_type += + (transparency_has_underlying_layer ? + "\tconst float sample = Sampler_Sample1D(sampler, SAMPLER_ARGS);\n" + "\tif (sample < shader_data->transparency)\n" + "\t{\n" : "") + + std::string( + "\t\tbxdf_flags |= (kBxdfFlagsTransparency | kBxdfFlagsSingular);\n" + "\t\tBxdf_SetFlags(dg, bxdf_flags);\n" + "\t\tBxdf_UberV2_SetSampledComponent(dg, kBxdfUberV2SampleTransparency);\n" + "\t\treturn;\n") + + (transparency_has_underlying_layer ? "\t}\n" : ""); + } + + // Check refraction layer. If we have it and plan to sample it - set flags and sampled component + if ((layers & UberV2Material::Layers::kRefractionLayer) == UberV2Material::Layers::kRefractionLayer) + { + sources->m_get_bxdf_type += + (refraction_has_underlying_layer ? + "\tconst float sample1 = Sampler_Sample1D(sampler, SAMPLER_ARGS);\n" + "\tconst float fresnel = CalculateFresnel(1.0f, shader_data->refraction_ior, ndotwi);\n" + "\tif (sample1 >= fresnel)\n" + "\t{\n" : "") + + std::string("\t\tBxdf_UberV2_SetSampledComponent(dg, kBxdfUberV2SampleRefraction);\n" + "\t\tif (shader_data->refraction_roughness < ROUGHNESS_EPS)\n" + "\t\t{\n" + "\t\t\tbxdf_flags |= kBxdfFlagsSingular;\n" + "\t\t}\n" + "\t\tBxdf_SetFlags(dg, bxdf_flags);\n" + "\t\treturn;\n") + + (refraction_has_underlying_layer ? "\t}\n" : ""); + } + + if ((layers & + (UberV2Material::Layers::kReflectionLayer | UberV2Material::Layers::kRefractionLayer | UberV2Material::Layers::kCoatingLayer )) + != 0) + { + sources->m_get_bxdf_type += + "\tbxdf_flags |= kBxdfFlagsBrdf;\n" + "\tfloat top_ior = 1.0f;\n"; + } + + if ((layers & UberV2Material::Layers::kCoatingLayer) == UberV2Material::Layers::kCoatingLayer) + { + sources->m_get_bxdf_type += + (coating_has_underlying_layer ? + "\tconst float sample3 = Sampler_Sample1D(sampler, SAMPLER_ARGS);\n" + "\tconst float fresnel1 = CalculateFresnel(top_ior, shader_data->coating_ior, ndotwi);\n" + "\tif (sample3 < fresnel1)\n" + "\t{\n" : "") + + std::string( + "\t\tbxdf_flags |= kBxdfFlagsSingular;\n" + "\t\tBxdf_SetFlags(dg, bxdf_flags);\n" + "\t\tBxdf_UberV2_SetSampledComponent(dg, kBxdfUberV2SampleCoating);\n" + "\t\treturn;\n") + + (coating_has_underlying_layer ? + "\t}\n" + "\ttop_ior = shader_data->coating_ior;\n" : ""); + } + + if ((layers & UberV2Material::Layers::kReflectionLayer) == UberV2Material::Layers::kReflectionLayer) + { + sources->m_get_bxdf_type += + (reflection_has_underlying_layer ? + "\tconst float fresnel2 = CalculateFresnel(top_ior, shader_data->reflection_ior, ndotwi);\n" + "\tconst float sample4 = Sampler_Sample1D(sampler, SAMPLER_ARGS);\n" + "\tif (sample4 < fresnel2)\n" + "\t{\n" : "") + + std::string( + "\t\tif (shader_data->reflection_roughness < ROUGHNESS_EPS)\n" + "\t\t{\n" + "\t\t\tbxdf_flags |= kBxdfFlagsSingular;\n" + "\t\t}\n" + "\t\tBxdf_UberV2_SetSampledComponent(dg, kBxdfUberV2SampleReflection);\n" + "\t\tBxdf_SetFlags(dg, bxdf_flags);\n" + "\t\treturn;\n") + + (reflection_has_underlying_layer ? "\t}\n" : ""); + + } + + if ((layers & UberV2Material::Layers::kDiffuseLayer) == UberV2Material::Layers::kDiffuseLayer) + { + sources->m_get_bxdf_type += + "\tBxdf_UberV2_SetSampledComponent(dg, kBxdfUberV2SampleDiffuse);\n" + "\tbxdf_flags |= kBxdfFlagsBrdf;\n"; + } + sources->m_get_bxdf_type += + "\tBxdf_SetFlags(dg, bxdf_flags);\n" + "return;\n" + "}\n"; +} + +void CLUberV2Generator::MaterialGenerateEvaluate(UberV2Material::Ptr material, UberV2Sources *sources) +{ + std::uint32_t layers = material->GetLayers(); + + sources->m_evaluate = "float3 UberV2_Evaluate" + std::to_string(layers) + "(" + "DifferentialGeometry const* dg, float3 wi, float3 wo, TEXTURE_ARG_LIST, UberV2ShaderData const* shader_data)\n" + "{\n"; + + BlendData blend; + blend.m_brdf_iors.push_back("1.0f"); + + // BRDF layers + if ((layers & UberV2Material::Layers::kCoatingLayer) == UberV2Material::Layers::kCoatingLayer) + { + blend.m_brdf_iors.push_back("shader_data->coating_ior"); + blend.m_brdf_values.push_back("UberV2_IdealReflect_Evaluate(shader_data, wi, wo, TEXTURE_ARGS)"); + } + if ((layers & UberV2Material::Layers::kReflectionLayer) == UberV2Material::Layers::kReflectionLayer) + { + blend.m_brdf_iors.push_back("shader_data->reflection_ior"); + blend.m_brdf_values.push_back("UberV2_Reflection_Evaluate(shader_data, wi, wo, TEXTURE_ARGS)"); + } + if ((layers & UberV2Material::Layers::kDiffuseLayer) == UberV2Material::Layers::kDiffuseLayer) + { + blend.m_brdf_values.push_back("UberV2_Lambert_Evaluate(shader_data, wi, wo, TEXTURE_ARGS)"); + } + + // BTDF + if ((layers & UberV2Material::Layers::kRefractionLayer) == UberV2Material::Layers::kRefractionLayer) + { + blend.m_btdf_ior = "shader_data->refraction_ior"; + blend.m_btdf_value = "UberV2_Refraction_Evaluate(shader_data, wi, wo, TEXTURE_ARGS)"; + } + + //Transparency + if ((layers & UberV2Material::Layers::kTransparencyLayer) == UberV2Material::Layers::kTransparencyLayer) + { + blend.m_transparency_value = "shader_data->transparency"; + } + + sources->m_evaluate += "\treturn " + GenerateBlend(blend, false) + ";\n}\n"; +} + +std::string Baikal::CLUberV2Generator::BuildSource() +{ + std::string source; + source.reserve(10240); //10k should be enought + + // Merge all per-material sources + for(auto material : m_materials) + { + source += material.second.m_get_bxdf_type + "\n"; + source += material.second.m_evaluate + "\n"; + source += material.second.m_get_pdf + "\n"; + source += material.second.m_prepare_inputs + "\n"; + source += material.second.m_sample + "\n"; + } + source += GeneratePrepareInputsDispatcher(); + source += GenerateGetBxDFTypeDispatcher(); + source += GenerateGetPdfDispatcher(); + source += GenerateEvaluateDispatcher(); + source += GenerateSampleDispatcher(); + + return source; +} + +std::string Baikal::CLUberV2Generator::GenerateEvaluateDispatcher() +{ + std::string source; + source.reserve(1024); //10k should be enought + + source = "float3 UberV2_Evaluate" + "(DifferentialGeometry const* dg, float3 wi, float3 wo, TEXTURE_ARG_LIST, UberV2ShaderData const* shader_data)\n" + "{\n" + "\tfloat3 wi_t = matrix_mul_vector3(dg->world_to_tangent, wi);\n" + "\tfloat3 wo_t = matrix_mul_vector3(dg->world_to_tangent, wo);\n" + "\tswitch (dg->mat.layers)\n" + "\t{\n"; + + for(auto material : m_materials) + { + source += "\t\tcase " + std::to_string(material.first) + ":\n" + + "\t\t\treturn UberV2_Evaluate" + std::to_string(material.first) + "(dg, wi_t, wo_t, TEXTURE_ARGS, shader_data);\n"; + } + + source += "\t}\n\treturn (float3)(0.0f);\n}\n"; + + return source; +} + +std::string Baikal::CLUberV2Generator::GenerateGetPdfDispatcher() +{ + std::string source; + source.reserve(1024); //10k should be enought + + source = "float UberV2_GetPdf" + "(DifferentialGeometry const* dg, float3 wi, float3 wo, TEXTURE_ARG_LIST, UberV2ShaderData const* shader_data)\n" + "{\n" + "\tfloat3 wi_t = matrix_mul_vector3(dg->world_to_tangent, wi);\n" + "\tfloat3 wo_t = matrix_mul_vector3(dg->world_to_tangent, wo);\n" + "\tswitch (dg->mat.layers)\n" + "\t{\n"; + + for(auto material : m_materials) + { + source += "\t\tcase " + std::to_string(material.first) + ":\n" + + "\t\t\treturn UberV2_GetPdf" + std::to_string(material.first) + "(dg, wi_t, wo_t, TEXTURE_ARGS, shader_data);\n"; + } + + source += "\t}\n\treturn 0.0f;\n}\n"; + + return source; +} + +std::string Baikal::CLUberV2Generator::GenerateSampleDispatcher() +{ + std::string source; + source.reserve(1024); //10k should be enought + + source = "float3 UberV2_Sample" + "(DifferentialGeometry const* dg, float3 wi, TEXTURE_ARG_LIST, float2 sample, " + "float3 *wo, float *pdf, UberV2ShaderData const* shader_data)\n" + "{\n" + "\tfloat3 wi_t = matrix_mul_vector3(dg->world_to_tangent, wi);\n" + "\tfloat3 wo_t;\n" + "\tfloat3 res = 0.f;\n" + "\tswitch (dg->mat.layers)\n" + "\t{\n"; + + for(auto material : m_materials) + { + source += "\t\tcase " + std::to_string(material.first) + ":\n" + + "\t\t\tres = UberV2_Sample" + std::to_string(material.first) + "(dg, wi_t, TEXTURE_ARGS, sample, &wo_t, pdf, shader_data);\n" + "\t\t\tbreak;\n"; + } + + source += "\t}\n" + "\t*wo = matrix_mul_vector3(dg->tangent_to_world, wo_t);" + "\treturn res;\n" + "}\n"; + + return source; +} + +std::string Baikal::CLUberV2Generator::GeneratePrepareInputsDispatcher() +{ + std::string source = + "void UberV2PrepareInputs(" + "DifferentialGeometry const* dg, GLOBAL InputMapData const* restrict input_map_values," + "GLOBAL int const* restrict material_attributes, TEXTURE_ARG_LIST, UberV2ShaderData *shader_data)\n" + "{\n" + "\tswitch(dg->mat.layers)\n" + "\t{\n"; + + for(auto material : m_materials) + { + source += "\t\tcase " + std::to_string(material.first) + ":\n" + + "\t\t\treturn UberV2PrepareInputs" + std::to_string(material.first) + "(dg, input_map_values, material_attributes, TEXTURE_ARGS, shader_data);\n"; + } + + source += "\t}\n" + "}\n"; + + return source; + +} + +std::string Baikal::CLUberV2Generator::GenerateGetBxDFTypeDispatcher() +{ + std::string source = + "void GetMaterialBxDFType(" + "float3 wi, Sampler* sampler, SAMPLER_ARG_LIST, DifferentialGeometry* dg, UberV2ShaderData const* shader_data)" + "{\n" + "\tswitch(dg->mat.layers)\n" + "\t{\n"; + + for(auto material : m_materials) + { + source += "\t\tcase " + std::to_string(material.first) + ":\n" + + "\t\t\treturn GetMaterialBxDFType" + std::to_string(material.first) + "(wi, sampler, SAMPLER_ARGS, dg, shader_data);\n" + "\t\t\tbreak;\n"; + } + + source += "\t}\n" + "}\n"; + + return source; +} + + diff --git a/Baikal/Utils/cl_uberv2_generator.h b/Baikal/Utils/cl_uberv2_generator.h new file mode 100644 index 00000000..97b95d8c --- /dev/null +++ b/Baikal/Utils/cl_uberv2_generator.h @@ -0,0 +1,138 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ + +#pragma once + +#include + +#include "SceneGraph/uberv2material.h" + +namespace Baikal +{ + class CLUberV2Generator + { + public: + CLUberV2Generator(); + ~CLUberV2Generator(); + /** + * @brief Adds material to generator + * + * Adds material to generator. Generates all per-material functions if + * material with such layer combination wasn't added before + */ + void AddMaterial(UberV2Material::Ptr material); + + /** + * @brief generates source for uber material implementation + * + * Generates full source code of UberV2 material. It generates following things: + * - All per-material type functions + * - All selectors for per-material type functions + * + * @return generated source + */ + std::string BuildSource(); + + private: + struct UberV2Sources + { + std::string m_prepare_inputs; + std::string m_get_pdf; + std::string m_sample; + std::string m_get_bxdf_type; + std::string m_evaluate; + }; + + struct BlendData + { + std::vector m_brdf_iors; + std::vector m_brdf_values; + std::string m_btdf_ior; + std::string m_btdf_value; + std::string m_transparency_value; + }; + + /** + * @brief Generates blend for material + * + * Generates following code: + * result = mix(BxDF, 0.0f, transparency) where + * BxDF = F(1.0, refraction_ior) * BRDF + (1.0f - F(1.0, refraction_ior)) * refraction + * BRDF = F(1.0, coating_ior) * coating + (1.0f - F(1.0f, coating_ior) * + * (F(coating_ior, reflection_ior) * reflection + (1.0f - F(coating_ior, reflection_ior)) * diffuse) + * + * @param is_float should be set to true if generating blend for float value and false if generating for float4 + */ + std::string GenerateBlend(const BlendData &blend_data, bool is_float); + + /** + * @brief Generates function that will fill ShaderData structure with values + */ + void MaterialGeneratePrepareInputs(UberV2Material::Ptr material, UberV2Sources *sources); + + /** + * @brief Generates function for PDF calculation on material + * + * Generated function do following: + * - Calculates fresnel blend for all active layers on PDF + * - If material have single layer - directly return it + * - If we have mix - calculate following result: + * result = mix(BxDF, 0.0f, transparency) where + * BxDF = F(1.0, refraction_ior) * BRDF + (1.0f - F(1.0, refraction_ior)) * refraction + * BRDF = F(1.0, coating_ior) * coating + (1.0f - F(1.0f, coating_ior) * + * (F(coating_ior, reflection_ior) * reflection + (1.0f - F(coating_ior, reflection_ior)) * diffuse) + */ + void MaterialGenerateGetPdf(UberV2Material::Ptr material, UberV2Sources *sources); + /** + * @brief Generates material sampling function + */ + void MaterialGenerateSample(UberV2Material::Ptr material, UberV2Sources *sources); + /** + * @brief Generates function that will fill BxDF flags + * + * Function sets BxDF flags for provided material and select layer that will be sampled on current iteration + */ + void MaterialGenerateGetBxDFType(UberV2Material::Ptr material, UberV2Sources *sources); + /** + * @brief Generates material evaluation function + * + * Generated function do following: + * - Calculates fresnel blend for all active layers + * - If material have single layer - directly return it + * - If we have mix - calculate following result: + * result = mix(BxDF, 0.0f, transparency) where + * BxDF = F(1.0, refraction_ior) * BRDF + (1.0f - F(1.0, refraction_ior)) * refraction + * BRDF = F(1.0, coating_ior) * coating + (1.0f - F(1.0f, coating_ior) * + * (F(coating_ior, reflection_ior) * reflection + (1.0f - F(coating_ior, reflection_ior)) * diffuse) + */ + void MaterialGenerateEvaluate(UberV2Material::Ptr material, UberV2Sources *sources); + + std::string GenerateGetPdfDispatcher(); + std::string GenerateEvaluateDispatcher(); + std::string GenerateSampleDispatcher(); + std::string GenerateGetBxDFTypeDispatcher(); + std::string GeneratePrepareInputsDispatcher(); + + std::map m_materials; + }; + +} diff --git a/Baikal/Utils/clw_class.h b/Baikal/Utils/clw_class.h new file mode 100644 index 00000000..16adac04 --- /dev/null +++ b/Baikal/Utils/clw_class.h @@ -0,0 +1,130 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "CLW.h" +#include "version.h" +#include "cl_program_manager.h" + +namespace Baikal +{ + class ClwClass + { + public: +#ifdef BAIKAL_EMBED_KERNELS + //create from source + ClwClass(CLWContext context, + const CLProgramManager *program_manager, + std::string const& name, + std::string const& source, + std::unordered_map const& headers, + std::string const& opts = ""); +#else + //create from file + ClwClass(CLWContext context, + const CLProgramManager *program_manager, + std::string const& cl_file, + std::string const& opts = ""); +#endif + + virtual ~ClwClass() = default; + + CLWContext GetContext() const { return m_context; } + CLWKernel GetKernel(std::string const& name, std::string const& opts = ""); + void SetDefaultBuildOptions(std::string const& opts); + std::string GetDefaultBuildOpts() const { return m_default_opts; } + std::string GetFullBuildOpts() const; + + private: + void AddCommonOptions(std::string& opts) const; + + // Context to build programs for + CLWContext m_context; + // Program manager pointer + const CLProgramManager *m_program_manager; + // Program id + uint32_t m_program_id; + // Default build options + std::string m_default_opts; + }; + +#ifdef BAIKAL_EMBED_KERNELS + inline ClwClass::ClwClass( + CLWContext context, + const CLProgramManager *program_manager, + std::string const& name, + std::string const& source, + std::unordered_map const& headers, + std::string const& opts) + : m_context(context) + , m_program_manager(program_manager) + { + auto options = opts; + AddCommonOptions(options); + + m_program_id = m_program_manager->CreateProgramFromSource(context, name, source); + for (auto const& header : headers) + { + m_program_manager->AddHeader(header.first, header.second); + } + } +#else + inline ClwClass::ClwClass( + CLWContext context, + const CLProgramManager *program_manager, + std::string const& cl_file, + std::string const& opts) + : m_context(context) + , m_program_manager(program_manager) + { + auto options = opts; + AddCommonOptions(options); + + m_program_id = m_program_manager->CreateProgramFromFile(context, cl_file); + } +#endif + + inline CLWKernel ClwClass::GetKernel(std::string const& name, std::string const& opts) + { + std::string options = opts.empty() ? m_default_opts : opts; + AddCommonOptions(options); + return m_program_manager->GetProgram(m_program_id, options).GetKernel(name); + } + + + inline void ClwClass::AddCommonOptions(std::string& opts) const + { + opts.append(" -cl-mad-enable -cl-fast-relaxed-math " + "-cl-std=CL1.2 -I . "); + + opts.append( +#if defined(__APPLE__) + "-D APPLE " +#elif defined(_WIN32) || defined (WIN32) + "-D WIN32 " +#elif defined(__linux__) + "-D __linux__ " +#else + "" +#endif + ); + } + + inline std::string ClwClass::GetFullBuildOpts() const + { + auto options = m_default_opts; + AddCommonOptions(options); + return options; + } + + inline void ClwClass::SetDefaultBuildOptions(std::string const& opts) + { + m_default_opts = opts; + } +} diff --git a/Baikal/Utils/cmd_parser.cpp b/Baikal/Utils/cmd_parser.cpp new file mode 100644 index 00000000..a2ebb198 --- /dev/null +++ b/Baikal/Utils/cmd_parser.cpp @@ -0,0 +1,62 @@ +/********************************************************************** +Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + +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 "Utils/cmd_parser.h" +#include + +namespace Baikal +{ + + CmdParser::CmdParser(int argc, char* argv[]) + { + if (argc < 0) + { + throw std::logic_error(std::string(__func__) + ": 'argc' can't be negative"); + } + if (!argv) + { + throw std::logic_error(std::string(__func__) + ": 'argv' is nulltpr"); + } + + m_cmd_line = { argv, argv + argc }; + } + + bool CmdParser::OptionExists(const std::string& option) const + { + return (std::find(m_cmd_line.begin(), m_cmd_line.end(), option) != m_cmd_line.end()); + } + + const std::string* CmdParser::GetOptionValue(const std::string& option) const + { + auto it = std::find(m_cmd_line.begin(), m_cmd_line.end(), option); + + if ((it == m_cmd_line.end()) || (++it == m_cmd_line.end())) + { + return nullptr; + } + else + { + return &(*it); + } + } + +} \ No newline at end of file diff --git a/Baikal/Utils/cmd_parser.h b/Baikal/Utils/cmd_parser.h new file mode 100644 index 00000000..fa0f9498 --- /dev/null +++ b/Baikal/Utils/cmd_parser.h @@ -0,0 +1,105 @@ +/********************************************************************** +Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ + +#pragma once + +#include +#include +#include +#include + + +namespace Baikal +{ + + class CmdParser + { + public: + // 'argc' - number of the command line arguments + // 'argv' - command line arguments string + CmdParser(int argc, char* argv[]); + + // 'option' - name of the option in command line + // returns true in case there's exist + bool OptionExists(const std::string& option) const; + + // 'option' - name of the option in command line + // return the value of the option (the format of the strign should be 'option' 'value') + template + T GetOption(const std::string& option) const + { + auto value = GetOptionValue(option); + + if (!value) + { + std::stringstream ss; + + ss << __func__ << ": " + << option << " :option or its value is missed"; + + throw std::logic_error(ss.str()); + } + + return LexicalCast>>(*value); + } + + // 'option' - name of the option in command line + // 'default_value' - default value if option wasn't specified + // return the value of the option (the format of the strign should be 'option' 'value') or 'default_value' + template + std::decay_t GetOption(const std::string& option, T default_value) const + { + auto value = GetOptionValue(option); + + if (!value) + { + return std::forward(default_value); + } + else + { + return LexicalCast>(*value); + } + } + + private: + const std::string* GetOptionValue(const std::string& option) const; + + template + static T LexicalCast(const std::string& str) + { + T var; + + std::istringstream iss(str); + + if (iss.fail()) + { + throw std::logic_error(std::string(__func__) + "cmd stream failed"); + } + + iss >> var; + return var; + } + + std::vector m_cmd_line; + }; + +} \ No newline at end of file diff --git a/Baikal/Utils/distribution1d.cpp b/Baikal/Utils/distribution1d.cpp new file mode 100644 index 00000000..3bb45ba7 --- /dev/null +++ b/Baikal/Utils/distribution1d.cpp @@ -0,0 +1,81 @@ +#include "distribution1d.h" +#include "math/mathutils.h" + +#include +#include + +namespace Baikal +{ + Distribution1D::Distribution1D() + : m_num_segments(0u) + { + } + + Distribution1D::Distribution1D(float const* values, std::uint32_t num_segments) + { + Set(values, num_segments); + } + + void Distribution1D::Set(float const* values, std::uint32_t num_segments) + { + assert(num_segments > 0); + m_num_segments = num_segments; + m_func_values.resize(num_segments); + m_cdf.resize(num_segments + 1); + + // Copy function values + std::copy(values, values + num_segments, m_func_values.begin()); + + // Calculate CDF + m_cdf[0] = 0.f; + for (auto i = 1u; i < num_segments + 1; ++i) + { + m_cdf[i] = m_cdf[i - 1] + m_func_values[i - 1] / num_segments; + } + + // Calculate normalizer + m_func_sum = m_cdf[num_segments]; + + // Normalize CDF + for (auto i = 0u; i < num_segments + 1; ++i) + { + m_cdf[i] /= m_func_sum; + } + } + + float Distribution1D::Sample1D(float u, float& pdf) const + { + assert(m_num_segments > 0); + + // Find the segment here u lies + // this one is in [0, N-1] and we need to handle corner case: + // for 0 it returns 0 index + auto iter = std::lower_bound(m_cdf.cbegin(), m_cdf.cend(), u); + + // Find segment index : clamp it as last may be returned for 1 + auto segment_idx = std::max((std::uint32_t)std::distance(m_cdf.cbegin(), iter), 1u); + + assert(u >= m_cdf[segment_idx - 1] && u <= m_cdf[segment_idx]); + + // Find lerp coefficient + float du = (u - m_cdf[segment_idx - 1]) / (m_cdf[segment_idx] - m_cdf[segment_idx - 1]); + + // Calc pdf + pdf = m_func_values[segment_idx - 1] / m_func_sum; + + // Return corresponding value + return (segment_idx - 1 + du) / m_num_segments; + } + + float Distribution1D::pdf(float u) const + { + // Find the segment here u lies + auto iter = std::lower_bound(m_cdf.cbegin(), m_cdf.cend(), u); + + // Find segment index : clamp it as last may be returned for 1 + auto segment_idx = std::max((std::uint32_t)std::distance(m_cdf.cbegin(), iter), 1u); + + // Calc pdf + return m_func_values[segment_idx - 1] / m_func_sum; + } +} \ No newline at end of file diff --git a/Baikal/Utils/distribution1d.h b/Baikal/Utils/distribution1d.h new file mode 100644 index 00000000..13c3f90a --- /dev/null +++ b/Baikal/Utils/distribution1d.h @@ -0,0 +1,58 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once + +#include +#include + +namespace Baikal +{ + ///< The class represents 1D piecewise constant distribution of random variable. + ///< The PDF is proprtional to passed function defined at N points in [0,1] interval + ///< Partially taken from Pharr & Humphreys, but a bug with lower bound fixed. + ///< + struct Distribution1D + { + public: + // values are function values at equal spacing at numsegments points within [0,1] range + Distribution1D(); + Distribution1D(float const* values, std::uint32_t num_segments); + + void Set(float const* values, std::uint32_t num_segments); + + // Sample one value using this distribution + // u is uniformely distributed random var + float Sample1D(float u, float& pdf) const; + + // PDF + float pdf(float u) const; + + // Function values + std::vector m_func_values; + // Cumulative distribution function + std::vector m_cdf; + // Number of segments + std::uint32_t m_num_segments; + // Integral of the function over the whole range (normalizer) + float m_func_sum; + }; +} \ No newline at end of file diff --git a/Baikal/Utils/eLut.h b/Baikal/Utils/eLut.h new file mode 100644 index 00000000..f028cdbb --- /dev/null +++ b/Baikal/Utils/eLut.h @@ -0,0 +1,71 @@ +// +// This is an automatically generated file. +// Do not edit. +// + +{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1024, 2048, 3072, 4096, 5120, 6144, 7168, + 8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360, + 16384, 17408, 18432, 19456, 20480, 21504, 22528, 23552, + 24576, 25600, 26624, 27648, 28672, 29696, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 33792, 34816, 35840, 36864, 37888, 38912, 39936, + 40960, 41984, 43008, 44032, 45056, 46080, 47104, 48128, + 49152, 50176, 51200, 52224, 53248, 54272, 55296, 56320, + 57344, 58368, 59392, 60416, 61440, 62464, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; diff --git a/Baikal/Utils/half.cpp b/Baikal/Utils/half.cpp new file mode 100644 index 00000000..09a50aa2 --- /dev/null +++ b/Baikal/Utils/half.cpp @@ -0,0 +1,310 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may 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. +// +/////////////////////////////////////////////////////////////////////////// + +// Primary authors: +// Florian Kainz +// Rod Bogart + + +//--------------------------------------------------------------------------- +// +// class half -- +// implementation of non-inline members +// +//--------------------------------------------------------------------------- + +#include +#include "half.h" + +using namespace std; + +//------------------------------------------------------------- +// Lookup tables for half-to-float and float-to-half conversion +//------------------------------------------------------------- + +HALF_EXPORT const half::uif half::_toFloat[1 << 16] = + #include "toFloat.h" +HALF_EXPORT const unsigned short half::_eLut[1 << 9] = + #include "eLut.h" + +//----------------------------------------------- +// Overflow handler for float-to-half conversion; +// generates a hardware floating-point overflow, +// which may be trapped by the operating system. +//----------------------------------------------- + +HALF_EXPORT float +half::overflow () +{ + volatile float f = 1e10; + + for (int i = 0; i < 10; i++) + f *= f; // this will overflow before + // the for­loop terminates + return f; +} + + +//----------------------------------------------------- +// Float-to-half conversion -- general case, including +// zeroes, denormalized numbers and exponent overflows. +//----------------------------------------------------- + +HALF_EXPORT short +half::convert (int i) +{ + // + // Our floating point number, f, is represented by the bit + // pattern in integer i. Disassemble that bit pattern into + // the sign, s, the exponent, e, and the significand, m. + // Shift s into the position where it will go in in the + // resulting half number. + // Adjust e, accounting for the different exponent bias + // of float and half (127 versus 15). + // + + int s = (i >> 16) & 0x00008000; + int e = ((i >> 23) & 0x000000ff) - (127 - 15); + int m = i & 0x007fffff; + + // + // Now reassemble s, e and m into a half: + // + + if (e <= 0) + { + if (e < -10) + { + // + // E is less than -10. The absolute value of f is + // less than HALF_MIN (f may be a small normalized + // float, a denormalized float or a zero). + // + // We convert f to a half zero with the same sign as f. + // + + return s; + } + + // + // E is between -10 and 0. F is a normalized float + // whose magnitude is less than HALF_NRM_MIN. + // + // We convert f to a denormalized half. + // + + // + // Add an explicit leading 1 to the significand. + // + + m = m | 0x00800000; + + // + // Round to m to the nearest (10+e)-bit value (with e between + // -10 and 0); in case of a tie, round to the nearest even value. + // + // Rounding may cause the significand to overflow and make + // our number normalized. Because of the way a half's bits + // are laid out, we don't have to treat this case separately; + // the code below will handle it correctly. + // + + int t = 14 - e; + int a = (1 << (t - 1)) - 1; + int b = (m >> t) & 1; + + m = (m + a + b) >> t; + + // + // Assemble the half from s, e (zero) and m. + // + + return s | m; + } + else if (e == 0xff - (127 - 15)) + { + if (m == 0) + { + // + // F is an infinity; convert f to a half + // infinity with the same sign as f. + // + + return s | 0x7c00; + } + else + { + // + // F is a NAN; we produce a half NAN that preserves + // the sign bit and the 10 leftmost bits of the + // significand of f, with one exception: If the 10 + // leftmost bits are all zero, the NAN would turn + // into an infinity, so we have to set at least one + // bit in the significand. + // + + m >>= 13; + return s | 0x7c00 | m | (m == 0); + } + } + else + { + // + // E is greater than zero. F is a normalized float. + // We try to convert f to a normalized half. + // + + // + // Round to m to the nearest 10-bit value. In case of + // a tie, round to the nearest even value. + // + + m = m + 0x00000fff + ((m >> 13) & 1); + + if (m & 0x00800000) + { + m = 0; // overflow in significand, + e += 1; // adjust exponent + } + + // + // Handle exponent overflow + // + + if (e > 30) + { + overflow (); // Cause a hardware floating point overflow; + return s | 0x7c00; // if this returns, the half becomes an + } // infinity with the same sign as f. + + // + // Assemble the half from s, e and m. + // + + return s | (e << 10) | (m >> 13); + } +} + + +//--------------------- +// Stream I/O operators +//--------------------- + +HALF_EXPORT ostream & +operator << (ostream &os, half h) +{ + os << float (h); + return os; +} + + +HALF_EXPORT istream & +operator >> (istream &is, half &h) +{ + float f; + is >> f; + h = half (f); + return is; +} + + +//--------------------------------------- +// Functions to print the bit-layout of +// floats and halfs, mostly for debugging +//--------------------------------------- + +HALF_EXPORT void +printBits (ostream &os, half h) +{ + unsigned short b = h.bits(); + + for (int i = 15; i >= 0; i--) + { + os << (((b >> i) & 1)? '1': '0'); + + if (i == 15 || i == 10) + os << ' '; + } +} + + +HALF_EXPORT void +printBits (ostream &os, float f) +{ + half::uif x; + x.f = f; + + for (int i = 31; i >= 0; i--) + { + os << (((x.i >> i) & 1)? '1': '0'); + + if (i == 31 || i == 23) + os << ' '; + } +} + + +HALF_EXPORT void +printBits (char c[19], half h) +{ + unsigned short b = h.bits(); + + for (int i = 15, j = 0; i >= 0; i--, j++) + { + c[j] = (((b >> i) & 1)? '1': '0'); + + if (i == 15 || i == 10) + c[++j] = ' '; + } + + c[18] = 0; +} + + +HALF_EXPORT void +printBits (char c[35], float f) +{ + half::uif x; + x.f = f; + + for (int i = 31, j = 0; i >= 0; i--, j++) + { + c[j] = (((x.i >> i) & 1)? '1': '0'); + + if (i == 31 || i == 23) + c[++j] = ' '; + } + + c[34] = 0; +} diff --git a/Baikal/Utils/half.h b/Baikal/Utils/half.h new file mode 100644 index 00000000..765249ca --- /dev/null +++ b/Baikal/Utils/half.h @@ -0,0 +1,765 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may 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. +// +/////////////////////////////////////////////////////////////////////////// + +// Primary authors: +// Florian Kainz +// Rod Bogart + +//--------------------------------------------------------------------------- +// +// half -- a 16-bit floating point number class: +// +// Type half can represent positive and negative numbers whose +// magnitude is between roughly 6.1e-5 and 6.5e+4 with a relative +// error of 9.8e-4; numbers smaller than 6.1e-5 can be represented +// with an absolute error of 6.0e-8. All integers from -2048 to +// +2048 can be represented exactly. +// +// Type half behaves (almost) like the built-in C++ floating point +// types. In arithmetic expressions, half, float and double can be +// mixed freely. Here are a few examples: +// +// half a (3.5); +// float b (a + sqrt (a)); +// a += b; +// b += a; +// b = a + 7; +// +// Conversions from half to float are lossless; all half numbers +// are exactly representable as floats. +// +// Conversions from float to half may not preserve a float's value +// exactly. If a float is not representable as a half, then the +// float value is rounded to the nearest representable half. If a +// float value is exactly in the middle between the two closest +// representable half values, then the float value is rounded to +// the closest half whose least significant bit is zero. +// +// Overflows during float-to-half conversions cause arithmetic +// exceptions. An overflow occurs when the float value to be +// converted is too large to be represented as a half, or if the +// float value is an infinity or a NAN. +// +// The implementation of type half makes the following assumptions +// about the implementation of the built-in C++ types: +// +// float is an IEEE 754 single-precision number +// sizeof (float) == 4 +// sizeof (unsigned int) == sizeof (float) +// alignof (unsigned int) == alignof (float) +// sizeof (unsigned short) == 2 +// +//--------------------------------------------------------------------------- + +#ifndef _HALF_H_ +#define _HALF_H_ + +#ifdef WIN32 +#ifdef BAIKAL_EXPORT_DATA_SYMBOLS +#define HALF_EXPORT __declspec(dllexport) +#else +#define HALF_EXPORT __declspec(dllimport) +#endif +#else +#define HALF_EXPORT +#endif +#include + +class half +{ + public: + + //------------- + // Constructors + //------------- + + half (); // no initialization + half (float f); + + + //-------------------- + // Conversion to float + //-------------------- + + operator float () const; + + + //------------ + // Unary minus + //------------ + + half operator - () const; + + + //----------- + // Assignment + //----------- + + half & operator = (half h); + half & operator = (float f); + + half & operator += (half h); + half & operator += (float f); + + half & operator -= (half h); + half & operator -= (float f); + + half & operator *= (half h); + half & operator *= (float f); + + half & operator /= (half h); + half & operator /= (float f); + + + //--------------------------------------------------------- + // Round to n-bit precision (n should be between 0 and 10). + // After rounding, the significand's 10-n least significant + // bits will be zero. + //--------------------------------------------------------- + + half round (unsigned int n) const; + + + //-------------------------------------------------------------------- + // Classification: + // + // h.isFinite() returns true if h is a normalized number, + // a denormalized number or zero + // + // h.isNormalized() returns true if h is a normalized number + // + // h.isDenormalized() returns true if h is a denormalized number + // + // h.isZero() returns true if h is zero + // + // h.isNan() returns true if h is a NAN + // + // h.isInfinity() returns true if h is a positive + // or a negative infinity + // + // h.isNegative() returns true if the sign bit of h + // is set (negative) + //-------------------------------------------------------------------- + + bool isFinite () const; + bool isNormalized () const; + bool isDenormalized () const; + bool isZero () const; + bool isNan () const; + bool isInfinity () const; + bool isNegative () const; + + + //-------------------------------------------- + // Special values + // + // posInf() returns +infinity + // + // negInf() returns -infinity + // + // qNan() returns a NAN with the bit + // pattern 0111111111111111 + // + // sNan() returns a NAN with the bit + // pattern 0111110111111111 + //-------------------------------------------- + + static half posInf (); + static half negInf (); + static half qNan (); + static half sNan (); + + + //-------------------------------------- + // Access to the internal representation + //-------------------------------------- + + HALF_EXPORT unsigned short bits () const; + HALF_EXPORT void setBits (unsigned short bits); + + + public: + + union uif + { + unsigned int i; + float f; + }; + + private: + + HALF_EXPORT static short convert (int i); + HALF_EXPORT static float overflow (); + + unsigned short _h; + + HALF_EXPORT static const uif _toFloat[1 << 16]; + HALF_EXPORT static const unsigned short _eLut[1 << 9]; +}; + + + +//----------- +// Stream I/O +//----------- + +HALF_EXPORT std::ostream & operator << (std::ostream &os, half h); +HALF_EXPORT std::istream & operator >> (std::istream &is, half &h); + + +//---------- +// Debugging +//---------- + +HALF_EXPORT void printBits (std::ostream &os, half h); +HALF_EXPORT void printBits (std::ostream &os, float f); +HALF_EXPORT void printBits (char c[19], half h); +HALF_EXPORT void printBits (char c[35], float f); + + +//------------------------------------------------------------------------- +// Limits +// +// Visual C++ will complain if HALF_MIN, HALF_NRM_MIN etc. are not float +// constants, but at least one other compiler (gcc 2.96) produces incorrect +// results if they are. +//------------------------------------------------------------------------- + +#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER + + #define HALF_MIN 5.96046448e-08f // Smallest positive half + + #define HALF_NRM_MIN 6.10351562e-05f // Smallest positive normalized half + + #define HALF_MAX 65504.0f // Largest positive half + + #define HALF_EPSILON 0.00097656f // Smallest positive e for which + // half (1.0 + e) != half (1.0) +#else + + #define HALF_MIN 5.96046448e-08 // Smallest positive half + + #define HALF_NRM_MIN 6.10351562e-05 // Smallest positive normalized half + + #define HALF_MAX 65504.0 // Largest positive half + + #define HALF_EPSILON 0.00097656 // Smallest positive e for which + // half (1.0 + e) != half (1.0) +#endif + + +#define HALF_MANT_DIG 11 // Number of digits in mantissa + // (significand + hidden leading 1) + +#define HALF_DIG 2 // Number of base 10 digits that + // can be represented without change + +#define HALF_RADIX 2 // Base of the exponent + +#define HALF_MIN_EXP -13 // Minimum negative integer such that + // HALF_RADIX raised to the power of + // one less than that integer is a + // normalized half + +#define HALF_MAX_EXP 16 // Maximum positive integer such that + // HALF_RADIX raised to the power of + // one less than that integer is a + // normalized half + +#define HALF_MIN_10_EXP -4 // Minimum positive integer such + // that 10 raised to that power is + // a normalized half + +#define HALF_MAX_10_EXP 4 // Maximum positive integer such + // that 10 raised to that power is + // a normalized half + + +//--------------------------------------------------------------------------- +// +// Implementation -- +// +// Representation of a float: +// +// We assume that a float, f, is an IEEE 754 single-precision +// floating point number, whose bits are arranged as follows: +// +// 31 (msb) +// | +// | 30 23 +// | | | +// | | | 22 0 (lsb) +// | | | | | +// X XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX +// +// s e m +// +// S is the sign-bit, e is the exponent and m is the significand. +// +// If e is between 1 and 254, f is a normalized number: +// +// s e-127 +// f = (-1) * 2 * 1.m +// +// If e is 0, and m is not zero, f is a denormalized number: +// +// s -126 +// f = (-1) * 2 * 0.m +// +// If e and m are both zero, f is zero: +// +// f = 0.0 +// +// If e is 255, f is an "infinity" or "not a number" (NAN), +// depending on whether m is zero or not. +// +// Examples: +// +// 0 00000000 00000000000000000000000 = 0.0 +// 0 01111110 00000000000000000000000 = 0.5 +// 0 01111111 00000000000000000000000 = 1.0 +// 0 10000000 00000000000000000000000 = 2.0 +// 0 10000000 10000000000000000000000 = 3.0 +// 1 10000101 11110000010000000000000 = -124.0625 +// 0 11111111 00000000000000000000000 = +infinity +// 1 11111111 00000000000000000000000 = -infinity +// 0 11111111 10000000000000000000000 = NAN +// 1 11111111 11111111111111111111111 = NAN +// +// Representation of a half: +// +// Here is the bit-layout for a half number, h: +// +// 15 (msb) +// | +// | 14 10 +// | | | +// | | | 9 0 (lsb) +// | | | | | +// X XXXXX XXXXXXXXXX +// +// s e m +// +// S is the sign-bit, e is the exponent and m is the significand. +// +// If e is between 1 and 30, h is a normalized number: +// +// s e-15 +// h = (-1) * 2 * 1.m +// +// If e is 0, and m is not zero, h is a denormalized number: +// +// S -14 +// h = (-1) * 2 * 0.m +// +// If e and m are both zero, h is zero: +// +// h = 0.0 +// +// If e is 31, h is an "infinity" or "not a number" (NAN), +// depending on whether m is zero or not. +// +// Examples: +// +// 0 00000 0000000000 = 0.0 +// 0 01110 0000000000 = 0.5 +// 0 01111 0000000000 = 1.0 +// 0 10000 0000000000 = 2.0 +// 0 10000 1000000000 = 3.0 +// 1 10101 1111000001 = -124.0625 +// 0 11111 0000000000 = +infinity +// 1 11111 0000000000 = -infinity +// 0 11111 1000000000 = NAN +// 1 11111 1111111111 = NAN +// +// Conversion: +// +// Converting from a float to a half requires some non-trivial bit +// manipulations. In some cases, this makes conversion relatively +// slow, but the most common case is accelerated via table lookups. +// +// Converting back from a half to a float is easier because we don't +// have to do any rounding. In addition, there are only 65536 +// different half numbers; we can convert each of those numbers once +// and store the results in a table. Later, all conversions can be +// done using only simple table lookups. +// +//--------------------------------------------------------------------------- + + +//-------------------- +// Simple constructors +//-------------------- + +inline +half::half () +{ + // no initialization +} + + +//---------------------------- +// Half-from-float constructor +//---------------------------- + +inline +half::half (float f) +{ + uif x; + + x.f = f; + + if (f == 0) + { + // + // Common special case - zero. + // Preserve the zero's sign bit. + // + + _h = (x.i >> 16); + } + else + { + // + // We extract the combined sign and exponent, e, from our + // floating-point number, f. Then we convert e to the sign + // and exponent of the half number via a table lookup. + // + // For the most common case, where a normalized half is produced, + // the table lookup returns a non-zero value; in this case, all + // we have to do is round f's significand to 10 bits and combine + // the result with e. + // + // For all other cases (overflow, zeroes, denormalized numbers + // resulting from underflow, infinities and NANs), the table + // lookup returns zero, and we call a longer, non-inline function + // to do the float-to-half conversion. + // + + int e = (x.i >> 23) & 0x000001ff; + + e = _eLut[e]; + + if (e) + { + // + // Simple case - round the significand, m, to 10 + // bits and combine it with the sign and exponent. + // + + int m = x.i & 0x007fffff; + _h = e + ((m + 0x00000fff + ((m >> 13) & 1)) >> 13); + } + else + { + // + // Difficult case - call a function. + // + + _h = convert (x.i); + } + } +} + + +//------------------------------------------ +// Half-to-float conversion via table lookup +//------------------------------------------ + +inline +half::operator float () const +{ + return _toFloat[_h].f; +} + + +//------------------------- +// Round to n-bit precision +//------------------------- + +inline half +half::round (unsigned int n) const +{ + // + // Parameter check. + // + + if (n >= 10) + return *this; + + // + // Disassemble h into the sign, s, + // and the combined exponent and significand, e. + // + + unsigned short s = _h & 0x8000; + unsigned short e = _h & 0x7fff; + + // + // Round the exponent and significand to the nearest value + // where ones occur only in the (10-n) most significant bits. + // Note that the exponent adjusts automatically if rounding + // up causes the significand to overflow. + // + + e >>= 9 - n; + e += e & 1; + e <<= 9 - n; + + // + // Check for exponent overflow. + // + + if (e >= 0x7c00) + { + // + // Overflow occurred -- truncate instead of rounding. + // + + e = _h; + e >>= 10 - n; + e <<= 10 - n; + } + + // + // Put the original sign bit back. + // + + half h; + h._h = s | e; + + return h; +} + + +//----------------------- +// Other inline functions +//----------------------- + +inline half +half::operator - () const +{ + half h; + h._h = _h ^ 0x8000; + return h; +} + + +inline half & +half::operator = (half h) +{ + _h = h._h; + return *this; +} + + +inline half & +half::operator = (float f) +{ + *this = half (f); + return *this; +} + + +inline half & +half::operator += (half h) +{ + *this = half (float (*this) + float (h)); + return *this; +} + + +inline half & +half::operator += (float f) +{ + *this = half (float (*this) + f); + return *this; +} + + +inline half & +half::operator -= (half h) +{ + *this = half (float (*this) - float (h)); + return *this; +} + + +inline half & +half::operator -= (float f) +{ + *this = half (float (*this) - f); + return *this; +} + + +inline half & +half::operator *= (half h) +{ + *this = half (float (*this) * float (h)); + return *this; +} + + +inline half & +half::operator *= (float f) +{ + *this = half (float (*this) * f); + return *this; +} + + +inline half & +half::operator /= (half h) +{ + *this = half (float (*this) / float (h)); + return *this; +} + + +inline half & +half::operator /= (float f) +{ + *this = half (float (*this) / f); + return *this; +} + + +inline bool +half::isFinite () const +{ + unsigned short e = (_h >> 10) & 0x001f; + return e < 31; +} + + +inline bool +half::isNormalized () const +{ + unsigned short e = (_h >> 10) & 0x001f; + return e > 0 && e < 31; +} + + +inline bool +half::isDenormalized () const +{ + unsigned short e = (_h >> 10) & 0x001f; + unsigned short m = _h & 0x3ff; + return e == 0 && m != 0; +} + + +inline bool +half::isZero () const +{ + return (_h & 0x7fff) == 0; +} + + +inline bool +half::isNan () const +{ + unsigned short e = (_h >> 10) & 0x001f; + unsigned short m = _h & 0x3ff; + return e == 31 && m != 0; +} + + +inline bool +half::isInfinity () const +{ + unsigned short e = (_h >> 10) & 0x001f; + unsigned short m = _h & 0x3ff; + return e == 31 && m == 0; +} + + +inline bool +half::isNegative () const +{ + return (_h & 0x8000) != 0; +} + + +inline half +half::posInf () +{ + half h; + h._h = 0x7c00; + return h; +} + + +inline half +half::negInf () +{ + half h; + h._h = 0xfc00; + return h; +} + + +inline half +half::qNan () +{ + half h; + h._h = 0x7fff; + return h; +} + + +inline half +half::sNan () +{ + half h; + h._h = 0x7dff; + return h; +} + + +inline unsigned short +half::bits () const +{ + return _h; +} + + +inline void +half::setBits (unsigned short bits) +{ + _h = bits; +} + +#endif diff --git a/Baikal/PostEffects/post_effect_clw.h b/Baikal/Utils/log.h similarity index 59% rename from Baikal/PostEffects/post_effect_clw.h rename to Baikal/Utils/log.h index 1aa1ae93..e2019299 100644 --- a/Baikal/PostEffects/post_effect_clw.h +++ b/Baikal/Utils/log.h @@ -21,47 +21,37 @@ THE SOFTWARE. ********************************************************************/ #pragma once -#include "post_effect.h" - -#include "CLW.h" -#include "../CLW/clwoutput.h" +#include namespace Baikal { - /** - \brief Post effects partial implementation based on CLW framework. - */ - class PostEffectClw: public PostEffect + template + inline + void Log(Stream&) { - public: - // Constructor, receives CLW context - PostEffectClw(CLWContext context); - - // Check output compatibility, CLW effects are only compatible - // with ClwOutput. - bool IsCompatible(Output const& output) const override; - - protected: - CLWContext GetContext() const; - - private: - CLWContext m_context; - }; + } - inline PostEffectClw::PostEffectClw(CLWContext context) - : m_context(context) + template + inline + void Log(Stream& stream, F&& f, U&&... u) { +#ifdef ENABLE_LOG + stream << std::forward(f); + Log(stream, std::forward(u)...); +#endif } - inline bool PostEffectClw::IsCompatible(Output const& output) const + template + inline + void LogInfo(F&& f, U&&... u) { - auto tmp = dynamic_cast(&output); - - return tmp ? true : false; + Log(std::cout, std::forward(f), std::forward(u)...); } - inline CLWContext PostEffectClw::GetContext() const + template + inline + void LogError(F&& f, U&&... u) { - return m_context; + Log(std::cerr, std::forward(f), std::forward(u)...); } -} +} \ No newline at end of file diff --git a/Baikal/Utils/mkpath.cpp b/Baikal/Utils/mkpath.cpp new file mode 100644 index 00000000..07d43b04 --- /dev/null +++ b/Baikal/Utils/mkpath.cpp @@ -0,0 +1,57 @@ +#include "Utils/mkpath.h" + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include + +namespace Baikal +{ + static const std::string delimiters = "/\\"; + + int mkpath(const std::string& path) + { + int err = -1; + + size_t length = path.size(); + if (length == 0) + return 0; + + if (path.find_last_of(delimiters) == length - 1) + --length; + + size_t idx = 0; + while (idx < length) + { + idx = path.find_first_of(delimiters, idx + 1); + auto p = path.substr(0, idx); + + // Only store the error of the creation to deepest level + // The error of higher level can be ignored because + // they can either be existed or a root path or something like . and .. +#ifdef _WIN32 + err = _mkdir(p.c_str()); +#else + err = mkdir(p.c_str(), 0755); +#endif + } + + // ignore error if final directory existed + if (err != 0 && errno == EEXIST) + err = 0; + + return err; + } + + int mkfilepath(const std::string& filepath) + { + size_t pos = filepath.find_last_of(delimiters); + if (pos == std::string::npos) + return 0; + + return mkpath(filepath.substr(0, pos)); + } +} diff --git a/Baikal/Utils/mkpath.h b/Baikal/Utils/mkpath.h new file mode 100644 index 00000000..4a747c7b --- /dev/null +++ b/Baikal/Utils/mkpath.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace Baikal +{ + int mkpath(const std::string& path); + + int mkfilepath(const std::string& filepath); +} diff --git a/Baikal/Utils/tiny_obj_loader.cpp b/Baikal/Utils/tiny_obj_loader.cpp deleted file mode 100644 index a61ff2c4..00000000 --- a/Baikal/Utils/tiny_obj_loader.cpp +++ /dev/null @@ -1,725 +0,0 @@ -// -// Copyright 2012-2013, Syoyo Fujita. -// -// Licensed under 2-clause BSD liecense. -// - -// -// version 0.9.7: Support multi-materials(per-face material ID) per object/group. -// version 0.9.6: Support Ni(index of refraction) mtl parameter. -// Parse transmittance material parameter correctly. -// version 0.9.5: Parse multiple group name. -// Add support of specifying the base path to load material file. -// version 0.9.4: Initial suupport of group tag(g) -// version 0.9.3: Fix parsing triple 'x/y/z' -// version 0.9.2: Add more .mtl load support -// version 0.9.1: Add initial .mtl load support -// version 0.9.0: Initial -// - - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "tiny_obj_loader.h" - -namespace tinyobj { - -struct vertex_index { - int v_idx, vt_idx, vn_idx; - vertex_index() {}; - vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {}; - vertex_index(int vidx, int vtidx, int vnidx) : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {}; - -}; -// for std::map -static inline bool operator<(const vertex_index& a, const vertex_index& b) -{ - if (a.v_idx != b.v_idx) return (a.v_idx < b.v_idx); - if (a.vn_idx != b.vn_idx) return (a.vn_idx < b.vn_idx); - if (a.vt_idx != b.vt_idx) return (a.vt_idx < b.vt_idx); - - return false; -} - -struct obj_shape { - std::vector v; - std::vector vn; - std::vector vt; -}; - -static inline bool isSpace(const char c) { - return (c == ' ') || (c == '\t'); -} - -static inline bool isNewLine(const char c) { - return (c == '\r') || (c == '\n') || (c == '\0'); -} - -// Make index zero-base, and also support relative index. -static inline int fixIndex(int idx, int n) -{ - int i; - - if (idx > 0) { - i = idx - 1; - } else if (idx == 0) { - i = 0; - } else { // negative value = relative - i = n + idx; - } - return i; -} - -static inline std::string parseString(const char*& token) -{ - std::string s; - int b = (int)strspn(token, " \t"); - int e = (int)strcspn(token, " \t\r"); - s = std::string(&token[b], &token[e]); - - token += (e - b); - return s; -} - -static inline int parseInt(const char*& token) -{ - token += strspn(token, " \t"); - int i = atoi(token); - token += strcspn(token, " \t\r"); - return i; -} - -static inline float parseFloat(const char*& token) -{ - token += strspn(token, " \t"); - float f = (float)atof(token); - token += strcspn(token, " \t\r"); - return f; -} - -static inline void parseFloat2( - float& x, float& y, - const char*& token) -{ - x = parseFloat(token); - y = parseFloat(token); -} - -static inline void parseFloat3( - float& x, float& y, float& z, - const char*& token) -{ - x = parseFloat(token); - y = parseFloat(token); - z = parseFloat(token); -} - - -// Parse triples: i, i/j/k, i//k, i/j -static vertex_index parseTriple( - const char* &token, - int vsize, - int vnsize, - int vtsize) -{ - vertex_index vi(-1); - - vi.v_idx = fixIndex(atoi(token), vsize); - token += strcspn(token, "/ \t\r"); - if (token[0] != '/') { - return vi; - } - token++; - - // i//k - if (token[0] == '/') { - token++; - vi.vn_idx = fixIndex(atoi(token), vnsize); - token += strcspn(token, "/ \t\r"); - return vi; - } - - // i/j/k or i/j - vi.vt_idx = fixIndex(atoi(token), vtsize); - token += strcspn(token, "/ \t\r"); - if (token[0] != '/') { - return vi; - } - - // i/j/k - token++; // skip '/' - vi.vn_idx = fixIndex(atoi(token), vnsize); - token += strcspn(token, "/ \t\r"); - return vi; -} - -static unsigned int -updateVertex( - std::map& vertexCache, - std::vector& positions, - std::vector& normals, - std::vector& texcoords, - const std::vector& in_positions, - const std::vector& in_normals, - const std::vector& in_texcoords, - const vertex_index& i) -{ - const std::map::iterator it = vertexCache.find(i); - - if (it != vertexCache.end()) { - // found cache - return it->second; - } - - assert(in_positions.size() > (unsigned int) (3*i.v_idx+2)); - - positions.push_back(in_positions[3*i.v_idx+0]); - positions.push_back(in_positions[3*i.v_idx+1]); - positions.push_back(in_positions[3*i.v_idx+2]); - - if (i.vn_idx >= 0) { - normals.push_back(in_normals[3*i.vn_idx+0]); - normals.push_back(in_normals[3*i.vn_idx+1]); - normals.push_back(in_normals[3*i.vn_idx+2]); - } - - if (i.vt_idx >= 0) { - texcoords.push_back(in_texcoords[2*i.vt_idx+0]); - texcoords.push_back(in_texcoords[2*i.vt_idx+1]); - } - - unsigned int idx = (unsigned)positions.size() / 3 - 1; - vertexCache[i] = idx; - - return idx; -} - -void InitMaterial(material_t& material) { - material.name = ""; - material.ambient_texname = ""; - material.diffuse_texname = ""; - material.specular_texname = ""; - material.normal_texname = ""; - for (int i = 0; i < 3; i ++) { - material.ambient[i] = 0.f; - material.diffuse[i] = 0.f; - material.specular[i] = 0.f; - material.transmittance[i] = 0.f; - material.emission[i] = 0.f; - } - material.illum = 0; - material.dissolve = 1.f; - material.shininess = 1.f; - material.ior = 1.f; - material.unknown_parameter.clear(); -} - -static bool -exportFaceGroupToShape( - shape_t& shape, - std::map vertexCache, - const std::vector &in_positions, - const std::vector &in_normals, - const std::vector &in_texcoords, - const std::vector >& faceGroup, - const int material_id, - const std::string &name, - bool clearCache) -{ - if (faceGroup.empty()) { - return false; - } - - size_t offset; - - offset = shape.mesh.indices.size(); - - // Flatten vertices and indices - for (size_t i = 0; i < faceGroup.size(); i++) { - const std::vector& face = faceGroup[i]; - - vertex_index i0 = face[0]; - vertex_index i1(-1); - vertex_index i2 = face[1]; - - size_t npolys = face.size(); - - // Polygon -> triangle fan conversion - for (size_t k = 2; k < npolys; k++) { - i1 = i2; - i2 = face[k]; - - unsigned int v0 = updateVertex(vertexCache, shape.mesh.positions, shape.mesh.normals, shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i0); - unsigned int v1 = updateVertex(vertexCache, shape.mesh.positions, shape.mesh.normals, shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i1); - unsigned int v2 = updateVertex(vertexCache, shape.mesh.positions, shape.mesh.normals, shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i2); - - shape.mesh.indices.push_back(v0); - shape.mesh.indices.push_back(v1); - shape.mesh.indices.push_back(v2); - - shape.mesh.material_ids.push_back(material_id); - } - - } - - shape.name = name; - - if (clearCache) - vertexCache.clear(); - - return true; - -} - -std::string LoadMtl ( - std::map& material_map, - std::vector& materials, - std::istream& inStream) -{ - material_map.clear(); - std::stringstream err; - - material_t material; - - int maxchars = 8192; // Alloc enough size. - std::vector buf(maxchars); // Alloc enough size. - while (inStream.peek() != -1) { - inStream.getline(&buf[0], maxchars); - - std::string linebuf(&buf[0]); - - // Trim newline '\r\n' or '\n' - if (linebuf.size() > 0) { - if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1); - } - if (linebuf.size() > 0) { - if (linebuf[linebuf.size()-1] == '\r') linebuf.erase(linebuf.size()-1); - } - - // Skip if empty line. - if (linebuf.empty()) { - continue; - } - - // Skip leading space. - const char* token = linebuf.c_str(); - token += strspn(token, " \t"); - - assert(token); - if (token[0] == '\0') continue; // empty line - - if (token[0] == '#') continue; // comment line - - // new mtl - if ((0 == strncmp(token, "newmtl", 6)) && isSpace((token[6]))) { - // flush previous material. - if (!material.name.empty()) - { - material_map.insert(std::pair(material.name, (int)materials.size())); - materials.push_back(material); - } - - // initial temporary material - InitMaterial(material); - - // set new mtl name - char namebuf[4096]; - token += 7; - sscanf(token, "%s", namebuf); - material.name = namebuf; - continue; - } - - // ambient - if (token[0] == 'K' && token[1] == 'a' && isSpace((token[2]))) { - token += 2; - float r, g, b; - parseFloat3(r, g, b, token); - material.ambient[0] = r; - material.ambient[1] = g; - material.ambient[2] = b; - continue; - } - - // diffuse - if (token[0] == 'K' && token[1] == 'd' && isSpace((token[2]))) { - token += 2; - float r, g, b; - parseFloat3(r, g, b, token); - material.diffuse[0] = r; - material.diffuse[1] = g; - material.diffuse[2] = b; - continue; - } - - // specular - if (token[0] == 'K' && token[1] == 's' && isSpace((token[2]))) { - token += 2; - float r, g, b; - parseFloat3(r, g, b, token); - material.specular[0] = r; - material.specular[1] = g; - material.specular[2] = b; - continue; - } - - // transmittance - if (token[0] == 'K' && token[1] == 't' && isSpace((token[2]))) { - token += 2; - float r, g, b; - parseFloat3(r, g, b, token); - material.transmittance[0] = r; - material.transmittance[1] = g; - material.transmittance[2] = b; - continue; - } - - // ior(index of refraction) - if (token[0] == 'N' && token[1] == 'i' && isSpace((token[2]))) { - token += 2; - material.ior = parseFloat(token); - continue; - } - - // emission - if(token[0] == 'K' && token[1] == 'e' && isSpace(token[2])) { - token += 2; - float r, g, b; - parseFloat3(r, g, b, token); - material.emission[0] = r; - material.emission[1] = g; - material.emission[2] = b; - continue; - } - - // shininess - if(token[0] == 'N' && token[1] == 's' && isSpace(token[2])) { - token += 2; - material.shininess = parseFloat(token); - continue; - } - - // illum model - if (0 == strncmp(token, "illum", 5) && isSpace(token[5])) { - token += 6; - material.illum = parseInt(token); - continue; - } - - // dissolve - if ((token[0] == 'd' && isSpace(token[1]))) { - token += 1; - material.dissolve = parseFloat(token); - continue; - } - if (token[0] == 'T' && token[1] == 'r' && isSpace(token[2])) { - token += 2; - material.dissolve = parseFloat(token); - continue; - } - - // ambient texture - if ((0 == strncmp(token, "map_Ka", 6)) && isSpace(token[6])) { - token += 7; - material.ambient_texname = token; - continue; - } - - // diffuse texture - if ((0 == strncmp(token, "map_Kd", 6)) && isSpace(token[6])) { - token += 7; - material.diffuse_texname = token; - continue; - } - - // specular texture - if ((0 == strncmp(token, "map_Ks", 6)) && isSpace(token[6])) { - token += 7; - material.specular_texname = token; - continue; - } - - // normal texture - if ((0 == strncmp(token, "map_Ns", 6)) && isSpace(token[6])) { - token += 7; - material.normal_texname = token; - continue; - } - - // unknown parameter - const char* _space = strchr(token, ' '); - if(!_space) { - _space = strchr(token, '\t'); - } - if(_space) { - int len = (int)(_space - token); - std::string key(token, len); - std::string value = _space + 1; - material.unknown_parameter.insert(std::pair(key, value)); - } - } - // flush last material. - material_map.insert(std::pair(material.name, (int)materials.size())); - materials.push_back(material); - - return err.str(); -} - -std::string MaterialFileReader::operator() ( - const std::string& matId, - std::vector& materials, - std::map& matMap) -{ - std::string filepath; - - if (!m_mtlBasePath.empty()) { - filepath = std::string(m_mtlBasePath) + "/" + matId; - } else { - filepath = matId; - } - - std::ifstream matIStream(filepath.c_str()); - return LoadMtl(matMap, materials, matIStream); -} - -std::string -LoadObj( - std::vector& shapes, - std::vector& materials, // [output] - const char* filename, - const char* mtl_basepath) -{ - - shapes.clear(); - - std::stringstream err; - - std::ifstream ifs(filename); - if (!ifs) { - err << "Cannot open file [" << filename << "]" << std::endl; - return err.str(); - } - - std::string basePath; - if (mtl_basepath) { - basePath = mtl_basepath; - } - MaterialFileReader matFileReader( basePath ); - - return LoadObj(shapes, materials, ifs, matFileReader); -} - -std::string LoadObj( - std::vector& shapes, - std::vector& materials, // [output] - std::istream& inStream, - MaterialReader& readMatFn) -{ - std::stringstream err; - - std::vector v; - std::vector vn; - std::vector vt; - std::vector > faceGroup; - std::string name; - - // material - std::map material_map; - std::map vertexCache; - int material = -1; - - shape_t shape; - - int maxchars = 8192; // Alloc enough size. - std::vector buf(maxchars); // Alloc enough size. - while (inStream.peek() != -1) { - inStream.getline(&buf[0], maxchars); - - std::string linebuf(&buf[0]); - - // Trim newline '\r\n' or '\n' - if (linebuf.size() > 0) { - if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1); - } - if (linebuf.size() > 0) { - if (linebuf[linebuf.size()-1] == '\r') linebuf.erase(linebuf.size()-1); - } - - // Skip if empty line. - if (linebuf.empty()) { - continue; - } - - // Skip leading space. - const char* token = linebuf.c_str(); - token += strspn(token, " \t"); - - assert(token); - if (token[0] == '\0') continue; // empty line - - if (token[0] == '#') continue; // comment line - - // vertex - if (token[0] == 'v' && isSpace((token[1]))) { - token += 2; - float x, y, z; - parseFloat3(x, y, z, token); - v.push_back(x); - v.push_back(y); - v.push_back(z); - continue; - } - - // normal - if (token[0] == 'v' && token[1] == 'n' && isSpace((token[2]))) { - token += 3; - float x, y, z; - parseFloat3(x, y, z, token); - vn.push_back(x); - vn.push_back(y); - vn.push_back(z); - continue; - } - - // texcoord - if (token[0] == 'v' && token[1] == 't' && isSpace((token[2]))) { - token += 3; - float x, y; - parseFloat2(x, y, token); - vt.push_back(x); - vt.push_back(y); - continue; - } - - // face - if (token[0] == 'f' && isSpace((token[1]))) { - token += 2; - token += strspn(token, " \t"); - - std::vector face; - while (!isNewLine(token[0])) { - vertex_index vi = parseTriple(token, (int)v.size() / 3, (int)vn.size() / 3, (int)vt.size() / 2); - face.push_back(vi); - int n = (int)strspn(token, " \t\r"); - token += n; - } - - faceGroup.push_back(face); - - continue; - } - - // use mtl - if ((0 == strncmp(token, "usemtl", 6)) && isSpace((token[6]))) { - - char namebuf[4096]; - token += 7; - sscanf(token, "%s", namebuf); - - exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, false); - faceGroup.clear(); - - if (material_map.find(namebuf) != material_map.end()) { - material = material_map[namebuf]; - } else { - // { error!! material not found } - material = -1; - } - - continue; - - } - - // load mtl - if ((0 == strncmp(token, "mtllib", 6)) && isSpace((token[6]))) { - char namebuf[4096]; - token += 7; - sscanf(token, "%s", namebuf); - - std::string err_mtl = readMatFn(namebuf, materials, material_map); - if (!err_mtl.empty()) { - faceGroup.clear(); // for safety - return err_mtl; - } - - continue; - } - - // group name - if (token[0] == 'g' && isSpace((token[1]))) { - - // flush previous face group. - bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true); - if (ret) { - shapes.push_back(shape); - } - - shape = shape_t(); - - //material = -1; - faceGroup.clear(); - - std::vector names; - while (!isNewLine(token[0])) { - std::string str = parseString(token); - names.push_back(str); - token += strspn(token, " \t\r"); // skip tag - } - - assert(names.size() > 0); - - // names[0] must be 'g', so skipt 0th element. - if (names.size() > 1) { - name = names[1]; - } else { - name = ""; - } - - continue; - } - - // object name - if (token[0] == 'o' && isSpace((token[1]))) { - - // flush previous face group. - bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true); - if (ret) { - shapes.push_back(shape); - } - - //material = -1; - faceGroup.clear(); - shape = shape_t(); - - // @todo { multiple object name? } - char namebuf[4096]; - token += 2; - sscanf(token, "%s", namebuf); - name = std::string(namebuf); - - - continue; - } - - // Ignore unknown command. - } - - bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true); - if (ret) { - shapes.push_back(shape); - } - faceGroup.clear(); // for safety - - return err.str(); -} - - -} diff --git a/Baikal/Utils/tiny_obj_loader.h b/Baikal/Utils/tiny_obj_loader.h deleted file mode 100644 index 7cc6fa6a..00000000 --- a/Baikal/Utils/tiny_obj_loader.h +++ /dev/null @@ -1,107 +0,0 @@ -// -// Copyright 2012-2013, Syoyo Fujita. -// -// Licensed under 2-clause BSD liecense. -// -#ifndef _TINY_OBJ_LOADER_H -#define _TINY_OBJ_LOADER_H - -#include -#include -#include - -namespace tinyobj { - -typedef struct -{ - std::string name; - - float ambient[3]; - float diffuse[3]; - float specular[3]; - float transmittance[3]; - float emission[3]; - float shininess; - float ior; // index of refraction - float dissolve; // 1 == opaque; 0 == fully transparent - // illumination model (see http://www.fileformat.info/format/material/) - int illum; - - std::string ambient_texname; - std::string diffuse_texname; - std::string specular_texname; - std::string normal_texname; - std::map unknown_parameter; -} material_t; - -typedef struct -{ - std::vector positions; - std::vector normals; - std::vector texcoords; - std::vector indices; - std::vector material_ids; // per-mesh material ID -} mesh_t; - -typedef struct -{ - std::string name; - mesh_t mesh; -} shape_t; - -class MaterialReader -{ -public: - MaterialReader(){} - virtual ~MaterialReader(){} - - virtual std::string operator() ( - const std::string& matId, - std::vector& materials, - std::map& matMap) = 0; -}; - -class MaterialFileReader: - public MaterialReader -{ - public: - MaterialFileReader(const std::string& mtl_basepath): m_mtlBasePath(mtl_basepath) {} - virtual ~MaterialFileReader() {} - virtual std::string operator() ( - const std::string& matId, - std::vector& materials, - std::map& matMap); - - private: - std::string m_mtlBasePath; -}; - -/// Loads .obj from a file. -/// 'shapes' will be filled with parsed shape data -/// The function returns error string. -/// Returns empty string when loading .obj success. -/// 'mtl_basepath' is optional, and used for base path for .mtl file. -std::string LoadObj( - std::vector& shapes, // [output] - std::vector& materials, // [output] - const char* filename, - const char* mtl_basepath = NULL); - -/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve -/// std::istream for materials. -/// Returns empty string when loading .obj success. -std::string LoadObj( - std::vector& shapes, // [output] - std::vector& materials, // [output] - std::istream& inStream, - MaterialReader& readMatFn); - -/// Loads materials into std::map -/// Returns an empty string if successful -std::string LoadMtl ( - std::map& material_map, - std::vector& materials, - std::istream& inStream); -} - -#endif // _TINY_OBJ_LOADER_H diff --git a/Baikal/Utils/toFloat.h b/Baikal/Utils/toFloat.h new file mode 100644 index 00000000..37c95563 --- /dev/null +++ b/Baikal/Utils/toFloat.h @@ -0,0 +1,16391 @@ +// +// This is an automatically generated file. +// Do not edit. +// + +{ + {0x00000000}, {0x33800000}, {0x34000000}, {0x34400000}, + {0x34800000}, {0x34a00000}, {0x34c00000}, {0x34e00000}, + {0x35000000}, {0x35100000}, {0x35200000}, {0x35300000}, + {0x35400000}, {0x35500000}, {0x35600000}, {0x35700000}, + {0x35800000}, {0x35880000}, {0x35900000}, {0x35980000}, + {0x35a00000}, {0x35a80000}, {0x35b00000}, {0x35b80000}, + {0x35c00000}, {0x35c80000}, {0x35d00000}, {0x35d80000}, + {0x35e00000}, {0x35e80000}, {0x35f00000}, {0x35f80000}, + {0x36000000}, {0x36040000}, {0x36080000}, {0x360c0000}, + {0x36100000}, {0x36140000}, {0x36180000}, {0x361c0000}, + {0x36200000}, {0x36240000}, {0x36280000}, {0x362c0000}, + {0x36300000}, {0x36340000}, {0x36380000}, {0x363c0000}, + {0x36400000}, {0x36440000}, {0x36480000}, {0x364c0000}, + {0x36500000}, {0x36540000}, {0x36580000}, {0x365c0000}, + {0x36600000}, {0x36640000}, {0x36680000}, {0x366c0000}, + {0x36700000}, {0x36740000}, {0x36780000}, {0x367c0000}, + {0x36800000}, {0x36820000}, {0x36840000}, {0x36860000}, + {0x36880000}, {0x368a0000}, {0x368c0000}, {0x368e0000}, + {0x36900000}, {0x36920000}, {0x36940000}, {0x36960000}, + {0x36980000}, {0x369a0000}, {0x369c0000}, {0x369e0000}, + {0x36a00000}, {0x36a20000}, {0x36a40000}, {0x36a60000}, + {0x36a80000}, {0x36aa0000}, {0x36ac0000}, {0x36ae0000}, + {0x36b00000}, {0x36b20000}, {0x36b40000}, {0x36b60000}, + {0x36b80000}, {0x36ba0000}, {0x36bc0000}, {0x36be0000}, + {0x36c00000}, {0x36c20000}, {0x36c40000}, {0x36c60000}, + {0x36c80000}, {0x36ca0000}, {0x36cc0000}, {0x36ce0000}, + {0x36d00000}, {0x36d20000}, {0x36d40000}, {0x36d60000}, + {0x36d80000}, {0x36da0000}, {0x36dc0000}, {0x36de0000}, + {0x36e00000}, {0x36e20000}, {0x36e40000}, {0x36e60000}, + {0x36e80000}, {0x36ea0000}, {0x36ec0000}, {0x36ee0000}, + {0x36f00000}, {0x36f20000}, {0x36f40000}, {0x36f60000}, + {0x36f80000}, {0x36fa0000}, {0x36fc0000}, {0x36fe0000}, + {0x37000000}, {0x37010000}, {0x37020000}, {0x37030000}, + {0x37040000}, {0x37050000}, {0x37060000}, {0x37070000}, + {0x37080000}, {0x37090000}, {0x370a0000}, {0x370b0000}, + {0x370c0000}, {0x370d0000}, {0x370e0000}, {0x370f0000}, + {0x37100000}, {0x37110000}, {0x37120000}, {0x37130000}, + {0x37140000}, {0x37150000}, {0x37160000}, {0x37170000}, + {0x37180000}, {0x37190000}, {0x371a0000}, {0x371b0000}, + {0x371c0000}, {0x371d0000}, {0x371e0000}, {0x371f0000}, + {0x37200000}, {0x37210000}, {0x37220000}, {0x37230000}, + {0x37240000}, {0x37250000}, {0x37260000}, {0x37270000}, + {0x37280000}, {0x37290000}, {0x372a0000}, {0x372b0000}, + {0x372c0000}, {0x372d0000}, {0x372e0000}, {0x372f0000}, + {0x37300000}, {0x37310000}, {0x37320000}, {0x37330000}, + {0x37340000}, {0x37350000}, {0x37360000}, {0x37370000}, + {0x37380000}, {0x37390000}, {0x373a0000}, {0x373b0000}, + {0x373c0000}, {0x373d0000}, {0x373e0000}, {0x373f0000}, + {0x37400000}, {0x37410000}, {0x37420000}, {0x37430000}, + {0x37440000}, {0x37450000}, {0x37460000}, {0x37470000}, + {0x37480000}, {0x37490000}, {0x374a0000}, {0x374b0000}, + {0x374c0000}, {0x374d0000}, {0x374e0000}, {0x374f0000}, + {0x37500000}, {0x37510000}, {0x37520000}, {0x37530000}, + {0x37540000}, {0x37550000}, {0x37560000}, {0x37570000}, + {0x37580000}, {0x37590000}, {0x375a0000}, {0x375b0000}, + {0x375c0000}, {0x375d0000}, {0x375e0000}, {0x375f0000}, + {0x37600000}, {0x37610000}, {0x37620000}, {0x37630000}, + {0x37640000}, {0x37650000}, {0x37660000}, {0x37670000}, + {0x37680000}, {0x37690000}, {0x376a0000}, {0x376b0000}, + {0x376c0000}, {0x376d0000}, {0x376e0000}, {0x376f0000}, + {0x37700000}, {0x37710000}, {0x37720000}, {0x37730000}, + {0x37740000}, {0x37750000}, {0x37760000}, {0x37770000}, + {0x37780000}, {0x37790000}, {0x377a0000}, {0x377b0000}, + {0x377c0000}, {0x377d0000}, {0x377e0000}, {0x377f0000}, + {0x37800000}, {0x37808000}, {0x37810000}, {0x37818000}, + {0x37820000}, {0x37828000}, {0x37830000}, {0x37838000}, + {0x37840000}, {0x37848000}, {0x37850000}, {0x37858000}, + {0x37860000}, {0x37868000}, {0x37870000}, {0x37878000}, + {0x37880000}, {0x37888000}, {0x37890000}, {0x37898000}, + {0x378a0000}, {0x378a8000}, {0x378b0000}, {0x378b8000}, + {0x378c0000}, {0x378c8000}, {0x378d0000}, {0x378d8000}, + {0x378e0000}, {0x378e8000}, {0x378f0000}, {0x378f8000}, + {0x37900000}, {0x37908000}, {0x37910000}, {0x37918000}, + {0x37920000}, {0x37928000}, {0x37930000}, {0x37938000}, + {0x37940000}, {0x37948000}, {0x37950000}, {0x37958000}, + {0x37960000}, {0x37968000}, {0x37970000}, {0x37978000}, + {0x37980000}, {0x37988000}, {0x37990000}, {0x37998000}, + {0x379a0000}, {0x379a8000}, {0x379b0000}, {0x379b8000}, + {0x379c0000}, {0x379c8000}, {0x379d0000}, {0x379d8000}, + {0x379e0000}, {0x379e8000}, {0x379f0000}, {0x379f8000}, + {0x37a00000}, {0x37a08000}, {0x37a10000}, {0x37a18000}, + {0x37a20000}, {0x37a28000}, {0x37a30000}, {0x37a38000}, + {0x37a40000}, {0x37a48000}, {0x37a50000}, {0x37a58000}, + {0x37a60000}, {0x37a68000}, {0x37a70000}, {0x37a78000}, + {0x37a80000}, {0x37a88000}, {0x37a90000}, {0x37a98000}, + {0x37aa0000}, {0x37aa8000}, {0x37ab0000}, {0x37ab8000}, + {0x37ac0000}, {0x37ac8000}, {0x37ad0000}, {0x37ad8000}, + {0x37ae0000}, {0x37ae8000}, {0x37af0000}, {0x37af8000}, + {0x37b00000}, {0x37b08000}, {0x37b10000}, {0x37b18000}, + {0x37b20000}, {0x37b28000}, {0x37b30000}, {0x37b38000}, + {0x37b40000}, {0x37b48000}, {0x37b50000}, {0x37b58000}, + {0x37b60000}, {0x37b68000}, {0x37b70000}, {0x37b78000}, + {0x37b80000}, {0x37b88000}, {0x37b90000}, {0x37b98000}, + {0x37ba0000}, {0x37ba8000}, {0x37bb0000}, {0x37bb8000}, + {0x37bc0000}, {0x37bc8000}, {0x37bd0000}, {0x37bd8000}, + {0x37be0000}, {0x37be8000}, {0x37bf0000}, {0x37bf8000}, + {0x37c00000}, {0x37c08000}, {0x37c10000}, {0x37c18000}, + {0x37c20000}, {0x37c28000}, {0x37c30000}, {0x37c38000}, + {0x37c40000}, {0x37c48000}, {0x37c50000}, {0x37c58000}, + {0x37c60000}, {0x37c68000}, {0x37c70000}, {0x37c78000}, + {0x37c80000}, {0x37c88000}, {0x37c90000}, {0x37c98000}, + {0x37ca0000}, {0x37ca8000}, {0x37cb0000}, {0x37cb8000}, + {0x37cc0000}, {0x37cc8000}, {0x37cd0000}, {0x37cd8000}, + {0x37ce0000}, {0x37ce8000}, {0x37cf0000}, {0x37cf8000}, + {0x37d00000}, {0x37d08000}, {0x37d10000}, {0x37d18000}, + {0x37d20000}, {0x37d28000}, {0x37d30000}, {0x37d38000}, + {0x37d40000}, {0x37d48000}, {0x37d50000}, {0x37d58000}, + {0x37d60000}, {0x37d68000}, {0x37d70000}, {0x37d78000}, + {0x37d80000}, {0x37d88000}, {0x37d90000}, {0x37d98000}, + {0x37da0000}, {0x37da8000}, {0x37db0000}, {0x37db8000}, + {0x37dc0000}, {0x37dc8000}, {0x37dd0000}, {0x37dd8000}, + {0x37de0000}, {0x37de8000}, {0x37df0000}, {0x37df8000}, + {0x37e00000}, {0x37e08000}, {0x37e10000}, {0x37e18000}, + {0x37e20000}, {0x37e28000}, {0x37e30000}, {0x37e38000}, + {0x37e40000}, {0x37e48000}, {0x37e50000}, {0x37e58000}, + {0x37e60000}, {0x37e68000}, {0x37e70000}, {0x37e78000}, + {0x37e80000}, {0x37e88000}, {0x37e90000}, {0x37e98000}, + {0x37ea0000}, {0x37ea8000}, {0x37eb0000}, {0x37eb8000}, + {0x37ec0000}, {0x37ec8000}, {0x37ed0000}, {0x37ed8000}, + {0x37ee0000}, {0x37ee8000}, {0x37ef0000}, {0x37ef8000}, + {0x37f00000}, {0x37f08000}, {0x37f10000}, {0x37f18000}, + {0x37f20000}, {0x37f28000}, {0x37f30000}, {0x37f38000}, + {0x37f40000}, {0x37f48000}, {0x37f50000}, {0x37f58000}, + {0x37f60000}, {0x37f68000}, {0x37f70000}, {0x37f78000}, + {0x37f80000}, {0x37f88000}, {0x37f90000}, {0x37f98000}, + {0x37fa0000}, {0x37fa8000}, {0x37fb0000}, {0x37fb8000}, + {0x37fc0000}, {0x37fc8000}, {0x37fd0000}, {0x37fd8000}, + {0x37fe0000}, {0x37fe8000}, {0x37ff0000}, {0x37ff8000}, + {0x38000000}, {0x38004000}, {0x38008000}, {0x3800c000}, + {0x38010000}, {0x38014000}, {0x38018000}, {0x3801c000}, + {0x38020000}, {0x38024000}, {0x38028000}, {0x3802c000}, + {0x38030000}, {0x38034000}, {0x38038000}, {0x3803c000}, + {0x38040000}, {0x38044000}, {0x38048000}, {0x3804c000}, + {0x38050000}, {0x38054000}, {0x38058000}, {0x3805c000}, + {0x38060000}, {0x38064000}, {0x38068000}, {0x3806c000}, + {0x38070000}, {0x38074000}, {0x38078000}, {0x3807c000}, + {0x38080000}, {0x38084000}, {0x38088000}, {0x3808c000}, + {0x38090000}, {0x38094000}, {0x38098000}, {0x3809c000}, + {0x380a0000}, {0x380a4000}, {0x380a8000}, {0x380ac000}, + {0x380b0000}, {0x380b4000}, {0x380b8000}, {0x380bc000}, + {0x380c0000}, {0x380c4000}, {0x380c8000}, {0x380cc000}, + {0x380d0000}, {0x380d4000}, {0x380d8000}, {0x380dc000}, + {0x380e0000}, {0x380e4000}, {0x380e8000}, {0x380ec000}, + {0x380f0000}, {0x380f4000}, {0x380f8000}, {0x380fc000}, + {0x38100000}, {0x38104000}, {0x38108000}, {0x3810c000}, + {0x38110000}, {0x38114000}, {0x38118000}, {0x3811c000}, + {0x38120000}, {0x38124000}, {0x38128000}, {0x3812c000}, + {0x38130000}, {0x38134000}, {0x38138000}, {0x3813c000}, + {0x38140000}, {0x38144000}, {0x38148000}, {0x3814c000}, + {0x38150000}, {0x38154000}, {0x38158000}, {0x3815c000}, + {0x38160000}, {0x38164000}, {0x38168000}, {0x3816c000}, + {0x38170000}, {0x38174000}, {0x38178000}, {0x3817c000}, + {0x38180000}, {0x38184000}, {0x38188000}, {0x3818c000}, + {0x38190000}, {0x38194000}, {0x38198000}, {0x3819c000}, + {0x381a0000}, {0x381a4000}, {0x381a8000}, {0x381ac000}, + {0x381b0000}, {0x381b4000}, {0x381b8000}, {0x381bc000}, + {0x381c0000}, {0x381c4000}, {0x381c8000}, {0x381cc000}, + {0x381d0000}, {0x381d4000}, {0x381d8000}, {0x381dc000}, + {0x381e0000}, {0x381e4000}, {0x381e8000}, {0x381ec000}, + {0x381f0000}, {0x381f4000}, {0x381f8000}, {0x381fc000}, + {0x38200000}, {0x38204000}, {0x38208000}, {0x3820c000}, + {0x38210000}, {0x38214000}, {0x38218000}, {0x3821c000}, + {0x38220000}, {0x38224000}, {0x38228000}, {0x3822c000}, + {0x38230000}, {0x38234000}, {0x38238000}, {0x3823c000}, + {0x38240000}, {0x38244000}, {0x38248000}, {0x3824c000}, + {0x38250000}, {0x38254000}, {0x38258000}, {0x3825c000}, + {0x38260000}, {0x38264000}, {0x38268000}, {0x3826c000}, + {0x38270000}, {0x38274000}, {0x38278000}, {0x3827c000}, + {0x38280000}, {0x38284000}, {0x38288000}, {0x3828c000}, + {0x38290000}, {0x38294000}, {0x38298000}, {0x3829c000}, + {0x382a0000}, {0x382a4000}, {0x382a8000}, {0x382ac000}, + {0x382b0000}, {0x382b4000}, {0x382b8000}, {0x382bc000}, + {0x382c0000}, {0x382c4000}, {0x382c8000}, {0x382cc000}, + {0x382d0000}, {0x382d4000}, {0x382d8000}, {0x382dc000}, + {0x382e0000}, {0x382e4000}, {0x382e8000}, {0x382ec000}, + {0x382f0000}, {0x382f4000}, {0x382f8000}, {0x382fc000}, + {0x38300000}, {0x38304000}, {0x38308000}, {0x3830c000}, + {0x38310000}, {0x38314000}, {0x38318000}, {0x3831c000}, + {0x38320000}, {0x38324000}, {0x38328000}, {0x3832c000}, + {0x38330000}, {0x38334000}, {0x38338000}, {0x3833c000}, + {0x38340000}, {0x38344000}, {0x38348000}, {0x3834c000}, + {0x38350000}, {0x38354000}, {0x38358000}, {0x3835c000}, + {0x38360000}, {0x38364000}, {0x38368000}, {0x3836c000}, + {0x38370000}, {0x38374000}, {0x38378000}, {0x3837c000}, + {0x38380000}, {0x38384000}, {0x38388000}, {0x3838c000}, + {0x38390000}, {0x38394000}, {0x38398000}, {0x3839c000}, + {0x383a0000}, {0x383a4000}, {0x383a8000}, {0x383ac000}, + {0x383b0000}, {0x383b4000}, {0x383b8000}, {0x383bc000}, + {0x383c0000}, {0x383c4000}, {0x383c8000}, {0x383cc000}, + {0x383d0000}, {0x383d4000}, {0x383d8000}, {0x383dc000}, + {0x383e0000}, {0x383e4000}, {0x383e8000}, {0x383ec000}, + {0x383f0000}, {0x383f4000}, {0x383f8000}, {0x383fc000}, + {0x38400000}, {0x38404000}, {0x38408000}, {0x3840c000}, + {0x38410000}, {0x38414000}, {0x38418000}, {0x3841c000}, + {0x38420000}, {0x38424000}, {0x38428000}, {0x3842c000}, + {0x38430000}, {0x38434000}, {0x38438000}, {0x3843c000}, + {0x38440000}, {0x38444000}, {0x38448000}, {0x3844c000}, + {0x38450000}, {0x38454000}, {0x38458000}, {0x3845c000}, + {0x38460000}, {0x38464000}, {0x38468000}, {0x3846c000}, + {0x38470000}, {0x38474000}, {0x38478000}, {0x3847c000}, + {0x38480000}, {0x38484000}, {0x38488000}, {0x3848c000}, + {0x38490000}, {0x38494000}, {0x38498000}, {0x3849c000}, + {0x384a0000}, {0x384a4000}, {0x384a8000}, {0x384ac000}, + {0x384b0000}, {0x384b4000}, {0x384b8000}, {0x384bc000}, + {0x384c0000}, {0x384c4000}, {0x384c8000}, {0x384cc000}, + {0x384d0000}, {0x384d4000}, {0x384d8000}, {0x384dc000}, + {0x384e0000}, {0x384e4000}, {0x384e8000}, {0x384ec000}, + {0x384f0000}, {0x384f4000}, {0x384f8000}, {0x384fc000}, + {0x38500000}, {0x38504000}, {0x38508000}, {0x3850c000}, + {0x38510000}, {0x38514000}, {0x38518000}, {0x3851c000}, + {0x38520000}, {0x38524000}, {0x38528000}, {0x3852c000}, + {0x38530000}, {0x38534000}, {0x38538000}, {0x3853c000}, + {0x38540000}, {0x38544000}, {0x38548000}, {0x3854c000}, + {0x38550000}, {0x38554000}, {0x38558000}, {0x3855c000}, + {0x38560000}, {0x38564000}, {0x38568000}, {0x3856c000}, + {0x38570000}, {0x38574000}, {0x38578000}, {0x3857c000}, + {0x38580000}, {0x38584000}, {0x38588000}, {0x3858c000}, + {0x38590000}, {0x38594000}, {0x38598000}, {0x3859c000}, + {0x385a0000}, {0x385a4000}, {0x385a8000}, {0x385ac000}, + {0x385b0000}, {0x385b4000}, {0x385b8000}, {0x385bc000}, + {0x385c0000}, {0x385c4000}, {0x385c8000}, {0x385cc000}, + {0x385d0000}, {0x385d4000}, {0x385d8000}, {0x385dc000}, + {0x385e0000}, {0x385e4000}, {0x385e8000}, {0x385ec000}, + {0x385f0000}, {0x385f4000}, {0x385f8000}, {0x385fc000}, + {0x38600000}, {0x38604000}, {0x38608000}, {0x3860c000}, + {0x38610000}, {0x38614000}, {0x38618000}, {0x3861c000}, + {0x38620000}, {0x38624000}, {0x38628000}, {0x3862c000}, + {0x38630000}, {0x38634000}, {0x38638000}, {0x3863c000}, + {0x38640000}, {0x38644000}, {0x38648000}, {0x3864c000}, + {0x38650000}, {0x38654000}, {0x38658000}, {0x3865c000}, + {0x38660000}, {0x38664000}, {0x38668000}, {0x3866c000}, + {0x38670000}, {0x38674000}, {0x38678000}, {0x3867c000}, + {0x38680000}, {0x38684000}, {0x38688000}, {0x3868c000}, + {0x38690000}, {0x38694000}, {0x38698000}, {0x3869c000}, + {0x386a0000}, {0x386a4000}, {0x386a8000}, {0x386ac000}, + {0x386b0000}, {0x386b4000}, {0x386b8000}, {0x386bc000}, + {0x386c0000}, {0x386c4000}, {0x386c8000}, {0x386cc000}, + {0x386d0000}, {0x386d4000}, {0x386d8000}, {0x386dc000}, + {0x386e0000}, {0x386e4000}, {0x386e8000}, {0x386ec000}, + {0x386f0000}, {0x386f4000}, {0x386f8000}, {0x386fc000}, + {0x38700000}, {0x38704000}, {0x38708000}, {0x3870c000}, + {0x38710000}, {0x38714000}, {0x38718000}, {0x3871c000}, + {0x38720000}, {0x38724000}, {0x38728000}, {0x3872c000}, + {0x38730000}, {0x38734000}, {0x38738000}, {0x3873c000}, + {0x38740000}, {0x38744000}, {0x38748000}, {0x3874c000}, + {0x38750000}, {0x38754000}, {0x38758000}, {0x3875c000}, + {0x38760000}, {0x38764000}, {0x38768000}, {0x3876c000}, + {0x38770000}, {0x38774000}, {0x38778000}, {0x3877c000}, + {0x38780000}, {0x38784000}, {0x38788000}, {0x3878c000}, + {0x38790000}, {0x38794000}, {0x38798000}, {0x3879c000}, + {0x387a0000}, {0x387a4000}, {0x387a8000}, {0x387ac000}, + {0x387b0000}, {0x387b4000}, {0x387b8000}, {0x387bc000}, + {0x387c0000}, {0x387c4000}, {0x387c8000}, {0x387cc000}, + {0x387d0000}, {0x387d4000}, {0x387d8000}, {0x387dc000}, + {0x387e0000}, {0x387e4000}, {0x387e8000}, {0x387ec000}, + {0x387f0000}, {0x387f4000}, {0x387f8000}, {0x387fc000}, + {0x38800000}, {0x38802000}, {0x38804000}, {0x38806000}, + {0x38808000}, {0x3880a000}, {0x3880c000}, {0x3880e000}, + {0x38810000}, {0x38812000}, {0x38814000}, {0x38816000}, + {0x38818000}, {0x3881a000}, {0x3881c000}, {0x3881e000}, + {0x38820000}, {0x38822000}, {0x38824000}, {0x38826000}, + {0x38828000}, {0x3882a000}, {0x3882c000}, {0x3882e000}, + {0x38830000}, {0x38832000}, {0x38834000}, {0x38836000}, + {0x38838000}, {0x3883a000}, {0x3883c000}, {0x3883e000}, + {0x38840000}, {0x38842000}, {0x38844000}, {0x38846000}, + {0x38848000}, {0x3884a000}, {0x3884c000}, {0x3884e000}, + {0x38850000}, {0x38852000}, {0x38854000}, {0x38856000}, + {0x38858000}, {0x3885a000}, {0x3885c000}, {0x3885e000}, + {0x38860000}, {0x38862000}, {0x38864000}, {0x38866000}, + {0x38868000}, {0x3886a000}, {0x3886c000}, {0x3886e000}, + {0x38870000}, {0x38872000}, {0x38874000}, {0x38876000}, + {0x38878000}, {0x3887a000}, {0x3887c000}, {0x3887e000}, + {0x38880000}, {0x38882000}, {0x38884000}, {0x38886000}, + {0x38888000}, {0x3888a000}, {0x3888c000}, {0x3888e000}, + {0x38890000}, {0x38892000}, {0x38894000}, {0x38896000}, + {0x38898000}, {0x3889a000}, {0x3889c000}, {0x3889e000}, + {0x388a0000}, {0x388a2000}, {0x388a4000}, {0x388a6000}, + {0x388a8000}, {0x388aa000}, {0x388ac000}, {0x388ae000}, + {0x388b0000}, {0x388b2000}, {0x388b4000}, {0x388b6000}, + {0x388b8000}, {0x388ba000}, {0x388bc000}, {0x388be000}, + {0x388c0000}, {0x388c2000}, {0x388c4000}, {0x388c6000}, + {0x388c8000}, {0x388ca000}, {0x388cc000}, {0x388ce000}, + {0x388d0000}, {0x388d2000}, {0x388d4000}, {0x388d6000}, + {0x388d8000}, {0x388da000}, {0x388dc000}, {0x388de000}, + {0x388e0000}, {0x388e2000}, {0x388e4000}, {0x388e6000}, + {0x388e8000}, {0x388ea000}, {0x388ec000}, {0x388ee000}, + {0x388f0000}, {0x388f2000}, {0x388f4000}, {0x388f6000}, + {0x388f8000}, {0x388fa000}, {0x388fc000}, {0x388fe000}, + {0x38900000}, {0x38902000}, {0x38904000}, {0x38906000}, + {0x38908000}, {0x3890a000}, {0x3890c000}, {0x3890e000}, + {0x38910000}, {0x38912000}, {0x38914000}, {0x38916000}, + {0x38918000}, {0x3891a000}, {0x3891c000}, {0x3891e000}, + {0x38920000}, {0x38922000}, {0x38924000}, {0x38926000}, + {0x38928000}, {0x3892a000}, {0x3892c000}, {0x3892e000}, + {0x38930000}, {0x38932000}, {0x38934000}, {0x38936000}, + {0x38938000}, {0x3893a000}, {0x3893c000}, {0x3893e000}, + {0x38940000}, {0x38942000}, {0x38944000}, {0x38946000}, + {0x38948000}, {0x3894a000}, {0x3894c000}, {0x3894e000}, + {0x38950000}, {0x38952000}, {0x38954000}, {0x38956000}, + {0x38958000}, {0x3895a000}, {0x3895c000}, {0x3895e000}, + {0x38960000}, {0x38962000}, {0x38964000}, {0x38966000}, + {0x38968000}, {0x3896a000}, {0x3896c000}, {0x3896e000}, + {0x38970000}, {0x38972000}, {0x38974000}, {0x38976000}, + {0x38978000}, {0x3897a000}, {0x3897c000}, {0x3897e000}, + {0x38980000}, {0x38982000}, {0x38984000}, {0x38986000}, + {0x38988000}, {0x3898a000}, {0x3898c000}, {0x3898e000}, + {0x38990000}, {0x38992000}, {0x38994000}, {0x38996000}, + {0x38998000}, {0x3899a000}, {0x3899c000}, {0x3899e000}, + {0x389a0000}, {0x389a2000}, {0x389a4000}, {0x389a6000}, + {0x389a8000}, {0x389aa000}, {0x389ac000}, {0x389ae000}, + {0x389b0000}, {0x389b2000}, {0x389b4000}, {0x389b6000}, + {0x389b8000}, {0x389ba000}, {0x389bc000}, {0x389be000}, + {0x389c0000}, {0x389c2000}, {0x389c4000}, {0x389c6000}, + {0x389c8000}, {0x389ca000}, {0x389cc000}, {0x389ce000}, + {0x389d0000}, {0x389d2000}, {0x389d4000}, {0x389d6000}, + {0x389d8000}, {0x389da000}, {0x389dc000}, {0x389de000}, + {0x389e0000}, {0x389e2000}, {0x389e4000}, {0x389e6000}, + {0x389e8000}, {0x389ea000}, {0x389ec000}, {0x389ee000}, + {0x389f0000}, {0x389f2000}, {0x389f4000}, {0x389f6000}, + {0x389f8000}, {0x389fa000}, {0x389fc000}, {0x389fe000}, + {0x38a00000}, {0x38a02000}, {0x38a04000}, {0x38a06000}, + {0x38a08000}, {0x38a0a000}, {0x38a0c000}, {0x38a0e000}, + {0x38a10000}, {0x38a12000}, {0x38a14000}, {0x38a16000}, + {0x38a18000}, {0x38a1a000}, {0x38a1c000}, {0x38a1e000}, + {0x38a20000}, {0x38a22000}, {0x38a24000}, {0x38a26000}, + {0x38a28000}, {0x38a2a000}, {0x38a2c000}, {0x38a2e000}, + {0x38a30000}, {0x38a32000}, {0x38a34000}, {0x38a36000}, + {0x38a38000}, {0x38a3a000}, {0x38a3c000}, {0x38a3e000}, + {0x38a40000}, {0x38a42000}, {0x38a44000}, {0x38a46000}, + {0x38a48000}, {0x38a4a000}, {0x38a4c000}, {0x38a4e000}, + {0x38a50000}, {0x38a52000}, {0x38a54000}, {0x38a56000}, + {0x38a58000}, {0x38a5a000}, {0x38a5c000}, {0x38a5e000}, + {0x38a60000}, {0x38a62000}, {0x38a64000}, {0x38a66000}, + {0x38a68000}, {0x38a6a000}, {0x38a6c000}, {0x38a6e000}, + {0x38a70000}, {0x38a72000}, {0x38a74000}, {0x38a76000}, + {0x38a78000}, {0x38a7a000}, {0x38a7c000}, {0x38a7e000}, + {0x38a80000}, {0x38a82000}, {0x38a84000}, {0x38a86000}, + {0x38a88000}, {0x38a8a000}, {0x38a8c000}, {0x38a8e000}, + {0x38a90000}, {0x38a92000}, {0x38a94000}, {0x38a96000}, + {0x38a98000}, {0x38a9a000}, {0x38a9c000}, {0x38a9e000}, + {0x38aa0000}, {0x38aa2000}, {0x38aa4000}, {0x38aa6000}, + {0x38aa8000}, {0x38aaa000}, {0x38aac000}, {0x38aae000}, + {0x38ab0000}, {0x38ab2000}, {0x38ab4000}, {0x38ab6000}, + {0x38ab8000}, {0x38aba000}, {0x38abc000}, {0x38abe000}, + {0x38ac0000}, {0x38ac2000}, {0x38ac4000}, {0x38ac6000}, + {0x38ac8000}, {0x38aca000}, {0x38acc000}, {0x38ace000}, + {0x38ad0000}, {0x38ad2000}, {0x38ad4000}, {0x38ad6000}, + {0x38ad8000}, {0x38ada000}, {0x38adc000}, {0x38ade000}, + {0x38ae0000}, {0x38ae2000}, {0x38ae4000}, {0x38ae6000}, + {0x38ae8000}, {0x38aea000}, {0x38aec000}, {0x38aee000}, + {0x38af0000}, {0x38af2000}, {0x38af4000}, {0x38af6000}, + {0x38af8000}, {0x38afa000}, {0x38afc000}, {0x38afe000}, + {0x38b00000}, {0x38b02000}, {0x38b04000}, {0x38b06000}, + {0x38b08000}, {0x38b0a000}, {0x38b0c000}, {0x38b0e000}, + {0x38b10000}, {0x38b12000}, {0x38b14000}, {0x38b16000}, + {0x38b18000}, {0x38b1a000}, {0x38b1c000}, {0x38b1e000}, + {0x38b20000}, {0x38b22000}, {0x38b24000}, {0x38b26000}, + {0x38b28000}, {0x38b2a000}, {0x38b2c000}, {0x38b2e000}, + {0x38b30000}, {0x38b32000}, {0x38b34000}, {0x38b36000}, + {0x38b38000}, {0x38b3a000}, {0x38b3c000}, {0x38b3e000}, + {0x38b40000}, {0x38b42000}, {0x38b44000}, {0x38b46000}, + {0x38b48000}, {0x38b4a000}, {0x38b4c000}, {0x38b4e000}, + {0x38b50000}, {0x38b52000}, {0x38b54000}, {0x38b56000}, + {0x38b58000}, {0x38b5a000}, {0x38b5c000}, {0x38b5e000}, + {0x38b60000}, {0x38b62000}, {0x38b64000}, {0x38b66000}, + {0x38b68000}, {0x38b6a000}, {0x38b6c000}, {0x38b6e000}, + {0x38b70000}, {0x38b72000}, {0x38b74000}, {0x38b76000}, + {0x38b78000}, {0x38b7a000}, {0x38b7c000}, {0x38b7e000}, + {0x38b80000}, {0x38b82000}, {0x38b84000}, {0x38b86000}, + {0x38b88000}, {0x38b8a000}, {0x38b8c000}, {0x38b8e000}, + {0x38b90000}, {0x38b92000}, {0x38b94000}, {0x38b96000}, + {0x38b98000}, {0x38b9a000}, {0x38b9c000}, {0x38b9e000}, + {0x38ba0000}, {0x38ba2000}, {0x38ba4000}, {0x38ba6000}, + {0x38ba8000}, {0x38baa000}, {0x38bac000}, {0x38bae000}, + {0x38bb0000}, {0x38bb2000}, {0x38bb4000}, {0x38bb6000}, + {0x38bb8000}, {0x38bba000}, {0x38bbc000}, {0x38bbe000}, + {0x38bc0000}, {0x38bc2000}, {0x38bc4000}, {0x38bc6000}, + {0x38bc8000}, {0x38bca000}, {0x38bcc000}, {0x38bce000}, + {0x38bd0000}, {0x38bd2000}, {0x38bd4000}, {0x38bd6000}, + {0x38bd8000}, {0x38bda000}, {0x38bdc000}, {0x38bde000}, + {0x38be0000}, {0x38be2000}, {0x38be4000}, {0x38be6000}, + {0x38be8000}, {0x38bea000}, {0x38bec000}, {0x38bee000}, + {0x38bf0000}, {0x38bf2000}, {0x38bf4000}, {0x38bf6000}, + {0x38bf8000}, {0x38bfa000}, {0x38bfc000}, {0x38bfe000}, + {0x38c00000}, {0x38c02000}, {0x38c04000}, {0x38c06000}, + {0x38c08000}, {0x38c0a000}, {0x38c0c000}, {0x38c0e000}, + {0x38c10000}, {0x38c12000}, {0x38c14000}, {0x38c16000}, + {0x38c18000}, {0x38c1a000}, {0x38c1c000}, {0x38c1e000}, + {0x38c20000}, {0x38c22000}, {0x38c24000}, {0x38c26000}, + {0x38c28000}, {0x38c2a000}, {0x38c2c000}, {0x38c2e000}, + {0x38c30000}, {0x38c32000}, {0x38c34000}, {0x38c36000}, + {0x38c38000}, {0x38c3a000}, {0x38c3c000}, {0x38c3e000}, + {0x38c40000}, {0x38c42000}, {0x38c44000}, {0x38c46000}, + {0x38c48000}, {0x38c4a000}, {0x38c4c000}, {0x38c4e000}, + {0x38c50000}, {0x38c52000}, {0x38c54000}, {0x38c56000}, + {0x38c58000}, {0x38c5a000}, {0x38c5c000}, {0x38c5e000}, + {0x38c60000}, {0x38c62000}, {0x38c64000}, {0x38c66000}, + {0x38c68000}, {0x38c6a000}, {0x38c6c000}, {0x38c6e000}, + {0x38c70000}, {0x38c72000}, {0x38c74000}, {0x38c76000}, + {0x38c78000}, {0x38c7a000}, {0x38c7c000}, {0x38c7e000}, + {0x38c80000}, {0x38c82000}, {0x38c84000}, {0x38c86000}, + {0x38c88000}, {0x38c8a000}, {0x38c8c000}, {0x38c8e000}, + {0x38c90000}, {0x38c92000}, {0x38c94000}, {0x38c96000}, + {0x38c98000}, {0x38c9a000}, {0x38c9c000}, {0x38c9e000}, + {0x38ca0000}, {0x38ca2000}, {0x38ca4000}, {0x38ca6000}, + {0x38ca8000}, {0x38caa000}, {0x38cac000}, {0x38cae000}, + {0x38cb0000}, {0x38cb2000}, {0x38cb4000}, {0x38cb6000}, + {0x38cb8000}, {0x38cba000}, {0x38cbc000}, {0x38cbe000}, + {0x38cc0000}, {0x38cc2000}, {0x38cc4000}, {0x38cc6000}, + {0x38cc8000}, {0x38cca000}, {0x38ccc000}, {0x38cce000}, + {0x38cd0000}, {0x38cd2000}, {0x38cd4000}, {0x38cd6000}, + {0x38cd8000}, {0x38cda000}, {0x38cdc000}, {0x38cde000}, + {0x38ce0000}, {0x38ce2000}, {0x38ce4000}, {0x38ce6000}, + {0x38ce8000}, {0x38cea000}, {0x38cec000}, {0x38cee000}, + {0x38cf0000}, {0x38cf2000}, {0x38cf4000}, {0x38cf6000}, + {0x38cf8000}, {0x38cfa000}, {0x38cfc000}, {0x38cfe000}, + {0x38d00000}, {0x38d02000}, {0x38d04000}, {0x38d06000}, + {0x38d08000}, {0x38d0a000}, {0x38d0c000}, {0x38d0e000}, + {0x38d10000}, {0x38d12000}, {0x38d14000}, {0x38d16000}, + {0x38d18000}, {0x38d1a000}, {0x38d1c000}, {0x38d1e000}, + {0x38d20000}, {0x38d22000}, {0x38d24000}, {0x38d26000}, + {0x38d28000}, {0x38d2a000}, {0x38d2c000}, {0x38d2e000}, + {0x38d30000}, {0x38d32000}, {0x38d34000}, {0x38d36000}, + {0x38d38000}, {0x38d3a000}, {0x38d3c000}, {0x38d3e000}, + {0x38d40000}, {0x38d42000}, {0x38d44000}, {0x38d46000}, + {0x38d48000}, {0x38d4a000}, {0x38d4c000}, {0x38d4e000}, + {0x38d50000}, {0x38d52000}, {0x38d54000}, {0x38d56000}, + {0x38d58000}, {0x38d5a000}, {0x38d5c000}, {0x38d5e000}, + {0x38d60000}, {0x38d62000}, {0x38d64000}, {0x38d66000}, + {0x38d68000}, {0x38d6a000}, {0x38d6c000}, {0x38d6e000}, + {0x38d70000}, {0x38d72000}, {0x38d74000}, {0x38d76000}, + {0x38d78000}, {0x38d7a000}, {0x38d7c000}, {0x38d7e000}, + {0x38d80000}, {0x38d82000}, {0x38d84000}, {0x38d86000}, + {0x38d88000}, {0x38d8a000}, {0x38d8c000}, {0x38d8e000}, + {0x38d90000}, {0x38d92000}, {0x38d94000}, {0x38d96000}, + {0x38d98000}, {0x38d9a000}, {0x38d9c000}, {0x38d9e000}, + {0x38da0000}, {0x38da2000}, {0x38da4000}, {0x38da6000}, + {0x38da8000}, {0x38daa000}, {0x38dac000}, {0x38dae000}, + {0x38db0000}, {0x38db2000}, {0x38db4000}, {0x38db6000}, + {0x38db8000}, {0x38dba000}, {0x38dbc000}, {0x38dbe000}, + {0x38dc0000}, {0x38dc2000}, {0x38dc4000}, {0x38dc6000}, + {0x38dc8000}, {0x38dca000}, {0x38dcc000}, {0x38dce000}, + {0x38dd0000}, {0x38dd2000}, {0x38dd4000}, {0x38dd6000}, + {0x38dd8000}, {0x38dda000}, {0x38ddc000}, {0x38dde000}, + {0x38de0000}, {0x38de2000}, {0x38de4000}, {0x38de6000}, + {0x38de8000}, {0x38dea000}, {0x38dec000}, {0x38dee000}, + {0x38df0000}, {0x38df2000}, {0x38df4000}, {0x38df6000}, + {0x38df8000}, {0x38dfa000}, {0x38dfc000}, {0x38dfe000}, + {0x38e00000}, {0x38e02000}, {0x38e04000}, {0x38e06000}, + {0x38e08000}, {0x38e0a000}, {0x38e0c000}, {0x38e0e000}, + {0x38e10000}, {0x38e12000}, {0x38e14000}, {0x38e16000}, + {0x38e18000}, {0x38e1a000}, {0x38e1c000}, {0x38e1e000}, + {0x38e20000}, {0x38e22000}, {0x38e24000}, {0x38e26000}, + {0x38e28000}, {0x38e2a000}, {0x38e2c000}, {0x38e2e000}, + {0x38e30000}, {0x38e32000}, {0x38e34000}, {0x38e36000}, + {0x38e38000}, {0x38e3a000}, {0x38e3c000}, {0x38e3e000}, + {0x38e40000}, {0x38e42000}, {0x38e44000}, {0x38e46000}, + {0x38e48000}, {0x38e4a000}, {0x38e4c000}, {0x38e4e000}, + {0x38e50000}, {0x38e52000}, {0x38e54000}, {0x38e56000}, + {0x38e58000}, {0x38e5a000}, {0x38e5c000}, {0x38e5e000}, + {0x38e60000}, {0x38e62000}, {0x38e64000}, {0x38e66000}, + {0x38e68000}, {0x38e6a000}, {0x38e6c000}, {0x38e6e000}, + {0x38e70000}, {0x38e72000}, {0x38e74000}, {0x38e76000}, + {0x38e78000}, {0x38e7a000}, {0x38e7c000}, {0x38e7e000}, + {0x38e80000}, {0x38e82000}, {0x38e84000}, {0x38e86000}, + {0x38e88000}, {0x38e8a000}, {0x38e8c000}, {0x38e8e000}, + {0x38e90000}, {0x38e92000}, {0x38e94000}, {0x38e96000}, + {0x38e98000}, {0x38e9a000}, {0x38e9c000}, {0x38e9e000}, + {0x38ea0000}, {0x38ea2000}, {0x38ea4000}, {0x38ea6000}, + {0x38ea8000}, {0x38eaa000}, {0x38eac000}, {0x38eae000}, + {0x38eb0000}, {0x38eb2000}, {0x38eb4000}, {0x38eb6000}, + {0x38eb8000}, {0x38eba000}, {0x38ebc000}, {0x38ebe000}, + {0x38ec0000}, {0x38ec2000}, {0x38ec4000}, {0x38ec6000}, + {0x38ec8000}, {0x38eca000}, {0x38ecc000}, {0x38ece000}, + {0x38ed0000}, {0x38ed2000}, {0x38ed4000}, {0x38ed6000}, + {0x38ed8000}, {0x38eda000}, {0x38edc000}, {0x38ede000}, + {0x38ee0000}, {0x38ee2000}, {0x38ee4000}, {0x38ee6000}, + {0x38ee8000}, {0x38eea000}, {0x38eec000}, {0x38eee000}, + {0x38ef0000}, {0x38ef2000}, {0x38ef4000}, {0x38ef6000}, + {0x38ef8000}, {0x38efa000}, {0x38efc000}, {0x38efe000}, + {0x38f00000}, {0x38f02000}, {0x38f04000}, {0x38f06000}, + {0x38f08000}, {0x38f0a000}, {0x38f0c000}, {0x38f0e000}, + {0x38f10000}, {0x38f12000}, {0x38f14000}, {0x38f16000}, + {0x38f18000}, {0x38f1a000}, {0x38f1c000}, {0x38f1e000}, + {0x38f20000}, {0x38f22000}, {0x38f24000}, {0x38f26000}, + {0x38f28000}, {0x38f2a000}, {0x38f2c000}, {0x38f2e000}, + {0x38f30000}, {0x38f32000}, {0x38f34000}, {0x38f36000}, + {0x38f38000}, {0x38f3a000}, {0x38f3c000}, {0x38f3e000}, + {0x38f40000}, {0x38f42000}, {0x38f44000}, {0x38f46000}, + {0x38f48000}, {0x38f4a000}, {0x38f4c000}, {0x38f4e000}, + {0x38f50000}, {0x38f52000}, {0x38f54000}, {0x38f56000}, + {0x38f58000}, {0x38f5a000}, {0x38f5c000}, {0x38f5e000}, + {0x38f60000}, {0x38f62000}, {0x38f64000}, {0x38f66000}, + {0x38f68000}, {0x38f6a000}, {0x38f6c000}, {0x38f6e000}, + {0x38f70000}, {0x38f72000}, {0x38f74000}, {0x38f76000}, + {0x38f78000}, {0x38f7a000}, {0x38f7c000}, {0x38f7e000}, + {0x38f80000}, {0x38f82000}, {0x38f84000}, {0x38f86000}, + {0x38f88000}, {0x38f8a000}, {0x38f8c000}, {0x38f8e000}, + {0x38f90000}, {0x38f92000}, {0x38f94000}, {0x38f96000}, + {0x38f98000}, {0x38f9a000}, {0x38f9c000}, {0x38f9e000}, + {0x38fa0000}, {0x38fa2000}, {0x38fa4000}, {0x38fa6000}, + {0x38fa8000}, {0x38faa000}, {0x38fac000}, {0x38fae000}, + {0x38fb0000}, {0x38fb2000}, {0x38fb4000}, {0x38fb6000}, + {0x38fb8000}, {0x38fba000}, {0x38fbc000}, {0x38fbe000}, + {0x38fc0000}, {0x38fc2000}, {0x38fc4000}, {0x38fc6000}, + {0x38fc8000}, {0x38fca000}, {0x38fcc000}, {0x38fce000}, + {0x38fd0000}, {0x38fd2000}, {0x38fd4000}, {0x38fd6000}, + {0x38fd8000}, {0x38fda000}, {0x38fdc000}, {0x38fde000}, + {0x38fe0000}, {0x38fe2000}, {0x38fe4000}, {0x38fe6000}, + {0x38fe8000}, {0x38fea000}, {0x38fec000}, {0x38fee000}, + {0x38ff0000}, {0x38ff2000}, {0x38ff4000}, {0x38ff6000}, + {0x38ff8000}, {0x38ffa000}, {0x38ffc000}, {0x38ffe000}, + {0x39000000}, {0x39002000}, {0x39004000}, {0x39006000}, + {0x39008000}, {0x3900a000}, {0x3900c000}, {0x3900e000}, + {0x39010000}, {0x39012000}, {0x39014000}, {0x39016000}, + {0x39018000}, {0x3901a000}, {0x3901c000}, {0x3901e000}, + {0x39020000}, {0x39022000}, {0x39024000}, {0x39026000}, + {0x39028000}, {0x3902a000}, {0x3902c000}, {0x3902e000}, + {0x39030000}, {0x39032000}, {0x39034000}, {0x39036000}, + {0x39038000}, {0x3903a000}, {0x3903c000}, {0x3903e000}, + {0x39040000}, {0x39042000}, {0x39044000}, {0x39046000}, + {0x39048000}, {0x3904a000}, {0x3904c000}, {0x3904e000}, + {0x39050000}, {0x39052000}, {0x39054000}, {0x39056000}, + {0x39058000}, {0x3905a000}, {0x3905c000}, {0x3905e000}, + {0x39060000}, {0x39062000}, {0x39064000}, {0x39066000}, + {0x39068000}, {0x3906a000}, {0x3906c000}, {0x3906e000}, + {0x39070000}, {0x39072000}, {0x39074000}, {0x39076000}, + {0x39078000}, {0x3907a000}, {0x3907c000}, {0x3907e000}, + {0x39080000}, {0x39082000}, {0x39084000}, {0x39086000}, + {0x39088000}, {0x3908a000}, {0x3908c000}, {0x3908e000}, + {0x39090000}, {0x39092000}, {0x39094000}, {0x39096000}, + {0x39098000}, {0x3909a000}, {0x3909c000}, {0x3909e000}, + {0x390a0000}, {0x390a2000}, {0x390a4000}, {0x390a6000}, + {0x390a8000}, {0x390aa000}, {0x390ac000}, {0x390ae000}, + {0x390b0000}, {0x390b2000}, {0x390b4000}, {0x390b6000}, + {0x390b8000}, {0x390ba000}, {0x390bc000}, {0x390be000}, + {0x390c0000}, {0x390c2000}, {0x390c4000}, {0x390c6000}, + {0x390c8000}, {0x390ca000}, {0x390cc000}, {0x390ce000}, + {0x390d0000}, {0x390d2000}, {0x390d4000}, {0x390d6000}, + {0x390d8000}, {0x390da000}, {0x390dc000}, {0x390de000}, + {0x390e0000}, {0x390e2000}, {0x390e4000}, {0x390e6000}, + {0x390e8000}, {0x390ea000}, {0x390ec000}, {0x390ee000}, + {0x390f0000}, {0x390f2000}, {0x390f4000}, {0x390f6000}, + {0x390f8000}, {0x390fa000}, {0x390fc000}, {0x390fe000}, + {0x39100000}, {0x39102000}, {0x39104000}, {0x39106000}, + {0x39108000}, {0x3910a000}, {0x3910c000}, {0x3910e000}, + {0x39110000}, {0x39112000}, {0x39114000}, {0x39116000}, + {0x39118000}, {0x3911a000}, {0x3911c000}, {0x3911e000}, + {0x39120000}, {0x39122000}, {0x39124000}, {0x39126000}, + {0x39128000}, {0x3912a000}, {0x3912c000}, {0x3912e000}, + {0x39130000}, {0x39132000}, {0x39134000}, {0x39136000}, + {0x39138000}, {0x3913a000}, {0x3913c000}, {0x3913e000}, + {0x39140000}, {0x39142000}, {0x39144000}, {0x39146000}, + {0x39148000}, {0x3914a000}, {0x3914c000}, {0x3914e000}, + {0x39150000}, {0x39152000}, {0x39154000}, {0x39156000}, + {0x39158000}, {0x3915a000}, {0x3915c000}, {0x3915e000}, + {0x39160000}, {0x39162000}, {0x39164000}, {0x39166000}, + {0x39168000}, {0x3916a000}, {0x3916c000}, {0x3916e000}, + {0x39170000}, {0x39172000}, {0x39174000}, {0x39176000}, + {0x39178000}, {0x3917a000}, {0x3917c000}, {0x3917e000}, + {0x39180000}, {0x39182000}, {0x39184000}, {0x39186000}, + {0x39188000}, {0x3918a000}, {0x3918c000}, {0x3918e000}, + {0x39190000}, {0x39192000}, {0x39194000}, {0x39196000}, + {0x39198000}, {0x3919a000}, {0x3919c000}, {0x3919e000}, + {0x391a0000}, {0x391a2000}, {0x391a4000}, {0x391a6000}, + {0x391a8000}, {0x391aa000}, {0x391ac000}, {0x391ae000}, + {0x391b0000}, {0x391b2000}, {0x391b4000}, {0x391b6000}, + {0x391b8000}, {0x391ba000}, {0x391bc000}, {0x391be000}, + {0x391c0000}, {0x391c2000}, {0x391c4000}, {0x391c6000}, + {0x391c8000}, {0x391ca000}, {0x391cc000}, {0x391ce000}, + {0x391d0000}, {0x391d2000}, {0x391d4000}, {0x391d6000}, + {0x391d8000}, {0x391da000}, {0x391dc000}, {0x391de000}, + {0x391e0000}, {0x391e2000}, {0x391e4000}, {0x391e6000}, + {0x391e8000}, {0x391ea000}, {0x391ec000}, {0x391ee000}, + {0x391f0000}, {0x391f2000}, {0x391f4000}, {0x391f6000}, + {0x391f8000}, {0x391fa000}, {0x391fc000}, {0x391fe000}, + {0x39200000}, {0x39202000}, {0x39204000}, {0x39206000}, + {0x39208000}, {0x3920a000}, {0x3920c000}, {0x3920e000}, + {0x39210000}, {0x39212000}, {0x39214000}, {0x39216000}, + {0x39218000}, {0x3921a000}, {0x3921c000}, {0x3921e000}, + {0x39220000}, {0x39222000}, {0x39224000}, {0x39226000}, + {0x39228000}, {0x3922a000}, {0x3922c000}, {0x3922e000}, + {0x39230000}, {0x39232000}, {0x39234000}, {0x39236000}, + {0x39238000}, {0x3923a000}, {0x3923c000}, {0x3923e000}, + {0x39240000}, {0x39242000}, {0x39244000}, {0x39246000}, + {0x39248000}, {0x3924a000}, {0x3924c000}, {0x3924e000}, + {0x39250000}, {0x39252000}, {0x39254000}, {0x39256000}, + {0x39258000}, {0x3925a000}, {0x3925c000}, {0x3925e000}, + {0x39260000}, {0x39262000}, {0x39264000}, {0x39266000}, + {0x39268000}, {0x3926a000}, {0x3926c000}, {0x3926e000}, + {0x39270000}, {0x39272000}, {0x39274000}, {0x39276000}, + {0x39278000}, {0x3927a000}, {0x3927c000}, {0x3927e000}, + {0x39280000}, {0x39282000}, {0x39284000}, {0x39286000}, + {0x39288000}, {0x3928a000}, {0x3928c000}, {0x3928e000}, + {0x39290000}, {0x39292000}, {0x39294000}, {0x39296000}, + {0x39298000}, {0x3929a000}, {0x3929c000}, {0x3929e000}, + {0x392a0000}, {0x392a2000}, {0x392a4000}, {0x392a6000}, + {0x392a8000}, {0x392aa000}, {0x392ac000}, {0x392ae000}, + {0x392b0000}, {0x392b2000}, {0x392b4000}, {0x392b6000}, + {0x392b8000}, {0x392ba000}, {0x392bc000}, {0x392be000}, + {0x392c0000}, {0x392c2000}, {0x392c4000}, {0x392c6000}, + {0x392c8000}, {0x392ca000}, {0x392cc000}, {0x392ce000}, + {0x392d0000}, {0x392d2000}, {0x392d4000}, {0x392d6000}, + {0x392d8000}, {0x392da000}, {0x392dc000}, {0x392de000}, + {0x392e0000}, {0x392e2000}, {0x392e4000}, {0x392e6000}, + {0x392e8000}, {0x392ea000}, {0x392ec000}, {0x392ee000}, + {0x392f0000}, {0x392f2000}, {0x392f4000}, {0x392f6000}, + {0x392f8000}, {0x392fa000}, {0x392fc000}, {0x392fe000}, + {0x39300000}, {0x39302000}, {0x39304000}, {0x39306000}, + {0x39308000}, {0x3930a000}, {0x3930c000}, {0x3930e000}, + {0x39310000}, {0x39312000}, {0x39314000}, {0x39316000}, + {0x39318000}, {0x3931a000}, {0x3931c000}, {0x3931e000}, + {0x39320000}, {0x39322000}, {0x39324000}, {0x39326000}, + {0x39328000}, {0x3932a000}, {0x3932c000}, {0x3932e000}, + {0x39330000}, {0x39332000}, {0x39334000}, {0x39336000}, + {0x39338000}, {0x3933a000}, {0x3933c000}, {0x3933e000}, + {0x39340000}, {0x39342000}, {0x39344000}, {0x39346000}, + {0x39348000}, {0x3934a000}, {0x3934c000}, {0x3934e000}, + {0x39350000}, {0x39352000}, {0x39354000}, {0x39356000}, + {0x39358000}, {0x3935a000}, {0x3935c000}, {0x3935e000}, + {0x39360000}, {0x39362000}, {0x39364000}, {0x39366000}, + {0x39368000}, {0x3936a000}, {0x3936c000}, {0x3936e000}, + {0x39370000}, {0x39372000}, {0x39374000}, {0x39376000}, + {0x39378000}, {0x3937a000}, {0x3937c000}, {0x3937e000}, + {0x39380000}, {0x39382000}, {0x39384000}, {0x39386000}, + {0x39388000}, {0x3938a000}, {0x3938c000}, {0x3938e000}, + {0x39390000}, {0x39392000}, {0x39394000}, {0x39396000}, + {0x39398000}, {0x3939a000}, {0x3939c000}, {0x3939e000}, + {0x393a0000}, {0x393a2000}, {0x393a4000}, {0x393a6000}, + {0x393a8000}, {0x393aa000}, {0x393ac000}, {0x393ae000}, + {0x393b0000}, {0x393b2000}, {0x393b4000}, {0x393b6000}, + {0x393b8000}, {0x393ba000}, {0x393bc000}, {0x393be000}, + {0x393c0000}, {0x393c2000}, {0x393c4000}, {0x393c6000}, + {0x393c8000}, {0x393ca000}, {0x393cc000}, {0x393ce000}, + {0x393d0000}, {0x393d2000}, {0x393d4000}, {0x393d6000}, + {0x393d8000}, {0x393da000}, {0x393dc000}, {0x393de000}, + {0x393e0000}, {0x393e2000}, {0x393e4000}, {0x393e6000}, + {0x393e8000}, {0x393ea000}, {0x393ec000}, {0x393ee000}, + {0x393f0000}, {0x393f2000}, {0x393f4000}, {0x393f6000}, + {0x393f8000}, {0x393fa000}, {0x393fc000}, {0x393fe000}, + {0x39400000}, {0x39402000}, {0x39404000}, {0x39406000}, + {0x39408000}, {0x3940a000}, {0x3940c000}, {0x3940e000}, + {0x39410000}, {0x39412000}, {0x39414000}, {0x39416000}, + {0x39418000}, {0x3941a000}, {0x3941c000}, {0x3941e000}, + {0x39420000}, {0x39422000}, {0x39424000}, {0x39426000}, + {0x39428000}, {0x3942a000}, {0x3942c000}, {0x3942e000}, + {0x39430000}, {0x39432000}, {0x39434000}, {0x39436000}, + {0x39438000}, {0x3943a000}, {0x3943c000}, {0x3943e000}, + {0x39440000}, {0x39442000}, {0x39444000}, {0x39446000}, + {0x39448000}, {0x3944a000}, {0x3944c000}, {0x3944e000}, + {0x39450000}, {0x39452000}, {0x39454000}, {0x39456000}, + {0x39458000}, {0x3945a000}, {0x3945c000}, {0x3945e000}, + {0x39460000}, {0x39462000}, {0x39464000}, {0x39466000}, + {0x39468000}, {0x3946a000}, {0x3946c000}, {0x3946e000}, + {0x39470000}, {0x39472000}, {0x39474000}, {0x39476000}, + {0x39478000}, {0x3947a000}, {0x3947c000}, {0x3947e000}, + {0x39480000}, {0x39482000}, {0x39484000}, {0x39486000}, + {0x39488000}, {0x3948a000}, {0x3948c000}, {0x3948e000}, + {0x39490000}, {0x39492000}, {0x39494000}, {0x39496000}, + {0x39498000}, {0x3949a000}, {0x3949c000}, {0x3949e000}, + {0x394a0000}, {0x394a2000}, {0x394a4000}, {0x394a6000}, + {0x394a8000}, {0x394aa000}, {0x394ac000}, {0x394ae000}, + {0x394b0000}, {0x394b2000}, {0x394b4000}, {0x394b6000}, + {0x394b8000}, {0x394ba000}, {0x394bc000}, {0x394be000}, + {0x394c0000}, {0x394c2000}, {0x394c4000}, {0x394c6000}, + {0x394c8000}, {0x394ca000}, {0x394cc000}, {0x394ce000}, + {0x394d0000}, {0x394d2000}, {0x394d4000}, {0x394d6000}, + {0x394d8000}, {0x394da000}, {0x394dc000}, {0x394de000}, + {0x394e0000}, {0x394e2000}, {0x394e4000}, {0x394e6000}, + {0x394e8000}, {0x394ea000}, {0x394ec000}, {0x394ee000}, + {0x394f0000}, {0x394f2000}, {0x394f4000}, {0x394f6000}, + {0x394f8000}, {0x394fa000}, {0x394fc000}, {0x394fe000}, + {0x39500000}, {0x39502000}, {0x39504000}, {0x39506000}, + {0x39508000}, {0x3950a000}, {0x3950c000}, {0x3950e000}, + {0x39510000}, {0x39512000}, {0x39514000}, {0x39516000}, + {0x39518000}, {0x3951a000}, {0x3951c000}, {0x3951e000}, + {0x39520000}, {0x39522000}, {0x39524000}, {0x39526000}, + {0x39528000}, {0x3952a000}, {0x3952c000}, {0x3952e000}, + {0x39530000}, {0x39532000}, {0x39534000}, {0x39536000}, + {0x39538000}, {0x3953a000}, {0x3953c000}, {0x3953e000}, + {0x39540000}, {0x39542000}, {0x39544000}, {0x39546000}, + {0x39548000}, {0x3954a000}, {0x3954c000}, {0x3954e000}, + {0x39550000}, {0x39552000}, {0x39554000}, {0x39556000}, + {0x39558000}, {0x3955a000}, {0x3955c000}, {0x3955e000}, + {0x39560000}, {0x39562000}, {0x39564000}, {0x39566000}, + {0x39568000}, {0x3956a000}, {0x3956c000}, {0x3956e000}, + {0x39570000}, {0x39572000}, {0x39574000}, {0x39576000}, + {0x39578000}, {0x3957a000}, {0x3957c000}, {0x3957e000}, + {0x39580000}, {0x39582000}, {0x39584000}, {0x39586000}, + {0x39588000}, {0x3958a000}, {0x3958c000}, {0x3958e000}, + {0x39590000}, {0x39592000}, {0x39594000}, {0x39596000}, + {0x39598000}, {0x3959a000}, {0x3959c000}, {0x3959e000}, + {0x395a0000}, {0x395a2000}, {0x395a4000}, {0x395a6000}, + {0x395a8000}, {0x395aa000}, {0x395ac000}, {0x395ae000}, + {0x395b0000}, {0x395b2000}, {0x395b4000}, {0x395b6000}, + {0x395b8000}, {0x395ba000}, {0x395bc000}, {0x395be000}, + {0x395c0000}, {0x395c2000}, {0x395c4000}, {0x395c6000}, + {0x395c8000}, {0x395ca000}, {0x395cc000}, {0x395ce000}, + {0x395d0000}, {0x395d2000}, {0x395d4000}, {0x395d6000}, + {0x395d8000}, {0x395da000}, {0x395dc000}, {0x395de000}, + {0x395e0000}, {0x395e2000}, {0x395e4000}, {0x395e6000}, + {0x395e8000}, {0x395ea000}, {0x395ec000}, {0x395ee000}, + {0x395f0000}, {0x395f2000}, {0x395f4000}, {0x395f6000}, + {0x395f8000}, {0x395fa000}, {0x395fc000}, {0x395fe000}, + {0x39600000}, {0x39602000}, {0x39604000}, {0x39606000}, + {0x39608000}, {0x3960a000}, {0x3960c000}, {0x3960e000}, + {0x39610000}, {0x39612000}, {0x39614000}, {0x39616000}, + {0x39618000}, {0x3961a000}, {0x3961c000}, {0x3961e000}, + {0x39620000}, {0x39622000}, {0x39624000}, {0x39626000}, + {0x39628000}, {0x3962a000}, {0x3962c000}, {0x3962e000}, + {0x39630000}, {0x39632000}, {0x39634000}, {0x39636000}, + {0x39638000}, {0x3963a000}, {0x3963c000}, {0x3963e000}, + {0x39640000}, {0x39642000}, {0x39644000}, {0x39646000}, + {0x39648000}, {0x3964a000}, {0x3964c000}, {0x3964e000}, + {0x39650000}, {0x39652000}, {0x39654000}, {0x39656000}, + {0x39658000}, {0x3965a000}, {0x3965c000}, {0x3965e000}, + {0x39660000}, {0x39662000}, {0x39664000}, {0x39666000}, + {0x39668000}, {0x3966a000}, {0x3966c000}, {0x3966e000}, + {0x39670000}, {0x39672000}, {0x39674000}, {0x39676000}, + {0x39678000}, {0x3967a000}, {0x3967c000}, {0x3967e000}, + {0x39680000}, {0x39682000}, {0x39684000}, {0x39686000}, + {0x39688000}, {0x3968a000}, {0x3968c000}, {0x3968e000}, + {0x39690000}, {0x39692000}, {0x39694000}, {0x39696000}, + {0x39698000}, {0x3969a000}, {0x3969c000}, {0x3969e000}, + {0x396a0000}, {0x396a2000}, {0x396a4000}, {0x396a6000}, + {0x396a8000}, {0x396aa000}, {0x396ac000}, {0x396ae000}, + {0x396b0000}, {0x396b2000}, {0x396b4000}, {0x396b6000}, + {0x396b8000}, {0x396ba000}, {0x396bc000}, {0x396be000}, + {0x396c0000}, {0x396c2000}, {0x396c4000}, {0x396c6000}, + {0x396c8000}, {0x396ca000}, {0x396cc000}, {0x396ce000}, + {0x396d0000}, {0x396d2000}, {0x396d4000}, {0x396d6000}, + {0x396d8000}, {0x396da000}, {0x396dc000}, {0x396de000}, + {0x396e0000}, {0x396e2000}, {0x396e4000}, {0x396e6000}, + {0x396e8000}, {0x396ea000}, {0x396ec000}, {0x396ee000}, + {0x396f0000}, {0x396f2000}, {0x396f4000}, {0x396f6000}, + {0x396f8000}, {0x396fa000}, {0x396fc000}, {0x396fe000}, + {0x39700000}, {0x39702000}, {0x39704000}, {0x39706000}, + {0x39708000}, {0x3970a000}, {0x3970c000}, {0x3970e000}, + {0x39710000}, {0x39712000}, {0x39714000}, {0x39716000}, + {0x39718000}, {0x3971a000}, {0x3971c000}, {0x3971e000}, + {0x39720000}, {0x39722000}, {0x39724000}, {0x39726000}, + {0x39728000}, {0x3972a000}, {0x3972c000}, {0x3972e000}, + {0x39730000}, {0x39732000}, {0x39734000}, {0x39736000}, + {0x39738000}, {0x3973a000}, {0x3973c000}, {0x3973e000}, + {0x39740000}, {0x39742000}, {0x39744000}, {0x39746000}, + {0x39748000}, {0x3974a000}, {0x3974c000}, {0x3974e000}, + {0x39750000}, {0x39752000}, {0x39754000}, {0x39756000}, + {0x39758000}, {0x3975a000}, {0x3975c000}, {0x3975e000}, + {0x39760000}, {0x39762000}, {0x39764000}, {0x39766000}, + {0x39768000}, {0x3976a000}, {0x3976c000}, {0x3976e000}, + {0x39770000}, {0x39772000}, {0x39774000}, {0x39776000}, + {0x39778000}, {0x3977a000}, {0x3977c000}, {0x3977e000}, + {0x39780000}, {0x39782000}, {0x39784000}, {0x39786000}, + {0x39788000}, {0x3978a000}, {0x3978c000}, {0x3978e000}, + {0x39790000}, {0x39792000}, {0x39794000}, {0x39796000}, + {0x39798000}, {0x3979a000}, {0x3979c000}, {0x3979e000}, + {0x397a0000}, {0x397a2000}, {0x397a4000}, {0x397a6000}, + {0x397a8000}, {0x397aa000}, {0x397ac000}, {0x397ae000}, + {0x397b0000}, {0x397b2000}, {0x397b4000}, {0x397b6000}, + {0x397b8000}, {0x397ba000}, {0x397bc000}, {0x397be000}, + {0x397c0000}, {0x397c2000}, {0x397c4000}, {0x397c6000}, + {0x397c8000}, {0x397ca000}, {0x397cc000}, {0x397ce000}, + {0x397d0000}, {0x397d2000}, {0x397d4000}, {0x397d6000}, + {0x397d8000}, {0x397da000}, {0x397dc000}, {0x397de000}, + {0x397e0000}, {0x397e2000}, {0x397e4000}, {0x397e6000}, + {0x397e8000}, {0x397ea000}, {0x397ec000}, {0x397ee000}, + {0x397f0000}, {0x397f2000}, {0x397f4000}, {0x397f6000}, + {0x397f8000}, {0x397fa000}, {0x397fc000}, {0x397fe000}, + {0x39800000}, {0x39802000}, {0x39804000}, {0x39806000}, + {0x39808000}, {0x3980a000}, {0x3980c000}, {0x3980e000}, + {0x39810000}, {0x39812000}, {0x39814000}, {0x39816000}, + {0x39818000}, {0x3981a000}, {0x3981c000}, {0x3981e000}, + {0x39820000}, {0x39822000}, {0x39824000}, {0x39826000}, + {0x39828000}, {0x3982a000}, {0x3982c000}, {0x3982e000}, + {0x39830000}, {0x39832000}, {0x39834000}, {0x39836000}, + {0x39838000}, {0x3983a000}, {0x3983c000}, {0x3983e000}, + {0x39840000}, {0x39842000}, {0x39844000}, {0x39846000}, + {0x39848000}, {0x3984a000}, {0x3984c000}, {0x3984e000}, + {0x39850000}, {0x39852000}, {0x39854000}, {0x39856000}, + {0x39858000}, {0x3985a000}, {0x3985c000}, {0x3985e000}, + {0x39860000}, {0x39862000}, {0x39864000}, {0x39866000}, + {0x39868000}, {0x3986a000}, {0x3986c000}, {0x3986e000}, + {0x39870000}, {0x39872000}, {0x39874000}, {0x39876000}, + {0x39878000}, {0x3987a000}, {0x3987c000}, {0x3987e000}, + {0x39880000}, {0x39882000}, {0x39884000}, {0x39886000}, + {0x39888000}, {0x3988a000}, {0x3988c000}, {0x3988e000}, + {0x39890000}, {0x39892000}, {0x39894000}, {0x39896000}, + {0x39898000}, {0x3989a000}, {0x3989c000}, {0x3989e000}, + {0x398a0000}, {0x398a2000}, {0x398a4000}, {0x398a6000}, + {0x398a8000}, {0x398aa000}, {0x398ac000}, {0x398ae000}, + {0x398b0000}, {0x398b2000}, {0x398b4000}, {0x398b6000}, + {0x398b8000}, {0x398ba000}, {0x398bc000}, {0x398be000}, + {0x398c0000}, {0x398c2000}, {0x398c4000}, {0x398c6000}, + {0x398c8000}, {0x398ca000}, {0x398cc000}, {0x398ce000}, + {0x398d0000}, {0x398d2000}, {0x398d4000}, {0x398d6000}, + {0x398d8000}, {0x398da000}, {0x398dc000}, {0x398de000}, + {0x398e0000}, {0x398e2000}, {0x398e4000}, {0x398e6000}, + {0x398e8000}, {0x398ea000}, {0x398ec000}, {0x398ee000}, + {0x398f0000}, {0x398f2000}, {0x398f4000}, {0x398f6000}, + {0x398f8000}, {0x398fa000}, {0x398fc000}, {0x398fe000}, + {0x39900000}, {0x39902000}, {0x39904000}, {0x39906000}, + {0x39908000}, {0x3990a000}, {0x3990c000}, {0x3990e000}, + {0x39910000}, {0x39912000}, {0x39914000}, {0x39916000}, + {0x39918000}, {0x3991a000}, {0x3991c000}, {0x3991e000}, + {0x39920000}, {0x39922000}, {0x39924000}, {0x39926000}, + {0x39928000}, {0x3992a000}, {0x3992c000}, {0x3992e000}, + {0x39930000}, {0x39932000}, {0x39934000}, {0x39936000}, + {0x39938000}, {0x3993a000}, {0x3993c000}, {0x3993e000}, + {0x39940000}, {0x39942000}, {0x39944000}, {0x39946000}, + {0x39948000}, {0x3994a000}, {0x3994c000}, {0x3994e000}, + {0x39950000}, {0x39952000}, {0x39954000}, {0x39956000}, + {0x39958000}, {0x3995a000}, {0x3995c000}, {0x3995e000}, + {0x39960000}, {0x39962000}, {0x39964000}, {0x39966000}, + {0x39968000}, {0x3996a000}, {0x3996c000}, {0x3996e000}, + {0x39970000}, {0x39972000}, {0x39974000}, {0x39976000}, + {0x39978000}, {0x3997a000}, {0x3997c000}, {0x3997e000}, + {0x39980000}, {0x39982000}, {0x39984000}, {0x39986000}, + {0x39988000}, {0x3998a000}, {0x3998c000}, {0x3998e000}, + {0x39990000}, {0x39992000}, {0x39994000}, {0x39996000}, + {0x39998000}, {0x3999a000}, {0x3999c000}, {0x3999e000}, + {0x399a0000}, {0x399a2000}, {0x399a4000}, {0x399a6000}, + {0x399a8000}, {0x399aa000}, {0x399ac000}, {0x399ae000}, + {0x399b0000}, {0x399b2000}, {0x399b4000}, {0x399b6000}, + {0x399b8000}, {0x399ba000}, {0x399bc000}, {0x399be000}, + {0x399c0000}, {0x399c2000}, {0x399c4000}, {0x399c6000}, + {0x399c8000}, {0x399ca000}, {0x399cc000}, {0x399ce000}, + {0x399d0000}, {0x399d2000}, {0x399d4000}, {0x399d6000}, + {0x399d8000}, {0x399da000}, {0x399dc000}, {0x399de000}, + {0x399e0000}, {0x399e2000}, {0x399e4000}, {0x399e6000}, + {0x399e8000}, {0x399ea000}, {0x399ec000}, {0x399ee000}, + {0x399f0000}, {0x399f2000}, {0x399f4000}, {0x399f6000}, + {0x399f8000}, {0x399fa000}, {0x399fc000}, {0x399fe000}, + {0x39a00000}, {0x39a02000}, {0x39a04000}, {0x39a06000}, + {0x39a08000}, {0x39a0a000}, {0x39a0c000}, {0x39a0e000}, + {0x39a10000}, {0x39a12000}, {0x39a14000}, {0x39a16000}, + {0x39a18000}, {0x39a1a000}, {0x39a1c000}, {0x39a1e000}, + {0x39a20000}, {0x39a22000}, {0x39a24000}, {0x39a26000}, + {0x39a28000}, {0x39a2a000}, {0x39a2c000}, {0x39a2e000}, + {0x39a30000}, {0x39a32000}, {0x39a34000}, {0x39a36000}, + {0x39a38000}, {0x39a3a000}, {0x39a3c000}, {0x39a3e000}, + {0x39a40000}, {0x39a42000}, {0x39a44000}, {0x39a46000}, + {0x39a48000}, {0x39a4a000}, {0x39a4c000}, {0x39a4e000}, + {0x39a50000}, {0x39a52000}, {0x39a54000}, {0x39a56000}, + {0x39a58000}, {0x39a5a000}, {0x39a5c000}, {0x39a5e000}, + {0x39a60000}, {0x39a62000}, {0x39a64000}, {0x39a66000}, + {0x39a68000}, {0x39a6a000}, {0x39a6c000}, {0x39a6e000}, + {0x39a70000}, {0x39a72000}, {0x39a74000}, {0x39a76000}, + {0x39a78000}, {0x39a7a000}, {0x39a7c000}, {0x39a7e000}, + {0x39a80000}, {0x39a82000}, {0x39a84000}, {0x39a86000}, + {0x39a88000}, {0x39a8a000}, {0x39a8c000}, {0x39a8e000}, + {0x39a90000}, {0x39a92000}, {0x39a94000}, {0x39a96000}, + {0x39a98000}, {0x39a9a000}, {0x39a9c000}, {0x39a9e000}, + {0x39aa0000}, {0x39aa2000}, {0x39aa4000}, {0x39aa6000}, + {0x39aa8000}, {0x39aaa000}, {0x39aac000}, {0x39aae000}, + {0x39ab0000}, {0x39ab2000}, {0x39ab4000}, {0x39ab6000}, + {0x39ab8000}, {0x39aba000}, {0x39abc000}, {0x39abe000}, + {0x39ac0000}, {0x39ac2000}, {0x39ac4000}, {0x39ac6000}, + {0x39ac8000}, {0x39aca000}, {0x39acc000}, {0x39ace000}, + {0x39ad0000}, {0x39ad2000}, {0x39ad4000}, {0x39ad6000}, + {0x39ad8000}, {0x39ada000}, {0x39adc000}, {0x39ade000}, + {0x39ae0000}, {0x39ae2000}, {0x39ae4000}, {0x39ae6000}, + {0x39ae8000}, {0x39aea000}, {0x39aec000}, {0x39aee000}, + {0x39af0000}, {0x39af2000}, {0x39af4000}, {0x39af6000}, + {0x39af8000}, {0x39afa000}, {0x39afc000}, {0x39afe000}, + {0x39b00000}, {0x39b02000}, {0x39b04000}, {0x39b06000}, + {0x39b08000}, {0x39b0a000}, {0x39b0c000}, {0x39b0e000}, + {0x39b10000}, {0x39b12000}, {0x39b14000}, {0x39b16000}, + {0x39b18000}, {0x39b1a000}, {0x39b1c000}, {0x39b1e000}, + {0x39b20000}, {0x39b22000}, {0x39b24000}, {0x39b26000}, + {0x39b28000}, {0x39b2a000}, {0x39b2c000}, {0x39b2e000}, + {0x39b30000}, {0x39b32000}, {0x39b34000}, {0x39b36000}, + {0x39b38000}, {0x39b3a000}, {0x39b3c000}, {0x39b3e000}, + {0x39b40000}, {0x39b42000}, {0x39b44000}, {0x39b46000}, + {0x39b48000}, {0x39b4a000}, {0x39b4c000}, {0x39b4e000}, + {0x39b50000}, {0x39b52000}, {0x39b54000}, {0x39b56000}, + {0x39b58000}, {0x39b5a000}, {0x39b5c000}, {0x39b5e000}, + {0x39b60000}, {0x39b62000}, {0x39b64000}, {0x39b66000}, + {0x39b68000}, {0x39b6a000}, {0x39b6c000}, {0x39b6e000}, + {0x39b70000}, {0x39b72000}, {0x39b74000}, {0x39b76000}, + {0x39b78000}, {0x39b7a000}, {0x39b7c000}, {0x39b7e000}, + {0x39b80000}, {0x39b82000}, {0x39b84000}, {0x39b86000}, + {0x39b88000}, {0x39b8a000}, {0x39b8c000}, {0x39b8e000}, + {0x39b90000}, {0x39b92000}, {0x39b94000}, {0x39b96000}, + {0x39b98000}, {0x39b9a000}, {0x39b9c000}, {0x39b9e000}, + {0x39ba0000}, {0x39ba2000}, {0x39ba4000}, {0x39ba6000}, + {0x39ba8000}, {0x39baa000}, {0x39bac000}, {0x39bae000}, + {0x39bb0000}, {0x39bb2000}, {0x39bb4000}, {0x39bb6000}, + {0x39bb8000}, {0x39bba000}, {0x39bbc000}, {0x39bbe000}, + {0x39bc0000}, {0x39bc2000}, {0x39bc4000}, {0x39bc6000}, + {0x39bc8000}, {0x39bca000}, {0x39bcc000}, {0x39bce000}, + {0x39bd0000}, {0x39bd2000}, {0x39bd4000}, {0x39bd6000}, + {0x39bd8000}, {0x39bda000}, {0x39bdc000}, {0x39bde000}, + {0x39be0000}, {0x39be2000}, {0x39be4000}, {0x39be6000}, + {0x39be8000}, {0x39bea000}, {0x39bec000}, {0x39bee000}, + {0x39bf0000}, {0x39bf2000}, {0x39bf4000}, {0x39bf6000}, + {0x39bf8000}, {0x39bfa000}, {0x39bfc000}, {0x39bfe000}, + {0x39c00000}, {0x39c02000}, {0x39c04000}, {0x39c06000}, + {0x39c08000}, {0x39c0a000}, {0x39c0c000}, {0x39c0e000}, + {0x39c10000}, {0x39c12000}, {0x39c14000}, {0x39c16000}, + {0x39c18000}, {0x39c1a000}, {0x39c1c000}, {0x39c1e000}, + {0x39c20000}, {0x39c22000}, {0x39c24000}, {0x39c26000}, + {0x39c28000}, {0x39c2a000}, {0x39c2c000}, {0x39c2e000}, + {0x39c30000}, {0x39c32000}, {0x39c34000}, {0x39c36000}, + {0x39c38000}, {0x39c3a000}, {0x39c3c000}, {0x39c3e000}, + {0x39c40000}, {0x39c42000}, {0x39c44000}, {0x39c46000}, + {0x39c48000}, {0x39c4a000}, {0x39c4c000}, {0x39c4e000}, + {0x39c50000}, {0x39c52000}, {0x39c54000}, {0x39c56000}, + {0x39c58000}, {0x39c5a000}, {0x39c5c000}, {0x39c5e000}, + {0x39c60000}, {0x39c62000}, {0x39c64000}, {0x39c66000}, + {0x39c68000}, {0x39c6a000}, {0x39c6c000}, {0x39c6e000}, + {0x39c70000}, {0x39c72000}, {0x39c74000}, {0x39c76000}, + {0x39c78000}, {0x39c7a000}, {0x39c7c000}, {0x39c7e000}, + {0x39c80000}, {0x39c82000}, {0x39c84000}, {0x39c86000}, + {0x39c88000}, {0x39c8a000}, {0x39c8c000}, {0x39c8e000}, + {0x39c90000}, {0x39c92000}, {0x39c94000}, {0x39c96000}, + {0x39c98000}, {0x39c9a000}, {0x39c9c000}, {0x39c9e000}, + {0x39ca0000}, {0x39ca2000}, {0x39ca4000}, {0x39ca6000}, + {0x39ca8000}, {0x39caa000}, {0x39cac000}, {0x39cae000}, + {0x39cb0000}, {0x39cb2000}, {0x39cb4000}, {0x39cb6000}, + {0x39cb8000}, {0x39cba000}, {0x39cbc000}, {0x39cbe000}, + {0x39cc0000}, {0x39cc2000}, {0x39cc4000}, {0x39cc6000}, + {0x39cc8000}, {0x39cca000}, {0x39ccc000}, {0x39cce000}, + {0x39cd0000}, {0x39cd2000}, {0x39cd4000}, {0x39cd6000}, + {0x39cd8000}, {0x39cda000}, {0x39cdc000}, {0x39cde000}, + {0x39ce0000}, {0x39ce2000}, {0x39ce4000}, {0x39ce6000}, + {0x39ce8000}, {0x39cea000}, {0x39cec000}, {0x39cee000}, + {0x39cf0000}, {0x39cf2000}, {0x39cf4000}, {0x39cf6000}, + {0x39cf8000}, {0x39cfa000}, {0x39cfc000}, {0x39cfe000}, + {0x39d00000}, {0x39d02000}, {0x39d04000}, {0x39d06000}, + {0x39d08000}, {0x39d0a000}, {0x39d0c000}, {0x39d0e000}, + {0x39d10000}, {0x39d12000}, {0x39d14000}, {0x39d16000}, + {0x39d18000}, {0x39d1a000}, {0x39d1c000}, {0x39d1e000}, + {0x39d20000}, {0x39d22000}, {0x39d24000}, {0x39d26000}, + {0x39d28000}, {0x39d2a000}, {0x39d2c000}, {0x39d2e000}, + {0x39d30000}, {0x39d32000}, {0x39d34000}, {0x39d36000}, + {0x39d38000}, {0x39d3a000}, {0x39d3c000}, {0x39d3e000}, + {0x39d40000}, {0x39d42000}, {0x39d44000}, {0x39d46000}, + {0x39d48000}, {0x39d4a000}, {0x39d4c000}, {0x39d4e000}, + {0x39d50000}, {0x39d52000}, {0x39d54000}, {0x39d56000}, + {0x39d58000}, {0x39d5a000}, {0x39d5c000}, {0x39d5e000}, + {0x39d60000}, {0x39d62000}, {0x39d64000}, {0x39d66000}, + {0x39d68000}, {0x39d6a000}, {0x39d6c000}, {0x39d6e000}, + {0x39d70000}, {0x39d72000}, {0x39d74000}, {0x39d76000}, + {0x39d78000}, {0x39d7a000}, {0x39d7c000}, {0x39d7e000}, + {0x39d80000}, {0x39d82000}, {0x39d84000}, {0x39d86000}, + {0x39d88000}, {0x39d8a000}, {0x39d8c000}, {0x39d8e000}, + {0x39d90000}, {0x39d92000}, {0x39d94000}, {0x39d96000}, + {0x39d98000}, {0x39d9a000}, {0x39d9c000}, {0x39d9e000}, + {0x39da0000}, {0x39da2000}, {0x39da4000}, {0x39da6000}, + {0x39da8000}, {0x39daa000}, {0x39dac000}, {0x39dae000}, + {0x39db0000}, {0x39db2000}, {0x39db4000}, {0x39db6000}, + {0x39db8000}, {0x39dba000}, {0x39dbc000}, {0x39dbe000}, + {0x39dc0000}, {0x39dc2000}, {0x39dc4000}, {0x39dc6000}, + {0x39dc8000}, {0x39dca000}, {0x39dcc000}, {0x39dce000}, + {0x39dd0000}, {0x39dd2000}, {0x39dd4000}, {0x39dd6000}, + {0x39dd8000}, {0x39dda000}, {0x39ddc000}, {0x39dde000}, + {0x39de0000}, {0x39de2000}, {0x39de4000}, {0x39de6000}, + {0x39de8000}, {0x39dea000}, {0x39dec000}, {0x39dee000}, + {0x39df0000}, {0x39df2000}, {0x39df4000}, {0x39df6000}, + {0x39df8000}, {0x39dfa000}, {0x39dfc000}, {0x39dfe000}, + {0x39e00000}, {0x39e02000}, {0x39e04000}, {0x39e06000}, + {0x39e08000}, {0x39e0a000}, {0x39e0c000}, {0x39e0e000}, + {0x39e10000}, {0x39e12000}, {0x39e14000}, {0x39e16000}, + {0x39e18000}, {0x39e1a000}, {0x39e1c000}, {0x39e1e000}, + {0x39e20000}, {0x39e22000}, {0x39e24000}, {0x39e26000}, + {0x39e28000}, {0x39e2a000}, {0x39e2c000}, {0x39e2e000}, + {0x39e30000}, {0x39e32000}, {0x39e34000}, {0x39e36000}, + {0x39e38000}, {0x39e3a000}, {0x39e3c000}, {0x39e3e000}, + {0x39e40000}, {0x39e42000}, {0x39e44000}, {0x39e46000}, + {0x39e48000}, {0x39e4a000}, {0x39e4c000}, {0x39e4e000}, + {0x39e50000}, {0x39e52000}, {0x39e54000}, {0x39e56000}, + {0x39e58000}, {0x39e5a000}, {0x39e5c000}, {0x39e5e000}, + {0x39e60000}, {0x39e62000}, {0x39e64000}, {0x39e66000}, + {0x39e68000}, {0x39e6a000}, {0x39e6c000}, {0x39e6e000}, + {0x39e70000}, {0x39e72000}, {0x39e74000}, {0x39e76000}, + {0x39e78000}, {0x39e7a000}, {0x39e7c000}, {0x39e7e000}, + {0x39e80000}, {0x39e82000}, {0x39e84000}, {0x39e86000}, + {0x39e88000}, {0x39e8a000}, {0x39e8c000}, {0x39e8e000}, + {0x39e90000}, {0x39e92000}, {0x39e94000}, {0x39e96000}, + {0x39e98000}, {0x39e9a000}, {0x39e9c000}, {0x39e9e000}, + {0x39ea0000}, {0x39ea2000}, {0x39ea4000}, {0x39ea6000}, + {0x39ea8000}, {0x39eaa000}, {0x39eac000}, {0x39eae000}, + {0x39eb0000}, {0x39eb2000}, {0x39eb4000}, {0x39eb6000}, + {0x39eb8000}, {0x39eba000}, {0x39ebc000}, {0x39ebe000}, + {0x39ec0000}, {0x39ec2000}, {0x39ec4000}, {0x39ec6000}, + {0x39ec8000}, {0x39eca000}, {0x39ecc000}, {0x39ece000}, + {0x39ed0000}, {0x39ed2000}, {0x39ed4000}, {0x39ed6000}, + {0x39ed8000}, {0x39eda000}, {0x39edc000}, {0x39ede000}, + {0x39ee0000}, {0x39ee2000}, {0x39ee4000}, {0x39ee6000}, + {0x39ee8000}, {0x39eea000}, {0x39eec000}, {0x39eee000}, + {0x39ef0000}, {0x39ef2000}, {0x39ef4000}, {0x39ef6000}, + {0x39ef8000}, {0x39efa000}, {0x39efc000}, {0x39efe000}, + {0x39f00000}, {0x39f02000}, {0x39f04000}, {0x39f06000}, + {0x39f08000}, {0x39f0a000}, {0x39f0c000}, {0x39f0e000}, + {0x39f10000}, {0x39f12000}, {0x39f14000}, {0x39f16000}, + {0x39f18000}, {0x39f1a000}, {0x39f1c000}, {0x39f1e000}, + {0x39f20000}, {0x39f22000}, {0x39f24000}, {0x39f26000}, + {0x39f28000}, {0x39f2a000}, {0x39f2c000}, {0x39f2e000}, + {0x39f30000}, {0x39f32000}, {0x39f34000}, {0x39f36000}, + {0x39f38000}, {0x39f3a000}, {0x39f3c000}, {0x39f3e000}, + {0x39f40000}, {0x39f42000}, {0x39f44000}, {0x39f46000}, + {0x39f48000}, {0x39f4a000}, {0x39f4c000}, {0x39f4e000}, + {0x39f50000}, {0x39f52000}, {0x39f54000}, {0x39f56000}, + {0x39f58000}, {0x39f5a000}, {0x39f5c000}, {0x39f5e000}, + {0x39f60000}, {0x39f62000}, {0x39f64000}, {0x39f66000}, + {0x39f68000}, {0x39f6a000}, {0x39f6c000}, {0x39f6e000}, + {0x39f70000}, {0x39f72000}, {0x39f74000}, {0x39f76000}, + {0x39f78000}, {0x39f7a000}, {0x39f7c000}, {0x39f7e000}, + {0x39f80000}, {0x39f82000}, {0x39f84000}, {0x39f86000}, + {0x39f88000}, {0x39f8a000}, {0x39f8c000}, {0x39f8e000}, + {0x39f90000}, {0x39f92000}, {0x39f94000}, {0x39f96000}, + {0x39f98000}, {0x39f9a000}, {0x39f9c000}, {0x39f9e000}, + {0x39fa0000}, {0x39fa2000}, {0x39fa4000}, {0x39fa6000}, + {0x39fa8000}, {0x39faa000}, {0x39fac000}, {0x39fae000}, + {0x39fb0000}, {0x39fb2000}, {0x39fb4000}, {0x39fb6000}, + {0x39fb8000}, {0x39fba000}, {0x39fbc000}, {0x39fbe000}, + {0x39fc0000}, {0x39fc2000}, {0x39fc4000}, {0x39fc6000}, + {0x39fc8000}, {0x39fca000}, {0x39fcc000}, {0x39fce000}, + {0x39fd0000}, {0x39fd2000}, {0x39fd4000}, {0x39fd6000}, + {0x39fd8000}, {0x39fda000}, {0x39fdc000}, {0x39fde000}, + {0x39fe0000}, {0x39fe2000}, {0x39fe4000}, {0x39fe6000}, + {0x39fe8000}, {0x39fea000}, {0x39fec000}, {0x39fee000}, + {0x39ff0000}, {0x39ff2000}, {0x39ff4000}, {0x39ff6000}, + {0x39ff8000}, {0x39ffa000}, {0x39ffc000}, {0x39ffe000}, + {0x3a000000}, {0x3a002000}, {0x3a004000}, {0x3a006000}, + {0x3a008000}, {0x3a00a000}, {0x3a00c000}, {0x3a00e000}, + {0x3a010000}, {0x3a012000}, {0x3a014000}, {0x3a016000}, + {0x3a018000}, {0x3a01a000}, {0x3a01c000}, {0x3a01e000}, + {0x3a020000}, {0x3a022000}, {0x3a024000}, {0x3a026000}, + {0x3a028000}, {0x3a02a000}, {0x3a02c000}, {0x3a02e000}, + {0x3a030000}, {0x3a032000}, {0x3a034000}, {0x3a036000}, + {0x3a038000}, {0x3a03a000}, {0x3a03c000}, {0x3a03e000}, + {0x3a040000}, {0x3a042000}, {0x3a044000}, {0x3a046000}, + {0x3a048000}, {0x3a04a000}, {0x3a04c000}, {0x3a04e000}, + {0x3a050000}, {0x3a052000}, {0x3a054000}, {0x3a056000}, + {0x3a058000}, {0x3a05a000}, {0x3a05c000}, {0x3a05e000}, + {0x3a060000}, {0x3a062000}, {0x3a064000}, {0x3a066000}, + {0x3a068000}, {0x3a06a000}, {0x3a06c000}, {0x3a06e000}, + {0x3a070000}, {0x3a072000}, {0x3a074000}, {0x3a076000}, + {0x3a078000}, {0x3a07a000}, {0x3a07c000}, {0x3a07e000}, + {0x3a080000}, {0x3a082000}, {0x3a084000}, {0x3a086000}, + {0x3a088000}, {0x3a08a000}, {0x3a08c000}, {0x3a08e000}, + {0x3a090000}, {0x3a092000}, {0x3a094000}, {0x3a096000}, + {0x3a098000}, {0x3a09a000}, {0x3a09c000}, {0x3a09e000}, + {0x3a0a0000}, {0x3a0a2000}, {0x3a0a4000}, {0x3a0a6000}, + {0x3a0a8000}, {0x3a0aa000}, {0x3a0ac000}, {0x3a0ae000}, + {0x3a0b0000}, {0x3a0b2000}, {0x3a0b4000}, {0x3a0b6000}, + {0x3a0b8000}, {0x3a0ba000}, {0x3a0bc000}, {0x3a0be000}, + {0x3a0c0000}, {0x3a0c2000}, {0x3a0c4000}, {0x3a0c6000}, + {0x3a0c8000}, {0x3a0ca000}, {0x3a0cc000}, {0x3a0ce000}, + {0x3a0d0000}, {0x3a0d2000}, {0x3a0d4000}, {0x3a0d6000}, + {0x3a0d8000}, {0x3a0da000}, {0x3a0dc000}, {0x3a0de000}, + {0x3a0e0000}, {0x3a0e2000}, {0x3a0e4000}, {0x3a0e6000}, + {0x3a0e8000}, {0x3a0ea000}, {0x3a0ec000}, {0x3a0ee000}, + {0x3a0f0000}, {0x3a0f2000}, {0x3a0f4000}, {0x3a0f6000}, + {0x3a0f8000}, {0x3a0fa000}, {0x3a0fc000}, {0x3a0fe000}, + {0x3a100000}, {0x3a102000}, {0x3a104000}, {0x3a106000}, + {0x3a108000}, {0x3a10a000}, {0x3a10c000}, {0x3a10e000}, + {0x3a110000}, {0x3a112000}, {0x3a114000}, {0x3a116000}, + {0x3a118000}, {0x3a11a000}, {0x3a11c000}, {0x3a11e000}, + {0x3a120000}, {0x3a122000}, {0x3a124000}, {0x3a126000}, + {0x3a128000}, {0x3a12a000}, {0x3a12c000}, {0x3a12e000}, + {0x3a130000}, {0x3a132000}, {0x3a134000}, {0x3a136000}, + {0x3a138000}, {0x3a13a000}, {0x3a13c000}, {0x3a13e000}, + {0x3a140000}, {0x3a142000}, {0x3a144000}, {0x3a146000}, + {0x3a148000}, {0x3a14a000}, {0x3a14c000}, {0x3a14e000}, + {0x3a150000}, {0x3a152000}, {0x3a154000}, {0x3a156000}, + {0x3a158000}, {0x3a15a000}, {0x3a15c000}, {0x3a15e000}, + {0x3a160000}, {0x3a162000}, {0x3a164000}, {0x3a166000}, + {0x3a168000}, {0x3a16a000}, {0x3a16c000}, {0x3a16e000}, + {0x3a170000}, {0x3a172000}, {0x3a174000}, {0x3a176000}, + {0x3a178000}, {0x3a17a000}, {0x3a17c000}, {0x3a17e000}, + {0x3a180000}, {0x3a182000}, {0x3a184000}, {0x3a186000}, + {0x3a188000}, {0x3a18a000}, {0x3a18c000}, {0x3a18e000}, + {0x3a190000}, {0x3a192000}, {0x3a194000}, {0x3a196000}, + {0x3a198000}, {0x3a19a000}, {0x3a19c000}, {0x3a19e000}, + {0x3a1a0000}, {0x3a1a2000}, {0x3a1a4000}, {0x3a1a6000}, + {0x3a1a8000}, {0x3a1aa000}, {0x3a1ac000}, {0x3a1ae000}, + {0x3a1b0000}, {0x3a1b2000}, {0x3a1b4000}, {0x3a1b6000}, + {0x3a1b8000}, {0x3a1ba000}, {0x3a1bc000}, {0x3a1be000}, + {0x3a1c0000}, {0x3a1c2000}, {0x3a1c4000}, {0x3a1c6000}, + {0x3a1c8000}, {0x3a1ca000}, {0x3a1cc000}, {0x3a1ce000}, + {0x3a1d0000}, {0x3a1d2000}, {0x3a1d4000}, {0x3a1d6000}, + {0x3a1d8000}, {0x3a1da000}, {0x3a1dc000}, {0x3a1de000}, + {0x3a1e0000}, {0x3a1e2000}, {0x3a1e4000}, {0x3a1e6000}, + {0x3a1e8000}, {0x3a1ea000}, {0x3a1ec000}, {0x3a1ee000}, + {0x3a1f0000}, {0x3a1f2000}, {0x3a1f4000}, {0x3a1f6000}, + {0x3a1f8000}, {0x3a1fa000}, {0x3a1fc000}, {0x3a1fe000}, + {0x3a200000}, {0x3a202000}, {0x3a204000}, {0x3a206000}, + {0x3a208000}, {0x3a20a000}, {0x3a20c000}, {0x3a20e000}, + {0x3a210000}, {0x3a212000}, {0x3a214000}, {0x3a216000}, + {0x3a218000}, {0x3a21a000}, {0x3a21c000}, {0x3a21e000}, + {0x3a220000}, {0x3a222000}, {0x3a224000}, {0x3a226000}, + {0x3a228000}, {0x3a22a000}, {0x3a22c000}, {0x3a22e000}, + {0x3a230000}, {0x3a232000}, {0x3a234000}, {0x3a236000}, + {0x3a238000}, {0x3a23a000}, {0x3a23c000}, {0x3a23e000}, + {0x3a240000}, {0x3a242000}, {0x3a244000}, {0x3a246000}, + {0x3a248000}, {0x3a24a000}, {0x3a24c000}, {0x3a24e000}, + {0x3a250000}, {0x3a252000}, {0x3a254000}, {0x3a256000}, + {0x3a258000}, {0x3a25a000}, {0x3a25c000}, {0x3a25e000}, + {0x3a260000}, {0x3a262000}, {0x3a264000}, {0x3a266000}, + {0x3a268000}, {0x3a26a000}, {0x3a26c000}, {0x3a26e000}, + {0x3a270000}, {0x3a272000}, {0x3a274000}, {0x3a276000}, + {0x3a278000}, {0x3a27a000}, {0x3a27c000}, {0x3a27e000}, + {0x3a280000}, {0x3a282000}, {0x3a284000}, {0x3a286000}, + {0x3a288000}, {0x3a28a000}, {0x3a28c000}, {0x3a28e000}, + {0x3a290000}, {0x3a292000}, {0x3a294000}, {0x3a296000}, + {0x3a298000}, {0x3a29a000}, {0x3a29c000}, {0x3a29e000}, + {0x3a2a0000}, {0x3a2a2000}, {0x3a2a4000}, {0x3a2a6000}, + {0x3a2a8000}, {0x3a2aa000}, {0x3a2ac000}, {0x3a2ae000}, + {0x3a2b0000}, {0x3a2b2000}, {0x3a2b4000}, {0x3a2b6000}, + {0x3a2b8000}, {0x3a2ba000}, {0x3a2bc000}, {0x3a2be000}, + {0x3a2c0000}, {0x3a2c2000}, {0x3a2c4000}, {0x3a2c6000}, + {0x3a2c8000}, {0x3a2ca000}, {0x3a2cc000}, {0x3a2ce000}, + {0x3a2d0000}, {0x3a2d2000}, {0x3a2d4000}, {0x3a2d6000}, + {0x3a2d8000}, {0x3a2da000}, {0x3a2dc000}, {0x3a2de000}, + {0x3a2e0000}, {0x3a2e2000}, {0x3a2e4000}, {0x3a2e6000}, + {0x3a2e8000}, {0x3a2ea000}, {0x3a2ec000}, {0x3a2ee000}, + {0x3a2f0000}, {0x3a2f2000}, {0x3a2f4000}, {0x3a2f6000}, + {0x3a2f8000}, {0x3a2fa000}, {0x3a2fc000}, {0x3a2fe000}, + {0x3a300000}, {0x3a302000}, {0x3a304000}, {0x3a306000}, + {0x3a308000}, {0x3a30a000}, {0x3a30c000}, {0x3a30e000}, + {0x3a310000}, {0x3a312000}, {0x3a314000}, {0x3a316000}, + {0x3a318000}, {0x3a31a000}, {0x3a31c000}, {0x3a31e000}, + {0x3a320000}, {0x3a322000}, {0x3a324000}, {0x3a326000}, + {0x3a328000}, {0x3a32a000}, {0x3a32c000}, {0x3a32e000}, + {0x3a330000}, {0x3a332000}, {0x3a334000}, {0x3a336000}, + {0x3a338000}, {0x3a33a000}, {0x3a33c000}, {0x3a33e000}, + {0x3a340000}, {0x3a342000}, {0x3a344000}, {0x3a346000}, + {0x3a348000}, {0x3a34a000}, {0x3a34c000}, {0x3a34e000}, + {0x3a350000}, {0x3a352000}, {0x3a354000}, {0x3a356000}, + {0x3a358000}, {0x3a35a000}, {0x3a35c000}, {0x3a35e000}, + {0x3a360000}, {0x3a362000}, {0x3a364000}, {0x3a366000}, + {0x3a368000}, {0x3a36a000}, {0x3a36c000}, {0x3a36e000}, + {0x3a370000}, {0x3a372000}, {0x3a374000}, {0x3a376000}, + {0x3a378000}, {0x3a37a000}, {0x3a37c000}, {0x3a37e000}, + {0x3a380000}, {0x3a382000}, {0x3a384000}, {0x3a386000}, + {0x3a388000}, {0x3a38a000}, {0x3a38c000}, {0x3a38e000}, + {0x3a390000}, {0x3a392000}, {0x3a394000}, {0x3a396000}, + {0x3a398000}, {0x3a39a000}, {0x3a39c000}, {0x3a39e000}, + {0x3a3a0000}, {0x3a3a2000}, {0x3a3a4000}, {0x3a3a6000}, + {0x3a3a8000}, {0x3a3aa000}, {0x3a3ac000}, {0x3a3ae000}, + {0x3a3b0000}, {0x3a3b2000}, {0x3a3b4000}, {0x3a3b6000}, + {0x3a3b8000}, {0x3a3ba000}, {0x3a3bc000}, {0x3a3be000}, + {0x3a3c0000}, {0x3a3c2000}, {0x3a3c4000}, {0x3a3c6000}, + {0x3a3c8000}, {0x3a3ca000}, {0x3a3cc000}, {0x3a3ce000}, + {0x3a3d0000}, {0x3a3d2000}, {0x3a3d4000}, {0x3a3d6000}, + {0x3a3d8000}, {0x3a3da000}, {0x3a3dc000}, {0x3a3de000}, + {0x3a3e0000}, {0x3a3e2000}, {0x3a3e4000}, {0x3a3e6000}, + {0x3a3e8000}, {0x3a3ea000}, {0x3a3ec000}, {0x3a3ee000}, + {0x3a3f0000}, {0x3a3f2000}, {0x3a3f4000}, {0x3a3f6000}, + {0x3a3f8000}, {0x3a3fa000}, {0x3a3fc000}, {0x3a3fe000}, + {0x3a400000}, {0x3a402000}, {0x3a404000}, {0x3a406000}, + {0x3a408000}, {0x3a40a000}, {0x3a40c000}, {0x3a40e000}, + {0x3a410000}, {0x3a412000}, {0x3a414000}, {0x3a416000}, + {0x3a418000}, {0x3a41a000}, {0x3a41c000}, {0x3a41e000}, + {0x3a420000}, {0x3a422000}, {0x3a424000}, {0x3a426000}, + {0x3a428000}, {0x3a42a000}, {0x3a42c000}, {0x3a42e000}, + {0x3a430000}, {0x3a432000}, {0x3a434000}, {0x3a436000}, + {0x3a438000}, {0x3a43a000}, {0x3a43c000}, {0x3a43e000}, + {0x3a440000}, {0x3a442000}, {0x3a444000}, {0x3a446000}, + {0x3a448000}, {0x3a44a000}, {0x3a44c000}, {0x3a44e000}, + {0x3a450000}, {0x3a452000}, {0x3a454000}, {0x3a456000}, + {0x3a458000}, {0x3a45a000}, {0x3a45c000}, {0x3a45e000}, + {0x3a460000}, {0x3a462000}, {0x3a464000}, {0x3a466000}, + {0x3a468000}, {0x3a46a000}, {0x3a46c000}, {0x3a46e000}, + {0x3a470000}, {0x3a472000}, {0x3a474000}, {0x3a476000}, + {0x3a478000}, {0x3a47a000}, {0x3a47c000}, {0x3a47e000}, + {0x3a480000}, {0x3a482000}, {0x3a484000}, {0x3a486000}, + {0x3a488000}, {0x3a48a000}, {0x3a48c000}, {0x3a48e000}, + {0x3a490000}, {0x3a492000}, {0x3a494000}, {0x3a496000}, + {0x3a498000}, {0x3a49a000}, {0x3a49c000}, {0x3a49e000}, + {0x3a4a0000}, {0x3a4a2000}, {0x3a4a4000}, {0x3a4a6000}, + {0x3a4a8000}, {0x3a4aa000}, {0x3a4ac000}, {0x3a4ae000}, + {0x3a4b0000}, {0x3a4b2000}, {0x3a4b4000}, {0x3a4b6000}, + {0x3a4b8000}, {0x3a4ba000}, {0x3a4bc000}, {0x3a4be000}, + {0x3a4c0000}, {0x3a4c2000}, {0x3a4c4000}, {0x3a4c6000}, + {0x3a4c8000}, {0x3a4ca000}, {0x3a4cc000}, {0x3a4ce000}, + {0x3a4d0000}, {0x3a4d2000}, {0x3a4d4000}, {0x3a4d6000}, + {0x3a4d8000}, {0x3a4da000}, {0x3a4dc000}, {0x3a4de000}, + {0x3a4e0000}, {0x3a4e2000}, {0x3a4e4000}, {0x3a4e6000}, + {0x3a4e8000}, {0x3a4ea000}, {0x3a4ec000}, {0x3a4ee000}, + {0x3a4f0000}, {0x3a4f2000}, {0x3a4f4000}, {0x3a4f6000}, + {0x3a4f8000}, {0x3a4fa000}, {0x3a4fc000}, {0x3a4fe000}, + {0x3a500000}, {0x3a502000}, {0x3a504000}, {0x3a506000}, + {0x3a508000}, {0x3a50a000}, {0x3a50c000}, {0x3a50e000}, + {0x3a510000}, {0x3a512000}, {0x3a514000}, {0x3a516000}, + {0x3a518000}, {0x3a51a000}, {0x3a51c000}, {0x3a51e000}, + {0x3a520000}, {0x3a522000}, {0x3a524000}, {0x3a526000}, + {0x3a528000}, {0x3a52a000}, {0x3a52c000}, {0x3a52e000}, + {0x3a530000}, {0x3a532000}, {0x3a534000}, {0x3a536000}, + {0x3a538000}, {0x3a53a000}, {0x3a53c000}, {0x3a53e000}, + {0x3a540000}, {0x3a542000}, {0x3a544000}, {0x3a546000}, + {0x3a548000}, {0x3a54a000}, {0x3a54c000}, {0x3a54e000}, + {0x3a550000}, {0x3a552000}, {0x3a554000}, {0x3a556000}, + {0x3a558000}, {0x3a55a000}, {0x3a55c000}, {0x3a55e000}, + {0x3a560000}, {0x3a562000}, {0x3a564000}, {0x3a566000}, + {0x3a568000}, {0x3a56a000}, {0x3a56c000}, {0x3a56e000}, + {0x3a570000}, {0x3a572000}, {0x3a574000}, {0x3a576000}, + {0x3a578000}, {0x3a57a000}, {0x3a57c000}, {0x3a57e000}, + {0x3a580000}, {0x3a582000}, {0x3a584000}, {0x3a586000}, + {0x3a588000}, {0x3a58a000}, {0x3a58c000}, {0x3a58e000}, + {0x3a590000}, {0x3a592000}, {0x3a594000}, {0x3a596000}, + {0x3a598000}, {0x3a59a000}, {0x3a59c000}, {0x3a59e000}, + {0x3a5a0000}, {0x3a5a2000}, {0x3a5a4000}, {0x3a5a6000}, + {0x3a5a8000}, {0x3a5aa000}, {0x3a5ac000}, {0x3a5ae000}, + {0x3a5b0000}, {0x3a5b2000}, {0x3a5b4000}, {0x3a5b6000}, + {0x3a5b8000}, {0x3a5ba000}, {0x3a5bc000}, {0x3a5be000}, + {0x3a5c0000}, {0x3a5c2000}, {0x3a5c4000}, {0x3a5c6000}, + {0x3a5c8000}, {0x3a5ca000}, {0x3a5cc000}, {0x3a5ce000}, + {0x3a5d0000}, {0x3a5d2000}, {0x3a5d4000}, {0x3a5d6000}, + {0x3a5d8000}, {0x3a5da000}, {0x3a5dc000}, {0x3a5de000}, + {0x3a5e0000}, {0x3a5e2000}, {0x3a5e4000}, {0x3a5e6000}, + {0x3a5e8000}, {0x3a5ea000}, {0x3a5ec000}, {0x3a5ee000}, + {0x3a5f0000}, {0x3a5f2000}, {0x3a5f4000}, {0x3a5f6000}, + {0x3a5f8000}, {0x3a5fa000}, {0x3a5fc000}, {0x3a5fe000}, + {0x3a600000}, {0x3a602000}, {0x3a604000}, {0x3a606000}, + {0x3a608000}, {0x3a60a000}, {0x3a60c000}, {0x3a60e000}, + {0x3a610000}, {0x3a612000}, {0x3a614000}, {0x3a616000}, + {0x3a618000}, {0x3a61a000}, {0x3a61c000}, {0x3a61e000}, + {0x3a620000}, {0x3a622000}, {0x3a624000}, {0x3a626000}, + {0x3a628000}, {0x3a62a000}, {0x3a62c000}, {0x3a62e000}, + {0x3a630000}, {0x3a632000}, {0x3a634000}, {0x3a636000}, + {0x3a638000}, {0x3a63a000}, {0x3a63c000}, {0x3a63e000}, + {0x3a640000}, {0x3a642000}, {0x3a644000}, {0x3a646000}, + {0x3a648000}, {0x3a64a000}, {0x3a64c000}, {0x3a64e000}, + {0x3a650000}, {0x3a652000}, {0x3a654000}, {0x3a656000}, + {0x3a658000}, {0x3a65a000}, {0x3a65c000}, {0x3a65e000}, + {0x3a660000}, {0x3a662000}, {0x3a664000}, {0x3a666000}, + {0x3a668000}, {0x3a66a000}, {0x3a66c000}, {0x3a66e000}, + {0x3a670000}, {0x3a672000}, {0x3a674000}, {0x3a676000}, + {0x3a678000}, {0x3a67a000}, {0x3a67c000}, {0x3a67e000}, + {0x3a680000}, {0x3a682000}, {0x3a684000}, {0x3a686000}, + {0x3a688000}, {0x3a68a000}, {0x3a68c000}, {0x3a68e000}, + {0x3a690000}, {0x3a692000}, {0x3a694000}, {0x3a696000}, + {0x3a698000}, {0x3a69a000}, {0x3a69c000}, {0x3a69e000}, + {0x3a6a0000}, {0x3a6a2000}, {0x3a6a4000}, {0x3a6a6000}, + {0x3a6a8000}, {0x3a6aa000}, {0x3a6ac000}, {0x3a6ae000}, + {0x3a6b0000}, {0x3a6b2000}, {0x3a6b4000}, {0x3a6b6000}, + {0x3a6b8000}, {0x3a6ba000}, {0x3a6bc000}, {0x3a6be000}, + {0x3a6c0000}, {0x3a6c2000}, {0x3a6c4000}, {0x3a6c6000}, + {0x3a6c8000}, {0x3a6ca000}, {0x3a6cc000}, {0x3a6ce000}, + {0x3a6d0000}, {0x3a6d2000}, {0x3a6d4000}, {0x3a6d6000}, + {0x3a6d8000}, {0x3a6da000}, {0x3a6dc000}, {0x3a6de000}, + {0x3a6e0000}, {0x3a6e2000}, {0x3a6e4000}, {0x3a6e6000}, + {0x3a6e8000}, {0x3a6ea000}, {0x3a6ec000}, {0x3a6ee000}, + {0x3a6f0000}, {0x3a6f2000}, {0x3a6f4000}, {0x3a6f6000}, + {0x3a6f8000}, {0x3a6fa000}, {0x3a6fc000}, {0x3a6fe000}, + {0x3a700000}, {0x3a702000}, {0x3a704000}, {0x3a706000}, + {0x3a708000}, {0x3a70a000}, {0x3a70c000}, {0x3a70e000}, + {0x3a710000}, {0x3a712000}, {0x3a714000}, {0x3a716000}, + {0x3a718000}, {0x3a71a000}, {0x3a71c000}, {0x3a71e000}, + {0x3a720000}, {0x3a722000}, {0x3a724000}, {0x3a726000}, + {0x3a728000}, {0x3a72a000}, {0x3a72c000}, {0x3a72e000}, + {0x3a730000}, {0x3a732000}, {0x3a734000}, {0x3a736000}, + {0x3a738000}, {0x3a73a000}, {0x3a73c000}, {0x3a73e000}, + {0x3a740000}, {0x3a742000}, {0x3a744000}, {0x3a746000}, + {0x3a748000}, {0x3a74a000}, {0x3a74c000}, {0x3a74e000}, + {0x3a750000}, {0x3a752000}, {0x3a754000}, {0x3a756000}, + {0x3a758000}, {0x3a75a000}, {0x3a75c000}, {0x3a75e000}, + {0x3a760000}, {0x3a762000}, {0x3a764000}, {0x3a766000}, + {0x3a768000}, {0x3a76a000}, {0x3a76c000}, {0x3a76e000}, + {0x3a770000}, {0x3a772000}, {0x3a774000}, {0x3a776000}, + {0x3a778000}, {0x3a77a000}, {0x3a77c000}, {0x3a77e000}, + {0x3a780000}, {0x3a782000}, {0x3a784000}, {0x3a786000}, + {0x3a788000}, {0x3a78a000}, {0x3a78c000}, {0x3a78e000}, + {0x3a790000}, {0x3a792000}, {0x3a794000}, {0x3a796000}, + {0x3a798000}, {0x3a79a000}, {0x3a79c000}, {0x3a79e000}, + {0x3a7a0000}, {0x3a7a2000}, {0x3a7a4000}, {0x3a7a6000}, + {0x3a7a8000}, {0x3a7aa000}, {0x3a7ac000}, {0x3a7ae000}, + {0x3a7b0000}, {0x3a7b2000}, {0x3a7b4000}, {0x3a7b6000}, + {0x3a7b8000}, {0x3a7ba000}, {0x3a7bc000}, {0x3a7be000}, + {0x3a7c0000}, {0x3a7c2000}, {0x3a7c4000}, {0x3a7c6000}, + {0x3a7c8000}, {0x3a7ca000}, {0x3a7cc000}, {0x3a7ce000}, + {0x3a7d0000}, {0x3a7d2000}, {0x3a7d4000}, {0x3a7d6000}, + {0x3a7d8000}, {0x3a7da000}, {0x3a7dc000}, {0x3a7de000}, + {0x3a7e0000}, {0x3a7e2000}, {0x3a7e4000}, {0x3a7e6000}, + {0x3a7e8000}, {0x3a7ea000}, {0x3a7ec000}, {0x3a7ee000}, + {0x3a7f0000}, {0x3a7f2000}, {0x3a7f4000}, {0x3a7f6000}, + {0x3a7f8000}, {0x3a7fa000}, {0x3a7fc000}, {0x3a7fe000}, + {0x3a800000}, {0x3a802000}, {0x3a804000}, {0x3a806000}, + {0x3a808000}, {0x3a80a000}, {0x3a80c000}, {0x3a80e000}, + {0x3a810000}, {0x3a812000}, {0x3a814000}, {0x3a816000}, + {0x3a818000}, {0x3a81a000}, {0x3a81c000}, {0x3a81e000}, + {0x3a820000}, {0x3a822000}, {0x3a824000}, {0x3a826000}, + {0x3a828000}, {0x3a82a000}, {0x3a82c000}, {0x3a82e000}, + {0x3a830000}, {0x3a832000}, {0x3a834000}, {0x3a836000}, + {0x3a838000}, {0x3a83a000}, {0x3a83c000}, {0x3a83e000}, + {0x3a840000}, {0x3a842000}, {0x3a844000}, {0x3a846000}, + {0x3a848000}, {0x3a84a000}, {0x3a84c000}, {0x3a84e000}, + {0x3a850000}, {0x3a852000}, {0x3a854000}, {0x3a856000}, + {0x3a858000}, {0x3a85a000}, {0x3a85c000}, {0x3a85e000}, + {0x3a860000}, {0x3a862000}, {0x3a864000}, {0x3a866000}, + {0x3a868000}, {0x3a86a000}, {0x3a86c000}, {0x3a86e000}, + {0x3a870000}, {0x3a872000}, {0x3a874000}, {0x3a876000}, + {0x3a878000}, {0x3a87a000}, {0x3a87c000}, {0x3a87e000}, + {0x3a880000}, {0x3a882000}, {0x3a884000}, {0x3a886000}, + {0x3a888000}, {0x3a88a000}, {0x3a88c000}, {0x3a88e000}, + {0x3a890000}, {0x3a892000}, {0x3a894000}, {0x3a896000}, + {0x3a898000}, {0x3a89a000}, {0x3a89c000}, {0x3a89e000}, + {0x3a8a0000}, {0x3a8a2000}, {0x3a8a4000}, {0x3a8a6000}, + {0x3a8a8000}, {0x3a8aa000}, {0x3a8ac000}, {0x3a8ae000}, + {0x3a8b0000}, {0x3a8b2000}, {0x3a8b4000}, {0x3a8b6000}, + {0x3a8b8000}, {0x3a8ba000}, {0x3a8bc000}, {0x3a8be000}, + {0x3a8c0000}, {0x3a8c2000}, {0x3a8c4000}, {0x3a8c6000}, + {0x3a8c8000}, {0x3a8ca000}, {0x3a8cc000}, {0x3a8ce000}, + {0x3a8d0000}, {0x3a8d2000}, {0x3a8d4000}, {0x3a8d6000}, + {0x3a8d8000}, {0x3a8da000}, {0x3a8dc000}, {0x3a8de000}, + {0x3a8e0000}, {0x3a8e2000}, {0x3a8e4000}, {0x3a8e6000}, + {0x3a8e8000}, {0x3a8ea000}, {0x3a8ec000}, {0x3a8ee000}, + {0x3a8f0000}, {0x3a8f2000}, {0x3a8f4000}, {0x3a8f6000}, + {0x3a8f8000}, {0x3a8fa000}, {0x3a8fc000}, {0x3a8fe000}, + {0x3a900000}, {0x3a902000}, {0x3a904000}, {0x3a906000}, + {0x3a908000}, {0x3a90a000}, {0x3a90c000}, {0x3a90e000}, + {0x3a910000}, {0x3a912000}, {0x3a914000}, {0x3a916000}, + {0x3a918000}, {0x3a91a000}, {0x3a91c000}, {0x3a91e000}, + {0x3a920000}, {0x3a922000}, {0x3a924000}, {0x3a926000}, + {0x3a928000}, {0x3a92a000}, {0x3a92c000}, {0x3a92e000}, + {0x3a930000}, {0x3a932000}, {0x3a934000}, {0x3a936000}, + {0x3a938000}, {0x3a93a000}, {0x3a93c000}, {0x3a93e000}, + {0x3a940000}, {0x3a942000}, {0x3a944000}, {0x3a946000}, + {0x3a948000}, {0x3a94a000}, {0x3a94c000}, {0x3a94e000}, + {0x3a950000}, {0x3a952000}, {0x3a954000}, {0x3a956000}, + {0x3a958000}, {0x3a95a000}, {0x3a95c000}, {0x3a95e000}, + {0x3a960000}, {0x3a962000}, {0x3a964000}, {0x3a966000}, + {0x3a968000}, {0x3a96a000}, {0x3a96c000}, {0x3a96e000}, + {0x3a970000}, {0x3a972000}, {0x3a974000}, {0x3a976000}, + {0x3a978000}, {0x3a97a000}, {0x3a97c000}, {0x3a97e000}, + {0x3a980000}, {0x3a982000}, {0x3a984000}, {0x3a986000}, + {0x3a988000}, {0x3a98a000}, {0x3a98c000}, {0x3a98e000}, + {0x3a990000}, {0x3a992000}, {0x3a994000}, {0x3a996000}, + {0x3a998000}, {0x3a99a000}, {0x3a99c000}, {0x3a99e000}, + {0x3a9a0000}, {0x3a9a2000}, {0x3a9a4000}, {0x3a9a6000}, + {0x3a9a8000}, {0x3a9aa000}, {0x3a9ac000}, {0x3a9ae000}, + {0x3a9b0000}, {0x3a9b2000}, {0x3a9b4000}, {0x3a9b6000}, + {0x3a9b8000}, {0x3a9ba000}, {0x3a9bc000}, {0x3a9be000}, + {0x3a9c0000}, {0x3a9c2000}, {0x3a9c4000}, {0x3a9c6000}, + {0x3a9c8000}, {0x3a9ca000}, {0x3a9cc000}, {0x3a9ce000}, + {0x3a9d0000}, {0x3a9d2000}, {0x3a9d4000}, {0x3a9d6000}, + {0x3a9d8000}, {0x3a9da000}, {0x3a9dc000}, {0x3a9de000}, + {0x3a9e0000}, {0x3a9e2000}, {0x3a9e4000}, {0x3a9e6000}, + {0x3a9e8000}, {0x3a9ea000}, {0x3a9ec000}, {0x3a9ee000}, + {0x3a9f0000}, {0x3a9f2000}, {0x3a9f4000}, {0x3a9f6000}, + {0x3a9f8000}, {0x3a9fa000}, {0x3a9fc000}, {0x3a9fe000}, + {0x3aa00000}, {0x3aa02000}, {0x3aa04000}, {0x3aa06000}, + {0x3aa08000}, {0x3aa0a000}, {0x3aa0c000}, {0x3aa0e000}, + {0x3aa10000}, {0x3aa12000}, {0x3aa14000}, {0x3aa16000}, + {0x3aa18000}, {0x3aa1a000}, {0x3aa1c000}, {0x3aa1e000}, + {0x3aa20000}, {0x3aa22000}, {0x3aa24000}, {0x3aa26000}, + {0x3aa28000}, {0x3aa2a000}, {0x3aa2c000}, {0x3aa2e000}, + {0x3aa30000}, {0x3aa32000}, {0x3aa34000}, {0x3aa36000}, + {0x3aa38000}, {0x3aa3a000}, {0x3aa3c000}, {0x3aa3e000}, + {0x3aa40000}, {0x3aa42000}, {0x3aa44000}, {0x3aa46000}, + {0x3aa48000}, {0x3aa4a000}, {0x3aa4c000}, {0x3aa4e000}, + {0x3aa50000}, {0x3aa52000}, {0x3aa54000}, {0x3aa56000}, + {0x3aa58000}, {0x3aa5a000}, {0x3aa5c000}, {0x3aa5e000}, + {0x3aa60000}, {0x3aa62000}, {0x3aa64000}, {0x3aa66000}, + {0x3aa68000}, {0x3aa6a000}, {0x3aa6c000}, {0x3aa6e000}, + {0x3aa70000}, {0x3aa72000}, {0x3aa74000}, {0x3aa76000}, + {0x3aa78000}, {0x3aa7a000}, {0x3aa7c000}, {0x3aa7e000}, + {0x3aa80000}, {0x3aa82000}, {0x3aa84000}, {0x3aa86000}, + {0x3aa88000}, {0x3aa8a000}, {0x3aa8c000}, {0x3aa8e000}, + {0x3aa90000}, {0x3aa92000}, {0x3aa94000}, {0x3aa96000}, + {0x3aa98000}, {0x3aa9a000}, {0x3aa9c000}, {0x3aa9e000}, + {0x3aaa0000}, {0x3aaa2000}, {0x3aaa4000}, {0x3aaa6000}, + {0x3aaa8000}, {0x3aaaa000}, {0x3aaac000}, {0x3aaae000}, + {0x3aab0000}, {0x3aab2000}, {0x3aab4000}, {0x3aab6000}, + {0x3aab8000}, {0x3aaba000}, {0x3aabc000}, {0x3aabe000}, + {0x3aac0000}, {0x3aac2000}, {0x3aac4000}, {0x3aac6000}, + {0x3aac8000}, {0x3aaca000}, {0x3aacc000}, {0x3aace000}, + {0x3aad0000}, {0x3aad2000}, {0x3aad4000}, {0x3aad6000}, + {0x3aad8000}, {0x3aada000}, {0x3aadc000}, {0x3aade000}, + {0x3aae0000}, {0x3aae2000}, {0x3aae4000}, {0x3aae6000}, + {0x3aae8000}, {0x3aaea000}, {0x3aaec000}, {0x3aaee000}, + {0x3aaf0000}, {0x3aaf2000}, {0x3aaf4000}, {0x3aaf6000}, + {0x3aaf8000}, {0x3aafa000}, {0x3aafc000}, {0x3aafe000}, + {0x3ab00000}, {0x3ab02000}, {0x3ab04000}, {0x3ab06000}, + {0x3ab08000}, {0x3ab0a000}, {0x3ab0c000}, {0x3ab0e000}, + {0x3ab10000}, {0x3ab12000}, {0x3ab14000}, {0x3ab16000}, + {0x3ab18000}, {0x3ab1a000}, {0x3ab1c000}, {0x3ab1e000}, + {0x3ab20000}, {0x3ab22000}, {0x3ab24000}, {0x3ab26000}, + {0x3ab28000}, {0x3ab2a000}, {0x3ab2c000}, {0x3ab2e000}, + {0x3ab30000}, {0x3ab32000}, {0x3ab34000}, {0x3ab36000}, + {0x3ab38000}, {0x3ab3a000}, {0x3ab3c000}, {0x3ab3e000}, + {0x3ab40000}, {0x3ab42000}, {0x3ab44000}, {0x3ab46000}, + {0x3ab48000}, {0x3ab4a000}, {0x3ab4c000}, {0x3ab4e000}, + {0x3ab50000}, {0x3ab52000}, {0x3ab54000}, {0x3ab56000}, + {0x3ab58000}, {0x3ab5a000}, {0x3ab5c000}, {0x3ab5e000}, + {0x3ab60000}, {0x3ab62000}, {0x3ab64000}, {0x3ab66000}, + {0x3ab68000}, {0x3ab6a000}, {0x3ab6c000}, {0x3ab6e000}, + {0x3ab70000}, {0x3ab72000}, {0x3ab74000}, {0x3ab76000}, + {0x3ab78000}, {0x3ab7a000}, {0x3ab7c000}, {0x3ab7e000}, + {0x3ab80000}, {0x3ab82000}, {0x3ab84000}, {0x3ab86000}, + {0x3ab88000}, {0x3ab8a000}, {0x3ab8c000}, {0x3ab8e000}, + {0x3ab90000}, {0x3ab92000}, {0x3ab94000}, {0x3ab96000}, + {0x3ab98000}, {0x3ab9a000}, {0x3ab9c000}, {0x3ab9e000}, + {0x3aba0000}, {0x3aba2000}, {0x3aba4000}, {0x3aba6000}, + {0x3aba8000}, {0x3abaa000}, {0x3abac000}, {0x3abae000}, + {0x3abb0000}, {0x3abb2000}, {0x3abb4000}, {0x3abb6000}, + {0x3abb8000}, {0x3abba000}, {0x3abbc000}, {0x3abbe000}, + {0x3abc0000}, {0x3abc2000}, {0x3abc4000}, {0x3abc6000}, + {0x3abc8000}, {0x3abca000}, {0x3abcc000}, {0x3abce000}, + {0x3abd0000}, {0x3abd2000}, {0x3abd4000}, {0x3abd6000}, + {0x3abd8000}, {0x3abda000}, {0x3abdc000}, {0x3abde000}, + {0x3abe0000}, {0x3abe2000}, {0x3abe4000}, {0x3abe6000}, + {0x3abe8000}, {0x3abea000}, {0x3abec000}, {0x3abee000}, + {0x3abf0000}, {0x3abf2000}, {0x3abf4000}, {0x3abf6000}, + {0x3abf8000}, {0x3abfa000}, {0x3abfc000}, {0x3abfe000}, + {0x3ac00000}, {0x3ac02000}, {0x3ac04000}, {0x3ac06000}, + {0x3ac08000}, {0x3ac0a000}, {0x3ac0c000}, {0x3ac0e000}, + {0x3ac10000}, {0x3ac12000}, {0x3ac14000}, {0x3ac16000}, + {0x3ac18000}, {0x3ac1a000}, {0x3ac1c000}, {0x3ac1e000}, + {0x3ac20000}, {0x3ac22000}, {0x3ac24000}, {0x3ac26000}, + {0x3ac28000}, {0x3ac2a000}, {0x3ac2c000}, {0x3ac2e000}, + {0x3ac30000}, {0x3ac32000}, {0x3ac34000}, {0x3ac36000}, + {0x3ac38000}, {0x3ac3a000}, {0x3ac3c000}, {0x3ac3e000}, + {0x3ac40000}, {0x3ac42000}, {0x3ac44000}, {0x3ac46000}, + {0x3ac48000}, {0x3ac4a000}, {0x3ac4c000}, {0x3ac4e000}, + {0x3ac50000}, {0x3ac52000}, {0x3ac54000}, {0x3ac56000}, + {0x3ac58000}, {0x3ac5a000}, {0x3ac5c000}, {0x3ac5e000}, + {0x3ac60000}, {0x3ac62000}, {0x3ac64000}, {0x3ac66000}, + {0x3ac68000}, {0x3ac6a000}, {0x3ac6c000}, {0x3ac6e000}, + {0x3ac70000}, {0x3ac72000}, {0x3ac74000}, {0x3ac76000}, + {0x3ac78000}, {0x3ac7a000}, {0x3ac7c000}, {0x3ac7e000}, + {0x3ac80000}, {0x3ac82000}, {0x3ac84000}, {0x3ac86000}, + {0x3ac88000}, {0x3ac8a000}, {0x3ac8c000}, {0x3ac8e000}, + {0x3ac90000}, {0x3ac92000}, {0x3ac94000}, {0x3ac96000}, + {0x3ac98000}, {0x3ac9a000}, {0x3ac9c000}, {0x3ac9e000}, + {0x3aca0000}, {0x3aca2000}, {0x3aca4000}, {0x3aca6000}, + {0x3aca8000}, {0x3acaa000}, {0x3acac000}, {0x3acae000}, + {0x3acb0000}, {0x3acb2000}, {0x3acb4000}, {0x3acb6000}, + {0x3acb8000}, {0x3acba000}, {0x3acbc000}, {0x3acbe000}, + {0x3acc0000}, {0x3acc2000}, {0x3acc4000}, {0x3acc6000}, + {0x3acc8000}, {0x3acca000}, {0x3accc000}, {0x3acce000}, + {0x3acd0000}, {0x3acd2000}, {0x3acd4000}, {0x3acd6000}, + {0x3acd8000}, {0x3acda000}, {0x3acdc000}, {0x3acde000}, + {0x3ace0000}, {0x3ace2000}, {0x3ace4000}, {0x3ace6000}, + {0x3ace8000}, {0x3acea000}, {0x3acec000}, {0x3acee000}, + {0x3acf0000}, {0x3acf2000}, {0x3acf4000}, {0x3acf6000}, + {0x3acf8000}, {0x3acfa000}, {0x3acfc000}, {0x3acfe000}, + {0x3ad00000}, {0x3ad02000}, {0x3ad04000}, {0x3ad06000}, + {0x3ad08000}, {0x3ad0a000}, {0x3ad0c000}, {0x3ad0e000}, + {0x3ad10000}, {0x3ad12000}, {0x3ad14000}, {0x3ad16000}, + {0x3ad18000}, {0x3ad1a000}, {0x3ad1c000}, {0x3ad1e000}, + {0x3ad20000}, {0x3ad22000}, {0x3ad24000}, {0x3ad26000}, + {0x3ad28000}, {0x3ad2a000}, {0x3ad2c000}, {0x3ad2e000}, + {0x3ad30000}, {0x3ad32000}, {0x3ad34000}, {0x3ad36000}, + {0x3ad38000}, {0x3ad3a000}, {0x3ad3c000}, {0x3ad3e000}, + {0x3ad40000}, {0x3ad42000}, {0x3ad44000}, {0x3ad46000}, + {0x3ad48000}, {0x3ad4a000}, {0x3ad4c000}, {0x3ad4e000}, + {0x3ad50000}, {0x3ad52000}, {0x3ad54000}, {0x3ad56000}, + {0x3ad58000}, {0x3ad5a000}, {0x3ad5c000}, {0x3ad5e000}, + {0x3ad60000}, {0x3ad62000}, {0x3ad64000}, {0x3ad66000}, + {0x3ad68000}, {0x3ad6a000}, {0x3ad6c000}, {0x3ad6e000}, + {0x3ad70000}, {0x3ad72000}, {0x3ad74000}, {0x3ad76000}, + {0x3ad78000}, {0x3ad7a000}, {0x3ad7c000}, {0x3ad7e000}, + {0x3ad80000}, {0x3ad82000}, {0x3ad84000}, {0x3ad86000}, + {0x3ad88000}, {0x3ad8a000}, {0x3ad8c000}, {0x3ad8e000}, + {0x3ad90000}, {0x3ad92000}, {0x3ad94000}, {0x3ad96000}, + {0x3ad98000}, {0x3ad9a000}, {0x3ad9c000}, {0x3ad9e000}, + {0x3ada0000}, {0x3ada2000}, {0x3ada4000}, {0x3ada6000}, + {0x3ada8000}, {0x3adaa000}, {0x3adac000}, {0x3adae000}, + {0x3adb0000}, {0x3adb2000}, {0x3adb4000}, {0x3adb6000}, + {0x3adb8000}, {0x3adba000}, {0x3adbc000}, {0x3adbe000}, + {0x3adc0000}, {0x3adc2000}, {0x3adc4000}, {0x3adc6000}, + {0x3adc8000}, {0x3adca000}, {0x3adcc000}, {0x3adce000}, + {0x3add0000}, {0x3add2000}, {0x3add4000}, {0x3add6000}, + {0x3add8000}, {0x3adda000}, {0x3addc000}, {0x3adde000}, + {0x3ade0000}, {0x3ade2000}, {0x3ade4000}, {0x3ade6000}, + {0x3ade8000}, {0x3adea000}, {0x3adec000}, {0x3adee000}, + {0x3adf0000}, {0x3adf2000}, {0x3adf4000}, {0x3adf6000}, + {0x3adf8000}, {0x3adfa000}, {0x3adfc000}, {0x3adfe000}, + {0x3ae00000}, {0x3ae02000}, {0x3ae04000}, {0x3ae06000}, + {0x3ae08000}, {0x3ae0a000}, {0x3ae0c000}, {0x3ae0e000}, + {0x3ae10000}, {0x3ae12000}, {0x3ae14000}, {0x3ae16000}, + {0x3ae18000}, {0x3ae1a000}, {0x3ae1c000}, {0x3ae1e000}, + {0x3ae20000}, {0x3ae22000}, {0x3ae24000}, {0x3ae26000}, + {0x3ae28000}, {0x3ae2a000}, {0x3ae2c000}, {0x3ae2e000}, + {0x3ae30000}, {0x3ae32000}, {0x3ae34000}, {0x3ae36000}, + {0x3ae38000}, {0x3ae3a000}, {0x3ae3c000}, {0x3ae3e000}, + {0x3ae40000}, {0x3ae42000}, {0x3ae44000}, {0x3ae46000}, + {0x3ae48000}, {0x3ae4a000}, {0x3ae4c000}, {0x3ae4e000}, + {0x3ae50000}, {0x3ae52000}, {0x3ae54000}, {0x3ae56000}, + {0x3ae58000}, {0x3ae5a000}, {0x3ae5c000}, {0x3ae5e000}, + {0x3ae60000}, {0x3ae62000}, {0x3ae64000}, {0x3ae66000}, + {0x3ae68000}, {0x3ae6a000}, {0x3ae6c000}, {0x3ae6e000}, + {0x3ae70000}, {0x3ae72000}, {0x3ae74000}, {0x3ae76000}, + {0x3ae78000}, {0x3ae7a000}, {0x3ae7c000}, {0x3ae7e000}, + {0x3ae80000}, {0x3ae82000}, {0x3ae84000}, {0x3ae86000}, + {0x3ae88000}, {0x3ae8a000}, {0x3ae8c000}, {0x3ae8e000}, + {0x3ae90000}, {0x3ae92000}, {0x3ae94000}, {0x3ae96000}, + {0x3ae98000}, {0x3ae9a000}, {0x3ae9c000}, {0x3ae9e000}, + {0x3aea0000}, {0x3aea2000}, {0x3aea4000}, {0x3aea6000}, + {0x3aea8000}, {0x3aeaa000}, {0x3aeac000}, {0x3aeae000}, + {0x3aeb0000}, {0x3aeb2000}, {0x3aeb4000}, {0x3aeb6000}, + {0x3aeb8000}, {0x3aeba000}, {0x3aebc000}, {0x3aebe000}, + {0x3aec0000}, {0x3aec2000}, {0x3aec4000}, {0x3aec6000}, + {0x3aec8000}, {0x3aeca000}, {0x3aecc000}, {0x3aece000}, + {0x3aed0000}, {0x3aed2000}, {0x3aed4000}, {0x3aed6000}, + {0x3aed8000}, {0x3aeda000}, {0x3aedc000}, {0x3aede000}, + {0x3aee0000}, {0x3aee2000}, {0x3aee4000}, {0x3aee6000}, + {0x3aee8000}, {0x3aeea000}, {0x3aeec000}, {0x3aeee000}, + {0x3aef0000}, {0x3aef2000}, {0x3aef4000}, {0x3aef6000}, + {0x3aef8000}, {0x3aefa000}, {0x3aefc000}, {0x3aefe000}, + {0x3af00000}, {0x3af02000}, {0x3af04000}, {0x3af06000}, + {0x3af08000}, {0x3af0a000}, {0x3af0c000}, {0x3af0e000}, + {0x3af10000}, {0x3af12000}, {0x3af14000}, {0x3af16000}, + {0x3af18000}, {0x3af1a000}, {0x3af1c000}, {0x3af1e000}, + {0x3af20000}, {0x3af22000}, {0x3af24000}, {0x3af26000}, + {0x3af28000}, {0x3af2a000}, {0x3af2c000}, {0x3af2e000}, + {0x3af30000}, {0x3af32000}, {0x3af34000}, {0x3af36000}, + {0x3af38000}, {0x3af3a000}, {0x3af3c000}, {0x3af3e000}, + {0x3af40000}, {0x3af42000}, {0x3af44000}, {0x3af46000}, + {0x3af48000}, {0x3af4a000}, {0x3af4c000}, {0x3af4e000}, + {0x3af50000}, {0x3af52000}, {0x3af54000}, {0x3af56000}, + {0x3af58000}, {0x3af5a000}, {0x3af5c000}, {0x3af5e000}, + {0x3af60000}, {0x3af62000}, {0x3af64000}, {0x3af66000}, + {0x3af68000}, {0x3af6a000}, {0x3af6c000}, {0x3af6e000}, + {0x3af70000}, {0x3af72000}, {0x3af74000}, {0x3af76000}, + {0x3af78000}, {0x3af7a000}, {0x3af7c000}, {0x3af7e000}, + {0x3af80000}, {0x3af82000}, {0x3af84000}, {0x3af86000}, + {0x3af88000}, {0x3af8a000}, {0x3af8c000}, {0x3af8e000}, + {0x3af90000}, {0x3af92000}, {0x3af94000}, {0x3af96000}, + {0x3af98000}, {0x3af9a000}, {0x3af9c000}, {0x3af9e000}, + {0x3afa0000}, {0x3afa2000}, {0x3afa4000}, {0x3afa6000}, + {0x3afa8000}, {0x3afaa000}, {0x3afac000}, {0x3afae000}, + {0x3afb0000}, {0x3afb2000}, {0x3afb4000}, {0x3afb6000}, + {0x3afb8000}, {0x3afba000}, {0x3afbc000}, {0x3afbe000}, + {0x3afc0000}, {0x3afc2000}, {0x3afc4000}, {0x3afc6000}, + {0x3afc8000}, {0x3afca000}, {0x3afcc000}, {0x3afce000}, + {0x3afd0000}, {0x3afd2000}, {0x3afd4000}, {0x3afd6000}, + {0x3afd8000}, {0x3afda000}, {0x3afdc000}, {0x3afde000}, + {0x3afe0000}, {0x3afe2000}, {0x3afe4000}, {0x3afe6000}, + {0x3afe8000}, {0x3afea000}, {0x3afec000}, {0x3afee000}, + {0x3aff0000}, {0x3aff2000}, {0x3aff4000}, {0x3aff6000}, + {0x3aff8000}, {0x3affa000}, {0x3affc000}, {0x3affe000}, + {0x3b000000}, {0x3b002000}, {0x3b004000}, {0x3b006000}, + {0x3b008000}, {0x3b00a000}, {0x3b00c000}, {0x3b00e000}, + {0x3b010000}, {0x3b012000}, {0x3b014000}, {0x3b016000}, + {0x3b018000}, {0x3b01a000}, {0x3b01c000}, {0x3b01e000}, + {0x3b020000}, {0x3b022000}, {0x3b024000}, {0x3b026000}, + {0x3b028000}, {0x3b02a000}, {0x3b02c000}, {0x3b02e000}, + {0x3b030000}, {0x3b032000}, {0x3b034000}, {0x3b036000}, + {0x3b038000}, {0x3b03a000}, {0x3b03c000}, {0x3b03e000}, + {0x3b040000}, {0x3b042000}, {0x3b044000}, {0x3b046000}, + {0x3b048000}, {0x3b04a000}, {0x3b04c000}, {0x3b04e000}, + {0x3b050000}, {0x3b052000}, {0x3b054000}, {0x3b056000}, + {0x3b058000}, {0x3b05a000}, {0x3b05c000}, {0x3b05e000}, + {0x3b060000}, {0x3b062000}, {0x3b064000}, {0x3b066000}, + {0x3b068000}, {0x3b06a000}, {0x3b06c000}, {0x3b06e000}, + {0x3b070000}, {0x3b072000}, {0x3b074000}, {0x3b076000}, + {0x3b078000}, {0x3b07a000}, {0x3b07c000}, {0x3b07e000}, + {0x3b080000}, {0x3b082000}, {0x3b084000}, {0x3b086000}, + {0x3b088000}, {0x3b08a000}, {0x3b08c000}, {0x3b08e000}, + {0x3b090000}, {0x3b092000}, {0x3b094000}, {0x3b096000}, + {0x3b098000}, {0x3b09a000}, {0x3b09c000}, {0x3b09e000}, + {0x3b0a0000}, {0x3b0a2000}, {0x3b0a4000}, {0x3b0a6000}, + {0x3b0a8000}, {0x3b0aa000}, {0x3b0ac000}, {0x3b0ae000}, + {0x3b0b0000}, {0x3b0b2000}, {0x3b0b4000}, {0x3b0b6000}, + {0x3b0b8000}, {0x3b0ba000}, {0x3b0bc000}, {0x3b0be000}, + {0x3b0c0000}, {0x3b0c2000}, {0x3b0c4000}, {0x3b0c6000}, + {0x3b0c8000}, {0x3b0ca000}, {0x3b0cc000}, {0x3b0ce000}, + {0x3b0d0000}, {0x3b0d2000}, {0x3b0d4000}, {0x3b0d6000}, + {0x3b0d8000}, {0x3b0da000}, {0x3b0dc000}, {0x3b0de000}, + {0x3b0e0000}, {0x3b0e2000}, {0x3b0e4000}, {0x3b0e6000}, + {0x3b0e8000}, {0x3b0ea000}, {0x3b0ec000}, {0x3b0ee000}, + {0x3b0f0000}, {0x3b0f2000}, {0x3b0f4000}, {0x3b0f6000}, + {0x3b0f8000}, {0x3b0fa000}, {0x3b0fc000}, {0x3b0fe000}, + {0x3b100000}, {0x3b102000}, {0x3b104000}, {0x3b106000}, + {0x3b108000}, {0x3b10a000}, {0x3b10c000}, {0x3b10e000}, + {0x3b110000}, {0x3b112000}, {0x3b114000}, {0x3b116000}, + {0x3b118000}, {0x3b11a000}, {0x3b11c000}, {0x3b11e000}, + {0x3b120000}, {0x3b122000}, {0x3b124000}, {0x3b126000}, + {0x3b128000}, {0x3b12a000}, {0x3b12c000}, {0x3b12e000}, + {0x3b130000}, {0x3b132000}, {0x3b134000}, {0x3b136000}, + {0x3b138000}, {0x3b13a000}, {0x3b13c000}, {0x3b13e000}, + {0x3b140000}, {0x3b142000}, {0x3b144000}, {0x3b146000}, + {0x3b148000}, {0x3b14a000}, {0x3b14c000}, {0x3b14e000}, + {0x3b150000}, {0x3b152000}, {0x3b154000}, {0x3b156000}, + {0x3b158000}, {0x3b15a000}, {0x3b15c000}, {0x3b15e000}, + {0x3b160000}, {0x3b162000}, {0x3b164000}, {0x3b166000}, + {0x3b168000}, {0x3b16a000}, {0x3b16c000}, {0x3b16e000}, + {0x3b170000}, {0x3b172000}, {0x3b174000}, {0x3b176000}, + {0x3b178000}, {0x3b17a000}, {0x3b17c000}, {0x3b17e000}, + {0x3b180000}, {0x3b182000}, {0x3b184000}, {0x3b186000}, + {0x3b188000}, {0x3b18a000}, {0x3b18c000}, {0x3b18e000}, + {0x3b190000}, {0x3b192000}, {0x3b194000}, {0x3b196000}, + {0x3b198000}, {0x3b19a000}, {0x3b19c000}, {0x3b19e000}, + {0x3b1a0000}, {0x3b1a2000}, {0x3b1a4000}, {0x3b1a6000}, + {0x3b1a8000}, {0x3b1aa000}, {0x3b1ac000}, {0x3b1ae000}, + {0x3b1b0000}, {0x3b1b2000}, {0x3b1b4000}, {0x3b1b6000}, + {0x3b1b8000}, {0x3b1ba000}, {0x3b1bc000}, {0x3b1be000}, + {0x3b1c0000}, {0x3b1c2000}, {0x3b1c4000}, {0x3b1c6000}, + {0x3b1c8000}, {0x3b1ca000}, {0x3b1cc000}, {0x3b1ce000}, + {0x3b1d0000}, {0x3b1d2000}, {0x3b1d4000}, {0x3b1d6000}, + {0x3b1d8000}, {0x3b1da000}, {0x3b1dc000}, {0x3b1de000}, + {0x3b1e0000}, {0x3b1e2000}, {0x3b1e4000}, {0x3b1e6000}, + {0x3b1e8000}, {0x3b1ea000}, {0x3b1ec000}, {0x3b1ee000}, + {0x3b1f0000}, {0x3b1f2000}, {0x3b1f4000}, {0x3b1f6000}, + {0x3b1f8000}, {0x3b1fa000}, {0x3b1fc000}, {0x3b1fe000}, + {0x3b200000}, {0x3b202000}, {0x3b204000}, {0x3b206000}, + {0x3b208000}, {0x3b20a000}, {0x3b20c000}, {0x3b20e000}, + {0x3b210000}, {0x3b212000}, {0x3b214000}, {0x3b216000}, + {0x3b218000}, {0x3b21a000}, {0x3b21c000}, {0x3b21e000}, + {0x3b220000}, {0x3b222000}, {0x3b224000}, {0x3b226000}, + {0x3b228000}, {0x3b22a000}, {0x3b22c000}, {0x3b22e000}, + {0x3b230000}, {0x3b232000}, {0x3b234000}, {0x3b236000}, + {0x3b238000}, {0x3b23a000}, {0x3b23c000}, {0x3b23e000}, + {0x3b240000}, {0x3b242000}, {0x3b244000}, {0x3b246000}, + {0x3b248000}, {0x3b24a000}, {0x3b24c000}, {0x3b24e000}, + {0x3b250000}, {0x3b252000}, {0x3b254000}, {0x3b256000}, + {0x3b258000}, {0x3b25a000}, {0x3b25c000}, {0x3b25e000}, + {0x3b260000}, {0x3b262000}, {0x3b264000}, {0x3b266000}, + {0x3b268000}, {0x3b26a000}, {0x3b26c000}, {0x3b26e000}, + {0x3b270000}, {0x3b272000}, {0x3b274000}, {0x3b276000}, + {0x3b278000}, {0x3b27a000}, {0x3b27c000}, {0x3b27e000}, + {0x3b280000}, {0x3b282000}, {0x3b284000}, {0x3b286000}, + {0x3b288000}, {0x3b28a000}, {0x3b28c000}, {0x3b28e000}, + {0x3b290000}, {0x3b292000}, {0x3b294000}, {0x3b296000}, + {0x3b298000}, {0x3b29a000}, {0x3b29c000}, {0x3b29e000}, + {0x3b2a0000}, {0x3b2a2000}, {0x3b2a4000}, {0x3b2a6000}, + {0x3b2a8000}, {0x3b2aa000}, {0x3b2ac000}, {0x3b2ae000}, + {0x3b2b0000}, {0x3b2b2000}, {0x3b2b4000}, {0x3b2b6000}, + {0x3b2b8000}, {0x3b2ba000}, {0x3b2bc000}, {0x3b2be000}, + {0x3b2c0000}, {0x3b2c2000}, {0x3b2c4000}, {0x3b2c6000}, + {0x3b2c8000}, {0x3b2ca000}, {0x3b2cc000}, {0x3b2ce000}, + {0x3b2d0000}, {0x3b2d2000}, {0x3b2d4000}, {0x3b2d6000}, + {0x3b2d8000}, {0x3b2da000}, {0x3b2dc000}, {0x3b2de000}, + {0x3b2e0000}, {0x3b2e2000}, {0x3b2e4000}, {0x3b2e6000}, + {0x3b2e8000}, {0x3b2ea000}, {0x3b2ec000}, {0x3b2ee000}, + {0x3b2f0000}, {0x3b2f2000}, {0x3b2f4000}, {0x3b2f6000}, + {0x3b2f8000}, {0x3b2fa000}, {0x3b2fc000}, {0x3b2fe000}, + {0x3b300000}, {0x3b302000}, {0x3b304000}, {0x3b306000}, + {0x3b308000}, {0x3b30a000}, {0x3b30c000}, {0x3b30e000}, + {0x3b310000}, {0x3b312000}, {0x3b314000}, {0x3b316000}, + {0x3b318000}, {0x3b31a000}, {0x3b31c000}, {0x3b31e000}, + {0x3b320000}, {0x3b322000}, {0x3b324000}, {0x3b326000}, + {0x3b328000}, {0x3b32a000}, {0x3b32c000}, {0x3b32e000}, + {0x3b330000}, {0x3b332000}, {0x3b334000}, {0x3b336000}, + {0x3b338000}, {0x3b33a000}, {0x3b33c000}, {0x3b33e000}, + {0x3b340000}, {0x3b342000}, {0x3b344000}, {0x3b346000}, + {0x3b348000}, {0x3b34a000}, {0x3b34c000}, {0x3b34e000}, + {0x3b350000}, {0x3b352000}, {0x3b354000}, {0x3b356000}, + {0x3b358000}, {0x3b35a000}, {0x3b35c000}, {0x3b35e000}, + {0x3b360000}, {0x3b362000}, {0x3b364000}, {0x3b366000}, + {0x3b368000}, {0x3b36a000}, {0x3b36c000}, {0x3b36e000}, + {0x3b370000}, {0x3b372000}, {0x3b374000}, {0x3b376000}, + {0x3b378000}, {0x3b37a000}, {0x3b37c000}, {0x3b37e000}, + {0x3b380000}, {0x3b382000}, {0x3b384000}, {0x3b386000}, + {0x3b388000}, {0x3b38a000}, {0x3b38c000}, {0x3b38e000}, + {0x3b390000}, {0x3b392000}, {0x3b394000}, {0x3b396000}, + {0x3b398000}, {0x3b39a000}, {0x3b39c000}, {0x3b39e000}, + {0x3b3a0000}, {0x3b3a2000}, {0x3b3a4000}, {0x3b3a6000}, + {0x3b3a8000}, {0x3b3aa000}, {0x3b3ac000}, {0x3b3ae000}, + {0x3b3b0000}, {0x3b3b2000}, {0x3b3b4000}, {0x3b3b6000}, + {0x3b3b8000}, {0x3b3ba000}, {0x3b3bc000}, {0x3b3be000}, + {0x3b3c0000}, {0x3b3c2000}, {0x3b3c4000}, {0x3b3c6000}, + {0x3b3c8000}, {0x3b3ca000}, {0x3b3cc000}, {0x3b3ce000}, + {0x3b3d0000}, {0x3b3d2000}, {0x3b3d4000}, {0x3b3d6000}, + {0x3b3d8000}, {0x3b3da000}, {0x3b3dc000}, {0x3b3de000}, + {0x3b3e0000}, {0x3b3e2000}, {0x3b3e4000}, {0x3b3e6000}, + {0x3b3e8000}, {0x3b3ea000}, {0x3b3ec000}, {0x3b3ee000}, + {0x3b3f0000}, {0x3b3f2000}, {0x3b3f4000}, {0x3b3f6000}, + {0x3b3f8000}, {0x3b3fa000}, {0x3b3fc000}, {0x3b3fe000}, + {0x3b400000}, {0x3b402000}, {0x3b404000}, {0x3b406000}, + {0x3b408000}, {0x3b40a000}, {0x3b40c000}, {0x3b40e000}, + {0x3b410000}, {0x3b412000}, {0x3b414000}, {0x3b416000}, + {0x3b418000}, {0x3b41a000}, {0x3b41c000}, {0x3b41e000}, + {0x3b420000}, {0x3b422000}, {0x3b424000}, {0x3b426000}, + {0x3b428000}, {0x3b42a000}, {0x3b42c000}, {0x3b42e000}, + {0x3b430000}, {0x3b432000}, {0x3b434000}, {0x3b436000}, + {0x3b438000}, {0x3b43a000}, {0x3b43c000}, {0x3b43e000}, + {0x3b440000}, {0x3b442000}, {0x3b444000}, {0x3b446000}, + {0x3b448000}, {0x3b44a000}, {0x3b44c000}, {0x3b44e000}, + {0x3b450000}, {0x3b452000}, {0x3b454000}, {0x3b456000}, + {0x3b458000}, {0x3b45a000}, {0x3b45c000}, {0x3b45e000}, + {0x3b460000}, {0x3b462000}, {0x3b464000}, {0x3b466000}, + {0x3b468000}, {0x3b46a000}, {0x3b46c000}, {0x3b46e000}, + {0x3b470000}, {0x3b472000}, {0x3b474000}, {0x3b476000}, + {0x3b478000}, {0x3b47a000}, {0x3b47c000}, {0x3b47e000}, + {0x3b480000}, {0x3b482000}, {0x3b484000}, {0x3b486000}, + {0x3b488000}, {0x3b48a000}, {0x3b48c000}, {0x3b48e000}, + {0x3b490000}, {0x3b492000}, {0x3b494000}, {0x3b496000}, + {0x3b498000}, {0x3b49a000}, {0x3b49c000}, {0x3b49e000}, + {0x3b4a0000}, {0x3b4a2000}, {0x3b4a4000}, {0x3b4a6000}, + {0x3b4a8000}, {0x3b4aa000}, {0x3b4ac000}, {0x3b4ae000}, + {0x3b4b0000}, {0x3b4b2000}, {0x3b4b4000}, {0x3b4b6000}, + {0x3b4b8000}, {0x3b4ba000}, {0x3b4bc000}, {0x3b4be000}, + {0x3b4c0000}, {0x3b4c2000}, {0x3b4c4000}, {0x3b4c6000}, + {0x3b4c8000}, {0x3b4ca000}, {0x3b4cc000}, {0x3b4ce000}, + {0x3b4d0000}, {0x3b4d2000}, {0x3b4d4000}, {0x3b4d6000}, + {0x3b4d8000}, {0x3b4da000}, {0x3b4dc000}, {0x3b4de000}, + {0x3b4e0000}, {0x3b4e2000}, {0x3b4e4000}, {0x3b4e6000}, + {0x3b4e8000}, {0x3b4ea000}, {0x3b4ec000}, {0x3b4ee000}, + {0x3b4f0000}, {0x3b4f2000}, {0x3b4f4000}, {0x3b4f6000}, + {0x3b4f8000}, {0x3b4fa000}, {0x3b4fc000}, {0x3b4fe000}, + {0x3b500000}, {0x3b502000}, {0x3b504000}, {0x3b506000}, + {0x3b508000}, {0x3b50a000}, {0x3b50c000}, {0x3b50e000}, + {0x3b510000}, {0x3b512000}, {0x3b514000}, {0x3b516000}, + {0x3b518000}, {0x3b51a000}, {0x3b51c000}, {0x3b51e000}, + {0x3b520000}, {0x3b522000}, {0x3b524000}, {0x3b526000}, + {0x3b528000}, {0x3b52a000}, {0x3b52c000}, {0x3b52e000}, + {0x3b530000}, {0x3b532000}, {0x3b534000}, {0x3b536000}, + {0x3b538000}, {0x3b53a000}, {0x3b53c000}, {0x3b53e000}, + {0x3b540000}, {0x3b542000}, {0x3b544000}, {0x3b546000}, + {0x3b548000}, {0x3b54a000}, {0x3b54c000}, {0x3b54e000}, + {0x3b550000}, {0x3b552000}, {0x3b554000}, {0x3b556000}, + {0x3b558000}, {0x3b55a000}, {0x3b55c000}, {0x3b55e000}, + {0x3b560000}, {0x3b562000}, {0x3b564000}, {0x3b566000}, + {0x3b568000}, {0x3b56a000}, {0x3b56c000}, {0x3b56e000}, + {0x3b570000}, {0x3b572000}, {0x3b574000}, {0x3b576000}, + {0x3b578000}, {0x3b57a000}, {0x3b57c000}, {0x3b57e000}, + {0x3b580000}, {0x3b582000}, {0x3b584000}, {0x3b586000}, + {0x3b588000}, {0x3b58a000}, {0x3b58c000}, {0x3b58e000}, + {0x3b590000}, {0x3b592000}, {0x3b594000}, {0x3b596000}, + {0x3b598000}, {0x3b59a000}, {0x3b59c000}, {0x3b59e000}, + {0x3b5a0000}, {0x3b5a2000}, {0x3b5a4000}, {0x3b5a6000}, + {0x3b5a8000}, {0x3b5aa000}, {0x3b5ac000}, {0x3b5ae000}, + {0x3b5b0000}, {0x3b5b2000}, {0x3b5b4000}, {0x3b5b6000}, + {0x3b5b8000}, {0x3b5ba000}, {0x3b5bc000}, {0x3b5be000}, + {0x3b5c0000}, {0x3b5c2000}, {0x3b5c4000}, {0x3b5c6000}, + {0x3b5c8000}, {0x3b5ca000}, {0x3b5cc000}, {0x3b5ce000}, + {0x3b5d0000}, {0x3b5d2000}, {0x3b5d4000}, {0x3b5d6000}, + {0x3b5d8000}, {0x3b5da000}, {0x3b5dc000}, {0x3b5de000}, + {0x3b5e0000}, {0x3b5e2000}, {0x3b5e4000}, {0x3b5e6000}, + {0x3b5e8000}, {0x3b5ea000}, {0x3b5ec000}, {0x3b5ee000}, + {0x3b5f0000}, {0x3b5f2000}, {0x3b5f4000}, {0x3b5f6000}, + {0x3b5f8000}, {0x3b5fa000}, {0x3b5fc000}, {0x3b5fe000}, + {0x3b600000}, {0x3b602000}, {0x3b604000}, {0x3b606000}, + {0x3b608000}, {0x3b60a000}, {0x3b60c000}, {0x3b60e000}, + {0x3b610000}, {0x3b612000}, {0x3b614000}, {0x3b616000}, + {0x3b618000}, {0x3b61a000}, {0x3b61c000}, {0x3b61e000}, + {0x3b620000}, {0x3b622000}, {0x3b624000}, {0x3b626000}, + {0x3b628000}, {0x3b62a000}, {0x3b62c000}, {0x3b62e000}, + {0x3b630000}, {0x3b632000}, {0x3b634000}, {0x3b636000}, + {0x3b638000}, {0x3b63a000}, {0x3b63c000}, {0x3b63e000}, + {0x3b640000}, {0x3b642000}, {0x3b644000}, {0x3b646000}, + {0x3b648000}, {0x3b64a000}, {0x3b64c000}, {0x3b64e000}, + {0x3b650000}, {0x3b652000}, {0x3b654000}, {0x3b656000}, + {0x3b658000}, {0x3b65a000}, {0x3b65c000}, {0x3b65e000}, + {0x3b660000}, {0x3b662000}, {0x3b664000}, {0x3b666000}, + {0x3b668000}, {0x3b66a000}, {0x3b66c000}, {0x3b66e000}, + {0x3b670000}, {0x3b672000}, {0x3b674000}, {0x3b676000}, + {0x3b678000}, {0x3b67a000}, {0x3b67c000}, {0x3b67e000}, + {0x3b680000}, {0x3b682000}, {0x3b684000}, {0x3b686000}, + {0x3b688000}, {0x3b68a000}, {0x3b68c000}, {0x3b68e000}, + {0x3b690000}, {0x3b692000}, {0x3b694000}, {0x3b696000}, + {0x3b698000}, {0x3b69a000}, {0x3b69c000}, {0x3b69e000}, + {0x3b6a0000}, {0x3b6a2000}, {0x3b6a4000}, {0x3b6a6000}, + {0x3b6a8000}, {0x3b6aa000}, {0x3b6ac000}, {0x3b6ae000}, + {0x3b6b0000}, {0x3b6b2000}, {0x3b6b4000}, {0x3b6b6000}, + {0x3b6b8000}, {0x3b6ba000}, {0x3b6bc000}, {0x3b6be000}, + {0x3b6c0000}, {0x3b6c2000}, {0x3b6c4000}, {0x3b6c6000}, + {0x3b6c8000}, {0x3b6ca000}, {0x3b6cc000}, {0x3b6ce000}, + {0x3b6d0000}, {0x3b6d2000}, {0x3b6d4000}, {0x3b6d6000}, + {0x3b6d8000}, {0x3b6da000}, {0x3b6dc000}, {0x3b6de000}, + {0x3b6e0000}, {0x3b6e2000}, {0x3b6e4000}, {0x3b6e6000}, + {0x3b6e8000}, {0x3b6ea000}, {0x3b6ec000}, {0x3b6ee000}, + {0x3b6f0000}, {0x3b6f2000}, {0x3b6f4000}, {0x3b6f6000}, + {0x3b6f8000}, {0x3b6fa000}, {0x3b6fc000}, {0x3b6fe000}, + {0x3b700000}, {0x3b702000}, {0x3b704000}, {0x3b706000}, + {0x3b708000}, {0x3b70a000}, {0x3b70c000}, {0x3b70e000}, + {0x3b710000}, {0x3b712000}, {0x3b714000}, {0x3b716000}, + {0x3b718000}, {0x3b71a000}, {0x3b71c000}, {0x3b71e000}, + {0x3b720000}, {0x3b722000}, {0x3b724000}, {0x3b726000}, + {0x3b728000}, {0x3b72a000}, {0x3b72c000}, {0x3b72e000}, + {0x3b730000}, {0x3b732000}, {0x3b734000}, {0x3b736000}, + {0x3b738000}, {0x3b73a000}, {0x3b73c000}, {0x3b73e000}, + {0x3b740000}, {0x3b742000}, {0x3b744000}, {0x3b746000}, + {0x3b748000}, {0x3b74a000}, {0x3b74c000}, {0x3b74e000}, + {0x3b750000}, {0x3b752000}, {0x3b754000}, {0x3b756000}, + {0x3b758000}, {0x3b75a000}, {0x3b75c000}, {0x3b75e000}, + {0x3b760000}, {0x3b762000}, {0x3b764000}, {0x3b766000}, + {0x3b768000}, {0x3b76a000}, {0x3b76c000}, {0x3b76e000}, + {0x3b770000}, {0x3b772000}, {0x3b774000}, {0x3b776000}, + {0x3b778000}, {0x3b77a000}, {0x3b77c000}, {0x3b77e000}, + {0x3b780000}, {0x3b782000}, {0x3b784000}, {0x3b786000}, + {0x3b788000}, {0x3b78a000}, {0x3b78c000}, {0x3b78e000}, + {0x3b790000}, {0x3b792000}, {0x3b794000}, {0x3b796000}, + {0x3b798000}, {0x3b79a000}, {0x3b79c000}, {0x3b79e000}, + {0x3b7a0000}, {0x3b7a2000}, {0x3b7a4000}, {0x3b7a6000}, + {0x3b7a8000}, {0x3b7aa000}, {0x3b7ac000}, {0x3b7ae000}, + {0x3b7b0000}, {0x3b7b2000}, {0x3b7b4000}, {0x3b7b6000}, + {0x3b7b8000}, {0x3b7ba000}, {0x3b7bc000}, {0x3b7be000}, + {0x3b7c0000}, {0x3b7c2000}, {0x3b7c4000}, {0x3b7c6000}, + {0x3b7c8000}, {0x3b7ca000}, {0x3b7cc000}, {0x3b7ce000}, + {0x3b7d0000}, {0x3b7d2000}, {0x3b7d4000}, {0x3b7d6000}, + {0x3b7d8000}, {0x3b7da000}, {0x3b7dc000}, {0x3b7de000}, + {0x3b7e0000}, {0x3b7e2000}, {0x3b7e4000}, {0x3b7e6000}, + {0x3b7e8000}, {0x3b7ea000}, {0x3b7ec000}, {0x3b7ee000}, + {0x3b7f0000}, {0x3b7f2000}, {0x3b7f4000}, {0x3b7f6000}, + {0x3b7f8000}, {0x3b7fa000}, {0x3b7fc000}, {0x3b7fe000}, + {0x3b800000}, {0x3b802000}, {0x3b804000}, {0x3b806000}, + {0x3b808000}, {0x3b80a000}, {0x3b80c000}, {0x3b80e000}, + {0x3b810000}, {0x3b812000}, {0x3b814000}, {0x3b816000}, + {0x3b818000}, {0x3b81a000}, {0x3b81c000}, {0x3b81e000}, + {0x3b820000}, {0x3b822000}, {0x3b824000}, {0x3b826000}, + {0x3b828000}, {0x3b82a000}, {0x3b82c000}, {0x3b82e000}, + {0x3b830000}, {0x3b832000}, {0x3b834000}, {0x3b836000}, + {0x3b838000}, {0x3b83a000}, {0x3b83c000}, {0x3b83e000}, + {0x3b840000}, {0x3b842000}, {0x3b844000}, {0x3b846000}, + {0x3b848000}, {0x3b84a000}, {0x3b84c000}, {0x3b84e000}, + {0x3b850000}, {0x3b852000}, {0x3b854000}, {0x3b856000}, + {0x3b858000}, {0x3b85a000}, {0x3b85c000}, {0x3b85e000}, + {0x3b860000}, {0x3b862000}, {0x3b864000}, {0x3b866000}, + {0x3b868000}, {0x3b86a000}, {0x3b86c000}, {0x3b86e000}, + {0x3b870000}, {0x3b872000}, {0x3b874000}, {0x3b876000}, + {0x3b878000}, {0x3b87a000}, {0x3b87c000}, {0x3b87e000}, + {0x3b880000}, {0x3b882000}, {0x3b884000}, {0x3b886000}, + {0x3b888000}, {0x3b88a000}, {0x3b88c000}, {0x3b88e000}, + {0x3b890000}, {0x3b892000}, {0x3b894000}, {0x3b896000}, + {0x3b898000}, {0x3b89a000}, {0x3b89c000}, {0x3b89e000}, + {0x3b8a0000}, {0x3b8a2000}, {0x3b8a4000}, {0x3b8a6000}, + {0x3b8a8000}, {0x3b8aa000}, {0x3b8ac000}, {0x3b8ae000}, + {0x3b8b0000}, {0x3b8b2000}, {0x3b8b4000}, {0x3b8b6000}, + {0x3b8b8000}, {0x3b8ba000}, {0x3b8bc000}, {0x3b8be000}, + {0x3b8c0000}, {0x3b8c2000}, {0x3b8c4000}, {0x3b8c6000}, + {0x3b8c8000}, {0x3b8ca000}, {0x3b8cc000}, {0x3b8ce000}, + {0x3b8d0000}, {0x3b8d2000}, {0x3b8d4000}, {0x3b8d6000}, + {0x3b8d8000}, {0x3b8da000}, {0x3b8dc000}, {0x3b8de000}, + {0x3b8e0000}, {0x3b8e2000}, {0x3b8e4000}, {0x3b8e6000}, + {0x3b8e8000}, {0x3b8ea000}, {0x3b8ec000}, {0x3b8ee000}, + {0x3b8f0000}, {0x3b8f2000}, {0x3b8f4000}, {0x3b8f6000}, + {0x3b8f8000}, {0x3b8fa000}, {0x3b8fc000}, {0x3b8fe000}, + {0x3b900000}, {0x3b902000}, {0x3b904000}, {0x3b906000}, + {0x3b908000}, {0x3b90a000}, {0x3b90c000}, {0x3b90e000}, + {0x3b910000}, {0x3b912000}, {0x3b914000}, {0x3b916000}, + {0x3b918000}, {0x3b91a000}, {0x3b91c000}, {0x3b91e000}, + {0x3b920000}, {0x3b922000}, {0x3b924000}, {0x3b926000}, + {0x3b928000}, {0x3b92a000}, {0x3b92c000}, {0x3b92e000}, + {0x3b930000}, {0x3b932000}, {0x3b934000}, {0x3b936000}, + {0x3b938000}, {0x3b93a000}, {0x3b93c000}, {0x3b93e000}, + {0x3b940000}, {0x3b942000}, {0x3b944000}, {0x3b946000}, + {0x3b948000}, {0x3b94a000}, {0x3b94c000}, {0x3b94e000}, + {0x3b950000}, {0x3b952000}, {0x3b954000}, {0x3b956000}, + {0x3b958000}, {0x3b95a000}, {0x3b95c000}, {0x3b95e000}, + {0x3b960000}, {0x3b962000}, {0x3b964000}, {0x3b966000}, + {0x3b968000}, {0x3b96a000}, {0x3b96c000}, {0x3b96e000}, + {0x3b970000}, {0x3b972000}, {0x3b974000}, {0x3b976000}, + {0x3b978000}, {0x3b97a000}, {0x3b97c000}, {0x3b97e000}, + {0x3b980000}, {0x3b982000}, {0x3b984000}, {0x3b986000}, + {0x3b988000}, {0x3b98a000}, {0x3b98c000}, {0x3b98e000}, + {0x3b990000}, {0x3b992000}, {0x3b994000}, {0x3b996000}, + {0x3b998000}, {0x3b99a000}, {0x3b99c000}, {0x3b99e000}, + {0x3b9a0000}, {0x3b9a2000}, {0x3b9a4000}, {0x3b9a6000}, + {0x3b9a8000}, {0x3b9aa000}, {0x3b9ac000}, {0x3b9ae000}, + {0x3b9b0000}, {0x3b9b2000}, {0x3b9b4000}, {0x3b9b6000}, + {0x3b9b8000}, {0x3b9ba000}, {0x3b9bc000}, {0x3b9be000}, + {0x3b9c0000}, {0x3b9c2000}, {0x3b9c4000}, {0x3b9c6000}, + {0x3b9c8000}, {0x3b9ca000}, {0x3b9cc000}, {0x3b9ce000}, + {0x3b9d0000}, {0x3b9d2000}, {0x3b9d4000}, {0x3b9d6000}, + {0x3b9d8000}, {0x3b9da000}, {0x3b9dc000}, {0x3b9de000}, + {0x3b9e0000}, {0x3b9e2000}, {0x3b9e4000}, {0x3b9e6000}, + {0x3b9e8000}, {0x3b9ea000}, {0x3b9ec000}, {0x3b9ee000}, + {0x3b9f0000}, {0x3b9f2000}, {0x3b9f4000}, {0x3b9f6000}, + {0x3b9f8000}, {0x3b9fa000}, {0x3b9fc000}, {0x3b9fe000}, + {0x3ba00000}, {0x3ba02000}, {0x3ba04000}, {0x3ba06000}, + {0x3ba08000}, {0x3ba0a000}, {0x3ba0c000}, {0x3ba0e000}, + {0x3ba10000}, {0x3ba12000}, {0x3ba14000}, {0x3ba16000}, + {0x3ba18000}, {0x3ba1a000}, {0x3ba1c000}, {0x3ba1e000}, + {0x3ba20000}, {0x3ba22000}, {0x3ba24000}, {0x3ba26000}, + {0x3ba28000}, {0x3ba2a000}, {0x3ba2c000}, {0x3ba2e000}, + {0x3ba30000}, {0x3ba32000}, {0x3ba34000}, {0x3ba36000}, + {0x3ba38000}, {0x3ba3a000}, {0x3ba3c000}, {0x3ba3e000}, + {0x3ba40000}, {0x3ba42000}, {0x3ba44000}, {0x3ba46000}, + {0x3ba48000}, {0x3ba4a000}, {0x3ba4c000}, {0x3ba4e000}, + {0x3ba50000}, {0x3ba52000}, {0x3ba54000}, {0x3ba56000}, + {0x3ba58000}, {0x3ba5a000}, {0x3ba5c000}, {0x3ba5e000}, + {0x3ba60000}, {0x3ba62000}, {0x3ba64000}, {0x3ba66000}, + {0x3ba68000}, {0x3ba6a000}, {0x3ba6c000}, {0x3ba6e000}, + {0x3ba70000}, {0x3ba72000}, {0x3ba74000}, {0x3ba76000}, + {0x3ba78000}, {0x3ba7a000}, {0x3ba7c000}, {0x3ba7e000}, + {0x3ba80000}, {0x3ba82000}, {0x3ba84000}, {0x3ba86000}, + {0x3ba88000}, {0x3ba8a000}, {0x3ba8c000}, {0x3ba8e000}, + {0x3ba90000}, {0x3ba92000}, {0x3ba94000}, {0x3ba96000}, + {0x3ba98000}, {0x3ba9a000}, {0x3ba9c000}, {0x3ba9e000}, + {0x3baa0000}, {0x3baa2000}, {0x3baa4000}, {0x3baa6000}, + {0x3baa8000}, {0x3baaa000}, {0x3baac000}, {0x3baae000}, + {0x3bab0000}, {0x3bab2000}, {0x3bab4000}, {0x3bab6000}, + {0x3bab8000}, {0x3baba000}, {0x3babc000}, {0x3babe000}, + {0x3bac0000}, {0x3bac2000}, {0x3bac4000}, {0x3bac6000}, + {0x3bac8000}, {0x3baca000}, {0x3bacc000}, {0x3bace000}, + {0x3bad0000}, {0x3bad2000}, {0x3bad4000}, {0x3bad6000}, + {0x3bad8000}, {0x3bada000}, {0x3badc000}, {0x3bade000}, + {0x3bae0000}, {0x3bae2000}, {0x3bae4000}, {0x3bae6000}, + {0x3bae8000}, {0x3baea000}, {0x3baec000}, {0x3baee000}, + {0x3baf0000}, {0x3baf2000}, {0x3baf4000}, {0x3baf6000}, + {0x3baf8000}, {0x3bafa000}, {0x3bafc000}, {0x3bafe000}, + {0x3bb00000}, {0x3bb02000}, {0x3bb04000}, {0x3bb06000}, + {0x3bb08000}, {0x3bb0a000}, {0x3bb0c000}, {0x3bb0e000}, + {0x3bb10000}, {0x3bb12000}, {0x3bb14000}, {0x3bb16000}, + {0x3bb18000}, {0x3bb1a000}, {0x3bb1c000}, {0x3bb1e000}, + {0x3bb20000}, {0x3bb22000}, {0x3bb24000}, {0x3bb26000}, + {0x3bb28000}, {0x3bb2a000}, {0x3bb2c000}, {0x3bb2e000}, + {0x3bb30000}, {0x3bb32000}, {0x3bb34000}, {0x3bb36000}, + {0x3bb38000}, {0x3bb3a000}, {0x3bb3c000}, {0x3bb3e000}, + {0x3bb40000}, {0x3bb42000}, {0x3bb44000}, {0x3bb46000}, + {0x3bb48000}, {0x3bb4a000}, {0x3bb4c000}, {0x3bb4e000}, + {0x3bb50000}, {0x3bb52000}, {0x3bb54000}, {0x3bb56000}, + {0x3bb58000}, {0x3bb5a000}, {0x3bb5c000}, {0x3bb5e000}, + {0x3bb60000}, {0x3bb62000}, {0x3bb64000}, {0x3bb66000}, + {0x3bb68000}, {0x3bb6a000}, {0x3bb6c000}, {0x3bb6e000}, + {0x3bb70000}, {0x3bb72000}, {0x3bb74000}, {0x3bb76000}, + {0x3bb78000}, {0x3bb7a000}, {0x3bb7c000}, {0x3bb7e000}, + {0x3bb80000}, {0x3bb82000}, {0x3bb84000}, {0x3bb86000}, + {0x3bb88000}, {0x3bb8a000}, {0x3bb8c000}, {0x3bb8e000}, + {0x3bb90000}, {0x3bb92000}, {0x3bb94000}, {0x3bb96000}, + {0x3bb98000}, {0x3bb9a000}, {0x3bb9c000}, {0x3bb9e000}, + {0x3bba0000}, {0x3bba2000}, {0x3bba4000}, {0x3bba6000}, + {0x3bba8000}, {0x3bbaa000}, {0x3bbac000}, {0x3bbae000}, + {0x3bbb0000}, {0x3bbb2000}, {0x3bbb4000}, {0x3bbb6000}, + {0x3bbb8000}, {0x3bbba000}, {0x3bbbc000}, {0x3bbbe000}, + {0x3bbc0000}, {0x3bbc2000}, {0x3bbc4000}, {0x3bbc6000}, + {0x3bbc8000}, {0x3bbca000}, {0x3bbcc000}, {0x3bbce000}, + {0x3bbd0000}, {0x3bbd2000}, {0x3bbd4000}, {0x3bbd6000}, + {0x3bbd8000}, {0x3bbda000}, {0x3bbdc000}, {0x3bbde000}, + {0x3bbe0000}, {0x3bbe2000}, {0x3bbe4000}, {0x3bbe6000}, + {0x3bbe8000}, {0x3bbea000}, {0x3bbec000}, {0x3bbee000}, + {0x3bbf0000}, {0x3bbf2000}, {0x3bbf4000}, {0x3bbf6000}, + {0x3bbf8000}, {0x3bbfa000}, {0x3bbfc000}, {0x3bbfe000}, + {0x3bc00000}, {0x3bc02000}, {0x3bc04000}, {0x3bc06000}, + {0x3bc08000}, {0x3bc0a000}, {0x3bc0c000}, {0x3bc0e000}, + {0x3bc10000}, {0x3bc12000}, {0x3bc14000}, {0x3bc16000}, + {0x3bc18000}, {0x3bc1a000}, {0x3bc1c000}, {0x3bc1e000}, + {0x3bc20000}, {0x3bc22000}, {0x3bc24000}, {0x3bc26000}, + {0x3bc28000}, {0x3bc2a000}, {0x3bc2c000}, {0x3bc2e000}, + {0x3bc30000}, {0x3bc32000}, {0x3bc34000}, {0x3bc36000}, + {0x3bc38000}, {0x3bc3a000}, {0x3bc3c000}, {0x3bc3e000}, + {0x3bc40000}, {0x3bc42000}, {0x3bc44000}, {0x3bc46000}, + {0x3bc48000}, {0x3bc4a000}, {0x3bc4c000}, {0x3bc4e000}, + {0x3bc50000}, {0x3bc52000}, {0x3bc54000}, {0x3bc56000}, + {0x3bc58000}, {0x3bc5a000}, {0x3bc5c000}, {0x3bc5e000}, + {0x3bc60000}, {0x3bc62000}, {0x3bc64000}, {0x3bc66000}, + {0x3bc68000}, {0x3bc6a000}, {0x3bc6c000}, {0x3bc6e000}, + {0x3bc70000}, {0x3bc72000}, {0x3bc74000}, {0x3bc76000}, + {0x3bc78000}, {0x3bc7a000}, {0x3bc7c000}, {0x3bc7e000}, + {0x3bc80000}, {0x3bc82000}, {0x3bc84000}, {0x3bc86000}, + {0x3bc88000}, {0x3bc8a000}, {0x3bc8c000}, {0x3bc8e000}, + {0x3bc90000}, {0x3bc92000}, {0x3bc94000}, {0x3bc96000}, + {0x3bc98000}, {0x3bc9a000}, {0x3bc9c000}, {0x3bc9e000}, + {0x3bca0000}, {0x3bca2000}, {0x3bca4000}, {0x3bca6000}, + {0x3bca8000}, {0x3bcaa000}, {0x3bcac000}, {0x3bcae000}, + {0x3bcb0000}, {0x3bcb2000}, {0x3bcb4000}, {0x3bcb6000}, + {0x3bcb8000}, {0x3bcba000}, {0x3bcbc000}, {0x3bcbe000}, + {0x3bcc0000}, {0x3bcc2000}, {0x3bcc4000}, {0x3bcc6000}, + {0x3bcc8000}, {0x3bcca000}, {0x3bccc000}, {0x3bcce000}, + {0x3bcd0000}, {0x3bcd2000}, {0x3bcd4000}, {0x3bcd6000}, + {0x3bcd8000}, {0x3bcda000}, {0x3bcdc000}, {0x3bcde000}, + {0x3bce0000}, {0x3bce2000}, {0x3bce4000}, {0x3bce6000}, + {0x3bce8000}, {0x3bcea000}, {0x3bcec000}, {0x3bcee000}, + {0x3bcf0000}, {0x3bcf2000}, {0x3bcf4000}, {0x3bcf6000}, + {0x3bcf8000}, {0x3bcfa000}, {0x3bcfc000}, {0x3bcfe000}, + {0x3bd00000}, {0x3bd02000}, {0x3bd04000}, {0x3bd06000}, + {0x3bd08000}, {0x3bd0a000}, {0x3bd0c000}, {0x3bd0e000}, + {0x3bd10000}, {0x3bd12000}, {0x3bd14000}, {0x3bd16000}, + {0x3bd18000}, {0x3bd1a000}, {0x3bd1c000}, {0x3bd1e000}, + {0x3bd20000}, {0x3bd22000}, {0x3bd24000}, {0x3bd26000}, + {0x3bd28000}, {0x3bd2a000}, {0x3bd2c000}, {0x3bd2e000}, + {0x3bd30000}, {0x3bd32000}, {0x3bd34000}, {0x3bd36000}, + {0x3bd38000}, {0x3bd3a000}, {0x3bd3c000}, {0x3bd3e000}, + {0x3bd40000}, {0x3bd42000}, {0x3bd44000}, {0x3bd46000}, + {0x3bd48000}, {0x3bd4a000}, {0x3bd4c000}, {0x3bd4e000}, + {0x3bd50000}, {0x3bd52000}, {0x3bd54000}, {0x3bd56000}, + {0x3bd58000}, {0x3bd5a000}, {0x3bd5c000}, {0x3bd5e000}, + {0x3bd60000}, {0x3bd62000}, {0x3bd64000}, {0x3bd66000}, + {0x3bd68000}, {0x3bd6a000}, {0x3bd6c000}, {0x3bd6e000}, + {0x3bd70000}, {0x3bd72000}, {0x3bd74000}, {0x3bd76000}, + {0x3bd78000}, {0x3bd7a000}, {0x3bd7c000}, {0x3bd7e000}, + {0x3bd80000}, {0x3bd82000}, {0x3bd84000}, {0x3bd86000}, + {0x3bd88000}, {0x3bd8a000}, {0x3bd8c000}, {0x3bd8e000}, + {0x3bd90000}, {0x3bd92000}, {0x3bd94000}, {0x3bd96000}, + {0x3bd98000}, {0x3bd9a000}, {0x3bd9c000}, {0x3bd9e000}, + {0x3bda0000}, {0x3bda2000}, {0x3bda4000}, {0x3bda6000}, + {0x3bda8000}, {0x3bdaa000}, {0x3bdac000}, {0x3bdae000}, + {0x3bdb0000}, {0x3bdb2000}, {0x3bdb4000}, {0x3bdb6000}, + {0x3bdb8000}, {0x3bdba000}, {0x3bdbc000}, {0x3bdbe000}, + {0x3bdc0000}, {0x3bdc2000}, {0x3bdc4000}, {0x3bdc6000}, + {0x3bdc8000}, {0x3bdca000}, {0x3bdcc000}, {0x3bdce000}, + {0x3bdd0000}, {0x3bdd2000}, {0x3bdd4000}, {0x3bdd6000}, + {0x3bdd8000}, {0x3bdda000}, {0x3bddc000}, {0x3bdde000}, + {0x3bde0000}, {0x3bde2000}, {0x3bde4000}, {0x3bde6000}, + {0x3bde8000}, {0x3bdea000}, {0x3bdec000}, {0x3bdee000}, + {0x3bdf0000}, {0x3bdf2000}, {0x3bdf4000}, {0x3bdf6000}, + {0x3bdf8000}, {0x3bdfa000}, {0x3bdfc000}, {0x3bdfe000}, + {0x3be00000}, {0x3be02000}, {0x3be04000}, {0x3be06000}, + {0x3be08000}, {0x3be0a000}, {0x3be0c000}, {0x3be0e000}, + {0x3be10000}, {0x3be12000}, {0x3be14000}, {0x3be16000}, + {0x3be18000}, {0x3be1a000}, {0x3be1c000}, {0x3be1e000}, + {0x3be20000}, {0x3be22000}, {0x3be24000}, {0x3be26000}, + {0x3be28000}, {0x3be2a000}, {0x3be2c000}, {0x3be2e000}, + {0x3be30000}, {0x3be32000}, {0x3be34000}, {0x3be36000}, + {0x3be38000}, {0x3be3a000}, {0x3be3c000}, {0x3be3e000}, + {0x3be40000}, {0x3be42000}, {0x3be44000}, {0x3be46000}, + {0x3be48000}, {0x3be4a000}, {0x3be4c000}, {0x3be4e000}, + {0x3be50000}, {0x3be52000}, {0x3be54000}, {0x3be56000}, + {0x3be58000}, {0x3be5a000}, {0x3be5c000}, {0x3be5e000}, + {0x3be60000}, {0x3be62000}, {0x3be64000}, {0x3be66000}, + {0x3be68000}, {0x3be6a000}, {0x3be6c000}, {0x3be6e000}, + {0x3be70000}, {0x3be72000}, {0x3be74000}, {0x3be76000}, + {0x3be78000}, {0x3be7a000}, {0x3be7c000}, {0x3be7e000}, + {0x3be80000}, {0x3be82000}, {0x3be84000}, {0x3be86000}, + {0x3be88000}, {0x3be8a000}, {0x3be8c000}, {0x3be8e000}, + {0x3be90000}, {0x3be92000}, {0x3be94000}, {0x3be96000}, + {0x3be98000}, {0x3be9a000}, {0x3be9c000}, {0x3be9e000}, + {0x3bea0000}, {0x3bea2000}, {0x3bea4000}, {0x3bea6000}, + {0x3bea8000}, {0x3beaa000}, {0x3beac000}, {0x3beae000}, + {0x3beb0000}, {0x3beb2000}, {0x3beb4000}, {0x3beb6000}, + {0x3beb8000}, {0x3beba000}, {0x3bebc000}, {0x3bebe000}, + {0x3bec0000}, {0x3bec2000}, {0x3bec4000}, {0x3bec6000}, + {0x3bec8000}, {0x3beca000}, {0x3becc000}, {0x3bece000}, + {0x3bed0000}, {0x3bed2000}, {0x3bed4000}, {0x3bed6000}, + {0x3bed8000}, {0x3beda000}, {0x3bedc000}, {0x3bede000}, + {0x3bee0000}, {0x3bee2000}, {0x3bee4000}, {0x3bee6000}, + {0x3bee8000}, {0x3beea000}, {0x3beec000}, {0x3beee000}, + {0x3bef0000}, {0x3bef2000}, {0x3bef4000}, {0x3bef6000}, + {0x3bef8000}, {0x3befa000}, {0x3befc000}, {0x3befe000}, + {0x3bf00000}, {0x3bf02000}, {0x3bf04000}, {0x3bf06000}, + {0x3bf08000}, {0x3bf0a000}, {0x3bf0c000}, {0x3bf0e000}, + {0x3bf10000}, {0x3bf12000}, {0x3bf14000}, {0x3bf16000}, + {0x3bf18000}, {0x3bf1a000}, {0x3bf1c000}, {0x3bf1e000}, + {0x3bf20000}, {0x3bf22000}, {0x3bf24000}, {0x3bf26000}, + {0x3bf28000}, {0x3bf2a000}, {0x3bf2c000}, {0x3bf2e000}, + {0x3bf30000}, {0x3bf32000}, {0x3bf34000}, {0x3bf36000}, + {0x3bf38000}, {0x3bf3a000}, {0x3bf3c000}, {0x3bf3e000}, + {0x3bf40000}, {0x3bf42000}, {0x3bf44000}, {0x3bf46000}, + {0x3bf48000}, {0x3bf4a000}, {0x3bf4c000}, {0x3bf4e000}, + {0x3bf50000}, {0x3bf52000}, {0x3bf54000}, {0x3bf56000}, + {0x3bf58000}, {0x3bf5a000}, {0x3bf5c000}, {0x3bf5e000}, + {0x3bf60000}, {0x3bf62000}, {0x3bf64000}, {0x3bf66000}, + {0x3bf68000}, {0x3bf6a000}, {0x3bf6c000}, {0x3bf6e000}, + {0x3bf70000}, {0x3bf72000}, {0x3bf74000}, {0x3bf76000}, + {0x3bf78000}, {0x3bf7a000}, {0x3bf7c000}, {0x3bf7e000}, + {0x3bf80000}, {0x3bf82000}, {0x3bf84000}, {0x3bf86000}, + {0x3bf88000}, {0x3bf8a000}, {0x3bf8c000}, {0x3bf8e000}, + {0x3bf90000}, {0x3bf92000}, {0x3bf94000}, {0x3bf96000}, + {0x3bf98000}, {0x3bf9a000}, {0x3bf9c000}, {0x3bf9e000}, + {0x3bfa0000}, {0x3bfa2000}, {0x3bfa4000}, {0x3bfa6000}, + {0x3bfa8000}, {0x3bfaa000}, {0x3bfac000}, {0x3bfae000}, + {0x3bfb0000}, {0x3bfb2000}, {0x3bfb4000}, {0x3bfb6000}, + {0x3bfb8000}, {0x3bfba000}, {0x3bfbc000}, {0x3bfbe000}, + {0x3bfc0000}, {0x3bfc2000}, {0x3bfc4000}, {0x3bfc6000}, + {0x3bfc8000}, {0x3bfca000}, {0x3bfcc000}, {0x3bfce000}, + {0x3bfd0000}, {0x3bfd2000}, {0x3bfd4000}, {0x3bfd6000}, + {0x3bfd8000}, {0x3bfda000}, {0x3bfdc000}, {0x3bfde000}, + {0x3bfe0000}, {0x3bfe2000}, {0x3bfe4000}, {0x3bfe6000}, + {0x3bfe8000}, {0x3bfea000}, {0x3bfec000}, {0x3bfee000}, + {0x3bff0000}, {0x3bff2000}, {0x3bff4000}, {0x3bff6000}, + {0x3bff8000}, {0x3bffa000}, {0x3bffc000}, {0x3bffe000}, + {0x3c000000}, {0x3c002000}, {0x3c004000}, {0x3c006000}, + {0x3c008000}, {0x3c00a000}, {0x3c00c000}, {0x3c00e000}, + {0x3c010000}, {0x3c012000}, {0x3c014000}, {0x3c016000}, + {0x3c018000}, {0x3c01a000}, {0x3c01c000}, {0x3c01e000}, + {0x3c020000}, {0x3c022000}, {0x3c024000}, {0x3c026000}, + {0x3c028000}, {0x3c02a000}, {0x3c02c000}, {0x3c02e000}, + {0x3c030000}, {0x3c032000}, {0x3c034000}, {0x3c036000}, + {0x3c038000}, {0x3c03a000}, {0x3c03c000}, {0x3c03e000}, + {0x3c040000}, {0x3c042000}, {0x3c044000}, {0x3c046000}, + {0x3c048000}, {0x3c04a000}, {0x3c04c000}, {0x3c04e000}, + {0x3c050000}, {0x3c052000}, {0x3c054000}, {0x3c056000}, + {0x3c058000}, {0x3c05a000}, {0x3c05c000}, {0x3c05e000}, + {0x3c060000}, {0x3c062000}, {0x3c064000}, {0x3c066000}, + {0x3c068000}, {0x3c06a000}, {0x3c06c000}, {0x3c06e000}, + {0x3c070000}, {0x3c072000}, {0x3c074000}, {0x3c076000}, + {0x3c078000}, {0x3c07a000}, {0x3c07c000}, {0x3c07e000}, + {0x3c080000}, {0x3c082000}, {0x3c084000}, {0x3c086000}, + {0x3c088000}, {0x3c08a000}, {0x3c08c000}, {0x3c08e000}, + {0x3c090000}, {0x3c092000}, {0x3c094000}, {0x3c096000}, + {0x3c098000}, {0x3c09a000}, {0x3c09c000}, {0x3c09e000}, + {0x3c0a0000}, {0x3c0a2000}, {0x3c0a4000}, {0x3c0a6000}, + {0x3c0a8000}, {0x3c0aa000}, {0x3c0ac000}, {0x3c0ae000}, + {0x3c0b0000}, {0x3c0b2000}, {0x3c0b4000}, {0x3c0b6000}, + {0x3c0b8000}, {0x3c0ba000}, {0x3c0bc000}, {0x3c0be000}, + {0x3c0c0000}, {0x3c0c2000}, {0x3c0c4000}, {0x3c0c6000}, + {0x3c0c8000}, {0x3c0ca000}, {0x3c0cc000}, {0x3c0ce000}, + {0x3c0d0000}, {0x3c0d2000}, {0x3c0d4000}, {0x3c0d6000}, + {0x3c0d8000}, {0x3c0da000}, {0x3c0dc000}, {0x3c0de000}, + {0x3c0e0000}, {0x3c0e2000}, {0x3c0e4000}, {0x3c0e6000}, + {0x3c0e8000}, {0x3c0ea000}, {0x3c0ec000}, {0x3c0ee000}, + {0x3c0f0000}, {0x3c0f2000}, {0x3c0f4000}, {0x3c0f6000}, + {0x3c0f8000}, {0x3c0fa000}, {0x3c0fc000}, {0x3c0fe000}, + {0x3c100000}, {0x3c102000}, {0x3c104000}, {0x3c106000}, + {0x3c108000}, {0x3c10a000}, {0x3c10c000}, {0x3c10e000}, + {0x3c110000}, {0x3c112000}, {0x3c114000}, {0x3c116000}, + {0x3c118000}, {0x3c11a000}, {0x3c11c000}, {0x3c11e000}, + {0x3c120000}, {0x3c122000}, {0x3c124000}, {0x3c126000}, + {0x3c128000}, {0x3c12a000}, {0x3c12c000}, {0x3c12e000}, + {0x3c130000}, {0x3c132000}, {0x3c134000}, {0x3c136000}, + {0x3c138000}, {0x3c13a000}, {0x3c13c000}, {0x3c13e000}, + {0x3c140000}, {0x3c142000}, {0x3c144000}, {0x3c146000}, + {0x3c148000}, {0x3c14a000}, {0x3c14c000}, {0x3c14e000}, + {0x3c150000}, {0x3c152000}, {0x3c154000}, {0x3c156000}, + {0x3c158000}, {0x3c15a000}, {0x3c15c000}, {0x3c15e000}, + {0x3c160000}, {0x3c162000}, {0x3c164000}, {0x3c166000}, + {0x3c168000}, {0x3c16a000}, {0x3c16c000}, {0x3c16e000}, + {0x3c170000}, {0x3c172000}, {0x3c174000}, {0x3c176000}, + {0x3c178000}, {0x3c17a000}, {0x3c17c000}, {0x3c17e000}, + {0x3c180000}, {0x3c182000}, {0x3c184000}, {0x3c186000}, + {0x3c188000}, {0x3c18a000}, {0x3c18c000}, {0x3c18e000}, + {0x3c190000}, {0x3c192000}, {0x3c194000}, {0x3c196000}, + {0x3c198000}, {0x3c19a000}, {0x3c19c000}, {0x3c19e000}, + {0x3c1a0000}, {0x3c1a2000}, {0x3c1a4000}, {0x3c1a6000}, + {0x3c1a8000}, {0x3c1aa000}, {0x3c1ac000}, {0x3c1ae000}, + {0x3c1b0000}, {0x3c1b2000}, {0x3c1b4000}, {0x3c1b6000}, + {0x3c1b8000}, {0x3c1ba000}, {0x3c1bc000}, {0x3c1be000}, + {0x3c1c0000}, {0x3c1c2000}, {0x3c1c4000}, {0x3c1c6000}, + {0x3c1c8000}, {0x3c1ca000}, {0x3c1cc000}, {0x3c1ce000}, + {0x3c1d0000}, {0x3c1d2000}, {0x3c1d4000}, {0x3c1d6000}, + {0x3c1d8000}, {0x3c1da000}, {0x3c1dc000}, {0x3c1de000}, + {0x3c1e0000}, {0x3c1e2000}, {0x3c1e4000}, {0x3c1e6000}, + {0x3c1e8000}, {0x3c1ea000}, {0x3c1ec000}, {0x3c1ee000}, + {0x3c1f0000}, {0x3c1f2000}, {0x3c1f4000}, {0x3c1f6000}, + {0x3c1f8000}, {0x3c1fa000}, {0x3c1fc000}, {0x3c1fe000}, + {0x3c200000}, {0x3c202000}, {0x3c204000}, {0x3c206000}, + {0x3c208000}, {0x3c20a000}, {0x3c20c000}, {0x3c20e000}, + {0x3c210000}, {0x3c212000}, {0x3c214000}, {0x3c216000}, + {0x3c218000}, {0x3c21a000}, {0x3c21c000}, {0x3c21e000}, + {0x3c220000}, {0x3c222000}, {0x3c224000}, {0x3c226000}, + {0x3c228000}, {0x3c22a000}, {0x3c22c000}, {0x3c22e000}, + {0x3c230000}, {0x3c232000}, {0x3c234000}, {0x3c236000}, + {0x3c238000}, {0x3c23a000}, {0x3c23c000}, {0x3c23e000}, + {0x3c240000}, {0x3c242000}, {0x3c244000}, {0x3c246000}, + {0x3c248000}, {0x3c24a000}, {0x3c24c000}, {0x3c24e000}, + {0x3c250000}, {0x3c252000}, {0x3c254000}, {0x3c256000}, + {0x3c258000}, {0x3c25a000}, {0x3c25c000}, {0x3c25e000}, + {0x3c260000}, {0x3c262000}, {0x3c264000}, {0x3c266000}, + {0x3c268000}, {0x3c26a000}, {0x3c26c000}, {0x3c26e000}, + {0x3c270000}, {0x3c272000}, {0x3c274000}, {0x3c276000}, + {0x3c278000}, {0x3c27a000}, {0x3c27c000}, {0x3c27e000}, + {0x3c280000}, {0x3c282000}, {0x3c284000}, {0x3c286000}, + {0x3c288000}, {0x3c28a000}, {0x3c28c000}, {0x3c28e000}, + {0x3c290000}, {0x3c292000}, {0x3c294000}, {0x3c296000}, + {0x3c298000}, {0x3c29a000}, {0x3c29c000}, {0x3c29e000}, + {0x3c2a0000}, {0x3c2a2000}, {0x3c2a4000}, {0x3c2a6000}, + {0x3c2a8000}, {0x3c2aa000}, {0x3c2ac000}, {0x3c2ae000}, + {0x3c2b0000}, {0x3c2b2000}, {0x3c2b4000}, {0x3c2b6000}, + {0x3c2b8000}, {0x3c2ba000}, {0x3c2bc000}, {0x3c2be000}, + {0x3c2c0000}, {0x3c2c2000}, {0x3c2c4000}, {0x3c2c6000}, + {0x3c2c8000}, {0x3c2ca000}, {0x3c2cc000}, {0x3c2ce000}, + {0x3c2d0000}, {0x3c2d2000}, {0x3c2d4000}, {0x3c2d6000}, + {0x3c2d8000}, {0x3c2da000}, {0x3c2dc000}, {0x3c2de000}, + {0x3c2e0000}, {0x3c2e2000}, {0x3c2e4000}, {0x3c2e6000}, + {0x3c2e8000}, {0x3c2ea000}, {0x3c2ec000}, {0x3c2ee000}, + {0x3c2f0000}, {0x3c2f2000}, {0x3c2f4000}, {0x3c2f6000}, + {0x3c2f8000}, {0x3c2fa000}, {0x3c2fc000}, {0x3c2fe000}, + {0x3c300000}, {0x3c302000}, {0x3c304000}, {0x3c306000}, + {0x3c308000}, {0x3c30a000}, {0x3c30c000}, {0x3c30e000}, + {0x3c310000}, {0x3c312000}, {0x3c314000}, {0x3c316000}, + {0x3c318000}, {0x3c31a000}, {0x3c31c000}, {0x3c31e000}, + {0x3c320000}, {0x3c322000}, {0x3c324000}, {0x3c326000}, + {0x3c328000}, {0x3c32a000}, {0x3c32c000}, {0x3c32e000}, + {0x3c330000}, {0x3c332000}, {0x3c334000}, {0x3c336000}, + {0x3c338000}, {0x3c33a000}, {0x3c33c000}, {0x3c33e000}, + {0x3c340000}, {0x3c342000}, {0x3c344000}, {0x3c346000}, + {0x3c348000}, {0x3c34a000}, {0x3c34c000}, {0x3c34e000}, + {0x3c350000}, {0x3c352000}, {0x3c354000}, {0x3c356000}, + {0x3c358000}, {0x3c35a000}, {0x3c35c000}, {0x3c35e000}, + {0x3c360000}, {0x3c362000}, {0x3c364000}, {0x3c366000}, + {0x3c368000}, {0x3c36a000}, {0x3c36c000}, {0x3c36e000}, + {0x3c370000}, {0x3c372000}, {0x3c374000}, {0x3c376000}, + {0x3c378000}, {0x3c37a000}, {0x3c37c000}, {0x3c37e000}, + {0x3c380000}, {0x3c382000}, {0x3c384000}, {0x3c386000}, + {0x3c388000}, {0x3c38a000}, {0x3c38c000}, {0x3c38e000}, + {0x3c390000}, {0x3c392000}, {0x3c394000}, {0x3c396000}, + {0x3c398000}, {0x3c39a000}, {0x3c39c000}, {0x3c39e000}, + {0x3c3a0000}, {0x3c3a2000}, {0x3c3a4000}, {0x3c3a6000}, + {0x3c3a8000}, {0x3c3aa000}, {0x3c3ac000}, {0x3c3ae000}, + {0x3c3b0000}, {0x3c3b2000}, {0x3c3b4000}, {0x3c3b6000}, + {0x3c3b8000}, {0x3c3ba000}, {0x3c3bc000}, {0x3c3be000}, + {0x3c3c0000}, {0x3c3c2000}, {0x3c3c4000}, {0x3c3c6000}, + {0x3c3c8000}, {0x3c3ca000}, {0x3c3cc000}, {0x3c3ce000}, + {0x3c3d0000}, {0x3c3d2000}, {0x3c3d4000}, {0x3c3d6000}, + {0x3c3d8000}, {0x3c3da000}, {0x3c3dc000}, {0x3c3de000}, + {0x3c3e0000}, {0x3c3e2000}, {0x3c3e4000}, {0x3c3e6000}, + {0x3c3e8000}, {0x3c3ea000}, {0x3c3ec000}, {0x3c3ee000}, + {0x3c3f0000}, {0x3c3f2000}, {0x3c3f4000}, {0x3c3f6000}, + {0x3c3f8000}, {0x3c3fa000}, {0x3c3fc000}, {0x3c3fe000}, + {0x3c400000}, {0x3c402000}, {0x3c404000}, {0x3c406000}, + {0x3c408000}, {0x3c40a000}, {0x3c40c000}, {0x3c40e000}, + {0x3c410000}, {0x3c412000}, {0x3c414000}, {0x3c416000}, + {0x3c418000}, {0x3c41a000}, {0x3c41c000}, {0x3c41e000}, + {0x3c420000}, {0x3c422000}, {0x3c424000}, {0x3c426000}, + {0x3c428000}, {0x3c42a000}, {0x3c42c000}, {0x3c42e000}, + {0x3c430000}, {0x3c432000}, {0x3c434000}, {0x3c436000}, + {0x3c438000}, {0x3c43a000}, {0x3c43c000}, {0x3c43e000}, + {0x3c440000}, {0x3c442000}, {0x3c444000}, {0x3c446000}, + {0x3c448000}, {0x3c44a000}, {0x3c44c000}, {0x3c44e000}, + {0x3c450000}, {0x3c452000}, {0x3c454000}, {0x3c456000}, + {0x3c458000}, {0x3c45a000}, {0x3c45c000}, {0x3c45e000}, + {0x3c460000}, {0x3c462000}, {0x3c464000}, {0x3c466000}, + {0x3c468000}, {0x3c46a000}, {0x3c46c000}, {0x3c46e000}, + {0x3c470000}, {0x3c472000}, {0x3c474000}, {0x3c476000}, + {0x3c478000}, {0x3c47a000}, {0x3c47c000}, {0x3c47e000}, + {0x3c480000}, {0x3c482000}, {0x3c484000}, {0x3c486000}, + {0x3c488000}, {0x3c48a000}, {0x3c48c000}, {0x3c48e000}, + {0x3c490000}, {0x3c492000}, {0x3c494000}, {0x3c496000}, + {0x3c498000}, {0x3c49a000}, {0x3c49c000}, {0x3c49e000}, + {0x3c4a0000}, {0x3c4a2000}, {0x3c4a4000}, {0x3c4a6000}, + {0x3c4a8000}, {0x3c4aa000}, {0x3c4ac000}, {0x3c4ae000}, + {0x3c4b0000}, {0x3c4b2000}, {0x3c4b4000}, {0x3c4b6000}, + {0x3c4b8000}, {0x3c4ba000}, {0x3c4bc000}, {0x3c4be000}, + {0x3c4c0000}, {0x3c4c2000}, {0x3c4c4000}, {0x3c4c6000}, + {0x3c4c8000}, {0x3c4ca000}, {0x3c4cc000}, {0x3c4ce000}, + {0x3c4d0000}, {0x3c4d2000}, {0x3c4d4000}, {0x3c4d6000}, + {0x3c4d8000}, {0x3c4da000}, {0x3c4dc000}, {0x3c4de000}, + {0x3c4e0000}, {0x3c4e2000}, {0x3c4e4000}, {0x3c4e6000}, + {0x3c4e8000}, {0x3c4ea000}, {0x3c4ec000}, {0x3c4ee000}, + {0x3c4f0000}, {0x3c4f2000}, {0x3c4f4000}, {0x3c4f6000}, + {0x3c4f8000}, {0x3c4fa000}, {0x3c4fc000}, {0x3c4fe000}, + {0x3c500000}, {0x3c502000}, {0x3c504000}, {0x3c506000}, + {0x3c508000}, {0x3c50a000}, {0x3c50c000}, {0x3c50e000}, + {0x3c510000}, {0x3c512000}, {0x3c514000}, {0x3c516000}, + {0x3c518000}, {0x3c51a000}, {0x3c51c000}, {0x3c51e000}, + {0x3c520000}, {0x3c522000}, {0x3c524000}, {0x3c526000}, + {0x3c528000}, {0x3c52a000}, {0x3c52c000}, {0x3c52e000}, + {0x3c530000}, {0x3c532000}, {0x3c534000}, {0x3c536000}, + {0x3c538000}, {0x3c53a000}, {0x3c53c000}, {0x3c53e000}, + {0x3c540000}, {0x3c542000}, {0x3c544000}, {0x3c546000}, + {0x3c548000}, {0x3c54a000}, {0x3c54c000}, {0x3c54e000}, + {0x3c550000}, {0x3c552000}, {0x3c554000}, {0x3c556000}, + {0x3c558000}, {0x3c55a000}, {0x3c55c000}, {0x3c55e000}, + {0x3c560000}, {0x3c562000}, {0x3c564000}, {0x3c566000}, + {0x3c568000}, {0x3c56a000}, {0x3c56c000}, {0x3c56e000}, + {0x3c570000}, {0x3c572000}, {0x3c574000}, {0x3c576000}, + {0x3c578000}, {0x3c57a000}, {0x3c57c000}, {0x3c57e000}, + {0x3c580000}, {0x3c582000}, {0x3c584000}, {0x3c586000}, + {0x3c588000}, {0x3c58a000}, {0x3c58c000}, {0x3c58e000}, + {0x3c590000}, {0x3c592000}, {0x3c594000}, {0x3c596000}, + {0x3c598000}, {0x3c59a000}, {0x3c59c000}, {0x3c59e000}, + {0x3c5a0000}, {0x3c5a2000}, {0x3c5a4000}, {0x3c5a6000}, + {0x3c5a8000}, {0x3c5aa000}, {0x3c5ac000}, {0x3c5ae000}, + {0x3c5b0000}, {0x3c5b2000}, {0x3c5b4000}, {0x3c5b6000}, + {0x3c5b8000}, {0x3c5ba000}, {0x3c5bc000}, {0x3c5be000}, + {0x3c5c0000}, {0x3c5c2000}, {0x3c5c4000}, {0x3c5c6000}, + {0x3c5c8000}, {0x3c5ca000}, {0x3c5cc000}, {0x3c5ce000}, + {0x3c5d0000}, {0x3c5d2000}, {0x3c5d4000}, {0x3c5d6000}, + {0x3c5d8000}, {0x3c5da000}, {0x3c5dc000}, {0x3c5de000}, + {0x3c5e0000}, {0x3c5e2000}, {0x3c5e4000}, {0x3c5e6000}, + {0x3c5e8000}, {0x3c5ea000}, {0x3c5ec000}, {0x3c5ee000}, + {0x3c5f0000}, {0x3c5f2000}, {0x3c5f4000}, {0x3c5f6000}, + {0x3c5f8000}, {0x3c5fa000}, {0x3c5fc000}, {0x3c5fe000}, + {0x3c600000}, {0x3c602000}, {0x3c604000}, {0x3c606000}, + {0x3c608000}, {0x3c60a000}, {0x3c60c000}, {0x3c60e000}, + {0x3c610000}, {0x3c612000}, {0x3c614000}, {0x3c616000}, + {0x3c618000}, {0x3c61a000}, {0x3c61c000}, {0x3c61e000}, + {0x3c620000}, {0x3c622000}, {0x3c624000}, {0x3c626000}, + {0x3c628000}, {0x3c62a000}, {0x3c62c000}, {0x3c62e000}, + {0x3c630000}, {0x3c632000}, {0x3c634000}, {0x3c636000}, + {0x3c638000}, {0x3c63a000}, {0x3c63c000}, {0x3c63e000}, + {0x3c640000}, {0x3c642000}, {0x3c644000}, {0x3c646000}, + {0x3c648000}, {0x3c64a000}, {0x3c64c000}, {0x3c64e000}, + {0x3c650000}, {0x3c652000}, {0x3c654000}, {0x3c656000}, + {0x3c658000}, {0x3c65a000}, {0x3c65c000}, {0x3c65e000}, + {0x3c660000}, {0x3c662000}, {0x3c664000}, {0x3c666000}, + {0x3c668000}, {0x3c66a000}, {0x3c66c000}, {0x3c66e000}, + {0x3c670000}, {0x3c672000}, {0x3c674000}, {0x3c676000}, + {0x3c678000}, {0x3c67a000}, {0x3c67c000}, {0x3c67e000}, + {0x3c680000}, {0x3c682000}, {0x3c684000}, {0x3c686000}, + {0x3c688000}, {0x3c68a000}, {0x3c68c000}, {0x3c68e000}, + {0x3c690000}, {0x3c692000}, {0x3c694000}, {0x3c696000}, + {0x3c698000}, {0x3c69a000}, {0x3c69c000}, {0x3c69e000}, + {0x3c6a0000}, {0x3c6a2000}, {0x3c6a4000}, {0x3c6a6000}, + {0x3c6a8000}, {0x3c6aa000}, {0x3c6ac000}, {0x3c6ae000}, + {0x3c6b0000}, {0x3c6b2000}, {0x3c6b4000}, {0x3c6b6000}, + {0x3c6b8000}, {0x3c6ba000}, {0x3c6bc000}, {0x3c6be000}, + {0x3c6c0000}, {0x3c6c2000}, {0x3c6c4000}, {0x3c6c6000}, + {0x3c6c8000}, {0x3c6ca000}, {0x3c6cc000}, {0x3c6ce000}, + {0x3c6d0000}, {0x3c6d2000}, {0x3c6d4000}, {0x3c6d6000}, + {0x3c6d8000}, {0x3c6da000}, {0x3c6dc000}, {0x3c6de000}, + {0x3c6e0000}, {0x3c6e2000}, {0x3c6e4000}, {0x3c6e6000}, + {0x3c6e8000}, {0x3c6ea000}, {0x3c6ec000}, {0x3c6ee000}, + {0x3c6f0000}, {0x3c6f2000}, {0x3c6f4000}, {0x3c6f6000}, + {0x3c6f8000}, {0x3c6fa000}, {0x3c6fc000}, {0x3c6fe000}, + {0x3c700000}, {0x3c702000}, {0x3c704000}, {0x3c706000}, + {0x3c708000}, {0x3c70a000}, {0x3c70c000}, {0x3c70e000}, + {0x3c710000}, {0x3c712000}, {0x3c714000}, {0x3c716000}, + {0x3c718000}, {0x3c71a000}, {0x3c71c000}, {0x3c71e000}, + {0x3c720000}, {0x3c722000}, {0x3c724000}, {0x3c726000}, + {0x3c728000}, {0x3c72a000}, {0x3c72c000}, {0x3c72e000}, + {0x3c730000}, {0x3c732000}, {0x3c734000}, {0x3c736000}, + {0x3c738000}, {0x3c73a000}, {0x3c73c000}, {0x3c73e000}, + {0x3c740000}, {0x3c742000}, {0x3c744000}, {0x3c746000}, + {0x3c748000}, {0x3c74a000}, {0x3c74c000}, {0x3c74e000}, + {0x3c750000}, {0x3c752000}, {0x3c754000}, {0x3c756000}, + {0x3c758000}, {0x3c75a000}, {0x3c75c000}, {0x3c75e000}, + {0x3c760000}, {0x3c762000}, {0x3c764000}, {0x3c766000}, + {0x3c768000}, {0x3c76a000}, {0x3c76c000}, {0x3c76e000}, + {0x3c770000}, {0x3c772000}, {0x3c774000}, {0x3c776000}, + {0x3c778000}, {0x3c77a000}, {0x3c77c000}, {0x3c77e000}, + {0x3c780000}, {0x3c782000}, {0x3c784000}, {0x3c786000}, + {0x3c788000}, {0x3c78a000}, {0x3c78c000}, {0x3c78e000}, + {0x3c790000}, {0x3c792000}, {0x3c794000}, {0x3c796000}, + {0x3c798000}, {0x3c79a000}, {0x3c79c000}, {0x3c79e000}, + {0x3c7a0000}, {0x3c7a2000}, {0x3c7a4000}, {0x3c7a6000}, + {0x3c7a8000}, {0x3c7aa000}, {0x3c7ac000}, {0x3c7ae000}, + {0x3c7b0000}, {0x3c7b2000}, {0x3c7b4000}, {0x3c7b6000}, + {0x3c7b8000}, {0x3c7ba000}, {0x3c7bc000}, {0x3c7be000}, + {0x3c7c0000}, {0x3c7c2000}, {0x3c7c4000}, {0x3c7c6000}, + {0x3c7c8000}, {0x3c7ca000}, {0x3c7cc000}, {0x3c7ce000}, + {0x3c7d0000}, {0x3c7d2000}, {0x3c7d4000}, {0x3c7d6000}, + {0x3c7d8000}, {0x3c7da000}, {0x3c7dc000}, {0x3c7de000}, + {0x3c7e0000}, {0x3c7e2000}, {0x3c7e4000}, {0x3c7e6000}, + {0x3c7e8000}, {0x3c7ea000}, {0x3c7ec000}, {0x3c7ee000}, + {0x3c7f0000}, {0x3c7f2000}, {0x3c7f4000}, {0x3c7f6000}, + {0x3c7f8000}, {0x3c7fa000}, {0x3c7fc000}, {0x3c7fe000}, + {0x3c800000}, {0x3c802000}, {0x3c804000}, {0x3c806000}, + {0x3c808000}, {0x3c80a000}, {0x3c80c000}, {0x3c80e000}, + {0x3c810000}, {0x3c812000}, {0x3c814000}, {0x3c816000}, + {0x3c818000}, {0x3c81a000}, {0x3c81c000}, {0x3c81e000}, + {0x3c820000}, {0x3c822000}, {0x3c824000}, {0x3c826000}, + {0x3c828000}, {0x3c82a000}, {0x3c82c000}, {0x3c82e000}, + {0x3c830000}, {0x3c832000}, {0x3c834000}, {0x3c836000}, + {0x3c838000}, {0x3c83a000}, {0x3c83c000}, {0x3c83e000}, + {0x3c840000}, {0x3c842000}, {0x3c844000}, {0x3c846000}, + {0x3c848000}, {0x3c84a000}, {0x3c84c000}, {0x3c84e000}, + {0x3c850000}, {0x3c852000}, {0x3c854000}, {0x3c856000}, + {0x3c858000}, {0x3c85a000}, {0x3c85c000}, {0x3c85e000}, + {0x3c860000}, {0x3c862000}, {0x3c864000}, {0x3c866000}, + {0x3c868000}, {0x3c86a000}, {0x3c86c000}, {0x3c86e000}, + {0x3c870000}, {0x3c872000}, {0x3c874000}, {0x3c876000}, + {0x3c878000}, {0x3c87a000}, {0x3c87c000}, {0x3c87e000}, + {0x3c880000}, {0x3c882000}, {0x3c884000}, {0x3c886000}, + {0x3c888000}, {0x3c88a000}, {0x3c88c000}, {0x3c88e000}, + {0x3c890000}, {0x3c892000}, {0x3c894000}, {0x3c896000}, + {0x3c898000}, {0x3c89a000}, {0x3c89c000}, {0x3c89e000}, + {0x3c8a0000}, {0x3c8a2000}, {0x3c8a4000}, {0x3c8a6000}, + {0x3c8a8000}, {0x3c8aa000}, {0x3c8ac000}, {0x3c8ae000}, + {0x3c8b0000}, {0x3c8b2000}, {0x3c8b4000}, {0x3c8b6000}, + {0x3c8b8000}, {0x3c8ba000}, {0x3c8bc000}, {0x3c8be000}, + {0x3c8c0000}, {0x3c8c2000}, {0x3c8c4000}, {0x3c8c6000}, + {0x3c8c8000}, {0x3c8ca000}, {0x3c8cc000}, {0x3c8ce000}, + {0x3c8d0000}, {0x3c8d2000}, {0x3c8d4000}, {0x3c8d6000}, + {0x3c8d8000}, {0x3c8da000}, {0x3c8dc000}, {0x3c8de000}, + {0x3c8e0000}, {0x3c8e2000}, {0x3c8e4000}, {0x3c8e6000}, + {0x3c8e8000}, {0x3c8ea000}, {0x3c8ec000}, {0x3c8ee000}, + {0x3c8f0000}, {0x3c8f2000}, {0x3c8f4000}, {0x3c8f6000}, + {0x3c8f8000}, {0x3c8fa000}, {0x3c8fc000}, {0x3c8fe000}, + {0x3c900000}, {0x3c902000}, {0x3c904000}, {0x3c906000}, + {0x3c908000}, {0x3c90a000}, {0x3c90c000}, {0x3c90e000}, + {0x3c910000}, {0x3c912000}, {0x3c914000}, {0x3c916000}, + {0x3c918000}, {0x3c91a000}, {0x3c91c000}, {0x3c91e000}, + {0x3c920000}, {0x3c922000}, {0x3c924000}, {0x3c926000}, + {0x3c928000}, {0x3c92a000}, {0x3c92c000}, {0x3c92e000}, + {0x3c930000}, {0x3c932000}, {0x3c934000}, {0x3c936000}, + {0x3c938000}, {0x3c93a000}, {0x3c93c000}, {0x3c93e000}, + {0x3c940000}, {0x3c942000}, {0x3c944000}, {0x3c946000}, + {0x3c948000}, {0x3c94a000}, {0x3c94c000}, {0x3c94e000}, + {0x3c950000}, {0x3c952000}, {0x3c954000}, {0x3c956000}, + {0x3c958000}, {0x3c95a000}, {0x3c95c000}, {0x3c95e000}, + {0x3c960000}, {0x3c962000}, {0x3c964000}, {0x3c966000}, + {0x3c968000}, {0x3c96a000}, {0x3c96c000}, {0x3c96e000}, + {0x3c970000}, {0x3c972000}, {0x3c974000}, {0x3c976000}, + {0x3c978000}, {0x3c97a000}, {0x3c97c000}, {0x3c97e000}, + {0x3c980000}, {0x3c982000}, {0x3c984000}, {0x3c986000}, + {0x3c988000}, {0x3c98a000}, {0x3c98c000}, {0x3c98e000}, + {0x3c990000}, {0x3c992000}, {0x3c994000}, {0x3c996000}, + {0x3c998000}, {0x3c99a000}, {0x3c99c000}, {0x3c99e000}, + {0x3c9a0000}, {0x3c9a2000}, {0x3c9a4000}, {0x3c9a6000}, + {0x3c9a8000}, {0x3c9aa000}, {0x3c9ac000}, {0x3c9ae000}, + {0x3c9b0000}, {0x3c9b2000}, {0x3c9b4000}, {0x3c9b6000}, + {0x3c9b8000}, {0x3c9ba000}, {0x3c9bc000}, {0x3c9be000}, + {0x3c9c0000}, {0x3c9c2000}, {0x3c9c4000}, {0x3c9c6000}, + {0x3c9c8000}, {0x3c9ca000}, {0x3c9cc000}, {0x3c9ce000}, + {0x3c9d0000}, {0x3c9d2000}, {0x3c9d4000}, {0x3c9d6000}, + {0x3c9d8000}, {0x3c9da000}, {0x3c9dc000}, {0x3c9de000}, + {0x3c9e0000}, {0x3c9e2000}, {0x3c9e4000}, {0x3c9e6000}, + {0x3c9e8000}, {0x3c9ea000}, {0x3c9ec000}, {0x3c9ee000}, + {0x3c9f0000}, {0x3c9f2000}, {0x3c9f4000}, {0x3c9f6000}, + {0x3c9f8000}, {0x3c9fa000}, {0x3c9fc000}, {0x3c9fe000}, + {0x3ca00000}, {0x3ca02000}, {0x3ca04000}, {0x3ca06000}, + {0x3ca08000}, {0x3ca0a000}, {0x3ca0c000}, {0x3ca0e000}, + {0x3ca10000}, {0x3ca12000}, {0x3ca14000}, {0x3ca16000}, + {0x3ca18000}, {0x3ca1a000}, {0x3ca1c000}, {0x3ca1e000}, + {0x3ca20000}, {0x3ca22000}, {0x3ca24000}, {0x3ca26000}, + {0x3ca28000}, {0x3ca2a000}, {0x3ca2c000}, {0x3ca2e000}, + {0x3ca30000}, {0x3ca32000}, {0x3ca34000}, {0x3ca36000}, + {0x3ca38000}, {0x3ca3a000}, {0x3ca3c000}, {0x3ca3e000}, + {0x3ca40000}, {0x3ca42000}, {0x3ca44000}, {0x3ca46000}, + {0x3ca48000}, {0x3ca4a000}, {0x3ca4c000}, {0x3ca4e000}, + {0x3ca50000}, {0x3ca52000}, {0x3ca54000}, {0x3ca56000}, + {0x3ca58000}, {0x3ca5a000}, {0x3ca5c000}, {0x3ca5e000}, + {0x3ca60000}, {0x3ca62000}, {0x3ca64000}, {0x3ca66000}, + {0x3ca68000}, {0x3ca6a000}, {0x3ca6c000}, {0x3ca6e000}, + {0x3ca70000}, {0x3ca72000}, {0x3ca74000}, {0x3ca76000}, + {0x3ca78000}, {0x3ca7a000}, {0x3ca7c000}, {0x3ca7e000}, + {0x3ca80000}, {0x3ca82000}, {0x3ca84000}, {0x3ca86000}, + {0x3ca88000}, {0x3ca8a000}, {0x3ca8c000}, {0x3ca8e000}, + {0x3ca90000}, {0x3ca92000}, {0x3ca94000}, {0x3ca96000}, + {0x3ca98000}, {0x3ca9a000}, {0x3ca9c000}, {0x3ca9e000}, + {0x3caa0000}, {0x3caa2000}, {0x3caa4000}, {0x3caa6000}, + {0x3caa8000}, {0x3caaa000}, {0x3caac000}, {0x3caae000}, + {0x3cab0000}, {0x3cab2000}, {0x3cab4000}, {0x3cab6000}, + {0x3cab8000}, {0x3caba000}, {0x3cabc000}, {0x3cabe000}, + {0x3cac0000}, {0x3cac2000}, {0x3cac4000}, {0x3cac6000}, + {0x3cac8000}, {0x3caca000}, {0x3cacc000}, {0x3cace000}, + {0x3cad0000}, {0x3cad2000}, {0x3cad4000}, {0x3cad6000}, + {0x3cad8000}, {0x3cada000}, {0x3cadc000}, {0x3cade000}, + {0x3cae0000}, {0x3cae2000}, {0x3cae4000}, {0x3cae6000}, + {0x3cae8000}, {0x3caea000}, {0x3caec000}, {0x3caee000}, + {0x3caf0000}, {0x3caf2000}, {0x3caf4000}, {0x3caf6000}, + {0x3caf8000}, {0x3cafa000}, {0x3cafc000}, {0x3cafe000}, + {0x3cb00000}, {0x3cb02000}, {0x3cb04000}, {0x3cb06000}, + {0x3cb08000}, {0x3cb0a000}, {0x3cb0c000}, {0x3cb0e000}, + {0x3cb10000}, {0x3cb12000}, {0x3cb14000}, {0x3cb16000}, + {0x3cb18000}, {0x3cb1a000}, {0x3cb1c000}, {0x3cb1e000}, + {0x3cb20000}, {0x3cb22000}, {0x3cb24000}, {0x3cb26000}, + {0x3cb28000}, {0x3cb2a000}, {0x3cb2c000}, {0x3cb2e000}, + {0x3cb30000}, {0x3cb32000}, {0x3cb34000}, {0x3cb36000}, + {0x3cb38000}, {0x3cb3a000}, {0x3cb3c000}, {0x3cb3e000}, + {0x3cb40000}, {0x3cb42000}, {0x3cb44000}, {0x3cb46000}, + {0x3cb48000}, {0x3cb4a000}, {0x3cb4c000}, {0x3cb4e000}, + {0x3cb50000}, {0x3cb52000}, {0x3cb54000}, {0x3cb56000}, + {0x3cb58000}, {0x3cb5a000}, {0x3cb5c000}, {0x3cb5e000}, + {0x3cb60000}, {0x3cb62000}, {0x3cb64000}, {0x3cb66000}, + {0x3cb68000}, {0x3cb6a000}, {0x3cb6c000}, {0x3cb6e000}, + {0x3cb70000}, {0x3cb72000}, {0x3cb74000}, {0x3cb76000}, + {0x3cb78000}, {0x3cb7a000}, {0x3cb7c000}, {0x3cb7e000}, + {0x3cb80000}, {0x3cb82000}, {0x3cb84000}, {0x3cb86000}, + {0x3cb88000}, {0x3cb8a000}, {0x3cb8c000}, {0x3cb8e000}, + {0x3cb90000}, {0x3cb92000}, {0x3cb94000}, {0x3cb96000}, + {0x3cb98000}, {0x3cb9a000}, {0x3cb9c000}, {0x3cb9e000}, + {0x3cba0000}, {0x3cba2000}, {0x3cba4000}, {0x3cba6000}, + {0x3cba8000}, {0x3cbaa000}, {0x3cbac000}, {0x3cbae000}, + {0x3cbb0000}, {0x3cbb2000}, {0x3cbb4000}, {0x3cbb6000}, + {0x3cbb8000}, {0x3cbba000}, {0x3cbbc000}, {0x3cbbe000}, + {0x3cbc0000}, {0x3cbc2000}, {0x3cbc4000}, {0x3cbc6000}, + {0x3cbc8000}, {0x3cbca000}, {0x3cbcc000}, {0x3cbce000}, + {0x3cbd0000}, {0x3cbd2000}, {0x3cbd4000}, {0x3cbd6000}, + {0x3cbd8000}, {0x3cbda000}, {0x3cbdc000}, {0x3cbde000}, + {0x3cbe0000}, {0x3cbe2000}, {0x3cbe4000}, {0x3cbe6000}, + {0x3cbe8000}, {0x3cbea000}, {0x3cbec000}, {0x3cbee000}, + {0x3cbf0000}, {0x3cbf2000}, {0x3cbf4000}, {0x3cbf6000}, + {0x3cbf8000}, {0x3cbfa000}, {0x3cbfc000}, {0x3cbfe000}, + {0x3cc00000}, {0x3cc02000}, {0x3cc04000}, {0x3cc06000}, + {0x3cc08000}, {0x3cc0a000}, {0x3cc0c000}, {0x3cc0e000}, + {0x3cc10000}, {0x3cc12000}, {0x3cc14000}, {0x3cc16000}, + {0x3cc18000}, {0x3cc1a000}, {0x3cc1c000}, {0x3cc1e000}, + {0x3cc20000}, {0x3cc22000}, {0x3cc24000}, {0x3cc26000}, + {0x3cc28000}, {0x3cc2a000}, {0x3cc2c000}, {0x3cc2e000}, + {0x3cc30000}, {0x3cc32000}, {0x3cc34000}, {0x3cc36000}, + {0x3cc38000}, {0x3cc3a000}, {0x3cc3c000}, {0x3cc3e000}, + {0x3cc40000}, {0x3cc42000}, {0x3cc44000}, {0x3cc46000}, + {0x3cc48000}, {0x3cc4a000}, {0x3cc4c000}, {0x3cc4e000}, + {0x3cc50000}, {0x3cc52000}, {0x3cc54000}, {0x3cc56000}, + {0x3cc58000}, {0x3cc5a000}, {0x3cc5c000}, {0x3cc5e000}, + {0x3cc60000}, {0x3cc62000}, {0x3cc64000}, {0x3cc66000}, + {0x3cc68000}, {0x3cc6a000}, {0x3cc6c000}, {0x3cc6e000}, + {0x3cc70000}, {0x3cc72000}, {0x3cc74000}, {0x3cc76000}, + {0x3cc78000}, {0x3cc7a000}, {0x3cc7c000}, {0x3cc7e000}, + {0x3cc80000}, {0x3cc82000}, {0x3cc84000}, {0x3cc86000}, + {0x3cc88000}, {0x3cc8a000}, {0x3cc8c000}, {0x3cc8e000}, + {0x3cc90000}, {0x3cc92000}, {0x3cc94000}, {0x3cc96000}, + {0x3cc98000}, {0x3cc9a000}, {0x3cc9c000}, {0x3cc9e000}, + {0x3cca0000}, {0x3cca2000}, {0x3cca4000}, {0x3cca6000}, + {0x3cca8000}, {0x3ccaa000}, {0x3ccac000}, {0x3ccae000}, + {0x3ccb0000}, {0x3ccb2000}, {0x3ccb4000}, {0x3ccb6000}, + {0x3ccb8000}, {0x3ccba000}, {0x3ccbc000}, {0x3ccbe000}, + {0x3ccc0000}, {0x3ccc2000}, {0x3ccc4000}, {0x3ccc6000}, + {0x3ccc8000}, {0x3ccca000}, {0x3cccc000}, {0x3ccce000}, + {0x3ccd0000}, {0x3ccd2000}, {0x3ccd4000}, {0x3ccd6000}, + {0x3ccd8000}, {0x3ccda000}, {0x3ccdc000}, {0x3ccde000}, + {0x3cce0000}, {0x3cce2000}, {0x3cce4000}, {0x3cce6000}, + {0x3cce8000}, {0x3ccea000}, {0x3ccec000}, {0x3ccee000}, + {0x3ccf0000}, {0x3ccf2000}, {0x3ccf4000}, {0x3ccf6000}, + {0x3ccf8000}, {0x3ccfa000}, {0x3ccfc000}, {0x3ccfe000}, + {0x3cd00000}, {0x3cd02000}, {0x3cd04000}, {0x3cd06000}, + {0x3cd08000}, {0x3cd0a000}, {0x3cd0c000}, {0x3cd0e000}, + {0x3cd10000}, {0x3cd12000}, {0x3cd14000}, {0x3cd16000}, + {0x3cd18000}, {0x3cd1a000}, {0x3cd1c000}, {0x3cd1e000}, + {0x3cd20000}, {0x3cd22000}, {0x3cd24000}, {0x3cd26000}, + {0x3cd28000}, {0x3cd2a000}, {0x3cd2c000}, {0x3cd2e000}, + {0x3cd30000}, {0x3cd32000}, {0x3cd34000}, {0x3cd36000}, + {0x3cd38000}, {0x3cd3a000}, {0x3cd3c000}, {0x3cd3e000}, + {0x3cd40000}, {0x3cd42000}, {0x3cd44000}, {0x3cd46000}, + {0x3cd48000}, {0x3cd4a000}, {0x3cd4c000}, {0x3cd4e000}, + {0x3cd50000}, {0x3cd52000}, {0x3cd54000}, {0x3cd56000}, + {0x3cd58000}, {0x3cd5a000}, {0x3cd5c000}, {0x3cd5e000}, + {0x3cd60000}, {0x3cd62000}, {0x3cd64000}, {0x3cd66000}, + {0x3cd68000}, {0x3cd6a000}, {0x3cd6c000}, {0x3cd6e000}, + {0x3cd70000}, {0x3cd72000}, {0x3cd74000}, {0x3cd76000}, + {0x3cd78000}, {0x3cd7a000}, {0x3cd7c000}, {0x3cd7e000}, + {0x3cd80000}, {0x3cd82000}, {0x3cd84000}, {0x3cd86000}, + {0x3cd88000}, {0x3cd8a000}, {0x3cd8c000}, {0x3cd8e000}, + {0x3cd90000}, {0x3cd92000}, {0x3cd94000}, {0x3cd96000}, + {0x3cd98000}, {0x3cd9a000}, {0x3cd9c000}, {0x3cd9e000}, + {0x3cda0000}, {0x3cda2000}, {0x3cda4000}, {0x3cda6000}, + {0x3cda8000}, {0x3cdaa000}, {0x3cdac000}, {0x3cdae000}, + {0x3cdb0000}, {0x3cdb2000}, {0x3cdb4000}, {0x3cdb6000}, + {0x3cdb8000}, {0x3cdba000}, {0x3cdbc000}, {0x3cdbe000}, + {0x3cdc0000}, {0x3cdc2000}, {0x3cdc4000}, {0x3cdc6000}, + {0x3cdc8000}, {0x3cdca000}, {0x3cdcc000}, {0x3cdce000}, + {0x3cdd0000}, {0x3cdd2000}, {0x3cdd4000}, {0x3cdd6000}, + {0x3cdd8000}, {0x3cdda000}, {0x3cddc000}, {0x3cdde000}, + {0x3cde0000}, {0x3cde2000}, {0x3cde4000}, {0x3cde6000}, + {0x3cde8000}, {0x3cdea000}, {0x3cdec000}, {0x3cdee000}, + {0x3cdf0000}, {0x3cdf2000}, {0x3cdf4000}, {0x3cdf6000}, + {0x3cdf8000}, {0x3cdfa000}, {0x3cdfc000}, {0x3cdfe000}, + {0x3ce00000}, {0x3ce02000}, {0x3ce04000}, {0x3ce06000}, + {0x3ce08000}, {0x3ce0a000}, {0x3ce0c000}, {0x3ce0e000}, + {0x3ce10000}, {0x3ce12000}, {0x3ce14000}, {0x3ce16000}, + {0x3ce18000}, {0x3ce1a000}, {0x3ce1c000}, {0x3ce1e000}, + {0x3ce20000}, {0x3ce22000}, {0x3ce24000}, {0x3ce26000}, + {0x3ce28000}, {0x3ce2a000}, {0x3ce2c000}, {0x3ce2e000}, + {0x3ce30000}, {0x3ce32000}, {0x3ce34000}, {0x3ce36000}, + {0x3ce38000}, {0x3ce3a000}, {0x3ce3c000}, {0x3ce3e000}, + {0x3ce40000}, {0x3ce42000}, {0x3ce44000}, {0x3ce46000}, + {0x3ce48000}, {0x3ce4a000}, {0x3ce4c000}, {0x3ce4e000}, + {0x3ce50000}, {0x3ce52000}, {0x3ce54000}, {0x3ce56000}, + {0x3ce58000}, {0x3ce5a000}, {0x3ce5c000}, {0x3ce5e000}, + {0x3ce60000}, {0x3ce62000}, {0x3ce64000}, {0x3ce66000}, + {0x3ce68000}, {0x3ce6a000}, {0x3ce6c000}, {0x3ce6e000}, + {0x3ce70000}, {0x3ce72000}, {0x3ce74000}, {0x3ce76000}, + {0x3ce78000}, {0x3ce7a000}, {0x3ce7c000}, {0x3ce7e000}, + {0x3ce80000}, {0x3ce82000}, {0x3ce84000}, {0x3ce86000}, + {0x3ce88000}, {0x3ce8a000}, {0x3ce8c000}, {0x3ce8e000}, + {0x3ce90000}, {0x3ce92000}, {0x3ce94000}, {0x3ce96000}, + {0x3ce98000}, {0x3ce9a000}, {0x3ce9c000}, {0x3ce9e000}, + {0x3cea0000}, {0x3cea2000}, {0x3cea4000}, {0x3cea6000}, + {0x3cea8000}, {0x3ceaa000}, {0x3ceac000}, {0x3ceae000}, + {0x3ceb0000}, {0x3ceb2000}, {0x3ceb4000}, {0x3ceb6000}, + {0x3ceb8000}, {0x3ceba000}, {0x3cebc000}, {0x3cebe000}, + {0x3cec0000}, {0x3cec2000}, {0x3cec4000}, {0x3cec6000}, + {0x3cec8000}, {0x3ceca000}, {0x3cecc000}, {0x3cece000}, + {0x3ced0000}, {0x3ced2000}, {0x3ced4000}, {0x3ced6000}, + {0x3ced8000}, {0x3ceda000}, {0x3cedc000}, {0x3cede000}, + {0x3cee0000}, {0x3cee2000}, {0x3cee4000}, {0x3cee6000}, + {0x3cee8000}, {0x3ceea000}, {0x3ceec000}, {0x3ceee000}, + {0x3cef0000}, {0x3cef2000}, {0x3cef4000}, {0x3cef6000}, + {0x3cef8000}, {0x3cefa000}, {0x3cefc000}, {0x3cefe000}, + {0x3cf00000}, {0x3cf02000}, {0x3cf04000}, {0x3cf06000}, + {0x3cf08000}, {0x3cf0a000}, {0x3cf0c000}, {0x3cf0e000}, + {0x3cf10000}, {0x3cf12000}, {0x3cf14000}, {0x3cf16000}, + {0x3cf18000}, {0x3cf1a000}, {0x3cf1c000}, {0x3cf1e000}, + {0x3cf20000}, {0x3cf22000}, {0x3cf24000}, {0x3cf26000}, + {0x3cf28000}, {0x3cf2a000}, {0x3cf2c000}, {0x3cf2e000}, + {0x3cf30000}, {0x3cf32000}, {0x3cf34000}, {0x3cf36000}, + {0x3cf38000}, {0x3cf3a000}, {0x3cf3c000}, {0x3cf3e000}, + {0x3cf40000}, {0x3cf42000}, {0x3cf44000}, {0x3cf46000}, + {0x3cf48000}, {0x3cf4a000}, {0x3cf4c000}, {0x3cf4e000}, + {0x3cf50000}, {0x3cf52000}, {0x3cf54000}, {0x3cf56000}, + {0x3cf58000}, {0x3cf5a000}, {0x3cf5c000}, {0x3cf5e000}, + {0x3cf60000}, {0x3cf62000}, {0x3cf64000}, {0x3cf66000}, + {0x3cf68000}, {0x3cf6a000}, {0x3cf6c000}, {0x3cf6e000}, + {0x3cf70000}, {0x3cf72000}, {0x3cf74000}, {0x3cf76000}, + {0x3cf78000}, {0x3cf7a000}, {0x3cf7c000}, {0x3cf7e000}, + {0x3cf80000}, {0x3cf82000}, {0x3cf84000}, {0x3cf86000}, + {0x3cf88000}, {0x3cf8a000}, {0x3cf8c000}, {0x3cf8e000}, + {0x3cf90000}, {0x3cf92000}, {0x3cf94000}, {0x3cf96000}, + {0x3cf98000}, {0x3cf9a000}, {0x3cf9c000}, {0x3cf9e000}, + {0x3cfa0000}, {0x3cfa2000}, {0x3cfa4000}, {0x3cfa6000}, + {0x3cfa8000}, {0x3cfaa000}, {0x3cfac000}, {0x3cfae000}, + {0x3cfb0000}, {0x3cfb2000}, {0x3cfb4000}, {0x3cfb6000}, + {0x3cfb8000}, {0x3cfba000}, {0x3cfbc000}, {0x3cfbe000}, + {0x3cfc0000}, {0x3cfc2000}, {0x3cfc4000}, {0x3cfc6000}, + {0x3cfc8000}, {0x3cfca000}, {0x3cfcc000}, {0x3cfce000}, + {0x3cfd0000}, {0x3cfd2000}, {0x3cfd4000}, {0x3cfd6000}, + {0x3cfd8000}, {0x3cfda000}, {0x3cfdc000}, {0x3cfde000}, + {0x3cfe0000}, {0x3cfe2000}, {0x3cfe4000}, {0x3cfe6000}, + {0x3cfe8000}, {0x3cfea000}, {0x3cfec000}, {0x3cfee000}, + {0x3cff0000}, {0x3cff2000}, {0x3cff4000}, {0x3cff6000}, + {0x3cff8000}, {0x3cffa000}, {0x3cffc000}, {0x3cffe000}, + {0x3d000000}, {0x3d002000}, {0x3d004000}, {0x3d006000}, + {0x3d008000}, {0x3d00a000}, {0x3d00c000}, {0x3d00e000}, + {0x3d010000}, {0x3d012000}, {0x3d014000}, {0x3d016000}, + {0x3d018000}, {0x3d01a000}, {0x3d01c000}, {0x3d01e000}, + {0x3d020000}, {0x3d022000}, {0x3d024000}, {0x3d026000}, + {0x3d028000}, {0x3d02a000}, {0x3d02c000}, {0x3d02e000}, + {0x3d030000}, {0x3d032000}, {0x3d034000}, {0x3d036000}, + {0x3d038000}, {0x3d03a000}, {0x3d03c000}, {0x3d03e000}, + {0x3d040000}, {0x3d042000}, {0x3d044000}, {0x3d046000}, + {0x3d048000}, {0x3d04a000}, {0x3d04c000}, {0x3d04e000}, + {0x3d050000}, {0x3d052000}, {0x3d054000}, {0x3d056000}, + {0x3d058000}, {0x3d05a000}, {0x3d05c000}, {0x3d05e000}, + {0x3d060000}, {0x3d062000}, {0x3d064000}, {0x3d066000}, + {0x3d068000}, {0x3d06a000}, {0x3d06c000}, {0x3d06e000}, + {0x3d070000}, {0x3d072000}, {0x3d074000}, {0x3d076000}, + {0x3d078000}, {0x3d07a000}, {0x3d07c000}, {0x3d07e000}, + {0x3d080000}, {0x3d082000}, {0x3d084000}, {0x3d086000}, + {0x3d088000}, {0x3d08a000}, {0x3d08c000}, {0x3d08e000}, + {0x3d090000}, {0x3d092000}, {0x3d094000}, {0x3d096000}, + {0x3d098000}, {0x3d09a000}, {0x3d09c000}, {0x3d09e000}, + {0x3d0a0000}, {0x3d0a2000}, {0x3d0a4000}, {0x3d0a6000}, + {0x3d0a8000}, {0x3d0aa000}, {0x3d0ac000}, {0x3d0ae000}, + {0x3d0b0000}, {0x3d0b2000}, {0x3d0b4000}, {0x3d0b6000}, + {0x3d0b8000}, {0x3d0ba000}, {0x3d0bc000}, {0x3d0be000}, + {0x3d0c0000}, {0x3d0c2000}, {0x3d0c4000}, {0x3d0c6000}, + {0x3d0c8000}, {0x3d0ca000}, {0x3d0cc000}, {0x3d0ce000}, + {0x3d0d0000}, {0x3d0d2000}, {0x3d0d4000}, {0x3d0d6000}, + {0x3d0d8000}, {0x3d0da000}, {0x3d0dc000}, {0x3d0de000}, + {0x3d0e0000}, {0x3d0e2000}, {0x3d0e4000}, {0x3d0e6000}, + {0x3d0e8000}, {0x3d0ea000}, {0x3d0ec000}, {0x3d0ee000}, + {0x3d0f0000}, {0x3d0f2000}, {0x3d0f4000}, {0x3d0f6000}, + {0x3d0f8000}, {0x3d0fa000}, {0x3d0fc000}, {0x3d0fe000}, + {0x3d100000}, {0x3d102000}, {0x3d104000}, {0x3d106000}, + {0x3d108000}, {0x3d10a000}, {0x3d10c000}, {0x3d10e000}, + {0x3d110000}, {0x3d112000}, {0x3d114000}, {0x3d116000}, + {0x3d118000}, {0x3d11a000}, {0x3d11c000}, {0x3d11e000}, + {0x3d120000}, {0x3d122000}, {0x3d124000}, {0x3d126000}, + {0x3d128000}, {0x3d12a000}, {0x3d12c000}, {0x3d12e000}, + {0x3d130000}, {0x3d132000}, {0x3d134000}, {0x3d136000}, + {0x3d138000}, {0x3d13a000}, {0x3d13c000}, {0x3d13e000}, + {0x3d140000}, {0x3d142000}, {0x3d144000}, {0x3d146000}, + {0x3d148000}, {0x3d14a000}, {0x3d14c000}, {0x3d14e000}, + {0x3d150000}, {0x3d152000}, {0x3d154000}, {0x3d156000}, + {0x3d158000}, {0x3d15a000}, {0x3d15c000}, {0x3d15e000}, + {0x3d160000}, {0x3d162000}, {0x3d164000}, {0x3d166000}, + {0x3d168000}, {0x3d16a000}, {0x3d16c000}, {0x3d16e000}, + {0x3d170000}, {0x3d172000}, {0x3d174000}, {0x3d176000}, + {0x3d178000}, {0x3d17a000}, {0x3d17c000}, {0x3d17e000}, + {0x3d180000}, {0x3d182000}, {0x3d184000}, {0x3d186000}, + {0x3d188000}, {0x3d18a000}, {0x3d18c000}, {0x3d18e000}, + {0x3d190000}, {0x3d192000}, {0x3d194000}, {0x3d196000}, + {0x3d198000}, {0x3d19a000}, {0x3d19c000}, {0x3d19e000}, + {0x3d1a0000}, {0x3d1a2000}, {0x3d1a4000}, {0x3d1a6000}, + {0x3d1a8000}, {0x3d1aa000}, {0x3d1ac000}, {0x3d1ae000}, + {0x3d1b0000}, {0x3d1b2000}, {0x3d1b4000}, {0x3d1b6000}, + {0x3d1b8000}, {0x3d1ba000}, {0x3d1bc000}, {0x3d1be000}, + {0x3d1c0000}, {0x3d1c2000}, {0x3d1c4000}, {0x3d1c6000}, + {0x3d1c8000}, {0x3d1ca000}, {0x3d1cc000}, {0x3d1ce000}, + {0x3d1d0000}, {0x3d1d2000}, {0x3d1d4000}, {0x3d1d6000}, + {0x3d1d8000}, {0x3d1da000}, {0x3d1dc000}, {0x3d1de000}, + {0x3d1e0000}, {0x3d1e2000}, {0x3d1e4000}, {0x3d1e6000}, + {0x3d1e8000}, {0x3d1ea000}, {0x3d1ec000}, {0x3d1ee000}, + {0x3d1f0000}, {0x3d1f2000}, {0x3d1f4000}, {0x3d1f6000}, + {0x3d1f8000}, {0x3d1fa000}, {0x3d1fc000}, {0x3d1fe000}, + {0x3d200000}, {0x3d202000}, {0x3d204000}, {0x3d206000}, + {0x3d208000}, {0x3d20a000}, {0x3d20c000}, {0x3d20e000}, + {0x3d210000}, {0x3d212000}, {0x3d214000}, {0x3d216000}, + {0x3d218000}, {0x3d21a000}, {0x3d21c000}, {0x3d21e000}, + {0x3d220000}, {0x3d222000}, {0x3d224000}, {0x3d226000}, + {0x3d228000}, {0x3d22a000}, {0x3d22c000}, {0x3d22e000}, + {0x3d230000}, {0x3d232000}, {0x3d234000}, {0x3d236000}, + {0x3d238000}, {0x3d23a000}, {0x3d23c000}, {0x3d23e000}, + {0x3d240000}, {0x3d242000}, {0x3d244000}, {0x3d246000}, + {0x3d248000}, {0x3d24a000}, {0x3d24c000}, {0x3d24e000}, + {0x3d250000}, {0x3d252000}, {0x3d254000}, {0x3d256000}, + {0x3d258000}, {0x3d25a000}, {0x3d25c000}, {0x3d25e000}, + {0x3d260000}, {0x3d262000}, {0x3d264000}, {0x3d266000}, + {0x3d268000}, {0x3d26a000}, {0x3d26c000}, {0x3d26e000}, + {0x3d270000}, {0x3d272000}, {0x3d274000}, {0x3d276000}, + {0x3d278000}, {0x3d27a000}, {0x3d27c000}, {0x3d27e000}, + {0x3d280000}, {0x3d282000}, {0x3d284000}, {0x3d286000}, + {0x3d288000}, {0x3d28a000}, {0x3d28c000}, {0x3d28e000}, + {0x3d290000}, {0x3d292000}, {0x3d294000}, {0x3d296000}, + {0x3d298000}, {0x3d29a000}, {0x3d29c000}, {0x3d29e000}, + {0x3d2a0000}, {0x3d2a2000}, {0x3d2a4000}, {0x3d2a6000}, + {0x3d2a8000}, {0x3d2aa000}, {0x3d2ac000}, {0x3d2ae000}, + {0x3d2b0000}, {0x3d2b2000}, {0x3d2b4000}, {0x3d2b6000}, + {0x3d2b8000}, {0x3d2ba000}, {0x3d2bc000}, {0x3d2be000}, + {0x3d2c0000}, {0x3d2c2000}, {0x3d2c4000}, {0x3d2c6000}, + {0x3d2c8000}, {0x3d2ca000}, {0x3d2cc000}, {0x3d2ce000}, + {0x3d2d0000}, {0x3d2d2000}, {0x3d2d4000}, {0x3d2d6000}, + {0x3d2d8000}, {0x3d2da000}, {0x3d2dc000}, {0x3d2de000}, + {0x3d2e0000}, {0x3d2e2000}, {0x3d2e4000}, {0x3d2e6000}, + {0x3d2e8000}, {0x3d2ea000}, {0x3d2ec000}, {0x3d2ee000}, + {0x3d2f0000}, {0x3d2f2000}, {0x3d2f4000}, {0x3d2f6000}, + {0x3d2f8000}, {0x3d2fa000}, {0x3d2fc000}, {0x3d2fe000}, + {0x3d300000}, {0x3d302000}, {0x3d304000}, {0x3d306000}, + {0x3d308000}, {0x3d30a000}, {0x3d30c000}, {0x3d30e000}, + {0x3d310000}, {0x3d312000}, {0x3d314000}, {0x3d316000}, + {0x3d318000}, {0x3d31a000}, {0x3d31c000}, {0x3d31e000}, + {0x3d320000}, {0x3d322000}, {0x3d324000}, {0x3d326000}, + {0x3d328000}, {0x3d32a000}, {0x3d32c000}, {0x3d32e000}, + {0x3d330000}, {0x3d332000}, {0x3d334000}, {0x3d336000}, + {0x3d338000}, {0x3d33a000}, {0x3d33c000}, {0x3d33e000}, + {0x3d340000}, {0x3d342000}, {0x3d344000}, {0x3d346000}, + {0x3d348000}, {0x3d34a000}, {0x3d34c000}, {0x3d34e000}, + {0x3d350000}, {0x3d352000}, {0x3d354000}, {0x3d356000}, + {0x3d358000}, {0x3d35a000}, {0x3d35c000}, {0x3d35e000}, + {0x3d360000}, {0x3d362000}, {0x3d364000}, {0x3d366000}, + {0x3d368000}, {0x3d36a000}, {0x3d36c000}, {0x3d36e000}, + {0x3d370000}, {0x3d372000}, {0x3d374000}, {0x3d376000}, + {0x3d378000}, {0x3d37a000}, {0x3d37c000}, {0x3d37e000}, + {0x3d380000}, {0x3d382000}, {0x3d384000}, {0x3d386000}, + {0x3d388000}, {0x3d38a000}, {0x3d38c000}, {0x3d38e000}, + {0x3d390000}, {0x3d392000}, {0x3d394000}, {0x3d396000}, + {0x3d398000}, {0x3d39a000}, {0x3d39c000}, {0x3d39e000}, + {0x3d3a0000}, {0x3d3a2000}, {0x3d3a4000}, {0x3d3a6000}, + {0x3d3a8000}, {0x3d3aa000}, {0x3d3ac000}, {0x3d3ae000}, + {0x3d3b0000}, {0x3d3b2000}, {0x3d3b4000}, {0x3d3b6000}, + {0x3d3b8000}, {0x3d3ba000}, {0x3d3bc000}, {0x3d3be000}, + {0x3d3c0000}, {0x3d3c2000}, {0x3d3c4000}, {0x3d3c6000}, + {0x3d3c8000}, {0x3d3ca000}, {0x3d3cc000}, {0x3d3ce000}, + {0x3d3d0000}, {0x3d3d2000}, {0x3d3d4000}, {0x3d3d6000}, + {0x3d3d8000}, {0x3d3da000}, {0x3d3dc000}, {0x3d3de000}, + {0x3d3e0000}, {0x3d3e2000}, {0x3d3e4000}, {0x3d3e6000}, + {0x3d3e8000}, {0x3d3ea000}, {0x3d3ec000}, {0x3d3ee000}, + {0x3d3f0000}, {0x3d3f2000}, {0x3d3f4000}, {0x3d3f6000}, + {0x3d3f8000}, {0x3d3fa000}, {0x3d3fc000}, {0x3d3fe000}, + {0x3d400000}, {0x3d402000}, {0x3d404000}, {0x3d406000}, + {0x3d408000}, {0x3d40a000}, {0x3d40c000}, {0x3d40e000}, + {0x3d410000}, {0x3d412000}, {0x3d414000}, {0x3d416000}, + {0x3d418000}, {0x3d41a000}, {0x3d41c000}, {0x3d41e000}, + {0x3d420000}, {0x3d422000}, {0x3d424000}, {0x3d426000}, + {0x3d428000}, {0x3d42a000}, {0x3d42c000}, {0x3d42e000}, + {0x3d430000}, {0x3d432000}, {0x3d434000}, {0x3d436000}, + {0x3d438000}, {0x3d43a000}, {0x3d43c000}, {0x3d43e000}, + {0x3d440000}, {0x3d442000}, {0x3d444000}, {0x3d446000}, + {0x3d448000}, {0x3d44a000}, {0x3d44c000}, {0x3d44e000}, + {0x3d450000}, {0x3d452000}, {0x3d454000}, {0x3d456000}, + {0x3d458000}, {0x3d45a000}, {0x3d45c000}, {0x3d45e000}, + {0x3d460000}, {0x3d462000}, {0x3d464000}, {0x3d466000}, + {0x3d468000}, {0x3d46a000}, {0x3d46c000}, {0x3d46e000}, + {0x3d470000}, {0x3d472000}, {0x3d474000}, {0x3d476000}, + {0x3d478000}, {0x3d47a000}, {0x3d47c000}, {0x3d47e000}, + {0x3d480000}, {0x3d482000}, {0x3d484000}, {0x3d486000}, + {0x3d488000}, {0x3d48a000}, {0x3d48c000}, {0x3d48e000}, + {0x3d490000}, {0x3d492000}, {0x3d494000}, {0x3d496000}, + {0x3d498000}, {0x3d49a000}, {0x3d49c000}, {0x3d49e000}, + {0x3d4a0000}, {0x3d4a2000}, {0x3d4a4000}, {0x3d4a6000}, + {0x3d4a8000}, {0x3d4aa000}, {0x3d4ac000}, {0x3d4ae000}, + {0x3d4b0000}, {0x3d4b2000}, {0x3d4b4000}, {0x3d4b6000}, + {0x3d4b8000}, {0x3d4ba000}, {0x3d4bc000}, {0x3d4be000}, + {0x3d4c0000}, {0x3d4c2000}, {0x3d4c4000}, {0x3d4c6000}, + {0x3d4c8000}, {0x3d4ca000}, {0x3d4cc000}, {0x3d4ce000}, + {0x3d4d0000}, {0x3d4d2000}, {0x3d4d4000}, {0x3d4d6000}, + {0x3d4d8000}, {0x3d4da000}, {0x3d4dc000}, {0x3d4de000}, + {0x3d4e0000}, {0x3d4e2000}, {0x3d4e4000}, {0x3d4e6000}, + {0x3d4e8000}, {0x3d4ea000}, {0x3d4ec000}, {0x3d4ee000}, + {0x3d4f0000}, {0x3d4f2000}, {0x3d4f4000}, {0x3d4f6000}, + {0x3d4f8000}, {0x3d4fa000}, {0x3d4fc000}, {0x3d4fe000}, + {0x3d500000}, {0x3d502000}, {0x3d504000}, {0x3d506000}, + {0x3d508000}, {0x3d50a000}, {0x3d50c000}, {0x3d50e000}, + {0x3d510000}, {0x3d512000}, {0x3d514000}, {0x3d516000}, + {0x3d518000}, {0x3d51a000}, {0x3d51c000}, {0x3d51e000}, + {0x3d520000}, {0x3d522000}, {0x3d524000}, {0x3d526000}, + {0x3d528000}, {0x3d52a000}, {0x3d52c000}, {0x3d52e000}, + {0x3d530000}, {0x3d532000}, {0x3d534000}, {0x3d536000}, + {0x3d538000}, {0x3d53a000}, {0x3d53c000}, {0x3d53e000}, + {0x3d540000}, {0x3d542000}, {0x3d544000}, {0x3d546000}, + {0x3d548000}, {0x3d54a000}, {0x3d54c000}, {0x3d54e000}, + {0x3d550000}, {0x3d552000}, {0x3d554000}, {0x3d556000}, + {0x3d558000}, {0x3d55a000}, {0x3d55c000}, {0x3d55e000}, + {0x3d560000}, {0x3d562000}, {0x3d564000}, {0x3d566000}, + {0x3d568000}, {0x3d56a000}, {0x3d56c000}, {0x3d56e000}, + {0x3d570000}, {0x3d572000}, {0x3d574000}, {0x3d576000}, + {0x3d578000}, {0x3d57a000}, {0x3d57c000}, {0x3d57e000}, + {0x3d580000}, {0x3d582000}, {0x3d584000}, {0x3d586000}, + {0x3d588000}, {0x3d58a000}, {0x3d58c000}, {0x3d58e000}, + {0x3d590000}, {0x3d592000}, {0x3d594000}, {0x3d596000}, + {0x3d598000}, {0x3d59a000}, {0x3d59c000}, {0x3d59e000}, + {0x3d5a0000}, {0x3d5a2000}, {0x3d5a4000}, {0x3d5a6000}, + {0x3d5a8000}, {0x3d5aa000}, {0x3d5ac000}, {0x3d5ae000}, + {0x3d5b0000}, {0x3d5b2000}, {0x3d5b4000}, {0x3d5b6000}, + {0x3d5b8000}, {0x3d5ba000}, {0x3d5bc000}, {0x3d5be000}, + {0x3d5c0000}, {0x3d5c2000}, {0x3d5c4000}, {0x3d5c6000}, + {0x3d5c8000}, {0x3d5ca000}, {0x3d5cc000}, {0x3d5ce000}, + {0x3d5d0000}, {0x3d5d2000}, {0x3d5d4000}, {0x3d5d6000}, + {0x3d5d8000}, {0x3d5da000}, {0x3d5dc000}, {0x3d5de000}, + {0x3d5e0000}, {0x3d5e2000}, {0x3d5e4000}, {0x3d5e6000}, + {0x3d5e8000}, {0x3d5ea000}, {0x3d5ec000}, {0x3d5ee000}, + {0x3d5f0000}, {0x3d5f2000}, {0x3d5f4000}, {0x3d5f6000}, + {0x3d5f8000}, {0x3d5fa000}, {0x3d5fc000}, {0x3d5fe000}, + {0x3d600000}, {0x3d602000}, {0x3d604000}, {0x3d606000}, + {0x3d608000}, {0x3d60a000}, {0x3d60c000}, {0x3d60e000}, + {0x3d610000}, {0x3d612000}, {0x3d614000}, {0x3d616000}, + {0x3d618000}, {0x3d61a000}, {0x3d61c000}, {0x3d61e000}, + {0x3d620000}, {0x3d622000}, {0x3d624000}, {0x3d626000}, + {0x3d628000}, {0x3d62a000}, {0x3d62c000}, {0x3d62e000}, + {0x3d630000}, {0x3d632000}, {0x3d634000}, {0x3d636000}, + {0x3d638000}, {0x3d63a000}, {0x3d63c000}, {0x3d63e000}, + {0x3d640000}, {0x3d642000}, {0x3d644000}, {0x3d646000}, + {0x3d648000}, {0x3d64a000}, {0x3d64c000}, {0x3d64e000}, + {0x3d650000}, {0x3d652000}, {0x3d654000}, {0x3d656000}, + {0x3d658000}, {0x3d65a000}, {0x3d65c000}, {0x3d65e000}, + {0x3d660000}, {0x3d662000}, {0x3d664000}, {0x3d666000}, + {0x3d668000}, {0x3d66a000}, {0x3d66c000}, {0x3d66e000}, + {0x3d670000}, {0x3d672000}, {0x3d674000}, {0x3d676000}, + {0x3d678000}, {0x3d67a000}, {0x3d67c000}, {0x3d67e000}, + {0x3d680000}, {0x3d682000}, {0x3d684000}, {0x3d686000}, + {0x3d688000}, {0x3d68a000}, {0x3d68c000}, {0x3d68e000}, + {0x3d690000}, {0x3d692000}, {0x3d694000}, {0x3d696000}, + {0x3d698000}, {0x3d69a000}, {0x3d69c000}, {0x3d69e000}, + {0x3d6a0000}, {0x3d6a2000}, {0x3d6a4000}, {0x3d6a6000}, + {0x3d6a8000}, {0x3d6aa000}, {0x3d6ac000}, {0x3d6ae000}, + {0x3d6b0000}, {0x3d6b2000}, {0x3d6b4000}, {0x3d6b6000}, + {0x3d6b8000}, {0x3d6ba000}, {0x3d6bc000}, {0x3d6be000}, + {0x3d6c0000}, {0x3d6c2000}, {0x3d6c4000}, {0x3d6c6000}, + {0x3d6c8000}, {0x3d6ca000}, {0x3d6cc000}, {0x3d6ce000}, + {0x3d6d0000}, {0x3d6d2000}, {0x3d6d4000}, {0x3d6d6000}, + {0x3d6d8000}, {0x3d6da000}, {0x3d6dc000}, {0x3d6de000}, + {0x3d6e0000}, {0x3d6e2000}, {0x3d6e4000}, {0x3d6e6000}, + {0x3d6e8000}, {0x3d6ea000}, {0x3d6ec000}, {0x3d6ee000}, + {0x3d6f0000}, {0x3d6f2000}, {0x3d6f4000}, {0x3d6f6000}, + {0x3d6f8000}, {0x3d6fa000}, {0x3d6fc000}, {0x3d6fe000}, + {0x3d700000}, {0x3d702000}, {0x3d704000}, {0x3d706000}, + {0x3d708000}, {0x3d70a000}, {0x3d70c000}, {0x3d70e000}, + {0x3d710000}, {0x3d712000}, {0x3d714000}, {0x3d716000}, + {0x3d718000}, {0x3d71a000}, {0x3d71c000}, {0x3d71e000}, + {0x3d720000}, {0x3d722000}, {0x3d724000}, {0x3d726000}, + {0x3d728000}, {0x3d72a000}, {0x3d72c000}, {0x3d72e000}, + {0x3d730000}, {0x3d732000}, {0x3d734000}, {0x3d736000}, + {0x3d738000}, {0x3d73a000}, {0x3d73c000}, {0x3d73e000}, + {0x3d740000}, {0x3d742000}, {0x3d744000}, {0x3d746000}, + {0x3d748000}, {0x3d74a000}, {0x3d74c000}, {0x3d74e000}, + {0x3d750000}, {0x3d752000}, {0x3d754000}, {0x3d756000}, + {0x3d758000}, {0x3d75a000}, {0x3d75c000}, {0x3d75e000}, + {0x3d760000}, {0x3d762000}, {0x3d764000}, {0x3d766000}, + {0x3d768000}, {0x3d76a000}, {0x3d76c000}, {0x3d76e000}, + {0x3d770000}, {0x3d772000}, {0x3d774000}, {0x3d776000}, + {0x3d778000}, {0x3d77a000}, {0x3d77c000}, {0x3d77e000}, + {0x3d780000}, {0x3d782000}, {0x3d784000}, {0x3d786000}, + {0x3d788000}, {0x3d78a000}, {0x3d78c000}, {0x3d78e000}, + {0x3d790000}, {0x3d792000}, {0x3d794000}, {0x3d796000}, + {0x3d798000}, {0x3d79a000}, {0x3d79c000}, {0x3d79e000}, + {0x3d7a0000}, {0x3d7a2000}, {0x3d7a4000}, {0x3d7a6000}, + {0x3d7a8000}, {0x3d7aa000}, {0x3d7ac000}, {0x3d7ae000}, + {0x3d7b0000}, {0x3d7b2000}, {0x3d7b4000}, {0x3d7b6000}, + {0x3d7b8000}, {0x3d7ba000}, {0x3d7bc000}, {0x3d7be000}, + {0x3d7c0000}, {0x3d7c2000}, {0x3d7c4000}, {0x3d7c6000}, + {0x3d7c8000}, {0x3d7ca000}, {0x3d7cc000}, {0x3d7ce000}, + {0x3d7d0000}, {0x3d7d2000}, {0x3d7d4000}, {0x3d7d6000}, + {0x3d7d8000}, {0x3d7da000}, {0x3d7dc000}, {0x3d7de000}, + {0x3d7e0000}, {0x3d7e2000}, {0x3d7e4000}, {0x3d7e6000}, + {0x3d7e8000}, {0x3d7ea000}, {0x3d7ec000}, {0x3d7ee000}, + {0x3d7f0000}, {0x3d7f2000}, {0x3d7f4000}, {0x3d7f6000}, + {0x3d7f8000}, {0x3d7fa000}, {0x3d7fc000}, {0x3d7fe000}, + {0x3d800000}, {0x3d802000}, {0x3d804000}, {0x3d806000}, + {0x3d808000}, {0x3d80a000}, {0x3d80c000}, {0x3d80e000}, + {0x3d810000}, {0x3d812000}, {0x3d814000}, {0x3d816000}, + {0x3d818000}, {0x3d81a000}, {0x3d81c000}, {0x3d81e000}, + {0x3d820000}, {0x3d822000}, {0x3d824000}, {0x3d826000}, + {0x3d828000}, {0x3d82a000}, {0x3d82c000}, {0x3d82e000}, + {0x3d830000}, {0x3d832000}, {0x3d834000}, {0x3d836000}, + {0x3d838000}, {0x3d83a000}, {0x3d83c000}, {0x3d83e000}, + {0x3d840000}, {0x3d842000}, {0x3d844000}, {0x3d846000}, + {0x3d848000}, {0x3d84a000}, {0x3d84c000}, {0x3d84e000}, + {0x3d850000}, {0x3d852000}, {0x3d854000}, {0x3d856000}, + {0x3d858000}, {0x3d85a000}, {0x3d85c000}, {0x3d85e000}, + {0x3d860000}, {0x3d862000}, {0x3d864000}, {0x3d866000}, + {0x3d868000}, {0x3d86a000}, {0x3d86c000}, {0x3d86e000}, + {0x3d870000}, {0x3d872000}, {0x3d874000}, {0x3d876000}, + {0x3d878000}, {0x3d87a000}, {0x3d87c000}, {0x3d87e000}, + {0x3d880000}, {0x3d882000}, {0x3d884000}, {0x3d886000}, + {0x3d888000}, {0x3d88a000}, {0x3d88c000}, {0x3d88e000}, + {0x3d890000}, {0x3d892000}, {0x3d894000}, {0x3d896000}, + {0x3d898000}, {0x3d89a000}, {0x3d89c000}, {0x3d89e000}, + {0x3d8a0000}, {0x3d8a2000}, {0x3d8a4000}, {0x3d8a6000}, + {0x3d8a8000}, {0x3d8aa000}, {0x3d8ac000}, {0x3d8ae000}, + {0x3d8b0000}, {0x3d8b2000}, {0x3d8b4000}, {0x3d8b6000}, + {0x3d8b8000}, {0x3d8ba000}, {0x3d8bc000}, {0x3d8be000}, + {0x3d8c0000}, {0x3d8c2000}, {0x3d8c4000}, {0x3d8c6000}, + {0x3d8c8000}, {0x3d8ca000}, {0x3d8cc000}, {0x3d8ce000}, + {0x3d8d0000}, {0x3d8d2000}, {0x3d8d4000}, {0x3d8d6000}, + {0x3d8d8000}, {0x3d8da000}, {0x3d8dc000}, {0x3d8de000}, + {0x3d8e0000}, {0x3d8e2000}, {0x3d8e4000}, {0x3d8e6000}, + {0x3d8e8000}, {0x3d8ea000}, {0x3d8ec000}, {0x3d8ee000}, + {0x3d8f0000}, {0x3d8f2000}, {0x3d8f4000}, {0x3d8f6000}, + {0x3d8f8000}, {0x3d8fa000}, {0x3d8fc000}, {0x3d8fe000}, + {0x3d900000}, {0x3d902000}, {0x3d904000}, {0x3d906000}, + {0x3d908000}, {0x3d90a000}, {0x3d90c000}, {0x3d90e000}, + {0x3d910000}, {0x3d912000}, {0x3d914000}, {0x3d916000}, + {0x3d918000}, {0x3d91a000}, {0x3d91c000}, {0x3d91e000}, + {0x3d920000}, {0x3d922000}, {0x3d924000}, {0x3d926000}, + {0x3d928000}, {0x3d92a000}, {0x3d92c000}, {0x3d92e000}, + {0x3d930000}, {0x3d932000}, {0x3d934000}, {0x3d936000}, + {0x3d938000}, {0x3d93a000}, {0x3d93c000}, {0x3d93e000}, + {0x3d940000}, {0x3d942000}, {0x3d944000}, {0x3d946000}, + {0x3d948000}, {0x3d94a000}, {0x3d94c000}, {0x3d94e000}, + {0x3d950000}, {0x3d952000}, {0x3d954000}, {0x3d956000}, + {0x3d958000}, {0x3d95a000}, {0x3d95c000}, {0x3d95e000}, + {0x3d960000}, {0x3d962000}, {0x3d964000}, {0x3d966000}, + {0x3d968000}, {0x3d96a000}, {0x3d96c000}, {0x3d96e000}, + {0x3d970000}, {0x3d972000}, {0x3d974000}, {0x3d976000}, + {0x3d978000}, {0x3d97a000}, {0x3d97c000}, {0x3d97e000}, + {0x3d980000}, {0x3d982000}, {0x3d984000}, {0x3d986000}, + {0x3d988000}, {0x3d98a000}, {0x3d98c000}, {0x3d98e000}, + {0x3d990000}, {0x3d992000}, {0x3d994000}, {0x3d996000}, + {0x3d998000}, {0x3d99a000}, {0x3d99c000}, {0x3d99e000}, + {0x3d9a0000}, {0x3d9a2000}, {0x3d9a4000}, {0x3d9a6000}, + {0x3d9a8000}, {0x3d9aa000}, {0x3d9ac000}, {0x3d9ae000}, + {0x3d9b0000}, {0x3d9b2000}, {0x3d9b4000}, {0x3d9b6000}, + {0x3d9b8000}, {0x3d9ba000}, {0x3d9bc000}, {0x3d9be000}, + {0x3d9c0000}, {0x3d9c2000}, {0x3d9c4000}, {0x3d9c6000}, + {0x3d9c8000}, {0x3d9ca000}, {0x3d9cc000}, {0x3d9ce000}, + {0x3d9d0000}, {0x3d9d2000}, {0x3d9d4000}, {0x3d9d6000}, + {0x3d9d8000}, {0x3d9da000}, {0x3d9dc000}, {0x3d9de000}, + {0x3d9e0000}, {0x3d9e2000}, {0x3d9e4000}, {0x3d9e6000}, + {0x3d9e8000}, {0x3d9ea000}, {0x3d9ec000}, {0x3d9ee000}, + {0x3d9f0000}, {0x3d9f2000}, {0x3d9f4000}, {0x3d9f6000}, + {0x3d9f8000}, {0x3d9fa000}, {0x3d9fc000}, {0x3d9fe000}, + {0x3da00000}, {0x3da02000}, {0x3da04000}, {0x3da06000}, + {0x3da08000}, {0x3da0a000}, {0x3da0c000}, {0x3da0e000}, + {0x3da10000}, {0x3da12000}, {0x3da14000}, {0x3da16000}, + {0x3da18000}, {0x3da1a000}, {0x3da1c000}, {0x3da1e000}, + {0x3da20000}, {0x3da22000}, {0x3da24000}, {0x3da26000}, + {0x3da28000}, {0x3da2a000}, {0x3da2c000}, {0x3da2e000}, + {0x3da30000}, {0x3da32000}, {0x3da34000}, {0x3da36000}, + {0x3da38000}, {0x3da3a000}, {0x3da3c000}, {0x3da3e000}, + {0x3da40000}, {0x3da42000}, {0x3da44000}, {0x3da46000}, + {0x3da48000}, {0x3da4a000}, {0x3da4c000}, {0x3da4e000}, + {0x3da50000}, {0x3da52000}, {0x3da54000}, {0x3da56000}, + {0x3da58000}, {0x3da5a000}, {0x3da5c000}, {0x3da5e000}, + {0x3da60000}, {0x3da62000}, {0x3da64000}, {0x3da66000}, + {0x3da68000}, {0x3da6a000}, {0x3da6c000}, {0x3da6e000}, + {0x3da70000}, {0x3da72000}, {0x3da74000}, {0x3da76000}, + {0x3da78000}, {0x3da7a000}, {0x3da7c000}, {0x3da7e000}, + {0x3da80000}, {0x3da82000}, {0x3da84000}, {0x3da86000}, + {0x3da88000}, {0x3da8a000}, {0x3da8c000}, {0x3da8e000}, + {0x3da90000}, {0x3da92000}, {0x3da94000}, {0x3da96000}, + {0x3da98000}, {0x3da9a000}, {0x3da9c000}, {0x3da9e000}, + {0x3daa0000}, {0x3daa2000}, {0x3daa4000}, {0x3daa6000}, + {0x3daa8000}, {0x3daaa000}, {0x3daac000}, {0x3daae000}, + {0x3dab0000}, {0x3dab2000}, {0x3dab4000}, {0x3dab6000}, + {0x3dab8000}, {0x3daba000}, {0x3dabc000}, {0x3dabe000}, + {0x3dac0000}, {0x3dac2000}, {0x3dac4000}, {0x3dac6000}, + {0x3dac8000}, {0x3daca000}, {0x3dacc000}, {0x3dace000}, + {0x3dad0000}, {0x3dad2000}, {0x3dad4000}, {0x3dad6000}, + {0x3dad8000}, {0x3dada000}, {0x3dadc000}, {0x3dade000}, + {0x3dae0000}, {0x3dae2000}, {0x3dae4000}, {0x3dae6000}, + {0x3dae8000}, {0x3daea000}, {0x3daec000}, {0x3daee000}, + {0x3daf0000}, {0x3daf2000}, {0x3daf4000}, {0x3daf6000}, + {0x3daf8000}, {0x3dafa000}, {0x3dafc000}, {0x3dafe000}, + {0x3db00000}, {0x3db02000}, {0x3db04000}, {0x3db06000}, + {0x3db08000}, {0x3db0a000}, {0x3db0c000}, {0x3db0e000}, + {0x3db10000}, {0x3db12000}, {0x3db14000}, {0x3db16000}, + {0x3db18000}, {0x3db1a000}, {0x3db1c000}, {0x3db1e000}, + {0x3db20000}, {0x3db22000}, {0x3db24000}, {0x3db26000}, + {0x3db28000}, {0x3db2a000}, {0x3db2c000}, {0x3db2e000}, + {0x3db30000}, {0x3db32000}, {0x3db34000}, {0x3db36000}, + {0x3db38000}, {0x3db3a000}, {0x3db3c000}, {0x3db3e000}, + {0x3db40000}, {0x3db42000}, {0x3db44000}, {0x3db46000}, + {0x3db48000}, {0x3db4a000}, {0x3db4c000}, {0x3db4e000}, + {0x3db50000}, {0x3db52000}, {0x3db54000}, {0x3db56000}, + {0x3db58000}, {0x3db5a000}, {0x3db5c000}, {0x3db5e000}, + {0x3db60000}, {0x3db62000}, {0x3db64000}, {0x3db66000}, + {0x3db68000}, {0x3db6a000}, {0x3db6c000}, {0x3db6e000}, + {0x3db70000}, {0x3db72000}, {0x3db74000}, {0x3db76000}, + {0x3db78000}, {0x3db7a000}, {0x3db7c000}, {0x3db7e000}, + {0x3db80000}, {0x3db82000}, {0x3db84000}, {0x3db86000}, + {0x3db88000}, {0x3db8a000}, {0x3db8c000}, {0x3db8e000}, + {0x3db90000}, {0x3db92000}, {0x3db94000}, {0x3db96000}, + {0x3db98000}, {0x3db9a000}, {0x3db9c000}, {0x3db9e000}, + {0x3dba0000}, {0x3dba2000}, {0x3dba4000}, {0x3dba6000}, + {0x3dba8000}, {0x3dbaa000}, {0x3dbac000}, {0x3dbae000}, + {0x3dbb0000}, {0x3dbb2000}, {0x3dbb4000}, {0x3dbb6000}, + {0x3dbb8000}, {0x3dbba000}, {0x3dbbc000}, {0x3dbbe000}, + {0x3dbc0000}, {0x3dbc2000}, {0x3dbc4000}, {0x3dbc6000}, + {0x3dbc8000}, {0x3dbca000}, {0x3dbcc000}, {0x3dbce000}, + {0x3dbd0000}, {0x3dbd2000}, {0x3dbd4000}, {0x3dbd6000}, + {0x3dbd8000}, {0x3dbda000}, {0x3dbdc000}, {0x3dbde000}, + {0x3dbe0000}, {0x3dbe2000}, {0x3dbe4000}, {0x3dbe6000}, + {0x3dbe8000}, {0x3dbea000}, {0x3dbec000}, {0x3dbee000}, + {0x3dbf0000}, {0x3dbf2000}, {0x3dbf4000}, {0x3dbf6000}, + {0x3dbf8000}, {0x3dbfa000}, {0x3dbfc000}, {0x3dbfe000}, + {0x3dc00000}, {0x3dc02000}, {0x3dc04000}, {0x3dc06000}, + {0x3dc08000}, {0x3dc0a000}, {0x3dc0c000}, {0x3dc0e000}, + {0x3dc10000}, {0x3dc12000}, {0x3dc14000}, {0x3dc16000}, + {0x3dc18000}, {0x3dc1a000}, {0x3dc1c000}, {0x3dc1e000}, + {0x3dc20000}, {0x3dc22000}, {0x3dc24000}, {0x3dc26000}, + {0x3dc28000}, {0x3dc2a000}, {0x3dc2c000}, {0x3dc2e000}, + {0x3dc30000}, {0x3dc32000}, {0x3dc34000}, {0x3dc36000}, + {0x3dc38000}, {0x3dc3a000}, {0x3dc3c000}, {0x3dc3e000}, + {0x3dc40000}, {0x3dc42000}, {0x3dc44000}, {0x3dc46000}, + {0x3dc48000}, {0x3dc4a000}, {0x3dc4c000}, {0x3dc4e000}, + {0x3dc50000}, {0x3dc52000}, {0x3dc54000}, {0x3dc56000}, + {0x3dc58000}, {0x3dc5a000}, {0x3dc5c000}, {0x3dc5e000}, + {0x3dc60000}, {0x3dc62000}, {0x3dc64000}, {0x3dc66000}, + {0x3dc68000}, {0x3dc6a000}, {0x3dc6c000}, {0x3dc6e000}, + {0x3dc70000}, {0x3dc72000}, {0x3dc74000}, {0x3dc76000}, + {0x3dc78000}, {0x3dc7a000}, {0x3dc7c000}, {0x3dc7e000}, + {0x3dc80000}, {0x3dc82000}, {0x3dc84000}, {0x3dc86000}, + {0x3dc88000}, {0x3dc8a000}, {0x3dc8c000}, {0x3dc8e000}, + {0x3dc90000}, {0x3dc92000}, {0x3dc94000}, {0x3dc96000}, + {0x3dc98000}, {0x3dc9a000}, {0x3dc9c000}, {0x3dc9e000}, + {0x3dca0000}, {0x3dca2000}, {0x3dca4000}, {0x3dca6000}, + {0x3dca8000}, {0x3dcaa000}, {0x3dcac000}, {0x3dcae000}, + {0x3dcb0000}, {0x3dcb2000}, {0x3dcb4000}, {0x3dcb6000}, + {0x3dcb8000}, {0x3dcba000}, {0x3dcbc000}, {0x3dcbe000}, + {0x3dcc0000}, {0x3dcc2000}, {0x3dcc4000}, {0x3dcc6000}, + {0x3dcc8000}, {0x3dcca000}, {0x3dccc000}, {0x3dcce000}, + {0x3dcd0000}, {0x3dcd2000}, {0x3dcd4000}, {0x3dcd6000}, + {0x3dcd8000}, {0x3dcda000}, {0x3dcdc000}, {0x3dcde000}, + {0x3dce0000}, {0x3dce2000}, {0x3dce4000}, {0x3dce6000}, + {0x3dce8000}, {0x3dcea000}, {0x3dcec000}, {0x3dcee000}, + {0x3dcf0000}, {0x3dcf2000}, {0x3dcf4000}, {0x3dcf6000}, + {0x3dcf8000}, {0x3dcfa000}, {0x3dcfc000}, {0x3dcfe000}, + {0x3dd00000}, {0x3dd02000}, {0x3dd04000}, {0x3dd06000}, + {0x3dd08000}, {0x3dd0a000}, {0x3dd0c000}, {0x3dd0e000}, + {0x3dd10000}, {0x3dd12000}, {0x3dd14000}, {0x3dd16000}, + {0x3dd18000}, {0x3dd1a000}, {0x3dd1c000}, {0x3dd1e000}, + {0x3dd20000}, {0x3dd22000}, {0x3dd24000}, {0x3dd26000}, + {0x3dd28000}, {0x3dd2a000}, {0x3dd2c000}, {0x3dd2e000}, + {0x3dd30000}, {0x3dd32000}, {0x3dd34000}, {0x3dd36000}, + {0x3dd38000}, {0x3dd3a000}, {0x3dd3c000}, {0x3dd3e000}, + {0x3dd40000}, {0x3dd42000}, {0x3dd44000}, {0x3dd46000}, + {0x3dd48000}, {0x3dd4a000}, {0x3dd4c000}, {0x3dd4e000}, + {0x3dd50000}, {0x3dd52000}, {0x3dd54000}, {0x3dd56000}, + {0x3dd58000}, {0x3dd5a000}, {0x3dd5c000}, {0x3dd5e000}, + {0x3dd60000}, {0x3dd62000}, {0x3dd64000}, {0x3dd66000}, + {0x3dd68000}, {0x3dd6a000}, {0x3dd6c000}, {0x3dd6e000}, + {0x3dd70000}, {0x3dd72000}, {0x3dd74000}, {0x3dd76000}, + {0x3dd78000}, {0x3dd7a000}, {0x3dd7c000}, {0x3dd7e000}, + {0x3dd80000}, {0x3dd82000}, {0x3dd84000}, {0x3dd86000}, + {0x3dd88000}, {0x3dd8a000}, {0x3dd8c000}, {0x3dd8e000}, + {0x3dd90000}, {0x3dd92000}, {0x3dd94000}, {0x3dd96000}, + {0x3dd98000}, {0x3dd9a000}, {0x3dd9c000}, {0x3dd9e000}, + {0x3dda0000}, {0x3dda2000}, {0x3dda4000}, {0x3dda6000}, + {0x3dda8000}, {0x3ddaa000}, {0x3ddac000}, {0x3ddae000}, + {0x3ddb0000}, {0x3ddb2000}, {0x3ddb4000}, {0x3ddb6000}, + {0x3ddb8000}, {0x3ddba000}, {0x3ddbc000}, {0x3ddbe000}, + {0x3ddc0000}, {0x3ddc2000}, {0x3ddc4000}, {0x3ddc6000}, + {0x3ddc8000}, {0x3ddca000}, {0x3ddcc000}, {0x3ddce000}, + {0x3ddd0000}, {0x3ddd2000}, {0x3ddd4000}, {0x3ddd6000}, + {0x3ddd8000}, {0x3ddda000}, {0x3dddc000}, {0x3ddde000}, + {0x3dde0000}, {0x3dde2000}, {0x3dde4000}, {0x3dde6000}, + {0x3dde8000}, {0x3ddea000}, {0x3ddec000}, {0x3ddee000}, + {0x3ddf0000}, {0x3ddf2000}, {0x3ddf4000}, {0x3ddf6000}, + {0x3ddf8000}, {0x3ddfa000}, {0x3ddfc000}, {0x3ddfe000}, + {0x3de00000}, {0x3de02000}, {0x3de04000}, {0x3de06000}, + {0x3de08000}, {0x3de0a000}, {0x3de0c000}, {0x3de0e000}, + {0x3de10000}, {0x3de12000}, {0x3de14000}, {0x3de16000}, + {0x3de18000}, {0x3de1a000}, {0x3de1c000}, {0x3de1e000}, + {0x3de20000}, {0x3de22000}, {0x3de24000}, {0x3de26000}, + {0x3de28000}, {0x3de2a000}, {0x3de2c000}, {0x3de2e000}, + {0x3de30000}, {0x3de32000}, {0x3de34000}, {0x3de36000}, + {0x3de38000}, {0x3de3a000}, {0x3de3c000}, {0x3de3e000}, + {0x3de40000}, {0x3de42000}, {0x3de44000}, {0x3de46000}, + {0x3de48000}, {0x3de4a000}, {0x3de4c000}, {0x3de4e000}, + {0x3de50000}, {0x3de52000}, {0x3de54000}, {0x3de56000}, + {0x3de58000}, {0x3de5a000}, {0x3de5c000}, {0x3de5e000}, + {0x3de60000}, {0x3de62000}, {0x3de64000}, {0x3de66000}, + {0x3de68000}, {0x3de6a000}, {0x3de6c000}, {0x3de6e000}, + {0x3de70000}, {0x3de72000}, {0x3de74000}, {0x3de76000}, + {0x3de78000}, {0x3de7a000}, {0x3de7c000}, {0x3de7e000}, + {0x3de80000}, {0x3de82000}, {0x3de84000}, {0x3de86000}, + {0x3de88000}, {0x3de8a000}, {0x3de8c000}, {0x3de8e000}, + {0x3de90000}, {0x3de92000}, {0x3de94000}, {0x3de96000}, + {0x3de98000}, {0x3de9a000}, {0x3de9c000}, {0x3de9e000}, + {0x3dea0000}, {0x3dea2000}, {0x3dea4000}, {0x3dea6000}, + {0x3dea8000}, {0x3deaa000}, {0x3deac000}, {0x3deae000}, + {0x3deb0000}, {0x3deb2000}, {0x3deb4000}, {0x3deb6000}, + {0x3deb8000}, {0x3deba000}, {0x3debc000}, {0x3debe000}, + {0x3dec0000}, {0x3dec2000}, {0x3dec4000}, {0x3dec6000}, + {0x3dec8000}, {0x3deca000}, {0x3decc000}, {0x3dece000}, + {0x3ded0000}, {0x3ded2000}, {0x3ded4000}, {0x3ded6000}, + {0x3ded8000}, {0x3deda000}, {0x3dedc000}, {0x3dede000}, + {0x3dee0000}, {0x3dee2000}, {0x3dee4000}, {0x3dee6000}, + {0x3dee8000}, {0x3deea000}, {0x3deec000}, {0x3deee000}, + {0x3def0000}, {0x3def2000}, {0x3def4000}, {0x3def6000}, + {0x3def8000}, {0x3defa000}, {0x3defc000}, {0x3defe000}, + {0x3df00000}, {0x3df02000}, {0x3df04000}, {0x3df06000}, + {0x3df08000}, {0x3df0a000}, {0x3df0c000}, {0x3df0e000}, + {0x3df10000}, {0x3df12000}, {0x3df14000}, {0x3df16000}, + {0x3df18000}, {0x3df1a000}, {0x3df1c000}, {0x3df1e000}, + {0x3df20000}, {0x3df22000}, {0x3df24000}, {0x3df26000}, + {0x3df28000}, {0x3df2a000}, {0x3df2c000}, {0x3df2e000}, + {0x3df30000}, {0x3df32000}, {0x3df34000}, {0x3df36000}, + {0x3df38000}, {0x3df3a000}, {0x3df3c000}, {0x3df3e000}, + {0x3df40000}, {0x3df42000}, {0x3df44000}, {0x3df46000}, + {0x3df48000}, {0x3df4a000}, {0x3df4c000}, {0x3df4e000}, + {0x3df50000}, {0x3df52000}, {0x3df54000}, {0x3df56000}, + {0x3df58000}, {0x3df5a000}, {0x3df5c000}, {0x3df5e000}, + {0x3df60000}, {0x3df62000}, {0x3df64000}, {0x3df66000}, + {0x3df68000}, {0x3df6a000}, {0x3df6c000}, {0x3df6e000}, + {0x3df70000}, {0x3df72000}, {0x3df74000}, {0x3df76000}, + {0x3df78000}, {0x3df7a000}, {0x3df7c000}, {0x3df7e000}, + {0x3df80000}, {0x3df82000}, {0x3df84000}, {0x3df86000}, + {0x3df88000}, {0x3df8a000}, {0x3df8c000}, {0x3df8e000}, + {0x3df90000}, {0x3df92000}, {0x3df94000}, {0x3df96000}, + {0x3df98000}, {0x3df9a000}, {0x3df9c000}, {0x3df9e000}, + {0x3dfa0000}, {0x3dfa2000}, {0x3dfa4000}, {0x3dfa6000}, + {0x3dfa8000}, {0x3dfaa000}, {0x3dfac000}, {0x3dfae000}, + {0x3dfb0000}, {0x3dfb2000}, {0x3dfb4000}, {0x3dfb6000}, + {0x3dfb8000}, {0x3dfba000}, {0x3dfbc000}, {0x3dfbe000}, + {0x3dfc0000}, {0x3dfc2000}, {0x3dfc4000}, {0x3dfc6000}, + {0x3dfc8000}, {0x3dfca000}, {0x3dfcc000}, {0x3dfce000}, + {0x3dfd0000}, {0x3dfd2000}, {0x3dfd4000}, {0x3dfd6000}, + {0x3dfd8000}, {0x3dfda000}, {0x3dfdc000}, {0x3dfde000}, + {0x3dfe0000}, {0x3dfe2000}, {0x3dfe4000}, {0x3dfe6000}, + {0x3dfe8000}, {0x3dfea000}, {0x3dfec000}, {0x3dfee000}, + {0x3dff0000}, {0x3dff2000}, {0x3dff4000}, {0x3dff6000}, + {0x3dff8000}, {0x3dffa000}, {0x3dffc000}, {0x3dffe000}, + {0x3e000000}, {0x3e002000}, {0x3e004000}, {0x3e006000}, + {0x3e008000}, {0x3e00a000}, {0x3e00c000}, {0x3e00e000}, + {0x3e010000}, {0x3e012000}, {0x3e014000}, {0x3e016000}, + {0x3e018000}, {0x3e01a000}, {0x3e01c000}, {0x3e01e000}, + {0x3e020000}, {0x3e022000}, {0x3e024000}, {0x3e026000}, + {0x3e028000}, {0x3e02a000}, {0x3e02c000}, {0x3e02e000}, + {0x3e030000}, {0x3e032000}, {0x3e034000}, {0x3e036000}, + {0x3e038000}, {0x3e03a000}, {0x3e03c000}, {0x3e03e000}, + {0x3e040000}, {0x3e042000}, {0x3e044000}, {0x3e046000}, + {0x3e048000}, {0x3e04a000}, {0x3e04c000}, {0x3e04e000}, + {0x3e050000}, {0x3e052000}, {0x3e054000}, {0x3e056000}, + {0x3e058000}, {0x3e05a000}, {0x3e05c000}, {0x3e05e000}, + {0x3e060000}, {0x3e062000}, {0x3e064000}, {0x3e066000}, + {0x3e068000}, {0x3e06a000}, {0x3e06c000}, {0x3e06e000}, + {0x3e070000}, {0x3e072000}, {0x3e074000}, {0x3e076000}, + {0x3e078000}, {0x3e07a000}, {0x3e07c000}, {0x3e07e000}, + {0x3e080000}, {0x3e082000}, {0x3e084000}, {0x3e086000}, + {0x3e088000}, {0x3e08a000}, {0x3e08c000}, {0x3e08e000}, + {0x3e090000}, {0x3e092000}, {0x3e094000}, {0x3e096000}, + {0x3e098000}, {0x3e09a000}, {0x3e09c000}, {0x3e09e000}, + {0x3e0a0000}, {0x3e0a2000}, {0x3e0a4000}, {0x3e0a6000}, + {0x3e0a8000}, {0x3e0aa000}, {0x3e0ac000}, {0x3e0ae000}, + {0x3e0b0000}, {0x3e0b2000}, {0x3e0b4000}, {0x3e0b6000}, + {0x3e0b8000}, {0x3e0ba000}, {0x3e0bc000}, {0x3e0be000}, + {0x3e0c0000}, {0x3e0c2000}, {0x3e0c4000}, {0x3e0c6000}, + {0x3e0c8000}, {0x3e0ca000}, {0x3e0cc000}, {0x3e0ce000}, + {0x3e0d0000}, {0x3e0d2000}, {0x3e0d4000}, {0x3e0d6000}, + {0x3e0d8000}, {0x3e0da000}, {0x3e0dc000}, {0x3e0de000}, + {0x3e0e0000}, {0x3e0e2000}, {0x3e0e4000}, {0x3e0e6000}, + {0x3e0e8000}, {0x3e0ea000}, {0x3e0ec000}, {0x3e0ee000}, + {0x3e0f0000}, {0x3e0f2000}, {0x3e0f4000}, {0x3e0f6000}, + {0x3e0f8000}, {0x3e0fa000}, {0x3e0fc000}, {0x3e0fe000}, + {0x3e100000}, {0x3e102000}, {0x3e104000}, {0x3e106000}, + {0x3e108000}, {0x3e10a000}, {0x3e10c000}, {0x3e10e000}, + {0x3e110000}, {0x3e112000}, {0x3e114000}, {0x3e116000}, + {0x3e118000}, {0x3e11a000}, {0x3e11c000}, {0x3e11e000}, + {0x3e120000}, {0x3e122000}, {0x3e124000}, {0x3e126000}, + {0x3e128000}, {0x3e12a000}, {0x3e12c000}, {0x3e12e000}, + {0x3e130000}, {0x3e132000}, {0x3e134000}, {0x3e136000}, + {0x3e138000}, {0x3e13a000}, {0x3e13c000}, {0x3e13e000}, + {0x3e140000}, {0x3e142000}, {0x3e144000}, {0x3e146000}, + {0x3e148000}, {0x3e14a000}, {0x3e14c000}, {0x3e14e000}, + {0x3e150000}, {0x3e152000}, {0x3e154000}, {0x3e156000}, + {0x3e158000}, {0x3e15a000}, {0x3e15c000}, {0x3e15e000}, + {0x3e160000}, {0x3e162000}, {0x3e164000}, {0x3e166000}, + {0x3e168000}, {0x3e16a000}, {0x3e16c000}, {0x3e16e000}, + {0x3e170000}, {0x3e172000}, {0x3e174000}, {0x3e176000}, + {0x3e178000}, {0x3e17a000}, {0x3e17c000}, {0x3e17e000}, + {0x3e180000}, {0x3e182000}, {0x3e184000}, {0x3e186000}, + {0x3e188000}, {0x3e18a000}, {0x3e18c000}, {0x3e18e000}, + {0x3e190000}, {0x3e192000}, {0x3e194000}, {0x3e196000}, + {0x3e198000}, {0x3e19a000}, {0x3e19c000}, {0x3e19e000}, + {0x3e1a0000}, {0x3e1a2000}, {0x3e1a4000}, {0x3e1a6000}, + {0x3e1a8000}, {0x3e1aa000}, {0x3e1ac000}, {0x3e1ae000}, + {0x3e1b0000}, {0x3e1b2000}, {0x3e1b4000}, {0x3e1b6000}, + {0x3e1b8000}, {0x3e1ba000}, {0x3e1bc000}, {0x3e1be000}, + {0x3e1c0000}, {0x3e1c2000}, {0x3e1c4000}, {0x3e1c6000}, + {0x3e1c8000}, {0x3e1ca000}, {0x3e1cc000}, {0x3e1ce000}, + {0x3e1d0000}, {0x3e1d2000}, {0x3e1d4000}, {0x3e1d6000}, + {0x3e1d8000}, {0x3e1da000}, {0x3e1dc000}, {0x3e1de000}, + {0x3e1e0000}, {0x3e1e2000}, {0x3e1e4000}, {0x3e1e6000}, + {0x3e1e8000}, {0x3e1ea000}, {0x3e1ec000}, {0x3e1ee000}, + {0x3e1f0000}, {0x3e1f2000}, {0x3e1f4000}, {0x3e1f6000}, + {0x3e1f8000}, {0x3e1fa000}, {0x3e1fc000}, {0x3e1fe000}, + {0x3e200000}, {0x3e202000}, {0x3e204000}, {0x3e206000}, + {0x3e208000}, {0x3e20a000}, {0x3e20c000}, {0x3e20e000}, + {0x3e210000}, {0x3e212000}, {0x3e214000}, {0x3e216000}, + {0x3e218000}, {0x3e21a000}, {0x3e21c000}, {0x3e21e000}, + {0x3e220000}, {0x3e222000}, {0x3e224000}, {0x3e226000}, + {0x3e228000}, {0x3e22a000}, {0x3e22c000}, {0x3e22e000}, + {0x3e230000}, {0x3e232000}, {0x3e234000}, {0x3e236000}, + {0x3e238000}, {0x3e23a000}, {0x3e23c000}, {0x3e23e000}, + {0x3e240000}, {0x3e242000}, {0x3e244000}, {0x3e246000}, + {0x3e248000}, {0x3e24a000}, {0x3e24c000}, {0x3e24e000}, + {0x3e250000}, {0x3e252000}, {0x3e254000}, {0x3e256000}, + {0x3e258000}, {0x3e25a000}, {0x3e25c000}, {0x3e25e000}, + {0x3e260000}, {0x3e262000}, {0x3e264000}, {0x3e266000}, + {0x3e268000}, {0x3e26a000}, {0x3e26c000}, {0x3e26e000}, + {0x3e270000}, {0x3e272000}, {0x3e274000}, {0x3e276000}, + {0x3e278000}, {0x3e27a000}, {0x3e27c000}, {0x3e27e000}, + {0x3e280000}, {0x3e282000}, {0x3e284000}, {0x3e286000}, + {0x3e288000}, {0x3e28a000}, {0x3e28c000}, {0x3e28e000}, + {0x3e290000}, {0x3e292000}, {0x3e294000}, {0x3e296000}, + {0x3e298000}, {0x3e29a000}, {0x3e29c000}, {0x3e29e000}, + {0x3e2a0000}, {0x3e2a2000}, {0x3e2a4000}, {0x3e2a6000}, + {0x3e2a8000}, {0x3e2aa000}, {0x3e2ac000}, {0x3e2ae000}, + {0x3e2b0000}, {0x3e2b2000}, {0x3e2b4000}, {0x3e2b6000}, + {0x3e2b8000}, {0x3e2ba000}, {0x3e2bc000}, {0x3e2be000}, + {0x3e2c0000}, {0x3e2c2000}, {0x3e2c4000}, {0x3e2c6000}, + {0x3e2c8000}, {0x3e2ca000}, {0x3e2cc000}, {0x3e2ce000}, + {0x3e2d0000}, {0x3e2d2000}, {0x3e2d4000}, {0x3e2d6000}, + {0x3e2d8000}, {0x3e2da000}, {0x3e2dc000}, {0x3e2de000}, + {0x3e2e0000}, {0x3e2e2000}, {0x3e2e4000}, {0x3e2e6000}, + {0x3e2e8000}, {0x3e2ea000}, {0x3e2ec000}, {0x3e2ee000}, + {0x3e2f0000}, {0x3e2f2000}, {0x3e2f4000}, {0x3e2f6000}, + {0x3e2f8000}, {0x3e2fa000}, {0x3e2fc000}, {0x3e2fe000}, + {0x3e300000}, {0x3e302000}, {0x3e304000}, {0x3e306000}, + {0x3e308000}, {0x3e30a000}, {0x3e30c000}, {0x3e30e000}, + {0x3e310000}, {0x3e312000}, {0x3e314000}, {0x3e316000}, + {0x3e318000}, {0x3e31a000}, {0x3e31c000}, {0x3e31e000}, + {0x3e320000}, {0x3e322000}, {0x3e324000}, {0x3e326000}, + {0x3e328000}, {0x3e32a000}, {0x3e32c000}, {0x3e32e000}, + {0x3e330000}, {0x3e332000}, {0x3e334000}, {0x3e336000}, + {0x3e338000}, {0x3e33a000}, {0x3e33c000}, {0x3e33e000}, + {0x3e340000}, {0x3e342000}, {0x3e344000}, {0x3e346000}, + {0x3e348000}, {0x3e34a000}, {0x3e34c000}, {0x3e34e000}, + {0x3e350000}, {0x3e352000}, {0x3e354000}, {0x3e356000}, + {0x3e358000}, {0x3e35a000}, {0x3e35c000}, {0x3e35e000}, + {0x3e360000}, {0x3e362000}, {0x3e364000}, {0x3e366000}, + {0x3e368000}, {0x3e36a000}, {0x3e36c000}, {0x3e36e000}, + {0x3e370000}, {0x3e372000}, {0x3e374000}, {0x3e376000}, + {0x3e378000}, {0x3e37a000}, {0x3e37c000}, {0x3e37e000}, + {0x3e380000}, {0x3e382000}, {0x3e384000}, {0x3e386000}, + {0x3e388000}, {0x3e38a000}, {0x3e38c000}, {0x3e38e000}, + {0x3e390000}, {0x3e392000}, {0x3e394000}, {0x3e396000}, + {0x3e398000}, {0x3e39a000}, {0x3e39c000}, {0x3e39e000}, + {0x3e3a0000}, {0x3e3a2000}, {0x3e3a4000}, {0x3e3a6000}, + {0x3e3a8000}, {0x3e3aa000}, {0x3e3ac000}, {0x3e3ae000}, + {0x3e3b0000}, {0x3e3b2000}, {0x3e3b4000}, {0x3e3b6000}, + {0x3e3b8000}, {0x3e3ba000}, {0x3e3bc000}, {0x3e3be000}, + {0x3e3c0000}, {0x3e3c2000}, {0x3e3c4000}, {0x3e3c6000}, + {0x3e3c8000}, {0x3e3ca000}, {0x3e3cc000}, {0x3e3ce000}, + {0x3e3d0000}, {0x3e3d2000}, {0x3e3d4000}, {0x3e3d6000}, + {0x3e3d8000}, {0x3e3da000}, {0x3e3dc000}, {0x3e3de000}, + {0x3e3e0000}, {0x3e3e2000}, {0x3e3e4000}, {0x3e3e6000}, + {0x3e3e8000}, {0x3e3ea000}, {0x3e3ec000}, {0x3e3ee000}, + {0x3e3f0000}, {0x3e3f2000}, {0x3e3f4000}, {0x3e3f6000}, + {0x3e3f8000}, {0x3e3fa000}, {0x3e3fc000}, {0x3e3fe000}, + {0x3e400000}, {0x3e402000}, {0x3e404000}, {0x3e406000}, + {0x3e408000}, {0x3e40a000}, {0x3e40c000}, {0x3e40e000}, + {0x3e410000}, {0x3e412000}, {0x3e414000}, {0x3e416000}, + {0x3e418000}, {0x3e41a000}, {0x3e41c000}, {0x3e41e000}, + {0x3e420000}, {0x3e422000}, {0x3e424000}, {0x3e426000}, + {0x3e428000}, {0x3e42a000}, {0x3e42c000}, {0x3e42e000}, + {0x3e430000}, {0x3e432000}, {0x3e434000}, {0x3e436000}, + {0x3e438000}, {0x3e43a000}, {0x3e43c000}, {0x3e43e000}, + {0x3e440000}, {0x3e442000}, {0x3e444000}, {0x3e446000}, + {0x3e448000}, {0x3e44a000}, {0x3e44c000}, {0x3e44e000}, + {0x3e450000}, {0x3e452000}, {0x3e454000}, {0x3e456000}, + {0x3e458000}, {0x3e45a000}, {0x3e45c000}, {0x3e45e000}, + {0x3e460000}, {0x3e462000}, {0x3e464000}, {0x3e466000}, + {0x3e468000}, {0x3e46a000}, {0x3e46c000}, {0x3e46e000}, + {0x3e470000}, {0x3e472000}, {0x3e474000}, {0x3e476000}, + {0x3e478000}, {0x3e47a000}, {0x3e47c000}, {0x3e47e000}, + {0x3e480000}, {0x3e482000}, {0x3e484000}, {0x3e486000}, + {0x3e488000}, {0x3e48a000}, {0x3e48c000}, {0x3e48e000}, + {0x3e490000}, {0x3e492000}, {0x3e494000}, {0x3e496000}, + {0x3e498000}, {0x3e49a000}, {0x3e49c000}, {0x3e49e000}, + {0x3e4a0000}, {0x3e4a2000}, {0x3e4a4000}, {0x3e4a6000}, + {0x3e4a8000}, {0x3e4aa000}, {0x3e4ac000}, {0x3e4ae000}, + {0x3e4b0000}, {0x3e4b2000}, {0x3e4b4000}, {0x3e4b6000}, + {0x3e4b8000}, {0x3e4ba000}, {0x3e4bc000}, {0x3e4be000}, + {0x3e4c0000}, {0x3e4c2000}, {0x3e4c4000}, {0x3e4c6000}, + {0x3e4c8000}, {0x3e4ca000}, {0x3e4cc000}, {0x3e4ce000}, + {0x3e4d0000}, {0x3e4d2000}, {0x3e4d4000}, {0x3e4d6000}, + {0x3e4d8000}, {0x3e4da000}, {0x3e4dc000}, {0x3e4de000}, + {0x3e4e0000}, {0x3e4e2000}, {0x3e4e4000}, {0x3e4e6000}, + {0x3e4e8000}, {0x3e4ea000}, {0x3e4ec000}, {0x3e4ee000}, + {0x3e4f0000}, {0x3e4f2000}, {0x3e4f4000}, {0x3e4f6000}, + {0x3e4f8000}, {0x3e4fa000}, {0x3e4fc000}, {0x3e4fe000}, + {0x3e500000}, {0x3e502000}, {0x3e504000}, {0x3e506000}, + {0x3e508000}, {0x3e50a000}, {0x3e50c000}, {0x3e50e000}, + {0x3e510000}, {0x3e512000}, {0x3e514000}, {0x3e516000}, + {0x3e518000}, {0x3e51a000}, {0x3e51c000}, {0x3e51e000}, + {0x3e520000}, {0x3e522000}, {0x3e524000}, {0x3e526000}, + {0x3e528000}, {0x3e52a000}, {0x3e52c000}, {0x3e52e000}, + {0x3e530000}, {0x3e532000}, {0x3e534000}, {0x3e536000}, + {0x3e538000}, {0x3e53a000}, {0x3e53c000}, {0x3e53e000}, + {0x3e540000}, {0x3e542000}, {0x3e544000}, {0x3e546000}, + {0x3e548000}, {0x3e54a000}, {0x3e54c000}, {0x3e54e000}, + {0x3e550000}, {0x3e552000}, {0x3e554000}, {0x3e556000}, + {0x3e558000}, {0x3e55a000}, {0x3e55c000}, {0x3e55e000}, + {0x3e560000}, {0x3e562000}, {0x3e564000}, {0x3e566000}, + {0x3e568000}, {0x3e56a000}, {0x3e56c000}, {0x3e56e000}, + {0x3e570000}, {0x3e572000}, {0x3e574000}, {0x3e576000}, + {0x3e578000}, {0x3e57a000}, {0x3e57c000}, {0x3e57e000}, + {0x3e580000}, {0x3e582000}, {0x3e584000}, {0x3e586000}, + {0x3e588000}, {0x3e58a000}, {0x3e58c000}, {0x3e58e000}, + {0x3e590000}, {0x3e592000}, {0x3e594000}, {0x3e596000}, + {0x3e598000}, {0x3e59a000}, {0x3e59c000}, {0x3e59e000}, + {0x3e5a0000}, {0x3e5a2000}, {0x3e5a4000}, {0x3e5a6000}, + {0x3e5a8000}, {0x3e5aa000}, {0x3e5ac000}, {0x3e5ae000}, + {0x3e5b0000}, {0x3e5b2000}, {0x3e5b4000}, {0x3e5b6000}, + {0x3e5b8000}, {0x3e5ba000}, {0x3e5bc000}, {0x3e5be000}, + {0x3e5c0000}, {0x3e5c2000}, {0x3e5c4000}, {0x3e5c6000}, + {0x3e5c8000}, {0x3e5ca000}, {0x3e5cc000}, {0x3e5ce000}, + {0x3e5d0000}, {0x3e5d2000}, {0x3e5d4000}, {0x3e5d6000}, + {0x3e5d8000}, {0x3e5da000}, {0x3e5dc000}, {0x3e5de000}, + {0x3e5e0000}, {0x3e5e2000}, {0x3e5e4000}, {0x3e5e6000}, + {0x3e5e8000}, {0x3e5ea000}, {0x3e5ec000}, {0x3e5ee000}, + {0x3e5f0000}, {0x3e5f2000}, {0x3e5f4000}, {0x3e5f6000}, + {0x3e5f8000}, {0x3e5fa000}, {0x3e5fc000}, {0x3e5fe000}, + {0x3e600000}, {0x3e602000}, {0x3e604000}, {0x3e606000}, + {0x3e608000}, {0x3e60a000}, {0x3e60c000}, {0x3e60e000}, + {0x3e610000}, {0x3e612000}, {0x3e614000}, {0x3e616000}, + {0x3e618000}, {0x3e61a000}, {0x3e61c000}, {0x3e61e000}, + {0x3e620000}, {0x3e622000}, {0x3e624000}, {0x3e626000}, + {0x3e628000}, {0x3e62a000}, {0x3e62c000}, {0x3e62e000}, + {0x3e630000}, {0x3e632000}, {0x3e634000}, {0x3e636000}, + {0x3e638000}, {0x3e63a000}, {0x3e63c000}, {0x3e63e000}, + {0x3e640000}, {0x3e642000}, {0x3e644000}, {0x3e646000}, + {0x3e648000}, {0x3e64a000}, {0x3e64c000}, {0x3e64e000}, + {0x3e650000}, {0x3e652000}, {0x3e654000}, {0x3e656000}, + {0x3e658000}, {0x3e65a000}, {0x3e65c000}, {0x3e65e000}, + {0x3e660000}, {0x3e662000}, {0x3e664000}, {0x3e666000}, + {0x3e668000}, {0x3e66a000}, {0x3e66c000}, {0x3e66e000}, + {0x3e670000}, {0x3e672000}, {0x3e674000}, {0x3e676000}, + {0x3e678000}, {0x3e67a000}, {0x3e67c000}, {0x3e67e000}, + {0x3e680000}, {0x3e682000}, {0x3e684000}, {0x3e686000}, + {0x3e688000}, {0x3e68a000}, {0x3e68c000}, {0x3e68e000}, + {0x3e690000}, {0x3e692000}, {0x3e694000}, {0x3e696000}, + {0x3e698000}, {0x3e69a000}, {0x3e69c000}, {0x3e69e000}, + {0x3e6a0000}, {0x3e6a2000}, {0x3e6a4000}, {0x3e6a6000}, + {0x3e6a8000}, {0x3e6aa000}, {0x3e6ac000}, {0x3e6ae000}, + {0x3e6b0000}, {0x3e6b2000}, {0x3e6b4000}, {0x3e6b6000}, + {0x3e6b8000}, {0x3e6ba000}, {0x3e6bc000}, {0x3e6be000}, + {0x3e6c0000}, {0x3e6c2000}, {0x3e6c4000}, {0x3e6c6000}, + {0x3e6c8000}, {0x3e6ca000}, {0x3e6cc000}, {0x3e6ce000}, + {0x3e6d0000}, {0x3e6d2000}, {0x3e6d4000}, {0x3e6d6000}, + {0x3e6d8000}, {0x3e6da000}, {0x3e6dc000}, {0x3e6de000}, + {0x3e6e0000}, {0x3e6e2000}, {0x3e6e4000}, {0x3e6e6000}, + {0x3e6e8000}, {0x3e6ea000}, {0x3e6ec000}, {0x3e6ee000}, + {0x3e6f0000}, {0x3e6f2000}, {0x3e6f4000}, {0x3e6f6000}, + {0x3e6f8000}, {0x3e6fa000}, {0x3e6fc000}, {0x3e6fe000}, + {0x3e700000}, {0x3e702000}, {0x3e704000}, {0x3e706000}, + {0x3e708000}, {0x3e70a000}, {0x3e70c000}, {0x3e70e000}, + {0x3e710000}, {0x3e712000}, {0x3e714000}, {0x3e716000}, + {0x3e718000}, {0x3e71a000}, {0x3e71c000}, {0x3e71e000}, + {0x3e720000}, {0x3e722000}, {0x3e724000}, {0x3e726000}, + {0x3e728000}, {0x3e72a000}, {0x3e72c000}, {0x3e72e000}, + {0x3e730000}, {0x3e732000}, {0x3e734000}, {0x3e736000}, + {0x3e738000}, {0x3e73a000}, {0x3e73c000}, {0x3e73e000}, + {0x3e740000}, {0x3e742000}, {0x3e744000}, {0x3e746000}, + {0x3e748000}, {0x3e74a000}, {0x3e74c000}, {0x3e74e000}, + {0x3e750000}, {0x3e752000}, {0x3e754000}, {0x3e756000}, + {0x3e758000}, {0x3e75a000}, {0x3e75c000}, {0x3e75e000}, + {0x3e760000}, {0x3e762000}, {0x3e764000}, {0x3e766000}, + {0x3e768000}, {0x3e76a000}, {0x3e76c000}, {0x3e76e000}, + {0x3e770000}, {0x3e772000}, {0x3e774000}, {0x3e776000}, + {0x3e778000}, {0x3e77a000}, {0x3e77c000}, {0x3e77e000}, + {0x3e780000}, {0x3e782000}, {0x3e784000}, {0x3e786000}, + {0x3e788000}, {0x3e78a000}, {0x3e78c000}, {0x3e78e000}, + {0x3e790000}, {0x3e792000}, {0x3e794000}, {0x3e796000}, + {0x3e798000}, {0x3e79a000}, {0x3e79c000}, {0x3e79e000}, + {0x3e7a0000}, {0x3e7a2000}, {0x3e7a4000}, {0x3e7a6000}, + {0x3e7a8000}, {0x3e7aa000}, {0x3e7ac000}, {0x3e7ae000}, + {0x3e7b0000}, {0x3e7b2000}, {0x3e7b4000}, {0x3e7b6000}, + {0x3e7b8000}, {0x3e7ba000}, {0x3e7bc000}, {0x3e7be000}, + {0x3e7c0000}, {0x3e7c2000}, {0x3e7c4000}, {0x3e7c6000}, + {0x3e7c8000}, {0x3e7ca000}, {0x3e7cc000}, {0x3e7ce000}, + {0x3e7d0000}, {0x3e7d2000}, {0x3e7d4000}, {0x3e7d6000}, + {0x3e7d8000}, {0x3e7da000}, {0x3e7dc000}, {0x3e7de000}, + {0x3e7e0000}, {0x3e7e2000}, {0x3e7e4000}, {0x3e7e6000}, + {0x3e7e8000}, {0x3e7ea000}, {0x3e7ec000}, {0x3e7ee000}, + {0x3e7f0000}, {0x3e7f2000}, {0x3e7f4000}, {0x3e7f6000}, + {0x3e7f8000}, {0x3e7fa000}, {0x3e7fc000}, {0x3e7fe000}, + {0x3e800000}, {0x3e802000}, {0x3e804000}, {0x3e806000}, + {0x3e808000}, {0x3e80a000}, {0x3e80c000}, {0x3e80e000}, + {0x3e810000}, {0x3e812000}, {0x3e814000}, {0x3e816000}, + {0x3e818000}, {0x3e81a000}, {0x3e81c000}, {0x3e81e000}, + {0x3e820000}, {0x3e822000}, {0x3e824000}, {0x3e826000}, + {0x3e828000}, {0x3e82a000}, {0x3e82c000}, {0x3e82e000}, + {0x3e830000}, {0x3e832000}, {0x3e834000}, {0x3e836000}, + {0x3e838000}, {0x3e83a000}, {0x3e83c000}, {0x3e83e000}, + {0x3e840000}, {0x3e842000}, {0x3e844000}, {0x3e846000}, + {0x3e848000}, {0x3e84a000}, {0x3e84c000}, {0x3e84e000}, + {0x3e850000}, {0x3e852000}, {0x3e854000}, {0x3e856000}, + {0x3e858000}, {0x3e85a000}, {0x3e85c000}, {0x3e85e000}, + {0x3e860000}, {0x3e862000}, {0x3e864000}, {0x3e866000}, + {0x3e868000}, {0x3e86a000}, {0x3e86c000}, {0x3e86e000}, + {0x3e870000}, {0x3e872000}, {0x3e874000}, {0x3e876000}, + {0x3e878000}, {0x3e87a000}, {0x3e87c000}, {0x3e87e000}, + {0x3e880000}, {0x3e882000}, {0x3e884000}, {0x3e886000}, + {0x3e888000}, {0x3e88a000}, {0x3e88c000}, {0x3e88e000}, + {0x3e890000}, {0x3e892000}, {0x3e894000}, {0x3e896000}, + {0x3e898000}, {0x3e89a000}, {0x3e89c000}, {0x3e89e000}, + {0x3e8a0000}, {0x3e8a2000}, {0x3e8a4000}, {0x3e8a6000}, + {0x3e8a8000}, {0x3e8aa000}, {0x3e8ac000}, {0x3e8ae000}, + {0x3e8b0000}, {0x3e8b2000}, {0x3e8b4000}, {0x3e8b6000}, + {0x3e8b8000}, {0x3e8ba000}, {0x3e8bc000}, {0x3e8be000}, + {0x3e8c0000}, {0x3e8c2000}, {0x3e8c4000}, {0x3e8c6000}, + {0x3e8c8000}, {0x3e8ca000}, {0x3e8cc000}, {0x3e8ce000}, + {0x3e8d0000}, {0x3e8d2000}, {0x3e8d4000}, {0x3e8d6000}, + {0x3e8d8000}, {0x3e8da000}, {0x3e8dc000}, {0x3e8de000}, + {0x3e8e0000}, {0x3e8e2000}, {0x3e8e4000}, {0x3e8e6000}, + {0x3e8e8000}, {0x3e8ea000}, {0x3e8ec000}, {0x3e8ee000}, + {0x3e8f0000}, {0x3e8f2000}, {0x3e8f4000}, {0x3e8f6000}, + {0x3e8f8000}, {0x3e8fa000}, {0x3e8fc000}, {0x3e8fe000}, + {0x3e900000}, {0x3e902000}, {0x3e904000}, {0x3e906000}, + {0x3e908000}, {0x3e90a000}, {0x3e90c000}, {0x3e90e000}, + {0x3e910000}, {0x3e912000}, {0x3e914000}, {0x3e916000}, + {0x3e918000}, {0x3e91a000}, {0x3e91c000}, {0x3e91e000}, + {0x3e920000}, {0x3e922000}, {0x3e924000}, {0x3e926000}, + {0x3e928000}, {0x3e92a000}, {0x3e92c000}, {0x3e92e000}, + {0x3e930000}, {0x3e932000}, {0x3e934000}, {0x3e936000}, + {0x3e938000}, {0x3e93a000}, {0x3e93c000}, {0x3e93e000}, + {0x3e940000}, {0x3e942000}, {0x3e944000}, {0x3e946000}, + {0x3e948000}, {0x3e94a000}, {0x3e94c000}, {0x3e94e000}, + {0x3e950000}, {0x3e952000}, {0x3e954000}, {0x3e956000}, + {0x3e958000}, {0x3e95a000}, {0x3e95c000}, {0x3e95e000}, + {0x3e960000}, {0x3e962000}, {0x3e964000}, {0x3e966000}, + {0x3e968000}, {0x3e96a000}, {0x3e96c000}, {0x3e96e000}, + {0x3e970000}, {0x3e972000}, {0x3e974000}, {0x3e976000}, + {0x3e978000}, {0x3e97a000}, {0x3e97c000}, {0x3e97e000}, + {0x3e980000}, {0x3e982000}, {0x3e984000}, {0x3e986000}, + {0x3e988000}, {0x3e98a000}, {0x3e98c000}, {0x3e98e000}, + {0x3e990000}, {0x3e992000}, {0x3e994000}, {0x3e996000}, + {0x3e998000}, {0x3e99a000}, {0x3e99c000}, {0x3e99e000}, + {0x3e9a0000}, {0x3e9a2000}, {0x3e9a4000}, {0x3e9a6000}, + {0x3e9a8000}, {0x3e9aa000}, {0x3e9ac000}, {0x3e9ae000}, + {0x3e9b0000}, {0x3e9b2000}, {0x3e9b4000}, {0x3e9b6000}, + {0x3e9b8000}, {0x3e9ba000}, {0x3e9bc000}, {0x3e9be000}, + {0x3e9c0000}, {0x3e9c2000}, {0x3e9c4000}, {0x3e9c6000}, + {0x3e9c8000}, {0x3e9ca000}, {0x3e9cc000}, {0x3e9ce000}, + {0x3e9d0000}, {0x3e9d2000}, {0x3e9d4000}, {0x3e9d6000}, + {0x3e9d8000}, {0x3e9da000}, {0x3e9dc000}, {0x3e9de000}, + {0x3e9e0000}, {0x3e9e2000}, {0x3e9e4000}, {0x3e9e6000}, + {0x3e9e8000}, {0x3e9ea000}, {0x3e9ec000}, {0x3e9ee000}, + {0x3e9f0000}, {0x3e9f2000}, {0x3e9f4000}, {0x3e9f6000}, + {0x3e9f8000}, {0x3e9fa000}, {0x3e9fc000}, {0x3e9fe000}, + {0x3ea00000}, {0x3ea02000}, {0x3ea04000}, {0x3ea06000}, + {0x3ea08000}, {0x3ea0a000}, {0x3ea0c000}, {0x3ea0e000}, + {0x3ea10000}, {0x3ea12000}, {0x3ea14000}, {0x3ea16000}, + {0x3ea18000}, {0x3ea1a000}, {0x3ea1c000}, {0x3ea1e000}, + {0x3ea20000}, {0x3ea22000}, {0x3ea24000}, {0x3ea26000}, + {0x3ea28000}, {0x3ea2a000}, {0x3ea2c000}, {0x3ea2e000}, + {0x3ea30000}, {0x3ea32000}, {0x3ea34000}, {0x3ea36000}, + {0x3ea38000}, {0x3ea3a000}, {0x3ea3c000}, {0x3ea3e000}, + {0x3ea40000}, {0x3ea42000}, {0x3ea44000}, {0x3ea46000}, + {0x3ea48000}, {0x3ea4a000}, {0x3ea4c000}, {0x3ea4e000}, + {0x3ea50000}, {0x3ea52000}, {0x3ea54000}, {0x3ea56000}, + {0x3ea58000}, {0x3ea5a000}, {0x3ea5c000}, {0x3ea5e000}, + {0x3ea60000}, {0x3ea62000}, {0x3ea64000}, {0x3ea66000}, + {0x3ea68000}, {0x3ea6a000}, {0x3ea6c000}, {0x3ea6e000}, + {0x3ea70000}, {0x3ea72000}, {0x3ea74000}, {0x3ea76000}, + {0x3ea78000}, {0x3ea7a000}, {0x3ea7c000}, {0x3ea7e000}, + {0x3ea80000}, {0x3ea82000}, {0x3ea84000}, {0x3ea86000}, + {0x3ea88000}, {0x3ea8a000}, {0x3ea8c000}, {0x3ea8e000}, + {0x3ea90000}, {0x3ea92000}, {0x3ea94000}, {0x3ea96000}, + {0x3ea98000}, {0x3ea9a000}, {0x3ea9c000}, {0x3ea9e000}, + {0x3eaa0000}, {0x3eaa2000}, {0x3eaa4000}, {0x3eaa6000}, + {0x3eaa8000}, {0x3eaaa000}, {0x3eaac000}, {0x3eaae000}, + {0x3eab0000}, {0x3eab2000}, {0x3eab4000}, {0x3eab6000}, + {0x3eab8000}, {0x3eaba000}, {0x3eabc000}, {0x3eabe000}, + {0x3eac0000}, {0x3eac2000}, {0x3eac4000}, {0x3eac6000}, + {0x3eac8000}, {0x3eaca000}, {0x3eacc000}, {0x3eace000}, + {0x3ead0000}, {0x3ead2000}, {0x3ead4000}, {0x3ead6000}, + {0x3ead8000}, {0x3eada000}, {0x3eadc000}, {0x3eade000}, + {0x3eae0000}, {0x3eae2000}, {0x3eae4000}, {0x3eae6000}, + {0x3eae8000}, {0x3eaea000}, {0x3eaec000}, {0x3eaee000}, + {0x3eaf0000}, {0x3eaf2000}, {0x3eaf4000}, {0x3eaf6000}, + {0x3eaf8000}, {0x3eafa000}, {0x3eafc000}, {0x3eafe000}, + {0x3eb00000}, {0x3eb02000}, {0x3eb04000}, {0x3eb06000}, + {0x3eb08000}, {0x3eb0a000}, {0x3eb0c000}, {0x3eb0e000}, + {0x3eb10000}, {0x3eb12000}, {0x3eb14000}, {0x3eb16000}, + {0x3eb18000}, {0x3eb1a000}, {0x3eb1c000}, {0x3eb1e000}, + {0x3eb20000}, {0x3eb22000}, {0x3eb24000}, {0x3eb26000}, + {0x3eb28000}, {0x3eb2a000}, {0x3eb2c000}, {0x3eb2e000}, + {0x3eb30000}, {0x3eb32000}, {0x3eb34000}, {0x3eb36000}, + {0x3eb38000}, {0x3eb3a000}, {0x3eb3c000}, {0x3eb3e000}, + {0x3eb40000}, {0x3eb42000}, {0x3eb44000}, {0x3eb46000}, + {0x3eb48000}, {0x3eb4a000}, {0x3eb4c000}, {0x3eb4e000}, + {0x3eb50000}, {0x3eb52000}, {0x3eb54000}, {0x3eb56000}, + {0x3eb58000}, {0x3eb5a000}, {0x3eb5c000}, {0x3eb5e000}, + {0x3eb60000}, {0x3eb62000}, {0x3eb64000}, {0x3eb66000}, + {0x3eb68000}, {0x3eb6a000}, {0x3eb6c000}, {0x3eb6e000}, + {0x3eb70000}, {0x3eb72000}, {0x3eb74000}, {0x3eb76000}, + {0x3eb78000}, {0x3eb7a000}, {0x3eb7c000}, {0x3eb7e000}, + {0x3eb80000}, {0x3eb82000}, {0x3eb84000}, {0x3eb86000}, + {0x3eb88000}, {0x3eb8a000}, {0x3eb8c000}, {0x3eb8e000}, + {0x3eb90000}, {0x3eb92000}, {0x3eb94000}, {0x3eb96000}, + {0x3eb98000}, {0x3eb9a000}, {0x3eb9c000}, {0x3eb9e000}, + {0x3eba0000}, {0x3eba2000}, {0x3eba4000}, {0x3eba6000}, + {0x3eba8000}, {0x3ebaa000}, {0x3ebac000}, {0x3ebae000}, + {0x3ebb0000}, {0x3ebb2000}, {0x3ebb4000}, {0x3ebb6000}, + {0x3ebb8000}, {0x3ebba000}, {0x3ebbc000}, {0x3ebbe000}, + {0x3ebc0000}, {0x3ebc2000}, {0x3ebc4000}, {0x3ebc6000}, + {0x3ebc8000}, {0x3ebca000}, {0x3ebcc000}, {0x3ebce000}, + {0x3ebd0000}, {0x3ebd2000}, {0x3ebd4000}, {0x3ebd6000}, + {0x3ebd8000}, {0x3ebda000}, {0x3ebdc000}, {0x3ebde000}, + {0x3ebe0000}, {0x3ebe2000}, {0x3ebe4000}, {0x3ebe6000}, + {0x3ebe8000}, {0x3ebea000}, {0x3ebec000}, {0x3ebee000}, + {0x3ebf0000}, {0x3ebf2000}, {0x3ebf4000}, {0x3ebf6000}, + {0x3ebf8000}, {0x3ebfa000}, {0x3ebfc000}, {0x3ebfe000}, + {0x3ec00000}, {0x3ec02000}, {0x3ec04000}, {0x3ec06000}, + {0x3ec08000}, {0x3ec0a000}, {0x3ec0c000}, {0x3ec0e000}, + {0x3ec10000}, {0x3ec12000}, {0x3ec14000}, {0x3ec16000}, + {0x3ec18000}, {0x3ec1a000}, {0x3ec1c000}, {0x3ec1e000}, + {0x3ec20000}, {0x3ec22000}, {0x3ec24000}, {0x3ec26000}, + {0x3ec28000}, {0x3ec2a000}, {0x3ec2c000}, {0x3ec2e000}, + {0x3ec30000}, {0x3ec32000}, {0x3ec34000}, {0x3ec36000}, + {0x3ec38000}, {0x3ec3a000}, {0x3ec3c000}, {0x3ec3e000}, + {0x3ec40000}, {0x3ec42000}, {0x3ec44000}, {0x3ec46000}, + {0x3ec48000}, {0x3ec4a000}, {0x3ec4c000}, {0x3ec4e000}, + {0x3ec50000}, {0x3ec52000}, {0x3ec54000}, {0x3ec56000}, + {0x3ec58000}, {0x3ec5a000}, {0x3ec5c000}, {0x3ec5e000}, + {0x3ec60000}, {0x3ec62000}, {0x3ec64000}, {0x3ec66000}, + {0x3ec68000}, {0x3ec6a000}, {0x3ec6c000}, {0x3ec6e000}, + {0x3ec70000}, {0x3ec72000}, {0x3ec74000}, {0x3ec76000}, + {0x3ec78000}, {0x3ec7a000}, {0x3ec7c000}, {0x3ec7e000}, + {0x3ec80000}, {0x3ec82000}, {0x3ec84000}, {0x3ec86000}, + {0x3ec88000}, {0x3ec8a000}, {0x3ec8c000}, {0x3ec8e000}, + {0x3ec90000}, {0x3ec92000}, {0x3ec94000}, {0x3ec96000}, + {0x3ec98000}, {0x3ec9a000}, {0x3ec9c000}, {0x3ec9e000}, + {0x3eca0000}, {0x3eca2000}, {0x3eca4000}, {0x3eca6000}, + {0x3eca8000}, {0x3ecaa000}, {0x3ecac000}, {0x3ecae000}, + {0x3ecb0000}, {0x3ecb2000}, {0x3ecb4000}, {0x3ecb6000}, + {0x3ecb8000}, {0x3ecba000}, {0x3ecbc000}, {0x3ecbe000}, + {0x3ecc0000}, {0x3ecc2000}, {0x3ecc4000}, {0x3ecc6000}, + {0x3ecc8000}, {0x3ecca000}, {0x3eccc000}, {0x3ecce000}, + {0x3ecd0000}, {0x3ecd2000}, {0x3ecd4000}, {0x3ecd6000}, + {0x3ecd8000}, {0x3ecda000}, {0x3ecdc000}, {0x3ecde000}, + {0x3ece0000}, {0x3ece2000}, {0x3ece4000}, {0x3ece6000}, + {0x3ece8000}, {0x3ecea000}, {0x3ecec000}, {0x3ecee000}, + {0x3ecf0000}, {0x3ecf2000}, {0x3ecf4000}, {0x3ecf6000}, + {0x3ecf8000}, {0x3ecfa000}, {0x3ecfc000}, {0x3ecfe000}, + {0x3ed00000}, {0x3ed02000}, {0x3ed04000}, {0x3ed06000}, + {0x3ed08000}, {0x3ed0a000}, {0x3ed0c000}, {0x3ed0e000}, + {0x3ed10000}, {0x3ed12000}, {0x3ed14000}, {0x3ed16000}, + {0x3ed18000}, {0x3ed1a000}, {0x3ed1c000}, {0x3ed1e000}, + {0x3ed20000}, {0x3ed22000}, {0x3ed24000}, {0x3ed26000}, + {0x3ed28000}, {0x3ed2a000}, {0x3ed2c000}, {0x3ed2e000}, + {0x3ed30000}, {0x3ed32000}, {0x3ed34000}, {0x3ed36000}, + {0x3ed38000}, {0x3ed3a000}, {0x3ed3c000}, {0x3ed3e000}, + {0x3ed40000}, {0x3ed42000}, {0x3ed44000}, {0x3ed46000}, + {0x3ed48000}, {0x3ed4a000}, {0x3ed4c000}, {0x3ed4e000}, + {0x3ed50000}, {0x3ed52000}, {0x3ed54000}, {0x3ed56000}, + {0x3ed58000}, {0x3ed5a000}, {0x3ed5c000}, {0x3ed5e000}, + {0x3ed60000}, {0x3ed62000}, {0x3ed64000}, {0x3ed66000}, + {0x3ed68000}, {0x3ed6a000}, {0x3ed6c000}, {0x3ed6e000}, + {0x3ed70000}, {0x3ed72000}, {0x3ed74000}, {0x3ed76000}, + {0x3ed78000}, {0x3ed7a000}, {0x3ed7c000}, {0x3ed7e000}, + {0x3ed80000}, {0x3ed82000}, {0x3ed84000}, {0x3ed86000}, + {0x3ed88000}, {0x3ed8a000}, {0x3ed8c000}, {0x3ed8e000}, + {0x3ed90000}, {0x3ed92000}, {0x3ed94000}, {0x3ed96000}, + {0x3ed98000}, {0x3ed9a000}, {0x3ed9c000}, {0x3ed9e000}, + {0x3eda0000}, {0x3eda2000}, {0x3eda4000}, {0x3eda6000}, + {0x3eda8000}, {0x3edaa000}, {0x3edac000}, {0x3edae000}, + {0x3edb0000}, {0x3edb2000}, {0x3edb4000}, {0x3edb6000}, + {0x3edb8000}, {0x3edba000}, {0x3edbc000}, {0x3edbe000}, + {0x3edc0000}, {0x3edc2000}, {0x3edc4000}, {0x3edc6000}, + {0x3edc8000}, {0x3edca000}, {0x3edcc000}, {0x3edce000}, + {0x3edd0000}, {0x3edd2000}, {0x3edd4000}, {0x3edd6000}, + {0x3edd8000}, {0x3edda000}, {0x3eddc000}, {0x3edde000}, + {0x3ede0000}, {0x3ede2000}, {0x3ede4000}, {0x3ede6000}, + {0x3ede8000}, {0x3edea000}, {0x3edec000}, {0x3edee000}, + {0x3edf0000}, {0x3edf2000}, {0x3edf4000}, {0x3edf6000}, + {0x3edf8000}, {0x3edfa000}, {0x3edfc000}, {0x3edfe000}, + {0x3ee00000}, {0x3ee02000}, {0x3ee04000}, {0x3ee06000}, + {0x3ee08000}, {0x3ee0a000}, {0x3ee0c000}, {0x3ee0e000}, + {0x3ee10000}, {0x3ee12000}, {0x3ee14000}, {0x3ee16000}, + {0x3ee18000}, {0x3ee1a000}, {0x3ee1c000}, {0x3ee1e000}, + {0x3ee20000}, {0x3ee22000}, {0x3ee24000}, {0x3ee26000}, + {0x3ee28000}, {0x3ee2a000}, {0x3ee2c000}, {0x3ee2e000}, + {0x3ee30000}, {0x3ee32000}, {0x3ee34000}, {0x3ee36000}, + {0x3ee38000}, {0x3ee3a000}, {0x3ee3c000}, {0x3ee3e000}, + {0x3ee40000}, {0x3ee42000}, {0x3ee44000}, {0x3ee46000}, + {0x3ee48000}, {0x3ee4a000}, {0x3ee4c000}, {0x3ee4e000}, + {0x3ee50000}, {0x3ee52000}, {0x3ee54000}, {0x3ee56000}, + {0x3ee58000}, {0x3ee5a000}, {0x3ee5c000}, {0x3ee5e000}, + {0x3ee60000}, {0x3ee62000}, {0x3ee64000}, {0x3ee66000}, + {0x3ee68000}, {0x3ee6a000}, {0x3ee6c000}, {0x3ee6e000}, + {0x3ee70000}, {0x3ee72000}, {0x3ee74000}, {0x3ee76000}, + {0x3ee78000}, {0x3ee7a000}, {0x3ee7c000}, {0x3ee7e000}, + {0x3ee80000}, {0x3ee82000}, {0x3ee84000}, {0x3ee86000}, + {0x3ee88000}, {0x3ee8a000}, {0x3ee8c000}, {0x3ee8e000}, + {0x3ee90000}, {0x3ee92000}, {0x3ee94000}, {0x3ee96000}, + {0x3ee98000}, {0x3ee9a000}, {0x3ee9c000}, {0x3ee9e000}, + {0x3eea0000}, {0x3eea2000}, {0x3eea4000}, {0x3eea6000}, + {0x3eea8000}, {0x3eeaa000}, {0x3eeac000}, {0x3eeae000}, + {0x3eeb0000}, {0x3eeb2000}, {0x3eeb4000}, {0x3eeb6000}, + {0x3eeb8000}, {0x3eeba000}, {0x3eebc000}, {0x3eebe000}, + {0x3eec0000}, {0x3eec2000}, {0x3eec4000}, {0x3eec6000}, + {0x3eec8000}, {0x3eeca000}, {0x3eecc000}, {0x3eece000}, + {0x3eed0000}, {0x3eed2000}, {0x3eed4000}, {0x3eed6000}, + {0x3eed8000}, {0x3eeda000}, {0x3eedc000}, {0x3eede000}, + {0x3eee0000}, {0x3eee2000}, {0x3eee4000}, {0x3eee6000}, + {0x3eee8000}, {0x3eeea000}, {0x3eeec000}, {0x3eeee000}, + {0x3eef0000}, {0x3eef2000}, {0x3eef4000}, {0x3eef6000}, + {0x3eef8000}, {0x3eefa000}, {0x3eefc000}, {0x3eefe000}, + {0x3ef00000}, {0x3ef02000}, {0x3ef04000}, {0x3ef06000}, + {0x3ef08000}, {0x3ef0a000}, {0x3ef0c000}, {0x3ef0e000}, + {0x3ef10000}, {0x3ef12000}, {0x3ef14000}, {0x3ef16000}, + {0x3ef18000}, {0x3ef1a000}, {0x3ef1c000}, {0x3ef1e000}, + {0x3ef20000}, {0x3ef22000}, {0x3ef24000}, {0x3ef26000}, + {0x3ef28000}, {0x3ef2a000}, {0x3ef2c000}, {0x3ef2e000}, + {0x3ef30000}, {0x3ef32000}, {0x3ef34000}, {0x3ef36000}, + {0x3ef38000}, {0x3ef3a000}, {0x3ef3c000}, {0x3ef3e000}, + {0x3ef40000}, {0x3ef42000}, {0x3ef44000}, {0x3ef46000}, + {0x3ef48000}, {0x3ef4a000}, {0x3ef4c000}, {0x3ef4e000}, + {0x3ef50000}, {0x3ef52000}, {0x3ef54000}, {0x3ef56000}, + {0x3ef58000}, {0x3ef5a000}, {0x3ef5c000}, {0x3ef5e000}, + {0x3ef60000}, {0x3ef62000}, {0x3ef64000}, {0x3ef66000}, + {0x3ef68000}, {0x3ef6a000}, {0x3ef6c000}, {0x3ef6e000}, + {0x3ef70000}, {0x3ef72000}, {0x3ef74000}, {0x3ef76000}, + {0x3ef78000}, {0x3ef7a000}, {0x3ef7c000}, {0x3ef7e000}, + {0x3ef80000}, {0x3ef82000}, {0x3ef84000}, {0x3ef86000}, + {0x3ef88000}, {0x3ef8a000}, {0x3ef8c000}, {0x3ef8e000}, + {0x3ef90000}, {0x3ef92000}, {0x3ef94000}, {0x3ef96000}, + {0x3ef98000}, {0x3ef9a000}, {0x3ef9c000}, {0x3ef9e000}, + {0x3efa0000}, {0x3efa2000}, {0x3efa4000}, {0x3efa6000}, + {0x3efa8000}, {0x3efaa000}, {0x3efac000}, {0x3efae000}, + {0x3efb0000}, {0x3efb2000}, {0x3efb4000}, {0x3efb6000}, + {0x3efb8000}, {0x3efba000}, {0x3efbc000}, {0x3efbe000}, + {0x3efc0000}, {0x3efc2000}, {0x3efc4000}, {0x3efc6000}, + {0x3efc8000}, {0x3efca000}, {0x3efcc000}, {0x3efce000}, + {0x3efd0000}, {0x3efd2000}, {0x3efd4000}, {0x3efd6000}, + {0x3efd8000}, {0x3efda000}, {0x3efdc000}, {0x3efde000}, + {0x3efe0000}, {0x3efe2000}, {0x3efe4000}, {0x3efe6000}, + {0x3efe8000}, {0x3efea000}, {0x3efec000}, {0x3efee000}, + {0x3eff0000}, {0x3eff2000}, {0x3eff4000}, {0x3eff6000}, + {0x3eff8000}, {0x3effa000}, {0x3effc000}, {0x3effe000}, + {0x3f000000}, {0x3f002000}, {0x3f004000}, {0x3f006000}, + {0x3f008000}, {0x3f00a000}, {0x3f00c000}, {0x3f00e000}, + {0x3f010000}, {0x3f012000}, {0x3f014000}, {0x3f016000}, + {0x3f018000}, {0x3f01a000}, {0x3f01c000}, {0x3f01e000}, + {0x3f020000}, {0x3f022000}, {0x3f024000}, {0x3f026000}, + {0x3f028000}, {0x3f02a000}, {0x3f02c000}, {0x3f02e000}, + {0x3f030000}, {0x3f032000}, {0x3f034000}, {0x3f036000}, + {0x3f038000}, {0x3f03a000}, {0x3f03c000}, {0x3f03e000}, + {0x3f040000}, {0x3f042000}, {0x3f044000}, {0x3f046000}, + {0x3f048000}, {0x3f04a000}, {0x3f04c000}, {0x3f04e000}, + {0x3f050000}, {0x3f052000}, {0x3f054000}, {0x3f056000}, + {0x3f058000}, {0x3f05a000}, {0x3f05c000}, {0x3f05e000}, + {0x3f060000}, {0x3f062000}, {0x3f064000}, {0x3f066000}, + {0x3f068000}, {0x3f06a000}, {0x3f06c000}, {0x3f06e000}, + {0x3f070000}, {0x3f072000}, {0x3f074000}, {0x3f076000}, + {0x3f078000}, {0x3f07a000}, {0x3f07c000}, {0x3f07e000}, + {0x3f080000}, {0x3f082000}, {0x3f084000}, {0x3f086000}, + {0x3f088000}, {0x3f08a000}, {0x3f08c000}, {0x3f08e000}, + {0x3f090000}, {0x3f092000}, {0x3f094000}, {0x3f096000}, + {0x3f098000}, {0x3f09a000}, {0x3f09c000}, {0x3f09e000}, + {0x3f0a0000}, {0x3f0a2000}, {0x3f0a4000}, {0x3f0a6000}, + {0x3f0a8000}, {0x3f0aa000}, {0x3f0ac000}, {0x3f0ae000}, + {0x3f0b0000}, {0x3f0b2000}, {0x3f0b4000}, {0x3f0b6000}, + {0x3f0b8000}, {0x3f0ba000}, {0x3f0bc000}, {0x3f0be000}, + {0x3f0c0000}, {0x3f0c2000}, {0x3f0c4000}, {0x3f0c6000}, + {0x3f0c8000}, {0x3f0ca000}, {0x3f0cc000}, {0x3f0ce000}, + {0x3f0d0000}, {0x3f0d2000}, {0x3f0d4000}, {0x3f0d6000}, + {0x3f0d8000}, {0x3f0da000}, {0x3f0dc000}, {0x3f0de000}, + {0x3f0e0000}, {0x3f0e2000}, {0x3f0e4000}, {0x3f0e6000}, + {0x3f0e8000}, {0x3f0ea000}, {0x3f0ec000}, {0x3f0ee000}, + {0x3f0f0000}, {0x3f0f2000}, {0x3f0f4000}, {0x3f0f6000}, + {0x3f0f8000}, {0x3f0fa000}, {0x3f0fc000}, {0x3f0fe000}, + {0x3f100000}, {0x3f102000}, {0x3f104000}, {0x3f106000}, + {0x3f108000}, {0x3f10a000}, {0x3f10c000}, {0x3f10e000}, + {0x3f110000}, {0x3f112000}, {0x3f114000}, {0x3f116000}, + {0x3f118000}, {0x3f11a000}, {0x3f11c000}, {0x3f11e000}, + {0x3f120000}, {0x3f122000}, {0x3f124000}, {0x3f126000}, + {0x3f128000}, {0x3f12a000}, {0x3f12c000}, {0x3f12e000}, + {0x3f130000}, {0x3f132000}, {0x3f134000}, {0x3f136000}, + {0x3f138000}, {0x3f13a000}, {0x3f13c000}, {0x3f13e000}, + {0x3f140000}, {0x3f142000}, {0x3f144000}, {0x3f146000}, + {0x3f148000}, {0x3f14a000}, {0x3f14c000}, {0x3f14e000}, + {0x3f150000}, {0x3f152000}, {0x3f154000}, {0x3f156000}, + {0x3f158000}, {0x3f15a000}, {0x3f15c000}, {0x3f15e000}, + {0x3f160000}, {0x3f162000}, {0x3f164000}, {0x3f166000}, + {0x3f168000}, {0x3f16a000}, {0x3f16c000}, {0x3f16e000}, + {0x3f170000}, {0x3f172000}, {0x3f174000}, {0x3f176000}, + {0x3f178000}, {0x3f17a000}, {0x3f17c000}, {0x3f17e000}, + {0x3f180000}, {0x3f182000}, {0x3f184000}, {0x3f186000}, + {0x3f188000}, {0x3f18a000}, {0x3f18c000}, {0x3f18e000}, + {0x3f190000}, {0x3f192000}, {0x3f194000}, {0x3f196000}, + {0x3f198000}, {0x3f19a000}, {0x3f19c000}, {0x3f19e000}, + {0x3f1a0000}, {0x3f1a2000}, {0x3f1a4000}, {0x3f1a6000}, + {0x3f1a8000}, {0x3f1aa000}, {0x3f1ac000}, {0x3f1ae000}, + {0x3f1b0000}, {0x3f1b2000}, {0x3f1b4000}, {0x3f1b6000}, + {0x3f1b8000}, {0x3f1ba000}, {0x3f1bc000}, {0x3f1be000}, + {0x3f1c0000}, {0x3f1c2000}, {0x3f1c4000}, {0x3f1c6000}, + {0x3f1c8000}, {0x3f1ca000}, {0x3f1cc000}, {0x3f1ce000}, + {0x3f1d0000}, {0x3f1d2000}, {0x3f1d4000}, {0x3f1d6000}, + {0x3f1d8000}, {0x3f1da000}, {0x3f1dc000}, {0x3f1de000}, + {0x3f1e0000}, {0x3f1e2000}, {0x3f1e4000}, {0x3f1e6000}, + {0x3f1e8000}, {0x3f1ea000}, {0x3f1ec000}, {0x3f1ee000}, + {0x3f1f0000}, {0x3f1f2000}, {0x3f1f4000}, {0x3f1f6000}, + {0x3f1f8000}, {0x3f1fa000}, {0x3f1fc000}, {0x3f1fe000}, + {0x3f200000}, {0x3f202000}, {0x3f204000}, {0x3f206000}, + {0x3f208000}, {0x3f20a000}, {0x3f20c000}, {0x3f20e000}, + {0x3f210000}, {0x3f212000}, {0x3f214000}, {0x3f216000}, + {0x3f218000}, {0x3f21a000}, {0x3f21c000}, {0x3f21e000}, + {0x3f220000}, {0x3f222000}, {0x3f224000}, {0x3f226000}, + {0x3f228000}, {0x3f22a000}, {0x3f22c000}, {0x3f22e000}, + {0x3f230000}, {0x3f232000}, {0x3f234000}, {0x3f236000}, + {0x3f238000}, {0x3f23a000}, {0x3f23c000}, {0x3f23e000}, + {0x3f240000}, {0x3f242000}, {0x3f244000}, {0x3f246000}, + {0x3f248000}, {0x3f24a000}, {0x3f24c000}, {0x3f24e000}, + {0x3f250000}, {0x3f252000}, {0x3f254000}, {0x3f256000}, + {0x3f258000}, {0x3f25a000}, {0x3f25c000}, {0x3f25e000}, + {0x3f260000}, {0x3f262000}, {0x3f264000}, {0x3f266000}, + {0x3f268000}, {0x3f26a000}, {0x3f26c000}, {0x3f26e000}, + {0x3f270000}, {0x3f272000}, {0x3f274000}, {0x3f276000}, + {0x3f278000}, {0x3f27a000}, {0x3f27c000}, {0x3f27e000}, + {0x3f280000}, {0x3f282000}, {0x3f284000}, {0x3f286000}, + {0x3f288000}, {0x3f28a000}, {0x3f28c000}, {0x3f28e000}, + {0x3f290000}, {0x3f292000}, {0x3f294000}, {0x3f296000}, + {0x3f298000}, {0x3f29a000}, {0x3f29c000}, {0x3f29e000}, + {0x3f2a0000}, {0x3f2a2000}, {0x3f2a4000}, {0x3f2a6000}, + {0x3f2a8000}, {0x3f2aa000}, {0x3f2ac000}, {0x3f2ae000}, + {0x3f2b0000}, {0x3f2b2000}, {0x3f2b4000}, {0x3f2b6000}, + {0x3f2b8000}, {0x3f2ba000}, {0x3f2bc000}, {0x3f2be000}, + {0x3f2c0000}, {0x3f2c2000}, {0x3f2c4000}, {0x3f2c6000}, + {0x3f2c8000}, {0x3f2ca000}, {0x3f2cc000}, {0x3f2ce000}, + {0x3f2d0000}, {0x3f2d2000}, {0x3f2d4000}, {0x3f2d6000}, + {0x3f2d8000}, {0x3f2da000}, {0x3f2dc000}, {0x3f2de000}, + {0x3f2e0000}, {0x3f2e2000}, {0x3f2e4000}, {0x3f2e6000}, + {0x3f2e8000}, {0x3f2ea000}, {0x3f2ec000}, {0x3f2ee000}, + {0x3f2f0000}, {0x3f2f2000}, {0x3f2f4000}, {0x3f2f6000}, + {0x3f2f8000}, {0x3f2fa000}, {0x3f2fc000}, {0x3f2fe000}, + {0x3f300000}, {0x3f302000}, {0x3f304000}, {0x3f306000}, + {0x3f308000}, {0x3f30a000}, {0x3f30c000}, {0x3f30e000}, + {0x3f310000}, {0x3f312000}, {0x3f314000}, {0x3f316000}, + {0x3f318000}, {0x3f31a000}, {0x3f31c000}, {0x3f31e000}, + {0x3f320000}, {0x3f322000}, {0x3f324000}, {0x3f326000}, + {0x3f328000}, {0x3f32a000}, {0x3f32c000}, {0x3f32e000}, + {0x3f330000}, {0x3f332000}, {0x3f334000}, {0x3f336000}, + {0x3f338000}, {0x3f33a000}, {0x3f33c000}, {0x3f33e000}, + {0x3f340000}, {0x3f342000}, {0x3f344000}, {0x3f346000}, + {0x3f348000}, {0x3f34a000}, {0x3f34c000}, {0x3f34e000}, + {0x3f350000}, {0x3f352000}, {0x3f354000}, {0x3f356000}, + {0x3f358000}, {0x3f35a000}, {0x3f35c000}, {0x3f35e000}, + {0x3f360000}, {0x3f362000}, {0x3f364000}, {0x3f366000}, + {0x3f368000}, {0x3f36a000}, {0x3f36c000}, {0x3f36e000}, + {0x3f370000}, {0x3f372000}, {0x3f374000}, {0x3f376000}, + {0x3f378000}, {0x3f37a000}, {0x3f37c000}, {0x3f37e000}, + {0x3f380000}, {0x3f382000}, {0x3f384000}, {0x3f386000}, + {0x3f388000}, {0x3f38a000}, {0x3f38c000}, {0x3f38e000}, + {0x3f390000}, {0x3f392000}, {0x3f394000}, {0x3f396000}, + {0x3f398000}, {0x3f39a000}, {0x3f39c000}, {0x3f39e000}, + {0x3f3a0000}, {0x3f3a2000}, {0x3f3a4000}, {0x3f3a6000}, + {0x3f3a8000}, {0x3f3aa000}, {0x3f3ac000}, {0x3f3ae000}, + {0x3f3b0000}, {0x3f3b2000}, {0x3f3b4000}, {0x3f3b6000}, + {0x3f3b8000}, {0x3f3ba000}, {0x3f3bc000}, {0x3f3be000}, + {0x3f3c0000}, {0x3f3c2000}, {0x3f3c4000}, {0x3f3c6000}, + {0x3f3c8000}, {0x3f3ca000}, {0x3f3cc000}, {0x3f3ce000}, + {0x3f3d0000}, {0x3f3d2000}, {0x3f3d4000}, {0x3f3d6000}, + {0x3f3d8000}, {0x3f3da000}, {0x3f3dc000}, {0x3f3de000}, + {0x3f3e0000}, {0x3f3e2000}, {0x3f3e4000}, {0x3f3e6000}, + {0x3f3e8000}, {0x3f3ea000}, {0x3f3ec000}, {0x3f3ee000}, + {0x3f3f0000}, {0x3f3f2000}, {0x3f3f4000}, {0x3f3f6000}, + {0x3f3f8000}, {0x3f3fa000}, {0x3f3fc000}, {0x3f3fe000}, + {0x3f400000}, {0x3f402000}, {0x3f404000}, {0x3f406000}, + {0x3f408000}, {0x3f40a000}, {0x3f40c000}, {0x3f40e000}, + {0x3f410000}, {0x3f412000}, {0x3f414000}, {0x3f416000}, + {0x3f418000}, {0x3f41a000}, {0x3f41c000}, {0x3f41e000}, + {0x3f420000}, {0x3f422000}, {0x3f424000}, {0x3f426000}, + {0x3f428000}, {0x3f42a000}, {0x3f42c000}, {0x3f42e000}, + {0x3f430000}, {0x3f432000}, {0x3f434000}, {0x3f436000}, + {0x3f438000}, {0x3f43a000}, {0x3f43c000}, {0x3f43e000}, + {0x3f440000}, {0x3f442000}, {0x3f444000}, {0x3f446000}, + {0x3f448000}, {0x3f44a000}, {0x3f44c000}, {0x3f44e000}, + {0x3f450000}, {0x3f452000}, {0x3f454000}, {0x3f456000}, + {0x3f458000}, {0x3f45a000}, {0x3f45c000}, {0x3f45e000}, + {0x3f460000}, {0x3f462000}, {0x3f464000}, {0x3f466000}, + {0x3f468000}, {0x3f46a000}, {0x3f46c000}, {0x3f46e000}, + {0x3f470000}, {0x3f472000}, {0x3f474000}, {0x3f476000}, + {0x3f478000}, {0x3f47a000}, {0x3f47c000}, {0x3f47e000}, + {0x3f480000}, {0x3f482000}, {0x3f484000}, {0x3f486000}, + {0x3f488000}, {0x3f48a000}, {0x3f48c000}, {0x3f48e000}, + {0x3f490000}, {0x3f492000}, {0x3f494000}, {0x3f496000}, + {0x3f498000}, {0x3f49a000}, {0x3f49c000}, {0x3f49e000}, + {0x3f4a0000}, {0x3f4a2000}, {0x3f4a4000}, {0x3f4a6000}, + {0x3f4a8000}, {0x3f4aa000}, {0x3f4ac000}, {0x3f4ae000}, + {0x3f4b0000}, {0x3f4b2000}, {0x3f4b4000}, {0x3f4b6000}, + {0x3f4b8000}, {0x3f4ba000}, {0x3f4bc000}, {0x3f4be000}, + {0x3f4c0000}, {0x3f4c2000}, {0x3f4c4000}, {0x3f4c6000}, + {0x3f4c8000}, {0x3f4ca000}, {0x3f4cc000}, {0x3f4ce000}, + {0x3f4d0000}, {0x3f4d2000}, {0x3f4d4000}, {0x3f4d6000}, + {0x3f4d8000}, {0x3f4da000}, {0x3f4dc000}, {0x3f4de000}, + {0x3f4e0000}, {0x3f4e2000}, {0x3f4e4000}, {0x3f4e6000}, + {0x3f4e8000}, {0x3f4ea000}, {0x3f4ec000}, {0x3f4ee000}, + {0x3f4f0000}, {0x3f4f2000}, {0x3f4f4000}, {0x3f4f6000}, + {0x3f4f8000}, {0x3f4fa000}, {0x3f4fc000}, {0x3f4fe000}, + {0x3f500000}, {0x3f502000}, {0x3f504000}, {0x3f506000}, + {0x3f508000}, {0x3f50a000}, {0x3f50c000}, {0x3f50e000}, + {0x3f510000}, {0x3f512000}, {0x3f514000}, {0x3f516000}, + {0x3f518000}, {0x3f51a000}, {0x3f51c000}, {0x3f51e000}, + {0x3f520000}, {0x3f522000}, {0x3f524000}, {0x3f526000}, + {0x3f528000}, {0x3f52a000}, {0x3f52c000}, {0x3f52e000}, + {0x3f530000}, {0x3f532000}, {0x3f534000}, {0x3f536000}, + {0x3f538000}, {0x3f53a000}, {0x3f53c000}, {0x3f53e000}, + {0x3f540000}, {0x3f542000}, {0x3f544000}, {0x3f546000}, + {0x3f548000}, {0x3f54a000}, {0x3f54c000}, {0x3f54e000}, + {0x3f550000}, {0x3f552000}, {0x3f554000}, {0x3f556000}, + {0x3f558000}, {0x3f55a000}, {0x3f55c000}, {0x3f55e000}, + {0x3f560000}, {0x3f562000}, {0x3f564000}, {0x3f566000}, + {0x3f568000}, {0x3f56a000}, {0x3f56c000}, {0x3f56e000}, + {0x3f570000}, {0x3f572000}, {0x3f574000}, {0x3f576000}, + {0x3f578000}, {0x3f57a000}, {0x3f57c000}, {0x3f57e000}, + {0x3f580000}, {0x3f582000}, {0x3f584000}, {0x3f586000}, + {0x3f588000}, {0x3f58a000}, {0x3f58c000}, {0x3f58e000}, + {0x3f590000}, {0x3f592000}, {0x3f594000}, {0x3f596000}, + {0x3f598000}, {0x3f59a000}, {0x3f59c000}, {0x3f59e000}, + {0x3f5a0000}, {0x3f5a2000}, {0x3f5a4000}, {0x3f5a6000}, + {0x3f5a8000}, {0x3f5aa000}, {0x3f5ac000}, {0x3f5ae000}, + {0x3f5b0000}, {0x3f5b2000}, {0x3f5b4000}, {0x3f5b6000}, + {0x3f5b8000}, {0x3f5ba000}, {0x3f5bc000}, {0x3f5be000}, + {0x3f5c0000}, {0x3f5c2000}, {0x3f5c4000}, {0x3f5c6000}, + {0x3f5c8000}, {0x3f5ca000}, {0x3f5cc000}, {0x3f5ce000}, + {0x3f5d0000}, {0x3f5d2000}, {0x3f5d4000}, {0x3f5d6000}, + {0x3f5d8000}, {0x3f5da000}, {0x3f5dc000}, {0x3f5de000}, + {0x3f5e0000}, {0x3f5e2000}, {0x3f5e4000}, {0x3f5e6000}, + {0x3f5e8000}, {0x3f5ea000}, {0x3f5ec000}, {0x3f5ee000}, + {0x3f5f0000}, {0x3f5f2000}, {0x3f5f4000}, {0x3f5f6000}, + {0x3f5f8000}, {0x3f5fa000}, {0x3f5fc000}, {0x3f5fe000}, + {0x3f600000}, {0x3f602000}, {0x3f604000}, {0x3f606000}, + {0x3f608000}, {0x3f60a000}, {0x3f60c000}, {0x3f60e000}, + {0x3f610000}, {0x3f612000}, {0x3f614000}, {0x3f616000}, + {0x3f618000}, {0x3f61a000}, {0x3f61c000}, {0x3f61e000}, + {0x3f620000}, {0x3f622000}, {0x3f624000}, {0x3f626000}, + {0x3f628000}, {0x3f62a000}, {0x3f62c000}, {0x3f62e000}, + {0x3f630000}, {0x3f632000}, {0x3f634000}, {0x3f636000}, + {0x3f638000}, {0x3f63a000}, {0x3f63c000}, {0x3f63e000}, + {0x3f640000}, {0x3f642000}, {0x3f644000}, {0x3f646000}, + {0x3f648000}, {0x3f64a000}, {0x3f64c000}, {0x3f64e000}, + {0x3f650000}, {0x3f652000}, {0x3f654000}, {0x3f656000}, + {0x3f658000}, {0x3f65a000}, {0x3f65c000}, {0x3f65e000}, + {0x3f660000}, {0x3f662000}, {0x3f664000}, {0x3f666000}, + {0x3f668000}, {0x3f66a000}, {0x3f66c000}, {0x3f66e000}, + {0x3f670000}, {0x3f672000}, {0x3f674000}, {0x3f676000}, + {0x3f678000}, {0x3f67a000}, {0x3f67c000}, {0x3f67e000}, + {0x3f680000}, {0x3f682000}, {0x3f684000}, {0x3f686000}, + {0x3f688000}, {0x3f68a000}, {0x3f68c000}, {0x3f68e000}, + {0x3f690000}, {0x3f692000}, {0x3f694000}, {0x3f696000}, + {0x3f698000}, {0x3f69a000}, {0x3f69c000}, {0x3f69e000}, + {0x3f6a0000}, {0x3f6a2000}, {0x3f6a4000}, {0x3f6a6000}, + {0x3f6a8000}, {0x3f6aa000}, {0x3f6ac000}, {0x3f6ae000}, + {0x3f6b0000}, {0x3f6b2000}, {0x3f6b4000}, {0x3f6b6000}, + {0x3f6b8000}, {0x3f6ba000}, {0x3f6bc000}, {0x3f6be000}, + {0x3f6c0000}, {0x3f6c2000}, {0x3f6c4000}, {0x3f6c6000}, + {0x3f6c8000}, {0x3f6ca000}, {0x3f6cc000}, {0x3f6ce000}, + {0x3f6d0000}, {0x3f6d2000}, {0x3f6d4000}, {0x3f6d6000}, + {0x3f6d8000}, {0x3f6da000}, {0x3f6dc000}, {0x3f6de000}, + {0x3f6e0000}, {0x3f6e2000}, {0x3f6e4000}, {0x3f6e6000}, + {0x3f6e8000}, {0x3f6ea000}, {0x3f6ec000}, {0x3f6ee000}, + {0x3f6f0000}, {0x3f6f2000}, {0x3f6f4000}, {0x3f6f6000}, + {0x3f6f8000}, {0x3f6fa000}, {0x3f6fc000}, {0x3f6fe000}, + {0x3f700000}, {0x3f702000}, {0x3f704000}, {0x3f706000}, + {0x3f708000}, {0x3f70a000}, {0x3f70c000}, {0x3f70e000}, + {0x3f710000}, {0x3f712000}, {0x3f714000}, {0x3f716000}, + {0x3f718000}, {0x3f71a000}, {0x3f71c000}, {0x3f71e000}, + {0x3f720000}, {0x3f722000}, {0x3f724000}, {0x3f726000}, + {0x3f728000}, {0x3f72a000}, {0x3f72c000}, {0x3f72e000}, + {0x3f730000}, {0x3f732000}, {0x3f734000}, {0x3f736000}, + {0x3f738000}, {0x3f73a000}, {0x3f73c000}, {0x3f73e000}, + {0x3f740000}, {0x3f742000}, {0x3f744000}, {0x3f746000}, + {0x3f748000}, {0x3f74a000}, {0x3f74c000}, {0x3f74e000}, + {0x3f750000}, {0x3f752000}, {0x3f754000}, {0x3f756000}, + {0x3f758000}, {0x3f75a000}, {0x3f75c000}, {0x3f75e000}, + {0x3f760000}, {0x3f762000}, {0x3f764000}, {0x3f766000}, + {0x3f768000}, {0x3f76a000}, {0x3f76c000}, {0x3f76e000}, + {0x3f770000}, {0x3f772000}, {0x3f774000}, {0x3f776000}, + {0x3f778000}, {0x3f77a000}, {0x3f77c000}, {0x3f77e000}, + {0x3f780000}, {0x3f782000}, {0x3f784000}, {0x3f786000}, + {0x3f788000}, {0x3f78a000}, {0x3f78c000}, {0x3f78e000}, + {0x3f790000}, {0x3f792000}, {0x3f794000}, {0x3f796000}, + {0x3f798000}, {0x3f79a000}, {0x3f79c000}, {0x3f79e000}, + {0x3f7a0000}, {0x3f7a2000}, {0x3f7a4000}, {0x3f7a6000}, + {0x3f7a8000}, {0x3f7aa000}, {0x3f7ac000}, {0x3f7ae000}, + {0x3f7b0000}, {0x3f7b2000}, {0x3f7b4000}, {0x3f7b6000}, + {0x3f7b8000}, {0x3f7ba000}, {0x3f7bc000}, {0x3f7be000}, + {0x3f7c0000}, {0x3f7c2000}, {0x3f7c4000}, {0x3f7c6000}, + {0x3f7c8000}, {0x3f7ca000}, {0x3f7cc000}, {0x3f7ce000}, + {0x3f7d0000}, {0x3f7d2000}, {0x3f7d4000}, {0x3f7d6000}, + {0x3f7d8000}, {0x3f7da000}, {0x3f7dc000}, {0x3f7de000}, + {0x3f7e0000}, {0x3f7e2000}, {0x3f7e4000}, {0x3f7e6000}, + {0x3f7e8000}, {0x3f7ea000}, {0x3f7ec000}, {0x3f7ee000}, + {0x3f7f0000}, {0x3f7f2000}, {0x3f7f4000}, {0x3f7f6000}, + {0x3f7f8000}, {0x3f7fa000}, {0x3f7fc000}, {0x3f7fe000}, + {0x3f800000}, {0x3f802000}, {0x3f804000}, {0x3f806000}, + {0x3f808000}, {0x3f80a000}, {0x3f80c000}, {0x3f80e000}, + {0x3f810000}, {0x3f812000}, {0x3f814000}, {0x3f816000}, + {0x3f818000}, {0x3f81a000}, {0x3f81c000}, {0x3f81e000}, + {0x3f820000}, {0x3f822000}, {0x3f824000}, {0x3f826000}, + {0x3f828000}, {0x3f82a000}, {0x3f82c000}, {0x3f82e000}, + {0x3f830000}, {0x3f832000}, {0x3f834000}, {0x3f836000}, + {0x3f838000}, {0x3f83a000}, {0x3f83c000}, {0x3f83e000}, + {0x3f840000}, {0x3f842000}, {0x3f844000}, {0x3f846000}, + {0x3f848000}, {0x3f84a000}, {0x3f84c000}, {0x3f84e000}, + {0x3f850000}, {0x3f852000}, {0x3f854000}, {0x3f856000}, + {0x3f858000}, {0x3f85a000}, {0x3f85c000}, {0x3f85e000}, + {0x3f860000}, {0x3f862000}, {0x3f864000}, {0x3f866000}, + {0x3f868000}, {0x3f86a000}, {0x3f86c000}, {0x3f86e000}, + {0x3f870000}, {0x3f872000}, {0x3f874000}, {0x3f876000}, + {0x3f878000}, {0x3f87a000}, {0x3f87c000}, {0x3f87e000}, + {0x3f880000}, {0x3f882000}, {0x3f884000}, {0x3f886000}, + {0x3f888000}, {0x3f88a000}, {0x3f88c000}, {0x3f88e000}, + {0x3f890000}, {0x3f892000}, {0x3f894000}, {0x3f896000}, + {0x3f898000}, {0x3f89a000}, {0x3f89c000}, {0x3f89e000}, + {0x3f8a0000}, {0x3f8a2000}, {0x3f8a4000}, {0x3f8a6000}, + {0x3f8a8000}, {0x3f8aa000}, {0x3f8ac000}, {0x3f8ae000}, + {0x3f8b0000}, {0x3f8b2000}, {0x3f8b4000}, {0x3f8b6000}, + {0x3f8b8000}, {0x3f8ba000}, {0x3f8bc000}, {0x3f8be000}, + {0x3f8c0000}, {0x3f8c2000}, {0x3f8c4000}, {0x3f8c6000}, + {0x3f8c8000}, {0x3f8ca000}, {0x3f8cc000}, {0x3f8ce000}, + {0x3f8d0000}, {0x3f8d2000}, {0x3f8d4000}, {0x3f8d6000}, + {0x3f8d8000}, {0x3f8da000}, {0x3f8dc000}, {0x3f8de000}, + {0x3f8e0000}, {0x3f8e2000}, {0x3f8e4000}, {0x3f8e6000}, + {0x3f8e8000}, {0x3f8ea000}, {0x3f8ec000}, {0x3f8ee000}, + {0x3f8f0000}, {0x3f8f2000}, {0x3f8f4000}, {0x3f8f6000}, + {0x3f8f8000}, {0x3f8fa000}, {0x3f8fc000}, {0x3f8fe000}, + {0x3f900000}, {0x3f902000}, {0x3f904000}, {0x3f906000}, + {0x3f908000}, {0x3f90a000}, {0x3f90c000}, {0x3f90e000}, + {0x3f910000}, {0x3f912000}, {0x3f914000}, {0x3f916000}, + {0x3f918000}, {0x3f91a000}, {0x3f91c000}, {0x3f91e000}, + {0x3f920000}, {0x3f922000}, {0x3f924000}, {0x3f926000}, + {0x3f928000}, {0x3f92a000}, {0x3f92c000}, {0x3f92e000}, + {0x3f930000}, {0x3f932000}, {0x3f934000}, {0x3f936000}, + {0x3f938000}, {0x3f93a000}, {0x3f93c000}, {0x3f93e000}, + {0x3f940000}, {0x3f942000}, {0x3f944000}, {0x3f946000}, + {0x3f948000}, {0x3f94a000}, {0x3f94c000}, {0x3f94e000}, + {0x3f950000}, {0x3f952000}, {0x3f954000}, {0x3f956000}, + {0x3f958000}, {0x3f95a000}, {0x3f95c000}, {0x3f95e000}, + {0x3f960000}, {0x3f962000}, {0x3f964000}, {0x3f966000}, + {0x3f968000}, {0x3f96a000}, {0x3f96c000}, {0x3f96e000}, + {0x3f970000}, {0x3f972000}, {0x3f974000}, {0x3f976000}, + {0x3f978000}, {0x3f97a000}, {0x3f97c000}, {0x3f97e000}, + {0x3f980000}, {0x3f982000}, {0x3f984000}, {0x3f986000}, + {0x3f988000}, {0x3f98a000}, {0x3f98c000}, {0x3f98e000}, + {0x3f990000}, {0x3f992000}, {0x3f994000}, {0x3f996000}, + {0x3f998000}, {0x3f99a000}, {0x3f99c000}, {0x3f99e000}, + {0x3f9a0000}, {0x3f9a2000}, {0x3f9a4000}, {0x3f9a6000}, + {0x3f9a8000}, {0x3f9aa000}, {0x3f9ac000}, {0x3f9ae000}, + {0x3f9b0000}, {0x3f9b2000}, {0x3f9b4000}, {0x3f9b6000}, + {0x3f9b8000}, {0x3f9ba000}, {0x3f9bc000}, {0x3f9be000}, + {0x3f9c0000}, {0x3f9c2000}, {0x3f9c4000}, {0x3f9c6000}, + {0x3f9c8000}, {0x3f9ca000}, {0x3f9cc000}, {0x3f9ce000}, + {0x3f9d0000}, {0x3f9d2000}, {0x3f9d4000}, {0x3f9d6000}, + {0x3f9d8000}, {0x3f9da000}, {0x3f9dc000}, {0x3f9de000}, + {0x3f9e0000}, {0x3f9e2000}, {0x3f9e4000}, {0x3f9e6000}, + {0x3f9e8000}, {0x3f9ea000}, {0x3f9ec000}, {0x3f9ee000}, + {0x3f9f0000}, {0x3f9f2000}, {0x3f9f4000}, {0x3f9f6000}, + {0x3f9f8000}, {0x3f9fa000}, {0x3f9fc000}, {0x3f9fe000}, + {0x3fa00000}, {0x3fa02000}, {0x3fa04000}, {0x3fa06000}, + {0x3fa08000}, {0x3fa0a000}, {0x3fa0c000}, {0x3fa0e000}, + {0x3fa10000}, {0x3fa12000}, {0x3fa14000}, {0x3fa16000}, + {0x3fa18000}, {0x3fa1a000}, {0x3fa1c000}, {0x3fa1e000}, + {0x3fa20000}, {0x3fa22000}, {0x3fa24000}, {0x3fa26000}, + {0x3fa28000}, {0x3fa2a000}, {0x3fa2c000}, {0x3fa2e000}, + {0x3fa30000}, {0x3fa32000}, {0x3fa34000}, {0x3fa36000}, + {0x3fa38000}, {0x3fa3a000}, {0x3fa3c000}, {0x3fa3e000}, + {0x3fa40000}, {0x3fa42000}, {0x3fa44000}, {0x3fa46000}, + {0x3fa48000}, {0x3fa4a000}, {0x3fa4c000}, {0x3fa4e000}, + {0x3fa50000}, {0x3fa52000}, {0x3fa54000}, {0x3fa56000}, + {0x3fa58000}, {0x3fa5a000}, {0x3fa5c000}, {0x3fa5e000}, + {0x3fa60000}, {0x3fa62000}, {0x3fa64000}, {0x3fa66000}, + {0x3fa68000}, {0x3fa6a000}, {0x3fa6c000}, {0x3fa6e000}, + {0x3fa70000}, {0x3fa72000}, {0x3fa74000}, {0x3fa76000}, + {0x3fa78000}, {0x3fa7a000}, {0x3fa7c000}, {0x3fa7e000}, + {0x3fa80000}, {0x3fa82000}, {0x3fa84000}, {0x3fa86000}, + {0x3fa88000}, {0x3fa8a000}, {0x3fa8c000}, {0x3fa8e000}, + {0x3fa90000}, {0x3fa92000}, {0x3fa94000}, {0x3fa96000}, + {0x3fa98000}, {0x3fa9a000}, {0x3fa9c000}, {0x3fa9e000}, + {0x3faa0000}, {0x3faa2000}, {0x3faa4000}, {0x3faa6000}, + {0x3faa8000}, {0x3faaa000}, {0x3faac000}, {0x3faae000}, + {0x3fab0000}, {0x3fab2000}, {0x3fab4000}, {0x3fab6000}, + {0x3fab8000}, {0x3faba000}, {0x3fabc000}, {0x3fabe000}, + {0x3fac0000}, {0x3fac2000}, {0x3fac4000}, {0x3fac6000}, + {0x3fac8000}, {0x3faca000}, {0x3facc000}, {0x3face000}, + {0x3fad0000}, {0x3fad2000}, {0x3fad4000}, {0x3fad6000}, + {0x3fad8000}, {0x3fada000}, {0x3fadc000}, {0x3fade000}, + {0x3fae0000}, {0x3fae2000}, {0x3fae4000}, {0x3fae6000}, + {0x3fae8000}, {0x3faea000}, {0x3faec000}, {0x3faee000}, + {0x3faf0000}, {0x3faf2000}, {0x3faf4000}, {0x3faf6000}, + {0x3faf8000}, {0x3fafa000}, {0x3fafc000}, {0x3fafe000}, + {0x3fb00000}, {0x3fb02000}, {0x3fb04000}, {0x3fb06000}, + {0x3fb08000}, {0x3fb0a000}, {0x3fb0c000}, {0x3fb0e000}, + {0x3fb10000}, {0x3fb12000}, {0x3fb14000}, {0x3fb16000}, + {0x3fb18000}, {0x3fb1a000}, {0x3fb1c000}, {0x3fb1e000}, + {0x3fb20000}, {0x3fb22000}, {0x3fb24000}, {0x3fb26000}, + {0x3fb28000}, {0x3fb2a000}, {0x3fb2c000}, {0x3fb2e000}, + {0x3fb30000}, {0x3fb32000}, {0x3fb34000}, {0x3fb36000}, + {0x3fb38000}, {0x3fb3a000}, {0x3fb3c000}, {0x3fb3e000}, + {0x3fb40000}, {0x3fb42000}, {0x3fb44000}, {0x3fb46000}, + {0x3fb48000}, {0x3fb4a000}, {0x3fb4c000}, {0x3fb4e000}, + {0x3fb50000}, {0x3fb52000}, {0x3fb54000}, {0x3fb56000}, + {0x3fb58000}, {0x3fb5a000}, {0x3fb5c000}, {0x3fb5e000}, + {0x3fb60000}, {0x3fb62000}, {0x3fb64000}, {0x3fb66000}, + {0x3fb68000}, {0x3fb6a000}, {0x3fb6c000}, {0x3fb6e000}, + {0x3fb70000}, {0x3fb72000}, {0x3fb74000}, {0x3fb76000}, + {0x3fb78000}, {0x3fb7a000}, {0x3fb7c000}, {0x3fb7e000}, + {0x3fb80000}, {0x3fb82000}, {0x3fb84000}, {0x3fb86000}, + {0x3fb88000}, {0x3fb8a000}, {0x3fb8c000}, {0x3fb8e000}, + {0x3fb90000}, {0x3fb92000}, {0x3fb94000}, {0x3fb96000}, + {0x3fb98000}, {0x3fb9a000}, {0x3fb9c000}, {0x3fb9e000}, + {0x3fba0000}, {0x3fba2000}, {0x3fba4000}, {0x3fba6000}, + {0x3fba8000}, {0x3fbaa000}, {0x3fbac000}, {0x3fbae000}, + {0x3fbb0000}, {0x3fbb2000}, {0x3fbb4000}, {0x3fbb6000}, + {0x3fbb8000}, {0x3fbba000}, {0x3fbbc000}, {0x3fbbe000}, + {0x3fbc0000}, {0x3fbc2000}, {0x3fbc4000}, {0x3fbc6000}, + {0x3fbc8000}, {0x3fbca000}, {0x3fbcc000}, {0x3fbce000}, + {0x3fbd0000}, {0x3fbd2000}, {0x3fbd4000}, {0x3fbd6000}, + {0x3fbd8000}, {0x3fbda000}, {0x3fbdc000}, {0x3fbde000}, + {0x3fbe0000}, {0x3fbe2000}, {0x3fbe4000}, {0x3fbe6000}, + {0x3fbe8000}, {0x3fbea000}, {0x3fbec000}, {0x3fbee000}, + {0x3fbf0000}, {0x3fbf2000}, {0x3fbf4000}, {0x3fbf6000}, + {0x3fbf8000}, {0x3fbfa000}, {0x3fbfc000}, {0x3fbfe000}, + {0x3fc00000}, {0x3fc02000}, {0x3fc04000}, {0x3fc06000}, + {0x3fc08000}, {0x3fc0a000}, {0x3fc0c000}, {0x3fc0e000}, + {0x3fc10000}, {0x3fc12000}, {0x3fc14000}, {0x3fc16000}, + {0x3fc18000}, {0x3fc1a000}, {0x3fc1c000}, {0x3fc1e000}, + {0x3fc20000}, {0x3fc22000}, {0x3fc24000}, {0x3fc26000}, + {0x3fc28000}, {0x3fc2a000}, {0x3fc2c000}, {0x3fc2e000}, + {0x3fc30000}, {0x3fc32000}, {0x3fc34000}, {0x3fc36000}, + {0x3fc38000}, {0x3fc3a000}, {0x3fc3c000}, {0x3fc3e000}, + {0x3fc40000}, {0x3fc42000}, {0x3fc44000}, {0x3fc46000}, + {0x3fc48000}, {0x3fc4a000}, {0x3fc4c000}, {0x3fc4e000}, + {0x3fc50000}, {0x3fc52000}, {0x3fc54000}, {0x3fc56000}, + {0x3fc58000}, {0x3fc5a000}, {0x3fc5c000}, {0x3fc5e000}, + {0x3fc60000}, {0x3fc62000}, {0x3fc64000}, {0x3fc66000}, + {0x3fc68000}, {0x3fc6a000}, {0x3fc6c000}, {0x3fc6e000}, + {0x3fc70000}, {0x3fc72000}, {0x3fc74000}, {0x3fc76000}, + {0x3fc78000}, {0x3fc7a000}, {0x3fc7c000}, {0x3fc7e000}, + {0x3fc80000}, {0x3fc82000}, {0x3fc84000}, {0x3fc86000}, + {0x3fc88000}, {0x3fc8a000}, {0x3fc8c000}, {0x3fc8e000}, + {0x3fc90000}, {0x3fc92000}, {0x3fc94000}, {0x3fc96000}, + {0x3fc98000}, {0x3fc9a000}, {0x3fc9c000}, {0x3fc9e000}, + {0x3fca0000}, {0x3fca2000}, {0x3fca4000}, {0x3fca6000}, + {0x3fca8000}, {0x3fcaa000}, {0x3fcac000}, {0x3fcae000}, + {0x3fcb0000}, {0x3fcb2000}, {0x3fcb4000}, {0x3fcb6000}, + {0x3fcb8000}, {0x3fcba000}, {0x3fcbc000}, {0x3fcbe000}, + {0x3fcc0000}, {0x3fcc2000}, {0x3fcc4000}, {0x3fcc6000}, + {0x3fcc8000}, {0x3fcca000}, {0x3fccc000}, {0x3fcce000}, + {0x3fcd0000}, {0x3fcd2000}, {0x3fcd4000}, {0x3fcd6000}, + {0x3fcd8000}, {0x3fcda000}, {0x3fcdc000}, {0x3fcde000}, + {0x3fce0000}, {0x3fce2000}, {0x3fce4000}, {0x3fce6000}, + {0x3fce8000}, {0x3fcea000}, {0x3fcec000}, {0x3fcee000}, + {0x3fcf0000}, {0x3fcf2000}, {0x3fcf4000}, {0x3fcf6000}, + {0x3fcf8000}, {0x3fcfa000}, {0x3fcfc000}, {0x3fcfe000}, + {0x3fd00000}, {0x3fd02000}, {0x3fd04000}, {0x3fd06000}, + {0x3fd08000}, {0x3fd0a000}, {0x3fd0c000}, {0x3fd0e000}, + {0x3fd10000}, {0x3fd12000}, {0x3fd14000}, {0x3fd16000}, + {0x3fd18000}, {0x3fd1a000}, {0x3fd1c000}, {0x3fd1e000}, + {0x3fd20000}, {0x3fd22000}, {0x3fd24000}, {0x3fd26000}, + {0x3fd28000}, {0x3fd2a000}, {0x3fd2c000}, {0x3fd2e000}, + {0x3fd30000}, {0x3fd32000}, {0x3fd34000}, {0x3fd36000}, + {0x3fd38000}, {0x3fd3a000}, {0x3fd3c000}, {0x3fd3e000}, + {0x3fd40000}, {0x3fd42000}, {0x3fd44000}, {0x3fd46000}, + {0x3fd48000}, {0x3fd4a000}, {0x3fd4c000}, {0x3fd4e000}, + {0x3fd50000}, {0x3fd52000}, {0x3fd54000}, {0x3fd56000}, + {0x3fd58000}, {0x3fd5a000}, {0x3fd5c000}, {0x3fd5e000}, + {0x3fd60000}, {0x3fd62000}, {0x3fd64000}, {0x3fd66000}, + {0x3fd68000}, {0x3fd6a000}, {0x3fd6c000}, {0x3fd6e000}, + {0x3fd70000}, {0x3fd72000}, {0x3fd74000}, {0x3fd76000}, + {0x3fd78000}, {0x3fd7a000}, {0x3fd7c000}, {0x3fd7e000}, + {0x3fd80000}, {0x3fd82000}, {0x3fd84000}, {0x3fd86000}, + {0x3fd88000}, {0x3fd8a000}, {0x3fd8c000}, {0x3fd8e000}, + {0x3fd90000}, {0x3fd92000}, {0x3fd94000}, {0x3fd96000}, + {0x3fd98000}, {0x3fd9a000}, {0x3fd9c000}, {0x3fd9e000}, + {0x3fda0000}, {0x3fda2000}, {0x3fda4000}, {0x3fda6000}, + {0x3fda8000}, {0x3fdaa000}, {0x3fdac000}, {0x3fdae000}, + {0x3fdb0000}, {0x3fdb2000}, {0x3fdb4000}, {0x3fdb6000}, + {0x3fdb8000}, {0x3fdba000}, {0x3fdbc000}, {0x3fdbe000}, + {0x3fdc0000}, {0x3fdc2000}, {0x3fdc4000}, {0x3fdc6000}, + {0x3fdc8000}, {0x3fdca000}, {0x3fdcc000}, {0x3fdce000}, + {0x3fdd0000}, {0x3fdd2000}, {0x3fdd4000}, {0x3fdd6000}, + {0x3fdd8000}, {0x3fdda000}, {0x3fddc000}, {0x3fdde000}, + {0x3fde0000}, {0x3fde2000}, {0x3fde4000}, {0x3fde6000}, + {0x3fde8000}, {0x3fdea000}, {0x3fdec000}, {0x3fdee000}, + {0x3fdf0000}, {0x3fdf2000}, {0x3fdf4000}, {0x3fdf6000}, + {0x3fdf8000}, {0x3fdfa000}, {0x3fdfc000}, {0x3fdfe000}, + {0x3fe00000}, {0x3fe02000}, {0x3fe04000}, {0x3fe06000}, + {0x3fe08000}, {0x3fe0a000}, {0x3fe0c000}, {0x3fe0e000}, + {0x3fe10000}, {0x3fe12000}, {0x3fe14000}, {0x3fe16000}, + {0x3fe18000}, {0x3fe1a000}, {0x3fe1c000}, {0x3fe1e000}, + {0x3fe20000}, {0x3fe22000}, {0x3fe24000}, {0x3fe26000}, + {0x3fe28000}, {0x3fe2a000}, {0x3fe2c000}, {0x3fe2e000}, + {0x3fe30000}, {0x3fe32000}, {0x3fe34000}, {0x3fe36000}, + {0x3fe38000}, {0x3fe3a000}, {0x3fe3c000}, {0x3fe3e000}, + {0x3fe40000}, {0x3fe42000}, {0x3fe44000}, {0x3fe46000}, + {0x3fe48000}, {0x3fe4a000}, {0x3fe4c000}, {0x3fe4e000}, + {0x3fe50000}, {0x3fe52000}, {0x3fe54000}, {0x3fe56000}, + {0x3fe58000}, {0x3fe5a000}, {0x3fe5c000}, {0x3fe5e000}, + {0x3fe60000}, {0x3fe62000}, {0x3fe64000}, {0x3fe66000}, + {0x3fe68000}, {0x3fe6a000}, {0x3fe6c000}, {0x3fe6e000}, + {0x3fe70000}, {0x3fe72000}, {0x3fe74000}, {0x3fe76000}, + {0x3fe78000}, {0x3fe7a000}, {0x3fe7c000}, {0x3fe7e000}, + {0x3fe80000}, {0x3fe82000}, {0x3fe84000}, {0x3fe86000}, + {0x3fe88000}, {0x3fe8a000}, {0x3fe8c000}, {0x3fe8e000}, + {0x3fe90000}, {0x3fe92000}, {0x3fe94000}, {0x3fe96000}, + {0x3fe98000}, {0x3fe9a000}, {0x3fe9c000}, {0x3fe9e000}, + {0x3fea0000}, {0x3fea2000}, {0x3fea4000}, {0x3fea6000}, + {0x3fea8000}, {0x3feaa000}, {0x3feac000}, {0x3feae000}, + {0x3feb0000}, {0x3feb2000}, {0x3feb4000}, {0x3feb6000}, + {0x3feb8000}, {0x3feba000}, {0x3febc000}, {0x3febe000}, + {0x3fec0000}, {0x3fec2000}, {0x3fec4000}, {0x3fec6000}, + {0x3fec8000}, {0x3feca000}, {0x3fecc000}, {0x3fece000}, + {0x3fed0000}, {0x3fed2000}, {0x3fed4000}, {0x3fed6000}, + {0x3fed8000}, {0x3feda000}, {0x3fedc000}, {0x3fede000}, + {0x3fee0000}, {0x3fee2000}, {0x3fee4000}, {0x3fee6000}, + {0x3fee8000}, {0x3feea000}, {0x3feec000}, {0x3feee000}, + {0x3fef0000}, {0x3fef2000}, {0x3fef4000}, {0x3fef6000}, + {0x3fef8000}, {0x3fefa000}, {0x3fefc000}, {0x3fefe000}, + {0x3ff00000}, {0x3ff02000}, {0x3ff04000}, {0x3ff06000}, + {0x3ff08000}, {0x3ff0a000}, {0x3ff0c000}, {0x3ff0e000}, + {0x3ff10000}, {0x3ff12000}, {0x3ff14000}, {0x3ff16000}, + {0x3ff18000}, {0x3ff1a000}, {0x3ff1c000}, {0x3ff1e000}, + {0x3ff20000}, {0x3ff22000}, {0x3ff24000}, {0x3ff26000}, + {0x3ff28000}, {0x3ff2a000}, {0x3ff2c000}, {0x3ff2e000}, + {0x3ff30000}, {0x3ff32000}, {0x3ff34000}, {0x3ff36000}, + {0x3ff38000}, {0x3ff3a000}, {0x3ff3c000}, {0x3ff3e000}, + {0x3ff40000}, {0x3ff42000}, {0x3ff44000}, {0x3ff46000}, + {0x3ff48000}, {0x3ff4a000}, {0x3ff4c000}, {0x3ff4e000}, + {0x3ff50000}, {0x3ff52000}, {0x3ff54000}, {0x3ff56000}, + {0x3ff58000}, {0x3ff5a000}, {0x3ff5c000}, {0x3ff5e000}, + {0x3ff60000}, {0x3ff62000}, {0x3ff64000}, {0x3ff66000}, + {0x3ff68000}, {0x3ff6a000}, {0x3ff6c000}, {0x3ff6e000}, + {0x3ff70000}, {0x3ff72000}, {0x3ff74000}, {0x3ff76000}, + {0x3ff78000}, {0x3ff7a000}, {0x3ff7c000}, {0x3ff7e000}, + {0x3ff80000}, {0x3ff82000}, {0x3ff84000}, {0x3ff86000}, + {0x3ff88000}, {0x3ff8a000}, {0x3ff8c000}, {0x3ff8e000}, + {0x3ff90000}, {0x3ff92000}, {0x3ff94000}, {0x3ff96000}, + {0x3ff98000}, {0x3ff9a000}, {0x3ff9c000}, {0x3ff9e000}, + {0x3ffa0000}, {0x3ffa2000}, {0x3ffa4000}, {0x3ffa6000}, + {0x3ffa8000}, {0x3ffaa000}, {0x3ffac000}, {0x3ffae000}, + {0x3ffb0000}, {0x3ffb2000}, {0x3ffb4000}, {0x3ffb6000}, + {0x3ffb8000}, {0x3ffba000}, {0x3ffbc000}, {0x3ffbe000}, + {0x3ffc0000}, {0x3ffc2000}, {0x3ffc4000}, {0x3ffc6000}, + {0x3ffc8000}, {0x3ffca000}, {0x3ffcc000}, {0x3ffce000}, + {0x3ffd0000}, {0x3ffd2000}, {0x3ffd4000}, {0x3ffd6000}, + {0x3ffd8000}, {0x3ffda000}, {0x3ffdc000}, {0x3ffde000}, + {0x3ffe0000}, {0x3ffe2000}, {0x3ffe4000}, {0x3ffe6000}, + {0x3ffe8000}, {0x3ffea000}, {0x3ffec000}, {0x3ffee000}, + {0x3fff0000}, {0x3fff2000}, {0x3fff4000}, {0x3fff6000}, + {0x3fff8000}, {0x3fffa000}, {0x3fffc000}, {0x3fffe000}, + {0x40000000}, {0x40002000}, {0x40004000}, {0x40006000}, + {0x40008000}, {0x4000a000}, {0x4000c000}, {0x4000e000}, + {0x40010000}, {0x40012000}, {0x40014000}, {0x40016000}, + {0x40018000}, {0x4001a000}, {0x4001c000}, {0x4001e000}, + {0x40020000}, {0x40022000}, {0x40024000}, {0x40026000}, + {0x40028000}, {0x4002a000}, {0x4002c000}, {0x4002e000}, + {0x40030000}, {0x40032000}, {0x40034000}, {0x40036000}, + {0x40038000}, {0x4003a000}, {0x4003c000}, {0x4003e000}, + {0x40040000}, {0x40042000}, {0x40044000}, {0x40046000}, + {0x40048000}, {0x4004a000}, {0x4004c000}, {0x4004e000}, + {0x40050000}, {0x40052000}, {0x40054000}, {0x40056000}, + {0x40058000}, {0x4005a000}, {0x4005c000}, {0x4005e000}, + {0x40060000}, {0x40062000}, {0x40064000}, {0x40066000}, + {0x40068000}, {0x4006a000}, {0x4006c000}, {0x4006e000}, + {0x40070000}, {0x40072000}, {0x40074000}, {0x40076000}, + {0x40078000}, {0x4007a000}, {0x4007c000}, {0x4007e000}, + {0x40080000}, {0x40082000}, {0x40084000}, {0x40086000}, + {0x40088000}, {0x4008a000}, {0x4008c000}, {0x4008e000}, + {0x40090000}, {0x40092000}, {0x40094000}, {0x40096000}, + {0x40098000}, {0x4009a000}, {0x4009c000}, {0x4009e000}, + {0x400a0000}, {0x400a2000}, {0x400a4000}, {0x400a6000}, + {0x400a8000}, {0x400aa000}, {0x400ac000}, {0x400ae000}, + {0x400b0000}, {0x400b2000}, {0x400b4000}, {0x400b6000}, + {0x400b8000}, {0x400ba000}, {0x400bc000}, {0x400be000}, + {0x400c0000}, {0x400c2000}, {0x400c4000}, {0x400c6000}, + {0x400c8000}, {0x400ca000}, {0x400cc000}, {0x400ce000}, + {0x400d0000}, {0x400d2000}, {0x400d4000}, {0x400d6000}, + {0x400d8000}, {0x400da000}, {0x400dc000}, {0x400de000}, + {0x400e0000}, {0x400e2000}, {0x400e4000}, {0x400e6000}, + {0x400e8000}, {0x400ea000}, {0x400ec000}, {0x400ee000}, + {0x400f0000}, {0x400f2000}, {0x400f4000}, {0x400f6000}, + {0x400f8000}, {0x400fa000}, {0x400fc000}, {0x400fe000}, + {0x40100000}, {0x40102000}, {0x40104000}, {0x40106000}, + {0x40108000}, {0x4010a000}, {0x4010c000}, {0x4010e000}, + {0x40110000}, {0x40112000}, {0x40114000}, {0x40116000}, + {0x40118000}, {0x4011a000}, {0x4011c000}, {0x4011e000}, + {0x40120000}, {0x40122000}, {0x40124000}, {0x40126000}, + {0x40128000}, {0x4012a000}, {0x4012c000}, {0x4012e000}, + {0x40130000}, {0x40132000}, {0x40134000}, {0x40136000}, + {0x40138000}, {0x4013a000}, {0x4013c000}, {0x4013e000}, + {0x40140000}, {0x40142000}, {0x40144000}, {0x40146000}, + {0x40148000}, {0x4014a000}, {0x4014c000}, {0x4014e000}, + {0x40150000}, {0x40152000}, {0x40154000}, {0x40156000}, + {0x40158000}, {0x4015a000}, {0x4015c000}, {0x4015e000}, + {0x40160000}, {0x40162000}, {0x40164000}, {0x40166000}, + {0x40168000}, {0x4016a000}, {0x4016c000}, {0x4016e000}, + {0x40170000}, {0x40172000}, {0x40174000}, {0x40176000}, + {0x40178000}, {0x4017a000}, {0x4017c000}, {0x4017e000}, + {0x40180000}, {0x40182000}, {0x40184000}, {0x40186000}, + {0x40188000}, {0x4018a000}, {0x4018c000}, {0x4018e000}, + {0x40190000}, {0x40192000}, {0x40194000}, {0x40196000}, + {0x40198000}, {0x4019a000}, {0x4019c000}, {0x4019e000}, + {0x401a0000}, {0x401a2000}, {0x401a4000}, {0x401a6000}, + {0x401a8000}, {0x401aa000}, {0x401ac000}, {0x401ae000}, + {0x401b0000}, {0x401b2000}, {0x401b4000}, {0x401b6000}, + {0x401b8000}, {0x401ba000}, {0x401bc000}, {0x401be000}, + {0x401c0000}, {0x401c2000}, {0x401c4000}, {0x401c6000}, + {0x401c8000}, {0x401ca000}, {0x401cc000}, {0x401ce000}, + {0x401d0000}, {0x401d2000}, {0x401d4000}, {0x401d6000}, + {0x401d8000}, {0x401da000}, {0x401dc000}, {0x401de000}, + {0x401e0000}, {0x401e2000}, {0x401e4000}, {0x401e6000}, + {0x401e8000}, {0x401ea000}, {0x401ec000}, {0x401ee000}, + {0x401f0000}, {0x401f2000}, {0x401f4000}, {0x401f6000}, + {0x401f8000}, {0x401fa000}, {0x401fc000}, {0x401fe000}, + {0x40200000}, {0x40202000}, {0x40204000}, {0x40206000}, + {0x40208000}, {0x4020a000}, {0x4020c000}, {0x4020e000}, + {0x40210000}, {0x40212000}, {0x40214000}, {0x40216000}, + {0x40218000}, {0x4021a000}, {0x4021c000}, {0x4021e000}, + {0x40220000}, {0x40222000}, {0x40224000}, {0x40226000}, + {0x40228000}, {0x4022a000}, {0x4022c000}, {0x4022e000}, + {0x40230000}, {0x40232000}, {0x40234000}, {0x40236000}, + {0x40238000}, {0x4023a000}, {0x4023c000}, {0x4023e000}, + {0x40240000}, {0x40242000}, {0x40244000}, {0x40246000}, + {0x40248000}, {0x4024a000}, {0x4024c000}, {0x4024e000}, + {0x40250000}, {0x40252000}, {0x40254000}, {0x40256000}, + {0x40258000}, {0x4025a000}, {0x4025c000}, {0x4025e000}, + {0x40260000}, {0x40262000}, {0x40264000}, {0x40266000}, + {0x40268000}, {0x4026a000}, {0x4026c000}, {0x4026e000}, + {0x40270000}, {0x40272000}, {0x40274000}, {0x40276000}, + {0x40278000}, {0x4027a000}, {0x4027c000}, {0x4027e000}, + {0x40280000}, {0x40282000}, {0x40284000}, {0x40286000}, + {0x40288000}, {0x4028a000}, {0x4028c000}, {0x4028e000}, + {0x40290000}, {0x40292000}, {0x40294000}, {0x40296000}, + {0x40298000}, {0x4029a000}, {0x4029c000}, {0x4029e000}, + {0x402a0000}, {0x402a2000}, {0x402a4000}, {0x402a6000}, + {0x402a8000}, {0x402aa000}, {0x402ac000}, {0x402ae000}, + {0x402b0000}, {0x402b2000}, {0x402b4000}, {0x402b6000}, + {0x402b8000}, {0x402ba000}, {0x402bc000}, {0x402be000}, + {0x402c0000}, {0x402c2000}, {0x402c4000}, {0x402c6000}, + {0x402c8000}, {0x402ca000}, {0x402cc000}, {0x402ce000}, + {0x402d0000}, {0x402d2000}, {0x402d4000}, {0x402d6000}, + {0x402d8000}, {0x402da000}, {0x402dc000}, {0x402de000}, + {0x402e0000}, {0x402e2000}, {0x402e4000}, {0x402e6000}, + {0x402e8000}, {0x402ea000}, {0x402ec000}, {0x402ee000}, + {0x402f0000}, {0x402f2000}, {0x402f4000}, {0x402f6000}, + {0x402f8000}, {0x402fa000}, {0x402fc000}, {0x402fe000}, + {0x40300000}, {0x40302000}, {0x40304000}, {0x40306000}, + {0x40308000}, {0x4030a000}, {0x4030c000}, {0x4030e000}, + {0x40310000}, {0x40312000}, {0x40314000}, {0x40316000}, + {0x40318000}, {0x4031a000}, {0x4031c000}, {0x4031e000}, + {0x40320000}, {0x40322000}, {0x40324000}, {0x40326000}, + {0x40328000}, {0x4032a000}, {0x4032c000}, {0x4032e000}, + {0x40330000}, {0x40332000}, {0x40334000}, {0x40336000}, + {0x40338000}, {0x4033a000}, {0x4033c000}, {0x4033e000}, + {0x40340000}, {0x40342000}, {0x40344000}, {0x40346000}, + {0x40348000}, {0x4034a000}, {0x4034c000}, {0x4034e000}, + {0x40350000}, {0x40352000}, {0x40354000}, {0x40356000}, + {0x40358000}, {0x4035a000}, {0x4035c000}, {0x4035e000}, + {0x40360000}, {0x40362000}, {0x40364000}, {0x40366000}, + {0x40368000}, {0x4036a000}, {0x4036c000}, {0x4036e000}, + {0x40370000}, {0x40372000}, {0x40374000}, {0x40376000}, + {0x40378000}, {0x4037a000}, {0x4037c000}, {0x4037e000}, + {0x40380000}, {0x40382000}, {0x40384000}, {0x40386000}, + {0x40388000}, {0x4038a000}, {0x4038c000}, {0x4038e000}, + {0x40390000}, {0x40392000}, {0x40394000}, {0x40396000}, + {0x40398000}, {0x4039a000}, {0x4039c000}, {0x4039e000}, + {0x403a0000}, {0x403a2000}, {0x403a4000}, {0x403a6000}, + {0x403a8000}, {0x403aa000}, {0x403ac000}, {0x403ae000}, + {0x403b0000}, {0x403b2000}, {0x403b4000}, {0x403b6000}, + {0x403b8000}, {0x403ba000}, {0x403bc000}, {0x403be000}, + {0x403c0000}, {0x403c2000}, {0x403c4000}, {0x403c6000}, + {0x403c8000}, {0x403ca000}, {0x403cc000}, {0x403ce000}, + {0x403d0000}, {0x403d2000}, {0x403d4000}, {0x403d6000}, + {0x403d8000}, {0x403da000}, {0x403dc000}, {0x403de000}, + {0x403e0000}, {0x403e2000}, {0x403e4000}, {0x403e6000}, + {0x403e8000}, {0x403ea000}, {0x403ec000}, {0x403ee000}, + {0x403f0000}, {0x403f2000}, {0x403f4000}, {0x403f6000}, + {0x403f8000}, {0x403fa000}, {0x403fc000}, {0x403fe000}, + {0x40400000}, {0x40402000}, {0x40404000}, {0x40406000}, + {0x40408000}, {0x4040a000}, {0x4040c000}, {0x4040e000}, + {0x40410000}, {0x40412000}, {0x40414000}, {0x40416000}, + {0x40418000}, {0x4041a000}, {0x4041c000}, {0x4041e000}, + {0x40420000}, {0x40422000}, {0x40424000}, {0x40426000}, + {0x40428000}, {0x4042a000}, {0x4042c000}, {0x4042e000}, + {0x40430000}, {0x40432000}, {0x40434000}, {0x40436000}, + {0x40438000}, {0x4043a000}, {0x4043c000}, {0x4043e000}, + {0x40440000}, {0x40442000}, {0x40444000}, {0x40446000}, + {0x40448000}, {0x4044a000}, {0x4044c000}, {0x4044e000}, + {0x40450000}, {0x40452000}, {0x40454000}, {0x40456000}, + {0x40458000}, {0x4045a000}, {0x4045c000}, {0x4045e000}, + {0x40460000}, {0x40462000}, {0x40464000}, {0x40466000}, + {0x40468000}, {0x4046a000}, {0x4046c000}, {0x4046e000}, + {0x40470000}, {0x40472000}, {0x40474000}, {0x40476000}, + {0x40478000}, {0x4047a000}, {0x4047c000}, {0x4047e000}, + {0x40480000}, {0x40482000}, {0x40484000}, {0x40486000}, + {0x40488000}, {0x4048a000}, {0x4048c000}, {0x4048e000}, + {0x40490000}, {0x40492000}, {0x40494000}, {0x40496000}, + {0x40498000}, {0x4049a000}, {0x4049c000}, {0x4049e000}, + {0x404a0000}, {0x404a2000}, {0x404a4000}, {0x404a6000}, + {0x404a8000}, {0x404aa000}, {0x404ac000}, {0x404ae000}, + {0x404b0000}, {0x404b2000}, {0x404b4000}, {0x404b6000}, + {0x404b8000}, {0x404ba000}, {0x404bc000}, {0x404be000}, + {0x404c0000}, {0x404c2000}, {0x404c4000}, {0x404c6000}, + {0x404c8000}, {0x404ca000}, {0x404cc000}, {0x404ce000}, + {0x404d0000}, {0x404d2000}, {0x404d4000}, {0x404d6000}, + {0x404d8000}, {0x404da000}, {0x404dc000}, {0x404de000}, + {0x404e0000}, {0x404e2000}, {0x404e4000}, {0x404e6000}, + {0x404e8000}, {0x404ea000}, {0x404ec000}, {0x404ee000}, + {0x404f0000}, {0x404f2000}, {0x404f4000}, {0x404f6000}, + {0x404f8000}, {0x404fa000}, {0x404fc000}, {0x404fe000}, + {0x40500000}, {0x40502000}, {0x40504000}, {0x40506000}, + {0x40508000}, {0x4050a000}, {0x4050c000}, {0x4050e000}, + {0x40510000}, {0x40512000}, {0x40514000}, {0x40516000}, + {0x40518000}, {0x4051a000}, {0x4051c000}, {0x4051e000}, + {0x40520000}, {0x40522000}, {0x40524000}, {0x40526000}, + {0x40528000}, {0x4052a000}, {0x4052c000}, {0x4052e000}, + {0x40530000}, {0x40532000}, {0x40534000}, {0x40536000}, + {0x40538000}, {0x4053a000}, {0x4053c000}, {0x4053e000}, + {0x40540000}, {0x40542000}, {0x40544000}, {0x40546000}, + {0x40548000}, {0x4054a000}, {0x4054c000}, {0x4054e000}, + {0x40550000}, {0x40552000}, {0x40554000}, {0x40556000}, + {0x40558000}, {0x4055a000}, {0x4055c000}, {0x4055e000}, + {0x40560000}, {0x40562000}, {0x40564000}, {0x40566000}, + {0x40568000}, {0x4056a000}, {0x4056c000}, {0x4056e000}, + {0x40570000}, {0x40572000}, {0x40574000}, {0x40576000}, + {0x40578000}, {0x4057a000}, {0x4057c000}, {0x4057e000}, + {0x40580000}, {0x40582000}, {0x40584000}, {0x40586000}, + {0x40588000}, {0x4058a000}, {0x4058c000}, {0x4058e000}, + {0x40590000}, {0x40592000}, {0x40594000}, {0x40596000}, + {0x40598000}, {0x4059a000}, {0x4059c000}, {0x4059e000}, + {0x405a0000}, {0x405a2000}, {0x405a4000}, {0x405a6000}, + {0x405a8000}, {0x405aa000}, {0x405ac000}, {0x405ae000}, + {0x405b0000}, {0x405b2000}, {0x405b4000}, {0x405b6000}, + {0x405b8000}, {0x405ba000}, {0x405bc000}, {0x405be000}, + {0x405c0000}, {0x405c2000}, {0x405c4000}, {0x405c6000}, + {0x405c8000}, {0x405ca000}, {0x405cc000}, {0x405ce000}, + {0x405d0000}, {0x405d2000}, {0x405d4000}, {0x405d6000}, + {0x405d8000}, {0x405da000}, {0x405dc000}, {0x405de000}, + {0x405e0000}, {0x405e2000}, {0x405e4000}, {0x405e6000}, + {0x405e8000}, {0x405ea000}, {0x405ec000}, {0x405ee000}, + {0x405f0000}, {0x405f2000}, {0x405f4000}, {0x405f6000}, + {0x405f8000}, {0x405fa000}, {0x405fc000}, {0x405fe000}, + {0x40600000}, {0x40602000}, {0x40604000}, {0x40606000}, + {0x40608000}, {0x4060a000}, {0x4060c000}, {0x4060e000}, + {0x40610000}, {0x40612000}, {0x40614000}, {0x40616000}, + {0x40618000}, {0x4061a000}, {0x4061c000}, {0x4061e000}, + {0x40620000}, {0x40622000}, {0x40624000}, {0x40626000}, + {0x40628000}, {0x4062a000}, {0x4062c000}, {0x4062e000}, + {0x40630000}, {0x40632000}, {0x40634000}, {0x40636000}, + {0x40638000}, {0x4063a000}, {0x4063c000}, {0x4063e000}, + {0x40640000}, {0x40642000}, {0x40644000}, {0x40646000}, + {0x40648000}, {0x4064a000}, {0x4064c000}, {0x4064e000}, + {0x40650000}, {0x40652000}, {0x40654000}, {0x40656000}, + {0x40658000}, {0x4065a000}, {0x4065c000}, {0x4065e000}, + {0x40660000}, {0x40662000}, {0x40664000}, {0x40666000}, + {0x40668000}, {0x4066a000}, {0x4066c000}, {0x4066e000}, + {0x40670000}, {0x40672000}, {0x40674000}, {0x40676000}, + {0x40678000}, {0x4067a000}, {0x4067c000}, {0x4067e000}, + {0x40680000}, {0x40682000}, {0x40684000}, {0x40686000}, + {0x40688000}, {0x4068a000}, {0x4068c000}, {0x4068e000}, + {0x40690000}, {0x40692000}, {0x40694000}, {0x40696000}, + {0x40698000}, {0x4069a000}, {0x4069c000}, {0x4069e000}, + {0x406a0000}, {0x406a2000}, {0x406a4000}, {0x406a6000}, + {0x406a8000}, {0x406aa000}, {0x406ac000}, {0x406ae000}, + {0x406b0000}, {0x406b2000}, {0x406b4000}, {0x406b6000}, + {0x406b8000}, {0x406ba000}, {0x406bc000}, {0x406be000}, + {0x406c0000}, {0x406c2000}, {0x406c4000}, {0x406c6000}, + {0x406c8000}, {0x406ca000}, {0x406cc000}, {0x406ce000}, + {0x406d0000}, {0x406d2000}, {0x406d4000}, {0x406d6000}, + {0x406d8000}, {0x406da000}, {0x406dc000}, {0x406de000}, + {0x406e0000}, {0x406e2000}, {0x406e4000}, {0x406e6000}, + {0x406e8000}, {0x406ea000}, {0x406ec000}, {0x406ee000}, + {0x406f0000}, {0x406f2000}, {0x406f4000}, {0x406f6000}, + {0x406f8000}, {0x406fa000}, {0x406fc000}, {0x406fe000}, + {0x40700000}, {0x40702000}, {0x40704000}, {0x40706000}, + {0x40708000}, {0x4070a000}, {0x4070c000}, {0x4070e000}, + {0x40710000}, {0x40712000}, {0x40714000}, {0x40716000}, + {0x40718000}, {0x4071a000}, {0x4071c000}, {0x4071e000}, + {0x40720000}, {0x40722000}, {0x40724000}, {0x40726000}, + {0x40728000}, {0x4072a000}, {0x4072c000}, {0x4072e000}, + {0x40730000}, {0x40732000}, {0x40734000}, {0x40736000}, + {0x40738000}, {0x4073a000}, {0x4073c000}, {0x4073e000}, + {0x40740000}, {0x40742000}, {0x40744000}, {0x40746000}, + {0x40748000}, {0x4074a000}, {0x4074c000}, {0x4074e000}, + {0x40750000}, {0x40752000}, {0x40754000}, {0x40756000}, + {0x40758000}, {0x4075a000}, {0x4075c000}, {0x4075e000}, + {0x40760000}, {0x40762000}, {0x40764000}, {0x40766000}, + {0x40768000}, {0x4076a000}, {0x4076c000}, {0x4076e000}, + {0x40770000}, {0x40772000}, {0x40774000}, {0x40776000}, + {0x40778000}, {0x4077a000}, {0x4077c000}, {0x4077e000}, + {0x40780000}, {0x40782000}, {0x40784000}, {0x40786000}, + {0x40788000}, {0x4078a000}, {0x4078c000}, {0x4078e000}, + {0x40790000}, {0x40792000}, {0x40794000}, {0x40796000}, + {0x40798000}, {0x4079a000}, {0x4079c000}, {0x4079e000}, + {0x407a0000}, {0x407a2000}, {0x407a4000}, {0x407a6000}, + {0x407a8000}, {0x407aa000}, {0x407ac000}, {0x407ae000}, + {0x407b0000}, {0x407b2000}, {0x407b4000}, {0x407b6000}, + {0x407b8000}, {0x407ba000}, {0x407bc000}, {0x407be000}, + {0x407c0000}, {0x407c2000}, {0x407c4000}, {0x407c6000}, + {0x407c8000}, {0x407ca000}, {0x407cc000}, {0x407ce000}, + {0x407d0000}, {0x407d2000}, {0x407d4000}, {0x407d6000}, + {0x407d8000}, {0x407da000}, {0x407dc000}, {0x407de000}, + {0x407e0000}, {0x407e2000}, {0x407e4000}, {0x407e6000}, + {0x407e8000}, {0x407ea000}, {0x407ec000}, {0x407ee000}, + {0x407f0000}, {0x407f2000}, {0x407f4000}, {0x407f6000}, + {0x407f8000}, {0x407fa000}, {0x407fc000}, {0x407fe000}, + {0x40800000}, {0x40802000}, {0x40804000}, {0x40806000}, + {0x40808000}, {0x4080a000}, {0x4080c000}, {0x4080e000}, + {0x40810000}, {0x40812000}, {0x40814000}, {0x40816000}, + {0x40818000}, {0x4081a000}, {0x4081c000}, {0x4081e000}, + {0x40820000}, {0x40822000}, {0x40824000}, {0x40826000}, + {0x40828000}, {0x4082a000}, {0x4082c000}, {0x4082e000}, + {0x40830000}, {0x40832000}, {0x40834000}, {0x40836000}, + {0x40838000}, {0x4083a000}, {0x4083c000}, {0x4083e000}, + {0x40840000}, {0x40842000}, {0x40844000}, {0x40846000}, + {0x40848000}, {0x4084a000}, {0x4084c000}, {0x4084e000}, + {0x40850000}, {0x40852000}, {0x40854000}, {0x40856000}, + {0x40858000}, {0x4085a000}, {0x4085c000}, {0x4085e000}, + {0x40860000}, {0x40862000}, {0x40864000}, {0x40866000}, + {0x40868000}, {0x4086a000}, {0x4086c000}, {0x4086e000}, + {0x40870000}, {0x40872000}, {0x40874000}, {0x40876000}, + {0x40878000}, {0x4087a000}, {0x4087c000}, {0x4087e000}, + {0x40880000}, {0x40882000}, {0x40884000}, {0x40886000}, + {0x40888000}, {0x4088a000}, {0x4088c000}, {0x4088e000}, + {0x40890000}, {0x40892000}, {0x40894000}, {0x40896000}, + {0x40898000}, {0x4089a000}, {0x4089c000}, {0x4089e000}, + {0x408a0000}, {0x408a2000}, {0x408a4000}, {0x408a6000}, + {0x408a8000}, {0x408aa000}, {0x408ac000}, {0x408ae000}, + {0x408b0000}, {0x408b2000}, {0x408b4000}, {0x408b6000}, + {0x408b8000}, {0x408ba000}, {0x408bc000}, {0x408be000}, + {0x408c0000}, {0x408c2000}, {0x408c4000}, {0x408c6000}, + {0x408c8000}, {0x408ca000}, {0x408cc000}, {0x408ce000}, + {0x408d0000}, {0x408d2000}, {0x408d4000}, {0x408d6000}, + {0x408d8000}, {0x408da000}, {0x408dc000}, {0x408de000}, + {0x408e0000}, {0x408e2000}, {0x408e4000}, {0x408e6000}, + {0x408e8000}, {0x408ea000}, {0x408ec000}, {0x408ee000}, + {0x408f0000}, {0x408f2000}, {0x408f4000}, {0x408f6000}, + {0x408f8000}, {0x408fa000}, {0x408fc000}, {0x408fe000}, + {0x40900000}, {0x40902000}, {0x40904000}, {0x40906000}, + {0x40908000}, {0x4090a000}, {0x4090c000}, {0x4090e000}, + {0x40910000}, {0x40912000}, {0x40914000}, {0x40916000}, + {0x40918000}, {0x4091a000}, {0x4091c000}, {0x4091e000}, + {0x40920000}, {0x40922000}, {0x40924000}, {0x40926000}, + {0x40928000}, {0x4092a000}, {0x4092c000}, {0x4092e000}, + {0x40930000}, {0x40932000}, {0x40934000}, {0x40936000}, + {0x40938000}, {0x4093a000}, {0x4093c000}, {0x4093e000}, + {0x40940000}, {0x40942000}, {0x40944000}, {0x40946000}, + {0x40948000}, {0x4094a000}, {0x4094c000}, {0x4094e000}, + {0x40950000}, {0x40952000}, {0x40954000}, {0x40956000}, + {0x40958000}, {0x4095a000}, {0x4095c000}, {0x4095e000}, + {0x40960000}, {0x40962000}, {0x40964000}, {0x40966000}, + {0x40968000}, {0x4096a000}, {0x4096c000}, {0x4096e000}, + {0x40970000}, {0x40972000}, {0x40974000}, {0x40976000}, + {0x40978000}, {0x4097a000}, {0x4097c000}, {0x4097e000}, + {0x40980000}, {0x40982000}, {0x40984000}, {0x40986000}, + {0x40988000}, {0x4098a000}, {0x4098c000}, {0x4098e000}, + {0x40990000}, {0x40992000}, {0x40994000}, {0x40996000}, + {0x40998000}, {0x4099a000}, {0x4099c000}, {0x4099e000}, + {0x409a0000}, {0x409a2000}, {0x409a4000}, {0x409a6000}, + {0x409a8000}, {0x409aa000}, {0x409ac000}, {0x409ae000}, + {0x409b0000}, {0x409b2000}, {0x409b4000}, {0x409b6000}, + {0x409b8000}, {0x409ba000}, {0x409bc000}, {0x409be000}, + {0x409c0000}, {0x409c2000}, {0x409c4000}, {0x409c6000}, + {0x409c8000}, {0x409ca000}, {0x409cc000}, {0x409ce000}, + {0x409d0000}, {0x409d2000}, {0x409d4000}, {0x409d6000}, + {0x409d8000}, {0x409da000}, {0x409dc000}, {0x409de000}, + {0x409e0000}, {0x409e2000}, {0x409e4000}, {0x409e6000}, + {0x409e8000}, {0x409ea000}, {0x409ec000}, {0x409ee000}, + {0x409f0000}, {0x409f2000}, {0x409f4000}, {0x409f6000}, + {0x409f8000}, {0x409fa000}, {0x409fc000}, {0x409fe000}, + {0x40a00000}, {0x40a02000}, {0x40a04000}, {0x40a06000}, + {0x40a08000}, {0x40a0a000}, {0x40a0c000}, {0x40a0e000}, + {0x40a10000}, {0x40a12000}, {0x40a14000}, {0x40a16000}, + {0x40a18000}, {0x40a1a000}, {0x40a1c000}, {0x40a1e000}, + {0x40a20000}, {0x40a22000}, {0x40a24000}, {0x40a26000}, + {0x40a28000}, {0x40a2a000}, {0x40a2c000}, {0x40a2e000}, + {0x40a30000}, {0x40a32000}, {0x40a34000}, {0x40a36000}, + {0x40a38000}, {0x40a3a000}, {0x40a3c000}, {0x40a3e000}, + {0x40a40000}, {0x40a42000}, {0x40a44000}, {0x40a46000}, + {0x40a48000}, {0x40a4a000}, {0x40a4c000}, {0x40a4e000}, + {0x40a50000}, {0x40a52000}, {0x40a54000}, {0x40a56000}, + {0x40a58000}, {0x40a5a000}, {0x40a5c000}, {0x40a5e000}, + {0x40a60000}, {0x40a62000}, {0x40a64000}, {0x40a66000}, + {0x40a68000}, {0x40a6a000}, {0x40a6c000}, {0x40a6e000}, + {0x40a70000}, {0x40a72000}, {0x40a74000}, {0x40a76000}, + {0x40a78000}, {0x40a7a000}, {0x40a7c000}, {0x40a7e000}, + {0x40a80000}, {0x40a82000}, {0x40a84000}, {0x40a86000}, + {0x40a88000}, {0x40a8a000}, {0x40a8c000}, {0x40a8e000}, + {0x40a90000}, {0x40a92000}, {0x40a94000}, {0x40a96000}, + {0x40a98000}, {0x40a9a000}, {0x40a9c000}, {0x40a9e000}, + {0x40aa0000}, {0x40aa2000}, {0x40aa4000}, {0x40aa6000}, + {0x40aa8000}, {0x40aaa000}, {0x40aac000}, {0x40aae000}, + {0x40ab0000}, {0x40ab2000}, {0x40ab4000}, {0x40ab6000}, + {0x40ab8000}, {0x40aba000}, {0x40abc000}, {0x40abe000}, + {0x40ac0000}, {0x40ac2000}, {0x40ac4000}, {0x40ac6000}, + {0x40ac8000}, {0x40aca000}, {0x40acc000}, {0x40ace000}, + {0x40ad0000}, {0x40ad2000}, {0x40ad4000}, {0x40ad6000}, + {0x40ad8000}, {0x40ada000}, {0x40adc000}, {0x40ade000}, + {0x40ae0000}, {0x40ae2000}, {0x40ae4000}, {0x40ae6000}, + {0x40ae8000}, {0x40aea000}, {0x40aec000}, {0x40aee000}, + {0x40af0000}, {0x40af2000}, {0x40af4000}, {0x40af6000}, + {0x40af8000}, {0x40afa000}, {0x40afc000}, {0x40afe000}, + {0x40b00000}, {0x40b02000}, {0x40b04000}, {0x40b06000}, + {0x40b08000}, {0x40b0a000}, {0x40b0c000}, {0x40b0e000}, + {0x40b10000}, {0x40b12000}, {0x40b14000}, {0x40b16000}, + {0x40b18000}, {0x40b1a000}, {0x40b1c000}, {0x40b1e000}, + {0x40b20000}, {0x40b22000}, {0x40b24000}, {0x40b26000}, + {0x40b28000}, {0x40b2a000}, {0x40b2c000}, {0x40b2e000}, + {0x40b30000}, {0x40b32000}, {0x40b34000}, {0x40b36000}, + {0x40b38000}, {0x40b3a000}, {0x40b3c000}, {0x40b3e000}, + {0x40b40000}, {0x40b42000}, {0x40b44000}, {0x40b46000}, + {0x40b48000}, {0x40b4a000}, {0x40b4c000}, {0x40b4e000}, + {0x40b50000}, {0x40b52000}, {0x40b54000}, {0x40b56000}, + {0x40b58000}, {0x40b5a000}, {0x40b5c000}, {0x40b5e000}, + {0x40b60000}, {0x40b62000}, {0x40b64000}, {0x40b66000}, + {0x40b68000}, {0x40b6a000}, {0x40b6c000}, {0x40b6e000}, + {0x40b70000}, {0x40b72000}, {0x40b74000}, {0x40b76000}, + {0x40b78000}, {0x40b7a000}, {0x40b7c000}, {0x40b7e000}, + {0x40b80000}, {0x40b82000}, {0x40b84000}, {0x40b86000}, + {0x40b88000}, {0x40b8a000}, {0x40b8c000}, {0x40b8e000}, + {0x40b90000}, {0x40b92000}, {0x40b94000}, {0x40b96000}, + {0x40b98000}, {0x40b9a000}, {0x40b9c000}, {0x40b9e000}, + {0x40ba0000}, {0x40ba2000}, {0x40ba4000}, {0x40ba6000}, + {0x40ba8000}, {0x40baa000}, {0x40bac000}, {0x40bae000}, + {0x40bb0000}, {0x40bb2000}, {0x40bb4000}, {0x40bb6000}, + {0x40bb8000}, {0x40bba000}, {0x40bbc000}, {0x40bbe000}, + {0x40bc0000}, {0x40bc2000}, {0x40bc4000}, {0x40bc6000}, + {0x40bc8000}, {0x40bca000}, {0x40bcc000}, {0x40bce000}, + {0x40bd0000}, {0x40bd2000}, {0x40bd4000}, {0x40bd6000}, + {0x40bd8000}, {0x40bda000}, {0x40bdc000}, {0x40bde000}, + {0x40be0000}, {0x40be2000}, {0x40be4000}, {0x40be6000}, + {0x40be8000}, {0x40bea000}, {0x40bec000}, {0x40bee000}, + {0x40bf0000}, {0x40bf2000}, {0x40bf4000}, {0x40bf6000}, + {0x40bf8000}, {0x40bfa000}, {0x40bfc000}, {0x40bfe000}, + {0x40c00000}, {0x40c02000}, {0x40c04000}, {0x40c06000}, + {0x40c08000}, {0x40c0a000}, {0x40c0c000}, {0x40c0e000}, + {0x40c10000}, {0x40c12000}, {0x40c14000}, {0x40c16000}, + {0x40c18000}, {0x40c1a000}, {0x40c1c000}, {0x40c1e000}, + {0x40c20000}, {0x40c22000}, {0x40c24000}, {0x40c26000}, + {0x40c28000}, {0x40c2a000}, {0x40c2c000}, {0x40c2e000}, + {0x40c30000}, {0x40c32000}, {0x40c34000}, {0x40c36000}, + {0x40c38000}, {0x40c3a000}, {0x40c3c000}, {0x40c3e000}, + {0x40c40000}, {0x40c42000}, {0x40c44000}, {0x40c46000}, + {0x40c48000}, {0x40c4a000}, {0x40c4c000}, {0x40c4e000}, + {0x40c50000}, {0x40c52000}, {0x40c54000}, {0x40c56000}, + {0x40c58000}, {0x40c5a000}, {0x40c5c000}, {0x40c5e000}, + {0x40c60000}, {0x40c62000}, {0x40c64000}, {0x40c66000}, + {0x40c68000}, {0x40c6a000}, {0x40c6c000}, {0x40c6e000}, + {0x40c70000}, {0x40c72000}, {0x40c74000}, {0x40c76000}, + {0x40c78000}, {0x40c7a000}, {0x40c7c000}, {0x40c7e000}, + {0x40c80000}, {0x40c82000}, {0x40c84000}, {0x40c86000}, + {0x40c88000}, {0x40c8a000}, {0x40c8c000}, {0x40c8e000}, + {0x40c90000}, {0x40c92000}, {0x40c94000}, {0x40c96000}, + {0x40c98000}, {0x40c9a000}, {0x40c9c000}, {0x40c9e000}, + {0x40ca0000}, {0x40ca2000}, {0x40ca4000}, {0x40ca6000}, + {0x40ca8000}, {0x40caa000}, {0x40cac000}, {0x40cae000}, + {0x40cb0000}, {0x40cb2000}, {0x40cb4000}, {0x40cb6000}, + {0x40cb8000}, {0x40cba000}, {0x40cbc000}, {0x40cbe000}, + {0x40cc0000}, {0x40cc2000}, {0x40cc4000}, {0x40cc6000}, + {0x40cc8000}, {0x40cca000}, {0x40ccc000}, {0x40cce000}, + {0x40cd0000}, {0x40cd2000}, {0x40cd4000}, {0x40cd6000}, + {0x40cd8000}, {0x40cda000}, {0x40cdc000}, {0x40cde000}, + {0x40ce0000}, {0x40ce2000}, {0x40ce4000}, {0x40ce6000}, + {0x40ce8000}, {0x40cea000}, {0x40cec000}, {0x40cee000}, + {0x40cf0000}, {0x40cf2000}, {0x40cf4000}, {0x40cf6000}, + {0x40cf8000}, {0x40cfa000}, {0x40cfc000}, {0x40cfe000}, + {0x40d00000}, {0x40d02000}, {0x40d04000}, {0x40d06000}, + {0x40d08000}, {0x40d0a000}, {0x40d0c000}, {0x40d0e000}, + {0x40d10000}, {0x40d12000}, {0x40d14000}, {0x40d16000}, + {0x40d18000}, {0x40d1a000}, {0x40d1c000}, {0x40d1e000}, + {0x40d20000}, {0x40d22000}, {0x40d24000}, {0x40d26000}, + {0x40d28000}, {0x40d2a000}, {0x40d2c000}, {0x40d2e000}, + {0x40d30000}, {0x40d32000}, {0x40d34000}, {0x40d36000}, + {0x40d38000}, {0x40d3a000}, {0x40d3c000}, {0x40d3e000}, + {0x40d40000}, {0x40d42000}, {0x40d44000}, {0x40d46000}, + {0x40d48000}, {0x40d4a000}, {0x40d4c000}, {0x40d4e000}, + {0x40d50000}, {0x40d52000}, {0x40d54000}, {0x40d56000}, + {0x40d58000}, {0x40d5a000}, {0x40d5c000}, {0x40d5e000}, + {0x40d60000}, {0x40d62000}, {0x40d64000}, {0x40d66000}, + {0x40d68000}, {0x40d6a000}, {0x40d6c000}, {0x40d6e000}, + {0x40d70000}, {0x40d72000}, {0x40d74000}, {0x40d76000}, + {0x40d78000}, {0x40d7a000}, {0x40d7c000}, {0x40d7e000}, + {0x40d80000}, {0x40d82000}, {0x40d84000}, {0x40d86000}, + {0x40d88000}, {0x40d8a000}, {0x40d8c000}, {0x40d8e000}, + {0x40d90000}, {0x40d92000}, {0x40d94000}, {0x40d96000}, + {0x40d98000}, {0x40d9a000}, {0x40d9c000}, {0x40d9e000}, + {0x40da0000}, {0x40da2000}, {0x40da4000}, {0x40da6000}, + {0x40da8000}, {0x40daa000}, {0x40dac000}, {0x40dae000}, + {0x40db0000}, {0x40db2000}, {0x40db4000}, {0x40db6000}, + {0x40db8000}, {0x40dba000}, {0x40dbc000}, {0x40dbe000}, + {0x40dc0000}, {0x40dc2000}, {0x40dc4000}, {0x40dc6000}, + {0x40dc8000}, {0x40dca000}, {0x40dcc000}, {0x40dce000}, + {0x40dd0000}, {0x40dd2000}, {0x40dd4000}, {0x40dd6000}, + {0x40dd8000}, {0x40dda000}, {0x40ddc000}, {0x40dde000}, + {0x40de0000}, {0x40de2000}, {0x40de4000}, {0x40de6000}, + {0x40de8000}, {0x40dea000}, {0x40dec000}, {0x40dee000}, + {0x40df0000}, {0x40df2000}, {0x40df4000}, {0x40df6000}, + {0x40df8000}, {0x40dfa000}, {0x40dfc000}, {0x40dfe000}, + {0x40e00000}, {0x40e02000}, {0x40e04000}, {0x40e06000}, + {0x40e08000}, {0x40e0a000}, {0x40e0c000}, {0x40e0e000}, + {0x40e10000}, {0x40e12000}, {0x40e14000}, {0x40e16000}, + {0x40e18000}, {0x40e1a000}, {0x40e1c000}, {0x40e1e000}, + {0x40e20000}, {0x40e22000}, {0x40e24000}, {0x40e26000}, + {0x40e28000}, {0x40e2a000}, {0x40e2c000}, {0x40e2e000}, + {0x40e30000}, {0x40e32000}, {0x40e34000}, {0x40e36000}, + {0x40e38000}, {0x40e3a000}, {0x40e3c000}, {0x40e3e000}, + {0x40e40000}, {0x40e42000}, {0x40e44000}, {0x40e46000}, + {0x40e48000}, {0x40e4a000}, {0x40e4c000}, {0x40e4e000}, + {0x40e50000}, {0x40e52000}, {0x40e54000}, {0x40e56000}, + {0x40e58000}, {0x40e5a000}, {0x40e5c000}, {0x40e5e000}, + {0x40e60000}, {0x40e62000}, {0x40e64000}, {0x40e66000}, + {0x40e68000}, {0x40e6a000}, {0x40e6c000}, {0x40e6e000}, + {0x40e70000}, {0x40e72000}, {0x40e74000}, {0x40e76000}, + {0x40e78000}, {0x40e7a000}, {0x40e7c000}, {0x40e7e000}, + {0x40e80000}, {0x40e82000}, {0x40e84000}, {0x40e86000}, + {0x40e88000}, {0x40e8a000}, {0x40e8c000}, {0x40e8e000}, + {0x40e90000}, {0x40e92000}, {0x40e94000}, {0x40e96000}, + {0x40e98000}, {0x40e9a000}, {0x40e9c000}, {0x40e9e000}, + {0x40ea0000}, {0x40ea2000}, {0x40ea4000}, {0x40ea6000}, + {0x40ea8000}, {0x40eaa000}, {0x40eac000}, {0x40eae000}, + {0x40eb0000}, {0x40eb2000}, {0x40eb4000}, {0x40eb6000}, + {0x40eb8000}, {0x40eba000}, {0x40ebc000}, {0x40ebe000}, + {0x40ec0000}, {0x40ec2000}, {0x40ec4000}, {0x40ec6000}, + {0x40ec8000}, {0x40eca000}, {0x40ecc000}, {0x40ece000}, + {0x40ed0000}, {0x40ed2000}, {0x40ed4000}, {0x40ed6000}, + {0x40ed8000}, {0x40eda000}, {0x40edc000}, {0x40ede000}, + {0x40ee0000}, {0x40ee2000}, {0x40ee4000}, {0x40ee6000}, + {0x40ee8000}, {0x40eea000}, {0x40eec000}, {0x40eee000}, + {0x40ef0000}, {0x40ef2000}, {0x40ef4000}, {0x40ef6000}, + {0x40ef8000}, {0x40efa000}, {0x40efc000}, {0x40efe000}, + {0x40f00000}, {0x40f02000}, {0x40f04000}, {0x40f06000}, + {0x40f08000}, {0x40f0a000}, {0x40f0c000}, {0x40f0e000}, + {0x40f10000}, {0x40f12000}, {0x40f14000}, {0x40f16000}, + {0x40f18000}, {0x40f1a000}, {0x40f1c000}, {0x40f1e000}, + {0x40f20000}, {0x40f22000}, {0x40f24000}, {0x40f26000}, + {0x40f28000}, {0x40f2a000}, {0x40f2c000}, {0x40f2e000}, + {0x40f30000}, {0x40f32000}, {0x40f34000}, {0x40f36000}, + {0x40f38000}, {0x40f3a000}, {0x40f3c000}, {0x40f3e000}, + {0x40f40000}, {0x40f42000}, {0x40f44000}, {0x40f46000}, + {0x40f48000}, {0x40f4a000}, {0x40f4c000}, {0x40f4e000}, + {0x40f50000}, {0x40f52000}, {0x40f54000}, {0x40f56000}, + {0x40f58000}, {0x40f5a000}, {0x40f5c000}, {0x40f5e000}, + {0x40f60000}, {0x40f62000}, {0x40f64000}, {0x40f66000}, + {0x40f68000}, {0x40f6a000}, {0x40f6c000}, {0x40f6e000}, + {0x40f70000}, {0x40f72000}, {0x40f74000}, {0x40f76000}, + {0x40f78000}, {0x40f7a000}, {0x40f7c000}, {0x40f7e000}, + {0x40f80000}, {0x40f82000}, {0x40f84000}, {0x40f86000}, + {0x40f88000}, {0x40f8a000}, {0x40f8c000}, {0x40f8e000}, + {0x40f90000}, {0x40f92000}, {0x40f94000}, {0x40f96000}, + {0x40f98000}, {0x40f9a000}, {0x40f9c000}, {0x40f9e000}, + {0x40fa0000}, {0x40fa2000}, {0x40fa4000}, {0x40fa6000}, + {0x40fa8000}, {0x40faa000}, {0x40fac000}, {0x40fae000}, + {0x40fb0000}, {0x40fb2000}, {0x40fb4000}, {0x40fb6000}, + {0x40fb8000}, {0x40fba000}, {0x40fbc000}, {0x40fbe000}, + {0x40fc0000}, {0x40fc2000}, {0x40fc4000}, {0x40fc6000}, + {0x40fc8000}, {0x40fca000}, {0x40fcc000}, {0x40fce000}, + {0x40fd0000}, {0x40fd2000}, {0x40fd4000}, {0x40fd6000}, + {0x40fd8000}, {0x40fda000}, {0x40fdc000}, {0x40fde000}, + {0x40fe0000}, {0x40fe2000}, {0x40fe4000}, {0x40fe6000}, + {0x40fe8000}, {0x40fea000}, {0x40fec000}, {0x40fee000}, + {0x40ff0000}, {0x40ff2000}, {0x40ff4000}, {0x40ff6000}, + {0x40ff8000}, {0x40ffa000}, {0x40ffc000}, {0x40ffe000}, + {0x41000000}, {0x41002000}, {0x41004000}, {0x41006000}, + {0x41008000}, {0x4100a000}, {0x4100c000}, {0x4100e000}, + {0x41010000}, {0x41012000}, {0x41014000}, {0x41016000}, + {0x41018000}, {0x4101a000}, {0x4101c000}, {0x4101e000}, + {0x41020000}, {0x41022000}, {0x41024000}, {0x41026000}, + {0x41028000}, {0x4102a000}, {0x4102c000}, {0x4102e000}, + {0x41030000}, {0x41032000}, {0x41034000}, {0x41036000}, + {0x41038000}, {0x4103a000}, {0x4103c000}, {0x4103e000}, + {0x41040000}, {0x41042000}, {0x41044000}, {0x41046000}, + {0x41048000}, {0x4104a000}, {0x4104c000}, {0x4104e000}, + {0x41050000}, {0x41052000}, {0x41054000}, {0x41056000}, + {0x41058000}, {0x4105a000}, {0x4105c000}, {0x4105e000}, + {0x41060000}, {0x41062000}, {0x41064000}, {0x41066000}, + {0x41068000}, {0x4106a000}, {0x4106c000}, {0x4106e000}, + {0x41070000}, {0x41072000}, {0x41074000}, {0x41076000}, + {0x41078000}, {0x4107a000}, {0x4107c000}, {0x4107e000}, + {0x41080000}, {0x41082000}, {0x41084000}, {0x41086000}, + {0x41088000}, {0x4108a000}, {0x4108c000}, {0x4108e000}, + {0x41090000}, {0x41092000}, {0x41094000}, {0x41096000}, + {0x41098000}, {0x4109a000}, {0x4109c000}, {0x4109e000}, + {0x410a0000}, {0x410a2000}, {0x410a4000}, {0x410a6000}, + {0x410a8000}, {0x410aa000}, {0x410ac000}, {0x410ae000}, + {0x410b0000}, {0x410b2000}, {0x410b4000}, {0x410b6000}, + {0x410b8000}, {0x410ba000}, {0x410bc000}, {0x410be000}, + {0x410c0000}, {0x410c2000}, {0x410c4000}, {0x410c6000}, + {0x410c8000}, {0x410ca000}, {0x410cc000}, {0x410ce000}, + {0x410d0000}, {0x410d2000}, {0x410d4000}, {0x410d6000}, + {0x410d8000}, {0x410da000}, {0x410dc000}, {0x410de000}, + {0x410e0000}, {0x410e2000}, {0x410e4000}, {0x410e6000}, + {0x410e8000}, {0x410ea000}, {0x410ec000}, {0x410ee000}, + {0x410f0000}, {0x410f2000}, {0x410f4000}, {0x410f6000}, + {0x410f8000}, {0x410fa000}, {0x410fc000}, {0x410fe000}, + {0x41100000}, {0x41102000}, {0x41104000}, {0x41106000}, + {0x41108000}, {0x4110a000}, {0x4110c000}, {0x4110e000}, + {0x41110000}, {0x41112000}, {0x41114000}, {0x41116000}, + {0x41118000}, {0x4111a000}, {0x4111c000}, {0x4111e000}, + {0x41120000}, {0x41122000}, {0x41124000}, {0x41126000}, + {0x41128000}, {0x4112a000}, {0x4112c000}, {0x4112e000}, + {0x41130000}, {0x41132000}, {0x41134000}, {0x41136000}, + {0x41138000}, {0x4113a000}, {0x4113c000}, {0x4113e000}, + {0x41140000}, {0x41142000}, {0x41144000}, {0x41146000}, + {0x41148000}, {0x4114a000}, {0x4114c000}, {0x4114e000}, + {0x41150000}, {0x41152000}, {0x41154000}, {0x41156000}, + {0x41158000}, {0x4115a000}, {0x4115c000}, {0x4115e000}, + {0x41160000}, {0x41162000}, {0x41164000}, {0x41166000}, + {0x41168000}, {0x4116a000}, {0x4116c000}, {0x4116e000}, + {0x41170000}, {0x41172000}, {0x41174000}, {0x41176000}, + {0x41178000}, {0x4117a000}, {0x4117c000}, {0x4117e000}, + {0x41180000}, {0x41182000}, {0x41184000}, {0x41186000}, + {0x41188000}, {0x4118a000}, {0x4118c000}, {0x4118e000}, + {0x41190000}, {0x41192000}, {0x41194000}, {0x41196000}, + {0x41198000}, {0x4119a000}, {0x4119c000}, {0x4119e000}, + {0x411a0000}, {0x411a2000}, {0x411a4000}, {0x411a6000}, + {0x411a8000}, {0x411aa000}, {0x411ac000}, {0x411ae000}, + {0x411b0000}, {0x411b2000}, {0x411b4000}, {0x411b6000}, + {0x411b8000}, {0x411ba000}, {0x411bc000}, {0x411be000}, + {0x411c0000}, {0x411c2000}, {0x411c4000}, {0x411c6000}, + {0x411c8000}, {0x411ca000}, {0x411cc000}, {0x411ce000}, + {0x411d0000}, {0x411d2000}, {0x411d4000}, {0x411d6000}, + {0x411d8000}, {0x411da000}, {0x411dc000}, {0x411de000}, + {0x411e0000}, {0x411e2000}, {0x411e4000}, {0x411e6000}, + {0x411e8000}, {0x411ea000}, {0x411ec000}, {0x411ee000}, + {0x411f0000}, {0x411f2000}, {0x411f4000}, {0x411f6000}, + {0x411f8000}, {0x411fa000}, {0x411fc000}, {0x411fe000}, + {0x41200000}, {0x41202000}, {0x41204000}, {0x41206000}, + {0x41208000}, {0x4120a000}, {0x4120c000}, {0x4120e000}, + {0x41210000}, {0x41212000}, {0x41214000}, {0x41216000}, + {0x41218000}, {0x4121a000}, {0x4121c000}, {0x4121e000}, + {0x41220000}, {0x41222000}, {0x41224000}, {0x41226000}, + {0x41228000}, {0x4122a000}, {0x4122c000}, {0x4122e000}, + {0x41230000}, {0x41232000}, {0x41234000}, {0x41236000}, + {0x41238000}, {0x4123a000}, {0x4123c000}, {0x4123e000}, + {0x41240000}, {0x41242000}, {0x41244000}, {0x41246000}, + {0x41248000}, {0x4124a000}, {0x4124c000}, {0x4124e000}, + {0x41250000}, {0x41252000}, {0x41254000}, {0x41256000}, + {0x41258000}, {0x4125a000}, {0x4125c000}, {0x4125e000}, + {0x41260000}, {0x41262000}, {0x41264000}, {0x41266000}, + {0x41268000}, {0x4126a000}, {0x4126c000}, {0x4126e000}, + {0x41270000}, {0x41272000}, {0x41274000}, {0x41276000}, + {0x41278000}, {0x4127a000}, {0x4127c000}, {0x4127e000}, + {0x41280000}, {0x41282000}, {0x41284000}, {0x41286000}, + {0x41288000}, {0x4128a000}, {0x4128c000}, {0x4128e000}, + {0x41290000}, {0x41292000}, {0x41294000}, {0x41296000}, + {0x41298000}, {0x4129a000}, {0x4129c000}, {0x4129e000}, + {0x412a0000}, {0x412a2000}, {0x412a4000}, {0x412a6000}, + {0x412a8000}, {0x412aa000}, {0x412ac000}, {0x412ae000}, + {0x412b0000}, {0x412b2000}, {0x412b4000}, {0x412b6000}, + {0x412b8000}, {0x412ba000}, {0x412bc000}, {0x412be000}, + {0x412c0000}, {0x412c2000}, {0x412c4000}, {0x412c6000}, + {0x412c8000}, {0x412ca000}, {0x412cc000}, {0x412ce000}, + {0x412d0000}, {0x412d2000}, {0x412d4000}, {0x412d6000}, + {0x412d8000}, {0x412da000}, {0x412dc000}, {0x412de000}, + {0x412e0000}, {0x412e2000}, {0x412e4000}, {0x412e6000}, + {0x412e8000}, {0x412ea000}, {0x412ec000}, {0x412ee000}, + {0x412f0000}, {0x412f2000}, {0x412f4000}, {0x412f6000}, + {0x412f8000}, {0x412fa000}, {0x412fc000}, {0x412fe000}, + {0x41300000}, {0x41302000}, {0x41304000}, {0x41306000}, + {0x41308000}, {0x4130a000}, {0x4130c000}, {0x4130e000}, + {0x41310000}, {0x41312000}, {0x41314000}, {0x41316000}, + {0x41318000}, {0x4131a000}, {0x4131c000}, {0x4131e000}, + {0x41320000}, {0x41322000}, {0x41324000}, {0x41326000}, + {0x41328000}, {0x4132a000}, {0x4132c000}, {0x4132e000}, + {0x41330000}, {0x41332000}, {0x41334000}, {0x41336000}, + {0x41338000}, {0x4133a000}, {0x4133c000}, {0x4133e000}, + {0x41340000}, {0x41342000}, {0x41344000}, {0x41346000}, + {0x41348000}, {0x4134a000}, {0x4134c000}, {0x4134e000}, + {0x41350000}, {0x41352000}, {0x41354000}, {0x41356000}, + {0x41358000}, {0x4135a000}, {0x4135c000}, {0x4135e000}, + {0x41360000}, {0x41362000}, {0x41364000}, {0x41366000}, + {0x41368000}, {0x4136a000}, {0x4136c000}, {0x4136e000}, + {0x41370000}, {0x41372000}, {0x41374000}, {0x41376000}, + {0x41378000}, {0x4137a000}, {0x4137c000}, {0x4137e000}, + {0x41380000}, {0x41382000}, {0x41384000}, {0x41386000}, + {0x41388000}, {0x4138a000}, {0x4138c000}, {0x4138e000}, + {0x41390000}, {0x41392000}, {0x41394000}, {0x41396000}, + {0x41398000}, {0x4139a000}, {0x4139c000}, {0x4139e000}, + {0x413a0000}, {0x413a2000}, {0x413a4000}, {0x413a6000}, + {0x413a8000}, {0x413aa000}, {0x413ac000}, {0x413ae000}, + {0x413b0000}, {0x413b2000}, {0x413b4000}, {0x413b6000}, + {0x413b8000}, {0x413ba000}, {0x413bc000}, {0x413be000}, + {0x413c0000}, {0x413c2000}, {0x413c4000}, {0x413c6000}, + {0x413c8000}, {0x413ca000}, {0x413cc000}, {0x413ce000}, + {0x413d0000}, {0x413d2000}, {0x413d4000}, {0x413d6000}, + {0x413d8000}, {0x413da000}, {0x413dc000}, {0x413de000}, + {0x413e0000}, {0x413e2000}, {0x413e4000}, {0x413e6000}, + {0x413e8000}, {0x413ea000}, {0x413ec000}, {0x413ee000}, + {0x413f0000}, {0x413f2000}, {0x413f4000}, {0x413f6000}, + {0x413f8000}, {0x413fa000}, {0x413fc000}, {0x413fe000}, + {0x41400000}, {0x41402000}, {0x41404000}, {0x41406000}, + {0x41408000}, {0x4140a000}, {0x4140c000}, {0x4140e000}, + {0x41410000}, {0x41412000}, {0x41414000}, {0x41416000}, + {0x41418000}, {0x4141a000}, {0x4141c000}, {0x4141e000}, + {0x41420000}, {0x41422000}, {0x41424000}, {0x41426000}, + {0x41428000}, {0x4142a000}, {0x4142c000}, {0x4142e000}, + {0x41430000}, {0x41432000}, {0x41434000}, {0x41436000}, + {0x41438000}, {0x4143a000}, {0x4143c000}, {0x4143e000}, + {0x41440000}, {0x41442000}, {0x41444000}, {0x41446000}, + {0x41448000}, {0x4144a000}, {0x4144c000}, {0x4144e000}, + {0x41450000}, {0x41452000}, {0x41454000}, {0x41456000}, + {0x41458000}, {0x4145a000}, {0x4145c000}, {0x4145e000}, + {0x41460000}, {0x41462000}, {0x41464000}, {0x41466000}, + {0x41468000}, {0x4146a000}, {0x4146c000}, {0x4146e000}, + {0x41470000}, {0x41472000}, {0x41474000}, {0x41476000}, + {0x41478000}, {0x4147a000}, {0x4147c000}, {0x4147e000}, + {0x41480000}, {0x41482000}, {0x41484000}, {0x41486000}, + {0x41488000}, {0x4148a000}, {0x4148c000}, {0x4148e000}, + {0x41490000}, {0x41492000}, {0x41494000}, {0x41496000}, + {0x41498000}, {0x4149a000}, {0x4149c000}, {0x4149e000}, + {0x414a0000}, {0x414a2000}, {0x414a4000}, {0x414a6000}, + {0x414a8000}, {0x414aa000}, {0x414ac000}, {0x414ae000}, + {0x414b0000}, {0x414b2000}, {0x414b4000}, {0x414b6000}, + {0x414b8000}, {0x414ba000}, {0x414bc000}, {0x414be000}, + {0x414c0000}, {0x414c2000}, {0x414c4000}, {0x414c6000}, + {0x414c8000}, {0x414ca000}, {0x414cc000}, {0x414ce000}, + {0x414d0000}, {0x414d2000}, {0x414d4000}, {0x414d6000}, + {0x414d8000}, {0x414da000}, {0x414dc000}, {0x414de000}, + {0x414e0000}, {0x414e2000}, {0x414e4000}, {0x414e6000}, + {0x414e8000}, {0x414ea000}, {0x414ec000}, {0x414ee000}, + {0x414f0000}, {0x414f2000}, {0x414f4000}, {0x414f6000}, + {0x414f8000}, {0x414fa000}, {0x414fc000}, {0x414fe000}, + {0x41500000}, {0x41502000}, {0x41504000}, {0x41506000}, + {0x41508000}, {0x4150a000}, {0x4150c000}, {0x4150e000}, + {0x41510000}, {0x41512000}, {0x41514000}, {0x41516000}, + {0x41518000}, {0x4151a000}, {0x4151c000}, {0x4151e000}, + {0x41520000}, {0x41522000}, {0x41524000}, {0x41526000}, + {0x41528000}, {0x4152a000}, {0x4152c000}, {0x4152e000}, + {0x41530000}, {0x41532000}, {0x41534000}, {0x41536000}, + {0x41538000}, {0x4153a000}, {0x4153c000}, {0x4153e000}, + {0x41540000}, {0x41542000}, {0x41544000}, {0x41546000}, + {0x41548000}, {0x4154a000}, {0x4154c000}, {0x4154e000}, + {0x41550000}, {0x41552000}, {0x41554000}, {0x41556000}, + {0x41558000}, {0x4155a000}, {0x4155c000}, {0x4155e000}, + {0x41560000}, {0x41562000}, {0x41564000}, {0x41566000}, + {0x41568000}, {0x4156a000}, {0x4156c000}, {0x4156e000}, + {0x41570000}, {0x41572000}, {0x41574000}, {0x41576000}, + {0x41578000}, {0x4157a000}, {0x4157c000}, {0x4157e000}, + {0x41580000}, {0x41582000}, {0x41584000}, {0x41586000}, + {0x41588000}, {0x4158a000}, {0x4158c000}, {0x4158e000}, + {0x41590000}, {0x41592000}, {0x41594000}, {0x41596000}, + {0x41598000}, {0x4159a000}, {0x4159c000}, {0x4159e000}, + {0x415a0000}, {0x415a2000}, {0x415a4000}, {0x415a6000}, + {0x415a8000}, {0x415aa000}, {0x415ac000}, {0x415ae000}, + {0x415b0000}, {0x415b2000}, {0x415b4000}, {0x415b6000}, + {0x415b8000}, {0x415ba000}, {0x415bc000}, {0x415be000}, + {0x415c0000}, {0x415c2000}, {0x415c4000}, {0x415c6000}, + {0x415c8000}, {0x415ca000}, {0x415cc000}, {0x415ce000}, + {0x415d0000}, {0x415d2000}, {0x415d4000}, {0x415d6000}, + {0x415d8000}, {0x415da000}, {0x415dc000}, {0x415de000}, + {0x415e0000}, {0x415e2000}, {0x415e4000}, {0x415e6000}, + {0x415e8000}, {0x415ea000}, {0x415ec000}, {0x415ee000}, + {0x415f0000}, {0x415f2000}, {0x415f4000}, {0x415f6000}, + {0x415f8000}, {0x415fa000}, {0x415fc000}, {0x415fe000}, + {0x41600000}, {0x41602000}, {0x41604000}, {0x41606000}, + {0x41608000}, {0x4160a000}, {0x4160c000}, {0x4160e000}, + {0x41610000}, {0x41612000}, {0x41614000}, {0x41616000}, + {0x41618000}, {0x4161a000}, {0x4161c000}, {0x4161e000}, + {0x41620000}, {0x41622000}, {0x41624000}, {0x41626000}, + {0x41628000}, {0x4162a000}, {0x4162c000}, {0x4162e000}, + {0x41630000}, {0x41632000}, {0x41634000}, {0x41636000}, + {0x41638000}, {0x4163a000}, {0x4163c000}, {0x4163e000}, + {0x41640000}, {0x41642000}, {0x41644000}, {0x41646000}, + {0x41648000}, {0x4164a000}, {0x4164c000}, {0x4164e000}, + {0x41650000}, {0x41652000}, {0x41654000}, {0x41656000}, + {0x41658000}, {0x4165a000}, {0x4165c000}, {0x4165e000}, + {0x41660000}, {0x41662000}, {0x41664000}, {0x41666000}, + {0x41668000}, {0x4166a000}, {0x4166c000}, {0x4166e000}, + {0x41670000}, {0x41672000}, {0x41674000}, {0x41676000}, + {0x41678000}, {0x4167a000}, {0x4167c000}, {0x4167e000}, + {0x41680000}, {0x41682000}, {0x41684000}, {0x41686000}, + {0x41688000}, {0x4168a000}, {0x4168c000}, {0x4168e000}, + {0x41690000}, {0x41692000}, {0x41694000}, {0x41696000}, + {0x41698000}, {0x4169a000}, {0x4169c000}, {0x4169e000}, + {0x416a0000}, {0x416a2000}, {0x416a4000}, {0x416a6000}, + {0x416a8000}, {0x416aa000}, {0x416ac000}, {0x416ae000}, + {0x416b0000}, {0x416b2000}, {0x416b4000}, {0x416b6000}, + {0x416b8000}, {0x416ba000}, {0x416bc000}, {0x416be000}, + {0x416c0000}, {0x416c2000}, {0x416c4000}, {0x416c6000}, + {0x416c8000}, {0x416ca000}, {0x416cc000}, {0x416ce000}, + {0x416d0000}, {0x416d2000}, {0x416d4000}, {0x416d6000}, + {0x416d8000}, {0x416da000}, {0x416dc000}, {0x416de000}, + {0x416e0000}, {0x416e2000}, {0x416e4000}, {0x416e6000}, + {0x416e8000}, {0x416ea000}, {0x416ec000}, {0x416ee000}, + {0x416f0000}, {0x416f2000}, {0x416f4000}, {0x416f6000}, + {0x416f8000}, {0x416fa000}, {0x416fc000}, {0x416fe000}, + {0x41700000}, {0x41702000}, {0x41704000}, {0x41706000}, + {0x41708000}, {0x4170a000}, {0x4170c000}, {0x4170e000}, + {0x41710000}, {0x41712000}, {0x41714000}, {0x41716000}, + {0x41718000}, {0x4171a000}, {0x4171c000}, {0x4171e000}, + {0x41720000}, {0x41722000}, {0x41724000}, {0x41726000}, + {0x41728000}, {0x4172a000}, {0x4172c000}, {0x4172e000}, + {0x41730000}, {0x41732000}, {0x41734000}, {0x41736000}, + {0x41738000}, {0x4173a000}, {0x4173c000}, {0x4173e000}, + {0x41740000}, {0x41742000}, {0x41744000}, {0x41746000}, + {0x41748000}, {0x4174a000}, {0x4174c000}, {0x4174e000}, + {0x41750000}, {0x41752000}, {0x41754000}, {0x41756000}, + {0x41758000}, {0x4175a000}, {0x4175c000}, {0x4175e000}, + {0x41760000}, {0x41762000}, {0x41764000}, {0x41766000}, + {0x41768000}, {0x4176a000}, {0x4176c000}, {0x4176e000}, + {0x41770000}, {0x41772000}, {0x41774000}, {0x41776000}, + {0x41778000}, {0x4177a000}, {0x4177c000}, {0x4177e000}, + {0x41780000}, {0x41782000}, {0x41784000}, {0x41786000}, + {0x41788000}, {0x4178a000}, {0x4178c000}, {0x4178e000}, + {0x41790000}, {0x41792000}, {0x41794000}, {0x41796000}, + {0x41798000}, {0x4179a000}, {0x4179c000}, {0x4179e000}, + {0x417a0000}, {0x417a2000}, {0x417a4000}, {0x417a6000}, + {0x417a8000}, {0x417aa000}, {0x417ac000}, {0x417ae000}, + {0x417b0000}, {0x417b2000}, {0x417b4000}, {0x417b6000}, + {0x417b8000}, {0x417ba000}, {0x417bc000}, {0x417be000}, + {0x417c0000}, {0x417c2000}, {0x417c4000}, {0x417c6000}, + {0x417c8000}, {0x417ca000}, {0x417cc000}, {0x417ce000}, + {0x417d0000}, {0x417d2000}, {0x417d4000}, {0x417d6000}, + {0x417d8000}, {0x417da000}, {0x417dc000}, {0x417de000}, + {0x417e0000}, {0x417e2000}, {0x417e4000}, {0x417e6000}, + {0x417e8000}, {0x417ea000}, {0x417ec000}, {0x417ee000}, + {0x417f0000}, {0x417f2000}, {0x417f4000}, {0x417f6000}, + {0x417f8000}, {0x417fa000}, {0x417fc000}, {0x417fe000}, + {0x41800000}, {0x41802000}, {0x41804000}, {0x41806000}, + {0x41808000}, {0x4180a000}, {0x4180c000}, {0x4180e000}, + {0x41810000}, {0x41812000}, {0x41814000}, {0x41816000}, + {0x41818000}, {0x4181a000}, {0x4181c000}, {0x4181e000}, + {0x41820000}, {0x41822000}, {0x41824000}, {0x41826000}, + {0x41828000}, {0x4182a000}, {0x4182c000}, {0x4182e000}, + {0x41830000}, {0x41832000}, {0x41834000}, {0x41836000}, + {0x41838000}, {0x4183a000}, {0x4183c000}, {0x4183e000}, + {0x41840000}, {0x41842000}, {0x41844000}, {0x41846000}, + {0x41848000}, {0x4184a000}, {0x4184c000}, {0x4184e000}, + {0x41850000}, {0x41852000}, {0x41854000}, {0x41856000}, + {0x41858000}, {0x4185a000}, {0x4185c000}, {0x4185e000}, + {0x41860000}, {0x41862000}, {0x41864000}, {0x41866000}, + {0x41868000}, {0x4186a000}, {0x4186c000}, {0x4186e000}, + {0x41870000}, {0x41872000}, {0x41874000}, {0x41876000}, + {0x41878000}, {0x4187a000}, {0x4187c000}, {0x4187e000}, + {0x41880000}, {0x41882000}, {0x41884000}, {0x41886000}, + {0x41888000}, {0x4188a000}, {0x4188c000}, {0x4188e000}, + {0x41890000}, {0x41892000}, {0x41894000}, {0x41896000}, + {0x41898000}, {0x4189a000}, {0x4189c000}, {0x4189e000}, + {0x418a0000}, {0x418a2000}, {0x418a4000}, {0x418a6000}, + {0x418a8000}, {0x418aa000}, {0x418ac000}, {0x418ae000}, + {0x418b0000}, {0x418b2000}, {0x418b4000}, {0x418b6000}, + {0x418b8000}, {0x418ba000}, {0x418bc000}, {0x418be000}, + {0x418c0000}, {0x418c2000}, {0x418c4000}, {0x418c6000}, + {0x418c8000}, {0x418ca000}, {0x418cc000}, {0x418ce000}, + {0x418d0000}, {0x418d2000}, {0x418d4000}, {0x418d6000}, + {0x418d8000}, {0x418da000}, {0x418dc000}, {0x418de000}, + {0x418e0000}, {0x418e2000}, {0x418e4000}, {0x418e6000}, + {0x418e8000}, {0x418ea000}, {0x418ec000}, {0x418ee000}, + {0x418f0000}, {0x418f2000}, {0x418f4000}, {0x418f6000}, + {0x418f8000}, {0x418fa000}, {0x418fc000}, {0x418fe000}, + {0x41900000}, {0x41902000}, {0x41904000}, {0x41906000}, + {0x41908000}, {0x4190a000}, {0x4190c000}, {0x4190e000}, + {0x41910000}, {0x41912000}, {0x41914000}, {0x41916000}, + {0x41918000}, {0x4191a000}, {0x4191c000}, {0x4191e000}, + {0x41920000}, {0x41922000}, {0x41924000}, {0x41926000}, + {0x41928000}, {0x4192a000}, {0x4192c000}, {0x4192e000}, + {0x41930000}, {0x41932000}, {0x41934000}, {0x41936000}, + {0x41938000}, {0x4193a000}, {0x4193c000}, {0x4193e000}, + {0x41940000}, {0x41942000}, {0x41944000}, {0x41946000}, + {0x41948000}, {0x4194a000}, {0x4194c000}, {0x4194e000}, + {0x41950000}, {0x41952000}, {0x41954000}, {0x41956000}, + {0x41958000}, {0x4195a000}, {0x4195c000}, {0x4195e000}, + {0x41960000}, {0x41962000}, {0x41964000}, {0x41966000}, + {0x41968000}, {0x4196a000}, {0x4196c000}, {0x4196e000}, + {0x41970000}, {0x41972000}, {0x41974000}, {0x41976000}, + {0x41978000}, {0x4197a000}, {0x4197c000}, {0x4197e000}, + {0x41980000}, {0x41982000}, {0x41984000}, {0x41986000}, + {0x41988000}, {0x4198a000}, {0x4198c000}, {0x4198e000}, + {0x41990000}, {0x41992000}, {0x41994000}, {0x41996000}, + {0x41998000}, {0x4199a000}, {0x4199c000}, {0x4199e000}, + {0x419a0000}, {0x419a2000}, {0x419a4000}, {0x419a6000}, + {0x419a8000}, {0x419aa000}, {0x419ac000}, {0x419ae000}, + {0x419b0000}, {0x419b2000}, {0x419b4000}, {0x419b6000}, + {0x419b8000}, {0x419ba000}, {0x419bc000}, {0x419be000}, + {0x419c0000}, {0x419c2000}, {0x419c4000}, {0x419c6000}, + {0x419c8000}, {0x419ca000}, {0x419cc000}, {0x419ce000}, + {0x419d0000}, {0x419d2000}, {0x419d4000}, {0x419d6000}, + {0x419d8000}, {0x419da000}, {0x419dc000}, {0x419de000}, + {0x419e0000}, {0x419e2000}, {0x419e4000}, {0x419e6000}, + {0x419e8000}, {0x419ea000}, {0x419ec000}, {0x419ee000}, + {0x419f0000}, {0x419f2000}, {0x419f4000}, {0x419f6000}, + {0x419f8000}, {0x419fa000}, {0x419fc000}, {0x419fe000}, + {0x41a00000}, {0x41a02000}, {0x41a04000}, {0x41a06000}, + {0x41a08000}, {0x41a0a000}, {0x41a0c000}, {0x41a0e000}, + {0x41a10000}, {0x41a12000}, {0x41a14000}, {0x41a16000}, + {0x41a18000}, {0x41a1a000}, {0x41a1c000}, {0x41a1e000}, + {0x41a20000}, {0x41a22000}, {0x41a24000}, {0x41a26000}, + {0x41a28000}, {0x41a2a000}, {0x41a2c000}, {0x41a2e000}, + {0x41a30000}, {0x41a32000}, {0x41a34000}, {0x41a36000}, + {0x41a38000}, {0x41a3a000}, {0x41a3c000}, {0x41a3e000}, + {0x41a40000}, {0x41a42000}, {0x41a44000}, {0x41a46000}, + {0x41a48000}, {0x41a4a000}, {0x41a4c000}, {0x41a4e000}, + {0x41a50000}, {0x41a52000}, {0x41a54000}, {0x41a56000}, + {0x41a58000}, {0x41a5a000}, {0x41a5c000}, {0x41a5e000}, + {0x41a60000}, {0x41a62000}, {0x41a64000}, {0x41a66000}, + {0x41a68000}, {0x41a6a000}, {0x41a6c000}, {0x41a6e000}, + {0x41a70000}, {0x41a72000}, {0x41a74000}, {0x41a76000}, + {0x41a78000}, {0x41a7a000}, {0x41a7c000}, {0x41a7e000}, + {0x41a80000}, {0x41a82000}, {0x41a84000}, {0x41a86000}, + {0x41a88000}, {0x41a8a000}, {0x41a8c000}, {0x41a8e000}, + {0x41a90000}, {0x41a92000}, {0x41a94000}, {0x41a96000}, + {0x41a98000}, {0x41a9a000}, {0x41a9c000}, {0x41a9e000}, + {0x41aa0000}, {0x41aa2000}, {0x41aa4000}, {0x41aa6000}, + {0x41aa8000}, {0x41aaa000}, {0x41aac000}, {0x41aae000}, + {0x41ab0000}, {0x41ab2000}, {0x41ab4000}, {0x41ab6000}, + {0x41ab8000}, {0x41aba000}, {0x41abc000}, {0x41abe000}, + {0x41ac0000}, {0x41ac2000}, {0x41ac4000}, {0x41ac6000}, + {0x41ac8000}, {0x41aca000}, {0x41acc000}, {0x41ace000}, + {0x41ad0000}, {0x41ad2000}, {0x41ad4000}, {0x41ad6000}, + {0x41ad8000}, {0x41ada000}, {0x41adc000}, {0x41ade000}, + {0x41ae0000}, {0x41ae2000}, {0x41ae4000}, {0x41ae6000}, + {0x41ae8000}, {0x41aea000}, {0x41aec000}, {0x41aee000}, + {0x41af0000}, {0x41af2000}, {0x41af4000}, {0x41af6000}, + {0x41af8000}, {0x41afa000}, {0x41afc000}, {0x41afe000}, + {0x41b00000}, {0x41b02000}, {0x41b04000}, {0x41b06000}, + {0x41b08000}, {0x41b0a000}, {0x41b0c000}, {0x41b0e000}, + {0x41b10000}, {0x41b12000}, {0x41b14000}, {0x41b16000}, + {0x41b18000}, {0x41b1a000}, {0x41b1c000}, {0x41b1e000}, + {0x41b20000}, {0x41b22000}, {0x41b24000}, {0x41b26000}, + {0x41b28000}, {0x41b2a000}, {0x41b2c000}, {0x41b2e000}, + {0x41b30000}, {0x41b32000}, {0x41b34000}, {0x41b36000}, + {0x41b38000}, {0x41b3a000}, {0x41b3c000}, {0x41b3e000}, + {0x41b40000}, {0x41b42000}, {0x41b44000}, {0x41b46000}, + {0x41b48000}, {0x41b4a000}, {0x41b4c000}, {0x41b4e000}, + {0x41b50000}, {0x41b52000}, {0x41b54000}, {0x41b56000}, + {0x41b58000}, {0x41b5a000}, {0x41b5c000}, {0x41b5e000}, + {0x41b60000}, {0x41b62000}, {0x41b64000}, {0x41b66000}, + {0x41b68000}, {0x41b6a000}, {0x41b6c000}, {0x41b6e000}, + {0x41b70000}, {0x41b72000}, {0x41b74000}, {0x41b76000}, + {0x41b78000}, {0x41b7a000}, {0x41b7c000}, {0x41b7e000}, + {0x41b80000}, {0x41b82000}, {0x41b84000}, {0x41b86000}, + {0x41b88000}, {0x41b8a000}, {0x41b8c000}, {0x41b8e000}, + {0x41b90000}, {0x41b92000}, {0x41b94000}, {0x41b96000}, + {0x41b98000}, {0x41b9a000}, {0x41b9c000}, {0x41b9e000}, + {0x41ba0000}, {0x41ba2000}, {0x41ba4000}, {0x41ba6000}, + {0x41ba8000}, {0x41baa000}, {0x41bac000}, {0x41bae000}, + {0x41bb0000}, {0x41bb2000}, {0x41bb4000}, {0x41bb6000}, + {0x41bb8000}, {0x41bba000}, {0x41bbc000}, {0x41bbe000}, + {0x41bc0000}, {0x41bc2000}, {0x41bc4000}, {0x41bc6000}, + {0x41bc8000}, {0x41bca000}, {0x41bcc000}, {0x41bce000}, + {0x41bd0000}, {0x41bd2000}, {0x41bd4000}, {0x41bd6000}, + {0x41bd8000}, {0x41bda000}, {0x41bdc000}, {0x41bde000}, + {0x41be0000}, {0x41be2000}, {0x41be4000}, {0x41be6000}, + {0x41be8000}, {0x41bea000}, {0x41bec000}, {0x41bee000}, + {0x41bf0000}, {0x41bf2000}, {0x41bf4000}, {0x41bf6000}, + {0x41bf8000}, {0x41bfa000}, {0x41bfc000}, {0x41bfe000}, + {0x41c00000}, {0x41c02000}, {0x41c04000}, {0x41c06000}, + {0x41c08000}, {0x41c0a000}, {0x41c0c000}, {0x41c0e000}, + {0x41c10000}, {0x41c12000}, {0x41c14000}, {0x41c16000}, + {0x41c18000}, {0x41c1a000}, {0x41c1c000}, {0x41c1e000}, + {0x41c20000}, {0x41c22000}, {0x41c24000}, {0x41c26000}, + {0x41c28000}, {0x41c2a000}, {0x41c2c000}, {0x41c2e000}, + {0x41c30000}, {0x41c32000}, {0x41c34000}, {0x41c36000}, + {0x41c38000}, {0x41c3a000}, {0x41c3c000}, {0x41c3e000}, + {0x41c40000}, {0x41c42000}, {0x41c44000}, {0x41c46000}, + {0x41c48000}, {0x41c4a000}, {0x41c4c000}, {0x41c4e000}, + {0x41c50000}, {0x41c52000}, {0x41c54000}, {0x41c56000}, + {0x41c58000}, {0x41c5a000}, {0x41c5c000}, {0x41c5e000}, + {0x41c60000}, {0x41c62000}, {0x41c64000}, {0x41c66000}, + {0x41c68000}, {0x41c6a000}, {0x41c6c000}, {0x41c6e000}, + {0x41c70000}, {0x41c72000}, {0x41c74000}, {0x41c76000}, + {0x41c78000}, {0x41c7a000}, {0x41c7c000}, {0x41c7e000}, + {0x41c80000}, {0x41c82000}, {0x41c84000}, {0x41c86000}, + {0x41c88000}, {0x41c8a000}, {0x41c8c000}, {0x41c8e000}, + {0x41c90000}, {0x41c92000}, {0x41c94000}, {0x41c96000}, + {0x41c98000}, {0x41c9a000}, {0x41c9c000}, {0x41c9e000}, + {0x41ca0000}, {0x41ca2000}, {0x41ca4000}, {0x41ca6000}, + {0x41ca8000}, {0x41caa000}, {0x41cac000}, {0x41cae000}, + {0x41cb0000}, {0x41cb2000}, {0x41cb4000}, {0x41cb6000}, + {0x41cb8000}, {0x41cba000}, {0x41cbc000}, {0x41cbe000}, + {0x41cc0000}, {0x41cc2000}, {0x41cc4000}, {0x41cc6000}, + {0x41cc8000}, {0x41cca000}, {0x41ccc000}, {0x41cce000}, + {0x41cd0000}, {0x41cd2000}, {0x41cd4000}, {0x41cd6000}, + {0x41cd8000}, {0x41cda000}, {0x41cdc000}, {0x41cde000}, + {0x41ce0000}, {0x41ce2000}, {0x41ce4000}, {0x41ce6000}, + {0x41ce8000}, {0x41cea000}, {0x41cec000}, {0x41cee000}, + {0x41cf0000}, {0x41cf2000}, {0x41cf4000}, {0x41cf6000}, + {0x41cf8000}, {0x41cfa000}, {0x41cfc000}, {0x41cfe000}, + {0x41d00000}, {0x41d02000}, {0x41d04000}, {0x41d06000}, + {0x41d08000}, {0x41d0a000}, {0x41d0c000}, {0x41d0e000}, + {0x41d10000}, {0x41d12000}, {0x41d14000}, {0x41d16000}, + {0x41d18000}, {0x41d1a000}, {0x41d1c000}, {0x41d1e000}, + {0x41d20000}, {0x41d22000}, {0x41d24000}, {0x41d26000}, + {0x41d28000}, {0x41d2a000}, {0x41d2c000}, {0x41d2e000}, + {0x41d30000}, {0x41d32000}, {0x41d34000}, {0x41d36000}, + {0x41d38000}, {0x41d3a000}, {0x41d3c000}, {0x41d3e000}, + {0x41d40000}, {0x41d42000}, {0x41d44000}, {0x41d46000}, + {0x41d48000}, {0x41d4a000}, {0x41d4c000}, {0x41d4e000}, + {0x41d50000}, {0x41d52000}, {0x41d54000}, {0x41d56000}, + {0x41d58000}, {0x41d5a000}, {0x41d5c000}, {0x41d5e000}, + {0x41d60000}, {0x41d62000}, {0x41d64000}, {0x41d66000}, + {0x41d68000}, {0x41d6a000}, {0x41d6c000}, {0x41d6e000}, + {0x41d70000}, {0x41d72000}, {0x41d74000}, {0x41d76000}, + {0x41d78000}, {0x41d7a000}, {0x41d7c000}, {0x41d7e000}, + {0x41d80000}, {0x41d82000}, {0x41d84000}, {0x41d86000}, + {0x41d88000}, {0x41d8a000}, {0x41d8c000}, {0x41d8e000}, + {0x41d90000}, {0x41d92000}, {0x41d94000}, {0x41d96000}, + {0x41d98000}, {0x41d9a000}, {0x41d9c000}, {0x41d9e000}, + {0x41da0000}, {0x41da2000}, {0x41da4000}, {0x41da6000}, + {0x41da8000}, {0x41daa000}, {0x41dac000}, {0x41dae000}, + {0x41db0000}, {0x41db2000}, {0x41db4000}, {0x41db6000}, + {0x41db8000}, {0x41dba000}, {0x41dbc000}, {0x41dbe000}, + {0x41dc0000}, {0x41dc2000}, {0x41dc4000}, {0x41dc6000}, + {0x41dc8000}, {0x41dca000}, {0x41dcc000}, {0x41dce000}, + {0x41dd0000}, {0x41dd2000}, {0x41dd4000}, {0x41dd6000}, + {0x41dd8000}, {0x41dda000}, {0x41ddc000}, {0x41dde000}, + {0x41de0000}, {0x41de2000}, {0x41de4000}, {0x41de6000}, + {0x41de8000}, {0x41dea000}, {0x41dec000}, {0x41dee000}, + {0x41df0000}, {0x41df2000}, {0x41df4000}, {0x41df6000}, + {0x41df8000}, {0x41dfa000}, {0x41dfc000}, {0x41dfe000}, + {0x41e00000}, {0x41e02000}, {0x41e04000}, {0x41e06000}, + {0x41e08000}, {0x41e0a000}, {0x41e0c000}, {0x41e0e000}, + {0x41e10000}, {0x41e12000}, {0x41e14000}, {0x41e16000}, + {0x41e18000}, {0x41e1a000}, {0x41e1c000}, {0x41e1e000}, + {0x41e20000}, {0x41e22000}, {0x41e24000}, {0x41e26000}, + {0x41e28000}, {0x41e2a000}, {0x41e2c000}, {0x41e2e000}, + {0x41e30000}, {0x41e32000}, {0x41e34000}, {0x41e36000}, + {0x41e38000}, {0x41e3a000}, {0x41e3c000}, {0x41e3e000}, + {0x41e40000}, {0x41e42000}, {0x41e44000}, {0x41e46000}, + {0x41e48000}, {0x41e4a000}, {0x41e4c000}, {0x41e4e000}, + {0x41e50000}, {0x41e52000}, {0x41e54000}, {0x41e56000}, + {0x41e58000}, {0x41e5a000}, {0x41e5c000}, {0x41e5e000}, + {0x41e60000}, {0x41e62000}, {0x41e64000}, {0x41e66000}, + {0x41e68000}, {0x41e6a000}, {0x41e6c000}, {0x41e6e000}, + {0x41e70000}, {0x41e72000}, {0x41e74000}, {0x41e76000}, + {0x41e78000}, {0x41e7a000}, {0x41e7c000}, {0x41e7e000}, + {0x41e80000}, {0x41e82000}, {0x41e84000}, {0x41e86000}, + {0x41e88000}, {0x41e8a000}, {0x41e8c000}, {0x41e8e000}, + {0x41e90000}, {0x41e92000}, {0x41e94000}, {0x41e96000}, + {0x41e98000}, {0x41e9a000}, {0x41e9c000}, {0x41e9e000}, + {0x41ea0000}, {0x41ea2000}, {0x41ea4000}, {0x41ea6000}, + {0x41ea8000}, {0x41eaa000}, {0x41eac000}, {0x41eae000}, + {0x41eb0000}, {0x41eb2000}, {0x41eb4000}, {0x41eb6000}, + {0x41eb8000}, {0x41eba000}, {0x41ebc000}, {0x41ebe000}, + {0x41ec0000}, {0x41ec2000}, {0x41ec4000}, {0x41ec6000}, + {0x41ec8000}, {0x41eca000}, {0x41ecc000}, {0x41ece000}, + {0x41ed0000}, {0x41ed2000}, {0x41ed4000}, {0x41ed6000}, + {0x41ed8000}, {0x41eda000}, {0x41edc000}, {0x41ede000}, + {0x41ee0000}, {0x41ee2000}, {0x41ee4000}, {0x41ee6000}, + {0x41ee8000}, {0x41eea000}, {0x41eec000}, {0x41eee000}, + {0x41ef0000}, {0x41ef2000}, {0x41ef4000}, {0x41ef6000}, + {0x41ef8000}, {0x41efa000}, {0x41efc000}, {0x41efe000}, + {0x41f00000}, {0x41f02000}, {0x41f04000}, {0x41f06000}, + {0x41f08000}, {0x41f0a000}, {0x41f0c000}, {0x41f0e000}, + {0x41f10000}, {0x41f12000}, {0x41f14000}, {0x41f16000}, + {0x41f18000}, {0x41f1a000}, {0x41f1c000}, {0x41f1e000}, + {0x41f20000}, {0x41f22000}, {0x41f24000}, {0x41f26000}, + {0x41f28000}, {0x41f2a000}, {0x41f2c000}, {0x41f2e000}, + {0x41f30000}, {0x41f32000}, {0x41f34000}, {0x41f36000}, + {0x41f38000}, {0x41f3a000}, {0x41f3c000}, {0x41f3e000}, + {0x41f40000}, {0x41f42000}, {0x41f44000}, {0x41f46000}, + {0x41f48000}, {0x41f4a000}, {0x41f4c000}, {0x41f4e000}, + {0x41f50000}, {0x41f52000}, {0x41f54000}, {0x41f56000}, + {0x41f58000}, {0x41f5a000}, {0x41f5c000}, {0x41f5e000}, + {0x41f60000}, {0x41f62000}, {0x41f64000}, {0x41f66000}, + {0x41f68000}, {0x41f6a000}, {0x41f6c000}, {0x41f6e000}, + {0x41f70000}, {0x41f72000}, {0x41f74000}, {0x41f76000}, + {0x41f78000}, {0x41f7a000}, {0x41f7c000}, {0x41f7e000}, + {0x41f80000}, {0x41f82000}, {0x41f84000}, {0x41f86000}, + {0x41f88000}, {0x41f8a000}, {0x41f8c000}, {0x41f8e000}, + {0x41f90000}, {0x41f92000}, {0x41f94000}, {0x41f96000}, + {0x41f98000}, {0x41f9a000}, {0x41f9c000}, {0x41f9e000}, + {0x41fa0000}, {0x41fa2000}, {0x41fa4000}, {0x41fa6000}, + {0x41fa8000}, {0x41faa000}, {0x41fac000}, {0x41fae000}, + {0x41fb0000}, {0x41fb2000}, {0x41fb4000}, {0x41fb6000}, + {0x41fb8000}, {0x41fba000}, {0x41fbc000}, {0x41fbe000}, + {0x41fc0000}, {0x41fc2000}, {0x41fc4000}, {0x41fc6000}, + {0x41fc8000}, {0x41fca000}, {0x41fcc000}, {0x41fce000}, + {0x41fd0000}, {0x41fd2000}, {0x41fd4000}, {0x41fd6000}, + {0x41fd8000}, {0x41fda000}, {0x41fdc000}, {0x41fde000}, + {0x41fe0000}, {0x41fe2000}, {0x41fe4000}, {0x41fe6000}, + {0x41fe8000}, {0x41fea000}, {0x41fec000}, {0x41fee000}, + {0x41ff0000}, {0x41ff2000}, {0x41ff4000}, {0x41ff6000}, + {0x41ff8000}, {0x41ffa000}, {0x41ffc000}, {0x41ffe000}, + {0x42000000}, {0x42002000}, {0x42004000}, {0x42006000}, + {0x42008000}, {0x4200a000}, {0x4200c000}, {0x4200e000}, + {0x42010000}, {0x42012000}, {0x42014000}, {0x42016000}, + {0x42018000}, {0x4201a000}, {0x4201c000}, {0x4201e000}, + {0x42020000}, {0x42022000}, {0x42024000}, {0x42026000}, + {0x42028000}, {0x4202a000}, {0x4202c000}, {0x4202e000}, + {0x42030000}, {0x42032000}, {0x42034000}, {0x42036000}, + {0x42038000}, {0x4203a000}, {0x4203c000}, {0x4203e000}, + {0x42040000}, {0x42042000}, {0x42044000}, {0x42046000}, + {0x42048000}, {0x4204a000}, {0x4204c000}, {0x4204e000}, + {0x42050000}, {0x42052000}, {0x42054000}, {0x42056000}, + {0x42058000}, {0x4205a000}, {0x4205c000}, {0x4205e000}, + {0x42060000}, {0x42062000}, {0x42064000}, {0x42066000}, + {0x42068000}, {0x4206a000}, {0x4206c000}, {0x4206e000}, + {0x42070000}, {0x42072000}, {0x42074000}, {0x42076000}, + {0x42078000}, {0x4207a000}, {0x4207c000}, {0x4207e000}, + {0x42080000}, {0x42082000}, {0x42084000}, {0x42086000}, + {0x42088000}, {0x4208a000}, {0x4208c000}, {0x4208e000}, + {0x42090000}, {0x42092000}, {0x42094000}, {0x42096000}, + {0x42098000}, {0x4209a000}, {0x4209c000}, {0x4209e000}, + {0x420a0000}, {0x420a2000}, {0x420a4000}, {0x420a6000}, + {0x420a8000}, {0x420aa000}, {0x420ac000}, {0x420ae000}, + {0x420b0000}, {0x420b2000}, {0x420b4000}, {0x420b6000}, + {0x420b8000}, {0x420ba000}, {0x420bc000}, {0x420be000}, + {0x420c0000}, {0x420c2000}, {0x420c4000}, {0x420c6000}, + {0x420c8000}, {0x420ca000}, {0x420cc000}, {0x420ce000}, + {0x420d0000}, {0x420d2000}, {0x420d4000}, {0x420d6000}, + {0x420d8000}, {0x420da000}, {0x420dc000}, {0x420de000}, + {0x420e0000}, {0x420e2000}, {0x420e4000}, {0x420e6000}, + {0x420e8000}, {0x420ea000}, {0x420ec000}, {0x420ee000}, + {0x420f0000}, {0x420f2000}, {0x420f4000}, {0x420f6000}, + {0x420f8000}, {0x420fa000}, {0x420fc000}, {0x420fe000}, + {0x42100000}, {0x42102000}, {0x42104000}, {0x42106000}, + {0x42108000}, {0x4210a000}, {0x4210c000}, {0x4210e000}, + {0x42110000}, {0x42112000}, {0x42114000}, {0x42116000}, + {0x42118000}, {0x4211a000}, {0x4211c000}, {0x4211e000}, + {0x42120000}, {0x42122000}, {0x42124000}, {0x42126000}, + {0x42128000}, {0x4212a000}, {0x4212c000}, {0x4212e000}, + {0x42130000}, {0x42132000}, {0x42134000}, {0x42136000}, + {0x42138000}, {0x4213a000}, {0x4213c000}, {0x4213e000}, + {0x42140000}, {0x42142000}, {0x42144000}, {0x42146000}, + {0x42148000}, {0x4214a000}, {0x4214c000}, {0x4214e000}, + {0x42150000}, {0x42152000}, {0x42154000}, {0x42156000}, + {0x42158000}, {0x4215a000}, {0x4215c000}, {0x4215e000}, + {0x42160000}, {0x42162000}, {0x42164000}, {0x42166000}, + {0x42168000}, {0x4216a000}, {0x4216c000}, {0x4216e000}, + {0x42170000}, {0x42172000}, {0x42174000}, {0x42176000}, + {0x42178000}, {0x4217a000}, {0x4217c000}, {0x4217e000}, + {0x42180000}, {0x42182000}, {0x42184000}, {0x42186000}, + {0x42188000}, {0x4218a000}, {0x4218c000}, {0x4218e000}, + {0x42190000}, {0x42192000}, {0x42194000}, {0x42196000}, + {0x42198000}, {0x4219a000}, {0x4219c000}, {0x4219e000}, + {0x421a0000}, {0x421a2000}, {0x421a4000}, {0x421a6000}, + {0x421a8000}, {0x421aa000}, {0x421ac000}, {0x421ae000}, + {0x421b0000}, {0x421b2000}, {0x421b4000}, {0x421b6000}, + {0x421b8000}, {0x421ba000}, {0x421bc000}, {0x421be000}, + {0x421c0000}, {0x421c2000}, {0x421c4000}, {0x421c6000}, + {0x421c8000}, {0x421ca000}, {0x421cc000}, {0x421ce000}, + {0x421d0000}, {0x421d2000}, {0x421d4000}, {0x421d6000}, + {0x421d8000}, {0x421da000}, {0x421dc000}, {0x421de000}, + {0x421e0000}, {0x421e2000}, {0x421e4000}, {0x421e6000}, + {0x421e8000}, {0x421ea000}, {0x421ec000}, {0x421ee000}, + {0x421f0000}, {0x421f2000}, {0x421f4000}, {0x421f6000}, + {0x421f8000}, {0x421fa000}, {0x421fc000}, {0x421fe000}, + {0x42200000}, {0x42202000}, {0x42204000}, {0x42206000}, + {0x42208000}, {0x4220a000}, {0x4220c000}, {0x4220e000}, + {0x42210000}, {0x42212000}, {0x42214000}, {0x42216000}, + {0x42218000}, {0x4221a000}, {0x4221c000}, {0x4221e000}, + {0x42220000}, {0x42222000}, {0x42224000}, {0x42226000}, + {0x42228000}, {0x4222a000}, {0x4222c000}, {0x4222e000}, + {0x42230000}, {0x42232000}, {0x42234000}, {0x42236000}, + {0x42238000}, {0x4223a000}, {0x4223c000}, {0x4223e000}, + {0x42240000}, {0x42242000}, {0x42244000}, {0x42246000}, + {0x42248000}, {0x4224a000}, {0x4224c000}, {0x4224e000}, + {0x42250000}, {0x42252000}, {0x42254000}, {0x42256000}, + {0x42258000}, {0x4225a000}, {0x4225c000}, {0x4225e000}, + {0x42260000}, {0x42262000}, {0x42264000}, {0x42266000}, + {0x42268000}, {0x4226a000}, {0x4226c000}, {0x4226e000}, + {0x42270000}, {0x42272000}, {0x42274000}, {0x42276000}, + {0x42278000}, {0x4227a000}, {0x4227c000}, {0x4227e000}, + {0x42280000}, {0x42282000}, {0x42284000}, {0x42286000}, + {0x42288000}, {0x4228a000}, {0x4228c000}, {0x4228e000}, + {0x42290000}, {0x42292000}, {0x42294000}, {0x42296000}, + {0x42298000}, {0x4229a000}, {0x4229c000}, {0x4229e000}, + {0x422a0000}, {0x422a2000}, {0x422a4000}, {0x422a6000}, + {0x422a8000}, {0x422aa000}, {0x422ac000}, {0x422ae000}, + {0x422b0000}, {0x422b2000}, {0x422b4000}, {0x422b6000}, + {0x422b8000}, {0x422ba000}, {0x422bc000}, {0x422be000}, + {0x422c0000}, {0x422c2000}, {0x422c4000}, {0x422c6000}, + {0x422c8000}, {0x422ca000}, {0x422cc000}, {0x422ce000}, + {0x422d0000}, {0x422d2000}, {0x422d4000}, {0x422d6000}, + {0x422d8000}, {0x422da000}, {0x422dc000}, {0x422de000}, + {0x422e0000}, {0x422e2000}, {0x422e4000}, {0x422e6000}, + {0x422e8000}, {0x422ea000}, {0x422ec000}, {0x422ee000}, + {0x422f0000}, {0x422f2000}, {0x422f4000}, {0x422f6000}, + {0x422f8000}, {0x422fa000}, {0x422fc000}, {0x422fe000}, + {0x42300000}, {0x42302000}, {0x42304000}, {0x42306000}, + {0x42308000}, {0x4230a000}, {0x4230c000}, {0x4230e000}, + {0x42310000}, {0x42312000}, {0x42314000}, {0x42316000}, + {0x42318000}, {0x4231a000}, {0x4231c000}, {0x4231e000}, + {0x42320000}, {0x42322000}, {0x42324000}, {0x42326000}, + {0x42328000}, {0x4232a000}, {0x4232c000}, {0x4232e000}, + {0x42330000}, {0x42332000}, {0x42334000}, {0x42336000}, + {0x42338000}, {0x4233a000}, {0x4233c000}, {0x4233e000}, + {0x42340000}, {0x42342000}, {0x42344000}, {0x42346000}, + {0x42348000}, {0x4234a000}, {0x4234c000}, {0x4234e000}, + {0x42350000}, {0x42352000}, {0x42354000}, {0x42356000}, + {0x42358000}, {0x4235a000}, {0x4235c000}, {0x4235e000}, + {0x42360000}, {0x42362000}, {0x42364000}, {0x42366000}, + {0x42368000}, {0x4236a000}, {0x4236c000}, {0x4236e000}, + {0x42370000}, {0x42372000}, {0x42374000}, {0x42376000}, + {0x42378000}, {0x4237a000}, {0x4237c000}, {0x4237e000}, + {0x42380000}, {0x42382000}, {0x42384000}, {0x42386000}, + {0x42388000}, {0x4238a000}, {0x4238c000}, {0x4238e000}, + {0x42390000}, {0x42392000}, {0x42394000}, {0x42396000}, + {0x42398000}, {0x4239a000}, {0x4239c000}, {0x4239e000}, + {0x423a0000}, {0x423a2000}, {0x423a4000}, {0x423a6000}, + {0x423a8000}, {0x423aa000}, {0x423ac000}, {0x423ae000}, + {0x423b0000}, {0x423b2000}, {0x423b4000}, {0x423b6000}, + {0x423b8000}, {0x423ba000}, {0x423bc000}, {0x423be000}, + {0x423c0000}, {0x423c2000}, {0x423c4000}, {0x423c6000}, + {0x423c8000}, {0x423ca000}, {0x423cc000}, {0x423ce000}, + {0x423d0000}, {0x423d2000}, {0x423d4000}, {0x423d6000}, + {0x423d8000}, {0x423da000}, {0x423dc000}, {0x423de000}, + {0x423e0000}, {0x423e2000}, {0x423e4000}, {0x423e6000}, + {0x423e8000}, {0x423ea000}, {0x423ec000}, {0x423ee000}, + {0x423f0000}, {0x423f2000}, {0x423f4000}, {0x423f6000}, + {0x423f8000}, {0x423fa000}, {0x423fc000}, {0x423fe000}, + {0x42400000}, {0x42402000}, {0x42404000}, {0x42406000}, + {0x42408000}, {0x4240a000}, {0x4240c000}, {0x4240e000}, + {0x42410000}, {0x42412000}, {0x42414000}, {0x42416000}, + {0x42418000}, {0x4241a000}, {0x4241c000}, {0x4241e000}, + {0x42420000}, {0x42422000}, {0x42424000}, {0x42426000}, + {0x42428000}, {0x4242a000}, {0x4242c000}, {0x4242e000}, + {0x42430000}, {0x42432000}, {0x42434000}, {0x42436000}, + {0x42438000}, {0x4243a000}, {0x4243c000}, {0x4243e000}, + {0x42440000}, {0x42442000}, {0x42444000}, {0x42446000}, + {0x42448000}, {0x4244a000}, {0x4244c000}, {0x4244e000}, + {0x42450000}, {0x42452000}, {0x42454000}, {0x42456000}, + {0x42458000}, {0x4245a000}, {0x4245c000}, {0x4245e000}, + {0x42460000}, {0x42462000}, {0x42464000}, {0x42466000}, + {0x42468000}, {0x4246a000}, {0x4246c000}, {0x4246e000}, + {0x42470000}, {0x42472000}, {0x42474000}, {0x42476000}, + {0x42478000}, {0x4247a000}, {0x4247c000}, {0x4247e000}, + {0x42480000}, {0x42482000}, {0x42484000}, {0x42486000}, + {0x42488000}, {0x4248a000}, {0x4248c000}, {0x4248e000}, + {0x42490000}, {0x42492000}, {0x42494000}, {0x42496000}, + {0x42498000}, {0x4249a000}, {0x4249c000}, {0x4249e000}, + {0x424a0000}, {0x424a2000}, {0x424a4000}, {0x424a6000}, + {0x424a8000}, {0x424aa000}, {0x424ac000}, {0x424ae000}, + {0x424b0000}, {0x424b2000}, {0x424b4000}, {0x424b6000}, + {0x424b8000}, {0x424ba000}, {0x424bc000}, {0x424be000}, + {0x424c0000}, {0x424c2000}, {0x424c4000}, {0x424c6000}, + {0x424c8000}, {0x424ca000}, {0x424cc000}, {0x424ce000}, + {0x424d0000}, {0x424d2000}, {0x424d4000}, {0x424d6000}, + {0x424d8000}, {0x424da000}, {0x424dc000}, {0x424de000}, + {0x424e0000}, {0x424e2000}, {0x424e4000}, {0x424e6000}, + {0x424e8000}, {0x424ea000}, {0x424ec000}, {0x424ee000}, + {0x424f0000}, {0x424f2000}, {0x424f4000}, {0x424f6000}, + {0x424f8000}, {0x424fa000}, {0x424fc000}, {0x424fe000}, + {0x42500000}, {0x42502000}, {0x42504000}, {0x42506000}, + {0x42508000}, {0x4250a000}, {0x4250c000}, {0x4250e000}, + {0x42510000}, {0x42512000}, {0x42514000}, {0x42516000}, + {0x42518000}, {0x4251a000}, {0x4251c000}, {0x4251e000}, + {0x42520000}, {0x42522000}, {0x42524000}, {0x42526000}, + {0x42528000}, {0x4252a000}, {0x4252c000}, {0x4252e000}, + {0x42530000}, {0x42532000}, {0x42534000}, {0x42536000}, + {0x42538000}, {0x4253a000}, {0x4253c000}, {0x4253e000}, + {0x42540000}, {0x42542000}, {0x42544000}, {0x42546000}, + {0x42548000}, {0x4254a000}, {0x4254c000}, {0x4254e000}, + {0x42550000}, {0x42552000}, {0x42554000}, {0x42556000}, + {0x42558000}, {0x4255a000}, {0x4255c000}, {0x4255e000}, + {0x42560000}, {0x42562000}, {0x42564000}, {0x42566000}, + {0x42568000}, {0x4256a000}, {0x4256c000}, {0x4256e000}, + {0x42570000}, {0x42572000}, {0x42574000}, {0x42576000}, + {0x42578000}, {0x4257a000}, {0x4257c000}, {0x4257e000}, + {0x42580000}, {0x42582000}, {0x42584000}, {0x42586000}, + {0x42588000}, {0x4258a000}, {0x4258c000}, {0x4258e000}, + {0x42590000}, {0x42592000}, {0x42594000}, {0x42596000}, + {0x42598000}, {0x4259a000}, {0x4259c000}, {0x4259e000}, + {0x425a0000}, {0x425a2000}, {0x425a4000}, {0x425a6000}, + {0x425a8000}, {0x425aa000}, {0x425ac000}, {0x425ae000}, + {0x425b0000}, {0x425b2000}, {0x425b4000}, {0x425b6000}, + {0x425b8000}, {0x425ba000}, {0x425bc000}, {0x425be000}, + {0x425c0000}, {0x425c2000}, {0x425c4000}, {0x425c6000}, + {0x425c8000}, {0x425ca000}, {0x425cc000}, {0x425ce000}, + {0x425d0000}, {0x425d2000}, {0x425d4000}, {0x425d6000}, + {0x425d8000}, {0x425da000}, {0x425dc000}, {0x425de000}, + {0x425e0000}, {0x425e2000}, {0x425e4000}, {0x425e6000}, + {0x425e8000}, {0x425ea000}, {0x425ec000}, {0x425ee000}, + {0x425f0000}, {0x425f2000}, {0x425f4000}, {0x425f6000}, + {0x425f8000}, {0x425fa000}, {0x425fc000}, {0x425fe000}, + {0x42600000}, {0x42602000}, {0x42604000}, {0x42606000}, + {0x42608000}, {0x4260a000}, {0x4260c000}, {0x4260e000}, + {0x42610000}, {0x42612000}, {0x42614000}, {0x42616000}, + {0x42618000}, {0x4261a000}, {0x4261c000}, {0x4261e000}, + {0x42620000}, {0x42622000}, {0x42624000}, {0x42626000}, + {0x42628000}, {0x4262a000}, {0x4262c000}, {0x4262e000}, + {0x42630000}, {0x42632000}, {0x42634000}, {0x42636000}, + {0x42638000}, {0x4263a000}, {0x4263c000}, {0x4263e000}, + {0x42640000}, {0x42642000}, {0x42644000}, {0x42646000}, + {0x42648000}, {0x4264a000}, {0x4264c000}, {0x4264e000}, + {0x42650000}, {0x42652000}, {0x42654000}, {0x42656000}, + {0x42658000}, {0x4265a000}, {0x4265c000}, {0x4265e000}, + {0x42660000}, {0x42662000}, {0x42664000}, {0x42666000}, + {0x42668000}, {0x4266a000}, {0x4266c000}, {0x4266e000}, + {0x42670000}, {0x42672000}, {0x42674000}, {0x42676000}, + {0x42678000}, {0x4267a000}, {0x4267c000}, {0x4267e000}, + {0x42680000}, {0x42682000}, {0x42684000}, {0x42686000}, + {0x42688000}, {0x4268a000}, {0x4268c000}, {0x4268e000}, + {0x42690000}, {0x42692000}, {0x42694000}, {0x42696000}, + {0x42698000}, {0x4269a000}, {0x4269c000}, {0x4269e000}, + {0x426a0000}, {0x426a2000}, {0x426a4000}, {0x426a6000}, + {0x426a8000}, {0x426aa000}, {0x426ac000}, {0x426ae000}, + {0x426b0000}, {0x426b2000}, {0x426b4000}, {0x426b6000}, + {0x426b8000}, {0x426ba000}, {0x426bc000}, {0x426be000}, + {0x426c0000}, {0x426c2000}, {0x426c4000}, {0x426c6000}, + {0x426c8000}, {0x426ca000}, {0x426cc000}, {0x426ce000}, + {0x426d0000}, {0x426d2000}, {0x426d4000}, {0x426d6000}, + {0x426d8000}, {0x426da000}, {0x426dc000}, {0x426de000}, + {0x426e0000}, {0x426e2000}, {0x426e4000}, {0x426e6000}, + {0x426e8000}, {0x426ea000}, {0x426ec000}, {0x426ee000}, + {0x426f0000}, {0x426f2000}, {0x426f4000}, {0x426f6000}, + {0x426f8000}, {0x426fa000}, {0x426fc000}, {0x426fe000}, + {0x42700000}, {0x42702000}, {0x42704000}, {0x42706000}, + {0x42708000}, {0x4270a000}, {0x4270c000}, {0x4270e000}, + {0x42710000}, {0x42712000}, {0x42714000}, {0x42716000}, + {0x42718000}, {0x4271a000}, {0x4271c000}, {0x4271e000}, + {0x42720000}, {0x42722000}, {0x42724000}, {0x42726000}, + {0x42728000}, {0x4272a000}, {0x4272c000}, {0x4272e000}, + {0x42730000}, {0x42732000}, {0x42734000}, {0x42736000}, + {0x42738000}, {0x4273a000}, {0x4273c000}, {0x4273e000}, + {0x42740000}, {0x42742000}, {0x42744000}, {0x42746000}, + {0x42748000}, {0x4274a000}, {0x4274c000}, {0x4274e000}, + {0x42750000}, {0x42752000}, {0x42754000}, {0x42756000}, + {0x42758000}, {0x4275a000}, {0x4275c000}, {0x4275e000}, + {0x42760000}, {0x42762000}, {0x42764000}, {0x42766000}, + {0x42768000}, {0x4276a000}, {0x4276c000}, {0x4276e000}, + {0x42770000}, {0x42772000}, {0x42774000}, {0x42776000}, + {0x42778000}, {0x4277a000}, {0x4277c000}, {0x4277e000}, + {0x42780000}, {0x42782000}, {0x42784000}, {0x42786000}, + {0x42788000}, {0x4278a000}, {0x4278c000}, {0x4278e000}, + {0x42790000}, {0x42792000}, {0x42794000}, {0x42796000}, + {0x42798000}, {0x4279a000}, {0x4279c000}, {0x4279e000}, + {0x427a0000}, {0x427a2000}, {0x427a4000}, {0x427a6000}, + {0x427a8000}, {0x427aa000}, {0x427ac000}, {0x427ae000}, + {0x427b0000}, {0x427b2000}, {0x427b4000}, {0x427b6000}, + {0x427b8000}, {0x427ba000}, {0x427bc000}, {0x427be000}, + {0x427c0000}, {0x427c2000}, {0x427c4000}, {0x427c6000}, + {0x427c8000}, {0x427ca000}, {0x427cc000}, {0x427ce000}, + {0x427d0000}, {0x427d2000}, {0x427d4000}, {0x427d6000}, + {0x427d8000}, {0x427da000}, {0x427dc000}, {0x427de000}, + {0x427e0000}, {0x427e2000}, {0x427e4000}, {0x427e6000}, + {0x427e8000}, {0x427ea000}, {0x427ec000}, {0x427ee000}, + {0x427f0000}, {0x427f2000}, {0x427f4000}, {0x427f6000}, + {0x427f8000}, {0x427fa000}, {0x427fc000}, {0x427fe000}, + {0x42800000}, {0x42802000}, {0x42804000}, {0x42806000}, + {0x42808000}, {0x4280a000}, {0x4280c000}, {0x4280e000}, + {0x42810000}, {0x42812000}, {0x42814000}, {0x42816000}, + {0x42818000}, {0x4281a000}, {0x4281c000}, {0x4281e000}, + {0x42820000}, {0x42822000}, {0x42824000}, {0x42826000}, + {0x42828000}, {0x4282a000}, {0x4282c000}, {0x4282e000}, + {0x42830000}, {0x42832000}, {0x42834000}, {0x42836000}, + {0x42838000}, {0x4283a000}, {0x4283c000}, {0x4283e000}, + {0x42840000}, {0x42842000}, {0x42844000}, {0x42846000}, + {0x42848000}, {0x4284a000}, {0x4284c000}, {0x4284e000}, + {0x42850000}, {0x42852000}, {0x42854000}, {0x42856000}, + {0x42858000}, {0x4285a000}, {0x4285c000}, {0x4285e000}, + {0x42860000}, {0x42862000}, {0x42864000}, {0x42866000}, + {0x42868000}, {0x4286a000}, {0x4286c000}, {0x4286e000}, + {0x42870000}, {0x42872000}, {0x42874000}, {0x42876000}, + {0x42878000}, {0x4287a000}, {0x4287c000}, {0x4287e000}, + {0x42880000}, {0x42882000}, {0x42884000}, {0x42886000}, + {0x42888000}, {0x4288a000}, {0x4288c000}, {0x4288e000}, + {0x42890000}, {0x42892000}, {0x42894000}, {0x42896000}, + {0x42898000}, {0x4289a000}, {0x4289c000}, {0x4289e000}, + {0x428a0000}, {0x428a2000}, {0x428a4000}, {0x428a6000}, + {0x428a8000}, {0x428aa000}, {0x428ac000}, {0x428ae000}, + {0x428b0000}, {0x428b2000}, {0x428b4000}, {0x428b6000}, + {0x428b8000}, {0x428ba000}, {0x428bc000}, {0x428be000}, + {0x428c0000}, {0x428c2000}, {0x428c4000}, {0x428c6000}, + {0x428c8000}, {0x428ca000}, {0x428cc000}, {0x428ce000}, + {0x428d0000}, {0x428d2000}, {0x428d4000}, {0x428d6000}, + {0x428d8000}, {0x428da000}, {0x428dc000}, {0x428de000}, + {0x428e0000}, {0x428e2000}, {0x428e4000}, {0x428e6000}, + {0x428e8000}, {0x428ea000}, {0x428ec000}, {0x428ee000}, + {0x428f0000}, {0x428f2000}, {0x428f4000}, {0x428f6000}, + {0x428f8000}, {0x428fa000}, {0x428fc000}, {0x428fe000}, + {0x42900000}, {0x42902000}, {0x42904000}, {0x42906000}, + {0x42908000}, {0x4290a000}, {0x4290c000}, {0x4290e000}, + {0x42910000}, {0x42912000}, {0x42914000}, {0x42916000}, + {0x42918000}, {0x4291a000}, {0x4291c000}, {0x4291e000}, + {0x42920000}, {0x42922000}, {0x42924000}, {0x42926000}, + {0x42928000}, {0x4292a000}, {0x4292c000}, {0x4292e000}, + {0x42930000}, {0x42932000}, {0x42934000}, {0x42936000}, + {0x42938000}, {0x4293a000}, {0x4293c000}, {0x4293e000}, + {0x42940000}, {0x42942000}, {0x42944000}, {0x42946000}, + {0x42948000}, {0x4294a000}, {0x4294c000}, {0x4294e000}, + {0x42950000}, {0x42952000}, {0x42954000}, {0x42956000}, + {0x42958000}, {0x4295a000}, {0x4295c000}, {0x4295e000}, + {0x42960000}, {0x42962000}, {0x42964000}, {0x42966000}, + {0x42968000}, {0x4296a000}, {0x4296c000}, {0x4296e000}, + {0x42970000}, {0x42972000}, {0x42974000}, {0x42976000}, + {0x42978000}, {0x4297a000}, {0x4297c000}, {0x4297e000}, + {0x42980000}, {0x42982000}, {0x42984000}, {0x42986000}, + {0x42988000}, {0x4298a000}, {0x4298c000}, {0x4298e000}, + {0x42990000}, {0x42992000}, {0x42994000}, {0x42996000}, + {0x42998000}, {0x4299a000}, {0x4299c000}, {0x4299e000}, + {0x429a0000}, {0x429a2000}, {0x429a4000}, {0x429a6000}, + {0x429a8000}, {0x429aa000}, {0x429ac000}, {0x429ae000}, + {0x429b0000}, {0x429b2000}, {0x429b4000}, {0x429b6000}, + {0x429b8000}, {0x429ba000}, {0x429bc000}, {0x429be000}, + {0x429c0000}, {0x429c2000}, {0x429c4000}, {0x429c6000}, + {0x429c8000}, {0x429ca000}, {0x429cc000}, {0x429ce000}, + {0x429d0000}, {0x429d2000}, {0x429d4000}, {0x429d6000}, + {0x429d8000}, {0x429da000}, {0x429dc000}, {0x429de000}, + {0x429e0000}, {0x429e2000}, {0x429e4000}, {0x429e6000}, + {0x429e8000}, {0x429ea000}, {0x429ec000}, {0x429ee000}, + {0x429f0000}, {0x429f2000}, {0x429f4000}, {0x429f6000}, + {0x429f8000}, {0x429fa000}, {0x429fc000}, {0x429fe000}, + {0x42a00000}, {0x42a02000}, {0x42a04000}, {0x42a06000}, + {0x42a08000}, {0x42a0a000}, {0x42a0c000}, {0x42a0e000}, + {0x42a10000}, {0x42a12000}, {0x42a14000}, {0x42a16000}, + {0x42a18000}, {0x42a1a000}, {0x42a1c000}, {0x42a1e000}, + {0x42a20000}, {0x42a22000}, {0x42a24000}, {0x42a26000}, + {0x42a28000}, {0x42a2a000}, {0x42a2c000}, {0x42a2e000}, + {0x42a30000}, {0x42a32000}, {0x42a34000}, {0x42a36000}, + {0x42a38000}, {0x42a3a000}, {0x42a3c000}, {0x42a3e000}, + {0x42a40000}, {0x42a42000}, {0x42a44000}, {0x42a46000}, + {0x42a48000}, {0x42a4a000}, {0x42a4c000}, {0x42a4e000}, + {0x42a50000}, {0x42a52000}, {0x42a54000}, {0x42a56000}, + {0x42a58000}, {0x42a5a000}, {0x42a5c000}, {0x42a5e000}, + {0x42a60000}, {0x42a62000}, {0x42a64000}, {0x42a66000}, + {0x42a68000}, {0x42a6a000}, {0x42a6c000}, {0x42a6e000}, + {0x42a70000}, {0x42a72000}, {0x42a74000}, {0x42a76000}, + {0x42a78000}, {0x42a7a000}, {0x42a7c000}, {0x42a7e000}, + {0x42a80000}, {0x42a82000}, {0x42a84000}, {0x42a86000}, + {0x42a88000}, {0x42a8a000}, {0x42a8c000}, {0x42a8e000}, + {0x42a90000}, {0x42a92000}, {0x42a94000}, {0x42a96000}, + {0x42a98000}, {0x42a9a000}, {0x42a9c000}, {0x42a9e000}, + {0x42aa0000}, {0x42aa2000}, {0x42aa4000}, {0x42aa6000}, + {0x42aa8000}, {0x42aaa000}, {0x42aac000}, {0x42aae000}, + {0x42ab0000}, {0x42ab2000}, {0x42ab4000}, {0x42ab6000}, + {0x42ab8000}, {0x42aba000}, {0x42abc000}, {0x42abe000}, + {0x42ac0000}, {0x42ac2000}, {0x42ac4000}, {0x42ac6000}, + {0x42ac8000}, {0x42aca000}, {0x42acc000}, {0x42ace000}, + {0x42ad0000}, {0x42ad2000}, {0x42ad4000}, {0x42ad6000}, + {0x42ad8000}, {0x42ada000}, {0x42adc000}, {0x42ade000}, + {0x42ae0000}, {0x42ae2000}, {0x42ae4000}, {0x42ae6000}, + {0x42ae8000}, {0x42aea000}, {0x42aec000}, {0x42aee000}, + {0x42af0000}, {0x42af2000}, {0x42af4000}, {0x42af6000}, + {0x42af8000}, {0x42afa000}, {0x42afc000}, {0x42afe000}, + {0x42b00000}, {0x42b02000}, {0x42b04000}, {0x42b06000}, + {0x42b08000}, {0x42b0a000}, {0x42b0c000}, {0x42b0e000}, + {0x42b10000}, {0x42b12000}, {0x42b14000}, {0x42b16000}, + {0x42b18000}, {0x42b1a000}, {0x42b1c000}, {0x42b1e000}, + {0x42b20000}, {0x42b22000}, {0x42b24000}, {0x42b26000}, + {0x42b28000}, {0x42b2a000}, {0x42b2c000}, {0x42b2e000}, + {0x42b30000}, {0x42b32000}, {0x42b34000}, {0x42b36000}, + {0x42b38000}, {0x42b3a000}, {0x42b3c000}, {0x42b3e000}, + {0x42b40000}, {0x42b42000}, {0x42b44000}, {0x42b46000}, + {0x42b48000}, {0x42b4a000}, {0x42b4c000}, {0x42b4e000}, + {0x42b50000}, {0x42b52000}, {0x42b54000}, {0x42b56000}, + {0x42b58000}, {0x42b5a000}, {0x42b5c000}, {0x42b5e000}, + {0x42b60000}, {0x42b62000}, {0x42b64000}, {0x42b66000}, + {0x42b68000}, {0x42b6a000}, {0x42b6c000}, {0x42b6e000}, + {0x42b70000}, {0x42b72000}, {0x42b74000}, {0x42b76000}, + {0x42b78000}, {0x42b7a000}, {0x42b7c000}, {0x42b7e000}, + {0x42b80000}, {0x42b82000}, {0x42b84000}, {0x42b86000}, + {0x42b88000}, {0x42b8a000}, {0x42b8c000}, {0x42b8e000}, + {0x42b90000}, {0x42b92000}, {0x42b94000}, {0x42b96000}, + {0x42b98000}, {0x42b9a000}, {0x42b9c000}, {0x42b9e000}, + {0x42ba0000}, {0x42ba2000}, {0x42ba4000}, {0x42ba6000}, + {0x42ba8000}, {0x42baa000}, {0x42bac000}, {0x42bae000}, + {0x42bb0000}, {0x42bb2000}, {0x42bb4000}, {0x42bb6000}, + {0x42bb8000}, {0x42bba000}, {0x42bbc000}, {0x42bbe000}, + {0x42bc0000}, {0x42bc2000}, {0x42bc4000}, {0x42bc6000}, + {0x42bc8000}, {0x42bca000}, {0x42bcc000}, {0x42bce000}, + {0x42bd0000}, {0x42bd2000}, {0x42bd4000}, {0x42bd6000}, + {0x42bd8000}, {0x42bda000}, {0x42bdc000}, {0x42bde000}, + {0x42be0000}, {0x42be2000}, {0x42be4000}, {0x42be6000}, + {0x42be8000}, {0x42bea000}, {0x42bec000}, {0x42bee000}, + {0x42bf0000}, {0x42bf2000}, {0x42bf4000}, {0x42bf6000}, + {0x42bf8000}, {0x42bfa000}, {0x42bfc000}, {0x42bfe000}, + {0x42c00000}, {0x42c02000}, {0x42c04000}, {0x42c06000}, + {0x42c08000}, {0x42c0a000}, {0x42c0c000}, {0x42c0e000}, + {0x42c10000}, {0x42c12000}, {0x42c14000}, {0x42c16000}, + {0x42c18000}, {0x42c1a000}, {0x42c1c000}, {0x42c1e000}, + {0x42c20000}, {0x42c22000}, {0x42c24000}, {0x42c26000}, + {0x42c28000}, {0x42c2a000}, {0x42c2c000}, {0x42c2e000}, + {0x42c30000}, {0x42c32000}, {0x42c34000}, {0x42c36000}, + {0x42c38000}, {0x42c3a000}, {0x42c3c000}, {0x42c3e000}, + {0x42c40000}, {0x42c42000}, {0x42c44000}, {0x42c46000}, + {0x42c48000}, {0x42c4a000}, {0x42c4c000}, {0x42c4e000}, + {0x42c50000}, {0x42c52000}, {0x42c54000}, {0x42c56000}, + {0x42c58000}, {0x42c5a000}, {0x42c5c000}, {0x42c5e000}, + {0x42c60000}, {0x42c62000}, {0x42c64000}, {0x42c66000}, + {0x42c68000}, {0x42c6a000}, {0x42c6c000}, {0x42c6e000}, + {0x42c70000}, {0x42c72000}, {0x42c74000}, {0x42c76000}, + {0x42c78000}, {0x42c7a000}, {0x42c7c000}, {0x42c7e000}, + {0x42c80000}, {0x42c82000}, {0x42c84000}, {0x42c86000}, + {0x42c88000}, {0x42c8a000}, {0x42c8c000}, {0x42c8e000}, + {0x42c90000}, {0x42c92000}, {0x42c94000}, {0x42c96000}, + {0x42c98000}, {0x42c9a000}, {0x42c9c000}, {0x42c9e000}, + {0x42ca0000}, {0x42ca2000}, {0x42ca4000}, {0x42ca6000}, + {0x42ca8000}, {0x42caa000}, {0x42cac000}, {0x42cae000}, + {0x42cb0000}, {0x42cb2000}, {0x42cb4000}, {0x42cb6000}, + {0x42cb8000}, {0x42cba000}, {0x42cbc000}, {0x42cbe000}, + {0x42cc0000}, {0x42cc2000}, {0x42cc4000}, {0x42cc6000}, + {0x42cc8000}, {0x42cca000}, {0x42ccc000}, {0x42cce000}, + {0x42cd0000}, {0x42cd2000}, {0x42cd4000}, {0x42cd6000}, + {0x42cd8000}, {0x42cda000}, {0x42cdc000}, {0x42cde000}, + {0x42ce0000}, {0x42ce2000}, {0x42ce4000}, {0x42ce6000}, + {0x42ce8000}, {0x42cea000}, {0x42cec000}, {0x42cee000}, + {0x42cf0000}, {0x42cf2000}, {0x42cf4000}, {0x42cf6000}, + {0x42cf8000}, {0x42cfa000}, {0x42cfc000}, {0x42cfe000}, + {0x42d00000}, {0x42d02000}, {0x42d04000}, {0x42d06000}, + {0x42d08000}, {0x42d0a000}, {0x42d0c000}, {0x42d0e000}, + {0x42d10000}, {0x42d12000}, {0x42d14000}, {0x42d16000}, + {0x42d18000}, {0x42d1a000}, {0x42d1c000}, {0x42d1e000}, + {0x42d20000}, {0x42d22000}, {0x42d24000}, {0x42d26000}, + {0x42d28000}, {0x42d2a000}, {0x42d2c000}, {0x42d2e000}, + {0x42d30000}, {0x42d32000}, {0x42d34000}, {0x42d36000}, + {0x42d38000}, {0x42d3a000}, {0x42d3c000}, {0x42d3e000}, + {0x42d40000}, {0x42d42000}, {0x42d44000}, {0x42d46000}, + {0x42d48000}, {0x42d4a000}, {0x42d4c000}, {0x42d4e000}, + {0x42d50000}, {0x42d52000}, {0x42d54000}, {0x42d56000}, + {0x42d58000}, {0x42d5a000}, {0x42d5c000}, {0x42d5e000}, + {0x42d60000}, {0x42d62000}, {0x42d64000}, {0x42d66000}, + {0x42d68000}, {0x42d6a000}, {0x42d6c000}, {0x42d6e000}, + {0x42d70000}, {0x42d72000}, {0x42d74000}, {0x42d76000}, + {0x42d78000}, {0x42d7a000}, {0x42d7c000}, {0x42d7e000}, + {0x42d80000}, {0x42d82000}, {0x42d84000}, {0x42d86000}, + {0x42d88000}, {0x42d8a000}, {0x42d8c000}, {0x42d8e000}, + {0x42d90000}, {0x42d92000}, {0x42d94000}, {0x42d96000}, + {0x42d98000}, {0x42d9a000}, {0x42d9c000}, {0x42d9e000}, + {0x42da0000}, {0x42da2000}, {0x42da4000}, {0x42da6000}, + {0x42da8000}, {0x42daa000}, {0x42dac000}, {0x42dae000}, + {0x42db0000}, {0x42db2000}, {0x42db4000}, {0x42db6000}, + {0x42db8000}, {0x42dba000}, {0x42dbc000}, {0x42dbe000}, + {0x42dc0000}, {0x42dc2000}, {0x42dc4000}, {0x42dc6000}, + {0x42dc8000}, {0x42dca000}, {0x42dcc000}, {0x42dce000}, + {0x42dd0000}, {0x42dd2000}, {0x42dd4000}, {0x42dd6000}, + {0x42dd8000}, {0x42dda000}, {0x42ddc000}, {0x42dde000}, + {0x42de0000}, {0x42de2000}, {0x42de4000}, {0x42de6000}, + {0x42de8000}, {0x42dea000}, {0x42dec000}, {0x42dee000}, + {0x42df0000}, {0x42df2000}, {0x42df4000}, {0x42df6000}, + {0x42df8000}, {0x42dfa000}, {0x42dfc000}, {0x42dfe000}, + {0x42e00000}, {0x42e02000}, {0x42e04000}, {0x42e06000}, + {0x42e08000}, {0x42e0a000}, {0x42e0c000}, {0x42e0e000}, + {0x42e10000}, {0x42e12000}, {0x42e14000}, {0x42e16000}, + {0x42e18000}, {0x42e1a000}, {0x42e1c000}, {0x42e1e000}, + {0x42e20000}, {0x42e22000}, {0x42e24000}, {0x42e26000}, + {0x42e28000}, {0x42e2a000}, {0x42e2c000}, {0x42e2e000}, + {0x42e30000}, {0x42e32000}, {0x42e34000}, {0x42e36000}, + {0x42e38000}, {0x42e3a000}, {0x42e3c000}, {0x42e3e000}, + {0x42e40000}, {0x42e42000}, {0x42e44000}, {0x42e46000}, + {0x42e48000}, {0x42e4a000}, {0x42e4c000}, {0x42e4e000}, + {0x42e50000}, {0x42e52000}, {0x42e54000}, {0x42e56000}, + {0x42e58000}, {0x42e5a000}, {0x42e5c000}, {0x42e5e000}, + {0x42e60000}, {0x42e62000}, {0x42e64000}, {0x42e66000}, + {0x42e68000}, {0x42e6a000}, {0x42e6c000}, {0x42e6e000}, + {0x42e70000}, {0x42e72000}, {0x42e74000}, {0x42e76000}, + {0x42e78000}, {0x42e7a000}, {0x42e7c000}, {0x42e7e000}, + {0x42e80000}, {0x42e82000}, {0x42e84000}, {0x42e86000}, + {0x42e88000}, {0x42e8a000}, {0x42e8c000}, {0x42e8e000}, + {0x42e90000}, {0x42e92000}, {0x42e94000}, {0x42e96000}, + {0x42e98000}, {0x42e9a000}, {0x42e9c000}, {0x42e9e000}, + {0x42ea0000}, {0x42ea2000}, {0x42ea4000}, {0x42ea6000}, + {0x42ea8000}, {0x42eaa000}, {0x42eac000}, {0x42eae000}, + {0x42eb0000}, {0x42eb2000}, {0x42eb4000}, {0x42eb6000}, + {0x42eb8000}, {0x42eba000}, {0x42ebc000}, {0x42ebe000}, + {0x42ec0000}, {0x42ec2000}, {0x42ec4000}, {0x42ec6000}, + {0x42ec8000}, {0x42eca000}, {0x42ecc000}, {0x42ece000}, + {0x42ed0000}, {0x42ed2000}, {0x42ed4000}, {0x42ed6000}, + {0x42ed8000}, {0x42eda000}, {0x42edc000}, {0x42ede000}, + {0x42ee0000}, {0x42ee2000}, {0x42ee4000}, {0x42ee6000}, + {0x42ee8000}, {0x42eea000}, {0x42eec000}, {0x42eee000}, + {0x42ef0000}, {0x42ef2000}, {0x42ef4000}, {0x42ef6000}, + {0x42ef8000}, {0x42efa000}, {0x42efc000}, {0x42efe000}, + {0x42f00000}, {0x42f02000}, {0x42f04000}, {0x42f06000}, + {0x42f08000}, {0x42f0a000}, {0x42f0c000}, {0x42f0e000}, + {0x42f10000}, {0x42f12000}, {0x42f14000}, {0x42f16000}, + {0x42f18000}, {0x42f1a000}, {0x42f1c000}, {0x42f1e000}, + {0x42f20000}, {0x42f22000}, {0x42f24000}, {0x42f26000}, + {0x42f28000}, {0x42f2a000}, {0x42f2c000}, {0x42f2e000}, + {0x42f30000}, {0x42f32000}, {0x42f34000}, {0x42f36000}, + {0x42f38000}, {0x42f3a000}, {0x42f3c000}, {0x42f3e000}, + {0x42f40000}, {0x42f42000}, {0x42f44000}, {0x42f46000}, + {0x42f48000}, {0x42f4a000}, {0x42f4c000}, {0x42f4e000}, + {0x42f50000}, {0x42f52000}, {0x42f54000}, {0x42f56000}, + {0x42f58000}, {0x42f5a000}, {0x42f5c000}, {0x42f5e000}, + {0x42f60000}, {0x42f62000}, {0x42f64000}, {0x42f66000}, + {0x42f68000}, {0x42f6a000}, {0x42f6c000}, {0x42f6e000}, + {0x42f70000}, {0x42f72000}, {0x42f74000}, {0x42f76000}, + {0x42f78000}, {0x42f7a000}, {0x42f7c000}, {0x42f7e000}, + {0x42f80000}, {0x42f82000}, {0x42f84000}, {0x42f86000}, + {0x42f88000}, {0x42f8a000}, {0x42f8c000}, {0x42f8e000}, + {0x42f90000}, {0x42f92000}, {0x42f94000}, {0x42f96000}, + {0x42f98000}, {0x42f9a000}, {0x42f9c000}, {0x42f9e000}, + {0x42fa0000}, {0x42fa2000}, {0x42fa4000}, {0x42fa6000}, + {0x42fa8000}, {0x42faa000}, {0x42fac000}, {0x42fae000}, + {0x42fb0000}, {0x42fb2000}, {0x42fb4000}, {0x42fb6000}, + {0x42fb8000}, {0x42fba000}, {0x42fbc000}, {0x42fbe000}, + {0x42fc0000}, {0x42fc2000}, {0x42fc4000}, {0x42fc6000}, + {0x42fc8000}, {0x42fca000}, {0x42fcc000}, {0x42fce000}, + {0x42fd0000}, {0x42fd2000}, {0x42fd4000}, {0x42fd6000}, + {0x42fd8000}, {0x42fda000}, {0x42fdc000}, {0x42fde000}, + {0x42fe0000}, {0x42fe2000}, {0x42fe4000}, {0x42fe6000}, + {0x42fe8000}, {0x42fea000}, {0x42fec000}, {0x42fee000}, + {0x42ff0000}, {0x42ff2000}, {0x42ff4000}, {0x42ff6000}, + {0x42ff8000}, {0x42ffa000}, {0x42ffc000}, {0x42ffe000}, + {0x43000000}, {0x43002000}, {0x43004000}, {0x43006000}, + {0x43008000}, {0x4300a000}, {0x4300c000}, {0x4300e000}, + {0x43010000}, {0x43012000}, {0x43014000}, {0x43016000}, + {0x43018000}, {0x4301a000}, {0x4301c000}, {0x4301e000}, + {0x43020000}, {0x43022000}, {0x43024000}, {0x43026000}, + {0x43028000}, {0x4302a000}, {0x4302c000}, {0x4302e000}, + {0x43030000}, {0x43032000}, {0x43034000}, {0x43036000}, + {0x43038000}, {0x4303a000}, {0x4303c000}, {0x4303e000}, + {0x43040000}, {0x43042000}, {0x43044000}, {0x43046000}, + {0x43048000}, {0x4304a000}, {0x4304c000}, {0x4304e000}, + {0x43050000}, {0x43052000}, {0x43054000}, {0x43056000}, + {0x43058000}, {0x4305a000}, {0x4305c000}, {0x4305e000}, + {0x43060000}, {0x43062000}, {0x43064000}, {0x43066000}, + {0x43068000}, {0x4306a000}, {0x4306c000}, {0x4306e000}, + {0x43070000}, {0x43072000}, {0x43074000}, {0x43076000}, + {0x43078000}, {0x4307a000}, {0x4307c000}, {0x4307e000}, + {0x43080000}, {0x43082000}, {0x43084000}, {0x43086000}, + {0x43088000}, {0x4308a000}, {0x4308c000}, {0x4308e000}, + {0x43090000}, {0x43092000}, {0x43094000}, {0x43096000}, + {0x43098000}, {0x4309a000}, {0x4309c000}, {0x4309e000}, + {0x430a0000}, {0x430a2000}, {0x430a4000}, {0x430a6000}, + {0x430a8000}, {0x430aa000}, {0x430ac000}, {0x430ae000}, + {0x430b0000}, {0x430b2000}, {0x430b4000}, {0x430b6000}, + {0x430b8000}, {0x430ba000}, {0x430bc000}, {0x430be000}, + {0x430c0000}, {0x430c2000}, {0x430c4000}, {0x430c6000}, + {0x430c8000}, {0x430ca000}, {0x430cc000}, {0x430ce000}, + {0x430d0000}, {0x430d2000}, {0x430d4000}, {0x430d6000}, + {0x430d8000}, {0x430da000}, {0x430dc000}, {0x430de000}, + {0x430e0000}, {0x430e2000}, {0x430e4000}, {0x430e6000}, + {0x430e8000}, {0x430ea000}, {0x430ec000}, {0x430ee000}, + {0x430f0000}, {0x430f2000}, {0x430f4000}, {0x430f6000}, + {0x430f8000}, {0x430fa000}, {0x430fc000}, {0x430fe000}, + {0x43100000}, {0x43102000}, {0x43104000}, {0x43106000}, + {0x43108000}, {0x4310a000}, {0x4310c000}, {0x4310e000}, + {0x43110000}, {0x43112000}, {0x43114000}, {0x43116000}, + {0x43118000}, {0x4311a000}, {0x4311c000}, {0x4311e000}, + {0x43120000}, {0x43122000}, {0x43124000}, {0x43126000}, + {0x43128000}, {0x4312a000}, {0x4312c000}, {0x4312e000}, + {0x43130000}, {0x43132000}, {0x43134000}, {0x43136000}, + {0x43138000}, {0x4313a000}, {0x4313c000}, {0x4313e000}, + {0x43140000}, {0x43142000}, {0x43144000}, {0x43146000}, + {0x43148000}, {0x4314a000}, {0x4314c000}, {0x4314e000}, + {0x43150000}, {0x43152000}, {0x43154000}, {0x43156000}, + {0x43158000}, {0x4315a000}, {0x4315c000}, {0x4315e000}, + {0x43160000}, {0x43162000}, {0x43164000}, {0x43166000}, + {0x43168000}, {0x4316a000}, {0x4316c000}, {0x4316e000}, + {0x43170000}, {0x43172000}, {0x43174000}, {0x43176000}, + {0x43178000}, {0x4317a000}, {0x4317c000}, {0x4317e000}, + {0x43180000}, {0x43182000}, {0x43184000}, {0x43186000}, + {0x43188000}, {0x4318a000}, {0x4318c000}, {0x4318e000}, + {0x43190000}, {0x43192000}, {0x43194000}, {0x43196000}, + {0x43198000}, {0x4319a000}, {0x4319c000}, {0x4319e000}, + {0x431a0000}, {0x431a2000}, {0x431a4000}, {0x431a6000}, + {0x431a8000}, {0x431aa000}, {0x431ac000}, {0x431ae000}, + {0x431b0000}, {0x431b2000}, {0x431b4000}, {0x431b6000}, + {0x431b8000}, {0x431ba000}, {0x431bc000}, {0x431be000}, + {0x431c0000}, {0x431c2000}, {0x431c4000}, {0x431c6000}, + {0x431c8000}, {0x431ca000}, {0x431cc000}, {0x431ce000}, + {0x431d0000}, {0x431d2000}, {0x431d4000}, {0x431d6000}, + {0x431d8000}, {0x431da000}, {0x431dc000}, {0x431de000}, + {0x431e0000}, {0x431e2000}, {0x431e4000}, {0x431e6000}, + {0x431e8000}, {0x431ea000}, {0x431ec000}, {0x431ee000}, + {0x431f0000}, {0x431f2000}, {0x431f4000}, {0x431f6000}, + {0x431f8000}, {0x431fa000}, {0x431fc000}, {0x431fe000}, + {0x43200000}, {0x43202000}, {0x43204000}, {0x43206000}, + {0x43208000}, {0x4320a000}, {0x4320c000}, {0x4320e000}, + {0x43210000}, {0x43212000}, {0x43214000}, {0x43216000}, + {0x43218000}, {0x4321a000}, {0x4321c000}, {0x4321e000}, + {0x43220000}, {0x43222000}, {0x43224000}, {0x43226000}, + {0x43228000}, {0x4322a000}, {0x4322c000}, {0x4322e000}, + {0x43230000}, {0x43232000}, {0x43234000}, {0x43236000}, + {0x43238000}, {0x4323a000}, {0x4323c000}, {0x4323e000}, + {0x43240000}, {0x43242000}, {0x43244000}, {0x43246000}, + {0x43248000}, {0x4324a000}, {0x4324c000}, {0x4324e000}, + {0x43250000}, {0x43252000}, {0x43254000}, {0x43256000}, + {0x43258000}, {0x4325a000}, {0x4325c000}, {0x4325e000}, + {0x43260000}, {0x43262000}, {0x43264000}, {0x43266000}, + {0x43268000}, {0x4326a000}, {0x4326c000}, {0x4326e000}, + {0x43270000}, {0x43272000}, {0x43274000}, {0x43276000}, + {0x43278000}, {0x4327a000}, {0x4327c000}, {0x4327e000}, + {0x43280000}, {0x43282000}, {0x43284000}, {0x43286000}, + {0x43288000}, {0x4328a000}, {0x4328c000}, {0x4328e000}, + {0x43290000}, {0x43292000}, {0x43294000}, {0x43296000}, + {0x43298000}, {0x4329a000}, {0x4329c000}, {0x4329e000}, + {0x432a0000}, {0x432a2000}, {0x432a4000}, {0x432a6000}, + {0x432a8000}, {0x432aa000}, {0x432ac000}, {0x432ae000}, + {0x432b0000}, {0x432b2000}, {0x432b4000}, {0x432b6000}, + {0x432b8000}, {0x432ba000}, {0x432bc000}, {0x432be000}, + {0x432c0000}, {0x432c2000}, {0x432c4000}, {0x432c6000}, + {0x432c8000}, {0x432ca000}, {0x432cc000}, {0x432ce000}, + {0x432d0000}, {0x432d2000}, {0x432d4000}, {0x432d6000}, + {0x432d8000}, {0x432da000}, {0x432dc000}, {0x432de000}, + {0x432e0000}, {0x432e2000}, {0x432e4000}, {0x432e6000}, + {0x432e8000}, {0x432ea000}, {0x432ec000}, {0x432ee000}, + {0x432f0000}, {0x432f2000}, {0x432f4000}, {0x432f6000}, + {0x432f8000}, {0x432fa000}, {0x432fc000}, {0x432fe000}, + {0x43300000}, {0x43302000}, {0x43304000}, {0x43306000}, + {0x43308000}, {0x4330a000}, {0x4330c000}, {0x4330e000}, + {0x43310000}, {0x43312000}, {0x43314000}, {0x43316000}, + {0x43318000}, {0x4331a000}, {0x4331c000}, {0x4331e000}, + {0x43320000}, {0x43322000}, {0x43324000}, {0x43326000}, + {0x43328000}, {0x4332a000}, {0x4332c000}, {0x4332e000}, + {0x43330000}, {0x43332000}, {0x43334000}, {0x43336000}, + {0x43338000}, {0x4333a000}, {0x4333c000}, {0x4333e000}, + {0x43340000}, {0x43342000}, {0x43344000}, {0x43346000}, + {0x43348000}, {0x4334a000}, {0x4334c000}, {0x4334e000}, + {0x43350000}, {0x43352000}, {0x43354000}, {0x43356000}, + {0x43358000}, {0x4335a000}, {0x4335c000}, {0x4335e000}, + {0x43360000}, {0x43362000}, {0x43364000}, {0x43366000}, + {0x43368000}, {0x4336a000}, {0x4336c000}, {0x4336e000}, + {0x43370000}, {0x43372000}, {0x43374000}, {0x43376000}, + {0x43378000}, {0x4337a000}, {0x4337c000}, {0x4337e000}, + {0x43380000}, {0x43382000}, {0x43384000}, {0x43386000}, + {0x43388000}, {0x4338a000}, {0x4338c000}, {0x4338e000}, + {0x43390000}, {0x43392000}, {0x43394000}, {0x43396000}, + {0x43398000}, {0x4339a000}, {0x4339c000}, {0x4339e000}, + {0x433a0000}, {0x433a2000}, {0x433a4000}, {0x433a6000}, + {0x433a8000}, {0x433aa000}, {0x433ac000}, {0x433ae000}, + {0x433b0000}, {0x433b2000}, {0x433b4000}, {0x433b6000}, + {0x433b8000}, {0x433ba000}, {0x433bc000}, {0x433be000}, + {0x433c0000}, {0x433c2000}, {0x433c4000}, {0x433c6000}, + {0x433c8000}, {0x433ca000}, {0x433cc000}, {0x433ce000}, + {0x433d0000}, {0x433d2000}, {0x433d4000}, {0x433d6000}, + {0x433d8000}, {0x433da000}, {0x433dc000}, {0x433de000}, + {0x433e0000}, {0x433e2000}, {0x433e4000}, {0x433e6000}, + {0x433e8000}, {0x433ea000}, {0x433ec000}, {0x433ee000}, + {0x433f0000}, {0x433f2000}, {0x433f4000}, {0x433f6000}, + {0x433f8000}, {0x433fa000}, {0x433fc000}, {0x433fe000}, + {0x43400000}, {0x43402000}, {0x43404000}, {0x43406000}, + {0x43408000}, {0x4340a000}, {0x4340c000}, {0x4340e000}, + {0x43410000}, {0x43412000}, {0x43414000}, {0x43416000}, + {0x43418000}, {0x4341a000}, {0x4341c000}, {0x4341e000}, + {0x43420000}, {0x43422000}, {0x43424000}, {0x43426000}, + {0x43428000}, {0x4342a000}, {0x4342c000}, {0x4342e000}, + {0x43430000}, {0x43432000}, {0x43434000}, {0x43436000}, + {0x43438000}, {0x4343a000}, {0x4343c000}, {0x4343e000}, + {0x43440000}, {0x43442000}, {0x43444000}, {0x43446000}, + {0x43448000}, {0x4344a000}, {0x4344c000}, {0x4344e000}, + {0x43450000}, {0x43452000}, {0x43454000}, {0x43456000}, + {0x43458000}, {0x4345a000}, {0x4345c000}, {0x4345e000}, + {0x43460000}, {0x43462000}, {0x43464000}, {0x43466000}, + {0x43468000}, {0x4346a000}, {0x4346c000}, {0x4346e000}, + {0x43470000}, {0x43472000}, {0x43474000}, {0x43476000}, + {0x43478000}, {0x4347a000}, {0x4347c000}, {0x4347e000}, + {0x43480000}, {0x43482000}, {0x43484000}, {0x43486000}, + {0x43488000}, {0x4348a000}, {0x4348c000}, {0x4348e000}, + {0x43490000}, {0x43492000}, {0x43494000}, {0x43496000}, + {0x43498000}, {0x4349a000}, {0x4349c000}, {0x4349e000}, + {0x434a0000}, {0x434a2000}, {0x434a4000}, {0x434a6000}, + {0x434a8000}, {0x434aa000}, {0x434ac000}, {0x434ae000}, + {0x434b0000}, {0x434b2000}, {0x434b4000}, {0x434b6000}, + {0x434b8000}, {0x434ba000}, {0x434bc000}, {0x434be000}, + {0x434c0000}, {0x434c2000}, {0x434c4000}, {0x434c6000}, + {0x434c8000}, {0x434ca000}, {0x434cc000}, {0x434ce000}, + {0x434d0000}, {0x434d2000}, {0x434d4000}, {0x434d6000}, + {0x434d8000}, {0x434da000}, {0x434dc000}, {0x434de000}, + {0x434e0000}, {0x434e2000}, {0x434e4000}, {0x434e6000}, + {0x434e8000}, {0x434ea000}, {0x434ec000}, {0x434ee000}, + {0x434f0000}, {0x434f2000}, {0x434f4000}, {0x434f6000}, + {0x434f8000}, {0x434fa000}, {0x434fc000}, {0x434fe000}, + {0x43500000}, {0x43502000}, {0x43504000}, {0x43506000}, + {0x43508000}, {0x4350a000}, {0x4350c000}, {0x4350e000}, + {0x43510000}, {0x43512000}, {0x43514000}, {0x43516000}, + {0x43518000}, {0x4351a000}, {0x4351c000}, {0x4351e000}, + {0x43520000}, {0x43522000}, {0x43524000}, {0x43526000}, + {0x43528000}, {0x4352a000}, {0x4352c000}, {0x4352e000}, + {0x43530000}, {0x43532000}, {0x43534000}, {0x43536000}, + {0x43538000}, {0x4353a000}, {0x4353c000}, {0x4353e000}, + {0x43540000}, {0x43542000}, {0x43544000}, {0x43546000}, + {0x43548000}, {0x4354a000}, {0x4354c000}, {0x4354e000}, + {0x43550000}, {0x43552000}, {0x43554000}, {0x43556000}, + {0x43558000}, {0x4355a000}, {0x4355c000}, {0x4355e000}, + {0x43560000}, {0x43562000}, {0x43564000}, {0x43566000}, + {0x43568000}, {0x4356a000}, {0x4356c000}, {0x4356e000}, + {0x43570000}, {0x43572000}, {0x43574000}, {0x43576000}, + {0x43578000}, {0x4357a000}, {0x4357c000}, {0x4357e000}, + {0x43580000}, {0x43582000}, {0x43584000}, {0x43586000}, + {0x43588000}, {0x4358a000}, {0x4358c000}, {0x4358e000}, + {0x43590000}, {0x43592000}, {0x43594000}, {0x43596000}, + {0x43598000}, {0x4359a000}, {0x4359c000}, {0x4359e000}, + {0x435a0000}, {0x435a2000}, {0x435a4000}, {0x435a6000}, + {0x435a8000}, {0x435aa000}, {0x435ac000}, {0x435ae000}, + {0x435b0000}, {0x435b2000}, {0x435b4000}, {0x435b6000}, + {0x435b8000}, {0x435ba000}, {0x435bc000}, {0x435be000}, + {0x435c0000}, {0x435c2000}, {0x435c4000}, {0x435c6000}, + {0x435c8000}, {0x435ca000}, {0x435cc000}, {0x435ce000}, + {0x435d0000}, {0x435d2000}, {0x435d4000}, {0x435d6000}, + {0x435d8000}, {0x435da000}, {0x435dc000}, {0x435de000}, + {0x435e0000}, {0x435e2000}, {0x435e4000}, {0x435e6000}, + {0x435e8000}, {0x435ea000}, {0x435ec000}, {0x435ee000}, + {0x435f0000}, {0x435f2000}, {0x435f4000}, {0x435f6000}, + {0x435f8000}, {0x435fa000}, {0x435fc000}, {0x435fe000}, + {0x43600000}, {0x43602000}, {0x43604000}, {0x43606000}, + {0x43608000}, {0x4360a000}, {0x4360c000}, {0x4360e000}, + {0x43610000}, {0x43612000}, {0x43614000}, {0x43616000}, + {0x43618000}, {0x4361a000}, {0x4361c000}, {0x4361e000}, + {0x43620000}, {0x43622000}, {0x43624000}, {0x43626000}, + {0x43628000}, {0x4362a000}, {0x4362c000}, {0x4362e000}, + {0x43630000}, {0x43632000}, {0x43634000}, {0x43636000}, + {0x43638000}, {0x4363a000}, {0x4363c000}, {0x4363e000}, + {0x43640000}, {0x43642000}, {0x43644000}, {0x43646000}, + {0x43648000}, {0x4364a000}, {0x4364c000}, {0x4364e000}, + {0x43650000}, {0x43652000}, {0x43654000}, {0x43656000}, + {0x43658000}, {0x4365a000}, {0x4365c000}, {0x4365e000}, + {0x43660000}, {0x43662000}, {0x43664000}, {0x43666000}, + {0x43668000}, {0x4366a000}, {0x4366c000}, {0x4366e000}, + {0x43670000}, {0x43672000}, {0x43674000}, {0x43676000}, + {0x43678000}, {0x4367a000}, {0x4367c000}, {0x4367e000}, + {0x43680000}, {0x43682000}, {0x43684000}, {0x43686000}, + {0x43688000}, {0x4368a000}, {0x4368c000}, {0x4368e000}, + {0x43690000}, {0x43692000}, {0x43694000}, {0x43696000}, + {0x43698000}, {0x4369a000}, {0x4369c000}, {0x4369e000}, + {0x436a0000}, {0x436a2000}, {0x436a4000}, {0x436a6000}, + {0x436a8000}, {0x436aa000}, {0x436ac000}, {0x436ae000}, + {0x436b0000}, {0x436b2000}, {0x436b4000}, {0x436b6000}, + {0x436b8000}, {0x436ba000}, {0x436bc000}, {0x436be000}, + {0x436c0000}, {0x436c2000}, {0x436c4000}, {0x436c6000}, + {0x436c8000}, {0x436ca000}, {0x436cc000}, {0x436ce000}, + {0x436d0000}, {0x436d2000}, {0x436d4000}, {0x436d6000}, + {0x436d8000}, {0x436da000}, {0x436dc000}, {0x436de000}, + {0x436e0000}, {0x436e2000}, {0x436e4000}, {0x436e6000}, + {0x436e8000}, {0x436ea000}, {0x436ec000}, {0x436ee000}, + {0x436f0000}, {0x436f2000}, {0x436f4000}, {0x436f6000}, + {0x436f8000}, {0x436fa000}, {0x436fc000}, {0x436fe000}, + {0x43700000}, {0x43702000}, {0x43704000}, {0x43706000}, + {0x43708000}, {0x4370a000}, {0x4370c000}, {0x4370e000}, + {0x43710000}, {0x43712000}, {0x43714000}, {0x43716000}, + {0x43718000}, {0x4371a000}, {0x4371c000}, {0x4371e000}, + {0x43720000}, {0x43722000}, {0x43724000}, {0x43726000}, + {0x43728000}, {0x4372a000}, {0x4372c000}, {0x4372e000}, + {0x43730000}, {0x43732000}, {0x43734000}, {0x43736000}, + {0x43738000}, {0x4373a000}, {0x4373c000}, {0x4373e000}, + {0x43740000}, {0x43742000}, {0x43744000}, {0x43746000}, + {0x43748000}, {0x4374a000}, {0x4374c000}, {0x4374e000}, + {0x43750000}, {0x43752000}, {0x43754000}, {0x43756000}, + {0x43758000}, {0x4375a000}, {0x4375c000}, {0x4375e000}, + {0x43760000}, {0x43762000}, {0x43764000}, {0x43766000}, + {0x43768000}, {0x4376a000}, {0x4376c000}, {0x4376e000}, + {0x43770000}, {0x43772000}, {0x43774000}, {0x43776000}, + {0x43778000}, {0x4377a000}, {0x4377c000}, {0x4377e000}, + {0x43780000}, {0x43782000}, {0x43784000}, {0x43786000}, + {0x43788000}, {0x4378a000}, {0x4378c000}, {0x4378e000}, + {0x43790000}, {0x43792000}, {0x43794000}, {0x43796000}, + {0x43798000}, {0x4379a000}, {0x4379c000}, {0x4379e000}, + {0x437a0000}, {0x437a2000}, {0x437a4000}, {0x437a6000}, + {0x437a8000}, {0x437aa000}, {0x437ac000}, {0x437ae000}, + {0x437b0000}, {0x437b2000}, {0x437b4000}, {0x437b6000}, + {0x437b8000}, {0x437ba000}, {0x437bc000}, {0x437be000}, + {0x437c0000}, {0x437c2000}, {0x437c4000}, {0x437c6000}, + {0x437c8000}, {0x437ca000}, {0x437cc000}, {0x437ce000}, + {0x437d0000}, {0x437d2000}, {0x437d4000}, {0x437d6000}, + {0x437d8000}, {0x437da000}, {0x437dc000}, {0x437de000}, + {0x437e0000}, {0x437e2000}, {0x437e4000}, {0x437e6000}, + {0x437e8000}, {0x437ea000}, {0x437ec000}, {0x437ee000}, + {0x437f0000}, {0x437f2000}, {0x437f4000}, {0x437f6000}, + {0x437f8000}, {0x437fa000}, {0x437fc000}, {0x437fe000}, + {0x43800000}, {0x43802000}, {0x43804000}, {0x43806000}, + {0x43808000}, {0x4380a000}, {0x4380c000}, {0x4380e000}, + {0x43810000}, {0x43812000}, {0x43814000}, {0x43816000}, + {0x43818000}, {0x4381a000}, {0x4381c000}, {0x4381e000}, + {0x43820000}, {0x43822000}, {0x43824000}, {0x43826000}, + {0x43828000}, {0x4382a000}, {0x4382c000}, {0x4382e000}, + {0x43830000}, {0x43832000}, {0x43834000}, {0x43836000}, + {0x43838000}, {0x4383a000}, {0x4383c000}, {0x4383e000}, + {0x43840000}, {0x43842000}, {0x43844000}, {0x43846000}, + {0x43848000}, {0x4384a000}, {0x4384c000}, {0x4384e000}, + {0x43850000}, {0x43852000}, {0x43854000}, {0x43856000}, + {0x43858000}, {0x4385a000}, {0x4385c000}, {0x4385e000}, + {0x43860000}, {0x43862000}, {0x43864000}, {0x43866000}, + {0x43868000}, {0x4386a000}, {0x4386c000}, {0x4386e000}, + {0x43870000}, {0x43872000}, {0x43874000}, {0x43876000}, + {0x43878000}, {0x4387a000}, {0x4387c000}, {0x4387e000}, + {0x43880000}, {0x43882000}, {0x43884000}, {0x43886000}, + {0x43888000}, {0x4388a000}, {0x4388c000}, {0x4388e000}, + {0x43890000}, {0x43892000}, {0x43894000}, {0x43896000}, + {0x43898000}, {0x4389a000}, {0x4389c000}, {0x4389e000}, + {0x438a0000}, {0x438a2000}, {0x438a4000}, {0x438a6000}, + {0x438a8000}, {0x438aa000}, {0x438ac000}, {0x438ae000}, + {0x438b0000}, {0x438b2000}, {0x438b4000}, {0x438b6000}, + {0x438b8000}, {0x438ba000}, {0x438bc000}, {0x438be000}, + {0x438c0000}, {0x438c2000}, {0x438c4000}, {0x438c6000}, + {0x438c8000}, {0x438ca000}, {0x438cc000}, {0x438ce000}, + {0x438d0000}, {0x438d2000}, {0x438d4000}, {0x438d6000}, + {0x438d8000}, {0x438da000}, {0x438dc000}, {0x438de000}, + {0x438e0000}, {0x438e2000}, {0x438e4000}, {0x438e6000}, + {0x438e8000}, {0x438ea000}, {0x438ec000}, {0x438ee000}, + {0x438f0000}, {0x438f2000}, {0x438f4000}, {0x438f6000}, + {0x438f8000}, {0x438fa000}, {0x438fc000}, {0x438fe000}, + {0x43900000}, {0x43902000}, {0x43904000}, {0x43906000}, + {0x43908000}, {0x4390a000}, {0x4390c000}, {0x4390e000}, + {0x43910000}, {0x43912000}, {0x43914000}, {0x43916000}, + {0x43918000}, {0x4391a000}, {0x4391c000}, {0x4391e000}, + {0x43920000}, {0x43922000}, {0x43924000}, {0x43926000}, + {0x43928000}, {0x4392a000}, {0x4392c000}, {0x4392e000}, + {0x43930000}, {0x43932000}, {0x43934000}, {0x43936000}, + {0x43938000}, {0x4393a000}, {0x4393c000}, {0x4393e000}, + {0x43940000}, {0x43942000}, {0x43944000}, {0x43946000}, + {0x43948000}, {0x4394a000}, {0x4394c000}, {0x4394e000}, + {0x43950000}, {0x43952000}, {0x43954000}, {0x43956000}, + {0x43958000}, {0x4395a000}, {0x4395c000}, {0x4395e000}, + {0x43960000}, {0x43962000}, {0x43964000}, {0x43966000}, + {0x43968000}, {0x4396a000}, {0x4396c000}, {0x4396e000}, + {0x43970000}, {0x43972000}, {0x43974000}, {0x43976000}, + {0x43978000}, {0x4397a000}, {0x4397c000}, {0x4397e000}, + {0x43980000}, {0x43982000}, {0x43984000}, {0x43986000}, + {0x43988000}, {0x4398a000}, {0x4398c000}, {0x4398e000}, + {0x43990000}, {0x43992000}, {0x43994000}, {0x43996000}, + {0x43998000}, {0x4399a000}, {0x4399c000}, {0x4399e000}, + {0x439a0000}, {0x439a2000}, {0x439a4000}, {0x439a6000}, + {0x439a8000}, {0x439aa000}, {0x439ac000}, {0x439ae000}, + {0x439b0000}, {0x439b2000}, {0x439b4000}, {0x439b6000}, + {0x439b8000}, {0x439ba000}, {0x439bc000}, {0x439be000}, + {0x439c0000}, {0x439c2000}, {0x439c4000}, {0x439c6000}, + {0x439c8000}, {0x439ca000}, {0x439cc000}, {0x439ce000}, + {0x439d0000}, {0x439d2000}, {0x439d4000}, {0x439d6000}, + {0x439d8000}, {0x439da000}, {0x439dc000}, {0x439de000}, + {0x439e0000}, {0x439e2000}, {0x439e4000}, {0x439e6000}, + {0x439e8000}, {0x439ea000}, {0x439ec000}, {0x439ee000}, + {0x439f0000}, {0x439f2000}, {0x439f4000}, {0x439f6000}, + {0x439f8000}, {0x439fa000}, {0x439fc000}, {0x439fe000}, + {0x43a00000}, {0x43a02000}, {0x43a04000}, {0x43a06000}, + {0x43a08000}, {0x43a0a000}, {0x43a0c000}, {0x43a0e000}, + {0x43a10000}, {0x43a12000}, {0x43a14000}, {0x43a16000}, + {0x43a18000}, {0x43a1a000}, {0x43a1c000}, {0x43a1e000}, + {0x43a20000}, {0x43a22000}, {0x43a24000}, {0x43a26000}, + {0x43a28000}, {0x43a2a000}, {0x43a2c000}, {0x43a2e000}, + {0x43a30000}, {0x43a32000}, {0x43a34000}, {0x43a36000}, + {0x43a38000}, {0x43a3a000}, {0x43a3c000}, {0x43a3e000}, + {0x43a40000}, {0x43a42000}, {0x43a44000}, {0x43a46000}, + {0x43a48000}, {0x43a4a000}, {0x43a4c000}, {0x43a4e000}, + {0x43a50000}, {0x43a52000}, {0x43a54000}, {0x43a56000}, + {0x43a58000}, {0x43a5a000}, {0x43a5c000}, {0x43a5e000}, + {0x43a60000}, {0x43a62000}, {0x43a64000}, {0x43a66000}, + {0x43a68000}, {0x43a6a000}, {0x43a6c000}, {0x43a6e000}, + {0x43a70000}, {0x43a72000}, {0x43a74000}, {0x43a76000}, + {0x43a78000}, {0x43a7a000}, {0x43a7c000}, {0x43a7e000}, + {0x43a80000}, {0x43a82000}, {0x43a84000}, {0x43a86000}, + {0x43a88000}, {0x43a8a000}, {0x43a8c000}, {0x43a8e000}, + {0x43a90000}, {0x43a92000}, {0x43a94000}, {0x43a96000}, + {0x43a98000}, {0x43a9a000}, {0x43a9c000}, {0x43a9e000}, + {0x43aa0000}, {0x43aa2000}, {0x43aa4000}, {0x43aa6000}, + {0x43aa8000}, {0x43aaa000}, {0x43aac000}, {0x43aae000}, + {0x43ab0000}, {0x43ab2000}, {0x43ab4000}, {0x43ab6000}, + {0x43ab8000}, {0x43aba000}, {0x43abc000}, {0x43abe000}, + {0x43ac0000}, {0x43ac2000}, {0x43ac4000}, {0x43ac6000}, + {0x43ac8000}, {0x43aca000}, {0x43acc000}, {0x43ace000}, + {0x43ad0000}, {0x43ad2000}, {0x43ad4000}, {0x43ad6000}, + {0x43ad8000}, {0x43ada000}, {0x43adc000}, {0x43ade000}, + {0x43ae0000}, {0x43ae2000}, {0x43ae4000}, {0x43ae6000}, + {0x43ae8000}, {0x43aea000}, {0x43aec000}, {0x43aee000}, + {0x43af0000}, {0x43af2000}, {0x43af4000}, {0x43af6000}, + {0x43af8000}, {0x43afa000}, {0x43afc000}, {0x43afe000}, + {0x43b00000}, {0x43b02000}, {0x43b04000}, {0x43b06000}, + {0x43b08000}, {0x43b0a000}, {0x43b0c000}, {0x43b0e000}, + {0x43b10000}, {0x43b12000}, {0x43b14000}, {0x43b16000}, + {0x43b18000}, {0x43b1a000}, {0x43b1c000}, {0x43b1e000}, + {0x43b20000}, {0x43b22000}, {0x43b24000}, {0x43b26000}, + {0x43b28000}, {0x43b2a000}, {0x43b2c000}, {0x43b2e000}, + {0x43b30000}, {0x43b32000}, {0x43b34000}, {0x43b36000}, + {0x43b38000}, {0x43b3a000}, {0x43b3c000}, {0x43b3e000}, + {0x43b40000}, {0x43b42000}, {0x43b44000}, {0x43b46000}, + {0x43b48000}, {0x43b4a000}, {0x43b4c000}, {0x43b4e000}, + {0x43b50000}, {0x43b52000}, {0x43b54000}, {0x43b56000}, + {0x43b58000}, {0x43b5a000}, {0x43b5c000}, {0x43b5e000}, + {0x43b60000}, {0x43b62000}, {0x43b64000}, {0x43b66000}, + {0x43b68000}, {0x43b6a000}, {0x43b6c000}, {0x43b6e000}, + {0x43b70000}, {0x43b72000}, {0x43b74000}, {0x43b76000}, + {0x43b78000}, {0x43b7a000}, {0x43b7c000}, {0x43b7e000}, + {0x43b80000}, {0x43b82000}, {0x43b84000}, {0x43b86000}, + {0x43b88000}, {0x43b8a000}, {0x43b8c000}, {0x43b8e000}, + {0x43b90000}, {0x43b92000}, {0x43b94000}, {0x43b96000}, + {0x43b98000}, {0x43b9a000}, {0x43b9c000}, {0x43b9e000}, + {0x43ba0000}, {0x43ba2000}, {0x43ba4000}, {0x43ba6000}, + {0x43ba8000}, {0x43baa000}, {0x43bac000}, {0x43bae000}, + {0x43bb0000}, {0x43bb2000}, {0x43bb4000}, {0x43bb6000}, + {0x43bb8000}, {0x43bba000}, {0x43bbc000}, {0x43bbe000}, + {0x43bc0000}, {0x43bc2000}, {0x43bc4000}, {0x43bc6000}, + {0x43bc8000}, {0x43bca000}, {0x43bcc000}, {0x43bce000}, + {0x43bd0000}, {0x43bd2000}, {0x43bd4000}, {0x43bd6000}, + {0x43bd8000}, {0x43bda000}, {0x43bdc000}, {0x43bde000}, + {0x43be0000}, {0x43be2000}, {0x43be4000}, {0x43be6000}, + {0x43be8000}, {0x43bea000}, {0x43bec000}, {0x43bee000}, + {0x43bf0000}, {0x43bf2000}, {0x43bf4000}, {0x43bf6000}, + {0x43bf8000}, {0x43bfa000}, {0x43bfc000}, {0x43bfe000}, + {0x43c00000}, {0x43c02000}, {0x43c04000}, {0x43c06000}, + {0x43c08000}, {0x43c0a000}, {0x43c0c000}, {0x43c0e000}, + {0x43c10000}, {0x43c12000}, {0x43c14000}, {0x43c16000}, + {0x43c18000}, {0x43c1a000}, {0x43c1c000}, {0x43c1e000}, + {0x43c20000}, {0x43c22000}, {0x43c24000}, {0x43c26000}, + {0x43c28000}, {0x43c2a000}, {0x43c2c000}, {0x43c2e000}, + {0x43c30000}, {0x43c32000}, {0x43c34000}, {0x43c36000}, + {0x43c38000}, {0x43c3a000}, {0x43c3c000}, {0x43c3e000}, + {0x43c40000}, {0x43c42000}, {0x43c44000}, {0x43c46000}, + {0x43c48000}, {0x43c4a000}, {0x43c4c000}, {0x43c4e000}, + {0x43c50000}, {0x43c52000}, {0x43c54000}, {0x43c56000}, + {0x43c58000}, {0x43c5a000}, {0x43c5c000}, {0x43c5e000}, + {0x43c60000}, {0x43c62000}, {0x43c64000}, {0x43c66000}, + {0x43c68000}, {0x43c6a000}, {0x43c6c000}, {0x43c6e000}, + {0x43c70000}, {0x43c72000}, {0x43c74000}, {0x43c76000}, + {0x43c78000}, {0x43c7a000}, {0x43c7c000}, {0x43c7e000}, + {0x43c80000}, {0x43c82000}, {0x43c84000}, {0x43c86000}, + {0x43c88000}, {0x43c8a000}, {0x43c8c000}, {0x43c8e000}, + {0x43c90000}, {0x43c92000}, {0x43c94000}, {0x43c96000}, + {0x43c98000}, {0x43c9a000}, {0x43c9c000}, {0x43c9e000}, + {0x43ca0000}, {0x43ca2000}, {0x43ca4000}, {0x43ca6000}, + {0x43ca8000}, {0x43caa000}, {0x43cac000}, {0x43cae000}, + {0x43cb0000}, {0x43cb2000}, {0x43cb4000}, {0x43cb6000}, + {0x43cb8000}, {0x43cba000}, {0x43cbc000}, {0x43cbe000}, + {0x43cc0000}, {0x43cc2000}, {0x43cc4000}, {0x43cc6000}, + {0x43cc8000}, {0x43cca000}, {0x43ccc000}, {0x43cce000}, + {0x43cd0000}, {0x43cd2000}, {0x43cd4000}, {0x43cd6000}, + {0x43cd8000}, {0x43cda000}, {0x43cdc000}, {0x43cde000}, + {0x43ce0000}, {0x43ce2000}, {0x43ce4000}, {0x43ce6000}, + {0x43ce8000}, {0x43cea000}, {0x43cec000}, {0x43cee000}, + {0x43cf0000}, {0x43cf2000}, {0x43cf4000}, {0x43cf6000}, + {0x43cf8000}, {0x43cfa000}, {0x43cfc000}, {0x43cfe000}, + {0x43d00000}, {0x43d02000}, {0x43d04000}, {0x43d06000}, + {0x43d08000}, {0x43d0a000}, {0x43d0c000}, {0x43d0e000}, + {0x43d10000}, {0x43d12000}, {0x43d14000}, {0x43d16000}, + {0x43d18000}, {0x43d1a000}, {0x43d1c000}, {0x43d1e000}, + {0x43d20000}, {0x43d22000}, {0x43d24000}, {0x43d26000}, + {0x43d28000}, {0x43d2a000}, {0x43d2c000}, {0x43d2e000}, + {0x43d30000}, {0x43d32000}, {0x43d34000}, {0x43d36000}, + {0x43d38000}, {0x43d3a000}, {0x43d3c000}, {0x43d3e000}, + {0x43d40000}, {0x43d42000}, {0x43d44000}, {0x43d46000}, + {0x43d48000}, {0x43d4a000}, {0x43d4c000}, {0x43d4e000}, + {0x43d50000}, {0x43d52000}, {0x43d54000}, {0x43d56000}, + {0x43d58000}, {0x43d5a000}, {0x43d5c000}, {0x43d5e000}, + {0x43d60000}, {0x43d62000}, {0x43d64000}, {0x43d66000}, + {0x43d68000}, {0x43d6a000}, {0x43d6c000}, {0x43d6e000}, + {0x43d70000}, {0x43d72000}, {0x43d74000}, {0x43d76000}, + {0x43d78000}, {0x43d7a000}, {0x43d7c000}, {0x43d7e000}, + {0x43d80000}, {0x43d82000}, {0x43d84000}, {0x43d86000}, + {0x43d88000}, {0x43d8a000}, {0x43d8c000}, {0x43d8e000}, + {0x43d90000}, {0x43d92000}, {0x43d94000}, {0x43d96000}, + {0x43d98000}, {0x43d9a000}, {0x43d9c000}, {0x43d9e000}, + {0x43da0000}, {0x43da2000}, {0x43da4000}, {0x43da6000}, + {0x43da8000}, {0x43daa000}, {0x43dac000}, {0x43dae000}, + {0x43db0000}, {0x43db2000}, {0x43db4000}, {0x43db6000}, + {0x43db8000}, {0x43dba000}, {0x43dbc000}, {0x43dbe000}, + {0x43dc0000}, {0x43dc2000}, {0x43dc4000}, {0x43dc6000}, + {0x43dc8000}, {0x43dca000}, {0x43dcc000}, {0x43dce000}, + {0x43dd0000}, {0x43dd2000}, {0x43dd4000}, {0x43dd6000}, + {0x43dd8000}, {0x43dda000}, {0x43ddc000}, {0x43dde000}, + {0x43de0000}, {0x43de2000}, {0x43de4000}, {0x43de6000}, + {0x43de8000}, {0x43dea000}, {0x43dec000}, {0x43dee000}, + {0x43df0000}, {0x43df2000}, {0x43df4000}, {0x43df6000}, + {0x43df8000}, {0x43dfa000}, {0x43dfc000}, {0x43dfe000}, + {0x43e00000}, {0x43e02000}, {0x43e04000}, {0x43e06000}, + {0x43e08000}, {0x43e0a000}, {0x43e0c000}, {0x43e0e000}, + {0x43e10000}, {0x43e12000}, {0x43e14000}, {0x43e16000}, + {0x43e18000}, {0x43e1a000}, {0x43e1c000}, {0x43e1e000}, + {0x43e20000}, {0x43e22000}, {0x43e24000}, {0x43e26000}, + {0x43e28000}, {0x43e2a000}, {0x43e2c000}, {0x43e2e000}, + {0x43e30000}, {0x43e32000}, {0x43e34000}, {0x43e36000}, + {0x43e38000}, {0x43e3a000}, {0x43e3c000}, {0x43e3e000}, + {0x43e40000}, {0x43e42000}, {0x43e44000}, {0x43e46000}, + {0x43e48000}, {0x43e4a000}, {0x43e4c000}, {0x43e4e000}, + {0x43e50000}, {0x43e52000}, {0x43e54000}, {0x43e56000}, + {0x43e58000}, {0x43e5a000}, {0x43e5c000}, {0x43e5e000}, + {0x43e60000}, {0x43e62000}, {0x43e64000}, {0x43e66000}, + {0x43e68000}, {0x43e6a000}, {0x43e6c000}, {0x43e6e000}, + {0x43e70000}, {0x43e72000}, {0x43e74000}, {0x43e76000}, + {0x43e78000}, {0x43e7a000}, {0x43e7c000}, {0x43e7e000}, + {0x43e80000}, {0x43e82000}, {0x43e84000}, {0x43e86000}, + {0x43e88000}, {0x43e8a000}, {0x43e8c000}, {0x43e8e000}, + {0x43e90000}, {0x43e92000}, {0x43e94000}, {0x43e96000}, + {0x43e98000}, {0x43e9a000}, {0x43e9c000}, {0x43e9e000}, + {0x43ea0000}, {0x43ea2000}, {0x43ea4000}, {0x43ea6000}, + {0x43ea8000}, {0x43eaa000}, {0x43eac000}, {0x43eae000}, + {0x43eb0000}, {0x43eb2000}, {0x43eb4000}, {0x43eb6000}, + {0x43eb8000}, {0x43eba000}, {0x43ebc000}, {0x43ebe000}, + {0x43ec0000}, {0x43ec2000}, {0x43ec4000}, {0x43ec6000}, + {0x43ec8000}, {0x43eca000}, {0x43ecc000}, {0x43ece000}, + {0x43ed0000}, {0x43ed2000}, {0x43ed4000}, {0x43ed6000}, + {0x43ed8000}, {0x43eda000}, {0x43edc000}, {0x43ede000}, + {0x43ee0000}, {0x43ee2000}, {0x43ee4000}, {0x43ee6000}, + {0x43ee8000}, {0x43eea000}, {0x43eec000}, {0x43eee000}, + {0x43ef0000}, {0x43ef2000}, {0x43ef4000}, {0x43ef6000}, + {0x43ef8000}, {0x43efa000}, {0x43efc000}, {0x43efe000}, + {0x43f00000}, {0x43f02000}, {0x43f04000}, {0x43f06000}, + {0x43f08000}, {0x43f0a000}, {0x43f0c000}, {0x43f0e000}, + {0x43f10000}, {0x43f12000}, {0x43f14000}, {0x43f16000}, + {0x43f18000}, {0x43f1a000}, {0x43f1c000}, {0x43f1e000}, + {0x43f20000}, {0x43f22000}, {0x43f24000}, {0x43f26000}, + {0x43f28000}, {0x43f2a000}, {0x43f2c000}, {0x43f2e000}, + {0x43f30000}, {0x43f32000}, {0x43f34000}, {0x43f36000}, + {0x43f38000}, {0x43f3a000}, {0x43f3c000}, {0x43f3e000}, + {0x43f40000}, {0x43f42000}, {0x43f44000}, {0x43f46000}, + {0x43f48000}, {0x43f4a000}, {0x43f4c000}, {0x43f4e000}, + {0x43f50000}, {0x43f52000}, {0x43f54000}, {0x43f56000}, + {0x43f58000}, {0x43f5a000}, {0x43f5c000}, {0x43f5e000}, + {0x43f60000}, {0x43f62000}, {0x43f64000}, {0x43f66000}, + {0x43f68000}, {0x43f6a000}, {0x43f6c000}, {0x43f6e000}, + {0x43f70000}, {0x43f72000}, {0x43f74000}, {0x43f76000}, + {0x43f78000}, {0x43f7a000}, {0x43f7c000}, {0x43f7e000}, + {0x43f80000}, {0x43f82000}, {0x43f84000}, {0x43f86000}, + {0x43f88000}, {0x43f8a000}, {0x43f8c000}, {0x43f8e000}, + {0x43f90000}, {0x43f92000}, {0x43f94000}, {0x43f96000}, + {0x43f98000}, {0x43f9a000}, {0x43f9c000}, {0x43f9e000}, + {0x43fa0000}, {0x43fa2000}, {0x43fa4000}, {0x43fa6000}, + {0x43fa8000}, {0x43faa000}, {0x43fac000}, {0x43fae000}, + {0x43fb0000}, {0x43fb2000}, {0x43fb4000}, {0x43fb6000}, + {0x43fb8000}, {0x43fba000}, {0x43fbc000}, {0x43fbe000}, + {0x43fc0000}, {0x43fc2000}, {0x43fc4000}, {0x43fc6000}, + {0x43fc8000}, {0x43fca000}, {0x43fcc000}, {0x43fce000}, + {0x43fd0000}, {0x43fd2000}, {0x43fd4000}, {0x43fd6000}, + {0x43fd8000}, {0x43fda000}, {0x43fdc000}, {0x43fde000}, + {0x43fe0000}, {0x43fe2000}, {0x43fe4000}, {0x43fe6000}, + {0x43fe8000}, {0x43fea000}, {0x43fec000}, {0x43fee000}, + {0x43ff0000}, {0x43ff2000}, {0x43ff4000}, {0x43ff6000}, + {0x43ff8000}, {0x43ffa000}, {0x43ffc000}, {0x43ffe000}, + {0x44000000}, {0x44002000}, {0x44004000}, {0x44006000}, + {0x44008000}, {0x4400a000}, {0x4400c000}, {0x4400e000}, + {0x44010000}, {0x44012000}, {0x44014000}, {0x44016000}, + {0x44018000}, {0x4401a000}, {0x4401c000}, {0x4401e000}, + {0x44020000}, {0x44022000}, {0x44024000}, {0x44026000}, + {0x44028000}, {0x4402a000}, {0x4402c000}, {0x4402e000}, + {0x44030000}, {0x44032000}, {0x44034000}, {0x44036000}, + {0x44038000}, {0x4403a000}, {0x4403c000}, {0x4403e000}, + {0x44040000}, {0x44042000}, {0x44044000}, {0x44046000}, + {0x44048000}, {0x4404a000}, {0x4404c000}, {0x4404e000}, + {0x44050000}, {0x44052000}, {0x44054000}, {0x44056000}, + {0x44058000}, {0x4405a000}, {0x4405c000}, {0x4405e000}, + {0x44060000}, {0x44062000}, {0x44064000}, {0x44066000}, + {0x44068000}, {0x4406a000}, {0x4406c000}, {0x4406e000}, + {0x44070000}, {0x44072000}, {0x44074000}, {0x44076000}, + {0x44078000}, {0x4407a000}, {0x4407c000}, {0x4407e000}, + {0x44080000}, {0x44082000}, {0x44084000}, {0x44086000}, + {0x44088000}, {0x4408a000}, {0x4408c000}, {0x4408e000}, + {0x44090000}, {0x44092000}, {0x44094000}, {0x44096000}, + {0x44098000}, {0x4409a000}, {0x4409c000}, {0x4409e000}, + {0x440a0000}, {0x440a2000}, {0x440a4000}, {0x440a6000}, + {0x440a8000}, {0x440aa000}, {0x440ac000}, {0x440ae000}, + {0x440b0000}, {0x440b2000}, {0x440b4000}, {0x440b6000}, + {0x440b8000}, {0x440ba000}, {0x440bc000}, {0x440be000}, + {0x440c0000}, {0x440c2000}, {0x440c4000}, {0x440c6000}, + {0x440c8000}, {0x440ca000}, {0x440cc000}, {0x440ce000}, + {0x440d0000}, {0x440d2000}, {0x440d4000}, {0x440d6000}, + {0x440d8000}, {0x440da000}, {0x440dc000}, {0x440de000}, + {0x440e0000}, {0x440e2000}, {0x440e4000}, {0x440e6000}, + {0x440e8000}, {0x440ea000}, {0x440ec000}, {0x440ee000}, + {0x440f0000}, {0x440f2000}, {0x440f4000}, {0x440f6000}, + {0x440f8000}, {0x440fa000}, {0x440fc000}, {0x440fe000}, + {0x44100000}, {0x44102000}, {0x44104000}, {0x44106000}, + {0x44108000}, {0x4410a000}, {0x4410c000}, {0x4410e000}, + {0x44110000}, {0x44112000}, {0x44114000}, {0x44116000}, + {0x44118000}, {0x4411a000}, {0x4411c000}, {0x4411e000}, + {0x44120000}, {0x44122000}, {0x44124000}, {0x44126000}, + {0x44128000}, {0x4412a000}, {0x4412c000}, {0x4412e000}, + {0x44130000}, {0x44132000}, {0x44134000}, {0x44136000}, + {0x44138000}, {0x4413a000}, {0x4413c000}, {0x4413e000}, + {0x44140000}, {0x44142000}, {0x44144000}, {0x44146000}, + {0x44148000}, {0x4414a000}, {0x4414c000}, {0x4414e000}, + {0x44150000}, {0x44152000}, {0x44154000}, {0x44156000}, + {0x44158000}, {0x4415a000}, {0x4415c000}, {0x4415e000}, + {0x44160000}, {0x44162000}, {0x44164000}, {0x44166000}, + {0x44168000}, {0x4416a000}, {0x4416c000}, {0x4416e000}, + {0x44170000}, {0x44172000}, {0x44174000}, {0x44176000}, + {0x44178000}, {0x4417a000}, {0x4417c000}, {0x4417e000}, + {0x44180000}, {0x44182000}, {0x44184000}, {0x44186000}, + {0x44188000}, {0x4418a000}, {0x4418c000}, {0x4418e000}, + {0x44190000}, {0x44192000}, {0x44194000}, {0x44196000}, + {0x44198000}, {0x4419a000}, {0x4419c000}, {0x4419e000}, + {0x441a0000}, {0x441a2000}, {0x441a4000}, {0x441a6000}, + {0x441a8000}, {0x441aa000}, {0x441ac000}, {0x441ae000}, + {0x441b0000}, {0x441b2000}, {0x441b4000}, {0x441b6000}, + {0x441b8000}, {0x441ba000}, {0x441bc000}, {0x441be000}, + {0x441c0000}, {0x441c2000}, {0x441c4000}, {0x441c6000}, + {0x441c8000}, {0x441ca000}, {0x441cc000}, {0x441ce000}, + {0x441d0000}, {0x441d2000}, {0x441d4000}, {0x441d6000}, + {0x441d8000}, {0x441da000}, {0x441dc000}, {0x441de000}, + {0x441e0000}, {0x441e2000}, {0x441e4000}, {0x441e6000}, + {0x441e8000}, {0x441ea000}, {0x441ec000}, {0x441ee000}, + {0x441f0000}, {0x441f2000}, {0x441f4000}, {0x441f6000}, + {0x441f8000}, {0x441fa000}, {0x441fc000}, {0x441fe000}, + {0x44200000}, {0x44202000}, {0x44204000}, {0x44206000}, + {0x44208000}, {0x4420a000}, {0x4420c000}, {0x4420e000}, + {0x44210000}, {0x44212000}, {0x44214000}, {0x44216000}, + {0x44218000}, {0x4421a000}, {0x4421c000}, {0x4421e000}, + {0x44220000}, {0x44222000}, {0x44224000}, {0x44226000}, + {0x44228000}, {0x4422a000}, {0x4422c000}, {0x4422e000}, + {0x44230000}, {0x44232000}, {0x44234000}, {0x44236000}, + {0x44238000}, {0x4423a000}, {0x4423c000}, {0x4423e000}, + {0x44240000}, {0x44242000}, {0x44244000}, {0x44246000}, + {0x44248000}, {0x4424a000}, {0x4424c000}, {0x4424e000}, + {0x44250000}, {0x44252000}, {0x44254000}, {0x44256000}, + {0x44258000}, {0x4425a000}, {0x4425c000}, {0x4425e000}, + {0x44260000}, {0x44262000}, {0x44264000}, {0x44266000}, + {0x44268000}, {0x4426a000}, {0x4426c000}, {0x4426e000}, + {0x44270000}, {0x44272000}, {0x44274000}, {0x44276000}, + {0x44278000}, {0x4427a000}, {0x4427c000}, {0x4427e000}, + {0x44280000}, {0x44282000}, {0x44284000}, {0x44286000}, + {0x44288000}, {0x4428a000}, {0x4428c000}, {0x4428e000}, + {0x44290000}, {0x44292000}, {0x44294000}, {0x44296000}, + {0x44298000}, {0x4429a000}, {0x4429c000}, {0x4429e000}, + {0x442a0000}, {0x442a2000}, {0x442a4000}, {0x442a6000}, + {0x442a8000}, {0x442aa000}, {0x442ac000}, {0x442ae000}, + {0x442b0000}, {0x442b2000}, {0x442b4000}, {0x442b6000}, + {0x442b8000}, {0x442ba000}, {0x442bc000}, {0x442be000}, + {0x442c0000}, {0x442c2000}, {0x442c4000}, {0x442c6000}, + {0x442c8000}, {0x442ca000}, {0x442cc000}, {0x442ce000}, + {0x442d0000}, {0x442d2000}, {0x442d4000}, {0x442d6000}, + {0x442d8000}, {0x442da000}, {0x442dc000}, {0x442de000}, + {0x442e0000}, {0x442e2000}, {0x442e4000}, {0x442e6000}, + {0x442e8000}, {0x442ea000}, {0x442ec000}, {0x442ee000}, + {0x442f0000}, {0x442f2000}, {0x442f4000}, {0x442f6000}, + {0x442f8000}, {0x442fa000}, {0x442fc000}, {0x442fe000}, + {0x44300000}, {0x44302000}, {0x44304000}, {0x44306000}, + {0x44308000}, {0x4430a000}, {0x4430c000}, {0x4430e000}, + {0x44310000}, {0x44312000}, {0x44314000}, {0x44316000}, + {0x44318000}, {0x4431a000}, {0x4431c000}, {0x4431e000}, + {0x44320000}, {0x44322000}, {0x44324000}, {0x44326000}, + {0x44328000}, {0x4432a000}, {0x4432c000}, {0x4432e000}, + {0x44330000}, {0x44332000}, {0x44334000}, {0x44336000}, + {0x44338000}, {0x4433a000}, {0x4433c000}, {0x4433e000}, + {0x44340000}, {0x44342000}, {0x44344000}, {0x44346000}, + {0x44348000}, {0x4434a000}, {0x4434c000}, {0x4434e000}, + {0x44350000}, {0x44352000}, {0x44354000}, {0x44356000}, + {0x44358000}, {0x4435a000}, {0x4435c000}, {0x4435e000}, + {0x44360000}, {0x44362000}, {0x44364000}, {0x44366000}, + {0x44368000}, {0x4436a000}, {0x4436c000}, {0x4436e000}, + {0x44370000}, {0x44372000}, {0x44374000}, {0x44376000}, + {0x44378000}, {0x4437a000}, {0x4437c000}, {0x4437e000}, + {0x44380000}, {0x44382000}, {0x44384000}, {0x44386000}, + {0x44388000}, {0x4438a000}, {0x4438c000}, {0x4438e000}, + {0x44390000}, {0x44392000}, {0x44394000}, {0x44396000}, + {0x44398000}, {0x4439a000}, {0x4439c000}, {0x4439e000}, + {0x443a0000}, {0x443a2000}, {0x443a4000}, {0x443a6000}, + {0x443a8000}, {0x443aa000}, {0x443ac000}, {0x443ae000}, + {0x443b0000}, {0x443b2000}, {0x443b4000}, {0x443b6000}, + {0x443b8000}, {0x443ba000}, {0x443bc000}, {0x443be000}, + {0x443c0000}, {0x443c2000}, {0x443c4000}, {0x443c6000}, + {0x443c8000}, {0x443ca000}, {0x443cc000}, {0x443ce000}, + {0x443d0000}, {0x443d2000}, {0x443d4000}, {0x443d6000}, + {0x443d8000}, {0x443da000}, {0x443dc000}, {0x443de000}, + {0x443e0000}, {0x443e2000}, {0x443e4000}, {0x443e6000}, + {0x443e8000}, {0x443ea000}, {0x443ec000}, {0x443ee000}, + {0x443f0000}, {0x443f2000}, {0x443f4000}, {0x443f6000}, + {0x443f8000}, {0x443fa000}, {0x443fc000}, {0x443fe000}, + {0x44400000}, {0x44402000}, {0x44404000}, {0x44406000}, + {0x44408000}, {0x4440a000}, {0x4440c000}, {0x4440e000}, + {0x44410000}, {0x44412000}, {0x44414000}, {0x44416000}, + {0x44418000}, {0x4441a000}, {0x4441c000}, {0x4441e000}, + {0x44420000}, {0x44422000}, {0x44424000}, {0x44426000}, + {0x44428000}, {0x4442a000}, {0x4442c000}, {0x4442e000}, + {0x44430000}, {0x44432000}, {0x44434000}, {0x44436000}, + {0x44438000}, {0x4443a000}, {0x4443c000}, {0x4443e000}, + {0x44440000}, {0x44442000}, {0x44444000}, {0x44446000}, + {0x44448000}, {0x4444a000}, {0x4444c000}, {0x4444e000}, + {0x44450000}, {0x44452000}, {0x44454000}, {0x44456000}, + {0x44458000}, {0x4445a000}, {0x4445c000}, {0x4445e000}, + {0x44460000}, {0x44462000}, {0x44464000}, {0x44466000}, + {0x44468000}, {0x4446a000}, {0x4446c000}, {0x4446e000}, + {0x44470000}, {0x44472000}, {0x44474000}, {0x44476000}, + {0x44478000}, {0x4447a000}, {0x4447c000}, {0x4447e000}, + {0x44480000}, {0x44482000}, {0x44484000}, {0x44486000}, + {0x44488000}, {0x4448a000}, {0x4448c000}, {0x4448e000}, + {0x44490000}, {0x44492000}, {0x44494000}, {0x44496000}, + {0x44498000}, {0x4449a000}, {0x4449c000}, {0x4449e000}, + {0x444a0000}, {0x444a2000}, {0x444a4000}, {0x444a6000}, + {0x444a8000}, {0x444aa000}, {0x444ac000}, {0x444ae000}, + {0x444b0000}, {0x444b2000}, {0x444b4000}, {0x444b6000}, + {0x444b8000}, {0x444ba000}, {0x444bc000}, {0x444be000}, + {0x444c0000}, {0x444c2000}, {0x444c4000}, {0x444c6000}, + {0x444c8000}, {0x444ca000}, {0x444cc000}, {0x444ce000}, + {0x444d0000}, {0x444d2000}, {0x444d4000}, {0x444d6000}, + {0x444d8000}, {0x444da000}, {0x444dc000}, {0x444de000}, + {0x444e0000}, {0x444e2000}, {0x444e4000}, {0x444e6000}, + {0x444e8000}, {0x444ea000}, {0x444ec000}, {0x444ee000}, + {0x444f0000}, {0x444f2000}, {0x444f4000}, {0x444f6000}, + {0x444f8000}, {0x444fa000}, {0x444fc000}, {0x444fe000}, + {0x44500000}, {0x44502000}, {0x44504000}, {0x44506000}, + {0x44508000}, {0x4450a000}, {0x4450c000}, {0x4450e000}, + {0x44510000}, {0x44512000}, {0x44514000}, {0x44516000}, + {0x44518000}, {0x4451a000}, {0x4451c000}, {0x4451e000}, + {0x44520000}, {0x44522000}, {0x44524000}, {0x44526000}, + {0x44528000}, {0x4452a000}, {0x4452c000}, {0x4452e000}, + {0x44530000}, {0x44532000}, {0x44534000}, {0x44536000}, + {0x44538000}, {0x4453a000}, {0x4453c000}, {0x4453e000}, + {0x44540000}, {0x44542000}, {0x44544000}, {0x44546000}, + {0x44548000}, {0x4454a000}, {0x4454c000}, {0x4454e000}, + {0x44550000}, {0x44552000}, {0x44554000}, {0x44556000}, + {0x44558000}, {0x4455a000}, {0x4455c000}, {0x4455e000}, + {0x44560000}, {0x44562000}, {0x44564000}, {0x44566000}, + {0x44568000}, {0x4456a000}, {0x4456c000}, {0x4456e000}, + {0x44570000}, {0x44572000}, {0x44574000}, {0x44576000}, + {0x44578000}, {0x4457a000}, {0x4457c000}, {0x4457e000}, + {0x44580000}, {0x44582000}, {0x44584000}, {0x44586000}, + {0x44588000}, {0x4458a000}, {0x4458c000}, {0x4458e000}, + {0x44590000}, {0x44592000}, {0x44594000}, {0x44596000}, + {0x44598000}, {0x4459a000}, {0x4459c000}, {0x4459e000}, + {0x445a0000}, {0x445a2000}, {0x445a4000}, {0x445a6000}, + {0x445a8000}, {0x445aa000}, {0x445ac000}, {0x445ae000}, + {0x445b0000}, {0x445b2000}, {0x445b4000}, {0x445b6000}, + {0x445b8000}, {0x445ba000}, {0x445bc000}, {0x445be000}, + {0x445c0000}, {0x445c2000}, {0x445c4000}, {0x445c6000}, + {0x445c8000}, {0x445ca000}, {0x445cc000}, {0x445ce000}, + {0x445d0000}, {0x445d2000}, {0x445d4000}, {0x445d6000}, + {0x445d8000}, {0x445da000}, {0x445dc000}, {0x445de000}, + {0x445e0000}, {0x445e2000}, {0x445e4000}, {0x445e6000}, + {0x445e8000}, {0x445ea000}, {0x445ec000}, {0x445ee000}, + {0x445f0000}, {0x445f2000}, {0x445f4000}, {0x445f6000}, + {0x445f8000}, {0x445fa000}, {0x445fc000}, {0x445fe000}, + {0x44600000}, {0x44602000}, {0x44604000}, {0x44606000}, + {0x44608000}, {0x4460a000}, {0x4460c000}, {0x4460e000}, + {0x44610000}, {0x44612000}, {0x44614000}, {0x44616000}, + {0x44618000}, {0x4461a000}, {0x4461c000}, {0x4461e000}, + {0x44620000}, {0x44622000}, {0x44624000}, {0x44626000}, + {0x44628000}, {0x4462a000}, {0x4462c000}, {0x4462e000}, + {0x44630000}, {0x44632000}, {0x44634000}, {0x44636000}, + {0x44638000}, {0x4463a000}, {0x4463c000}, {0x4463e000}, + {0x44640000}, {0x44642000}, {0x44644000}, {0x44646000}, + {0x44648000}, {0x4464a000}, {0x4464c000}, {0x4464e000}, + {0x44650000}, {0x44652000}, {0x44654000}, {0x44656000}, + {0x44658000}, {0x4465a000}, {0x4465c000}, {0x4465e000}, + {0x44660000}, {0x44662000}, {0x44664000}, {0x44666000}, + {0x44668000}, {0x4466a000}, {0x4466c000}, {0x4466e000}, + {0x44670000}, {0x44672000}, {0x44674000}, {0x44676000}, + {0x44678000}, {0x4467a000}, {0x4467c000}, {0x4467e000}, + {0x44680000}, {0x44682000}, {0x44684000}, {0x44686000}, + {0x44688000}, {0x4468a000}, {0x4468c000}, {0x4468e000}, + {0x44690000}, {0x44692000}, {0x44694000}, {0x44696000}, + {0x44698000}, {0x4469a000}, {0x4469c000}, {0x4469e000}, + {0x446a0000}, {0x446a2000}, {0x446a4000}, {0x446a6000}, + {0x446a8000}, {0x446aa000}, {0x446ac000}, {0x446ae000}, + {0x446b0000}, {0x446b2000}, {0x446b4000}, {0x446b6000}, + {0x446b8000}, {0x446ba000}, {0x446bc000}, {0x446be000}, + {0x446c0000}, {0x446c2000}, {0x446c4000}, {0x446c6000}, + {0x446c8000}, {0x446ca000}, {0x446cc000}, {0x446ce000}, + {0x446d0000}, {0x446d2000}, {0x446d4000}, {0x446d6000}, + {0x446d8000}, {0x446da000}, {0x446dc000}, {0x446de000}, + {0x446e0000}, {0x446e2000}, {0x446e4000}, {0x446e6000}, + {0x446e8000}, {0x446ea000}, {0x446ec000}, {0x446ee000}, + {0x446f0000}, {0x446f2000}, {0x446f4000}, {0x446f6000}, + {0x446f8000}, {0x446fa000}, {0x446fc000}, {0x446fe000}, + {0x44700000}, {0x44702000}, {0x44704000}, {0x44706000}, + {0x44708000}, {0x4470a000}, {0x4470c000}, {0x4470e000}, + {0x44710000}, {0x44712000}, {0x44714000}, {0x44716000}, + {0x44718000}, {0x4471a000}, {0x4471c000}, {0x4471e000}, + {0x44720000}, {0x44722000}, {0x44724000}, {0x44726000}, + {0x44728000}, {0x4472a000}, {0x4472c000}, {0x4472e000}, + {0x44730000}, {0x44732000}, {0x44734000}, {0x44736000}, + {0x44738000}, {0x4473a000}, {0x4473c000}, {0x4473e000}, + {0x44740000}, {0x44742000}, {0x44744000}, {0x44746000}, + {0x44748000}, {0x4474a000}, {0x4474c000}, {0x4474e000}, + {0x44750000}, {0x44752000}, {0x44754000}, {0x44756000}, + {0x44758000}, {0x4475a000}, {0x4475c000}, {0x4475e000}, + {0x44760000}, {0x44762000}, {0x44764000}, {0x44766000}, + {0x44768000}, {0x4476a000}, {0x4476c000}, {0x4476e000}, + {0x44770000}, {0x44772000}, {0x44774000}, {0x44776000}, + {0x44778000}, {0x4477a000}, {0x4477c000}, {0x4477e000}, + {0x44780000}, {0x44782000}, {0x44784000}, {0x44786000}, + {0x44788000}, {0x4478a000}, {0x4478c000}, {0x4478e000}, + {0x44790000}, {0x44792000}, {0x44794000}, {0x44796000}, + {0x44798000}, {0x4479a000}, {0x4479c000}, {0x4479e000}, + {0x447a0000}, {0x447a2000}, {0x447a4000}, {0x447a6000}, + {0x447a8000}, {0x447aa000}, {0x447ac000}, {0x447ae000}, + {0x447b0000}, {0x447b2000}, {0x447b4000}, {0x447b6000}, + {0x447b8000}, {0x447ba000}, {0x447bc000}, {0x447be000}, + {0x447c0000}, {0x447c2000}, {0x447c4000}, {0x447c6000}, + {0x447c8000}, {0x447ca000}, {0x447cc000}, {0x447ce000}, + {0x447d0000}, {0x447d2000}, {0x447d4000}, {0x447d6000}, + {0x447d8000}, {0x447da000}, {0x447dc000}, {0x447de000}, + {0x447e0000}, {0x447e2000}, {0x447e4000}, {0x447e6000}, + {0x447e8000}, {0x447ea000}, {0x447ec000}, {0x447ee000}, + {0x447f0000}, {0x447f2000}, {0x447f4000}, {0x447f6000}, + {0x447f8000}, {0x447fa000}, {0x447fc000}, {0x447fe000}, + {0x44800000}, {0x44802000}, {0x44804000}, {0x44806000}, + {0x44808000}, {0x4480a000}, {0x4480c000}, {0x4480e000}, + {0x44810000}, {0x44812000}, {0x44814000}, {0x44816000}, + {0x44818000}, {0x4481a000}, {0x4481c000}, {0x4481e000}, + {0x44820000}, {0x44822000}, {0x44824000}, {0x44826000}, + {0x44828000}, {0x4482a000}, {0x4482c000}, {0x4482e000}, + {0x44830000}, {0x44832000}, {0x44834000}, {0x44836000}, + {0x44838000}, {0x4483a000}, {0x4483c000}, {0x4483e000}, + {0x44840000}, {0x44842000}, {0x44844000}, {0x44846000}, + {0x44848000}, {0x4484a000}, {0x4484c000}, {0x4484e000}, + {0x44850000}, {0x44852000}, {0x44854000}, {0x44856000}, + {0x44858000}, {0x4485a000}, {0x4485c000}, {0x4485e000}, + {0x44860000}, {0x44862000}, {0x44864000}, {0x44866000}, + {0x44868000}, {0x4486a000}, {0x4486c000}, {0x4486e000}, + {0x44870000}, {0x44872000}, {0x44874000}, {0x44876000}, + {0x44878000}, {0x4487a000}, {0x4487c000}, {0x4487e000}, + {0x44880000}, {0x44882000}, {0x44884000}, {0x44886000}, + {0x44888000}, {0x4488a000}, {0x4488c000}, {0x4488e000}, + {0x44890000}, {0x44892000}, {0x44894000}, {0x44896000}, + {0x44898000}, {0x4489a000}, {0x4489c000}, {0x4489e000}, + {0x448a0000}, {0x448a2000}, {0x448a4000}, {0x448a6000}, + {0x448a8000}, {0x448aa000}, {0x448ac000}, {0x448ae000}, + {0x448b0000}, {0x448b2000}, {0x448b4000}, {0x448b6000}, + {0x448b8000}, {0x448ba000}, {0x448bc000}, {0x448be000}, + {0x448c0000}, {0x448c2000}, {0x448c4000}, {0x448c6000}, + {0x448c8000}, {0x448ca000}, {0x448cc000}, {0x448ce000}, + {0x448d0000}, {0x448d2000}, {0x448d4000}, {0x448d6000}, + {0x448d8000}, {0x448da000}, {0x448dc000}, {0x448de000}, + {0x448e0000}, {0x448e2000}, {0x448e4000}, {0x448e6000}, + {0x448e8000}, {0x448ea000}, {0x448ec000}, {0x448ee000}, + {0x448f0000}, {0x448f2000}, {0x448f4000}, {0x448f6000}, + {0x448f8000}, {0x448fa000}, {0x448fc000}, {0x448fe000}, + {0x44900000}, {0x44902000}, {0x44904000}, {0x44906000}, + {0x44908000}, {0x4490a000}, {0x4490c000}, {0x4490e000}, + {0x44910000}, {0x44912000}, {0x44914000}, {0x44916000}, + {0x44918000}, {0x4491a000}, {0x4491c000}, {0x4491e000}, + {0x44920000}, {0x44922000}, {0x44924000}, {0x44926000}, + {0x44928000}, {0x4492a000}, {0x4492c000}, {0x4492e000}, + {0x44930000}, {0x44932000}, {0x44934000}, {0x44936000}, + {0x44938000}, {0x4493a000}, {0x4493c000}, {0x4493e000}, + {0x44940000}, {0x44942000}, {0x44944000}, {0x44946000}, + {0x44948000}, {0x4494a000}, {0x4494c000}, {0x4494e000}, + {0x44950000}, {0x44952000}, {0x44954000}, {0x44956000}, + {0x44958000}, {0x4495a000}, {0x4495c000}, {0x4495e000}, + {0x44960000}, {0x44962000}, {0x44964000}, {0x44966000}, + {0x44968000}, {0x4496a000}, {0x4496c000}, {0x4496e000}, + {0x44970000}, {0x44972000}, {0x44974000}, {0x44976000}, + {0x44978000}, {0x4497a000}, {0x4497c000}, {0x4497e000}, + {0x44980000}, {0x44982000}, {0x44984000}, {0x44986000}, + {0x44988000}, {0x4498a000}, {0x4498c000}, {0x4498e000}, + {0x44990000}, {0x44992000}, {0x44994000}, {0x44996000}, + {0x44998000}, {0x4499a000}, {0x4499c000}, {0x4499e000}, + {0x449a0000}, {0x449a2000}, {0x449a4000}, {0x449a6000}, + {0x449a8000}, {0x449aa000}, {0x449ac000}, {0x449ae000}, + {0x449b0000}, {0x449b2000}, {0x449b4000}, {0x449b6000}, + {0x449b8000}, {0x449ba000}, {0x449bc000}, {0x449be000}, + {0x449c0000}, {0x449c2000}, {0x449c4000}, {0x449c6000}, + {0x449c8000}, {0x449ca000}, {0x449cc000}, {0x449ce000}, + {0x449d0000}, {0x449d2000}, {0x449d4000}, {0x449d6000}, + {0x449d8000}, {0x449da000}, {0x449dc000}, {0x449de000}, + {0x449e0000}, {0x449e2000}, {0x449e4000}, {0x449e6000}, + {0x449e8000}, {0x449ea000}, {0x449ec000}, {0x449ee000}, + {0x449f0000}, {0x449f2000}, {0x449f4000}, {0x449f6000}, + {0x449f8000}, {0x449fa000}, {0x449fc000}, {0x449fe000}, + {0x44a00000}, {0x44a02000}, {0x44a04000}, {0x44a06000}, + {0x44a08000}, {0x44a0a000}, {0x44a0c000}, {0x44a0e000}, + {0x44a10000}, {0x44a12000}, {0x44a14000}, {0x44a16000}, + {0x44a18000}, {0x44a1a000}, {0x44a1c000}, {0x44a1e000}, + {0x44a20000}, {0x44a22000}, {0x44a24000}, {0x44a26000}, + {0x44a28000}, {0x44a2a000}, {0x44a2c000}, {0x44a2e000}, + {0x44a30000}, {0x44a32000}, {0x44a34000}, {0x44a36000}, + {0x44a38000}, {0x44a3a000}, {0x44a3c000}, {0x44a3e000}, + {0x44a40000}, {0x44a42000}, {0x44a44000}, {0x44a46000}, + {0x44a48000}, {0x44a4a000}, {0x44a4c000}, {0x44a4e000}, + {0x44a50000}, {0x44a52000}, {0x44a54000}, {0x44a56000}, + {0x44a58000}, {0x44a5a000}, {0x44a5c000}, {0x44a5e000}, + {0x44a60000}, {0x44a62000}, {0x44a64000}, {0x44a66000}, + {0x44a68000}, {0x44a6a000}, {0x44a6c000}, {0x44a6e000}, + {0x44a70000}, {0x44a72000}, {0x44a74000}, {0x44a76000}, + {0x44a78000}, {0x44a7a000}, {0x44a7c000}, {0x44a7e000}, + {0x44a80000}, {0x44a82000}, {0x44a84000}, {0x44a86000}, + {0x44a88000}, {0x44a8a000}, {0x44a8c000}, {0x44a8e000}, + {0x44a90000}, {0x44a92000}, {0x44a94000}, {0x44a96000}, + {0x44a98000}, {0x44a9a000}, {0x44a9c000}, {0x44a9e000}, + {0x44aa0000}, {0x44aa2000}, {0x44aa4000}, {0x44aa6000}, + {0x44aa8000}, {0x44aaa000}, {0x44aac000}, {0x44aae000}, + {0x44ab0000}, {0x44ab2000}, {0x44ab4000}, {0x44ab6000}, + {0x44ab8000}, {0x44aba000}, {0x44abc000}, {0x44abe000}, + {0x44ac0000}, {0x44ac2000}, {0x44ac4000}, {0x44ac6000}, + {0x44ac8000}, {0x44aca000}, {0x44acc000}, {0x44ace000}, + {0x44ad0000}, {0x44ad2000}, {0x44ad4000}, {0x44ad6000}, + {0x44ad8000}, {0x44ada000}, {0x44adc000}, {0x44ade000}, + {0x44ae0000}, {0x44ae2000}, {0x44ae4000}, {0x44ae6000}, + {0x44ae8000}, {0x44aea000}, {0x44aec000}, {0x44aee000}, + {0x44af0000}, {0x44af2000}, {0x44af4000}, {0x44af6000}, + {0x44af8000}, {0x44afa000}, {0x44afc000}, {0x44afe000}, + {0x44b00000}, {0x44b02000}, {0x44b04000}, {0x44b06000}, + {0x44b08000}, {0x44b0a000}, {0x44b0c000}, {0x44b0e000}, + {0x44b10000}, {0x44b12000}, {0x44b14000}, {0x44b16000}, + {0x44b18000}, {0x44b1a000}, {0x44b1c000}, {0x44b1e000}, + {0x44b20000}, {0x44b22000}, {0x44b24000}, {0x44b26000}, + {0x44b28000}, {0x44b2a000}, {0x44b2c000}, {0x44b2e000}, + {0x44b30000}, {0x44b32000}, {0x44b34000}, {0x44b36000}, + {0x44b38000}, {0x44b3a000}, {0x44b3c000}, {0x44b3e000}, + {0x44b40000}, {0x44b42000}, {0x44b44000}, {0x44b46000}, + {0x44b48000}, {0x44b4a000}, {0x44b4c000}, {0x44b4e000}, + {0x44b50000}, {0x44b52000}, {0x44b54000}, {0x44b56000}, + {0x44b58000}, {0x44b5a000}, {0x44b5c000}, {0x44b5e000}, + {0x44b60000}, {0x44b62000}, {0x44b64000}, {0x44b66000}, + {0x44b68000}, {0x44b6a000}, {0x44b6c000}, {0x44b6e000}, + {0x44b70000}, {0x44b72000}, {0x44b74000}, {0x44b76000}, + {0x44b78000}, {0x44b7a000}, {0x44b7c000}, {0x44b7e000}, + {0x44b80000}, {0x44b82000}, {0x44b84000}, {0x44b86000}, + {0x44b88000}, {0x44b8a000}, {0x44b8c000}, {0x44b8e000}, + {0x44b90000}, {0x44b92000}, {0x44b94000}, {0x44b96000}, + {0x44b98000}, {0x44b9a000}, {0x44b9c000}, {0x44b9e000}, + {0x44ba0000}, {0x44ba2000}, {0x44ba4000}, {0x44ba6000}, + {0x44ba8000}, {0x44baa000}, {0x44bac000}, {0x44bae000}, + {0x44bb0000}, {0x44bb2000}, {0x44bb4000}, {0x44bb6000}, + {0x44bb8000}, {0x44bba000}, {0x44bbc000}, {0x44bbe000}, + {0x44bc0000}, {0x44bc2000}, {0x44bc4000}, {0x44bc6000}, + {0x44bc8000}, {0x44bca000}, {0x44bcc000}, {0x44bce000}, + {0x44bd0000}, {0x44bd2000}, {0x44bd4000}, {0x44bd6000}, + {0x44bd8000}, {0x44bda000}, {0x44bdc000}, {0x44bde000}, + {0x44be0000}, {0x44be2000}, {0x44be4000}, {0x44be6000}, + {0x44be8000}, {0x44bea000}, {0x44bec000}, {0x44bee000}, + {0x44bf0000}, {0x44bf2000}, {0x44bf4000}, {0x44bf6000}, + {0x44bf8000}, {0x44bfa000}, {0x44bfc000}, {0x44bfe000}, + {0x44c00000}, {0x44c02000}, {0x44c04000}, {0x44c06000}, + {0x44c08000}, {0x44c0a000}, {0x44c0c000}, {0x44c0e000}, + {0x44c10000}, {0x44c12000}, {0x44c14000}, {0x44c16000}, + {0x44c18000}, {0x44c1a000}, {0x44c1c000}, {0x44c1e000}, + {0x44c20000}, {0x44c22000}, {0x44c24000}, {0x44c26000}, + {0x44c28000}, {0x44c2a000}, {0x44c2c000}, {0x44c2e000}, + {0x44c30000}, {0x44c32000}, {0x44c34000}, {0x44c36000}, + {0x44c38000}, {0x44c3a000}, {0x44c3c000}, {0x44c3e000}, + {0x44c40000}, {0x44c42000}, {0x44c44000}, {0x44c46000}, + {0x44c48000}, {0x44c4a000}, {0x44c4c000}, {0x44c4e000}, + {0x44c50000}, {0x44c52000}, {0x44c54000}, {0x44c56000}, + {0x44c58000}, {0x44c5a000}, {0x44c5c000}, {0x44c5e000}, + {0x44c60000}, {0x44c62000}, {0x44c64000}, {0x44c66000}, + {0x44c68000}, {0x44c6a000}, {0x44c6c000}, {0x44c6e000}, + {0x44c70000}, {0x44c72000}, {0x44c74000}, {0x44c76000}, + {0x44c78000}, {0x44c7a000}, {0x44c7c000}, {0x44c7e000}, + {0x44c80000}, {0x44c82000}, {0x44c84000}, {0x44c86000}, + {0x44c88000}, {0x44c8a000}, {0x44c8c000}, {0x44c8e000}, + {0x44c90000}, {0x44c92000}, {0x44c94000}, {0x44c96000}, + {0x44c98000}, {0x44c9a000}, {0x44c9c000}, {0x44c9e000}, + {0x44ca0000}, {0x44ca2000}, {0x44ca4000}, {0x44ca6000}, + {0x44ca8000}, {0x44caa000}, {0x44cac000}, {0x44cae000}, + {0x44cb0000}, {0x44cb2000}, {0x44cb4000}, {0x44cb6000}, + {0x44cb8000}, {0x44cba000}, {0x44cbc000}, {0x44cbe000}, + {0x44cc0000}, {0x44cc2000}, {0x44cc4000}, {0x44cc6000}, + {0x44cc8000}, {0x44cca000}, {0x44ccc000}, {0x44cce000}, + {0x44cd0000}, {0x44cd2000}, {0x44cd4000}, {0x44cd6000}, + {0x44cd8000}, {0x44cda000}, {0x44cdc000}, {0x44cde000}, + {0x44ce0000}, {0x44ce2000}, {0x44ce4000}, {0x44ce6000}, + {0x44ce8000}, {0x44cea000}, {0x44cec000}, {0x44cee000}, + {0x44cf0000}, {0x44cf2000}, {0x44cf4000}, {0x44cf6000}, + {0x44cf8000}, {0x44cfa000}, {0x44cfc000}, {0x44cfe000}, + {0x44d00000}, {0x44d02000}, {0x44d04000}, {0x44d06000}, + {0x44d08000}, {0x44d0a000}, {0x44d0c000}, {0x44d0e000}, + {0x44d10000}, {0x44d12000}, {0x44d14000}, {0x44d16000}, + {0x44d18000}, {0x44d1a000}, {0x44d1c000}, {0x44d1e000}, + {0x44d20000}, {0x44d22000}, {0x44d24000}, {0x44d26000}, + {0x44d28000}, {0x44d2a000}, {0x44d2c000}, {0x44d2e000}, + {0x44d30000}, {0x44d32000}, {0x44d34000}, {0x44d36000}, + {0x44d38000}, {0x44d3a000}, {0x44d3c000}, {0x44d3e000}, + {0x44d40000}, {0x44d42000}, {0x44d44000}, {0x44d46000}, + {0x44d48000}, {0x44d4a000}, {0x44d4c000}, {0x44d4e000}, + {0x44d50000}, {0x44d52000}, {0x44d54000}, {0x44d56000}, + {0x44d58000}, {0x44d5a000}, {0x44d5c000}, {0x44d5e000}, + {0x44d60000}, {0x44d62000}, {0x44d64000}, {0x44d66000}, + {0x44d68000}, {0x44d6a000}, {0x44d6c000}, {0x44d6e000}, + {0x44d70000}, {0x44d72000}, {0x44d74000}, {0x44d76000}, + {0x44d78000}, {0x44d7a000}, {0x44d7c000}, {0x44d7e000}, + {0x44d80000}, {0x44d82000}, {0x44d84000}, {0x44d86000}, + {0x44d88000}, {0x44d8a000}, {0x44d8c000}, {0x44d8e000}, + {0x44d90000}, {0x44d92000}, {0x44d94000}, {0x44d96000}, + {0x44d98000}, {0x44d9a000}, {0x44d9c000}, {0x44d9e000}, + {0x44da0000}, {0x44da2000}, {0x44da4000}, {0x44da6000}, + {0x44da8000}, {0x44daa000}, {0x44dac000}, {0x44dae000}, + {0x44db0000}, {0x44db2000}, {0x44db4000}, {0x44db6000}, + {0x44db8000}, {0x44dba000}, {0x44dbc000}, {0x44dbe000}, + {0x44dc0000}, {0x44dc2000}, {0x44dc4000}, {0x44dc6000}, + {0x44dc8000}, {0x44dca000}, {0x44dcc000}, {0x44dce000}, + {0x44dd0000}, {0x44dd2000}, {0x44dd4000}, {0x44dd6000}, + {0x44dd8000}, {0x44dda000}, {0x44ddc000}, {0x44dde000}, + {0x44de0000}, {0x44de2000}, {0x44de4000}, {0x44de6000}, + {0x44de8000}, {0x44dea000}, {0x44dec000}, {0x44dee000}, + {0x44df0000}, {0x44df2000}, {0x44df4000}, {0x44df6000}, + {0x44df8000}, {0x44dfa000}, {0x44dfc000}, {0x44dfe000}, + {0x44e00000}, {0x44e02000}, {0x44e04000}, {0x44e06000}, + {0x44e08000}, {0x44e0a000}, {0x44e0c000}, {0x44e0e000}, + {0x44e10000}, {0x44e12000}, {0x44e14000}, {0x44e16000}, + {0x44e18000}, {0x44e1a000}, {0x44e1c000}, {0x44e1e000}, + {0x44e20000}, {0x44e22000}, {0x44e24000}, {0x44e26000}, + {0x44e28000}, {0x44e2a000}, {0x44e2c000}, {0x44e2e000}, + {0x44e30000}, {0x44e32000}, {0x44e34000}, {0x44e36000}, + {0x44e38000}, {0x44e3a000}, {0x44e3c000}, {0x44e3e000}, + {0x44e40000}, {0x44e42000}, {0x44e44000}, {0x44e46000}, + {0x44e48000}, {0x44e4a000}, {0x44e4c000}, {0x44e4e000}, + {0x44e50000}, {0x44e52000}, {0x44e54000}, {0x44e56000}, + {0x44e58000}, {0x44e5a000}, {0x44e5c000}, {0x44e5e000}, + {0x44e60000}, {0x44e62000}, {0x44e64000}, {0x44e66000}, + {0x44e68000}, {0x44e6a000}, {0x44e6c000}, {0x44e6e000}, + {0x44e70000}, {0x44e72000}, {0x44e74000}, {0x44e76000}, + {0x44e78000}, {0x44e7a000}, {0x44e7c000}, {0x44e7e000}, + {0x44e80000}, {0x44e82000}, {0x44e84000}, {0x44e86000}, + {0x44e88000}, {0x44e8a000}, {0x44e8c000}, {0x44e8e000}, + {0x44e90000}, {0x44e92000}, {0x44e94000}, {0x44e96000}, + {0x44e98000}, {0x44e9a000}, {0x44e9c000}, {0x44e9e000}, + {0x44ea0000}, {0x44ea2000}, {0x44ea4000}, {0x44ea6000}, + {0x44ea8000}, {0x44eaa000}, {0x44eac000}, {0x44eae000}, + {0x44eb0000}, {0x44eb2000}, {0x44eb4000}, {0x44eb6000}, + {0x44eb8000}, {0x44eba000}, {0x44ebc000}, {0x44ebe000}, + {0x44ec0000}, {0x44ec2000}, {0x44ec4000}, {0x44ec6000}, + {0x44ec8000}, {0x44eca000}, {0x44ecc000}, {0x44ece000}, + {0x44ed0000}, {0x44ed2000}, {0x44ed4000}, {0x44ed6000}, + {0x44ed8000}, {0x44eda000}, {0x44edc000}, {0x44ede000}, + {0x44ee0000}, {0x44ee2000}, {0x44ee4000}, {0x44ee6000}, + {0x44ee8000}, {0x44eea000}, {0x44eec000}, {0x44eee000}, + {0x44ef0000}, {0x44ef2000}, {0x44ef4000}, {0x44ef6000}, + {0x44ef8000}, {0x44efa000}, {0x44efc000}, {0x44efe000}, + {0x44f00000}, {0x44f02000}, {0x44f04000}, {0x44f06000}, + {0x44f08000}, {0x44f0a000}, {0x44f0c000}, {0x44f0e000}, + {0x44f10000}, {0x44f12000}, {0x44f14000}, {0x44f16000}, + {0x44f18000}, {0x44f1a000}, {0x44f1c000}, {0x44f1e000}, + {0x44f20000}, {0x44f22000}, {0x44f24000}, {0x44f26000}, + {0x44f28000}, {0x44f2a000}, {0x44f2c000}, {0x44f2e000}, + {0x44f30000}, {0x44f32000}, {0x44f34000}, {0x44f36000}, + {0x44f38000}, {0x44f3a000}, {0x44f3c000}, {0x44f3e000}, + {0x44f40000}, {0x44f42000}, {0x44f44000}, {0x44f46000}, + {0x44f48000}, {0x44f4a000}, {0x44f4c000}, {0x44f4e000}, + {0x44f50000}, {0x44f52000}, {0x44f54000}, {0x44f56000}, + {0x44f58000}, {0x44f5a000}, {0x44f5c000}, {0x44f5e000}, + {0x44f60000}, {0x44f62000}, {0x44f64000}, {0x44f66000}, + {0x44f68000}, {0x44f6a000}, {0x44f6c000}, {0x44f6e000}, + {0x44f70000}, {0x44f72000}, {0x44f74000}, {0x44f76000}, + {0x44f78000}, {0x44f7a000}, {0x44f7c000}, {0x44f7e000}, + {0x44f80000}, {0x44f82000}, {0x44f84000}, {0x44f86000}, + {0x44f88000}, {0x44f8a000}, {0x44f8c000}, {0x44f8e000}, + {0x44f90000}, {0x44f92000}, {0x44f94000}, {0x44f96000}, + {0x44f98000}, {0x44f9a000}, {0x44f9c000}, {0x44f9e000}, + {0x44fa0000}, {0x44fa2000}, {0x44fa4000}, {0x44fa6000}, + {0x44fa8000}, {0x44faa000}, {0x44fac000}, {0x44fae000}, + {0x44fb0000}, {0x44fb2000}, {0x44fb4000}, {0x44fb6000}, + {0x44fb8000}, {0x44fba000}, {0x44fbc000}, {0x44fbe000}, + {0x44fc0000}, {0x44fc2000}, {0x44fc4000}, {0x44fc6000}, + {0x44fc8000}, {0x44fca000}, {0x44fcc000}, {0x44fce000}, + {0x44fd0000}, {0x44fd2000}, {0x44fd4000}, {0x44fd6000}, + {0x44fd8000}, {0x44fda000}, {0x44fdc000}, {0x44fde000}, + {0x44fe0000}, {0x44fe2000}, {0x44fe4000}, {0x44fe6000}, + {0x44fe8000}, {0x44fea000}, {0x44fec000}, {0x44fee000}, + {0x44ff0000}, {0x44ff2000}, {0x44ff4000}, {0x44ff6000}, + {0x44ff8000}, {0x44ffa000}, {0x44ffc000}, {0x44ffe000}, + {0x45000000}, {0x45002000}, {0x45004000}, {0x45006000}, + {0x45008000}, {0x4500a000}, {0x4500c000}, {0x4500e000}, + {0x45010000}, {0x45012000}, {0x45014000}, {0x45016000}, + {0x45018000}, {0x4501a000}, {0x4501c000}, {0x4501e000}, + {0x45020000}, {0x45022000}, {0x45024000}, {0x45026000}, + {0x45028000}, {0x4502a000}, {0x4502c000}, {0x4502e000}, + {0x45030000}, {0x45032000}, {0x45034000}, {0x45036000}, + {0x45038000}, {0x4503a000}, {0x4503c000}, {0x4503e000}, + {0x45040000}, {0x45042000}, {0x45044000}, {0x45046000}, + {0x45048000}, {0x4504a000}, {0x4504c000}, {0x4504e000}, + {0x45050000}, {0x45052000}, {0x45054000}, {0x45056000}, + {0x45058000}, {0x4505a000}, {0x4505c000}, {0x4505e000}, + {0x45060000}, {0x45062000}, {0x45064000}, {0x45066000}, + {0x45068000}, {0x4506a000}, {0x4506c000}, {0x4506e000}, + {0x45070000}, {0x45072000}, {0x45074000}, {0x45076000}, + {0x45078000}, {0x4507a000}, {0x4507c000}, {0x4507e000}, + {0x45080000}, {0x45082000}, {0x45084000}, {0x45086000}, + {0x45088000}, {0x4508a000}, {0x4508c000}, {0x4508e000}, + {0x45090000}, {0x45092000}, {0x45094000}, {0x45096000}, + {0x45098000}, {0x4509a000}, {0x4509c000}, {0x4509e000}, + {0x450a0000}, {0x450a2000}, {0x450a4000}, {0x450a6000}, + {0x450a8000}, {0x450aa000}, {0x450ac000}, {0x450ae000}, + {0x450b0000}, {0x450b2000}, {0x450b4000}, {0x450b6000}, + {0x450b8000}, {0x450ba000}, {0x450bc000}, {0x450be000}, + {0x450c0000}, {0x450c2000}, {0x450c4000}, {0x450c6000}, + {0x450c8000}, {0x450ca000}, {0x450cc000}, {0x450ce000}, + {0x450d0000}, {0x450d2000}, {0x450d4000}, {0x450d6000}, + {0x450d8000}, {0x450da000}, {0x450dc000}, {0x450de000}, + {0x450e0000}, {0x450e2000}, {0x450e4000}, {0x450e6000}, + {0x450e8000}, {0x450ea000}, {0x450ec000}, {0x450ee000}, + {0x450f0000}, {0x450f2000}, {0x450f4000}, {0x450f6000}, + {0x450f8000}, {0x450fa000}, {0x450fc000}, {0x450fe000}, + {0x45100000}, {0x45102000}, {0x45104000}, {0x45106000}, + {0x45108000}, {0x4510a000}, {0x4510c000}, {0x4510e000}, + {0x45110000}, {0x45112000}, {0x45114000}, {0x45116000}, + {0x45118000}, {0x4511a000}, {0x4511c000}, {0x4511e000}, + {0x45120000}, {0x45122000}, {0x45124000}, {0x45126000}, + {0x45128000}, {0x4512a000}, {0x4512c000}, {0x4512e000}, + {0x45130000}, {0x45132000}, {0x45134000}, {0x45136000}, + {0x45138000}, {0x4513a000}, {0x4513c000}, {0x4513e000}, + {0x45140000}, {0x45142000}, {0x45144000}, {0x45146000}, + {0x45148000}, {0x4514a000}, {0x4514c000}, {0x4514e000}, + {0x45150000}, {0x45152000}, {0x45154000}, {0x45156000}, + {0x45158000}, {0x4515a000}, {0x4515c000}, {0x4515e000}, + {0x45160000}, {0x45162000}, {0x45164000}, {0x45166000}, + {0x45168000}, {0x4516a000}, {0x4516c000}, {0x4516e000}, + {0x45170000}, {0x45172000}, {0x45174000}, {0x45176000}, + {0x45178000}, {0x4517a000}, {0x4517c000}, {0x4517e000}, + {0x45180000}, {0x45182000}, {0x45184000}, {0x45186000}, + {0x45188000}, {0x4518a000}, {0x4518c000}, {0x4518e000}, + {0x45190000}, {0x45192000}, {0x45194000}, {0x45196000}, + {0x45198000}, {0x4519a000}, {0x4519c000}, {0x4519e000}, + {0x451a0000}, {0x451a2000}, {0x451a4000}, {0x451a6000}, + {0x451a8000}, {0x451aa000}, {0x451ac000}, {0x451ae000}, + {0x451b0000}, {0x451b2000}, {0x451b4000}, {0x451b6000}, + {0x451b8000}, {0x451ba000}, {0x451bc000}, {0x451be000}, + {0x451c0000}, {0x451c2000}, {0x451c4000}, {0x451c6000}, + {0x451c8000}, {0x451ca000}, {0x451cc000}, {0x451ce000}, + {0x451d0000}, {0x451d2000}, {0x451d4000}, {0x451d6000}, + {0x451d8000}, {0x451da000}, {0x451dc000}, {0x451de000}, + {0x451e0000}, {0x451e2000}, {0x451e4000}, {0x451e6000}, + {0x451e8000}, {0x451ea000}, {0x451ec000}, {0x451ee000}, + {0x451f0000}, {0x451f2000}, {0x451f4000}, {0x451f6000}, + {0x451f8000}, {0x451fa000}, {0x451fc000}, {0x451fe000}, + {0x45200000}, {0x45202000}, {0x45204000}, {0x45206000}, + {0x45208000}, {0x4520a000}, {0x4520c000}, {0x4520e000}, + {0x45210000}, {0x45212000}, {0x45214000}, {0x45216000}, + {0x45218000}, {0x4521a000}, {0x4521c000}, {0x4521e000}, + {0x45220000}, {0x45222000}, {0x45224000}, {0x45226000}, + {0x45228000}, {0x4522a000}, {0x4522c000}, {0x4522e000}, + {0x45230000}, {0x45232000}, {0x45234000}, {0x45236000}, + {0x45238000}, {0x4523a000}, {0x4523c000}, {0x4523e000}, + {0x45240000}, {0x45242000}, {0x45244000}, {0x45246000}, + {0x45248000}, {0x4524a000}, {0x4524c000}, {0x4524e000}, + {0x45250000}, {0x45252000}, {0x45254000}, {0x45256000}, + {0x45258000}, {0x4525a000}, {0x4525c000}, {0x4525e000}, + {0x45260000}, {0x45262000}, {0x45264000}, {0x45266000}, + {0x45268000}, {0x4526a000}, {0x4526c000}, {0x4526e000}, + {0x45270000}, {0x45272000}, {0x45274000}, {0x45276000}, + {0x45278000}, {0x4527a000}, {0x4527c000}, {0x4527e000}, + {0x45280000}, {0x45282000}, {0x45284000}, {0x45286000}, + {0x45288000}, {0x4528a000}, {0x4528c000}, {0x4528e000}, + {0x45290000}, {0x45292000}, {0x45294000}, {0x45296000}, + {0x45298000}, {0x4529a000}, {0x4529c000}, {0x4529e000}, + {0x452a0000}, {0x452a2000}, {0x452a4000}, {0x452a6000}, + {0x452a8000}, {0x452aa000}, {0x452ac000}, {0x452ae000}, + {0x452b0000}, {0x452b2000}, {0x452b4000}, {0x452b6000}, + {0x452b8000}, {0x452ba000}, {0x452bc000}, {0x452be000}, + {0x452c0000}, {0x452c2000}, {0x452c4000}, {0x452c6000}, + {0x452c8000}, {0x452ca000}, {0x452cc000}, {0x452ce000}, + {0x452d0000}, {0x452d2000}, {0x452d4000}, {0x452d6000}, + {0x452d8000}, {0x452da000}, {0x452dc000}, {0x452de000}, + {0x452e0000}, {0x452e2000}, {0x452e4000}, {0x452e6000}, + {0x452e8000}, {0x452ea000}, {0x452ec000}, {0x452ee000}, + {0x452f0000}, {0x452f2000}, {0x452f4000}, {0x452f6000}, + {0x452f8000}, {0x452fa000}, {0x452fc000}, {0x452fe000}, + {0x45300000}, {0x45302000}, {0x45304000}, {0x45306000}, + {0x45308000}, {0x4530a000}, {0x4530c000}, {0x4530e000}, + {0x45310000}, {0x45312000}, {0x45314000}, {0x45316000}, + {0x45318000}, {0x4531a000}, {0x4531c000}, {0x4531e000}, + {0x45320000}, {0x45322000}, {0x45324000}, {0x45326000}, + {0x45328000}, {0x4532a000}, {0x4532c000}, {0x4532e000}, + {0x45330000}, {0x45332000}, {0x45334000}, {0x45336000}, + {0x45338000}, {0x4533a000}, {0x4533c000}, {0x4533e000}, + {0x45340000}, {0x45342000}, {0x45344000}, {0x45346000}, + {0x45348000}, {0x4534a000}, {0x4534c000}, {0x4534e000}, + {0x45350000}, {0x45352000}, {0x45354000}, {0x45356000}, + {0x45358000}, {0x4535a000}, {0x4535c000}, {0x4535e000}, + {0x45360000}, {0x45362000}, {0x45364000}, {0x45366000}, + {0x45368000}, {0x4536a000}, {0x4536c000}, {0x4536e000}, + {0x45370000}, {0x45372000}, {0x45374000}, {0x45376000}, + {0x45378000}, {0x4537a000}, {0x4537c000}, {0x4537e000}, + {0x45380000}, {0x45382000}, {0x45384000}, {0x45386000}, + {0x45388000}, {0x4538a000}, {0x4538c000}, {0x4538e000}, + {0x45390000}, {0x45392000}, {0x45394000}, {0x45396000}, + {0x45398000}, {0x4539a000}, {0x4539c000}, {0x4539e000}, + {0x453a0000}, {0x453a2000}, {0x453a4000}, {0x453a6000}, + {0x453a8000}, {0x453aa000}, {0x453ac000}, {0x453ae000}, + {0x453b0000}, {0x453b2000}, {0x453b4000}, {0x453b6000}, + {0x453b8000}, {0x453ba000}, {0x453bc000}, {0x453be000}, + {0x453c0000}, {0x453c2000}, {0x453c4000}, {0x453c6000}, + {0x453c8000}, {0x453ca000}, {0x453cc000}, {0x453ce000}, + {0x453d0000}, {0x453d2000}, {0x453d4000}, {0x453d6000}, + {0x453d8000}, {0x453da000}, {0x453dc000}, {0x453de000}, + {0x453e0000}, {0x453e2000}, {0x453e4000}, {0x453e6000}, + {0x453e8000}, {0x453ea000}, {0x453ec000}, {0x453ee000}, + {0x453f0000}, {0x453f2000}, {0x453f4000}, {0x453f6000}, + {0x453f8000}, {0x453fa000}, {0x453fc000}, {0x453fe000}, + {0x45400000}, {0x45402000}, {0x45404000}, {0x45406000}, + {0x45408000}, {0x4540a000}, {0x4540c000}, {0x4540e000}, + {0x45410000}, {0x45412000}, {0x45414000}, {0x45416000}, + {0x45418000}, {0x4541a000}, {0x4541c000}, {0x4541e000}, + {0x45420000}, {0x45422000}, {0x45424000}, {0x45426000}, + {0x45428000}, {0x4542a000}, {0x4542c000}, {0x4542e000}, + {0x45430000}, {0x45432000}, {0x45434000}, {0x45436000}, + {0x45438000}, {0x4543a000}, {0x4543c000}, {0x4543e000}, + {0x45440000}, {0x45442000}, {0x45444000}, {0x45446000}, + {0x45448000}, {0x4544a000}, {0x4544c000}, {0x4544e000}, + {0x45450000}, {0x45452000}, {0x45454000}, {0x45456000}, + {0x45458000}, {0x4545a000}, {0x4545c000}, {0x4545e000}, + {0x45460000}, {0x45462000}, {0x45464000}, {0x45466000}, + {0x45468000}, {0x4546a000}, {0x4546c000}, {0x4546e000}, + {0x45470000}, {0x45472000}, {0x45474000}, {0x45476000}, + {0x45478000}, {0x4547a000}, {0x4547c000}, {0x4547e000}, + {0x45480000}, {0x45482000}, {0x45484000}, {0x45486000}, + {0x45488000}, {0x4548a000}, {0x4548c000}, {0x4548e000}, + {0x45490000}, {0x45492000}, {0x45494000}, {0x45496000}, + {0x45498000}, {0x4549a000}, {0x4549c000}, {0x4549e000}, + {0x454a0000}, {0x454a2000}, {0x454a4000}, {0x454a6000}, + {0x454a8000}, {0x454aa000}, {0x454ac000}, {0x454ae000}, + {0x454b0000}, {0x454b2000}, {0x454b4000}, {0x454b6000}, + {0x454b8000}, {0x454ba000}, {0x454bc000}, {0x454be000}, + {0x454c0000}, {0x454c2000}, {0x454c4000}, {0x454c6000}, + {0x454c8000}, {0x454ca000}, {0x454cc000}, {0x454ce000}, + {0x454d0000}, {0x454d2000}, {0x454d4000}, {0x454d6000}, + {0x454d8000}, {0x454da000}, {0x454dc000}, {0x454de000}, + {0x454e0000}, {0x454e2000}, {0x454e4000}, {0x454e6000}, + {0x454e8000}, {0x454ea000}, {0x454ec000}, {0x454ee000}, + {0x454f0000}, {0x454f2000}, {0x454f4000}, {0x454f6000}, + {0x454f8000}, {0x454fa000}, {0x454fc000}, {0x454fe000}, + {0x45500000}, {0x45502000}, {0x45504000}, {0x45506000}, + {0x45508000}, {0x4550a000}, {0x4550c000}, {0x4550e000}, + {0x45510000}, {0x45512000}, {0x45514000}, {0x45516000}, + {0x45518000}, {0x4551a000}, {0x4551c000}, {0x4551e000}, + {0x45520000}, {0x45522000}, {0x45524000}, {0x45526000}, + {0x45528000}, {0x4552a000}, {0x4552c000}, {0x4552e000}, + {0x45530000}, {0x45532000}, {0x45534000}, {0x45536000}, + {0x45538000}, {0x4553a000}, {0x4553c000}, {0x4553e000}, + {0x45540000}, {0x45542000}, {0x45544000}, {0x45546000}, + {0x45548000}, {0x4554a000}, {0x4554c000}, {0x4554e000}, + {0x45550000}, {0x45552000}, {0x45554000}, {0x45556000}, + {0x45558000}, {0x4555a000}, {0x4555c000}, {0x4555e000}, + {0x45560000}, {0x45562000}, {0x45564000}, {0x45566000}, + {0x45568000}, {0x4556a000}, {0x4556c000}, {0x4556e000}, + {0x45570000}, {0x45572000}, {0x45574000}, {0x45576000}, + {0x45578000}, {0x4557a000}, {0x4557c000}, {0x4557e000}, + {0x45580000}, {0x45582000}, {0x45584000}, {0x45586000}, + {0x45588000}, {0x4558a000}, {0x4558c000}, {0x4558e000}, + {0x45590000}, {0x45592000}, {0x45594000}, {0x45596000}, + {0x45598000}, {0x4559a000}, {0x4559c000}, {0x4559e000}, + {0x455a0000}, {0x455a2000}, {0x455a4000}, {0x455a6000}, + {0x455a8000}, {0x455aa000}, {0x455ac000}, {0x455ae000}, + {0x455b0000}, {0x455b2000}, {0x455b4000}, {0x455b6000}, + {0x455b8000}, {0x455ba000}, {0x455bc000}, {0x455be000}, + {0x455c0000}, {0x455c2000}, {0x455c4000}, {0x455c6000}, + {0x455c8000}, {0x455ca000}, {0x455cc000}, {0x455ce000}, + {0x455d0000}, {0x455d2000}, {0x455d4000}, {0x455d6000}, + {0x455d8000}, {0x455da000}, {0x455dc000}, {0x455de000}, + {0x455e0000}, {0x455e2000}, {0x455e4000}, {0x455e6000}, + {0x455e8000}, {0x455ea000}, {0x455ec000}, {0x455ee000}, + {0x455f0000}, {0x455f2000}, {0x455f4000}, {0x455f6000}, + {0x455f8000}, {0x455fa000}, {0x455fc000}, {0x455fe000}, + {0x45600000}, {0x45602000}, {0x45604000}, {0x45606000}, + {0x45608000}, {0x4560a000}, {0x4560c000}, {0x4560e000}, + {0x45610000}, {0x45612000}, {0x45614000}, {0x45616000}, + {0x45618000}, {0x4561a000}, {0x4561c000}, {0x4561e000}, + {0x45620000}, {0x45622000}, {0x45624000}, {0x45626000}, + {0x45628000}, {0x4562a000}, {0x4562c000}, {0x4562e000}, + {0x45630000}, {0x45632000}, {0x45634000}, {0x45636000}, + {0x45638000}, {0x4563a000}, {0x4563c000}, {0x4563e000}, + {0x45640000}, {0x45642000}, {0x45644000}, {0x45646000}, + {0x45648000}, {0x4564a000}, {0x4564c000}, {0x4564e000}, + {0x45650000}, {0x45652000}, {0x45654000}, {0x45656000}, + {0x45658000}, {0x4565a000}, {0x4565c000}, {0x4565e000}, + {0x45660000}, {0x45662000}, {0x45664000}, {0x45666000}, + {0x45668000}, {0x4566a000}, {0x4566c000}, {0x4566e000}, + {0x45670000}, {0x45672000}, {0x45674000}, {0x45676000}, + {0x45678000}, {0x4567a000}, {0x4567c000}, {0x4567e000}, + {0x45680000}, {0x45682000}, {0x45684000}, {0x45686000}, + {0x45688000}, {0x4568a000}, {0x4568c000}, {0x4568e000}, + {0x45690000}, {0x45692000}, {0x45694000}, {0x45696000}, + {0x45698000}, {0x4569a000}, {0x4569c000}, {0x4569e000}, + {0x456a0000}, {0x456a2000}, {0x456a4000}, {0x456a6000}, + {0x456a8000}, {0x456aa000}, {0x456ac000}, {0x456ae000}, + {0x456b0000}, {0x456b2000}, {0x456b4000}, {0x456b6000}, + {0x456b8000}, {0x456ba000}, {0x456bc000}, {0x456be000}, + {0x456c0000}, {0x456c2000}, {0x456c4000}, {0x456c6000}, + {0x456c8000}, {0x456ca000}, {0x456cc000}, {0x456ce000}, + {0x456d0000}, {0x456d2000}, {0x456d4000}, {0x456d6000}, + {0x456d8000}, {0x456da000}, {0x456dc000}, {0x456de000}, + {0x456e0000}, {0x456e2000}, {0x456e4000}, {0x456e6000}, + {0x456e8000}, {0x456ea000}, {0x456ec000}, {0x456ee000}, + {0x456f0000}, {0x456f2000}, {0x456f4000}, {0x456f6000}, + {0x456f8000}, {0x456fa000}, {0x456fc000}, {0x456fe000}, + {0x45700000}, {0x45702000}, {0x45704000}, {0x45706000}, + {0x45708000}, {0x4570a000}, {0x4570c000}, {0x4570e000}, + {0x45710000}, {0x45712000}, {0x45714000}, {0x45716000}, + {0x45718000}, {0x4571a000}, {0x4571c000}, {0x4571e000}, + {0x45720000}, {0x45722000}, {0x45724000}, {0x45726000}, + {0x45728000}, {0x4572a000}, {0x4572c000}, {0x4572e000}, + {0x45730000}, {0x45732000}, {0x45734000}, {0x45736000}, + {0x45738000}, {0x4573a000}, {0x4573c000}, {0x4573e000}, + {0x45740000}, {0x45742000}, {0x45744000}, {0x45746000}, + {0x45748000}, {0x4574a000}, {0x4574c000}, {0x4574e000}, + {0x45750000}, {0x45752000}, {0x45754000}, {0x45756000}, + {0x45758000}, {0x4575a000}, {0x4575c000}, {0x4575e000}, + {0x45760000}, {0x45762000}, {0x45764000}, {0x45766000}, + {0x45768000}, {0x4576a000}, {0x4576c000}, {0x4576e000}, + {0x45770000}, {0x45772000}, {0x45774000}, {0x45776000}, + {0x45778000}, {0x4577a000}, {0x4577c000}, {0x4577e000}, + {0x45780000}, {0x45782000}, {0x45784000}, {0x45786000}, + {0x45788000}, {0x4578a000}, {0x4578c000}, {0x4578e000}, + {0x45790000}, {0x45792000}, {0x45794000}, {0x45796000}, + {0x45798000}, {0x4579a000}, {0x4579c000}, {0x4579e000}, + {0x457a0000}, {0x457a2000}, {0x457a4000}, {0x457a6000}, + {0x457a8000}, {0x457aa000}, {0x457ac000}, {0x457ae000}, + {0x457b0000}, {0x457b2000}, {0x457b4000}, {0x457b6000}, + {0x457b8000}, {0x457ba000}, {0x457bc000}, {0x457be000}, + {0x457c0000}, {0x457c2000}, {0x457c4000}, {0x457c6000}, + {0x457c8000}, {0x457ca000}, {0x457cc000}, {0x457ce000}, + {0x457d0000}, {0x457d2000}, {0x457d4000}, {0x457d6000}, + {0x457d8000}, {0x457da000}, {0x457dc000}, {0x457de000}, + {0x457e0000}, {0x457e2000}, {0x457e4000}, {0x457e6000}, + {0x457e8000}, {0x457ea000}, {0x457ec000}, {0x457ee000}, + {0x457f0000}, {0x457f2000}, {0x457f4000}, {0x457f6000}, + {0x457f8000}, {0x457fa000}, {0x457fc000}, {0x457fe000}, + {0x45800000}, {0x45802000}, {0x45804000}, {0x45806000}, + {0x45808000}, {0x4580a000}, {0x4580c000}, {0x4580e000}, + {0x45810000}, {0x45812000}, {0x45814000}, {0x45816000}, + {0x45818000}, {0x4581a000}, {0x4581c000}, {0x4581e000}, + {0x45820000}, {0x45822000}, {0x45824000}, {0x45826000}, + {0x45828000}, {0x4582a000}, {0x4582c000}, {0x4582e000}, + {0x45830000}, {0x45832000}, {0x45834000}, {0x45836000}, + {0x45838000}, {0x4583a000}, {0x4583c000}, {0x4583e000}, + {0x45840000}, {0x45842000}, {0x45844000}, {0x45846000}, + {0x45848000}, {0x4584a000}, {0x4584c000}, {0x4584e000}, + {0x45850000}, {0x45852000}, {0x45854000}, {0x45856000}, + {0x45858000}, {0x4585a000}, {0x4585c000}, {0x4585e000}, + {0x45860000}, {0x45862000}, {0x45864000}, {0x45866000}, + {0x45868000}, {0x4586a000}, {0x4586c000}, {0x4586e000}, + {0x45870000}, {0x45872000}, {0x45874000}, {0x45876000}, + {0x45878000}, {0x4587a000}, {0x4587c000}, {0x4587e000}, + {0x45880000}, {0x45882000}, {0x45884000}, {0x45886000}, + {0x45888000}, {0x4588a000}, {0x4588c000}, {0x4588e000}, + {0x45890000}, {0x45892000}, {0x45894000}, {0x45896000}, + {0x45898000}, {0x4589a000}, {0x4589c000}, {0x4589e000}, + {0x458a0000}, {0x458a2000}, {0x458a4000}, {0x458a6000}, + {0x458a8000}, {0x458aa000}, {0x458ac000}, {0x458ae000}, + {0x458b0000}, {0x458b2000}, {0x458b4000}, {0x458b6000}, + {0x458b8000}, {0x458ba000}, {0x458bc000}, {0x458be000}, + {0x458c0000}, {0x458c2000}, {0x458c4000}, {0x458c6000}, + {0x458c8000}, {0x458ca000}, {0x458cc000}, {0x458ce000}, + {0x458d0000}, {0x458d2000}, {0x458d4000}, {0x458d6000}, + {0x458d8000}, {0x458da000}, {0x458dc000}, {0x458de000}, + {0x458e0000}, {0x458e2000}, {0x458e4000}, {0x458e6000}, + {0x458e8000}, {0x458ea000}, {0x458ec000}, {0x458ee000}, + {0x458f0000}, {0x458f2000}, {0x458f4000}, {0x458f6000}, + {0x458f8000}, {0x458fa000}, {0x458fc000}, {0x458fe000}, + {0x45900000}, {0x45902000}, {0x45904000}, {0x45906000}, + {0x45908000}, {0x4590a000}, {0x4590c000}, {0x4590e000}, + {0x45910000}, {0x45912000}, {0x45914000}, {0x45916000}, + {0x45918000}, {0x4591a000}, {0x4591c000}, {0x4591e000}, + {0x45920000}, {0x45922000}, {0x45924000}, {0x45926000}, + {0x45928000}, {0x4592a000}, {0x4592c000}, {0x4592e000}, + {0x45930000}, {0x45932000}, {0x45934000}, {0x45936000}, + {0x45938000}, {0x4593a000}, {0x4593c000}, {0x4593e000}, + {0x45940000}, {0x45942000}, {0x45944000}, {0x45946000}, + {0x45948000}, {0x4594a000}, {0x4594c000}, {0x4594e000}, + {0x45950000}, {0x45952000}, {0x45954000}, {0x45956000}, + {0x45958000}, {0x4595a000}, {0x4595c000}, {0x4595e000}, + {0x45960000}, {0x45962000}, {0x45964000}, {0x45966000}, + {0x45968000}, {0x4596a000}, {0x4596c000}, {0x4596e000}, + {0x45970000}, {0x45972000}, {0x45974000}, {0x45976000}, + {0x45978000}, {0x4597a000}, {0x4597c000}, {0x4597e000}, + {0x45980000}, {0x45982000}, {0x45984000}, {0x45986000}, + {0x45988000}, {0x4598a000}, {0x4598c000}, {0x4598e000}, + {0x45990000}, {0x45992000}, {0x45994000}, {0x45996000}, + {0x45998000}, {0x4599a000}, {0x4599c000}, {0x4599e000}, + {0x459a0000}, {0x459a2000}, {0x459a4000}, {0x459a6000}, + {0x459a8000}, {0x459aa000}, {0x459ac000}, {0x459ae000}, + {0x459b0000}, {0x459b2000}, {0x459b4000}, {0x459b6000}, + {0x459b8000}, {0x459ba000}, {0x459bc000}, {0x459be000}, + {0x459c0000}, {0x459c2000}, {0x459c4000}, {0x459c6000}, + {0x459c8000}, {0x459ca000}, {0x459cc000}, {0x459ce000}, + {0x459d0000}, {0x459d2000}, {0x459d4000}, {0x459d6000}, + {0x459d8000}, {0x459da000}, {0x459dc000}, {0x459de000}, + {0x459e0000}, {0x459e2000}, {0x459e4000}, {0x459e6000}, + {0x459e8000}, {0x459ea000}, {0x459ec000}, {0x459ee000}, + {0x459f0000}, {0x459f2000}, {0x459f4000}, {0x459f6000}, + {0x459f8000}, {0x459fa000}, {0x459fc000}, {0x459fe000}, + {0x45a00000}, {0x45a02000}, {0x45a04000}, {0x45a06000}, + {0x45a08000}, {0x45a0a000}, {0x45a0c000}, {0x45a0e000}, + {0x45a10000}, {0x45a12000}, {0x45a14000}, {0x45a16000}, + {0x45a18000}, {0x45a1a000}, {0x45a1c000}, {0x45a1e000}, + {0x45a20000}, {0x45a22000}, {0x45a24000}, {0x45a26000}, + {0x45a28000}, {0x45a2a000}, {0x45a2c000}, {0x45a2e000}, + {0x45a30000}, {0x45a32000}, {0x45a34000}, {0x45a36000}, + {0x45a38000}, {0x45a3a000}, {0x45a3c000}, {0x45a3e000}, + {0x45a40000}, {0x45a42000}, {0x45a44000}, {0x45a46000}, + {0x45a48000}, {0x45a4a000}, {0x45a4c000}, {0x45a4e000}, + {0x45a50000}, {0x45a52000}, {0x45a54000}, {0x45a56000}, + {0x45a58000}, {0x45a5a000}, {0x45a5c000}, {0x45a5e000}, + {0x45a60000}, {0x45a62000}, {0x45a64000}, {0x45a66000}, + {0x45a68000}, {0x45a6a000}, {0x45a6c000}, {0x45a6e000}, + {0x45a70000}, {0x45a72000}, {0x45a74000}, {0x45a76000}, + {0x45a78000}, {0x45a7a000}, {0x45a7c000}, {0x45a7e000}, + {0x45a80000}, {0x45a82000}, {0x45a84000}, {0x45a86000}, + {0x45a88000}, {0x45a8a000}, {0x45a8c000}, {0x45a8e000}, + {0x45a90000}, {0x45a92000}, {0x45a94000}, {0x45a96000}, + {0x45a98000}, {0x45a9a000}, {0x45a9c000}, {0x45a9e000}, + {0x45aa0000}, {0x45aa2000}, {0x45aa4000}, {0x45aa6000}, + {0x45aa8000}, {0x45aaa000}, {0x45aac000}, {0x45aae000}, + {0x45ab0000}, {0x45ab2000}, {0x45ab4000}, {0x45ab6000}, + {0x45ab8000}, {0x45aba000}, {0x45abc000}, {0x45abe000}, + {0x45ac0000}, {0x45ac2000}, {0x45ac4000}, {0x45ac6000}, + {0x45ac8000}, {0x45aca000}, {0x45acc000}, {0x45ace000}, + {0x45ad0000}, {0x45ad2000}, {0x45ad4000}, {0x45ad6000}, + {0x45ad8000}, {0x45ada000}, {0x45adc000}, {0x45ade000}, + {0x45ae0000}, {0x45ae2000}, {0x45ae4000}, {0x45ae6000}, + {0x45ae8000}, {0x45aea000}, {0x45aec000}, {0x45aee000}, + {0x45af0000}, {0x45af2000}, {0x45af4000}, {0x45af6000}, + {0x45af8000}, {0x45afa000}, {0x45afc000}, {0x45afe000}, + {0x45b00000}, {0x45b02000}, {0x45b04000}, {0x45b06000}, + {0x45b08000}, {0x45b0a000}, {0x45b0c000}, {0x45b0e000}, + {0x45b10000}, {0x45b12000}, {0x45b14000}, {0x45b16000}, + {0x45b18000}, {0x45b1a000}, {0x45b1c000}, {0x45b1e000}, + {0x45b20000}, {0x45b22000}, {0x45b24000}, {0x45b26000}, + {0x45b28000}, {0x45b2a000}, {0x45b2c000}, {0x45b2e000}, + {0x45b30000}, {0x45b32000}, {0x45b34000}, {0x45b36000}, + {0x45b38000}, {0x45b3a000}, {0x45b3c000}, {0x45b3e000}, + {0x45b40000}, {0x45b42000}, {0x45b44000}, {0x45b46000}, + {0x45b48000}, {0x45b4a000}, {0x45b4c000}, {0x45b4e000}, + {0x45b50000}, {0x45b52000}, {0x45b54000}, {0x45b56000}, + {0x45b58000}, {0x45b5a000}, {0x45b5c000}, {0x45b5e000}, + {0x45b60000}, {0x45b62000}, {0x45b64000}, {0x45b66000}, + {0x45b68000}, {0x45b6a000}, {0x45b6c000}, {0x45b6e000}, + {0x45b70000}, {0x45b72000}, {0x45b74000}, {0x45b76000}, + {0x45b78000}, {0x45b7a000}, {0x45b7c000}, {0x45b7e000}, + {0x45b80000}, {0x45b82000}, {0x45b84000}, {0x45b86000}, + {0x45b88000}, {0x45b8a000}, {0x45b8c000}, {0x45b8e000}, + {0x45b90000}, {0x45b92000}, {0x45b94000}, {0x45b96000}, + {0x45b98000}, {0x45b9a000}, {0x45b9c000}, {0x45b9e000}, + {0x45ba0000}, {0x45ba2000}, {0x45ba4000}, {0x45ba6000}, + {0x45ba8000}, {0x45baa000}, {0x45bac000}, {0x45bae000}, + {0x45bb0000}, {0x45bb2000}, {0x45bb4000}, {0x45bb6000}, + {0x45bb8000}, {0x45bba000}, {0x45bbc000}, {0x45bbe000}, + {0x45bc0000}, {0x45bc2000}, {0x45bc4000}, {0x45bc6000}, + {0x45bc8000}, {0x45bca000}, {0x45bcc000}, {0x45bce000}, + {0x45bd0000}, {0x45bd2000}, {0x45bd4000}, {0x45bd6000}, + {0x45bd8000}, {0x45bda000}, {0x45bdc000}, {0x45bde000}, + {0x45be0000}, {0x45be2000}, {0x45be4000}, {0x45be6000}, + {0x45be8000}, {0x45bea000}, {0x45bec000}, {0x45bee000}, + {0x45bf0000}, {0x45bf2000}, {0x45bf4000}, {0x45bf6000}, + {0x45bf8000}, {0x45bfa000}, {0x45bfc000}, {0x45bfe000}, + {0x45c00000}, {0x45c02000}, {0x45c04000}, {0x45c06000}, + {0x45c08000}, {0x45c0a000}, {0x45c0c000}, {0x45c0e000}, + {0x45c10000}, {0x45c12000}, {0x45c14000}, {0x45c16000}, + {0x45c18000}, {0x45c1a000}, {0x45c1c000}, {0x45c1e000}, + {0x45c20000}, {0x45c22000}, {0x45c24000}, {0x45c26000}, + {0x45c28000}, {0x45c2a000}, {0x45c2c000}, {0x45c2e000}, + {0x45c30000}, {0x45c32000}, {0x45c34000}, {0x45c36000}, + {0x45c38000}, {0x45c3a000}, {0x45c3c000}, {0x45c3e000}, + {0x45c40000}, {0x45c42000}, {0x45c44000}, {0x45c46000}, + {0x45c48000}, {0x45c4a000}, {0x45c4c000}, {0x45c4e000}, + {0x45c50000}, {0x45c52000}, {0x45c54000}, {0x45c56000}, + {0x45c58000}, {0x45c5a000}, {0x45c5c000}, {0x45c5e000}, + {0x45c60000}, {0x45c62000}, {0x45c64000}, {0x45c66000}, + {0x45c68000}, {0x45c6a000}, {0x45c6c000}, {0x45c6e000}, + {0x45c70000}, {0x45c72000}, {0x45c74000}, {0x45c76000}, + {0x45c78000}, {0x45c7a000}, {0x45c7c000}, {0x45c7e000}, + {0x45c80000}, {0x45c82000}, {0x45c84000}, {0x45c86000}, + {0x45c88000}, {0x45c8a000}, {0x45c8c000}, {0x45c8e000}, + {0x45c90000}, {0x45c92000}, {0x45c94000}, {0x45c96000}, + {0x45c98000}, {0x45c9a000}, {0x45c9c000}, {0x45c9e000}, + {0x45ca0000}, {0x45ca2000}, {0x45ca4000}, {0x45ca6000}, + {0x45ca8000}, {0x45caa000}, {0x45cac000}, {0x45cae000}, + {0x45cb0000}, {0x45cb2000}, {0x45cb4000}, {0x45cb6000}, + {0x45cb8000}, {0x45cba000}, {0x45cbc000}, {0x45cbe000}, + {0x45cc0000}, {0x45cc2000}, {0x45cc4000}, {0x45cc6000}, + {0x45cc8000}, {0x45cca000}, {0x45ccc000}, {0x45cce000}, + {0x45cd0000}, {0x45cd2000}, {0x45cd4000}, {0x45cd6000}, + {0x45cd8000}, {0x45cda000}, {0x45cdc000}, {0x45cde000}, + {0x45ce0000}, {0x45ce2000}, {0x45ce4000}, {0x45ce6000}, + {0x45ce8000}, {0x45cea000}, {0x45cec000}, {0x45cee000}, + {0x45cf0000}, {0x45cf2000}, {0x45cf4000}, {0x45cf6000}, + {0x45cf8000}, {0x45cfa000}, {0x45cfc000}, {0x45cfe000}, + {0x45d00000}, {0x45d02000}, {0x45d04000}, {0x45d06000}, + {0x45d08000}, {0x45d0a000}, {0x45d0c000}, {0x45d0e000}, + {0x45d10000}, {0x45d12000}, {0x45d14000}, {0x45d16000}, + {0x45d18000}, {0x45d1a000}, {0x45d1c000}, {0x45d1e000}, + {0x45d20000}, {0x45d22000}, {0x45d24000}, {0x45d26000}, + {0x45d28000}, {0x45d2a000}, {0x45d2c000}, {0x45d2e000}, + {0x45d30000}, {0x45d32000}, {0x45d34000}, {0x45d36000}, + {0x45d38000}, {0x45d3a000}, {0x45d3c000}, {0x45d3e000}, + {0x45d40000}, {0x45d42000}, {0x45d44000}, {0x45d46000}, + {0x45d48000}, {0x45d4a000}, {0x45d4c000}, {0x45d4e000}, + {0x45d50000}, {0x45d52000}, {0x45d54000}, {0x45d56000}, + {0x45d58000}, {0x45d5a000}, {0x45d5c000}, {0x45d5e000}, + {0x45d60000}, {0x45d62000}, {0x45d64000}, {0x45d66000}, + {0x45d68000}, {0x45d6a000}, {0x45d6c000}, {0x45d6e000}, + {0x45d70000}, {0x45d72000}, {0x45d74000}, {0x45d76000}, + {0x45d78000}, {0x45d7a000}, {0x45d7c000}, {0x45d7e000}, + {0x45d80000}, {0x45d82000}, {0x45d84000}, {0x45d86000}, + {0x45d88000}, {0x45d8a000}, {0x45d8c000}, {0x45d8e000}, + {0x45d90000}, {0x45d92000}, {0x45d94000}, {0x45d96000}, + {0x45d98000}, {0x45d9a000}, {0x45d9c000}, {0x45d9e000}, + {0x45da0000}, {0x45da2000}, {0x45da4000}, {0x45da6000}, + {0x45da8000}, {0x45daa000}, {0x45dac000}, {0x45dae000}, + {0x45db0000}, {0x45db2000}, {0x45db4000}, {0x45db6000}, + {0x45db8000}, {0x45dba000}, {0x45dbc000}, {0x45dbe000}, + {0x45dc0000}, {0x45dc2000}, {0x45dc4000}, {0x45dc6000}, + {0x45dc8000}, {0x45dca000}, {0x45dcc000}, {0x45dce000}, + {0x45dd0000}, {0x45dd2000}, {0x45dd4000}, {0x45dd6000}, + {0x45dd8000}, {0x45dda000}, {0x45ddc000}, {0x45dde000}, + {0x45de0000}, {0x45de2000}, {0x45de4000}, {0x45de6000}, + {0x45de8000}, {0x45dea000}, {0x45dec000}, {0x45dee000}, + {0x45df0000}, {0x45df2000}, {0x45df4000}, {0x45df6000}, + {0x45df8000}, {0x45dfa000}, {0x45dfc000}, {0x45dfe000}, + {0x45e00000}, {0x45e02000}, {0x45e04000}, {0x45e06000}, + {0x45e08000}, {0x45e0a000}, {0x45e0c000}, {0x45e0e000}, + {0x45e10000}, {0x45e12000}, {0x45e14000}, {0x45e16000}, + {0x45e18000}, {0x45e1a000}, {0x45e1c000}, {0x45e1e000}, + {0x45e20000}, {0x45e22000}, {0x45e24000}, {0x45e26000}, + {0x45e28000}, {0x45e2a000}, {0x45e2c000}, {0x45e2e000}, + {0x45e30000}, {0x45e32000}, {0x45e34000}, {0x45e36000}, + {0x45e38000}, {0x45e3a000}, {0x45e3c000}, {0x45e3e000}, + {0x45e40000}, {0x45e42000}, {0x45e44000}, {0x45e46000}, + {0x45e48000}, {0x45e4a000}, {0x45e4c000}, {0x45e4e000}, + {0x45e50000}, {0x45e52000}, {0x45e54000}, {0x45e56000}, + {0x45e58000}, {0x45e5a000}, {0x45e5c000}, {0x45e5e000}, + {0x45e60000}, {0x45e62000}, {0x45e64000}, {0x45e66000}, + {0x45e68000}, {0x45e6a000}, {0x45e6c000}, {0x45e6e000}, + {0x45e70000}, {0x45e72000}, {0x45e74000}, {0x45e76000}, + {0x45e78000}, {0x45e7a000}, {0x45e7c000}, {0x45e7e000}, + {0x45e80000}, {0x45e82000}, {0x45e84000}, {0x45e86000}, + {0x45e88000}, {0x45e8a000}, {0x45e8c000}, {0x45e8e000}, + {0x45e90000}, {0x45e92000}, {0x45e94000}, {0x45e96000}, + {0x45e98000}, {0x45e9a000}, {0x45e9c000}, {0x45e9e000}, + {0x45ea0000}, {0x45ea2000}, {0x45ea4000}, {0x45ea6000}, + {0x45ea8000}, {0x45eaa000}, {0x45eac000}, {0x45eae000}, + {0x45eb0000}, {0x45eb2000}, {0x45eb4000}, {0x45eb6000}, + {0x45eb8000}, {0x45eba000}, {0x45ebc000}, {0x45ebe000}, + {0x45ec0000}, {0x45ec2000}, {0x45ec4000}, {0x45ec6000}, + {0x45ec8000}, {0x45eca000}, {0x45ecc000}, {0x45ece000}, + {0x45ed0000}, {0x45ed2000}, {0x45ed4000}, {0x45ed6000}, + {0x45ed8000}, {0x45eda000}, {0x45edc000}, {0x45ede000}, + {0x45ee0000}, {0x45ee2000}, {0x45ee4000}, {0x45ee6000}, + {0x45ee8000}, {0x45eea000}, {0x45eec000}, {0x45eee000}, + {0x45ef0000}, {0x45ef2000}, {0x45ef4000}, {0x45ef6000}, + {0x45ef8000}, {0x45efa000}, {0x45efc000}, {0x45efe000}, + {0x45f00000}, {0x45f02000}, {0x45f04000}, {0x45f06000}, + {0x45f08000}, {0x45f0a000}, {0x45f0c000}, {0x45f0e000}, + {0x45f10000}, {0x45f12000}, {0x45f14000}, {0x45f16000}, + {0x45f18000}, {0x45f1a000}, {0x45f1c000}, {0x45f1e000}, + {0x45f20000}, {0x45f22000}, {0x45f24000}, {0x45f26000}, + {0x45f28000}, {0x45f2a000}, {0x45f2c000}, {0x45f2e000}, + {0x45f30000}, {0x45f32000}, {0x45f34000}, {0x45f36000}, + {0x45f38000}, {0x45f3a000}, {0x45f3c000}, {0x45f3e000}, + {0x45f40000}, {0x45f42000}, {0x45f44000}, {0x45f46000}, + {0x45f48000}, {0x45f4a000}, {0x45f4c000}, {0x45f4e000}, + {0x45f50000}, {0x45f52000}, {0x45f54000}, {0x45f56000}, + {0x45f58000}, {0x45f5a000}, {0x45f5c000}, {0x45f5e000}, + {0x45f60000}, {0x45f62000}, {0x45f64000}, {0x45f66000}, + {0x45f68000}, {0x45f6a000}, {0x45f6c000}, {0x45f6e000}, + {0x45f70000}, {0x45f72000}, {0x45f74000}, {0x45f76000}, + {0x45f78000}, {0x45f7a000}, {0x45f7c000}, {0x45f7e000}, + {0x45f80000}, {0x45f82000}, {0x45f84000}, {0x45f86000}, + {0x45f88000}, {0x45f8a000}, {0x45f8c000}, {0x45f8e000}, + {0x45f90000}, {0x45f92000}, {0x45f94000}, {0x45f96000}, + {0x45f98000}, {0x45f9a000}, {0x45f9c000}, {0x45f9e000}, + {0x45fa0000}, {0x45fa2000}, {0x45fa4000}, {0x45fa6000}, + {0x45fa8000}, {0x45faa000}, {0x45fac000}, {0x45fae000}, + {0x45fb0000}, {0x45fb2000}, {0x45fb4000}, {0x45fb6000}, + {0x45fb8000}, {0x45fba000}, {0x45fbc000}, {0x45fbe000}, + {0x45fc0000}, {0x45fc2000}, {0x45fc4000}, {0x45fc6000}, + {0x45fc8000}, {0x45fca000}, {0x45fcc000}, {0x45fce000}, + {0x45fd0000}, {0x45fd2000}, {0x45fd4000}, {0x45fd6000}, + {0x45fd8000}, {0x45fda000}, {0x45fdc000}, {0x45fde000}, + {0x45fe0000}, {0x45fe2000}, {0x45fe4000}, {0x45fe6000}, + {0x45fe8000}, {0x45fea000}, {0x45fec000}, {0x45fee000}, + {0x45ff0000}, {0x45ff2000}, {0x45ff4000}, {0x45ff6000}, + {0x45ff8000}, {0x45ffa000}, {0x45ffc000}, {0x45ffe000}, + {0x46000000}, {0x46002000}, {0x46004000}, {0x46006000}, + {0x46008000}, {0x4600a000}, {0x4600c000}, {0x4600e000}, + {0x46010000}, {0x46012000}, {0x46014000}, {0x46016000}, + {0x46018000}, {0x4601a000}, {0x4601c000}, {0x4601e000}, + {0x46020000}, {0x46022000}, {0x46024000}, {0x46026000}, + {0x46028000}, {0x4602a000}, {0x4602c000}, {0x4602e000}, + {0x46030000}, {0x46032000}, {0x46034000}, {0x46036000}, + {0x46038000}, {0x4603a000}, {0x4603c000}, {0x4603e000}, + {0x46040000}, {0x46042000}, {0x46044000}, {0x46046000}, + {0x46048000}, {0x4604a000}, {0x4604c000}, {0x4604e000}, + {0x46050000}, {0x46052000}, {0x46054000}, {0x46056000}, + {0x46058000}, {0x4605a000}, {0x4605c000}, {0x4605e000}, + {0x46060000}, {0x46062000}, {0x46064000}, {0x46066000}, + {0x46068000}, {0x4606a000}, {0x4606c000}, {0x4606e000}, + {0x46070000}, {0x46072000}, {0x46074000}, {0x46076000}, + {0x46078000}, {0x4607a000}, {0x4607c000}, {0x4607e000}, + {0x46080000}, {0x46082000}, {0x46084000}, {0x46086000}, + {0x46088000}, {0x4608a000}, {0x4608c000}, {0x4608e000}, + {0x46090000}, {0x46092000}, {0x46094000}, {0x46096000}, + {0x46098000}, {0x4609a000}, {0x4609c000}, {0x4609e000}, + {0x460a0000}, {0x460a2000}, {0x460a4000}, {0x460a6000}, + {0x460a8000}, {0x460aa000}, {0x460ac000}, {0x460ae000}, + {0x460b0000}, {0x460b2000}, {0x460b4000}, {0x460b6000}, + {0x460b8000}, {0x460ba000}, {0x460bc000}, {0x460be000}, + {0x460c0000}, {0x460c2000}, {0x460c4000}, {0x460c6000}, + {0x460c8000}, {0x460ca000}, {0x460cc000}, {0x460ce000}, + {0x460d0000}, {0x460d2000}, {0x460d4000}, {0x460d6000}, + {0x460d8000}, {0x460da000}, {0x460dc000}, {0x460de000}, + {0x460e0000}, {0x460e2000}, {0x460e4000}, {0x460e6000}, + {0x460e8000}, {0x460ea000}, {0x460ec000}, {0x460ee000}, + {0x460f0000}, {0x460f2000}, {0x460f4000}, {0x460f6000}, + {0x460f8000}, {0x460fa000}, {0x460fc000}, {0x460fe000}, + {0x46100000}, {0x46102000}, {0x46104000}, {0x46106000}, + {0x46108000}, {0x4610a000}, {0x4610c000}, {0x4610e000}, + {0x46110000}, {0x46112000}, {0x46114000}, {0x46116000}, + {0x46118000}, {0x4611a000}, {0x4611c000}, {0x4611e000}, + {0x46120000}, {0x46122000}, {0x46124000}, {0x46126000}, + {0x46128000}, {0x4612a000}, {0x4612c000}, {0x4612e000}, + {0x46130000}, {0x46132000}, {0x46134000}, {0x46136000}, + {0x46138000}, {0x4613a000}, {0x4613c000}, {0x4613e000}, + {0x46140000}, {0x46142000}, {0x46144000}, {0x46146000}, + {0x46148000}, {0x4614a000}, {0x4614c000}, {0x4614e000}, + {0x46150000}, {0x46152000}, {0x46154000}, {0x46156000}, + {0x46158000}, {0x4615a000}, {0x4615c000}, {0x4615e000}, + {0x46160000}, {0x46162000}, {0x46164000}, {0x46166000}, + {0x46168000}, {0x4616a000}, {0x4616c000}, {0x4616e000}, + {0x46170000}, {0x46172000}, {0x46174000}, {0x46176000}, + {0x46178000}, {0x4617a000}, {0x4617c000}, {0x4617e000}, + {0x46180000}, {0x46182000}, {0x46184000}, {0x46186000}, + {0x46188000}, {0x4618a000}, {0x4618c000}, {0x4618e000}, + {0x46190000}, {0x46192000}, {0x46194000}, {0x46196000}, + {0x46198000}, {0x4619a000}, {0x4619c000}, {0x4619e000}, + {0x461a0000}, {0x461a2000}, {0x461a4000}, {0x461a6000}, + {0x461a8000}, {0x461aa000}, {0x461ac000}, {0x461ae000}, + {0x461b0000}, {0x461b2000}, {0x461b4000}, {0x461b6000}, + {0x461b8000}, {0x461ba000}, {0x461bc000}, {0x461be000}, + {0x461c0000}, {0x461c2000}, {0x461c4000}, {0x461c6000}, + {0x461c8000}, {0x461ca000}, {0x461cc000}, {0x461ce000}, + {0x461d0000}, {0x461d2000}, {0x461d4000}, {0x461d6000}, + {0x461d8000}, {0x461da000}, {0x461dc000}, {0x461de000}, + {0x461e0000}, {0x461e2000}, {0x461e4000}, {0x461e6000}, + {0x461e8000}, {0x461ea000}, {0x461ec000}, {0x461ee000}, + {0x461f0000}, {0x461f2000}, {0x461f4000}, {0x461f6000}, + {0x461f8000}, {0x461fa000}, {0x461fc000}, {0x461fe000}, + {0x46200000}, {0x46202000}, {0x46204000}, {0x46206000}, + {0x46208000}, {0x4620a000}, {0x4620c000}, {0x4620e000}, + {0x46210000}, {0x46212000}, {0x46214000}, {0x46216000}, + {0x46218000}, {0x4621a000}, {0x4621c000}, {0x4621e000}, + {0x46220000}, {0x46222000}, {0x46224000}, {0x46226000}, + {0x46228000}, {0x4622a000}, {0x4622c000}, {0x4622e000}, + {0x46230000}, {0x46232000}, {0x46234000}, {0x46236000}, + {0x46238000}, {0x4623a000}, {0x4623c000}, {0x4623e000}, + {0x46240000}, {0x46242000}, {0x46244000}, {0x46246000}, + {0x46248000}, {0x4624a000}, {0x4624c000}, {0x4624e000}, + {0x46250000}, {0x46252000}, {0x46254000}, {0x46256000}, + {0x46258000}, {0x4625a000}, {0x4625c000}, {0x4625e000}, + {0x46260000}, {0x46262000}, {0x46264000}, {0x46266000}, + {0x46268000}, {0x4626a000}, {0x4626c000}, {0x4626e000}, + {0x46270000}, {0x46272000}, {0x46274000}, {0x46276000}, + {0x46278000}, {0x4627a000}, {0x4627c000}, {0x4627e000}, + {0x46280000}, {0x46282000}, {0x46284000}, {0x46286000}, + {0x46288000}, {0x4628a000}, {0x4628c000}, {0x4628e000}, + {0x46290000}, {0x46292000}, {0x46294000}, {0x46296000}, + {0x46298000}, {0x4629a000}, {0x4629c000}, {0x4629e000}, + {0x462a0000}, {0x462a2000}, {0x462a4000}, {0x462a6000}, + {0x462a8000}, {0x462aa000}, {0x462ac000}, {0x462ae000}, + {0x462b0000}, {0x462b2000}, {0x462b4000}, {0x462b6000}, + {0x462b8000}, {0x462ba000}, {0x462bc000}, {0x462be000}, + {0x462c0000}, {0x462c2000}, {0x462c4000}, {0x462c6000}, + {0x462c8000}, {0x462ca000}, {0x462cc000}, {0x462ce000}, + {0x462d0000}, {0x462d2000}, {0x462d4000}, {0x462d6000}, + {0x462d8000}, {0x462da000}, {0x462dc000}, {0x462de000}, + {0x462e0000}, {0x462e2000}, {0x462e4000}, {0x462e6000}, + {0x462e8000}, {0x462ea000}, {0x462ec000}, {0x462ee000}, + {0x462f0000}, {0x462f2000}, {0x462f4000}, {0x462f6000}, + {0x462f8000}, {0x462fa000}, {0x462fc000}, {0x462fe000}, + {0x46300000}, {0x46302000}, {0x46304000}, {0x46306000}, + {0x46308000}, {0x4630a000}, {0x4630c000}, {0x4630e000}, + {0x46310000}, {0x46312000}, {0x46314000}, {0x46316000}, + {0x46318000}, {0x4631a000}, {0x4631c000}, {0x4631e000}, + {0x46320000}, {0x46322000}, {0x46324000}, {0x46326000}, + {0x46328000}, {0x4632a000}, {0x4632c000}, {0x4632e000}, + {0x46330000}, {0x46332000}, {0x46334000}, {0x46336000}, + {0x46338000}, {0x4633a000}, {0x4633c000}, {0x4633e000}, + {0x46340000}, {0x46342000}, {0x46344000}, {0x46346000}, + {0x46348000}, {0x4634a000}, {0x4634c000}, {0x4634e000}, + {0x46350000}, {0x46352000}, {0x46354000}, {0x46356000}, + {0x46358000}, {0x4635a000}, {0x4635c000}, {0x4635e000}, + {0x46360000}, {0x46362000}, {0x46364000}, {0x46366000}, + {0x46368000}, {0x4636a000}, {0x4636c000}, {0x4636e000}, + {0x46370000}, {0x46372000}, {0x46374000}, {0x46376000}, + {0x46378000}, {0x4637a000}, {0x4637c000}, {0x4637e000}, + {0x46380000}, {0x46382000}, {0x46384000}, {0x46386000}, + {0x46388000}, {0x4638a000}, {0x4638c000}, {0x4638e000}, + {0x46390000}, {0x46392000}, {0x46394000}, {0x46396000}, + {0x46398000}, {0x4639a000}, {0x4639c000}, {0x4639e000}, + {0x463a0000}, {0x463a2000}, {0x463a4000}, {0x463a6000}, + {0x463a8000}, {0x463aa000}, {0x463ac000}, {0x463ae000}, + {0x463b0000}, {0x463b2000}, {0x463b4000}, {0x463b6000}, + {0x463b8000}, {0x463ba000}, {0x463bc000}, {0x463be000}, + {0x463c0000}, {0x463c2000}, {0x463c4000}, {0x463c6000}, + {0x463c8000}, {0x463ca000}, {0x463cc000}, {0x463ce000}, + {0x463d0000}, {0x463d2000}, {0x463d4000}, {0x463d6000}, + {0x463d8000}, {0x463da000}, {0x463dc000}, {0x463de000}, + {0x463e0000}, {0x463e2000}, {0x463e4000}, {0x463e6000}, + {0x463e8000}, {0x463ea000}, {0x463ec000}, {0x463ee000}, + {0x463f0000}, {0x463f2000}, {0x463f4000}, {0x463f6000}, + {0x463f8000}, {0x463fa000}, {0x463fc000}, {0x463fe000}, + {0x46400000}, {0x46402000}, {0x46404000}, {0x46406000}, + {0x46408000}, {0x4640a000}, {0x4640c000}, {0x4640e000}, + {0x46410000}, {0x46412000}, {0x46414000}, {0x46416000}, + {0x46418000}, {0x4641a000}, {0x4641c000}, {0x4641e000}, + {0x46420000}, {0x46422000}, {0x46424000}, {0x46426000}, + {0x46428000}, {0x4642a000}, {0x4642c000}, {0x4642e000}, + {0x46430000}, {0x46432000}, {0x46434000}, {0x46436000}, + {0x46438000}, {0x4643a000}, {0x4643c000}, {0x4643e000}, + {0x46440000}, {0x46442000}, {0x46444000}, {0x46446000}, + {0x46448000}, {0x4644a000}, {0x4644c000}, {0x4644e000}, + {0x46450000}, {0x46452000}, {0x46454000}, {0x46456000}, + {0x46458000}, {0x4645a000}, {0x4645c000}, {0x4645e000}, + {0x46460000}, {0x46462000}, {0x46464000}, {0x46466000}, + {0x46468000}, {0x4646a000}, {0x4646c000}, {0x4646e000}, + {0x46470000}, {0x46472000}, {0x46474000}, {0x46476000}, + {0x46478000}, {0x4647a000}, {0x4647c000}, {0x4647e000}, + {0x46480000}, {0x46482000}, {0x46484000}, {0x46486000}, + {0x46488000}, {0x4648a000}, {0x4648c000}, {0x4648e000}, + {0x46490000}, {0x46492000}, {0x46494000}, {0x46496000}, + {0x46498000}, {0x4649a000}, {0x4649c000}, {0x4649e000}, + {0x464a0000}, {0x464a2000}, {0x464a4000}, {0x464a6000}, + {0x464a8000}, {0x464aa000}, {0x464ac000}, {0x464ae000}, + {0x464b0000}, {0x464b2000}, {0x464b4000}, {0x464b6000}, + {0x464b8000}, {0x464ba000}, {0x464bc000}, {0x464be000}, + {0x464c0000}, {0x464c2000}, {0x464c4000}, {0x464c6000}, + {0x464c8000}, {0x464ca000}, {0x464cc000}, {0x464ce000}, + {0x464d0000}, {0x464d2000}, {0x464d4000}, {0x464d6000}, + {0x464d8000}, {0x464da000}, {0x464dc000}, {0x464de000}, + {0x464e0000}, {0x464e2000}, {0x464e4000}, {0x464e6000}, + {0x464e8000}, {0x464ea000}, {0x464ec000}, {0x464ee000}, + {0x464f0000}, {0x464f2000}, {0x464f4000}, {0x464f6000}, + {0x464f8000}, {0x464fa000}, {0x464fc000}, {0x464fe000}, + {0x46500000}, {0x46502000}, {0x46504000}, {0x46506000}, + {0x46508000}, {0x4650a000}, {0x4650c000}, {0x4650e000}, + {0x46510000}, {0x46512000}, {0x46514000}, {0x46516000}, + {0x46518000}, {0x4651a000}, {0x4651c000}, {0x4651e000}, + {0x46520000}, {0x46522000}, {0x46524000}, {0x46526000}, + {0x46528000}, {0x4652a000}, {0x4652c000}, {0x4652e000}, + {0x46530000}, {0x46532000}, {0x46534000}, {0x46536000}, + {0x46538000}, {0x4653a000}, {0x4653c000}, {0x4653e000}, + {0x46540000}, {0x46542000}, {0x46544000}, {0x46546000}, + {0x46548000}, {0x4654a000}, {0x4654c000}, {0x4654e000}, + {0x46550000}, {0x46552000}, {0x46554000}, {0x46556000}, + {0x46558000}, {0x4655a000}, {0x4655c000}, {0x4655e000}, + {0x46560000}, {0x46562000}, {0x46564000}, {0x46566000}, + {0x46568000}, {0x4656a000}, {0x4656c000}, {0x4656e000}, + {0x46570000}, {0x46572000}, {0x46574000}, {0x46576000}, + {0x46578000}, {0x4657a000}, {0x4657c000}, {0x4657e000}, + {0x46580000}, {0x46582000}, {0x46584000}, {0x46586000}, + {0x46588000}, {0x4658a000}, {0x4658c000}, {0x4658e000}, + {0x46590000}, {0x46592000}, {0x46594000}, {0x46596000}, + {0x46598000}, {0x4659a000}, {0x4659c000}, {0x4659e000}, + {0x465a0000}, {0x465a2000}, {0x465a4000}, {0x465a6000}, + {0x465a8000}, {0x465aa000}, {0x465ac000}, {0x465ae000}, + {0x465b0000}, {0x465b2000}, {0x465b4000}, {0x465b6000}, + {0x465b8000}, {0x465ba000}, {0x465bc000}, {0x465be000}, + {0x465c0000}, {0x465c2000}, {0x465c4000}, {0x465c6000}, + {0x465c8000}, {0x465ca000}, {0x465cc000}, {0x465ce000}, + {0x465d0000}, {0x465d2000}, {0x465d4000}, {0x465d6000}, + {0x465d8000}, {0x465da000}, {0x465dc000}, {0x465de000}, + {0x465e0000}, {0x465e2000}, {0x465e4000}, {0x465e6000}, + {0x465e8000}, {0x465ea000}, {0x465ec000}, {0x465ee000}, + {0x465f0000}, {0x465f2000}, {0x465f4000}, {0x465f6000}, + {0x465f8000}, {0x465fa000}, {0x465fc000}, {0x465fe000}, + {0x46600000}, {0x46602000}, {0x46604000}, {0x46606000}, + {0x46608000}, {0x4660a000}, {0x4660c000}, {0x4660e000}, + {0x46610000}, {0x46612000}, {0x46614000}, {0x46616000}, + {0x46618000}, {0x4661a000}, {0x4661c000}, {0x4661e000}, + {0x46620000}, {0x46622000}, {0x46624000}, {0x46626000}, + {0x46628000}, {0x4662a000}, {0x4662c000}, {0x4662e000}, + {0x46630000}, {0x46632000}, {0x46634000}, {0x46636000}, + {0x46638000}, {0x4663a000}, {0x4663c000}, {0x4663e000}, + {0x46640000}, {0x46642000}, {0x46644000}, {0x46646000}, + {0x46648000}, {0x4664a000}, {0x4664c000}, {0x4664e000}, + {0x46650000}, {0x46652000}, {0x46654000}, {0x46656000}, + {0x46658000}, {0x4665a000}, {0x4665c000}, {0x4665e000}, + {0x46660000}, {0x46662000}, {0x46664000}, {0x46666000}, + {0x46668000}, {0x4666a000}, {0x4666c000}, {0x4666e000}, + {0x46670000}, {0x46672000}, {0x46674000}, {0x46676000}, + {0x46678000}, {0x4667a000}, {0x4667c000}, {0x4667e000}, + {0x46680000}, {0x46682000}, {0x46684000}, {0x46686000}, + {0x46688000}, {0x4668a000}, {0x4668c000}, {0x4668e000}, + {0x46690000}, {0x46692000}, {0x46694000}, {0x46696000}, + {0x46698000}, {0x4669a000}, {0x4669c000}, {0x4669e000}, + {0x466a0000}, {0x466a2000}, {0x466a4000}, {0x466a6000}, + {0x466a8000}, {0x466aa000}, {0x466ac000}, {0x466ae000}, + {0x466b0000}, {0x466b2000}, {0x466b4000}, {0x466b6000}, + {0x466b8000}, {0x466ba000}, {0x466bc000}, {0x466be000}, + {0x466c0000}, {0x466c2000}, {0x466c4000}, {0x466c6000}, + {0x466c8000}, {0x466ca000}, {0x466cc000}, {0x466ce000}, + {0x466d0000}, {0x466d2000}, {0x466d4000}, {0x466d6000}, + {0x466d8000}, {0x466da000}, {0x466dc000}, {0x466de000}, + {0x466e0000}, {0x466e2000}, {0x466e4000}, {0x466e6000}, + {0x466e8000}, {0x466ea000}, {0x466ec000}, {0x466ee000}, + {0x466f0000}, {0x466f2000}, {0x466f4000}, {0x466f6000}, + {0x466f8000}, {0x466fa000}, {0x466fc000}, {0x466fe000}, + {0x46700000}, {0x46702000}, {0x46704000}, {0x46706000}, + {0x46708000}, {0x4670a000}, {0x4670c000}, {0x4670e000}, + {0x46710000}, {0x46712000}, {0x46714000}, {0x46716000}, + {0x46718000}, {0x4671a000}, {0x4671c000}, {0x4671e000}, + {0x46720000}, {0x46722000}, {0x46724000}, {0x46726000}, + {0x46728000}, {0x4672a000}, {0x4672c000}, {0x4672e000}, + {0x46730000}, {0x46732000}, {0x46734000}, {0x46736000}, + {0x46738000}, {0x4673a000}, {0x4673c000}, {0x4673e000}, + {0x46740000}, {0x46742000}, {0x46744000}, {0x46746000}, + {0x46748000}, {0x4674a000}, {0x4674c000}, {0x4674e000}, + {0x46750000}, {0x46752000}, {0x46754000}, {0x46756000}, + {0x46758000}, {0x4675a000}, {0x4675c000}, {0x4675e000}, + {0x46760000}, {0x46762000}, {0x46764000}, {0x46766000}, + {0x46768000}, {0x4676a000}, {0x4676c000}, {0x4676e000}, + {0x46770000}, {0x46772000}, {0x46774000}, {0x46776000}, + {0x46778000}, {0x4677a000}, {0x4677c000}, {0x4677e000}, + {0x46780000}, {0x46782000}, {0x46784000}, {0x46786000}, + {0x46788000}, {0x4678a000}, {0x4678c000}, {0x4678e000}, + {0x46790000}, {0x46792000}, {0x46794000}, {0x46796000}, + {0x46798000}, {0x4679a000}, {0x4679c000}, {0x4679e000}, + {0x467a0000}, {0x467a2000}, {0x467a4000}, {0x467a6000}, + {0x467a8000}, {0x467aa000}, {0x467ac000}, {0x467ae000}, + {0x467b0000}, {0x467b2000}, {0x467b4000}, {0x467b6000}, + {0x467b8000}, {0x467ba000}, {0x467bc000}, {0x467be000}, + {0x467c0000}, {0x467c2000}, {0x467c4000}, {0x467c6000}, + {0x467c8000}, {0x467ca000}, {0x467cc000}, {0x467ce000}, + {0x467d0000}, {0x467d2000}, {0x467d4000}, {0x467d6000}, + {0x467d8000}, {0x467da000}, {0x467dc000}, {0x467de000}, + {0x467e0000}, {0x467e2000}, {0x467e4000}, {0x467e6000}, + {0x467e8000}, {0x467ea000}, {0x467ec000}, {0x467ee000}, + {0x467f0000}, {0x467f2000}, {0x467f4000}, {0x467f6000}, + {0x467f8000}, {0x467fa000}, {0x467fc000}, {0x467fe000}, + {0x46800000}, {0x46802000}, {0x46804000}, {0x46806000}, + {0x46808000}, {0x4680a000}, {0x4680c000}, {0x4680e000}, + {0x46810000}, {0x46812000}, {0x46814000}, {0x46816000}, + {0x46818000}, {0x4681a000}, {0x4681c000}, {0x4681e000}, + {0x46820000}, {0x46822000}, {0x46824000}, {0x46826000}, + {0x46828000}, {0x4682a000}, {0x4682c000}, {0x4682e000}, + {0x46830000}, {0x46832000}, {0x46834000}, {0x46836000}, + {0x46838000}, {0x4683a000}, {0x4683c000}, {0x4683e000}, + {0x46840000}, {0x46842000}, {0x46844000}, {0x46846000}, + {0x46848000}, {0x4684a000}, {0x4684c000}, {0x4684e000}, + {0x46850000}, {0x46852000}, {0x46854000}, {0x46856000}, + {0x46858000}, {0x4685a000}, {0x4685c000}, {0x4685e000}, + {0x46860000}, {0x46862000}, {0x46864000}, {0x46866000}, + {0x46868000}, {0x4686a000}, {0x4686c000}, {0x4686e000}, + {0x46870000}, {0x46872000}, {0x46874000}, {0x46876000}, + {0x46878000}, {0x4687a000}, {0x4687c000}, {0x4687e000}, + {0x46880000}, {0x46882000}, {0x46884000}, {0x46886000}, + {0x46888000}, {0x4688a000}, {0x4688c000}, {0x4688e000}, + {0x46890000}, {0x46892000}, {0x46894000}, {0x46896000}, + {0x46898000}, {0x4689a000}, {0x4689c000}, {0x4689e000}, + {0x468a0000}, {0x468a2000}, {0x468a4000}, {0x468a6000}, + {0x468a8000}, {0x468aa000}, {0x468ac000}, {0x468ae000}, + {0x468b0000}, {0x468b2000}, {0x468b4000}, {0x468b6000}, + {0x468b8000}, {0x468ba000}, {0x468bc000}, {0x468be000}, + {0x468c0000}, {0x468c2000}, {0x468c4000}, {0x468c6000}, + {0x468c8000}, {0x468ca000}, {0x468cc000}, {0x468ce000}, + {0x468d0000}, {0x468d2000}, {0x468d4000}, {0x468d6000}, + {0x468d8000}, {0x468da000}, {0x468dc000}, {0x468de000}, + {0x468e0000}, {0x468e2000}, {0x468e4000}, {0x468e6000}, + {0x468e8000}, {0x468ea000}, {0x468ec000}, {0x468ee000}, + {0x468f0000}, {0x468f2000}, {0x468f4000}, {0x468f6000}, + {0x468f8000}, {0x468fa000}, {0x468fc000}, {0x468fe000}, + {0x46900000}, {0x46902000}, {0x46904000}, {0x46906000}, + {0x46908000}, {0x4690a000}, {0x4690c000}, {0x4690e000}, + {0x46910000}, {0x46912000}, {0x46914000}, {0x46916000}, + {0x46918000}, {0x4691a000}, {0x4691c000}, {0x4691e000}, + {0x46920000}, {0x46922000}, {0x46924000}, {0x46926000}, + {0x46928000}, {0x4692a000}, {0x4692c000}, {0x4692e000}, + {0x46930000}, {0x46932000}, {0x46934000}, {0x46936000}, + {0x46938000}, {0x4693a000}, {0x4693c000}, {0x4693e000}, + {0x46940000}, {0x46942000}, {0x46944000}, {0x46946000}, + {0x46948000}, {0x4694a000}, {0x4694c000}, {0x4694e000}, + {0x46950000}, {0x46952000}, {0x46954000}, {0x46956000}, + {0x46958000}, {0x4695a000}, {0x4695c000}, {0x4695e000}, + {0x46960000}, {0x46962000}, {0x46964000}, {0x46966000}, + {0x46968000}, {0x4696a000}, {0x4696c000}, {0x4696e000}, + {0x46970000}, {0x46972000}, {0x46974000}, {0x46976000}, + {0x46978000}, {0x4697a000}, {0x4697c000}, {0x4697e000}, + {0x46980000}, {0x46982000}, {0x46984000}, {0x46986000}, + {0x46988000}, {0x4698a000}, {0x4698c000}, {0x4698e000}, + {0x46990000}, {0x46992000}, {0x46994000}, {0x46996000}, + {0x46998000}, {0x4699a000}, {0x4699c000}, {0x4699e000}, + {0x469a0000}, {0x469a2000}, {0x469a4000}, {0x469a6000}, + {0x469a8000}, {0x469aa000}, {0x469ac000}, {0x469ae000}, + {0x469b0000}, {0x469b2000}, {0x469b4000}, {0x469b6000}, + {0x469b8000}, {0x469ba000}, {0x469bc000}, {0x469be000}, + {0x469c0000}, {0x469c2000}, {0x469c4000}, {0x469c6000}, + {0x469c8000}, {0x469ca000}, {0x469cc000}, {0x469ce000}, + {0x469d0000}, {0x469d2000}, {0x469d4000}, {0x469d6000}, + {0x469d8000}, {0x469da000}, {0x469dc000}, {0x469de000}, + {0x469e0000}, {0x469e2000}, {0x469e4000}, {0x469e6000}, + {0x469e8000}, {0x469ea000}, {0x469ec000}, {0x469ee000}, + {0x469f0000}, {0x469f2000}, {0x469f4000}, {0x469f6000}, + {0x469f8000}, {0x469fa000}, {0x469fc000}, {0x469fe000}, + {0x46a00000}, {0x46a02000}, {0x46a04000}, {0x46a06000}, + {0x46a08000}, {0x46a0a000}, {0x46a0c000}, {0x46a0e000}, + {0x46a10000}, {0x46a12000}, {0x46a14000}, {0x46a16000}, + {0x46a18000}, {0x46a1a000}, {0x46a1c000}, {0x46a1e000}, + {0x46a20000}, {0x46a22000}, {0x46a24000}, {0x46a26000}, + {0x46a28000}, {0x46a2a000}, {0x46a2c000}, {0x46a2e000}, + {0x46a30000}, {0x46a32000}, {0x46a34000}, {0x46a36000}, + {0x46a38000}, {0x46a3a000}, {0x46a3c000}, {0x46a3e000}, + {0x46a40000}, {0x46a42000}, {0x46a44000}, {0x46a46000}, + {0x46a48000}, {0x46a4a000}, {0x46a4c000}, {0x46a4e000}, + {0x46a50000}, {0x46a52000}, {0x46a54000}, {0x46a56000}, + {0x46a58000}, {0x46a5a000}, {0x46a5c000}, {0x46a5e000}, + {0x46a60000}, {0x46a62000}, {0x46a64000}, {0x46a66000}, + {0x46a68000}, {0x46a6a000}, {0x46a6c000}, {0x46a6e000}, + {0x46a70000}, {0x46a72000}, {0x46a74000}, {0x46a76000}, + {0x46a78000}, {0x46a7a000}, {0x46a7c000}, {0x46a7e000}, + {0x46a80000}, {0x46a82000}, {0x46a84000}, {0x46a86000}, + {0x46a88000}, {0x46a8a000}, {0x46a8c000}, {0x46a8e000}, + {0x46a90000}, {0x46a92000}, {0x46a94000}, {0x46a96000}, + {0x46a98000}, {0x46a9a000}, {0x46a9c000}, {0x46a9e000}, + {0x46aa0000}, {0x46aa2000}, {0x46aa4000}, {0x46aa6000}, + {0x46aa8000}, {0x46aaa000}, {0x46aac000}, {0x46aae000}, + {0x46ab0000}, {0x46ab2000}, {0x46ab4000}, {0x46ab6000}, + {0x46ab8000}, {0x46aba000}, {0x46abc000}, {0x46abe000}, + {0x46ac0000}, {0x46ac2000}, {0x46ac4000}, {0x46ac6000}, + {0x46ac8000}, {0x46aca000}, {0x46acc000}, {0x46ace000}, + {0x46ad0000}, {0x46ad2000}, {0x46ad4000}, {0x46ad6000}, + {0x46ad8000}, {0x46ada000}, {0x46adc000}, {0x46ade000}, + {0x46ae0000}, {0x46ae2000}, {0x46ae4000}, {0x46ae6000}, + {0x46ae8000}, {0x46aea000}, {0x46aec000}, {0x46aee000}, + {0x46af0000}, {0x46af2000}, {0x46af4000}, {0x46af6000}, + {0x46af8000}, {0x46afa000}, {0x46afc000}, {0x46afe000}, + {0x46b00000}, {0x46b02000}, {0x46b04000}, {0x46b06000}, + {0x46b08000}, {0x46b0a000}, {0x46b0c000}, {0x46b0e000}, + {0x46b10000}, {0x46b12000}, {0x46b14000}, {0x46b16000}, + {0x46b18000}, {0x46b1a000}, {0x46b1c000}, {0x46b1e000}, + {0x46b20000}, {0x46b22000}, {0x46b24000}, {0x46b26000}, + {0x46b28000}, {0x46b2a000}, {0x46b2c000}, {0x46b2e000}, + {0x46b30000}, {0x46b32000}, {0x46b34000}, {0x46b36000}, + {0x46b38000}, {0x46b3a000}, {0x46b3c000}, {0x46b3e000}, + {0x46b40000}, {0x46b42000}, {0x46b44000}, {0x46b46000}, + {0x46b48000}, {0x46b4a000}, {0x46b4c000}, {0x46b4e000}, + {0x46b50000}, {0x46b52000}, {0x46b54000}, {0x46b56000}, + {0x46b58000}, {0x46b5a000}, {0x46b5c000}, {0x46b5e000}, + {0x46b60000}, {0x46b62000}, {0x46b64000}, {0x46b66000}, + {0x46b68000}, {0x46b6a000}, {0x46b6c000}, {0x46b6e000}, + {0x46b70000}, {0x46b72000}, {0x46b74000}, {0x46b76000}, + {0x46b78000}, {0x46b7a000}, {0x46b7c000}, {0x46b7e000}, + {0x46b80000}, {0x46b82000}, {0x46b84000}, {0x46b86000}, + {0x46b88000}, {0x46b8a000}, {0x46b8c000}, {0x46b8e000}, + {0x46b90000}, {0x46b92000}, {0x46b94000}, {0x46b96000}, + {0x46b98000}, {0x46b9a000}, {0x46b9c000}, {0x46b9e000}, + {0x46ba0000}, {0x46ba2000}, {0x46ba4000}, {0x46ba6000}, + {0x46ba8000}, {0x46baa000}, {0x46bac000}, {0x46bae000}, + {0x46bb0000}, {0x46bb2000}, {0x46bb4000}, {0x46bb6000}, + {0x46bb8000}, {0x46bba000}, {0x46bbc000}, {0x46bbe000}, + {0x46bc0000}, {0x46bc2000}, {0x46bc4000}, {0x46bc6000}, + {0x46bc8000}, {0x46bca000}, {0x46bcc000}, {0x46bce000}, + {0x46bd0000}, {0x46bd2000}, {0x46bd4000}, {0x46bd6000}, + {0x46bd8000}, {0x46bda000}, {0x46bdc000}, {0x46bde000}, + {0x46be0000}, {0x46be2000}, {0x46be4000}, {0x46be6000}, + {0x46be8000}, {0x46bea000}, {0x46bec000}, {0x46bee000}, + {0x46bf0000}, {0x46bf2000}, {0x46bf4000}, {0x46bf6000}, + {0x46bf8000}, {0x46bfa000}, {0x46bfc000}, {0x46bfe000}, + {0x46c00000}, {0x46c02000}, {0x46c04000}, {0x46c06000}, + {0x46c08000}, {0x46c0a000}, {0x46c0c000}, {0x46c0e000}, + {0x46c10000}, {0x46c12000}, {0x46c14000}, {0x46c16000}, + {0x46c18000}, {0x46c1a000}, {0x46c1c000}, {0x46c1e000}, + {0x46c20000}, {0x46c22000}, {0x46c24000}, {0x46c26000}, + {0x46c28000}, {0x46c2a000}, {0x46c2c000}, {0x46c2e000}, + {0x46c30000}, {0x46c32000}, {0x46c34000}, {0x46c36000}, + {0x46c38000}, {0x46c3a000}, {0x46c3c000}, {0x46c3e000}, + {0x46c40000}, {0x46c42000}, {0x46c44000}, {0x46c46000}, + {0x46c48000}, {0x46c4a000}, {0x46c4c000}, {0x46c4e000}, + {0x46c50000}, {0x46c52000}, {0x46c54000}, {0x46c56000}, + {0x46c58000}, {0x46c5a000}, {0x46c5c000}, {0x46c5e000}, + {0x46c60000}, {0x46c62000}, {0x46c64000}, {0x46c66000}, + {0x46c68000}, {0x46c6a000}, {0x46c6c000}, {0x46c6e000}, + {0x46c70000}, {0x46c72000}, {0x46c74000}, {0x46c76000}, + {0x46c78000}, {0x46c7a000}, {0x46c7c000}, {0x46c7e000}, + {0x46c80000}, {0x46c82000}, {0x46c84000}, {0x46c86000}, + {0x46c88000}, {0x46c8a000}, {0x46c8c000}, {0x46c8e000}, + {0x46c90000}, {0x46c92000}, {0x46c94000}, {0x46c96000}, + {0x46c98000}, {0x46c9a000}, {0x46c9c000}, {0x46c9e000}, + {0x46ca0000}, {0x46ca2000}, {0x46ca4000}, {0x46ca6000}, + {0x46ca8000}, {0x46caa000}, {0x46cac000}, {0x46cae000}, + {0x46cb0000}, {0x46cb2000}, {0x46cb4000}, {0x46cb6000}, + {0x46cb8000}, {0x46cba000}, {0x46cbc000}, {0x46cbe000}, + {0x46cc0000}, {0x46cc2000}, {0x46cc4000}, {0x46cc6000}, + {0x46cc8000}, {0x46cca000}, {0x46ccc000}, {0x46cce000}, + {0x46cd0000}, {0x46cd2000}, {0x46cd4000}, {0x46cd6000}, + {0x46cd8000}, {0x46cda000}, {0x46cdc000}, {0x46cde000}, + {0x46ce0000}, {0x46ce2000}, {0x46ce4000}, {0x46ce6000}, + {0x46ce8000}, {0x46cea000}, {0x46cec000}, {0x46cee000}, + {0x46cf0000}, {0x46cf2000}, {0x46cf4000}, {0x46cf6000}, + {0x46cf8000}, {0x46cfa000}, {0x46cfc000}, {0x46cfe000}, + {0x46d00000}, {0x46d02000}, {0x46d04000}, {0x46d06000}, + {0x46d08000}, {0x46d0a000}, {0x46d0c000}, {0x46d0e000}, + {0x46d10000}, {0x46d12000}, {0x46d14000}, {0x46d16000}, + {0x46d18000}, {0x46d1a000}, {0x46d1c000}, {0x46d1e000}, + {0x46d20000}, {0x46d22000}, {0x46d24000}, {0x46d26000}, + {0x46d28000}, {0x46d2a000}, {0x46d2c000}, {0x46d2e000}, + {0x46d30000}, {0x46d32000}, {0x46d34000}, {0x46d36000}, + {0x46d38000}, {0x46d3a000}, {0x46d3c000}, {0x46d3e000}, + {0x46d40000}, {0x46d42000}, {0x46d44000}, {0x46d46000}, + {0x46d48000}, {0x46d4a000}, {0x46d4c000}, {0x46d4e000}, + {0x46d50000}, {0x46d52000}, {0x46d54000}, {0x46d56000}, + {0x46d58000}, {0x46d5a000}, {0x46d5c000}, {0x46d5e000}, + {0x46d60000}, {0x46d62000}, {0x46d64000}, {0x46d66000}, + {0x46d68000}, {0x46d6a000}, {0x46d6c000}, {0x46d6e000}, + {0x46d70000}, {0x46d72000}, {0x46d74000}, {0x46d76000}, + {0x46d78000}, {0x46d7a000}, {0x46d7c000}, {0x46d7e000}, + {0x46d80000}, {0x46d82000}, {0x46d84000}, {0x46d86000}, + {0x46d88000}, {0x46d8a000}, {0x46d8c000}, {0x46d8e000}, + {0x46d90000}, {0x46d92000}, {0x46d94000}, {0x46d96000}, + {0x46d98000}, {0x46d9a000}, {0x46d9c000}, {0x46d9e000}, + {0x46da0000}, {0x46da2000}, {0x46da4000}, {0x46da6000}, + {0x46da8000}, {0x46daa000}, {0x46dac000}, {0x46dae000}, + {0x46db0000}, {0x46db2000}, {0x46db4000}, {0x46db6000}, + {0x46db8000}, {0x46dba000}, {0x46dbc000}, {0x46dbe000}, + {0x46dc0000}, {0x46dc2000}, {0x46dc4000}, {0x46dc6000}, + {0x46dc8000}, {0x46dca000}, {0x46dcc000}, {0x46dce000}, + {0x46dd0000}, {0x46dd2000}, {0x46dd4000}, {0x46dd6000}, + {0x46dd8000}, {0x46dda000}, {0x46ddc000}, {0x46dde000}, + {0x46de0000}, {0x46de2000}, {0x46de4000}, {0x46de6000}, + {0x46de8000}, {0x46dea000}, {0x46dec000}, {0x46dee000}, + {0x46df0000}, {0x46df2000}, {0x46df4000}, {0x46df6000}, + {0x46df8000}, {0x46dfa000}, {0x46dfc000}, {0x46dfe000}, + {0x46e00000}, {0x46e02000}, {0x46e04000}, {0x46e06000}, + {0x46e08000}, {0x46e0a000}, {0x46e0c000}, {0x46e0e000}, + {0x46e10000}, {0x46e12000}, {0x46e14000}, {0x46e16000}, + {0x46e18000}, {0x46e1a000}, {0x46e1c000}, {0x46e1e000}, + {0x46e20000}, {0x46e22000}, {0x46e24000}, {0x46e26000}, + {0x46e28000}, {0x46e2a000}, {0x46e2c000}, {0x46e2e000}, + {0x46e30000}, {0x46e32000}, {0x46e34000}, {0x46e36000}, + {0x46e38000}, {0x46e3a000}, {0x46e3c000}, {0x46e3e000}, + {0x46e40000}, {0x46e42000}, {0x46e44000}, {0x46e46000}, + {0x46e48000}, {0x46e4a000}, {0x46e4c000}, {0x46e4e000}, + {0x46e50000}, {0x46e52000}, {0x46e54000}, {0x46e56000}, + {0x46e58000}, {0x46e5a000}, {0x46e5c000}, {0x46e5e000}, + {0x46e60000}, {0x46e62000}, {0x46e64000}, {0x46e66000}, + {0x46e68000}, {0x46e6a000}, {0x46e6c000}, {0x46e6e000}, + {0x46e70000}, {0x46e72000}, {0x46e74000}, {0x46e76000}, + {0x46e78000}, {0x46e7a000}, {0x46e7c000}, {0x46e7e000}, + {0x46e80000}, {0x46e82000}, {0x46e84000}, {0x46e86000}, + {0x46e88000}, {0x46e8a000}, {0x46e8c000}, {0x46e8e000}, + {0x46e90000}, {0x46e92000}, {0x46e94000}, {0x46e96000}, + {0x46e98000}, {0x46e9a000}, {0x46e9c000}, {0x46e9e000}, + {0x46ea0000}, {0x46ea2000}, {0x46ea4000}, {0x46ea6000}, + {0x46ea8000}, {0x46eaa000}, {0x46eac000}, {0x46eae000}, + {0x46eb0000}, {0x46eb2000}, {0x46eb4000}, {0x46eb6000}, + {0x46eb8000}, {0x46eba000}, {0x46ebc000}, {0x46ebe000}, + {0x46ec0000}, {0x46ec2000}, {0x46ec4000}, {0x46ec6000}, + {0x46ec8000}, {0x46eca000}, {0x46ecc000}, {0x46ece000}, + {0x46ed0000}, {0x46ed2000}, {0x46ed4000}, {0x46ed6000}, + {0x46ed8000}, {0x46eda000}, {0x46edc000}, {0x46ede000}, + {0x46ee0000}, {0x46ee2000}, {0x46ee4000}, {0x46ee6000}, + {0x46ee8000}, {0x46eea000}, {0x46eec000}, {0x46eee000}, + {0x46ef0000}, {0x46ef2000}, {0x46ef4000}, {0x46ef6000}, + {0x46ef8000}, {0x46efa000}, {0x46efc000}, {0x46efe000}, + {0x46f00000}, {0x46f02000}, {0x46f04000}, {0x46f06000}, + {0x46f08000}, {0x46f0a000}, {0x46f0c000}, {0x46f0e000}, + {0x46f10000}, {0x46f12000}, {0x46f14000}, {0x46f16000}, + {0x46f18000}, {0x46f1a000}, {0x46f1c000}, {0x46f1e000}, + {0x46f20000}, {0x46f22000}, {0x46f24000}, {0x46f26000}, + {0x46f28000}, {0x46f2a000}, {0x46f2c000}, {0x46f2e000}, + {0x46f30000}, {0x46f32000}, {0x46f34000}, {0x46f36000}, + {0x46f38000}, {0x46f3a000}, {0x46f3c000}, {0x46f3e000}, + {0x46f40000}, {0x46f42000}, {0x46f44000}, {0x46f46000}, + {0x46f48000}, {0x46f4a000}, {0x46f4c000}, {0x46f4e000}, + {0x46f50000}, {0x46f52000}, {0x46f54000}, {0x46f56000}, + {0x46f58000}, {0x46f5a000}, {0x46f5c000}, {0x46f5e000}, + {0x46f60000}, {0x46f62000}, {0x46f64000}, {0x46f66000}, + {0x46f68000}, {0x46f6a000}, {0x46f6c000}, {0x46f6e000}, + {0x46f70000}, {0x46f72000}, {0x46f74000}, {0x46f76000}, + {0x46f78000}, {0x46f7a000}, {0x46f7c000}, {0x46f7e000}, + {0x46f80000}, {0x46f82000}, {0x46f84000}, {0x46f86000}, + {0x46f88000}, {0x46f8a000}, {0x46f8c000}, {0x46f8e000}, + {0x46f90000}, {0x46f92000}, {0x46f94000}, {0x46f96000}, + {0x46f98000}, {0x46f9a000}, {0x46f9c000}, {0x46f9e000}, + {0x46fa0000}, {0x46fa2000}, {0x46fa4000}, {0x46fa6000}, + {0x46fa8000}, {0x46faa000}, {0x46fac000}, {0x46fae000}, + {0x46fb0000}, {0x46fb2000}, {0x46fb4000}, {0x46fb6000}, + {0x46fb8000}, {0x46fba000}, {0x46fbc000}, {0x46fbe000}, + {0x46fc0000}, {0x46fc2000}, {0x46fc4000}, {0x46fc6000}, + {0x46fc8000}, {0x46fca000}, {0x46fcc000}, {0x46fce000}, + {0x46fd0000}, {0x46fd2000}, {0x46fd4000}, {0x46fd6000}, + {0x46fd8000}, {0x46fda000}, {0x46fdc000}, {0x46fde000}, + {0x46fe0000}, {0x46fe2000}, {0x46fe4000}, {0x46fe6000}, + {0x46fe8000}, {0x46fea000}, {0x46fec000}, {0x46fee000}, + {0x46ff0000}, {0x46ff2000}, {0x46ff4000}, {0x46ff6000}, + {0x46ff8000}, {0x46ffa000}, {0x46ffc000}, {0x46ffe000}, + {0x47000000}, {0x47002000}, {0x47004000}, {0x47006000}, + {0x47008000}, {0x4700a000}, {0x4700c000}, {0x4700e000}, + {0x47010000}, {0x47012000}, {0x47014000}, {0x47016000}, + {0x47018000}, {0x4701a000}, {0x4701c000}, {0x4701e000}, + {0x47020000}, {0x47022000}, {0x47024000}, {0x47026000}, + {0x47028000}, {0x4702a000}, {0x4702c000}, {0x4702e000}, + {0x47030000}, {0x47032000}, {0x47034000}, {0x47036000}, + {0x47038000}, {0x4703a000}, {0x4703c000}, {0x4703e000}, + {0x47040000}, {0x47042000}, {0x47044000}, {0x47046000}, + {0x47048000}, {0x4704a000}, {0x4704c000}, {0x4704e000}, + {0x47050000}, {0x47052000}, {0x47054000}, {0x47056000}, + {0x47058000}, {0x4705a000}, {0x4705c000}, {0x4705e000}, + {0x47060000}, {0x47062000}, {0x47064000}, {0x47066000}, + {0x47068000}, {0x4706a000}, {0x4706c000}, {0x4706e000}, + {0x47070000}, {0x47072000}, {0x47074000}, {0x47076000}, + {0x47078000}, {0x4707a000}, {0x4707c000}, {0x4707e000}, + {0x47080000}, {0x47082000}, {0x47084000}, {0x47086000}, + {0x47088000}, {0x4708a000}, {0x4708c000}, {0x4708e000}, + {0x47090000}, {0x47092000}, {0x47094000}, {0x47096000}, + {0x47098000}, {0x4709a000}, {0x4709c000}, {0x4709e000}, + {0x470a0000}, {0x470a2000}, {0x470a4000}, {0x470a6000}, + {0x470a8000}, {0x470aa000}, {0x470ac000}, {0x470ae000}, + {0x470b0000}, {0x470b2000}, {0x470b4000}, {0x470b6000}, + {0x470b8000}, {0x470ba000}, {0x470bc000}, {0x470be000}, + {0x470c0000}, {0x470c2000}, {0x470c4000}, {0x470c6000}, + {0x470c8000}, {0x470ca000}, {0x470cc000}, {0x470ce000}, + {0x470d0000}, {0x470d2000}, {0x470d4000}, {0x470d6000}, + {0x470d8000}, {0x470da000}, {0x470dc000}, {0x470de000}, + {0x470e0000}, {0x470e2000}, {0x470e4000}, {0x470e6000}, + {0x470e8000}, {0x470ea000}, {0x470ec000}, {0x470ee000}, + {0x470f0000}, {0x470f2000}, {0x470f4000}, {0x470f6000}, + {0x470f8000}, {0x470fa000}, {0x470fc000}, {0x470fe000}, + {0x47100000}, {0x47102000}, {0x47104000}, {0x47106000}, + {0x47108000}, {0x4710a000}, {0x4710c000}, {0x4710e000}, + {0x47110000}, {0x47112000}, {0x47114000}, {0x47116000}, + {0x47118000}, {0x4711a000}, {0x4711c000}, {0x4711e000}, + {0x47120000}, {0x47122000}, {0x47124000}, {0x47126000}, + {0x47128000}, {0x4712a000}, {0x4712c000}, {0x4712e000}, + {0x47130000}, {0x47132000}, {0x47134000}, {0x47136000}, + {0x47138000}, {0x4713a000}, {0x4713c000}, {0x4713e000}, + {0x47140000}, {0x47142000}, {0x47144000}, {0x47146000}, + {0x47148000}, {0x4714a000}, {0x4714c000}, {0x4714e000}, + {0x47150000}, {0x47152000}, {0x47154000}, {0x47156000}, + {0x47158000}, {0x4715a000}, {0x4715c000}, {0x4715e000}, + {0x47160000}, {0x47162000}, {0x47164000}, {0x47166000}, + {0x47168000}, {0x4716a000}, {0x4716c000}, {0x4716e000}, + {0x47170000}, {0x47172000}, {0x47174000}, {0x47176000}, + {0x47178000}, {0x4717a000}, {0x4717c000}, {0x4717e000}, + {0x47180000}, {0x47182000}, {0x47184000}, {0x47186000}, + {0x47188000}, {0x4718a000}, {0x4718c000}, {0x4718e000}, + {0x47190000}, {0x47192000}, {0x47194000}, {0x47196000}, + {0x47198000}, {0x4719a000}, {0x4719c000}, {0x4719e000}, + {0x471a0000}, {0x471a2000}, {0x471a4000}, {0x471a6000}, + {0x471a8000}, {0x471aa000}, {0x471ac000}, {0x471ae000}, + {0x471b0000}, {0x471b2000}, {0x471b4000}, {0x471b6000}, + {0x471b8000}, {0x471ba000}, {0x471bc000}, {0x471be000}, + {0x471c0000}, {0x471c2000}, {0x471c4000}, {0x471c6000}, + {0x471c8000}, {0x471ca000}, {0x471cc000}, {0x471ce000}, + {0x471d0000}, {0x471d2000}, {0x471d4000}, {0x471d6000}, + {0x471d8000}, {0x471da000}, {0x471dc000}, {0x471de000}, + {0x471e0000}, {0x471e2000}, {0x471e4000}, {0x471e6000}, + {0x471e8000}, {0x471ea000}, {0x471ec000}, {0x471ee000}, + {0x471f0000}, {0x471f2000}, {0x471f4000}, {0x471f6000}, + {0x471f8000}, {0x471fa000}, {0x471fc000}, {0x471fe000}, + {0x47200000}, {0x47202000}, {0x47204000}, {0x47206000}, + {0x47208000}, {0x4720a000}, {0x4720c000}, {0x4720e000}, + {0x47210000}, {0x47212000}, {0x47214000}, {0x47216000}, + {0x47218000}, {0x4721a000}, {0x4721c000}, {0x4721e000}, + {0x47220000}, {0x47222000}, {0x47224000}, {0x47226000}, + {0x47228000}, {0x4722a000}, {0x4722c000}, {0x4722e000}, + {0x47230000}, {0x47232000}, {0x47234000}, {0x47236000}, + {0x47238000}, {0x4723a000}, {0x4723c000}, {0x4723e000}, + {0x47240000}, {0x47242000}, {0x47244000}, {0x47246000}, + {0x47248000}, {0x4724a000}, {0x4724c000}, {0x4724e000}, + {0x47250000}, {0x47252000}, {0x47254000}, {0x47256000}, + {0x47258000}, {0x4725a000}, {0x4725c000}, {0x4725e000}, + {0x47260000}, {0x47262000}, {0x47264000}, {0x47266000}, + {0x47268000}, {0x4726a000}, {0x4726c000}, {0x4726e000}, + {0x47270000}, {0x47272000}, {0x47274000}, {0x47276000}, + {0x47278000}, {0x4727a000}, {0x4727c000}, {0x4727e000}, + {0x47280000}, {0x47282000}, {0x47284000}, {0x47286000}, + {0x47288000}, {0x4728a000}, {0x4728c000}, {0x4728e000}, + {0x47290000}, {0x47292000}, {0x47294000}, {0x47296000}, + {0x47298000}, {0x4729a000}, {0x4729c000}, {0x4729e000}, + {0x472a0000}, {0x472a2000}, {0x472a4000}, {0x472a6000}, + {0x472a8000}, {0x472aa000}, {0x472ac000}, {0x472ae000}, + {0x472b0000}, {0x472b2000}, {0x472b4000}, {0x472b6000}, + {0x472b8000}, {0x472ba000}, {0x472bc000}, {0x472be000}, + {0x472c0000}, {0x472c2000}, {0x472c4000}, {0x472c6000}, + {0x472c8000}, {0x472ca000}, {0x472cc000}, {0x472ce000}, + {0x472d0000}, {0x472d2000}, {0x472d4000}, {0x472d6000}, + {0x472d8000}, {0x472da000}, {0x472dc000}, {0x472de000}, + {0x472e0000}, {0x472e2000}, {0x472e4000}, {0x472e6000}, + {0x472e8000}, {0x472ea000}, {0x472ec000}, {0x472ee000}, + {0x472f0000}, {0x472f2000}, {0x472f4000}, {0x472f6000}, + {0x472f8000}, {0x472fa000}, {0x472fc000}, {0x472fe000}, + {0x47300000}, {0x47302000}, {0x47304000}, {0x47306000}, + {0x47308000}, {0x4730a000}, {0x4730c000}, {0x4730e000}, + {0x47310000}, {0x47312000}, {0x47314000}, {0x47316000}, + {0x47318000}, {0x4731a000}, {0x4731c000}, {0x4731e000}, + {0x47320000}, {0x47322000}, {0x47324000}, {0x47326000}, + {0x47328000}, {0x4732a000}, {0x4732c000}, {0x4732e000}, + {0x47330000}, {0x47332000}, {0x47334000}, {0x47336000}, + {0x47338000}, {0x4733a000}, {0x4733c000}, {0x4733e000}, + {0x47340000}, {0x47342000}, {0x47344000}, {0x47346000}, + {0x47348000}, {0x4734a000}, {0x4734c000}, {0x4734e000}, + {0x47350000}, {0x47352000}, {0x47354000}, {0x47356000}, + {0x47358000}, {0x4735a000}, {0x4735c000}, {0x4735e000}, + {0x47360000}, {0x47362000}, {0x47364000}, {0x47366000}, + {0x47368000}, {0x4736a000}, {0x4736c000}, {0x4736e000}, + {0x47370000}, {0x47372000}, {0x47374000}, {0x47376000}, + {0x47378000}, {0x4737a000}, {0x4737c000}, {0x4737e000}, + {0x47380000}, {0x47382000}, {0x47384000}, {0x47386000}, + {0x47388000}, {0x4738a000}, {0x4738c000}, {0x4738e000}, + {0x47390000}, {0x47392000}, {0x47394000}, {0x47396000}, + {0x47398000}, {0x4739a000}, {0x4739c000}, {0x4739e000}, + {0x473a0000}, {0x473a2000}, {0x473a4000}, {0x473a6000}, + {0x473a8000}, {0x473aa000}, {0x473ac000}, {0x473ae000}, + {0x473b0000}, {0x473b2000}, {0x473b4000}, {0x473b6000}, + {0x473b8000}, {0x473ba000}, {0x473bc000}, {0x473be000}, + {0x473c0000}, {0x473c2000}, {0x473c4000}, {0x473c6000}, + {0x473c8000}, {0x473ca000}, {0x473cc000}, {0x473ce000}, + {0x473d0000}, {0x473d2000}, {0x473d4000}, {0x473d6000}, + {0x473d8000}, {0x473da000}, {0x473dc000}, {0x473de000}, + {0x473e0000}, {0x473e2000}, {0x473e4000}, {0x473e6000}, + {0x473e8000}, {0x473ea000}, {0x473ec000}, {0x473ee000}, + {0x473f0000}, {0x473f2000}, {0x473f4000}, {0x473f6000}, + {0x473f8000}, {0x473fa000}, {0x473fc000}, {0x473fe000}, + {0x47400000}, {0x47402000}, {0x47404000}, {0x47406000}, + {0x47408000}, {0x4740a000}, {0x4740c000}, {0x4740e000}, + {0x47410000}, {0x47412000}, {0x47414000}, {0x47416000}, + {0x47418000}, {0x4741a000}, {0x4741c000}, {0x4741e000}, + {0x47420000}, {0x47422000}, {0x47424000}, {0x47426000}, + {0x47428000}, {0x4742a000}, {0x4742c000}, {0x4742e000}, + {0x47430000}, {0x47432000}, {0x47434000}, {0x47436000}, + {0x47438000}, {0x4743a000}, {0x4743c000}, {0x4743e000}, + {0x47440000}, {0x47442000}, {0x47444000}, {0x47446000}, + {0x47448000}, {0x4744a000}, {0x4744c000}, {0x4744e000}, + {0x47450000}, {0x47452000}, {0x47454000}, {0x47456000}, + {0x47458000}, {0x4745a000}, {0x4745c000}, {0x4745e000}, + {0x47460000}, {0x47462000}, {0x47464000}, {0x47466000}, + {0x47468000}, {0x4746a000}, {0x4746c000}, {0x4746e000}, + {0x47470000}, {0x47472000}, {0x47474000}, {0x47476000}, + {0x47478000}, {0x4747a000}, {0x4747c000}, {0x4747e000}, + {0x47480000}, {0x47482000}, {0x47484000}, {0x47486000}, + {0x47488000}, {0x4748a000}, {0x4748c000}, {0x4748e000}, + {0x47490000}, {0x47492000}, {0x47494000}, {0x47496000}, + {0x47498000}, {0x4749a000}, {0x4749c000}, {0x4749e000}, + {0x474a0000}, {0x474a2000}, {0x474a4000}, {0x474a6000}, + {0x474a8000}, {0x474aa000}, {0x474ac000}, {0x474ae000}, + {0x474b0000}, {0x474b2000}, {0x474b4000}, {0x474b6000}, + {0x474b8000}, {0x474ba000}, {0x474bc000}, {0x474be000}, + {0x474c0000}, {0x474c2000}, {0x474c4000}, {0x474c6000}, + {0x474c8000}, {0x474ca000}, {0x474cc000}, {0x474ce000}, + {0x474d0000}, {0x474d2000}, {0x474d4000}, {0x474d6000}, + {0x474d8000}, {0x474da000}, {0x474dc000}, {0x474de000}, + {0x474e0000}, {0x474e2000}, {0x474e4000}, {0x474e6000}, + {0x474e8000}, {0x474ea000}, {0x474ec000}, {0x474ee000}, + {0x474f0000}, {0x474f2000}, {0x474f4000}, {0x474f6000}, + {0x474f8000}, {0x474fa000}, {0x474fc000}, {0x474fe000}, + {0x47500000}, {0x47502000}, {0x47504000}, {0x47506000}, + {0x47508000}, {0x4750a000}, {0x4750c000}, {0x4750e000}, + {0x47510000}, {0x47512000}, {0x47514000}, {0x47516000}, + {0x47518000}, {0x4751a000}, {0x4751c000}, {0x4751e000}, + {0x47520000}, {0x47522000}, {0x47524000}, {0x47526000}, + {0x47528000}, {0x4752a000}, {0x4752c000}, {0x4752e000}, + {0x47530000}, {0x47532000}, {0x47534000}, {0x47536000}, + {0x47538000}, {0x4753a000}, {0x4753c000}, {0x4753e000}, + {0x47540000}, {0x47542000}, {0x47544000}, {0x47546000}, + {0x47548000}, {0x4754a000}, {0x4754c000}, {0x4754e000}, + {0x47550000}, {0x47552000}, {0x47554000}, {0x47556000}, + {0x47558000}, {0x4755a000}, {0x4755c000}, {0x4755e000}, + {0x47560000}, {0x47562000}, {0x47564000}, {0x47566000}, + {0x47568000}, {0x4756a000}, {0x4756c000}, {0x4756e000}, + {0x47570000}, {0x47572000}, {0x47574000}, {0x47576000}, + {0x47578000}, {0x4757a000}, {0x4757c000}, {0x4757e000}, + {0x47580000}, {0x47582000}, {0x47584000}, {0x47586000}, + {0x47588000}, {0x4758a000}, {0x4758c000}, {0x4758e000}, + {0x47590000}, {0x47592000}, {0x47594000}, {0x47596000}, + {0x47598000}, {0x4759a000}, {0x4759c000}, {0x4759e000}, + {0x475a0000}, {0x475a2000}, {0x475a4000}, {0x475a6000}, + {0x475a8000}, {0x475aa000}, {0x475ac000}, {0x475ae000}, + {0x475b0000}, {0x475b2000}, {0x475b4000}, {0x475b6000}, + {0x475b8000}, {0x475ba000}, {0x475bc000}, {0x475be000}, + {0x475c0000}, {0x475c2000}, {0x475c4000}, {0x475c6000}, + {0x475c8000}, {0x475ca000}, {0x475cc000}, {0x475ce000}, + {0x475d0000}, {0x475d2000}, {0x475d4000}, {0x475d6000}, + {0x475d8000}, {0x475da000}, {0x475dc000}, {0x475de000}, + {0x475e0000}, {0x475e2000}, {0x475e4000}, {0x475e6000}, + {0x475e8000}, {0x475ea000}, {0x475ec000}, {0x475ee000}, + {0x475f0000}, {0x475f2000}, {0x475f4000}, {0x475f6000}, + {0x475f8000}, {0x475fa000}, {0x475fc000}, {0x475fe000}, + {0x47600000}, {0x47602000}, {0x47604000}, {0x47606000}, + {0x47608000}, {0x4760a000}, {0x4760c000}, {0x4760e000}, + {0x47610000}, {0x47612000}, {0x47614000}, {0x47616000}, + {0x47618000}, {0x4761a000}, {0x4761c000}, {0x4761e000}, + {0x47620000}, {0x47622000}, {0x47624000}, {0x47626000}, + {0x47628000}, {0x4762a000}, {0x4762c000}, {0x4762e000}, + {0x47630000}, {0x47632000}, {0x47634000}, {0x47636000}, + {0x47638000}, {0x4763a000}, {0x4763c000}, {0x4763e000}, + {0x47640000}, {0x47642000}, {0x47644000}, {0x47646000}, + {0x47648000}, {0x4764a000}, {0x4764c000}, {0x4764e000}, + {0x47650000}, {0x47652000}, {0x47654000}, {0x47656000}, + {0x47658000}, {0x4765a000}, {0x4765c000}, {0x4765e000}, + {0x47660000}, {0x47662000}, {0x47664000}, {0x47666000}, + {0x47668000}, {0x4766a000}, {0x4766c000}, {0x4766e000}, + {0x47670000}, {0x47672000}, {0x47674000}, {0x47676000}, + {0x47678000}, {0x4767a000}, {0x4767c000}, {0x4767e000}, + {0x47680000}, {0x47682000}, {0x47684000}, {0x47686000}, + {0x47688000}, {0x4768a000}, {0x4768c000}, {0x4768e000}, + {0x47690000}, {0x47692000}, {0x47694000}, {0x47696000}, + {0x47698000}, {0x4769a000}, {0x4769c000}, {0x4769e000}, + {0x476a0000}, {0x476a2000}, {0x476a4000}, {0x476a6000}, + {0x476a8000}, {0x476aa000}, {0x476ac000}, {0x476ae000}, + {0x476b0000}, {0x476b2000}, {0x476b4000}, {0x476b6000}, + {0x476b8000}, {0x476ba000}, {0x476bc000}, {0x476be000}, + {0x476c0000}, {0x476c2000}, {0x476c4000}, {0x476c6000}, + {0x476c8000}, {0x476ca000}, {0x476cc000}, {0x476ce000}, + {0x476d0000}, {0x476d2000}, {0x476d4000}, {0x476d6000}, + {0x476d8000}, {0x476da000}, {0x476dc000}, {0x476de000}, + {0x476e0000}, {0x476e2000}, {0x476e4000}, {0x476e6000}, + {0x476e8000}, {0x476ea000}, {0x476ec000}, {0x476ee000}, + {0x476f0000}, {0x476f2000}, {0x476f4000}, {0x476f6000}, + {0x476f8000}, {0x476fa000}, {0x476fc000}, {0x476fe000}, + {0x47700000}, {0x47702000}, {0x47704000}, {0x47706000}, + {0x47708000}, {0x4770a000}, {0x4770c000}, {0x4770e000}, + {0x47710000}, {0x47712000}, {0x47714000}, {0x47716000}, + {0x47718000}, {0x4771a000}, {0x4771c000}, {0x4771e000}, + {0x47720000}, {0x47722000}, {0x47724000}, {0x47726000}, + {0x47728000}, {0x4772a000}, {0x4772c000}, {0x4772e000}, + {0x47730000}, {0x47732000}, {0x47734000}, {0x47736000}, + {0x47738000}, {0x4773a000}, {0x4773c000}, {0x4773e000}, + {0x47740000}, {0x47742000}, {0x47744000}, {0x47746000}, + {0x47748000}, {0x4774a000}, {0x4774c000}, {0x4774e000}, + {0x47750000}, {0x47752000}, {0x47754000}, {0x47756000}, + {0x47758000}, {0x4775a000}, {0x4775c000}, {0x4775e000}, + {0x47760000}, {0x47762000}, {0x47764000}, {0x47766000}, + {0x47768000}, {0x4776a000}, {0x4776c000}, {0x4776e000}, + {0x47770000}, {0x47772000}, {0x47774000}, {0x47776000}, + {0x47778000}, {0x4777a000}, {0x4777c000}, {0x4777e000}, + {0x47780000}, {0x47782000}, {0x47784000}, {0x47786000}, + {0x47788000}, {0x4778a000}, {0x4778c000}, {0x4778e000}, + {0x47790000}, {0x47792000}, {0x47794000}, {0x47796000}, + {0x47798000}, {0x4779a000}, {0x4779c000}, {0x4779e000}, + {0x477a0000}, {0x477a2000}, {0x477a4000}, {0x477a6000}, + {0x477a8000}, {0x477aa000}, {0x477ac000}, {0x477ae000}, + {0x477b0000}, {0x477b2000}, {0x477b4000}, {0x477b6000}, + {0x477b8000}, {0x477ba000}, {0x477bc000}, {0x477be000}, + {0x477c0000}, {0x477c2000}, {0x477c4000}, {0x477c6000}, + {0x477c8000}, {0x477ca000}, {0x477cc000}, {0x477ce000}, + {0x477d0000}, {0x477d2000}, {0x477d4000}, {0x477d6000}, + {0x477d8000}, {0x477da000}, {0x477dc000}, {0x477de000}, + {0x477e0000}, {0x477e2000}, {0x477e4000}, {0x477e6000}, + {0x477e8000}, {0x477ea000}, {0x477ec000}, {0x477ee000}, + {0x477f0000}, {0x477f2000}, {0x477f4000}, {0x477f6000}, + {0x477f8000}, {0x477fa000}, {0x477fc000}, {0x477fe000}, + {0x7f800000}, {0x7f802000}, {0x7f804000}, {0x7f806000}, + {0x7f808000}, {0x7f80a000}, {0x7f80c000}, {0x7f80e000}, + {0x7f810000}, {0x7f812000}, {0x7f814000}, {0x7f816000}, + {0x7f818000}, {0x7f81a000}, {0x7f81c000}, {0x7f81e000}, + {0x7f820000}, {0x7f822000}, {0x7f824000}, {0x7f826000}, + {0x7f828000}, {0x7f82a000}, {0x7f82c000}, {0x7f82e000}, + {0x7f830000}, {0x7f832000}, {0x7f834000}, {0x7f836000}, + {0x7f838000}, {0x7f83a000}, {0x7f83c000}, {0x7f83e000}, + {0x7f840000}, {0x7f842000}, {0x7f844000}, {0x7f846000}, + {0x7f848000}, {0x7f84a000}, {0x7f84c000}, {0x7f84e000}, + {0x7f850000}, {0x7f852000}, {0x7f854000}, {0x7f856000}, + {0x7f858000}, {0x7f85a000}, {0x7f85c000}, {0x7f85e000}, + {0x7f860000}, {0x7f862000}, {0x7f864000}, {0x7f866000}, + {0x7f868000}, {0x7f86a000}, {0x7f86c000}, {0x7f86e000}, + {0x7f870000}, {0x7f872000}, {0x7f874000}, {0x7f876000}, + {0x7f878000}, {0x7f87a000}, {0x7f87c000}, {0x7f87e000}, + {0x7f880000}, {0x7f882000}, {0x7f884000}, {0x7f886000}, + {0x7f888000}, {0x7f88a000}, {0x7f88c000}, {0x7f88e000}, + {0x7f890000}, {0x7f892000}, {0x7f894000}, {0x7f896000}, + {0x7f898000}, {0x7f89a000}, {0x7f89c000}, {0x7f89e000}, + {0x7f8a0000}, {0x7f8a2000}, {0x7f8a4000}, {0x7f8a6000}, + {0x7f8a8000}, {0x7f8aa000}, {0x7f8ac000}, {0x7f8ae000}, + {0x7f8b0000}, {0x7f8b2000}, {0x7f8b4000}, {0x7f8b6000}, + {0x7f8b8000}, {0x7f8ba000}, {0x7f8bc000}, {0x7f8be000}, + {0x7f8c0000}, {0x7f8c2000}, {0x7f8c4000}, {0x7f8c6000}, + {0x7f8c8000}, {0x7f8ca000}, {0x7f8cc000}, {0x7f8ce000}, + {0x7f8d0000}, {0x7f8d2000}, {0x7f8d4000}, {0x7f8d6000}, + {0x7f8d8000}, {0x7f8da000}, {0x7f8dc000}, {0x7f8de000}, + {0x7f8e0000}, {0x7f8e2000}, {0x7f8e4000}, {0x7f8e6000}, + {0x7f8e8000}, {0x7f8ea000}, {0x7f8ec000}, {0x7f8ee000}, + {0x7f8f0000}, {0x7f8f2000}, {0x7f8f4000}, {0x7f8f6000}, + {0x7f8f8000}, {0x7f8fa000}, {0x7f8fc000}, {0x7f8fe000}, + {0x7f900000}, {0x7f902000}, {0x7f904000}, {0x7f906000}, + {0x7f908000}, {0x7f90a000}, {0x7f90c000}, {0x7f90e000}, + {0x7f910000}, {0x7f912000}, {0x7f914000}, {0x7f916000}, + {0x7f918000}, {0x7f91a000}, {0x7f91c000}, {0x7f91e000}, + {0x7f920000}, {0x7f922000}, {0x7f924000}, {0x7f926000}, + {0x7f928000}, {0x7f92a000}, {0x7f92c000}, {0x7f92e000}, + {0x7f930000}, {0x7f932000}, {0x7f934000}, {0x7f936000}, + {0x7f938000}, {0x7f93a000}, {0x7f93c000}, {0x7f93e000}, + {0x7f940000}, {0x7f942000}, {0x7f944000}, {0x7f946000}, + {0x7f948000}, {0x7f94a000}, {0x7f94c000}, {0x7f94e000}, + {0x7f950000}, {0x7f952000}, {0x7f954000}, {0x7f956000}, + {0x7f958000}, {0x7f95a000}, {0x7f95c000}, {0x7f95e000}, + {0x7f960000}, {0x7f962000}, {0x7f964000}, {0x7f966000}, + {0x7f968000}, {0x7f96a000}, {0x7f96c000}, {0x7f96e000}, + {0x7f970000}, {0x7f972000}, {0x7f974000}, {0x7f976000}, + {0x7f978000}, {0x7f97a000}, {0x7f97c000}, {0x7f97e000}, + {0x7f980000}, {0x7f982000}, {0x7f984000}, {0x7f986000}, + {0x7f988000}, {0x7f98a000}, {0x7f98c000}, {0x7f98e000}, + {0x7f990000}, {0x7f992000}, {0x7f994000}, {0x7f996000}, + {0x7f998000}, {0x7f99a000}, {0x7f99c000}, {0x7f99e000}, + {0x7f9a0000}, {0x7f9a2000}, {0x7f9a4000}, {0x7f9a6000}, + {0x7f9a8000}, {0x7f9aa000}, {0x7f9ac000}, {0x7f9ae000}, + {0x7f9b0000}, {0x7f9b2000}, {0x7f9b4000}, {0x7f9b6000}, + {0x7f9b8000}, {0x7f9ba000}, {0x7f9bc000}, {0x7f9be000}, + {0x7f9c0000}, {0x7f9c2000}, {0x7f9c4000}, {0x7f9c6000}, + {0x7f9c8000}, {0x7f9ca000}, {0x7f9cc000}, {0x7f9ce000}, + {0x7f9d0000}, {0x7f9d2000}, {0x7f9d4000}, {0x7f9d6000}, + {0x7f9d8000}, {0x7f9da000}, {0x7f9dc000}, {0x7f9de000}, + {0x7f9e0000}, {0x7f9e2000}, {0x7f9e4000}, {0x7f9e6000}, + {0x7f9e8000}, {0x7f9ea000}, {0x7f9ec000}, {0x7f9ee000}, + {0x7f9f0000}, {0x7f9f2000}, {0x7f9f4000}, {0x7f9f6000}, + {0x7f9f8000}, {0x7f9fa000}, {0x7f9fc000}, {0x7f9fe000}, + {0x7fa00000}, {0x7fa02000}, {0x7fa04000}, {0x7fa06000}, + {0x7fa08000}, {0x7fa0a000}, {0x7fa0c000}, {0x7fa0e000}, + {0x7fa10000}, {0x7fa12000}, {0x7fa14000}, {0x7fa16000}, + {0x7fa18000}, {0x7fa1a000}, {0x7fa1c000}, {0x7fa1e000}, + {0x7fa20000}, {0x7fa22000}, {0x7fa24000}, {0x7fa26000}, + {0x7fa28000}, {0x7fa2a000}, {0x7fa2c000}, {0x7fa2e000}, + {0x7fa30000}, {0x7fa32000}, {0x7fa34000}, {0x7fa36000}, + {0x7fa38000}, {0x7fa3a000}, {0x7fa3c000}, {0x7fa3e000}, + {0x7fa40000}, {0x7fa42000}, {0x7fa44000}, {0x7fa46000}, + {0x7fa48000}, {0x7fa4a000}, {0x7fa4c000}, {0x7fa4e000}, + {0x7fa50000}, {0x7fa52000}, {0x7fa54000}, {0x7fa56000}, + {0x7fa58000}, {0x7fa5a000}, {0x7fa5c000}, {0x7fa5e000}, + {0x7fa60000}, {0x7fa62000}, {0x7fa64000}, {0x7fa66000}, + {0x7fa68000}, {0x7fa6a000}, {0x7fa6c000}, {0x7fa6e000}, + {0x7fa70000}, {0x7fa72000}, {0x7fa74000}, {0x7fa76000}, + {0x7fa78000}, {0x7fa7a000}, {0x7fa7c000}, {0x7fa7e000}, + {0x7fa80000}, {0x7fa82000}, {0x7fa84000}, {0x7fa86000}, + {0x7fa88000}, {0x7fa8a000}, {0x7fa8c000}, {0x7fa8e000}, + {0x7fa90000}, {0x7fa92000}, {0x7fa94000}, {0x7fa96000}, + {0x7fa98000}, {0x7fa9a000}, {0x7fa9c000}, {0x7fa9e000}, + {0x7faa0000}, {0x7faa2000}, {0x7faa4000}, {0x7faa6000}, + {0x7faa8000}, {0x7faaa000}, {0x7faac000}, {0x7faae000}, + {0x7fab0000}, {0x7fab2000}, {0x7fab4000}, {0x7fab6000}, + {0x7fab8000}, {0x7faba000}, {0x7fabc000}, {0x7fabe000}, + {0x7fac0000}, {0x7fac2000}, {0x7fac4000}, {0x7fac6000}, + {0x7fac8000}, {0x7faca000}, {0x7facc000}, {0x7face000}, + {0x7fad0000}, {0x7fad2000}, {0x7fad4000}, {0x7fad6000}, + {0x7fad8000}, {0x7fada000}, {0x7fadc000}, {0x7fade000}, + {0x7fae0000}, {0x7fae2000}, {0x7fae4000}, {0x7fae6000}, + {0x7fae8000}, {0x7faea000}, {0x7faec000}, {0x7faee000}, + {0x7faf0000}, {0x7faf2000}, {0x7faf4000}, {0x7faf6000}, + {0x7faf8000}, {0x7fafa000}, {0x7fafc000}, {0x7fafe000}, + {0x7fb00000}, {0x7fb02000}, {0x7fb04000}, {0x7fb06000}, + {0x7fb08000}, {0x7fb0a000}, {0x7fb0c000}, {0x7fb0e000}, + {0x7fb10000}, {0x7fb12000}, {0x7fb14000}, {0x7fb16000}, + {0x7fb18000}, {0x7fb1a000}, {0x7fb1c000}, {0x7fb1e000}, + {0x7fb20000}, {0x7fb22000}, {0x7fb24000}, {0x7fb26000}, + {0x7fb28000}, {0x7fb2a000}, {0x7fb2c000}, {0x7fb2e000}, + {0x7fb30000}, {0x7fb32000}, {0x7fb34000}, {0x7fb36000}, + {0x7fb38000}, {0x7fb3a000}, {0x7fb3c000}, {0x7fb3e000}, + {0x7fb40000}, {0x7fb42000}, {0x7fb44000}, {0x7fb46000}, + {0x7fb48000}, {0x7fb4a000}, {0x7fb4c000}, {0x7fb4e000}, + {0x7fb50000}, {0x7fb52000}, {0x7fb54000}, {0x7fb56000}, + {0x7fb58000}, {0x7fb5a000}, {0x7fb5c000}, {0x7fb5e000}, + {0x7fb60000}, {0x7fb62000}, {0x7fb64000}, {0x7fb66000}, + {0x7fb68000}, {0x7fb6a000}, {0x7fb6c000}, {0x7fb6e000}, + {0x7fb70000}, {0x7fb72000}, {0x7fb74000}, {0x7fb76000}, + {0x7fb78000}, {0x7fb7a000}, {0x7fb7c000}, {0x7fb7e000}, + {0x7fb80000}, {0x7fb82000}, {0x7fb84000}, {0x7fb86000}, + {0x7fb88000}, {0x7fb8a000}, {0x7fb8c000}, {0x7fb8e000}, + {0x7fb90000}, {0x7fb92000}, {0x7fb94000}, {0x7fb96000}, + {0x7fb98000}, {0x7fb9a000}, {0x7fb9c000}, {0x7fb9e000}, + {0x7fba0000}, {0x7fba2000}, {0x7fba4000}, {0x7fba6000}, + {0x7fba8000}, {0x7fbaa000}, {0x7fbac000}, {0x7fbae000}, + {0x7fbb0000}, {0x7fbb2000}, {0x7fbb4000}, {0x7fbb6000}, + {0x7fbb8000}, {0x7fbba000}, {0x7fbbc000}, {0x7fbbe000}, + {0x7fbc0000}, {0x7fbc2000}, {0x7fbc4000}, {0x7fbc6000}, + {0x7fbc8000}, {0x7fbca000}, {0x7fbcc000}, {0x7fbce000}, + {0x7fbd0000}, {0x7fbd2000}, {0x7fbd4000}, {0x7fbd6000}, + {0x7fbd8000}, {0x7fbda000}, {0x7fbdc000}, {0x7fbde000}, + {0x7fbe0000}, {0x7fbe2000}, {0x7fbe4000}, {0x7fbe6000}, + {0x7fbe8000}, {0x7fbea000}, {0x7fbec000}, {0x7fbee000}, + {0x7fbf0000}, {0x7fbf2000}, {0x7fbf4000}, {0x7fbf6000}, + {0x7fbf8000}, {0x7fbfa000}, {0x7fbfc000}, {0x7fbfe000}, + {0x7fc00000}, {0x7fc02000}, {0x7fc04000}, {0x7fc06000}, + {0x7fc08000}, {0x7fc0a000}, {0x7fc0c000}, {0x7fc0e000}, + {0x7fc10000}, {0x7fc12000}, {0x7fc14000}, {0x7fc16000}, + {0x7fc18000}, {0x7fc1a000}, {0x7fc1c000}, {0x7fc1e000}, + {0x7fc20000}, {0x7fc22000}, {0x7fc24000}, {0x7fc26000}, + {0x7fc28000}, {0x7fc2a000}, {0x7fc2c000}, {0x7fc2e000}, + {0x7fc30000}, {0x7fc32000}, {0x7fc34000}, {0x7fc36000}, + {0x7fc38000}, {0x7fc3a000}, {0x7fc3c000}, {0x7fc3e000}, + {0x7fc40000}, {0x7fc42000}, {0x7fc44000}, {0x7fc46000}, + {0x7fc48000}, {0x7fc4a000}, {0x7fc4c000}, {0x7fc4e000}, + {0x7fc50000}, {0x7fc52000}, {0x7fc54000}, {0x7fc56000}, + {0x7fc58000}, {0x7fc5a000}, {0x7fc5c000}, {0x7fc5e000}, + {0x7fc60000}, {0x7fc62000}, {0x7fc64000}, {0x7fc66000}, + {0x7fc68000}, {0x7fc6a000}, {0x7fc6c000}, {0x7fc6e000}, + {0x7fc70000}, {0x7fc72000}, {0x7fc74000}, {0x7fc76000}, + {0x7fc78000}, {0x7fc7a000}, {0x7fc7c000}, {0x7fc7e000}, + {0x7fc80000}, {0x7fc82000}, {0x7fc84000}, {0x7fc86000}, + {0x7fc88000}, {0x7fc8a000}, {0x7fc8c000}, {0x7fc8e000}, + {0x7fc90000}, {0x7fc92000}, {0x7fc94000}, {0x7fc96000}, + {0x7fc98000}, {0x7fc9a000}, {0x7fc9c000}, {0x7fc9e000}, + {0x7fca0000}, {0x7fca2000}, {0x7fca4000}, {0x7fca6000}, + {0x7fca8000}, {0x7fcaa000}, {0x7fcac000}, {0x7fcae000}, + {0x7fcb0000}, {0x7fcb2000}, {0x7fcb4000}, {0x7fcb6000}, + {0x7fcb8000}, {0x7fcba000}, {0x7fcbc000}, {0x7fcbe000}, + {0x7fcc0000}, {0x7fcc2000}, {0x7fcc4000}, {0x7fcc6000}, + {0x7fcc8000}, {0x7fcca000}, {0x7fccc000}, {0x7fcce000}, + {0x7fcd0000}, {0x7fcd2000}, {0x7fcd4000}, {0x7fcd6000}, + {0x7fcd8000}, {0x7fcda000}, {0x7fcdc000}, {0x7fcde000}, + {0x7fce0000}, {0x7fce2000}, {0x7fce4000}, {0x7fce6000}, + {0x7fce8000}, {0x7fcea000}, {0x7fcec000}, {0x7fcee000}, + {0x7fcf0000}, {0x7fcf2000}, {0x7fcf4000}, {0x7fcf6000}, + {0x7fcf8000}, {0x7fcfa000}, {0x7fcfc000}, {0x7fcfe000}, + {0x7fd00000}, {0x7fd02000}, {0x7fd04000}, {0x7fd06000}, + {0x7fd08000}, {0x7fd0a000}, {0x7fd0c000}, {0x7fd0e000}, + {0x7fd10000}, {0x7fd12000}, {0x7fd14000}, {0x7fd16000}, + {0x7fd18000}, {0x7fd1a000}, {0x7fd1c000}, {0x7fd1e000}, + {0x7fd20000}, {0x7fd22000}, {0x7fd24000}, {0x7fd26000}, + {0x7fd28000}, {0x7fd2a000}, {0x7fd2c000}, {0x7fd2e000}, + {0x7fd30000}, {0x7fd32000}, {0x7fd34000}, {0x7fd36000}, + {0x7fd38000}, {0x7fd3a000}, {0x7fd3c000}, {0x7fd3e000}, + {0x7fd40000}, {0x7fd42000}, {0x7fd44000}, {0x7fd46000}, + {0x7fd48000}, {0x7fd4a000}, {0x7fd4c000}, {0x7fd4e000}, + {0x7fd50000}, {0x7fd52000}, {0x7fd54000}, {0x7fd56000}, + {0x7fd58000}, {0x7fd5a000}, {0x7fd5c000}, {0x7fd5e000}, + {0x7fd60000}, {0x7fd62000}, {0x7fd64000}, {0x7fd66000}, + {0x7fd68000}, {0x7fd6a000}, {0x7fd6c000}, {0x7fd6e000}, + {0x7fd70000}, {0x7fd72000}, {0x7fd74000}, {0x7fd76000}, + {0x7fd78000}, {0x7fd7a000}, {0x7fd7c000}, {0x7fd7e000}, + {0x7fd80000}, {0x7fd82000}, {0x7fd84000}, {0x7fd86000}, + {0x7fd88000}, {0x7fd8a000}, {0x7fd8c000}, {0x7fd8e000}, + {0x7fd90000}, {0x7fd92000}, {0x7fd94000}, {0x7fd96000}, + {0x7fd98000}, {0x7fd9a000}, {0x7fd9c000}, {0x7fd9e000}, + {0x7fda0000}, {0x7fda2000}, {0x7fda4000}, {0x7fda6000}, + {0x7fda8000}, {0x7fdaa000}, {0x7fdac000}, {0x7fdae000}, + {0x7fdb0000}, {0x7fdb2000}, {0x7fdb4000}, {0x7fdb6000}, + {0x7fdb8000}, {0x7fdba000}, {0x7fdbc000}, {0x7fdbe000}, + {0x7fdc0000}, {0x7fdc2000}, {0x7fdc4000}, {0x7fdc6000}, + {0x7fdc8000}, {0x7fdca000}, {0x7fdcc000}, {0x7fdce000}, + {0x7fdd0000}, {0x7fdd2000}, {0x7fdd4000}, {0x7fdd6000}, + {0x7fdd8000}, {0x7fdda000}, {0x7fddc000}, {0x7fdde000}, + {0x7fde0000}, {0x7fde2000}, {0x7fde4000}, {0x7fde6000}, + {0x7fde8000}, {0x7fdea000}, {0x7fdec000}, {0x7fdee000}, + {0x7fdf0000}, {0x7fdf2000}, {0x7fdf4000}, {0x7fdf6000}, + {0x7fdf8000}, {0x7fdfa000}, {0x7fdfc000}, {0x7fdfe000}, + {0x7fe00000}, {0x7fe02000}, {0x7fe04000}, {0x7fe06000}, + {0x7fe08000}, {0x7fe0a000}, {0x7fe0c000}, {0x7fe0e000}, + {0x7fe10000}, {0x7fe12000}, {0x7fe14000}, {0x7fe16000}, + {0x7fe18000}, {0x7fe1a000}, {0x7fe1c000}, {0x7fe1e000}, + {0x7fe20000}, {0x7fe22000}, {0x7fe24000}, {0x7fe26000}, + {0x7fe28000}, {0x7fe2a000}, {0x7fe2c000}, {0x7fe2e000}, + {0x7fe30000}, {0x7fe32000}, {0x7fe34000}, {0x7fe36000}, + {0x7fe38000}, {0x7fe3a000}, {0x7fe3c000}, {0x7fe3e000}, + {0x7fe40000}, {0x7fe42000}, {0x7fe44000}, {0x7fe46000}, + {0x7fe48000}, {0x7fe4a000}, {0x7fe4c000}, {0x7fe4e000}, + {0x7fe50000}, {0x7fe52000}, {0x7fe54000}, {0x7fe56000}, + {0x7fe58000}, {0x7fe5a000}, {0x7fe5c000}, {0x7fe5e000}, + {0x7fe60000}, {0x7fe62000}, {0x7fe64000}, {0x7fe66000}, + {0x7fe68000}, {0x7fe6a000}, {0x7fe6c000}, {0x7fe6e000}, + {0x7fe70000}, {0x7fe72000}, {0x7fe74000}, {0x7fe76000}, + {0x7fe78000}, {0x7fe7a000}, {0x7fe7c000}, {0x7fe7e000}, + {0x7fe80000}, {0x7fe82000}, {0x7fe84000}, {0x7fe86000}, + {0x7fe88000}, {0x7fe8a000}, {0x7fe8c000}, {0x7fe8e000}, + {0x7fe90000}, {0x7fe92000}, {0x7fe94000}, {0x7fe96000}, + {0x7fe98000}, {0x7fe9a000}, {0x7fe9c000}, {0x7fe9e000}, + {0x7fea0000}, {0x7fea2000}, {0x7fea4000}, {0x7fea6000}, + {0x7fea8000}, {0x7feaa000}, {0x7feac000}, {0x7feae000}, + {0x7feb0000}, {0x7feb2000}, {0x7feb4000}, {0x7feb6000}, + {0x7feb8000}, {0x7feba000}, {0x7febc000}, {0x7febe000}, + {0x7fec0000}, {0x7fec2000}, {0x7fec4000}, {0x7fec6000}, + {0x7fec8000}, {0x7feca000}, {0x7fecc000}, {0x7fece000}, + {0x7fed0000}, {0x7fed2000}, {0x7fed4000}, {0x7fed6000}, + {0x7fed8000}, {0x7feda000}, {0x7fedc000}, {0x7fede000}, + {0x7fee0000}, {0x7fee2000}, {0x7fee4000}, {0x7fee6000}, + {0x7fee8000}, {0x7feea000}, {0x7feec000}, {0x7feee000}, + {0x7fef0000}, {0x7fef2000}, {0x7fef4000}, {0x7fef6000}, + {0x7fef8000}, {0x7fefa000}, {0x7fefc000}, {0x7fefe000}, + {0x7ff00000}, {0x7ff02000}, {0x7ff04000}, {0x7ff06000}, + {0x7ff08000}, {0x7ff0a000}, {0x7ff0c000}, {0x7ff0e000}, + {0x7ff10000}, {0x7ff12000}, {0x7ff14000}, {0x7ff16000}, + {0x7ff18000}, {0x7ff1a000}, {0x7ff1c000}, {0x7ff1e000}, + {0x7ff20000}, {0x7ff22000}, {0x7ff24000}, {0x7ff26000}, + {0x7ff28000}, {0x7ff2a000}, {0x7ff2c000}, {0x7ff2e000}, + {0x7ff30000}, {0x7ff32000}, {0x7ff34000}, {0x7ff36000}, + {0x7ff38000}, {0x7ff3a000}, {0x7ff3c000}, {0x7ff3e000}, + {0x7ff40000}, {0x7ff42000}, {0x7ff44000}, {0x7ff46000}, + {0x7ff48000}, {0x7ff4a000}, {0x7ff4c000}, {0x7ff4e000}, + {0x7ff50000}, {0x7ff52000}, {0x7ff54000}, {0x7ff56000}, + {0x7ff58000}, {0x7ff5a000}, {0x7ff5c000}, {0x7ff5e000}, + {0x7ff60000}, {0x7ff62000}, {0x7ff64000}, {0x7ff66000}, + {0x7ff68000}, {0x7ff6a000}, {0x7ff6c000}, {0x7ff6e000}, + {0x7ff70000}, {0x7ff72000}, {0x7ff74000}, {0x7ff76000}, + {0x7ff78000}, {0x7ff7a000}, {0x7ff7c000}, {0x7ff7e000}, + {0x7ff80000}, {0x7ff82000}, {0x7ff84000}, {0x7ff86000}, + {0x7ff88000}, {0x7ff8a000}, {0x7ff8c000}, {0x7ff8e000}, + {0x7ff90000}, {0x7ff92000}, {0x7ff94000}, {0x7ff96000}, + {0x7ff98000}, {0x7ff9a000}, {0x7ff9c000}, {0x7ff9e000}, + {0x7ffa0000}, {0x7ffa2000}, {0x7ffa4000}, {0x7ffa6000}, + {0x7ffa8000}, {0x7ffaa000}, {0x7ffac000}, {0x7ffae000}, + {0x7ffb0000}, {0x7ffb2000}, {0x7ffb4000}, {0x7ffb6000}, + {0x7ffb8000}, {0x7ffba000}, {0x7ffbc000}, {0x7ffbe000}, + {0x7ffc0000}, {0x7ffc2000}, {0x7ffc4000}, {0x7ffc6000}, + {0x7ffc8000}, {0x7ffca000}, {0x7ffcc000}, {0x7ffce000}, + {0x7ffd0000}, {0x7ffd2000}, {0x7ffd4000}, {0x7ffd6000}, + {0x7ffd8000}, {0x7ffda000}, {0x7ffdc000}, {0x7ffde000}, + {0x7ffe0000}, {0x7ffe2000}, {0x7ffe4000}, {0x7ffe6000}, + {0x7ffe8000}, {0x7ffea000}, {0x7ffec000}, {0x7ffee000}, + {0x7fff0000}, {0x7fff2000}, {0x7fff4000}, {0x7fff6000}, + {0x7fff8000}, {0x7fffa000}, {0x7fffc000}, {0x7fffe000}, + {0x80000000}, {0xb3800000}, {0xb4000000}, {0xb4400000}, + {0xb4800000}, {0xb4a00000}, {0xb4c00000}, {0xb4e00000}, + {0xb5000000}, {0xb5100000}, {0xb5200000}, {0xb5300000}, + {0xb5400000}, {0xb5500000}, {0xb5600000}, {0xb5700000}, + {0xb5800000}, {0xb5880000}, {0xb5900000}, {0xb5980000}, + {0xb5a00000}, {0xb5a80000}, {0xb5b00000}, {0xb5b80000}, + {0xb5c00000}, {0xb5c80000}, {0xb5d00000}, {0xb5d80000}, + {0xb5e00000}, {0xb5e80000}, {0xb5f00000}, {0xb5f80000}, + {0xb6000000}, {0xb6040000}, {0xb6080000}, {0xb60c0000}, + {0xb6100000}, {0xb6140000}, {0xb6180000}, {0xb61c0000}, + {0xb6200000}, {0xb6240000}, {0xb6280000}, {0xb62c0000}, + {0xb6300000}, {0xb6340000}, {0xb6380000}, {0xb63c0000}, + {0xb6400000}, {0xb6440000}, {0xb6480000}, {0xb64c0000}, + {0xb6500000}, {0xb6540000}, {0xb6580000}, {0xb65c0000}, + {0xb6600000}, {0xb6640000}, {0xb6680000}, {0xb66c0000}, + {0xb6700000}, {0xb6740000}, {0xb6780000}, {0xb67c0000}, + {0xb6800000}, {0xb6820000}, {0xb6840000}, {0xb6860000}, + {0xb6880000}, {0xb68a0000}, {0xb68c0000}, {0xb68e0000}, + {0xb6900000}, {0xb6920000}, {0xb6940000}, {0xb6960000}, + {0xb6980000}, {0xb69a0000}, {0xb69c0000}, {0xb69e0000}, + {0xb6a00000}, {0xb6a20000}, {0xb6a40000}, {0xb6a60000}, + {0xb6a80000}, {0xb6aa0000}, {0xb6ac0000}, {0xb6ae0000}, + {0xb6b00000}, {0xb6b20000}, {0xb6b40000}, {0xb6b60000}, + {0xb6b80000}, {0xb6ba0000}, {0xb6bc0000}, {0xb6be0000}, + {0xb6c00000}, {0xb6c20000}, {0xb6c40000}, {0xb6c60000}, + {0xb6c80000}, {0xb6ca0000}, {0xb6cc0000}, {0xb6ce0000}, + {0xb6d00000}, {0xb6d20000}, {0xb6d40000}, {0xb6d60000}, + {0xb6d80000}, {0xb6da0000}, {0xb6dc0000}, {0xb6de0000}, + {0xb6e00000}, {0xb6e20000}, {0xb6e40000}, {0xb6e60000}, + {0xb6e80000}, {0xb6ea0000}, {0xb6ec0000}, {0xb6ee0000}, + {0xb6f00000}, {0xb6f20000}, {0xb6f40000}, {0xb6f60000}, + {0xb6f80000}, {0xb6fa0000}, {0xb6fc0000}, {0xb6fe0000}, + {0xb7000000}, {0xb7010000}, {0xb7020000}, {0xb7030000}, + {0xb7040000}, {0xb7050000}, {0xb7060000}, {0xb7070000}, + {0xb7080000}, {0xb7090000}, {0xb70a0000}, {0xb70b0000}, + {0xb70c0000}, {0xb70d0000}, {0xb70e0000}, {0xb70f0000}, + {0xb7100000}, {0xb7110000}, {0xb7120000}, {0xb7130000}, + {0xb7140000}, {0xb7150000}, {0xb7160000}, {0xb7170000}, + {0xb7180000}, {0xb7190000}, {0xb71a0000}, {0xb71b0000}, + {0xb71c0000}, {0xb71d0000}, {0xb71e0000}, {0xb71f0000}, + {0xb7200000}, {0xb7210000}, {0xb7220000}, {0xb7230000}, + {0xb7240000}, {0xb7250000}, {0xb7260000}, {0xb7270000}, + {0xb7280000}, {0xb7290000}, {0xb72a0000}, {0xb72b0000}, + {0xb72c0000}, {0xb72d0000}, {0xb72e0000}, {0xb72f0000}, + {0xb7300000}, {0xb7310000}, {0xb7320000}, {0xb7330000}, + {0xb7340000}, {0xb7350000}, {0xb7360000}, {0xb7370000}, + {0xb7380000}, {0xb7390000}, {0xb73a0000}, {0xb73b0000}, + {0xb73c0000}, {0xb73d0000}, {0xb73e0000}, {0xb73f0000}, + {0xb7400000}, {0xb7410000}, {0xb7420000}, {0xb7430000}, + {0xb7440000}, {0xb7450000}, {0xb7460000}, {0xb7470000}, + {0xb7480000}, {0xb7490000}, {0xb74a0000}, {0xb74b0000}, + {0xb74c0000}, {0xb74d0000}, {0xb74e0000}, {0xb74f0000}, + {0xb7500000}, {0xb7510000}, {0xb7520000}, {0xb7530000}, + {0xb7540000}, {0xb7550000}, {0xb7560000}, {0xb7570000}, + {0xb7580000}, {0xb7590000}, {0xb75a0000}, {0xb75b0000}, + {0xb75c0000}, {0xb75d0000}, {0xb75e0000}, {0xb75f0000}, + {0xb7600000}, {0xb7610000}, {0xb7620000}, {0xb7630000}, + {0xb7640000}, {0xb7650000}, {0xb7660000}, {0xb7670000}, + {0xb7680000}, {0xb7690000}, {0xb76a0000}, {0xb76b0000}, + {0xb76c0000}, {0xb76d0000}, {0xb76e0000}, {0xb76f0000}, + {0xb7700000}, {0xb7710000}, {0xb7720000}, {0xb7730000}, + {0xb7740000}, {0xb7750000}, {0xb7760000}, {0xb7770000}, + {0xb7780000}, {0xb7790000}, {0xb77a0000}, {0xb77b0000}, + {0xb77c0000}, {0xb77d0000}, {0xb77e0000}, {0xb77f0000}, + {0xb7800000}, {0xb7808000}, {0xb7810000}, {0xb7818000}, + {0xb7820000}, {0xb7828000}, {0xb7830000}, {0xb7838000}, + {0xb7840000}, {0xb7848000}, {0xb7850000}, {0xb7858000}, + {0xb7860000}, {0xb7868000}, {0xb7870000}, {0xb7878000}, + {0xb7880000}, {0xb7888000}, {0xb7890000}, {0xb7898000}, + {0xb78a0000}, {0xb78a8000}, {0xb78b0000}, {0xb78b8000}, + {0xb78c0000}, {0xb78c8000}, {0xb78d0000}, {0xb78d8000}, + {0xb78e0000}, {0xb78e8000}, {0xb78f0000}, {0xb78f8000}, + {0xb7900000}, {0xb7908000}, {0xb7910000}, {0xb7918000}, + {0xb7920000}, {0xb7928000}, {0xb7930000}, {0xb7938000}, + {0xb7940000}, {0xb7948000}, {0xb7950000}, {0xb7958000}, + {0xb7960000}, {0xb7968000}, {0xb7970000}, {0xb7978000}, + {0xb7980000}, {0xb7988000}, {0xb7990000}, {0xb7998000}, + {0xb79a0000}, {0xb79a8000}, {0xb79b0000}, {0xb79b8000}, + {0xb79c0000}, {0xb79c8000}, {0xb79d0000}, {0xb79d8000}, + {0xb79e0000}, {0xb79e8000}, {0xb79f0000}, {0xb79f8000}, + {0xb7a00000}, {0xb7a08000}, {0xb7a10000}, {0xb7a18000}, + {0xb7a20000}, {0xb7a28000}, {0xb7a30000}, {0xb7a38000}, + {0xb7a40000}, {0xb7a48000}, {0xb7a50000}, {0xb7a58000}, + {0xb7a60000}, {0xb7a68000}, {0xb7a70000}, {0xb7a78000}, + {0xb7a80000}, {0xb7a88000}, {0xb7a90000}, {0xb7a98000}, + {0xb7aa0000}, {0xb7aa8000}, {0xb7ab0000}, {0xb7ab8000}, + {0xb7ac0000}, {0xb7ac8000}, {0xb7ad0000}, {0xb7ad8000}, + {0xb7ae0000}, {0xb7ae8000}, {0xb7af0000}, {0xb7af8000}, + {0xb7b00000}, {0xb7b08000}, {0xb7b10000}, {0xb7b18000}, + {0xb7b20000}, {0xb7b28000}, {0xb7b30000}, {0xb7b38000}, + {0xb7b40000}, {0xb7b48000}, {0xb7b50000}, {0xb7b58000}, + {0xb7b60000}, {0xb7b68000}, {0xb7b70000}, {0xb7b78000}, + {0xb7b80000}, {0xb7b88000}, {0xb7b90000}, {0xb7b98000}, + {0xb7ba0000}, {0xb7ba8000}, {0xb7bb0000}, {0xb7bb8000}, + {0xb7bc0000}, {0xb7bc8000}, {0xb7bd0000}, {0xb7bd8000}, + {0xb7be0000}, {0xb7be8000}, {0xb7bf0000}, {0xb7bf8000}, + {0xb7c00000}, {0xb7c08000}, {0xb7c10000}, {0xb7c18000}, + {0xb7c20000}, {0xb7c28000}, {0xb7c30000}, {0xb7c38000}, + {0xb7c40000}, {0xb7c48000}, {0xb7c50000}, {0xb7c58000}, + {0xb7c60000}, {0xb7c68000}, {0xb7c70000}, {0xb7c78000}, + {0xb7c80000}, {0xb7c88000}, {0xb7c90000}, {0xb7c98000}, + {0xb7ca0000}, {0xb7ca8000}, {0xb7cb0000}, {0xb7cb8000}, + {0xb7cc0000}, {0xb7cc8000}, {0xb7cd0000}, {0xb7cd8000}, + {0xb7ce0000}, {0xb7ce8000}, {0xb7cf0000}, {0xb7cf8000}, + {0xb7d00000}, {0xb7d08000}, {0xb7d10000}, {0xb7d18000}, + {0xb7d20000}, {0xb7d28000}, {0xb7d30000}, {0xb7d38000}, + {0xb7d40000}, {0xb7d48000}, {0xb7d50000}, {0xb7d58000}, + {0xb7d60000}, {0xb7d68000}, {0xb7d70000}, {0xb7d78000}, + {0xb7d80000}, {0xb7d88000}, {0xb7d90000}, {0xb7d98000}, + {0xb7da0000}, {0xb7da8000}, {0xb7db0000}, {0xb7db8000}, + {0xb7dc0000}, {0xb7dc8000}, {0xb7dd0000}, {0xb7dd8000}, + {0xb7de0000}, {0xb7de8000}, {0xb7df0000}, {0xb7df8000}, + {0xb7e00000}, {0xb7e08000}, {0xb7e10000}, {0xb7e18000}, + {0xb7e20000}, {0xb7e28000}, {0xb7e30000}, {0xb7e38000}, + {0xb7e40000}, {0xb7e48000}, {0xb7e50000}, {0xb7e58000}, + {0xb7e60000}, {0xb7e68000}, {0xb7e70000}, {0xb7e78000}, + {0xb7e80000}, {0xb7e88000}, {0xb7e90000}, {0xb7e98000}, + {0xb7ea0000}, {0xb7ea8000}, {0xb7eb0000}, {0xb7eb8000}, + {0xb7ec0000}, {0xb7ec8000}, {0xb7ed0000}, {0xb7ed8000}, + {0xb7ee0000}, {0xb7ee8000}, {0xb7ef0000}, {0xb7ef8000}, + {0xb7f00000}, {0xb7f08000}, {0xb7f10000}, {0xb7f18000}, + {0xb7f20000}, {0xb7f28000}, {0xb7f30000}, {0xb7f38000}, + {0xb7f40000}, {0xb7f48000}, {0xb7f50000}, {0xb7f58000}, + {0xb7f60000}, {0xb7f68000}, {0xb7f70000}, {0xb7f78000}, + {0xb7f80000}, {0xb7f88000}, {0xb7f90000}, {0xb7f98000}, + {0xb7fa0000}, {0xb7fa8000}, {0xb7fb0000}, {0xb7fb8000}, + {0xb7fc0000}, {0xb7fc8000}, {0xb7fd0000}, {0xb7fd8000}, + {0xb7fe0000}, {0xb7fe8000}, {0xb7ff0000}, {0xb7ff8000}, + {0xb8000000}, {0xb8004000}, {0xb8008000}, {0xb800c000}, + {0xb8010000}, {0xb8014000}, {0xb8018000}, {0xb801c000}, + {0xb8020000}, {0xb8024000}, {0xb8028000}, {0xb802c000}, + {0xb8030000}, {0xb8034000}, {0xb8038000}, {0xb803c000}, + {0xb8040000}, {0xb8044000}, {0xb8048000}, {0xb804c000}, + {0xb8050000}, {0xb8054000}, {0xb8058000}, {0xb805c000}, + {0xb8060000}, {0xb8064000}, {0xb8068000}, {0xb806c000}, + {0xb8070000}, {0xb8074000}, {0xb8078000}, {0xb807c000}, + {0xb8080000}, {0xb8084000}, {0xb8088000}, {0xb808c000}, + {0xb8090000}, {0xb8094000}, {0xb8098000}, {0xb809c000}, + {0xb80a0000}, {0xb80a4000}, {0xb80a8000}, {0xb80ac000}, + {0xb80b0000}, {0xb80b4000}, {0xb80b8000}, {0xb80bc000}, + {0xb80c0000}, {0xb80c4000}, {0xb80c8000}, {0xb80cc000}, + {0xb80d0000}, {0xb80d4000}, {0xb80d8000}, {0xb80dc000}, + {0xb80e0000}, {0xb80e4000}, {0xb80e8000}, {0xb80ec000}, + {0xb80f0000}, {0xb80f4000}, {0xb80f8000}, {0xb80fc000}, + {0xb8100000}, {0xb8104000}, {0xb8108000}, {0xb810c000}, + {0xb8110000}, {0xb8114000}, {0xb8118000}, {0xb811c000}, + {0xb8120000}, {0xb8124000}, {0xb8128000}, {0xb812c000}, + {0xb8130000}, {0xb8134000}, {0xb8138000}, {0xb813c000}, + {0xb8140000}, {0xb8144000}, {0xb8148000}, {0xb814c000}, + {0xb8150000}, {0xb8154000}, {0xb8158000}, {0xb815c000}, + {0xb8160000}, {0xb8164000}, {0xb8168000}, {0xb816c000}, + {0xb8170000}, {0xb8174000}, {0xb8178000}, {0xb817c000}, + {0xb8180000}, {0xb8184000}, {0xb8188000}, {0xb818c000}, + {0xb8190000}, {0xb8194000}, {0xb8198000}, {0xb819c000}, + {0xb81a0000}, {0xb81a4000}, {0xb81a8000}, {0xb81ac000}, + {0xb81b0000}, {0xb81b4000}, {0xb81b8000}, {0xb81bc000}, + {0xb81c0000}, {0xb81c4000}, {0xb81c8000}, {0xb81cc000}, + {0xb81d0000}, {0xb81d4000}, {0xb81d8000}, {0xb81dc000}, + {0xb81e0000}, {0xb81e4000}, {0xb81e8000}, {0xb81ec000}, + {0xb81f0000}, {0xb81f4000}, {0xb81f8000}, {0xb81fc000}, + {0xb8200000}, {0xb8204000}, {0xb8208000}, {0xb820c000}, + {0xb8210000}, {0xb8214000}, {0xb8218000}, {0xb821c000}, + {0xb8220000}, {0xb8224000}, {0xb8228000}, {0xb822c000}, + {0xb8230000}, {0xb8234000}, {0xb8238000}, {0xb823c000}, + {0xb8240000}, {0xb8244000}, {0xb8248000}, {0xb824c000}, + {0xb8250000}, {0xb8254000}, {0xb8258000}, {0xb825c000}, + {0xb8260000}, {0xb8264000}, {0xb8268000}, {0xb826c000}, + {0xb8270000}, {0xb8274000}, {0xb8278000}, {0xb827c000}, + {0xb8280000}, {0xb8284000}, {0xb8288000}, {0xb828c000}, + {0xb8290000}, {0xb8294000}, {0xb8298000}, {0xb829c000}, + {0xb82a0000}, {0xb82a4000}, {0xb82a8000}, {0xb82ac000}, + {0xb82b0000}, {0xb82b4000}, {0xb82b8000}, {0xb82bc000}, + {0xb82c0000}, {0xb82c4000}, {0xb82c8000}, {0xb82cc000}, + {0xb82d0000}, {0xb82d4000}, {0xb82d8000}, {0xb82dc000}, + {0xb82e0000}, {0xb82e4000}, {0xb82e8000}, {0xb82ec000}, + {0xb82f0000}, {0xb82f4000}, {0xb82f8000}, {0xb82fc000}, + {0xb8300000}, {0xb8304000}, {0xb8308000}, {0xb830c000}, + {0xb8310000}, {0xb8314000}, {0xb8318000}, {0xb831c000}, + {0xb8320000}, {0xb8324000}, {0xb8328000}, {0xb832c000}, + {0xb8330000}, {0xb8334000}, {0xb8338000}, {0xb833c000}, + {0xb8340000}, {0xb8344000}, {0xb8348000}, {0xb834c000}, + {0xb8350000}, {0xb8354000}, {0xb8358000}, {0xb835c000}, + {0xb8360000}, {0xb8364000}, {0xb8368000}, {0xb836c000}, + {0xb8370000}, {0xb8374000}, {0xb8378000}, {0xb837c000}, + {0xb8380000}, {0xb8384000}, {0xb8388000}, {0xb838c000}, + {0xb8390000}, {0xb8394000}, {0xb8398000}, {0xb839c000}, + {0xb83a0000}, {0xb83a4000}, {0xb83a8000}, {0xb83ac000}, + {0xb83b0000}, {0xb83b4000}, {0xb83b8000}, {0xb83bc000}, + {0xb83c0000}, {0xb83c4000}, {0xb83c8000}, {0xb83cc000}, + {0xb83d0000}, {0xb83d4000}, {0xb83d8000}, {0xb83dc000}, + {0xb83e0000}, {0xb83e4000}, {0xb83e8000}, {0xb83ec000}, + {0xb83f0000}, {0xb83f4000}, {0xb83f8000}, {0xb83fc000}, + {0xb8400000}, {0xb8404000}, {0xb8408000}, {0xb840c000}, + {0xb8410000}, {0xb8414000}, {0xb8418000}, {0xb841c000}, + {0xb8420000}, {0xb8424000}, {0xb8428000}, {0xb842c000}, + {0xb8430000}, {0xb8434000}, {0xb8438000}, {0xb843c000}, + {0xb8440000}, {0xb8444000}, {0xb8448000}, {0xb844c000}, + {0xb8450000}, {0xb8454000}, {0xb8458000}, {0xb845c000}, + {0xb8460000}, {0xb8464000}, {0xb8468000}, {0xb846c000}, + {0xb8470000}, {0xb8474000}, {0xb8478000}, {0xb847c000}, + {0xb8480000}, {0xb8484000}, {0xb8488000}, {0xb848c000}, + {0xb8490000}, {0xb8494000}, {0xb8498000}, {0xb849c000}, + {0xb84a0000}, {0xb84a4000}, {0xb84a8000}, {0xb84ac000}, + {0xb84b0000}, {0xb84b4000}, {0xb84b8000}, {0xb84bc000}, + {0xb84c0000}, {0xb84c4000}, {0xb84c8000}, {0xb84cc000}, + {0xb84d0000}, {0xb84d4000}, {0xb84d8000}, {0xb84dc000}, + {0xb84e0000}, {0xb84e4000}, {0xb84e8000}, {0xb84ec000}, + {0xb84f0000}, {0xb84f4000}, {0xb84f8000}, {0xb84fc000}, + {0xb8500000}, {0xb8504000}, {0xb8508000}, {0xb850c000}, + {0xb8510000}, {0xb8514000}, {0xb8518000}, {0xb851c000}, + {0xb8520000}, {0xb8524000}, {0xb8528000}, {0xb852c000}, + {0xb8530000}, {0xb8534000}, {0xb8538000}, {0xb853c000}, + {0xb8540000}, {0xb8544000}, {0xb8548000}, {0xb854c000}, + {0xb8550000}, {0xb8554000}, {0xb8558000}, {0xb855c000}, + {0xb8560000}, {0xb8564000}, {0xb8568000}, {0xb856c000}, + {0xb8570000}, {0xb8574000}, {0xb8578000}, {0xb857c000}, + {0xb8580000}, {0xb8584000}, {0xb8588000}, {0xb858c000}, + {0xb8590000}, {0xb8594000}, {0xb8598000}, {0xb859c000}, + {0xb85a0000}, {0xb85a4000}, {0xb85a8000}, {0xb85ac000}, + {0xb85b0000}, {0xb85b4000}, {0xb85b8000}, {0xb85bc000}, + {0xb85c0000}, {0xb85c4000}, {0xb85c8000}, {0xb85cc000}, + {0xb85d0000}, {0xb85d4000}, {0xb85d8000}, {0xb85dc000}, + {0xb85e0000}, {0xb85e4000}, {0xb85e8000}, {0xb85ec000}, + {0xb85f0000}, {0xb85f4000}, {0xb85f8000}, {0xb85fc000}, + {0xb8600000}, {0xb8604000}, {0xb8608000}, {0xb860c000}, + {0xb8610000}, {0xb8614000}, {0xb8618000}, {0xb861c000}, + {0xb8620000}, {0xb8624000}, {0xb8628000}, {0xb862c000}, + {0xb8630000}, {0xb8634000}, {0xb8638000}, {0xb863c000}, + {0xb8640000}, {0xb8644000}, {0xb8648000}, {0xb864c000}, + {0xb8650000}, {0xb8654000}, {0xb8658000}, {0xb865c000}, + {0xb8660000}, {0xb8664000}, {0xb8668000}, {0xb866c000}, + {0xb8670000}, {0xb8674000}, {0xb8678000}, {0xb867c000}, + {0xb8680000}, {0xb8684000}, {0xb8688000}, {0xb868c000}, + {0xb8690000}, {0xb8694000}, {0xb8698000}, {0xb869c000}, + {0xb86a0000}, {0xb86a4000}, {0xb86a8000}, {0xb86ac000}, + {0xb86b0000}, {0xb86b4000}, {0xb86b8000}, {0xb86bc000}, + {0xb86c0000}, {0xb86c4000}, {0xb86c8000}, {0xb86cc000}, + {0xb86d0000}, {0xb86d4000}, {0xb86d8000}, {0xb86dc000}, + {0xb86e0000}, {0xb86e4000}, {0xb86e8000}, {0xb86ec000}, + {0xb86f0000}, {0xb86f4000}, {0xb86f8000}, {0xb86fc000}, + {0xb8700000}, {0xb8704000}, {0xb8708000}, {0xb870c000}, + {0xb8710000}, {0xb8714000}, {0xb8718000}, {0xb871c000}, + {0xb8720000}, {0xb8724000}, {0xb8728000}, {0xb872c000}, + {0xb8730000}, {0xb8734000}, {0xb8738000}, {0xb873c000}, + {0xb8740000}, {0xb8744000}, {0xb8748000}, {0xb874c000}, + {0xb8750000}, {0xb8754000}, {0xb8758000}, {0xb875c000}, + {0xb8760000}, {0xb8764000}, {0xb8768000}, {0xb876c000}, + {0xb8770000}, {0xb8774000}, {0xb8778000}, {0xb877c000}, + {0xb8780000}, {0xb8784000}, {0xb8788000}, {0xb878c000}, + {0xb8790000}, {0xb8794000}, {0xb8798000}, {0xb879c000}, + {0xb87a0000}, {0xb87a4000}, {0xb87a8000}, {0xb87ac000}, + {0xb87b0000}, {0xb87b4000}, {0xb87b8000}, {0xb87bc000}, + {0xb87c0000}, {0xb87c4000}, {0xb87c8000}, {0xb87cc000}, + {0xb87d0000}, {0xb87d4000}, {0xb87d8000}, {0xb87dc000}, + {0xb87e0000}, {0xb87e4000}, {0xb87e8000}, {0xb87ec000}, + {0xb87f0000}, {0xb87f4000}, {0xb87f8000}, {0xb87fc000}, + {0xb8800000}, {0xb8802000}, {0xb8804000}, {0xb8806000}, + {0xb8808000}, {0xb880a000}, {0xb880c000}, {0xb880e000}, + {0xb8810000}, {0xb8812000}, {0xb8814000}, {0xb8816000}, + {0xb8818000}, {0xb881a000}, {0xb881c000}, {0xb881e000}, + {0xb8820000}, {0xb8822000}, {0xb8824000}, {0xb8826000}, + {0xb8828000}, {0xb882a000}, {0xb882c000}, {0xb882e000}, + {0xb8830000}, {0xb8832000}, {0xb8834000}, {0xb8836000}, + {0xb8838000}, {0xb883a000}, {0xb883c000}, {0xb883e000}, + {0xb8840000}, {0xb8842000}, {0xb8844000}, {0xb8846000}, + {0xb8848000}, {0xb884a000}, {0xb884c000}, {0xb884e000}, + {0xb8850000}, {0xb8852000}, {0xb8854000}, {0xb8856000}, + {0xb8858000}, {0xb885a000}, {0xb885c000}, {0xb885e000}, + {0xb8860000}, {0xb8862000}, {0xb8864000}, {0xb8866000}, + {0xb8868000}, {0xb886a000}, {0xb886c000}, {0xb886e000}, + {0xb8870000}, {0xb8872000}, {0xb8874000}, {0xb8876000}, + {0xb8878000}, {0xb887a000}, {0xb887c000}, {0xb887e000}, + {0xb8880000}, {0xb8882000}, {0xb8884000}, {0xb8886000}, + {0xb8888000}, {0xb888a000}, {0xb888c000}, {0xb888e000}, + {0xb8890000}, {0xb8892000}, {0xb8894000}, {0xb8896000}, + {0xb8898000}, {0xb889a000}, {0xb889c000}, {0xb889e000}, + {0xb88a0000}, {0xb88a2000}, {0xb88a4000}, {0xb88a6000}, + {0xb88a8000}, {0xb88aa000}, {0xb88ac000}, {0xb88ae000}, + {0xb88b0000}, {0xb88b2000}, {0xb88b4000}, {0xb88b6000}, + {0xb88b8000}, {0xb88ba000}, {0xb88bc000}, {0xb88be000}, + {0xb88c0000}, {0xb88c2000}, {0xb88c4000}, {0xb88c6000}, + {0xb88c8000}, {0xb88ca000}, {0xb88cc000}, {0xb88ce000}, + {0xb88d0000}, {0xb88d2000}, {0xb88d4000}, {0xb88d6000}, + {0xb88d8000}, {0xb88da000}, {0xb88dc000}, {0xb88de000}, + {0xb88e0000}, {0xb88e2000}, {0xb88e4000}, {0xb88e6000}, + {0xb88e8000}, {0xb88ea000}, {0xb88ec000}, {0xb88ee000}, + {0xb88f0000}, {0xb88f2000}, {0xb88f4000}, {0xb88f6000}, + {0xb88f8000}, {0xb88fa000}, {0xb88fc000}, {0xb88fe000}, + {0xb8900000}, {0xb8902000}, {0xb8904000}, {0xb8906000}, + {0xb8908000}, {0xb890a000}, {0xb890c000}, {0xb890e000}, + {0xb8910000}, {0xb8912000}, {0xb8914000}, {0xb8916000}, + {0xb8918000}, {0xb891a000}, {0xb891c000}, {0xb891e000}, + {0xb8920000}, {0xb8922000}, {0xb8924000}, {0xb8926000}, + {0xb8928000}, {0xb892a000}, {0xb892c000}, {0xb892e000}, + {0xb8930000}, {0xb8932000}, {0xb8934000}, {0xb8936000}, + {0xb8938000}, {0xb893a000}, {0xb893c000}, {0xb893e000}, + {0xb8940000}, {0xb8942000}, {0xb8944000}, {0xb8946000}, + {0xb8948000}, {0xb894a000}, {0xb894c000}, {0xb894e000}, + {0xb8950000}, {0xb8952000}, {0xb8954000}, {0xb8956000}, + {0xb8958000}, {0xb895a000}, {0xb895c000}, {0xb895e000}, + {0xb8960000}, {0xb8962000}, {0xb8964000}, {0xb8966000}, + {0xb8968000}, {0xb896a000}, {0xb896c000}, {0xb896e000}, + {0xb8970000}, {0xb8972000}, {0xb8974000}, {0xb8976000}, + {0xb8978000}, {0xb897a000}, {0xb897c000}, {0xb897e000}, + {0xb8980000}, {0xb8982000}, {0xb8984000}, {0xb8986000}, + {0xb8988000}, {0xb898a000}, {0xb898c000}, {0xb898e000}, + {0xb8990000}, {0xb8992000}, {0xb8994000}, {0xb8996000}, + {0xb8998000}, {0xb899a000}, {0xb899c000}, {0xb899e000}, + {0xb89a0000}, {0xb89a2000}, {0xb89a4000}, {0xb89a6000}, + {0xb89a8000}, {0xb89aa000}, {0xb89ac000}, {0xb89ae000}, + {0xb89b0000}, {0xb89b2000}, {0xb89b4000}, {0xb89b6000}, + {0xb89b8000}, {0xb89ba000}, {0xb89bc000}, {0xb89be000}, + {0xb89c0000}, {0xb89c2000}, {0xb89c4000}, {0xb89c6000}, + {0xb89c8000}, {0xb89ca000}, {0xb89cc000}, {0xb89ce000}, + {0xb89d0000}, {0xb89d2000}, {0xb89d4000}, {0xb89d6000}, + {0xb89d8000}, {0xb89da000}, {0xb89dc000}, {0xb89de000}, + {0xb89e0000}, {0xb89e2000}, {0xb89e4000}, {0xb89e6000}, + {0xb89e8000}, {0xb89ea000}, {0xb89ec000}, {0xb89ee000}, + {0xb89f0000}, {0xb89f2000}, {0xb89f4000}, {0xb89f6000}, + {0xb89f8000}, {0xb89fa000}, {0xb89fc000}, {0xb89fe000}, + {0xb8a00000}, {0xb8a02000}, {0xb8a04000}, {0xb8a06000}, + {0xb8a08000}, {0xb8a0a000}, {0xb8a0c000}, {0xb8a0e000}, + {0xb8a10000}, {0xb8a12000}, {0xb8a14000}, {0xb8a16000}, + {0xb8a18000}, {0xb8a1a000}, {0xb8a1c000}, {0xb8a1e000}, + {0xb8a20000}, {0xb8a22000}, {0xb8a24000}, {0xb8a26000}, + {0xb8a28000}, {0xb8a2a000}, {0xb8a2c000}, {0xb8a2e000}, + {0xb8a30000}, {0xb8a32000}, {0xb8a34000}, {0xb8a36000}, + {0xb8a38000}, {0xb8a3a000}, {0xb8a3c000}, {0xb8a3e000}, + {0xb8a40000}, {0xb8a42000}, {0xb8a44000}, {0xb8a46000}, + {0xb8a48000}, {0xb8a4a000}, {0xb8a4c000}, {0xb8a4e000}, + {0xb8a50000}, {0xb8a52000}, {0xb8a54000}, {0xb8a56000}, + {0xb8a58000}, {0xb8a5a000}, {0xb8a5c000}, {0xb8a5e000}, + {0xb8a60000}, {0xb8a62000}, {0xb8a64000}, {0xb8a66000}, + {0xb8a68000}, {0xb8a6a000}, {0xb8a6c000}, {0xb8a6e000}, + {0xb8a70000}, {0xb8a72000}, {0xb8a74000}, {0xb8a76000}, + {0xb8a78000}, {0xb8a7a000}, {0xb8a7c000}, {0xb8a7e000}, + {0xb8a80000}, {0xb8a82000}, {0xb8a84000}, {0xb8a86000}, + {0xb8a88000}, {0xb8a8a000}, {0xb8a8c000}, {0xb8a8e000}, + {0xb8a90000}, {0xb8a92000}, {0xb8a94000}, {0xb8a96000}, + {0xb8a98000}, {0xb8a9a000}, {0xb8a9c000}, {0xb8a9e000}, + {0xb8aa0000}, {0xb8aa2000}, {0xb8aa4000}, {0xb8aa6000}, + {0xb8aa8000}, {0xb8aaa000}, {0xb8aac000}, {0xb8aae000}, + {0xb8ab0000}, {0xb8ab2000}, {0xb8ab4000}, {0xb8ab6000}, + {0xb8ab8000}, {0xb8aba000}, {0xb8abc000}, {0xb8abe000}, + {0xb8ac0000}, {0xb8ac2000}, {0xb8ac4000}, {0xb8ac6000}, + {0xb8ac8000}, {0xb8aca000}, {0xb8acc000}, {0xb8ace000}, + {0xb8ad0000}, {0xb8ad2000}, {0xb8ad4000}, {0xb8ad6000}, + {0xb8ad8000}, {0xb8ada000}, {0xb8adc000}, {0xb8ade000}, + {0xb8ae0000}, {0xb8ae2000}, {0xb8ae4000}, {0xb8ae6000}, + {0xb8ae8000}, {0xb8aea000}, {0xb8aec000}, {0xb8aee000}, + {0xb8af0000}, {0xb8af2000}, {0xb8af4000}, {0xb8af6000}, + {0xb8af8000}, {0xb8afa000}, {0xb8afc000}, {0xb8afe000}, + {0xb8b00000}, {0xb8b02000}, {0xb8b04000}, {0xb8b06000}, + {0xb8b08000}, {0xb8b0a000}, {0xb8b0c000}, {0xb8b0e000}, + {0xb8b10000}, {0xb8b12000}, {0xb8b14000}, {0xb8b16000}, + {0xb8b18000}, {0xb8b1a000}, {0xb8b1c000}, {0xb8b1e000}, + {0xb8b20000}, {0xb8b22000}, {0xb8b24000}, {0xb8b26000}, + {0xb8b28000}, {0xb8b2a000}, {0xb8b2c000}, {0xb8b2e000}, + {0xb8b30000}, {0xb8b32000}, {0xb8b34000}, {0xb8b36000}, + {0xb8b38000}, {0xb8b3a000}, {0xb8b3c000}, {0xb8b3e000}, + {0xb8b40000}, {0xb8b42000}, {0xb8b44000}, {0xb8b46000}, + {0xb8b48000}, {0xb8b4a000}, {0xb8b4c000}, {0xb8b4e000}, + {0xb8b50000}, {0xb8b52000}, {0xb8b54000}, {0xb8b56000}, + {0xb8b58000}, {0xb8b5a000}, {0xb8b5c000}, {0xb8b5e000}, + {0xb8b60000}, {0xb8b62000}, {0xb8b64000}, {0xb8b66000}, + {0xb8b68000}, {0xb8b6a000}, {0xb8b6c000}, {0xb8b6e000}, + {0xb8b70000}, {0xb8b72000}, {0xb8b74000}, {0xb8b76000}, + {0xb8b78000}, {0xb8b7a000}, {0xb8b7c000}, {0xb8b7e000}, + {0xb8b80000}, {0xb8b82000}, {0xb8b84000}, {0xb8b86000}, + {0xb8b88000}, {0xb8b8a000}, {0xb8b8c000}, {0xb8b8e000}, + {0xb8b90000}, {0xb8b92000}, {0xb8b94000}, {0xb8b96000}, + {0xb8b98000}, {0xb8b9a000}, {0xb8b9c000}, {0xb8b9e000}, + {0xb8ba0000}, {0xb8ba2000}, {0xb8ba4000}, {0xb8ba6000}, + {0xb8ba8000}, {0xb8baa000}, {0xb8bac000}, {0xb8bae000}, + {0xb8bb0000}, {0xb8bb2000}, {0xb8bb4000}, {0xb8bb6000}, + {0xb8bb8000}, {0xb8bba000}, {0xb8bbc000}, {0xb8bbe000}, + {0xb8bc0000}, {0xb8bc2000}, {0xb8bc4000}, {0xb8bc6000}, + {0xb8bc8000}, {0xb8bca000}, {0xb8bcc000}, {0xb8bce000}, + {0xb8bd0000}, {0xb8bd2000}, {0xb8bd4000}, {0xb8bd6000}, + {0xb8bd8000}, {0xb8bda000}, {0xb8bdc000}, {0xb8bde000}, + {0xb8be0000}, {0xb8be2000}, {0xb8be4000}, {0xb8be6000}, + {0xb8be8000}, {0xb8bea000}, {0xb8bec000}, {0xb8bee000}, + {0xb8bf0000}, {0xb8bf2000}, {0xb8bf4000}, {0xb8bf6000}, + {0xb8bf8000}, {0xb8bfa000}, {0xb8bfc000}, {0xb8bfe000}, + {0xb8c00000}, {0xb8c02000}, {0xb8c04000}, {0xb8c06000}, + {0xb8c08000}, {0xb8c0a000}, {0xb8c0c000}, {0xb8c0e000}, + {0xb8c10000}, {0xb8c12000}, {0xb8c14000}, {0xb8c16000}, + {0xb8c18000}, {0xb8c1a000}, {0xb8c1c000}, {0xb8c1e000}, + {0xb8c20000}, {0xb8c22000}, {0xb8c24000}, {0xb8c26000}, + {0xb8c28000}, {0xb8c2a000}, {0xb8c2c000}, {0xb8c2e000}, + {0xb8c30000}, {0xb8c32000}, {0xb8c34000}, {0xb8c36000}, + {0xb8c38000}, {0xb8c3a000}, {0xb8c3c000}, {0xb8c3e000}, + {0xb8c40000}, {0xb8c42000}, {0xb8c44000}, {0xb8c46000}, + {0xb8c48000}, {0xb8c4a000}, {0xb8c4c000}, {0xb8c4e000}, + {0xb8c50000}, {0xb8c52000}, {0xb8c54000}, {0xb8c56000}, + {0xb8c58000}, {0xb8c5a000}, {0xb8c5c000}, {0xb8c5e000}, + {0xb8c60000}, {0xb8c62000}, {0xb8c64000}, {0xb8c66000}, + {0xb8c68000}, {0xb8c6a000}, {0xb8c6c000}, {0xb8c6e000}, + {0xb8c70000}, {0xb8c72000}, {0xb8c74000}, {0xb8c76000}, + {0xb8c78000}, {0xb8c7a000}, {0xb8c7c000}, {0xb8c7e000}, + {0xb8c80000}, {0xb8c82000}, {0xb8c84000}, {0xb8c86000}, + {0xb8c88000}, {0xb8c8a000}, {0xb8c8c000}, {0xb8c8e000}, + {0xb8c90000}, {0xb8c92000}, {0xb8c94000}, {0xb8c96000}, + {0xb8c98000}, {0xb8c9a000}, {0xb8c9c000}, {0xb8c9e000}, + {0xb8ca0000}, {0xb8ca2000}, {0xb8ca4000}, {0xb8ca6000}, + {0xb8ca8000}, {0xb8caa000}, {0xb8cac000}, {0xb8cae000}, + {0xb8cb0000}, {0xb8cb2000}, {0xb8cb4000}, {0xb8cb6000}, + {0xb8cb8000}, {0xb8cba000}, {0xb8cbc000}, {0xb8cbe000}, + {0xb8cc0000}, {0xb8cc2000}, {0xb8cc4000}, {0xb8cc6000}, + {0xb8cc8000}, {0xb8cca000}, {0xb8ccc000}, {0xb8cce000}, + {0xb8cd0000}, {0xb8cd2000}, {0xb8cd4000}, {0xb8cd6000}, + {0xb8cd8000}, {0xb8cda000}, {0xb8cdc000}, {0xb8cde000}, + {0xb8ce0000}, {0xb8ce2000}, {0xb8ce4000}, {0xb8ce6000}, + {0xb8ce8000}, {0xb8cea000}, {0xb8cec000}, {0xb8cee000}, + {0xb8cf0000}, {0xb8cf2000}, {0xb8cf4000}, {0xb8cf6000}, + {0xb8cf8000}, {0xb8cfa000}, {0xb8cfc000}, {0xb8cfe000}, + {0xb8d00000}, {0xb8d02000}, {0xb8d04000}, {0xb8d06000}, + {0xb8d08000}, {0xb8d0a000}, {0xb8d0c000}, {0xb8d0e000}, + {0xb8d10000}, {0xb8d12000}, {0xb8d14000}, {0xb8d16000}, + {0xb8d18000}, {0xb8d1a000}, {0xb8d1c000}, {0xb8d1e000}, + {0xb8d20000}, {0xb8d22000}, {0xb8d24000}, {0xb8d26000}, + {0xb8d28000}, {0xb8d2a000}, {0xb8d2c000}, {0xb8d2e000}, + {0xb8d30000}, {0xb8d32000}, {0xb8d34000}, {0xb8d36000}, + {0xb8d38000}, {0xb8d3a000}, {0xb8d3c000}, {0xb8d3e000}, + {0xb8d40000}, {0xb8d42000}, {0xb8d44000}, {0xb8d46000}, + {0xb8d48000}, {0xb8d4a000}, {0xb8d4c000}, {0xb8d4e000}, + {0xb8d50000}, {0xb8d52000}, {0xb8d54000}, {0xb8d56000}, + {0xb8d58000}, {0xb8d5a000}, {0xb8d5c000}, {0xb8d5e000}, + {0xb8d60000}, {0xb8d62000}, {0xb8d64000}, {0xb8d66000}, + {0xb8d68000}, {0xb8d6a000}, {0xb8d6c000}, {0xb8d6e000}, + {0xb8d70000}, {0xb8d72000}, {0xb8d74000}, {0xb8d76000}, + {0xb8d78000}, {0xb8d7a000}, {0xb8d7c000}, {0xb8d7e000}, + {0xb8d80000}, {0xb8d82000}, {0xb8d84000}, {0xb8d86000}, + {0xb8d88000}, {0xb8d8a000}, {0xb8d8c000}, {0xb8d8e000}, + {0xb8d90000}, {0xb8d92000}, {0xb8d94000}, {0xb8d96000}, + {0xb8d98000}, {0xb8d9a000}, {0xb8d9c000}, {0xb8d9e000}, + {0xb8da0000}, {0xb8da2000}, {0xb8da4000}, {0xb8da6000}, + {0xb8da8000}, {0xb8daa000}, {0xb8dac000}, {0xb8dae000}, + {0xb8db0000}, {0xb8db2000}, {0xb8db4000}, {0xb8db6000}, + {0xb8db8000}, {0xb8dba000}, {0xb8dbc000}, {0xb8dbe000}, + {0xb8dc0000}, {0xb8dc2000}, {0xb8dc4000}, {0xb8dc6000}, + {0xb8dc8000}, {0xb8dca000}, {0xb8dcc000}, {0xb8dce000}, + {0xb8dd0000}, {0xb8dd2000}, {0xb8dd4000}, {0xb8dd6000}, + {0xb8dd8000}, {0xb8dda000}, {0xb8ddc000}, {0xb8dde000}, + {0xb8de0000}, {0xb8de2000}, {0xb8de4000}, {0xb8de6000}, + {0xb8de8000}, {0xb8dea000}, {0xb8dec000}, {0xb8dee000}, + {0xb8df0000}, {0xb8df2000}, {0xb8df4000}, {0xb8df6000}, + {0xb8df8000}, {0xb8dfa000}, {0xb8dfc000}, {0xb8dfe000}, + {0xb8e00000}, {0xb8e02000}, {0xb8e04000}, {0xb8e06000}, + {0xb8e08000}, {0xb8e0a000}, {0xb8e0c000}, {0xb8e0e000}, + {0xb8e10000}, {0xb8e12000}, {0xb8e14000}, {0xb8e16000}, + {0xb8e18000}, {0xb8e1a000}, {0xb8e1c000}, {0xb8e1e000}, + {0xb8e20000}, {0xb8e22000}, {0xb8e24000}, {0xb8e26000}, + {0xb8e28000}, {0xb8e2a000}, {0xb8e2c000}, {0xb8e2e000}, + {0xb8e30000}, {0xb8e32000}, {0xb8e34000}, {0xb8e36000}, + {0xb8e38000}, {0xb8e3a000}, {0xb8e3c000}, {0xb8e3e000}, + {0xb8e40000}, {0xb8e42000}, {0xb8e44000}, {0xb8e46000}, + {0xb8e48000}, {0xb8e4a000}, {0xb8e4c000}, {0xb8e4e000}, + {0xb8e50000}, {0xb8e52000}, {0xb8e54000}, {0xb8e56000}, + {0xb8e58000}, {0xb8e5a000}, {0xb8e5c000}, {0xb8e5e000}, + {0xb8e60000}, {0xb8e62000}, {0xb8e64000}, {0xb8e66000}, + {0xb8e68000}, {0xb8e6a000}, {0xb8e6c000}, {0xb8e6e000}, + {0xb8e70000}, {0xb8e72000}, {0xb8e74000}, {0xb8e76000}, + {0xb8e78000}, {0xb8e7a000}, {0xb8e7c000}, {0xb8e7e000}, + {0xb8e80000}, {0xb8e82000}, {0xb8e84000}, {0xb8e86000}, + {0xb8e88000}, {0xb8e8a000}, {0xb8e8c000}, {0xb8e8e000}, + {0xb8e90000}, {0xb8e92000}, {0xb8e94000}, {0xb8e96000}, + {0xb8e98000}, {0xb8e9a000}, {0xb8e9c000}, {0xb8e9e000}, + {0xb8ea0000}, {0xb8ea2000}, {0xb8ea4000}, {0xb8ea6000}, + {0xb8ea8000}, {0xb8eaa000}, {0xb8eac000}, {0xb8eae000}, + {0xb8eb0000}, {0xb8eb2000}, {0xb8eb4000}, {0xb8eb6000}, + {0xb8eb8000}, {0xb8eba000}, {0xb8ebc000}, {0xb8ebe000}, + {0xb8ec0000}, {0xb8ec2000}, {0xb8ec4000}, {0xb8ec6000}, + {0xb8ec8000}, {0xb8eca000}, {0xb8ecc000}, {0xb8ece000}, + {0xb8ed0000}, {0xb8ed2000}, {0xb8ed4000}, {0xb8ed6000}, + {0xb8ed8000}, {0xb8eda000}, {0xb8edc000}, {0xb8ede000}, + {0xb8ee0000}, {0xb8ee2000}, {0xb8ee4000}, {0xb8ee6000}, + {0xb8ee8000}, {0xb8eea000}, {0xb8eec000}, {0xb8eee000}, + {0xb8ef0000}, {0xb8ef2000}, {0xb8ef4000}, {0xb8ef6000}, + {0xb8ef8000}, {0xb8efa000}, {0xb8efc000}, {0xb8efe000}, + {0xb8f00000}, {0xb8f02000}, {0xb8f04000}, {0xb8f06000}, + {0xb8f08000}, {0xb8f0a000}, {0xb8f0c000}, {0xb8f0e000}, + {0xb8f10000}, {0xb8f12000}, {0xb8f14000}, {0xb8f16000}, + {0xb8f18000}, {0xb8f1a000}, {0xb8f1c000}, {0xb8f1e000}, + {0xb8f20000}, {0xb8f22000}, {0xb8f24000}, {0xb8f26000}, + {0xb8f28000}, {0xb8f2a000}, {0xb8f2c000}, {0xb8f2e000}, + {0xb8f30000}, {0xb8f32000}, {0xb8f34000}, {0xb8f36000}, + {0xb8f38000}, {0xb8f3a000}, {0xb8f3c000}, {0xb8f3e000}, + {0xb8f40000}, {0xb8f42000}, {0xb8f44000}, {0xb8f46000}, + {0xb8f48000}, {0xb8f4a000}, {0xb8f4c000}, {0xb8f4e000}, + {0xb8f50000}, {0xb8f52000}, {0xb8f54000}, {0xb8f56000}, + {0xb8f58000}, {0xb8f5a000}, {0xb8f5c000}, {0xb8f5e000}, + {0xb8f60000}, {0xb8f62000}, {0xb8f64000}, {0xb8f66000}, + {0xb8f68000}, {0xb8f6a000}, {0xb8f6c000}, {0xb8f6e000}, + {0xb8f70000}, {0xb8f72000}, {0xb8f74000}, {0xb8f76000}, + {0xb8f78000}, {0xb8f7a000}, {0xb8f7c000}, {0xb8f7e000}, + {0xb8f80000}, {0xb8f82000}, {0xb8f84000}, {0xb8f86000}, + {0xb8f88000}, {0xb8f8a000}, {0xb8f8c000}, {0xb8f8e000}, + {0xb8f90000}, {0xb8f92000}, {0xb8f94000}, {0xb8f96000}, + {0xb8f98000}, {0xb8f9a000}, {0xb8f9c000}, {0xb8f9e000}, + {0xb8fa0000}, {0xb8fa2000}, {0xb8fa4000}, {0xb8fa6000}, + {0xb8fa8000}, {0xb8faa000}, {0xb8fac000}, {0xb8fae000}, + {0xb8fb0000}, {0xb8fb2000}, {0xb8fb4000}, {0xb8fb6000}, + {0xb8fb8000}, {0xb8fba000}, {0xb8fbc000}, {0xb8fbe000}, + {0xb8fc0000}, {0xb8fc2000}, {0xb8fc4000}, {0xb8fc6000}, + {0xb8fc8000}, {0xb8fca000}, {0xb8fcc000}, {0xb8fce000}, + {0xb8fd0000}, {0xb8fd2000}, {0xb8fd4000}, {0xb8fd6000}, + {0xb8fd8000}, {0xb8fda000}, {0xb8fdc000}, {0xb8fde000}, + {0xb8fe0000}, {0xb8fe2000}, {0xb8fe4000}, {0xb8fe6000}, + {0xb8fe8000}, {0xb8fea000}, {0xb8fec000}, {0xb8fee000}, + {0xb8ff0000}, {0xb8ff2000}, {0xb8ff4000}, {0xb8ff6000}, + {0xb8ff8000}, {0xb8ffa000}, {0xb8ffc000}, {0xb8ffe000}, + {0xb9000000}, {0xb9002000}, {0xb9004000}, {0xb9006000}, + {0xb9008000}, {0xb900a000}, {0xb900c000}, {0xb900e000}, + {0xb9010000}, {0xb9012000}, {0xb9014000}, {0xb9016000}, + {0xb9018000}, {0xb901a000}, {0xb901c000}, {0xb901e000}, + {0xb9020000}, {0xb9022000}, {0xb9024000}, {0xb9026000}, + {0xb9028000}, {0xb902a000}, {0xb902c000}, {0xb902e000}, + {0xb9030000}, {0xb9032000}, {0xb9034000}, {0xb9036000}, + {0xb9038000}, {0xb903a000}, {0xb903c000}, {0xb903e000}, + {0xb9040000}, {0xb9042000}, {0xb9044000}, {0xb9046000}, + {0xb9048000}, {0xb904a000}, {0xb904c000}, {0xb904e000}, + {0xb9050000}, {0xb9052000}, {0xb9054000}, {0xb9056000}, + {0xb9058000}, {0xb905a000}, {0xb905c000}, {0xb905e000}, + {0xb9060000}, {0xb9062000}, {0xb9064000}, {0xb9066000}, + {0xb9068000}, {0xb906a000}, {0xb906c000}, {0xb906e000}, + {0xb9070000}, {0xb9072000}, {0xb9074000}, {0xb9076000}, + {0xb9078000}, {0xb907a000}, {0xb907c000}, {0xb907e000}, + {0xb9080000}, {0xb9082000}, {0xb9084000}, {0xb9086000}, + {0xb9088000}, {0xb908a000}, {0xb908c000}, {0xb908e000}, + {0xb9090000}, {0xb9092000}, {0xb9094000}, {0xb9096000}, + {0xb9098000}, {0xb909a000}, {0xb909c000}, {0xb909e000}, + {0xb90a0000}, {0xb90a2000}, {0xb90a4000}, {0xb90a6000}, + {0xb90a8000}, {0xb90aa000}, {0xb90ac000}, {0xb90ae000}, + {0xb90b0000}, {0xb90b2000}, {0xb90b4000}, {0xb90b6000}, + {0xb90b8000}, {0xb90ba000}, {0xb90bc000}, {0xb90be000}, + {0xb90c0000}, {0xb90c2000}, {0xb90c4000}, {0xb90c6000}, + {0xb90c8000}, {0xb90ca000}, {0xb90cc000}, {0xb90ce000}, + {0xb90d0000}, {0xb90d2000}, {0xb90d4000}, {0xb90d6000}, + {0xb90d8000}, {0xb90da000}, {0xb90dc000}, {0xb90de000}, + {0xb90e0000}, {0xb90e2000}, {0xb90e4000}, {0xb90e6000}, + {0xb90e8000}, {0xb90ea000}, {0xb90ec000}, {0xb90ee000}, + {0xb90f0000}, {0xb90f2000}, {0xb90f4000}, {0xb90f6000}, + {0xb90f8000}, {0xb90fa000}, {0xb90fc000}, {0xb90fe000}, + {0xb9100000}, {0xb9102000}, {0xb9104000}, {0xb9106000}, + {0xb9108000}, {0xb910a000}, {0xb910c000}, {0xb910e000}, + {0xb9110000}, {0xb9112000}, {0xb9114000}, {0xb9116000}, + {0xb9118000}, {0xb911a000}, {0xb911c000}, {0xb911e000}, + {0xb9120000}, {0xb9122000}, {0xb9124000}, {0xb9126000}, + {0xb9128000}, {0xb912a000}, {0xb912c000}, {0xb912e000}, + {0xb9130000}, {0xb9132000}, {0xb9134000}, {0xb9136000}, + {0xb9138000}, {0xb913a000}, {0xb913c000}, {0xb913e000}, + {0xb9140000}, {0xb9142000}, {0xb9144000}, {0xb9146000}, + {0xb9148000}, {0xb914a000}, {0xb914c000}, {0xb914e000}, + {0xb9150000}, {0xb9152000}, {0xb9154000}, {0xb9156000}, + {0xb9158000}, {0xb915a000}, {0xb915c000}, {0xb915e000}, + {0xb9160000}, {0xb9162000}, {0xb9164000}, {0xb9166000}, + {0xb9168000}, {0xb916a000}, {0xb916c000}, {0xb916e000}, + {0xb9170000}, {0xb9172000}, {0xb9174000}, {0xb9176000}, + {0xb9178000}, {0xb917a000}, {0xb917c000}, {0xb917e000}, + {0xb9180000}, {0xb9182000}, {0xb9184000}, {0xb9186000}, + {0xb9188000}, {0xb918a000}, {0xb918c000}, {0xb918e000}, + {0xb9190000}, {0xb9192000}, {0xb9194000}, {0xb9196000}, + {0xb9198000}, {0xb919a000}, {0xb919c000}, {0xb919e000}, + {0xb91a0000}, {0xb91a2000}, {0xb91a4000}, {0xb91a6000}, + {0xb91a8000}, {0xb91aa000}, {0xb91ac000}, {0xb91ae000}, + {0xb91b0000}, {0xb91b2000}, {0xb91b4000}, {0xb91b6000}, + {0xb91b8000}, {0xb91ba000}, {0xb91bc000}, {0xb91be000}, + {0xb91c0000}, {0xb91c2000}, {0xb91c4000}, {0xb91c6000}, + {0xb91c8000}, {0xb91ca000}, {0xb91cc000}, {0xb91ce000}, + {0xb91d0000}, {0xb91d2000}, {0xb91d4000}, {0xb91d6000}, + {0xb91d8000}, {0xb91da000}, {0xb91dc000}, {0xb91de000}, + {0xb91e0000}, {0xb91e2000}, {0xb91e4000}, {0xb91e6000}, + {0xb91e8000}, {0xb91ea000}, {0xb91ec000}, {0xb91ee000}, + {0xb91f0000}, {0xb91f2000}, {0xb91f4000}, {0xb91f6000}, + {0xb91f8000}, {0xb91fa000}, {0xb91fc000}, {0xb91fe000}, + {0xb9200000}, {0xb9202000}, {0xb9204000}, {0xb9206000}, + {0xb9208000}, {0xb920a000}, {0xb920c000}, {0xb920e000}, + {0xb9210000}, {0xb9212000}, {0xb9214000}, {0xb9216000}, + {0xb9218000}, {0xb921a000}, {0xb921c000}, {0xb921e000}, + {0xb9220000}, {0xb9222000}, {0xb9224000}, {0xb9226000}, + {0xb9228000}, {0xb922a000}, {0xb922c000}, {0xb922e000}, + {0xb9230000}, {0xb9232000}, {0xb9234000}, {0xb9236000}, + {0xb9238000}, {0xb923a000}, {0xb923c000}, {0xb923e000}, + {0xb9240000}, {0xb9242000}, {0xb9244000}, {0xb9246000}, + {0xb9248000}, {0xb924a000}, {0xb924c000}, {0xb924e000}, + {0xb9250000}, {0xb9252000}, {0xb9254000}, {0xb9256000}, + {0xb9258000}, {0xb925a000}, {0xb925c000}, {0xb925e000}, + {0xb9260000}, {0xb9262000}, {0xb9264000}, {0xb9266000}, + {0xb9268000}, {0xb926a000}, {0xb926c000}, {0xb926e000}, + {0xb9270000}, {0xb9272000}, {0xb9274000}, {0xb9276000}, + {0xb9278000}, {0xb927a000}, {0xb927c000}, {0xb927e000}, + {0xb9280000}, {0xb9282000}, {0xb9284000}, {0xb9286000}, + {0xb9288000}, {0xb928a000}, {0xb928c000}, {0xb928e000}, + {0xb9290000}, {0xb9292000}, {0xb9294000}, {0xb9296000}, + {0xb9298000}, {0xb929a000}, {0xb929c000}, {0xb929e000}, + {0xb92a0000}, {0xb92a2000}, {0xb92a4000}, {0xb92a6000}, + {0xb92a8000}, {0xb92aa000}, {0xb92ac000}, {0xb92ae000}, + {0xb92b0000}, {0xb92b2000}, {0xb92b4000}, {0xb92b6000}, + {0xb92b8000}, {0xb92ba000}, {0xb92bc000}, {0xb92be000}, + {0xb92c0000}, {0xb92c2000}, {0xb92c4000}, {0xb92c6000}, + {0xb92c8000}, {0xb92ca000}, {0xb92cc000}, {0xb92ce000}, + {0xb92d0000}, {0xb92d2000}, {0xb92d4000}, {0xb92d6000}, + {0xb92d8000}, {0xb92da000}, {0xb92dc000}, {0xb92de000}, + {0xb92e0000}, {0xb92e2000}, {0xb92e4000}, {0xb92e6000}, + {0xb92e8000}, {0xb92ea000}, {0xb92ec000}, {0xb92ee000}, + {0xb92f0000}, {0xb92f2000}, {0xb92f4000}, {0xb92f6000}, + {0xb92f8000}, {0xb92fa000}, {0xb92fc000}, {0xb92fe000}, + {0xb9300000}, {0xb9302000}, {0xb9304000}, {0xb9306000}, + {0xb9308000}, {0xb930a000}, {0xb930c000}, {0xb930e000}, + {0xb9310000}, {0xb9312000}, {0xb9314000}, {0xb9316000}, + {0xb9318000}, {0xb931a000}, {0xb931c000}, {0xb931e000}, + {0xb9320000}, {0xb9322000}, {0xb9324000}, {0xb9326000}, + {0xb9328000}, {0xb932a000}, {0xb932c000}, {0xb932e000}, + {0xb9330000}, {0xb9332000}, {0xb9334000}, {0xb9336000}, + {0xb9338000}, {0xb933a000}, {0xb933c000}, {0xb933e000}, + {0xb9340000}, {0xb9342000}, {0xb9344000}, {0xb9346000}, + {0xb9348000}, {0xb934a000}, {0xb934c000}, {0xb934e000}, + {0xb9350000}, {0xb9352000}, {0xb9354000}, {0xb9356000}, + {0xb9358000}, {0xb935a000}, {0xb935c000}, {0xb935e000}, + {0xb9360000}, {0xb9362000}, {0xb9364000}, {0xb9366000}, + {0xb9368000}, {0xb936a000}, {0xb936c000}, {0xb936e000}, + {0xb9370000}, {0xb9372000}, {0xb9374000}, {0xb9376000}, + {0xb9378000}, {0xb937a000}, {0xb937c000}, {0xb937e000}, + {0xb9380000}, {0xb9382000}, {0xb9384000}, {0xb9386000}, + {0xb9388000}, {0xb938a000}, {0xb938c000}, {0xb938e000}, + {0xb9390000}, {0xb9392000}, {0xb9394000}, {0xb9396000}, + {0xb9398000}, {0xb939a000}, {0xb939c000}, {0xb939e000}, + {0xb93a0000}, {0xb93a2000}, {0xb93a4000}, {0xb93a6000}, + {0xb93a8000}, {0xb93aa000}, {0xb93ac000}, {0xb93ae000}, + {0xb93b0000}, {0xb93b2000}, {0xb93b4000}, {0xb93b6000}, + {0xb93b8000}, {0xb93ba000}, {0xb93bc000}, {0xb93be000}, + {0xb93c0000}, {0xb93c2000}, {0xb93c4000}, {0xb93c6000}, + {0xb93c8000}, {0xb93ca000}, {0xb93cc000}, {0xb93ce000}, + {0xb93d0000}, {0xb93d2000}, {0xb93d4000}, {0xb93d6000}, + {0xb93d8000}, {0xb93da000}, {0xb93dc000}, {0xb93de000}, + {0xb93e0000}, {0xb93e2000}, {0xb93e4000}, {0xb93e6000}, + {0xb93e8000}, {0xb93ea000}, {0xb93ec000}, {0xb93ee000}, + {0xb93f0000}, {0xb93f2000}, {0xb93f4000}, {0xb93f6000}, + {0xb93f8000}, {0xb93fa000}, {0xb93fc000}, {0xb93fe000}, + {0xb9400000}, {0xb9402000}, {0xb9404000}, {0xb9406000}, + {0xb9408000}, {0xb940a000}, {0xb940c000}, {0xb940e000}, + {0xb9410000}, {0xb9412000}, {0xb9414000}, {0xb9416000}, + {0xb9418000}, {0xb941a000}, {0xb941c000}, {0xb941e000}, + {0xb9420000}, {0xb9422000}, {0xb9424000}, {0xb9426000}, + {0xb9428000}, {0xb942a000}, {0xb942c000}, {0xb942e000}, + {0xb9430000}, {0xb9432000}, {0xb9434000}, {0xb9436000}, + {0xb9438000}, {0xb943a000}, {0xb943c000}, {0xb943e000}, + {0xb9440000}, {0xb9442000}, {0xb9444000}, {0xb9446000}, + {0xb9448000}, {0xb944a000}, {0xb944c000}, {0xb944e000}, + {0xb9450000}, {0xb9452000}, {0xb9454000}, {0xb9456000}, + {0xb9458000}, {0xb945a000}, {0xb945c000}, {0xb945e000}, + {0xb9460000}, {0xb9462000}, {0xb9464000}, {0xb9466000}, + {0xb9468000}, {0xb946a000}, {0xb946c000}, {0xb946e000}, + {0xb9470000}, {0xb9472000}, {0xb9474000}, {0xb9476000}, + {0xb9478000}, {0xb947a000}, {0xb947c000}, {0xb947e000}, + {0xb9480000}, {0xb9482000}, {0xb9484000}, {0xb9486000}, + {0xb9488000}, {0xb948a000}, {0xb948c000}, {0xb948e000}, + {0xb9490000}, {0xb9492000}, {0xb9494000}, {0xb9496000}, + {0xb9498000}, {0xb949a000}, {0xb949c000}, {0xb949e000}, + {0xb94a0000}, {0xb94a2000}, {0xb94a4000}, {0xb94a6000}, + {0xb94a8000}, {0xb94aa000}, {0xb94ac000}, {0xb94ae000}, + {0xb94b0000}, {0xb94b2000}, {0xb94b4000}, {0xb94b6000}, + {0xb94b8000}, {0xb94ba000}, {0xb94bc000}, {0xb94be000}, + {0xb94c0000}, {0xb94c2000}, {0xb94c4000}, {0xb94c6000}, + {0xb94c8000}, {0xb94ca000}, {0xb94cc000}, {0xb94ce000}, + {0xb94d0000}, {0xb94d2000}, {0xb94d4000}, {0xb94d6000}, + {0xb94d8000}, {0xb94da000}, {0xb94dc000}, {0xb94de000}, + {0xb94e0000}, {0xb94e2000}, {0xb94e4000}, {0xb94e6000}, + {0xb94e8000}, {0xb94ea000}, {0xb94ec000}, {0xb94ee000}, + {0xb94f0000}, {0xb94f2000}, {0xb94f4000}, {0xb94f6000}, + {0xb94f8000}, {0xb94fa000}, {0xb94fc000}, {0xb94fe000}, + {0xb9500000}, {0xb9502000}, {0xb9504000}, {0xb9506000}, + {0xb9508000}, {0xb950a000}, {0xb950c000}, {0xb950e000}, + {0xb9510000}, {0xb9512000}, {0xb9514000}, {0xb9516000}, + {0xb9518000}, {0xb951a000}, {0xb951c000}, {0xb951e000}, + {0xb9520000}, {0xb9522000}, {0xb9524000}, {0xb9526000}, + {0xb9528000}, {0xb952a000}, {0xb952c000}, {0xb952e000}, + {0xb9530000}, {0xb9532000}, {0xb9534000}, {0xb9536000}, + {0xb9538000}, {0xb953a000}, {0xb953c000}, {0xb953e000}, + {0xb9540000}, {0xb9542000}, {0xb9544000}, {0xb9546000}, + {0xb9548000}, {0xb954a000}, {0xb954c000}, {0xb954e000}, + {0xb9550000}, {0xb9552000}, {0xb9554000}, {0xb9556000}, + {0xb9558000}, {0xb955a000}, {0xb955c000}, {0xb955e000}, + {0xb9560000}, {0xb9562000}, {0xb9564000}, {0xb9566000}, + {0xb9568000}, {0xb956a000}, {0xb956c000}, {0xb956e000}, + {0xb9570000}, {0xb9572000}, {0xb9574000}, {0xb9576000}, + {0xb9578000}, {0xb957a000}, {0xb957c000}, {0xb957e000}, + {0xb9580000}, {0xb9582000}, {0xb9584000}, {0xb9586000}, + {0xb9588000}, {0xb958a000}, {0xb958c000}, {0xb958e000}, + {0xb9590000}, {0xb9592000}, {0xb9594000}, {0xb9596000}, + {0xb9598000}, {0xb959a000}, {0xb959c000}, {0xb959e000}, + {0xb95a0000}, {0xb95a2000}, {0xb95a4000}, {0xb95a6000}, + {0xb95a8000}, {0xb95aa000}, {0xb95ac000}, {0xb95ae000}, + {0xb95b0000}, {0xb95b2000}, {0xb95b4000}, {0xb95b6000}, + {0xb95b8000}, {0xb95ba000}, {0xb95bc000}, {0xb95be000}, + {0xb95c0000}, {0xb95c2000}, {0xb95c4000}, {0xb95c6000}, + {0xb95c8000}, {0xb95ca000}, {0xb95cc000}, {0xb95ce000}, + {0xb95d0000}, {0xb95d2000}, {0xb95d4000}, {0xb95d6000}, + {0xb95d8000}, {0xb95da000}, {0xb95dc000}, {0xb95de000}, + {0xb95e0000}, {0xb95e2000}, {0xb95e4000}, {0xb95e6000}, + {0xb95e8000}, {0xb95ea000}, {0xb95ec000}, {0xb95ee000}, + {0xb95f0000}, {0xb95f2000}, {0xb95f4000}, {0xb95f6000}, + {0xb95f8000}, {0xb95fa000}, {0xb95fc000}, {0xb95fe000}, + {0xb9600000}, {0xb9602000}, {0xb9604000}, {0xb9606000}, + {0xb9608000}, {0xb960a000}, {0xb960c000}, {0xb960e000}, + {0xb9610000}, {0xb9612000}, {0xb9614000}, {0xb9616000}, + {0xb9618000}, {0xb961a000}, {0xb961c000}, {0xb961e000}, + {0xb9620000}, {0xb9622000}, {0xb9624000}, {0xb9626000}, + {0xb9628000}, {0xb962a000}, {0xb962c000}, {0xb962e000}, + {0xb9630000}, {0xb9632000}, {0xb9634000}, {0xb9636000}, + {0xb9638000}, {0xb963a000}, {0xb963c000}, {0xb963e000}, + {0xb9640000}, {0xb9642000}, {0xb9644000}, {0xb9646000}, + {0xb9648000}, {0xb964a000}, {0xb964c000}, {0xb964e000}, + {0xb9650000}, {0xb9652000}, {0xb9654000}, {0xb9656000}, + {0xb9658000}, {0xb965a000}, {0xb965c000}, {0xb965e000}, + {0xb9660000}, {0xb9662000}, {0xb9664000}, {0xb9666000}, + {0xb9668000}, {0xb966a000}, {0xb966c000}, {0xb966e000}, + {0xb9670000}, {0xb9672000}, {0xb9674000}, {0xb9676000}, + {0xb9678000}, {0xb967a000}, {0xb967c000}, {0xb967e000}, + {0xb9680000}, {0xb9682000}, {0xb9684000}, {0xb9686000}, + {0xb9688000}, {0xb968a000}, {0xb968c000}, {0xb968e000}, + {0xb9690000}, {0xb9692000}, {0xb9694000}, {0xb9696000}, + {0xb9698000}, {0xb969a000}, {0xb969c000}, {0xb969e000}, + {0xb96a0000}, {0xb96a2000}, {0xb96a4000}, {0xb96a6000}, + {0xb96a8000}, {0xb96aa000}, {0xb96ac000}, {0xb96ae000}, + {0xb96b0000}, {0xb96b2000}, {0xb96b4000}, {0xb96b6000}, + {0xb96b8000}, {0xb96ba000}, {0xb96bc000}, {0xb96be000}, + {0xb96c0000}, {0xb96c2000}, {0xb96c4000}, {0xb96c6000}, + {0xb96c8000}, {0xb96ca000}, {0xb96cc000}, {0xb96ce000}, + {0xb96d0000}, {0xb96d2000}, {0xb96d4000}, {0xb96d6000}, + {0xb96d8000}, {0xb96da000}, {0xb96dc000}, {0xb96de000}, + {0xb96e0000}, {0xb96e2000}, {0xb96e4000}, {0xb96e6000}, + {0xb96e8000}, {0xb96ea000}, {0xb96ec000}, {0xb96ee000}, + {0xb96f0000}, {0xb96f2000}, {0xb96f4000}, {0xb96f6000}, + {0xb96f8000}, {0xb96fa000}, {0xb96fc000}, {0xb96fe000}, + {0xb9700000}, {0xb9702000}, {0xb9704000}, {0xb9706000}, + {0xb9708000}, {0xb970a000}, {0xb970c000}, {0xb970e000}, + {0xb9710000}, {0xb9712000}, {0xb9714000}, {0xb9716000}, + {0xb9718000}, {0xb971a000}, {0xb971c000}, {0xb971e000}, + {0xb9720000}, {0xb9722000}, {0xb9724000}, {0xb9726000}, + {0xb9728000}, {0xb972a000}, {0xb972c000}, {0xb972e000}, + {0xb9730000}, {0xb9732000}, {0xb9734000}, {0xb9736000}, + {0xb9738000}, {0xb973a000}, {0xb973c000}, {0xb973e000}, + {0xb9740000}, {0xb9742000}, {0xb9744000}, {0xb9746000}, + {0xb9748000}, {0xb974a000}, {0xb974c000}, {0xb974e000}, + {0xb9750000}, {0xb9752000}, {0xb9754000}, {0xb9756000}, + {0xb9758000}, {0xb975a000}, {0xb975c000}, {0xb975e000}, + {0xb9760000}, {0xb9762000}, {0xb9764000}, {0xb9766000}, + {0xb9768000}, {0xb976a000}, {0xb976c000}, {0xb976e000}, + {0xb9770000}, {0xb9772000}, {0xb9774000}, {0xb9776000}, + {0xb9778000}, {0xb977a000}, {0xb977c000}, {0xb977e000}, + {0xb9780000}, {0xb9782000}, {0xb9784000}, {0xb9786000}, + {0xb9788000}, {0xb978a000}, {0xb978c000}, {0xb978e000}, + {0xb9790000}, {0xb9792000}, {0xb9794000}, {0xb9796000}, + {0xb9798000}, {0xb979a000}, {0xb979c000}, {0xb979e000}, + {0xb97a0000}, {0xb97a2000}, {0xb97a4000}, {0xb97a6000}, + {0xb97a8000}, {0xb97aa000}, {0xb97ac000}, {0xb97ae000}, + {0xb97b0000}, {0xb97b2000}, {0xb97b4000}, {0xb97b6000}, + {0xb97b8000}, {0xb97ba000}, {0xb97bc000}, {0xb97be000}, + {0xb97c0000}, {0xb97c2000}, {0xb97c4000}, {0xb97c6000}, + {0xb97c8000}, {0xb97ca000}, {0xb97cc000}, {0xb97ce000}, + {0xb97d0000}, {0xb97d2000}, {0xb97d4000}, {0xb97d6000}, + {0xb97d8000}, {0xb97da000}, {0xb97dc000}, {0xb97de000}, + {0xb97e0000}, {0xb97e2000}, {0xb97e4000}, {0xb97e6000}, + {0xb97e8000}, {0xb97ea000}, {0xb97ec000}, {0xb97ee000}, + {0xb97f0000}, {0xb97f2000}, {0xb97f4000}, {0xb97f6000}, + {0xb97f8000}, {0xb97fa000}, {0xb97fc000}, {0xb97fe000}, + {0xb9800000}, {0xb9802000}, {0xb9804000}, {0xb9806000}, + {0xb9808000}, {0xb980a000}, {0xb980c000}, {0xb980e000}, + {0xb9810000}, {0xb9812000}, {0xb9814000}, {0xb9816000}, + {0xb9818000}, {0xb981a000}, {0xb981c000}, {0xb981e000}, + {0xb9820000}, {0xb9822000}, {0xb9824000}, {0xb9826000}, + {0xb9828000}, {0xb982a000}, {0xb982c000}, {0xb982e000}, + {0xb9830000}, {0xb9832000}, {0xb9834000}, {0xb9836000}, + {0xb9838000}, {0xb983a000}, {0xb983c000}, {0xb983e000}, + {0xb9840000}, {0xb9842000}, {0xb9844000}, {0xb9846000}, + {0xb9848000}, {0xb984a000}, {0xb984c000}, {0xb984e000}, + {0xb9850000}, {0xb9852000}, {0xb9854000}, {0xb9856000}, + {0xb9858000}, {0xb985a000}, {0xb985c000}, {0xb985e000}, + {0xb9860000}, {0xb9862000}, {0xb9864000}, {0xb9866000}, + {0xb9868000}, {0xb986a000}, {0xb986c000}, {0xb986e000}, + {0xb9870000}, {0xb9872000}, {0xb9874000}, {0xb9876000}, + {0xb9878000}, {0xb987a000}, {0xb987c000}, {0xb987e000}, + {0xb9880000}, {0xb9882000}, {0xb9884000}, {0xb9886000}, + {0xb9888000}, {0xb988a000}, {0xb988c000}, {0xb988e000}, + {0xb9890000}, {0xb9892000}, {0xb9894000}, {0xb9896000}, + {0xb9898000}, {0xb989a000}, {0xb989c000}, {0xb989e000}, + {0xb98a0000}, {0xb98a2000}, {0xb98a4000}, {0xb98a6000}, + {0xb98a8000}, {0xb98aa000}, {0xb98ac000}, {0xb98ae000}, + {0xb98b0000}, {0xb98b2000}, {0xb98b4000}, {0xb98b6000}, + {0xb98b8000}, {0xb98ba000}, {0xb98bc000}, {0xb98be000}, + {0xb98c0000}, {0xb98c2000}, {0xb98c4000}, {0xb98c6000}, + {0xb98c8000}, {0xb98ca000}, {0xb98cc000}, {0xb98ce000}, + {0xb98d0000}, {0xb98d2000}, {0xb98d4000}, {0xb98d6000}, + {0xb98d8000}, {0xb98da000}, {0xb98dc000}, {0xb98de000}, + {0xb98e0000}, {0xb98e2000}, {0xb98e4000}, {0xb98e6000}, + {0xb98e8000}, {0xb98ea000}, {0xb98ec000}, {0xb98ee000}, + {0xb98f0000}, {0xb98f2000}, {0xb98f4000}, {0xb98f6000}, + {0xb98f8000}, {0xb98fa000}, {0xb98fc000}, {0xb98fe000}, + {0xb9900000}, {0xb9902000}, {0xb9904000}, {0xb9906000}, + {0xb9908000}, {0xb990a000}, {0xb990c000}, {0xb990e000}, + {0xb9910000}, {0xb9912000}, {0xb9914000}, {0xb9916000}, + {0xb9918000}, {0xb991a000}, {0xb991c000}, {0xb991e000}, + {0xb9920000}, {0xb9922000}, {0xb9924000}, {0xb9926000}, + {0xb9928000}, {0xb992a000}, {0xb992c000}, {0xb992e000}, + {0xb9930000}, {0xb9932000}, {0xb9934000}, {0xb9936000}, + {0xb9938000}, {0xb993a000}, {0xb993c000}, {0xb993e000}, + {0xb9940000}, {0xb9942000}, {0xb9944000}, {0xb9946000}, + {0xb9948000}, {0xb994a000}, {0xb994c000}, {0xb994e000}, + {0xb9950000}, {0xb9952000}, {0xb9954000}, {0xb9956000}, + {0xb9958000}, {0xb995a000}, {0xb995c000}, {0xb995e000}, + {0xb9960000}, {0xb9962000}, {0xb9964000}, {0xb9966000}, + {0xb9968000}, {0xb996a000}, {0xb996c000}, {0xb996e000}, + {0xb9970000}, {0xb9972000}, {0xb9974000}, {0xb9976000}, + {0xb9978000}, {0xb997a000}, {0xb997c000}, {0xb997e000}, + {0xb9980000}, {0xb9982000}, {0xb9984000}, {0xb9986000}, + {0xb9988000}, {0xb998a000}, {0xb998c000}, {0xb998e000}, + {0xb9990000}, {0xb9992000}, {0xb9994000}, {0xb9996000}, + {0xb9998000}, {0xb999a000}, {0xb999c000}, {0xb999e000}, + {0xb99a0000}, {0xb99a2000}, {0xb99a4000}, {0xb99a6000}, + {0xb99a8000}, {0xb99aa000}, {0xb99ac000}, {0xb99ae000}, + {0xb99b0000}, {0xb99b2000}, {0xb99b4000}, {0xb99b6000}, + {0xb99b8000}, {0xb99ba000}, {0xb99bc000}, {0xb99be000}, + {0xb99c0000}, {0xb99c2000}, {0xb99c4000}, {0xb99c6000}, + {0xb99c8000}, {0xb99ca000}, {0xb99cc000}, {0xb99ce000}, + {0xb99d0000}, {0xb99d2000}, {0xb99d4000}, {0xb99d6000}, + {0xb99d8000}, {0xb99da000}, {0xb99dc000}, {0xb99de000}, + {0xb99e0000}, {0xb99e2000}, {0xb99e4000}, {0xb99e6000}, + {0xb99e8000}, {0xb99ea000}, {0xb99ec000}, {0xb99ee000}, + {0xb99f0000}, {0xb99f2000}, {0xb99f4000}, {0xb99f6000}, + {0xb99f8000}, {0xb99fa000}, {0xb99fc000}, {0xb99fe000}, + {0xb9a00000}, {0xb9a02000}, {0xb9a04000}, {0xb9a06000}, + {0xb9a08000}, {0xb9a0a000}, {0xb9a0c000}, {0xb9a0e000}, + {0xb9a10000}, {0xb9a12000}, {0xb9a14000}, {0xb9a16000}, + {0xb9a18000}, {0xb9a1a000}, {0xb9a1c000}, {0xb9a1e000}, + {0xb9a20000}, {0xb9a22000}, {0xb9a24000}, {0xb9a26000}, + {0xb9a28000}, {0xb9a2a000}, {0xb9a2c000}, {0xb9a2e000}, + {0xb9a30000}, {0xb9a32000}, {0xb9a34000}, {0xb9a36000}, + {0xb9a38000}, {0xb9a3a000}, {0xb9a3c000}, {0xb9a3e000}, + {0xb9a40000}, {0xb9a42000}, {0xb9a44000}, {0xb9a46000}, + {0xb9a48000}, {0xb9a4a000}, {0xb9a4c000}, {0xb9a4e000}, + {0xb9a50000}, {0xb9a52000}, {0xb9a54000}, {0xb9a56000}, + {0xb9a58000}, {0xb9a5a000}, {0xb9a5c000}, {0xb9a5e000}, + {0xb9a60000}, {0xb9a62000}, {0xb9a64000}, {0xb9a66000}, + {0xb9a68000}, {0xb9a6a000}, {0xb9a6c000}, {0xb9a6e000}, + {0xb9a70000}, {0xb9a72000}, {0xb9a74000}, {0xb9a76000}, + {0xb9a78000}, {0xb9a7a000}, {0xb9a7c000}, {0xb9a7e000}, + {0xb9a80000}, {0xb9a82000}, {0xb9a84000}, {0xb9a86000}, + {0xb9a88000}, {0xb9a8a000}, {0xb9a8c000}, {0xb9a8e000}, + {0xb9a90000}, {0xb9a92000}, {0xb9a94000}, {0xb9a96000}, + {0xb9a98000}, {0xb9a9a000}, {0xb9a9c000}, {0xb9a9e000}, + {0xb9aa0000}, {0xb9aa2000}, {0xb9aa4000}, {0xb9aa6000}, + {0xb9aa8000}, {0xb9aaa000}, {0xb9aac000}, {0xb9aae000}, + {0xb9ab0000}, {0xb9ab2000}, {0xb9ab4000}, {0xb9ab6000}, + {0xb9ab8000}, {0xb9aba000}, {0xb9abc000}, {0xb9abe000}, + {0xb9ac0000}, {0xb9ac2000}, {0xb9ac4000}, {0xb9ac6000}, + {0xb9ac8000}, {0xb9aca000}, {0xb9acc000}, {0xb9ace000}, + {0xb9ad0000}, {0xb9ad2000}, {0xb9ad4000}, {0xb9ad6000}, + {0xb9ad8000}, {0xb9ada000}, {0xb9adc000}, {0xb9ade000}, + {0xb9ae0000}, {0xb9ae2000}, {0xb9ae4000}, {0xb9ae6000}, + {0xb9ae8000}, {0xb9aea000}, {0xb9aec000}, {0xb9aee000}, + {0xb9af0000}, {0xb9af2000}, {0xb9af4000}, {0xb9af6000}, + {0xb9af8000}, {0xb9afa000}, {0xb9afc000}, {0xb9afe000}, + {0xb9b00000}, {0xb9b02000}, {0xb9b04000}, {0xb9b06000}, + {0xb9b08000}, {0xb9b0a000}, {0xb9b0c000}, {0xb9b0e000}, + {0xb9b10000}, {0xb9b12000}, {0xb9b14000}, {0xb9b16000}, + {0xb9b18000}, {0xb9b1a000}, {0xb9b1c000}, {0xb9b1e000}, + {0xb9b20000}, {0xb9b22000}, {0xb9b24000}, {0xb9b26000}, + {0xb9b28000}, {0xb9b2a000}, {0xb9b2c000}, {0xb9b2e000}, + {0xb9b30000}, {0xb9b32000}, {0xb9b34000}, {0xb9b36000}, + {0xb9b38000}, {0xb9b3a000}, {0xb9b3c000}, {0xb9b3e000}, + {0xb9b40000}, {0xb9b42000}, {0xb9b44000}, {0xb9b46000}, + {0xb9b48000}, {0xb9b4a000}, {0xb9b4c000}, {0xb9b4e000}, + {0xb9b50000}, {0xb9b52000}, {0xb9b54000}, {0xb9b56000}, + {0xb9b58000}, {0xb9b5a000}, {0xb9b5c000}, {0xb9b5e000}, + {0xb9b60000}, {0xb9b62000}, {0xb9b64000}, {0xb9b66000}, + {0xb9b68000}, {0xb9b6a000}, {0xb9b6c000}, {0xb9b6e000}, + {0xb9b70000}, {0xb9b72000}, {0xb9b74000}, {0xb9b76000}, + {0xb9b78000}, {0xb9b7a000}, {0xb9b7c000}, {0xb9b7e000}, + {0xb9b80000}, {0xb9b82000}, {0xb9b84000}, {0xb9b86000}, + {0xb9b88000}, {0xb9b8a000}, {0xb9b8c000}, {0xb9b8e000}, + {0xb9b90000}, {0xb9b92000}, {0xb9b94000}, {0xb9b96000}, + {0xb9b98000}, {0xb9b9a000}, {0xb9b9c000}, {0xb9b9e000}, + {0xb9ba0000}, {0xb9ba2000}, {0xb9ba4000}, {0xb9ba6000}, + {0xb9ba8000}, {0xb9baa000}, {0xb9bac000}, {0xb9bae000}, + {0xb9bb0000}, {0xb9bb2000}, {0xb9bb4000}, {0xb9bb6000}, + {0xb9bb8000}, {0xb9bba000}, {0xb9bbc000}, {0xb9bbe000}, + {0xb9bc0000}, {0xb9bc2000}, {0xb9bc4000}, {0xb9bc6000}, + {0xb9bc8000}, {0xb9bca000}, {0xb9bcc000}, {0xb9bce000}, + {0xb9bd0000}, {0xb9bd2000}, {0xb9bd4000}, {0xb9bd6000}, + {0xb9bd8000}, {0xb9bda000}, {0xb9bdc000}, {0xb9bde000}, + {0xb9be0000}, {0xb9be2000}, {0xb9be4000}, {0xb9be6000}, + {0xb9be8000}, {0xb9bea000}, {0xb9bec000}, {0xb9bee000}, + {0xb9bf0000}, {0xb9bf2000}, {0xb9bf4000}, {0xb9bf6000}, + {0xb9bf8000}, {0xb9bfa000}, {0xb9bfc000}, {0xb9bfe000}, + {0xb9c00000}, {0xb9c02000}, {0xb9c04000}, {0xb9c06000}, + {0xb9c08000}, {0xb9c0a000}, {0xb9c0c000}, {0xb9c0e000}, + {0xb9c10000}, {0xb9c12000}, {0xb9c14000}, {0xb9c16000}, + {0xb9c18000}, {0xb9c1a000}, {0xb9c1c000}, {0xb9c1e000}, + {0xb9c20000}, {0xb9c22000}, {0xb9c24000}, {0xb9c26000}, + {0xb9c28000}, {0xb9c2a000}, {0xb9c2c000}, {0xb9c2e000}, + {0xb9c30000}, {0xb9c32000}, {0xb9c34000}, {0xb9c36000}, + {0xb9c38000}, {0xb9c3a000}, {0xb9c3c000}, {0xb9c3e000}, + {0xb9c40000}, {0xb9c42000}, {0xb9c44000}, {0xb9c46000}, + {0xb9c48000}, {0xb9c4a000}, {0xb9c4c000}, {0xb9c4e000}, + {0xb9c50000}, {0xb9c52000}, {0xb9c54000}, {0xb9c56000}, + {0xb9c58000}, {0xb9c5a000}, {0xb9c5c000}, {0xb9c5e000}, + {0xb9c60000}, {0xb9c62000}, {0xb9c64000}, {0xb9c66000}, + {0xb9c68000}, {0xb9c6a000}, {0xb9c6c000}, {0xb9c6e000}, + {0xb9c70000}, {0xb9c72000}, {0xb9c74000}, {0xb9c76000}, + {0xb9c78000}, {0xb9c7a000}, {0xb9c7c000}, {0xb9c7e000}, + {0xb9c80000}, {0xb9c82000}, {0xb9c84000}, {0xb9c86000}, + {0xb9c88000}, {0xb9c8a000}, {0xb9c8c000}, {0xb9c8e000}, + {0xb9c90000}, {0xb9c92000}, {0xb9c94000}, {0xb9c96000}, + {0xb9c98000}, {0xb9c9a000}, {0xb9c9c000}, {0xb9c9e000}, + {0xb9ca0000}, {0xb9ca2000}, {0xb9ca4000}, {0xb9ca6000}, + {0xb9ca8000}, {0xb9caa000}, {0xb9cac000}, {0xb9cae000}, + {0xb9cb0000}, {0xb9cb2000}, {0xb9cb4000}, {0xb9cb6000}, + {0xb9cb8000}, {0xb9cba000}, {0xb9cbc000}, {0xb9cbe000}, + {0xb9cc0000}, {0xb9cc2000}, {0xb9cc4000}, {0xb9cc6000}, + {0xb9cc8000}, {0xb9cca000}, {0xb9ccc000}, {0xb9cce000}, + {0xb9cd0000}, {0xb9cd2000}, {0xb9cd4000}, {0xb9cd6000}, + {0xb9cd8000}, {0xb9cda000}, {0xb9cdc000}, {0xb9cde000}, + {0xb9ce0000}, {0xb9ce2000}, {0xb9ce4000}, {0xb9ce6000}, + {0xb9ce8000}, {0xb9cea000}, {0xb9cec000}, {0xb9cee000}, + {0xb9cf0000}, {0xb9cf2000}, {0xb9cf4000}, {0xb9cf6000}, + {0xb9cf8000}, {0xb9cfa000}, {0xb9cfc000}, {0xb9cfe000}, + {0xb9d00000}, {0xb9d02000}, {0xb9d04000}, {0xb9d06000}, + {0xb9d08000}, {0xb9d0a000}, {0xb9d0c000}, {0xb9d0e000}, + {0xb9d10000}, {0xb9d12000}, {0xb9d14000}, {0xb9d16000}, + {0xb9d18000}, {0xb9d1a000}, {0xb9d1c000}, {0xb9d1e000}, + {0xb9d20000}, {0xb9d22000}, {0xb9d24000}, {0xb9d26000}, + {0xb9d28000}, {0xb9d2a000}, {0xb9d2c000}, {0xb9d2e000}, + {0xb9d30000}, {0xb9d32000}, {0xb9d34000}, {0xb9d36000}, + {0xb9d38000}, {0xb9d3a000}, {0xb9d3c000}, {0xb9d3e000}, + {0xb9d40000}, {0xb9d42000}, {0xb9d44000}, {0xb9d46000}, + {0xb9d48000}, {0xb9d4a000}, {0xb9d4c000}, {0xb9d4e000}, + {0xb9d50000}, {0xb9d52000}, {0xb9d54000}, {0xb9d56000}, + {0xb9d58000}, {0xb9d5a000}, {0xb9d5c000}, {0xb9d5e000}, + {0xb9d60000}, {0xb9d62000}, {0xb9d64000}, {0xb9d66000}, + {0xb9d68000}, {0xb9d6a000}, {0xb9d6c000}, {0xb9d6e000}, + {0xb9d70000}, {0xb9d72000}, {0xb9d74000}, {0xb9d76000}, + {0xb9d78000}, {0xb9d7a000}, {0xb9d7c000}, {0xb9d7e000}, + {0xb9d80000}, {0xb9d82000}, {0xb9d84000}, {0xb9d86000}, + {0xb9d88000}, {0xb9d8a000}, {0xb9d8c000}, {0xb9d8e000}, + {0xb9d90000}, {0xb9d92000}, {0xb9d94000}, {0xb9d96000}, + {0xb9d98000}, {0xb9d9a000}, {0xb9d9c000}, {0xb9d9e000}, + {0xb9da0000}, {0xb9da2000}, {0xb9da4000}, {0xb9da6000}, + {0xb9da8000}, {0xb9daa000}, {0xb9dac000}, {0xb9dae000}, + {0xb9db0000}, {0xb9db2000}, {0xb9db4000}, {0xb9db6000}, + {0xb9db8000}, {0xb9dba000}, {0xb9dbc000}, {0xb9dbe000}, + {0xb9dc0000}, {0xb9dc2000}, {0xb9dc4000}, {0xb9dc6000}, + {0xb9dc8000}, {0xb9dca000}, {0xb9dcc000}, {0xb9dce000}, + {0xb9dd0000}, {0xb9dd2000}, {0xb9dd4000}, {0xb9dd6000}, + {0xb9dd8000}, {0xb9dda000}, {0xb9ddc000}, {0xb9dde000}, + {0xb9de0000}, {0xb9de2000}, {0xb9de4000}, {0xb9de6000}, + {0xb9de8000}, {0xb9dea000}, {0xb9dec000}, {0xb9dee000}, + {0xb9df0000}, {0xb9df2000}, {0xb9df4000}, {0xb9df6000}, + {0xb9df8000}, {0xb9dfa000}, {0xb9dfc000}, {0xb9dfe000}, + {0xb9e00000}, {0xb9e02000}, {0xb9e04000}, {0xb9e06000}, + {0xb9e08000}, {0xb9e0a000}, {0xb9e0c000}, {0xb9e0e000}, + {0xb9e10000}, {0xb9e12000}, {0xb9e14000}, {0xb9e16000}, + {0xb9e18000}, {0xb9e1a000}, {0xb9e1c000}, {0xb9e1e000}, + {0xb9e20000}, {0xb9e22000}, {0xb9e24000}, {0xb9e26000}, + {0xb9e28000}, {0xb9e2a000}, {0xb9e2c000}, {0xb9e2e000}, + {0xb9e30000}, {0xb9e32000}, {0xb9e34000}, {0xb9e36000}, + {0xb9e38000}, {0xb9e3a000}, {0xb9e3c000}, {0xb9e3e000}, + {0xb9e40000}, {0xb9e42000}, {0xb9e44000}, {0xb9e46000}, + {0xb9e48000}, {0xb9e4a000}, {0xb9e4c000}, {0xb9e4e000}, + {0xb9e50000}, {0xb9e52000}, {0xb9e54000}, {0xb9e56000}, + {0xb9e58000}, {0xb9e5a000}, {0xb9e5c000}, {0xb9e5e000}, + {0xb9e60000}, {0xb9e62000}, {0xb9e64000}, {0xb9e66000}, + {0xb9e68000}, {0xb9e6a000}, {0xb9e6c000}, {0xb9e6e000}, + {0xb9e70000}, {0xb9e72000}, {0xb9e74000}, {0xb9e76000}, + {0xb9e78000}, {0xb9e7a000}, {0xb9e7c000}, {0xb9e7e000}, + {0xb9e80000}, {0xb9e82000}, {0xb9e84000}, {0xb9e86000}, + {0xb9e88000}, {0xb9e8a000}, {0xb9e8c000}, {0xb9e8e000}, + {0xb9e90000}, {0xb9e92000}, {0xb9e94000}, {0xb9e96000}, + {0xb9e98000}, {0xb9e9a000}, {0xb9e9c000}, {0xb9e9e000}, + {0xb9ea0000}, {0xb9ea2000}, {0xb9ea4000}, {0xb9ea6000}, + {0xb9ea8000}, {0xb9eaa000}, {0xb9eac000}, {0xb9eae000}, + {0xb9eb0000}, {0xb9eb2000}, {0xb9eb4000}, {0xb9eb6000}, + {0xb9eb8000}, {0xb9eba000}, {0xb9ebc000}, {0xb9ebe000}, + {0xb9ec0000}, {0xb9ec2000}, {0xb9ec4000}, {0xb9ec6000}, + {0xb9ec8000}, {0xb9eca000}, {0xb9ecc000}, {0xb9ece000}, + {0xb9ed0000}, {0xb9ed2000}, {0xb9ed4000}, {0xb9ed6000}, + {0xb9ed8000}, {0xb9eda000}, {0xb9edc000}, {0xb9ede000}, + {0xb9ee0000}, {0xb9ee2000}, {0xb9ee4000}, {0xb9ee6000}, + {0xb9ee8000}, {0xb9eea000}, {0xb9eec000}, {0xb9eee000}, + {0xb9ef0000}, {0xb9ef2000}, {0xb9ef4000}, {0xb9ef6000}, + {0xb9ef8000}, {0xb9efa000}, {0xb9efc000}, {0xb9efe000}, + {0xb9f00000}, {0xb9f02000}, {0xb9f04000}, {0xb9f06000}, + {0xb9f08000}, {0xb9f0a000}, {0xb9f0c000}, {0xb9f0e000}, + {0xb9f10000}, {0xb9f12000}, {0xb9f14000}, {0xb9f16000}, + {0xb9f18000}, {0xb9f1a000}, {0xb9f1c000}, {0xb9f1e000}, + {0xb9f20000}, {0xb9f22000}, {0xb9f24000}, {0xb9f26000}, + {0xb9f28000}, {0xb9f2a000}, {0xb9f2c000}, {0xb9f2e000}, + {0xb9f30000}, {0xb9f32000}, {0xb9f34000}, {0xb9f36000}, + {0xb9f38000}, {0xb9f3a000}, {0xb9f3c000}, {0xb9f3e000}, + {0xb9f40000}, {0xb9f42000}, {0xb9f44000}, {0xb9f46000}, + {0xb9f48000}, {0xb9f4a000}, {0xb9f4c000}, {0xb9f4e000}, + {0xb9f50000}, {0xb9f52000}, {0xb9f54000}, {0xb9f56000}, + {0xb9f58000}, {0xb9f5a000}, {0xb9f5c000}, {0xb9f5e000}, + {0xb9f60000}, {0xb9f62000}, {0xb9f64000}, {0xb9f66000}, + {0xb9f68000}, {0xb9f6a000}, {0xb9f6c000}, {0xb9f6e000}, + {0xb9f70000}, {0xb9f72000}, {0xb9f74000}, {0xb9f76000}, + {0xb9f78000}, {0xb9f7a000}, {0xb9f7c000}, {0xb9f7e000}, + {0xb9f80000}, {0xb9f82000}, {0xb9f84000}, {0xb9f86000}, + {0xb9f88000}, {0xb9f8a000}, {0xb9f8c000}, {0xb9f8e000}, + {0xb9f90000}, {0xb9f92000}, {0xb9f94000}, {0xb9f96000}, + {0xb9f98000}, {0xb9f9a000}, {0xb9f9c000}, {0xb9f9e000}, + {0xb9fa0000}, {0xb9fa2000}, {0xb9fa4000}, {0xb9fa6000}, + {0xb9fa8000}, {0xb9faa000}, {0xb9fac000}, {0xb9fae000}, + {0xb9fb0000}, {0xb9fb2000}, {0xb9fb4000}, {0xb9fb6000}, + {0xb9fb8000}, {0xb9fba000}, {0xb9fbc000}, {0xb9fbe000}, + {0xb9fc0000}, {0xb9fc2000}, {0xb9fc4000}, {0xb9fc6000}, + {0xb9fc8000}, {0xb9fca000}, {0xb9fcc000}, {0xb9fce000}, + {0xb9fd0000}, {0xb9fd2000}, {0xb9fd4000}, {0xb9fd6000}, + {0xb9fd8000}, {0xb9fda000}, {0xb9fdc000}, {0xb9fde000}, + {0xb9fe0000}, {0xb9fe2000}, {0xb9fe4000}, {0xb9fe6000}, + {0xb9fe8000}, {0xb9fea000}, {0xb9fec000}, {0xb9fee000}, + {0xb9ff0000}, {0xb9ff2000}, {0xb9ff4000}, {0xb9ff6000}, + {0xb9ff8000}, {0xb9ffa000}, {0xb9ffc000}, {0xb9ffe000}, + {0xba000000}, {0xba002000}, {0xba004000}, {0xba006000}, + {0xba008000}, {0xba00a000}, {0xba00c000}, {0xba00e000}, + {0xba010000}, {0xba012000}, {0xba014000}, {0xba016000}, + {0xba018000}, {0xba01a000}, {0xba01c000}, {0xba01e000}, + {0xba020000}, {0xba022000}, {0xba024000}, {0xba026000}, + {0xba028000}, {0xba02a000}, {0xba02c000}, {0xba02e000}, + {0xba030000}, {0xba032000}, {0xba034000}, {0xba036000}, + {0xba038000}, {0xba03a000}, {0xba03c000}, {0xba03e000}, + {0xba040000}, {0xba042000}, {0xba044000}, {0xba046000}, + {0xba048000}, {0xba04a000}, {0xba04c000}, {0xba04e000}, + {0xba050000}, {0xba052000}, {0xba054000}, {0xba056000}, + {0xba058000}, {0xba05a000}, {0xba05c000}, {0xba05e000}, + {0xba060000}, {0xba062000}, {0xba064000}, {0xba066000}, + {0xba068000}, {0xba06a000}, {0xba06c000}, {0xba06e000}, + {0xba070000}, {0xba072000}, {0xba074000}, {0xba076000}, + {0xba078000}, {0xba07a000}, {0xba07c000}, {0xba07e000}, + {0xba080000}, {0xba082000}, {0xba084000}, {0xba086000}, + {0xba088000}, {0xba08a000}, {0xba08c000}, {0xba08e000}, + {0xba090000}, {0xba092000}, {0xba094000}, {0xba096000}, + {0xba098000}, {0xba09a000}, {0xba09c000}, {0xba09e000}, + {0xba0a0000}, {0xba0a2000}, {0xba0a4000}, {0xba0a6000}, + {0xba0a8000}, {0xba0aa000}, {0xba0ac000}, {0xba0ae000}, + {0xba0b0000}, {0xba0b2000}, {0xba0b4000}, {0xba0b6000}, + {0xba0b8000}, {0xba0ba000}, {0xba0bc000}, {0xba0be000}, + {0xba0c0000}, {0xba0c2000}, {0xba0c4000}, {0xba0c6000}, + {0xba0c8000}, {0xba0ca000}, {0xba0cc000}, {0xba0ce000}, + {0xba0d0000}, {0xba0d2000}, {0xba0d4000}, {0xba0d6000}, + {0xba0d8000}, {0xba0da000}, {0xba0dc000}, {0xba0de000}, + {0xba0e0000}, {0xba0e2000}, {0xba0e4000}, {0xba0e6000}, + {0xba0e8000}, {0xba0ea000}, {0xba0ec000}, {0xba0ee000}, + {0xba0f0000}, {0xba0f2000}, {0xba0f4000}, {0xba0f6000}, + {0xba0f8000}, {0xba0fa000}, {0xba0fc000}, {0xba0fe000}, + {0xba100000}, {0xba102000}, {0xba104000}, {0xba106000}, + {0xba108000}, {0xba10a000}, {0xba10c000}, {0xba10e000}, + {0xba110000}, {0xba112000}, {0xba114000}, {0xba116000}, + {0xba118000}, {0xba11a000}, {0xba11c000}, {0xba11e000}, + {0xba120000}, {0xba122000}, {0xba124000}, {0xba126000}, + {0xba128000}, {0xba12a000}, {0xba12c000}, {0xba12e000}, + {0xba130000}, {0xba132000}, {0xba134000}, {0xba136000}, + {0xba138000}, {0xba13a000}, {0xba13c000}, {0xba13e000}, + {0xba140000}, {0xba142000}, {0xba144000}, {0xba146000}, + {0xba148000}, {0xba14a000}, {0xba14c000}, {0xba14e000}, + {0xba150000}, {0xba152000}, {0xba154000}, {0xba156000}, + {0xba158000}, {0xba15a000}, {0xba15c000}, {0xba15e000}, + {0xba160000}, {0xba162000}, {0xba164000}, {0xba166000}, + {0xba168000}, {0xba16a000}, {0xba16c000}, {0xba16e000}, + {0xba170000}, {0xba172000}, {0xba174000}, {0xba176000}, + {0xba178000}, {0xba17a000}, {0xba17c000}, {0xba17e000}, + {0xba180000}, {0xba182000}, {0xba184000}, {0xba186000}, + {0xba188000}, {0xba18a000}, {0xba18c000}, {0xba18e000}, + {0xba190000}, {0xba192000}, {0xba194000}, {0xba196000}, + {0xba198000}, {0xba19a000}, {0xba19c000}, {0xba19e000}, + {0xba1a0000}, {0xba1a2000}, {0xba1a4000}, {0xba1a6000}, + {0xba1a8000}, {0xba1aa000}, {0xba1ac000}, {0xba1ae000}, + {0xba1b0000}, {0xba1b2000}, {0xba1b4000}, {0xba1b6000}, + {0xba1b8000}, {0xba1ba000}, {0xba1bc000}, {0xba1be000}, + {0xba1c0000}, {0xba1c2000}, {0xba1c4000}, {0xba1c6000}, + {0xba1c8000}, {0xba1ca000}, {0xba1cc000}, {0xba1ce000}, + {0xba1d0000}, {0xba1d2000}, {0xba1d4000}, {0xba1d6000}, + {0xba1d8000}, {0xba1da000}, {0xba1dc000}, {0xba1de000}, + {0xba1e0000}, {0xba1e2000}, {0xba1e4000}, {0xba1e6000}, + {0xba1e8000}, {0xba1ea000}, {0xba1ec000}, {0xba1ee000}, + {0xba1f0000}, {0xba1f2000}, {0xba1f4000}, {0xba1f6000}, + {0xba1f8000}, {0xba1fa000}, {0xba1fc000}, {0xba1fe000}, + {0xba200000}, {0xba202000}, {0xba204000}, {0xba206000}, + {0xba208000}, {0xba20a000}, {0xba20c000}, {0xba20e000}, + {0xba210000}, {0xba212000}, {0xba214000}, {0xba216000}, + {0xba218000}, {0xba21a000}, {0xba21c000}, {0xba21e000}, + {0xba220000}, {0xba222000}, {0xba224000}, {0xba226000}, + {0xba228000}, {0xba22a000}, {0xba22c000}, {0xba22e000}, + {0xba230000}, {0xba232000}, {0xba234000}, {0xba236000}, + {0xba238000}, {0xba23a000}, {0xba23c000}, {0xba23e000}, + {0xba240000}, {0xba242000}, {0xba244000}, {0xba246000}, + {0xba248000}, {0xba24a000}, {0xba24c000}, {0xba24e000}, + {0xba250000}, {0xba252000}, {0xba254000}, {0xba256000}, + {0xba258000}, {0xba25a000}, {0xba25c000}, {0xba25e000}, + {0xba260000}, {0xba262000}, {0xba264000}, {0xba266000}, + {0xba268000}, {0xba26a000}, {0xba26c000}, {0xba26e000}, + {0xba270000}, {0xba272000}, {0xba274000}, {0xba276000}, + {0xba278000}, {0xba27a000}, {0xba27c000}, {0xba27e000}, + {0xba280000}, {0xba282000}, {0xba284000}, {0xba286000}, + {0xba288000}, {0xba28a000}, {0xba28c000}, {0xba28e000}, + {0xba290000}, {0xba292000}, {0xba294000}, {0xba296000}, + {0xba298000}, {0xba29a000}, {0xba29c000}, {0xba29e000}, + {0xba2a0000}, {0xba2a2000}, {0xba2a4000}, {0xba2a6000}, + {0xba2a8000}, {0xba2aa000}, {0xba2ac000}, {0xba2ae000}, + {0xba2b0000}, {0xba2b2000}, {0xba2b4000}, {0xba2b6000}, + {0xba2b8000}, {0xba2ba000}, {0xba2bc000}, {0xba2be000}, + {0xba2c0000}, {0xba2c2000}, {0xba2c4000}, {0xba2c6000}, + {0xba2c8000}, {0xba2ca000}, {0xba2cc000}, {0xba2ce000}, + {0xba2d0000}, {0xba2d2000}, {0xba2d4000}, {0xba2d6000}, + {0xba2d8000}, {0xba2da000}, {0xba2dc000}, {0xba2de000}, + {0xba2e0000}, {0xba2e2000}, {0xba2e4000}, {0xba2e6000}, + {0xba2e8000}, {0xba2ea000}, {0xba2ec000}, {0xba2ee000}, + {0xba2f0000}, {0xba2f2000}, {0xba2f4000}, {0xba2f6000}, + {0xba2f8000}, {0xba2fa000}, {0xba2fc000}, {0xba2fe000}, + {0xba300000}, {0xba302000}, {0xba304000}, {0xba306000}, + {0xba308000}, {0xba30a000}, {0xba30c000}, {0xba30e000}, + {0xba310000}, {0xba312000}, {0xba314000}, {0xba316000}, + {0xba318000}, {0xba31a000}, {0xba31c000}, {0xba31e000}, + {0xba320000}, {0xba322000}, {0xba324000}, {0xba326000}, + {0xba328000}, {0xba32a000}, {0xba32c000}, {0xba32e000}, + {0xba330000}, {0xba332000}, {0xba334000}, {0xba336000}, + {0xba338000}, {0xba33a000}, {0xba33c000}, {0xba33e000}, + {0xba340000}, {0xba342000}, {0xba344000}, {0xba346000}, + {0xba348000}, {0xba34a000}, {0xba34c000}, {0xba34e000}, + {0xba350000}, {0xba352000}, {0xba354000}, {0xba356000}, + {0xba358000}, {0xba35a000}, {0xba35c000}, {0xba35e000}, + {0xba360000}, {0xba362000}, {0xba364000}, {0xba366000}, + {0xba368000}, {0xba36a000}, {0xba36c000}, {0xba36e000}, + {0xba370000}, {0xba372000}, {0xba374000}, {0xba376000}, + {0xba378000}, {0xba37a000}, {0xba37c000}, {0xba37e000}, + {0xba380000}, {0xba382000}, {0xba384000}, {0xba386000}, + {0xba388000}, {0xba38a000}, {0xba38c000}, {0xba38e000}, + {0xba390000}, {0xba392000}, {0xba394000}, {0xba396000}, + {0xba398000}, {0xba39a000}, {0xba39c000}, {0xba39e000}, + {0xba3a0000}, {0xba3a2000}, {0xba3a4000}, {0xba3a6000}, + {0xba3a8000}, {0xba3aa000}, {0xba3ac000}, {0xba3ae000}, + {0xba3b0000}, {0xba3b2000}, {0xba3b4000}, {0xba3b6000}, + {0xba3b8000}, {0xba3ba000}, {0xba3bc000}, {0xba3be000}, + {0xba3c0000}, {0xba3c2000}, {0xba3c4000}, {0xba3c6000}, + {0xba3c8000}, {0xba3ca000}, {0xba3cc000}, {0xba3ce000}, + {0xba3d0000}, {0xba3d2000}, {0xba3d4000}, {0xba3d6000}, + {0xba3d8000}, {0xba3da000}, {0xba3dc000}, {0xba3de000}, + {0xba3e0000}, {0xba3e2000}, {0xba3e4000}, {0xba3e6000}, + {0xba3e8000}, {0xba3ea000}, {0xba3ec000}, {0xba3ee000}, + {0xba3f0000}, {0xba3f2000}, {0xba3f4000}, {0xba3f6000}, + {0xba3f8000}, {0xba3fa000}, {0xba3fc000}, {0xba3fe000}, + {0xba400000}, {0xba402000}, {0xba404000}, {0xba406000}, + {0xba408000}, {0xba40a000}, {0xba40c000}, {0xba40e000}, + {0xba410000}, {0xba412000}, {0xba414000}, {0xba416000}, + {0xba418000}, {0xba41a000}, {0xba41c000}, {0xba41e000}, + {0xba420000}, {0xba422000}, {0xba424000}, {0xba426000}, + {0xba428000}, {0xba42a000}, {0xba42c000}, {0xba42e000}, + {0xba430000}, {0xba432000}, {0xba434000}, {0xba436000}, + {0xba438000}, {0xba43a000}, {0xba43c000}, {0xba43e000}, + {0xba440000}, {0xba442000}, {0xba444000}, {0xba446000}, + {0xba448000}, {0xba44a000}, {0xba44c000}, {0xba44e000}, + {0xba450000}, {0xba452000}, {0xba454000}, {0xba456000}, + {0xba458000}, {0xba45a000}, {0xba45c000}, {0xba45e000}, + {0xba460000}, {0xba462000}, {0xba464000}, {0xba466000}, + {0xba468000}, {0xba46a000}, {0xba46c000}, {0xba46e000}, + {0xba470000}, {0xba472000}, {0xba474000}, {0xba476000}, + {0xba478000}, {0xba47a000}, {0xba47c000}, {0xba47e000}, + {0xba480000}, {0xba482000}, {0xba484000}, {0xba486000}, + {0xba488000}, {0xba48a000}, {0xba48c000}, {0xba48e000}, + {0xba490000}, {0xba492000}, {0xba494000}, {0xba496000}, + {0xba498000}, {0xba49a000}, {0xba49c000}, {0xba49e000}, + {0xba4a0000}, {0xba4a2000}, {0xba4a4000}, {0xba4a6000}, + {0xba4a8000}, {0xba4aa000}, {0xba4ac000}, {0xba4ae000}, + {0xba4b0000}, {0xba4b2000}, {0xba4b4000}, {0xba4b6000}, + {0xba4b8000}, {0xba4ba000}, {0xba4bc000}, {0xba4be000}, + {0xba4c0000}, {0xba4c2000}, {0xba4c4000}, {0xba4c6000}, + {0xba4c8000}, {0xba4ca000}, {0xba4cc000}, {0xba4ce000}, + {0xba4d0000}, {0xba4d2000}, {0xba4d4000}, {0xba4d6000}, + {0xba4d8000}, {0xba4da000}, {0xba4dc000}, {0xba4de000}, + {0xba4e0000}, {0xba4e2000}, {0xba4e4000}, {0xba4e6000}, + {0xba4e8000}, {0xba4ea000}, {0xba4ec000}, {0xba4ee000}, + {0xba4f0000}, {0xba4f2000}, {0xba4f4000}, {0xba4f6000}, + {0xba4f8000}, {0xba4fa000}, {0xba4fc000}, {0xba4fe000}, + {0xba500000}, {0xba502000}, {0xba504000}, {0xba506000}, + {0xba508000}, {0xba50a000}, {0xba50c000}, {0xba50e000}, + {0xba510000}, {0xba512000}, {0xba514000}, {0xba516000}, + {0xba518000}, {0xba51a000}, {0xba51c000}, {0xba51e000}, + {0xba520000}, {0xba522000}, {0xba524000}, {0xba526000}, + {0xba528000}, {0xba52a000}, {0xba52c000}, {0xba52e000}, + {0xba530000}, {0xba532000}, {0xba534000}, {0xba536000}, + {0xba538000}, {0xba53a000}, {0xba53c000}, {0xba53e000}, + {0xba540000}, {0xba542000}, {0xba544000}, {0xba546000}, + {0xba548000}, {0xba54a000}, {0xba54c000}, {0xba54e000}, + {0xba550000}, {0xba552000}, {0xba554000}, {0xba556000}, + {0xba558000}, {0xba55a000}, {0xba55c000}, {0xba55e000}, + {0xba560000}, {0xba562000}, {0xba564000}, {0xba566000}, + {0xba568000}, {0xba56a000}, {0xba56c000}, {0xba56e000}, + {0xba570000}, {0xba572000}, {0xba574000}, {0xba576000}, + {0xba578000}, {0xba57a000}, {0xba57c000}, {0xba57e000}, + {0xba580000}, {0xba582000}, {0xba584000}, {0xba586000}, + {0xba588000}, {0xba58a000}, {0xba58c000}, {0xba58e000}, + {0xba590000}, {0xba592000}, {0xba594000}, {0xba596000}, + {0xba598000}, {0xba59a000}, {0xba59c000}, {0xba59e000}, + {0xba5a0000}, {0xba5a2000}, {0xba5a4000}, {0xba5a6000}, + {0xba5a8000}, {0xba5aa000}, {0xba5ac000}, {0xba5ae000}, + {0xba5b0000}, {0xba5b2000}, {0xba5b4000}, {0xba5b6000}, + {0xba5b8000}, {0xba5ba000}, {0xba5bc000}, {0xba5be000}, + {0xba5c0000}, {0xba5c2000}, {0xba5c4000}, {0xba5c6000}, + {0xba5c8000}, {0xba5ca000}, {0xba5cc000}, {0xba5ce000}, + {0xba5d0000}, {0xba5d2000}, {0xba5d4000}, {0xba5d6000}, + {0xba5d8000}, {0xba5da000}, {0xba5dc000}, {0xba5de000}, + {0xba5e0000}, {0xba5e2000}, {0xba5e4000}, {0xba5e6000}, + {0xba5e8000}, {0xba5ea000}, {0xba5ec000}, {0xba5ee000}, + {0xba5f0000}, {0xba5f2000}, {0xba5f4000}, {0xba5f6000}, + {0xba5f8000}, {0xba5fa000}, {0xba5fc000}, {0xba5fe000}, + {0xba600000}, {0xba602000}, {0xba604000}, {0xba606000}, + {0xba608000}, {0xba60a000}, {0xba60c000}, {0xba60e000}, + {0xba610000}, {0xba612000}, {0xba614000}, {0xba616000}, + {0xba618000}, {0xba61a000}, {0xba61c000}, {0xba61e000}, + {0xba620000}, {0xba622000}, {0xba624000}, {0xba626000}, + {0xba628000}, {0xba62a000}, {0xba62c000}, {0xba62e000}, + {0xba630000}, {0xba632000}, {0xba634000}, {0xba636000}, + {0xba638000}, {0xba63a000}, {0xba63c000}, {0xba63e000}, + {0xba640000}, {0xba642000}, {0xba644000}, {0xba646000}, + {0xba648000}, {0xba64a000}, {0xba64c000}, {0xba64e000}, + {0xba650000}, {0xba652000}, {0xba654000}, {0xba656000}, + {0xba658000}, {0xba65a000}, {0xba65c000}, {0xba65e000}, + {0xba660000}, {0xba662000}, {0xba664000}, {0xba666000}, + {0xba668000}, {0xba66a000}, {0xba66c000}, {0xba66e000}, + {0xba670000}, {0xba672000}, {0xba674000}, {0xba676000}, + {0xba678000}, {0xba67a000}, {0xba67c000}, {0xba67e000}, + {0xba680000}, {0xba682000}, {0xba684000}, {0xba686000}, + {0xba688000}, {0xba68a000}, {0xba68c000}, {0xba68e000}, + {0xba690000}, {0xba692000}, {0xba694000}, {0xba696000}, + {0xba698000}, {0xba69a000}, {0xba69c000}, {0xba69e000}, + {0xba6a0000}, {0xba6a2000}, {0xba6a4000}, {0xba6a6000}, + {0xba6a8000}, {0xba6aa000}, {0xba6ac000}, {0xba6ae000}, + {0xba6b0000}, {0xba6b2000}, {0xba6b4000}, {0xba6b6000}, + {0xba6b8000}, {0xba6ba000}, {0xba6bc000}, {0xba6be000}, + {0xba6c0000}, {0xba6c2000}, {0xba6c4000}, {0xba6c6000}, + {0xba6c8000}, {0xba6ca000}, {0xba6cc000}, {0xba6ce000}, + {0xba6d0000}, {0xba6d2000}, {0xba6d4000}, {0xba6d6000}, + {0xba6d8000}, {0xba6da000}, {0xba6dc000}, {0xba6de000}, + {0xba6e0000}, {0xba6e2000}, {0xba6e4000}, {0xba6e6000}, + {0xba6e8000}, {0xba6ea000}, {0xba6ec000}, {0xba6ee000}, + {0xba6f0000}, {0xba6f2000}, {0xba6f4000}, {0xba6f6000}, + {0xba6f8000}, {0xba6fa000}, {0xba6fc000}, {0xba6fe000}, + {0xba700000}, {0xba702000}, {0xba704000}, {0xba706000}, + {0xba708000}, {0xba70a000}, {0xba70c000}, {0xba70e000}, + {0xba710000}, {0xba712000}, {0xba714000}, {0xba716000}, + {0xba718000}, {0xba71a000}, {0xba71c000}, {0xba71e000}, + {0xba720000}, {0xba722000}, {0xba724000}, {0xba726000}, + {0xba728000}, {0xba72a000}, {0xba72c000}, {0xba72e000}, + {0xba730000}, {0xba732000}, {0xba734000}, {0xba736000}, + {0xba738000}, {0xba73a000}, {0xba73c000}, {0xba73e000}, + {0xba740000}, {0xba742000}, {0xba744000}, {0xba746000}, + {0xba748000}, {0xba74a000}, {0xba74c000}, {0xba74e000}, + {0xba750000}, {0xba752000}, {0xba754000}, {0xba756000}, + {0xba758000}, {0xba75a000}, {0xba75c000}, {0xba75e000}, + {0xba760000}, {0xba762000}, {0xba764000}, {0xba766000}, + {0xba768000}, {0xba76a000}, {0xba76c000}, {0xba76e000}, + {0xba770000}, {0xba772000}, {0xba774000}, {0xba776000}, + {0xba778000}, {0xba77a000}, {0xba77c000}, {0xba77e000}, + {0xba780000}, {0xba782000}, {0xba784000}, {0xba786000}, + {0xba788000}, {0xba78a000}, {0xba78c000}, {0xba78e000}, + {0xba790000}, {0xba792000}, {0xba794000}, {0xba796000}, + {0xba798000}, {0xba79a000}, {0xba79c000}, {0xba79e000}, + {0xba7a0000}, {0xba7a2000}, {0xba7a4000}, {0xba7a6000}, + {0xba7a8000}, {0xba7aa000}, {0xba7ac000}, {0xba7ae000}, + {0xba7b0000}, {0xba7b2000}, {0xba7b4000}, {0xba7b6000}, + {0xba7b8000}, {0xba7ba000}, {0xba7bc000}, {0xba7be000}, + {0xba7c0000}, {0xba7c2000}, {0xba7c4000}, {0xba7c6000}, + {0xba7c8000}, {0xba7ca000}, {0xba7cc000}, {0xba7ce000}, + {0xba7d0000}, {0xba7d2000}, {0xba7d4000}, {0xba7d6000}, + {0xba7d8000}, {0xba7da000}, {0xba7dc000}, {0xba7de000}, + {0xba7e0000}, {0xba7e2000}, {0xba7e4000}, {0xba7e6000}, + {0xba7e8000}, {0xba7ea000}, {0xba7ec000}, {0xba7ee000}, + {0xba7f0000}, {0xba7f2000}, {0xba7f4000}, {0xba7f6000}, + {0xba7f8000}, {0xba7fa000}, {0xba7fc000}, {0xba7fe000}, + {0xba800000}, {0xba802000}, {0xba804000}, {0xba806000}, + {0xba808000}, {0xba80a000}, {0xba80c000}, {0xba80e000}, + {0xba810000}, {0xba812000}, {0xba814000}, {0xba816000}, + {0xba818000}, {0xba81a000}, {0xba81c000}, {0xba81e000}, + {0xba820000}, {0xba822000}, {0xba824000}, {0xba826000}, + {0xba828000}, {0xba82a000}, {0xba82c000}, {0xba82e000}, + {0xba830000}, {0xba832000}, {0xba834000}, {0xba836000}, + {0xba838000}, {0xba83a000}, {0xba83c000}, {0xba83e000}, + {0xba840000}, {0xba842000}, {0xba844000}, {0xba846000}, + {0xba848000}, {0xba84a000}, {0xba84c000}, {0xba84e000}, + {0xba850000}, {0xba852000}, {0xba854000}, {0xba856000}, + {0xba858000}, {0xba85a000}, {0xba85c000}, {0xba85e000}, + {0xba860000}, {0xba862000}, {0xba864000}, {0xba866000}, + {0xba868000}, {0xba86a000}, {0xba86c000}, {0xba86e000}, + {0xba870000}, {0xba872000}, {0xba874000}, {0xba876000}, + {0xba878000}, {0xba87a000}, {0xba87c000}, {0xba87e000}, + {0xba880000}, {0xba882000}, {0xba884000}, {0xba886000}, + {0xba888000}, {0xba88a000}, {0xba88c000}, {0xba88e000}, + {0xba890000}, {0xba892000}, {0xba894000}, {0xba896000}, + {0xba898000}, {0xba89a000}, {0xba89c000}, {0xba89e000}, + {0xba8a0000}, {0xba8a2000}, {0xba8a4000}, {0xba8a6000}, + {0xba8a8000}, {0xba8aa000}, {0xba8ac000}, {0xba8ae000}, + {0xba8b0000}, {0xba8b2000}, {0xba8b4000}, {0xba8b6000}, + {0xba8b8000}, {0xba8ba000}, {0xba8bc000}, {0xba8be000}, + {0xba8c0000}, {0xba8c2000}, {0xba8c4000}, {0xba8c6000}, + {0xba8c8000}, {0xba8ca000}, {0xba8cc000}, {0xba8ce000}, + {0xba8d0000}, {0xba8d2000}, {0xba8d4000}, {0xba8d6000}, + {0xba8d8000}, {0xba8da000}, {0xba8dc000}, {0xba8de000}, + {0xba8e0000}, {0xba8e2000}, {0xba8e4000}, {0xba8e6000}, + {0xba8e8000}, {0xba8ea000}, {0xba8ec000}, {0xba8ee000}, + {0xba8f0000}, {0xba8f2000}, {0xba8f4000}, {0xba8f6000}, + {0xba8f8000}, {0xba8fa000}, {0xba8fc000}, {0xba8fe000}, + {0xba900000}, {0xba902000}, {0xba904000}, {0xba906000}, + {0xba908000}, {0xba90a000}, {0xba90c000}, {0xba90e000}, + {0xba910000}, {0xba912000}, {0xba914000}, {0xba916000}, + {0xba918000}, {0xba91a000}, {0xba91c000}, {0xba91e000}, + {0xba920000}, {0xba922000}, {0xba924000}, {0xba926000}, + {0xba928000}, {0xba92a000}, {0xba92c000}, {0xba92e000}, + {0xba930000}, {0xba932000}, {0xba934000}, {0xba936000}, + {0xba938000}, {0xba93a000}, {0xba93c000}, {0xba93e000}, + {0xba940000}, {0xba942000}, {0xba944000}, {0xba946000}, + {0xba948000}, {0xba94a000}, {0xba94c000}, {0xba94e000}, + {0xba950000}, {0xba952000}, {0xba954000}, {0xba956000}, + {0xba958000}, {0xba95a000}, {0xba95c000}, {0xba95e000}, + {0xba960000}, {0xba962000}, {0xba964000}, {0xba966000}, + {0xba968000}, {0xba96a000}, {0xba96c000}, {0xba96e000}, + {0xba970000}, {0xba972000}, {0xba974000}, {0xba976000}, + {0xba978000}, {0xba97a000}, {0xba97c000}, {0xba97e000}, + {0xba980000}, {0xba982000}, {0xba984000}, {0xba986000}, + {0xba988000}, {0xba98a000}, {0xba98c000}, {0xba98e000}, + {0xba990000}, {0xba992000}, {0xba994000}, {0xba996000}, + {0xba998000}, {0xba99a000}, {0xba99c000}, {0xba99e000}, + {0xba9a0000}, {0xba9a2000}, {0xba9a4000}, {0xba9a6000}, + {0xba9a8000}, {0xba9aa000}, {0xba9ac000}, {0xba9ae000}, + {0xba9b0000}, {0xba9b2000}, {0xba9b4000}, {0xba9b6000}, + {0xba9b8000}, {0xba9ba000}, {0xba9bc000}, {0xba9be000}, + {0xba9c0000}, {0xba9c2000}, {0xba9c4000}, {0xba9c6000}, + {0xba9c8000}, {0xba9ca000}, {0xba9cc000}, {0xba9ce000}, + {0xba9d0000}, {0xba9d2000}, {0xba9d4000}, {0xba9d6000}, + {0xba9d8000}, {0xba9da000}, {0xba9dc000}, {0xba9de000}, + {0xba9e0000}, {0xba9e2000}, {0xba9e4000}, {0xba9e6000}, + {0xba9e8000}, {0xba9ea000}, {0xba9ec000}, {0xba9ee000}, + {0xba9f0000}, {0xba9f2000}, {0xba9f4000}, {0xba9f6000}, + {0xba9f8000}, {0xba9fa000}, {0xba9fc000}, {0xba9fe000}, + {0xbaa00000}, {0xbaa02000}, {0xbaa04000}, {0xbaa06000}, + {0xbaa08000}, {0xbaa0a000}, {0xbaa0c000}, {0xbaa0e000}, + {0xbaa10000}, {0xbaa12000}, {0xbaa14000}, {0xbaa16000}, + {0xbaa18000}, {0xbaa1a000}, {0xbaa1c000}, {0xbaa1e000}, + {0xbaa20000}, {0xbaa22000}, {0xbaa24000}, {0xbaa26000}, + {0xbaa28000}, {0xbaa2a000}, {0xbaa2c000}, {0xbaa2e000}, + {0xbaa30000}, {0xbaa32000}, {0xbaa34000}, {0xbaa36000}, + {0xbaa38000}, {0xbaa3a000}, {0xbaa3c000}, {0xbaa3e000}, + {0xbaa40000}, {0xbaa42000}, {0xbaa44000}, {0xbaa46000}, + {0xbaa48000}, {0xbaa4a000}, {0xbaa4c000}, {0xbaa4e000}, + {0xbaa50000}, {0xbaa52000}, {0xbaa54000}, {0xbaa56000}, + {0xbaa58000}, {0xbaa5a000}, {0xbaa5c000}, {0xbaa5e000}, + {0xbaa60000}, {0xbaa62000}, {0xbaa64000}, {0xbaa66000}, + {0xbaa68000}, {0xbaa6a000}, {0xbaa6c000}, {0xbaa6e000}, + {0xbaa70000}, {0xbaa72000}, {0xbaa74000}, {0xbaa76000}, + {0xbaa78000}, {0xbaa7a000}, {0xbaa7c000}, {0xbaa7e000}, + {0xbaa80000}, {0xbaa82000}, {0xbaa84000}, {0xbaa86000}, + {0xbaa88000}, {0xbaa8a000}, {0xbaa8c000}, {0xbaa8e000}, + {0xbaa90000}, {0xbaa92000}, {0xbaa94000}, {0xbaa96000}, + {0xbaa98000}, {0xbaa9a000}, {0xbaa9c000}, {0xbaa9e000}, + {0xbaaa0000}, {0xbaaa2000}, {0xbaaa4000}, {0xbaaa6000}, + {0xbaaa8000}, {0xbaaaa000}, {0xbaaac000}, {0xbaaae000}, + {0xbaab0000}, {0xbaab2000}, {0xbaab4000}, {0xbaab6000}, + {0xbaab8000}, {0xbaaba000}, {0xbaabc000}, {0xbaabe000}, + {0xbaac0000}, {0xbaac2000}, {0xbaac4000}, {0xbaac6000}, + {0xbaac8000}, {0xbaaca000}, {0xbaacc000}, {0xbaace000}, + {0xbaad0000}, {0xbaad2000}, {0xbaad4000}, {0xbaad6000}, + {0xbaad8000}, {0xbaada000}, {0xbaadc000}, {0xbaade000}, + {0xbaae0000}, {0xbaae2000}, {0xbaae4000}, {0xbaae6000}, + {0xbaae8000}, {0xbaaea000}, {0xbaaec000}, {0xbaaee000}, + {0xbaaf0000}, {0xbaaf2000}, {0xbaaf4000}, {0xbaaf6000}, + {0xbaaf8000}, {0xbaafa000}, {0xbaafc000}, {0xbaafe000}, + {0xbab00000}, {0xbab02000}, {0xbab04000}, {0xbab06000}, + {0xbab08000}, {0xbab0a000}, {0xbab0c000}, {0xbab0e000}, + {0xbab10000}, {0xbab12000}, {0xbab14000}, {0xbab16000}, + {0xbab18000}, {0xbab1a000}, {0xbab1c000}, {0xbab1e000}, + {0xbab20000}, {0xbab22000}, {0xbab24000}, {0xbab26000}, + {0xbab28000}, {0xbab2a000}, {0xbab2c000}, {0xbab2e000}, + {0xbab30000}, {0xbab32000}, {0xbab34000}, {0xbab36000}, + {0xbab38000}, {0xbab3a000}, {0xbab3c000}, {0xbab3e000}, + {0xbab40000}, {0xbab42000}, {0xbab44000}, {0xbab46000}, + {0xbab48000}, {0xbab4a000}, {0xbab4c000}, {0xbab4e000}, + {0xbab50000}, {0xbab52000}, {0xbab54000}, {0xbab56000}, + {0xbab58000}, {0xbab5a000}, {0xbab5c000}, {0xbab5e000}, + {0xbab60000}, {0xbab62000}, {0xbab64000}, {0xbab66000}, + {0xbab68000}, {0xbab6a000}, {0xbab6c000}, {0xbab6e000}, + {0xbab70000}, {0xbab72000}, {0xbab74000}, {0xbab76000}, + {0xbab78000}, {0xbab7a000}, {0xbab7c000}, {0xbab7e000}, + {0xbab80000}, {0xbab82000}, {0xbab84000}, {0xbab86000}, + {0xbab88000}, {0xbab8a000}, {0xbab8c000}, {0xbab8e000}, + {0xbab90000}, {0xbab92000}, {0xbab94000}, {0xbab96000}, + {0xbab98000}, {0xbab9a000}, {0xbab9c000}, {0xbab9e000}, + {0xbaba0000}, {0xbaba2000}, {0xbaba4000}, {0xbaba6000}, + {0xbaba8000}, {0xbabaa000}, {0xbabac000}, {0xbabae000}, + {0xbabb0000}, {0xbabb2000}, {0xbabb4000}, {0xbabb6000}, + {0xbabb8000}, {0xbabba000}, {0xbabbc000}, {0xbabbe000}, + {0xbabc0000}, {0xbabc2000}, {0xbabc4000}, {0xbabc6000}, + {0xbabc8000}, {0xbabca000}, {0xbabcc000}, {0xbabce000}, + {0xbabd0000}, {0xbabd2000}, {0xbabd4000}, {0xbabd6000}, + {0xbabd8000}, {0xbabda000}, {0xbabdc000}, {0xbabde000}, + {0xbabe0000}, {0xbabe2000}, {0xbabe4000}, {0xbabe6000}, + {0xbabe8000}, {0xbabea000}, {0xbabec000}, {0xbabee000}, + {0xbabf0000}, {0xbabf2000}, {0xbabf4000}, {0xbabf6000}, + {0xbabf8000}, {0xbabfa000}, {0xbabfc000}, {0xbabfe000}, + {0xbac00000}, {0xbac02000}, {0xbac04000}, {0xbac06000}, + {0xbac08000}, {0xbac0a000}, {0xbac0c000}, {0xbac0e000}, + {0xbac10000}, {0xbac12000}, {0xbac14000}, {0xbac16000}, + {0xbac18000}, {0xbac1a000}, {0xbac1c000}, {0xbac1e000}, + {0xbac20000}, {0xbac22000}, {0xbac24000}, {0xbac26000}, + {0xbac28000}, {0xbac2a000}, {0xbac2c000}, {0xbac2e000}, + {0xbac30000}, {0xbac32000}, {0xbac34000}, {0xbac36000}, + {0xbac38000}, {0xbac3a000}, {0xbac3c000}, {0xbac3e000}, + {0xbac40000}, {0xbac42000}, {0xbac44000}, {0xbac46000}, + {0xbac48000}, {0xbac4a000}, {0xbac4c000}, {0xbac4e000}, + {0xbac50000}, {0xbac52000}, {0xbac54000}, {0xbac56000}, + {0xbac58000}, {0xbac5a000}, {0xbac5c000}, {0xbac5e000}, + {0xbac60000}, {0xbac62000}, {0xbac64000}, {0xbac66000}, + {0xbac68000}, {0xbac6a000}, {0xbac6c000}, {0xbac6e000}, + {0xbac70000}, {0xbac72000}, {0xbac74000}, {0xbac76000}, + {0xbac78000}, {0xbac7a000}, {0xbac7c000}, {0xbac7e000}, + {0xbac80000}, {0xbac82000}, {0xbac84000}, {0xbac86000}, + {0xbac88000}, {0xbac8a000}, {0xbac8c000}, {0xbac8e000}, + {0xbac90000}, {0xbac92000}, {0xbac94000}, {0xbac96000}, + {0xbac98000}, {0xbac9a000}, {0xbac9c000}, {0xbac9e000}, + {0xbaca0000}, {0xbaca2000}, {0xbaca4000}, {0xbaca6000}, + {0xbaca8000}, {0xbacaa000}, {0xbacac000}, {0xbacae000}, + {0xbacb0000}, {0xbacb2000}, {0xbacb4000}, {0xbacb6000}, + {0xbacb8000}, {0xbacba000}, {0xbacbc000}, {0xbacbe000}, + {0xbacc0000}, {0xbacc2000}, {0xbacc4000}, {0xbacc6000}, + {0xbacc8000}, {0xbacca000}, {0xbaccc000}, {0xbacce000}, + {0xbacd0000}, {0xbacd2000}, {0xbacd4000}, {0xbacd6000}, + {0xbacd8000}, {0xbacda000}, {0xbacdc000}, {0xbacde000}, + {0xbace0000}, {0xbace2000}, {0xbace4000}, {0xbace6000}, + {0xbace8000}, {0xbacea000}, {0xbacec000}, {0xbacee000}, + {0xbacf0000}, {0xbacf2000}, {0xbacf4000}, {0xbacf6000}, + {0xbacf8000}, {0xbacfa000}, {0xbacfc000}, {0xbacfe000}, + {0xbad00000}, {0xbad02000}, {0xbad04000}, {0xbad06000}, + {0xbad08000}, {0xbad0a000}, {0xbad0c000}, {0xbad0e000}, + {0xbad10000}, {0xbad12000}, {0xbad14000}, {0xbad16000}, + {0xbad18000}, {0xbad1a000}, {0xbad1c000}, {0xbad1e000}, + {0xbad20000}, {0xbad22000}, {0xbad24000}, {0xbad26000}, + {0xbad28000}, {0xbad2a000}, {0xbad2c000}, {0xbad2e000}, + {0xbad30000}, {0xbad32000}, {0xbad34000}, {0xbad36000}, + {0xbad38000}, {0xbad3a000}, {0xbad3c000}, {0xbad3e000}, + {0xbad40000}, {0xbad42000}, {0xbad44000}, {0xbad46000}, + {0xbad48000}, {0xbad4a000}, {0xbad4c000}, {0xbad4e000}, + {0xbad50000}, {0xbad52000}, {0xbad54000}, {0xbad56000}, + {0xbad58000}, {0xbad5a000}, {0xbad5c000}, {0xbad5e000}, + {0xbad60000}, {0xbad62000}, {0xbad64000}, {0xbad66000}, + {0xbad68000}, {0xbad6a000}, {0xbad6c000}, {0xbad6e000}, + {0xbad70000}, {0xbad72000}, {0xbad74000}, {0xbad76000}, + {0xbad78000}, {0xbad7a000}, {0xbad7c000}, {0xbad7e000}, + {0xbad80000}, {0xbad82000}, {0xbad84000}, {0xbad86000}, + {0xbad88000}, {0xbad8a000}, {0xbad8c000}, {0xbad8e000}, + {0xbad90000}, {0xbad92000}, {0xbad94000}, {0xbad96000}, + {0xbad98000}, {0xbad9a000}, {0xbad9c000}, {0xbad9e000}, + {0xbada0000}, {0xbada2000}, {0xbada4000}, {0xbada6000}, + {0xbada8000}, {0xbadaa000}, {0xbadac000}, {0xbadae000}, + {0xbadb0000}, {0xbadb2000}, {0xbadb4000}, {0xbadb6000}, + {0xbadb8000}, {0xbadba000}, {0xbadbc000}, {0xbadbe000}, + {0xbadc0000}, {0xbadc2000}, {0xbadc4000}, {0xbadc6000}, + {0xbadc8000}, {0xbadca000}, {0xbadcc000}, {0xbadce000}, + {0xbadd0000}, {0xbadd2000}, {0xbadd4000}, {0xbadd6000}, + {0xbadd8000}, {0xbadda000}, {0xbaddc000}, {0xbadde000}, + {0xbade0000}, {0xbade2000}, {0xbade4000}, {0xbade6000}, + {0xbade8000}, {0xbadea000}, {0xbadec000}, {0xbadee000}, + {0xbadf0000}, {0xbadf2000}, {0xbadf4000}, {0xbadf6000}, + {0xbadf8000}, {0xbadfa000}, {0xbadfc000}, {0xbadfe000}, + {0xbae00000}, {0xbae02000}, {0xbae04000}, {0xbae06000}, + {0xbae08000}, {0xbae0a000}, {0xbae0c000}, {0xbae0e000}, + {0xbae10000}, {0xbae12000}, {0xbae14000}, {0xbae16000}, + {0xbae18000}, {0xbae1a000}, {0xbae1c000}, {0xbae1e000}, + {0xbae20000}, {0xbae22000}, {0xbae24000}, {0xbae26000}, + {0xbae28000}, {0xbae2a000}, {0xbae2c000}, {0xbae2e000}, + {0xbae30000}, {0xbae32000}, {0xbae34000}, {0xbae36000}, + {0xbae38000}, {0xbae3a000}, {0xbae3c000}, {0xbae3e000}, + {0xbae40000}, {0xbae42000}, {0xbae44000}, {0xbae46000}, + {0xbae48000}, {0xbae4a000}, {0xbae4c000}, {0xbae4e000}, + {0xbae50000}, {0xbae52000}, {0xbae54000}, {0xbae56000}, + {0xbae58000}, {0xbae5a000}, {0xbae5c000}, {0xbae5e000}, + {0xbae60000}, {0xbae62000}, {0xbae64000}, {0xbae66000}, + {0xbae68000}, {0xbae6a000}, {0xbae6c000}, {0xbae6e000}, + {0xbae70000}, {0xbae72000}, {0xbae74000}, {0xbae76000}, + {0xbae78000}, {0xbae7a000}, {0xbae7c000}, {0xbae7e000}, + {0xbae80000}, {0xbae82000}, {0xbae84000}, {0xbae86000}, + {0xbae88000}, {0xbae8a000}, {0xbae8c000}, {0xbae8e000}, + {0xbae90000}, {0xbae92000}, {0xbae94000}, {0xbae96000}, + {0xbae98000}, {0xbae9a000}, {0xbae9c000}, {0xbae9e000}, + {0xbaea0000}, {0xbaea2000}, {0xbaea4000}, {0xbaea6000}, + {0xbaea8000}, {0xbaeaa000}, {0xbaeac000}, {0xbaeae000}, + {0xbaeb0000}, {0xbaeb2000}, {0xbaeb4000}, {0xbaeb6000}, + {0xbaeb8000}, {0xbaeba000}, {0xbaebc000}, {0xbaebe000}, + {0xbaec0000}, {0xbaec2000}, {0xbaec4000}, {0xbaec6000}, + {0xbaec8000}, {0xbaeca000}, {0xbaecc000}, {0xbaece000}, + {0xbaed0000}, {0xbaed2000}, {0xbaed4000}, {0xbaed6000}, + {0xbaed8000}, {0xbaeda000}, {0xbaedc000}, {0xbaede000}, + {0xbaee0000}, {0xbaee2000}, {0xbaee4000}, {0xbaee6000}, + {0xbaee8000}, {0xbaeea000}, {0xbaeec000}, {0xbaeee000}, + {0xbaef0000}, {0xbaef2000}, {0xbaef4000}, {0xbaef6000}, + {0xbaef8000}, {0xbaefa000}, {0xbaefc000}, {0xbaefe000}, + {0xbaf00000}, {0xbaf02000}, {0xbaf04000}, {0xbaf06000}, + {0xbaf08000}, {0xbaf0a000}, {0xbaf0c000}, {0xbaf0e000}, + {0xbaf10000}, {0xbaf12000}, {0xbaf14000}, {0xbaf16000}, + {0xbaf18000}, {0xbaf1a000}, {0xbaf1c000}, {0xbaf1e000}, + {0xbaf20000}, {0xbaf22000}, {0xbaf24000}, {0xbaf26000}, + {0xbaf28000}, {0xbaf2a000}, {0xbaf2c000}, {0xbaf2e000}, + {0xbaf30000}, {0xbaf32000}, {0xbaf34000}, {0xbaf36000}, + {0xbaf38000}, {0xbaf3a000}, {0xbaf3c000}, {0xbaf3e000}, + {0xbaf40000}, {0xbaf42000}, {0xbaf44000}, {0xbaf46000}, + {0xbaf48000}, {0xbaf4a000}, {0xbaf4c000}, {0xbaf4e000}, + {0xbaf50000}, {0xbaf52000}, {0xbaf54000}, {0xbaf56000}, + {0xbaf58000}, {0xbaf5a000}, {0xbaf5c000}, {0xbaf5e000}, + {0xbaf60000}, {0xbaf62000}, {0xbaf64000}, {0xbaf66000}, + {0xbaf68000}, {0xbaf6a000}, {0xbaf6c000}, {0xbaf6e000}, + {0xbaf70000}, {0xbaf72000}, {0xbaf74000}, {0xbaf76000}, + {0xbaf78000}, {0xbaf7a000}, {0xbaf7c000}, {0xbaf7e000}, + {0xbaf80000}, {0xbaf82000}, {0xbaf84000}, {0xbaf86000}, + {0xbaf88000}, {0xbaf8a000}, {0xbaf8c000}, {0xbaf8e000}, + {0xbaf90000}, {0xbaf92000}, {0xbaf94000}, {0xbaf96000}, + {0xbaf98000}, {0xbaf9a000}, {0xbaf9c000}, {0xbaf9e000}, + {0xbafa0000}, {0xbafa2000}, {0xbafa4000}, {0xbafa6000}, + {0xbafa8000}, {0xbafaa000}, {0xbafac000}, {0xbafae000}, + {0xbafb0000}, {0xbafb2000}, {0xbafb4000}, {0xbafb6000}, + {0xbafb8000}, {0xbafba000}, {0xbafbc000}, {0xbafbe000}, + {0xbafc0000}, {0xbafc2000}, {0xbafc4000}, {0xbafc6000}, + {0xbafc8000}, {0xbafca000}, {0xbafcc000}, {0xbafce000}, + {0xbafd0000}, {0xbafd2000}, {0xbafd4000}, {0xbafd6000}, + {0xbafd8000}, {0xbafda000}, {0xbafdc000}, {0xbafde000}, + {0xbafe0000}, {0xbafe2000}, {0xbafe4000}, {0xbafe6000}, + {0xbafe8000}, {0xbafea000}, {0xbafec000}, {0xbafee000}, + {0xbaff0000}, {0xbaff2000}, {0xbaff4000}, {0xbaff6000}, + {0xbaff8000}, {0xbaffa000}, {0xbaffc000}, {0xbaffe000}, + {0xbb000000}, {0xbb002000}, {0xbb004000}, {0xbb006000}, + {0xbb008000}, {0xbb00a000}, {0xbb00c000}, {0xbb00e000}, + {0xbb010000}, {0xbb012000}, {0xbb014000}, {0xbb016000}, + {0xbb018000}, {0xbb01a000}, {0xbb01c000}, {0xbb01e000}, + {0xbb020000}, {0xbb022000}, {0xbb024000}, {0xbb026000}, + {0xbb028000}, {0xbb02a000}, {0xbb02c000}, {0xbb02e000}, + {0xbb030000}, {0xbb032000}, {0xbb034000}, {0xbb036000}, + {0xbb038000}, {0xbb03a000}, {0xbb03c000}, {0xbb03e000}, + {0xbb040000}, {0xbb042000}, {0xbb044000}, {0xbb046000}, + {0xbb048000}, {0xbb04a000}, {0xbb04c000}, {0xbb04e000}, + {0xbb050000}, {0xbb052000}, {0xbb054000}, {0xbb056000}, + {0xbb058000}, {0xbb05a000}, {0xbb05c000}, {0xbb05e000}, + {0xbb060000}, {0xbb062000}, {0xbb064000}, {0xbb066000}, + {0xbb068000}, {0xbb06a000}, {0xbb06c000}, {0xbb06e000}, + {0xbb070000}, {0xbb072000}, {0xbb074000}, {0xbb076000}, + {0xbb078000}, {0xbb07a000}, {0xbb07c000}, {0xbb07e000}, + {0xbb080000}, {0xbb082000}, {0xbb084000}, {0xbb086000}, + {0xbb088000}, {0xbb08a000}, {0xbb08c000}, {0xbb08e000}, + {0xbb090000}, {0xbb092000}, {0xbb094000}, {0xbb096000}, + {0xbb098000}, {0xbb09a000}, {0xbb09c000}, {0xbb09e000}, + {0xbb0a0000}, {0xbb0a2000}, {0xbb0a4000}, {0xbb0a6000}, + {0xbb0a8000}, {0xbb0aa000}, {0xbb0ac000}, {0xbb0ae000}, + {0xbb0b0000}, {0xbb0b2000}, {0xbb0b4000}, {0xbb0b6000}, + {0xbb0b8000}, {0xbb0ba000}, {0xbb0bc000}, {0xbb0be000}, + {0xbb0c0000}, {0xbb0c2000}, {0xbb0c4000}, {0xbb0c6000}, + {0xbb0c8000}, {0xbb0ca000}, {0xbb0cc000}, {0xbb0ce000}, + {0xbb0d0000}, {0xbb0d2000}, {0xbb0d4000}, {0xbb0d6000}, + {0xbb0d8000}, {0xbb0da000}, {0xbb0dc000}, {0xbb0de000}, + {0xbb0e0000}, {0xbb0e2000}, {0xbb0e4000}, {0xbb0e6000}, + {0xbb0e8000}, {0xbb0ea000}, {0xbb0ec000}, {0xbb0ee000}, + {0xbb0f0000}, {0xbb0f2000}, {0xbb0f4000}, {0xbb0f6000}, + {0xbb0f8000}, {0xbb0fa000}, {0xbb0fc000}, {0xbb0fe000}, + {0xbb100000}, {0xbb102000}, {0xbb104000}, {0xbb106000}, + {0xbb108000}, {0xbb10a000}, {0xbb10c000}, {0xbb10e000}, + {0xbb110000}, {0xbb112000}, {0xbb114000}, {0xbb116000}, + {0xbb118000}, {0xbb11a000}, {0xbb11c000}, {0xbb11e000}, + {0xbb120000}, {0xbb122000}, {0xbb124000}, {0xbb126000}, + {0xbb128000}, {0xbb12a000}, {0xbb12c000}, {0xbb12e000}, + {0xbb130000}, {0xbb132000}, {0xbb134000}, {0xbb136000}, + {0xbb138000}, {0xbb13a000}, {0xbb13c000}, {0xbb13e000}, + {0xbb140000}, {0xbb142000}, {0xbb144000}, {0xbb146000}, + {0xbb148000}, {0xbb14a000}, {0xbb14c000}, {0xbb14e000}, + {0xbb150000}, {0xbb152000}, {0xbb154000}, {0xbb156000}, + {0xbb158000}, {0xbb15a000}, {0xbb15c000}, {0xbb15e000}, + {0xbb160000}, {0xbb162000}, {0xbb164000}, {0xbb166000}, + {0xbb168000}, {0xbb16a000}, {0xbb16c000}, {0xbb16e000}, + {0xbb170000}, {0xbb172000}, {0xbb174000}, {0xbb176000}, + {0xbb178000}, {0xbb17a000}, {0xbb17c000}, {0xbb17e000}, + {0xbb180000}, {0xbb182000}, {0xbb184000}, {0xbb186000}, + {0xbb188000}, {0xbb18a000}, {0xbb18c000}, {0xbb18e000}, + {0xbb190000}, {0xbb192000}, {0xbb194000}, {0xbb196000}, + {0xbb198000}, {0xbb19a000}, {0xbb19c000}, {0xbb19e000}, + {0xbb1a0000}, {0xbb1a2000}, {0xbb1a4000}, {0xbb1a6000}, + {0xbb1a8000}, {0xbb1aa000}, {0xbb1ac000}, {0xbb1ae000}, + {0xbb1b0000}, {0xbb1b2000}, {0xbb1b4000}, {0xbb1b6000}, + {0xbb1b8000}, {0xbb1ba000}, {0xbb1bc000}, {0xbb1be000}, + {0xbb1c0000}, {0xbb1c2000}, {0xbb1c4000}, {0xbb1c6000}, + {0xbb1c8000}, {0xbb1ca000}, {0xbb1cc000}, {0xbb1ce000}, + {0xbb1d0000}, {0xbb1d2000}, {0xbb1d4000}, {0xbb1d6000}, + {0xbb1d8000}, {0xbb1da000}, {0xbb1dc000}, {0xbb1de000}, + {0xbb1e0000}, {0xbb1e2000}, {0xbb1e4000}, {0xbb1e6000}, + {0xbb1e8000}, {0xbb1ea000}, {0xbb1ec000}, {0xbb1ee000}, + {0xbb1f0000}, {0xbb1f2000}, {0xbb1f4000}, {0xbb1f6000}, + {0xbb1f8000}, {0xbb1fa000}, {0xbb1fc000}, {0xbb1fe000}, + {0xbb200000}, {0xbb202000}, {0xbb204000}, {0xbb206000}, + {0xbb208000}, {0xbb20a000}, {0xbb20c000}, {0xbb20e000}, + {0xbb210000}, {0xbb212000}, {0xbb214000}, {0xbb216000}, + {0xbb218000}, {0xbb21a000}, {0xbb21c000}, {0xbb21e000}, + {0xbb220000}, {0xbb222000}, {0xbb224000}, {0xbb226000}, + {0xbb228000}, {0xbb22a000}, {0xbb22c000}, {0xbb22e000}, + {0xbb230000}, {0xbb232000}, {0xbb234000}, {0xbb236000}, + {0xbb238000}, {0xbb23a000}, {0xbb23c000}, {0xbb23e000}, + {0xbb240000}, {0xbb242000}, {0xbb244000}, {0xbb246000}, + {0xbb248000}, {0xbb24a000}, {0xbb24c000}, {0xbb24e000}, + {0xbb250000}, {0xbb252000}, {0xbb254000}, {0xbb256000}, + {0xbb258000}, {0xbb25a000}, {0xbb25c000}, {0xbb25e000}, + {0xbb260000}, {0xbb262000}, {0xbb264000}, {0xbb266000}, + {0xbb268000}, {0xbb26a000}, {0xbb26c000}, {0xbb26e000}, + {0xbb270000}, {0xbb272000}, {0xbb274000}, {0xbb276000}, + {0xbb278000}, {0xbb27a000}, {0xbb27c000}, {0xbb27e000}, + {0xbb280000}, {0xbb282000}, {0xbb284000}, {0xbb286000}, + {0xbb288000}, {0xbb28a000}, {0xbb28c000}, {0xbb28e000}, + {0xbb290000}, {0xbb292000}, {0xbb294000}, {0xbb296000}, + {0xbb298000}, {0xbb29a000}, {0xbb29c000}, {0xbb29e000}, + {0xbb2a0000}, {0xbb2a2000}, {0xbb2a4000}, {0xbb2a6000}, + {0xbb2a8000}, {0xbb2aa000}, {0xbb2ac000}, {0xbb2ae000}, + {0xbb2b0000}, {0xbb2b2000}, {0xbb2b4000}, {0xbb2b6000}, + {0xbb2b8000}, {0xbb2ba000}, {0xbb2bc000}, {0xbb2be000}, + {0xbb2c0000}, {0xbb2c2000}, {0xbb2c4000}, {0xbb2c6000}, + {0xbb2c8000}, {0xbb2ca000}, {0xbb2cc000}, {0xbb2ce000}, + {0xbb2d0000}, {0xbb2d2000}, {0xbb2d4000}, {0xbb2d6000}, + {0xbb2d8000}, {0xbb2da000}, {0xbb2dc000}, {0xbb2de000}, + {0xbb2e0000}, {0xbb2e2000}, {0xbb2e4000}, {0xbb2e6000}, + {0xbb2e8000}, {0xbb2ea000}, {0xbb2ec000}, {0xbb2ee000}, + {0xbb2f0000}, {0xbb2f2000}, {0xbb2f4000}, {0xbb2f6000}, + {0xbb2f8000}, {0xbb2fa000}, {0xbb2fc000}, {0xbb2fe000}, + {0xbb300000}, {0xbb302000}, {0xbb304000}, {0xbb306000}, + {0xbb308000}, {0xbb30a000}, {0xbb30c000}, {0xbb30e000}, + {0xbb310000}, {0xbb312000}, {0xbb314000}, {0xbb316000}, + {0xbb318000}, {0xbb31a000}, {0xbb31c000}, {0xbb31e000}, + {0xbb320000}, {0xbb322000}, {0xbb324000}, {0xbb326000}, + {0xbb328000}, {0xbb32a000}, {0xbb32c000}, {0xbb32e000}, + {0xbb330000}, {0xbb332000}, {0xbb334000}, {0xbb336000}, + {0xbb338000}, {0xbb33a000}, {0xbb33c000}, {0xbb33e000}, + {0xbb340000}, {0xbb342000}, {0xbb344000}, {0xbb346000}, + {0xbb348000}, {0xbb34a000}, {0xbb34c000}, {0xbb34e000}, + {0xbb350000}, {0xbb352000}, {0xbb354000}, {0xbb356000}, + {0xbb358000}, {0xbb35a000}, {0xbb35c000}, {0xbb35e000}, + {0xbb360000}, {0xbb362000}, {0xbb364000}, {0xbb366000}, + {0xbb368000}, {0xbb36a000}, {0xbb36c000}, {0xbb36e000}, + {0xbb370000}, {0xbb372000}, {0xbb374000}, {0xbb376000}, + {0xbb378000}, {0xbb37a000}, {0xbb37c000}, {0xbb37e000}, + {0xbb380000}, {0xbb382000}, {0xbb384000}, {0xbb386000}, + {0xbb388000}, {0xbb38a000}, {0xbb38c000}, {0xbb38e000}, + {0xbb390000}, {0xbb392000}, {0xbb394000}, {0xbb396000}, + {0xbb398000}, {0xbb39a000}, {0xbb39c000}, {0xbb39e000}, + {0xbb3a0000}, {0xbb3a2000}, {0xbb3a4000}, {0xbb3a6000}, + {0xbb3a8000}, {0xbb3aa000}, {0xbb3ac000}, {0xbb3ae000}, + {0xbb3b0000}, {0xbb3b2000}, {0xbb3b4000}, {0xbb3b6000}, + {0xbb3b8000}, {0xbb3ba000}, {0xbb3bc000}, {0xbb3be000}, + {0xbb3c0000}, {0xbb3c2000}, {0xbb3c4000}, {0xbb3c6000}, + {0xbb3c8000}, {0xbb3ca000}, {0xbb3cc000}, {0xbb3ce000}, + {0xbb3d0000}, {0xbb3d2000}, {0xbb3d4000}, {0xbb3d6000}, + {0xbb3d8000}, {0xbb3da000}, {0xbb3dc000}, {0xbb3de000}, + {0xbb3e0000}, {0xbb3e2000}, {0xbb3e4000}, {0xbb3e6000}, + {0xbb3e8000}, {0xbb3ea000}, {0xbb3ec000}, {0xbb3ee000}, + {0xbb3f0000}, {0xbb3f2000}, {0xbb3f4000}, {0xbb3f6000}, + {0xbb3f8000}, {0xbb3fa000}, {0xbb3fc000}, {0xbb3fe000}, + {0xbb400000}, {0xbb402000}, {0xbb404000}, {0xbb406000}, + {0xbb408000}, {0xbb40a000}, {0xbb40c000}, {0xbb40e000}, + {0xbb410000}, {0xbb412000}, {0xbb414000}, {0xbb416000}, + {0xbb418000}, {0xbb41a000}, {0xbb41c000}, {0xbb41e000}, + {0xbb420000}, {0xbb422000}, {0xbb424000}, {0xbb426000}, + {0xbb428000}, {0xbb42a000}, {0xbb42c000}, {0xbb42e000}, + {0xbb430000}, {0xbb432000}, {0xbb434000}, {0xbb436000}, + {0xbb438000}, {0xbb43a000}, {0xbb43c000}, {0xbb43e000}, + {0xbb440000}, {0xbb442000}, {0xbb444000}, {0xbb446000}, + {0xbb448000}, {0xbb44a000}, {0xbb44c000}, {0xbb44e000}, + {0xbb450000}, {0xbb452000}, {0xbb454000}, {0xbb456000}, + {0xbb458000}, {0xbb45a000}, {0xbb45c000}, {0xbb45e000}, + {0xbb460000}, {0xbb462000}, {0xbb464000}, {0xbb466000}, + {0xbb468000}, {0xbb46a000}, {0xbb46c000}, {0xbb46e000}, + {0xbb470000}, {0xbb472000}, {0xbb474000}, {0xbb476000}, + {0xbb478000}, {0xbb47a000}, {0xbb47c000}, {0xbb47e000}, + {0xbb480000}, {0xbb482000}, {0xbb484000}, {0xbb486000}, + {0xbb488000}, {0xbb48a000}, {0xbb48c000}, {0xbb48e000}, + {0xbb490000}, {0xbb492000}, {0xbb494000}, {0xbb496000}, + {0xbb498000}, {0xbb49a000}, {0xbb49c000}, {0xbb49e000}, + {0xbb4a0000}, {0xbb4a2000}, {0xbb4a4000}, {0xbb4a6000}, + {0xbb4a8000}, {0xbb4aa000}, {0xbb4ac000}, {0xbb4ae000}, + {0xbb4b0000}, {0xbb4b2000}, {0xbb4b4000}, {0xbb4b6000}, + {0xbb4b8000}, {0xbb4ba000}, {0xbb4bc000}, {0xbb4be000}, + {0xbb4c0000}, {0xbb4c2000}, {0xbb4c4000}, {0xbb4c6000}, + {0xbb4c8000}, {0xbb4ca000}, {0xbb4cc000}, {0xbb4ce000}, + {0xbb4d0000}, {0xbb4d2000}, {0xbb4d4000}, {0xbb4d6000}, + {0xbb4d8000}, {0xbb4da000}, {0xbb4dc000}, {0xbb4de000}, + {0xbb4e0000}, {0xbb4e2000}, {0xbb4e4000}, {0xbb4e6000}, + {0xbb4e8000}, {0xbb4ea000}, {0xbb4ec000}, {0xbb4ee000}, + {0xbb4f0000}, {0xbb4f2000}, {0xbb4f4000}, {0xbb4f6000}, + {0xbb4f8000}, {0xbb4fa000}, {0xbb4fc000}, {0xbb4fe000}, + {0xbb500000}, {0xbb502000}, {0xbb504000}, {0xbb506000}, + {0xbb508000}, {0xbb50a000}, {0xbb50c000}, {0xbb50e000}, + {0xbb510000}, {0xbb512000}, {0xbb514000}, {0xbb516000}, + {0xbb518000}, {0xbb51a000}, {0xbb51c000}, {0xbb51e000}, + {0xbb520000}, {0xbb522000}, {0xbb524000}, {0xbb526000}, + {0xbb528000}, {0xbb52a000}, {0xbb52c000}, {0xbb52e000}, + {0xbb530000}, {0xbb532000}, {0xbb534000}, {0xbb536000}, + {0xbb538000}, {0xbb53a000}, {0xbb53c000}, {0xbb53e000}, + {0xbb540000}, {0xbb542000}, {0xbb544000}, {0xbb546000}, + {0xbb548000}, {0xbb54a000}, {0xbb54c000}, {0xbb54e000}, + {0xbb550000}, {0xbb552000}, {0xbb554000}, {0xbb556000}, + {0xbb558000}, {0xbb55a000}, {0xbb55c000}, {0xbb55e000}, + {0xbb560000}, {0xbb562000}, {0xbb564000}, {0xbb566000}, + {0xbb568000}, {0xbb56a000}, {0xbb56c000}, {0xbb56e000}, + {0xbb570000}, {0xbb572000}, {0xbb574000}, {0xbb576000}, + {0xbb578000}, {0xbb57a000}, {0xbb57c000}, {0xbb57e000}, + {0xbb580000}, {0xbb582000}, {0xbb584000}, {0xbb586000}, + {0xbb588000}, {0xbb58a000}, {0xbb58c000}, {0xbb58e000}, + {0xbb590000}, {0xbb592000}, {0xbb594000}, {0xbb596000}, + {0xbb598000}, {0xbb59a000}, {0xbb59c000}, {0xbb59e000}, + {0xbb5a0000}, {0xbb5a2000}, {0xbb5a4000}, {0xbb5a6000}, + {0xbb5a8000}, {0xbb5aa000}, {0xbb5ac000}, {0xbb5ae000}, + {0xbb5b0000}, {0xbb5b2000}, {0xbb5b4000}, {0xbb5b6000}, + {0xbb5b8000}, {0xbb5ba000}, {0xbb5bc000}, {0xbb5be000}, + {0xbb5c0000}, {0xbb5c2000}, {0xbb5c4000}, {0xbb5c6000}, + {0xbb5c8000}, {0xbb5ca000}, {0xbb5cc000}, {0xbb5ce000}, + {0xbb5d0000}, {0xbb5d2000}, {0xbb5d4000}, {0xbb5d6000}, + {0xbb5d8000}, {0xbb5da000}, {0xbb5dc000}, {0xbb5de000}, + {0xbb5e0000}, {0xbb5e2000}, {0xbb5e4000}, {0xbb5e6000}, + {0xbb5e8000}, {0xbb5ea000}, {0xbb5ec000}, {0xbb5ee000}, + {0xbb5f0000}, {0xbb5f2000}, {0xbb5f4000}, {0xbb5f6000}, + {0xbb5f8000}, {0xbb5fa000}, {0xbb5fc000}, {0xbb5fe000}, + {0xbb600000}, {0xbb602000}, {0xbb604000}, {0xbb606000}, + {0xbb608000}, {0xbb60a000}, {0xbb60c000}, {0xbb60e000}, + {0xbb610000}, {0xbb612000}, {0xbb614000}, {0xbb616000}, + {0xbb618000}, {0xbb61a000}, {0xbb61c000}, {0xbb61e000}, + {0xbb620000}, {0xbb622000}, {0xbb624000}, {0xbb626000}, + {0xbb628000}, {0xbb62a000}, {0xbb62c000}, {0xbb62e000}, + {0xbb630000}, {0xbb632000}, {0xbb634000}, {0xbb636000}, + {0xbb638000}, {0xbb63a000}, {0xbb63c000}, {0xbb63e000}, + {0xbb640000}, {0xbb642000}, {0xbb644000}, {0xbb646000}, + {0xbb648000}, {0xbb64a000}, {0xbb64c000}, {0xbb64e000}, + {0xbb650000}, {0xbb652000}, {0xbb654000}, {0xbb656000}, + {0xbb658000}, {0xbb65a000}, {0xbb65c000}, {0xbb65e000}, + {0xbb660000}, {0xbb662000}, {0xbb664000}, {0xbb666000}, + {0xbb668000}, {0xbb66a000}, {0xbb66c000}, {0xbb66e000}, + {0xbb670000}, {0xbb672000}, {0xbb674000}, {0xbb676000}, + {0xbb678000}, {0xbb67a000}, {0xbb67c000}, {0xbb67e000}, + {0xbb680000}, {0xbb682000}, {0xbb684000}, {0xbb686000}, + {0xbb688000}, {0xbb68a000}, {0xbb68c000}, {0xbb68e000}, + {0xbb690000}, {0xbb692000}, {0xbb694000}, {0xbb696000}, + {0xbb698000}, {0xbb69a000}, {0xbb69c000}, {0xbb69e000}, + {0xbb6a0000}, {0xbb6a2000}, {0xbb6a4000}, {0xbb6a6000}, + {0xbb6a8000}, {0xbb6aa000}, {0xbb6ac000}, {0xbb6ae000}, + {0xbb6b0000}, {0xbb6b2000}, {0xbb6b4000}, {0xbb6b6000}, + {0xbb6b8000}, {0xbb6ba000}, {0xbb6bc000}, {0xbb6be000}, + {0xbb6c0000}, {0xbb6c2000}, {0xbb6c4000}, {0xbb6c6000}, + {0xbb6c8000}, {0xbb6ca000}, {0xbb6cc000}, {0xbb6ce000}, + {0xbb6d0000}, {0xbb6d2000}, {0xbb6d4000}, {0xbb6d6000}, + {0xbb6d8000}, {0xbb6da000}, {0xbb6dc000}, {0xbb6de000}, + {0xbb6e0000}, {0xbb6e2000}, {0xbb6e4000}, {0xbb6e6000}, + {0xbb6e8000}, {0xbb6ea000}, {0xbb6ec000}, {0xbb6ee000}, + {0xbb6f0000}, {0xbb6f2000}, {0xbb6f4000}, {0xbb6f6000}, + {0xbb6f8000}, {0xbb6fa000}, {0xbb6fc000}, {0xbb6fe000}, + {0xbb700000}, {0xbb702000}, {0xbb704000}, {0xbb706000}, + {0xbb708000}, {0xbb70a000}, {0xbb70c000}, {0xbb70e000}, + {0xbb710000}, {0xbb712000}, {0xbb714000}, {0xbb716000}, + {0xbb718000}, {0xbb71a000}, {0xbb71c000}, {0xbb71e000}, + {0xbb720000}, {0xbb722000}, {0xbb724000}, {0xbb726000}, + {0xbb728000}, {0xbb72a000}, {0xbb72c000}, {0xbb72e000}, + {0xbb730000}, {0xbb732000}, {0xbb734000}, {0xbb736000}, + {0xbb738000}, {0xbb73a000}, {0xbb73c000}, {0xbb73e000}, + {0xbb740000}, {0xbb742000}, {0xbb744000}, {0xbb746000}, + {0xbb748000}, {0xbb74a000}, {0xbb74c000}, {0xbb74e000}, + {0xbb750000}, {0xbb752000}, {0xbb754000}, {0xbb756000}, + {0xbb758000}, {0xbb75a000}, {0xbb75c000}, {0xbb75e000}, + {0xbb760000}, {0xbb762000}, {0xbb764000}, {0xbb766000}, + {0xbb768000}, {0xbb76a000}, {0xbb76c000}, {0xbb76e000}, + {0xbb770000}, {0xbb772000}, {0xbb774000}, {0xbb776000}, + {0xbb778000}, {0xbb77a000}, {0xbb77c000}, {0xbb77e000}, + {0xbb780000}, {0xbb782000}, {0xbb784000}, {0xbb786000}, + {0xbb788000}, {0xbb78a000}, {0xbb78c000}, {0xbb78e000}, + {0xbb790000}, {0xbb792000}, {0xbb794000}, {0xbb796000}, + {0xbb798000}, {0xbb79a000}, {0xbb79c000}, {0xbb79e000}, + {0xbb7a0000}, {0xbb7a2000}, {0xbb7a4000}, {0xbb7a6000}, + {0xbb7a8000}, {0xbb7aa000}, {0xbb7ac000}, {0xbb7ae000}, + {0xbb7b0000}, {0xbb7b2000}, {0xbb7b4000}, {0xbb7b6000}, + {0xbb7b8000}, {0xbb7ba000}, {0xbb7bc000}, {0xbb7be000}, + {0xbb7c0000}, {0xbb7c2000}, {0xbb7c4000}, {0xbb7c6000}, + {0xbb7c8000}, {0xbb7ca000}, {0xbb7cc000}, {0xbb7ce000}, + {0xbb7d0000}, {0xbb7d2000}, {0xbb7d4000}, {0xbb7d6000}, + {0xbb7d8000}, {0xbb7da000}, {0xbb7dc000}, {0xbb7de000}, + {0xbb7e0000}, {0xbb7e2000}, {0xbb7e4000}, {0xbb7e6000}, + {0xbb7e8000}, {0xbb7ea000}, {0xbb7ec000}, {0xbb7ee000}, + {0xbb7f0000}, {0xbb7f2000}, {0xbb7f4000}, {0xbb7f6000}, + {0xbb7f8000}, {0xbb7fa000}, {0xbb7fc000}, {0xbb7fe000}, + {0xbb800000}, {0xbb802000}, {0xbb804000}, {0xbb806000}, + {0xbb808000}, {0xbb80a000}, {0xbb80c000}, {0xbb80e000}, + {0xbb810000}, {0xbb812000}, {0xbb814000}, {0xbb816000}, + {0xbb818000}, {0xbb81a000}, {0xbb81c000}, {0xbb81e000}, + {0xbb820000}, {0xbb822000}, {0xbb824000}, {0xbb826000}, + {0xbb828000}, {0xbb82a000}, {0xbb82c000}, {0xbb82e000}, + {0xbb830000}, {0xbb832000}, {0xbb834000}, {0xbb836000}, + {0xbb838000}, {0xbb83a000}, {0xbb83c000}, {0xbb83e000}, + {0xbb840000}, {0xbb842000}, {0xbb844000}, {0xbb846000}, + {0xbb848000}, {0xbb84a000}, {0xbb84c000}, {0xbb84e000}, + {0xbb850000}, {0xbb852000}, {0xbb854000}, {0xbb856000}, + {0xbb858000}, {0xbb85a000}, {0xbb85c000}, {0xbb85e000}, + {0xbb860000}, {0xbb862000}, {0xbb864000}, {0xbb866000}, + {0xbb868000}, {0xbb86a000}, {0xbb86c000}, {0xbb86e000}, + {0xbb870000}, {0xbb872000}, {0xbb874000}, {0xbb876000}, + {0xbb878000}, {0xbb87a000}, {0xbb87c000}, {0xbb87e000}, + {0xbb880000}, {0xbb882000}, {0xbb884000}, {0xbb886000}, + {0xbb888000}, {0xbb88a000}, {0xbb88c000}, {0xbb88e000}, + {0xbb890000}, {0xbb892000}, {0xbb894000}, {0xbb896000}, + {0xbb898000}, {0xbb89a000}, {0xbb89c000}, {0xbb89e000}, + {0xbb8a0000}, {0xbb8a2000}, {0xbb8a4000}, {0xbb8a6000}, + {0xbb8a8000}, {0xbb8aa000}, {0xbb8ac000}, {0xbb8ae000}, + {0xbb8b0000}, {0xbb8b2000}, {0xbb8b4000}, {0xbb8b6000}, + {0xbb8b8000}, {0xbb8ba000}, {0xbb8bc000}, {0xbb8be000}, + {0xbb8c0000}, {0xbb8c2000}, {0xbb8c4000}, {0xbb8c6000}, + {0xbb8c8000}, {0xbb8ca000}, {0xbb8cc000}, {0xbb8ce000}, + {0xbb8d0000}, {0xbb8d2000}, {0xbb8d4000}, {0xbb8d6000}, + {0xbb8d8000}, {0xbb8da000}, {0xbb8dc000}, {0xbb8de000}, + {0xbb8e0000}, {0xbb8e2000}, {0xbb8e4000}, {0xbb8e6000}, + {0xbb8e8000}, {0xbb8ea000}, {0xbb8ec000}, {0xbb8ee000}, + {0xbb8f0000}, {0xbb8f2000}, {0xbb8f4000}, {0xbb8f6000}, + {0xbb8f8000}, {0xbb8fa000}, {0xbb8fc000}, {0xbb8fe000}, + {0xbb900000}, {0xbb902000}, {0xbb904000}, {0xbb906000}, + {0xbb908000}, {0xbb90a000}, {0xbb90c000}, {0xbb90e000}, + {0xbb910000}, {0xbb912000}, {0xbb914000}, {0xbb916000}, + {0xbb918000}, {0xbb91a000}, {0xbb91c000}, {0xbb91e000}, + {0xbb920000}, {0xbb922000}, {0xbb924000}, {0xbb926000}, + {0xbb928000}, {0xbb92a000}, {0xbb92c000}, {0xbb92e000}, + {0xbb930000}, {0xbb932000}, {0xbb934000}, {0xbb936000}, + {0xbb938000}, {0xbb93a000}, {0xbb93c000}, {0xbb93e000}, + {0xbb940000}, {0xbb942000}, {0xbb944000}, {0xbb946000}, + {0xbb948000}, {0xbb94a000}, {0xbb94c000}, {0xbb94e000}, + {0xbb950000}, {0xbb952000}, {0xbb954000}, {0xbb956000}, + {0xbb958000}, {0xbb95a000}, {0xbb95c000}, {0xbb95e000}, + {0xbb960000}, {0xbb962000}, {0xbb964000}, {0xbb966000}, + {0xbb968000}, {0xbb96a000}, {0xbb96c000}, {0xbb96e000}, + {0xbb970000}, {0xbb972000}, {0xbb974000}, {0xbb976000}, + {0xbb978000}, {0xbb97a000}, {0xbb97c000}, {0xbb97e000}, + {0xbb980000}, {0xbb982000}, {0xbb984000}, {0xbb986000}, + {0xbb988000}, {0xbb98a000}, {0xbb98c000}, {0xbb98e000}, + {0xbb990000}, {0xbb992000}, {0xbb994000}, {0xbb996000}, + {0xbb998000}, {0xbb99a000}, {0xbb99c000}, {0xbb99e000}, + {0xbb9a0000}, {0xbb9a2000}, {0xbb9a4000}, {0xbb9a6000}, + {0xbb9a8000}, {0xbb9aa000}, {0xbb9ac000}, {0xbb9ae000}, + {0xbb9b0000}, {0xbb9b2000}, {0xbb9b4000}, {0xbb9b6000}, + {0xbb9b8000}, {0xbb9ba000}, {0xbb9bc000}, {0xbb9be000}, + {0xbb9c0000}, {0xbb9c2000}, {0xbb9c4000}, {0xbb9c6000}, + {0xbb9c8000}, {0xbb9ca000}, {0xbb9cc000}, {0xbb9ce000}, + {0xbb9d0000}, {0xbb9d2000}, {0xbb9d4000}, {0xbb9d6000}, + {0xbb9d8000}, {0xbb9da000}, {0xbb9dc000}, {0xbb9de000}, + {0xbb9e0000}, {0xbb9e2000}, {0xbb9e4000}, {0xbb9e6000}, + {0xbb9e8000}, {0xbb9ea000}, {0xbb9ec000}, {0xbb9ee000}, + {0xbb9f0000}, {0xbb9f2000}, {0xbb9f4000}, {0xbb9f6000}, + {0xbb9f8000}, {0xbb9fa000}, {0xbb9fc000}, {0xbb9fe000}, + {0xbba00000}, {0xbba02000}, {0xbba04000}, {0xbba06000}, + {0xbba08000}, {0xbba0a000}, {0xbba0c000}, {0xbba0e000}, + {0xbba10000}, {0xbba12000}, {0xbba14000}, {0xbba16000}, + {0xbba18000}, {0xbba1a000}, {0xbba1c000}, {0xbba1e000}, + {0xbba20000}, {0xbba22000}, {0xbba24000}, {0xbba26000}, + {0xbba28000}, {0xbba2a000}, {0xbba2c000}, {0xbba2e000}, + {0xbba30000}, {0xbba32000}, {0xbba34000}, {0xbba36000}, + {0xbba38000}, {0xbba3a000}, {0xbba3c000}, {0xbba3e000}, + {0xbba40000}, {0xbba42000}, {0xbba44000}, {0xbba46000}, + {0xbba48000}, {0xbba4a000}, {0xbba4c000}, {0xbba4e000}, + {0xbba50000}, {0xbba52000}, {0xbba54000}, {0xbba56000}, + {0xbba58000}, {0xbba5a000}, {0xbba5c000}, {0xbba5e000}, + {0xbba60000}, {0xbba62000}, {0xbba64000}, {0xbba66000}, + {0xbba68000}, {0xbba6a000}, {0xbba6c000}, {0xbba6e000}, + {0xbba70000}, {0xbba72000}, {0xbba74000}, {0xbba76000}, + {0xbba78000}, {0xbba7a000}, {0xbba7c000}, {0xbba7e000}, + {0xbba80000}, {0xbba82000}, {0xbba84000}, {0xbba86000}, + {0xbba88000}, {0xbba8a000}, {0xbba8c000}, {0xbba8e000}, + {0xbba90000}, {0xbba92000}, {0xbba94000}, {0xbba96000}, + {0xbba98000}, {0xbba9a000}, {0xbba9c000}, {0xbba9e000}, + {0xbbaa0000}, {0xbbaa2000}, {0xbbaa4000}, {0xbbaa6000}, + {0xbbaa8000}, {0xbbaaa000}, {0xbbaac000}, {0xbbaae000}, + {0xbbab0000}, {0xbbab2000}, {0xbbab4000}, {0xbbab6000}, + {0xbbab8000}, {0xbbaba000}, {0xbbabc000}, {0xbbabe000}, + {0xbbac0000}, {0xbbac2000}, {0xbbac4000}, {0xbbac6000}, + {0xbbac8000}, {0xbbaca000}, {0xbbacc000}, {0xbbace000}, + {0xbbad0000}, {0xbbad2000}, {0xbbad4000}, {0xbbad6000}, + {0xbbad8000}, {0xbbada000}, {0xbbadc000}, {0xbbade000}, + {0xbbae0000}, {0xbbae2000}, {0xbbae4000}, {0xbbae6000}, + {0xbbae8000}, {0xbbaea000}, {0xbbaec000}, {0xbbaee000}, + {0xbbaf0000}, {0xbbaf2000}, {0xbbaf4000}, {0xbbaf6000}, + {0xbbaf8000}, {0xbbafa000}, {0xbbafc000}, {0xbbafe000}, + {0xbbb00000}, {0xbbb02000}, {0xbbb04000}, {0xbbb06000}, + {0xbbb08000}, {0xbbb0a000}, {0xbbb0c000}, {0xbbb0e000}, + {0xbbb10000}, {0xbbb12000}, {0xbbb14000}, {0xbbb16000}, + {0xbbb18000}, {0xbbb1a000}, {0xbbb1c000}, {0xbbb1e000}, + {0xbbb20000}, {0xbbb22000}, {0xbbb24000}, {0xbbb26000}, + {0xbbb28000}, {0xbbb2a000}, {0xbbb2c000}, {0xbbb2e000}, + {0xbbb30000}, {0xbbb32000}, {0xbbb34000}, {0xbbb36000}, + {0xbbb38000}, {0xbbb3a000}, {0xbbb3c000}, {0xbbb3e000}, + {0xbbb40000}, {0xbbb42000}, {0xbbb44000}, {0xbbb46000}, + {0xbbb48000}, {0xbbb4a000}, {0xbbb4c000}, {0xbbb4e000}, + {0xbbb50000}, {0xbbb52000}, {0xbbb54000}, {0xbbb56000}, + {0xbbb58000}, {0xbbb5a000}, {0xbbb5c000}, {0xbbb5e000}, + {0xbbb60000}, {0xbbb62000}, {0xbbb64000}, {0xbbb66000}, + {0xbbb68000}, {0xbbb6a000}, {0xbbb6c000}, {0xbbb6e000}, + {0xbbb70000}, {0xbbb72000}, {0xbbb74000}, {0xbbb76000}, + {0xbbb78000}, {0xbbb7a000}, {0xbbb7c000}, {0xbbb7e000}, + {0xbbb80000}, {0xbbb82000}, {0xbbb84000}, {0xbbb86000}, + {0xbbb88000}, {0xbbb8a000}, {0xbbb8c000}, {0xbbb8e000}, + {0xbbb90000}, {0xbbb92000}, {0xbbb94000}, {0xbbb96000}, + {0xbbb98000}, {0xbbb9a000}, {0xbbb9c000}, {0xbbb9e000}, + {0xbbba0000}, {0xbbba2000}, {0xbbba4000}, {0xbbba6000}, + {0xbbba8000}, {0xbbbaa000}, {0xbbbac000}, {0xbbbae000}, + {0xbbbb0000}, {0xbbbb2000}, {0xbbbb4000}, {0xbbbb6000}, + {0xbbbb8000}, {0xbbbba000}, {0xbbbbc000}, {0xbbbbe000}, + {0xbbbc0000}, {0xbbbc2000}, {0xbbbc4000}, {0xbbbc6000}, + {0xbbbc8000}, {0xbbbca000}, {0xbbbcc000}, {0xbbbce000}, + {0xbbbd0000}, {0xbbbd2000}, {0xbbbd4000}, {0xbbbd6000}, + {0xbbbd8000}, {0xbbbda000}, {0xbbbdc000}, {0xbbbde000}, + {0xbbbe0000}, {0xbbbe2000}, {0xbbbe4000}, {0xbbbe6000}, + {0xbbbe8000}, {0xbbbea000}, {0xbbbec000}, {0xbbbee000}, + {0xbbbf0000}, {0xbbbf2000}, {0xbbbf4000}, {0xbbbf6000}, + {0xbbbf8000}, {0xbbbfa000}, {0xbbbfc000}, {0xbbbfe000}, + {0xbbc00000}, {0xbbc02000}, {0xbbc04000}, {0xbbc06000}, + {0xbbc08000}, {0xbbc0a000}, {0xbbc0c000}, {0xbbc0e000}, + {0xbbc10000}, {0xbbc12000}, {0xbbc14000}, {0xbbc16000}, + {0xbbc18000}, {0xbbc1a000}, {0xbbc1c000}, {0xbbc1e000}, + {0xbbc20000}, {0xbbc22000}, {0xbbc24000}, {0xbbc26000}, + {0xbbc28000}, {0xbbc2a000}, {0xbbc2c000}, {0xbbc2e000}, + {0xbbc30000}, {0xbbc32000}, {0xbbc34000}, {0xbbc36000}, + {0xbbc38000}, {0xbbc3a000}, {0xbbc3c000}, {0xbbc3e000}, + {0xbbc40000}, {0xbbc42000}, {0xbbc44000}, {0xbbc46000}, + {0xbbc48000}, {0xbbc4a000}, {0xbbc4c000}, {0xbbc4e000}, + {0xbbc50000}, {0xbbc52000}, {0xbbc54000}, {0xbbc56000}, + {0xbbc58000}, {0xbbc5a000}, {0xbbc5c000}, {0xbbc5e000}, + {0xbbc60000}, {0xbbc62000}, {0xbbc64000}, {0xbbc66000}, + {0xbbc68000}, {0xbbc6a000}, {0xbbc6c000}, {0xbbc6e000}, + {0xbbc70000}, {0xbbc72000}, {0xbbc74000}, {0xbbc76000}, + {0xbbc78000}, {0xbbc7a000}, {0xbbc7c000}, {0xbbc7e000}, + {0xbbc80000}, {0xbbc82000}, {0xbbc84000}, {0xbbc86000}, + {0xbbc88000}, {0xbbc8a000}, {0xbbc8c000}, {0xbbc8e000}, + {0xbbc90000}, {0xbbc92000}, {0xbbc94000}, {0xbbc96000}, + {0xbbc98000}, {0xbbc9a000}, {0xbbc9c000}, {0xbbc9e000}, + {0xbbca0000}, {0xbbca2000}, {0xbbca4000}, {0xbbca6000}, + {0xbbca8000}, {0xbbcaa000}, {0xbbcac000}, {0xbbcae000}, + {0xbbcb0000}, {0xbbcb2000}, {0xbbcb4000}, {0xbbcb6000}, + {0xbbcb8000}, {0xbbcba000}, {0xbbcbc000}, {0xbbcbe000}, + {0xbbcc0000}, {0xbbcc2000}, {0xbbcc4000}, {0xbbcc6000}, + {0xbbcc8000}, {0xbbcca000}, {0xbbccc000}, {0xbbcce000}, + {0xbbcd0000}, {0xbbcd2000}, {0xbbcd4000}, {0xbbcd6000}, + {0xbbcd8000}, {0xbbcda000}, {0xbbcdc000}, {0xbbcde000}, + {0xbbce0000}, {0xbbce2000}, {0xbbce4000}, {0xbbce6000}, + {0xbbce8000}, {0xbbcea000}, {0xbbcec000}, {0xbbcee000}, + {0xbbcf0000}, {0xbbcf2000}, {0xbbcf4000}, {0xbbcf6000}, + {0xbbcf8000}, {0xbbcfa000}, {0xbbcfc000}, {0xbbcfe000}, + {0xbbd00000}, {0xbbd02000}, {0xbbd04000}, {0xbbd06000}, + {0xbbd08000}, {0xbbd0a000}, {0xbbd0c000}, {0xbbd0e000}, + {0xbbd10000}, {0xbbd12000}, {0xbbd14000}, {0xbbd16000}, + {0xbbd18000}, {0xbbd1a000}, {0xbbd1c000}, {0xbbd1e000}, + {0xbbd20000}, {0xbbd22000}, {0xbbd24000}, {0xbbd26000}, + {0xbbd28000}, {0xbbd2a000}, {0xbbd2c000}, {0xbbd2e000}, + {0xbbd30000}, {0xbbd32000}, {0xbbd34000}, {0xbbd36000}, + {0xbbd38000}, {0xbbd3a000}, {0xbbd3c000}, {0xbbd3e000}, + {0xbbd40000}, {0xbbd42000}, {0xbbd44000}, {0xbbd46000}, + {0xbbd48000}, {0xbbd4a000}, {0xbbd4c000}, {0xbbd4e000}, + {0xbbd50000}, {0xbbd52000}, {0xbbd54000}, {0xbbd56000}, + {0xbbd58000}, {0xbbd5a000}, {0xbbd5c000}, {0xbbd5e000}, + {0xbbd60000}, {0xbbd62000}, {0xbbd64000}, {0xbbd66000}, + {0xbbd68000}, {0xbbd6a000}, {0xbbd6c000}, {0xbbd6e000}, + {0xbbd70000}, {0xbbd72000}, {0xbbd74000}, {0xbbd76000}, + {0xbbd78000}, {0xbbd7a000}, {0xbbd7c000}, {0xbbd7e000}, + {0xbbd80000}, {0xbbd82000}, {0xbbd84000}, {0xbbd86000}, + {0xbbd88000}, {0xbbd8a000}, {0xbbd8c000}, {0xbbd8e000}, + {0xbbd90000}, {0xbbd92000}, {0xbbd94000}, {0xbbd96000}, + {0xbbd98000}, {0xbbd9a000}, {0xbbd9c000}, {0xbbd9e000}, + {0xbbda0000}, {0xbbda2000}, {0xbbda4000}, {0xbbda6000}, + {0xbbda8000}, {0xbbdaa000}, {0xbbdac000}, {0xbbdae000}, + {0xbbdb0000}, {0xbbdb2000}, {0xbbdb4000}, {0xbbdb6000}, + {0xbbdb8000}, {0xbbdba000}, {0xbbdbc000}, {0xbbdbe000}, + {0xbbdc0000}, {0xbbdc2000}, {0xbbdc4000}, {0xbbdc6000}, + {0xbbdc8000}, {0xbbdca000}, {0xbbdcc000}, {0xbbdce000}, + {0xbbdd0000}, {0xbbdd2000}, {0xbbdd4000}, {0xbbdd6000}, + {0xbbdd8000}, {0xbbdda000}, {0xbbddc000}, {0xbbdde000}, + {0xbbde0000}, {0xbbde2000}, {0xbbde4000}, {0xbbde6000}, + {0xbbde8000}, {0xbbdea000}, {0xbbdec000}, {0xbbdee000}, + {0xbbdf0000}, {0xbbdf2000}, {0xbbdf4000}, {0xbbdf6000}, + {0xbbdf8000}, {0xbbdfa000}, {0xbbdfc000}, {0xbbdfe000}, + {0xbbe00000}, {0xbbe02000}, {0xbbe04000}, {0xbbe06000}, + {0xbbe08000}, {0xbbe0a000}, {0xbbe0c000}, {0xbbe0e000}, + {0xbbe10000}, {0xbbe12000}, {0xbbe14000}, {0xbbe16000}, + {0xbbe18000}, {0xbbe1a000}, {0xbbe1c000}, {0xbbe1e000}, + {0xbbe20000}, {0xbbe22000}, {0xbbe24000}, {0xbbe26000}, + {0xbbe28000}, {0xbbe2a000}, {0xbbe2c000}, {0xbbe2e000}, + {0xbbe30000}, {0xbbe32000}, {0xbbe34000}, {0xbbe36000}, + {0xbbe38000}, {0xbbe3a000}, {0xbbe3c000}, {0xbbe3e000}, + {0xbbe40000}, {0xbbe42000}, {0xbbe44000}, {0xbbe46000}, + {0xbbe48000}, {0xbbe4a000}, {0xbbe4c000}, {0xbbe4e000}, + {0xbbe50000}, {0xbbe52000}, {0xbbe54000}, {0xbbe56000}, + {0xbbe58000}, {0xbbe5a000}, {0xbbe5c000}, {0xbbe5e000}, + {0xbbe60000}, {0xbbe62000}, {0xbbe64000}, {0xbbe66000}, + {0xbbe68000}, {0xbbe6a000}, {0xbbe6c000}, {0xbbe6e000}, + {0xbbe70000}, {0xbbe72000}, {0xbbe74000}, {0xbbe76000}, + {0xbbe78000}, {0xbbe7a000}, {0xbbe7c000}, {0xbbe7e000}, + {0xbbe80000}, {0xbbe82000}, {0xbbe84000}, {0xbbe86000}, + {0xbbe88000}, {0xbbe8a000}, {0xbbe8c000}, {0xbbe8e000}, + {0xbbe90000}, {0xbbe92000}, {0xbbe94000}, {0xbbe96000}, + {0xbbe98000}, {0xbbe9a000}, {0xbbe9c000}, {0xbbe9e000}, + {0xbbea0000}, {0xbbea2000}, {0xbbea4000}, {0xbbea6000}, + {0xbbea8000}, {0xbbeaa000}, {0xbbeac000}, {0xbbeae000}, + {0xbbeb0000}, {0xbbeb2000}, {0xbbeb4000}, {0xbbeb6000}, + {0xbbeb8000}, {0xbbeba000}, {0xbbebc000}, {0xbbebe000}, + {0xbbec0000}, {0xbbec2000}, {0xbbec4000}, {0xbbec6000}, + {0xbbec8000}, {0xbbeca000}, {0xbbecc000}, {0xbbece000}, + {0xbbed0000}, {0xbbed2000}, {0xbbed4000}, {0xbbed6000}, + {0xbbed8000}, {0xbbeda000}, {0xbbedc000}, {0xbbede000}, + {0xbbee0000}, {0xbbee2000}, {0xbbee4000}, {0xbbee6000}, + {0xbbee8000}, {0xbbeea000}, {0xbbeec000}, {0xbbeee000}, + {0xbbef0000}, {0xbbef2000}, {0xbbef4000}, {0xbbef6000}, + {0xbbef8000}, {0xbbefa000}, {0xbbefc000}, {0xbbefe000}, + {0xbbf00000}, {0xbbf02000}, {0xbbf04000}, {0xbbf06000}, + {0xbbf08000}, {0xbbf0a000}, {0xbbf0c000}, {0xbbf0e000}, + {0xbbf10000}, {0xbbf12000}, {0xbbf14000}, {0xbbf16000}, + {0xbbf18000}, {0xbbf1a000}, {0xbbf1c000}, {0xbbf1e000}, + {0xbbf20000}, {0xbbf22000}, {0xbbf24000}, {0xbbf26000}, + {0xbbf28000}, {0xbbf2a000}, {0xbbf2c000}, {0xbbf2e000}, + {0xbbf30000}, {0xbbf32000}, {0xbbf34000}, {0xbbf36000}, + {0xbbf38000}, {0xbbf3a000}, {0xbbf3c000}, {0xbbf3e000}, + {0xbbf40000}, {0xbbf42000}, {0xbbf44000}, {0xbbf46000}, + {0xbbf48000}, {0xbbf4a000}, {0xbbf4c000}, {0xbbf4e000}, + {0xbbf50000}, {0xbbf52000}, {0xbbf54000}, {0xbbf56000}, + {0xbbf58000}, {0xbbf5a000}, {0xbbf5c000}, {0xbbf5e000}, + {0xbbf60000}, {0xbbf62000}, {0xbbf64000}, {0xbbf66000}, + {0xbbf68000}, {0xbbf6a000}, {0xbbf6c000}, {0xbbf6e000}, + {0xbbf70000}, {0xbbf72000}, {0xbbf74000}, {0xbbf76000}, + {0xbbf78000}, {0xbbf7a000}, {0xbbf7c000}, {0xbbf7e000}, + {0xbbf80000}, {0xbbf82000}, {0xbbf84000}, {0xbbf86000}, + {0xbbf88000}, {0xbbf8a000}, {0xbbf8c000}, {0xbbf8e000}, + {0xbbf90000}, {0xbbf92000}, {0xbbf94000}, {0xbbf96000}, + {0xbbf98000}, {0xbbf9a000}, {0xbbf9c000}, {0xbbf9e000}, + {0xbbfa0000}, {0xbbfa2000}, {0xbbfa4000}, {0xbbfa6000}, + {0xbbfa8000}, {0xbbfaa000}, {0xbbfac000}, {0xbbfae000}, + {0xbbfb0000}, {0xbbfb2000}, {0xbbfb4000}, {0xbbfb6000}, + {0xbbfb8000}, {0xbbfba000}, {0xbbfbc000}, {0xbbfbe000}, + {0xbbfc0000}, {0xbbfc2000}, {0xbbfc4000}, {0xbbfc6000}, + {0xbbfc8000}, {0xbbfca000}, {0xbbfcc000}, {0xbbfce000}, + {0xbbfd0000}, {0xbbfd2000}, {0xbbfd4000}, {0xbbfd6000}, + {0xbbfd8000}, {0xbbfda000}, {0xbbfdc000}, {0xbbfde000}, + {0xbbfe0000}, {0xbbfe2000}, {0xbbfe4000}, {0xbbfe6000}, + {0xbbfe8000}, {0xbbfea000}, {0xbbfec000}, {0xbbfee000}, + {0xbbff0000}, {0xbbff2000}, {0xbbff4000}, {0xbbff6000}, + {0xbbff8000}, {0xbbffa000}, {0xbbffc000}, {0xbbffe000}, + {0xbc000000}, {0xbc002000}, {0xbc004000}, {0xbc006000}, + {0xbc008000}, {0xbc00a000}, {0xbc00c000}, {0xbc00e000}, + {0xbc010000}, {0xbc012000}, {0xbc014000}, {0xbc016000}, + {0xbc018000}, {0xbc01a000}, {0xbc01c000}, {0xbc01e000}, + {0xbc020000}, {0xbc022000}, {0xbc024000}, {0xbc026000}, + {0xbc028000}, {0xbc02a000}, {0xbc02c000}, {0xbc02e000}, + {0xbc030000}, {0xbc032000}, {0xbc034000}, {0xbc036000}, + {0xbc038000}, {0xbc03a000}, {0xbc03c000}, {0xbc03e000}, + {0xbc040000}, {0xbc042000}, {0xbc044000}, {0xbc046000}, + {0xbc048000}, {0xbc04a000}, {0xbc04c000}, {0xbc04e000}, + {0xbc050000}, {0xbc052000}, {0xbc054000}, {0xbc056000}, + {0xbc058000}, {0xbc05a000}, {0xbc05c000}, {0xbc05e000}, + {0xbc060000}, {0xbc062000}, {0xbc064000}, {0xbc066000}, + {0xbc068000}, {0xbc06a000}, {0xbc06c000}, {0xbc06e000}, + {0xbc070000}, {0xbc072000}, {0xbc074000}, {0xbc076000}, + {0xbc078000}, {0xbc07a000}, {0xbc07c000}, {0xbc07e000}, + {0xbc080000}, {0xbc082000}, {0xbc084000}, {0xbc086000}, + {0xbc088000}, {0xbc08a000}, {0xbc08c000}, {0xbc08e000}, + {0xbc090000}, {0xbc092000}, {0xbc094000}, {0xbc096000}, + {0xbc098000}, {0xbc09a000}, {0xbc09c000}, {0xbc09e000}, + {0xbc0a0000}, {0xbc0a2000}, {0xbc0a4000}, {0xbc0a6000}, + {0xbc0a8000}, {0xbc0aa000}, {0xbc0ac000}, {0xbc0ae000}, + {0xbc0b0000}, {0xbc0b2000}, {0xbc0b4000}, {0xbc0b6000}, + {0xbc0b8000}, {0xbc0ba000}, {0xbc0bc000}, {0xbc0be000}, + {0xbc0c0000}, {0xbc0c2000}, {0xbc0c4000}, {0xbc0c6000}, + {0xbc0c8000}, {0xbc0ca000}, {0xbc0cc000}, {0xbc0ce000}, + {0xbc0d0000}, {0xbc0d2000}, {0xbc0d4000}, {0xbc0d6000}, + {0xbc0d8000}, {0xbc0da000}, {0xbc0dc000}, {0xbc0de000}, + {0xbc0e0000}, {0xbc0e2000}, {0xbc0e4000}, {0xbc0e6000}, + {0xbc0e8000}, {0xbc0ea000}, {0xbc0ec000}, {0xbc0ee000}, + {0xbc0f0000}, {0xbc0f2000}, {0xbc0f4000}, {0xbc0f6000}, + {0xbc0f8000}, {0xbc0fa000}, {0xbc0fc000}, {0xbc0fe000}, + {0xbc100000}, {0xbc102000}, {0xbc104000}, {0xbc106000}, + {0xbc108000}, {0xbc10a000}, {0xbc10c000}, {0xbc10e000}, + {0xbc110000}, {0xbc112000}, {0xbc114000}, {0xbc116000}, + {0xbc118000}, {0xbc11a000}, {0xbc11c000}, {0xbc11e000}, + {0xbc120000}, {0xbc122000}, {0xbc124000}, {0xbc126000}, + {0xbc128000}, {0xbc12a000}, {0xbc12c000}, {0xbc12e000}, + {0xbc130000}, {0xbc132000}, {0xbc134000}, {0xbc136000}, + {0xbc138000}, {0xbc13a000}, {0xbc13c000}, {0xbc13e000}, + {0xbc140000}, {0xbc142000}, {0xbc144000}, {0xbc146000}, + {0xbc148000}, {0xbc14a000}, {0xbc14c000}, {0xbc14e000}, + {0xbc150000}, {0xbc152000}, {0xbc154000}, {0xbc156000}, + {0xbc158000}, {0xbc15a000}, {0xbc15c000}, {0xbc15e000}, + {0xbc160000}, {0xbc162000}, {0xbc164000}, {0xbc166000}, + {0xbc168000}, {0xbc16a000}, {0xbc16c000}, {0xbc16e000}, + {0xbc170000}, {0xbc172000}, {0xbc174000}, {0xbc176000}, + {0xbc178000}, {0xbc17a000}, {0xbc17c000}, {0xbc17e000}, + {0xbc180000}, {0xbc182000}, {0xbc184000}, {0xbc186000}, + {0xbc188000}, {0xbc18a000}, {0xbc18c000}, {0xbc18e000}, + {0xbc190000}, {0xbc192000}, {0xbc194000}, {0xbc196000}, + {0xbc198000}, {0xbc19a000}, {0xbc19c000}, {0xbc19e000}, + {0xbc1a0000}, {0xbc1a2000}, {0xbc1a4000}, {0xbc1a6000}, + {0xbc1a8000}, {0xbc1aa000}, {0xbc1ac000}, {0xbc1ae000}, + {0xbc1b0000}, {0xbc1b2000}, {0xbc1b4000}, {0xbc1b6000}, + {0xbc1b8000}, {0xbc1ba000}, {0xbc1bc000}, {0xbc1be000}, + {0xbc1c0000}, {0xbc1c2000}, {0xbc1c4000}, {0xbc1c6000}, + {0xbc1c8000}, {0xbc1ca000}, {0xbc1cc000}, {0xbc1ce000}, + {0xbc1d0000}, {0xbc1d2000}, {0xbc1d4000}, {0xbc1d6000}, + {0xbc1d8000}, {0xbc1da000}, {0xbc1dc000}, {0xbc1de000}, + {0xbc1e0000}, {0xbc1e2000}, {0xbc1e4000}, {0xbc1e6000}, + {0xbc1e8000}, {0xbc1ea000}, {0xbc1ec000}, {0xbc1ee000}, + {0xbc1f0000}, {0xbc1f2000}, {0xbc1f4000}, {0xbc1f6000}, + {0xbc1f8000}, {0xbc1fa000}, {0xbc1fc000}, {0xbc1fe000}, + {0xbc200000}, {0xbc202000}, {0xbc204000}, {0xbc206000}, + {0xbc208000}, {0xbc20a000}, {0xbc20c000}, {0xbc20e000}, + {0xbc210000}, {0xbc212000}, {0xbc214000}, {0xbc216000}, + {0xbc218000}, {0xbc21a000}, {0xbc21c000}, {0xbc21e000}, + {0xbc220000}, {0xbc222000}, {0xbc224000}, {0xbc226000}, + {0xbc228000}, {0xbc22a000}, {0xbc22c000}, {0xbc22e000}, + {0xbc230000}, {0xbc232000}, {0xbc234000}, {0xbc236000}, + {0xbc238000}, {0xbc23a000}, {0xbc23c000}, {0xbc23e000}, + {0xbc240000}, {0xbc242000}, {0xbc244000}, {0xbc246000}, + {0xbc248000}, {0xbc24a000}, {0xbc24c000}, {0xbc24e000}, + {0xbc250000}, {0xbc252000}, {0xbc254000}, {0xbc256000}, + {0xbc258000}, {0xbc25a000}, {0xbc25c000}, {0xbc25e000}, + {0xbc260000}, {0xbc262000}, {0xbc264000}, {0xbc266000}, + {0xbc268000}, {0xbc26a000}, {0xbc26c000}, {0xbc26e000}, + {0xbc270000}, {0xbc272000}, {0xbc274000}, {0xbc276000}, + {0xbc278000}, {0xbc27a000}, {0xbc27c000}, {0xbc27e000}, + {0xbc280000}, {0xbc282000}, {0xbc284000}, {0xbc286000}, + {0xbc288000}, {0xbc28a000}, {0xbc28c000}, {0xbc28e000}, + {0xbc290000}, {0xbc292000}, {0xbc294000}, {0xbc296000}, + {0xbc298000}, {0xbc29a000}, {0xbc29c000}, {0xbc29e000}, + {0xbc2a0000}, {0xbc2a2000}, {0xbc2a4000}, {0xbc2a6000}, + {0xbc2a8000}, {0xbc2aa000}, {0xbc2ac000}, {0xbc2ae000}, + {0xbc2b0000}, {0xbc2b2000}, {0xbc2b4000}, {0xbc2b6000}, + {0xbc2b8000}, {0xbc2ba000}, {0xbc2bc000}, {0xbc2be000}, + {0xbc2c0000}, {0xbc2c2000}, {0xbc2c4000}, {0xbc2c6000}, + {0xbc2c8000}, {0xbc2ca000}, {0xbc2cc000}, {0xbc2ce000}, + {0xbc2d0000}, {0xbc2d2000}, {0xbc2d4000}, {0xbc2d6000}, + {0xbc2d8000}, {0xbc2da000}, {0xbc2dc000}, {0xbc2de000}, + {0xbc2e0000}, {0xbc2e2000}, {0xbc2e4000}, {0xbc2e6000}, + {0xbc2e8000}, {0xbc2ea000}, {0xbc2ec000}, {0xbc2ee000}, + {0xbc2f0000}, {0xbc2f2000}, {0xbc2f4000}, {0xbc2f6000}, + {0xbc2f8000}, {0xbc2fa000}, {0xbc2fc000}, {0xbc2fe000}, + {0xbc300000}, {0xbc302000}, {0xbc304000}, {0xbc306000}, + {0xbc308000}, {0xbc30a000}, {0xbc30c000}, {0xbc30e000}, + {0xbc310000}, {0xbc312000}, {0xbc314000}, {0xbc316000}, + {0xbc318000}, {0xbc31a000}, {0xbc31c000}, {0xbc31e000}, + {0xbc320000}, {0xbc322000}, {0xbc324000}, {0xbc326000}, + {0xbc328000}, {0xbc32a000}, {0xbc32c000}, {0xbc32e000}, + {0xbc330000}, {0xbc332000}, {0xbc334000}, {0xbc336000}, + {0xbc338000}, {0xbc33a000}, {0xbc33c000}, {0xbc33e000}, + {0xbc340000}, {0xbc342000}, {0xbc344000}, {0xbc346000}, + {0xbc348000}, {0xbc34a000}, {0xbc34c000}, {0xbc34e000}, + {0xbc350000}, {0xbc352000}, {0xbc354000}, {0xbc356000}, + {0xbc358000}, {0xbc35a000}, {0xbc35c000}, {0xbc35e000}, + {0xbc360000}, {0xbc362000}, {0xbc364000}, {0xbc366000}, + {0xbc368000}, {0xbc36a000}, {0xbc36c000}, {0xbc36e000}, + {0xbc370000}, {0xbc372000}, {0xbc374000}, {0xbc376000}, + {0xbc378000}, {0xbc37a000}, {0xbc37c000}, {0xbc37e000}, + {0xbc380000}, {0xbc382000}, {0xbc384000}, {0xbc386000}, + {0xbc388000}, {0xbc38a000}, {0xbc38c000}, {0xbc38e000}, + {0xbc390000}, {0xbc392000}, {0xbc394000}, {0xbc396000}, + {0xbc398000}, {0xbc39a000}, {0xbc39c000}, {0xbc39e000}, + {0xbc3a0000}, {0xbc3a2000}, {0xbc3a4000}, {0xbc3a6000}, + {0xbc3a8000}, {0xbc3aa000}, {0xbc3ac000}, {0xbc3ae000}, + {0xbc3b0000}, {0xbc3b2000}, {0xbc3b4000}, {0xbc3b6000}, + {0xbc3b8000}, {0xbc3ba000}, {0xbc3bc000}, {0xbc3be000}, + {0xbc3c0000}, {0xbc3c2000}, {0xbc3c4000}, {0xbc3c6000}, + {0xbc3c8000}, {0xbc3ca000}, {0xbc3cc000}, {0xbc3ce000}, + {0xbc3d0000}, {0xbc3d2000}, {0xbc3d4000}, {0xbc3d6000}, + {0xbc3d8000}, {0xbc3da000}, {0xbc3dc000}, {0xbc3de000}, + {0xbc3e0000}, {0xbc3e2000}, {0xbc3e4000}, {0xbc3e6000}, + {0xbc3e8000}, {0xbc3ea000}, {0xbc3ec000}, {0xbc3ee000}, + {0xbc3f0000}, {0xbc3f2000}, {0xbc3f4000}, {0xbc3f6000}, + {0xbc3f8000}, {0xbc3fa000}, {0xbc3fc000}, {0xbc3fe000}, + {0xbc400000}, {0xbc402000}, {0xbc404000}, {0xbc406000}, + {0xbc408000}, {0xbc40a000}, {0xbc40c000}, {0xbc40e000}, + {0xbc410000}, {0xbc412000}, {0xbc414000}, {0xbc416000}, + {0xbc418000}, {0xbc41a000}, {0xbc41c000}, {0xbc41e000}, + {0xbc420000}, {0xbc422000}, {0xbc424000}, {0xbc426000}, + {0xbc428000}, {0xbc42a000}, {0xbc42c000}, {0xbc42e000}, + {0xbc430000}, {0xbc432000}, {0xbc434000}, {0xbc436000}, + {0xbc438000}, {0xbc43a000}, {0xbc43c000}, {0xbc43e000}, + {0xbc440000}, {0xbc442000}, {0xbc444000}, {0xbc446000}, + {0xbc448000}, {0xbc44a000}, {0xbc44c000}, {0xbc44e000}, + {0xbc450000}, {0xbc452000}, {0xbc454000}, {0xbc456000}, + {0xbc458000}, {0xbc45a000}, {0xbc45c000}, {0xbc45e000}, + {0xbc460000}, {0xbc462000}, {0xbc464000}, {0xbc466000}, + {0xbc468000}, {0xbc46a000}, {0xbc46c000}, {0xbc46e000}, + {0xbc470000}, {0xbc472000}, {0xbc474000}, {0xbc476000}, + {0xbc478000}, {0xbc47a000}, {0xbc47c000}, {0xbc47e000}, + {0xbc480000}, {0xbc482000}, {0xbc484000}, {0xbc486000}, + {0xbc488000}, {0xbc48a000}, {0xbc48c000}, {0xbc48e000}, + {0xbc490000}, {0xbc492000}, {0xbc494000}, {0xbc496000}, + {0xbc498000}, {0xbc49a000}, {0xbc49c000}, {0xbc49e000}, + {0xbc4a0000}, {0xbc4a2000}, {0xbc4a4000}, {0xbc4a6000}, + {0xbc4a8000}, {0xbc4aa000}, {0xbc4ac000}, {0xbc4ae000}, + {0xbc4b0000}, {0xbc4b2000}, {0xbc4b4000}, {0xbc4b6000}, + {0xbc4b8000}, {0xbc4ba000}, {0xbc4bc000}, {0xbc4be000}, + {0xbc4c0000}, {0xbc4c2000}, {0xbc4c4000}, {0xbc4c6000}, + {0xbc4c8000}, {0xbc4ca000}, {0xbc4cc000}, {0xbc4ce000}, + {0xbc4d0000}, {0xbc4d2000}, {0xbc4d4000}, {0xbc4d6000}, + {0xbc4d8000}, {0xbc4da000}, {0xbc4dc000}, {0xbc4de000}, + {0xbc4e0000}, {0xbc4e2000}, {0xbc4e4000}, {0xbc4e6000}, + {0xbc4e8000}, {0xbc4ea000}, {0xbc4ec000}, {0xbc4ee000}, + {0xbc4f0000}, {0xbc4f2000}, {0xbc4f4000}, {0xbc4f6000}, + {0xbc4f8000}, {0xbc4fa000}, {0xbc4fc000}, {0xbc4fe000}, + {0xbc500000}, {0xbc502000}, {0xbc504000}, {0xbc506000}, + {0xbc508000}, {0xbc50a000}, {0xbc50c000}, {0xbc50e000}, + {0xbc510000}, {0xbc512000}, {0xbc514000}, {0xbc516000}, + {0xbc518000}, {0xbc51a000}, {0xbc51c000}, {0xbc51e000}, + {0xbc520000}, {0xbc522000}, {0xbc524000}, {0xbc526000}, + {0xbc528000}, {0xbc52a000}, {0xbc52c000}, {0xbc52e000}, + {0xbc530000}, {0xbc532000}, {0xbc534000}, {0xbc536000}, + {0xbc538000}, {0xbc53a000}, {0xbc53c000}, {0xbc53e000}, + {0xbc540000}, {0xbc542000}, {0xbc544000}, {0xbc546000}, + {0xbc548000}, {0xbc54a000}, {0xbc54c000}, {0xbc54e000}, + {0xbc550000}, {0xbc552000}, {0xbc554000}, {0xbc556000}, + {0xbc558000}, {0xbc55a000}, {0xbc55c000}, {0xbc55e000}, + {0xbc560000}, {0xbc562000}, {0xbc564000}, {0xbc566000}, + {0xbc568000}, {0xbc56a000}, {0xbc56c000}, {0xbc56e000}, + {0xbc570000}, {0xbc572000}, {0xbc574000}, {0xbc576000}, + {0xbc578000}, {0xbc57a000}, {0xbc57c000}, {0xbc57e000}, + {0xbc580000}, {0xbc582000}, {0xbc584000}, {0xbc586000}, + {0xbc588000}, {0xbc58a000}, {0xbc58c000}, {0xbc58e000}, + {0xbc590000}, {0xbc592000}, {0xbc594000}, {0xbc596000}, + {0xbc598000}, {0xbc59a000}, {0xbc59c000}, {0xbc59e000}, + {0xbc5a0000}, {0xbc5a2000}, {0xbc5a4000}, {0xbc5a6000}, + {0xbc5a8000}, {0xbc5aa000}, {0xbc5ac000}, {0xbc5ae000}, + {0xbc5b0000}, {0xbc5b2000}, {0xbc5b4000}, {0xbc5b6000}, + {0xbc5b8000}, {0xbc5ba000}, {0xbc5bc000}, {0xbc5be000}, + {0xbc5c0000}, {0xbc5c2000}, {0xbc5c4000}, {0xbc5c6000}, + {0xbc5c8000}, {0xbc5ca000}, {0xbc5cc000}, {0xbc5ce000}, + {0xbc5d0000}, {0xbc5d2000}, {0xbc5d4000}, {0xbc5d6000}, + {0xbc5d8000}, {0xbc5da000}, {0xbc5dc000}, {0xbc5de000}, + {0xbc5e0000}, {0xbc5e2000}, {0xbc5e4000}, {0xbc5e6000}, + {0xbc5e8000}, {0xbc5ea000}, {0xbc5ec000}, {0xbc5ee000}, + {0xbc5f0000}, {0xbc5f2000}, {0xbc5f4000}, {0xbc5f6000}, + {0xbc5f8000}, {0xbc5fa000}, {0xbc5fc000}, {0xbc5fe000}, + {0xbc600000}, {0xbc602000}, {0xbc604000}, {0xbc606000}, + {0xbc608000}, {0xbc60a000}, {0xbc60c000}, {0xbc60e000}, + {0xbc610000}, {0xbc612000}, {0xbc614000}, {0xbc616000}, + {0xbc618000}, {0xbc61a000}, {0xbc61c000}, {0xbc61e000}, + {0xbc620000}, {0xbc622000}, {0xbc624000}, {0xbc626000}, + {0xbc628000}, {0xbc62a000}, {0xbc62c000}, {0xbc62e000}, + {0xbc630000}, {0xbc632000}, {0xbc634000}, {0xbc636000}, + {0xbc638000}, {0xbc63a000}, {0xbc63c000}, {0xbc63e000}, + {0xbc640000}, {0xbc642000}, {0xbc644000}, {0xbc646000}, + {0xbc648000}, {0xbc64a000}, {0xbc64c000}, {0xbc64e000}, + {0xbc650000}, {0xbc652000}, {0xbc654000}, {0xbc656000}, + {0xbc658000}, {0xbc65a000}, {0xbc65c000}, {0xbc65e000}, + {0xbc660000}, {0xbc662000}, {0xbc664000}, {0xbc666000}, + {0xbc668000}, {0xbc66a000}, {0xbc66c000}, {0xbc66e000}, + {0xbc670000}, {0xbc672000}, {0xbc674000}, {0xbc676000}, + {0xbc678000}, {0xbc67a000}, {0xbc67c000}, {0xbc67e000}, + {0xbc680000}, {0xbc682000}, {0xbc684000}, {0xbc686000}, + {0xbc688000}, {0xbc68a000}, {0xbc68c000}, {0xbc68e000}, + {0xbc690000}, {0xbc692000}, {0xbc694000}, {0xbc696000}, + {0xbc698000}, {0xbc69a000}, {0xbc69c000}, {0xbc69e000}, + {0xbc6a0000}, {0xbc6a2000}, {0xbc6a4000}, {0xbc6a6000}, + {0xbc6a8000}, {0xbc6aa000}, {0xbc6ac000}, {0xbc6ae000}, + {0xbc6b0000}, {0xbc6b2000}, {0xbc6b4000}, {0xbc6b6000}, + {0xbc6b8000}, {0xbc6ba000}, {0xbc6bc000}, {0xbc6be000}, + {0xbc6c0000}, {0xbc6c2000}, {0xbc6c4000}, {0xbc6c6000}, + {0xbc6c8000}, {0xbc6ca000}, {0xbc6cc000}, {0xbc6ce000}, + {0xbc6d0000}, {0xbc6d2000}, {0xbc6d4000}, {0xbc6d6000}, + {0xbc6d8000}, {0xbc6da000}, {0xbc6dc000}, {0xbc6de000}, + {0xbc6e0000}, {0xbc6e2000}, {0xbc6e4000}, {0xbc6e6000}, + {0xbc6e8000}, {0xbc6ea000}, {0xbc6ec000}, {0xbc6ee000}, + {0xbc6f0000}, {0xbc6f2000}, {0xbc6f4000}, {0xbc6f6000}, + {0xbc6f8000}, {0xbc6fa000}, {0xbc6fc000}, {0xbc6fe000}, + {0xbc700000}, {0xbc702000}, {0xbc704000}, {0xbc706000}, + {0xbc708000}, {0xbc70a000}, {0xbc70c000}, {0xbc70e000}, + {0xbc710000}, {0xbc712000}, {0xbc714000}, {0xbc716000}, + {0xbc718000}, {0xbc71a000}, {0xbc71c000}, {0xbc71e000}, + {0xbc720000}, {0xbc722000}, {0xbc724000}, {0xbc726000}, + {0xbc728000}, {0xbc72a000}, {0xbc72c000}, {0xbc72e000}, + {0xbc730000}, {0xbc732000}, {0xbc734000}, {0xbc736000}, + {0xbc738000}, {0xbc73a000}, {0xbc73c000}, {0xbc73e000}, + {0xbc740000}, {0xbc742000}, {0xbc744000}, {0xbc746000}, + {0xbc748000}, {0xbc74a000}, {0xbc74c000}, {0xbc74e000}, + {0xbc750000}, {0xbc752000}, {0xbc754000}, {0xbc756000}, + {0xbc758000}, {0xbc75a000}, {0xbc75c000}, {0xbc75e000}, + {0xbc760000}, {0xbc762000}, {0xbc764000}, {0xbc766000}, + {0xbc768000}, {0xbc76a000}, {0xbc76c000}, {0xbc76e000}, + {0xbc770000}, {0xbc772000}, {0xbc774000}, {0xbc776000}, + {0xbc778000}, {0xbc77a000}, {0xbc77c000}, {0xbc77e000}, + {0xbc780000}, {0xbc782000}, {0xbc784000}, {0xbc786000}, + {0xbc788000}, {0xbc78a000}, {0xbc78c000}, {0xbc78e000}, + {0xbc790000}, {0xbc792000}, {0xbc794000}, {0xbc796000}, + {0xbc798000}, {0xbc79a000}, {0xbc79c000}, {0xbc79e000}, + {0xbc7a0000}, {0xbc7a2000}, {0xbc7a4000}, {0xbc7a6000}, + {0xbc7a8000}, {0xbc7aa000}, {0xbc7ac000}, {0xbc7ae000}, + {0xbc7b0000}, {0xbc7b2000}, {0xbc7b4000}, {0xbc7b6000}, + {0xbc7b8000}, {0xbc7ba000}, {0xbc7bc000}, {0xbc7be000}, + {0xbc7c0000}, {0xbc7c2000}, {0xbc7c4000}, {0xbc7c6000}, + {0xbc7c8000}, {0xbc7ca000}, {0xbc7cc000}, {0xbc7ce000}, + {0xbc7d0000}, {0xbc7d2000}, {0xbc7d4000}, {0xbc7d6000}, + {0xbc7d8000}, {0xbc7da000}, {0xbc7dc000}, {0xbc7de000}, + {0xbc7e0000}, {0xbc7e2000}, {0xbc7e4000}, {0xbc7e6000}, + {0xbc7e8000}, {0xbc7ea000}, {0xbc7ec000}, {0xbc7ee000}, + {0xbc7f0000}, {0xbc7f2000}, {0xbc7f4000}, {0xbc7f6000}, + {0xbc7f8000}, {0xbc7fa000}, {0xbc7fc000}, {0xbc7fe000}, + {0xbc800000}, {0xbc802000}, {0xbc804000}, {0xbc806000}, + {0xbc808000}, {0xbc80a000}, {0xbc80c000}, {0xbc80e000}, + {0xbc810000}, {0xbc812000}, {0xbc814000}, {0xbc816000}, + {0xbc818000}, {0xbc81a000}, {0xbc81c000}, {0xbc81e000}, + {0xbc820000}, {0xbc822000}, {0xbc824000}, {0xbc826000}, + {0xbc828000}, {0xbc82a000}, {0xbc82c000}, {0xbc82e000}, + {0xbc830000}, {0xbc832000}, {0xbc834000}, {0xbc836000}, + {0xbc838000}, {0xbc83a000}, {0xbc83c000}, {0xbc83e000}, + {0xbc840000}, {0xbc842000}, {0xbc844000}, {0xbc846000}, + {0xbc848000}, {0xbc84a000}, {0xbc84c000}, {0xbc84e000}, + {0xbc850000}, {0xbc852000}, {0xbc854000}, {0xbc856000}, + {0xbc858000}, {0xbc85a000}, {0xbc85c000}, {0xbc85e000}, + {0xbc860000}, {0xbc862000}, {0xbc864000}, {0xbc866000}, + {0xbc868000}, {0xbc86a000}, {0xbc86c000}, {0xbc86e000}, + {0xbc870000}, {0xbc872000}, {0xbc874000}, {0xbc876000}, + {0xbc878000}, {0xbc87a000}, {0xbc87c000}, {0xbc87e000}, + {0xbc880000}, {0xbc882000}, {0xbc884000}, {0xbc886000}, + {0xbc888000}, {0xbc88a000}, {0xbc88c000}, {0xbc88e000}, + {0xbc890000}, {0xbc892000}, {0xbc894000}, {0xbc896000}, + {0xbc898000}, {0xbc89a000}, {0xbc89c000}, {0xbc89e000}, + {0xbc8a0000}, {0xbc8a2000}, {0xbc8a4000}, {0xbc8a6000}, + {0xbc8a8000}, {0xbc8aa000}, {0xbc8ac000}, {0xbc8ae000}, + {0xbc8b0000}, {0xbc8b2000}, {0xbc8b4000}, {0xbc8b6000}, + {0xbc8b8000}, {0xbc8ba000}, {0xbc8bc000}, {0xbc8be000}, + {0xbc8c0000}, {0xbc8c2000}, {0xbc8c4000}, {0xbc8c6000}, + {0xbc8c8000}, {0xbc8ca000}, {0xbc8cc000}, {0xbc8ce000}, + {0xbc8d0000}, {0xbc8d2000}, {0xbc8d4000}, {0xbc8d6000}, + {0xbc8d8000}, {0xbc8da000}, {0xbc8dc000}, {0xbc8de000}, + {0xbc8e0000}, {0xbc8e2000}, {0xbc8e4000}, {0xbc8e6000}, + {0xbc8e8000}, {0xbc8ea000}, {0xbc8ec000}, {0xbc8ee000}, + {0xbc8f0000}, {0xbc8f2000}, {0xbc8f4000}, {0xbc8f6000}, + {0xbc8f8000}, {0xbc8fa000}, {0xbc8fc000}, {0xbc8fe000}, + {0xbc900000}, {0xbc902000}, {0xbc904000}, {0xbc906000}, + {0xbc908000}, {0xbc90a000}, {0xbc90c000}, {0xbc90e000}, + {0xbc910000}, {0xbc912000}, {0xbc914000}, {0xbc916000}, + {0xbc918000}, {0xbc91a000}, {0xbc91c000}, {0xbc91e000}, + {0xbc920000}, {0xbc922000}, {0xbc924000}, {0xbc926000}, + {0xbc928000}, {0xbc92a000}, {0xbc92c000}, {0xbc92e000}, + {0xbc930000}, {0xbc932000}, {0xbc934000}, {0xbc936000}, + {0xbc938000}, {0xbc93a000}, {0xbc93c000}, {0xbc93e000}, + {0xbc940000}, {0xbc942000}, {0xbc944000}, {0xbc946000}, + {0xbc948000}, {0xbc94a000}, {0xbc94c000}, {0xbc94e000}, + {0xbc950000}, {0xbc952000}, {0xbc954000}, {0xbc956000}, + {0xbc958000}, {0xbc95a000}, {0xbc95c000}, {0xbc95e000}, + {0xbc960000}, {0xbc962000}, {0xbc964000}, {0xbc966000}, + {0xbc968000}, {0xbc96a000}, {0xbc96c000}, {0xbc96e000}, + {0xbc970000}, {0xbc972000}, {0xbc974000}, {0xbc976000}, + {0xbc978000}, {0xbc97a000}, {0xbc97c000}, {0xbc97e000}, + {0xbc980000}, {0xbc982000}, {0xbc984000}, {0xbc986000}, + {0xbc988000}, {0xbc98a000}, {0xbc98c000}, {0xbc98e000}, + {0xbc990000}, {0xbc992000}, {0xbc994000}, {0xbc996000}, + {0xbc998000}, {0xbc99a000}, {0xbc99c000}, {0xbc99e000}, + {0xbc9a0000}, {0xbc9a2000}, {0xbc9a4000}, {0xbc9a6000}, + {0xbc9a8000}, {0xbc9aa000}, {0xbc9ac000}, {0xbc9ae000}, + {0xbc9b0000}, {0xbc9b2000}, {0xbc9b4000}, {0xbc9b6000}, + {0xbc9b8000}, {0xbc9ba000}, {0xbc9bc000}, {0xbc9be000}, + {0xbc9c0000}, {0xbc9c2000}, {0xbc9c4000}, {0xbc9c6000}, + {0xbc9c8000}, {0xbc9ca000}, {0xbc9cc000}, {0xbc9ce000}, + {0xbc9d0000}, {0xbc9d2000}, {0xbc9d4000}, {0xbc9d6000}, + {0xbc9d8000}, {0xbc9da000}, {0xbc9dc000}, {0xbc9de000}, + {0xbc9e0000}, {0xbc9e2000}, {0xbc9e4000}, {0xbc9e6000}, + {0xbc9e8000}, {0xbc9ea000}, {0xbc9ec000}, {0xbc9ee000}, + {0xbc9f0000}, {0xbc9f2000}, {0xbc9f4000}, {0xbc9f6000}, + {0xbc9f8000}, {0xbc9fa000}, {0xbc9fc000}, {0xbc9fe000}, + {0xbca00000}, {0xbca02000}, {0xbca04000}, {0xbca06000}, + {0xbca08000}, {0xbca0a000}, {0xbca0c000}, {0xbca0e000}, + {0xbca10000}, {0xbca12000}, {0xbca14000}, {0xbca16000}, + {0xbca18000}, {0xbca1a000}, {0xbca1c000}, {0xbca1e000}, + {0xbca20000}, {0xbca22000}, {0xbca24000}, {0xbca26000}, + {0xbca28000}, {0xbca2a000}, {0xbca2c000}, {0xbca2e000}, + {0xbca30000}, {0xbca32000}, {0xbca34000}, {0xbca36000}, + {0xbca38000}, {0xbca3a000}, {0xbca3c000}, {0xbca3e000}, + {0xbca40000}, {0xbca42000}, {0xbca44000}, {0xbca46000}, + {0xbca48000}, {0xbca4a000}, {0xbca4c000}, {0xbca4e000}, + {0xbca50000}, {0xbca52000}, {0xbca54000}, {0xbca56000}, + {0xbca58000}, {0xbca5a000}, {0xbca5c000}, {0xbca5e000}, + {0xbca60000}, {0xbca62000}, {0xbca64000}, {0xbca66000}, + {0xbca68000}, {0xbca6a000}, {0xbca6c000}, {0xbca6e000}, + {0xbca70000}, {0xbca72000}, {0xbca74000}, {0xbca76000}, + {0xbca78000}, {0xbca7a000}, {0xbca7c000}, {0xbca7e000}, + {0xbca80000}, {0xbca82000}, {0xbca84000}, {0xbca86000}, + {0xbca88000}, {0xbca8a000}, {0xbca8c000}, {0xbca8e000}, + {0xbca90000}, {0xbca92000}, {0xbca94000}, {0xbca96000}, + {0xbca98000}, {0xbca9a000}, {0xbca9c000}, {0xbca9e000}, + {0xbcaa0000}, {0xbcaa2000}, {0xbcaa4000}, {0xbcaa6000}, + {0xbcaa8000}, {0xbcaaa000}, {0xbcaac000}, {0xbcaae000}, + {0xbcab0000}, {0xbcab2000}, {0xbcab4000}, {0xbcab6000}, + {0xbcab8000}, {0xbcaba000}, {0xbcabc000}, {0xbcabe000}, + {0xbcac0000}, {0xbcac2000}, {0xbcac4000}, {0xbcac6000}, + {0xbcac8000}, {0xbcaca000}, {0xbcacc000}, {0xbcace000}, + {0xbcad0000}, {0xbcad2000}, {0xbcad4000}, {0xbcad6000}, + {0xbcad8000}, {0xbcada000}, {0xbcadc000}, {0xbcade000}, + {0xbcae0000}, {0xbcae2000}, {0xbcae4000}, {0xbcae6000}, + {0xbcae8000}, {0xbcaea000}, {0xbcaec000}, {0xbcaee000}, + {0xbcaf0000}, {0xbcaf2000}, {0xbcaf4000}, {0xbcaf6000}, + {0xbcaf8000}, {0xbcafa000}, {0xbcafc000}, {0xbcafe000}, + {0xbcb00000}, {0xbcb02000}, {0xbcb04000}, {0xbcb06000}, + {0xbcb08000}, {0xbcb0a000}, {0xbcb0c000}, {0xbcb0e000}, + {0xbcb10000}, {0xbcb12000}, {0xbcb14000}, {0xbcb16000}, + {0xbcb18000}, {0xbcb1a000}, {0xbcb1c000}, {0xbcb1e000}, + {0xbcb20000}, {0xbcb22000}, {0xbcb24000}, {0xbcb26000}, + {0xbcb28000}, {0xbcb2a000}, {0xbcb2c000}, {0xbcb2e000}, + {0xbcb30000}, {0xbcb32000}, {0xbcb34000}, {0xbcb36000}, + {0xbcb38000}, {0xbcb3a000}, {0xbcb3c000}, {0xbcb3e000}, + {0xbcb40000}, {0xbcb42000}, {0xbcb44000}, {0xbcb46000}, + {0xbcb48000}, {0xbcb4a000}, {0xbcb4c000}, {0xbcb4e000}, + {0xbcb50000}, {0xbcb52000}, {0xbcb54000}, {0xbcb56000}, + {0xbcb58000}, {0xbcb5a000}, {0xbcb5c000}, {0xbcb5e000}, + {0xbcb60000}, {0xbcb62000}, {0xbcb64000}, {0xbcb66000}, + {0xbcb68000}, {0xbcb6a000}, {0xbcb6c000}, {0xbcb6e000}, + {0xbcb70000}, {0xbcb72000}, {0xbcb74000}, {0xbcb76000}, + {0xbcb78000}, {0xbcb7a000}, {0xbcb7c000}, {0xbcb7e000}, + {0xbcb80000}, {0xbcb82000}, {0xbcb84000}, {0xbcb86000}, + {0xbcb88000}, {0xbcb8a000}, {0xbcb8c000}, {0xbcb8e000}, + {0xbcb90000}, {0xbcb92000}, {0xbcb94000}, {0xbcb96000}, + {0xbcb98000}, {0xbcb9a000}, {0xbcb9c000}, {0xbcb9e000}, + {0xbcba0000}, {0xbcba2000}, {0xbcba4000}, {0xbcba6000}, + {0xbcba8000}, {0xbcbaa000}, {0xbcbac000}, {0xbcbae000}, + {0xbcbb0000}, {0xbcbb2000}, {0xbcbb4000}, {0xbcbb6000}, + {0xbcbb8000}, {0xbcbba000}, {0xbcbbc000}, {0xbcbbe000}, + {0xbcbc0000}, {0xbcbc2000}, {0xbcbc4000}, {0xbcbc6000}, + {0xbcbc8000}, {0xbcbca000}, {0xbcbcc000}, {0xbcbce000}, + {0xbcbd0000}, {0xbcbd2000}, {0xbcbd4000}, {0xbcbd6000}, + {0xbcbd8000}, {0xbcbda000}, {0xbcbdc000}, {0xbcbde000}, + {0xbcbe0000}, {0xbcbe2000}, {0xbcbe4000}, {0xbcbe6000}, + {0xbcbe8000}, {0xbcbea000}, {0xbcbec000}, {0xbcbee000}, + {0xbcbf0000}, {0xbcbf2000}, {0xbcbf4000}, {0xbcbf6000}, + {0xbcbf8000}, {0xbcbfa000}, {0xbcbfc000}, {0xbcbfe000}, + {0xbcc00000}, {0xbcc02000}, {0xbcc04000}, {0xbcc06000}, + {0xbcc08000}, {0xbcc0a000}, {0xbcc0c000}, {0xbcc0e000}, + {0xbcc10000}, {0xbcc12000}, {0xbcc14000}, {0xbcc16000}, + {0xbcc18000}, {0xbcc1a000}, {0xbcc1c000}, {0xbcc1e000}, + {0xbcc20000}, {0xbcc22000}, {0xbcc24000}, {0xbcc26000}, + {0xbcc28000}, {0xbcc2a000}, {0xbcc2c000}, {0xbcc2e000}, + {0xbcc30000}, {0xbcc32000}, {0xbcc34000}, {0xbcc36000}, + {0xbcc38000}, {0xbcc3a000}, {0xbcc3c000}, {0xbcc3e000}, + {0xbcc40000}, {0xbcc42000}, {0xbcc44000}, {0xbcc46000}, + {0xbcc48000}, {0xbcc4a000}, {0xbcc4c000}, {0xbcc4e000}, + {0xbcc50000}, {0xbcc52000}, {0xbcc54000}, {0xbcc56000}, + {0xbcc58000}, {0xbcc5a000}, {0xbcc5c000}, {0xbcc5e000}, + {0xbcc60000}, {0xbcc62000}, {0xbcc64000}, {0xbcc66000}, + {0xbcc68000}, {0xbcc6a000}, {0xbcc6c000}, {0xbcc6e000}, + {0xbcc70000}, {0xbcc72000}, {0xbcc74000}, {0xbcc76000}, + {0xbcc78000}, {0xbcc7a000}, {0xbcc7c000}, {0xbcc7e000}, + {0xbcc80000}, {0xbcc82000}, {0xbcc84000}, {0xbcc86000}, + {0xbcc88000}, {0xbcc8a000}, {0xbcc8c000}, {0xbcc8e000}, + {0xbcc90000}, {0xbcc92000}, {0xbcc94000}, {0xbcc96000}, + {0xbcc98000}, {0xbcc9a000}, {0xbcc9c000}, {0xbcc9e000}, + {0xbcca0000}, {0xbcca2000}, {0xbcca4000}, {0xbcca6000}, + {0xbcca8000}, {0xbccaa000}, {0xbccac000}, {0xbccae000}, + {0xbccb0000}, {0xbccb2000}, {0xbccb4000}, {0xbccb6000}, + {0xbccb8000}, {0xbccba000}, {0xbccbc000}, {0xbccbe000}, + {0xbccc0000}, {0xbccc2000}, {0xbccc4000}, {0xbccc6000}, + {0xbccc8000}, {0xbccca000}, {0xbcccc000}, {0xbccce000}, + {0xbccd0000}, {0xbccd2000}, {0xbccd4000}, {0xbccd6000}, + {0xbccd8000}, {0xbccda000}, {0xbccdc000}, {0xbccde000}, + {0xbcce0000}, {0xbcce2000}, {0xbcce4000}, {0xbcce6000}, + {0xbcce8000}, {0xbccea000}, {0xbccec000}, {0xbccee000}, + {0xbccf0000}, {0xbccf2000}, {0xbccf4000}, {0xbccf6000}, + {0xbccf8000}, {0xbccfa000}, {0xbccfc000}, {0xbccfe000}, + {0xbcd00000}, {0xbcd02000}, {0xbcd04000}, {0xbcd06000}, + {0xbcd08000}, {0xbcd0a000}, {0xbcd0c000}, {0xbcd0e000}, + {0xbcd10000}, {0xbcd12000}, {0xbcd14000}, {0xbcd16000}, + {0xbcd18000}, {0xbcd1a000}, {0xbcd1c000}, {0xbcd1e000}, + {0xbcd20000}, {0xbcd22000}, {0xbcd24000}, {0xbcd26000}, + {0xbcd28000}, {0xbcd2a000}, {0xbcd2c000}, {0xbcd2e000}, + {0xbcd30000}, {0xbcd32000}, {0xbcd34000}, {0xbcd36000}, + {0xbcd38000}, {0xbcd3a000}, {0xbcd3c000}, {0xbcd3e000}, + {0xbcd40000}, {0xbcd42000}, {0xbcd44000}, {0xbcd46000}, + {0xbcd48000}, {0xbcd4a000}, {0xbcd4c000}, {0xbcd4e000}, + {0xbcd50000}, {0xbcd52000}, {0xbcd54000}, {0xbcd56000}, + {0xbcd58000}, {0xbcd5a000}, {0xbcd5c000}, {0xbcd5e000}, + {0xbcd60000}, {0xbcd62000}, {0xbcd64000}, {0xbcd66000}, + {0xbcd68000}, {0xbcd6a000}, {0xbcd6c000}, {0xbcd6e000}, + {0xbcd70000}, {0xbcd72000}, {0xbcd74000}, {0xbcd76000}, + {0xbcd78000}, {0xbcd7a000}, {0xbcd7c000}, {0xbcd7e000}, + {0xbcd80000}, {0xbcd82000}, {0xbcd84000}, {0xbcd86000}, + {0xbcd88000}, {0xbcd8a000}, {0xbcd8c000}, {0xbcd8e000}, + {0xbcd90000}, {0xbcd92000}, {0xbcd94000}, {0xbcd96000}, + {0xbcd98000}, {0xbcd9a000}, {0xbcd9c000}, {0xbcd9e000}, + {0xbcda0000}, {0xbcda2000}, {0xbcda4000}, {0xbcda6000}, + {0xbcda8000}, {0xbcdaa000}, {0xbcdac000}, {0xbcdae000}, + {0xbcdb0000}, {0xbcdb2000}, {0xbcdb4000}, {0xbcdb6000}, + {0xbcdb8000}, {0xbcdba000}, {0xbcdbc000}, {0xbcdbe000}, + {0xbcdc0000}, {0xbcdc2000}, {0xbcdc4000}, {0xbcdc6000}, + {0xbcdc8000}, {0xbcdca000}, {0xbcdcc000}, {0xbcdce000}, + {0xbcdd0000}, {0xbcdd2000}, {0xbcdd4000}, {0xbcdd6000}, + {0xbcdd8000}, {0xbcdda000}, {0xbcddc000}, {0xbcdde000}, + {0xbcde0000}, {0xbcde2000}, {0xbcde4000}, {0xbcde6000}, + {0xbcde8000}, {0xbcdea000}, {0xbcdec000}, {0xbcdee000}, + {0xbcdf0000}, {0xbcdf2000}, {0xbcdf4000}, {0xbcdf6000}, + {0xbcdf8000}, {0xbcdfa000}, {0xbcdfc000}, {0xbcdfe000}, + {0xbce00000}, {0xbce02000}, {0xbce04000}, {0xbce06000}, + {0xbce08000}, {0xbce0a000}, {0xbce0c000}, {0xbce0e000}, + {0xbce10000}, {0xbce12000}, {0xbce14000}, {0xbce16000}, + {0xbce18000}, {0xbce1a000}, {0xbce1c000}, {0xbce1e000}, + {0xbce20000}, {0xbce22000}, {0xbce24000}, {0xbce26000}, + {0xbce28000}, {0xbce2a000}, {0xbce2c000}, {0xbce2e000}, + {0xbce30000}, {0xbce32000}, {0xbce34000}, {0xbce36000}, + {0xbce38000}, {0xbce3a000}, {0xbce3c000}, {0xbce3e000}, + {0xbce40000}, {0xbce42000}, {0xbce44000}, {0xbce46000}, + {0xbce48000}, {0xbce4a000}, {0xbce4c000}, {0xbce4e000}, + {0xbce50000}, {0xbce52000}, {0xbce54000}, {0xbce56000}, + {0xbce58000}, {0xbce5a000}, {0xbce5c000}, {0xbce5e000}, + {0xbce60000}, {0xbce62000}, {0xbce64000}, {0xbce66000}, + {0xbce68000}, {0xbce6a000}, {0xbce6c000}, {0xbce6e000}, + {0xbce70000}, {0xbce72000}, {0xbce74000}, {0xbce76000}, + {0xbce78000}, {0xbce7a000}, {0xbce7c000}, {0xbce7e000}, + {0xbce80000}, {0xbce82000}, {0xbce84000}, {0xbce86000}, + {0xbce88000}, {0xbce8a000}, {0xbce8c000}, {0xbce8e000}, + {0xbce90000}, {0xbce92000}, {0xbce94000}, {0xbce96000}, + {0xbce98000}, {0xbce9a000}, {0xbce9c000}, {0xbce9e000}, + {0xbcea0000}, {0xbcea2000}, {0xbcea4000}, {0xbcea6000}, + {0xbcea8000}, {0xbceaa000}, {0xbceac000}, {0xbceae000}, + {0xbceb0000}, {0xbceb2000}, {0xbceb4000}, {0xbceb6000}, + {0xbceb8000}, {0xbceba000}, {0xbcebc000}, {0xbcebe000}, + {0xbcec0000}, {0xbcec2000}, {0xbcec4000}, {0xbcec6000}, + {0xbcec8000}, {0xbceca000}, {0xbcecc000}, {0xbcece000}, + {0xbced0000}, {0xbced2000}, {0xbced4000}, {0xbced6000}, + {0xbced8000}, {0xbceda000}, {0xbcedc000}, {0xbcede000}, + {0xbcee0000}, {0xbcee2000}, {0xbcee4000}, {0xbcee6000}, + {0xbcee8000}, {0xbceea000}, {0xbceec000}, {0xbceee000}, + {0xbcef0000}, {0xbcef2000}, {0xbcef4000}, {0xbcef6000}, + {0xbcef8000}, {0xbcefa000}, {0xbcefc000}, {0xbcefe000}, + {0xbcf00000}, {0xbcf02000}, {0xbcf04000}, {0xbcf06000}, + {0xbcf08000}, {0xbcf0a000}, {0xbcf0c000}, {0xbcf0e000}, + {0xbcf10000}, {0xbcf12000}, {0xbcf14000}, {0xbcf16000}, + {0xbcf18000}, {0xbcf1a000}, {0xbcf1c000}, {0xbcf1e000}, + {0xbcf20000}, {0xbcf22000}, {0xbcf24000}, {0xbcf26000}, + {0xbcf28000}, {0xbcf2a000}, {0xbcf2c000}, {0xbcf2e000}, + {0xbcf30000}, {0xbcf32000}, {0xbcf34000}, {0xbcf36000}, + {0xbcf38000}, {0xbcf3a000}, {0xbcf3c000}, {0xbcf3e000}, + {0xbcf40000}, {0xbcf42000}, {0xbcf44000}, {0xbcf46000}, + {0xbcf48000}, {0xbcf4a000}, {0xbcf4c000}, {0xbcf4e000}, + {0xbcf50000}, {0xbcf52000}, {0xbcf54000}, {0xbcf56000}, + {0xbcf58000}, {0xbcf5a000}, {0xbcf5c000}, {0xbcf5e000}, + {0xbcf60000}, {0xbcf62000}, {0xbcf64000}, {0xbcf66000}, + {0xbcf68000}, {0xbcf6a000}, {0xbcf6c000}, {0xbcf6e000}, + {0xbcf70000}, {0xbcf72000}, {0xbcf74000}, {0xbcf76000}, + {0xbcf78000}, {0xbcf7a000}, {0xbcf7c000}, {0xbcf7e000}, + {0xbcf80000}, {0xbcf82000}, {0xbcf84000}, {0xbcf86000}, + {0xbcf88000}, {0xbcf8a000}, {0xbcf8c000}, {0xbcf8e000}, + {0xbcf90000}, {0xbcf92000}, {0xbcf94000}, {0xbcf96000}, + {0xbcf98000}, {0xbcf9a000}, {0xbcf9c000}, {0xbcf9e000}, + {0xbcfa0000}, {0xbcfa2000}, {0xbcfa4000}, {0xbcfa6000}, + {0xbcfa8000}, {0xbcfaa000}, {0xbcfac000}, {0xbcfae000}, + {0xbcfb0000}, {0xbcfb2000}, {0xbcfb4000}, {0xbcfb6000}, + {0xbcfb8000}, {0xbcfba000}, {0xbcfbc000}, {0xbcfbe000}, + {0xbcfc0000}, {0xbcfc2000}, {0xbcfc4000}, {0xbcfc6000}, + {0xbcfc8000}, {0xbcfca000}, {0xbcfcc000}, {0xbcfce000}, + {0xbcfd0000}, {0xbcfd2000}, {0xbcfd4000}, {0xbcfd6000}, + {0xbcfd8000}, {0xbcfda000}, {0xbcfdc000}, {0xbcfde000}, + {0xbcfe0000}, {0xbcfe2000}, {0xbcfe4000}, {0xbcfe6000}, + {0xbcfe8000}, {0xbcfea000}, {0xbcfec000}, {0xbcfee000}, + {0xbcff0000}, {0xbcff2000}, {0xbcff4000}, {0xbcff6000}, + {0xbcff8000}, {0xbcffa000}, {0xbcffc000}, {0xbcffe000}, + {0xbd000000}, {0xbd002000}, {0xbd004000}, {0xbd006000}, + {0xbd008000}, {0xbd00a000}, {0xbd00c000}, {0xbd00e000}, + {0xbd010000}, {0xbd012000}, {0xbd014000}, {0xbd016000}, + {0xbd018000}, {0xbd01a000}, {0xbd01c000}, {0xbd01e000}, + {0xbd020000}, {0xbd022000}, {0xbd024000}, {0xbd026000}, + {0xbd028000}, {0xbd02a000}, {0xbd02c000}, {0xbd02e000}, + {0xbd030000}, {0xbd032000}, {0xbd034000}, {0xbd036000}, + {0xbd038000}, {0xbd03a000}, {0xbd03c000}, {0xbd03e000}, + {0xbd040000}, {0xbd042000}, {0xbd044000}, {0xbd046000}, + {0xbd048000}, {0xbd04a000}, {0xbd04c000}, {0xbd04e000}, + {0xbd050000}, {0xbd052000}, {0xbd054000}, {0xbd056000}, + {0xbd058000}, {0xbd05a000}, {0xbd05c000}, {0xbd05e000}, + {0xbd060000}, {0xbd062000}, {0xbd064000}, {0xbd066000}, + {0xbd068000}, {0xbd06a000}, {0xbd06c000}, {0xbd06e000}, + {0xbd070000}, {0xbd072000}, {0xbd074000}, {0xbd076000}, + {0xbd078000}, {0xbd07a000}, {0xbd07c000}, {0xbd07e000}, + {0xbd080000}, {0xbd082000}, {0xbd084000}, {0xbd086000}, + {0xbd088000}, {0xbd08a000}, {0xbd08c000}, {0xbd08e000}, + {0xbd090000}, {0xbd092000}, {0xbd094000}, {0xbd096000}, + {0xbd098000}, {0xbd09a000}, {0xbd09c000}, {0xbd09e000}, + {0xbd0a0000}, {0xbd0a2000}, {0xbd0a4000}, {0xbd0a6000}, + {0xbd0a8000}, {0xbd0aa000}, {0xbd0ac000}, {0xbd0ae000}, + {0xbd0b0000}, {0xbd0b2000}, {0xbd0b4000}, {0xbd0b6000}, + {0xbd0b8000}, {0xbd0ba000}, {0xbd0bc000}, {0xbd0be000}, + {0xbd0c0000}, {0xbd0c2000}, {0xbd0c4000}, {0xbd0c6000}, + {0xbd0c8000}, {0xbd0ca000}, {0xbd0cc000}, {0xbd0ce000}, + {0xbd0d0000}, {0xbd0d2000}, {0xbd0d4000}, {0xbd0d6000}, + {0xbd0d8000}, {0xbd0da000}, {0xbd0dc000}, {0xbd0de000}, + {0xbd0e0000}, {0xbd0e2000}, {0xbd0e4000}, {0xbd0e6000}, + {0xbd0e8000}, {0xbd0ea000}, {0xbd0ec000}, {0xbd0ee000}, + {0xbd0f0000}, {0xbd0f2000}, {0xbd0f4000}, {0xbd0f6000}, + {0xbd0f8000}, {0xbd0fa000}, {0xbd0fc000}, {0xbd0fe000}, + {0xbd100000}, {0xbd102000}, {0xbd104000}, {0xbd106000}, + {0xbd108000}, {0xbd10a000}, {0xbd10c000}, {0xbd10e000}, + {0xbd110000}, {0xbd112000}, {0xbd114000}, {0xbd116000}, + {0xbd118000}, {0xbd11a000}, {0xbd11c000}, {0xbd11e000}, + {0xbd120000}, {0xbd122000}, {0xbd124000}, {0xbd126000}, + {0xbd128000}, {0xbd12a000}, {0xbd12c000}, {0xbd12e000}, + {0xbd130000}, {0xbd132000}, {0xbd134000}, {0xbd136000}, + {0xbd138000}, {0xbd13a000}, {0xbd13c000}, {0xbd13e000}, + {0xbd140000}, {0xbd142000}, {0xbd144000}, {0xbd146000}, + {0xbd148000}, {0xbd14a000}, {0xbd14c000}, {0xbd14e000}, + {0xbd150000}, {0xbd152000}, {0xbd154000}, {0xbd156000}, + {0xbd158000}, {0xbd15a000}, {0xbd15c000}, {0xbd15e000}, + {0xbd160000}, {0xbd162000}, {0xbd164000}, {0xbd166000}, + {0xbd168000}, {0xbd16a000}, {0xbd16c000}, {0xbd16e000}, + {0xbd170000}, {0xbd172000}, {0xbd174000}, {0xbd176000}, + {0xbd178000}, {0xbd17a000}, {0xbd17c000}, {0xbd17e000}, + {0xbd180000}, {0xbd182000}, {0xbd184000}, {0xbd186000}, + {0xbd188000}, {0xbd18a000}, {0xbd18c000}, {0xbd18e000}, + {0xbd190000}, {0xbd192000}, {0xbd194000}, {0xbd196000}, + {0xbd198000}, {0xbd19a000}, {0xbd19c000}, {0xbd19e000}, + {0xbd1a0000}, {0xbd1a2000}, {0xbd1a4000}, {0xbd1a6000}, + {0xbd1a8000}, {0xbd1aa000}, {0xbd1ac000}, {0xbd1ae000}, + {0xbd1b0000}, {0xbd1b2000}, {0xbd1b4000}, {0xbd1b6000}, + {0xbd1b8000}, {0xbd1ba000}, {0xbd1bc000}, {0xbd1be000}, + {0xbd1c0000}, {0xbd1c2000}, {0xbd1c4000}, {0xbd1c6000}, + {0xbd1c8000}, {0xbd1ca000}, {0xbd1cc000}, {0xbd1ce000}, + {0xbd1d0000}, {0xbd1d2000}, {0xbd1d4000}, {0xbd1d6000}, + {0xbd1d8000}, {0xbd1da000}, {0xbd1dc000}, {0xbd1de000}, + {0xbd1e0000}, {0xbd1e2000}, {0xbd1e4000}, {0xbd1e6000}, + {0xbd1e8000}, {0xbd1ea000}, {0xbd1ec000}, {0xbd1ee000}, + {0xbd1f0000}, {0xbd1f2000}, {0xbd1f4000}, {0xbd1f6000}, + {0xbd1f8000}, {0xbd1fa000}, {0xbd1fc000}, {0xbd1fe000}, + {0xbd200000}, {0xbd202000}, {0xbd204000}, {0xbd206000}, + {0xbd208000}, {0xbd20a000}, {0xbd20c000}, {0xbd20e000}, + {0xbd210000}, {0xbd212000}, {0xbd214000}, {0xbd216000}, + {0xbd218000}, {0xbd21a000}, {0xbd21c000}, {0xbd21e000}, + {0xbd220000}, {0xbd222000}, {0xbd224000}, {0xbd226000}, + {0xbd228000}, {0xbd22a000}, {0xbd22c000}, {0xbd22e000}, + {0xbd230000}, {0xbd232000}, {0xbd234000}, {0xbd236000}, + {0xbd238000}, {0xbd23a000}, {0xbd23c000}, {0xbd23e000}, + {0xbd240000}, {0xbd242000}, {0xbd244000}, {0xbd246000}, + {0xbd248000}, {0xbd24a000}, {0xbd24c000}, {0xbd24e000}, + {0xbd250000}, {0xbd252000}, {0xbd254000}, {0xbd256000}, + {0xbd258000}, {0xbd25a000}, {0xbd25c000}, {0xbd25e000}, + {0xbd260000}, {0xbd262000}, {0xbd264000}, {0xbd266000}, + {0xbd268000}, {0xbd26a000}, {0xbd26c000}, {0xbd26e000}, + {0xbd270000}, {0xbd272000}, {0xbd274000}, {0xbd276000}, + {0xbd278000}, {0xbd27a000}, {0xbd27c000}, {0xbd27e000}, + {0xbd280000}, {0xbd282000}, {0xbd284000}, {0xbd286000}, + {0xbd288000}, {0xbd28a000}, {0xbd28c000}, {0xbd28e000}, + {0xbd290000}, {0xbd292000}, {0xbd294000}, {0xbd296000}, + {0xbd298000}, {0xbd29a000}, {0xbd29c000}, {0xbd29e000}, + {0xbd2a0000}, {0xbd2a2000}, {0xbd2a4000}, {0xbd2a6000}, + {0xbd2a8000}, {0xbd2aa000}, {0xbd2ac000}, {0xbd2ae000}, + {0xbd2b0000}, {0xbd2b2000}, {0xbd2b4000}, {0xbd2b6000}, + {0xbd2b8000}, {0xbd2ba000}, {0xbd2bc000}, {0xbd2be000}, + {0xbd2c0000}, {0xbd2c2000}, {0xbd2c4000}, {0xbd2c6000}, + {0xbd2c8000}, {0xbd2ca000}, {0xbd2cc000}, {0xbd2ce000}, + {0xbd2d0000}, {0xbd2d2000}, {0xbd2d4000}, {0xbd2d6000}, + {0xbd2d8000}, {0xbd2da000}, {0xbd2dc000}, {0xbd2de000}, + {0xbd2e0000}, {0xbd2e2000}, {0xbd2e4000}, {0xbd2e6000}, + {0xbd2e8000}, {0xbd2ea000}, {0xbd2ec000}, {0xbd2ee000}, + {0xbd2f0000}, {0xbd2f2000}, {0xbd2f4000}, {0xbd2f6000}, + {0xbd2f8000}, {0xbd2fa000}, {0xbd2fc000}, {0xbd2fe000}, + {0xbd300000}, {0xbd302000}, {0xbd304000}, {0xbd306000}, + {0xbd308000}, {0xbd30a000}, {0xbd30c000}, {0xbd30e000}, + {0xbd310000}, {0xbd312000}, {0xbd314000}, {0xbd316000}, + {0xbd318000}, {0xbd31a000}, {0xbd31c000}, {0xbd31e000}, + {0xbd320000}, {0xbd322000}, {0xbd324000}, {0xbd326000}, + {0xbd328000}, {0xbd32a000}, {0xbd32c000}, {0xbd32e000}, + {0xbd330000}, {0xbd332000}, {0xbd334000}, {0xbd336000}, + {0xbd338000}, {0xbd33a000}, {0xbd33c000}, {0xbd33e000}, + {0xbd340000}, {0xbd342000}, {0xbd344000}, {0xbd346000}, + {0xbd348000}, {0xbd34a000}, {0xbd34c000}, {0xbd34e000}, + {0xbd350000}, {0xbd352000}, {0xbd354000}, {0xbd356000}, + {0xbd358000}, {0xbd35a000}, {0xbd35c000}, {0xbd35e000}, + {0xbd360000}, {0xbd362000}, {0xbd364000}, {0xbd366000}, + {0xbd368000}, {0xbd36a000}, {0xbd36c000}, {0xbd36e000}, + {0xbd370000}, {0xbd372000}, {0xbd374000}, {0xbd376000}, + {0xbd378000}, {0xbd37a000}, {0xbd37c000}, {0xbd37e000}, + {0xbd380000}, {0xbd382000}, {0xbd384000}, {0xbd386000}, + {0xbd388000}, {0xbd38a000}, {0xbd38c000}, {0xbd38e000}, + {0xbd390000}, {0xbd392000}, {0xbd394000}, {0xbd396000}, + {0xbd398000}, {0xbd39a000}, {0xbd39c000}, {0xbd39e000}, + {0xbd3a0000}, {0xbd3a2000}, {0xbd3a4000}, {0xbd3a6000}, + {0xbd3a8000}, {0xbd3aa000}, {0xbd3ac000}, {0xbd3ae000}, + {0xbd3b0000}, {0xbd3b2000}, {0xbd3b4000}, {0xbd3b6000}, + {0xbd3b8000}, {0xbd3ba000}, {0xbd3bc000}, {0xbd3be000}, + {0xbd3c0000}, {0xbd3c2000}, {0xbd3c4000}, {0xbd3c6000}, + {0xbd3c8000}, {0xbd3ca000}, {0xbd3cc000}, {0xbd3ce000}, + {0xbd3d0000}, {0xbd3d2000}, {0xbd3d4000}, {0xbd3d6000}, + {0xbd3d8000}, {0xbd3da000}, {0xbd3dc000}, {0xbd3de000}, + {0xbd3e0000}, {0xbd3e2000}, {0xbd3e4000}, {0xbd3e6000}, + {0xbd3e8000}, {0xbd3ea000}, {0xbd3ec000}, {0xbd3ee000}, + {0xbd3f0000}, {0xbd3f2000}, {0xbd3f4000}, {0xbd3f6000}, + {0xbd3f8000}, {0xbd3fa000}, {0xbd3fc000}, {0xbd3fe000}, + {0xbd400000}, {0xbd402000}, {0xbd404000}, {0xbd406000}, + {0xbd408000}, {0xbd40a000}, {0xbd40c000}, {0xbd40e000}, + {0xbd410000}, {0xbd412000}, {0xbd414000}, {0xbd416000}, + {0xbd418000}, {0xbd41a000}, {0xbd41c000}, {0xbd41e000}, + {0xbd420000}, {0xbd422000}, {0xbd424000}, {0xbd426000}, + {0xbd428000}, {0xbd42a000}, {0xbd42c000}, {0xbd42e000}, + {0xbd430000}, {0xbd432000}, {0xbd434000}, {0xbd436000}, + {0xbd438000}, {0xbd43a000}, {0xbd43c000}, {0xbd43e000}, + {0xbd440000}, {0xbd442000}, {0xbd444000}, {0xbd446000}, + {0xbd448000}, {0xbd44a000}, {0xbd44c000}, {0xbd44e000}, + {0xbd450000}, {0xbd452000}, {0xbd454000}, {0xbd456000}, + {0xbd458000}, {0xbd45a000}, {0xbd45c000}, {0xbd45e000}, + {0xbd460000}, {0xbd462000}, {0xbd464000}, {0xbd466000}, + {0xbd468000}, {0xbd46a000}, {0xbd46c000}, {0xbd46e000}, + {0xbd470000}, {0xbd472000}, {0xbd474000}, {0xbd476000}, + {0xbd478000}, {0xbd47a000}, {0xbd47c000}, {0xbd47e000}, + {0xbd480000}, {0xbd482000}, {0xbd484000}, {0xbd486000}, + {0xbd488000}, {0xbd48a000}, {0xbd48c000}, {0xbd48e000}, + {0xbd490000}, {0xbd492000}, {0xbd494000}, {0xbd496000}, + {0xbd498000}, {0xbd49a000}, {0xbd49c000}, {0xbd49e000}, + {0xbd4a0000}, {0xbd4a2000}, {0xbd4a4000}, {0xbd4a6000}, + {0xbd4a8000}, {0xbd4aa000}, {0xbd4ac000}, {0xbd4ae000}, + {0xbd4b0000}, {0xbd4b2000}, {0xbd4b4000}, {0xbd4b6000}, + {0xbd4b8000}, {0xbd4ba000}, {0xbd4bc000}, {0xbd4be000}, + {0xbd4c0000}, {0xbd4c2000}, {0xbd4c4000}, {0xbd4c6000}, + {0xbd4c8000}, {0xbd4ca000}, {0xbd4cc000}, {0xbd4ce000}, + {0xbd4d0000}, {0xbd4d2000}, {0xbd4d4000}, {0xbd4d6000}, + {0xbd4d8000}, {0xbd4da000}, {0xbd4dc000}, {0xbd4de000}, + {0xbd4e0000}, {0xbd4e2000}, {0xbd4e4000}, {0xbd4e6000}, + {0xbd4e8000}, {0xbd4ea000}, {0xbd4ec000}, {0xbd4ee000}, + {0xbd4f0000}, {0xbd4f2000}, {0xbd4f4000}, {0xbd4f6000}, + {0xbd4f8000}, {0xbd4fa000}, {0xbd4fc000}, {0xbd4fe000}, + {0xbd500000}, {0xbd502000}, {0xbd504000}, {0xbd506000}, + {0xbd508000}, {0xbd50a000}, {0xbd50c000}, {0xbd50e000}, + {0xbd510000}, {0xbd512000}, {0xbd514000}, {0xbd516000}, + {0xbd518000}, {0xbd51a000}, {0xbd51c000}, {0xbd51e000}, + {0xbd520000}, {0xbd522000}, {0xbd524000}, {0xbd526000}, + {0xbd528000}, {0xbd52a000}, {0xbd52c000}, {0xbd52e000}, + {0xbd530000}, {0xbd532000}, {0xbd534000}, {0xbd536000}, + {0xbd538000}, {0xbd53a000}, {0xbd53c000}, {0xbd53e000}, + {0xbd540000}, {0xbd542000}, {0xbd544000}, {0xbd546000}, + {0xbd548000}, {0xbd54a000}, {0xbd54c000}, {0xbd54e000}, + {0xbd550000}, {0xbd552000}, {0xbd554000}, {0xbd556000}, + {0xbd558000}, {0xbd55a000}, {0xbd55c000}, {0xbd55e000}, + {0xbd560000}, {0xbd562000}, {0xbd564000}, {0xbd566000}, + {0xbd568000}, {0xbd56a000}, {0xbd56c000}, {0xbd56e000}, + {0xbd570000}, {0xbd572000}, {0xbd574000}, {0xbd576000}, + {0xbd578000}, {0xbd57a000}, {0xbd57c000}, {0xbd57e000}, + {0xbd580000}, {0xbd582000}, {0xbd584000}, {0xbd586000}, + {0xbd588000}, {0xbd58a000}, {0xbd58c000}, {0xbd58e000}, + {0xbd590000}, {0xbd592000}, {0xbd594000}, {0xbd596000}, + {0xbd598000}, {0xbd59a000}, {0xbd59c000}, {0xbd59e000}, + {0xbd5a0000}, {0xbd5a2000}, {0xbd5a4000}, {0xbd5a6000}, + {0xbd5a8000}, {0xbd5aa000}, {0xbd5ac000}, {0xbd5ae000}, + {0xbd5b0000}, {0xbd5b2000}, {0xbd5b4000}, {0xbd5b6000}, + {0xbd5b8000}, {0xbd5ba000}, {0xbd5bc000}, {0xbd5be000}, + {0xbd5c0000}, {0xbd5c2000}, {0xbd5c4000}, {0xbd5c6000}, + {0xbd5c8000}, {0xbd5ca000}, {0xbd5cc000}, {0xbd5ce000}, + {0xbd5d0000}, {0xbd5d2000}, {0xbd5d4000}, {0xbd5d6000}, + {0xbd5d8000}, {0xbd5da000}, {0xbd5dc000}, {0xbd5de000}, + {0xbd5e0000}, {0xbd5e2000}, {0xbd5e4000}, {0xbd5e6000}, + {0xbd5e8000}, {0xbd5ea000}, {0xbd5ec000}, {0xbd5ee000}, + {0xbd5f0000}, {0xbd5f2000}, {0xbd5f4000}, {0xbd5f6000}, + {0xbd5f8000}, {0xbd5fa000}, {0xbd5fc000}, {0xbd5fe000}, + {0xbd600000}, {0xbd602000}, {0xbd604000}, {0xbd606000}, + {0xbd608000}, {0xbd60a000}, {0xbd60c000}, {0xbd60e000}, + {0xbd610000}, {0xbd612000}, {0xbd614000}, {0xbd616000}, + {0xbd618000}, {0xbd61a000}, {0xbd61c000}, {0xbd61e000}, + {0xbd620000}, {0xbd622000}, {0xbd624000}, {0xbd626000}, + {0xbd628000}, {0xbd62a000}, {0xbd62c000}, {0xbd62e000}, + {0xbd630000}, {0xbd632000}, {0xbd634000}, {0xbd636000}, + {0xbd638000}, {0xbd63a000}, {0xbd63c000}, {0xbd63e000}, + {0xbd640000}, {0xbd642000}, {0xbd644000}, {0xbd646000}, + {0xbd648000}, {0xbd64a000}, {0xbd64c000}, {0xbd64e000}, + {0xbd650000}, {0xbd652000}, {0xbd654000}, {0xbd656000}, + {0xbd658000}, {0xbd65a000}, {0xbd65c000}, {0xbd65e000}, + {0xbd660000}, {0xbd662000}, {0xbd664000}, {0xbd666000}, + {0xbd668000}, {0xbd66a000}, {0xbd66c000}, {0xbd66e000}, + {0xbd670000}, {0xbd672000}, {0xbd674000}, {0xbd676000}, + {0xbd678000}, {0xbd67a000}, {0xbd67c000}, {0xbd67e000}, + {0xbd680000}, {0xbd682000}, {0xbd684000}, {0xbd686000}, + {0xbd688000}, {0xbd68a000}, {0xbd68c000}, {0xbd68e000}, + {0xbd690000}, {0xbd692000}, {0xbd694000}, {0xbd696000}, + {0xbd698000}, {0xbd69a000}, {0xbd69c000}, {0xbd69e000}, + {0xbd6a0000}, {0xbd6a2000}, {0xbd6a4000}, {0xbd6a6000}, + {0xbd6a8000}, {0xbd6aa000}, {0xbd6ac000}, {0xbd6ae000}, + {0xbd6b0000}, {0xbd6b2000}, {0xbd6b4000}, {0xbd6b6000}, + {0xbd6b8000}, {0xbd6ba000}, {0xbd6bc000}, {0xbd6be000}, + {0xbd6c0000}, {0xbd6c2000}, {0xbd6c4000}, {0xbd6c6000}, + {0xbd6c8000}, {0xbd6ca000}, {0xbd6cc000}, {0xbd6ce000}, + {0xbd6d0000}, {0xbd6d2000}, {0xbd6d4000}, {0xbd6d6000}, + {0xbd6d8000}, {0xbd6da000}, {0xbd6dc000}, {0xbd6de000}, + {0xbd6e0000}, {0xbd6e2000}, {0xbd6e4000}, {0xbd6e6000}, + {0xbd6e8000}, {0xbd6ea000}, {0xbd6ec000}, {0xbd6ee000}, + {0xbd6f0000}, {0xbd6f2000}, {0xbd6f4000}, {0xbd6f6000}, + {0xbd6f8000}, {0xbd6fa000}, {0xbd6fc000}, {0xbd6fe000}, + {0xbd700000}, {0xbd702000}, {0xbd704000}, {0xbd706000}, + {0xbd708000}, {0xbd70a000}, {0xbd70c000}, {0xbd70e000}, + {0xbd710000}, {0xbd712000}, {0xbd714000}, {0xbd716000}, + {0xbd718000}, {0xbd71a000}, {0xbd71c000}, {0xbd71e000}, + {0xbd720000}, {0xbd722000}, {0xbd724000}, {0xbd726000}, + {0xbd728000}, {0xbd72a000}, {0xbd72c000}, {0xbd72e000}, + {0xbd730000}, {0xbd732000}, {0xbd734000}, {0xbd736000}, + {0xbd738000}, {0xbd73a000}, {0xbd73c000}, {0xbd73e000}, + {0xbd740000}, {0xbd742000}, {0xbd744000}, {0xbd746000}, + {0xbd748000}, {0xbd74a000}, {0xbd74c000}, {0xbd74e000}, + {0xbd750000}, {0xbd752000}, {0xbd754000}, {0xbd756000}, + {0xbd758000}, {0xbd75a000}, {0xbd75c000}, {0xbd75e000}, + {0xbd760000}, {0xbd762000}, {0xbd764000}, {0xbd766000}, + {0xbd768000}, {0xbd76a000}, {0xbd76c000}, {0xbd76e000}, + {0xbd770000}, {0xbd772000}, {0xbd774000}, {0xbd776000}, + {0xbd778000}, {0xbd77a000}, {0xbd77c000}, {0xbd77e000}, + {0xbd780000}, {0xbd782000}, {0xbd784000}, {0xbd786000}, + {0xbd788000}, {0xbd78a000}, {0xbd78c000}, {0xbd78e000}, + {0xbd790000}, {0xbd792000}, {0xbd794000}, {0xbd796000}, + {0xbd798000}, {0xbd79a000}, {0xbd79c000}, {0xbd79e000}, + {0xbd7a0000}, {0xbd7a2000}, {0xbd7a4000}, {0xbd7a6000}, + {0xbd7a8000}, {0xbd7aa000}, {0xbd7ac000}, {0xbd7ae000}, + {0xbd7b0000}, {0xbd7b2000}, {0xbd7b4000}, {0xbd7b6000}, + {0xbd7b8000}, {0xbd7ba000}, {0xbd7bc000}, {0xbd7be000}, + {0xbd7c0000}, {0xbd7c2000}, {0xbd7c4000}, {0xbd7c6000}, + {0xbd7c8000}, {0xbd7ca000}, {0xbd7cc000}, {0xbd7ce000}, + {0xbd7d0000}, {0xbd7d2000}, {0xbd7d4000}, {0xbd7d6000}, + {0xbd7d8000}, {0xbd7da000}, {0xbd7dc000}, {0xbd7de000}, + {0xbd7e0000}, {0xbd7e2000}, {0xbd7e4000}, {0xbd7e6000}, + {0xbd7e8000}, {0xbd7ea000}, {0xbd7ec000}, {0xbd7ee000}, + {0xbd7f0000}, {0xbd7f2000}, {0xbd7f4000}, {0xbd7f6000}, + {0xbd7f8000}, {0xbd7fa000}, {0xbd7fc000}, {0xbd7fe000}, + {0xbd800000}, {0xbd802000}, {0xbd804000}, {0xbd806000}, + {0xbd808000}, {0xbd80a000}, {0xbd80c000}, {0xbd80e000}, + {0xbd810000}, {0xbd812000}, {0xbd814000}, {0xbd816000}, + {0xbd818000}, {0xbd81a000}, {0xbd81c000}, {0xbd81e000}, + {0xbd820000}, {0xbd822000}, {0xbd824000}, {0xbd826000}, + {0xbd828000}, {0xbd82a000}, {0xbd82c000}, {0xbd82e000}, + {0xbd830000}, {0xbd832000}, {0xbd834000}, {0xbd836000}, + {0xbd838000}, {0xbd83a000}, {0xbd83c000}, {0xbd83e000}, + {0xbd840000}, {0xbd842000}, {0xbd844000}, {0xbd846000}, + {0xbd848000}, {0xbd84a000}, {0xbd84c000}, {0xbd84e000}, + {0xbd850000}, {0xbd852000}, {0xbd854000}, {0xbd856000}, + {0xbd858000}, {0xbd85a000}, {0xbd85c000}, {0xbd85e000}, + {0xbd860000}, {0xbd862000}, {0xbd864000}, {0xbd866000}, + {0xbd868000}, {0xbd86a000}, {0xbd86c000}, {0xbd86e000}, + {0xbd870000}, {0xbd872000}, {0xbd874000}, {0xbd876000}, + {0xbd878000}, {0xbd87a000}, {0xbd87c000}, {0xbd87e000}, + {0xbd880000}, {0xbd882000}, {0xbd884000}, {0xbd886000}, + {0xbd888000}, {0xbd88a000}, {0xbd88c000}, {0xbd88e000}, + {0xbd890000}, {0xbd892000}, {0xbd894000}, {0xbd896000}, + {0xbd898000}, {0xbd89a000}, {0xbd89c000}, {0xbd89e000}, + {0xbd8a0000}, {0xbd8a2000}, {0xbd8a4000}, {0xbd8a6000}, + {0xbd8a8000}, {0xbd8aa000}, {0xbd8ac000}, {0xbd8ae000}, + {0xbd8b0000}, {0xbd8b2000}, {0xbd8b4000}, {0xbd8b6000}, + {0xbd8b8000}, {0xbd8ba000}, {0xbd8bc000}, {0xbd8be000}, + {0xbd8c0000}, {0xbd8c2000}, {0xbd8c4000}, {0xbd8c6000}, + {0xbd8c8000}, {0xbd8ca000}, {0xbd8cc000}, {0xbd8ce000}, + {0xbd8d0000}, {0xbd8d2000}, {0xbd8d4000}, {0xbd8d6000}, + {0xbd8d8000}, {0xbd8da000}, {0xbd8dc000}, {0xbd8de000}, + {0xbd8e0000}, {0xbd8e2000}, {0xbd8e4000}, {0xbd8e6000}, + {0xbd8e8000}, {0xbd8ea000}, {0xbd8ec000}, {0xbd8ee000}, + {0xbd8f0000}, {0xbd8f2000}, {0xbd8f4000}, {0xbd8f6000}, + {0xbd8f8000}, {0xbd8fa000}, {0xbd8fc000}, {0xbd8fe000}, + {0xbd900000}, {0xbd902000}, {0xbd904000}, {0xbd906000}, + {0xbd908000}, {0xbd90a000}, {0xbd90c000}, {0xbd90e000}, + {0xbd910000}, {0xbd912000}, {0xbd914000}, {0xbd916000}, + {0xbd918000}, {0xbd91a000}, {0xbd91c000}, {0xbd91e000}, + {0xbd920000}, {0xbd922000}, {0xbd924000}, {0xbd926000}, + {0xbd928000}, {0xbd92a000}, {0xbd92c000}, {0xbd92e000}, + {0xbd930000}, {0xbd932000}, {0xbd934000}, {0xbd936000}, + {0xbd938000}, {0xbd93a000}, {0xbd93c000}, {0xbd93e000}, + {0xbd940000}, {0xbd942000}, {0xbd944000}, {0xbd946000}, + {0xbd948000}, {0xbd94a000}, {0xbd94c000}, {0xbd94e000}, + {0xbd950000}, {0xbd952000}, {0xbd954000}, {0xbd956000}, + {0xbd958000}, {0xbd95a000}, {0xbd95c000}, {0xbd95e000}, + {0xbd960000}, {0xbd962000}, {0xbd964000}, {0xbd966000}, + {0xbd968000}, {0xbd96a000}, {0xbd96c000}, {0xbd96e000}, + {0xbd970000}, {0xbd972000}, {0xbd974000}, {0xbd976000}, + {0xbd978000}, {0xbd97a000}, {0xbd97c000}, {0xbd97e000}, + {0xbd980000}, {0xbd982000}, {0xbd984000}, {0xbd986000}, + {0xbd988000}, {0xbd98a000}, {0xbd98c000}, {0xbd98e000}, + {0xbd990000}, {0xbd992000}, {0xbd994000}, {0xbd996000}, + {0xbd998000}, {0xbd99a000}, {0xbd99c000}, {0xbd99e000}, + {0xbd9a0000}, {0xbd9a2000}, {0xbd9a4000}, {0xbd9a6000}, + {0xbd9a8000}, {0xbd9aa000}, {0xbd9ac000}, {0xbd9ae000}, + {0xbd9b0000}, {0xbd9b2000}, {0xbd9b4000}, {0xbd9b6000}, + {0xbd9b8000}, {0xbd9ba000}, {0xbd9bc000}, {0xbd9be000}, + {0xbd9c0000}, {0xbd9c2000}, {0xbd9c4000}, {0xbd9c6000}, + {0xbd9c8000}, {0xbd9ca000}, {0xbd9cc000}, {0xbd9ce000}, + {0xbd9d0000}, {0xbd9d2000}, {0xbd9d4000}, {0xbd9d6000}, + {0xbd9d8000}, {0xbd9da000}, {0xbd9dc000}, {0xbd9de000}, + {0xbd9e0000}, {0xbd9e2000}, {0xbd9e4000}, {0xbd9e6000}, + {0xbd9e8000}, {0xbd9ea000}, {0xbd9ec000}, {0xbd9ee000}, + {0xbd9f0000}, {0xbd9f2000}, {0xbd9f4000}, {0xbd9f6000}, + {0xbd9f8000}, {0xbd9fa000}, {0xbd9fc000}, {0xbd9fe000}, + {0xbda00000}, {0xbda02000}, {0xbda04000}, {0xbda06000}, + {0xbda08000}, {0xbda0a000}, {0xbda0c000}, {0xbda0e000}, + {0xbda10000}, {0xbda12000}, {0xbda14000}, {0xbda16000}, + {0xbda18000}, {0xbda1a000}, {0xbda1c000}, {0xbda1e000}, + {0xbda20000}, {0xbda22000}, {0xbda24000}, {0xbda26000}, + {0xbda28000}, {0xbda2a000}, {0xbda2c000}, {0xbda2e000}, + {0xbda30000}, {0xbda32000}, {0xbda34000}, {0xbda36000}, + {0xbda38000}, {0xbda3a000}, {0xbda3c000}, {0xbda3e000}, + {0xbda40000}, {0xbda42000}, {0xbda44000}, {0xbda46000}, + {0xbda48000}, {0xbda4a000}, {0xbda4c000}, {0xbda4e000}, + {0xbda50000}, {0xbda52000}, {0xbda54000}, {0xbda56000}, + {0xbda58000}, {0xbda5a000}, {0xbda5c000}, {0xbda5e000}, + {0xbda60000}, {0xbda62000}, {0xbda64000}, {0xbda66000}, + {0xbda68000}, {0xbda6a000}, {0xbda6c000}, {0xbda6e000}, + {0xbda70000}, {0xbda72000}, {0xbda74000}, {0xbda76000}, + {0xbda78000}, {0xbda7a000}, {0xbda7c000}, {0xbda7e000}, + {0xbda80000}, {0xbda82000}, {0xbda84000}, {0xbda86000}, + {0xbda88000}, {0xbda8a000}, {0xbda8c000}, {0xbda8e000}, + {0xbda90000}, {0xbda92000}, {0xbda94000}, {0xbda96000}, + {0xbda98000}, {0xbda9a000}, {0xbda9c000}, {0xbda9e000}, + {0xbdaa0000}, {0xbdaa2000}, {0xbdaa4000}, {0xbdaa6000}, + {0xbdaa8000}, {0xbdaaa000}, {0xbdaac000}, {0xbdaae000}, + {0xbdab0000}, {0xbdab2000}, {0xbdab4000}, {0xbdab6000}, + {0xbdab8000}, {0xbdaba000}, {0xbdabc000}, {0xbdabe000}, + {0xbdac0000}, {0xbdac2000}, {0xbdac4000}, {0xbdac6000}, + {0xbdac8000}, {0xbdaca000}, {0xbdacc000}, {0xbdace000}, + {0xbdad0000}, {0xbdad2000}, {0xbdad4000}, {0xbdad6000}, + {0xbdad8000}, {0xbdada000}, {0xbdadc000}, {0xbdade000}, + {0xbdae0000}, {0xbdae2000}, {0xbdae4000}, {0xbdae6000}, + {0xbdae8000}, {0xbdaea000}, {0xbdaec000}, {0xbdaee000}, + {0xbdaf0000}, {0xbdaf2000}, {0xbdaf4000}, {0xbdaf6000}, + {0xbdaf8000}, {0xbdafa000}, {0xbdafc000}, {0xbdafe000}, + {0xbdb00000}, {0xbdb02000}, {0xbdb04000}, {0xbdb06000}, + {0xbdb08000}, {0xbdb0a000}, {0xbdb0c000}, {0xbdb0e000}, + {0xbdb10000}, {0xbdb12000}, {0xbdb14000}, {0xbdb16000}, + {0xbdb18000}, {0xbdb1a000}, {0xbdb1c000}, {0xbdb1e000}, + {0xbdb20000}, {0xbdb22000}, {0xbdb24000}, {0xbdb26000}, + {0xbdb28000}, {0xbdb2a000}, {0xbdb2c000}, {0xbdb2e000}, + {0xbdb30000}, {0xbdb32000}, {0xbdb34000}, {0xbdb36000}, + {0xbdb38000}, {0xbdb3a000}, {0xbdb3c000}, {0xbdb3e000}, + {0xbdb40000}, {0xbdb42000}, {0xbdb44000}, {0xbdb46000}, + {0xbdb48000}, {0xbdb4a000}, {0xbdb4c000}, {0xbdb4e000}, + {0xbdb50000}, {0xbdb52000}, {0xbdb54000}, {0xbdb56000}, + {0xbdb58000}, {0xbdb5a000}, {0xbdb5c000}, {0xbdb5e000}, + {0xbdb60000}, {0xbdb62000}, {0xbdb64000}, {0xbdb66000}, + {0xbdb68000}, {0xbdb6a000}, {0xbdb6c000}, {0xbdb6e000}, + {0xbdb70000}, {0xbdb72000}, {0xbdb74000}, {0xbdb76000}, + {0xbdb78000}, {0xbdb7a000}, {0xbdb7c000}, {0xbdb7e000}, + {0xbdb80000}, {0xbdb82000}, {0xbdb84000}, {0xbdb86000}, + {0xbdb88000}, {0xbdb8a000}, {0xbdb8c000}, {0xbdb8e000}, + {0xbdb90000}, {0xbdb92000}, {0xbdb94000}, {0xbdb96000}, + {0xbdb98000}, {0xbdb9a000}, {0xbdb9c000}, {0xbdb9e000}, + {0xbdba0000}, {0xbdba2000}, {0xbdba4000}, {0xbdba6000}, + {0xbdba8000}, {0xbdbaa000}, {0xbdbac000}, {0xbdbae000}, + {0xbdbb0000}, {0xbdbb2000}, {0xbdbb4000}, {0xbdbb6000}, + {0xbdbb8000}, {0xbdbba000}, {0xbdbbc000}, {0xbdbbe000}, + {0xbdbc0000}, {0xbdbc2000}, {0xbdbc4000}, {0xbdbc6000}, + {0xbdbc8000}, {0xbdbca000}, {0xbdbcc000}, {0xbdbce000}, + {0xbdbd0000}, {0xbdbd2000}, {0xbdbd4000}, {0xbdbd6000}, + {0xbdbd8000}, {0xbdbda000}, {0xbdbdc000}, {0xbdbde000}, + {0xbdbe0000}, {0xbdbe2000}, {0xbdbe4000}, {0xbdbe6000}, + {0xbdbe8000}, {0xbdbea000}, {0xbdbec000}, {0xbdbee000}, + {0xbdbf0000}, {0xbdbf2000}, {0xbdbf4000}, {0xbdbf6000}, + {0xbdbf8000}, {0xbdbfa000}, {0xbdbfc000}, {0xbdbfe000}, + {0xbdc00000}, {0xbdc02000}, {0xbdc04000}, {0xbdc06000}, + {0xbdc08000}, {0xbdc0a000}, {0xbdc0c000}, {0xbdc0e000}, + {0xbdc10000}, {0xbdc12000}, {0xbdc14000}, {0xbdc16000}, + {0xbdc18000}, {0xbdc1a000}, {0xbdc1c000}, {0xbdc1e000}, + {0xbdc20000}, {0xbdc22000}, {0xbdc24000}, {0xbdc26000}, + {0xbdc28000}, {0xbdc2a000}, {0xbdc2c000}, {0xbdc2e000}, + {0xbdc30000}, {0xbdc32000}, {0xbdc34000}, {0xbdc36000}, + {0xbdc38000}, {0xbdc3a000}, {0xbdc3c000}, {0xbdc3e000}, + {0xbdc40000}, {0xbdc42000}, {0xbdc44000}, {0xbdc46000}, + {0xbdc48000}, {0xbdc4a000}, {0xbdc4c000}, {0xbdc4e000}, + {0xbdc50000}, {0xbdc52000}, {0xbdc54000}, {0xbdc56000}, + {0xbdc58000}, {0xbdc5a000}, {0xbdc5c000}, {0xbdc5e000}, + {0xbdc60000}, {0xbdc62000}, {0xbdc64000}, {0xbdc66000}, + {0xbdc68000}, {0xbdc6a000}, {0xbdc6c000}, {0xbdc6e000}, + {0xbdc70000}, {0xbdc72000}, {0xbdc74000}, {0xbdc76000}, + {0xbdc78000}, {0xbdc7a000}, {0xbdc7c000}, {0xbdc7e000}, + {0xbdc80000}, {0xbdc82000}, {0xbdc84000}, {0xbdc86000}, + {0xbdc88000}, {0xbdc8a000}, {0xbdc8c000}, {0xbdc8e000}, + {0xbdc90000}, {0xbdc92000}, {0xbdc94000}, {0xbdc96000}, + {0xbdc98000}, {0xbdc9a000}, {0xbdc9c000}, {0xbdc9e000}, + {0xbdca0000}, {0xbdca2000}, {0xbdca4000}, {0xbdca6000}, + {0xbdca8000}, {0xbdcaa000}, {0xbdcac000}, {0xbdcae000}, + {0xbdcb0000}, {0xbdcb2000}, {0xbdcb4000}, {0xbdcb6000}, + {0xbdcb8000}, {0xbdcba000}, {0xbdcbc000}, {0xbdcbe000}, + {0xbdcc0000}, {0xbdcc2000}, {0xbdcc4000}, {0xbdcc6000}, + {0xbdcc8000}, {0xbdcca000}, {0xbdccc000}, {0xbdcce000}, + {0xbdcd0000}, {0xbdcd2000}, {0xbdcd4000}, {0xbdcd6000}, + {0xbdcd8000}, {0xbdcda000}, {0xbdcdc000}, {0xbdcde000}, + {0xbdce0000}, {0xbdce2000}, {0xbdce4000}, {0xbdce6000}, + {0xbdce8000}, {0xbdcea000}, {0xbdcec000}, {0xbdcee000}, + {0xbdcf0000}, {0xbdcf2000}, {0xbdcf4000}, {0xbdcf6000}, + {0xbdcf8000}, {0xbdcfa000}, {0xbdcfc000}, {0xbdcfe000}, + {0xbdd00000}, {0xbdd02000}, {0xbdd04000}, {0xbdd06000}, + {0xbdd08000}, {0xbdd0a000}, {0xbdd0c000}, {0xbdd0e000}, + {0xbdd10000}, {0xbdd12000}, {0xbdd14000}, {0xbdd16000}, + {0xbdd18000}, {0xbdd1a000}, {0xbdd1c000}, {0xbdd1e000}, + {0xbdd20000}, {0xbdd22000}, {0xbdd24000}, {0xbdd26000}, + {0xbdd28000}, {0xbdd2a000}, {0xbdd2c000}, {0xbdd2e000}, + {0xbdd30000}, {0xbdd32000}, {0xbdd34000}, {0xbdd36000}, + {0xbdd38000}, {0xbdd3a000}, {0xbdd3c000}, {0xbdd3e000}, + {0xbdd40000}, {0xbdd42000}, {0xbdd44000}, {0xbdd46000}, + {0xbdd48000}, {0xbdd4a000}, {0xbdd4c000}, {0xbdd4e000}, + {0xbdd50000}, {0xbdd52000}, {0xbdd54000}, {0xbdd56000}, + {0xbdd58000}, {0xbdd5a000}, {0xbdd5c000}, {0xbdd5e000}, + {0xbdd60000}, {0xbdd62000}, {0xbdd64000}, {0xbdd66000}, + {0xbdd68000}, {0xbdd6a000}, {0xbdd6c000}, {0xbdd6e000}, + {0xbdd70000}, {0xbdd72000}, {0xbdd74000}, {0xbdd76000}, + {0xbdd78000}, {0xbdd7a000}, {0xbdd7c000}, {0xbdd7e000}, + {0xbdd80000}, {0xbdd82000}, {0xbdd84000}, {0xbdd86000}, + {0xbdd88000}, {0xbdd8a000}, {0xbdd8c000}, {0xbdd8e000}, + {0xbdd90000}, {0xbdd92000}, {0xbdd94000}, {0xbdd96000}, + {0xbdd98000}, {0xbdd9a000}, {0xbdd9c000}, {0xbdd9e000}, + {0xbdda0000}, {0xbdda2000}, {0xbdda4000}, {0xbdda6000}, + {0xbdda8000}, {0xbddaa000}, {0xbddac000}, {0xbddae000}, + {0xbddb0000}, {0xbddb2000}, {0xbddb4000}, {0xbddb6000}, + {0xbddb8000}, {0xbddba000}, {0xbddbc000}, {0xbddbe000}, + {0xbddc0000}, {0xbddc2000}, {0xbddc4000}, {0xbddc6000}, + {0xbddc8000}, {0xbddca000}, {0xbddcc000}, {0xbddce000}, + {0xbddd0000}, {0xbddd2000}, {0xbddd4000}, {0xbddd6000}, + {0xbddd8000}, {0xbddda000}, {0xbdddc000}, {0xbddde000}, + {0xbdde0000}, {0xbdde2000}, {0xbdde4000}, {0xbdde6000}, + {0xbdde8000}, {0xbddea000}, {0xbddec000}, {0xbddee000}, + {0xbddf0000}, {0xbddf2000}, {0xbddf4000}, {0xbddf6000}, + {0xbddf8000}, {0xbddfa000}, {0xbddfc000}, {0xbddfe000}, + {0xbde00000}, {0xbde02000}, {0xbde04000}, {0xbde06000}, + {0xbde08000}, {0xbde0a000}, {0xbde0c000}, {0xbde0e000}, + {0xbde10000}, {0xbde12000}, {0xbde14000}, {0xbde16000}, + {0xbde18000}, {0xbde1a000}, {0xbde1c000}, {0xbde1e000}, + {0xbde20000}, {0xbde22000}, {0xbde24000}, {0xbde26000}, + {0xbde28000}, {0xbde2a000}, {0xbde2c000}, {0xbde2e000}, + {0xbde30000}, {0xbde32000}, {0xbde34000}, {0xbde36000}, + {0xbde38000}, {0xbde3a000}, {0xbde3c000}, {0xbde3e000}, + {0xbde40000}, {0xbde42000}, {0xbde44000}, {0xbde46000}, + {0xbde48000}, {0xbde4a000}, {0xbde4c000}, {0xbde4e000}, + {0xbde50000}, {0xbde52000}, {0xbde54000}, {0xbde56000}, + {0xbde58000}, {0xbde5a000}, {0xbde5c000}, {0xbde5e000}, + {0xbde60000}, {0xbde62000}, {0xbde64000}, {0xbde66000}, + {0xbde68000}, {0xbde6a000}, {0xbde6c000}, {0xbde6e000}, + {0xbde70000}, {0xbde72000}, {0xbde74000}, {0xbde76000}, + {0xbde78000}, {0xbde7a000}, {0xbde7c000}, {0xbde7e000}, + {0xbde80000}, {0xbde82000}, {0xbde84000}, {0xbde86000}, + {0xbde88000}, {0xbde8a000}, {0xbde8c000}, {0xbde8e000}, + {0xbde90000}, {0xbde92000}, {0xbde94000}, {0xbde96000}, + {0xbde98000}, {0xbde9a000}, {0xbde9c000}, {0xbde9e000}, + {0xbdea0000}, {0xbdea2000}, {0xbdea4000}, {0xbdea6000}, + {0xbdea8000}, {0xbdeaa000}, {0xbdeac000}, {0xbdeae000}, + {0xbdeb0000}, {0xbdeb2000}, {0xbdeb4000}, {0xbdeb6000}, + {0xbdeb8000}, {0xbdeba000}, {0xbdebc000}, {0xbdebe000}, + {0xbdec0000}, {0xbdec2000}, {0xbdec4000}, {0xbdec6000}, + {0xbdec8000}, {0xbdeca000}, {0xbdecc000}, {0xbdece000}, + {0xbded0000}, {0xbded2000}, {0xbded4000}, {0xbded6000}, + {0xbded8000}, {0xbdeda000}, {0xbdedc000}, {0xbdede000}, + {0xbdee0000}, {0xbdee2000}, {0xbdee4000}, {0xbdee6000}, + {0xbdee8000}, {0xbdeea000}, {0xbdeec000}, {0xbdeee000}, + {0xbdef0000}, {0xbdef2000}, {0xbdef4000}, {0xbdef6000}, + {0xbdef8000}, {0xbdefa000}, {0xbdefc000}, {0xbdefe000}, + {0xbdf00000}, {0xbdf02000}, {0xbdf04000}, {0xbdf06000}, + {0xbdf08000}, {0xbdf0a000}, {0xbdf0c000}, {0xbdf0e000}, + {0xbdf10000}, {0xbdf12000}, {0xbdf14000}, {0xbdf16000}, + {0xbdf18000}, {0xbdf1a000}, {0xbdf1c000}, {0xbdf1e000}, + {0xbdf20000}, {0xbdf22000}, {0xbdf24000}, {0xbdf26000}, + {0xbdf28000}, {0xbdf2a000}, {0xbdf2c000}, {0xbdf2e000}, + {0xbdf30000}, {0xbdf32000}, {0xbdf34000}, {0xbdf36000}, + {0xbdf38000}, {0xbdf3a000}, {0xbdf3c000}, {0xbdf3e000}, + {0xbdf40000}, {0xbdf42000}, {0xbdf44000}, {0xbdf46000}, + {0xbdf48000}, {0xbdf4a000}, {0xbdf4c000}, {0xbdf4e000}, + {0xbdf50000}, {0xbdf52000}, {0xbdf54000}, {0xbdf56000}, + {0xbdf58000}, {0xbdf5a000}, {0xbdf5c000}, {0xbdf5e000}, + {0xbdf60000}, {0xbdf62000}, {0xbdf64000}, {0xbdf66000}, + {0xbdf68000}, {0xbdf6a000}, {0xbdf6c000}, {0xbdf6e000}, + {0xbdf70000}, {0xbdf72000}, {0xbdf74000}, {0xbdf76000}, + {0xbdf78000}, {0xbdf7a000}, {0xbdf7c000}, {0xbdf7e000}, + {0xbdf80000}, {0xbdf82000}, {0xbdf84000}, {0xbdf86000}, + {0xbdf88000}, {0xbdf8a000}, {0xbdf8c000}, {0xbdf8e000}, + {0xbdf90000}, {0xbdf92000}, {0xbdf94000}, {0xbdf96000}, + {0xbdf98000}, {0xbdf9a000}, {0xbdf9c000}, {0xbdf9e000}, + {0xbdfa0000}, {0xbdfa2000}, {0xbdfa4000}, {0xbdfa6000}, + {0xbdfa8000}, {0xbdfaa000}, {0xbdfac000}, {0xbdfae000}, + {0xbdfb0000}, {0xbdfb2000}, {0xbdfb4000}, {0xbdfb6000}, + {0xbdfb8000}, {0xbdfba000}, {0xbdfbc000}, {0xbdfbe000}, + {0xbdfc0000}, {0xbdfc2000}, {0xbdfc4000}, {0xbdfc6000}, + {0xbdfc8000}, {0xbdfca000}, {0xbdfcc000}, {0xbdfce000}, + {0xbdfd0000}, {0xbdfd2000}, {0xbdfd4000}, {0xbdfd6000}, + {0xbdfd8000}, {0xbdfda000}, {0xbdfdc000}, {0xbdfde000}, + {0xbdfe0000}, {0xbdfe2000}, {0xbdfe4000}, {0xbdfe6000}, + {0xbdfe8000}, {0xbdfea000}, {0xbdfec000}, {0xbdfee000}, + {0xbdff0000}, {0xbdff2000}, {0xbdff4000}, {0xbdff6000}, + {0xbdff8000}, {0xbdffa000}, {0xbdffc000}, {0xbdffe000}, + {0xbe000000}, {0xbe002000}, {0xbe004000}, {0xbe006000}, + {0xbe008000}, {0xbe00a000}, {0xbe00c000}, {0xbe00e000}, + {0xbe010000}, {0xbe012000}, {0xbe014000}, {0xbe016000}, + {0xbe018000}, {0xbe01a000}, {0xbe01c000}, {0xbe01e000}, + {0xbe020000}, {0xbe022000}, {0xbe024000}, {0xbe026000}, + {0xbe028000}, {0xbe02a000}, {0xbe02c000}, {0xbe02e000}, + {0xbe030000}, {0xbe032000}, {0xbe034000}, {0xbe036000}, + {0xbe038000}, {0xbe03a000}, {0xbe03c000}, {0xbe03e000}, + {0xbe040000}, {0xbe042000}, {0xbe044000}, {0xbe046000}, + {0xbe048000}, {0xbe04a000}, {0xbe04c000}, {0xbe04e000}, + {0xbe050000}, {0xbe052000}, {0xbe054000}, {0xbe056000}, + {0xbe058000}, {0xbe05a000}, {0xbe05c000}, {0xbe05e000}, + {0xbe060000}, {0xbe062000}, {0xbe064000}, {0xbe066000}, + {0xbe068000}, {0xbe06a000}, {0xbe06c000}, {0xbe06e000}, + {0xbe070000}, {0xbe072000}, {0xbe074000}, {0xbe076000}, + {0xbe078000}, {0xbe07a000}, {0xbe07c000}, {0xbe07e000}, + {0xbe080000}, {0xbe082000}, {0xbe084000}, {0xbe086000}, + {0xbe088000}, {0xbe08a000}, {0xbe08c000}, {0xbe08e000}, + {0xbe090000}, {0xbe092000}, {0xbe094000}, {0xbe096000}, + {0xbe098000}, {0xbe09a000}, {0xbe09c000}, {0xbe09e000}, + {0xbe0a0000}, {0xbe0a2000}, {0xbe0a4000}, {0xbe0a6000}, + {0xbe0a8000}, {0xbe0aa000}, {0xbe0ac000}, {0xbe0ae000}, + {0xbe0b0000}, {0xbe0b2000}, {0xbe0b4000}, {0xbe0b6000}, + {0xbe0b8000}, {0xbe0ba000}, {0xbe0bc000}, {0xbe0be000}, + {0xbe0c0000}, {0xbe0c2000}, {0xbe0c4000}, {0xbe0c6000}, + {0xbe0c8000}, {0xbe0ca000}, {0xbe0cc000}, {0xbe0ce000}, + {0xbe0d0000}, {0xbe0d2000}, {0xbe0d4000}, {0xbe0d6000}, + {0xbe0d8000}, {0xbe0da000}, {0xbe0dc000}, {0xbe0de000}, + {0xbe0e0000}, {0xbe0e2000}, {0xbe0e4000}, {0xbe0e6000}, + {0xbe0e8000}, {0xbe0ea000}, {0xbe0ec000}, {0xbe0ee000}, + {0xbe0f0000}, {0xbe0f2000}, {0xbe0f4000}, {0xbe0f6000}, + {0xbe0f8000}, {0xbe0fa000}, {0xbe0fc000}, {0xbe0fe000}, + {0xbe100000}, {0xbe102000}, {0xbe104000}, {0xbe106000}, + {0xbe108000}, {0xbe10a000}, {0xbe10c000}, {0xbe10e000}, + {0xbe110000}, {0xbe112000}, {0xbe114000}, {0xbe116000}, + {0xbe118000}, {0xbe11a000}, {0xbe11c000}, {0xbe11e000}, + {0xbe120000}, {0xbe122000}, {0xbe124000}, {0xbe126000}, + {0xbe128000}, {0xbe12a000}, {0xbe12c000}, {0xbe12e000}, + {0xbe130000}, {0xbe132000}, {0xbe134000}, {0xbe136000}, + {0xbe138000}, {0xbe13a000}, {0xbe13c000}, {0xbe13e000}, + {0xbe140000}, {0xbe142000}, {0xbe144000}, {0xbe146000}, + {0xbe148000}, {0xbe14a000}, {0xbe14c000}, {0xbe14e000}, + {0xbe150000}, {0xbe152000}, {0xbe154000}, {0xbe156000}, + {0xbe158000}, {0xbe15a000}, {0xbe15c000}, {0xbe15e000}, + {0xbe160000}, {0xbe162000}, {0xbe164000}, {0xbe166000}, + {0xbe168000}, {0xbe16a000}, {0xbe16c000}, {0xbe16e000}, + {0xbe170000}, {0xbe172000}, {0xbe174000}, {0xbe176000}, + {0xbe178000}, {0xbe17a000}, {0xbe17c000}, {0xbe17e000}, + {0xbe180000}, {0xbe182000}, {0xbe184000}, {0xbe186000}, + {0xbe188000}, {0xbe18a000}, {0xbe18c000}, {0xbe18e000}, + {0xbe190000}, {0xbe192000}, {0xbe194000}, {0xbe196000}, + {0xbe198000}, {0xbe19a000}, {0xbe19c000}, {0xbe19e000}, + {0xbe1a0000}, {0xbe1a2000}, {0xbe1a4000}, {0xbe1a6000}, + {0xbe1a8000}, {0xbe1aa000}, {0xbe1ac000}, {0xbe1ae000}, + {0xbe1b0000}, {0xbe1b2000}, {0xbe1b4000}, {0xbe1b6000}, + {0xbe1b8000}, {0xbe1ba000}, {0xbe1bc000}, {0xbe1be000}, + {0xbe1c0000}, {0xbe1c2000}, {0xbe1c4000}, {0xbe1c6000}, + {0xbe1c8000}, {0xbe1ca000}, {0xbe1cc000}, {0xbe1ce000}, + {0xbe1d0000}, {0xbe1d2000}, {0xbe1d4000}, {0xbe1d6000}, + {0xbe1d8000}, {0xbe1da000}, {0xbe1dc000}, {0xbe1de000}, + {0xbe1e0000}, {0xbe1e2000}, {0xbe1e4000}, {0xbe1e6000}, + {0xbe1e8000}, {0xbe1ea000}, {0xbe1ec000}, {0xbe1ee000}, + {0xbe1f0000}, {0xbe1f2000}, {0xbe1f4000}, {0xbe1f6000}, + {0xbe1f8000}, {0xbe1fa000}, {0xbe1fc000}, {0xbe1fe000}, + {0xbe200000}, {0xbe202000}, {0xbe204000}, {0xbe206000}, + {0xbe208000}, {0xbe20a000}, {0xbe20c000}, {0xbe20e000}, + {0xbe210000}, {0xbe212000}, {0xbe214000}, {0xbe216000}, + {0xbe218000}, {0xbe21a000}, {0xbe21c000}, {0xbe21e000}, + {0xbe220000}, {0xbe222000}, {0xbe224000}, {0xbe226000}, + {0xbe228000}, {0xbe22a000}, {0xbe22c000}, {0xbe22e000}, + {0xbe230000}, {0xbe232000}, {0xbe234000}, {0xbe236000}, + {0xbe238000}, {0xbe23a000}, {0xbe23c000}, {0xbe23e000}, + {0xbe240000}, {0xbe242000}, {0xbe244000}, {0xbe246000}, + {0xbe248000}, {0xbe24a000}, {0xbe24c000}, {0xbe24e000}, + {0xbe250000}, {0xbe252000}, {0xbe254000}, {0xbe256000}, + {0xbe258000}, {0xbe25a000}, {0xbe25c000}, {0xbe25e000}, + {0xbe260000}, {0xbe262000}, {0xbe264000}, {0xbe266000}, + {0xbe268000}, {0xbe26a000}, {0xbe26c000}, {0xbe26e000}, + {0xbe270000}, {0xbe272000}, {0xbe274000}, {0xbe276000}, + {0xbe278000}, {0xbe27a000}, {0xbe27c000}, {0xbe27e000}, + {0xbe280000}, {0xbe282000}, {0xbe284000}, {0xbe286000}, + {0xbe288000}, {0xbe28a000}, {0xbe28c000}, {0xbe28e000}, + {0xbe290000}, {0xbe292000}, {0xbe294000}, {0xbe296000}, + {0xbe298000}, {0xbe29a000}, {0xbe29c000}, {0xbe29e000}, + {0xbe2a0000}, {0xbe2a2000}, {0xbe2a4000}, {0xbe2a6000}, + {0xbe2a8000}, {0xbe2aa000}, {0xbe2ac000}, {0xbe2ae000}, + {0xbe2b0000}, {0xbe2b2000}, {0xbe2b4000}, {0xbe2b6000}, + {0xbe2b8000}, {0xbe2ba000}, {0xbe2bc000}, {0xbe2be000}, + {0xbe2c0000}, {0xbe2c2000}, {0xbe2c4000}, {0xbe2c6000}, + {0xbe2c8000}, {0xbe2ca000}, {0xbe2cc000}, {0xbe2ce000}, + {0xbe2d0000}, {0xbe2d2000}, {0xbe2d4000}, {0xbe2d6000}, + {0xbe2d8000}, {0xbe2da000}, {0xbe2dc000}, {0xbe2de000}, + {0xbe2e0000}, {0xbe2e2000}, {0xbe2e4000}, {0xbe2e6000}, + {0xbe2e8000}, {0xbe2ea000}, {0xbe2ec000}, {0xbe2ee000}, + {0xbe2f0000}, {0xbe2f2000}, {0xbe2f4000}, {0xbe2f6000}, + {0xbe2f8000}, {0xbe2fa000}, {0xbe2fc000}, {0xbe2fe000}, + {0xbe300000}, {0xbe302000}, {0xbe304000}, {0xbe306000}, + {0xbe308000}, {0xbe30a000}, {0xbe30c000}, {0xbe30e000}, + {0xbe310000}, {0xbe312000}, {0xbe314000}, {0xbe316000}, + {0xbe318000}, {0xbe31a000}, {0xbe31c000}, {0xbe31e000}, + {0xbe320000}, {0xbe322000}, {0xbe324000}, {0xbe326000}, + {0xbe328000}, {0xbe32a000}, {0xbe32c000}, {0xbe32e000}, + {0xbe330000}, {0xbe332000}, {0xbe334000}, {0xbe336000}, + {0xbe338000}, {0xbe33a000}, {0xbe33c000}, {0xbe33e000}, + {0xbe340000}, {0xbe342000}, {0xbe344000}, {0xbe346000}, + {0xbe348000}, {0xbe34a000}, {0xbe34c000}, {0xbe34e000}, + {0xbe350000}, {0xbe352000}, {0xbe354000}, {0xbe356000}, + {0xbe358000}, {0xbe35a000}, {0xbe35c000}, {0xbe35e000}, + {0xbe360000}, {0xbe362000}, {0xbe364000}, {0xbe366000}, + {0xbe368000}, {0xbe36a000}, {0xbe36c000}, {0xbe36e000}, + {0xbe370000}, {0xbe372000}, {0xbe374000}, {0xbe376000}, + {0xbe378000}, {0xbe37a000}, {0xbe37c000}, {0xbe37e000}, + {0xbe380000}, {0xbe382000}, {0xbe384000}, {0xbe386000}, + {0xbe388000}, {0xbe38a000}, {0xbe38c000}, {0xbe38e000}, + {0xbe390000}, {0xbe392000}, {0xbe394000}, {0xbe396000}, + {0xbe398000}, {0xbe39a000}, {0xbe39c000}, {0xbe39e000}, + {0xbe3a0000}, {0xbe3a2000}, {0xbe3a4000}, {0xbe3a6000}, + {0xbe3a8000}, {0xbe3aa000}, {0xbe3ac000}, {0xbe3ae000}, + {0xbe3b0000}, {0xbe3b2000}, {0xbe3b4000}, {0xbe3b6000}, + {0xbe3b8000}, {0xbe3ba000}, {0xbe3bc000}, {0xbe3be000}, + {0xbe3c0000}, {0xbe3c2000}, {0xbe3c4000}, {0xbe3c6000}, + {0xbe3c8000}, {0xbe3ca000}, {0xbe3cc000}, {0xbe3ce000}, + {0xbe3d0000}, {0xbe3d2000}, {0xbe3d4000}, {0xbe3d6000}, + {0xbe3d8000}, {0xbe3da000}, {0xbe3dc000}, {0xbe3de000}, + {0xbe3e0000}, {0xbe3e2000}, {0xbe3e4000}, {0xbe3e6000}, + {0xbe3e8000}, {0xbe3ea000}, {0xbe3ec000}, {0xbe3ee000}, + {0xbe3f0000}, {0xbe3f2000}, {0xbe3f4000}, {0xbe3f6000}, + {0xbe3f8000}, {0xbe3fa000}, {0xbe3fc000}, {0xbe3fe000}, + {0xbe400000}, {0xbe402000}, {0xbe404000}, {0xbe406000}, + {0xbe408000}, {0xbe40a000}, {0xbe40c000}, {0xbe40e000}, + {0xbe410000}, {0xbe412000}, {0xbe414000}, {0xbe416000}, + {0xbe418000}, {0xbe41a000}, {0xbe41c000}, {0xbe41e000}, + {0xbe420000}, {0xbe422000}, {0xbe424000}, {0xbe426000}, + {0xbe428000}, {0xbe42a000}, {0xbe42c000}, {0xbe42e000}, + {0xbe430000}, {0xbe432000}, {0xbe434000}, {0xbe436000}, + {0xbe438000}, {0xbe43a000}, {0xbe43c000}, {0xbe43e000}, + {0xbe440000}, {0xbe442000}, {0xbe444000}, {0xbe446000}, + {0xbe448000}, {0xbe44a000}, {0xbe44c000}, {0xbe44e000}, + {0xbe450000}, {0xbe452000}, {0xbe454000}, {0xbe456000}, + {0xbe458000}, {0xbe45a000}, {0xbe45c000}, {0xbe45e000}, + {0xbe460000}, {0xbe462000}, {0xbe464000}, {0xbe466000}, + {0xbe468000}, {0xbe46a000}, {0xbe46c000}, {0xbe46e000}, + {0xbe470000}, {0xbe472000}, {0xbe474000}, {0xbe476000}, + {0xbe478000}, {0xbe47a000}, {0xbe47c000}, {0xbe47e000}, + {0xbe480000}, {0xbe482000}, {0xbe484000}, {0xbe486000}, + {0xbe488000}, {0xbe48a000}, {0xbe48c000}, {0xbe48e000}, + {0xbe490000}, {0xbe492000}, {0xbe494000}, {0xbe496000}, + {0xbe498000}, {0xbe49a000}, {0xbe49c000}, {0xbe49e000}, + {0xbe4a0000}, {0xbe4a2000}, {0xbe4a4000}, {0xbe4a6000}, + {0xbe4a8000}, {0xbe4aa000}, {0xbe4ac000}, {0xbe4ae000}, + {0xbe4b0000}, {0xbe4b2000}, {0xbe4b4000}, {0xbe4b6000}, + {0xbe4b8000}, {0xbe4ba000}, {0xbe4bc000}, {0xbe4be000}, + {0xbe4c0000}, {0xbe4c2000}, {0xbe4c4000}, {0xbe4c6000}, + {0xbe4c8000}, {0xbe4ca000}, {0xbe4cc000}, {0xbe4ce000}, + {0xbe4d0000}, {0xbe4d2000}, {0xbe4d4000}, {0xbe4d6000}, + {0xbe4d8000}, {0xbe4da000}, {0xbe4dc000}, {0xbe4de000}, + {0xbe4e0000}, {0xbe4e2000}, {0xbe4e4000}, {0xbe4e6000}, + {0xbe4e8000}, {0xbe4ea000}, {0xbe4ec000}, {0xbe4ee000}, + {0xbe4f0000}, {0xbe4f2000}, {0xbe4f4000}, {0xbe4f6000}, + {0xbe4f8000}, {0xbe4fa000}, {0xbe4fc000}, {0xbe4fe000}, + {0xbe500000}, {0xbe502000}, {0xbe504000}, {0xbe506000}, + {0xbe508000}, {0xbe50a000}, {0xbe50c000}, {0xbe50e000}, + {0xbe510000}, {0xbe512000}, {0xbe514000}, {0xbe516000}, + {0xbe518000}, {0xbe51a000}, {0xbe51c000}, {0xbe51e000}, + {0xbe520000}, {0xbe522000}, {0xbe524000}, {0xbe526000}, + {0xbe528000}, {0xbe52a000}, {0xbe52c000}, {0xbe52e000}, + {0xbe530000}, {0xbe532000}, {0xbe534000}, {0xbe536000}, + {0xbe538000}, {0xbe53a000}, {0xbe53c000}, {0xbe53e000}, + {0xbe540000}, {0xbe542000}, {0xbe544000}, {0xbe546000}, + {0xbe548000}, {0xbe54a000}, {0xbe54c000}, {0xbe54e000}, + {0xbe550000}, {0xbe552000}, {0xbe554000}, {0xbe556000}, + {0xbe558000}, {0xbe55a000}, {0xbe55c000}, {0xbe55e000}, + {0xbe560000}, {0xbe562000}, {0xbe564000}, {0xbe566000}, + {0xbe568000}, {0xbe56a000}, {0xbe56c000}, {0xbe56e000}, + {0xbe570000}, {0xbe572000}, {0xbe574000}, {0xbe576000}, + {0xbe578000}, {0xbe57a000}, {0xbe57c000}, {0xbe57e000}, + {0xbe580000}, {0xbe582000}, {0xbe584000}, {0xbe586000}, + {0xbe588000}, {0xbe58a000}, {0xbe58c000}, {0xbe58e000}, + {0xbe590000}, {0xbe592000}, {0xbe594000}, {0xbe596000}, + {0xbe598000}, {0xbe59a000}, {0xbe59c000}, {0xbe59e000}, + {0xbe5a0000}, {0xbe5a2000}, {0xbe5a4000}, {0xbe5a6000}, + {0xbe5a8000}, {0xbe5aa000}, {0xbe5ac000}, {0xbe5ae000}, + {0xbe5b0000}, {0xbe5b2000}, {0xbe5b4000}, {0xbe5b6000}, + {0xbe5b8000}, {0xbe5ba000}, {0xbe5bc000}, {0xbe5be000}, + {0xbe5c0000}, {0xbe5c2000}, {0xbe5c4000}, {0xbe5c6000}, + {0xbe5c8000}, {0xbe5ca000}, {0xbe5cc000}, {0xbe5ce000}, + {0xbe5d0000}, {0xbe5d2000}, {0xbe5d4000}, {0xbe5d6000}, + {0xbe5d8000}, {0xbe5da000}, {0xbe5dc000}, {0xbe5de000}, + {0xbe5e0000}, {0xbe5e2000}, {0xbe5e4000}, {0xbe5e6000}, + {0xbe5e8000}, {0xbe5ea000}, {0xbe5ec000}, {0xbe5ee000}, + {0xbe5f0000}, {0xbe5f2000}, {0xbe5f4000}, {0xbe5f6000}, + {0xbe5f8000}, {0xbe5fa000}, {0xbe5fc000}, {0xbe5fe000}, + {0xbe600000}, {0xbe602000}, {0xbe604000}, {0xbe606000}, + {0xbe608000}, {0xbe60a000}, {0xbe60c000}, {0xbe60e000}, + {0xbe610000}, {0xbe612000}, {0xbe614000}, {0xbe616000}, + {0xbe618000}, {0xbe61a000}, {0xbe61c000}, {0xbe61e000}, + {0xbe620000}, {0xbe622000}, {0xbe624000}, {0xbe626000}, + {0xbe628000}, {0xbe62a000}, {0xbe62c000}, {0xbe62e000}, + {0xbe630000}, {0xbe632000}, {0xbe634000}, {0xbe636000}, + {0xbe638000}, {0xbe63a000}, {0xbe63c000}, {0xbe63e000}, + {0xbe640000}, {0xbe642000}, {0xbe644000}, {0xbe646000}, + {0xbe648000}, {0xbe64a000}, {0xbe64c000}, {0xbe64e000}, + {0xbe650000}, {0xbe652000}, {0xbe654000}, {0xbe656000}, + {0xbe658000}, {0xbe65a000}, {0xbe65c000}, {0xbe65e000}, + {0xbe660000}, {0xbe662000}, {0xbe664000}, {0xbe666000}, + {0xbe668000}, {0xbe66a000}, {0xbe66c000}, {0xbe66e000}, + {0xbe670000}, {0xbe672000}, {0xbe674000}, {0xbe676000}, + {0xbe678000}, {0xbe67a000}, {0xbe67c000}, {0xbe67e000}, + {0xbe680000}, {0xbe682000}, {0xbe684000}, {0xbe686000}, + {0xbe688000}, {0xbe68a000}, {0xbe68c000}, {0xbe68e000}, + {0xbe690000}, {0xbe692000}, {0xbe694000}, {0xbe696000}, + {0xbe698000}, {0xbe69a000}, {0xbe69c000}, {0xbe69e000}, + {0xbe6a0000}, {0xbe6a2000}, {0xbe6a4000}, {0xbe6a6000}, + {0xbe6a8000}, {0xbe6aa000}, {0xbe6ac000}, {0xbe6ae000}, + {0xbe6b0000}, {0xbe6b2000}, {0xbe6b4000}, {0xbe6b6000}, + {0xbe6b8000}, {0xbe6ba000}, {0xbe6bc000}, {0xbe6be000}, + {0xbe6c0000}, {0xbe6c2000}, {0xbe6c4000}, {0xbe6c6000}, + {0xbe6c8000}, {0xbe6ca000}, {0xbe6cc000}, {0xbe6ce000}, + {0xbe6d0000}, {0xbe6d2000}, {0xbe6d4000}, {0xbe6d6000}, + {0xbe6d8000}, {0xbe6da000}, {0xbe6dc000}, {0xbe6de000}, + {0xbe6e0000}, {0xbe6e2000}, {0xbe6e4000}, {0xbe6e6000}, + {0xbe6e8000}, {0xbe6ea000}, {0xbe6ec000}, {0xbe6ee000}, + {0xbe6f0000}, {0xbe6f2000}, {0xbe6f4000}, {0xbe6f6000}, + {0xbe6f8000}, {0xbe6fa000}, {0xbe6fc000}, {0xbe6fe000}, + {0xbe700000}, {0xbe702000}, {0xbe704000}, {0xbe706000}, + {0xbe708000}, {0xbe70a000}, {0xbe70c000}, {0xbe70e000}, + {0xbe710000}, {0xbe712000}, {0xbe714000}, {0xbe716000}, + {0xbe718000}, {0xbe71a000}, {0xbe71c000}, {0xbe71e000}, + {0xbe720000}, {0xbe722000}, {0xbe724000}, {0xbe726000}, + {0xbe728000}, {0xbe72a000}, {0xbe72c000}, {0xbe72e000}, + {0xbe730000}, {0xbe732000}, {0xbe734000}, {0xbe736000}, + {0xbe738000}, {0xbe73a000}, {0xbe73c000}, {0xbe73e000}, + {0xbe740000}, {0xbe742000}, {0xbe744000}, {0xbe746000}, + {0xbe748000}, {0xbe74a000}, {0xbe74c000}, {0xbe74e000}, + {0xbe750000}, {0xbe752000}, {0xbe754000}, {0xbe756000}, + {0xbe758000}, {0xbe75a000}, {0xbe75c000}, {0xbe75e000}, + {0xbe760000}, {0xbe762000}, {0xbe764000}, {0xbe766000}, + {0xbe768000}, {0xbe76a000}, {0xbe76c000}, {0xbe76e000}, + {0xbe770000}, {0xbe772000}, {0xbe774000}, {0xbe776000}, + {0xbe778000}, {0xbe77a000}, {0xbe77c000}, {0xbe77e000}, + {0xbe780000}, {0xbe782000}, {0xbe784000}, {0xbe786000}, + {0xbe788000}, {0xbe78a000}, {0xbe78c000}, {0xbe78e000}, + {0xbe790000}, {0xbe792000}, {0xbe794000}, {0xbe796000}, + {0xbe798000}, {0xbe79a000}, {0xbe79c000}, {0xbe79e000}, + {0xbe7a0000}, {0xbe7a2000}, {0xbe7a4000}, {0xbe7a6000}, + {0xbe7a8000}, {0xbe7aa000}, {0xbe7ac000}, {0xbe7ae000}, + {0xbe7b0000}, {0xbe7b2000}, {0xbe7b4000}, {0xbe7b6000}, + {0xbe7b8000}, {0xbe7ba000}, {0xbe7bc000}, {0xbe7be000}, + {0xbe7c0000}, {0xbe7c2000}, {0xbe7c4000}, {0xbe7c6000}, + {0xbe7c8000}, {0xbe7ca000}, {0xbe7cc000}, {0xbe7ce000}, + {0xbe7d0000}, {0xbe7d2000}, {0xbe7d4000}, {0xbe7d6000}, + {0xbe7d8000}, {0xbe7da000}, {0xbe7dc000}, {0xbe7de000}, + {0xbe7e0000}, {0xbe7e2000}, {0xbe7e4000}, {0xbe7e6000}, + {0xbe7e8000}, {0xbe7ea000}, {0xbe7ec000}, {0xbe7ee000}, + {0xbe7f0000}, {0xbe7f2000}, {0xbe7f4000}, {0xbe7f6000}, + {0xbe7f8000}, {0xbe7fa000}, {0xbe7fc000}, {0xbe7fe000}, + {0xbe800000}, {0xbe802000}, {0xbe804000}, {0xbe806000}, + {0xbe808000}, {0xbe80a000}, {0xbe80c000}, {0xbe80e000}, + {0xbe810000}, {0xbe812000}, {0xbe814000}, {0xbe816000}, + {0xbe818000}, {0xbe81a000}, {0xbe81c000}, {0xbe81e000}, + {0xbe820000}, {0xbe822000}, {0xbe824000}, {0xbe826000}, + {0xbe828000}, {0xbe82a000}, {0xbe82c000}, {0xbe82e000}, + {0xbe830000}, {0xbe832000}, {0xbe834000}, {0xbe836000}, + {0xbe838000}, {0xbe83a000}, {0xbe83c000}, {0xbe83e000}, + {0xbe840000}, {0xbe842000}, {0xbe844000}, {0xbe846000}, + {0xbe848000}, {0xbe84a000}, {0xbe84c000}, {0xbe84e000}, + {0xbe850000}, {0xbe852000}, {0xbe854000}, {0xbe856000}, + {0xbe858000}, {0xbe85a000}, {0xbe85c000}, {0xbe85e000}, + {0xbe860000}, {0xbe862000}, {0xbe864000}, {0xbe866000}, + {0xbe868000}, {0xbe86a000}, {0xbe86c000}, {0xbe86e000}, + {0xbe870000}, {0xbe872000}, {0xbe874000}, {0xbe876000}, + {0xbe878000}, {0xbe87a000}, {0xbe87c000}, {0xbe87e000}, + {0xbe880000}, {0xbe882000}, {0xbe884000}, {0xbe886000}, + {0xbe888000}, {0xbe88a000}, {0xbe88c000}, {0xbe88e000}, + {0xbe890000}, {0xbe892000}, {0xbe894000}, {0xbe896000}, + {0xbe898000}, {0xbe89a000}, {0xbe89c000}, {0xbe89e000}, + {0xbe8a0000}, {0xbe8a2000}, {0xbe8a4000}, {0xbe8a6000}, + {0xbe8a8000}, {0xbe8aa000}, {0xbe8ac000}, {0xbe8ae000}, + {0xbe8b0000}, {0xbe8b2000}, {0xbe8b4000}, {0xbe8b6000}, + {0xbe8b8000}, {0xbe8ba000}, {0xbe8bc000}, {0xbe8be000}, + {0xbe8c0000}, {0xbe8c2000}, {0xbe8c4000}, {0xbe8c6000}, + {0xbe8c8000}, {0xbe8ca000}, {0xbe8cc000}, {0xbe8ce000}, + {0xbe8d0000}, {0xbe8d2000}, {0xbe8d4000}, {0xbe8d6000}, + {0xbe8d8000}, {0xbe8da000}, {0xbe8dc000}, {0xbe8de000}, + {0xbe8e0000}, {0xbe8e2000}, {0xbe8e4000}, {0xbe8e6000}, + {0xbe8e8000}, {0xbe8ea000}, {0xbe8ec000}, {0xbe8ee000}, + {0xbe8f0000}, {0xbe8f2000}, {0xbe8f4000}, {0xbe8f6000}, + {0xbe8f8000}, {0xbe8fa000}, {0xbe8fc000}, {0xbe8fe000}, + {0xbe900000}, {0xbe902000}, {0xbe904000}, {0xbe906000}, + {0xbe908000}, {0xbe90a000}, {0xbe90c000}, {0xbe90e000}, + {0xbe910000}, {0xbe912000}, {0xbe914000}, {0xbe916000}, + {0xbe918000}, {0xbe91a000}, {0xbe91c000}, {0xbe91e000}, + {0xbe920000}, {0xbe922000}, {0xbe924000}, {0xbe926000}, + {0xbe928000}, {0xbe92a000}, {0xbe92c000}, {0xbe92e000}, + {0xbe930000}, {0xbe932000}, {0xbe934000}, {0xbe936000}, + {0xbe938000}, {0xbe93a000}, {0xbe93c000}, {0xbe93e000}, + {0xbe940000}, {0xbe942000}, {0xbe944000}, {0xbe946000}, + {0xbe948000}, {0xbe94a000}, {0xbe94c000}, {0xbe94e000}, + {0xbe950000}, {0xbe952000}, {0xbe954000}, {0xbe956000}, + {0xbe958000}, {0xbe95a000}, {0xbe95c000}, {0xbe95e000}, + {0xbe960000}, {0xbe962000}, {0xbe964000}, {0xbe966000}, + {0xbe968000}, {0xbe96a000}, {0xbe96c000}, {0xbe96e000}, + {0xbe970000}, {0xbe972000}, {0xbe974000}, {0xbe976000}, + {0xbe978000}, {0xbe97a000}, {0xbe97c000}, {0xbe97e000}, + {0xbe980000}, {0xbe982000}, {0xbe984000}, {0xbe986000}, + {0xbe988000}, {0xbe98a000}, {0xbe98c000}, {0xbe98e000}, + {0xbe990000}, {0xbe992000}, {0xbe994000}, {0xbe996000}, + {0xbe998000}, {0xbe99a000}, {0xbe99c000}, {0xbe99e000}, + {0xbe9a0000}, {0xbe9a2000}, {0xbe9a4000}, {0xbe9a6000}, + {0xbe9a8000}, {0xbe9aa000}, {0xbe9ac000}, {0xbe9ae000}, + {0xbe9b0000}, {0xbe9b2000}, {0xbe9b4000}, {0xbe9b6000}, + {0xbe9b8000}, {0xbe9ba000}, {0xbe9bc000}, {0xbe9be000}, + {0xbe9c0000}, {0xbe9c2000}, {0xbe9c4000}, {0xbe9c6000}, + {0xbe9c8000}, {0xbe9ca000}, {0xbe9cc000}, {0xbe9ce000}, + {0xbe9d0000}, {0xbe9d2000}, {0xbe9d4000}, {0xbe9d6000}, + {0xbe9d8000}, {0xbe9da000}, {0xbe9dc000}, {0xbe9de000}, + {0xbe9e0000}, {0xbe9e2000}, {0xbe9e4000}, {0xbe9e6000}, + {0xbe9e8000}, {0xbe9ea000}, {0xbe9ec000}, {0xbe9ee000}, + {0xbe9f0000}, {0xbe9f2000}, {0xbe9f4000}, {0xbe9f6000}, + {0xbe9f8000}, {0xbe9fa000}, {0xbe9fc000}, {0xbe9fe000}, + {0xbea00000}, {0xbea02000}, {0xbea04000}, {0xbea06000}, + {0xbea08000}, {0xbea0a000}, {0xbea0c000}, {0xbea0e000}, + {0xbea10000}, {0xbea12000}, {0xbea14000}, {0xbea16000}, + {0xbea18000}, {0xbea1a000}, {0xbea1c000}, {0xbea1e000}, + {0xbea20000}, {0xbea22000}, {0xbea24000}, {0xbea26000}, + {0xbea28000}, {0xbea2a000}, {0xbea2c000}, {0xbea2e000}, + {0xbea30000}, {0xbea32000}, {0xbea34000}, {0xbea36000}, + {0xbea38000}, {0xbea3a000}, {0xbea3c000}, {0xbea3e000}, + {0xbea40000}, {0xbea42000}, {0xbea44000}, {0xbea46000}, + {0xbea48000}, {0xbea4a000}, {0xbea4c000}, {0xbea4e000}, + {0xbea50000}, {0xbea52000}, {0xbea54000}, {0xbea56000}, + {0xbea58000}, {0xbea5a000}, {0xbea5c000}, {0xbea5e000}, + {0xbea60000}, {0xbea62000}, {0xbea64000}, {0xbea66000}, + {0xbea68000}, {0xbea6a000}, {0xbea6c000}, {0xbea6e000}, + {0xbea70000}, {0xbea72000}, {0xbea74000}, {0xbea76000}, + {0xbea78000}, {0xbea7a000}, {0xbea7c000}, {0xbea7e000}, + {0xbea80000}, {0xbea82000}, {0xbea84000}, {0xbea86000}, + {0xbea88000}, {0xbea8a000}, {0xbea8c000}, {0xbea8e000}, + {0xbea90000}, {0xbea92000}, {0xbea94000}, {0xbea96000}, + {0xbea98000}, {0xbea9a000}, {0xbea9c000}, {0xbea9e000}, + {0xbeaa0000}, {0xbeaa2000}, {0xbeaa4000}, {0xbeaa6000}, + {0xbeaa8000}, {0xbeaaa000}, {0xbeaac000}, {0xbeaae000}, + {0xbeab0000}, {0xbeab2000}, {0xbeab4000}, {0xbeab6000}, + {0xbeab8000}, {0xbeaba000}, {0xbeabc000}, {0xbeabe000}, + {0xbeac0000}, {0xbeac2000}, {0xbeac4000}, {0xbeac6000}, + {0xbeac8000}, {0xbeaca000}, {0xbeacc000}, {0xbeace000}, + {0xbead0000}, {0xbead2000}, {0xbead4000}, {0xbead6000}, + {0xbead8000}, {0xbeada000}, {0xbeadc000}, {0xbeade000}, + {0xbeae0000}, {0xbeae2000}, {0xbeae4000}, {0xbeae6000}, + {0xbeae8000}, {0xbeaea000}, {0xbeaec000}, {0xbeaee000}, + {0xbeaf0000}, {0xbeaf2000}, {0xbeaf4000}, {0xbeaf6000}, + {0xbeaf8000}, {0xbeafa000}, {0xbeafc000}, {0xbeafe000}, + {0xbeb00000}, {0xbeb02000}, {0xbeb04000}, {0xbeb06000}, + {0xbeb08000}, {0xbeb0a000}, {0xbeb0c000}, {0xbeb0e000}, + {0xbeb10000}, {0xbeb12000}, {0xbeb14000}, {0xbeb16000}, + {0xbeb18000}, {0xbeb1a000}, {0xbeb1c000}, {0xbeb1e000}, + {0xbeb20000}, {0xbeb22000}, {0xbeb24000}, {0xbeb26000}, + {0xbeb28000}, {0xbeb2a000}, {0xbeb2c000}, {0xbeb2e000}, + {0xbeb30000}, {0xbeb32000}, {0xbeb34000}, {0xbeb36000}, + {0xbeb38000}, {0xbeb3a000}, {0xbeb3c000}, {0xbeb3e000}, + {0xbeb40000}, {0xbeb42000}, {0xbeb44000}, {0xbeb46000}, + {0xbeb48000}, {0xbeb4a000}, {0xbeb4c000}, {0xbeb4e000}, + {0xbeb50000}, {0xbeb52000}, {0xbeb54000}, {0xbeb56000}, + {0xbeb58000}, {0xbeb5a000}, {0xbeb5c000}, {0xbeb5e000}, + {0xbeb60000}, {0xbeb62000}, {0xbeb64000}, {0xbeb66000}, + {0xbeb68000}, {0xbeb6a000}, {0xbeb6c000}, {0xbeb6e000}, + {0xbeb70000}, {0xbeb72000}, {0xbeb74000}, {0xbeb76000}, + {0xbeb78000}, {0xbeb7a000}, {0xbeb7c000}, {0xbeb7e000}, + {0xbeb80000}, {0xbeb82000}, {0xbeb84000}, {0xbeb86000}, + {0xbeb88000}, {0xbeb8a000}, {0xbeb8c000}, {0xbeb8e000}, + {0xbeb90000}, {0xbeb92000}, {0xbeb94000}, {0xbeb96000}, + {0xbeb98000}, {0xbeb9a000}, {0xbeb9c000}, {0xbeb9e000}, + {0xbeba0000}, {0xbeba2000}, {0xbeba4000}, {0xbeba6000}, + {0xbeba8000}, {0xbebaa000}, {0xbebac000}, {0xbebae000}, + {0xbebb0000}, {0xbebb2000}, {0xbebb4000}, {0xbebb6000}, + {0xbebb8000}, {0xbebba000}, {0xbebbc000}, {0xbebbe000}, + {0xbebc0000}, {0xbebc2000}, {0xbebc4000}, {0xbebc6000}, + {0xbebc8000}, {0xbebca000}, {0xbebcc000}, {0xbebce000}, + {0xbebd0000}, {0xbebd2000}, {0xbebd4000}, {0xbebd6000}, + {0xbebd8000}, {0xbebda000}, {0xbebdc000}, {0xbebde000}, + {0xbebe0000}, {0xbebe2000}, {0xbebe4000}, {0xbebe6000}, + {0xbebe8000}, {0xbebea000}, {0xbebec000}, {0xbebee000}, + {0xbebf0000}, {0xbebf2000}, {0xbebf4000}, {0xbebf6000}, + {0xbebf8000}, {0xbebfa000}, {0xbebfc000}, {0xbebfe000}, + {0xbec00000}, {0xbec02000}, {0xbec04000}, {0xbec06000}, + {0xbec08000}, {0xbec0a000}, {0xbec0c000}, {0xbec0e000}, + {0xbec10000}, {0xbec12000}, {0xbec14000}, {0xbec16000}, + {0xbec18000}, {0xbec1a000}, {0xbec1c000}, {0xbec1e000}, + {0xbec20000}, {0xbec22000}, {0xbec24000}, {0xbec26000}, + {0xbec28000}, {0xbec2a000}, {0xbec2c000}, {0xbec2e000}, + {0xbec30000}, {0xbec32000}, {0xbec34000}, {0xbec36000}, + {0xbec38000}, {0xbec3a000}, {0xbec3c000}, {0xbec3e000}, + {0xbec40000}, {0xbec42000}, {0xbec44000}, {0xbec46000}, + {0xbec48000}, {0xbec4a000}, {0xbec4c000}, {0xbec4e000}, + {0xbec50000}, {0xbec52000}, {0xbec54000}, {0xbec56000}, + {0xbec58000}, {0xbec5a000}, {0xbec5c000}, {0xbec5e000}, + {0xbec60000}, {0xbec62000}, {0xbec64000}, {0xbec66000}, + {0xbec68000}, {0xbec6a000}, {0xbec6c000}, {0xbec6e000}, + {0xbec70000}, {0xbec72000}, {0xbec74000}, {0xbec76000}, + {0xbec78000}, {0xbec7a000}, {0xbec7c000}, {0xbec7e000}, + {0xbec80000}, {0xbec82000}, {0xbec84000}, {0xbec86000}, + {0xbec88000}, {0xbec8a000}, {0xbec8c000}, {0xbec8e000}, + {0xbec90000}, {0xbec92000}, {0xbec94000}, {0xbec96000}, + {0xbec98000}, {0xbec9a000}, {0xbec9c000}, {0xbec9e000}, + {0xbeca0000}, {0xbeca2000}, {0xbeca4000}, {0xbeca6000}, + {0xbeca8000}, {0xbecaa000}, {0xbecac000}, {0xbecae000}, + {0xbecb0000}, {0xbecb2000}, {0xbecb4000}, {0xbecb6000}, + {0xbecb8000}, {0xbecba000}, {0xbecbc000}, {0xbecbe000}, + {0xbecc0000}, {0xbecc2000}, {0xbecc4000}, {0xbecc6000}, + {0xbecc8000}, {0xbecca000}, {0xbeccc000}, {0xbecce000}, + {0xbecd0000}, {0xbecd2000}, {0xbecd4000}, {0xbecd6000}, + {0xbecd8000}, {0xbecda000}, {0xbecdc000}, {0xbecde000}, + {0xbece0000}, {0xbece2000}, {0xbece4000}, {0xbece6000}, + {0xbece8000}, {0xbecea000}, {0xbecec000}, {0xbecee000}, + {0xbecf0000}, {0xbecf2000}, {0xbecf4000}, {0xbecf6000}, + {0xbecf8000}, {0xbecfa000}, {0xbecfc000}, {0xbecfe000}, + {0xbed00000}, {0xbed02000}, {0xbed04000}, {0xbed06000}, + {0xbed08000}, {0xbed0a000}, {0xbed0c000}, {0xbed0e000}, + {0xbed10000}, {0xbed12000}, {0xbed14000}, {0xbed16000}, + {0xbed18000}, {0xbed1a000}, {0xbed1c000}, {0xbed1e000}, + {0xbed20000}, {0xbed22000}, {0xbed24000}, {0xbed26000}, + {0xbed28000}, {0xbed2a000}, {0xbed2c000}, {0xbed2e000}, + {0xbed30000}, {0xbed32000}, {0xbed34000}, {0xbed36000}, + {0xbed38000}, {0xbed3a000}, {0xbed3c000}, {0xbed3e000}, + {0xbed40000}, {0xbed42000}, {0xbed44000}, {0xbed46000}, + {0xbed48000}, {0xbed4a000}, {0xbed4c000}, {0xbed4e000}, + {0xbed50000}, {0xbed52000}, {0xbed54000}, {0xbed56000}, + {0xbed58000}, {0xbed5a000}, {0xbed5c000}, {0xbed5e000}, + {0xbed60000}, {0xbed62000}, {0xbed64000}, {0xbed66000}, + {0xbed68000}, {0xbed6a000}, {0xbed6c000}, {0xbed6e000}, + {0xbed70000}, {0xbed72000}, {0xbed74000}, {0xbed76000}, + {0xbed78000}, {0xbed7a000}, {0xbed7c000}, {0xbed7e000}, + {0xbed80000}, {0xbed82000}, {0xbed84000}, {0xbed86000}, + {0xbed88000}, {0xbed8a000}, {0xbed8c000}, {0xbed8e000}, + {0xbed90000}, {0xbed92000}, {0xbed94000}, {0xbed96000}, + {0xbed98000}, {0xbed9a000}, {0xbed9c000}, {0xbed9e000}, + {0xbeda0000}, {0xbeda2000}, {0xbeda4000}, {0xbeda6000}, + {0xbeda8000}, {0xbedaa000}, {0xbedac000}, {0xbedae000}, + {0xbedb0000}, {0xbedb2000}, {0xbedb4000}, {0xbedb6000}, + {0xbedb8000}, {0xbedba000}, {0xbedbc000}, {0xbedbe000}, + {0xbedc0000}, {0xbedc2000}, {0xbedc4000}, {0xbedc6000}, + {0xbedc8000}, {0xbedca000}, {0xbedcc000}, {0xbedce000}, + {0xbedd0000}, {0xbedd2000}, {0xbedd4000}, {0xbedd6000}, + {0xbedd8000}, {0xbedda000}, {0xbeddc000}, {0xbedde000}, + {0xbede0000}, {0xbede2000}, {0xbede4000}, {0xbede6000}, + {0xbede8000}, {0xbedea000}, {0xbedec000}, {0xbedee000}, + {0xbedf0000}, {0xbedf2000}, {0xbedf4000}, {0xbedf6000}, + {0xbedf8000}, {0xbedfa000}, {0xbedfc000}, {0xbedfe000}, + {0xbee00000}, {0xbee02000}, {0xbee04000}, {0xbee06000}, + {0xbee08000}, {0xbee0a000}, {0xbee0c000}, {0xbee0e000}, + {0xbee10000}, {0xbee12000}, {0xbee14000}, {0xbee16000}, + {0xbee18000}, {0xbee1a000}, {0xbee1c000}, {0xbee1e000}, + {0xbee20000}, {0xbee22000}, {0xbee24000}, {0xbee26000}, + {0xbee28000}, {0xbee2a000}, {0xbee2c000}, {0xbee2e000}, + {0xbee30000}, {0xbee32000}, {0xbee34000}, {0xbee36000}, + {0xbee38000}, {0xbee3a000}, {0xbee3c000}, {0xbee3e000}, + {0xbee40000}, {0xbee42000}, {0xbee44000}, {0xbee46000}, + {0xbee48000}, {0xbee4a000}, {0xbee4c000}, {0xbee4e000}, + {0xbee50000}, {0xbee52000}, {0xbee54000}, {0xbee56000}, + {0xbee58000}, {0xbee5a000}, {0xbee5c000}, {0xbee5e000}, + {0xbee60000}, {0xbee62000}, {0xbee64000}, {0xbee66000}, + {0xbee68000}, {0xbee6a000}, {0xbee6c000}, {0xbee6e000}, + {0xbee70000}, {0xbee72000}, {0xbee74000}, {0xbee76000}, + {0xbee78000}, {0xbee7a000}, {0xbee7c000}, {0xbee7e000}, + {0xbee80000}, {0xbee82000}, {0xbee84000}, {0xbee86000}, + {0xbee88000}, {0xbee8a000}, {0xbee8c000}, {0xbee8e000}, + {0xbee90000}, {0xbee92000}, {0xbee94000}, {0xbee96000}, + {0xbee98000}, {0xbee9a000}, {0xbee9c000}, {0xbee9e000}, + {0xbeea0000}, {0xbeea2000}, {0xbeea4000}, {0xbeea6000}, + {0xbeea8000}, {0xbeeaa000}, {0xbeeac000}, {0xbeeae000}, + {0xbeeb0000}, {0xbeeb2000}, {0xbeeb4000}, {0xbeeb6000}, + {0xbeeb8000}, {0xbeeba000}, {0xbeebc000}, {0xbeebe000}, + {0xbeec0000}, {0xbeec2000}, {0xbeec4000}, {0xbeec6000}, + {0xbeec8000}, {0xbeeca000}, {0xbeecc000}, {0xbeece000}, + {0xbeed0000}, {0xbeed2000}, {0xbeed4000}, {0xbeed6000}, + {0xbeed8000}, {0xbeeda000}, {0xbeedc000}, {0xbeede000}, + {0xbeee0000}, {0xbeee2000}, {0xbeee4000}, {0xbeee6000}, + {0xbeee8000}, {0xbeeea000}, {0xbeeec000}, {0xbeeee000}, + {0xbeef0000}, {0xbeef2000}, {0xbeef4000}, {0xbeef6000}, + {0xbeef8000}, {0xbeefa000}, {0xbeefc000}, {0xbeefe000}, + {0xbef00000}, {0xbef02000}, {0xbef04000}, {0xbef06000}, + {0xbef08000}, {0xbef0a000}, {0xbef0c000}, {0xbef0e000}, + {0xbef10000}, {0xbef12000}, {0xbef14000}, {0xbef16000}, + {0xbef18000}, {0xbef1a000}, {0xbef1c000}, {0xbef1e000}, + {0xbef20000}, {0xbef22000}, {0xbef24000}, {0xbef26000}, + {0xbef28000}, {0xbef2a000}, {0xbef2c000}, {0xbef2e000}, + {0xbef30000}, {0xbef32000}, {0xbef34000}, {0xbef36000}, + {0xbef38000}, {0xbef3a000}, {0xbef3c000}, {0xbef3e000}, + {0xbef40000}, {0xbef42000}, {0xbef44000}, {0xbef46000}, + {0xbef48000}, {0xbef4a000}, {0xbef4c000}, {0xbef4e000}, + {0xbef50000}, {0xbef52000}, {0xbef54000}, {0xbef56000}, + {0xbef58000}, {0xbef5a000}, {0xbef5c000}, {0xbef5e000}, + {0xbef60000}, {0xbef62000}, {0xbef64000}, {0xbef66000}, + {0xbef68000}, {0xbef6a000}, {0xbef6c000}, {0xbef6e000}, + {0xbef70000}, {0xbef72000}, {0xbef74000}, {0xbef76000}, + {0xbef78000}, {0xbef7a000}, {0xbef7c000}, {0xbef7e000}, + {0xbef80000}, {0xbef82000}, {0xbef84000}, {0xbef86000}, + {0xbef88000}, {0xbef8a000}, {0xbef8c000}, {0xbef8e000}, + {0xbef90000}, {0xbef92000}, {0xbef94000}, {0xbef96000}, + {0xbef98000}, {0xbef9a000}, {0xbef9c000}, {0xbef9e000}, + {0xbefa0000}, {0xbefa2000}, {0xbefa4000}, {0xbefa6000}, + {0xbefa8000}, {0xbefaa000}, {0xbefac000}, {0xbefae000}, + {0xbefb0000}, {0xbefb2000}, {0xbefb4000}, {0xbefb6000}, + {0xbefb8000}, {0xbefba000}, {0xbefbc000}, {0xbefbe000}, + {0xbefc0000}, {0xbefc2000}, {0xbefc4000}, {0xbefc6000}, + {0xbefc8000}, {0xbefca000}, {0xbefcc000}, {0xbefce000}, + {0xbefd0000}, {0xbefd2000}, {0xbefd4000}, {0xbefd6000}, + {0xbefd8000}, {0xbefda000}, {0xbefdc000}, {0xbefde000}, + {0xbefe0000}, {0xbefe2000}, {0xbefe4000}, {0xbefe6000}, + {0xbefe8000}, {0xbefea000}, {0xbefec000}, {0xbefee000}, + {0xbeff0000}, {0xbeff2000}, {0xbeff4000}, {0xbeff6000}, + {0xbeff8000}, {0xbeffa000}, {0xbeffc000}, {0xbeffe000}, + {0xbf000000}, {0xbf002000}, {0xbf004000}, {0xbf006000}, + {0xbf008000}, {0xbf00a000}, {0xbf00c000}, {0xbf00e000}, + {0xbf010000}, {0xbf012000}, {0xbf014000}, {0xbf016000}, + {0xbf018000}, {0xbf01a000}, {0xbf01c000}, {0xbf01e000}, + {0xbf020000}, {0xbf022000}, {0xbf024000}, {0xbf026000}, + {0xbf028000}, {0xbf02a000}, {0xbf02c000}, {0xbf02e000}, + {0xbf030000}, {0xbf032000}, {0xbf034000}, {0xbf036000}, + {0xbf038000}, {0xbf03a000}, {0xbf03c000}, {0xbf03e000}, + {0xbf040000}, {0xbf042000}, {0xbf044000}, {0xbf046000}, + {0xbf048000}, {0xbf04a000}, {0xbf04c000}, {0xbf04e000}, + {0xbf050000}, {0xbf052000}, {0xbf054000}, {0xbf056000}, + {0xbf058000}, {0xbf05a000}, {0xbf05c000}, {0xbf05e000}, + {0xbf060000}, {0xbf062000}, {0xbf064000}, {0xbf066000}, + {0xbf068000}, {0xbf06a000}, {0xbf06c000}, {0xbf06e000}, + {0xbf070000}, {0xbf072000}, {0xbf074000}, {0xbf076000}, + {0xbf078000}, {0xbf07a000}, {0xbf07c000}, {0xbf07e000}, + {0xbf080000}, {0xbf082000}, {0xbf084000}, {0xbf086000}, + {0xbf088000}, {0xbf08a000}, {0xbf08c000}, {0xbf08e000}, + {0xbf090000}, {0xbf092000}, {0xbf094000}, {0xbf096000}, + {0xbf098000}, {0xbf09a000}, {0xbf09c000}, {0xbf09e000}, + {0xbf0a0000}, {0xbf0a2000}, {0xbf0a4000}, {0xbf0a6000}, + {0xbf0a8000}, {0xbf0aa000}, {0xbf0ac000}, {0xbf0ae000}, + {0xbf0b0000}, {0xbf0b2000}, {0xbf0b4000}, {0xbf0b6000}, + {0xbf0b8000}, {0xbf0ba000}, {0xbf0bc000}, {0xbf0be000}, + {0xbf0c0000}, {0xbf0c2000}, {0xbf0c4000}, {0xbf0c6000}, + {0xbf0c8000}, {0xbf0ca000}, {0xbf0cc000}, {0xbf0ce000}, + {0xbf0d0000}, {0xbf0d2000}, {0xbf0d4000}, {0xbf0d6000}, + {0xbf0d8000}, {0xbf0da000}, {0xbf0dc000}, {0xbf0de000}, + {0xbf0e0000}, {0xbf0e2000}, {0xbf0e4000}, {0xbf0e6000}, + {0xbf0e8000}, {0xbf0ea000}, {0xbf0ec000}, {0xbf0ee000}, + {0xbf0f0000}, {0xbf0f2000}, {0xbf0f4000}, {0xbf0f6000}, + {0xbf0f8000}, {0xbf0fa000}, {0xbf0fc000}, {0xbf0fe000}, + {0xbf100000}, {0xbf102000}, {0xbf104000}, {0xbf106000}, + {0xbf108000}, {0xbf10a000}, {0xbf10c000}, {0xbf10e000}, + {0xbf110000}, {0xbf112000}, {0xbf114000}, {0xbf116000}, + {0xbf118000}, {0xbf11a000}, {0xbf11c000}, {0xbf11e000}, + {0xbf120000}, {0xbf122000}, {0xbf124000}, {0xbf126000}, + {0xbf128000}, {0xbf12a000}, {0xbf12c000}, {0xbf12e000}, + {0xbf130000}, {0xbf132000}, {0xbf134000}, {0xbf136000}, + {0xbf138000}, {0xbf13a000}, {0xbf13c000}, {0xbf13e000}, + {0xbf140000}, {0xbf142000}, {0xbf144000}, {0xbf146000}, + {0xbf148000}, {0xbf14a000}, {0xbf14c000}, {0xbf14e000}, + {0xbf150000}, {0xbf152000}, {0xbf154000}, {0xbf156000}, + {0xbf158000}, {0xbf15a000}, {0xbf15c000}, {0xbf15e000}, + {0xbf160000}, {0xbf162000}, {0xbf164000}, {0xbf166000}, + {0xbf168000}, {0xbf16a000}, {0xbf16c000}, {0xbf16e000}, + {0xbf170000}, {0xbf172000}, {0xbf174000}, {0xbf176000}, + {0xbf178000}, {0xbf17a000}, {0xbf17c000}, {0xbf17e000}, + {0xbf180000}, {0xbf182000}, {0xbf184000}, {0xbf186000}, + {0xbf188000}, {0xbf18a000}, {0xbf18c000}, {0xbf18e000}, + {0xbf190000}, {0xbf192000}, {0xbf194000}, {0xbf196000}, + {0xbf198000}, {0xbf19a000}, {0xbf19c000}, {0xbf19e000}, + {0xbf1a0000}, {0xbf1a2000}, {0xbf1a4000}, {0xbf1a6000}, + {0xbf1a8000}, {0xbf1aa000}, {0xbf1ac000}, {0xbf1ae000}, + {0xbf1b0000}, {0xbf1b2000}, {0xbf1b4000}, {0xbf1b6000}, + {0xbf1b8000}, {0xbf1ba000}, {0xbf1bc000}, {0xbf1be000}, + {0xbf1c0000}, {0xbf1c2000}, {0xbf1c4000}, {0xbf1c6000}, + {0xbf1c8000}, {0xbf1ca000}, {0xbf1cc000}, {0xbf1ce000}, + {0xbf1d0000}, {0xbf1d2000}, {0xbf1d4000}, {0xbf1d6000}, + {0xbf1d8000}, {0xbf1da000}, {0xbf1dc000}, {0xbf1de000}, + {0xbf1e0000}, {0xbf1e2000}, {0xbf1e4000}, {0xbf1e6000}, + {0xbf1e8000}, {0xbf1ea000}, {0xbf1ec000}, {0xbf1ee000}, + {0xbf1f0000}, {0xbf1f2000}, {0xbf1f4000}, {0xbf1f6000}, + {0xbf1f8000}, {0xbf1fa000}, {0xbf1fc000}, {0xbf1fe000}, + {0xbf200000}, {0xbf202000}, {0xbf204000}, {0xbf206000}, + {0xbf208000}, {0xbf20a000}, {0xbf20c000}, {0xbf20e000}, + {0xbf210000}, {0xbf212000}, {0xbf214000}, {0xbf216000}, + {0xbf218000}, {0xbf21a000}, {0xbf21c000}, {0xbf21e000}, + {0xbf220000}, {0xbf222000}, {0xbf224000}, {0xbf226000}, + {0xbf228000}, {0xbf22a000}, {0xbf22c000}, {0xbf22e000}, + {0xbf230000}, {0xbf232000}, {0xbf234000}, {0xbf236000}, + {0xbf238000}, {0xbf23a000}, {0xbf23c000}, {0xbf23e000}, + {0xbf240000}, {0xbf242000}, {0xbf244000}, {0xbf246000}, + {0xbf248000}, {0xbf24a000}, {0xbf24c000}, {0xbf24e000}, + {0xbf250000}, {0xbf252000}, {0xbf254000}, {0xbf256000}, + {0xbf258000}, {0xbf25a000}, {0xbf25c000}, {0xbf25e000}, + {0xbf260000}, {0xbf262000}, {0xbf264000}, {0xbf266000}, + {0xbf268000}, {0xbf26a000}, {0xbf26c000}, {0xbf26e000}, + {0xbf270000}, {0xbf272000}, {0xbf274000}, {0xbf276000}, + {0xbf278000}, {0xbf27a000}, {0xbf27c000}, {0xbf27e000}, + {0xbf280000}, {0xbf282000}, {0xbf284000}, {0xbf286000}, + {0xbf288000}, {0xbf28a000}, {0xbf28c000}, {0xbf28e000}, + {0xbf290000}, {0xbf292000}, {0xbf294000}, {0xbf296000}, + {0xbf298000}, {0xbf29a000}, {0xbf29c000}, {0xbf29e000}, + {0xbf2a0000}, {0xbf2a2000}, {0xbf2a4000}, {0xbf2a6000}, + {0xbf2a8000}, {0xbf2aa000}, {0xbf2ac000}, {0xbf2ae000}, + {0xbf2b0000}, {0xbf2b2000}, {0xbf2b4000}, {0xbf2b6000}, + {0xbf2b8000}, {0xbf2ba000}, {0xbf2bc000}, {0xbf2be000}, + {0xbf2c0000}, {0xbf2c2000}, {0xbf2c4000}, {0xbf2c6000}, + {0xbf2c8000}, {0xbf2ca000}, {0xbf2cc000}, {0xbf2ce000}, + {0xbf2d0000}, {0xbf2d2000}, {0xbf2d4000}, {0xbf2d6000}, + {0xbf2d8000}, {0xbf2da000}, {0xbf2dc000}, {0xbf2de000}, + {0xbf2e0000}, {0xbf2e2000}, {0xbf2e4000}, {0xbf2e6000}, + {0xbf2e8000}, {0xbf2ea000}, {0xbf2ec000}, {0xbf2ee000}, + {0xbf2f0000}, {0xbf2f2000}, {0xbf2f4000}, {0xbf2f6000}, + {0xbf2f8000}, {0xbf2fa000}, {0xbf2fc000}, {0xbf2fe000}, + {0xbf300000}, {0xbf302000}, {0xbf304000}, {0xbf306000}, + {0xbf308000}, {0xbf30a000}, {0xbf30c000}, {0xbf30e000}, + {0xbf310000}, {0xbf312000}, {0xbf314000}, {0xbf316000}, + {0xbf318000}, {0xbf31a000}, {0xbf31c000}, {0xbf31e000}, + {0xbf320000}, {0xbf322000}, {0xbf324000}, {0xbf326000}, + {0xbf328000}, {0xbf32a000}, {0xbf32c000}, {0xbf32e000}, + {0xbf330000}, {0xbf332000}, {0xbf334000}, {0xbf336000}, + {0xbf338000}, {0xbf33a000}, {0xbf33c000}, {0xbf33e000}, + {0xbf340000}, {0xbf342000}, {0xbf344000}, {0xbf346000}, + {0xbf348000}, {0xbf34a000}, {0xbf34c000}, {0xbf34e000}, + {0xbf350000}, {0xbf352000}, {0xbf354000}, {0xbf356000}, + {0xbf358000}, {0xbf35a000}, {0xbf35c000}, {0xbf35e000}, + {0xbf360000}, {0xbf362000}, {0xbf364000}, {0xbf366000}, + {0xbf368000}, {0xbf36a000}, {0xbf36c000}, {0xbf36e000}, + {0xbf370000}, {0xbf372000}, {0xbf374000}, {0xbf376000}, + {0xbf378000}, {0xbf37a000}, {0xbf37c000}, {0xbf37e000}, + {0xbf380000}, {0xbf382000}, {0xbf384000}, {0xbf386000}, + {0xbf388000}, {0xbf38a000}, {0xbf38c000}, {0xbf38e000}, + {0xbf390000}, {0xbf392000}, {0xbf394000}, {0xbf396000}, + {0xbf398000}, {0xbf39a000}, {0xbf39c000}, {0xbf39e000}, + {0xbf3a0000}, {0xbf3a2000}, {0xbf3a4000}, {0xbf3a6000}, + {0xbf3a8000}, {0xbf3aa000}, {0xbf3ac000}, {0xbf3ae000}, + {0xbf3b0000}, {0xbf3b2000}, {0xbf3b4000}, {0xbf3b6000}, + {0xbf3b8000}, {0xbf3ba000}, {0xbf3bc000}, {0xbf3be000}, + {0xbf3c0000}, {0xbf3c2000}, {0xbf3c4000}, {0xbf3c6000}, + {0xbf3c8000}, {0xbf3ca000}, {0xbf3cc000}, {0xbf3ce000}, + {0xbf3d0000}, {0xbf3d2000}, {0xbf3d4000}, {0xbf3d6000}, + {0xbf3d8000}, {0xbf3da000}, {0xbf3dc000}, {0xbf3de000}, + {0xbf3e0000}, {0xbf3e2000}, {0xbf3e4000}, {0xbf3e6000}, + {0xbf3e8000}, {0xbf3ea000}, {0xbf3ec000}, {0xbf3ee000}, + {0xbf3f0000}, {0xbf3f2000}, {0xbf3f4000}, {0xbf3f6000}, + {0xbf3f8000}, {0xbf3fa000}, {0xbf3fc000}, {0xbf3fe000}, + {0xbf400000}, {0xbf402000}, {0xbf404000}, {0xbf406000}, + {0xbf408000}, {0xbf40a000}, {0xbf40c000}, {0xbf40e000}, + {0xbf410000}, {0xbf412000}, {0xbf414000}, {0xbf416000}, + {0xbf418000}, {0xbf41a000}, {0xbf41c000}, {0xbf41e000}, + {0xbf420000}, {0xbf422000}, {0xbf424000}, {0xbf426000}, + {0xbf428000}, {0xbf42a000}, {0xbf42c000}, {0xbf42e000}, + {0xbf430000}, {0xbf432000}, {0xbf434000}, {0xbf436000}, + {0xbf438000}, {0xbf43a000}, {0xbf43c000}, {0xbf43e000}, + {0xbf440000}, {0xbf442000}, {0xbf444000}, {0xbf446000}, + {0xbf448000}, {0xbf44a000}, {0xbf44c000}, {0xbf44e000}, + {0xbf450000}, {0xbf452000}, {0xbf454000}, {0xbf456000}, + {0xbf458000}, {0xbf45a000}, {0xbf45c000}, {0xbf45e000}, + {0xbf460000}, {0xbf462000}, {0xbf464000}, {0xbf466000}, + {0xbf468000}, {0xbf46a000}, {0xbf46c000}, {0xbf46e000}, + {0xbf470000}, {0xbf472000}, {0xbf474000}, {0xbf476000}, + {0xbf478000}, {0xbf47a000}, {0xbf47c000}, {0xbf47e000}, + {0xbf480000}, {0xbf482000}, {0xbf484000}, {0xbf486000}, + {0xbf488000}, {0xbf48a000}, {0xbf48c000}, {0xbf48e000}, + {0xbf490000}, {0xbf492000}, {0xbf494000}, {0xbf496000}, + {0xbf498000}, {0xbf49a000}, {0xbf49c000}, {0xbf49e000}, + {0xbf4a0000}, {0xbf4a2000}, {0xbf4a4000}, {0xbf4a6000}, + {0xbf4a8000}, {0xbf4aa000}, {0xbf4ac000}, {0xbf4ae000}, + {0xbf4b0000}, {0xbf4b2000}, {0xbf4b4000}, {0xbf4b6000}, + {0xbf4b8000}, {0xbf4ba000}, {0xbf4bc000}, {0xbf4be000}, + {0xbf4c0000}, {0xbf4c2000}, {0xbf4c4000}, {0xbf4c6000}, + {0xbf4c8000}, {0xbf4ca000}, {0xbf4cc000}, {0xbf4ce000}, + {0xbf4d0000}, {0xbf4d2000}, {0xbf4d4000}, {0xbf4d6000}, + {0xbf4d8000}, {0xbf4da000}, {0xbf4dc000}, {0xbf4de000}, + {0xbf4e0000}, {0xbf4e2000}, {0xbf4e4000}, {0xbf4e6000}, + {0xbf4e8000}, {0xbf4ea000}, {0xbf4ec000}, {0xbf4ee000}, + {0xbf4f0000}, {0xbf4f2000}, {0xbf4f4000}, {0xbf4f6000}, + {0xbf4f8000}, {0xbf4fa000}, {0xbf4fc000}, {0xbf4fe000}, + {0xbf500000}, {0xbf502000}, {0xbf504000}, {0xbf506000}, + {0xbf508000}, {0xbf50a000}, {0xbf50c000}, {0xbf50e000}, + {0xbf510000}, {0xbf512000}, {0xbf514000}, {0xbf516000}, + {0xbf518000}, {0xbf51a000}, {0xbf51c000}, {0xbf51e000}, + {0xbf520000}, {0xbf522000}, {0xbf524000}, {0xbf526000}, + {0xbf528000}, {0xbf52a000}, {0xbf52c000}, {0xbf52e000}, + {0xbf530000}, {0xbf532000}, {0xbf534000}, {0xbf536000}, + {0xbf538000}, {0xbf53a000}, {0xbf53c000}, {0xbf53e000}, + {0xbf540000}, {0xbf542000}, {0xbf544000}, {0xbf546000}, + {0xbf548000}, {0xbf54a000}, {0xbf54c000}, {0xbf54e000}, + {0xbf550000}, {0xbf552000}, {0xbf554000}, {0xbf556000}, + {0xbf558000}, {0xbf55a000}, {0xbf55c000}, {0xbf55e000}, + {0xbf560000}, {0xbf562000}, {0xbf564000}, {0xbf566000}, + {0xbf568000}, {0xbf56a000}, {0xbf56c000}, {0xbf56e000}, + {0xbf570000}, {0xbf572000}, {0xbf574000}, {0xbf576000}, + {0xbf578000}, {0xbf57a000}, {0xbf57c000}, {0xbf57e000}, + {0xbf580000}, {0xbf582000}, {0xbf584000}, {0xbf586000}, + {0xbf588000}, {0xbf58a000}, {0xbf58c000}, {0xbf58e000}, + {0xbf590000}, {0xbf592000}, {0xbf594000}, {0xbf596000}, + {0xbf598000}, {0xbf59a000}, {0xbf59c000}, {0xbf59e000}, + {0xbf5a0000}, {0xbf5a2000}, {0xbf5a4000}, {0xbf5a6000}, + {0xbf5a8000}, {0xbf5aa000}, {0xbf5ac000}, {0xbf5ae000}, + {0xbf5b0000}, {0xbf5b2000}, {0xbf5b4000}, {0xbf5b6000}, + {0xbf5b8000}, {0xbf5ba000}, {0xbf5bc000}, {0xbf5be000}, + {0xbf5c0000}, {0xbf5c2000}, {0xbf5c4000}, {0xbf5c6000}, + {0xbf5c8000}, {0xbf5ca000}, {0xbf5cc000}, {0xbf5ce000}, + {0xbf5d0000}, {0xbf5d2000}, {0xbf5d4000}, {0xbf5d6000}, + {0xbf5d8000}, {0xbf5da000}, {0xbf5dc000}, {0xbf5de000}, + {0xbf5e0000}, {0xbf5e2000}, {0xbf5e4000}, {0xbf5e6000}, + {0xbf5e8000}, {0xbf5ea000}, {0xbf5ec000}, {0xbf5ee000}, + {0xbf5f0000}, {0xbf5f2000}, {0xbf5f4000}, {0xbf5f6000}, + {0xbf5f8000}, {0xbf5fa000}, {0xbf5fc000}, {0xbf5fe000}, + {0xbf600000}, {0xbf602000}, {0xbf604000}, {0xbf606000}, + {0xbf608000}, {0xbf60a000}, {0xbf60c000}, {0xbf60e000}, + {0xbf610000}, {0xbf612000}, {0xbf614000}, {0xbf616000}, + {0xbf618000}, {0xbf61a000}, {0xbf61c000}, {0xbf61e000}, + {0xbf620000}, {0xbf622000}, {0xbf624000}, {0xbf626000}, + {0xbf628000}, {0xbf62a000}, {0xbf62c000}, {0xbf62e000}, + {0xbf630000}, {0xbf632000}, {0xbf634000}, {0xbf636000}, + {0xbf638000}, {0xbf63a000}, {0xbf63c000}, {0xbf63e000}, + {0xbf640000}, {0xbf642000}, {0xbf644000}, {0xbf646000}, + {0xbf648000}, {0xbf64a000}, {0xbf64c000}, {0xbf64e000}, + {0xbf650000}, {0xbf652000}, {0xbf654000}, {0xbf656000}, + {0xbf658000}, {0xbf65a000}, {0xbf65c000}, {0xbf65e000}, + {0xbf660000}, {0xbf662000}, {0xbf664000}, {0xbf666000}, + {0xbf668000}, {0xbf66a000}, {0xbf66c000}, {0xbf66e000}, + {0xbf670000}, {0xbf672000}, {0xbf674000}, {0xbf676000}, + {0xbf678000}, {0xbf67a000}, {0xbf67c000}, {0xbf67e000}, + {0xbf680000}, {0xbf682000}, {0xbf684000}, {0xbf686000}, + {0xbf688000}, {0xbf68a000}, {0xbf68c000}, {0xbf68e000}, + {0xbf690000}, {0xbf692000}, {0xbf694000}, {0xbf696000}, + {0xbf698000}, {0xbf69a000}, {0xbf69c000}, {0xbf69e000}, + {0xbf6a0000}, {0xbf6a2000}, {0xbf6a4000}, {0xbf6a6000}, + {0xbf6a8000}, {0xbf6aa000}, {0xbf6ac000}, {0xbf6ae000}, + {0xbf6b0000}, {0xbf6b2000}, {0xbf6b4000}, {0xbf6b6000}, + {0xbf6b8000}, {0xbf6ba000}, {0xbf6bc000}, {0xbf6be000}, + {0xbf6c0000}, {0xbf6c2000}, {0xbf6c4000}, {0xbf6c6000}, + {0xbf6c8000}, {0xbf6ca000}, {0xbf6cc000}, {0xbf6ce000}, + {0xbf6d0000}, {0xbf6d2000}, {0xbf6d4000}, {0xbf6d6000}, + {0xbf6d8000}, {0xbf6da000}, {0xbf6dc000}, {0xbf6de000}, + {0xbf6e0000}, {0xbf6e2000}, {0xbf6e4000}, {0xbf6e6000}, + {0xbf6e8000}, {0xbf6ea000}, {0xbf6ec000}, {0xbf6ee000}, + {0xbf6f0000}, {0xbf6f2000}, {0xbf6f4000}, {0xbf6f6000}, + {0xbf6f8000}, {0xbf6fa000}, {0xbf6fc000}, {0xbf6fe000}, + {0xbf700000}, {0xbf702000}, {0xbf704000}, {0xbf706000}, + {0xbf708000}, {0xbf70a000}, {0xbf70c000}, {0xbf70e000}, + {0xbf710000}, {0xbf712000}, {0xbf714000}, {0xbf716000}, + {0xbf718000}, {0xbf71a000}, {0xbf71c000}, {0xbf71e000}, + {0xbf720000}, {0xbf722000}, {0xbf724000}, {0xbf726000}, + {0xbf728000}, {0xbf72a000}, {0xbf72c000}, {0xbf72e000}, + {0xbf730000}, {0xbf732000}, {0xbf734000}, {0xbf736000}, + {0xbf738000}, {0xbf73a000}, {0xbf73c000}, {0xbf73e000}, + {0xbf740000}, {0xbf742000}, {0xbf744000}, {0xbf746000}, + {0xbf748000}, {0xbf74a000}, {0xbf74c000}, {0xbf74e000}, + {0xbf750000}, {0xbf752000}, {0xbf754000}, {0xbf756000}, + {0xbf758000}, {0xbf75a000}, {0xbf75c000}, {0xbf75e000}, + {0xbf760000}, {0xbf762000}, {0xbf764000}, {0xbf766000}, + {0xbf768000}, {0xbf76a000}, {0xbf76c000}, {0xbf76e000}, + {0xbf770000}, {0xbf772000}, {0xbf774000}, {0xbf776000}, + {0xbf778000}, {0xbf77a000}, {0xbf77c000}, {0xbf77e000}, + {0xbf780000}, {0xbf782000}, {0xbf784000}, {0xbf786000}, + {0xbf788000}, {0xbf78a000}, {0xbf78c000}, {0xbf78e000}, + {0xbf790000}, {0xbf792000}, {0xbf794000}, {0xbf796000}, + {0xbf798000}, {0xbf79a000}, {0xbf79c000}, {0xbf79e000}, + {0xbf7a0000}, {0xbf7a2000}, {0xbf7a4000}, {0xbf7a6000}, + {0xbf7a8000}, {0xbf7aa000}, {0xbf7ac000}, {0xbf7ae000}, + {0xbf7b0000}, {0xbf7b2000}, {0xbf7b4000}, {0xbf7b6000}, + {0xbf7b8000}, {0xbf7ba000}, {0xbf7bc000}, {0xbf7be000}, + {0xbf7c0000}, {0xbf7c2000}, {0xbf7c4000}, {0xbf7c6000}, + {0xbf7c8000}, {0xbf7ca000}, {0xbf7cc000}, {0xbf7ce000}, + {0xbf7d0000}, {0xbf7d2000}, {0xbf7d4000}, {0xbf7d6000}, + {0xbf7d8000}, {0xbf7da000}, {0xbf7dc000}, {0xbf7de000}, + {0xbf7e0000}, {0xbf7e2000}, {0xbf7e4000}, {0xbf7e6000}, + {0xbf7e8000}, {0xbf7ea000}, {0xbf7ec000}, {0xbf7ee000}, + {0xbf7f0000}, {0xbf7f2000}, {0xbf7f4000}, {0xbf7f6000}, + {0xbf7f8000}, {0xbf7fa000}, {0xbf7fc000}, {0xbf7fe000}, + {0xbf800000}, {0xbf802000}, {0xbf804000}, {0xbf806000}, + {0xbf808000}, {0xbf80a000}, {0xbf80c000}, {0xbf80e000}, + {0xbf810000}, {0xbf812000}, {0xbf814000}, {0xbf816000}, + {0xbf818000}, {0xbf81a000}, {0xbf81c000}, {0xbf81e000}, + {0xbf820000}, {0xbf822000}, {0xbf824000}, {0xbf826000}, + {0xbf828000}, {0xbf82a000}, {0xbf82c000}, {0xbf82e000}, + {0xbf830000}, {0xbf832000}, {0xbf834000}, {0xbf836000}, + {0xbf838000}, {0xbf83a000}, {0xbf83c000}, {0xbf83e000}, + {0xbf840000}, {0xbf842000}, {0xbf844000}, {0xbf846000}, + {0xbf848000}, {0xbf84a000}, {0xbf84c000}, {0xbf84e000}, + {0xbf850000}, {0xbf852000}, {0xbf854000}, {0xbf856000}, + {0xbf858000}, {0xbf85a000}, {0xbf85c000}, {0xbf85e000}, + {0xbf860000}, {0xbf862000}, {0xbf864000}, {0xbf866000}, + {0xbf868000}, {0xbf86a000}, {0xbf86c000}, {0xbf86e000}, + {0xbf870000}, {0xbf872000}, {0xbf874000}, {0xbf876000}, + {0xbf878000}, {0xbf87a000}, {0xbf87c000}, {0xbf87e000}, + {0xbf880000}, {0xbf882000}, {0xbf884000}, {0xbf886000}, + {0xbf888000}, {0xbf88a000}, {0xbf88c000}, {0xbf88e000}, + {0xbf890000}, {0xbf892000}, {0xbf894000}, {0xbf896000}, + {0xbf898000}, {0xbf89a000}, {0xbf89c000}, {0xbf89e000}, + {0xbf8a0000}, {0xbf8a2000}, {0xbf8a4000}, {0xbf8a6000}, + {0xbf8a8000}, {0xbf8aa000}, {0xbf8ac000}, {0xbf8ae000}, + {0xbf8b0000}, {0xbf8b2000}, {0xbf8b4000}, {0xbf8b6000}, + {0xbf8b8000}, {0xbf8ba000}, {0xbf8bc000}, {0xbf8be000}, + {0xbf8c0000}, {0xbf8c2000}, {0xbf8c4000}, {0xbf8c6000}, + {0xbf8c8000}, {0xbf8ca000}, {0xbf8cc000}, {0xbf8ce000}, + {0xbf8d0000}, {0xbf8d2000}, {0xbf8d4000}, {0xbf8d6000}, + {0xbf8d8000}, {0xbf8da000}, {0xbf8dc000}, {0xbf8de000}, + {0xbf8e0000}, {0xbf8e2000}, {0xbf8e4000}, {0xbf8e6000}, + {0xbf8e8000}, {0xbf8ea000}, {0xbf8ec000}, {0xbf8ee000}, + {0xbf8f0000}, {0xbf8f2000}, {0xbf8f4000}, {0xbf8f6000}, + {0xbf8f8000}, {0xbf8fa000}, {0xbf8fc000}, {0xbf8fe000}, + {0xbf900000}, {0xbf902000}, {0xbf904000}, {0xbf906000}, + {0xbf908000}, {0xbf90a000}, {0xbf90c000}, {0xbf90e000}, + {0xbf910000}, {0xbf912000}, {0xbf914000}, {0xbf916000}, + {0xbf918000}, {0xbf91a000}, {0xbf91c000}, {0xbf91e000}, + {0xbf920000}, {0xbf922000}, {0xbf924000}, {0xbf926000}, + {0xbf928000}, {0xbf92a000}, {0xbf92c000}, {0xbf92e000}, + {0xbf930000}, {0xbf932000}, {0xbf934000}, {0xbf936000}, + {0xbf938000}, {0xbf93a000}, {0xbf93c000}, {0xbf93e000}, + {0xbf940000}, {0xbf942000}, {0xbf944000}, {0xbf946000}, + {0xbf948000}, {0xbf94a000}, {0xbf94c000}, {0xbf94e000}, + {0xbf950000}, {0xbf952000}, {0xbf954000}, {0xbf956000}, + {0xbf958000}, {0xbf95a000}, {0xbf95c000}, {0xbf95e000}, + {0xbf960000}, {0xbf962000}, {0xbf964000}, {0xbf966000}, + {0xbf968000}, {0xbf96a000}, {0xbf96c000}, {0xbf96e000}, + {0xbf970000}, {0xbf972000}, {0xbf974000}, {0xbf976000}, + {0xbf978000}, {0xbf97a000}, {0xbf97c000}, {0xbf97e000}, + {0xbf980000}, {0xbf982000}, {0xbf984000}, {0xbf986000}, + {0xbf988000}, {0xbf98a000}, {0xbf98c000}, {0xbf98e000}, + {0xbf990000}, {0xbf992000}, {0xbf994000}, {0xbf996000}, + {0xbf998000}, {0xbf99a000}, {0xbf99c000}, {0xbf99e000}, + {0xbf9a0000}, {0xbf9a2000}, {0xbf9a4000}, {0xbf9a6000}, + {0xbf9a8000}, {0xbf9aa000}, {0xbf9ac000}, {0xbf9ae000}, + {0xbf9b0000}, {0xbf9b2000}, {0xbf9b4000}, {0xbf9b6000}, + {0xbf9b8000}, {0xbf9ba000}, {0xbf9bc000}, {0xbf9be000}, + {0xbf9c0000}, {0xbf9c2000}, {0xbf9c4000}, {0xbf9c6000}, + {0xbf9c8000}, {0xbf9ca000}, {0xbf9cc000}, {0xbf9ce000}, + {0xbf9d0000}, {0xbf9d2000}, {0xbf9d4000}, {0xbf9d6000}, + {0xbf9d8000}, {0xbf9da000}, {0xbf9dc000}, {0xbf9de000}, + {0xbf9e0000}, {0xbf9e2000}, {0xbf9e4000}, {0xbf9e6000}, + {0xbf9e8000}, {0xbf9ea000}, {0xbf9ec000}, {0xbf9ee000}, + {0xbf9f0000}, {0xbf9f2000}, {0xbf9f4000}, {0xbf9f6000}, + {0xbf9f8000}, {0xbf9fa000}, {0xbf9fc000}, {0xbf9fe000}, + {0xbfa00000}, {0xbfa02000}, {0xbfa04000}, {0xbfa06000}, + {0xbfa08000}, {0xbfa0a000}, {0xbfa0c000}, {0xbfa0e000}, + {0xbfa10000}, {0xbfa12000}, {0xbfa14000}, {0xbfa16000}, + {0xbfa18000}, {0xbfa1a000}, {0xbfa1c000}, {0xbfa1e000}, + {0xbfa20000}, {0xbfa22000}, {0xbfa24000}, {0xbfa26000}, + {0xbfa28000}, {0xbfa2a000}, {0xbfa2c000}, {0xbfa2e000}, + {0xbfa30000}, {0xbfa32000}, {0xbfa34000}, {0xbfa36000}, + {0xbfa38000}, {0xbfa3a000}, {0xbfa3c000}, {0xbfa3e000}, + {0xbfa40000}, {0xbfa42000}, {0xbfa44000}, {0xbfa46000}, + {0xbfa48000}, {0xbfa4a000}, {0xbfa4c000}, {0xbfa4e000}, + {0xbfa50000}, {0xbfa52000}, {0xbfa54000}, {0xbfa56000}, + {0xbfa58000}, {0xbfa5a000}, {0xbfa5c000}, {0xbfa5e000}, + {0xbfa60000}, {0xbfa62000}, {0xbfa64000}, {0xbfa66000}, + {0xbfa68000}, {0xbfa6a000}, {0xbfa6c000}, {0xbfa6e000}, + {0xbfa70000}, {0xbfa72000}, {0xbfa74000}, {0xbfa76000}, + {0xbfa78000}, {0xbfa7a000}, {0xbfa7c000}, {0xbfa7e000}, + {0xbfa80000}, {0xbfa82000}, {0xbfa84000}, {0xbfa86000}, + {0xbfa88000}, {0xbfa8a000}, {0xbfa8c000}, {0xbfa8e000}, + {0xbfa90000}, {0xbfa92000}, {0xbfa94000}, {0xbfa96000}, + {0xbfa98000}, {0xbfa9a000}, {0xbfa9c000}, {0xbfa9e000}, + {0xbfaa0000}, {0xbfaa2000}, {0xbfaa4000}, {0xbfaa6000}, + {0xbfaa8000}, {0xbfaaa000}, {0xbfaac000}, {0xbfaae000}, + {0xbfab0000}, {0xbfab2000}, {0xbfab4000}, {0xbfab6000}, + {0xbfab8000}, {0xbfaba000}, {0xbfabc000}, {0xbfabe000}, + {0xbfac0000}, {0xbfac2000}, {0xbfac4000}, {0xbfac6000}, + {0xbfac8000}, {0xbfaca000}, {0xbfacc000}, {0xbface000}, + {0xbfad0000}, {0xbfad2000}, {0xbfad4000}, {0xbfad6000}, + {0xbfad8000}, {0xbfada000}, {0xbfadc000}, {0xbfade000}, + {0xbfae0000}, {0xbfae2000}, {0xbfae4000}, {0xbfae6000}, + {0xbfae8000}, {0xbfaea000}, {0xbfaec000}, {0xbfaee000}, + {0xbfaf0000}, {0xbfaf2000}, {0xbfaf4000}, {0xbfaf6000}, + {0xbfaf8000}, {0xbfafa000}, {0xbfafc000}, {0xbfafe000}, + {0xbfb00000}, {0xbfb02000}, {0xbfb04000}, {0xbfb06000}, + {0xbfb08000}, {0xbfb0a000}, {0xbfb0c000}, {0xbfb0e000}, + {0xbfb10000}, {0xbfb12000}, {0xbfb14000}, {0xbfb16000}, + {0xbfb18000}, {0xbfb1a000}, {0xbfb1c000}, {0xbfb1e000}, + {0xbfb20000}, {0xbfb22000}, {0xbfb24000}, {0xbfb26000}, + {0xbfb28000}, {0xbfb2a000}, {0xbfb2c000}, {0xbfb2e000}, + {0xbfb30000}, {0xbfb32000}, {0xbfb34000}, {0xbfb36000}, + {0xbfb38000}, {0xbfb3a000}, {0xbfb3c000}, {0xbfb3e000}, + {0xbfb40000}, {0xbfb42000}, {0xbfb44000}, {0xbfb46000}, + {0xbfb48000}, {0xbfb4a000}, {0xbfb4c000}, {0xbfb4e000}, + {0xbfb50000}, {0xbfb52000}, {0xbfb54000}, {0xbfb56000}, + {0xbfb58000}, {0xbfb5a000}, {0xbfb5c000}, {0xbfb5e000}, + {0xbfb60000}, {0xbfb62000}, {0xbfb64000}, {0xbfb66000}, + {0xbfb68000}, {0xbfb6a000}, {0xbfb6c000}, {0xbfb6e000}, + {0xbfb70000}, {0xbfb72000}, {0xbfb74000}, {0xbfb76000}, + {0xbfb78000}, {0xbfb7a000}, {0xbfb7c000}, {0xbfb7e000}, + {0xbfb80000}, {0xbfb82000}, {0xbfb84000}, {0xbfb86000}, + {0xbfb88000}, {0xbfb8a000}, {0xbfb8c000}, {0xbfb8e000}, + {0xbfb90000}, {0xbfb92000}, {0xbfb94000}, {0xbfb96000}, + {0xbfb98000}, {0xbfb9a000}, {0xbfb9c000}, {0xbfb9e000}, + {0xbfba0000}, {0xbfba2000}, {0xbfba4000}, {0xbfba6000}, + {0xbfba8000}, {0xbfbaa000}, {0xbfbac000}, {0xbfbae000}, + {0xbfbb0000}, {0xbfbb2000}, {0xbfbb4000}, {0xbfbb6000}, + {0xbfbb8000}, {0xbfbba000}, {0xbfbbc000}, {0xbfbbe000}, + {0xbfbc0000}, {0xbfbc2000}, {0xbfbc4000}, {0xbfbc6000}, + {0xbfbc8000}, {0xbfbca000}, {0xbfbcc000}, {0xbfbce000}, + {0xbfbd0000}, {0xbfbd2000}, {0xbfbd4000}, {0xbfbd6000}, + {0xbfbd8000}, {0xbfbda000}, {0xbfbdc000}, {0xbfbde000}, + {0xbfbe0000}, {0xbfbe2000}, {0xbfbe4000}, {0xbfbe6000}, + {0xbfbe8000}, {0xbfbea000}, {0xbfbec000}, {0xbfbee000}, + {0xbfbf0000}, {0xbfbf2000}, {0xbfbf4000}, {0xbfbf6000}, + {0xbfbf8000}, {0xbfbfa000}, {0xbfbfc000}, {0xbfbfe000}, + {0xbfc00000}, {0xbfc02000}, {0xbfc04000}, {0xbfc06000}, + {0xbfc08000}, {0xbfc0a000}, {0xbfc0c000}, {0xbfc0e000}, + {0xbfc10000}, {0xbfc12000}, {0xbfc14000}, {0xbfc16000}, + {0xbfc18000}, {0xbfc1a000}, {0xbfc1c000}, {0xbfc1e000}, + {0xbfc20000}, {0xbfc22000}, {0xbfc24000}, {0xbfc26000}, + {0xbfc28000}, {0xbfc2a000}, {0xbfc2c000}, {0xbfc2e000}, + {0xbfc30000}, {0xbfc32000}, {0xbfc34000}, {0xbfc36000}, + {0xbfc38000}, {0xbfc3a000}, {0xbfc3c000}, {0xbfc3e000}, + {0xbfc40000}, {0xbfc42000}, {0xbfc44000}, {0xbfc46000}, + {0xbfc48000}, {0xbfc4a000}, {0xbfc4c000}, {0xbfc4e000}, + {0xbfc50000}, {0xbfc52000}, {0xbfc54000}, {0xbfc56000}, + {0xbfc58000}, {0xbfc5a000}, {0xbfc5c000}, {0xbfc5e000}, + {0xbfc60000}, {0xbfc62000}, {0xbfc64000}, {0xbfc66000}, + {0xbfc68000}, {0xbfc6a000}, {0xbfc6c000}, {0xbfc6e000}, + {0xbfc70000}, {0xbfc72000}, {0xbfc74000}, {0xbfc76000}, + {0xbfc78000}, {0xbfc7a000}, {0xbfc7c000}, {0xbfc7e000}, + {0xbfc80000}, {0xbfc82000}, {0xbfc84000}, {0xbfc86000}, + {0xbfc88000}, {0xbfc8a000}, {0xbfc8c000}, {0xbfc8e000}, + {0xbfc90000}, {0xbfc92000}, {0xbfc94000}, {0xbfc96000}, + {0xbfc98000}, {0xbfc9a000}, {0xbfc9c000}, {0xbfc9e000}, + {0xbfca0000}, {0xbfca2000}, {0xbfca4000}, {0xbfca6000}, + {0xbfca8000}, {0xbfcaa000}, {0xbfcac000}, {0xbfcae000}, + {0xbfcb0000}, {0xbfcb2000}, {0xbfcb4000}, {0xbfcb6000}, + {0xbfcb8000}, {0xbfcba000}, {0xbfcbc000}, {0xbfcbe000}, + {0xbfcc0000}, {0xbfcc2000}, {0xbfcc4000}, {0xbfcc6000}, + {0xbfcc8000}, {0xbfcca000}, {0xbfccc000}, {0xbfcce000}, + {0xbfcd0000}, {0xbfcd2000}, {0xbfcd4000}, {0xbfcd6000}, + {0xbfcd8000}, {0xbfcda000}, {0xbfcdc000}, {0xbfcde000}, + {0xbfce0000}, {0xbfce2000}, {0xbfce4000}, {0xbfce6000}, + {0xbfce8000}, {0xbfcea000}, {0xbfcec000}, {0xbfcee000}, + {0xbfcf0000}, {0xbfcf2000}, {0xbfcf4000}, {0xbfcf6000}, + {0xbfcf8000}, {0xbfcfa000}, {0xbfcfc000}, {0xbfcfe000}, + {0xbfd00000}, {0xbfd02000}, {0xbfd04000}, {0xbfd06000}, + {0xbfd08000}, {0xbfd0a000}, {0xbfd0c000}, {0xbfd0e000}, + {0xbfd10000}, {0xbfd12000}, {0xbfd14000}, {0xbfd16000}, + {0xbfd18000}, {0xbfd1a000}, {0xbfd1c000}, {0xbfd1e000}, + {0xbfd20000}, {0xbfd22000}, {0xbfd24000}, {0xbfd26000}, + {0xbfd28000}, {0xbfd2a000}, {0xbfd2c000}, {0xbfd2e000}, + {0xbfd30000}, {0xbfd32000}, {0xbfd34000}, {0xbfd36000}, + {0xbfd38000}, {0xbfd3a000}, {0xbfd3c000}, {0xbfd3e000}, + {0xbfd40000}, {0xbfd42000}, {0xbfd44000}, {0xbfd46000}, + {0xbfd48000}, {0xbfd4a000}, {0xbfd4c000}, {0xbfd4e000}, + {0xbfd50000}, {0xbfd52000}, {0xbfd54000}, {0xbfd56000}, + {0xbfd58000}, {0xbfd5a000}, {0xbfd5c000}, {0xbfd5e000}, + {0xbfd60000}, {0xbfd62000}, {0xbfd64000}, {0xbfd66000}, + {0xbfd68000}, {0xbfd6a000}, {0xbfd6c000}, {0xbfd6e000}, + {0xbfd70000}, {0xbfd72000}, {0xbfd74000}, {0xbfd76000}, + {0xbfd78000}, {0xbfd7a000}, {0xbfd7c000}, {0xbfd7e000}, + {0xbfd80000}, {0xbfd82000}, {0xbfd84000}, {0xbfd86000}, + {0xbfd88000}, {0xbfd8a000}, {0xbfd8c000}, {0xbfd8e000}, + {0xbfd90000}, {0xbfd92000}, {0xbfd94000}, {0xbfd96000}, + {0xbfd98000}, {0xbfd9a000}, {0xbfd9c000}, {0xbfd9e000}, + {0xbfda0000}, {0xbfda2000}, {0xbfda4000}, {0xbfda6000}, + {0xbfda8000}, {0xbfdaa000}, {0xbfdac000}, {0xbfdae000}, + {0xbfdb0000}, {0xbfdb2000}, {0xbfdb4000}, {0xbfdb6000}, + {0xbfdb8000}, {0xbfdba000}, {0xbfdbc000}, {0xbfdbe000}, + {0xbfdc0000}, {0xbfdc2000}, {0xbfdc4000}, {0xbfdc6000}, + {0xbfdc8000}, {0xbfdca000}, {0xbfdcc000}, {0xbfdce000}, + {0xbfdd0000}, {0xbfdd2000}, {0xbfdd4000}, {0xbfdd6000}, + {0xbfdd8000}, {0xbfdda000}, {0xbfddc000}, {0xbfdde000}, + {0xbfde0000}, {0xbfde2000}, {0xbfde4000}, {0xbfde6000}, + {0xbfde8000}, {0xbfdea000}, {0xbfdec000}, {0xbfdee000}, + {0xbfdf0000}, {0xbfdf2000}, {0xbfdf4000}, {0xbfdf6000}, + {0xbfdf8000}, {0xbfdfa000}, {0xbfdfc000}, {0xbfdfe000}, + {0xbfe00000}, {0xbfe02000}, {0xbfe04000}, {0xbfe06000}, + {0xbfe08000}, {0xbfe0a000}, {0xbfe0c000}, {0xbfe0e000}, + {0xbfe10000}, {0xbfe12000}, {0xbfe14000}, {0xbfe16000}, + {0xbfe18000}, {0xbfe1a000}, {0xbfe1c000}, {0xbfe1e000}, + {0xbfe20000}, {0xbfe22000}, {0xbfe24000}, {0xbfe26000}, + {0xbfe28000}, {0xbfe2a000}, {0xbfe2c000}, {0xbfe2e000}, + {0xbfe30000}, {0xbfe32000}, {0xbfe34000}, {0xbfe36000}, + {0xbfe38000}, {0xbfe3a000}, {0xbfe3c000}, {0xbfe3e000}, + {0xbfe40000}, {0xbfe42000}, {0xbfe44000}, {0xbfe46000}, + {0xbfe48000}, {0xbfe4a000}, {0xbfe4c000}, {0xbfe4e000}, + {0xbfe50000}, {0xbfe52000}, {0xbfe54000}, {0xbfe56000}, + {0xbfe58000}, {0xbfe5a000}, {0xbfe5c000}, {0xbfe5e000}, + {0xbfe60000}, {0xbfe62000}, {0xbfe64000}, {0xbfe66000}, + {0xbfe68000}, {0xbfe6a000}, {0xbfe6c000}, {0xbfe6e000}, + {0xbfe70000}, {0xbfe72000}, {0xbfe74000}, {0xbfe76000}, + {0xbfe78000}, {0xbfe7a000}, {0xbfe7c000}, {0xbfe7e000}, + {0xbfe80000}, {0xbfe82000}, {0xbfe84000}, {0xbfe86000}, + {0xbfe88000}, {0xbfe8a000}, {0xbfe8c000}, {0xbfe8e000}, + {0xbfe90000}, {0xbfe92000}, {0xbfe94000}, {0xbfe96000}, + {0xbfe98000}, {0xbfe9a000}, {0xbfe9c000}, {0xbfe9e000}, + {0xbfea0000}, {0xbfea2000}, {0xbfea4000}, {0xbfea6000}, + {0xbfea8000}, {0xbfeaa000}, {0xbfeac000}, {0xbfeae000}, + {0xbfeb0000}, {0xbfeb2000}, {0xbfeb4000}, {0xbfeb6000}, + {0xbfeb8000}, {0xbfeba000}, {0xbfebc000}, {0xbfebe000}, + {0xbfec0000}, {0xbfec2000}, {0xbfec4000}, {0xbfec6000}, + {0xbfec8000}, {0xbfeca000}, {0xbfecc000}, {0xbfece000}, + {0xbfed0000}, {0xbfed2000}, {0xbfed4000}, {0xbfed6000}, + {0xbfed8000}, {0xbfeda000}, {0xbfedc000}, {0xbfede000}, + {0xbfee0000}, {0xbfee2000}, {0xbfee4000}, {0xbfee6000}, + {0xbfee8000}, {0xbfeea000}, {0xbfeec000}, {0xbfeee000}, + {0xbfef0000}, {0xbfef2000}, {0xbfef4000}, {0xbfef6000}, + {0xbfef8000}, {0xbfefa000}, {0xbfefc000}, {0xbfefe000}, + {0xbff00000}, {0xbff02000}, {0xbff04000}, {0xbff06000}, + {0xbff08000}, {0xbff0a000}, {0xbff0c000}, {0xbff0e000}, + {0xbff10000}, {0xbff12000}, {0xbff14000}, {0xbff16000}, + {0xbff18000}, {0xbff1a000}, {0xbff1c000}, {0xbff1e000}, + {0xbff20000}, {0xbff22000}, {0xbff24000}, {0xbff26000}, + {0xbff28000}, {0xbff2a000}, {0xbff2c000}, {0xbff2e000}, + {0xbff30000}, {0xbff32000}, {0xbff34000}, {0xbff36000}, + {0xbff38000}, {0xbff3a000}, {0xbff3c000}, {0xbff3e000}, + {0xbff40000}, {0xbff42000}, {0xbff44000}, {0xbff46000}, + {0xbff48000}, {0xbff4a000}, {0xbff4c000}, {0xbff4e000}, + {0xbff50000}, {0xbff52000}, {0xbff54000}, {0xbff56000}, + {0xbff58000}, {0xbff5a000}, {0xbff5c000}, {0xbff5e000}, + {0xbff60000}, {0xbff62000}, {0xbff64000}, {0xbff66000}, + {0xbff68000}, {0xbff6a000}, {0xbff6c000}, {0xbff6e000}, + {0xbff70000}, {0xbff72000}, {0xbff74000}, {0xbff76000}, + {0xbff78000}, {0xbff7a000}, {0xbff7c000}, {0xbff7e000}, + {0xbff80000}, {0xbff82000}, {0xbff84000}, {0xbff86000}, + {0xbff88000}, {0xbff8a000}, {0xbff8c000}, {0xbff8e000}, + {0xbff90000}, {0xbff92000}, {0xbff94000}, {0xbff96000}, + {0xbff98000}, {0xbff9a000}, {0xbff9c000}, {0xbff9e000}, + {0xbffa0000}, {0xbffa2000}, {0xbffa4000}, {0xbffa6000}, + {0xbffa8000}, {0xbffaa000}, {0xbffac000}, {0xbffae000}, + {0xbffb0000}, {0xbffb2000}, {0xbffb4000}, {0xbffb6000}, + {0xbffb8000}, {0xbffba000}, {0xbffbc000}, {0xbffbe000}, + {0xbffc0000}, {0xbffc2000}, {0xbffc4000}, {0xbffc6000}, + {0xbffc8000}, {0xbffca000}, {0xbffcc000}, {0xbffce000}, + {0xbffd0000}, {0xbffd2000}, {0xbffd4000}, {0xbffd6000}, + {0xbffd8000}, {0xbffda000}, {0xbffdc000}, {0xbffde000}, + {0xbffe0000}, {0xbffe2000}, {0xbffe4000}, {0xbffe6000}, + {0xbffe8000}, {0xbffea000}, {0xbffec000}, {0xbffee000}, + {0xbfff0000}, {0xbfff2000}, {0xbfff4000}, {0xbfff6000}, + {0xbfff8000}, {0xbfffa000}, {0xbfffc000}, {0xbfffe000}, + {0xc0000000}, {0xc0002000}, {0xc0004000}, {0xc0006000}, + {0xc0008000}, {0xc000a000}, {0xc000c000}, {0xc000e000}, + {0xc0010000}, {0xc0012000}, {0xc0014000}, {0xc0016000}, + {0xc0018000}, {0xc001a000}, {0xc001c000}, {0xc001e000}, + {0xc0020000}, {0xc0022000}, {0xc0024000}, {0xc0026000}, + {0xc0028000}, {0xc002a000}, {0xc002c000}, {0xc002e000}, + {0xc0030000}, {0xc0032000}, {0xc0034000}, {0xc0036000}, + {0xc0038000}, {0xc003a000}, {0xc003c000}, {0xc003e000}, + {0xc0040000}, {0xc0042000}, {0xc0044000}, {0xc0046000}, + {0xc0048000}, {0xc004a000}, {0xc004c000}, {0xc004e000}, + {0xc0050000}, {0xc0052000}, {0xc0054000}, {0xc0056000}, + {0xc0058000}, {0xc005a000}, {0xc005c000}, {0xc005e000}, + {0xc0060000}, {0xc0062000}, {0xc0064000}, {0xc0066000}, + {0xc0068000}, {0xc006a000}, {0xc006c000}, {0xc006e000}, + {0xc0070000}, {0xc0072000}, {0xc0074000}, {0xc0076000}, + {0xc0078000}, {0xc007a000}, {0xc007c000}, {0xc007e000}, + {0xc0080000}, {0xc0082000}, {0xc0084000}, {0xc0086000}, + {0xc0088000}, {0xc008a000}, {0xc008c000}, {0xc008e000}, + {0xc0090000}, {0xc0092000}, {0xc0094000}, {0xc0096000}, + {0xc0098000}, {0xc009a000}, {0xc009c000}, {0xc009e000}, + {0xc00a0000}, {0xc00a2000}, {0xc00a4000}, {0xc00a6000}, + {0xc00a8000}, {0xc00aa000}, {0xc00ac000}, {0xc00ae000}, + {0xc00b0000}, {0xc00b2000}, {0xc00b4000}, {0xc00b6000}, + {0xc00b8000}, {0xc00ba000}, {0xc00bc000}, {0xc00be000}, + {0xc00c0000}, {0xc00c2000}, {0xc00c4000}, {0xc00c6000}, + {0xc00c8000}, {0xc00ca000}, {0xc00cc000}, {0xc00ce000}, + {0xc00d0000}, {0xc00d2000}, {0xc00d4000}, {0xc00d6000}, + {0xc00d8000}, {0xc00da000}, {0xc00dc000}, {0xc00de000}, + {0xc00e0000}, {0xc00e2000}, {0xc00e4000}, {0xc00e6000}, + {0xc00e8000}, {0xc00ea000}, {0xc00ec000}, {0xc00ee000}, + {0xc00f0000}, {0xc00f2000}, {0xc00f4000}, {0xc00f6000}, + {0xc00f8000}, {0xc00fa000}, {0xc00fc000}, {0xc00fe000}, + {0xc0100000}, {0xc0102000}, {0xc0104000}, {0xc0106000}, + {0xc0108000}, {0xc010a000}, {0xc010c000}, {0xc010e000}, + {0xc0110000}, {0xc0112000}, {0xc0114000}, {0xc0116000}, + {0xc0118000}, {0xc011a000}, {0xc011c000}, {0xc011e000}, + {0xc0120000}, {0xc0122000}, {0xc0124000}, {0xc0126000}, + {0xc0128000}, {0xc012a000}, {0xc012c000}, {0xc012e000}, + {0xc0130000}, {0xc0132000}, {0xc0134000}, {0xc0136000}, + {0xc0138000}, {0xc013a000}, {0xc013c000}, {0xc013e000}, + {0xc0140000}, {0xc0142000}, {0xc0144000}, {0xc0146000}, + {0xc0148000}, {0xc014a000}, {0xc014c000}, {0xc014e000}, + {0xc0150000}, {0xc0152000}, {0xc0154000}, {0xc0156000}, + {0xc0158000}, {0xc015a000}, {0xc015c000}, {0xc015e000}, + {0xc0160000}, {0xc0162000}, {0xc0164000}, {0xc0166000}, + {0xc0168000}, {0xc016a000}, {0xc016c000}, {0xc016e000}, + {0xc0170000}, {0xc0172000}, {0xc0174000}, {0xc0176000}, + {0xc0178000}, {0xc017a000}, {0xc017c000}, {0xc017e000}, + {0xc0180000}, {0xc0182000}, {0xc0184000}, {0xc0186000}, + {0xc0188000}, {0xc018a000}, {0xc018c000}, {0xc018e000}, + {0xc0190000}, {0xc0192000}, {0xc0194000}, {0xc0196000}, + {0xc0198000}, {0xc019a000}, {0xc019c000}, {0xc019e000}, + {0xc01a0000}, {0xc01a2000}, {0xc01a4000}, {0xc01a6000}, + {0xc01a8000}, {0xc01aa000}, {0xc01ac000}, {0xc01ae000}, + {0xc01b0000}, {0xc01b2000}, {0xc01b4000}, {0xc01b6000}, + {0xc01b8000}, {0xc01ba000}, {0xc01bc000}, {0xc01be000}, + {0xc01c0000}, {0xc01c2000}, {0xc01c4000}, {0xc01c6000}, + {0xc01c8000}, {0xc01ca000}, {0xc01cc000}, {0xc01ce000}, + {0xc01d0000}, {0xc01d2000}, {0xc01d4000}, {0xc01d6000}, + {0xc01d8000}, {0xc01da000}, {0xc01dc000}, {0xc01de000}, + {0xc01e0000}, {0xc01e2000}, {0xc01e4000}, {0xc01e6000}, + {0xc01e8000}, {0xc01ea000}, {0xc01ec000}, {0xc01ee000}, + {0xc01f0000}, {0xc01f2000}, {0xc01f4000}, {0xc01f6000}, + {0xc01f8000}, {0xc01fa000}, {0xc01fc000}, {0xc01fe000}, + {0xc0200000}, {0xc0202000}, {0xc0204000}, {0xc0206000}, + {0xc0208000}, {0xc020a000}, {0xc020c000}, {0xc020e000}, + {0xc0210000}, {0xc0212000}, {0xc0214000}, {0xc0216000}, + {0xc0218000}, {0xc021a000}, {0xc021c000}, {0xc021e000}, + {0xc0220000}, {0xc0222000}, {0xc0224000}, {0xc0226000}, + {0xc0228000}, {0xc022a000}, {0xc022c000}, {0xc022e000}, + {0xc0230000}, {0xc0232000}, {0xc0234000}, {0xc0236000}, + {0xc0238000}, {0xc023a000}, {0xc023c000}, {0xc023e000}, + {0xc0240000}, {0xc0242000}, {0xc0244000}, {0xc0246000}, + {0xc0248000}, {0xc024a000}, {0xc024c000}, {0xc024e000}, + {0xc0250000}, {0xc0252000}, {0xc0254000}, {0xc0256000}, + {0xc0258000}, {0xc025a000}, {0xc025c000}, {0xc025e000}, + {0xc0260000}, {0xc0262000}, {0xc0264000}, {0xc0266000}, + {0xc0268000}, {0xc026a000}, {0xc026c000}, {0xc026e000}, + {0xc0270000}, {0xc0272000}, {0xc0274000}, {0xc0276000}, + {0xc0278000}, {0xc027a000}, {0xc027c000}, {0xc027e000}, + {0xc0280000}, {0xc0282000}, {0xc0284000}, {0xc0286000}, + {0xc0288000}, {0xc028a000}, {0xc028c000}, {0xc028e000}, + {0xc0290000}, {0xc0292000}, {0xc0294000}, {0xc0296000}, + {0xc0298000}, {0xc029a000}, {0xc029c000}, {0xc029e000}, + {0xc02a0000}, {0xc02a2000}, {0xc02a4000}, {0xc02a6000}, + {0xc02a8000}, {0xc02aa000}, {0xc02ac000}, {0xc02ae000}, + {0xc02b0000}, {0xc02b2000}, {0xc02b4000}, {0xc02b6000}, + {0xc02b8000}, {0xc02ba000}, {0xc02bc000}, {0xc02be000}, + {0xc02c0000}, {0xc02c2000}, {0xc02c4000}, {0xc02c6000}, + {0xc02c8000}, {0xc02ca000}, {0xc02cc000}, {0xc02ce000}, + {0xc02d0000}, {0xc02d2000}, {0xc02d4000}, {0xc02d6000}, + {0xc02d8000}, {0xc02da000}, {0xc02dc000}, {0xc02de000}, + {0xc02e0000}, {0xc02e2000}, {0xc02e4000}, {0xc02e6000}, + {0xc02e8000}, {0xc02ea000}, {0xc02ec000}, {0xc02ee000}, + {0xc02f0000}, {0xc02f2000}, {0xc02f4000}, {0xc02f6000}, + {0xc02f8000}, {0xc02fa000}, {0xc02fc000}, {0xc02fe000}, + {0xc0300000}, {0xc0302000}, {0xc0304000}, {0xc0306000}, + {0xc0308000}, {0xc030a000}, {0xc030c000}, {0xc030e000}, + {0xc0310000}, {0xc0312000}, {0xc0314000}, {0xc0316000}, + {0xc0318000}, {0xc031a000}, {0xc031c000}, {0xc031e000}, + {0xc0320000}, {0xc0322000}, {0xc0324000}, {0xc0326000}, + {0xc0328000}, {0xc032a000}, {0xc032c000}, {0xc032e000}, + {0xc0330000}, {0xc0332000}, {0xc0334000}, {0xc0336000}, + {0xc0338000}, {0xc033a000}, {0xc033c000}, {0xc033e000}, + {0xc0340000}, {0xc0342000}, {0xc0344000}, {0xc0346000}, + {0xc0348000}, {0xc034a000}, {0xc034c000}, {0xc034e000}, + {0xc0350000}, {0xc0352000}, {0xc0354000}, {0xc0356000}, + {0xc0358000}, {0xc035a000}, {0xc035c000}, {0xc035e000}, + {0xc0360000}, {0xc0362000}, {0xc0364000}, {0xc0366000}, + {0xc0368000}, {0xc036a000}, {0xc036c000}, {0xc036e000}, + {0xc0370000}, {0xc0372000}, {0xc0374000}, {0xc0376000}, + {0xc0378000}, {0xc037a000}, {0xc037c000}, {0xc037e000}, + {0xc0380000}, {0xc0382000}, {0xc0384000}, {0xc0386000}, + {0xc0388000}, {0xc038a000}, {0xc038c000}, {0xc038e000}, + {0xc0390000}, {0xc0392000}, {0xc0394000}, {0xc0396000}, + {0xc0398000}, {0xc039a000}, {0xc039c000}, {0xc039e000}, + {0xc03a0000}, {0xc03a2000}, {0xc03a4000}, {0xc03a6000}, + {0xc03a8000}, {0xc03aa000}, {0xc03ac000}, {0xc03ae000}, + {0xc03b0000}, {0xc03b2000}, {0xc03b4000}, {0xc03b6000}, + {0xc03b8000}, {0xc03ba000}, {0xc03bc000}, {0xc03be000}, + {0xc03c0000}, {0xc03c2000}, {0xc03c4000}, {0xc03c6000}, + {0xc03c8000}, {0xc03ca000}, {0xc03cc000}, {0xc03ce000}, + {0xc03d0000}, {0xc03d2000}, {0xc03d4000}, {0xc03d6000}, + {0xc03d8000}, {0xc03da000}, {0xc03dc000}, {0xc03de000}, + {0xc03e0000}, {0xc03e2000}, {0xc03e4000}, {0xc03e6000}, + {0xc03e8000}, {0xc03ea000}, {0xc03ec000}, {0xc03ee000}, + {0xc03f0000}, {0xc03f2000}, {0xc03f4000}, {0xc03f6000}, + {0xc03f8000}, {0xc03fa000}, {0xc03fc000}, {0xc03fe000}, + {0xc0400000}, {0xc0402000}, {0xc0404000}, {0xc0406000}, + {0xc0408000}, {0xc040a000}, {0xc040c000}, {0xc040e000}, + {0xc0410000}, {0xc0412000}, {0xc0414000}, {0xc0416000}, + {0xc0418000}, {0xc041a000}, {0xc041c000}, {0xc041e000}, + {0xc0420000}, {0xc0422000}, {0xc0424000}, {0xc0426000}, + {0xc0428000}, {0xc042a000}, {0xc042c000}, {0xc042e000}, + {0xc0430000}, {0xc0432000}, {0xc0434000}, {0xc0436000}, + {0xc0438000}, {0xc043a000}, {0xc043c000}, {0xc043e000}, + {0xc0440000}, {0xc0442000}, {0xc0444000}, {0xc0446000}, + {0xc0448000}, {0xc044a000}, {0xc044c000}, {0xc044e000}, + {0xc0450000}, {0xc0452000}, {0xc0454000}, {0xc0456000}, + {0xc0458000}, {0xc045a000}, {0xc045c000}, {0xc045e000}, + {0xc0460000}, {0xc0462000}, {0xc0464000}, {0xc0466000}, + {0xc0468000}, {0xc046a000}, {0xc046c000}, {0xc046e000}, + {0xc0470000}, {0xc0472000}, {0xc0474000}, {0xc0476000}, + {0xc0478000}, {0xc047a000}, {0xc047c000}, {0xc047e000}, + {0xc0480000}, {0xc0482000}, {0xc0484000}, {0xc0486000}, + {0xc0488000}, {0xc048a000}, {0xc048c000}, {0xc048e000}, + {0xc0490000}, {0xc0492000}, {0xc0494000}, {0xc0496000}, + {0xc0498000}, {0xc049a000}, {0xc049c000}, {0xc049e000}, + {0xc04a0000}, {0xc04a2000}, {0xc04a4000}, {0xc04a6000}, + {0xc04a8000}, {0xc04aa000}, {0xc04ac000}, {0xc04ae000}, + {0xc04b0000}, {0xc04b2000}, {0xc04b4000}, {0xc04b6000}, + {0xc04b8000}, {0xc04ba000}, {0xc04bc000}, {0xc04be000}, + {0xc04c0000}, {0xc04c2000}, {0xc04c4000}, {0xc04c6000}, + {0xc04c8000}, {0xc04ca000}, {0xc04cc000}, {0xc04ce000}, + {0xc04d0000}, {0xc04d2000}, {0xc04d4000}, {0xc04d6000}, + {0xc04d8000}, {0xc04da000}, {0xc04dc000}, {0xc04de000}, + {0xc04e0000}, {0xc04e2000}, {0xc04e4000}, {0xc04e6000}, + {0xc04e8000}, {0xc04ea000}, {0xc04ec000}, {0xc04ee000}, + {0xc04f0000}, {0xc04f2000}, {0xc04f4000}, {0xc04f6000}, + {0xc04f8000}, {0xc04fa000}, {0xc04fc000}, {0xc04fe000}, + {0xc0500000}, {0xc0502000}, {0xc0504000}, {0xc0506000}, + {0xc0508000}, {0xc050a000}, {0xc050c000}, {0xc050e000}, + {0xc0510000}, {0xc0512000}, {0xc0514000}, {0xc0516000}, + {0xc0518000}, {0xc051a000}, {0xc051c000}, {0xc051e000}, + {0xc0520000}, {0xc0522000}, {0xc0524000}, {0xc0526000}, + {0xc0528000}, {0xc052a000}, {0xc052c000}, {0xc052e000}, + {0xc0530000}, {0xc0532000}, {0xc0534000}, {0xc0536000}, + {0xc0538000}, {0xc053a000}, {0xc053c000}, {0xc053e000}, + {0xc0540000}, {0xc0542000}, {0xc0544000}, {0xc0546000}, + {0xc0548000}, {0xc054a000}, {0xc054c000}, {0xc054e000}, + {0xc0550000}, {0xc0552000}, {0xc0554000}, {0xc0556000}, + {0xc0558000}, {0xc055a000}, {0xc055c000}, {0xc055e000}, + {0xc0560000}, {0xc0562000}, {0xc0564000}, {0xc0566000}, + {0xc0568000}, {0xc056a000}, {0xc056c000}, {0xc056e000}, + {0xc0570000}, {0xc0572000}, {0xc0574000}, {0xc0576000}, + {0xc0578000}, {0xc057a000}, {0xc057c000}, {0xc057e000}, + {0xc0580000}, {0xc0582000}, {0xc0584000}, {0xc0586000}, + {0xc0588000}, {0xc058a000}, {0xc058c000}, {0xc058e000}, + {0xc0590000}, {0xc0592000}, {0xc0594000}, {0xc0596000}, + {0xc0598000}, {0xc059a000}, {0xc059c000}, {0xc059e000}, + {0xc05a0000}, {0xc05a2000}, {0xc05a4000}, {0xc05a6000}, + {0xc05a8000}, {0xc05aa000}, {0xc05ac000}, {0xc05ae000}, + {0xc05b0000}, {0xc05b2000}, {0xc05b4000}, {0xc05b6000}, + {0xc05b8000}, {0xc05ba000}, {0xc05bc000}, {0xc05be000}, + {0xc05c0000}, {0xc05c2000}, {0xc05c4000}, {0xc05c6000}, + {0xc05c8000}, {0xc05ca000}, {0xc05cc000}, {0xc05ce000}, + {0xc05d0000}, {0xc05d2000}, {0xc05d4000}, {0xc05d6000}, + {0xc05d8000}, {0xc05da000}, {0xc05dc000}, {0xc05de000}, + {0xc05e0000}, {0xc05e2000}, {0xc05e4000}, {0xc05e6000}, + {0xc05e8000}, {0xc05ea000}, {0xc05ec000}, {0xc05ee000}, + {0xc05f0000}, {0xc05f2000}, {0xc05f4000}, {0xc05f6000}, + {0xc05f8000}, {0xc05fa000}, {0xc05fc000}, {0xc05fe000}, + {0xc0600000}, {0xc0602000}, {0xc0604000}, {0xc0606000}, + {0xc0608000}, {0xc060a000}, {0xc060c000}, {0xc060e000}, + {0xc0610000}, {0xc0612000}, {0xc0614000}, {0xc0616000}, + {0xc0618000}, {0xc061a000}, {0xc061c000}, {0xc061e000}, + {0xc0620000}, {0xc0622000}, {0xc0624000}, {0xc0626000}, + {0xc0628000}, {0xc062a000}, {0xc062c000}, {0xc062e000}, + {0xc0630000}, {0xc0632000}, {0xc0634000}, {0xc0636000}, + {0xc0638000}, {0xc063a000}, {0xc063c000}, {0xc063e000}, + {0xc0640000}, {0xc0642000}, {0xc0644000}, {0xc0646000}, + {0xc0648000}, {0xc064a000}, {0xc064c000}, {0xc064e000}, + {0xc0650000}, {0xc0652000}, {0xc0654000}, {0xc0656000}, + {0xc0658000}, {0xc065a000}, {0xc065c000}, {0xc065e000}, + {0xc0660000}, {0xc0662000}, {0xc0664000}, {0xc0666000}, + {0xc0668000}, {0xc066a000}, {0xc066c000}, {0xc066e000}, + {0xc0670000}, {0xc0672000}, {0xc0674000}, {0xc0676000}, + {0xc0678000}, {0xc067a000}, {0xc067c000}, {0xc067e000}, + {0xc0680000}, {0xc0682000}, {0xc0684000}, {0xc0686000}, + {0xc0688000}, {0xc068a000}, {0xc068c000}, {0xc068e000}, + {0xc0690000}, {0xc0692000}, {0xc0694000}, {0xc0696000}, + {0xc0698000}, {0xc069a000}, {0xc069c000}, {0xc069e000}, + {0xc06a0000}, {0xc06a2000}, {0xc06a4000}, {0xc06a6000}, + {0xc06a8000}, {0xc06aa000}, {0xc06ac000}, {0xc06ae000}, + {0xc06b0000}, {0xc06b2000}, {0xc06b4000}, {0xc06b6000}, + {0xc06b8000}, {0xc06ba000}, {0xc06bc000}, {0xc06be000}, + {0xc06c0000}, {0xc06c2000}, {0xc06c4000}, {0xc06c6000}, + {0xc06c8000}, {0xc06ca000}, {0xc06cc000}, {0xc06ce000}, + {0xc06d0000}, {0xc06d2000}, {0xc06d4000}, {0xc06d6000}, + {0xc06d8000}, {0xc06da000}, {0xc06dc000}, {0xc06de000}, + {0xc06e0000}, {0xc06e2000}, {0xc06e4000}, {0xc06e6000}, + {0xc06e8000}, {0xc06ea000}, {0xc06ec000}, {0xc06ee000}, + {0xc06f0000}, {0xc06f2000}, {0xc06f4000}, {0xc06f6000}, + {0xc06f8000}, {0xc06fa000}, {0xc06fc000}, {0xc06fe000}, + {0xc0700000}, {0xc0702000}, {0xc0704000}, {0xc0706000}, + {0xc0708000}, {0xc070a000}, {0xc070c000}, {0xc070e000}, + {0xc0710000}, {0xc0712000}, {0xc0714000}, {0xc0716000}, + {0xc0718000}, {0xc071a000}, {0xc071c000}, {0xc071e000}, + {0xc0720000}, {0xc0722000}, {0xc0724000}, {0xc0726000}, + {0xc0728000}, {0xc072a000}, {0xc072c000}, {0xc072e000}, + {0xc0730000}, {0xc0732000}, {0xc0734000}, {0xc0736000}, + {0xc0738000}, {0xc073a000}, {0xc073c000}, {0xc073e000}, + {0xc0740000}, {0xc0742000}, {0xc0744000}, {0xc0746000}, + {0xc0748000}, {0xc074a000}, {0xc074c000}, {0xc074e000}, + {0xc0750000}, {0xc0752000}, {0xc0754000}, {0xc0756000}, + {0xc0758000}, {0xc075a000}, {0xc075c000}, {0xc075e000}, + {0xc0760000}, {0xc0762000}, {0xc0764000}, {0xc0766000}, + {0xc0768000}, {0xc076a000}, {0xc076c000}, {0xc076e000}, + {0xc0770000}, {0xc0772000}, {0xc0774000}, {0xc0776000}, + {0xc0778000}, {0xc077a000}, {0xc077c000}, {0xc077e000}, + {0xc0780000}, {0xc0782000}, {0xc0784000}, {0xc0786000}, + {0xc0788000}, {0xc078a000}, {0xc078c000}, {0xc078e000}, + {0xc0790000}, {0xc0792000}, {0xc0794000}, {0xc0796000}, + {0xc0798000}, {0xc079a000}, {0xc079c000}, {0xc079e000}, + {0xc07a0000}, {0xc07a2000}, {0xc07a4000}, {0xc07a6000}, + {0xc07a8000}, {0xc07aa000}, {0xc07ac000}, {0xc07ae000}, + {0xc07b0000}, {0xc07b2000}, {0xc07b4000}, {0xc07b6000}, + {0xc07b8000}, {0xc07ba000}, {0xc07bc000}, {0xc07be000}, + {0xc07c0000}, {0xc07c2000}, {0xc07c4000}, {0xc07c6000}, + {0xc07c8000}, {0xc07ca000}, {0xc07cc000}, {0xc07ce000}, + {0xc07d0000}, {0xc07d2000}, {0xc07d4000}, {0xc07d6000}, + {0xc07d8000}, {0xc07da000}, {0xc07dc000}, {0xc07de000}, + {0xc07e0000}, {0xc07e2000}, {0xc07e4000}, {0xc07e6000}, + {0xc07e8000}, {0xc07ea000}, {0xc07ec000}, {0xc07ee000}, + {0xc07f0000}, {0xc07f2000}, {0xc07f4000}, {0xc07f6000}, + {0xc07f8000}, {0xc07fa000}, {0xc07fc000}, {0xc07fe000}, + {0xc0800000}, {0xc0802000}, {0xc0804000}, {0xc0806000}, + {0xc0808000}, {0xc080a000}, {0xc080c000}, {0xc080e000}, + {0xc0810000}, {0xc0812000}, {0xc0814000}, {0xc0816000}, + {0xc0818000}, {0xc081a000}, {0xc081c000}, {0xc081e000}, + {0xc0820000}, {0xc0822000}, {0xc0824000}, {0xc0826000}, + {0xc0828000}, {0xc082a000}, {0xc082c000}, {0xc082e000}, + {0xc0830000}, {0xc0832000}, {0xc0834000}, {0xc0836000}, + {0xc0838000}, {0xc083a000}, {0xc083c000}, {0xc083e000}, + {0xc0840000}, {0xc0842000}, {0xc0844000}, {0xc0846000}, + {0xc0848000}, {0xc084a000}, {0xc084c000}, {0xc084e000}, + {0xc0850000}, {0xc0852000}, {0xc0854000}, {0xc0856000}, + {0xc0858000}, {0xc085a000}, {0xc085c000}, {0xc085e000}, + {0xc0860000}, {0xc0862000}, {0xc0864000}, {0xc0866000}, + {0xc0868000}, {0xc086a000}, {0xc086c000}, {0xc086e000}, + {0xc0870000}, {0xc0872000}, {0xc0874000}, {0xc0876000}, + {0xc0878000}, {0xc087a000}, {0xc087c000}, {0xc087e000}, + {0xc0880000}, {0xc0882000}, {0xc0884000}, {0xc0886000}, + {0xc0888000}, {0xc088a000}, {0xc088c000}, {0xc088e000}, + {0xc0890000}, {0xc0892000}, {0xc0894000}, {0xc0896000}, + {0xc0898000}, {0xc089a000}, {0xc089c000}, {0xc089e000}, + {0xc08a0000}, {0xc08a2000}, {0xc08a4000}, {0xc08a6000}, + {0xc08a8000}, {0xc08aa000}, {0xc08ac000}, {0xc08ae000}, + {0xc08b0000}, {0xc08b2000}, {0xc08b4000}, {0xc08b6000}, + {0xc08b8000}, {0xc08ba000}, {0xc08bc000}, {0xc08be000}, + {0xc08c0000}, {0xc08c2000}, {0xc08c4000}, {0xc08c6000}, + {0xc08c8000}, {0xc08ca000}, {0xc08cc000}, {0xc08ce000}, + {0xc08d0000}, {0xc08d2000}, {0xc08d4000}, {0xc08d6000}, + {0xc08d8000}, {0xc08da000}, {0xc08dc000}, {0xc08de000}, + {0xc08e0000}, {0xc08e2000}, {0xc08e4000}, {0xc08e6000}, + {0xc08e8000}, {0xc08ea000}, {0xc08ec000}, {0xc08ee000}, + {0xc08f0000}, {0xc08f2000}, {0xc08f4000}, {0xc08f6000}, + {0xc08f8000}, {0xc08fa000}, {0xc08fc000}, {0xc08fe000}, + {0xc0900000}, {0xc0902000}, {0xc0904000}, {0xc0906000}, + {0xc0908000}, {0xc090a000}, {0xc090c000}, {0xc090e000}, + {0xc0910000}, {0xc0912000}, {0xc0914000}, {0xc0916000}, + {0xc0918000}, {0xc091a000}, {0xc091c000}, {0xc091e000}, + {0xc0920000}, {0xc0922000}, {0xc0924000}, {0xc0926000}, + {0xc0928000}, {0xc092a000}, {0xc092c000}, {0xc092e000}, + {0xc0930000}, {0xc0932000}, {0xc0934000}, {0xc0936000}, + {0xc0938000}, {0xc093a000}, {0xc093c000}, {0xc093e000}, + {0xc0940000}, {0xc0942000}, {0xc0944000}, {0xc0946000}, + {0xc0948000}, {0xc094a000}, {0xc094c000}, {0xc094e000}, + {0xc0950000}, {0xc0952000}, {0xc0954000}, {0xc0956000}, + {0xc0958000}, {0xc095a000}, {0xc095c000}, {0xc095e000}, + {0xc0960000}, {0xc0962000}, {0xc0964000}, {0xc0966000}, + {0xc0968000}, {0xc096a000}, {0xc096c000}, {0xc096e000}, + {0xc0970000}, {0xc0972000}, {0xc0974000}, {0xc0976000}, + {0xc0978000}, {0xc097a000}, {0xc097c000}, {0xc097e000}, + {0xc0980000}, {0xc0982000}, {0xc0984000}, {0xc0986000}, + {0xc0988000}, {0xc098a000}, {0xc098c000}, {0xc098e000}, + {0xc0990000}, {0xc0992000}, {0xc0994000}, {0xc0996000}, + {0xc0998000}, {0xc099a000}, {0xc099c000}, {0xc099e000}, + {0xc09a0000}, {0xc09a2000}, {0xc09a4000}, {0xc09a6000}, + {0xc09a8000}, {0xc09aa000}, {0xc09ac000}, {0xc09ae000}, + {0xc09b0000}, {0xc09b2000}, {0xc09b4000}, {0xc09b6000}, + {0xc09b8000}, {0xc09ba000}, {0xc09bc000}, {0xc09be000}, + {0xc09c0000}, {0xc09c2000}, {0xc09c4000}, {0xc09c6000}, + {0xc09c8000}, {0xc09ca000}, {0xc09cc000}, {0xc09ce000}, + {0xc09d0000}, {0xc09d2000}, {0xc09d4000}, {0xc09d6000}, + {0xc09d8000}, {0xc09da000}, {0xc09dc000}, {0xc09de000}, + {0xc09e0000}, {0xc09e2000}, {0xc09e4000}, {0xc09e6000}, + {0xc09e8000}, {0xc09ea000}, {0xc09ec000}, {0xc09ee000}, + {0xc09f0000}, {0xc09f2000}, {0xc09f4000}, {0xc09f6000}, + {0xc09f8000}, {0xc09fa000}, {0xc09fc000}, {0xc09fe000}, + {0xc0a00000}, {0xc0a02000}, {0xc0a04000}, {0xc0a06000}, + {0xc0a08000}, {0xc0a0a000}, {0xc0a0c000}, {0xc0a0e000}, + {0xc0a10000}, {0xc0a12000}, {0xc0a14000}, {0xc0a16000}, + {0xc0a18000}, {0xc0a1a000}, {0xc0a1c000}, {0xc0a1e000}, + {0xc0a20000}, {0xc0a22000}, {0xc0a24000}, {0xc0a26000}, + {0xc0a28000}, {0xc0a2a000}, {0xc0a2c000}, {0xc0a2e000}, + {0xc0a30000}, {0xc0a32000}, {0xc0a34000}, {0xc0a36000}, + {0xc0a38000}, {0xc0a3a000}, {0xc0a3c000}, {0xc0a3e000}, + {0xc0a40000}, {0xc0a42000}, {0xc0a44000}, {0xc0a46000}, + {0xc0a48000}, {0xc0a4a000}, {0xc0a4c000}, {0xc0a4e000}, + {0xc0a50000}, {0xc0a52000}, {0xc0a54000}, {0xc0a56000}, + {0xc0a58000}, {0xc0a5a000}, {0xc0a5c000}, {0xc0a5e000}, + {0xc0a60000}, {0xc0a62000}, {0xc0a64000}, {0xc0a66000}, + {0xc0a68000}, {0xc0a6a000}, {0xc0a6c000}, {0xc0a6e000}, + {0xc0a70000}, {0xc0a72000}, {0xc0a74000}, {0xc0a76000}, + {0xc0a78000}, {0xc0a7a000}, {0xc0a7c000}, {0xc0a7e000}, + {0xc0a80000}, {0xc0a82000}, {0xc0a84000}, {0xc0a86000}, + {0xc0a88000}, {0xc0a8a000}, {0xc0a8c000}, {0xc0a8e000}, + {0xc0a90000}, {0xc0a92000}, {0xc0a94000}, {0xc0a96000}, + {0xc0a98000}, {0xc0a9a000}, {0xc0a9c000}, {0xc0a9e000}, + {0xc0aa0000}, {0xc0aa2000}, {0xc0aa4000}, {0xc0aa6000}, + {0xc0aa8000}, {0xc0aaa000}, {0xc0aac000}, {0xc0aae000}, + {0xc0ab0000}, {0xc0ab2000}, {0xc0ab4000}, {0xc0ab6000}, + {0xc0ab8000}, {0xc0aba000}, {0xc0abc000}, {0xc0abe000}, + {0xc0ac0000}, {0xc0ac2000}, {0xc0ac4000}, {0xc0ac6000}, + {0xc0ac8000}, {0xc0aca000}, {0xc0acc000}, {0xc0ace000}, + {0xc0ad0000}, {0xc0ad2000}, {0xc0ad4000}, {0xc0ad6000}, + {0xc0ad8000}, {0xc0ada000}, {0xc0adc000}, {0xc0ade000}, + {0xc0ae0000}, {0xc0ae2000}, {0xc0ae4000}, {0xc0ae6000}, + {0xc0ae8000}, {0xc0aea000}, {0xc0aec000}, {0xc0aee000}, + {0xc0af0000}, {0xc0af2000}, {0xc0af4000}, {0xc0af6000}, + {0xc0af8000}, {0xc0afa000}, {0xc0afc000}, {0xc0afe000}, + {0xc0b00000}, {0xc0b02000}, {0xc0b04000}, {0xc0b06000}, + {0xc0b08000}, {0xc0b0a000}, {0xc0b0c000}, {0xc0b0e000}, + {0xc0b10000}, {0xc0b12000}, {0xc0b14000}, {0xc0b16000}, + {0xc0b18000}, {0xc0b1a000}, {0xc0b1c000}, {0xc0b1e000}, + {0xc0b20000}, {0xc0b22000}, {0xc0b24000}, {0xc0b26000}, + {0xc0b28000}, {0xc0b2a000}, {0xc0b2c000}, {0xc0b2e000}, + {0xc0b30000}, {0xc0b32000}, {0xc0b34000}, {0xc0b36000}, + {0xc0b38000}, {0xc0b3a000}, {0xc0b3c000}, {0xc0b3e000}, + {0xc0b40000}, {0xc0b42000}, {0xc0b44000}, {0xc0b46000}, + {0xc0b48000}, {0xc0b4a000}, {0xc0b4c000}, {0xc0b4e000}, + {0xc0b50000}, {0xc0b52000}, {0xc0b54000}, {0xc0b56000}, + {0xc0b58000}, {0xc0b5a000}, {0xc0b5c000}, {0xc0b5e000}, + {0xc0b60000}, {0xc0b62000}, {0xc0b64000}, {0xc0b66000}, + {0xc0b68000}, {0xc0b6a000}, {0xc0b6c000}, {0xc0b6e000}, + {0xc0b70000}, {0xc0b72000}, {0xc0b74000}, {0xc0b76000}, + {0xc0b78000}, {0xc0b7a000}, {0xc0b7c000}, {0xc0b7e000}, + {0xc0b80000}, {0xc0b82000}, {0xc0b84000}, {0xc0b86000}, + {0xc0b88000}, {0xc0b8a000}, {0xc0b8c000}, {0xc0b8e000}, + {0xc0b90000}, {0xc0b92000}, {0xc0b94000}, {0xc0b96000}, + {0xc0b98000}, {0xc0b9a000}, {0xc0b9c000}, {0xc0b9e000}, + {0xc0ba0000}, {0xc0ba2000}, {0xc0ba4000}, {0xc0ba6000}, + {0xc0ba8000}, {0xc0baa000}, {0xc0bac000}, {0xc0bae000}, + {0xc0bb0000}, {0xc0bb2000}, {0xc0bb4000}, {0xc0bb6000}, + {0xc0bb8000}, {0xc0bba000}, {0xc0bbc000}, {0xc0bbe000}, + {0xc0bc0000}, {0xc0bc2000}, {0xc0bc4000}, {0xc0bc6000}, + {0xc0bc8000}, {0xc0bca000}, {0xc0bcc000}, {0xc0bce000}, + {0xc0bd0000}, {0xc0bd2000}, {0xc0bd4000}, {0xc0bd6000}, + {0xc0bd8000}, {0xc0bda000}, {0xc0bdc000}, {0xc0bde000}, + {0xc0be0000}, {0xc0be2000}, {0xc0be4000}, {0xc0be6000}, + {0xc0be8000}, {0xc0bea000}, {0xc0bec000}, {0xc0bee000}, + {0xc0bf0000}, {0xc0bf2000}, {0xc0bf4000}, {0xc0bf6000}, + {0xc0bf8000}, {0xc0bfa000}, {0xc0bfc000}, {0xc0bfe000}, + {0xc0c00000}, {0xc0c02000}, {0xc0c04000}, {0xc0c06000}, + {0xc0c08000}, {0xc0c0a000}, {0xc0c0c000}, {0xc0c0e000}, + {0xc0c10000}, {0xc0c12000}, {0xc0c14000}, {0xc0c16000}, + {0xc0c18000}, {0xc0c1a000}, {0xc0c1c000}, {0xc0c1e000}, + {0xc0c20000}, {0xc0c22000}, {0xc0c24000}, {0xc0c26000}, + {0xc0c28000}, {0xc0c2a000}, {0xc0c2c000}, {0xc0c2e000}, + {0xc0c30000}, {0xc0c32000}, {0xc0c34000}, {0xc0c36000}, + {0xc0c38000}, {0xc0c3a000}, {0xc0c3c000}, {0xc0c3e000}, + {0xc0c40000}, {0xc0c42000}, {0xc0c44000}, {0xc0c46000}, + {0xc0c48000}, {0xc0c4a000}, {0xc0c4c000}, {0xc0c4e000}, + {0xc0c50000}, {0xc0c52000}, {0xc0c54000}, {0xc0c56000}, + {0xc0c58000}, {0xc0c5a000}, {0xc0c5c000}, {0xc0c5e000}, + {0xc0c60000}, {0xc0c62000}, {0xc0c64000}, {0xc0c66000}, + {0xc0c68000}, {0xc0c6a000}, {0xc0c6c000}, {0xc0c6e000}, + {0xc0c70000}, {0xc0c72000}, {0xc0c74000}, {0xc0c76000}, + {0xc0c78000}, {0xc0c7a000}, {0xc0c7c000}, {0xc0c7e000}, + {0xc0c80000}, {0xc0c82000}, {0xc0c84000}, {0xc0c86000}, + {0xc0c88000}, {0xc0c8a000}, {0xc0c8c000}, {0xc0c8e000}, + {0xc0c90000}, {0xc0c92000}, {0xc0c94000}, {0xc0c96000}, + {0xc0c98000}, {0xc0c9a000}, {0xc0c9c000}, {0xc0c9e000}, + {0xc0ca0000}, {0xc0ca2000}, {0xc0ca4000}, {0xc0ca6000}, + {0xc0ca8000}, {0xc0caa000}, {0xc0cac000}, {0xc0cae000}, + {0xc0cb0000}, {0xc0cb2000}, {0xc0cb4000}, {0xc0cb6000}, + {0xc0cb8000}, {0xc0cba000}, {0xc0cbc000}, {0xc0cbe000}, + {0xc0cc0000}, {0xc0cc2000}, {0xc0cc4000}, {0xc0cc6000}, + {0xc0cc8000}, {0xc0cca000}, {0xc0ccc000}, {0xc0cce000}, + {0xc0cd0000}, {0xc0cd2000}, {0xc0cd4000}, {0xc0cd6000}, + {0xc0cd8000}, {0xc0cda000}, {0xc0cdc000}, {0xc0cde000}, + {0xc0ce0000}, {0xc0ce2000}, {0xc0ce4000}, {0xc0ce6000}, + {0xc0ce8000}, {0xc0cea000}, {0xc0cec000}, {0xc0cee000}, + {0xc0cf0000}, {0xc0cf2000}, {0xc0cf4000}, {0xc0cf6000}, + {0xc0cf8000}, {0xc0cfa000}, {0xc0cfc000}, {0xc0cfe000}, + {0xc0d00000}, {0xc0d02000}, {0xc0d04000}, {0xc0d06000}, + {0xc0d08000}, {0xc0d0a000}, {0xc0d0c000}, {0xc0d0e000}, + {0xc0d10000}, {0xc0d12000}, {0xc0d14000}, {0xc0d16000}, + {0xc0d18000}, {0xc0d1a000}, {0xc0d1c000}, {0xc0d1e000}, + {0xc0d20000}, {0xc0d22000}, {0xc0d24000}, {0xc0d26000}, + {0xc0d28000}, {0xc0d2a000}, {0xc0d2c000}, {0xc0d2e000}, + {0xc0d30000}, {0xc0d32000}, {0xc0d34000}, {0xc0d36000}, + {0xc0d38000}, {0xc0d3a000}, {0xc0d3c000}, {0xc0d3e000}, + {0xc0d40000}, {0xc0d42000}, {0xc0d44000}, {0xc0d46000}, + {0xc0d48000}, {0xc0d4a000}, {0xc0d4c000}, {0xc0d4e000}, + {0xc0d50000}, {0xc0d52000}, {0xc0d54000}, {0xc0d56000}, + {0xc0d58000}, {0xc0d5a000}, {0xc0d5c000}, {0xc0d5e000}, + {0xc0d60000}, {0xc0d62000}, {0xc0d64000}, {0xc0d66000}, + {0xc0d68000}, {0xc0d6a000}, {0xc0d6c000}, {0xc0d6e000}, + {0xc0d70000}, {0xc0d72000}, {0xc0d74000}, {0xc0d76000}, + {0xc0d78000}, {0xc0d7a000}, {0xc0d7c000}, {0xc0d7e000}, + {0xc0d80000}, {0xc0d82000}, {0xc0d84000}, {0xc0d86000}, + {0xc0d88000}, {0xc0d8a000}, {0xc0d8c000}, {0xc0d8e000}, + {0xc0d90000}, {0xc0d92000}, {0xc0d94000}, {0xc0d96000}, + {0xc0d98000}, {0xc0d9a000}, {0xc0d9c000}, {0xc0d9e000}, + {0xc0da0000}, {0xc0da2000}, {0xc0da4000}, {0xc0da6000}, + {0xc0da8000}, {0xc0daa000}, {0xc0dac000}, {0xc0dae000}, + {0xc0db0000}, {0xc0db2000}, {0xc0db4000}, {0xc0db6000}, + {0xc0db8000}, {0xc0dba000}, {0xc0dbc000}, {0xc0dbe000}, + {0xc0dc0000}, {0xc0dc2000}, {0xc0dc4000}, {0xc0dc6000}, + {0xc0dc8000}, {0xc0dca000}, {0xc0dcc000}, {0xc0dce000}, + {0xc0dd0000}, {0xc0dd2000}, {0xc0dd4000}, {0xc0dd6000}, + {0xc0dd8000}, {0xc0dda000}, {0xc0ddc000}, {0xc0dde000}, + {0xc0de0000}, {0xc0de2000}, {0xc0de4000}, {0xc0de6000}, + {0xc0de8000}, {0xc0dea000}, {0xc0dec000}, {0xc0dee000}, + {0xc0df0000}, {0xc0df2000}, {0xc0df4000}, {0xc0df6000}, + {0xc0df8000}, {0xc0dfa000}, {0xc0dfc000}, {0xc0dfe000}, + {0xc0e00000}, {0xc0e02000}, {0xc0e04000}, {0xc0e06000}, + {0xc0e08000}, {0xc0e0a000}, {0xc0e0c000}, {0xc0e0e000}, + {0xc0e10000}, {0xc0e12000}, {0xc0e14000}, {0xc0e16000}, + {0xc0e18000}, {0xc0e1a000}, {0xc0e1c000}, {0xc0e1e000}, + {0xc0e20000}, {0xc0e22000}, {0xc0e24000}, {0xc0e26000}, + {0xc0e28000}, {0xc0e2a000}, {0xc0e2c000}, {0xc0e2e000}, + {0xc0e30000}, {0xc0e32000}, {0xc0e34000}, {0xc0e36000}, + {0xc0e38000}, {0xc0e3a000}, {0xc0e3c000}, {0xc0e3e000}, + {0xc0e40000}, {0xc0e42000}, {0xc0e44000}, {0xc0e46000}, + {0xc0e48000}, {0xc0e4a000}, {0xc0e4c000}, {0xc0e4e000}, + {0xc0e50000}, {0xc0e52000}, {0xc0e54000}, {0xc0e56000}, + {0xc0e58000}, {0xc0e5a000}, {0xc0e5c000}, {0xc0e5e000}, + {0xc0e60000}, {0xc0e62000}, {0xc0e64000}, {0xc0e66000}, + {0xc0e68000}, {0xc0e6a000}, {0xc0e6c000}, {0xc0e6e000}, + {0xc0e70000}, {0xc0e72000}, {0xc0e74000}, {0xc0e76000}, + {0xc0e78000}, {0xc0e7a000}, {0xc0e7c000}, {0xc0e7e000}, + {0xc0e80000}, {0xc0e82000}, {0xc0e84000}, {0xc0e86000}, + {0xc0e88000}, {0xc0e8a000}, {0xc0e8c000}, {0xc0e8e000}, + {0xc0e90000}, {0xc0e92000}, {0xc0e94000}, {0xc0e96000}, + {0xc0e98000}, {0xc0e9a000}, {0xc0e9c000}, {0xc0e9e000}, + {0xc0ea0000}, {0xc0ea2000}, {0xc0ea4000}, {0xc0ea6000}, + {0xc0ea8000}, {0xc0eaa000}, {0xc0eac000}, {0xc0eae000}, + {0xc0eb0000}, {0xc0eb2000}, {0xc0eb4000}, {0xc0eb6000}, + {0xc0eb8000}, {0xc0eba000}, {0xc0ebc000}, {0xc0ebe000}, + {0xc0ec0000}, {0xc0ec2000}, {0xc0ec4000}, {0xc0ec6000}, + {0xc0ec8000}, {0xc0eca000}, {0xc0ecc000}, {0xc0ece000}, + {0xc0ed0000}, {0xc0ed2000}, {0xc0ed4000}, {0xc0ed6000}, + {0xc0ed8000}, {0xc0eda000}, {0xc0edc000}, {0xc0ede000}, + {0xc0ee0000}, {0xc0ee2000}, {0xc0ee4000}, {0xc0ee6000}, + {0xc0ee8000}, {0xc0eea000}, {0xc0eec000}, {0xc0eee000}, + {0xc0ef0000}, {0xc0ef2000}, {0xc0ef4000}, {0xc0ef6000}, + {0xc0ef8000}, {0xc0efa000}, {0xc0efc000}, {0xc0efe000}, + {0xc0f00000}, {0xc0f02000}, {0xc0f04000}, {0xc0f06000}, + {0xc0f08000}, {0xc0f0a000}, {0xc0f0c000}, {0xc0f0e000}, + {0xc0f10000}, {0xc0f12000}, {0xc0f14000}, {0xc0f16000}, + {0xc0f18000}, {0xc0f1a000}, {0xc0f1c000}, {0xc0f1e000}, + {0xc0f20000}, {0xc0f22000}, {0xc0f24000}, {0xc0f26000}, + {0xc0f28000}, {0xc0f2a000}, {0xc0f2c000}, {0xc0f2e000}, + {0xc0f30000}, {0xc0f32000}, {0xc0f34000}, {0xc0f36000}, + {0xc0f38000}, {0xc0f3a000}, {0xc0f3c000}, {0xc0f3e000}, + {0xc0f40000}, {0xc0f42000}, {0xc0f44000}, {0xc0f46000}, + {0xc0f48000}, {0xc0f4a000}, {0xc0f4c000}, {0xc0f4e000}, + {0xc0f50000}, {0xc0f52000}, {0xc0f54000}, {0xc0f56000}, + {0xc0f58000}, {0xc0f5a000}, {0xc0f5c000}, {0xc0f5e000}, + {0xc0f60000}, {0xc0f62000}, {0xc0f64000}, {0xc0f66000}, + {0xc0f68000}, {0xc0f6a000}, {0xc0f6c000}, {0xc0f6e000}, + {0xc0f70000}, {0xc0f72000}, {0xc0f74000}, {0xc0f76000}, + {0xc0f78000}, {0xc0f7a000}, {0xc0f7c000}, {0xc0f7e000}, + {0xc0f80000}, {0xc0f82000}, {0xc0f84000}, {0xc0f86000}, + {0xc0f88000}, {0xc0f8a000}, {0xc0f8c000}, {0xc0f8e000}, + {0xc0f90000}, {0xc0f92000}, {0xc0f94000}, {0xc0f96000}, + {0xc0f98000}, {0xc0f9a000}, {0xc0f9c000}, {0xc0f9e000}, + {0xc0fa0000}, {0xc0fa2000}, {0xc0fa4000}, {0xc0fa6000}, + {0xc0fa8000}, {0xc0faa000}, {0xc0fac000}, {0xc0fae000}, + {0xc0fb0000}, {0xc0fb2000}, {0xc0fb4000}, {0xc0fb6000}, + {0xc0fb8000}, {0xc0fba000}, {0xc0fbc000}, {0xc0fbe000}, + {0xc0fc0000}, {0xc0fc2000}, {0xc0fc4000}, {0xc0fc6000}, + {0xc0fc8000}, {0xc0fca000}, {0xc0fcc000}, {0xc0fce000}, + {0xc0fd0000}, {0xc0fd2000}, {0xc0fd4000}, {0xc0fd6000}, + {0xc0fd8000}, {0xc0fda000}, {0xc0fdc000}, {0xc0fde000}, + {0xc0fe0000}, {0xc0fe2000}, {0xc0fe4000}, {0xc0fe6000}, + {0xc0fe8000}, {0xc0fea000}, {0xc0fec000}, {0xc0fee000}, + {0xc0ff0000}, {0xc0ff2000}, {0xc0ff4000}, {0xc0ff6000}, + {0xc0ff8000}, {0xc0ffa000}, {0xc0ffc000}, {0xc0ffe000}, + {0xc1000000}, {0xc1002000}, {0xc1004000}, {0xc1006000}, + {0xc1008000}, {0xc100a000}, {0xc100c000}, {0xc100e000}, + {0xc1010000}, {0xc1012000}, {0xc1014000}, {0xc1016000}, + {0xc1018000}, {0xc101a000}, {0xc101c000}, {0xc101e000}, + {0xc1020000}, {0xc1022000}, {0xc1024000}, {0xc1026000}, + {0xc1028000}, {0xc102a000}, {0xc102c000}, {0xc102e000}, + {0xc1030000}, {0xc1032000}, {0xc1034000}, {0xc1036000}, + {0xc1038000}, {0xc103a000}, {0xc103c000}, {0xc103e000}, + {0xc1040000}, {0xc1042000}, {0xc1044000}, {0xc1046000}, + {0xc1048000}, {0xc104a000}, {0xc104c000}, {0xc104e000}, + {0xc1050000}, {0xc1052000}, {0xc1054000}, {0xc1056000}, + {0xc1058000}, {0xc105a000}, {0xc105c000}, {0xc105e000}, + {0xc1060000}, {0xc1062000}, {0xc1064000}, {0xc1066000}, + {0xc1068000}, {0xc106a000}, {0xc106c000}, {0xc106e000}, + {0xc1070000}, {0xc1072000}, {0xc1074000}, {0xc1076000}, + {0xc1078000}, {0xc107a000}, {0xc107c000}, {0xc107e000}, + {0xc1080000}, {0xc1082000}, {0xc1084000}, {0xc1086000}, + {0xc1088000}, {0xc108a000}, {0xc108c000}, {0xc108e000}, + {0xc1090000}, {0xc1092000}, {0xc1094000}, {0xc1096000}, + {0xc1098000}, {0xc109a000}, {0xc109c000}, {0xc109e000}, + {0xc10a0000}, {0xc10a2000}, {0xc10a4000}, {0xc10a6000}, + {0xc10a8000}, {0xc10aa000}, {0xc10ac000}, {0xc10ae000}, + {0xc10b0000}, {0xc10b2000}, {0xc10b4000}, {0xc10b6000}, + {0xc10b8000}, {0xc10ba000}, {0xc10bc000}, {0xc10be000}, + {0xc10c0000}, {0xc10c2000}, {0xc10c4000}, {0xc10c6000}, + {0xc10c8000}, {0xc10ca000}, {0xc10cc000}, {0xc10ce000}, + {0xc10d0000}, {0xc10d2000}, {0xc10d4000}, {0xc10d6000}, + {0xc10d8000}, {0xc10da000}, {0xc10dc000}, {0xc10de000}, + {0xc10e0000}, {0xc10e2000}, {0xc10e4000}, {0xc10e6000}, + {0xc10e8000}, {0xc10ea000}, {0xc10ec000}, {0xc10ee000}, + {0xc10f0000}, {0xc10f2000}, {0xc10f4000}, {0xc10f6000}, + {0xc10f8000}, {0xc10fa000}, {0xc10fc000}, {0xc10fe000}, + {0xc1100000}, {0xc1102000}, {0xc1104000}, {0xc1106000}, + {0xc1108000}, {0xc110a000}, {0xc110c000}, {0xc110e000}, + {0xc1110000}, {0xc1112000}, {0xc1114000}, {0xc1116000}, + {0xc1118000}, {0xc111a000}, {0xc111c000}, {0xc111e000}, + {0xc1120000}, {0xc1122000}, {0xc1124000}, {0xc1126000}, + {0xc1128000}, {0xc112a000}, {0xc112c000}, {0xc112e000}, + {0xc1130000}, {0xc1132000}, {0xc1134000}, {0xc1136000}, + {0xc1138000}, {0xc113a000}, {0xc113c000}, {0xc113e000}, + {0xc1140000}, {0xc1142000}, {0xc1144000}, {0xc1146000}, + {0xc1148000}, {0xc114a000}, {0xc114c000}, {0xc114e000}, + {0xc1150000}, {0xc1152000}, {0xc1154000}, {0xc1156000}, + {0xc1158000}, {0xc115a000}, {0xc115c000}, {0xc115e000}, + {0xc1160000}, {0xc1162000}, {0xc1164000}, {0xc1166000}, + {0xc1168000}, {0xc116a000}, {0xc116c000}, {0xc116e000}, + {0xc1170000}, {0xc1172000}, {0xc1174000}, {0xc1176000}, + {0xc1178000}, {0xc117a000}, {0xc117c000}, {0xc117e000}, + {0xc1180000}, {0xc1182000}, {0xc1184000}, {0xc1186000}, + {0xc1188000}, {0xc118a000}, {0xc118c000}, {0xc118e000}, + {0xc1190000}, {0xc1192000}, {0xc1194000}, {0xc1196000}, + {0xc1198000}, {0xc119a000}, {0xc119c000}, {0xc119e000}, + {0xc11a0000}, {0xc11a2000}, {0xc11a4000}, {0xc11a6000}, + {0xc11a8000}, {0xc11aa000}, {0xc11ac000}, {0xc11ae000}, + {0xc11b0000}, {0xc11b2000}, {0xc11b4000}, {0xc11b6000}, + {0xc11b8000}, {0xc11ba000}, {0xc11bc000}, {0xc11be000}, + {0xc11c0000}, {0xc11c2000}, {0xc11c4000}, {0xc11c6000}, + {0xc11c8000}, {0xc11ca000}, {0xc11cc000}, {0xc11ce000}, + {0xc11d0000}, {0xc11d2000}, {0xc11d4000}, {0xc11d6000}, + {0xc11d8000}, {0xc11da000}, {0xc11dc000}, {0xc11de000}, + {0xc11e0000}, {0xc11e2000}, {0xc11e4000}, {0xc11e6000}, + {0xc11e8000}, {0xc11ea000}, {0xc11ec000}, {0xc11ee000}, + {0xc11f0000}, {0xc11f2000}, {0xc11f4000}, {0xc11f6000}, + {0xc11f8000}, {0xc11fa000}, {0xc11fc000}, {0xc11fe000}, + {0xc1200000}, {0xc1202000}, {0xc1204000}, {0xc1206000}, + {0xc1208000}, {0xc120a000}, {0xc120c000}, {0xc120e000}, + {0xc1210000}, {0xc1212000}, {0xc1214000}, {0xc1216000}, + {0xc1218000}, {0xc121a000}, {0xc121c000}, {0xc121e000}, + {0xc1220000}, {0xc1222000}, {0xc1224000}, {0xc1226000}, + {0xc1228000}, {0xc122a000}, {0xc122c000}, {0xc122e000}, + {0xc1230000}, {0xc1232000}, {0xc1234000}, {0xc1236000}, + {0xc1238000}, {0xc123a000}, {0xc123c000}, {0xc123e000}, + {0xc1240000}, {0xc1242000}, {0xc1244000}, {0xc1246000}, + {0xc1248000}, {0xc124a000}, {0xc124c000}, {0xc124e000}, + {0xc1250000}, {0xc1252000}, {0xc1254000}, {0xc1256000}, + {0xc1258000}, {0xc125a000}, {0xc125c000}, {0xc125e000}, + {0xc1260000}, {0xc1262000}, {0xc1264000}, {0xc1266000}, + {0xc1268000}, {0xc126a000}, {0xc126c000}, {0xc126e000}, + {0xc1270000}, {0xc1272000}, {0xc1274000}, {0xc1276000}, + {0xc1278000}, {0xc127a000}, {0xc127c000}, {0xc127e000}, + {0xc1280000}, {0xc1282000}, {0xc1284000}, {0xc1286000}, + {0xc1288000}, {0xc128a000}, {0xc128c000}, {0xc128e000}, + {0xc1290000}, {0xc1292000}, {0xc1294000}, {0xc1296000}, + {0xc1298000}, {0xc129a000}, {0xc129c000}, {0xc129e000}, + {0xc12a0000}, {0xc12a2000}, {0xc12a4000}, {0xc12a6000}, + {0xc12a8000}, {0xc12aa000}, {0xc12ac000}, {0xc12ae000}, + {0xc12b0000}, {0xc12b2000}, {0xc12b4000}, {0xc12b6000}, + {0xc12b8000}, {0xc12ba000}, {0xc12bc000}, {0xc12be000}, + {0xc12c0000}, {0xc12c2000}, {0xc12c4000}, {0xc12c6000}, + {0xc12c8000}, {0xc12ca000}, {0xc12cc000}, {0xc12ce000}, + {0xc12d0000}, {0xc12d2000}, {0xc12d4000}, {0xc12d6000}, + {0xc12d8000}, {0xc12da000}, {0xc12dc000}, {0xc12de000}, + {0xc12e0000}, {0xc12e2000}, {0xc12e4000}, {0xc12e6000}, + {0xc12e8000}, {0xc12ea000}, {0xc12ec000}, {0xc12ee000}, + {0xc12f0000}, {0xc12f2000}, {0xc12f4000}, {0xc12f6000}, + {0xc12f8000}, {0xc12fa000}, {0xc12fc000}, {0xc12fe000}, + {0xc1300000}, {0xc1302000}, {0xc1304000}, {0xc1306000}, + {0xc1308000}, {0xc130a000}, {0xc130c000}, {0xc130e000}, + {0xc1310000}, {0xc1312000}, {0xc1314000}, {0xc1316000}, + {0xc1318000}, {0xc131a000}, {0xc131c000}, {0xc131e000}, + {0xc1320000}, {0xc1322000}, {0xc1324000}, {0xc1326000}, + {0xc1328000}, {0xc132a000}, {0xc132c000}, {0xc132e000}, + {0xc1330000}, {0xc1332000}, {0xc1334000}, {0xc1336000}, + {0xc1338000}, {0xc133a000}, {0xc133c000}, {0xc133e000}, + {0xc1340000}, {0xc1342000}, {0xc1344000}, {0xc1346000}, + {0xc1348000}, {0xc134a000}, {0xc134c000}, {0xc134e000}, + {0xc1350000}, {0xc1352000}, {0xc1354000}, {0xc1356000}, + {0xc1358000}, {0xc135a000}, {0xc135c000}, {0xc135e000}, + {0xc1360000}, {0xc1362000}, {0xc1364000}, {0xc1366000}, + {0xc1368000}, {0xc136a000}, {0xc136c000}, {0xc136e000}, + {0xc1370000}, {0xc1372000}, {0xc1374000}, {0xc1376000}, + {0xc1378000}, {0xc137a000}, {0xc137c000}, {0xc137e000}, + {0xc1380000}, {0xc1382000}, {0xc1384000}, {0xc1386000}, + {0xc1388000}, {0xc138a000}, {0xc138c000}, {0xc138e000}, + {0xc1390000}, {0xc1392000}, {0xc1394000}, {0xc1396000}, + {0xc1398000}, {0xc139a000}, {0xc139c000}, {0xc139e000}, + {0xc13a0000}, {0xc13a2000}, {0xc13a4000}, {0xc13a6000}, + {0xc13a8000}, {0xc13aa000}, {0xc13ac000}, {0xc13ae000}, + {0xc13b0000}, {0xc13b2000}, {0xc13b4000}, {0xc13b6000}, + {0xc13b8000}, {0xc13ba000}, {0xc13bc000}, {0xc13be000}, + {0xc13c0000}, {0xc13c2000}, {0xc13c4000}, {0xc13c6000}, + {0xc13c8000}, {0xc13ca000}, {0xc13cc000}, {0xc13ce000}, + {0xc13d0000}, {0xc13d2000}, {0xc13d4000}, {0xc13d6000}, + {0xc13d8000}, {0xc13da000}, {0xc13dc000}, {0xc13de000}, + {0xc13e0000}, {0xc13e2000}, {0xc13e4000}, {0xc13e6000}, + {0xc13e8000}, {0xc13ea000}, {0xc13ec000}, {0xc13ee000}, + {0xc13f0000}, {0xc13f2000}, {0xc13f4000}, {0xc13f6000}, + {0xc13f8000}, {0xc13fa000}, {0xc13fc000}, {0xc13fe000}, + {0xc1400000}, {0xc1402000}, {0xc1404000}, {0xc1406000}, + {0xc1408000}, {0xc140a000}, {0xc140c000}, {0xc140e000}, + {0xc1410000}, {0xc1412000}, {0xc1414000}, {0xc1416000}, + {0xc1418000}, {0xc141a000}, {0xc141c000}, {0xc141e000}, + {0xc1420000}, {0xc1422000}, {0xc1424000}, {0xc1426000}, + {0xc1428000}, {0xc142a000}, {0xc142c000}, {0xc142e000}, + {0xc1430000}, {0xc1432000}, {0xc1434000}, {0xc1436000}, + {0xc1438000}, {0xc143a000}, {0xc143c000}, {0xc143e000}, + {0xc1440000}, {0xc1442000}, {0xc1444000}, {0xc1446000}, + {0xc1448000}, {0xc144a000}, {0xc144c000}, {0xc144e000}, + {0xc1450000}, {0xc1452000}, {0xc1454000}, {0xc1456000}, + {0xc1458000}, {0xc145a000}, {0xc145c000}, {0xc145e000}, + {0xc1460000}, {0xc1462000}, {0xc1464000}, {0xc1466000}, + {0xc1468000}, {0xc146a000}, {0xc146c000}, {0xc146e000}, + {0xc1470000}, {0xc1472000}, {0xc1474000}, {0xc1476000}, + {0xc1478000}, {0xc147a000}, {0xc147c000}, {0xc147e000}, + {0xc1480000}, {0xc1482000}, {0xc1484000}, {0xc1486000}, + {0xc1488000}, {0xc148a000}, {0xc148c000}, {0xc148e000}, + {0xc1490000}, {0xc1492000}, {0xc1494000}, {0xc1496000}, + {0xc1498000}, {0xc149a000}, {0xc149c000}, {0xc149e000}, + {0xc14a0000}, {0xc14a2000}, {0xc14a4000}, {0xc14a6000}, + {0xc14a8000}, {0xc14aa000}, {0xc14ac000}, {0xc14ae000}, + {0xc14b0000}, {0xc14b2000}, {0xc14b4000}, {0xc14b6000}, + {0xc14b8000}, {0xc14ba000}, {0xc14bc000}, {0xc14be000}, + {0xc14c0000}, {0xc14c2000}, {0xc14c4000}, {0xc14c6000}, + {0xc14c8000}, {0xc14ca000}, {0xc14cc000}, {0xc14ce000}, + {0xc14d0000}, {0xc14d2000}, {0xc14d4000}, {0xc14d6000}, + {0xc14d8000}, {0xc14da000}, {0xc14dc000}, {0xc14de000}, + {0xc14e0000}, {0xc14e2000}, {0xc14e4000}, {0xc14e6000}, + {0xc14e8000}, {0xc14ea000}, {0xc14ec000}, {0xc14ee000}, + {0xc14f0000}, {0xc14f2000}, {0xc14f4000}, {0xc14f6000}, + {0xc14f8000}, {0xc14fa000}, {0xc14fc000}, {0xc14fe000}, + {0xc1500000}, {0xc1502000}, {0xc1504000}, {0xc1506000}, + {0xc1508000}, {0xc150a000}, {0xc150c000}, {0xc150e000}, + {0xc1510000}, {0xc1512000}, {0xc1514000}, {0xc1516000}, + {0xc1518000}, {0xc151a000}, {0xc151c000}, {0xc151e000}, + {0xc1520000}, {0xc1522000}, {0xc1524000}, {0xc1526000}, + {0xc1528000}, {0xc152a000}, {0xc152c000}, {0xc152e000}, + {0xc1530000}, {0xc1532000}, {0xc1534000}, {0xc1536000}, + {0xc1538000}, {0xc153a000}, {0xc153c000}, {0xc153e000}, + {0xc1540000}, {0xc1542000}, {0xc1544000}, {0xc1546000}, + {0xc1548000}, {0xc154a000}, {0xc154c000}, {0xc154e000}, + {0xc1550000}, {0xc1552000}, {0xc1554000}, {0xc1556000}, + {0xc1558000}, {0xc155a000}, {0xc155c000}, {0xc155e000}, + {0xc1560000}, {0xc1562000}, {0xc1564000}, {0xc1566000}, + {0xc1568000}, {0xc156a000}, {0xc156c000}, {0xc156e000}, + {0xc1570000}, {0xc1572000}, {0xc1574000}, {0xc1576000}, + {0xc1578000}, {0xc157a000}, {0xc157c000}, {0xc157e000}, + {0xc1580000}, {0xc1582000}, {0xc1584000}, {0xc1586000}, + {0xc1588000}, {0xc158a000}, {0xc158c000}, {0xc158e000}, + {0xc1590000}, {0xc1592000}, {0xc1594000}, {0xc1596000}, + {0xc1598000}, {0xc159a000}, {0xc159c000}, {0xc159e000}, + {0xc15a0000}, {0xc15a2000}, {0xc15a4000}, {0xc15a6000}, + {0xc15a8000}, {0xc15aa000}, {0xc15ac000}, {0xc15ae000}, + {0xc15b0000}, {0xc15b2000}, {0xc15b4000}, {0xc15b6000}, + {0xc15b8000}, {0xc15ba000}, {0xc15bc000}, {0xc15be000}, + {0xc15c0000}, {0xc15c2000}, {0xc15c4000}, {0xc15c6000}, + {0xc15c8000}, {0xc15ca000}, {0xc15cc000}, {0xc15ce000}, + {0xc15d0000}, {0xc15d2000}, {0xc15d4000}, {0xc15d6000}, + {0xc15d8000}, {0xc15da000}, {0xc15dc000}, {0xc15de000}, + {0xc15e0000}, {0xc15e2000}, {0xc15e4000}, {0xc15e6000}, + {0xc15e8000}, {0xc15ea000}, {0xc15ec000}, {0xc15ee000}, + {0xc15f0000}, {0xc15f2000}, {0xc15f4000}, {0xc15f6000}, + {0xc15f8000}, {0xc15fa000}, {0xc15fc000}, {0xc15fe000}, + {0xc1600000}, {0xc1602000}, {0xc1604000}, {0xc1606000}, + {0xc1608000}, {0xc160a000}, {0xc160c000}, {0xc160e000}, + {0xc1610000}, {0xc1612000}, {0xc1614000}, {0xc1616000}, + {0xc1618000}, {0xc161a000}, {0xc161c000}, {0xc161e000}, + {0xc1620000}, {0xc1622000}, {0xc1624000}, {0xc1626000}, + {0xc1628000}, {0xc162a000}, {0xc162c000}, {0xc162e000}, + {0xc1630000}, {0xc1632000}, {0xc1634000}, {0xc1636000}, + {0xc1638000}, {0xc163a000}, {0xc163c000}, {0xc163e000}, + {0xc1640000}, {0xc1642000}, {0xc1644000}, {0xc1646000}, + {0xc1648000}, {0xc164a000}, {0xc164c000}, {0xc164e000}, + {0xc1650000}, {0xc1652000}, {0xc1654000}, {0xc1656000}, + {0xc1658000}, {0xc165a000}, {0xc165c000}, {0xc165e000}, + {0xc1660000}, {0xc1662000}, {0xc1664000}, {0xc1666000}, + {0xc1668000}, {0xc166a000}, {0xc166c000}, {0xc166e000}, + {0xc1670000}, {0xc1672000}, {0xc1674000}, {0xc1676000}, + {0xc1678000}, {0xc167a000}, {0xc167c000}, {0xc167e000}, + {0xc1680000}, {0xc1682000}, {0xc1684000}, {0xc1686000}, + {0xc1688000}, {0xc168a000}, {0xc168c000}, {0xc168e000}, + {0xc1690000}, {0xc1692000}, {0xc1694000}, {0xc1696000}, + {0xc1698000}, {0xc169a000}, {0xc169c000}, {0xc169e000}, + {0xc16a0000}, {0xc16a2000}, {0xc16a4000}, {0xc16a6000}, + {0xc16a8000}, {0xc16aa000}, {0xc16ac000}, {0xc16ae000}, + {0xc16b0000}, {0xc16b2000}, {0xc16b4000}, {0xc16b6000}, + {0xc16b8000}, {0xc16ba000}, {0xc16bc000}, {0xc16be000}, + {0xc16c0000}, {0xc16c2000}, {0xc16c4000}, {0xc16c6000}, + {0xc16c8000}, {0xc16ca000}, {0xc16cc000}, {0xc16ce000}, + {0xc16d0000}, {0xc16d2000}, {0xc16d4000}, {0xc16d6000}, + {0xc16d8000}, {0xc16da000}, {0xc16dc000}, {0xc16de000}, + {0xc16e0000}, {0xc16e2000}, {0xc16e4000}, {0xc16e6000}, + {0xc16e8000}, {0xc16ea000}, {0xc16ec000}, {0xc16ee000}, + {0xc16f0000}, {0xc16f2000}, {0xc16f4000}, {0xc16f6000}, + {0xc16f8000}, {0xc16fa000}, {0xc16fc000}, {0xc16fe000}, + {0xc1700000}, {0xc1702000}, {0xc1704000}, {0xc1706000}, + {0xc1708000}, {0xc170a000}, {0xc170c000}, {0xc170e000}, + {0xc1710000}, {0xc1712000}, {0xc1714000}, {0xc1716000}, + {0xc1718000}, {0xc171a000}, {0xc171c000}, {0xc171e000}, + {0xc1720000}, {0xc1722000}, {0xc1724000}, {0xc1726000}, + {0xc1728000}, {0xc172a000}, {0xc172c000}, {0xc172e000}, + {0xc1730000}, {0xc1732000}, {0xc1734000}, {0xc1736000}, + {0xc1738000}, {0xc173a000}, {0xc173c000}, {0xc173e000}, + {0xc1740000}, {0xc1742000}, {0xc1744000}, {0xc1746000}, + {0xc1748000}, {0xc174a000}, {0xc174c000}, {0xc174e000}, + {0xc1750000}, {0xc1752000}, {0xc1754000}, {0xc1756000}, + {0xc1758000}, {0xc175a000}, {0xc175c000}, {0xc175e000}, + {0xc1760000}, {0xc1762000}, {0xc1764000}, {0xc1766000}, + {0xc1768000}, {0xc176a000}, {0xc176c000}, {0xc176e000}, + {0xc1770000}, {0xc1772000}, {0xc1774000}, {0xc1776000}, + {0xc1778000}, {0xc177a000}, {0xc177c000}, {0xc177e000}, + {0xc1780000}, {0xc1782000}, {0xc1784000}, {0xc1786000}, + {0xc1788000}, {0xc178a000}, {0xc178c000}, {0xc178e000}, + {0xc1790000}, {0xc1792000}, {0xc1794000}, {0xc1796000}, + {0xc1798000}, {0xc179a000}, {0xc179c000}, {0xc179e000}, + {0xc17a0000}, {0xc17a2000}, {0xc17a4000}, {0xc17a6000}, + {0xc17a8000}, {0xc17aa000}, {0xc17ac000}, {0xc17ae000}, + {0xc17b0000}, {0xc17b2000}, {0xc17b4000}, {0xc17b6000}, + {0xc17b8000}, {0xc17ba000}, {0xc17bc000}, {0xc17be000}, + {0xc17c0000}, {0xc17c2000}, {0xc17c4000}, {0xc17c6000}, + {0xc17c8000}, {0xc17ca000}, {0xc17cc000}, {0xc17ce000}, + {0xc17d0000}, {0xc17d2000}, {0xc17d4000}, {0xc17d6000}, + {0xc17d8000}, {0xc17da000}, {0xc17dc000}, {0xc17de000}, + {0xc17e0000}, {0xc17e2000}, {0xc17e4000}, {0xc17e6000}, + {0xc17e8000}, {0xc17ea000}, {0xc17ec000}, {0xc17ee000}, + {0xc17f0000}, {0xc17f2000}, {0xc17f4000}, {0xc17f6000}, + {0xc17f8000}, {0xc17fa000}, {0xc17fc000}, {0xc17fe000}, + {0xc1800000}, {0xc1802000}, {0xc1804000}, {0xc1806000}, + {0xc1808000}, {0xc180a000}, {0xc180c000}, {0xc180e000}, + {0xc1810000}, {0xc1812000}, {0xc1814000}, {0xc1816000}, + {0xc1818000}, {0xc181a000}, {0xc181c000}, {0xc181e000}, + {0xc1820000}, {0xc1822000}, {0xc1824000}, {0xc1826000}, + {0xc1828000}, {0xc182a000}, {0xc182c000}, {0xc182e000}, + {0xc1830000}, {0xc1832000}, {0xc1834000}, {0xc1836000}, + {0xc1838000}, {0xc183a000}, {0xc183c000}, {0xc183e000}, + {0xc1840000}, {0xc1842000}, {0xc1844000}, {0xc1846000}, + {0xc1848000}, {0xc184a000}, {0xc184c000}, {0xc184e000}, + {0xc1850000}, {0xc1852000}, {0xc1854000}, {0xc1856000}, + {0xc1858000}, {0xc185a000}, {0xc185c000}, {0xc185e000}, + {0xc1860000}, {0xc1862000}, {0xc1864000}, {0xc1866000}, + {0xc1868000}, {0xc186a000}, {0xc186c000}, {0xc186e000}, + {0xc1870000}, {0xc1872000}, {0xc1874000}, {0xc1876000}, + {0xc1878000}, {0xc187a000}, {0xc187c000}, {0xc187e000}, + {0xc1880000}, {0xc1882000}, {0xc1884000}, {0xc1886000}, + {0xc1888000}, {0xc188a000}, {0xc188c000}, {0xc188e000}, + {0xc1890000}, {0xc1892000}, {0xc1894000}, {0xc1896000}, + {0xc1898000}, {0xc189a000}, {0xc189c000}, {0xc189e000}, + {0xc18a0000}, {0xc18a2000}, {0xc18a4000}, {0xc18a6000}, + {0xc18a8000}, {0xc18aa000}, {0xc18ac000}, {0xc18ae000}, + {0xc18b0000}, {0xc18b2000}, {0xc18b4000}, {0xc18b6000}, + {0xc18b8000}, {0xc18ba000}, {0xc18bc000}, {0xc18be000}, + {0xc18c0000}, {0xc18c2000}, {0xc18c4000}, {0xc18c6000}, + {0xc18c8000}, {0xc18ca000}, {0xc18cc000}, {0xc18ce000}, + {0xc18d0000}, {0xc18d2000}, {0xc18d4000}, {0xc18d6000}, + {0xc18d8000}, {0xc18da000}, {0xc18dc000}, {0xc18de000}, + {0xc18e0000}, {0xc18e2000}, {0xc18e4000}, {0xc18e6000}, + {0xc18e8000}, {0xc18ea000}, {0xc18ec000}, {0xc18ee000}, + {0xc18f0000}, {0xc18f2000}, {0xc18f4000}, {0xc18f6000}, + {0xc18f8000}, {0xc18fa000}, {0xc18fc000}, {0xc18fe000}, + {0xc1900000}, {0xc1902000}, {0xc1904000}, {0xc1906000}, + {0xc1908000}, {0xc190a000}, {0xc190c000}, {0xc190e000}, + {0xc1910000}, {0xc1912000}, {0xc1914000}, {0xc1916000}, + {0xc1918000}, {0xc191a000}, {0xc191c000}, {0xc191e000}, + {0xc1920000}, {0xc1922000}, {0xc1924000}, {0xc1926000}, + {0xc1928000}, {0xc192a000}, {0xc192c000}, {0xc192e000}, + {0xc1930000}, {0xc1932000}, {0xc1934000}, {0xc1936000}, + {0xc1938000}, {0xc193a000}, {0xc193c000}, {0xc193e000}, + {0xc1940000}, {0xc1942000}, {0xc1944000}, {0xc1946000}, + {0xc1948000}, {0xc194a000}, {0xc194c000}, {0xc194e000}, + {0xc1950000}, {0xc1952000}, {0xc1954000}, {0xc1956000}, + {0xc1958000}, {0xc195a000}, {0xc195c000}, {0xc195e000}, + {0xc1960000}, {0xc1962000}, {0xc1964000}, {0xc1966000}, + {0xc1968000}, {0xc196a000}, {0xc196c000}, {0xc196e000}, + {0xc1970000}, {0xc1972000}, {0xc1974000}, {0xc1976000}, + {0xc1978000}, {0xc197a000}, {0xc197c000}, {0xc197e000}, + {0xc1980000}, {0xc1982000}, {0xc1984000}, {0xc1986000}, + {0xc1988000}, {0xc198a000}, {0xc198c000}, {0xc198e000}, + {0xc1990000}, {0xc1992000}, {0xc1994000}, {0xc1996000}, + {0xc1998000}, {0xc199a000}, {0xc199c000}, {0xc199e000}, + {0xc19a0000}, {0xc19a2000}, {0xc19a4000}, {0xc19a6000}, + {0xc19a8000}, {0xc19aa000}, {0xc19ac000}, {0xc19ae000}, + {0xc19b0000}, {0xc19b2000}, {0xc19b4000}, {0xc19b6000}, + {0xc19b8000}, {0xc19ba000}, {0xc19bc000}, {0xc19be000}, + {0xc19c0000}, {0xc19c2000}, {0xc19c4000}, {0xc19c6000}, + {0xc19c8000}, {0xc19ca000}, {0xc19cc000}, {0xc19ce000}, + {0xc19d0000}, {0xc19d2000}, {0xc19d4000}, {0xc19d6000}, + {0xc19d8000}, {0xc19da000}, {0xc19dc000}, {0xc19de000}, + {0xc19e0000}, {0xc19e2000}, {0xc19e4000}, {0xc19e6000}, + {0xc19e8000}, {0xc19ea000}, {0xc19ec000}, {0xc19ee000}, + {0xc19f0000}, {0xc19f2000}, {0xc19f4000}, {0xc19f6000}, + {0xc19f8000}, {0xc19fa000}, {0xc19fc000}, {0xc19fe000}, + {0xc1a00000}, {0xc1a02000}, {0xc1a04000}, {0xc1a06000}, + {0xc1a08000}, {0xc1a0a000}, {0xc1a0c000}, {0xc1a0e000}, + {0xc1a10000}, {0xc1a12000}, {0xc1a14000}, {0xc1a16000}, + {0xc1a18000}, {0xc1a1a000}, {0xc1a1c000}, {0xc1a1e000}, + {0xc1a20000}, {0xc1a22000}, {0xc1a24000}, {0xc1a26000}, + {0xc1a28000}, {0xc1a2a000}, {0xc1a2c000}, {0xc1a2e000}, + {0xc1a30000}, {0xc1a32000}, {0xc1a34000}, {0xc1a36000}, + {0xc1a38000}, {0xc1a3a000}, {0xc1a3c000}, {0xc1a3e000}, + {0xc1a40000}, {0xc1a42000}, {0xc1a44000}, {0xc1a46000}, + {0xc1a48000}, {0xc1a4a000}, {0xc1a4c000}, {0xc1a4e000}, + {0xc1a50000}, {0xc1a52000}, {0xc1a54000}, {0xc1a56000}, + {0xc1a58000}, {0xc1a5a000}, {0xc1a5c000}, {0xc1a5e000}, + {0xc1a60000}, {0xc1a62000}, {0xc1a64000}, {0xc1a66000}, + {0xc1a68000}, {0xc1a6a000}, {0xc1a6c000}, {0xc1a6e000}, + {0xc1a70000}, {0xc1a72000}, {0xc1a74000}, {0xc1a76000}, + {0xc1a78000}, {0xc1a7a000}, {0xc1a7c000}, {0xc1a7e000}, + {0xc1a80000}, {0xc1a82000}, {0xc1a84000}, {0xc1a86000}, + {0xc1a88000}, {0xc1a8a000}, {0xc1a8c000}, {0xc1a8e000}, + {0xc1a90000}, {0xc1a92000}, {0xc1a94000}, {0xc1a96000}, + {0xc1a98000}, {0xc1a9a000}, {0xc1a9c000}, {0xc1a9e000}, + {0xc1aa0000}, {0xc1aa2000}, {0xc1aa4000}, {0xc1aa6000}, + {0xc1aa8000}, {0xc1aaa000}, {0xc1aac000}, {0xc1aae000}, + {0xc1ab0000}, {0xc1ab2000}, {0xc1ab4000}, {0xc1ab6000}, + {0xc1ab8000}, {0xc1aba000}, {0xc1abc000}, {0xc1abe000}, + {0xc1ac0000}, {0xc1ac2000}, {0xc1ac4000}, {0xc1ac6000}, + {0xc1ac8000}, {0xc1aca000}, {0xc1acc000}, {0xc1ace000}, + {0xc1ad0000}, {0xc1ad2000}, {0xc1ad4000}, {0xc1ad6000}, + {0xc1ad8000}, {0xc1ada000}, {0xc1adc000}, {0xc1ade000}, + {0xc1ae0000}, {0xc1ae2000}, {0xc1ae4000}, {0xc1ae6000}, + {0xc1ae8000}, {0xc1aea000}, {0xc1aec000}, {0xc1aee000}, + {0xc1af0000}, {0xc1af2000}, {0xc1af4000}, {0xc1af6000}, + {0xc1af8000}, {0xc1afa000}, {0xc1afc000}, {0xc1afe000}, + {0xc1b00000}, {0xc1b02000}, {0xc1b04000}, {0xc1b06000}, + {0xc1b08000}, {0xc1b0a000}, {0xc1b0c000}, {0xc1b0e000}, + {0xc1b10000}, {0xc1b12000}, {0xc1b14000}, {0xc1b16000}, + {0xc1b18000}, {0xc1b1a000}, {0xc1b1c000}, {0xc1b1e000}, + {0xc1b20000}, {0xc1b22000}, {0xc1b24000}, {0xc1b26000}, + {0xc1b28000}, {0xc1b2a000}, {0xc1b2c000}, {0xc1b2e000}, + {0xc1b30000}, {0xc1b32000}, {0xc1b34000}, {0xc1b36000}, + {0xc1b38000}, {0xc1b3a000}, {0xc1b3c000}, {0xc1b3e000}, + {0xc1b40000}, {0xc1b42000}, {0xc1b44000}, {0xc1b46000}, + {0xc1b48000}, {0xc1b4a000}, {0xc1b4c000}, {0xc1b4e000}, + {0xc1b50000}, {0xc1b52000}, {0xc1b54000}, {0xc1b56000}, + {0xc1b58000}, {0xc1b5a000}, {0xc1b5c000}, {0xc1b5e000}, + {0xc1b60000}, {0xc1b62000}, {0xc1b64000}, {0xc1b66000}, + {0xc1b68000}, {0xc1b6a000}, {0xc1b6c000}, {0xc1b6e000}, + {0xc1b70000}, {0xc1b72000}, {0xc1b74000}, {0xc1b76000}, + {0xc1b78000}, {0xc1b7a000}, {0xc1b7c000}, {0xc1b7e000}, + {0xc1b80000}, {0xc1b82000}, {0xc1b84000}, {0xc1b86000}, + {0xc1b88000}, {0xc1b8a000}, {0xc1b8c000}, {0xc1b8e000}, + {0xc1b90000}, {0xc1b92000}, {0xc1b94000}, {0xc1b96000}, + {0xc1b98000}, {0xc1b9a000}, {0xc1b9c000}, {0xc1b9e000}, + {0xc1ba0000}, {0xc1ba2000}, {0xc1ba4000}, {0xc1ba6000}, + {0xc1ba8000}, {0xc1baa000}, {0xc1bac000}, {0xc1bae000}, + {0xc1bb0000}, {0xc1bb2000}, {0xc1bb4000}, {0xc1bb6000}, + {0xc1bb8000}, {0xc1bba000}, {0xc1bbc000}, {0xc1bbe000}, + {0xc1bc0000}, {0xc1bc2000}, {0xc1bc4000}, {0xc1bc6000}, + {0xc1bc8000}, {0xc1bca000}, {0xc1bcc000}, {0xc1bce000}, + {0xc1bd0000}, {0xc1bd2000}, {0xc1bd4000}, {0xc1bd6000}, + {0xc1bd8000}, {0xc1bda000}, {0xc1bdc000}, {0xc1bde000}, + {0xc1be0000}, {0xc1be2000}, {0xc1be4000}, {0xc1be6000}, + {0xc1be8000}, {0xc1bea000}, {0xc1bec000}, {0xc1bee000}, + {0xc1bf0000}, {0xc1bf2000}, {0xc1bf4000}, {0xc1bf6000}, + {0xc1bf8000}, {0xc1bfa000}, {0xc1bfc000}, {0xc1bfe000}, + {0xc1c00000}, {0xc1c02000}, {0xc1c04000}, {0xc1c06000}, + {0xc1c08000}, {0xc1c0a000}, {0xc1c0c000}, {0xc1c0e000}, + {0xc1c10000}, {0xc1c12000}, {0xc1c14000}, {0xc1c16000}, + {0xc1c18000}, {0xc1c1a000}, {0xc1c1c000}, {0xc1c1e000}, + {0xc1c20000}, {0xc1c22000}, {0xc1c24000}, {0xc1c26000}, + {0xc1c28000}, {0xc1c2a000}, {0xc1c2c000}, {0xc1c2e000}, + {0xc1c30000}, {0xc1c32000}, {0xc1c34000}, {0xc1c36000}, + {0xc1c38000}, {0xc1c3a000}, {0xc1c3c000}, {0xc1c3e000}, + {0xc1c40000}, {0xc1c42000}, {0xc1c44000}, {0xc1c46000}, + {0xc1c48000}, {0xc1c4a000}, {0xc1c4c000}, {0xc1c4e000}, + {0xc1c50000}, {0xc1c52000}, {0xc1c54000}, {0xc1c56000}, + {0xc1c58000}, {0xc1c5a000}, {0xc1c5c000}, {0xc1c5e000}, + {0xc1c60000}, {0xc1c62000}, {0xc1c64000}, {0xc1c66000}, + {0xc1c68000}, {0xc1c6a000}, {0xc1c6c000}, {0xc1c6e000}, + {0xc1c70000}, {0xc1c72000}, {0xc1c74000}, {0xc1c76000}, + {0xc1c78000}, {0xc1c7a000}, {0xc1c7c000}, {0xc1c7e000}, + {0xc1c80000}, {0xc1c82000}, {0xc1c84000}, {0xc1c86000}, + {0xc1c88000}, {0xc1c8a000}, {0xc1c8c000}, {0xc1c8e000}, + {0xc1c90000}, {0xc1c92000}, {0xc1c94000}, {0xc1c96000}, + {0xc1c98000}, {0xc1c9a000}, {0xc1c9c000}, {0xc1c9e000}, + {0xc1ca0000}, {0xc1ca2000}, {0xc1ca4000}, {0xc1ca6000}, + {0xc1ca8000}, {0xc1caa000}, {0xc1cac000}, {0xc1cae000}, + {0xc1cb0000}, {0xc1cb2000}, {0xc1cb4000}, {0xc1cb6000}, + {0xc1cb8000}, {0xc1cba000}, {0xc1cbc000}, {0xc1cbe000}, + {0xc1cc0000}, {0xc1cc2000}, {0xc1cc4000}, {0xc1cc6000}, + {0xc1cc8000}, {0xc1cca000}, {0xc1ccc000}, {0xc1cce000}, + {0xc1cd0000}, {0xc1cd2000}, {0xc1cd4000}, {0xc1cd6000}, + {0xc1cd8000}, {0xc1cda000}, {0xc1cdc000}, {0xc1cde000}, + {0xc1ce0000}, {0xc1ce2000}, {0xc1ce4000}, {0xc1ce6000}, + {0xc1ce8000}, {0xc1cea000}, {0xc1cec000}, {0xc1cee000}, + {0xc1cf0000}, {0xc1cf2000}, {0xc1cf4000}, {0xc1cf6000}, + {0xc1cf8000}, {0xc1cfa000}, {0xc1cfc000}, {0xc1cfe000}, + {0xc1d00000}, {0xc1d02000}, {0xc1d04000}, {0xc1d06000}, + {0xc1d08000}, {0xc1d0a000}, {0xc1d0c000}, {0xc1d0e000}, + {0xc1d10000}, {0xc1d12000}, {0xc1d14000}, {0xc1d16000}, + {0xc1d18000}, {0xc1d1a000}, {0xc1d1c000}, {0xc1d1e000}, + {0xc1d20000}, {0xc1d22000}, {0xc1d24000}, {0xc1d26000}, + {0xc1d28000}, {0xc1d2a000}, {0xc1d2c000}, {0xc1d2e000}, + {0xc1d30000}, {0xc1d32000}, {0xc1d34000}, {0xc1d36000}, + {0xc1d38000}, {0xc1d3a000}, {0xc1d3c000}, {0xc1d3e000}, + {0xc1d40000}, {0xc1d42000}, {0xc1d44000}, {0xc1d46000}, + {0xc1d48000}, {0xc1d4a000}, {0xc1d4c000}, {0xc1d4e000}, + {0xc1d50000}, {0xc1d52000}, {0xc1d54000}, {0xc1d56000}, + {0xc1d58000}, {0xc1d5a000}, {0xc1d5c000}, {0xc1d5e000}, + {0xc1d60000}, {0xc1d62000}, {0xc1d64000}, {0xc1d66000}, + {0xc1d68000}, {0xc1d6a000}, {0xc1d6c000}, {0xc1d6e000}, + {0xc1d70000}, {0xc1d72000}, {0xc1d74000}, {0xc1d76000}, + {0xc1d78000}, {0xc1d7a000}, {0xc1d7c000}, {0xc1d7e000}, + {0xc1d80000}, {0xc1d82000}, {0xc1d84000}, {0xc1d86000}, + {0xc1d88000}, {0xc1d8a000}, {0xc1d8c000}, {0xc1d8e000}, + {0xc1d90000}, {0xc1d92000}, {0xc1d94000}, {0xc1d96000}, + {0xc1d98000}, {0xc1d9a000}, {0xc1d9c000}, {0xc1d9e000}, + {0xc1da0000}, {0xc1da2000}, {0xc1da4000}, {0xc1da6000}, + {0xc1da8000}, {0xc1daa000}, {0xc1dac000}, {0xc1dae000}, + {0xc1db0000}, {0xc1db2000}, {0xc1db4000}, {0xc1db6000}, + {0xc1db8000}, {0xc1dba000}, {0xc1dbc000}, {0xc1dbe000}, + {0xc1dc0000}, {0xc1dc2000}, {0xc1dc4000}, {0xc1dc6000}, + {0xc1dc8000}, {0xc1dca000}, {0xc1dcc000}, {0xc1dce000}, + {0xc1dd0000}, {0xc1dd2000}, {0xc1dd4000}, {0xc1dd6000}, + {0xc1dd8000}, {0xc1dda000}, {0xc1ddc000}, {0xc1dde000}, + {0xc1de0000}, {0xc1de2000}, {0xc1de4000}, {0xc1de6000}, + {0xc1de8000}, {0xc1dea000}, {0xc1dec000}, {0xc1dee000}, + {0xc1df0000}, {0xc1df2000}, {0xc1df4000}, {0xc1df6000}, + {0xc1df8000}, {0xc1dfa000}, {0xc1dfc000}, {0xc1dfe000}, + {0xc1e00000}, {0xc1e02000}, {0xc1e04000}, {0xc1e06000}, + {0xc1e08000}, {0xc1e0a000}, {0xc1e0c000}, {0xc1e0e000}, + {0xc1e10000}, {0xc1e12000}, {0xc1e14000}, {0xc1e16000}, + {0xc1e18000}, {0xc1e1a000}, {0xc1e1c000}, {0xc1e1e000}, + {0xc1e20000}, {0xc1e22000}, {0xc1e24000}, {0xc1e26000}, + {0xc1e28000}, {0xc1e2a000}, {0xc1e2c000}, {0xc1e2e000}, + {0xc1e30000}, {0xc1e32000}, {0xc1e34000}, {0xc1e36000}, + {0xc1e38000}, {0xc1e3a000}, {0xc1e3c000}, {0xc1e3e000}, + {0xc1e40000}, {0xc1e42000}, {0xc1e44000}, {0xc1e46000}, + {0xc1e48000}, {0xc1e4a000}, {0xc1e4c000}, {0xc1e4e000}, + {0xc1e50000}, {0xc1e52000}, {0xc1e54000}, {0xc1e56000}, + {0xc1e58000}, {0xc1e5a000}, {0xc1e5c000}, {0xc1e5e000}, + {0xc1e60000}, {0xc1e62000}, {0xc1e64000}, {0xc1e66000}, + {0xc1e68000}, {0xc1e6a000}, {0xc1e6c000}, {0xc1e6e000}, + {0xc1e70000}, {0xc1e72000}, {0xc1e74000}, {0xc1e76000}, + {0xc1e78000}, {0xc1e7a000}, {0xc1e7c000}, {0xc1e7e000}, + {0xc1e80000}, {0xc1e82000}, {0xc1e84000}, {0xc1e86000}, + {0xc1e88000}, {0xc1e8a000}, {0xc1e8c000}, {0xc1e8e000}, + {0xc1e90000}, {0xc1e92000}, {0xc1e94000}, {0xc1e96000}, + {0xc1e98000}, {0xc1e9a000}, {0xc1e9c000}, {0xc1e9e000}, + {0xc1ea0000}, {0xc1ea2000}, {0xc1ea4000}, {0xc1ea6000}, + {0xc1ea8000}, {0xc1eaa000}, {0xc1eac000}, {0xc1eae000}, + {0xc1eb0000}, {0xc1eb2000}, {0xc1eb4000}, {0xc1eb6000}, + {0xc1eb8000}, {0xc1eba000}, {0xc1ebc000}, {0xc1ebe000}, + {0xc1ec0000}, {0xc1ec2000}, {0xc1ec4000}, {0xc1ec6000}, + {0xc1ec8000}, {0xc1eca000}, {0xc1ecc000}, {0xc1ece000}, + {0xc1ed0000}, {0xc1ed2000}, {0xc1ed4000}, {0xc1ed6000}, + {0xc1ed8000}, {0xc1eda000}, {0xc1edc000}, {0xc1ede000}, + {0xc1ee0000}, {0xc1ee2000}, {0xc1ee4000}, {0xc1ee6000}, + {0xc1ee8000}, {0xc1eea000}, {0xc1eec000}, {0xc1eee000}, + {0xc1ef0000}, {0xc1ef2000}, {0xc1ef4000}, {0xc1ef6000}, + {0xc1ef8000}, {0xc1efa000}, {0xc1efc000}, {0xc1efe000}, + {0xc1f00000}, {0xc1f02000}, {0xc1f04000}, {0xc1f06000}, + {0xc1f08000}, {0xc1f0a000}, {0xc1f0c000}, {0xc1f0e000}, + {0xc1f10000}, {0xc1f12000}, {0xc1f14000}, {0xc1f16000}, + {0xc1f18000}, {0xc1f1a000}, {0xc1f1c000}, {0xc1f1e000}, + {0xc1f20000}, {0xc1f22000}, {0xc1f24000}, {0xc1f26000}, + {0xc1f28000}, {0xc1f2a000}, {0xc1f2c000}, {0xc1f2e000}, + {0xc1f30000}, {0xc1f32000}, {0xc1f34000}, {0xc1f36000}, + {0xc1f38000}, {0xc1f3a000}, {0xc1f3c000}, {0xc1f3e000}, + {0xc1f40000}, {0xc1f42000}, {0xc1f44000}, {0xc1f46000}, + {0xc1f48000}, {0xc1f4a000}, {0xc1f4c000}, {0xc1f4e000}, + {0xc1f50000}, {0xc1f52000}, {0xc1f54000}, {0xc1f56000}, + {0xc1f58000}, {0xc1f5a000}, {0xc1f5c000}, {0xc1f5e000}, + {0xc1f60000}, {0xc1f62000}, {0xc1f64000}, {0xc1f66000}, + {0xc1f68000}, {0xc1f6a000}, {0xc1f6c000}, {0xc1f6e000}, + {0xc1f70000}, {0xc1f72000}, {0xc1f74000}, {0xc1f76000}, + {0xc1f78000}, {0xc1f7a000}, {0xc1f7c000}, {0xc1f7e000}, + {0xc1f80000}, {0xc1f82000}, {0xc1f84000}, {0xc1f86000}, + {0xc1f88000}, {0xc1f8a000}, {0xc1f8c000}, {0xc1f8e000}, + {0xc1f90000}, {0xc1f92000}, {0xc1f94000}, {0xc1f96000}, + {0xc1f98000}, {0xc1f9a000}, {0xc1f9c000}, {0xc1f9e000}, + {0xc1fa0000}, {0xc1fa2000}, {0xc1fa4000}, {0xc1fa6000}, + {0xc1fa8000}, {0xc1faa000}, {0xc1fac000}, {0xc1fae000}, + {0xc1fb0000}, {0xc1fb2000}, {0xc1fb4000}, {0xc1fb6000}, + {0xc1fb8000}, {0xc1fba000}, {0xc1fbc000}, {0xc1fbe000}, + {0xc1fc0000}, {0xc1fc2000}, {0xc1fc4000}, {0xc1fc6000}, + {0xc1fc8000}, {0xc1fca000}, {0xc1fcc000}, {0xc1fce000}, + {0xc1fd0000}, {0xc1fd2000}, {0xc1fd4000}, {0xc1fd6000}, + {0xc1fd8000}, {0xc1fda000}, {0xc1fdc000}, {0xc1fde000}, + {0xc1fe0000}, {0xc1fe2000}, {0xc1fe4000}, {0xc1fe6000}, + {0xc1fe8000}, {0xc1fea000}, {0xc1fec000}, {0xc1fee000}, + {0xc1ff0000}, {0xc1ff2000}, {0xc1ff4000}, {0xc1ff6000}, + {0xc1ff8000}, {0xc1ffa000}, {0xc1ffc000}, {0xc1ffe000}, + {0xc2000000}, {0xc2002000}, {0xc2004000}, {0xc2006000}, + {0xc2008000}, {0xc200a000}, {0xc200c000}, {0xc200e000}, + {0xc2010000}, {0xc2012000}, {0xc2014000}, {0xc2016000}, + {0xc2018000}, {0xc201a000}, {0xc201c000}, {0xc201e000}, + {0xc2020000}, {0xc2022000}, {0xc2024000}, {0xc2026000}, + {0xc2028000}, {0xc202a000}, {0xc202c000}, {0xc202e000}, + {0xc2030000}, {0xc2032000}, {0xc2034000}, {0xc2036000}, + {0xc2038000}, {0xc203a000}, {0xc203c000}, {0xc203e000}, + {0xc2040000}, {0xc2042000}, {0xc2044000}, {0xc2046000}, + {0xc2048000}, {0xc204a000}, {0xc204c000}, {0xc204e000}, + {0xc2050000}, {0xc2052000}, {0xc2054000}, {0xc2056000}, + {0xc2058000}, {0xc205a000}, {0xc205c000}, {0xc205e000}, + {0xc2060000}, {0xc2062000}, {0xc2064000}, {0xc2066000}, + {0xc2068000}, {0xc206a000}, {0xc206c000}, {0xc206e000}, + {0xc2070000}, {0xc2072000}, {0xc2074000}, {0xc2076000}, + {0xc2078000}, {0xc207a000}, {0xc207c000}, {0xc207e000}, + {0xc2080000}, {0xc2082000}, {0xc2084000}, {0xc2086000}, + {0xc2088000}, {0xc208a000}, {0xc208c000}, {0xc208e000}, + {0xc2090000}, {0xc2092000}, {0xc2094000}, {0xc2096000}, + {0xc2098000}, {0xc209a000}, {0xc209c000}, {0xc209e000}, + {0xc20a0000}, {0xc20a2000}, {0xc20a4000}, {0xc20a6000}, + {0xc20a8000}, {0xc20aa000}, {0xc20ac000}, {0xc20ae000}, + {0xc20b0000}, {0xc20b2000}, {0xc20b4000}, {0xc20b6000}, + {0xc20b8000}, {0xc20ba000}, {0xc20bc000}, {0xc20be000}, + {0xc20c0000}, {0xc20c2000}, {0xc20c4000}, {0xc20c6000}, + {0xc20c8000}, {0xc20ca000}, {0xc20cc000}, {0xc20ce000}, + {0xc20d0000}, {0xc20d2000}, {0xc20d4000}, {0xc20d6000}, + {0xc20d8000}, {0xc20da000}, {0xc20dc000}, {0xc20de000}, + {0xc20e0000}, {0xc20e2000}, {0xc20e4000}, {0xc20e6000}, + {0xc20e8000}, {0xc20ea000}, {0xc20ec000}, {0xc20ee000}, + {0xc20f0000}, {0xc20f2000}, {0xc20f4000}, {0xc20f6000}, + {0xc20f8000}, {0xc20fa000}, {0xc20fc000}, {0xc20fe000}, + {0xc2100000}, {0xc2102000}, {0xc2104000}, {0xc2106000}, + {0xc2108000}, {0xc210a000}, {0xc210c000}, {0xc210e000}, + {0xc2110000}, {0xc2112000}, {0xc2114000}, {0xc2116000}, + {0xc2118000}, {0xc211a000}, {0xc211c000}, {0xc211e000}, + {0xc2120000}, {0xc2122000}, {0xc2124000}, {0xc2126000}, + {0xc2128000}, {0xc212a000}, {0xc212c000}, {0xc212e000}, + {0xc2130000}, {0xc2132000}, {0xc2134000}, {0xc2136000}, + {0xc2138000}, {0xc213a000}, {0xc213c000}, {0xc213e000}, + {0xc2140000}, {0xc2142000}, {0xc2144000}, {0xc2146000}, + {0xc2148000}, {0xc214a000}, {0xc214c000}, {0xc214e000}, + {0xc2150000}, {0xc2152000}, {0xc2154000}, {0xc2156000}, + {0xc2158000}, {0xc215a000}, {0xc215c000}, {0xc215e000}, + {0xc2160000}, {0xc2162000}, {0xc2164000}, {0xc2166000}, + {0xc2168000}, {0xc216a000}, {0xc216c000}, {0xc216e000}, + {0xc2170000}, {0xc2172000}, {0xc2174000}, {0xc2176000}, + {0xc2178000}, {0xc217a000}, {0xc217c000}, {0xc217e000}, + {0xc2180000}, {0xc2182000}, {0xc2184000}, {0xc2186000}, + {0xc2188000}, {0xc218a000}, {0xc218c000}, {0xc218e000}, + {0xc2190000}, {0xc2192000}, {0xc2194000}, {0xc2196000}, + {0xc2198000}, {0xc219a000}, {0xc219c000}, {0xc219e000}, + {0xc21a0000}, {0xc21a2000}, {0xc21a4000}, {0xc21a6000}, + {0xc21a8000}, {0xc21aa000}, {0xc21ac000}, {0xc21ae000}, + {0xc21b0000}, {0xc21b2000}, {0xc21b4000}, {0xc21b6000}, + {0xc21b8000}, {0xc21ba000}, {0xc21bc000}, {0xc21be000}, + {0xc21c0000}, {0xc21c2000}, {0xc21c4000}, {0xc21c6000}, + {0xc21c8000}, {0xc21ca000}, {0xc21cc000}, {0xc21ce000}, + {0xc21d0000}, {0xc21d2000}, {0xc21d4000}, {0xc21d6000}, + {0xc21d8000}, {0xc21da000}, {0xc21dc000}, {0xc21de000}, + {0xc21e0000}, {0xc21e2000}, {0xc21e4000}, {0xc21e6000}, + {0xc21e8000}, {0xc21ea000}, {0xc21ec000}, {0xc21ee000}, + {0xc21f0000}, {0xc21f2000}, {0xc21f4000}, {0xc21f6000}, + {0xc21f8000}, {0xc21fa000}, {0xc21fc000}, {0xc21fe000}, + {0xc2200000}, {0xc2202000}, {0xc2204000}, {0xc2206000}, + {0xc2208000}, {0xc220a000}, {0xc220c000}, {0xc220e000}, + {0xc2210000}, {0xc2212000}, {0xc2214000}, {0xc2216000}, + {0xc2218000}, {0xc221a000}, {0xc221c000}, {0xc221e000}, + {0xc2220000}, {0xc2222000}, {0xc2224000}, {0xc2226000}, + {0xc2228000}, {0xc222a000}, {0xc222c000}, {0xc222e000}, + {0xc2230000}, {0xc2232000}, {0xc2234000}, {0xc2236000}, + {0xc2238000}, {0xc223a000}, {0xc223c000}, {0xc223e000}, + {0xc2240000}, {0xc2242000}, {0xc2244000}, {0xc2246000}, + {0xc2248000}, {0xc224a000}, {0xc224c000}, {0xc224e000}, + {0xc2250000}, {0xc2252000}, {0xc2254000}, {0xc2256000}, + {0xc2258000}, {0xc225a000}, {0xc225c000}, {0xc225e000}, + {0xc2260000}, {0xc2262000}, {0xc2264000}, {0xc2266000}, + {0xc2268000}, {0xc226a000}, {0xc226c000}, {0xc226e000}, + {0xc2270000}, {0xc2272000}, {0xc2274000}, {0xc2276000}, + {0xc2278000}, {0xc227a000}, {0xc227c000}, {0xc227e000}, + {0xc2280000}, {0xc2282000}, {0xc2284000}, {0xc2286000}, + {0xc2288000}, {0xc228a000}, {0xc228c000}, {0xc228e000}, + {0xc2290000}, {0xc2292000}, {0xc2294000}, {0xc2296000}, + {0xc2298000}, {0xc229a000}, {0xc229c000}, {0xc229e000}, + {0xc22a0000}, {0xc22a2000}, {0xc22a4000}, {0xc22a6000}, + {0xc22a8000}, {0xc22aa000}, {0xc22ac000}, {0xc22ae000}, + {0xc22b0000}, {0xc22b2000}, {0xc22b4000}, {0xc22b6000}, + {0xc22b8000}, {0xc22ba000}, {0xc22bc000}, {0xc22be000}, + {0xc22c0000}, {0xc22c2000}, {0xc22c4000}, {0xc22c6000}, + {0xc22c8000}, {0xc22ca000}, {0xc22cc000}, {0xc22ce000}, + {0xc22d0000}, {0xc22d2000}, {0xc22d4000}, {0xc22d6000}, + {0xc22d8000}, {0xc22da000}, {0xc22dc000}, {0xc22de000}, + {0xc22e0000}, {0xc22e2000}, {0xc22e4000}, {0xc22e6000}, + {0xc22e8000}, {0xc22ea000}, {0xc22ec000}, {0xc22ee000}, + {0xc22f0000}, {0xc22f2000}, {0xc22f4000}, {0xc22f6000}, + {0xc22f8000}, {0xc22fa000}, {0xc22fc000}, {0xc22fe000}, + {0xc2300000}, {0xc2302000}, {0xc2304000}, {0xc2306000}, + {0xc2308000}, {0xc230a000}, {0xc230c000}, {0xc230e000}, + {0xc2310000}, {0xc2312000}, {0xc2314000}, {0xc2316000}, + {0xc2318000}, {0xc231a000}, {0xc231c000}, {0xc231e000}, + {0xc2320000}, {0xc2322000}, {0xc2324000}, {0xc2326000}, + {0xc2328000}, {0xc232a000}, {0xc232c000}, {0xc232e000}, + {0xc2330000}, {0xc2332000}, {0xc2334000}, {0xc2336000}, + {0xc2338000}, {0xc233a000}, {0xc233c000}, {0xc233e000}, + {0xc2340000}, {0xc2342000}, {0xc2344000}, {0xc2346000}, + {0xc2348000}, {0xc234a000}, {0xc234c000}, {0xc234e000}, + {0xc2350000}, {0xc2352000}, {0xc2354000}, {0xc2356000}, + {0xc2358000}, {0xc235a000}, {0xc235c000}, {0xc235e000}, + {0xc2360000}, {0xc2362000}, {0xc2364000}, {0xc2366000}, + {0xc2368000}, {0xc236a000}, {0xc236c000}, {0xc236e000}, + {0xc2370000}, {0xc2372000}, {0xc2374000}, {0xc2376000}, + {0xc2378000}, {0xc237a000}, {0xc237c000}, {0xc237e000}, + {0xc2380000}, {0xc2382000}, {0xc2384000}, {0xc2386000}, + {0xc2388000}, {0xc238a000}, {0xc238c000}, {0xc238e000}, + {0xc2390000}, {0xc2392000}, {0xc2394000}, {0xc2396000}, + {0xc2398000}, {0xc239a000}, {0xc239c000}, {0xc239e000}, + {0xc23a0000}, {0xc23a2000}, {0xc23a4000}, {0xc23a6000}, + {0xc23a8000}, {0xc23aa000}, {0xc23ac000}, {0xc23ae000}, + {0xc23b0000}, {0xc23b2000}, {0xc23b4000}, {0xc23b6000}, + {0xc23b8000}, {0xc23ba000}, {0xc23bc000}, {0xc23be000}, + {0xc23c0000}, {0xc23c2000}, {0xc23c4000}, {0xc23c6000}, + {0xc23c8000}, {0xc23ca000}, {0xc23cc000}, {0xc23ce000}, + {0xc23d0000}, {0xc23d2000}, {0xc23d4000}, {0xc23d6000}, + {0xc23d8000}, {0xc23da000}, {0xc23dc000}, {0xc23de000}, + {0xc23e0000}, {0xc23e2000}, {0xc23e4000}, {0xc23e6000}, + {0xc23e8000}, {0xc23ea000}, {0xc23ec000}, {0xc23ee000}, + {0xc23f0000}, {0xc23f2000}, {0xc23f4000}, {0xc23f6000}, + {0xc23f8000}, {0xc23fa000}, {0xc23fc000}, {0xc23fe000}, + {0xc2400000}, {0xc2402000}, {0xc2404000}, {0xc2406000}, + {0xc2408000}, {0xc240a000}, {0xc240c000}, {0xc240e000}, + {0xc2410000}, {0xc2412000}, {0xc2414000}, {0xc2416000}, + {0xc2418000}, {0xc241a000}, {0xc241c000}, {0xc241e000}, + {0xc2420000}, {0xc2422000}, {0xc2424000}, {0xc2426000}, + {0xc2428000}, {0xc242a000}, {0xc242c000}, {0xc242e000}, + {0xc2430000}, {0xc2432000}, {0xc2434000}, {0xc2436000}, + {0xc2438000}, {0xc243a000}, {0xc243c000}, {0xc243e000}, + {0xc2440000}, {0xc2442000}, {0xc2444000}, {0xc2446000}, + {0xc2448000}, {0xc244a000}, {0xc244c000}, {0xc244e000}, + {0xc2450000}, {0xc2452000}, {0xc2454000}, {0xc2456000}, + {0xc2458000}, {0xc245a000}, {0xc245c000}, {0xc245e000}, + {0xc2460000}, {0xc2462000}, {0xc2464000}, {0xc2466000}, + {0xc2468000}, {0xc246a000}, {0xc246c000}, {0xc246e000}, + {0xc2470000}, {0xc2472000}, {0xc2474000}, {0xc2476000}, + {0xc2478000}, {0xc247a000}, {0xc247c000}, {0xc247e000}, + {0xc2480000}, {0xc2482000}, {0xc2484000}, {0xc2486000}, + {0xc2488000}, {0xc248a000}, {0xc248c000}, {0xc248e000}, + {0xc2490000}, {0xc2492000}, {0xc2494000}, {0xc2496000}, + {0xc2498000}, {0xc249a000}, {0xc249c000}, {0xc249e000}, + {0xc24a0000}, {0xc24a2000}, {0xc24a4000}, {0xc24a6000}, + {0xc24a8000}, {0xc24aa000}, {0xc24ac000}, {0xc24ae000}, + {0xc24b0000}, {0xc24b2000}, {0xc24b4000}, {0xc24b6000}, + {0xc24b8000}, {0xc24ba000}, {0xc24bc000}, {0xc24be000}, + {0xc24c0000}, {0xc24c2000}, {0xc24c4000}, {0xc24c6000}, + {0xc24c8000}, {0xc24ca000}, {0xc24cc000}, {0xc24ce000}, + {0xc24d0000}, {0xc24d2000}, {0xc24d4000}, {0xc24d6000}, + {0xc24d8000}, {0xc24da000}, {0xc24dc000}, {0xc24de000}, + {0xc24e0000}, {0xc24e2000}, {0xc24e4000}, {0xc24e6000}, + {0xc24e8000}, {0xc24ea000}, {0xc24ec000}, {0xc24ee000}, + {0xc24f0000}, {0xc24f2000}, {0xc24f4000}, {0xc24f6000}, + {0xc24f8000}, {0xc24fa000}, {0xc24fc000}, {0xc24fe000}, + {0xc2500000}, {0xc2502000}, {0xc2504000}, {0xc2506000}, + {0xc2508000}, {0xc250a000}, {0xc250c000}, {0xc250e000}, + {0xc2510000}, {0xc2512000}, {0xc2514000}, {0xc2516000}, + {0xc2518000}, {0xc251a000}, {0xc251c000}, {0xc251e000}, + {0xc2520000}, {0xc2522000}, {0xc2524000}, {0xc2526000}, + {0xc2528000}, {0xc252a000}, {0xc252c000}, {0xc252e000}, + {0xc2530000}, {0xc2532000}, {0xc2534000}, {0xc2536000}, + {0xc2538000}, {0xc253a000}, {0xc253c000}, {0xc253e000}, + {0xc2540000}, {0xc2542000}, {0xc2544000}, {0xc2546000}, + {0xc2548000}, {0xc254a000}, {0xc254c000}, {0xc254e000}, + {0xc2550000}, {0xc2552000}, {0xc2554000}, {0xc2556000}, + {0xc2558000}, {0xc255a000}, {0xc255c000}, {0xc255e000}, + {0xc2560000}, {0xc2562000}, {0xc2564000}, {0xc2566000}, + {0xc2568000}, {0xc256a000}, {0xc256c000}, {0xc256e000}, + {0xc2570000}, {0xc2572000}, {0xc2574000}, {0xc2576000}, + {0xc2578000}, {0xc257a000}, {0xc257c000}, {0xc257e000}, + {0xc2580000}, {0xc2582000}, {0xc2584000}, {0xc2586000}, + {0xc2588000}, {0xc258a000}, {0xc258c000}, {0xc258e000}, + {0xc2590000}, {0xc2592000}, {0xc2594000}, {0xc2596000}, + {0xc2598000}, {0xc259a000}, {0xc259c000}, {0xc259e000}, + {0xc25a0000}, {0xc25a2000}, {0xc25a4000}, {0xc25a6000}, + {0xc25a8000}, {0xc25aa000}, {0xc25ac000}, {0xc25ae000}, + {0xc25b0000}, {0xc25b2000}, {0xc25b4000}, {0xc25b6000}, + {0xc25b8000}, {0xc25ba000}, {0xc25bc000}, {0xc25be000}, + {0xc25c0000}, {0xc25c2000}, {0xc25c4000}, {0xc25c6000}, + {0xc25c8000}, {0xc25ca000}, {0xc25cc000}, {0xc25ce000}, + {0xc25d0000}, {0xc25d2000}, {0xc25d4000}, {0xc25d6000}, + {0xc25d8000}, {0xc25da000}, {0xc25dc000}, {0xc25de000}, + {0xc25e0000}, {0xc25e2000}, {0xc25e4000}, {0xc25e6000}, + {0xc25e8000}, {0xc25ea000}, {0xc25ec000}, {0xc25ee000}, + {0xc25f0000}, {0xc25f2000}, {0xc25f4000}, {0xc25f6000}, + {0xc25f8000}, {0xc25fa000}, {0xc25fc000}, {0xc25fe000}, + {0xc2600000}, {0xc2602000}, {0xc2604000}, {0xc2606000}, + {0xc2608000}, {0xc260a000}, {0xc260c000}, {0xc260e000}, + {0xc2610000}, {0xc2612000}, {0xc2614000}, {0xc2616000}, + {0xc2618000}, {0xc261a000}, {0xc261c000}, {0xc261e000}, + {0xc2620000}, {0xc2622000}, {0xc2624000}, {0xc2626000}, + {0xc2628000}, {0xc262a000}, {0xc262c000}, {0xc262e000}, + {0xc2630000}, {0xc2632000}, {0xc2634000}, {0xc2636000}, + {0xc2638000}, {0xc263a000}, {0xc263c000}, {0xc263e000}, + {0xc2640000}, {0xc2642000}, {0xc2644000}, {0xc2646000}, + {0xc2648000}, {0xc264a000}, {0xc264c000}, {0xc264e000}, + {0xc2650000}, {0xc2652000}, {0xc2654000}, {0xc2656000}, + {0xc2658000}, {0xc265a000}, {0xc265c000}, {0xc265e000}, + {0xc2660000}, {0xc2662000}, {0xc2664000}, {0xc2666000}, + {0xc2668000}, {0xc266a000}, {0xc266c000}, {0xc266e000}, + {0xc2670000}, {0xc2672000}, {0xc2674000}, {0xc2676000}, + {0xc2678000}, {0xc267a000}, {0xc267c000}, {0xc267e000}, + {0xc2680000}, {0xc2682000}, {0xc2684000}, {0xc2686000}, + {0xc2688000}, {0xc268a000}, {0xc268c000}, {0xc268e000}, + {0xc2690000}, {0xc2692000}, {0xc2694000}, {0xc2696000}, + {0xc2698000}, {0xc269a000}, {0xc269c000}, {0xc269e000}, + {0xc26a0000}, {0xc26a2000}, {0xc26a4000}, {0xc26a6000}, + {0xc26a8000}, {0xc26aa000}, {0xc26ac000}, {0xc26ae000}, + {0xc26b0000}, {0xc26b2000}, {0xc26b4000}, {0xc26b6000}, + {0xc26b8000}, {0xc26ba000}, {0xc26bc000}, {0xc26be000}, + {0xc26c0000}, {0xc26c2000}, {0xc26c4000}, {0xc26c6000}, + {0xc26c8000}, {0xc26ca000}, {0xc26cc000}, {0xc26ce000}, + {0xc26d0000}, {0xc26d2000}, {0xc26d4000}, {0xc26d6000}, + {0xc26d8000}, {0xc26da000}, {0xc26dc000}, {0xc26de000}, + {0xc26e0000}, {0xc26e2000}, {0xc26e4000}, {0xc26e6000}, + {0xc26e8000}, {0xc26ea000}, {0xc26ec000}, {0xc26ee000}, + {0xc26f0000}, {0xc26f2000}, {0xc26f4000}, {0xc26f6000}, + {0xc26f8000}, {0xc26fa000}, {0xc26fc000}, {0xc26fe000}, + {0xc2700000}, {0xc2702000}, {0xc2704000}, {0xc2706000}, + {0xc2708000}, {0xc270a000}, {0xc270c000}, {0xc270e000}, + {0xc2710000}, {0xc2712000}, {0xc2714000}, {0xc2716000}, + {0xc2718000}, {0xc271a000}, {0xc271c000}, {0xc271e000}, + {0xc2720000}, {0xc2722000}, {0xc2724000}, {0xc2726000}, + {0xc2728000}, {0xc272a000}, {0xc272c000}, {0xc272e000}, + {0xc2730000}, {0xc2732000}, {0xc2734000}, {0xc2736000}, + {0xc2738000}, {0xc273a000}, {0xc273c000}, {0xc273e000}, + {0xc2740000}, {0xc2742000}, {0xc2744000}, {0xc2746000}, + {0xc2748000}, {0xc274a000}, {0xc274c000}, {0xc274e000}, + {0xc2750000}, {0xc2752000}, {0xc2754000}, {0xc2756000}, + {0xc2758000}, {0xc275a000}, {0xc275c000}, {0xc275e000}, + {0xc2760000}, {0xc2762000}, {0xc2764000}, {0xc2766000}, + {0xc2768000}, {0xc276a000}, {0xc276c000}, {0xc276e000}, + {0xc2770000}, {0xc2772000}, {0xc2774000}, {0xc2776000}, + {0xc2778000}, {0xc277a000}, {0xc277c000}, {0xc277e000}, + {0xc2780000}, {0xc2782000}, {0xc2784000}, {0xc2786000}, + {0xc2788000}, {0xc278a000}, {0xc278c000}, {0xc278e000}, + {0xc2790000}, {0xc2792000}, {0xc2794000}, {0xc2796000}, + {0xc2798000}, {0xc279a000}, {0xc279c000}, {0xc279e000}, + {0xc27a0000}, {0xc27a2000}, {0xc27a4000}, {0xc27a6000}, + {0xc27a8000}, {0xc27aa000}, {0xc27ac000}, {0xc27ae000}, + {0xc27b0000}, {0xc27b2000}, {0xc27b4000}, {0xc27b6000}, + {0xc27b8000}, {0xc27ba000}, {0xc27bc000}, {0xc27be000}, + {0xc27c0000}, {0xc27c2000}, {0xc27c4000}, {0xc27c6000}, + {0xc27c8000}, {0xc27ca000}, {0xc27cc000}, {0xc27ce000}, + {0xc27d0000}, {0xc27d2000}, {0xc27d4000}, {0xc27d6000}, + {0xc27d8000}, {0xc27da000}, {0xc27dc000}, {0xc27de000}, + {0xc27e0000}, {0xc27e2000}, {0xc27e4000}, {0xc27e6000}, + {0xc27e8000}, {0xc27ea000}, {0xc27ec000}, {0xc27ee000}, + {0xc27f0000}, {0xc27f2000}, {0xc27f4000}, {0xc27f6000}, + {0xc27f8000}, {0xc27fa000}, {0xc27fc000}, {0xc27fe000}, + {0xc2800000}, {0xc2802000}, {0xc2804000}, {0xc2806000}, + {0xc2808000}, {0xc280a000}, {0xc280c000}, {0xc280e000}, + {0xc2810000}, {0xc2812000}, {0xc2814000}, {0xc2816000}, + {0xc2818000}, {0xc281a000}, {0xc281c000}, {0xc281e000}, + {0xc2820000}, {0xc2822000}, {0xc2824000}, {0xc2826000}, + {0xc2828000}, {0xc282a000}, {0xc282c000}, {0xc282e000}, + {0xc2830000}, {0xc2832000}, {0xc2834000}, {0xc2836000}, + {0xc2838000}, {0xc283a000}, {0xc283c000}, {0xc283e000}, + {0xc2840000}, {0xc2842000}, {0xc2844000}, {0xc2846000}, + {0xc2848000}, {0xc284a000}, {0xc284c000}, {0xc284e000}, + {0xc2850000}, {0xc2852000}, {0xc2854000}, {0xc2856000}, + {0xc2858000}, {0xc285a000}, {0xc285c000}, {0xc285e000}, + {0xc2860000}, {0xc2862000}, {0xc2864000}, {0xc2866000}, + {0xc2868000}, {0xc286a000}, {0xc286c000}, {0xc286e000}, + {0xc2870000}, {0xc2872000}, {0xc2874000}, {0xc2876000}, + {0xc2878000}, {0xc287a000}, {0xc287c000}, {0xc287e000}, + {0xc2880000}, {0xc2882000}, {0xc2884000}, {0xc2886000}, + {0xc2888000}, {0xc288a000}, {0xc288c000}, {0xc288e000}, + {0xc2890000}, {0xc2892000}, {0xc2894000}, {0xc2896000}, + {0xc2898000}, {0xc289a000}, {0xc289c000}, {0xc289e000}, + {0xc28a0000}, {0xc28a2000}, {0xc28a4000}, {0xc28a6000}, + {0xc28a8000}, {0xc28aa000}, {0xc28ac000}, {0xc28ae000}, + {0xc28b0000}, {0xc28b2000}, {0xc28b4000}, {0xc28b6000}, + {0xc28b8000}, {0xc28ba000}, {0xc28bc000}, {0xc28be000}, + {0xc28c0000}, {0xc28c2000}, {0xc28c4000}, {0xc28c6000}, + {0xc28c8000}, {0xc28ca000}, {0xc28cc000}, {0xc28ce000}, + {0xc28d0000}, {0xc28d2000}, {0xc28d4000}, {0xc28d6000}, + {0xc28d8000}, {0xc28da000}, {0xc28dc000}, {0xc28de000}, + {0xc28e0000}, {0xc28e2000}, {0xc28e4000}, {0xc28e6000}, + {0xc28e8000}, {0xc28ea000}, {0xc28ec000}, {0xc28ee000}, + {0xc28f0000}, {0xc28f2000}, {0xc28f4000}, {0xc28f6000}, + {0xc28f8000}, {0xc28fa000}, {0xc28fc000}, {0xc28fe000}, + {0xc2900000}, {0xc2902000}, {0xc2904000}, {0xc2906000}, + {0xc2908000}, {0xc290a000}, {0xc290c000}, {0xc290e000}, + {0xc2910000}, {0xc2912000}, {0xc2914000}, {0xc2916000}, + {0xc2918000}, {0xc291a000}, {0xc291c000}, {0xc291e000}, + {0xc2920000}, {0xc2922000}, {0xc2924000}, {0xc2926000}, + {0xc2928000}, {0xc292a000}, {0xc292c000}, {0xc292e000}, + {0xc2930000}, {0xc2932000}, {0xc2934000}, {0xc2936000}, + {0xc2938000}, {0xc293a000}, {0xc293c000}, {0xc293e000}, + {0xc2940000}, {0xc2942000}, {0xc2944000}, {0xc2946000}, + {0xc2948000}, {0xc294a000}, {0xc294c000}, {0xc294e000}, + {0xc2950000}, {0xc2952000}, {0xc2954000}, {0xc2956000}, + {0xc2958000}, {0xc295a000}, {0xc295c000}, {0xc295e000}, + {0xc2960000}, {0xc2962000}, {0xc2964000}, {0xc2966000}, + {0xc2968000}, {0xc296a000}, {0xc296c000}, {0xc296e000}, + {0xc2970000}, {0xc2972000}, {0xc2974000}, {0xc2976000}, + {0xc2978000}, {0xc297a000}, {0xc297c000}, {0xc297e000}, + {0xc2980000}, {0xc2982000}, {0xc2984000}, {0xc2986000}, + {0xc2988000}, {0xc298a000}, {0xc298c000}, {0xc298e000}, + {0xc2990000}, {0xc2992000}, {0xc2994000}, {0xc2996000}, + {0xc2998000}, {0xc299a000}, {0xc299c000}, {0xc299e000}, + {0xc29a0000}, {0xc29a2000}, {0xc29a4000}, {0xc29a6000}, + {0xc29a8000}, {0xc29aa000}, {0xc29ac000}, {0xc29ae000}, + {0xc29b0000}, {0xc29b2000}, {0xc29b4000}, {0xc29b6000}, + {0xc29b8000}, {0xc29ba000}, {0xc29bc000}, {0xc29be000}, + {0xc29c0000}, {0xc29c2000}, {0xc29c4000}, {0xc29c6000}, + {0xc29c8000}, {0xc29ca000}, {0xc29cc000}, {0xc29ce000}, + {0xc29d0000}, {0xc29d2000}, {0xc29d4000}, {0xc29d6000}, + {0xc29d8000}, {0xc29da000}, {0xc29dc000}, {0xc29de000}, + {0xc29e0000}, {0xc29e2000}, {0xc29e4000}, {0xc29e6000}, + {0xc29e8000}, {0xc29ea000}, {0xc29ec000}, {0xc29ee000}, + {0xc29f0000}, {0xc29f2000}, {0xc29f4000}, {0xc29f6000}, + {0xc29f8000}, {0xc29fa000}, {0xc29fc000}, {0xc29fe000}, + {0xc2a00000}, {0xc2a02000}, {0xc2a04000}, {0xc2a06000}, + {0xc2a08000}, {0xc2a0a000}, {0xc2a0c000}, {0xc2a0e000}, + {0xc2a10000}, {0xc2a12000}, {0xc2a14000}, {0xc2a16000}, + {0xc2a18000}, {0xc2a1a000}, {0xc2a1c000}, {0xc2a1e000}, + {0xc2a20000}, {0xc2a22000}, {0xc2a24000}, {0xc2a26000}, + {0xc2a28000}, {0xc2a2a000}, {0xc2a2c000}, {0xc2a2e000}, + {0xc2a30000}, {0xc2a32000}, {0xc2a34000}, {0xc2a36000}, + {0xc2a38000}, {0xc2a3a000}, {0xc2a3c000}, {0xc2a3e000}, + {0xc2a40000}, {0xc2a42000}, {0xc2a44000}, {0xc2a46000}, + {0xc2a48000}, {0xc2a4a000}, {0xc2a4c000}, {0xc2a4e000}, + {0xc2a50000}, {0xc2a52000}, {0xc2a54000}, {0xc2a56000}, + {0xc2a58000}, {0xc2a5a000}, {0xc2a5c000}, {0xc2a5e000}, + {0xc2a60000}, {0xc2a62000}, {0xc2a64000}, {0xc2a66000}, + {0xc2a68000}, {0xc2a6a000}, {0xc2a6c000}, {0xc2a6e000}, + {0xc2a70000}, {0xc2a72000}, {0xc2a74000}, {0xc2a76000}, + {0xc2a78000}, {0xc2a7a000}, {0xc2a7c000}, {0xc2a7e000}, + {0xc2a80000}, {0xc2a82000}, {0xc2a84000}, {0xc2a86000}, + {0xc2a88000}, {0xc2a8a000}, {0xc2a8c000}, {0xc2a8e000}, + {0xc2a90000}, {0xc2a92000}, {0xc2a94000}, {0xc2a96000}, + {0xc2a98000}, {0xc2a9a000}, {0xc2a9c000}, {0xc2a9e000}, + {0xc2aa0000}, {0xc2aa2000}, {0xc2aa4000}, {0xc2aa6000}, + {0xc2aa8000}, {0xc2aaa000}, {0xc2aac000}, {0xc2aae000}, + {0xc2ab0000}, {0xc2ab2000}, {0xc2ab4000}, {0xc2ab6000}, + {0xc2ab8000}, {0xc2aba000}, {0xc2abc000}, {0xc2abe000}, + {0xc2ac0000}, {0xc2ac2000}, {0xc2ac4000}, {0xc2ac6000}, + {0xc2ac8000}, {0xc2aca000}, {0xc2acc000}, {0xc2ace000}, + {0xc2ad0000}, {0xc2ad2000}, {0xc2ad4000}, {0xc2ad6000}, + {0xc2ad8000}, {0xc2ada000}, {0xc2adc000}, {0xc2ade000}, + {0xc2ae0000}, {0xc2ae2000}, {0xc2ae4000}, {0xc2ae6000}, + {0xc2ae8000}, {0xc2aea000}, {0xc2aec000}, {0xc2aee000}, + {0xc2af0000}, {0xc2af2000}, {0xc2af4000}, {0xc2af6000}, + {0xc2af8000}, {0xc2afa000}, {0xc2afc000}, {0xc2afe000}, + {0xc2b00000}, {0xc2b02000}, {0xc2b04000}, {0xc2b06000}, + {0xc2b08000}, {0xc2b0a000}, {0xc2b0c000}, {0xc2b0e000}, + {0xc2b10000}, {0xc2b12000}, {0xc2b14000}, {0xc2b16000}, + {0xc2b18000}, {0xc2b1a000}, {0xc2b1c000}, {0xc2b1e000}, + {0xc2b20000}, {0xc2b22000}, {0xc2b24000}, {0xc2b26000}, + {0xc2b28000}, {0xc2b2a000}, {0xc2b2c000}, {0xc2b2e000}, + {0xc2b30000}, {0xc2b32000}, {0xc2b34000}, {0xc2b36000}, + {0xc2b38000}, {0xc2b3a000}, {0xc2b3c000}, {0xc2b3e000}, + {0xc2b40000}, {0xc2b42000}, {0xc2b44000}, {0xc2b46000}, + {0xc2b48000}, {0xc2b4a000}, {0xc2b4c000}, {0xc2b4e000}, + {0xc2b50000}, {0xc2b52000}, {0xc2b54000}, {0xc2b56000}, + {0xc2b58000}, {0xc2b5a000}, {0xc2b5c000}, {0xc2b5e000}, + {0xc2b60000}, {0xc2b62000}, {0xc2b64000}, {0xc2b66000}, + {0xc2b68000}, {0xc2b6a000}, {0xc2b6c000}, {0xc2b6e000}, + {0xc2b70000}, {0xc2b72000}, {0xc2b74000}, {0xc2b76000}, + {0xc2b78000}, {0xc2b7a000}, {0xc2b7c000}, {0xc2b7e000}, + {0xc2b80000}, {0xc2b82000}, {0xc2b84000}, {0xc2b86000}, + {0xc2b88000}, {0xc2b8a000}, {0xc2b8c000}, {0xc2b8e000}, + {0xc2b90000}, {0xc2b92000}, {0xc2b94000}, {0xc2b96000}, + {0xc2b98000}, {0xc2b9a000}, {0xc2b9c000}, {0xc2b9e000}, + {0xc2ba0000}, {0xc2ba2000}, {0xc2ba4000}, {0xc2ba6000}, + {0xc2ba8000}, {0xc2baa000}, {0xc2bac000}, {0xc2bae000}, + {0xc2bb0000}, {0xc2bb2000}, {0xc2bb4000}, {0xc2bb6000}, + {0xc2bb8000}, {0xc2bba000}, {0xc2bbc000}, {0xc2bbe000}, + {0xc2bc0000}, {0xc2bc2000}, {0xc2bc4000}, {0xc2bc6000}, + {0xc2bc8000}, {0xc2bca000}, {0xc2bcc000}, {0xc2bce000}, + {0xc2bd0000}, {0xc2bd2000}, {0xc2bd4000}, {0xc2bd6000}, + {0xc2bd8000}, {0xc2bda000}, {0xc2bdc000}, {0xc2bde000}, + {0xc2be0000}, {0xc2be2000}, {0xc2be4000}, {0xc2be6000}, + {0xc2be8000}, {0xc2bea000}, {0xc2bec000}, {0xc2bee000}, + {0xc2bf0000}, {0xc2bf2000}, {0xc2bf4000}, {0xc2bf6000}, + {0xc2bf8000}, {0xc2bfa000}, {0xc2bfc000}, {0xc2bfe000}, + {0xc2c00000}, {0xc2c02000}, {0xc2c04000}, {0xc2c06000}, + {0xc2c08000}, {0xc2c0a000}, {0xc2c0c000}, {0xc2c0e000}, + {0xc2c10000}, {0xc2c12000}, {0xc2c14000}, {0xc2c16000}, + {0xc2c18000}, {0xc2c1a000}, {0xc2c1c000}, {0xc2c1e000}, + {0xc2c20000}, {0xc2c22000}, {0xc2c24000}, {0xc2c26000}, + {0xc2c28000}, {0xc2c2a000}, {0xc2c2c000}, {0xc2c2e000}, + {0xc2c30000}, {0xc2c32000}, {0xc2c34000}, {0xc2c36000}, + {0xc2c38000}, {0xc2c3a000}, {0xc2c3c000}, {0xc2c3e000}, + {0xc2c40000}, {0xc2c42000}, {0xc2c44000}, {0xc2c46000}, + {0xc2c48000}, {0xc2c4a000}, {0xc2c4c000}, {0xc2c4e000}, + {0xc2c50000}, {0xc2c52000}, {0xc2c54000}, {0xc2c56000}, + {0xc2c58000}, {0xc2c5a000}, {0xc2c5c000}, {0xc2c5e000}, + {0xc2c60000}, {0xc2c62000}, {0xc2c64000}, {0xc2c66000}, + {0xc2c68000}, {0xc2c6a000}, {0xc2c6c000}, {0xc2c6e000}, + {0xc2c70000}, {0xc2c72000}, {0xc2c74000}, {0xc2c76000}, + {0xc2c78000}, {0xc2c7a000}, {0xc2c7c000}, {0xc2c7e000}, + {0xc2c80000}, {0xc2c82000}, {0xc2c84000}, {0xc2c86000}, + {0xc2c88000}, {0xc2c8a000}, {0xc2c8c000}, {0xc2c8e000}, + {0xc2c90000}, {0xc2c92000}, {0xc2c94000}, {0xc2c96000}, + {0xc2c98000}, {0xc2c9a000}, {0xc2c9c000}, {0xc2c9e000}, + {0xc2ca0000}, {0xc2ca2000}, {0xc2ca4000}, {0xc2ca6000}, + {0xc2ca8000}, {0xc2caa000}, {0xc2cac000}, {0xc2cae000}, + {0xc2cb0000}, {0xc2cb2000}, {0xc2cb4000}, {0xc2cb6000}, + {0xc2cb8000}, {0xc2cba000}, {0xc2cbc000}, {0xc2cbe000}, + {0xc2cc0000}, {0xc2cc2000}, {0xc2cc4000}, {0xc2cc6000}, + {0xc2cc8000}, {0xc2cca000}, {0xc2ccc000}, {0xc2cce000}, + {0xc2cd0000}, {0xc2cd2000}, {0xc2cd4000}, {0xc2cd6000}, + {0xc2cd8000}, {0xc2cda000}, {0xc2cdc000}, {0xc2cde000}, + {0xc2ce0000}, {0xc2ce2000}, {0xc2ce4000}, {0xc2ce6000}, + {0xc2ce8000}, {0xc2cea000}, {0xc2cec000}, {0xc2cee000}, + {0xc2cf0000}, {0xc2cf2000}, {0xc2cf4000}, {0xc2cf6000}, + {0xc2cf8000}, {0xc2cfa000}, {0xc2cfc000}, {0xc2cfe000}, + {0xc2d00000}, {0xc2d02000}, {0xc2d04000}, {0xc2d06000}, + {0xc2d08000}, {0xc2d0a000}, {0xc2d0c000}, {0xc2d0e000}, + {0xc2d10000}, {0xc2d12000}, {0xc2d14000}, {0xc2d16000}, + {0xc2d18000}, {0xc2d1a000}, {0xc2d1c000}, {0xc2d1e000}, + {0xc2d20000}, {0xc2d22000}, {0xc2d24000}, {0xc2d26000}, + {0xc2d28000}, {0xc2d2a000}, {0xc2d2c000}, {0xc2d2e000}, + {0xc2d30000}, {0xc2d32000}, {0xc2d34000}, {0xc2d36000}, + {0xc2d38000}, {0xc2d3a000}, {0xc2d3c000}, {0xc2d3e000}, + {0xc2d40000}, {0xc2d42000}, {0xc2d44000}, {0xc2d46000}, + {0xc2d48000}, {0xc2d4a000}, {0xc2d4c000}, {0xc2d4e000}, + {0xc2d50000}, {0xc2d52000}, {0xc2d54000}, {0xc2d56000}, + {0xc2d58000}, {0xc2d5a000}, {0xc2d5c000}, {0xc2d5e000}, + {0xc2d60000}, {0xc2d62000}, {0xc2d64000}, {0xc2d66000}, + {0xc2d68000}, {0xc2d6a000}, {0xc2d6c000}, {0xc2d6e000}, + {0xc2d70000}, {0xc2d72000}, {0xc2d74000}, {0xc2d76000}, + {0xc2d78000}, {0xc2d7a000}, {0xc2d7c000}, {0xc2d7e000}, + {0xc2d80000}, {0xc2d82000}, {0xc2d84000}, {0xc2d86000}, + {0xc2d88000}, {0xc2d8a000}, {0xc2d8c000}, {0xc2d8e000}, + {0xc2d90000}, {0xc2d92000}, {0xc2d94000}, {0xc2d96000}, + {0xc2d98000}, {0xc2d9a000}, {0xc2d9c000}, {0xc2d9e000}, + {0xc2da0000}, {0xc2da2000}, {0xc2da4000}, {0xc2da6000}, + {0xc2da8000}, {0xc2daa000}, {0xc2dac000}, {0xc2dae000}, + {0xc2db0000}, {0xc2db2000}, {0xc2db4000}, {0xc2db6000}, + {0xc2db8000}, {0xc2dba000}, {0xc2dbc000}, {0xc2dbe000}, + {0xc2dc0000}, {0xc2dc2000}, {0xc2dc4000}, {0xc2dc6000}, + {0xc2dc8000}, {0xc2dca000}, {0xc2dcc000}, {0xc2dce000}, + {0xc2dd0000}, {0xc2dd2000}, {0xc2dd4000}, {0xc2dd6000}, + {0xc2dd8000}, {0xc2dda000}, {0xc2ddc000}, {0xc2dde000}, + {0xc2de0000}, {0xc2de2000}, {0xc2de4000}, {0xc2de6000}, + {0xc2de8000}, {0xc2dea000}, {0xc2dec000}, {0xc2dee000}, + {0xc2df0000}, {0xc2df2000}, {0xc2df4000}, {0xc2df6000}, + {0xc2df8000}, {0xc2dfa000}, {0xc2dfc000}, {0xc2dfe000}, + {0xc2e00000}, {0xc2e02000}, {0xc2e04000}, {0xc2e06000}, + {0xc2e08000}, {0xc2e0a000}, {0xc2e0c000}, {0xc2e0e000}, + {0xc2e10000}, {0xc2e12000}, {0xc2e14000}, {0xc2e16000}, + {0xc2e18000}, {0xc2e1a000}, {0xc2e1c000}, {0xc2e1e000}, + {0xc2e20000}, {0xc2e22000}, {0xc2e24000}, {0xc2e26000}, + {0xc2e28000}, {0xc2e2a000}, {0xc2e2c000}, {0xc2e2e000}, + {0xc2e30000}, {0xc2e32000}, {0xc2e34000}, {0xc2e36000}, + {0xc2e38000}, {0xc2e3a000}, {0xc2e3c000}, {0xc2e3e000}, + {0xc2e40000}, {0xc2e42000}, {0xc2e44000}, {0xc2e46000}, + {0xc2e48000}, {0xc2e4a000}, {0xc2e4c000}, {0xc2e4e000}, + {0xc2e50000}, {0xc2e52000}, {0xc2e54000}, {0xc2e56000}, + {0xc2e58000}, {0xc2e5a000}, {0xc2e5c000}, {0xc2e5e000}, + {0xc2e60000}, {0xc2e62000}, {0xc2e64000}, {0xc2e66000}, + {0xc2e68000}, {0xc2e6a000}, {0xc2e6c000}, {0xc2e6e000}, + {0xc2e70000}, {0xc2e72000}, {0xc2e74000}, {0xc2e76000}, + {0xc2e78000}, {0xc2e7a000}, {0xc2e7c000}, {0xc2e7e000}, + {0xc2e80000}, {0xc2e82000}, {0xc2e84000}, {0xc2e86000}, + {0xc2e88000}, {0xc2e8a000}, {0xc2e8c000}, {0xc2e8e000}, + {0xc2e90000}, {0xc2e92000}, {0xc2e94000}, {0xc2e96000}, + {0xc2e98000}, {0xc2e9a000}, {0xc2e9c000}, {0xc2e9e000}, + {0xc2ea0000}, {0xc2ea2000}, {0xc2ea4000}, {0xc2ea6000}, + {0xc2ea8000}, {0xc2eaa000}, {0xc2eac000}, {0xc2eae000}, + {0xc2eb0000}, {0xc2eb2000}, {0xc2eb4000}, {0xc2eb6000}, + {0xc2eb8000}, {0xc2eba000}, {0xc2ebc000}, {0xc2ebe000}, + {0xc2ec0000}, {0xc2ec2000}, {0xc2ec4000}, {0xc2ec6000}, + {0xc2ec8000}, {0xc2eca000}, {0xc2ecc000}, {0xc2ece000}, + {0xc2ed0000}, {0xc2ed2000}, {0xc2ed4000}, {0xc2ed6000}, + {0xc2ed8000}, {0xc2eda000}, {0xc2edc000}, {0xc2ede000}, + {0xc2ee0000}, {0xc2ee2000}, {0xc2ee4000}, {0xc2ee6000}, + {0xc2ee8000}, {0xc2eea000}, {0xc2eec000}, {0xc2eee000}, + {0xc2ef0000}, {0xc2ef2000}, {0xc2ef4000}, {0xc2ef6000}, + {0xc2ef8000}, {0xc2efa000}, {0xc2efc000}, {0xc2efe000}, + {0xc2f00000}, {0xc2f02000}, {0xc2f04000}, {0xc2f06000}, + {0xc2f08000}, {0xc2f0a000}, {0xc2f0c000}, {0xc2f0e000}, + {0xc2f10000}, {0xc2f12000}, {0xc2f14000}, {0xc2f16000}, + {0xc2f18000}, {0xc2f1a000}, {0xc2f1c000}, {0xc2f1e000}, + {0xc2f20000}, {0xc2f22000}, {0xc2f24000}, {0xc2f26000}, + {0xc2f28000}, {0xc2f2a000}, {0xc2f2c000}, {0xc2f2e000}, + {0xc2f30000}, {0xc2f32000}, {0xc2f34000}, {0xc2f36000}, + {0xc2f38000}, {0xc2f3a000}, {0xc2f3c000}, {0xc2f3e000}, + {0xc2f40000}, {0xc2f42000}, {0xc2f44000}, {0xc2f46000}, + {0xc2f48000}, {0xc2f4a000}, {0xc2f4c000}, {0xc2f4e000}, + {0xc2f50000}, {0xc2f52000}, {0xc2f54000}, {0xc2f56000}, + {0xc2f58000}, {0xc2f5a000}, {0xc2f5c000}, {0xc2f5e000}, + {0xc2f60000}, {0xc2f62000}, {0xc2f64000}, {0xc2f66000}, + {0xc2f68000}, {0xc2f6a000}, {0xc2f6c000}, {0xc2f6e000}, + {0xc2f70000}, {0xc2f72000}, {0xc2f74000}, {0xc2f76000}, + {0xc2f78000}, {0xc2f7a000}, {0xc2f7c000}, {0xc2f7e000}, + {0xc2f80000}, {0xc2f82000}, {0xc2f84000}, {0xc2f86000}, + {0xc2f88000}, {0xc2f8a000}, {0xc2f8c000}, {0xc2f8e000}, + {0xc2f90000}, {0xc2f92000}, {0xc2f94000}, {0xc2f96000}, + {0xc2f98000}, {0xc2f9a000}, {0xc2f9c000}, {0xc2f9e000}, + {0xc2fa0000}, {0xc2fa2000}, {0xc2fa4000}, {0xc2fa6000}, + {0xc2fa8000}, {0xc2faa000}, {0xc2fac000}, {0xc2fae000}, + {0xc2fb0000}, {0xc2fb2000}, {0xc2fb4000}, {0xc2fb6000}, + {0xc2fb8000}, {0xc2fba000}, {0xc2fbc000}, {0xc2fbe000}, + {0xc2fc0000}, {0xc2fc2000}, {0xc2fc4000}, {0xc2fc6000}, + {0xc2fc8000}, {0xc2fca000}, {0xc2fcc000}, {0xc2fce000}, + {0xc2fd0000}, {0xc2fd2000}, {0xc2fd4000}, {0xc2fd6000}, + {0xc2fd8000}, {0xc2fda000}, {0xc2fdc000}, {0xc2fde000}, + {0xc2fe0000}, {0xc2fe2000}, {0xc2fe4000}, {0xc2fe6000}, + {0xc2fe8000}, {0xc2fea000}, {0xc2fec000}, {0xc2fee000}, + {0xc2ff0000}, {0xc2ff2000}, {0xc2ff4000}, {0xc2ff6000}, + {0xc2ff8000}, {0xc2ffa000}, {0xc2ffc000}, {0xc2ffe000}, + {0xc3000000}, {0xc3002000}, {0xc3004000}, {0xc3006000}, + {0xc3008000}, {0xc300a000}, {0xc300c000}, {0xc300e000}, + {0xc3010000}, {0xc3012000}, {0xc3014000}, {0xc3016000}, + {0xc3018000}, {0xc301a000}, {0xc301c000}, {0xc301e000}, + {0xc3020000}, {0xc3022000}, {0xc3024000}, {0xc3026000}, + {0xc3028000}, {0xc302a000}, {0xc302c000}, {0xc302e000}, + {0xc3030000}, {0xc3032000}, {0xc3034000}, {0xc3036000}, + {0xc3038000}, {0xc303a000}, {0xc303c000}, {0xc303e000}, + {0xc3040000}, {0xc3042000}, {0xc3044000}, {0xc3046000}, + {0xc3048000}, {0xc304a000}, {0xc304c000}, {0xc304e000}, + {0xc3050000}, {0xc3052000}, {0xc3054000}, {0xc3056000}, + {0xc3058000}, {0xc305a000}, {0xc305c000}, {0xc305e000}, + {0xc3060000}, {0xc3062000}, {0xc3064000}, {0xc3066000}, + {0xc3068000}, {0xc306a000}, {0xc306c000}, {0xc306e000}, + {0xc3070000}, {0xc3072000}, {0xc3074000}, {0xc3076000}, + {0xc3078000}, {0xc307a000}, {0xc307c000}, {0xc307e000}, + {0xc3080000}, {0xc3082000}, {0xc3084000}, {0xc3086000}, + {0xc3088000}, {0xc308a000}, {0xc308c000}, {0xc308e000}, + {0xc3090000}, {0xc3092000}, {0xc3094000}, {0xc3096000}, + {0xc3098000}, {0xc309a000}, {0xc309c000}, {0xc309e000}, + {0xc30a0000}, {0xc30a2000}, {0xc30a4000}, {0xc30a6000}, + {0xc30a8000}, {0xc30aa000}, {0xc30ac000}, {0xc30ae000}, + {0xc30b0000}, {0xc30b2000}, {0xc30b4000}, {0xc30b6000}, + {0xc30b8000}, {0xc30ba000}, {0xc30bc000}, {0xc30be000}, + {0xc30c0000}, {0xc30c2000}, {0xc30c4000}, {0xc30c6000}, + {0xc30c8000}, {0xc30ca000}, {0xc30cc000}, {0xc30ce000}, + {0xc30d0000}, {0xc30d2000}, {0xc30d4000}, {0xc30d6000}, + {0xc30d8000}, {0xc30da000}, {0xc30dc000}, {0xc30de000}, + {0xc30e0000}, {0xc30e2000}, {0xc30e4000}, {0xc30e6000}, + {0xc30e8000}, {0xc30ea000}, {0xc30ec000}, {0xc30ee000}, + {0xc30f0000}, {0xc30f2000}, {0xc30f4000}, {0xc30f6000}, + {0xc30f8000}, {0xc30fa000}, {0xc30fc000}, {0xc30fe000}, + {0xc3100000}, {0xc3102000}, {0xc3104000}, {0xc3106000}, + {0xc3108000}, {0xc310a000}, {0xc310c000}, {0xc310e000}, + {0xc3110000}, {0xc3112000}, {0xc3114000}, {0xc3116000}, + {0xc3118000}, {0xc311a000}, {0xc311c000}, {0xc311e000}, + {0xc3120000}, {0xc3122000}, {0xc3124000}, {0xc3126000}, + {0xc3128000}, {0xc312a000}, {0xc312c000}, {0xc312e000}, + {0xc3130000}, {0xc3132000}, {0xc3134000}, {0xc3136000}, + {0xc3138000}, {0xc313a000}, {0xc313c000}, {0xc313e000}, + {0xc3140000}, {0xc3142000}, {0xc3144000}, {0xc3146000}, + {0xc3148000}, {0xc314a000}, {0xc314c000}, {0xc314e000}, + {0xc3150000}, {0xc3152000}, {0xc3154000}, {0xc3156000}, + {0xc3158000}, {0xc315a000}, {0xc315c000}, {0xc315e000}, + {0xc3160000}, {0xc3162000}, {0xc3164000}, {0xc3166000}, + {0xc3168000}, {0xc316a000}, {0xc316c000}, {0xc316e000}, + {0xc3170000}, {0xc3172000}, {0xc3174000}, {0xc3176000}, + {0xc3178000}, {0xc317a000}, {0xc317c000}, {0xc317e000}, + {0xc3180000}, {0xc3182000}, {0xc3184000}, {0xc3186000}, + {0xc3188000}, {0xc318a000}, {0xc318c000}, {0xc318e000}, + {0xc3190000}, {0xc3192000}, {0xc3194000}, {0xc3196000}, + {0xc3198000}, {0xc319a000}, {0xc319c000}, {0xc319e000}, + {0xc31a0000}, {0xc31a2000}, {0xc31a4000}, {0xc31a6000}, + {0xc31a8000}, {0xc31aa000}, {0xc31ac000}, {0xc31ae000}, + {0xc31b0000}, {0xc31b2000}, {0xc31b4000}, {0xc31b6000}, + {0xc31b8000}, {0xc31ba000}, {0xc31bc000}, {0xc31be000}, + {0xc31c0000}, {0xc31c2000}, {0xc31c4000}, {0xc31c6000}, + {0xc31c8000}, {0xc31ca000}, {0xc31cc000}, {0xc31ce000}, + {0xc31d0000}, {0xc31d2000}, {0xc31d4000}, {0xc31d6000}, + {0xc31d8000}, {0xc31da000}, {0xc31dc000}, {0xc31de000}, + {0xc31e0000}, {0xc31e2000}, {0xc31e4000}, {0xc31e6000}, + {0xc31e8000}, {0xc31ea000}, {0xc31ec000}, {0xc31ee000}, + {0xc31f0000}, {0xc31f2000}, {0xc31f4000}, {0xc31f6000}, + {0xc31f8000}, {0xc31fa000}, {0xc31fc000}, {0xc31fe000}, + {0xc3200000}, {0xc3202000}, {0xc3204000}, {0xc3206000}, + {0xc3208000}, {0xc320a000}, {0xc320c000}, {0xc320e000}, + {0xc3210000}, {0xc3212000}, {0xc3214000}, {0xc3216000}, + {0xc3218000}, {0xc321a000}, {0xc321c000}, {0xc321e000}, + {0xc3220000}, {0xc3222000}, {0xc3224000}, {0xc3226000}, + {0xc3228000}, {0xc322a000}, {0xc322c000}, {0xc322e000}, + {0xc3230000}, {0xc3232000}, {0xc3234000}, {0xc3236000}, + {0xc3238000}, {0xc323a000}, {0xc323c000}, {0xc323e000}, + {0xc3240000}, {0xc3242000}, {0xc3244000}, {0xc3246000}, + {0xc3248000}, {0xc324a000}, {0xc324c000}, {0xc324e000}, + {0xc3250000}, {0xc3252000}, {0xc3254000}, {0xc3256000}, + {0xc3258000}, {0xc325a000}, {0xc325c000}, {0xc325e000}, + {0xc3260000}, {0xc3262000}, {0xc3264000}, {0xc3266000}, + {0xc3268000}, {0xc326a000}, {0xc326c000}, {0xc326e000}, + {0xc3270000}, {0xc3272000}, {0xc3274000}, {0xc3276000}, + {0xc3278000}, {0xc327a000}, {0xc327c000}, {0xc327e000}, + {0xc3280000}, {0xc3282000}, {0xc3284000}, {0xc3286000}, + {0xc3288000}, {0xc328a000}, {0xc328c000}, {0xc328e000}, + {0xc3290000}, {0xc3292000}, {0xc3294000}, {0xc3296000}, + {0xc3298000}, {0xc329a000}, {0xc329c000}, {0xc329e000}, + {0xc32a0000}, {0xc32a2000}, {0xc32a4000}, {0xc32a6000}, + {0xc32a8000}, {0xc32aa000}, {0xc32ac000}, {0xc32ae000}, + {0xc32b0000}, {0xc32b2000}, {0xc32b4000}, {0xc32b6000}, + {0xc32b8000}, {0xc32ba000}, {0xc32bc000}, {0xc32be000}, + {0xc32c0000}, {0xc32c2000}, {0xc32c4000}, {0xc32c6000}, + {0xc32c8000}, {0xc32ca000}, {0xc32cc000}, {0xc32ce000}, + {0xc32d0000}, {0xc32d2000}, {0xc32d4000}, {0xc32d6000}, + {0xc32d8000}, {0xc32da000}, {0xc32dc000}, {0xc32de000}, + {0xc32e0000}, {0xc32e2000}, {0xc32e4000}, {0xc32e6000}, + {0xc32e8000}, {0xc32ea000}, {0xc32ec000}, {0xc32ee000}, + {0xc32f0000}, {0xc32f2000}, {0xc32f4000}, {0xc32f6000}, + {0xc32f8000}, {0xc32fa000}, {0xc32fc000}, {0xc32fe000}, + {0xc3300000}, {0xc3302000}, {0xc3304000}, {0xc3306000}, + {0xc3308000}, {0xc330a000}, {0xc330c000}, {0xc330e000}, + {0xc3310000}, {0xc3312000}, {0xc3314000}, {0xc3316000}, + {0xc3318000}, {0xc331a000}, {0xc331c000}, {0xc331e000}, + {0xc3320000}, {0xc3322000}, {0xc3324000}, {0xc3326000}, + {0xc3328000}, {0xc332a000}, {0xc332c000}, {0xc332e000}, + {0xc3330000}, {0xc3332000}, {0xc3334000}, {0xc3336000}, + {0xc3338000}, {0xc333a000}, {0xc333c000}, {0xc333e000}, + {0xc3340000}, {0xc3342000}, {0xc3344000}, {0xc3346000}, + {0xc3348000}, {0xc334a000}, {0xc334c000}, {0xc334e000}, + {0xc3350000}, {0xc3352000}, {0xc3354000}, {0xc3356000}, + {0xc3358000}, {0xc335a000}, {0xc335c000}, {0xc335e000}, + {0xc3360000}, {0xc3362000}, {0xc3364000}, {0xc3366000}, + {0xc3368000}, {0xc336a000}, {0xc336c000}, {0xc336e000}, + {0xc3370000}, {0xc3372000}, {0xc3374000}, {0xc3376000}, + {0xc3378000}, {0xc337a000}, {0xc337c000}, {0xc337e000}, + {0xc3380000}, {0xc3382000}, {0xc3384000}, {0xc3386000}, + {0xc3388000}, {0xc338a000}, {0xc338c000}, {0xc338e000}, + {0xc3390000}, {0xc3392000}, {0xc3394000}, {0xc3396000}, + {0xc3398000}, {0xc339a000}, {0xc339c000}, {0xc339e000}, + {0xc33a0000}, {0xc33a2000}, {0xc33a4000}, {0xc33a6000}, + {0xc33a8000}, {0xc33aa000}, {0xc33ac000}, {0xc33ae000}, + {0xc33b0000}, {0xc33b2000}, {0xc33b4000}, {0xc33b6000}, + {0xc33b8000}, {0xc33ba000}, {0xc33bc000}, {0xc33be000}, + {0xc33c0000}, {0xc33c2000}, {0xc33c4000}, {0xc33c6000}, + {0xc33c8000}, {0xc33ca000}, {0xc33cc000}, {0xc33ce000}, + {0xc33d0000}, {0xc33d2000}, {0xc33d4000}, {0xc33d6000}, + {0xc33d8000}, {0xc33da000}, {0xc33dc000}, {0xc33de000}, + {0xc33e0000}, {0xc33e2000}, {0xc33e4000}, {0xc33e6000}, + {0xc33e8000}, {0xc33ea000}, {0xc33ec000}, {0xc33ee000}, + {0xc33f0000}, {0xc33f2000}, {0xc33f4000}, {0xc33f6000}, + {0xc33f8000}, {0xc33fa000}, {0xc33fc000}, {0xc33fe000}, + {0xc3400000}, {0xc3402000}, {0xc3404000}, {0xc3406000}, + {0xc3408000}, {0xc340a000}, {0xc340c000}, {0xc340e000}, + {0xc3410000}, {0xc3412000}, {0xc3414000}, {0xc3416000}, + {0xc3418000}, {0xc341a000}, {0xc341c000}, {0xc341e000}, + {0xc3420000}, {0xc3422000}, {0xc3424000}, {0xc3426000}, + {0xc3428000}, {0xc342a000}, {0xc342c000}, {0xc342e000}, + {0xc3430000}, {0xc3432000}, {0xc3434000}, {0xc3436000}, + {0xc3438000}, {0xc343a000}, {0xc343c000}, {0xc343e000}, + {0xc3440000}, {0xc3442000}, {0xc3444000}, {0xc3446000}, + {0xc3448000}, {0xc344a000}, {0xc344c000}, {0xc344e000}, + {0xc3450000}, {0xc3452000}, {0xc3454000}, {0xc3456000}, + {0xc3458000}, {0xc345a000}, {0xc345c000}, {0xc345e000}, + {0xc3460000}, {0xc3462000}, {0xc3464000}, {0xc3466000}, + {0xc3468000}, {0xc346a000}, {0xc346c000}, {0xc346e000}, + {0xc3470000}, {0xc3472000}, {0xc3474000}, {0xc3476000}, + {0xc3478000}, {0xc347a000}, {0xc347c000}, {0xc347e000}, + {0xc3480000}, {0xc3482000}, {0xc3484000}, {0xc3486000}, + {0xc3488000}, {0xc348a000}, {0xc348c000}, {0xc348e000}, + {0xc3490000}, {0xc3492000}, {0xc3494000}, {0xc3496000}, + {0xc3498000}, {0xc349a000}, {0xc349c000}, {0xc349e000}, + {0xc34a0000}, {0xc34a2000}, {0xc34a4000}, {0xc34a6000}, + {0xc34a8000}, {0xc34aa000}, {0xc34ac000}, {0xc34ae000}, + {0xc34b0000}, {0xc34b2000}, {0xc34b4000}, {0xc34b6000}, + {0xc34b8000}, {0xc34ba000}, {0xc34bc000}, {0xc34be000}, + {0xc34c0000}, {0xc34c2000}, {0xc34c4000}, {0xc34c6000}, + {0xc34c8000}, {0xc34ca000}, {0xc34cc000}, {0xc34ce000}, + {0xc34d0000}, {0xc34d2000}, {0xc34d4000}, {0xc34d6000}, + {0xc34d8000}, {0xc34da000}, {0xc34dc000}, {0xc34de000}, + {0xc34e0000}, {0xc34e2000}, {0xc34e4000}, {0xc34e6000}, + {0xc34e8000}, {0xc34ea000}, {0xc34ec000}, {0xc34ee000}, + {0xc34f0000}, {0xc34f2000}, {0xc34f4000}, {0xc34f6000}, + {0xc34f8000}, {0xc34fa000}, {0xc34fc000}, {0xc34fe000}, + {0xc3500000}, {0xc3502000}, {0xc3504000}, {0xc3506000}, + {0xc3508000}, {0xc350a000}, {0xc350c000}, {0xc350e000}, + {0xc3510000}, {0xc3512000}, {0xc3514000}, {0xc3516000}, + {0xc3518000}, {0xc351a000}, {0xc351c000}, {0xc351e000}, + {0xc3520000}, {0xc3522000}, {0xc3524000}, {0xc3526000}, + {0xc3528000}, {0xc352a000}, {0xc352c000}, {0xc352e000}, + {0xc3530000}, {0xc3532000}, {0xc3534000}, {0xc3536000}, + {0xc3538000}, {0xc353a000}, {0xc353c000}, {0xc353e000}, + {0xc3540000}, {0xc3542000}, {0xc3544000}, {0xc3546000}, + {0xc3548000}, {0xc354a000}, {0xc354c000}, {0xc354e000}, + {0xc3550000}, {0xc3552000}, {0xc3554000}, {0xc3556000}, + {0xc3558000}, {0xc355a000}, {0xc355c000}, {0xc355e000}, + {0xc3560000}, {0xc3562000}, {0xc3564000}, {0xc3566000}, + {0xc3568000}, {0xc356a000}, {0xc356c000}, {0xc356e000}, + {0xc3570000}, {0xc3572000}, {0xc3574000}, {0xc3576000}, + {0xc3578000}, {0xc357a000}, {0xc357c000}, {0xc357e000}, + {0xc3580000}, {0xc3582000}, {0xc3584000}, {0xc3586000}, + {0xc3588000}, {0xc358a000}, {0xc358c000}, {0xc358e000}, + {0xc3590000}, {0xc3592000}, {0xc3594000}, {0xc3596000}, + {0xc3598000}, {0xc359a000}, {0xc359c000}, {0xc359e000}, + {0xc35a0000}, {0xc35a2000}, {0xc35a4000}, {0xc35a6000}, + {0xc35a8000}, {0xc35aa000}, {0xc35ac000}, {0xc35ae000}, + {0xc35b0000}, {0xc35b2000}, {0xc35b4000}, {0xc35b6000}, + {0xc35b8000}, {0xc35ba000}, {0xc35bc000}, {0xc35be000}, + {0xc35c0000}, {0xc35c2000}, {0xc35c4000}, {0xc35c6000}, + {0xc35c8000}, {0xc35ca000}, {0xc35cc000}, {0xc35ce000}, + {0xc35d0000}, {0xc35d2000}, {0xc35d4000}, {0xc35d6000}, + {0xc35d8000}, {0xc35da000}, {0xc35dc000}, {0xc35de000}, + {0xc35e0000}, {0xc35e2000}, {0xc35e4000}, {0xc35e6000}, + {0xc35e8000}, {0xc35ea000}, {0xc35ec000}, {0xc35ee000}, + {0xc35f0000}, {0xc35f2000}, {0xc35f4000}, {0xc35f6000}, + {0xc35f8000}, {0xc35fa000}, {0xc35fc000}, {0xc35fe000}, + {0xc3600000}, {0xc3602000}, {0xc3604000}, {0xc3606000}, + {0xc3608000}, {0xc360a000}, {0xc360c000}, {0xc360e000}, + {0xc3610000}, {0xc3612000}, {0xc3614000}, {0xc3616000}, + {0xc3618000}, {0xc361a000}, {0xc361c000}, {0xc361e000}, + {0xc3620000}, {0xc3622000}, {0xc3624000}, {0xc3626000}, + {0xc3628000}, {0xc362a000}, {0xc362c000}, {0xc362e000}, + {0xc3630000}, {0xc3632000}, {0xc3634000}, {0xc3636000}, + {0xc3638000}, {0xc363a000}, {0xc363c000}, {0xc363e000}, + {0xc3640000}, {0xc3642000}, {0xc3644000}, {0xc3646000}, + {0xc3648000}, {0xc364a000}, {0xc364c000}, {0xc364e000}, + {0xc3650000}, {0xc3652000}, {0xc3654000}, {0xc3656000}, + {0xc3658000}, {0xc365a000}, {0xc365c000}, {0xc365e000}, + {0xc3660000}, {0xc3662000}, {0xc3664000}, {0xc3666000}, + {0xc3668000}, {0xc366a000}, {0xc366c000}, {0xc366e000}, + {0xc3670000}, {0xc3672000}, {0xc3674000}, {0xc3676000}, + {0xc3678000}, {0xc367a000}, {0xc367c000}, {0xc367e000}, + {0xc3680000}, {0xc3682000}, {0xc3684000}, {0xc3686000}, + {0xc3688000}, {0xc368a000}, {0xc368c000}, {0xc368e000}, + {0xc3690000}, {0xc3692000}, {0xc3694000}, {0xc3696000}, + {0xc3698000}, {0xc369a000}, {0xc369c000}, {0xc369e000}, + {0xc36a0000}, {0xc36a2000}, {0xc36a4000}, {0xc36a6000}, + {0xc36a8000}, {0xc36aa000}, {0xc36ac000}, {0xc36ae000}, + {0xc36b0000}, {0xc36b2000}, {0xc36b4000}, {0xc36b6000}, + {0xc36b8000}, {0xc36ba000}, {0xc36bc000}, {0xc36be000}, + {0xc36c0000}, {0xc36c2000}, {0xc36c4000}, {0xc36c6000}, + {0xc36c8000}, {0xc36ca000}, {0xc36cc000}, {0xc36ce000}, + {0xc36d0000}, {0xc36d2000}, {0xc36d4000}, {0xc36d6000}, + {0xc36d8000}, {0xc36da000}, {0xc36dc000}, {0xc36de000}, + {0xc36e0000}, {0xc36e2000}, {0xc36e4000}, {0xc36e6000}, + {0xc36e8000}, {0xc36ea000}, {0xc36ec000}, {0xc36ee000}, + {0xc36f0000}, {0xc36f2000}, {0xc36f4000}, {0xc36f6000}, + {0xc36f8000}, {0xc36fa000}, {0xc36fc000}, {0xc36fe000}, + {0xc3700000}, {0xc3702000}, {0xc3704000}, {0xc3706000}, + {0xc3708000}, {0xc370a000}, {0xc370c000}, {0xc370e000}, + {0xc3710000}, {0xc3712000}, {0xc3714000}, {0xc3716000}, + {0xc3718000}, {0xc371a000}, {0xc371c000}, {0xc371e000}, + {0xc3720000}, {0xc3722000}, {0xc3724000}, {0xc3726000}, + {0xc3728000}, {0xc372a000}, {0xc372c000}, {0xc372e000}, + {0xc3730000}, {0xc3732000}, {0xc3734000}, {0xc3736000}, + {0xc3738000}, {0xc373a000}, {0xc373c000}, {0xc373e000}, + {0xc3740000}, {0xc3742000}, {0xc3744000}, {0xc3746000}, + {0xc3748000}, {0xc374a000}, {0xc374c000}, {0xc374e000}, + {0xc3750000}, {0xc3752000}, {0xc3754000}, {0xc3756000}, + {0xc3758000}, {0xc375a000}, {0xc375c000}, {0xc375e000}, + {0xc3760000}, {0xc3762000}, {0xc3764000}, {0xc3766000}, + {0xc3768000}, {0xc376a000}, {0xc376c000}, {0xc376e000}, + {0xc3770000}, {0xc3772000}, {0xc3774000}, {0xc3776000}, + {0xc3778000}, {0xc377a000}, {0xc377c000}, {0xc377e000}, + {0xc3780000}, {0xc3782000}, {0xc3784000}, {0xc3786000}, + {0xc3788000}, {0xc378a000}, {0xc378c000}, {0xc378e000}, + {0xc3790000}, {0xc3792000}, {0xc3794000}, {0xc3796000}, + {0xc3798000}, {0xc379a000}, {0xc379c000}, {0xc379e000}, + {0xc37a0000}, {0xc37a2000}, {0xc37a4000}, {0xc37a6000}, + {0xc37a8000}, {0xc37aa000}, {0xc37ac000}, {0xc37ae000}, + {0xc37b0000}, {0xc37b2000}, {0xc37b4000}, {0xc37b6000}, + {0xc37b8000}, {0xc37ba000}, {0xc37bc000}, {0xc37be000}, + {0xc37c0000}, {0xc37c2000}, {0xc37c4000}, {0xc37c6000}, + {0xc37c8000}, {0xc37ca000}, {0xc37cc000}, {0xc37ce000}, + {0xc37d0000}, {0xc37d2000}, {0xc37d4000}, {0xc37d6000}, + {0xc37d8000}, {0xc37da000}, {0xc37dc000}, {0xc37de000}, + {0xc37e0000}, {0xc37e2000}, {0xc37e4000}, {0xc37e6000}, + {0xc37e8000}, {0xc37ea000}, {0xc37ec000}, {0xc37ee000}, + {0xc37f0000}, {0xc37f2000}, {0xc37f4000}, {0xc37f6000}, + {0xc37f8000}, {0xc37fa000}, {0xc37fc000}, {0xc37fe000}, + {0xc3800000}, {0xc3802000}, {0xc3804000}, {0xc3806000}, + {0xc3808000}, {0xc380a000}, {0xc380c000}, {0xc380e000}, + {0xc3810000}, {0xc3812000}, {0xc3814000}, {0xc3816000}, + {0xc3818000}, {0xc381a000}, {0xc381c000}, {0xc381e000}, + {0xc3820000}, {0xc3822000}, {0xc3824000}, {0xc3826000}, + {0xc3828000}, {0xc382a000}, {0xc382c000}, {0xc382e000}, + {0xc3830000}, {0xc3832000}, {0xc3834000}, {0xc3836000}, + {0xc3838000}, {0xc383a000}, {0xc383c000}, {0xc383e000}, + {0xc3840000}, {0xc3842000}, {0xc3844000}, {0xc3846000}, + {0xc3848000}, {0xc384a000}, {0xc384c000}, {0xc384e000}, + {0xc3850000}, {0xc3852000}, {0xc3854000}, {0xc3856000}, + {0xc3858000}, {0xc385a000}, {0xc385c000}, {0xc385e000}, + {0xc3860000}, {0xc3862000}, {0xc3864000}, {0xc3866000}, + {0xc3868000}, {0xc386a000}, {0xc386c000}, {0xc386e000}, + {0xc3870000}, {0xc3872000}, {0xc3874000}, {0xc3876000}, + {0xc3878000}, {0xc387a000}, {0xc387c000}, {0xc387e000}, + {0xc3880000}, {0xc3882000}, {0xc3884000}, {0xc3886000}, + {0xc3888000}, {0xc388a000}, {0xc388c000}, {0xc388e000}, + {0xc3890000}, {0xc3892000}, {0xc3894000}, {0xc3896000}, + {0xc3898000}, {0xc389a000}, {0xc389c000}, {0xc389e000}, + {0xc38a0000}, {0xc38a2000}, {0xc38a4000}, {0xc38a6000}, + {0xc38a8000}, {0xc38aa000}, {0xc38ac000}, {0xc38ae000}, + {0xc38b0000}, {0xc38b2000}, {0xc38b4000}, {0xc38b6000}, + {0xc38b8000}, {0xc38ba000}, {0xc38bc000}, {0xc38be000}, + {0xc38c0000}, {0xc38c2000}, {0xc38c4000}, {0xc38c6000}, + {0xc38c8000}, {0xc38ca000}, {0xc38cc000}, {0xc38ce000}, + {0xc38d0000}, {0xc38d2000}, {0xc38d4000}, {0xc38d6000}, + {0xc38d8000}, {0xc38da000}, {0xc38dc000}, {0xc38de000}, + {0xc38e0000}, {0xc38e2000}, {0xc38e4000}, {0xc38e6000}, + {0xc38e8000}, {0xc38ea000}, {0xc38ec000}, {0xc38ee000}, + {0xc38f0000}, {0xc38f2000}, {0xc38f4000}, {0xc38f6000}, + {0xc38f8000}, {0xc38fa000}, {0xc38fc000}, {0xc38fe000}, + {0xc3900000}, {0xc3902000}, {0xc3904000}, {0xc3906000}, + {0xc3908000}, {0xc390a000}, {0xc390c000}, {0xc390e000}, + {0xc3910000}, {0xc3912000}, {0xc3914000}, {0xc3916000}, + {0xc3918000}, {0xc391a000}, {0xc391c000}, {0xc391e000}, + {0xc3920000}, {0xc3922000}, {0xc3924000}, {0xc3926000}, + {0xc3928000}, {0xc392a000}, {0xc392c000}, {0xc392e000}, + {0xc3930000}, {0xc3932000}, {0xc3934000}, {0xc3936000}, + {0xc3938000}, {0xc393a000}, {0xc393c000}, {0xc393e000}, + {0xc3940000}, {0xc3942000}, {0xc3944000}, {0xc3946000}, + {0xc3948000}, {0xc394a000}, {0xc394c000}, {0xc394e000}, + {0xc3950000}, {0xc3952000}, {0xc3954000}, {0xc3956000}, + {0xc3958000}, {0xc395a000}, {0xc395c000}, {0xc395e000}, + {0xc3960000}, {0xc3962000}, {0xc3964000}, {0xc3966000}, + {0xc3968000}, {0xc396a000}, {0xc396c000}, {0xc396e000}, + {0xc3970000}, {0xc3972000}, {0xc3974000}, {0xc3976000}, + {0xc3978000}, {0xc397a000}, {0xc397c000}, {0xc397e000}, + {0xc3980000}, {0xc3982000}, {0xc3984000}, {0xc3986000}, + {0xc3988000}, {0xc398a000}, {0xc398c000}, {0xc398e000}, + {0xc3990000}, {0xc3992000}, {0xc3994000}, {0xc3996000}, + {0xc3998000}, {0xc399a000}, {0xc399c000}, {0xc399e000}, + {0xc39a0000}, {0xc39a2000}, {0xc39a4000}, {0xc39a6000}, + {0xc39a8000}, {0xc39aa000}, {0xc39ac000}, {0xc39ae000}, + {0xc39b0000}, {0xc39b2000}, {0xc39b4000}, {0xc39b6000}, + {0xc39b8000}, {0xc39ba000}, {0xc39bc000}, {0xc39be000}, + {0xc39c0000}, {0xc39c2000}, {0xc39c4000}, {0xc39c6000}, + {0xc39c8000}, {0xc39ca000}, {0xc39cc000}, {0xc39ce000}, + {0xc39d0000}, {0xc39d2000}, {0xc39d4000}, {0xc39d6000}, + {0xc39d8000}, {0xc39da000}, {0xc39dc000}, {0xc39de000}, + {0xc39e0000}, {0xc39e2000}, {0xc39e4000}, {0xc39e6000}, + {0xc39e8000}, {0xc39ea000}, {0xc39ec000}, {0xc39ee000}, + {0xc39f0000}, {0xc39f2000}, {0xc39f4000}, {0xc39f6000}, + {0xc39f8000}, {0xc39fa000}, {0xc39fc000}, {0xc39fe000}, + {0xc3a00000}, {0xc3a02000}, {0xc3a04000}, {0xc3a06000}, + {0xc3a08000}, {0xc3a0a000}, {0xc3a0c000}, {0xc3a0e000}, + {0xc3a10000}, {0xc3a12000}, {0xc3a14000}, {0xc3a16000}, + {0xc3a18000}, {0xc3a1a000}, {0xc3a1c000}, {0xc3a1e000}, + {0xc3a20000}, {0xc3a22000}, {0xc3a24000}, {0xc3a26000}, + {0xc3a28000}, {0xc3a2a000}, {0xc3a2c000}, {0xc3a2e000}, + {0xc3a30000}, {0xc3a32000}, {0xc3a34000}, {0xc3a36000}, + {0xc3a38000}, {0xc3a3a000}, {0xc3a3c000}, {0xc3a3e000}, + {0xc3a40000}, {0xc3a42000}, {0xc3a44000}, {0xc3a46000}, + {0xc3a48000}, {0xc3a4a000}, {0xc3a4c000}, {0xc3a4e000}, + {0xc3a50000}, {0xc3a52000}, {0xc3a54000}, {0xc3a56000}, + {0xc3a58000}, {0xc3a5a000}, {0xc3a5c000}, {0xc3a5e000}, + {0xc3a60000}, {0xc3a62000}, {0xc3a64000}, {0xc3a66000}, + {0xc3a68000}, {0xc3a6a000}, {0xc3a6c000}, {0xc3a6e000}, + {0xc3a70000}, {0xc3a72000}, {0xc3a74000}, {0xc3a76000}, + {0xc3a78000}, {0xc3a7a000}, {0xc3a7c000}, {0xc3a7e000}, + {0xc3a80000}, {0xc3a82000}, {0xc3a84000}, {0xc3a86000}, + {0xc3a88000}, {0xc3a8a000}, {0xc3a8c000}, {0xc3a8e000}, + {0xc3a90000}, {0xc3a92000}, {0xc3a94000}, {0xc3a96000}, + {0xc3a98000}, {0xc3a9a000}, {0xc3a9c000}, {0xc3a9e000}, + {0xc3aa0000}, {0xc3aa2000}, {0xc3aa4000}, {0xc3aa6000}, + {0xc3aa8000}, {0xc3aaa000}, {0xc3aac000}, {0xc3aae000}, + {0xc3ab0000}, {0xc3ab2000}, {0xc3ab4000}, {0xc3ab6000}, + {0xc3ab8000}, {0xc3aba000}, {0xc3abc000}, {0xc3abe000}, + {0xc3ac0000}, {0xc3ac2000}, {0xc3ac4000}, {0xc3ac6000}, + {0xc3ac8000}, {0xc3aca000}, {0xc3acc000}, {0xc3ace000}, + {0xc3ad0000}, {0xc3ad2000}, {0xc3ad4000}, {0xc3ad6000}, + {0xc3ad8000}, {0xc3ada000}, {0xc3adc000}, {0xc3ade000}, + {0xc3ae0000}, {0xc3ae2000}, {0xc3ae4000}, {0xc3ae6000}, + {0xc3ae8000}, {0xc3aea000}, {0xc3aec000}, {0xc3aee000}, + {0xc3af0000}, {0xc3af2000}, {0xc3af4000}, {0xc3af6000}, + {0xc3af8000}, {0xc3afa000}, {0xc3afc000}, {0xc3afe000}, + {0xc3b00000}, {0xc3b02000}, {0xc3b04000}, {0xc3b06000}, + {0xc3b08000}, {0xc3b0a000}, {0xc3b0c000}, {0xc3b0e000}, + {0xc3b10000}, {0xc3b12000}, {0xc3b14000}, {0xc3b16000}, + {0xc3b18000}, {0xc3b1a000}, {0xc3b1c000}, {0xc3b1e000}, + {0xc3b20000}, {0xc3b22000}, {0xc3b24000}, {0xc3b26000}, + {0xc3b28000}, {0xc3b2a000}, {0xc3b2c000}, {0xc3b2e000}, + {0xc3b30000}, {0xc3b32000}, {0xc3b34000}, {0xc3b36000}, + {0xc3b38000}, {0xc3b3a000}, {0xc3b3c000}, {0xc3b3e000}, + {0xc3b40000}, {0xc3b42000}, {0xc3b44000}, {0xc3b46000}, + {0xc3b48000}, {0xc3b4a000}, {0xc3b4c000}, {0xc3b4e000}, + {0xc3b50000}, {0xc3b52000}, {0xc3b54000}, {0xc3b56000}, + {0xc3b58000}, {0xc3b5a000}, {0xc3b5c000}, {0xc3b5e000}, + {0xc3b60000}, {0xc3b62000}, {0xc3b64000}, {0xc3b66000}, + {0xc3b68000}, {0xc3b6a000}, {0xc3b6c000}, {0xc3b6e000}, + {0xc3b70000}, {0xc3b72000}, {0xc3b74000}, {0xc3b76000}, + {0xc3b78000}, {0xc3b7a000}, {0xc3b7c000}, {0xc3b7e000}, + {0xc3b80000}, {0xc3b82000}, {0xc3b84000}, {0xc3b86000}, + {0xc3b88000}, {0xc3b8a000}, {0xc3b8c000}, {0xc3b8e000}, + {0xc3b90000}, {0xc3b92000}, {0xc3b94000}, {0xc3b96000}, + {0xc3b98000}, {0xc3b9a000}, {0xc3b9c000}, {0xc3b9e000}, + {0xc3ba0000}, {0xc3ba2000}, {0xc3ba4000}, {0xc3ba6000}, + {0xc3ba8000}, {0xc3baa000}, {0xc3bac000}, {0xc3bae000}, + {0xc3bb0000}, {0xc3bb2000}, {0xc3bb4000}, {0xc3bb6000}, + {0xc3bb8000}, {0xc3bba000}, {0xc3bbc000}, {0xc3bbe000}, + {0xc3bc0000}, {0xc3bc2000}, {0xc3bc4000}, {0xc3bc6000}, + {0xc3bc8000}, {0xc3bca000}, {0xc3bcc000}, {0xc3bce000}, + {0xc3bd0000}, {0xc3bd2000}, {0xc3bd4000}, {0xc3bd6000}, + {0xc3bd8000}, {0xc3bda000}, {0xc3bdc000}, {0xc3bde000}, + {0xc3be0000}, {0xc3be2000}, {0xc3be4000}, {0xc3be6000}, + {0xc3be8000}, {0xc3bea000}, {0xc3bec000}, {0xc3bee000}, + {0xc3bf0000}, {0xc3bf2000}, {0xc3bf4000}, {0xc3bf6000}, + {0xc3bf8000}, {0xc3bfa000}, {0xc3bfc000}, {0xc3bfe000}, + {0xc3c00000}, {0xc3c02000}, {0xc3c04000}, {0xc3c06000}, + {0xc3c08000}, {0xc3c0a000}, {0xc3c0c000}, {0xc3c0e000}, + {0xc3c10000}, {0xc3c12000}, {0xc3c14000}, {0xc3c16000}, + {0xc3c18000}, {0xc3c1a000}, {0xc3c1c000}, {0xc3c1e000}, + {0xc3c20000}, {0xc3c22000}, {0xc3c24000}, {0xc3c26000}, + {0xc3c28000}, {0xc3c2a000}, {0xc3c2c000}, {0xc3c2e000}, + {0xc3c30000}, {0xc3c32000}, {0xc3c34000}, {0xc3c36000}, + {0xc3c38000}, {0xc3c3a000}, {0xc3c3c000}, {0xc3c3e000}, + {0xc3c40000}, {0xc3c42000}, {0xc3c44000}, {0xc3c46000}, + {0xc3c48000}, {0xc3c4a000}, {0xc3c4c000}, {0xc3c4e000}, + {0xc3c50000}, {0xc3c52000}, {0xc3c54000}, {0xc3c56000}, + {0xc3c58000}, {0xc3c5a000}, {0xc3c5c000}, {0xc3c5e000}, + {0xc3c60000}, {0xc3c62000}, {0xc3c64000}, {0xc3c66000}, + {0xc3c68000}, {0xc3c6a000}, {0xc3c6c000}, {0xc3c6e000}, + {0xc3c70000}, {0xc3c72000}, {0xc3c74000}, {0xc3c76000}, + {0xc3c78000}, {0xc3c7a000}, {0xc3c7c000}, {0xc3c7e000}, + {0xc3c80000}, {0xc3c82000}, {0xc3c84000}, {0xc3c86000}, + {0xc3c88000}, {0xc3c8a000}, {0xc3c8c000}, {0xc3c8e000}, + {0xc3c90000}, {0xc3c92000}, {0xc3c94000}, {0xc3c96000}, + {0xc3c98000}, {0xc3c9a000}, {0xc3c9c000}, {0xc3c9e000}, + {0xc3ca0000}, {0xc3ca2000}, {0xc3ca4000}, {0xc3ca6000}, + {0xc3ca8000}, {0xc3caa000}, {0xc3cac000}, {0xc3cae000}, + {0xc3cb0000}, {0xc3cb2000}, {0xc3cb4000}, {0xc3cb6000}, + {0xc3cb8000}, {0xc3cba000}, {0xc3cbc000}, {0xc3cbe000}, + {0xc3cc0000}, {0xc3cc2000}, {0xc3cc4000}, {0xc3cc6000}, + {0xc3cc8000}, {0xc3cca000}, {0xc3ccc000}, {0xc3cce000}, + {0xc3cd0000}, {0xc3cd2000}, {0xc3cd4000}, {0xc3cd6000}, + {0xc3cd8000}, {0xc3cda000}, {0xc3cdc000}, {0xc3cde000}, + {0xc3ce0000}, {0xc3ce2000}, {0xc3ce4000}, {0xc3ce6000}, + {0xc3ce8000}, {0xc3cea000}, {0xc3cec000}, {0xc3cee000}, + {0xc3cf0000}, {0xc3cf2000}, {0xc3cf4000}, {0xc3cf6000}, + {0xc3cf8000}, {0xc3cfa000}, {0xc3cfc000}, {0xc3cfe000}, + {0xc3d00000}, {0xc3d02000}, {0xc3d04000}, {0xc3d06000}, + {0xc3d08000}, {0xc3d0a000}, {0xc3d0c000}, {0xc3d0e000}, + {0xc3d10000}, {0xc3d12000}, {0xc3d14000}, {0xc3d16000}, + {0xc3d18000}, {0xc3d1a000}, {0xc3d1c000}, {0xc3d1e000}, + {0xc3d20000}, {0xc3d22000}, {0xc3d24000}, {0xc3d26000}, + {0xc3d28000}, {0xc3d2a000}, {0xc3d2c000}, {0xc3d2e000}, + {0xc3d30000}, {0xc3d32000}, {0xc3d34000}, {0xc3d36000}, + {0xc3d38000}, {0xc3d3a000}, {0xc3d3c000}, {0xc3d3e000}, + {0xc3d40000}, {0xc3d42000}, {0xc3d44000}, {0xc3d46000}, + {0xc3d48000}, {0xc3d4a000}, {0xc3d4c000}, {0xc3d4e000}, + {0xc3d50000}, {0xc3d52000}, {0xc3d54000}, {0xc3d56000}, + {0xc3d58000}, {0xc3d5a000}, {0xc3d5c000}, {0xc3d5e000}, + {0xc3d60000}, {0xc3d62000}, {0xc3d64000}, {0xc3d66000}, + {0xc3d68000}, {0xc3d6a000}, {0xc3d6c000}, {0xc3d6e000}, + {0xc3d70000}, {0xc3d72000}, {0xc3d74000}, {0xc3d76000}, + {0xc3d78000}, {0xc3d7a000}, {0xc3d7c000}, {0xc3d7e000}, + {0xc3d80000}, {0xc3d82000}, {0xc3d84000}, {0xc3d86000}, + {0xc3d88000}, {0xc3d8a000}, {0xc3d8c000}, {0xc3d8e000}, + {0xc3d90000}, {0xc3d92000}, {0xc3d94000}, {0xc3d96000}, + {0xc3d98000}, {0xc3d9a000}, {0xc3d9c000}, {0xc3d9e000}, + {0xc3da0000}, {0xc3da2000}, {0xc3da4000}, {0xc3da6000}, + {0xc3da8000}, {0xc3daa000}, {0xc3dac000}, {0xc3dae000}, + {0xc3db0000}, {0xc3db2000}, {0xc3db4000}, {0xc3db6000}, + {0xc3db8000}, {0xc3dba000}, {0xc3dbc000}, {0xc3dbe000}, + {0xc3dc0000}, {0xc3dc2000}, {0xc3dc4000}, {0xc3dc6000}, + {0xc3dc8000}, {0xc3dca000}, {0xc3dcc000}, {0xc3dce000}, + {0xc3dd0000}, {0xc3dd2000}, {0xc3dd4000}, {0xc3dd6000}, + {0xc3dd8000}, {0xc3dda000}, {0xc3ddc000}, {0xc3dde000}, + {0xc3de0000}, {0xc3de2000}, {0xc3de4000}, {0xc3de6000}, + {0xc3de8000}, {0xc3dea000}, {0xc3dec000}, {0xc3dee000}, + {0xc3df0000}, {0xc3df2000}, {0xc3df4000}, {0xc3df6000}, + {0xc3df8000}, {0xc3dfa000}, {0xc3dfc000}, {0xc3dfe000}, + {0xc3e00000}, {0xc3e02000}, {0xc3e04000}, {0xc3e06000}, + {0xc3e08000}, {0xc3e0a000}, {0xc3e0c000}, {0xc3e0e000}, + {0xc3e10000}, {0xc3e12000}, {0xc3e14000}, {0xc3e16000}, + {0xc3e18000}, {0xc3e1a000}, {0xc3e1c000}, {0xc3e1e000}, + {0xc3e20000}, {0xc3e22000}, {0xc3e24000}, {0xc3e26000}, + {0xc3e28000}, {0xc3e2a000}, {0xc3e2c000}, {0xc3e2e000}, + {0xc3e30000}, {0xc3e32000}, {0xc3e34000}, {0xc3e36000}, + {0xc3e38000}, {0xc3e3a000}, {0xc3e3c000}, {0xc3e3e000}, + {0xc3e40000}, {0xc3e42000}, {0xc3e44000}, {0xc3e46000}, + {0xc3e48000}, {0xc3e4a000}, {0xc3e4c000}, {0xc3e4e000}, + {0xc3e50000}, {0xc3e52000}, {0xc3e54000}, {0xc3e56000}, + {0xc3e58000}, {0xc3e5a000}, {0xc3e5c000}, {0xc3e5e000}, + {0xc3e60000}, {0xc3e62000}, {0xc3e64000}, {0xc3e66000}, + {0xc3e68000}, {0xc3e6a000}, {0xc3e6c000}, {0xc3e6e000}, + {0xc3e70000}, {0xc3e72000}, {0xc3e74000}, {0xc3e76000}, + {0xc3e78000}, {0xc3e7a000}, {0xc3e7c000}, {0xc3e7e000}, + {0xc3e80000}, {0xc3e82000}, {0xc3e84000}, {0xc3e86000}, + {0xc3e88000}, {0xc3e8a000}, {0xc3e8c000}, {0xc3e8e000}, + {0xc3e90000}, {0xc3e92000}, {0xc3e94000}, {0xc3e96000}, + {0xc3e98000}, {0xc3e9a000}, {0xc3e9c000}, {0xc3e9e000}, + {0xc3ea0000}, {0xc3ea2000}, {0xc3ea4000}, {0xc3ea6000}, + {0xc3ea8000}, {0xc3eaa000}, {0xc3eac000}, {0xc3eae000}, + {0xc3eb0000}, {0xc3eb2000}, {0xc3eb4000}, {0xc3eb6000}, + {0xc3eb8000}, {0xc3eba000}, {0xc3ebc000}, {0xc3ebe000}, + {0xc3ec0000}, {0xc3ec2000}, {0xc3ec4000}, {0xc3ec6000}, + {0xc3ec8000}, {0xc3eca000}, {0xc3ecc000}, {0xc3ece000}, + {0xc3ed0000}, {0xc3ed2000}, {0xc3ed4000}, {0xc3ed6000}, + {0xc3ed8000}, {0xc3eda000}, {0xc3edc000}, {0xc3ede000}, + {0xc3ee0000}, {0xc3ee2000}, {0xc3ee4000}, {0xc3ee6000}, + {0xc3ee8000}, {0xc3eea000}, {0xc3eec000}, {0xc3eee000}, + {0xc3ef0000}, {0xc3ef2000}, {0xc3ef4000}, {0xc3ef6000}, + {0xc3ef8000}, {0xc3efa000}, {0xc3efc000}, {0xc3efe000}, + {0xc3f00000}, {0xc3f02000}, {0xc3f04000}, {0xc3f06000}, + {0xc3f08000}, {0xc3f0a000}, {0xc3f0c000}, {0xc3f0e000}, + {0xc3f10000}, {0xc3f12000}, {0xc3f14000}, {0xc3f16000}, + {0xc3f18000}, {0xc3f1a000}, {0xc3f1c000}, {0xc3f1e000}, + {0xc3f20000}, {0xc3f22000}, {0xc3f24000}, {0xc3f26000}, + {0xc3f28000}, {0xc3f2a000}, {0xc3f2c000}, {0xc3f2e000}, + {0xc3f30000}, {0xc3f32000}, {0xc3f34000}, {0xc3f36000}, + {0xc3f38000}, {0xc3f3a000}, {0xc3f3c000}, {0xc3f3e000}, + {0xc3f40000}, {0xc3f42000}, {0xc3f44000}, {0xc3f46000}, + {0xc3f48000}, {0xc3f4a000}, {0xc3f4c000}, {0xc3f4e000}, + {0xc3f50000}, {0xc3f52000}, {0xc3f54000}, {0xc3f56000}, + {0xc3f58000}, {0xc3f5a000}, {0xc3f5c000}, {0xc3f5e000}, + {0xc3f60000}, {0xc3f62000}, {0xc3f64000}, {0xc3f66000}, + {0xc3f68000}, {0xc3f6a000}, {0xc3f6c000}, {0xc3f6e000}, + {0xc3f70000}, {0xc3f72000}, {0xc3f74000}, {0xc3f76000}, + {0xc3f78000}, {0xc3f7a000}, {0xc3f7c000}, {0xc3f7e000}, + {0xc3f80000}, {0xc3f82000}, {0xc3f84000}, {0xc3f86000}, + {0xc3f88000}, {0xc3f8a000}, {0xc3f8c000}, {0xc3f8e000}, + {0xc3f90000}, {0xc3f92000}, {0xc3f94000}, {0xc3f96000}, + {0xc3f98000}, {0xc3f9a000}, {0xc3f9c000}, {0xc3f9e000}, + {0xc3fa0000}, {0xc3fa2000}, {0xc3fa4000}, {0xc3fa6000}, + {0xc3fa8000}, {0xc3faa000}, {0xc3fac000}, {0xc3fae000}, + {0xc3fb0000}, {0xc3fb2000}, {0xc3fb4000}, {0xc3fb6000}, + {0xc3fb8000}, {0xc3fba000}, {0xc3fbc000}, {0xc3fbe000}, + {0xc3fc0000}, {0xc3fc2000}, {0xc3fc4000}, {0xc3fc6000}, + {0xc3fc8000}, {0xc3fca000}, {0xc3fcc000}, {0xc3fce000}, + {0xc3fd0000}, {0xc3fd2000}, {0xc3fd4000}, {0xc3fd6000}, + {0xc3fd8000}, {0xc3fda000}, {0xc3fdc000}, {0xc3fde000}, + {0xc3fe0000}, {0xc3fe2000}, {0xc3fe4000}, {0xc3fe6000}, + {0xc3fe8000}, {0xc3fea000}, {0xc3fec000}, {0xc3fee000}, + {0xc3ff0000}, {0xc3ff2000}, {0xc3ff4000}, {0xc3ff6000}, + {0xc3ff8000}, {0xc3ffa000}, {0xc3ffc000}, {0xc3ffe000}, + {0xc4000000}, {0xc4002000}, {0xc4004000}, {0xc4006000}, + {0xc4008000}, {0xc400a000}, {0xc400c000}, {0xc400e000}, + {0xc4010000}, {0xc4012000}, {0xc4014000}, {0xc4016000}, + {0xc4018000}, {0xc401a000}, {0xc401c000}, {0xc401e000}, + {0xc4020000}, {0xc4022000}, {0xc4024000}, {0xc4026000}, + {0xc4028000}, {0xc402a000}, {0xc402c000}, {0xc402e000}, + {0xc4030000}, {0xc4032000}, {0xc4034000}, {0xc4036000}, + {0xc4038000}, {0xc403a000}, {0xc403c000}, {0xc403e000}, + {0xc4040000}, {0xc4042000}, {0xc4044000}, {0xc4046000}, + {0xc4048000}, {0xc404a000}, {0xc404c000}, {0xc404e000}, + {0xc4050000}, {0xc4052000}, {0xc4054000}, {0xc4056000}, + {0xc4058000}, {0xc405a000}, {0xc405c000}, {0xc405e000}, + {0xc4060000}, {0xc4062000}, {0xc4064000}, {0xc4066000}, + {0xc4068000}, {0xc406a000}, {0xc406c000}, {0xc406e000}, + {0xc4070000}, {0xc4072000}, {0xc4074000}, {0xc4076000}, + {0xc4078000}, {0xc407a000}, {0xc407c000}, {0xc407e000}, + {0xc4080000}, {0xc4082000}, {0xc4084000}, {0xc4086000}, + {0xc4088000}, {0xc408a000}, {0xc408c000}, {0xc408e000}, + {0xc4090000}, {0xc4092000}, {0xc4094000}, {0xc4096000}, + {0xc4098000}, {0xc409a000}, {0xc409c000}, {0xc409e000}, + {0xc40a0000}, {0xc40a2000}, {0xc40a4000}, {0xc40a6000}, + {0xc40a8000}, {0xc40aa000}, {0xc40ac000}, {0xc40ae000}, + {0xc40b0000}, {0xc40b2000}, {0xc40b4000}, {0xc40b6000}, + {0xc40b8000}, {0xc40ba000}, {0xc40bc000}, {0xc40be000}, + {0xc40c0000}, {0xc40c2000}, {0xc40c4000}, {0xc40c6000}, + {0xc40c8000}, {0xc40ca000}, {0xc40cc000}, {0xc40ce000}, + {0xc40d0000}, {0xc40d2000}, {0xc40d4000}, {0xc40d6000}, + {0xc40d8000}, {0xc40da000}, {0xc40dc000}, {0xc40de000}, + {0xc40e0000}, {0xc40e2000}, {0xc40e4000}, {0xc40e6000}, + {0xc40e8000}, {0xc40ea000}, {0xc40ec000}, {0xc40ee000}, + {0xc40f0000}, {0xc40f2000}, {0xc40f4000}, {0xc40f6000}, + {0xc40f8000}, {0xc40fa000}, {0xc40fc000}, {0xc40fe000}, + {0xc4100000}, {0xc4102000}, {0xc4104000}, {0xc4106000}, + {0xc4108000}, {0xc410a000}, {0xc410c000}, {0xc410e000}, + {0xc4110000}, {0xc4112000}, {0xc4114000}, {0xc4116000}, + {0xc4118000}, {0xc411a000}, {0xc411c000}, {0xc411e000}, + {0xc4120000}, {0xc4122000}, {0xc4124000}, {0xc4126000}, + {0xc4128000}, {0xc412a000}, {0xc412c000}, {0xc412e000}, + {0xc4130000}, {0xc4132000}, {0xc4134000}, {0xc4136000}, + {0xc4138000}, {0xc413a000}, {0xc413c000}, {0xc413e000}, + {0xc4140000}, {0xc4142000}, {0xc4144000}, {0xc4146000}, + {0xc4148000}, {0xc414a000}, {0xc414c000}, {0xc414e000}, + {0xc4150000}, {0xc4152000}, {0xc4154000}, {0xc4156000}, + {0xc4158000}, {0xc415a000}, {0xc415c000}, {0xc415e000}, + {0xc4160000}, {0xc4162000}, {0xc4164000}, {0xc4166000}, + {0xc4168000}, {0xc416a000}, {0xc416c000}, {0xc416e000}, + {0xc4170000}, {0xc4172000}, {0xc4174000}, {0xc4176000}, + {0xc4178000}, {0xc417a000}, {0xc417c000}, {0xc417e000}, + {0xc4180000}, {0xc4182000}, {0xc4184000}, {0xc4186000}, + {0xc4188000}, {0xc418a000}, {0xc418c000}, {0xc418e000}, + {0xc4190000}, {0xc4192000}, {0xc4194000}, {0xc4196000}, + {0xc4198000}, {0xc419a000}, {0xc419c000}, {0xc419e000}, + {0xc41a0000}, {0xc41a2000}, {0xc41a4000}, {0xc41a6000}, + {0xc41a8000}, {0xc41aa000}, {0xc41ac000}, {0xc41ae000}, + {0xc41b0000}, {0xc41b2000}, {0xc41b4000}, {0xc41b6000}, + {0xc41b8000}, {0xc41ba000}, {0xc41bc000}, {0xc41be000}, + {0xc41c0000}, {0xc41c2000}, {0xc41c4000}, {0xc41c6000}, + {0xc41c8000}, {0xc41ca000}, {0xc41cc000}, {0xc41ce000}, + {0xc41d0000}, {0xc41d2000}, {0xc41d4000}, {0xc41d6000}, + {0xc41d8000}, {0xc41da000}, {0xc41dc000}, {0xc41de000}, + {0xc41e0000}, {0xc41e2000}, {0xc41e4000}, {0xc41e6000}, + {0xc41e8000}, {0xc41ea000}, {0xc41ec000}, {0xc41ee000}, + {0xc41f0000}, {0xc41f2000}, {0xc41f4000}, {0xc41f6000}, + {0xc41f8000}, {0xc41fa000}, {0xc41fc000}, {0xc41fe000}, + {0xc4200000}, {0xc4202000}, {0xc4204000}, {0xc4206000}, + {0xc4208000}, {0xc420a000}, {0xc420c000}, {0xc420e000}, + {0xc4210000}, {0xc4212000}, {0xc4214000}, {0xc4216000}, + {0xc4218000}, {0xc421a000}, {0xc421c000}, {0xc421e000}, + {0xc4220000}, {0xc4222000}, {0xc4224000}, {0xc4226000}, + {0xc4228000}, {0xc422a000}, {0xc422c000}, {0xc422e000}, + {0xc4230000}, {0xc4232000}, {0xc4234000}, {0xc4236000}, + {0xc4238000}, {0xc423a000}, {0xc423c000}, {0xc423e000}, + {0xc4240000}, {0xc4242000}, {0xc4244000}, {0xc4246000}, + {0xc4248000}, {0xc424a000}, {0xc424c000}, {0xc424e000}, + {0xc4250000}, {0xc4252000}, {0xc4254000}, {0xc4256000}, + {0xc4258000}, {0xc425a000}, {0xc425c000}, {0xc425e000}, + {0xc4260000}, {0xc4262000}, {0xc4264000}, {0xc4266000}, + {0xc4268000}, {0xc426a000}, {0xc426c000}, {0xc426e000}, + {0xc4270000}, {0xc4272000}, {0xc4274000}, {0xc4276000}, + {0xc4278000}, {0xc427a000}, {0xc427c000}, {0xc427e000}, + {0xc4280000}, {0xc4282000}, {0xc4284000}, {0xc4286000}, + {0xc4288000}, {0xc428a000}, {0xc428c000}, {0xc428e000}, + {0xc4290000}, {0xc4292000}, {0xc4294000}, {0xc4296000}, + {0xc4298000}, {0xc429a000}, {0xc429c000}, {0xc429e000}, + {0xc42a0000}, {0xc42a2000}, {0xc42a4000}, {0xc42a6000}, + {0xc42a8000}, {0xc42aa000}, {0xc42ac000}, {0xc42ae000}, + {0xc42b0000}, {0xc42b2000}, {0xc42b4000}, {0xc42b6000}, + {0xc42b8000}, {0xc42ba000}, {0xc42bc000}, {0xc42be000}, + {0xc42c0000}, {0xc42c2000}, {0xc42c4000}, {0xc42c6000}, + {0xc42c8000}, {0xc42ca000}, {0xc42cc000}, {0xc42ce000}, + {0xc42d0000}, {0xc42d2000}, {0xc42d4000}, {0xc42d6000}, + {0xc42d8000}, {0xc42da000}, {0xc42dc000}, {0xc42de000}, + {0xc42e0000}, {0xc42e2000}, {0xc42e4000}, {0xc42e6000}, + {0xc42e8000}, {0xc42ea000}, {0xc42ec000}, {0xc42ee000}, + {0xc42f0000}, {0xc42f2000}, {0xc42f4000}, {0xc42f6000}, + {0xc42f8000}, {0xc42fa000}, {0xc42fc000}, {0xc42fe000}, + {0xc4300000}, {0xc4302000}, {0xc4304000}, {0xc4306000}, + {0xc4308000}, {0xc430a000}, {0xc430c000}, {0xc430e000}, + {0xc4310000}, {0xc4312000}, {0xc4314000}, {0xc4316000}, + {0xc4318000}, {0xc431a000}, {0xc431c000}, {0xc431e000}, + {0xc4320000}, {0xc4322000}, {0xc4324000}, {0xc4326000}, + {0xc4328000}, {0xc432a000}, {0xc432c000}, {0xc432e000}, + {0xc4330000}, {0xc4332000}, {0xc4334000}, {0xc4336000}, + {0xc4338000}, {0xc433a000}, {0xc433c000}, {0xc433e000}, + {0xc4340000}, {0xc4342000}, {0xc4344000}, {0xc4346000}, + {0xc4348000}, {0xc434a000}, {0xc434c000}, {0xc434e000}, + {0xc4350000}, {0xc4352000}, {0xc4354000}, {0xc4356000}, + {0xc4358000}, {0xc435a000}, {0xc435c000}, {0xc435e000}, + {0xc4360000}, {0xc4362000}, {0xc4364000}, {0xc4366000}, + {0xc4368000}, {0xc436a000}, {0xc436c000}, {0xc436e000}, + {0xc4370000}, {0xc4372000}, {0xc4374000}, {0xc4376000}, + {0xc4378000}, {0xc437a000}, {0xc437c000}, {0xc437e000}, + {0xc4380000}, {0xc4382000}, {0xc4384000}, {0xc4386000}, + {0xc4388000}, {0xc438a000}, {0xc438c000}, {0xc438e000}, + {0xc4390000}, {0xc4392000}, {0xc4394000}, {0xc4396000}, + {0xc4398000}, {0xc439a000}, {0xc439c000}, {0xc439e000}, + {0xc43a0000}, {0xc43a2000}, {0xc43a4000}, {0xc43a6000}, + {0xc43a8000}, {0xc43aa000}, {0xc43ac000}, {0xc43ae000}, + {0xc43b0000}, {0xc43b2000}, {0xc43b4000}, {0xc43b6000}, + {0xc43b8000}, {0xc43ba000}, {0xc43bc000}, {0xc43be000}, + {0xc43c0000}, {0xc43c2000}, {0xc43c4000}, {0xc43c6000}, + {0xc43c8000}, {0xc43ca000}, {0xc43cc000}, {0xc43ce000}, + {0xc43d0000}, {0xc43d2000}, {0xc43d4000}, {0xc43d6000}, + {0xc43d8000}, {0xc43da000}, {0xc43dc000}, {0xc43de000}, + {0xc43e0000}, {0xc43e2000}, {0xc43e4000}, {0xc43e6000}, + {0xc43e8000}, {0xc43ea000}, {0xc43ec000}, {0xc43ee000}, + {0xc43f0000}, {0xc43f2000}, {0xc43f4000}, {0xc43f6000}, + {0xc43f8000}, {0xc43fa000}, {0xc43fc000}, {0xc43fe000}, + {0xc4400000}, {0xc4402000}, {0xc4404000}, {0xc4406000}, + {0xc4408000}, {0xc440a000}, {0xc440c000}, {0xc440e000}, + {0xc4410000}, {0xc4412000}, {0xc4414000}, {0xc4416000}, + {0xc4418000}, {0xc441a000}, {0xc441c000}, {0xc441e000}, + {0xc4420000}, {0xc4422000}, {0xc4424000}, {0xc4426000}, + {0xc4428000}, {0xc442a000}, {0xc442c000}, {0xc442e000}, + {0xc4430000}, {0xc4432000}, {0xc4434000}, {0xc4436000}, + {0xc4438000}, {0xc443a000}, {0xc443c000}, {0xc443e000}, + {0xc4440000}, {0xc4442000}, {0xc4444000}, {0xc4446000}, + {0xc4448000}, {0xc444a000}, {0xc444c000}, {0xc444e000}, + {0xc4450000}, {0xc4452000}, {0xc4454000}, {0xc4456000}, + {0xc4458000}, {0xc445a000}, {0xc445c000}, {0xc445e000}, + {0xc4460000}, {0xc4462000}, {0xc4464000}, {0xc4466000}, + {0xc4468000}, {0xc446a000}, {0xc446c000}, {0xc446e000}, + {0xc4470000}, {0xc4472000}, {0xc4474000}, {0xc4476000}, + {0xc4478000}, {0xc447a000}, {0xc447c000}, {0xc447e000}, + {0xc4480000}, {0xc4482000}, {0xc4484000}, {0xc4486000}, + {0xc4488000}, {0xc448a000}, {0xc448c000}, {0xc448e000}, + {0xc4490000}, {0xc4492000}, {0xc4494000}, {0xc4496000}, + {0xc4498000}, {0xc449a000}, {0xc449c000}, {0xc449e000}, + {0xc44a0000}, {0xc44a2000}, {0xc44a4000}, {0xc44a6000}, + {0xc44a8000}, {0xc44aa000}, {0xc44ac000}, {0xc44ae000}, + {0xc44b0000}, {0xc44b2000}, {0xc44b4000}, {0xc44b6000}, + {0xc44b8000}, {0xc44ba000}, {0xc44bc000}, {0xc44be000}, + {0xc44c0000}, {0xc44c2000}, {0xc44c4000}, {0xc44c6000}, + {0xc44c8000}, {0xc44ca000}, {0xc44cc000}, {0xc44ce000}, + {0xc44d0000}, {0xc44d2000}, {0xc44d4000}, {0xc44d6000}, + {0xc44d8000}, {0xc44da000}, {0xc44dc000}, {0xc44de000}, + {0xc44e0000}, {0xc44e2000}, {0xc44e4000}, {0xc44e6000}, + {0xc44e8000}, {0xc44ea000}, {0xc44ec000}, {0xc44ee000}, + {0xc44f0000}, {0xc44f2000}, {0xc44f4000}, {0xc44f6000}, + {0xc44f8000}, {0xc44fa000}, {0xc44fc000}, {0xc44fe000}, + {0xc4500000}, {0xc4502000}, {0xc4504000}, {0xc4506000}, + {0xc4508000}, {0xc450a000}, {0xc450c000}, {0xc450e000}, + {0xc4510000}, {0xc4512000}, {0xc4514000}, {0xc4516000}, + {0xc4518000}, {0xc451a000}, {0xc451c000}, {0xc451e000}, + {0xc4520000}, {0xc4522000}, {0xc4524000}, {0xc4526000}, + {0xc4528000}, {0xc452a000}, {0xc452c000}, {0xc452e000}, + {0xc4530000}, {0xc4532000}, {0xc4534000}, {0xc4536000}, + {0xc4538000}, {0xc453a000}, {0xc453c000}, {0xc453e000}, + {0xc4540000}, {0xc4542000}, {0xc4544000}, {0xc4546000}, + {0xc4548000}, {0xc454a000}, {0xc454c000}, {0xc454e000}, + {0xc4550000}, {0xc4552000}, {0xc4554000}, {0xc4556000}, + {0xc4558000}, {0xc455a000}, {0xc455c000}, {0xc455e000}, + {0xc4560000}, {0xc4562000}, {0xc4564000}, {0xc4566000}, + {0xc4568000}, {0xc456a000}, {0xc456c000}, {0xc456e000}, + {0xc4570000}, {0xc4572000}, {0xc4574000}, {0xc4576000}, + {0xc4578000}, {0xc457a000}, {0xc457c000}, {0xc457e000}, + {0xc4580000}, {0xc4582000}, {0xc4584000}, {0xc4586000}, + {0xc4588000}, {0xc458a000}, {0xc458c000}, {0xc458e000}, + {0xc4590000}, {0xc4592000}, {0xc4594000}, {0xc4596000}, + {0xc4598000}, {0xc459a000}, {0xc459c000}, {0xc459e000}, + {0xc45a0000}, {0xc45a2000}, {0xc45a4000}, {0xc45a6000}, + {0xc45a8000}, {0xc45aa000}, {0xc45ac000}, {0xc45ae000}, + {0xc45b0000}, {0xc45b2000}, {0xc45b4000}, {0xc45b6000}, + {0xc45b8000}, {0xc45ba000}, {0xc45bc000}, {0xc45be000}, + {0xc45c0000}, {0xc45c2000}, {0xc45c4000}, {0xc45c6000}, + {0xc45c8000}, {0xc45ca000}, {0xc45cc000}, {0xc45ce000}, + {0xc45d0000}, {0xc45d2000}, {0xc45d4000}, {0xc45d6000}, + {0xc45d8000}, {0xc45da000}, {0xc45dc000}, {0xc45de000}, + {0xc45e0000}, {0xc45e2000}, {0xc45e4000}, {0xc45e6000}, + {0xc45e8000}, {0xc45ea000}, {0xc45ec000}, {0xc45ee000}, + {0xc45f0000}, {0xc45f2000}, {0xc45f4000}, {0xc45f6000}, + {0xc45f8000}, {0xc45fa000}, {0xc45fc000}, {0xc45fe000}, + {0xc4600000}, {0xc4602000}, {0xc4604000}, {0xc4606000}, + {0xc4608000}, {0xc460a000}, {0xc460c000}, {0xc460e000}, + {0xc4610000}, {0xc4612000}, {0xc4614000}, {0xc4616000}, + {0xc4618000}, {0xc461a000}, {0xc461c000}, {0xc461e000}, + {0xc4620000}, {0xc4622000}, {0xc4624000}, {0xc4626000}, + {0xc4628000}, {0xc462a000}, {0xc462c000}, {0xc462e000}, + {0xc4630000}, {0xc4632000}, {0xc4634000}, {0xc4636000}, + {0xc4638000}, {0xc463a000}, {0xc463c000}, {0xc463e000}, + {0xc4640000}, {0xc4642000}, {0xc4644000}, {0xc4646000}, + {0xc4648000}, {0xc464a000}, {0xc464c000}, {0xc464e000}, + {0xc4650000}, {0xc4652000}, {0xc4654000}, {0xc4656000}, + {0xc4658000}, {0xc465a000}, {0xc465c000}, {0xc465e000}, + {0xc4660000}, {0xc4662000}, {0xc4664000}, {0xc4666000}, + {0xc4668000}, {0xc466a000}, {0xc466c000}, {0xc466e000}, + {0xc4670000}, {0xc4672000}, {0xc4674000}, {0xc4676000}, + {0xc4678000}, {0xc467a000}, {0xc467c000}, {0xc467e000}, + {0xc4680000}, {0xc4682000}, {0xc4684000}, {0xc4686000}, + {0xc4688000}, {0xc468a000}, {0xc468c000}, {0xc468e000}, + {0xc4690000}, {0xc4692000}, {0xc4694000}, {0xc4696000}, + {0xc4698000}, {0xc469a000}, {0xc469c000}, {0xc469e000}, + {0xc46a0000}, {0xc46a2000}, {0xc46a4000}, {0xc46a6000}, + {0xc46a8000}, {0xc46aa000}, {0xc46ac000}, {0xc46ae000}, + {0xc46b0000}, {0xc46b2000}, {0xc46b4000}, {0xc46b6000}, + {0xc46b8000}, {0xc46ba000}, {0xc46bc000}, {0xc46be000}, + {0xc46c0000}, {0xc46c2000}, {0xc46c4000}, {0xc46c6000}, + {0xc46c8000}, {0xc46ca000}, {0xc46cc000}, {0xc46ce000}, + {0xc46d0000}, {0xc46d2000}, {0xc46d4000}, {0xc46d6000}, + {0xc46d8000}, {0xc46da000}, {0xc46dc000}, {0xc46de000}, + {0xc46e0000}, {0xc46e2000}, {0xc46e4000}, {0xc46e6000}, + {0xc46e8000}, {0xc46ea000}, {0xc46ec000}, {0xc46ee000}, + {0xc46f0000}, {0xc46f2000}, {0xc46f4000}, {0xc46f6000}, + {0xc46f8000}, {0xc46fa000}, {0xc46fc000}, {0xc46fe000}, + {0xc4700000}, {0xc4702000}, {0xc4704000}, {0xc4706000}, + {0xc4708000}, {0xc470a000}, {0xc470c000}, {0xc470e000}, + {0xc4710000}, {0xc4712000}, {0xc4714000}, {0xc4716000}, + {0xc4718000}, {0xc471a000}, {0xc471c000}, {0xc471e000}, + {0xc4720000}, {0xc4722000}, {0xc4724000}, {0xc4726000}, + {0xc4728000}, {0xc472a000}, {0xc472c000}, {0xc472e000}, + {0xc4730000}, {0xc4732000}, {0xc4734000}, {0xc4736000}, + {0xc4738000}, {0xc473a000}, {0xc473c000}, {0xc473e000}, + {0xc4740000}, {0xc4742000}, {0xc4744000}, {0xc4746000}, + {0xc4748000}, {0xc474a000}, {0xc474c000}, {0xc474e000}, + {0xc4750000}, {0xc4752000}, {0xc4754000}, {0xc4756000}, + {0xc4758000}, {0xc475a000}, {0xc475c000}, {0xc475e000}, + {0xc4760000}, {0xc4762000}, {0xc4764000}, {0xc4766000}, + {0xc4768000}, {0xc476a000}, {0xc476c000}, {0xc476e000}, + {0xc4770000}, {0xc4772000}, {0xc4774000}, {0xc4776000}, + {0xc4778000}, {0xc477a000}, {0xc477c000}, {0xc477e000}, + {0xc4780000}, {0xc4782000}, {0xc4784000}, {0xc4786000}, + {0xc4788000}, {0xc478a000}, {0xc478c000}, {0xc478e000}, + {0xc4790000}, {0xc4792000}, {0xc4794000}, {0xc4796000}, + {0xc4798000}, {0xc479a000}, {0xc479c000}, {0xc479e000}, + {0xc47a0000}, {0xc47a2000}, {0xc47a4000}, {0xc47a6000}, + {0xc47a8000}, {0xc47aa000}, {0xc47ac000}, {0xc47ae000}, + {0xc47b0000}, {0xc47b2000}, {0xc47b4000}, {0xc47b6000}, + {0xc47b8000}, {0xc47ba000}, {0xc47bc000}, {0xc47be000}, + {0xc47c0000}, {0xc47c2000}, {0xc47c4000}, {0xc47c6000}, + {0xc47c8000}, {0xc47ca000}, {0xc47cc000}, {0xc47ce000}, + {0xc47d0000}, {0xc47d2000}, {0xc47d4000}, {0xc47d6000}, + {0xc47d8000}, {0xc47da000}, {0xc47dc000}, {0xc47de000}, + {0xc47e0000}, {0xc47e2000}, {0xc47e4000}, {0xc47e6000}, + {0xc47e8000}, {0xc47ea000}, {0xc47ec000}, {0xc47ee000}, + {0xc47f0000}, {0xc47f2000}, {0xc47f4000}, {0xc47f6000}, + {0xc47f8000}, {0xc47fa000}, {0xc47fc000}, {0xc47fe000}, + {0xc4800000}, {0xc4802000}, {0xc4804000}, {0xc4806000}, + {0xc4808000}, {0xc480a000}, {0xc480c000}, {0xc480e000}, + {0xc4810000}, {0xc4812000}, {0xc4814000}, {0xc4816000}, + {0xc4818000}, {0xc481a000}, {0xc481c000}, {0xc481e000}, + {0xc4820000}, {0xc4822000}, {0xc4824000}, {0xc4826000}, + {0xc4828000}, {0xc482a000}, {0xc482c000}, {0xc482e000}, + {0xc4830000}, {0xc4832000}, {0xc4834000}, {0xc4836000}, + {0xc4838000}, {0xc483a000}, {0xc483c000}, {0xc483e000}, + {0xc4840000}, {0xc4842000}, {0xc4844000}, {0xc4846000}, + {0xc4848000}, {0xc484a000}, {0xc484c000}, {0xc484e000}, + {0xc4850000}, {0xc4852000}, {0xc4854000}, {0xc4856000}, + {0xc4858000}, {0xc485a000}, {0xc485c000}, {0xc485e000}, + {0xc4860000}, {0xc4862000}, {0xc4864000}, {0xc4866000}, + {0xc4868000}, {0xc486a000}, {0xc486c000}, {0xc486e000}, + {0xc4870000}, {0xc4872000}, {0xc4874000}, {0xc4876000}, + {0xc4878000}, {0xc487a000}, {0xc487c000}, {0xc487e000}, + {0xc4880000}, {0xc4882000}, {0xc4884000}, {0xc4886000}, + {0xc4888000}, {0xc488a000}, {0xc488c000}, {0xc488e000}, + {0xc4890000}, {0xc4892000}, {0xc4894000}, {0xc4896000}, + {0xc4898000}, {0xc489a000}, {0xc489c000}, {0xc489e000}, + {0xc48a0000}, {0xc48a2000}, {0xc48a4000}, {0xc48a6000}, + {0xc48a8000}, {0xc48aa000}, {0xc48ac000}, {0xc48ae000}, + {0xc48b0000}, {0xc48b2000}, {0xc48b4000}, {0xc48b6000}, + {0xc48b8000}, {0xc48ba000}, {0xc48bc000}, {0xc48be000}, + {0xc48c0000}, {0xc48c2000}, {0xc48c4000}, {0xc48c6000}, + {0xc48c8000}, {0xc48ca000}, {0xc48cc000}, {0xc48ce000}, + {0xc48d0000}, {0xc48d2000}, {0xc48d4000}, {0xc48d6000}, + {0xc48d8000}, {0xc48da000}, {0xc48dc000}, {0xc48de000}, + {0xc48e0000}, {0xc48e2000}, {0xc48e4000}, {0xc48e6000}, + {0xc48e8000}, {0xc48ea000}, {0xc48ec000}, {0xc48ee000}, + {0xc48f0000}, {0xc48f2000}, {0xc48f4000}, {0xc48f6000}, + {0xc48f8000}, {0xc48fa000}, {0xc48fc000}, {0xc48fe000}, + {0xc4900000}, {0xc4902000}, {0xc4904000}, {0xc4906000}, + {0xc4908000}, {0xc490a000}, {0xc490c000}, {0xc490e000}, + {0xc4910000}, {0xc4912000}, {0xc4914000}, {0xc4916000}, + {0xc4918000}, {0xc491a000}, {0xc491c000}, {0xc491e000}, + {0xc4920000}, {0xc4922000}, {0xc4924000}, {0xc4926000}, + {0xc4928000}, {0xc492a000}, {0xc492c000}, {0xc492e000}, + {0xc4930000}, {0xc4932000}, {0xc4934000}, {0xc4936000}, + {0xc4938000}, {0xc493a000}, {0xc493c000}, {0xc493e000}, + {0xc4940000}, {0xc4942000}, {0xc4944000}, {0xc4946000}, + {0xc4948000}, {0xc494a000}, {0xc494c000}, {0xc494e000}, + {0xc4950000}, {0xc4952000}, {0xc4954000}, {0xc4956000}, + {0xc4958000}, {0xc495a000}, {0xc495c000}, {0xc495e000}, + {0xc4960000}, {0xc4962000}, {0xc4964000}, {0xc4966000}, + {0xc4968000}, {0xc496a000}, {0xc496c000}, {0xc496e000}, + {0xc4970000}, {0xc4972000}, {0xc4974000}, {0xc4976000}, + {0xc4978000}, {0xc497a000}, {0xc497c000}, {0xc497e000}, + {0xc4980000}, {0xc4982000}, {0xc4984000}, {0xc4986000}, + {0xc4988000}, {0xc498a000}, {0xc498c000}, {0xc498e000}, + {0xc4990000}, {0xc4992000}, {0xc4994000}, {0xc4996000}, + {0xc4998000}, {0xc499a000}, {0xc499c000}, {0xc499e000}, + {0xc49a0000}, {0xc49a2000}, {0xc49a4000}, {0xc49a6000}, + {0xc49a8000}, {0xc49aa000}, {0xc49ac000}, {0xc49ae000}, + {0xc49b0000}, {0xc49b2000}, {0xc49b4000}, {0xc49b6000}, + {0xc49b8000}, {0xc49ba000}, {0xc49bc000}, {0xc49be000}, + {0xc49c0000}, {0xc49c2000}, {0xc49c4000}, {0xc49c6000}, + {0xc49c8000}, {0xc49ca000}, {0xc49cc000}, {0xc49ce000}, + {0xc49d0000}, {0xc49d2000}, {0xc49d4000}, {0xc49d6000}, + {0xc49d8000}, {0xc49da000}, {0xc49dc000}, {0xc49de000}, + {0xc49e0000}, {0xc49e2000}, {0xc49e4000}, {0xc49e6000}, + {0xc49e8000}, {0xc49ea000}, {0xc49ec000}, {0xc49ee000}, + {0xc49f0000}, {0xc49f2000}, {0xc49f4000}, {0xc49f6000}, + {0xc49f8000}, {0xc49fa000}, {0xc49fc000}, {0xc49fe000}, + {0xc4a00000}, {0xc4a02000}, {0xc4a04000}, {0xc4a06000}, + {0xc4a08000}, {0xc4a0a000}, {0xc4a0c000}, {0xc4a0e000}, + {0xc4a10000}, {0xc4a12000}, {0xc4a14000}, {0xc4a16000}, + {0xc4a18000}, {0xc4a1a000}, {0xc4a1c000}, {0xc4a1e000}, + {0xc4a20000}, {0xc4a22000}, {0xc4a24000}, {0xc4a26000}, + {0xc4a28000}, {0xc4a2a000}, {0xc4a2c000}, {0xc4a2e000}, + {0xc4a30000}, {0xc4a32000}, {0xc4a34000}, {0xc4a36000}, + {0xc4a38000}, {0xc4a3a000}, {0xc4a3c000}, {0xc4a3e000}, + {0xc4a40000}, {0xc4a42000}, {0xc4a44000}, {0xc4a46000}, + {0xc4a48000}, {0xc4a4a000}, {0xc4a4c000}, {0xc4a4e000}, + {0xc4a50000}, {0xc4a52000}, {0xc4a54000}, {0xc4a56000}, + {0xc4a58000}, {0xc4a5a000}, {0xc4a5c000}, {0xc4a5e000}, + {0xc4a60000}, {0xc4a62000}, {0xc4a64000}, {0xc4a66000}, + {0xc4a68000}, {0xc4a6a000}, {0xc4a6c000}, {0xc4a6e000}, + {0xc4a70000}, {0xc4a72000}, {0xc4a74000}, {0xc4a76000}, + {0xc4a78000}, {0xc4a7a000}, {0xc4a7c000}, {0xc4a7e000}, + {0xc4a80000}, {0xc4a82000}, {0xc4a84000}, {0xc4a86000}, + {0xc4a88000}, {0xc4a8a000}, {0xc4a8c000}, {0xc4a8e000}, + {0xc4a90000}, {0xc4a92000}, {0xc4a94000}, {0xc4a96000}, + {0xc4a98000}, {0xc4a9a000}, {0xc4a9c000}, {0xc4a9e000}, + {0xc4aa0000}, {0xc4aa2000}, {0xc4aa4000}, {0xc4aa6000}, + {0xc4aa8000}, {0xc4aaa000}, {0xc4aac000}, {0xc4aae000}, + {0xc4ab0000}, {0xc4ab2000}, {0xc4ab4000}, {0xc4ab6000}, + {0xc4ab8000}, {0xc4aba000}, {0xc4abc000}, {0xc4abe000}, + {0xc4ac0000}, {0xc4ac2000}, {0xc4ac4000}, {0xc4ac6000}, + {0xc4ac8000}, {0xc4aca000}, {0xc4acc000}, {0xc4ace000}, + {0xc4ad0000}, {0xc4ad2000}, {0xc4ad4000}, {0xc4ad6000}, + {0xc4ad8000}, {0xc4ada000}, {0xc4adc000}, {0xc4ade000}, + {0xc4ae0000}, {0xc4ae2000}, {0xc4ae4000}, {0xc4ae6000}, + {0xc4ae8000}, {0xc4aea000}, {0xc4aec000}, {0xc4aee000}, + {0xc4af0000}, {0xc4af2000}, {0xc4af4000}, {0xc4af6000}, + {0xc4af8000}, {0xc4afa000}, {0xc4afc000}, {0xc4afe000}, + {0xc4b00000}, {0xc4b02000}, {0xc4b04000}, {0xc4b06000}, + {0xc4b08000}, {0xc4b0a000}, {0xc4b0c000}, {0xc4b0e000}, + {0xc4b10000}, {0xc4b12000}, {0xc4b14000}, {0xc4b16000}, + {0xc4b18000}, {0xc4b1a000}, {0xc4b1c000}, {0xc4b1e000}, + {0xc4b20000}, {0xc4b22000}, {0xc4b24000}, {0xc4b26000}, + {0xc4b28000}, {0xc4b2a000}, {0xc4b2c000}, {0xc4b2e000}, + {0xc4b30000}, {0xc4b32000}, {0xc4b34000}, {0xc4b36000}, + {0xc4b38000}, {0xc4b3a000}, {0xc4b3c000}, {0xc4b3e000}, + {0xc4b40000}, {0xc4b42000}, {0xc4b44000}, {0xc4b46000}, + {0xc4b48000}, {0xc4b4a000}, {0xc4b4c000}, {0xc4b4e000}, + {0xc4b50000}, {0xc4b52000}, {0xc4b54000}, {0xc4b56000}, + {0xc4b58000}, {0xc4b5a000}, {0xc4b5c000}, {0xc4b5e000}, + {0xc4b60000}, {0xc4b62000}, {0xc4b64000}, {0xc4b66000}, + {0xc4b68000}, {0xc4b6a000}, {0xc4b6c000}, {0xc4b6e000}, + {0xc4b70000}, {0xc4b72000}, {0xc4b74000}, {0xc4b76000}, + {0xc4b78000}, {0xc4b7a000}, {0xc4b7c000}, {0xc4b7e000}, + {0xc4b80000}, {0xc4b82000}, {0xc4b84000}, {0xc4b86000}, + {0xc4b88000}, {0xc4b8a000}, {0xc4b8c000}, {0xc4b8e000}, + {0xc4b90000}, {0xc4b92000}, {0xc4b94000}, {0xc4b96000}, + {0xc4b98000}, {0xc4b9a000}, {0xc4b9c000}, {0xc4b9e000}, + {0xc4ba0000}, {0xc4ba2000}, {0xc4ba4000}, {0xc4ba6000}, + {0xc4ba8000}, {0xc4baa000}, {0xc4bac000}, {0xc4bae000}, + {0xc4bb0000}, {0xc4bb2000}, {0xc4bb4000}, {0xc4bb6000}, + {0xc4bb8000}, {0xc4bba000}, {0xc4bbc000}, {0xc4bbe000}, + {0xc4bc0000}, {0xc4bc2000}, {0xc4bc4000}, {0xc4bc6000}, + {0xc4bc8000}, {0xc4bca000}, {0xc4bcc000}, {0xc4bce000}, + {0xc4bd0000}, {0xc4bd2000}, {0xc4bd4000}, {0xc4bd6000}, + {0xc4bd8000}, {0xc4bda000}, {0xc4bdc000}, {0xc4bde000}, + {0xc4be0000}, {0xc4be2000}, {0xc4be4000}, {0xc4be6000}, + {0xc4be8000}, {0xc4bea000}, {0xc4bec000}, {0xc4bee000}, + {0xc4bf0000}, {0xc4bf2000}, {0xc4bf4000}, {0xc4bf6000}, + {0xc4bf8000}, {0xc4bfa000}, {0xc4bfc000}, {0xc4bfe000}, + {0xc4c00000}, {0xc4c02000}, {0xc4c04000}, {0xc4c06000}, + {0xc4c08000}, {0xc4c0a000}, {0xc4c0c000}, {0xc4c0e000}, + {0xc4c10000}, {0xc4c12000}, {0xc4c14000}, {0xc4c16000}, + {0xc4c18000}, {0xc4c1a000}, {0xc4c1c000}, {0xc4c1e000}, + {0xc4c20000}, {0xc4c22000}, {0xc4c24000}, {0xc4c26000}, + {0xc4c28000}, {0xc4c2a000}, {0xc4c2c000}, {0xc4c2e000}, + {0xc4c30000}, {0xc4c32000}, {0xc4c34000}, {0xc4c36000}, + {0xc4c38000}, {0xc4c3a000}, {0xc4c3c000}, {0xc4c3e000}, + {0xc4c40000}, {0xc4c42000}, {0xc4c44000}, {0xc4c46000}, + {0xc4c48000}, {0xc4c4a000}, {0xc4c4c000}, {0xc4c4e000}, + {0xc4c50000}, {0xc4c52000}, {0xc4c54000}, {0xc4c56000}, + {0xc4c58000}, {0xc4c5a000}, {0xc4c5c000}, {0xc4c5e000}, + {0xc4c60000}, {0xc4c62000}, {0xc4c64000}, {0xc4c66000}, + {0xc4c68000}, {0xc4c6a000}, {0xc4c6c000}, {0xc4c6e000}, + {0xc4c70000}, {0xc4c72000}, {0xc4c74000}, {0xc4c76000}, + {0xc4c78000}, {0xc4c7a000}, {0xc4c7c000}, {0xc4c7e000}, + {0xc4c80000}, {0xc4c82000}, {0xc4c84000}, {0xc4c86000}, + {0xc4c88000}, {0xc4c8a000}, {0xc4c8c000}, {0xc4c8e000}, + {0xc4c90000}, {0xc4c92000}, {0xc4c94000}, {0xc4c96000}, + {0xc4c98000}, {0xc4c9a000}, {0xc4c9c000}, {0xc4c9e000}, + {0xc4ca0000}, {0xc4ca2000}, {0xc4ca4000}, {0xc4ca6000}, + {0xc4ca8000}, {0xc4caa000}, {0xc4cac000}, {0xc4cae000}, + {0xc4cb0000}, {0xc4cb2000}, {0xc4cb4000}, {0xc4cb6000}, + {0xc4cb8000}, {0xc4cba000}, {0xc4cbc000}, {0xc4cbe000}, + {0xc4cc0000}, {0xc4cc2000}, {0xc4cc4000}, {0xc4cc6000}, + {0xc4cc8000}, {0xc4cca000}, {0xc4ccc000}, {0xc4cce000}, + {0xc4cd0000}, {0xc4cd2000}, {0xc4cd4000}, {0xc4cd6000}, + {0xc4cd8000}, {0xc4cda000}, {0xc4cdc000}, {0xc4cde000}, + {0xc4ce0000}, {0xc4ce2000}, {0xc4ce4000}, {0xc4ce6000}, + {0xc4ce8000}, {0xc4cea000}, {0xc4cec000}, {0xc4cee000}, + {0xc4cf0000}, {0xc4cf2000}, {0xc4cf4000}, {0xc4cf6000}, + {0xc4cf8000}, {0xc4cfa000}, {0xc4cfc000}, {0xc4cfe000}, + {0xc4d00000}, {0xc4d02000}, {0xc4d04000}, {0xc4d06000}, + {0xc4d08000}, {0xc4d0a000}, {0xc4d0c000}, {0xc4d0e000}, + {0xc4d10000}, {0xc4d12000}, {0xc4d14000}, {0xc4d16000}, + {0xc4d18000}, {0xc4d1a000}, {0xc4d1c000}, {0xc4d1e000}, + {0xc4d20000}, {0xc4d22000}, {0xc4d24000}, {0xc4d26000}, + {0xc4d28000}, {0xc4d2a000}, {0xc4d2c000}, {0xc4d2e000}, + {0xc4d30000}, {0xc4d32000}, {0xc4d34000}, {0xc4d36000}, + {0xc4d38000}, {0xc4d3a000}, {0xc4d3c000}, {0xc4d3e000}, + {0xc4d40000}, {0xc4d42000}, {0xc4d44000}, {0xc4d46000}, + {0xc4d48000}, {0xc4d4a000}, {0xc4d4c000}, {0xc4d4e000}, + {0xc4d50000}, {0xc4d52000}, {0xc4d54000}, {0xc4d56000}, + {0xc4d58000}, {0xc4d5a000}, {0xc4d5c000}, {0xc4d5e000}, + {0xc4d60000}, {0xc4d62000}, {0xc4d64000}, {0xc4d66000}, + {0xc4d68000}, {0xc4d6a000}, {0xc4d6c000}, {0xc4d6e000}, + {0xc4d70000}, {0xc4d72000}, {0xc4d74000}, {0xc4d76000}, + {0xc4d78000}, {0xc4d7a000}, {0xc4d7c000}, {0xc4d7e000}, + {0xc4d80000}, {0xc4d82000}, {0xc4d84000}, {0xc4d86000}, + {0xc4d88000}, {0xc4d8a000}, {0xc4d8c000}, {0xc4d8e000}, + {0xc4d90000}, {0xc4d92000}, {0xc4d94000}, {0xc4d96000}, + {0xc4d98000}, {0xc4d9a000}, {0xc4d9c000}, {0xc4d9e000}, + {0xc4da0000}, {0xc4da2000}, {0xc4da4000}, {0xc4da6000}, + {0xc4da8000}, {0xc4daa000}, {0xc4dac000}, {0xc4dae000}, + {0xc4db0000}, {0xc4db2000}, {0xc4db4000}, {0xc4db6000}, + {0xc4db8000}, {0xc4dba000}, {0xc4dbc000}, {0xc4dbe000}, + {0xc4dc0000}, {0xc4dc2000}, {0xc4dc4000}, {0xc4dc6000}, + {0xc4dc8000}, {0xc4dca000}, {0xc4dcc000}, {0xc4dce000}, + {0xc4dd0000}, {0xc4dd2000}, {0xc4dd4000}, {0xc4dd6000}, + {0xc4dd8000}, {0xc4dda000}, {0xc4ddc000}, {0xc4dde000}, + {0xc4de0000}, {0xc4de2000}, {0xc4de4000}, {0xc4de6000}, + {0xc4de8000}, {0xc4dea000}, {0xc4dec000}, {0xc4dee000}, + {0xc4df0000}, {0xc4df2000}, {0xc4df4000}, {0xc4df6000}, + {0xc4df8000}, {0xc4dfa000}, {0xc4dfc000}, {0xc4dfe000}, + {0xc4e00000}, {0xc4e02000}, {0xc4e04000}, {0xc4e06000}, + {0xc4e08000}, {0xc4e0a000}, {0xc4e0c000}, {0xc4e0e000}, + {0xc4e10000}, {0xc4e12000}, {0xc4e14000}, {0xc4e16000}, + {0xc4e18000}, {0xc4e1a000}, {0xc4e1c000}, {0xc4e1e000}, + {0xc4e20000}, {0xc4e22000}, {0xc4e24000}, {0xc4e26000}, + {0xc4e28000}, {0xc4e2a000}, {0xc4e2c000}, {0xc4e2e000}, + {0xc4e30000}, {0xc4e32000}, {0xc4e34000}, {0xc4e36000}, + {0xc4e38000}, {0xc4e3a000}, {0xc4e3c000}, {0xc4e3e000}, + {0xc4e40000}, {0xc4e42000}, {0xc4e44000}, {0xc4e46000}, + {0xc4e48000}, {0xc4e4a000}, {0xc4e4c000}, {0xc4e4e000}, + {0xc4e50000}, {0xc4e52000}, {0xc4e54000}, {0xc4e56000}, + {0xc4e58000}, {0xc4e5a000}, {0xc4e5c000}, {0xc4e5e000}, + {0xc4e60000}, {0xc4e62000}, {0xc4e64000}, {0xc4e66000}, + {0xc4e68000}, {0xc4e6a000}, {0xc4e6c000}, {0xc4e6e000}, + {0xc4e70000}, {0xc4e72000}, {0xc4e74000}, {0xc4e76000}, + {0xc4e78000}, {0xc4e7a000}, {0xc4e7c000}, {0xc4e7e000}, + {0xc4e80000}, {0xc4e82000}, {0xc4e84000}, {0xc4e86000}, + {0xc4e88000}, {0xc4e8a000}, {0xc4e8c000}, {0xc4e8e000}, + {0xc4e90000}, {0xc4e92000}, {0xc4e94000}, {0xc4e96000}, + {0xc4e98000}, {0xc4e9a000}, {0xc4e9c000}, {0xc4e9e000}, + {0xc4ea0000}, {0xc4ea2000}, {0xc4ea4000}, {0xc4ea6000}, + {0xc4ea8000}, {0xc4eaa000}, {0xc4eac000}, {0xc4eae000}, + {0xc4eb0000}, {0xc4eb2000}, {0xc4eb4000}, {0xc4eb6000}, + {0xc4eb8000}, {0xc4eba000}, {0xc4ebc000}, {0xc4ebe000}, + {0xc4ec0000}, {0xc4ec2000}, {0xc4ec4000}, {0xc4ec6000}, + {0xc4ec8000}, {0xc4eca000}, {0xc4ecc000}, {0xc4ece000}, + {0xc4ed0000}, {0xc4ed2000}, {0xc4ed4000}, {0xc4ed6000}, + {0xc4ed8000}, {0xc4eda000}, {0xc4edc000}, {0xc4ede000}, + {0xc4ee0000}, {0xc4ee2000}, {0xc4ee4000}, {0xc4ee6000}, + {0xc4ee8000}, {0xc4eea000}, {0xc4eec000}, {0xc4eee000}, + {0xc4ef0000}, {0xc4ef2000}, {0xc4ef4000}, {0xc4ef6000}, + {0xc4ef8000}, {0xc4efa000}, {0xc4efc000}, {0xc4efe000}, + {0xc4f00000}, {0xc4f02000}, {0xc4f04000}, {0xc4f06000}, + {0xc4f08000}, {0xc4f0a000}, {0xc4f0c000}, {0xc4f0e000}, + {0xc4f10000}, {0xc4f12000}, {0xc4f14000}, {0xc4f16000}, + {0xc4f18000}, {0xc4f1a000}, {0xc4f1c000}, {0xc4f1e000}, + {0xc4f20000}, {0xc4f22000}, {0xc4f24000}, {0xc4f26000}, + {0xc4f28000}, {0xc4f2a000}, {0xc4f2c000}, {0xc4f2e000}, + {0xc4f30000}, {0xc4f32000}, {0xc4f34000}, {0xc4f36000}, + {0xc4f38000}, {0xc4f3a000}, {0xc4f3c000}, {0xc4f3e000}, + {0xc4f40000}, {0xc4f42000}, {0xc4f44000}, {0xc4f46000}, + {0xc4f48000}, {0xc4f4a000}, {0xc4f4c000}, {0xc4f4e000}, + {0xc4f50000}, {0xc4f52000}, {0xc4f54000}, {0xc4f56000}, + {0xc4f58000}, {0xc4f5a000}, {0xc4f5c000}, {0xc4f5e000}, + {0xc4f60000}, {0xc4f62000}, {0xc4f64000}, {0xc4f66000}, + {0xc4f68000}, {0xc4f6a000}, {0xc4f6c000}, {0xc4f6e000}, + {0xc4f70000}, {0xc4f72000}, {0xc4f74000}, {0xc4f76000}, + {0xc4f78000}, {0xc4f7a000}, {0xc4f7c000}, {0xc4f7e000}, + {0xc4f80000}, {0xc4f82000}, {0xc4f84000}, {0xc4f86000}, + {0xc4f88000}, {0xc4f8a000}, {0xc4f8c000}, {0xc4f8e000}, + {0xc4f90000}, {0xc4f92000}, {0xc4f94000}, {0xc4f96000}, + {0xc4f98000}, {0xc4f9a000}, {0xc4f9c000}, {0xc4f9e000}, + {0xc4fa0000}, {0xc4fa2000}, {0xc4fa4000}, {0xc4fa6000}, + {0xc4fa8000}, {0xc4faa000}, {0xc4fac000}, {0xc4fae000}, + {0xc4fb0000}, {0xc4fb2000}, {0xc4fb4000}, {0xc4fb6000}, + {0xc4fb8000}, {0xc4fba000}, {0xc4fbc000}, {0xc4fbe000}, + {0xc4fc0000}, {0xc4fc2000}, {0xc4fc4000}, {0xc4fc6000}, + {0xc4fc8000}, {0xc4fca000}, {0xc4fcc000}, {0xc4fce000}, + {0xc4fd0000}, {0xc4fd2000}, {0xc4fd4000}, {0xc4fd6000}, + {0xc4fd8000}, {0xc4fda000}, {0xc4fdc000}, {0xc4fde000}, + {0xc4fe0000}, {0xc4fe2000}, {0xc4fe4000}, {0xc4fe6000}, + {0xc4fe8000}, {0xc4fea000}, {0xc4fec000}, {0xc4fee000}, + {0xc4ff0000}, {0xc4ff2000}, {0xc4ff4000}, {0xc4ff6000}, + {0xc4ff8000}, {0xc4ffa000}, {0xc4ffc000}, {0xc4ffe000}, + {0xc5000000}, {0xc5002000}, {0xc5004000}, {0xc5006000}, + {0xc5008000}, {0xc500a000}, {0xc500c000}, {0xc500e000}, + {0xc5010000}, {0xc5012000}, {0xc5014000}, {0xc5016000}, + {0xc5018000}, {0xc501a000}, {0xc501c000}, {0xc501e000}, + {0xc5020000}, {0xc5022000}, {0xc5024000}, {0xc5026000}, + {0xc5028000}, {0xc502a000}, {0xc502c000}, {0xc502e000}, + {0xc5030000}, {0xc5032000}, {0xc5034000}, {0xc5036000}, + {0xc5038000}, {0xc503a000}, {0xc503c000}, {0xc503e000}, + {0xc5040000}, {0xc5042000}, {0xc5044000}, {0xc5046000}, + {0xc5048000}, {0xc504a000}, {0xc504c000}, {0xc504e000}, + {0xc5050000}, {0xc5052000}, {0xc5054000}, {0xc5056000}, + {0xc5058000}, {0xc505a000}, {0xc505c000}, {0xc505e000}, + {0xc5060000}, {0xc5062000}, {0xc5064000}, {0xc5066000}, + {0xc5068000}, {0xc506a000}, {0xc506c000}, {0xc506e000}, + {0xc5070000}, {0xc5072000}, {0xc5074000}, {0xc5076000}, + {0xc5078000}, {0xc507a000}, {0xc507c000}, {0xc507e000}, + {0xc5080000}, {0xc5082000}, {0xc5084000}, {0xc5086000}, + {0xc5088000}, {0xc508a000}, {0xc508c000}, {0xc508e000}, + {0xc5090000}, {0xc5092000}, {0xc5094000}, {0xc5096000}, + {0xc5098000}, {0xc509a000}, {0xc509c000}, {0xc509e000}, + {0xc50a0000}, {0xc50a2000}, {0xc50a4000}, {0xc50a6000}, + {0xc50a8000}, {0xc50aa000}, {0xc50ac000}, {0xc50ae000}, + {0xc50b0000}, {0xc50b2000}, {0xc50b4000}, {0xc50b6000}, + {0xc50b8000}, {0xc50ba000}, {0xc50bc000}, {0xc50be000}, + {0xc50c0000}, {0xc50c2000}, {0xc50c4000}, {0xc50c6000}, + {0xc50c8000}, {0xc50ca000}, {0xc50cc000}, {0xc50ce000}, + {0xc50d0000}, {0xc50d2000}, {0xc50d4000}, {0xc50d6000}, + {0xc50d8000}, {0xc50da000}, {0xc50dc000}, {0xc50de000}, + {0xc50e0000}, {0xc50e2000}, {0xc50e4000}, {0xc50e6000}, + {0xc50e8000}, {0xc50ea000}, {0xc50ec000}, {0xc50ee000}, + {0xc50f0000}, {0xc50f2000}, {0xc50f4000}, {0xc50f6000}, + {0xc50f8000}, {0xc50fa000}, {0xc50fc000}, {0xc50fe000}, + {0xc5100000}, {0xc5102000}, {0xc5104000}, {0xc5106000}, + {0xc5108000}, {0xc510a000}, {0xc510c000}, {0xc510e000}, + {0xc5110000}, {0xc5112000}, {0xc5114000}, {0xc5116000}, + {0xc5118000}, {0xc511a000}, {0xc511c000}, {0xc511e000}, + {0xc5120000}, {0xc5122000}, {0xc5124000}, {0xc5126000}, + {0xc5128000}, {0xc512a000}, {0xc512c000}, {0xc512e000}, + {0xc5130000}, {0xc5132000}, {0xc5134000}, {0xc5136000}, + {0xc5138000}, {0xc513a000}, {0xc513c000}, {0xc513e000}, + {0xc5140000}, {0xc5142000}, {0xc5144000}, {0xc5146000}, + {0xc5148000}, {0xc514a000}, {0xc514c000}, {0xc514e000}, + {0xc5150000}, {0xc5152000}, {0xc5154000}, {0xc5156000}, + {0xc5158000}, {0xc515a000}, {0xc515c000}, {0xc515e000}, + {0xc5160000}, {0xc5162000}, {0xc5164000}, {0xc5166000}, + {0xc5168000}, {0xc516a000}, {0xc516c000}, {0xc516e000}, + {0xc5170000}, {0xc5172000}, {0xc5174000}, {0xc5176000}, + {0xc5178000}, {0xc517a000}, {0xc517c000}, {0xc517e000}, + {0xc5180000}, {0xc5182000}, {0xc5184000}, {0xc5186000}, + {0xc5188000}, {0xc518a000}, {0xc518c000}, {0xc518e000}, + {0xc5190000}, {0xc5192000}, {0xc5194000}, {0xc5196000}, + {0xc5198000}, {0xc519a000}, {0xc519c000}, {0xc519e000}, + {0xc51a0000}, {0xc51a2000}, {0xc51a4000}, {0xc51a6000}, + {0xc51a8000}, {0xc51aa000}, {0xc51ac000}, {0xc51ae000}, + {0xc51b0000}, {0xc51b2000}, {0xc51b4000}, {0xc51b6000}, + {0xc51b8000}, {0xc51ba000}, {0xc51bc000}, {0xc51be000}, + {0xc51c0000}, {0xc51c2000}, {0xc51c4000}, {0xc51c6000}, + {0xc51c8000}, {0xc51ca000}, {0xc51cc000}, {0xc51ce000}, + {0xc51d0000}, {0xc51d2000}, {0xc51d4000}, {0xc51d6000}, + {0xc51d8000}, {0xc51da000}, {0xc51dc000}, {0xc51de000}, + {0xc51e0000}, {0xc51e2000}, {0xc51e4000}, {0xc51e6000}, + {0xc51e8000}, {0xc51ea000}, {0xc51ec000}, {0xc51ee000}, + {0xc51f0000}, {0xc51f2000}, {0xc51f4000}, {0xc51f6000}, + {0xc51f8000}, {0xc51fa000}, {0xc51fc000}, {0xc51fe000}, + {0xc5200000}, {0xc5202000}, {0xc5204000}, {0xc5206000}, + {0xc5208000}, {0xc520a000}, {0xc520c000}, {0xc520e000}, + {0xc5210000}, {0xc5212000}, {0xc5214000}, {0xc5216000}, + {0xc5218000}, {0xc521a000}, {0xc521c000}, {0xc521e000}, + {0xc5220000}, {0xc5222000}, {0xc5224000}, {0xc5226000}, + {0xc5228000}, {0xc522a000}, {0xc522c000}, {0xc522e000}, + {0xc5230000}, {0xc5232000}, {0xc5234000}, {0xc5236000}, + {0xc5238000}, {0xc523a000}, {0xc523c000}, {0xc523e000}, + {0xc5240000}, {0xc5242000}, {0xc5244000}, {0xc5246000}, + {0xc5248000}, {0xc524a000}, {0xc524c000}, {0xc524e000}, + {0xc5250000}, {0xc5252000}, {0xc5254000}, {0xc5256000}, + {0xc5258000}, {0xc525a000}, {0xc525c000}, {0xc525e000}, + {0xc5260000}, {0xc5262000}, {0xc5264000}, {0xc5266000}, + {0xc5268000}, {0xc526a000}, {0xc526c000}, {0xc526e000}, + {0xc5270000}, {0xc5272000}, {0xc5274000}, {0xc5276000}, + {0xc5278000}, {0xc527a000}, {0xc527c000}, {0xc527e000}, + {0xc5280000}, {0xc5282000}, {0xc5284000}, {0xc5286000}, + {0xc5288000}, {0xc528a000}, {0xc528c000}, {0xc528e000}, + {0xc5290000}, {0xc5292000}, {0xc5294000}, {0xc5296000}, + {0xc5298000}, {0xc529a000}, {0xc529c000}, {0xc529e000}, + {0xc52a0000}, {0xc52a2000}, {0xc52a4000}, {0xc52a6000}, + {0xc52a8000}, {0xc52aa000}, {0xc52ac000}, {0xc52ae000}, + {0xc52b0000}, {0xc52b2000}, {0xc52b4000}, {0xc52b6000}, + {0xc52b8000}, {0xc52ba000}, {0xc52bc000}, {0xc52be000}, + {0xc52c0000}, {0xc52c2000}, {0xc52c4000}, {0xc52c6000}, + {0xc52c8000}, {0xc52ca000}, {0xc52cc000}, {0xc52ce000}, + {0xc52d0000}, {0xc52d2000}, {0xc52d4000}, {0xc52d6000}, + {0xc52d8000}, {0xc52da000}, {0xc52dc000}, {0xc52de000}, + {0xc52e0000}, {0xc52e2000}, {0xc52e4000}, {0xc52e6000}, + {0xc52e8000}, {0xc52ea000}, {0xc52ec000}, {0xc52ee000}, + {0xc52f0000}, {0xc52f2000}, {0xc52f4000}, {0xc52f6000}, + {0xc52f8000}, {0xc52fa000}, {0xc52fc000}, {0xc52fe000}, + {0xc5300000}, {0xc5302000}, {0xc5304000}, {0xc5306000}, + {0xc5308000}, {0xc530a000}, {0xc530c000}, {0xc530e000}, + {0xc5310000}, {0xc5312000}, {0xc5314000}, {0xc5316000}, + {0xc5318000}, {0xc531a000}, {0xc531c000}, {0xc531e000}, + {0xc5320000}, {0xc5322000}, {0xc5324000}, {0xc5326000}, + {0xc5328000}, {0xc532a000}, {0xc532c000}, {0xc532e000}, + {0xc5330000}, {0xc5332000}, {0xc5334000}, {0xc5336000}, + {0xc5338000}, {0xc533a000}, {0xc533c000}, {0xc533e000}, + {0xc5340000}, {0xc5342000}, {0xc5344000}, {0xc5346000}, + {0xc5348000}, {0xc534a000}, {0xc534c000}, {0xc534e000}, + {0xc5350000}, {0xc5352000}, {0xc5354000}, {0xc5356000}, + {0xc5358000}, {0xc535a000}, {0xc535c000}, {0xc535e000}, + {0xc5360000}, {0xc5362000}, {0xc5364000}, {0xc5366000}, + {0xc5368000}, {0xc536a000}, {0xc536c000}, {0xc536e000}, + {0xc5370000}, {0xc5372000}, {0xc5374000}, {0xc5376000}, + {0xc5378000}, {0xc537a000}, {0xc537c000}, {0xc537e000}, + {0xc5380000}, {0xc5382000}, {0xc5384000}, {0xc5386000}, + {0xc5388000}, {0xc538a000}, {0xc538c000}, {0xc538e000}, + {0xc5390000}, {0xc5392000}, {0xc5394000}, {0xc5396000}, + {0xc5398000}, {0xc539a000}, {0xc539c000}, {0xc539e000}, + {0xc53a0000}, {0xc53a2000}, {0xc53a4000}, {0xc53a6000}, + {0xc53a8000}, {0xc53aa000}, {0xc53ac000}, {0xc53ae000}, + {0xc53b0000}, {0xc53b2000}, {0xc53b4000}, {0xc53b6000}, + {0xc53b8000}, {0xc53ba000}, {0xc53bc000}, {0xc53be000}, + {0xc53c0000}, {0xc53c2000}, {0xc53c4000}, {0xc53c6000}, + {0xc53c8000}, {0xc53ca000}, {0xc53cc000}, {0xc53ce000}, + {0xc53d0000}, {0xc53d2000}, {0xc53d4000}, {0xc53d6000}, + {0xc53d8000}, {0xc53da000}, {0xc53dc000}, {0xc53de000}, + {0xc53e0000}, {0xc53e2000}, {0xc53e4000}, {0xc53e6000}, + {0xc53e8000}, {0xc53ea000}, {0xc53ec000}, {0xc53ee000}, + {0xc53f0000}, {0xc53f2000}, {0xc53f4000}, {0xc53f6000}, + {0xc53f8000}, {0xc53fa000}, {0xc53fc000}, {0xc53fe000}, + {0xc5400000}, {0xc5402000}, {0xc5404000}, {0xc5406000}, + {0xc5408000}, {0xc540a000}, {0xc540c000}, {0xc540e000}, + {0xc5410000}, {0xc5412000}, {0xc5414000}, {0xc5416000}, + {0xc5418000}, {0xc541a000}, {0xc541c000}, {0xc541e000}, + {0xc5420000}, {0xc5422000}, {0xc5424000}, {0xc5426000}, + {0xc5428000}, {0xc542a000}, {0xc542c000}, {0xc542e000}, + {0xc5430000}, {0xc5432000}, {0xc5434000}, {0xc5436000}, + {0xc5438000}, {0xc543a000}, {0xc543c000}, {0xc543e000}, + {0xc5440000}, {0xc5442000}, {0xc5444000}, {0xc5446000}, + {0xc5448000}, {0xc544a000}, {0xc544c000}, {0xc544e000}, + {0xc5450000}, {0xc5452000}, {0xc5454000}, {0xc5456000}, + {0xc5458000}, {0xc545a000}, {0xc545c000}, {0xc545e000}, + {0xc5460000}, {0xc5462000}, {0xc5464000}, {0xc5466000}, + {0xc5468000}, {0xc546a000}, {0xc546c000}, {0xc546e000}, + {0xc5470000}, {0xc5472000}, {0xc5474000}, {0xc5476000}, + {0xc5478000}, {0xc547a000}, {0xc547c000}, {0xc547e000}, + {0xc5480000}, {0xc5482000}, {0xc5484000}, {0xc5486000}, + {0xc5488000}, {0xc548a000}, {0xc548c000}, {0xc548e000}, + {0xc5490000}, {0xc5492000}, {0xc5494000}, {0xc5496000}, + {0xc5498000}, {0xc549a000}, {0xc549c000}, {0xc549e000}, + {0xc54a0000}, {0xc54a2000}, {0xc54a4000}, {0xc54a6000}, + {0xc54a8000}, {0xc54aa000}, {0xc54ac000}, {0xc54ae000}, + {0xc54b0000}, {0xc54b2000}, {0xc54b4000}, {0xc54b6000}, + {0xc54b8000}, {0xc54ba000}, {0xc54bc000}, {0xc54be000}, + {0xc54c0000}, {0xc54c2000}, {0xc54c4000}, {0xc54c6000}, + {0xc54c8000}, {0xc54ca000}, {0xc54cc000}, {0xc54ce000}, + {0xc54d0000}, {0xc54d2000}, {0xc54d4000}, {0xc54d6000}, + {0xc54d8000}, {0xc54da000}, {0xc54dc000}, {0xc54de000}, + {0xc54e0000}, {0xc54e2000}, {0xc54e4000}, {0xc54e6000}, + {0xc54e8000}, {0xc54ea000}, {0xc54ec000}, {0xc54ee000}, + {0xc54f0000}, {0xc54f2000}, {0xc54f4000}, {0xc54f6000}, + {0xc54f8000}, {0xc54fa000}, {0xc54fc000}, {0xc54fe000}, + {0xc5500000}, {0xc5502000}, {0xc5504000}, {0xc5506000}, + {0xc5508000}, {0xc550a000}, {0xc550c000}, {0xc550e000}, + {0xc5510000}, {0xc5512000}, {0xc5514000}, {0xc5516000}, + {0xc5518000}, {0xc551a000}, {0xc551c000}, {0xc551e000}, + {0xc5520000}, {0xc5522000}, {0xc5524000}, {0xc5526000}, + {0xc5528000}, {0xc552a000}, {0xc552c000}, {0xc552e000}, + {0xc5530000}, {0xc5532000}, {0xc5534000}, {0xc5536000}, + {0xc5538000}, {0xc553a000}, {0xc553c000}, {0xc553e000}, + {0xc5540000}, {0xc5542000}, {0xc5544000}, {0xc5546000}, + {0xc5548000}, {0xc554a000}, {0xc554c000}, {0xc554e000}, + {0xc5550000}, {0xc5552000}, {0xc5554000}, {0xc5556000}, + {0xc5558000}, {0xc555a000}, {0xc555c000}, {0xc555e000}, + {0xc5560000}, {0xc5562000}, {0xc5564000}, {0xc5566000}, + {0xc5568000}, {0xc556a000}, {0xc556c000}, {0xc556e000}, + {0xc5570000}, {0xc5572000}, {0xc5574000}, {0xc5576000}, + {0xc5578000}, {0xc557a000}, {0xc557c000}, {0xc557e000}, + {0xc5580000}, {0xc5582000}, {0xc5584000}, {0xc5586000}, + {0xc5588000}, {0xc558a000}, {0xc558c000}, {0xc558e000}, + {0xc5590000}, {0xc5592000}, {0xc5594000}, {0xc5596000}, + {0xc5598000}, {0xc559a000}, {0xc559c000}, {0xc559e000}, + {0xc55a0000}, {0xc55a2000}, {0xc55a4000}, {0xc55a6000}, + {0xc55a8000}, {0xc55aa000}, {0xc55ac000}, {0xc55ae000}, + {0xc55b0000}, {0xc55b2000}, {0xc55b4000}, {0xc55b6000}, + {0xc55b8000}, {0xc55ba000}, {0xc55bc000}, {0xc55be000}, + {0xc55c0000}, {0xc55c2000}, {0xc55c4000}, {0xc55c6000}, + {0xc55c8000}, {0xc55ca000}, {0xc55cc000}, {0xc55ce000}, + {0xc55d0000}, {0xc55d2000}, {0xc55d4000}, {0xc55d6000}, + {0xc55d8000}, {0xc55da000}, {0xc55dc000}, {0xc55de000}, + {0xc55e0000}, {0xc55e2000}, {0xc55e4000}, {0xc55e6000}, + {0xc55e8000}, {0xc55ea000}, {0xc55ec000}, {0xc55ee000}, + {0xc55f0000}, {0xc55f2000}, {0xc55f4000}, {0xc55f6000}, + {0xc55f8000}, {0xc55fa000}, {0xc55fc000}, {0xc55fe000}, + {0xc5600000}, {0xc5602000}, {0xc5604000}, {0xc5606000}, + {0xc5608000}, {0xc560a000}, {0xc560c000}, {0xc560e000}, + {0xc5610000}, {0xc5612000}, {0xc5614000}, {0xc5616000}, + {0xc5618000}, {0xc561a000}, {0xc561c000}, {0xc561e000}, + {0xc5620000}, {0xc5622000}, {0xc5624000}, {0xc5626000}, + {0xc5628000}, {0xc562a000}, {0xc562c000}, {0xc562e000}, + {0xc5630000}, {0xc5632000}, {0xc5634000}, {0xc5636000}, + {0xc5638000}, {0xc563a000}, {0xc563c000}, {0xc563e000}, + {0xc5640000}, {0xc5642000}, {0xc5644000}, {0xc5646000}, + {0xc5648000}, {0xc564a000}, {0xc564c000}, {0xc564e000}, + {0xc5650000}, {0xc5652000}, {0xc5654000}, {0xc5656000}, + {0xc5658000}, {0xc565a000}, {0xc565c000}, {0xc565e000}, + {0xc5660000}, {0xc5662000}, {0xc5664000}, {0xc5666000}, + {0xc5668000}, {0xc566a000}, {0xc566c000}, {0xc566e000}, + {0xc5670000}, {0xc5672000}, {0xc5674000}, {0xc5676000}, + {0xc5678000}, {0xc567a000}, {0xc567c000}, {0xc567e000}, + {0xc5680000}, {0xc5682000}, {0xc5684000}, {0xc5686000}, + {0xc5688000}, {0xc568a000}, {0xc568c000}, {0xc568e000}, + {0xc5690000}, {0xc5692000}, {0xc5694000}, {0xc5696000}, + {0xc5698000}, {0xc569a000}, {0xc569c000}, {0xc569e000}, + {0xc56a0000}, {0xc56a2000}, {0xc56a4000}, {0xc56a6000}, + {0xc56a8000}, {0xc56aa000}, {0xc56ac000}, {0xc56ae000}, + {0xc56b0000}, {0xc56b2000}, {0xc56b4000}, {0xc56b6000}, + {0xc56b8000}, {0xc56ba000}, {0xc56bc000}, {0xc56be000}, + {0xc56c0000}, {0xc56c2000}, {0xc56c4000}, {0xc56c6000}, + {0xc56c8000}, {0xc56ca000}, {0xc56cc000}, {0xc56ce000}, + {0xc56d0000}, {0xc56d2000}, {0xc56d4000}, {0xc56d6000}, + {0xc56d8000}, {0xc56da000}, {0xc56dc000}, {0xc56de000}, + {0xc56e0000}, {0xc56e2000}, {0xc56e4000}, {0xc56e6000}, + {0xc56e8000}, {0xc56ea000}, {0xc56ec000}, {0xc56ee000}, + {0xc56f0000}, {0xc56f2000}, {0xc56f4000}, {0xc56f6000}, + {0xc56f8000}, {0xc56fa000}, {0xc56fc000}, {0xc56fe000}, + {0xc5700000}, {0xc5702000}, {0xc5704000}, {0xc5706000}, + {0xc5708000}, {0xc570a000}, {0xc570c000}, {0xc570e000}, + {0xc5710000}, {0xc5712000}, {0xc5714000}, {0xc5716000}, + {0xc5718000}, {0xc571a000}, {0xc571c000}, {0xc571e000}, + {0xc5720000}, {0xc5722000}, {0xc5724000}, {0xc5726000}, + {0xc5728000}, {0xc572a000}, {0xc572c000}, {0xc572e000}, + {0xc5730000}, {0xc5732000}, {0xc5734000}, {0xc5736000}, + {0xc5738000}, {0xc573a000}, {0xc573c000}, {0xc573e000}, + {0xc5740000}, {0xc5742000}, {0xc5744000}, {0xc5746000}, + {0xc5748000}, {0xc574a000}, {0xc574c000}, {0xc574e000}, + {0xc5750000}, {0xc5752000}, {0xc5754000}, {0xc5756000}, + {0xc5758000}, {0xc575a000}, {0xc575c000}, {0xc575e000}, + {0xc5760000}, {0xc5762000}, {0xc5764000}, {0xc5766000}, + {0xc5768000}, {0xc576a000}, {0xc576c000}, {0xc576e000}, + {0xc5770000}, {0xc5772000}, {0xc5774000}, {0xc5776000}, + {0xc5778000}, {0xc577a000}, {0xc577c000}, {0xc577e000}, + {0xc5780000}, {0xc5782000}, {0xc5784000}, {0xc5786000}, + {0xc5788000}, {0xc578a000}, {0xc578c000}, {0xc578e000}, + {0xc5790000}, {0xc5792000}, {0xc5794000}, {0xc5796000}, + {0xc5798000}, {0xc579a000}, {0xc579c000}, {0xc579e000}, + {0xc57a0000}, {0xc57a2000}, {0xc57a4000}, {0xc57a6000}, + {0xc57a8000}, {0xc57aa000}, {0xc57ac000}, {0xc57ae000}, + {0xc57b0000}, {0xc57b2000}, {0xc57b4000}, {0xc57b6000}, + {0xc57b8000}, {0xc57ba000}, {0xc57bc000}, {0xc57be000}, + {0xc57c0000}, {0xc57c2000}, {0xc57c4000}, {0xc57c6000}, + {0xc57c8000}, {0xc57ca000}, {0xc57cc000}, {0xc57ce000}, + {0xc57d0000}, {0xc57d2000}, {0xc57d4000}, {0xc57d6000}, + {0xc57d8000}, {0xc57da000}, {0xc57dc000}, {0xc57de000}, + {0xc57e0000}, {0xc57e2000}, {0xc57e4000}, {0xc57e6000}, + {0xc57e8000}, {0xc57ea000}, {0xc57ec000}, {0xc57ee000}, + {0xc57f0000}, {0xc57f2000}, {0xc57f4000}, {0xc57f6000}, + {0xc57f8000}, {0xc57fa000}, {0xc57fc000}, {0xc57fe000}, + {0xc5800000}, {0xc5802000}, {0xc5804000}, {0xc5806000}, + {0xc5808000}, {0xc580a000}, {0xc580c000}, {0xc580e000}, + {0xc5810000}, {0xc5812000}, {0xc5814000}, {0xc5816000}, + {0xc5818000}, {0xc581a000}, {0xc581c000}, {0xc581e000}, + {0xc5820000}, {0xc5822000}, {0xc5824000}, {0xc5826000}, + {0xc5828000}, {0xc582a000}, {0xc582c000}, {0xc582e000}, + {0xc5830000}, {0xc5832000}, {0xc5834000}, {0xc5836000}, + {0xc5838000}, {0xc583a000}, {0xc583c000}, {0xc583e000}, + {0xc5840000}, {0xc5842000}, {0xc5844000}, {0xc5846000}, + {0xc5848000}, {0xc584a000}, {0xc584c000}, {0xc584e000}, + {0xc5850000}, {0xc5852000}, {0xc5854000}, {0xc5856000}, + {0xc5858000}, {0xc585a000}, {0xc585c000}, {0xc585e000}, + {0xc5860000}, {0xc5862000}, {0xc5864000}, {0xc5866000}, + {0xc5868000}, {0xc586a000}, {0xc586c000}, {0xc586e000}, + {0xc5870000}, {0xc5872000}, {0xc5874000}, {0xc5876000}, + {0xc5878000}, {0xc587a000}, {0xc587c000}, {0xc587e000}, + {0xc5880000}, {0xc5882000}, {0xc5884000}, {0xc5886000}, + {0xc5888000}, {0xc588a000}, {0xc588c000}, {0xc588e000}, + {0xc5890000}, {0xc5892000}, {0xc5894000}, {0xc5896000}, + {0xc5898000}, {0xc589a000}, {0xc589c000}, {0xc589e000}, + {0xc58a0000}, {0xc58a2000}, {0xc58a4000}, {0xc58a6000}, + {0xc58a8000}, {0xc58aa000}, {0xc58ac000}, {0xc58ae000}, + {0xc58b0000}, {0xc58b2000}, {0xc58b4000}, {0xc58b6000}, + {0xc58b8000}, {0xc58ba000}, {0xc58bc000}, {0xc58be000}, + {0xc58c0000}, {0xc58c2000}, {0xc58c4000}, {0xc58c6000}, + {0xc58c8000}, {0xc58ca000}, {0xc58cc000}, {0xc58ce000}, + {0xc58d0000}, {0xc58d2000}, {0xc58d4000}, {0xc58d6000}, + {0xc58d8000}, {0xc58da000}, {0xc58dc000}, {0xc58de000}, + {0xc58e0000}, {0xc58e2000}, {0xc58e4000}, {0xc58e6000}, + {0xc58e8000}, {0xc58ea000}, {0xc58ec000}, {0xc58ee000}, + {0xc58f0000}, {0xc58f2000}, {0xc58f4000}, {0xc58f6000}, + {0xc58f8000}, {0xc58fa000}, {0xc58fc000}, {0xc58fe000}, + {0xc5900000}, {0xc5902000}, {0xc5904000}, {0xc5906000}, + {0xc5908000}, {0xc590a000}, {0xc590c000}, {0xc590e000}, + {0xc5910000}, {0xc5912000}, {0xc5914000}, {0xc5916000}, + {0xc5918000}, {0xc591a000}, {0xc591c000}, {0xc591e000}, + {0xc5920000}, {0xc5922000}, {0xc5924000}, {0xc5926000}, + {0xc5928000}, {0xc592a000}, {0xc592c000}, {0xc592e000}, + {0xc5930000}, {0xc5932000}, {0xc5934000}, {0xc5936000}, + {0xc5938000}, {0xc593a000}, {0xc593c000}, {0xc593e000}, + {0xc5940000}, {0xc5942000}, {0xc5944000}, {0xc5946000}, + {0xc5948000}, {0xc594a000}, {0xc594c000}, {0xc594e000}, + {0xc5950000}, {0xc5952000}, {0xc5954000}, {0xc5956000}, + {0xc5958000}, {0xc595a000}, {0xc595c000}, {0xc595e000}, + {0xc5960000}, {0xc5962000}, {0xc5964000}, {0xc5966000}, + {0xc5968000}, {0xc596a000}, {0xc596c000}, {0xc596e000}, + {0xc5970000}, {0xc5972000}, {0xc5974000}, {0xc5976000}, + {0xc5978000}, {0xc597a000}, {0xc597c000}, {0xc597e000}, + {0xc5980000}, {0xc5982000}, {0xc5984000}, {0xc5986000}, + {0xc5988000}, {0xc598a000}, {0xc598c000}, {0xc598e000}, + {0xc5990000}, {0xc5992000}, {0xc5994000}, {0xc5996000}, + {0xc5998000}, {0xc599a000}, {0xc599c000}, {0xc599e000}, + {0xc59a0000}, {0xc59a2000}, {0xc59a4000}, {0xc59a6000}, + {0xc59a8000}, {0xc59aa000}, {0xc59ac000}, {0xc59ae000}, + {0xc59b0000}, {0xc59b2000}, {0xc59b4000}, {0xc59b6000}, + {0xc59b8000}, {0xc59ba000}, {0xc59bc000}, {0xc59be000}, + {0xc59c0000}, {0xc59c2000}, {0xc59c4000}, {0xc59c6000}, + {0xc59c8000}, {0xc59ca000}, {0xc59cc000}, {0xc59ce000}, + {0xc59d0000}, {0xc59d2000}, {0xc59d4000}, {0xc59d6000}, + {0xc59d8000}, {0xc59da000}, {0xc59dc000}, {0xc59de000}, + {0xc59e0000}, {0xc59e2000}, {0xc59e4000}, {0xc59e6000}, + {0xc59e8000}, {0xc59ea000}, {0xc59ec000}, {0xc59ee000}, + {0xc59f0000}, {0xc59f2000}, {0xc59f4000}, {0xc59f6000}, + {0xc59f8000}, {0xc59fa000}, {0xc59fc000}, {0xc59fe000}, + {0xc5a00000}, {0xc5a02000}, {0xc5a04000}, {0xc5a06000}, + {0xc5a08000}, {0xc5a0a000}, {0xc5a0c000}, {0xc5a0e000}, + {0xc5a10000}, {0xc5a12000}, {0xc5a14000}, {0xc5a16000}, + {0xc5a18000}, {0xc5a1a000}, {0xc5a1c000}, {0xc5a1e000}, + {0xc5a20000}, {0xc5a22000}, {0xc5a24000}, {0xc5a26000}, + {0xc5a28000}, {0xc5a2a000}, {0xc5a2c000}, {0xc5a2e000}, + {0xc5a30000}, {0xc5a32000}, {0xc5a34000}, {0xc5a36000}, + {0xc5a38000}, {0xc5a3a000}, {0xc5a3c000}, {0xc5a3e000}, + {0xc5a40000}, {0xc5a42000}, {0xc5a44000}, {0xc5a46000}, + {0xc5a48000}, {0xc5a4a000}, {0xc5a4c000}, {0xc5a4e000}, + {0xc5a50000}, {0xc5a52000}, {0xc5a54000}, {0xc5a56000}, + {0xc5a58000}, {0xc5a5a000}, {0xc5a5c000}, {0xc5a5e000}, + {0xc5a60000}, {0xc5a62000}, {0xc5a64000}, {0xc5a66000}, + {0xc5a68000}, {0xc5a6a000}, {0xc5a6c000}, {0xc5a6e000}, + {0xc5a70000}, {0xc5a72000}, {0xc5a74000}, {0xc5a76000}, + {0xc5a78000}, {0xc5a7a000}, {0xc5a7c000}, {0xc5a7e000}, + {0xc5a80000}, {0xc5a82000}, {0xc5a84000}, {0xc5a86000}, + {0xc5a88000}, {0xc5a8a000}, {0xc5a8c000}, {0xc5a8e000}, + {0xc5a90000}, {0xc5a92000}, {0xc5a94000}, {0xc5a96000}, + {0xc5a98000}, {0xc5a9a000}, {0xc5a9c000}, {0xc5a9e000}, + {0xc5aa0000}, {0xc5aa2000}, {0xc5aa4000}, {0xc5aa6000}, + {0xc5aa8000}, {0xc5aaa000}, {0xc5aac000}, {0xc5aae000}, + {0xc5ab0000}, {0xc5ab2000}, {0xc5ab4000}, {0xc5ab6000}, + {0xc5ab8000}, {0xc5aba000}, {0xc5abc000}, {0xc5abe000}, + {0xc5ac0000}, {0xc5ac2000}, {0xc5ac4000}, {0xc5ac6000}, + {0xc5ac8000}, {0xc5aca000}, {0xc5acc000}, {0xc5ace000}, + {0xc5ad0000}, {0xc5ad2000}, {0xc5ad4000}, {0xc5ad6000}, + {0xc5ad8000}, {0xc5ada000}, {0xc5adc000}, {0xc5ade000}, + {0xc5ae0000}, {0xc5ae2000}, {0xc5ae4000}, {0xc5ae6000}, + {0xc5ae8000}, {0xc5aea000}, {0xc5aec000}, {0xc5aee000}, + {0xc5af0000}, {0xc5af2000}, {0xc5af4000}, {0xc5af6000}, + {0xc5af8000}, {0xc5afa000}, {0xc5afc000}, {0xc5afe000}, + {0xc5b00000}, {0xc5b02000}, {0xc5b04000}, {0xc5b06000}, + {0xc5b08000}, {0xc5b0a000}, {0xc5b0c000}, {0xc5b0e000}, + {0xc5b10000}, {0xc5b12000}, {0xc5b14000}, {0xc5b16000}, + {0xc5b18000}, {0xc5b1a000}, {0xc5b1c000}, {0xc5b1e000}, + {0xc5b20000}, {0xc5b22000}, {0xc5b24000}, {0xc5b26000}, + {0xc5b28000}, {0xc5b2a000}, {0xc5b2c000}, {0xc5b2e000}, + {0xc5b30000}, {0xc5b32000}, {0xc5b34000}, {0xc5b36000}, + {0xc5b38000}, {0xc5b3a000}, {0xc5b3c000}, {0xc5b3e000}, + {0xc5b40000}, {0xc5b42000}, {0xc5b44000}, {0xc5b46000}, + {0xc5b48000}, {0xc5b4a000}, {0xc5b4c000}, {0xc5b4e000}, + {0xc5b50000}, {0xc5b52000}, {0xc5b54000}, {0xc5b56000}, + {0xc5b58000}, {0xc5b5a000}, {0xc5b5c000}, {0xc5b5e000}, + {0xc5b60000}, {0xc5b62000}, {0xc5b64000}, {0xc5b66000}, + {0xc5b68000}, {0xc5b6a000}, {0xc5b6c000}, {0xc5b6e000}, + {0xc5b70000}, {0xc5b72000}, {0xc5b74000}, {0xc5b76000}, + {0xc5b78000}, {0xc5b7a000}, {0xc5b7c000}, {0xc5b7e000}, + {0xc5b80000}, {0xc5b82000}, {0xc5b84000}, {0xc5b86000}, + {0xc5b88000}, {0xc5b8a000}, {0xc5b8c000}, {0xc5b8e000}, + {0xc5b90000}, {0xc5b92000}, {0xc5b94000}, {0xc5b96000}, + {0xc5b98000}, {0xc5b9a000}, {0xc5b9c000}, {0xc5b9e000}, + {0xc5ba0000}, {0xc5ba2000}, {0xc5ba4000}, {0xc5ba6000}, + {0xc5ba8000}, {0xc5baa000}, {0xc5bac000}, {0xc5bae000}, + {0xc5bb0000}, {0xc5bb2000}, {0xc5bb4000}, {0xc5bb6000}, + {0xc5bb8000}, {0xc5bba000}, {0xc5bbc000}, {0xc5bbe000}, + {0xc5bc0000}, {0xc5bc2000}, {0xc5bc4000}, {0xc5bc6000}, + {0xc5bc8000}, {0xc5bca000}, {0xc5bcc000}, {0xc5bce000}, + {0xc5bd0000}, {0xc5bd2000}, {0xc5bd4000}, {0xc5bd6000}, + {0xc5bd8000}, {0xc5bda000}, {0xc5bdc000}, {0xc5bde000}, + {0xc5be0000}, {0xc5be2000}, {0xc5be4000}, {0xc5be6000}, + {0xc5be8000}, {0xc5bea000}, {0xc5bec000}, {0xc5bee000}, + {0xc5bf0000}, {0xc5bf2000}, {0xc5bf4000}, {0xc5bf6000}, + {0xc5bf8000}, {0xc5bfa000}, {0xc5bfc000}, {0xc5bfe000}, + {0xc5c00000}, {0xc5c02000}, {0xc5c04000}, {0xc5c06000}, + {0xc5c08000}, {0xc5c0a000}, {0xc5c0c000}, {0xc5c0e000}, + {0xc5c10000}, {0xc5c12000}, {0xc5c14000}, {0xc5c16000}, + {0xc5c18000}, {0xc5c1a000}, {0xc5c1c000}, {0xc5c1e000}, + {0xc5c20000}, {0xc5c22000}, {0xc5c24000}, {0xc5c26000}, + {0xc5c28000}, {0xc5c2a000}, {0xc5c2c000}, {0xc5c2e000}, + {0xc5c30000}, {0xc5c32000}, {0xc5c34000}, {0xc5c36000}, + {0xc5c38000}, {0xc5c3a000}, {0xc5c3c000}, {0xc5c3e000}, + {0xc5c40000}, {0xc5c42000}, {0xc5c44000}, {0xc5c46000}, + {0xc5c48000}, {0xc5c4a000}, {0xc5c4c000}, {0xc5c4e000}, + {0xc5c50000}, {0xc5c52000}, {0xc5c54000}, {0xc5c56000}, + {0xc5c58000}, {0xc5c5a000}, {0xc5c5c000}, {0xc5c5e000}, + {0xc5c60000}, {0xc5c62000}, {0xc5c64000}, {0xc5c66000}, + {0xc5c68000}, {0xc5c6a000}, {0xc5c6c000}, {0xc5c6e000}, + {0xc5c70000}, {0xc5c72000}, {0xc5c74000}, {0xc5c76000}, + {0xc5c78000}, {0xc5c7a000}, {0xc5c7c000}, {0xc5c7e000}, + {0xc5c80000}, {0xc5c82000}, {0xc5c84000}, {0xc5c86000}, + {0xc5c88000}, {0xc5c8a000}, {0xc5c8c000}, {0xc5c8e000}, + {0xc5c90000}, {0xc5c92000}, {0xc5c94000}, {0xc5c96000}, + {0xc5c98000}, {0xc5c9a000}, {0xc5c9c000}, {0xc5c9e000}, + {0xc5ca0000}, {0xc5ca2000}, {0xc5ca4000}, {0xc5ca6000}, + {0xc5ca8000}, {0xc5caa000}, {0xc5cac000}, {0xc5cae000}, + {0xc5cb0000}, {0xc5cb2000}, {0xc5cb4000}, {0xc5cb6000}, + {0xc5cb8000}, {0xc5cba000}, {0xc5cbc000}, {0xc5cbe000}, + {0xc5cc0000}, {0xc5cc2000}, {0xc5cc4000}, {0xc5cc6000}, + {0xc5cc8000}, {0xc5cca000}, {0xc5ccc000}, {0xc5cce000}, + {0xc5cd0000}, {0xc5cd2000}, {0xc5cd4000}, {0xc5cd6000}, + {0xc5cd8000}, {0xc5cda000}, {0xc5cdc000}, {0xc5cde000}, + {0xc5ce0000}, {0xc5ce2000}, {0xc5ce4000}, {0xc5ce6000}, + {0xc5ce8000}, {0xc5cea000}, {0xc5cec000}, {0xc5cee000}, + {0xc5cf0000}, {0xc5cf2000}, {0xc5cf4000}, {0xc5cf6000}, + {0xc5cf8000}, {0xc5cfa000}, {0xc5cfc000}, {0xc5cfe000}, + {0xc5d00000}, {0xc5d02000}, {0xc5d04000}, {0xc5d06000}, + {0xc5d08000}, {0xc5d0a000}, {0xc5d0c000}, {0xc5d0e000}, + {0xc5d10000}, {0xc5d12000}, {0xc5d14000}, {0xc5d16000}, + {0xc5d18000}, {0xc5d1a000}, {0xc5d1c000}, {0xc5d1e000}, + {0xc5d20000}, {0xc5d22000}, {0xc5d24000}, {0xc5d26000}, + {0xc5d28000}, {0xc5d2a000}, {0xc5d2c000}, {0xc5d2e000}, + {0xc5d30000}, {0xc5d32000}, {0xc5d34000}, {0xc5d36000}, + {0xc5d38000}, {0xc5d3a000}, {0xc5d3c000}, {0xc5d3e000}, + {0xc5d40000}, {0xc5d42000}, {0xc5d44000}, {0xc5d46000}, + {0xc5d48000}, {0xc5d4a000}, {0xc5d4c000}, {0xc5d4e000}, + {0xc5d50000}, {0xc5d52000}, {0xc5d54000}, {0xc5d56000}, + {0xc5d58000}, {0xc5d5a000}, {0xc5d5c000}, {0xc5d5e000}, + {0xc5d60000}, {0xc5d62000}, {0xc5d64000}, {0xc5d66000}, + {0xc5d68000}, {0xc5d6a000}, {0xc5d6c000}, {0xc5d6e000}, + {0xc5d70000}, {0xc5d72000}, {0xc5d74000}, {0xc5d76000}, + {0xc5d78000}, {0xc5d7a000}, {0xc5d7c000}, {0xc5d7e000}, + {0xc5d80000}, {0xc5d82000}, {0xc5d84000}, {0xc5d86000}, + {0xc5d88000}, {0xc5d8a000}, {0xc5d8c000}, {0xc5d8e000}, + {0xc5d90000}, {0xc5d92000}, {0xc5d94000}, {0xc5d96000}, + {0xc5d98000}, {0xc5d9a000}, {0xc5d9c000}, {0xc5d9e000}, + {0xc5da0000}, {0xc5da2000}, {0xc5da4000}, {0xc5da6000}, + {0xc5da8000}, {0xc5daa000}, {0xc5dac000}, {0xc5dae000}, + {0xc5db0000}, {0xc5db2000}, {0xc5db4000}, {0xc5db6000}, + {0xc5db8000}, {0xc5dba000}, {0xc5dbc000}, {0xc5dbe000}, + {0xc5dc0000}, {0xc5dc2000}, {0xc5dc4000}, {0xc5dc6000}, + {0xc5dc8000}, {0xc5dca000}, {0xc5dcc000}, {0xc5dce000}, + {0xc5dd0000}, {0xc5dd2000}, {0xc5dd4000}, {0xc5dd6000}, + {0xc5dd8000}, {0xc5dda000}, {0xc5ddc000}, {0xc5dde000}, + {0xc5de0000}, {0xc5de2000}, {0xc5de4000}, {0xc5de6000}, + {0xc5de8000}, {0xc5dea000}, {0xc5dec000}, {0xc5dee000}, + {0xc5df0000}, {0xc5df2000}, {0xc5df4000}, {0xc5df6000}, + {0xc5df8000}, {0xc5dfa000}, {0xc5dfc000}, {0xc5dfe000}, + {0xc5e00000}, {0xc5e02000}, {0xc5e04000}, {0xc5e06000}, + {0xc5e08000}, {0xc5e0a000}, {0xc5e0c000}, {0xc5e0e000}, + {0xc5e10000}, {0xc5e12000}, {0xc5e14000}, {0xc5e16000}, + {0xc5e18000}, {0xc5e1a000}, {0xc5e1c000}, {0xc5e1e000}, + {0xc5e20000}, {0xc5e22000}, {0xc5e24000}, {0xc5e26000}, + {0xc5e28000}, {0xc5e2a000}, {0xc5e2c000}, {0xc5e2e000}, + {0xc5e30000}, {0xc5e32000}, {0xc5e34000}, {0xc5e36000}, + {0xc5e38000}, {0xc5e3a000}, {0xc5e3c000}, {0xc5e3e000}, + {0xc5e40000}, {0xc5e42000}, {0xc5e44000}, {0xc5e46000}, + {0xc5e48000}, {0xc5e4a000}, {0xc5e4c000}, {0xc5e4e000}, + {0xc5e50000}, {0xc5e52000}, {0xc5e54000}, {0xc5e56000}, + {0xc5e58000}, {0xc5e5a000}, {0xc5e5c000}, {0xc5e5e000}, + {0xc5e60000}, {0xc5e62000}, {0xc5e64000}, {0xc5e66000}, + {0xc5e68000}, {0xc5e6a000}, {0xc5e6c000}, {0xc5e6e000}, + {0xc5e70000}, {0xc5e72000}, {0xc5e74000}, {0xc5e76000}, + {0xc5e78000}, {0xc5e7a000}, {0xc5e7c000}, {0xc5e7e000}, + {0xc5e80000}, {0xc5e82000}, {0xc5e84000}, {0xc5e86000}, + {0xc5e88000}, {0xc5e8a000}, {0xc5e8c000}, {0xc5e8e000}, + {0xc5e90000}, {0xc5e92000}, {0xc5e94000}, {0xc5e96000}, + {0xc5e98000}, {0xc5e9a000}, {0xc5e9c000}, {0xc5e9e000}, + {0xc5ea0000}, {0xc5ea2000}, {0xc5ea4000}, {0xc5ea6000}, + {0xc5ea8000}, {0xc5eaa000}, {0xc5eac000}, {0xc5eae000}, + {0xc5eb0000}, {0xc5eb2000}, {0xc5eb4000}, {0xc5eb6000}, + {0xc5eb8000}, {0xc5eba000}, {0xc5ebc000}, {0xc5ebe000}, + {0xc5ec0000}, {0xc5ec2000}, {0xc5ec4000}, {0xc5ec6000}, + {0xc5ec8000}, {0xc5eca000}, {0xc5ecc000}, {0xc5ece000}, + {0xc5ed0000}, {0xc5ed2000}, {0xc5ed4000}, {0xc5ed6000}, + {0xc5ed8000}, {0xc5eda000}, {0xc5edc000}, {0xc5ede000}, + {0xc5ee0000}, {0xc5ee2000}, {0xc5ee4000}, {0xc5ee6000}, + {0xc5ee8000}, {0xc5eea000}, {0xc5eec000}, {0xc5eee000}, + {0xc5ef0000}, {0xc5ef2000}, {0xc5ef4000}, {0xc5ef6000}, + {0xc5ef8000}, {0xc5efa000}, {0xc5efc000}, {0xc5efe000}, + {0xc5f00000}, {0xc5f02000}, {0xc5f04000}, {0xc5f06000}, + {0xc5f08000}, {0xc5f0a000}, {0xc5f0c000}, {0xc5f0e000}, + {0xc5f10000}, {0xc5f12000}, {0xc5f14000}, {0xc5f16000}, + {0xc5f18000}, {0xc5f1a000}, {0xc5f1c000}, {0xc5f1e000}, + {0xc5f20000}, {0xc5f22000}, {0xc5f24000}, {0xc5f26000}, + {0xc5f28000}, {0xc5f2a000}, {0xc5f2c000}, {0xc5f2e000}, + {0xc5f30000}, {0xc5f32000}, {0xc5f34000}, {0xc5f36000}, + {0xc5f38000}, {0xc5f3a000}, {0xc5f3c000}, {0xc5f3e000}, + {0xc5f40000}, {0xc5f42000}, {0xc5f44000}, {0xc5f46000}, + {0xc5f48000}, {0xc5f4a000}, {0xc5f4c000}, {0xc5f4e000}, + {0xc5f50000}, {0xc5f52000}, {0xc5f54000}, {0xc5f56000}, + {0xc5f58000}, {0xc5f5a000}, {0xc5f5c000}, {0xc5f5e000}, + {0xc5f60000}, {0xc5f62000}, {0xc5f64000}, {0xc5f66000}, + {0xc5f68000}, {0xc5f6a000}, {0xc5f6c000}, {0xc5f6e000}, + {0xc5f70000}, {0xc5f72000}, {0xc5f74000}, {0xc5f76000}, + {0xc5f78000}, {0xc5f7a000}, {0xc5f7c000}, {0xc5f7e000}, + {0xc5f80000}, {0xc5f82000}, {0xc5f84000}, {0xc5f86000}, + {0xc5f88000}, {0xc5f8a000}, {0xc5f8c000}, {0xc5f8e000}, + {0xc5f90000}, {0xc5f92000}, {0xc5f94000}, {0xc5f96000}, + {0xc5f98000}, {0xc5f9a000}, {0xc5f9c000}, {0xc5f9e000}, + {0xc5fa0000}, {0xc5fa2000}, {0xc5fa4000}, {0xc5fa6000}, + {0xc5fa8000}, {0xc5faa000}, {0xc5fac000}, {0xc5fae000}, + {0xc5fb0000}, {0xc5fb2000}, {0xc5fb4000}, {0xc5fb6000}, + {0xc5fb8000}, {0xc5fba000}, {0xc5fbc000}, {0xc5fbe000}, + {0xc5fc0000}, {0xc5fc2000}, {0xc5fc4000}, {0xc5fc6000}, + {0xc5fc8000}, {0xc5fca000}, {0xc5fcc000}, {0xc5fce000}, + {0xc5fd0000}, {0xc5fd2000}, {0xc5fd4000}, {0xc5fd6000}, + {0xc5fd8000}, {0xc5fda000}, {0xc5fdc000}, {0xc5fde000}, + {0xc5fe0000}, {0xc5fe2000}, {0xc5fe4000}, {0xc5fe6000}, + {0xc5fe8000}, {0xc5fea000}, {0xc5fec000}, {0xc5fee000}, + {0xc5ff0000}, {0xc5ff2000}, {0xc5ff4000}, {0xc5ff6000}, + {0xc5ff8000}, {0xc5ffa000}, {0xc5ffc000}, {0xc5ffe000}, + {0xc6000000}, {0xc6002000}, {0xc6004000}, {0xc6006000}, + {0xc6008000}, {0xc600a000}, {0xc600c000}, {0xc600e000}, + {0xc6010000}, {0xc6012000}, {0xc6014000}, {0xc6016000}, + {0xc6018000}, {0xc601a000}, {0xc601c000}, {0xc601e000}, + {0xc6020000}, {0xc6022000}, {0xc6024000}, {0xc6026000}, + {0xc6028000}, {0xc602a000}, {0xc602c000}, {0xc602e000}, + {0xc6030000}, {0xc6032000}, {0xc6034000}, {0xc6036000}, + {0xc6038000}, {0xc603a000}, {0xc603c000}, {0xc603e000}, + {0xc6040000}, {0xc6042000}, {0xc6044000}, {0xc6046000}, + {0xc6048000}, {0xc604a000}, {0xc604c000}, {0xc604e000}, + {0xc6050000}, {0xc6052000}, {0xc6054000}, {0xc6056000}, + {0xc6058000}, {0xc605a000}, {0xc605c000}, {0xc605e000}, + {0xc6060000}, {0xc6062000}, {0xc6064000}, {0xc6066000}, + {0xc6068000}, {0xc606a000}, {0xc606c000}, {0xc606e000}, + {0xc6070000}, {0xc6072000}, {0xc6074000}, {0xc6076000}, + {0xc6078000}, {0xc607a000}, {0xc607c000}, {0xc607e000}, + {0xc6080000}, {0xc6082000}, {0xc6084000}, {0xc6086000}, + {0xc6088000}, {0xc608a000}, {0xc608c000}, {0xc608e000}, + {0xc6090000}, {0xc6092000}, {0xc6094000}, {0xc6096000}, + {0xc6098000}, {0xc609a000}, {0xc609c000}, {0xc609e000}, + {0xc60a0000}, {0xc60a2000}, {0xc60a4000}, {0xc60a6000}, + {0xc60a8000}, {0xc60aa000}, {0xc60ac000}, {0xc60ae000}, + {0xc60b0000}, {0xc60b2000}, {0xc60b4000}, {0xc60b6000}, + {0xc60b8000}, {0xc60ba000}, {0xc60bc000}, {0xc60be000}, + {0xc60c0000}, {0xc60c2000}, {0xc60c4000}, {0xc60c6000}, + {0xc60c8000}, {0xc60ca000}, {0xc60cc000}, {0xc60ce000}, + {0xc60d0000}, {0xc60d2000}, {0xc60d4000}, {0xc60d6000}, + {0xc60d8000}, {0xc60da000}, {0xc60dc000}, {0xc60de000}, + {0xc60e0000}, {0xc60e2000}, {0xc60e4000}, {0xc60e6000}, + {0xc60e8000}, {0xc60ea000}, {0xc60ec000}, {0xc60ee000}, + {0xc60f0000}, {0xc60f2000}, {0xc60f4000}, {0xc60f6000}, + {0xc60f8000}, {0xc60fa000}, {0xc60fc000}, {0xc60fe000}, + {0xc6100000}, {0xc6102000}, {0xc6104000}, {0xc6106000}, + {0xc6108000}, {0xc610a000}, {0xc610c000}, {0xc610e000}, + {0xc6110000}, {0xc6112000}, {0xc6114000}, {0xc6116000}, + {0xc6118000}, {0xc611a000}, {0xc611c000}, {0xc611e000}, + {0xc6120000}, {0xc6122000}, {0xc6124000}, {0xc6126000}, + {0xc6128000}, {0xc612a000}, {0xc612c000}, {0xc612e000}, + {0xc6130000}, {0xc6132000}, {0xc6134000}, {0xc6136000}, + {0xc6138000}, {0xc613a000}, {0xc613c000}, {0xc613e000}, + {0xc6140000}, {0xc6142000}, {0xc6144000}, {0xc6146000}, + {0xc6148000}, {0xc614a000}, {0xc614c000}, {0xc614e000}, + {0xc6150000}, {0xc6152000}, {0xc6154000}, {0xc6156000}, + {0xc6158000}, {0xc615a000}, {0xc615c000}, {0xc615e000}, + {0xc6160000}, {0xc6162000}, {0xc6164000}, {0xc6166000}, + {0xc6168000}, {0xc616a000}, {0xc616c000}, {0xc616e000}, + {0xc6170000}, {0xc6172000}, {0xc6174000}, {0xc6176000}, + {0xc6178000}, {0xc617a000}, {0xc617c000}, {0xc617e000}, + {0xc6180000}, {0xc6182000}, {0xc6184000}, {0xc6186000}, + {0xc6188000}, {0xc618a000}, {0xc618c000}, {0xc618e000}, + {0xc6190000}, {0xc6192000}, {0xc6194000}, {0xc6196000}, + {0xc6198000}, {0xc619a000}, {0xc619c000}, {0xc619e000}, + {0xc61a0000}, {0xc61a2000}, {0xc61a4000}, {0xc61a6000}, + {0xc61a8000}, {0xc61aa000}, {0xc61ac000}, {0xc61ae000}, + {0xc61b0000}, {0xc61b2000}, {0xc61b4000}, {0xc61b6000}, + {0xc61b8000}, {0xc61ba000}, {0xc61bc000}, {0xc61be000}, + {0xc61c0000}, {0xc61c2000}, {0xc61c4000}, {0xc61c6000}, + {0xc61c8000}, {0xc61ca000}, {0xc61cc000}, {0xc61ce000}, + {0xc61d0000}, {0xc61d2000}, {0xc61d4000}, {0xc61d6000}, + {0xc61d8000}, {0xc61da000}, {0xc61dc000}, {0xc61de000}, + {0xc61e0000}, {0xc61e2000}, {0xc61e4000}, {0xc61e6000}, + {0xc61e8000}, {0xc61ea000}, {0xc61ec000}, {0xc61ee000}, + {0xc61f0000}, {0xc61f2000}, {0xc61f4000}, {0xc61f6000}, + {0xc61f8000}, {0xc61fa000}, {0xc61fc000}, {0xc61fe000}, + {0xc6200000}, {0xc6202000}, {0xc6204000}, {0xc6206000}, + {0xc6208000}, {0xc620a000}, {0xc620c000}, {0xc620e000}, + {0xc6210000}, {0xc6212000}, {0xc6214000}, {0xc6216000}, + {0xc6218000}, {0xc621a000}, {0xc621c000}, {0xc621e000}, + {0xc6220000}, {0xc6222000}, {0xc6224000}, {0xc6226000}, + {0xc6228000}, {0xc622a000}, {0xc622c000}, {0xc622e000}, + {0xc6230000}, {0xc6232000}, {0xc6234000}, {0xc6236000}, + {0xc6238000}, {0xc623a000}, {0xc623c000}, {0xc623e000}, + {0xc6240000}, {0xc6242000}, {0xc6244000}, {0xc6246000}, + {0xc6248000}, {0xc624a000}, {0xc624c000}, {0xc624e000}, + {0xc6250000}, {0xc6252000}, {0xc6254000}, {0xc6256000}, + {0xc6258000}, {0xc625a000}, {0xc625c000}, {0xc625e000}, + {0xc6260000}, {0xc6262000}, {0xc6264000}, {0xc6266000}, + {0xc6268000}, {0xc626a000}, {0xc626c000}, {0xc626e000}, + {0xc6270000}, {0xc6272000}, {0xc6274000}, {0xc6276000}, + {0xc6278000}, {0xc627a000}, {0xc627c000}, {0xc627e000}, + {0xc6280000}, {0xc6282000}, {0xc6284000}, {0xc6286000}, + {0xc6288000}, {0xc628a000}, {0xc628c000}, {0xc628e000}, + {0xc6290000}, {0xc6292000}, {0xc6294000}, {0xc6296000}, + {0xc6298000}, {0xc629a000}, {0xc629c000}, {0xc629e000}, + {0xc62a0000}, {0xc62a2000}, {0xc62a4000}, {0xc62a6000}, + {0xc62a8000}, {0xc62aa000}, {0xc62ac000}, {0xc62ae000}, + {0xc62b0000}, {0xc62b2000}, {0xc62b4000}, {0xc62b6000}, + {0xc62b8000}, {0xc62ba000}, {0xc62bc000}, {0xc62be000}, + {0xc62c0000}, {0xc62c2000}, {0xc62c4000}, {0xc62c6000}, + {0xc62c8000}, {0xc62ca000}, {0xc62cc000}, {0xc62ce000}, + {0xc62d0000}, {0xc62d2000}, {0xc62d4000}, {0xc62d6000}, + {0xc62d8000}, {0xc62da000}, {0xc62dc000}, {0xc62de000}, + {0xc62e0000}, {0xc62e2000}, {0xc62e4000}, {0xc62e6000}, + {0xc62e8000}, {0xc62ea000}, {0xc62ec000}, {0xc62ee000}, + {0xc62f0000}, {0xc62f2000}, {0xc62f4000}, {0xc62f6000}, + {0xc62f8000}, {0xc62fa000}, {0xc62fc000}, {0xc62fe000}, + {0xc6300000}, {0xc6302000}, {0xc6304000}, {0xc6306000}, + {0xc6308000}, {0xc630a000}, {0xc630c000}, {0xc630e000}, + {0xc6310000}, {0xc6312000}, {0xc6314000}, {0xc6316000}, + {0xc6318000}, {0xc631a000}, {0xc631c000}, {0xc631e000}, + {0xc6320000}, {0xc6322000}, {0xc6324000}, {0xc6326000}, + {0xc6328000}, {0xc632a000}, {0xc632c000}, {0xc632e000}, + {0xc6330000}, {0xc6332000}, {0xc6334000}, {0xc6336000}, + {0xc6338000}, {0xc633a000}, {0xc633c000}, {0xc633e000}, + {0xc6340000}, {0xc6342000}, {0xc6344000}, {0xc6346000}, + {0xc6348000}, {0xc634a000}, {0xc634c000}, {0xc634e000}, + {0xc6350000}, {0xc6352000}, {0xc6354000}, {0xc6356000}, + {0xc6358000}, {0xc635a000}, {0xc635c000}, {0xc635e000}, + {0xc6360000}, {0xc6362000}, {0xc6364000}, {0xc6366000}, + {0xc6368000}, {0xc636a000}, {0xc636c000}, {0xc636e000}, + {0xc6370000}, {0xc6372000}, {0xc6374000}, {0xc6376000}, + {0xc6378000}, {0xc637a000}, {0xc637c000}, {0xc637e000}, + {0xc6380000}, {0xc6382000}, {0xc6384000}, {0xc6386000}, + {0xc6388000}, {0xc638a000}, {0xc638c000}, {0xc638e000}, + {0xc6390000}, {0xc6392000}, {0xc6394000}, {0xc6396000}, + {0xc6398000}, {0xc639a000}, {0xc639c000}, {0xc639e000}, + {0xc63a0000}, {0xc63a2000}, {0xc63a4000}, {0xc63a6000}, + {0xc63a8000}, {0xc63aa000}, {0xc63ac000}, {0xc63ae000}, + {0xc63b0000}, {0xc63b2000}, {0xc63b4000}, {0xc63b6000}, + {0xc63b8000}, {0xc63ba000}, {0xc63bc000}, {0xc63be000}, + {0xc63c0000}, {0xc63c2000}, {0xc63c4000}, {0xc63c6000}, + {0xc63c8000}, {0xc63ca000}, {0xc63cc000}, {0xc63ce000}, + {0xc63d0000}, {0xc63d2000}, {0xc63d4000}, {0xc63d6000}, + {0xc63d8000}, {0xc63da000}, {0xc63dc000}, {0xc63de000}, + {0xc63e0000}, {0xc63e2000}, {0xc63e4000}, {0xc63e6000}, + {0xc63e8000}, {0xc63ea000}, {0xc63ec000}, {0xc63ee000}, + {0xc63f0000}, {0xc63f2000}, {0xc63f4000}, {0xc63f6000}, + {0xc63f8000}, {0xc63fa000}, {0xc63fc000}, {0xc63fe000}, + {0xc6400000}, {0xc6402000}, {0xc6404000}, {0xc6406000}, + {0xc6408000}, {0xc640a000}, {0xc640c000}, {0xc640e000}, + {0xc6410000}, {0xc6412000}, {0xc6414000}, {0xc6416000}, + {0xc6418000}, {0xc641a000}, {0xc641c000}, {0xc641e000}, + {0xc6420000}, {0xc6422000}, {0xc6424000}, {0xc6426000}, + {0xc6428000}, {0xc642a000}, {0xc642c000}, {0xc642e000}, + {0xc6430000}, {0xc6432000}, {0xc6434000}, {0xc6436000}, + {0xc6438000}, {0xc643a000}, {0xc643c000}, {0xc643e000}, + {0xc6440000}, {0xc6442000}, {0xc6444000}, {0xc6446000}, + {0xc6448000}, {0xc644a000}, {0xc644c000}, {0xc644e000}, + {0xc6450000}, {0xc6452000}, {0xc6454000}, {0xc6456000}, + {0xc6458000}, {0xc645a000}, {0xc645c000}, {0xc645e000}, + {0xc6460000}, {0xc6462000}, {0xc6464000}, {0xc6466000}, + {0xc6468000}, {0xc646a000}, {0xc646c000}, {0xc646e000}, + {0xc6470000}, {0xc6472000}, {0xc6474000}, {0xc6476000}, + {0xc6478000}, {0xc647a000}, {0xc647c000}, {0xc647e000}, + {0xc6480000}, {0xc6482000}, {0xc6484000}, {0xc6486000}, + {0xc6488000}, {0xc648a000}, {0xc648c000}, {0xc648e000}, + {0xc6490000}, {0xc6492000}, {0xc6494000}, {0xc6496000}, + {0xc6498000}, {0xc649a000}, {0xc649c000}, {0xc649e000}, + {0xc64a0000}, {0xc64a2000}, {0xc64a4000}, {0xc64a6000}, + {0xc64a8000}, {0xc64aa000}, {0xc64ac000}, {0xc64ae000}, + {0xc64b0000}, {0xc64b2000}, {0xc64b4000}, {0xc64b6000}, + {0xc64b8000}, {0xc64ba000}, {0xc64bc000}, {0xc64be000}, + {0xc64c0000}, {0xc64c2000}, {0xc64c4000}, {0xc64c6000}, + {0xc64c8000}, {0xc64ca000}, {0xc64cc000}, {0xc64ce000}, + {0xc64d0000}, {0xc64d2000}, {0xc64d4000}, {0xc64d6000}, + {0xc64d8000}, {0xc64da000}, {0xc64dc000}, {0xc64de000}, + {0xc64e0000}, {0xc64e2000}, {0xc64e4000}, {0xc64e6000}, + {0xc64e8000}, {0xc64ea000}, {0xc64ec000}, {0xc64ee000}, + {0xc64f0000}, {0xc64f2000}, {0xc64f4000}, {0xc64f6000}, + {0xc64f8000}, {0xc64fa000}, {0xc64fc000}, {0xc64fe000}, + {0xc6500000}, {0xc6502000}, {0xc6504000}, {0xc6506000}, + {0xc6508000}, {0xc650a000}, {0xc650c000}, {0xc650e000}, + {0xc6510000}, {0xc6512000}, {0xc6514000}, {0xc6516000}, + {0xc6518000}, {0xc651a000}, {0xc651c000}, {0xc651e000}, + {0xc6520000}, {0xc6522000}, {0xc6524000}, {0xc6526000}, + {0xc6528000}, {0xc652a000}, {0xc652c000}, {0xc652e000}, + {0xc6530000}, {0xc6532000}, {0xc6534000}, {0xc6536000}, + {0xc6538000}, {0xc653a000}, {0xc653c000}, {0xc653e000}, + {0xc6540000}, {0xc6542000}, {0xc6544000}, {0xc6546000}, + {0xc6548000}, {0xc654a000}, {0xc654c000}, {0xc654e000}, + {0xc6550000}, {0xc6552000}, {0xc6554000}, {0xc6556000}, + {0xc6558000}, {0xc655a000}, {0xc655c000}, {0xc655e000}, + {0xc6560000}, {0xc6562000}, {0xc6564000}, {0xc6566000}, + {0xc6568000}, {0xc656a000}, {0xc656c000}, {0xc656e000}, + {0xc6570000}, {0xc6572000}, {0xc6574000}, {0xc6576000}, + {0xc6578000}, {0xc657a000}, {0xc657c000}, {0xc657e000}, + {0xc6580000}, {0xc6582000}, {0xc6584000}, {0xc6586000}, + {0xc6588000}, {0xc658a000}, {0xc658c000}, {0xc658e000}, + {0xc6590000}, {0xc6592000}, {0xc6594000}, {0xc6596000}, + {0xc6598000}, {0xc659a000}, {0xc659c000}, {0xc659e000}, + {0xc65a0000}, {0xc65a2000}, {0xc65a4000}, {0xc65a6000}, + {0xc65a8000}, {0xc65aa000}, {0xc65ac000}, {0xc65ae000}, + {0xc65b0000}, {0xc65b2000}, {0xc65b4000}, {0xc65b6000}, + {0xc65b8000}, {0xc65ba000}, {0xc65bc000}, {0xc65be000}, + {0xc65c0000}, {0xc65c2000}, {0xc65c4000}, {0xc65c6000}, + {0xc65c8000}, {0xc65ca000}, {0xc65cc000}, {0xc65ce000}, + {0xc65d0000}, {0xc65d2000}, {0xc65d4000}, {0xc65d6000}, + {0xc65d8000}, {0xc65da000}, {0xc65dc000}, {0xc65de000}, + {0xc65e0000}, {0xc65e2000}, {0xc65e4000}, {0xc65e6000}, + {0xc65e8000}, {0xc65ea000}, {0xc65ec000}, {0xc65ee000}, + {0xc65f0000}, {0xc65f2000}, {0xc65f4000}, {0xc65f6000}, + {0xc65f8000}, {0xc65fa000}, {0xc65fc000}, {0xc65fe000}, + {0xc6600000}, {0xc6602000}, {0xc6604000}, {0xc6606000}, + {0xc6608000}, {0xc660a000}, {0xc660c000}, {0xc660e000}, + {0xc6610000}, {0xc6612000}, {0xc6614000}, {0xc6616000}, + {0xc6618000}, {0xc661a000}, {0xc661c000}, {0xc661e000}, + {0xc6620000}, {0xc6622000}, {0xc6624000}, {0xc6626000}, + {0xc6628000}, {0xc662a000}, {0xc662c000}, {0xc662e000}, + {0xc6630000}, {0xc6632000}, {0xc6634000}, {0xc6636000}, + {0xc6638000}, {0xc663a000}, {0xc663c000}, {0xc663e000}, + {0xc6640000}, {0xc6642000}, {0xc6644000}, {0xc6646000}, + {0xc6648000}, {0xc664a000}, {0xc664c000}, {0xc664e000}, + {0xc6650000}, {0xc6652000}, {0xc6654000}, {0xc6656000}, + {0xc6658000}, {0xc665a000}, {0xc665c000}, {0xc665e000}, + {0xc6660000}, {0xc6662000}, {0xc6664000}, {0xc6666000}, + {0xc6668000}, {0xc666a000}, {0xc666c000}, {0xc666e000}, + {0xc6670000}, {0xc6672000}, {0xc6674000}, {0xc6676000}, + {0xc6678000}, {0xc667a000}, {0xc667c000}, {0xc667e000}, + {0xc6680000}, {0xc6682000}, {0xc6684000}, {0xc6686000}, + {0xc6688000}, {0xc668a000}, {0xc668c000}, {0xc668e000}, + {0xc6690000}, {0xc6692000}, {0xc6694000}, {0xc6696000}, + {0xc6698000}, {0xc669a000}, {0xc669c000}, {0xc669e000}, + {0xc66a0000}, {0xc66a2000}, {0xc66a4000}, {0xc66a6000}, + {0xc66a8000}, {0xc66aa000}, {0xc66ac000}, {0xc66ae000}, + {0xc66b0000}, {0xc66b2000}, {0xc66b4000}, {0xc66b6000}, + {0xc66b8000}, {0xc66ba000}, {0xc66bc000}, {0xc66be000}, + {0xc66c0000}, {0xc66c2000}, {0xc66c4000}, {0xc66c6000}, + {0xc66c8000}, {0xc66ca000}, {0xc66cc000}, {0xc66ce000}, + {0xc66d0000}, {0xc66d2000}, {0xc66d4000}, {0xc66d6000}, + {0xc66d8000}, {0xc66da000}, {0xc66dc000}, {0xc66de000}, + {0xc66e0000}, {0xc66e2000}, {0xc66e4000}, {0xc66e6000}, + {0xc66e8000}, {0xc66ea000}, {0xc66ec000}, {0xc66ee000}, + {0xc66f0000}, {0xc66f2000}, {0xc66f4000}, {0xc66f6000}, + {0xc66f8000}, {0xc66fa000}, {0xc66fc000}, {0xc66fe000}, + {0xc6700000}, {0xc6702000}, {0xc6704000}, {0xc6706000}, + {0xc6708000}, {0xc670a000}, {0xc670c000}, {0xc670e000}, + {0xc6710000}, {0xc6712000}, {0xc6714000}, {0xc6716000}, + {0xc6718000}, {0xc671a000}, {0xc671c000}, {0xc671e000}, + {0xc6720000}, {0xc6722000}, {0xc6724000}, {0xc6726000}, + {0xc6728000}, {0xc672a000}, {0xc672c000}, {0xc672e000}, + {0xc6730000}, {0xc6732000}, {0xc6734000}, {0xc6736000}, + {0xc6738000}, {0xc673a000}, {0xc673c000}, {0xc673e000}, + {0xc6740000}, {0xc6742000}, {0xc6744000}, {0xc6746000}, + {0xc6748000}, {0xc674a000}, {0xc674c000}, {0xc674e000}, + {0xc6750000}, {0xc6752000}, {0xc6754000}, {0xc6756000}, + {0xc6758000}, {0xc675a000}, {0xc675c000}, {0xc675e000}, + {0xc6760000}, {0xc6762000}, {0xc6764000}, {0xc6766000}, + {0xc6768000}, {0xc676a000}, {0xc676c000}, {0xc676e000}, + {0xc6770000}, {0xc6772000}, {0xc6774000}, {0xc6776000}, + {0xc6778000}, {0xc677a000}, {0xc677c000}, {0xc677e000}, + {0xc6780000}, {0xc6782000}, {0xc6784000}, {0xc6786000}, + {0xc6788000}, {0xc678a000}, {0xc678c000}, {0xc678e000}, + {0xc6790000}, {0xc6792000}, {0xc6794000}, {0xc6796000}, + {0xc6798000}, {0xc679a000}, {0xc679c000}, {0xc679e000}, + {0xc67a0000}, {0xc67a2000}, {0xc67a4000}, {0xc67a6000}, + {0xc67a8000}, {0xc67aa000}, {0xc67ac000}, {0xc67ae000}, + {0xc67b0000}, {0xc67b2000}, {0xc67b4000}, {0xc67b6000}, + {0xc67b8000}, {0xc67ba000}, {0xc67bc000}, {0xc67be000}, + {0xc67c0000}, {0xc67c2000}, {0xc67c4000}, {0xc67c6000}, + {0xc67c8000}, {0xc67ca000}, {0xc67cc000}, {0xc67ce000}, + {0xc67d0000}, {0xc67d2000}, {0xc67d4000}, {0xc67d6000}, + {0xc67d8000}, {0xc67da000}, {0xc67dc000}, {0xc67de000}, + {0xc67e0000}, {0xc67e2000}, {0xc67e4000}, {0xc67e6000}, + {0xc67e8000}, {0xc67ea000}, {0xc67ec000}, {0xc67ee000}, + {0xc67f0000}, {0xc67f2000}, {0xc67f4000}, {0xc67f6000}, + {0xc67f8000}, {0xc67fa000}, {0xc67fc000}, {0xc67fe000}, + {0xc6800000}, {0xc6802000}, {0xc6804000}, {0xc6806000}, + {0xc6808000}, {0xc680a000}, {0xc680c000}, {0xc680e000}, + {0xc6810000}, {0xc6812000}, {0xc6814000}, {0xc6816000}, + {0xc6818000}, {0xc681a000}, {0xc681c000}, {0xc681e000}, + {0xc6820000}, {0xc6822000}, {0xc6824000}, {0xc6826000}, + {0xc6828000}, {0xc682a000}, {0xc682c000}, {0xc682e000}, + {0xc6830000}, {0xc6832000}, {0xc6834000}, {0xc6836000}, + {0xc6838000}, {0xc683a000}, {0xc683c000}, {0xc683e000}, + {0xc6840000}, {0xc6842000}, {0xc6844000}, {0xc6846000}, + {0xc6848000}, {0xc684a000}, {0xc684c000}, {0xc684e000}, + {0xc6850000}, {0xc6852000}, {0xc6854000}, {0xc6856000}, + {0xc6858000}, {0xc685a000}, {0xc685c000}, {0xc685e000}, + {0xc6860000}, {0xc6862000}, {0xc6864000}, {0xc6866000}, + {0xc6868000}, {0xc686a000}, {0xc686c000}, {0xc686e000}, + {0xc6870000}, {0xc6872000}, {0xc6874000}, {0xc6876000}, + {0xc6878000}, {0xc687a000}, {0xc687c000}, {0xc687e000}, + {0xc6880000}, {0xc6882000}, {0xc6884000}, {0xc6886000}, + {0xc6888000}, {0xc688a000}, {0xc688c000}, {0xc688e000}, + {0xc6890000}, {0xc6892000}, {0xc6894000}, {0xc6896000}, + {0xc6898000}, {0xc689a000}, {0xc689c000}, {0xc689e000}, + {0xc68a0000}, {0xc68a2000}, {0xc68a4000}, {0xc68a6000}, + {0xc68a8000}, {0xc68aa000}, {0xc68ac000}, {0xc68ae000}, + {0xc68b0000}, {0xc68b2000}, {0xc68b4000}, {0xc68b6000}, + {0xc68b8000}, {0xc68ba000}, {0xc68bc000}, {0xc68be000}, + {0xc68c0000}, {0xc68c2000}, {0xc68c4000}, {0xc68c6000}, + {0xc68c8000}, {0xc68ca000}, {0xc68cc000}, {0xc68ce000}, + {0xc68d0000}, {0xc68d2000}, {0xc68d4000}, {0xc68d6000}, + {0xc68d8000}, {0xc68da000}, {0xc68dc000}, {0xc68de000}, + {0xc68e0000}, {0xc68e2000}, {0xc68e4000}, {0xc68e6000}, + {0xc68e8000}, {0xc68ea000}, {0xc68ec000}, {0xc68ee000}, + {0xc68f0000}, {0xc68f2000}, {0xc68f4000}, {0xc68f6000}, + {0xc68f8000}, {0xc68fa000}, {0xc68fc000}, {0xc68fe000}, + {0xc6900000}, {0xc6902000}, {0xc6904000}, {0xc6906000}, + {0xc6908000}, {0xc690a000}, {0xc690c000}, {0xc690e000}, + {0xc6910000}, {0xc6912000}, {0xc6914000}, {0xc6916000}, + {0xc6918000}, {0xc691a000}, {0xc691c000}, {0xc691e000}, + {0xc6920000}, {0xc6922000}, {0xc6924000}, {0xc6926000}, + {0xc6928000}, {0xc692a000}, {0xc692c000}, {0xc692e000}, + {0xc6930000}, {0xc6932000}, {0xc6934000}, {0xc6936000}, + {0xc6938000}, {0xc693a000}, {0xc693c000}, {0xc693e000}, + {0xc6940000}, {0xc6942000}, {0xc6944000}, {0xc6946000}, + {0xc6948000}, {0xc694a000}, {0xc694c000}, {0xc694e000}, + {0xc6950000}, {0xc6952000}, {0xc6954000}, {0xc6956000}, + {0xc6958000}, {0xc695a000}, {0xc695c000}, {0xc695e000}, + {0xc6960000}, {0xc6962000}, {0xc6964000}, {0xc6966000}, + {0xc6968000}, {0xc696a000}, {0xc696c000}, {0xc696e000}, + {0xc6970000}, {0xc6972000}, {0xc6974000}, {0xc6976000}, + {0xc6978000}, {0xc697a000}, {0xc697c000}, {0xc697e000}, + {0xc6980000}, {0xc6982000}, {0xc6984000}, {0xc6986000}, + {0xc6988000}, {0xc698a000}, {0xc698c000}, {0xc698e000}, + {0xc6990000}, {0xc6992000}, {0xc6994000}, {0xc6996000}, + {0xc6998000}, {0xc699a000}, {0xc699c000}, {0xc699e000}, + {0xc69a0000}, {0xc69a2000}, {0xc69a4000}, {0xc69a6000}, + {0xc69a8000}, {0xc69aa000}, {0xc69ac000}, {0xc69ae000}, + {0xc69b0000}, {0xc69b2000}, {0xc69b4000}, {0xc69b6000}, + {0xc69b8000}, {0xc69ba000}, {0xc69bc000}, {0xc69be000}, + {0xc69c0000}, {0xc69c2000}, {0xc69c4000}, {0xc69c6000}, + {0xc69c8000}, {0xc69ca000}, {0xc69cc000}, {0xc69ce000}, + {0xc69d0000}, {0xc69d2000}, {0xc69d4000}, {0xc69d6000}, + {0xc69d8000}, {0xc69da000}, {0xc69dc000}, {0xc69de000}, + {0xc69e0000}, {0xc69e2000}, {0xc69e4000}, {0xc69e6000}, + {0xc69e8000}, {0xc69ea000}, {0xc69ec000}, {0xc69ee000}, + {0xc69f0000}, {0xc69f2000}, {0xc69f4000}, {0xc69f6000}, + {0xc69f8000}, {0xc69fa000}, {0xc69fc000}, {0xc69fe000}, + {0xc6a00000}, {0xc6a02000}, {0xc6a04000}, {0xc6a06000}, + {0xc6a08000}, {0xc6a0a000}, {0xc6a0c000}, {0xc6a0e000}, + {0xc6a10000}, {0xc6a12000}, {0xc6a14000}, {0xc6a16000}, + {0xc6a18000}, {0xc6a1a000}, {0xc6a1c000}, {0xc6a1e000}, + {0xc6a20000}, {0xc6a22000}, {0xc6a24000}, {0xc6a26000}, + {0xc6a28000}, {0xc6a2a000}, {0xc6a2c000}, {0xc6a2e000}, + {0xc6a30000}, {0xc6a32000}, {0xc6a34000}, {0xc6a36000}, + {0xc6a38000}, {0xc6a3a000}, {0xc6a3c000}, {0xc6a3e000}, + {0xc6a40000}, {0xc6a42000}, {0xc6a44000}, {0xc6a46000}, + {0xc6a48000}, {0xc6a4a000}, {0xc6a4c000}, {0xc6a4e000}, + {0xc6a50000}, {0xc6a52000}, {0xc6a54000}, {0xc6a56000}, + {0xc6a58000}, {0xc6a5a000}, {0xc6a5c000}, {0xc6a5e000}, + {0xc6a60000}, {0xc6a62000}, {0xc6a64000}, {0xc6a66000}, + {0xc6a68000}, {0xc6a6a000}, {0xc6a6c000}, {0xc6a6e000}, + {0xc6a70000}, {0xc6a72000}, {0xc6a74000}, {0xc6a76000}, + {0xc6a78000}, {0xc6a7a000}, {0xc6a7c000}, {0xc6a7e000}, + {0xc6a80000}, {0xc6a82000}, {0xc6a84000}, {0xc6a86000}, + {0xc6a88000}, {0xc6a8a000}, {0xc6a8c000}, {0xc6a8e000}, + {0xc6a90000}, {0xc6a92000}, {0xc6a94000}, {0xc6a96000}, + {0xc6a98000}, {0xc6a9a000}, {0xc6a9c000}, {0xc6a9e000}, + {0xc6aa0000}, {0xc6aa2000}, {0xc6aa4000}, {0xc6aa6000}, + {0xc6aa8000}, {0xc6aaa000}, {0xc6aac000}, {0xc6aae000}, + {0xc6ab0000}, {0xc6ab2000}, {0xc6ab4000}, {0xc6ab6000}, + {0xc6ab8000}, {0xc6aba000}, {0xc6abc000}, {0xc6abe000}, + {0xc6ac0000}, {0xc6ac2000}, {0xc6ac4000}, {0xc6ac6000}, + {0xc6ac8000}, {0xc6aca000}, {0xc6acc000}, {0xc6ace000}, + {0xc6ad0000}, {0xc6ad2000}, {0xc6ad4000}, {0xc6ad6000}, + {0xc6ad8000}, {0xc6ada000}, {0xc6adc000}, {0xc6ade000}, + {0xc6ae0000}, {0xc6ae2000}, {0xc6ae4000}, {0xc6ae6000}, + {0xc6ae8000}, {0xc6aea000}, {0xc6aec000}, {0xc6aee000}, + {0xc6af0000}, {0xc6af2000}, {0xc6af4000}, {0xc6af6000}, + {0xc6af8000}, {0xc6afa000}, {0xc6afc000}, {0xc6afe000}, + {0xc6b00000}, {0xc6b02000}, {0xc6b04000}, {0xc6b06000}, + {0xc6b08000}, {0xc6b0a000}, {0xc6b0c000}, {0xc6b0e000}, + {0xc6b10000}, {0xc6b12000}, {0xc6b14000}, {0xc6b16000}, + {0xc6b18000}, {0xc6b1a000}, {0xc6b1c000}, {0xc6b1e000}, + {0xc6b20000}, {0xc6b22000}, {0xc6b24000}, {0xc6b26000}, + {0xc6b28000}, {0xc6b2a000}, {0xc6b2c000}, {0xc6b2e000}, + {0xc6b30000}, {0xc6b32000}, {0xc6b34000}, {0xc6b36000}, + {0xc6b38000}, {0xc6b3a000}, {0xc6b3c000}, {0xc6b3e000}, + {0xc6b40000}, {0xc6b42000}, {0xc6b44000}, {0xc6b46000}, + {0xc6b48000}, {0xc6b4a000}, {0xc6b4c000}, {0xc6b4e000}, + {0xc6b50000}, {0xc6b52000}, {0xc6b54000}, {0xc6b56000}, + {0xc6b58000}, {0xc6b5a000}, {0xc6b5c000}, {0xc6b5e000}, + {0xc6b60000}, {0xc6b62000}, {0xc6b64000}, {0xc6b66000}, + {0xc6b68000}, {0xc6b6a000}, {0xc6b6c000}, {0xc6b6e000}, + {0xc6b70000}, {0xc6b72000}, {0xc6b74000}, {0xc6b76000}, + {0xc6b78000}, {0xc6b7a000}, {0xc6b7c000}, {0xc6b7e000}, + {0xc6b80000}, {0xc6b82000}, {0xc6b84000}, {0xc6b86000}, + {0xc6b88000}, {0xc6b8a000}, {0xc6b8c000}, {0xc6b8e000}, + {0xc6b90000}, {0xc6b92000}, {0xc6b94000}, {0xc6b96000}, + {0xc6b98000}, {0xc6b9a000}, {0xc6b9c000}, {0xc6b9e000}, + {0xc6ba0000}, {0xc6ba2000}, {0xc6ba4000}, {0xc6ba6000}, + {0xc6ba8000}, {0xc6baa000}, {0xc6bac000}, {0xc6bae000}, + {0xc6bb0000}, {0xc6bb2000}, {0xc6bb4000}, {0xc6bb6000}, + {0xc6bb8000}, {0xc6bba000}, {0xc6bbc000}, {0xc6bbe000}, + {0xc6bc0000}, {0xc6bc2000}, {0xc6bc4000}, {0xc6bc6000}, + {0xc6bc8000}, {0xc6bca000}, {0xc6bcc000}, {0xc6bce000}, + {0xc6bd0000}, {0xc6bd2000}, {0xc6bd4000}, {0xc6bd6000}, + {0xc6bd8000}, {0xc6bda000}, {0xc6bdc000}, {0xc6bde000}, + {0xc6be0000}, {0xc6be2000}, {0xc6be4000}, {0xc6be6000}, + {0xc6be8000}, {0xc6bea000}, {0xc6bec000}, {0xc6bee000}, + {0xc6bf0000}, {0xc6bf2000}, {0xc6bf4000}, {0xc6bf6000}, + {0xc6bf8000}, {0xc6bfa000}, {0xc6bfc000}, {0xc6bfe000}, + {0xc6c00000}, {0xc6c02000}, {0xc6c04000}, {0xc6c06000}, + {0xc6c08000}, {0xc6c0a000}, {0xc6c0c000}, {0xc6c0e000}, + {0xc6c10000}, {0xc6c12000}, {0xc6c14000}, {0xc6c16000}, + {0xc6c18000}, {0xc6c1a000}, {0xc6c1c000}, {0xc6c1e000}, + {0xc6c20000}, {0xc6c22000}, {0xc6c24000}, {0xc6c26000}, + {0xc6c28000}, {0xc6c2a000}, {0xc6c2c000}, {0xc6c2e000}, + {0xc6c30000}, {0xc6c32000}, {0xc6c34000}, {0xc6c36000}, + {0xc6c38000}, {0xc6c3a000}, {0xc6c3c000}, {0xc6c3e000}, + {0xc6c40000}, {0xc6c42000}, {0xc6c44000}, {0xc6c46000}, + {0xc6c48000}, {0xc6c4a000}, {0xc6c4c000}, {0xc6c4e000}, + {0xc6c50000}, {0xc6c52000}, {0xc6c54000}, {0xc6c56000}, + {0xc6c58000}, {0xc6c5a000}, {0xc6c5c000}, {0xc6c5e000}, + {0xc6c60000}, {0xc6c62000}, {0xc6c64000}, {0xc6c66000}, + {0xc6c68000}, {0xc6c6a000}, {0xc6c6c000}, {0xc6c6e000}, + {0xc6c70000}, {0xc6c72000}, {0xc6c74000}, {0xc6c76000}, + {0xc6c78000}, {0xc6c7a000}, {0xc6c7c000}, {0xc6c7e000}, + {0xc6c80000}, {0xc6c82000}, {0xc6c84000}, {0xc6c86000}, + {0xc6c88000}, {0xc6c8a000}, {0xc6c8c000}, {0xc6c8e000}, + {0xc6c90000}, {0xc6c92000}, {0xc6c94000}, {0xc6c96000}, + {0xc6c98000}, {0xc6c9a000}, {0xc6c9c000}, {0xc6c9e000}, + {0xc6ca0000}, {0xc6ca2000}, {0xc6ca4000}, {0xc6ca6000}, + {0xc6ca8000}, {0xc6caa000}, {0xc6cac000}, {0xc6cae000}, + {0xc6cb0000}, {0xc6cb2000}, {0xc6cb4000}, {0xc6cb6000}, + {0xc6cb8000}, {0xc6cba000}, {0xc6cbc000}, {0xc6cbe000}, + {0xc6cc0000}, {0xc6cc2000}, {0xc6cc4000}, {0xc6cc6000}, + {0xc6cc8000}, {0xc6cca000}, {0xc6ccc000}, {0xc6cce000}, + {0xc6cd0000}, {0xc6cd2000}, {0xc6cd4000}, {0xc6cd6000}, + {0xc6cd8000}, {0xc6cda000}, {0xc6cdc000}, {0xc6cde000}, + {0xc6ce0000}, {0xc6ce2000}, {0xc6ce4000}, {0xc6ce6000}, + {0xc6ce8000}, {0xc6cea000}, {0xc6cec000}, {0xc6cee000}, + {0xc6cf0000}, {0xc6cf2000}, {0xc6cf4000}, {0xc6cf6000}, + {0xc6cf8000}, {0xc6cfa000}, {0xc6cfc000}, {0xc6cfe000}, + {0xc6d00000}, {0xc6d02000}, {0xc6d04000}, {0xc6d06000}, + {0xc6d08000}, {0xc6d0a000}, {0xc6d0c000}, {0xc6d0e000}, + {0xc6d10000}, {0xc6d12000}, {0xc6d14000}, {0xc6d16000}, + {0xc6d18000}, {0xc6d1a000}, {0xc6d1c000}, {0xc6d1e000}, + {0xc6d20000}, {0xc6d22000}, {0xc6d24000}, {0xc6d26000}, + {0xc6d28000}, {0xc6d2a000}, {0xc6d2c000}, {0xc6d2e000}, + {0xc6d30000}, {0xc6d32000}, {0xc6d34000}, {0xc6d36000}, + {0xc6d38000}, {0xc6d3a000}, {0xc6d3c000}, {0xc6d3e000}, + {0xc6d40000}, {0xc6d42000}, {0xc6d44000}, {0xc6d46000}, + {0xc6d48000}, {0xc6d4a000}, {0xc6d4c000}, {0xc6d4e000}, + {0xc6d50000}, {0xc6d52000}, {0xc6d54000}, {0xc6d56000}, + {0xc6d58000}, {0xc6d5a000}, {0xc6d5c000}, {0xc6d5e000}, + {0xc6d60000}, {0xc6d62000}, {0xc6d64000}, {0xc6d66000}, + {0xc6d68000}, {0xc6d6a000}, {0xc6d6c000}, {0xc6d6e000}, + {0xc6d70000}, {0xc6d72000}, {0xc6d74000}, {0xc6d76000}, + {0xc6d78000}, {0xc6d7a000}, {0xc6d7c000}, {0xc6d7e000}, + {0xc6d80000}, {0xc6d82000}, {0xc6d84000}, {0xc6d86000}, + {0xc6d88000}, {0xc6d8a000}, {0xc6d8c000}, {0xc6d8e000}, + {0xc6d90000}, {0xc6d92000}, {0xc6d94000}, {0xc6d96000}, + {0xc6d98000}, {0xc6d9a000}, {0xc6d9c000}, {0xc6d9e000}, + {0xc6da0000}, {0xc6da2000}, {0xc6da4000}, {0xc6da6000}, + {0xc6da8000}, {0xc6daa000}, {0xc6dac000}, {0xc6dae000}, + {0xc6db0000}, {0xc6db2000}, {0xc6db4000}, {0xc6db6000}, + {0xc6db8000}, {0xc6dba000}, {0xc6dbc000}, {0xc6dbe000}, + {0xc6dc0000}, {0xc6dc2000}, {0xc6dc4000}, {0xc6dc6000}, + {0xc6dc8000}, {0xc6dca000}, {0xc6dcc000}, {0xc6dce000}, + {0xc6dd0000}, {0xc6dd2000}, {0xc6dd4000}, {0xc6dd6000}, + {0xc6dd8000}, {0xc6dda000}, {0xc6ddc000}, {0xc6dde000}, + {0xc6de0000}, {0xc6de2000}, {0xc6de4000}, {0xc6de6000}, + {0xc6de8000}, {0xc6dea000}, {0xc6dec000}, {0xc6dee000}, + {0xc6df0000}, {0xc6df2000}, {0xc6df4000}, {0xc6df6000}, + {0xc6df8000}, {0xc6dfa000}, {0xc6dfc000}, {0xc6dfe000}, + {0xc6e00000}, {0xc6e02000}, {0xc6e04000}, {0xc6e06000}, + {0xc6e08000}, {0xc6e0a000}, {0xc6e0c000}, {0xc6e0e000}, + {0xc6e10000}, {0xc6e12000}, {0xc6e14000}, {0xc6e16000}, + {0xc6e18000}, {0xc6e1a000}, {0xc6e1c000}, {0xc6e1e000}, + {0xc6e20000}, {0xc6e22000}, {0xc6e24000}, {0xc6e26000}, + {0xc6e28000}, {0xc6e2a000}, {0xc6e2c000}, {0xc6e2e000}, + {0xc6e30000}, {0xc6e32000}, {0xc6e34000}, {0xc6e36000}, + {0xc6e38000}, {0xc6e3a000}, {0xc6e3c000}, {0xc6e3e000}, + {0xc6e40000}, {0xc6e42000}, {0xc6e44000}, {0xc6e46000}, + {0xc6e48000}, {0xc6e4a000}, {0xc6e4c000}, {0xc6e4e000}, + {0xc6e50000}, {0xc6e52000}, {0xc6e54000}, {0xc6e56000}, + {0xc6e58000}, {0xc6e5a000}, {0xc6e5c000}, {0xc6e5e000}, + {0xc6e60000}, {0xc6e62000}, {0xc6e64000}, {0xc6e66000}, + {0xc6e68000}, {0xc6e6a000}, {0xc6e6c000}, {0xc6e6e000}, + {0xc6e70000}, {0xc6e72000}, {0xc6e74000}, {0xc6e76000}, + {0xc6e78000}, {0xc6e7a000}, {0xc6e7c000}, {0xc6e7e000}, + {0xc6e80000}, {0xc6e82000}, {0xc6e84000}, {0xc6e86000}, + {0xc6e88000}, {0xc6e8a000}, {0xc6e8c000}, {0xc6e8e000}, + {0xc6e90000}, {0xc6e92000}, {0xc6e94000}, {0xc6e96000}, + {0xc6e98000}, {0xc6e9a000}, {0xc6e9c000}, {0xc6e9e000}, + {0xc6ea0000}, {0xc6ea2000}, {0xc6ea4000}, {0xc6ea6000}, + {0xc6ea8000}, {0xc6eaa000}, {0xc6eac000}, {0xc6eae000}, + {0xc6eb0000}, {0xc6eb2000}, {0xc6eb4000}, {0xc6eb6000}, + {0xc6eb8000}, {0xc6eba000}, {0xc6ebc000}, {0xc6ebe000}, + {0xc6ec0000}, {0xc6ec2000}, {0xc6ec4000}, {0xc6ec6000}, + {0xc6ec8000}, {0xc6eca000}, {0xc6ecc000}, {0xc6ece000}, + {0xc6ed0000}, {0xc6ed2000}, {0xc6ed4000}, {0xc6ed6000}, + {0xc6ed8000}, {0xc6eda000}, {0xc6edc000}, {0xc6ede000}, + {0xc6ee0000}, {0xc6ee2000}, {0xc6ee4000}, {0xc6ee6000}, + {0xc6ee8000}, {0xc6eea000}, {0xc6eec000}, {0xc6eee000}, + {0xc6ef0000}, {0xc6ef2000}, {0xc6ef4000}, {0xc6ef6000}, + {0xc6ef8000}, {0xc6efa000}, {0xc6efc000}, {0xc6efe000}, + {0xc6f00000}, {0xc6f02000}, {0xc6f04000}, {0xc6f06000}, + {0xc6f08000}, {0xc6f0a000}, {0xc6f0c000}, {0xc6f0e000}, + {0xc6f10000}, {0xc6f12000}, {0xc6f14000}, {0xc6f16000}, + {0xc6f18000}, {0xc6f1a000}, {0xc6f1c000}, {0xc6f1e000}, + {0xc6f20000}, {0xc6f22000}, {0xc6f24000}, {0xc6f26000}, + {0xc6f28000}, {0xc6f2a000}, {0xc6f2c000}, {0xc6f2e000}, + {0xc6f30000}, {0xc6f32000}, {0xc6f34000}, {0xc6f36000}, + {0xc6f38000}, {0xc6f3a000}, {0xc6f3c000}, {0xc6f3e000}, + {0xc6f40000}, {0xc6f42000}, {0xc6f44000}, {0xc6f46000}, + {0xc6f48000}, {0xc6f4a000}, {0xc6f4c000}, {0xc6f4e000}, + {0xc6f50000}, {0xc6f52000}, {0xc6f54000}, {0xc6f56000}, + {0xc6f58000}, {0xc6f5a000}, {0xc6f5c000}, {0xc6f5e000}, + {0xc6f60000}, {0xc6f62000}, {0xc6f64000}, {0xc6f66000}, + {0xc6f68000}, {0xc6f6a000}, {0xc6f6c000}, {0xc6f6e000}, + {0xc6f70000}, {0xc6f72000}, {0xc6f74000}, {0xc6f76000}, + {0xc6f78000}, {0xc6f7a000}, {0xc6f7c000}, {0xc6f7e000}, + {0xc6f80000}, {0xc6f82000}, {0xc6f84000}, {0xc6f86000}, + {0xc6f88000}, {0xc6f8a000}, {0xc6f8c000}, {0xc6f8e000}, + {0xc6f90000}, {0xc6f92000}, {0xc6f94000}, {0xc6f96000}, + {0xc6f98000}, {0xc6f9a000}, {0xc6f9c000}, {0xc6f9e000}, + {0xc6fa0000}, {0xc6fa2000}, {0xc6fa4000}, {0xc6fa6000}, + {0xc6fa8000}, {0xc6faa000}, {0xc6fac000}, {0xc6fae000}, + {0xc6fb0000}, {0xc6fb2000}, {0xc6fb4000}, {0xc6fb6000}, + {0xc6fb8000}, {0xc6fba000}, {0xc6fbc000}, {0xc6fbe000}, + {0xc6fc0000}, {0xc6fc2000}, {0xc6fc4000}, {0xc6fc6000}, + {0xc6fc8000}, {0xc6fca000}, {0xc6fcc000}, {0xc6fce000}, + {0xc6fd0000}, {0xc6fd2000}, {0xc6fd4000}, {0xc6fd6000}, + {0xc6fd8000}, {0xc6fda000}, {0xc6fdc000}, {0xc6fde000}, + {0xc6fe0000}, {0xc6fe2000}, {0xc6fe4000}, {0xc6fe6000}, + {0xc6fe8000}, {0xc6fea000}, {0xc6fec000}, {0xc6fee000}, + {0xc6ff0000}, {0xc6ff2000}, {0xc6ff4000}, {0xc6ff6000}, + {0xc6ff8000}, {0xc6ffa000}, {0xc6ffc000}, {0xc6ffe000}, + {0xc7000000}, {0xc7002000}, {0xc7004000}, {0xc7006000}, + {0xc7008000}, {0xc700a000}, {0xc700c000}, {0xc700e000}, + {0xc7010000}, {0xc7012000}, {0xc7014000}, {0xc7016000}, + {0xc7018000}, {0xc701a000}, {0xc701c000}, {0xc701e000}, + {0xc7020000}, {0xc7022000}, {0xc7024000}, {0xc7026000}, + {0xc7028000}, {0xc702a000}, {0xc702c000}, {0xc702e000}, + {0xc7030000}, {0xc7032000}, {0xc7034000}, {0xc7036000}, + {0xc7038000}, {0xc703a000}, {0xc703c000}, {0xc703e000}, + {0xc7040000}, {0xc7042000}, {0xc7044000}, {0xc7046000}, + {0xc7048000}, {0xc704a000}, {0xc704c000}, {0xc704e000}, + {0xc7050000}, {0xc7052000}, {0xc7054000}, {0xc7056000}, + {0xc7058000}, {0xc705a000}, {0xc705c000}, {0xc705e000}, + {0xc7060000}, {0xc7062000}, {0xc7064000}, {0xc7066000}, + {0xc7068000}, {0xc706a000}, {0xc706c000}, {0xc706e000}, + {0xc7070000}, {0xc7072000}, {0xc7074000}, {0xc7076000}, + {0xc7078000}, {0xc707a000}, {0xc707c000}, {0xc707e000}, + {0xc7080000}, {0xc7082000}, {0xc7084000}, {0xc7086000}, + {0xc7088000}, {0xc708a000}, {0xc708c000}, {0xc708e000}, + {0xc7090000}, {0xc7092000}, {0xc7094000}, {0xc7096000}, + {0xc7098000}, {0xc709a000}, {0xc709c000}, {0xc709e000}, + {0xc70a0000}, {0xc70a2000}, {0xc70a4000}, {0xc70a6000}, + {0xc70a8000}, {0xc70aa000}, {0xc70ac000}, {0xc70ae000}, + {0xc70b0000}, {0xc70b2000}, {0xc70b4000}, {0xc70b6000}, + {0xc70b8000}, {0xc70ba000}, {0xc70bc000}, {0xc70be000}, + {0xc70c0000}, {0xc70c2000}, {0xc70c4000}, {0xc70c6000}, + {0xc70c8000}, {0xc70ca000}, {0xc70cc000}, {0xc70ce000}, + {0xc70d0000}, {0xc70d2000}, {0xc70d4000}, {0xc70d6000}, + {0xc70d8000}, {0xc70da000}, {0xc70dc000}, {0xc70de000}, + {0xc70e0000}, {0xc70e2000}, {0xc70e4000}, {0xc70e6000}, + {0xc70e8000}, {0xc70ea000}, {0xc70ec000}, {0xc70ee000}, + {0xc70f0000}, {0xc70f2000}, {0xc70f4000}, {0xc70f6000}, + {0xc70f8000}, {0xc70fa000}, {0xc70fc000}, {0xc70fe000}, + {0xc7100000}, {0xc7102000}, {0xc7104000}, {0xc7106000}, + {0xc7108000}, {0xc710a000}, {0xc710c000}, {0xc710e000}, + {0xc7110000}, {0xc7112000}, {0xc7114000}, {0xc7116000}, + {0xc7118000}, {0xc711a000}, {0xc711c000}, {0xc711e000}, + {0xc7120000}, {0xc7122000}, {0xc7124000}, {0xc7126000}, + {0xc7128000}, {0xc712a000}, {0xc712c000}, {0xc712e000}, + {0xc7130000}, {0xc7132000}, {0xc7134000}, {0xc7136000}, + {0xc7138000}, {0xc713a000}, {0xc713c000}, {0xc713e000}, + {0xc7140000}, {0xc7142000}, {0xc7144000}, {0xc7146000}, + {0xc7148000}, {0xc714a000}, {0xc714c000}, {0xc714e000}, + {0xc7150000}, {0xc7152000}, {0xc7154000}, {0xc7156000}, + {0xc7158000}, {0xc715a000}, {0xc715c000}, {0xc715e000}, + {0xc7160000}, {0xc7162000}, {0xc7164000}, {0xc7166000}, + {0xc7168000}, {0xc716a000}, {0xc716c000}, {0xc716e000}, + {0xc7170000}, {0xc7172000}, {0xc7174000}, {0xc7176000}, + {0xc7178000}, {0xc717a000}, {0xc717c000}, {0xc717e000}, + {0xc7180000}, {0xc7182000}, {0xc7184000}, {0xc7186000}, + {0xc7188000}, {0xc718a000}, {0xc718c000}, {0xc718e000}, + {0xc7190000}, {0xc7192000}, {0xc7194000}, {0xc7196000}, + {0xc7198000}, {0xc719a000}, {0xc719c000}, {0xc719e000}, + {0xc71a0000}, {0xc71a2000}, {0xc71a4000}, {0xc71a6000}, + {0xc71a8000}, {0xc71aa000}, {0xc71ac000}, {0xc71ae000}, + {0xc71b0000}, {0xc71b2000}, {0xc71b4000}, {0xc71b6000}, + {0xc71b8000}, {0xc71ba000}, {0xc71bc000}, {0xc71be000}, + {0xc71c0000}, {0xc71c2000}, {0xc71c4000}, {0xc71c6000}, + {0xc71c8000}, {0xc71ca000}, {0xc71cc000}, {0xc71ce000}, + {0xc71d0000}, {0xc71d2000}, {0xc71d4000}, {0xc71d6000}, + {0xc71d8000}, {0xc71da000}, {0xc71dc000}, {0xc71de000}, + {0xc71e0000}, {0xc71e2000}, {0xc71e4000}, {0xc71e6000}, + {0xc71e8000}, {0xc71ea000}, {0xc71ec000}, {0xc71ee000}, + {0xc71f0000}, {0xc71f2000}, {0xc71f4000}, {0xc71f6000}, + {0xc71f8000}, {0xc71fa000}, {0xc71fc000}, {0xc71fe000}, + {0xc7200000}, {0xc7202000}, {0xc7204000}, {0xc7206000}, + {0xc7208000}, {0xc720a000}, {0xc720c000}, {0xc720e000}, + {0xc7210000}, {0xc7212000}, {0xc7214000}, {0xc7216000}, + {0xc7218000}, {0xc721a000}, {0xc721c000}, {0xc721e000}, + {0xc7220000}, {0xc7222000}, {0xc7224000}, {0xc7226000}, + {0xc7228000}, {0xc722a000}, {0xc722c000}, {0xc722e000}, + {0xc7230000}, {0xc7232000}, {0xc7234000}, {0xc7236000}, + {0xc7238000}, {0xc723a000}, {0xc723c000}, {0xc723e000}, + {0xc7240000}, {0xc7242000}, {0xc7244000}, {0xc7246000}, + {0xc7248000}, {0xc724a000}, {0xc724c000}, {0xc724e000}, + {0xc7250000}, {0xc7252000}, {0xc7254000}, {0xc7256000}, + {0xc7258000}, {0xc725a000}, {0xc725c000}, {0xc725e000}, + {0xc7260000}, {0xc7262000}, {0xc7264000}, {0xc7266000}, + {0xc7268000}, {0xc726a000}, {0xc726c000}, {0xc726e000}, + {0xc7270000}, {0xc7272000}, {0xc7274000}, {0xc7276000}, + {0xc7278000}, {0xc727a000}, {0xc727c000}, {0xc727e000}, + {0xc7280000}, {0xc7282000}, {0xc7284000}, {0xc7286000}, + {0xc7288000}, {0xc728a000}, {0xc728c000}, {0xc728e000}, + {0xc7290000}, {0xc7292000}, {0xc7294000}, {0xc7296000}, + {0xc7298000}, {0xc729a000}, {0xc729c000}, {0xc729e000}, + {0xc72a0000}, {0xc72a2000}, {0xc72a4000}, {0xc72a6000}, + {0xc72a8000}, {0xc72aa000}, {0xc72ac000}, {0xc72ae000}, + {0xc72b0000}, {0xc72b2000}, {0xc72b4000}, {0xc72b6000}, + {0xc72b8000}, {0xc72ba000}, {0xc72bc000}, {0xc72be000}, + {0xc72c0000}, {0xc72c2000}, {0xc72c4000}, {0xc72c6000}, + {0xc72c8000}, {0xc72ca000}, {0xc72cc000}, {0xc72ce000}, + {0xc72d0000}, {0xc72d2000}, {0xc72d4000}, {0xc72d6000}, + {0xc72d8000}, {0xc72da000}, {0xc72dc000}, {0xc72de000}, + {0xc72e0000}, {0xc72e2000}, {0xc72e4000}, {0xc72e6000}, + {0xc72e8000}, {0xc72ea000}, {0xc72ec000}, {0xc72ee000}, + {0xc72f0000}, {0xc72f2000}, {0xc72f4000}, {0xc72f6000}, + {0xc72f8000}, {0xc72fa000}, {0xc72fc000}, {0xc72fe000}, + {0xc7300000}, {0xc7302000}, {0xc7304000}, {0xc7306000}, + {0xc7308000}, {0xc730a000}, {0xc730c000}, {0xc730e000}, + {0xc7310000}, {0xc7312000}, {0xc7314000}, {0xc7316000}, + {0xc7318000}, {0xc731a000}, {0xc731c000}, {0xc731e000}, + {0xc7320000}, {0xc7322000}, {0xc7324000}, {0xc7326000}, + {0xc7328000}, {0xc732a000}, {0xc732c000}, {0xc732e000}, + {0xc7330000}, {0xc7332000}, {0xc7334000}, {0xc7336000}, + {0xc7338000}, {0xc733a000}, {0xc733c000}, {0xc733e000}, + {0xc7340000}, {0xc7342000}, {0xc7344000}, {0xc7346000}, + {0xc7348000}, {0xc734a000}, {0xc734c000}, {0xc734e000}, + {0xc7350000}, {0xc7352000}, {0xc7354000}, {0xc7356000}, + {0xc7358000}, {0xc735a000}, {0xc735c000}, {0xc735e000}, + {0xc7360000}, {0xc7362000}, {0xc7364000}, {0xc7366000}, + {0xc7368000}, {0xc736a000}, {0xc736c000}, {0xc736e000}, + {0xc7370000}, {0xc7372000}, {0xc7374000}, {0xc7376000}, + {0xc7378000}, {0xc737a000}, {0xc737c000}, {0xc737e000}, + {0xc7380000}, {0xc7382000}, {0xc7384000}, {0xc7386000}, + {0xc7388000}, {0xc738a000}, {0xc738c000}, {0xc738e000}, + {0xc7390000}, {0xc7392000}, {0xc7394000}, {0xc7396000}, + {0xc7398000}, {0xc739a000}, {0xc739c000}, {0xc739e000}, + {0xc73a0000}, {0xc73a2000}, {0xc73a4000}, {0xc73a6000}, + {0xc73a8000}, {0xc73aa000}, {0xc73ac000}, {0xc73ae000}, + {0xc73b0000}, {0xc73b2000}, {0xc73b4000}, {0xc73b6000}, + {0xc73b8000}, {0xc73ba000}, {0xc73bc000}, {0xc73be000}, + {0xc73c0000}, {0xc73c2000}, {0xc73c4000}, {0xc73c6000}, + {0xc73c8000}, {0xc73ca000}, {0xc73cc000}, {0xc73ce000}, + {0xc73d0000}, {0xc73d2000}, {0xc73d4000}, {0xc73d6000}, + {0xc73d8000}, {0xc73da000}, {0xc73dc000}, {0xc73de000}, + {0xc73e0000}, {0xc73e2000}, {0xc73e4000}, {0xc73e6000}, + {0xc73e8000}, {0xc73ea000}, {0xc73ec000}, {0xc73ee000}, + {0xc73f0000}, {0xc73f2000}, {0xc73f4000}, {0xc73f6000}, + {0xc73f8000}, {0xc73fa000}, {0xc73fc000}, {0xc73fe000}, + {0xc7400000}, {0xc7402000}, {0xc7404000}, {0xc7406000}, + {0xc7408000}, {0xc740a000}, {0xc740c000}, {0xc740e000}, + {0xc7410000}, {0xc7412000}, {0xc7414000}, {0xc7416000}, + {0xc7418000}, {0xc741a000}, {0xc741c000}, {0xc741e000}, + {0xc7420000}, {0xc7422000}, {0xc7424000}, {0xc7426000}, + {0xc7428000}, {0xc742a000}, {0xc742c000}, {0xc742e000}, + {0xc7430000}, {0xc7432000}, {0xc7434000}, {0xc7436000}, + {0xc7438000}, {0xc743a000}, {0xc743c000}, {0xc743e000}, + {0xc7440000}, {0xc7442000}, {0xc7444000}, {0xc7446000}, + {0xc7448000}, {0xc744a000}, {0xc744c000}, {0xc744e000}, + {0xc7450000}, {0xc7452000}, {0xc7454000}, {0xc7456000}, + {0xc7458000}, {0xc745a000}, {0xc745c000}, {0xc745e000}, + {0xc7460000}, {0xc7462000}, {0xc7464000}, {0xc7466000}, + {0xc7468000}, {0xc746a000}, {0xc746c000}, {0xc746e000}, + {0xc7470000}, {0xc7472000}, {0xc7474000}, {0xc7476000}, + {0xc7478000}, {0xc747a000}, {0xc747c000}, {0xc747e000}, + {0xc7480000}, {0xc7482000}, {0xc7484000}, {0xc7486000}, + {0xc7488000}, {0xc748a000}, {0xc748c000}, {0xc748e000}, + {0xc7490000}, {0xc7492000}, {0xc7494000}, {0xc7496000}, + {0xc7498000}, {0xc749a000}, {0xc749c000}, {0xc749e000}, + {0xc74a0000}, {0xc74a2000}, {0xc74a4000}, {0xc74a6000}, + {0xc74a8000}, {0xc74aa000}, {0xc74ac000}, {0xc74ae000}, + {0xc74b0000}, {0xc74b2000}, {0xc74b4000}, {0xc74b6000}, + {0xc74b8000}, {0xc74ba000}, {0xc74bc000}, {0xc74be000}, + {0xc74c0000}, {0xc74c2000}, {0xc74c4000}, {0xc74c6000}, + {0xc74c8000}, {0xc74ca000}, {0xc74cc000}, {0xc74ce000}, + {0xc74d0000}, {0xc74d2000}, {0xc74d4000}, {0xc74d6000}, + {0xc74d8000}, {0xc74da000}, {0xc74dc000}, {0xc74de000}, + {0xc74e0000}, {0xc74e2000}, {0xc74e4000}, {0xc74e6000}, + {0xc74e8000}, {0xc74ea000}, {0xc74ec000}, {0xc74ee000}, + {0xc74f0000}, {0xc74f2000}, {0xc74f4000}, {0xc74f6000}, + {0xc74f8000}, {0xc74fa000}, {0xc74fc000}, {0xc74fe000}, + {0xc7500000}, {0xc7502000}, {0xc7504000}, {0xc7506000}, + {0xc7508000}, {0xc750a000}, {0xc750c000}, {0xc750e000}, + {0xc7510000}, {0xc7512000}, {0xc7514000}, {0xc7516000}, + {0xc7518000}, {0xc751a000}, {0xc751c000}, {0xc751e000}, + {0xc7520000}, {0xc7522000}, {0xc7524000}, {0xc7526000}, + {0xc7528000}, {0xc752a000}, {0xc752c000}, {0xc752e000}, + {0xc7530000}, {0xc7532000}, {0xc7534000}, {0xc7536000}, + {0xc7538000}, {0xc753a000}, {0xc753c000}, {0xc753e000}, + {0xc7540000}, {0xc7542000}, {0xc7544000}, {0xc7546000}, + {0xc7548000}, {0xc754a000}, {0xc754c000}, {0xc754e000}, + {0xc7550000}, {0xc7552000}, {0xc7554000}, {0xc7556000}, + {0xc7558000}, {0xc755a000}, {0xc755c000}, {0xc755e000}, + {0xc7560000}, {0xc7562000}, {0xc7564000}, {0xc7566000}, + {0xc7568000}, {0xc756a000}, {0xc756c000}, {0xc756e000}, + {0xc7570000}, {0xc7572000}, {0xc7574000}, {0xc7576000}, + {0xc7578000}, {0xc757a000}, {0xc757c000}, {0xc757e000}, + {0xc7580000}, {0xc7582000}, {0xc7584000}, {0xc7586000}, + {0xc7588000}, {0xc758a000}, {0xc758c000}, {0xc758e000}, + {0xc7590000}, {0xc7592000}, {0xc7594000}, {0xc7596000}, + {0xc7598000}, {0xc759a000}, {0xc759c000}, {0xc759e000}, + {0xc75a0000}, {0xc75a2000}, {0xc75a4000}, {0xc75a6000}, + {0xc75a8000}, {0xc75aa000}, {0xc75ac000}, {0xc75ae000}, + {0xc75b0000}, {0xc75b2000}, {0xc75b4000}, {0xc75b6000}, + {0xc75b8000}, {0xc75ba000}, {0xc75bc000}, {0xc75be000}, + {0xc75c0000}, {0xc75c2000}, {0xc75c4000}, {0xc75c6000}, + {0xc75c8000}, {0xc75ca000}, {0xc75cc000}, {0xc75ce000}, + {0xc75d0000}, {0xc75d2000}, {0xc75d4000}, {0xc75d6000}, + {0xc75d8000}, {0xc75da000}, {0xc75dc000}, {0xc75de000}, + {0xc75e0000}, {0xc75e2000}, {0xc75e4000}, {0xc75e6000}, + {0xc75e8000}, {0xc75ea000}, {0xc75ec000}, {0xc75ee000}, + {0xc75f0000}, {0xc75f2000}, {0xc75f4000}, {0xc75f6000}, + {0xc75f8000}, {0xc75fa000}, {0xc75fc000}, {0xc75fe000}, + {0xc7600000}, {0xc7602000}, {0xc7604000}, {0xc7606000}, + {0xc7608000}, {0xc760a000}, {0xc760c000}, {0xc760e000}, + {0xc7610000}, {0xc7612000}, {0xc7614000}, {0xc7616000}, + {0xc7618000}, {0xc761a000}, {0xc761c000}, {0xc761e000}, + {0xc7620000}, {0xc7622000}, {0xc7624000}, {0xc7626000}, + {0xc7628000}, {0xc762a000}, {0xc762c000}, {0xc762e000}, + {0xc7630000}, {0xc7632000}, {0xc7634000}, {0xc7636000}, + {0xc7638000}, {0xc763a000}, {0xc763c000}, {0xc763e000}, + {0xc7640000}, {0xc7642000}, {0xc7644000}, {0xc7646000}, + {0xc7648000}, {0xc764a000}, {0xc764c000}, {0xc764e000}, + {0xc7650000}, {0xc7652000}, {0xc7654000}, {0xc7656000}, + {0xc7658000}, {0xc765a000}, {0xc765c000}, {0xc765e000}, + {0xc7660000}, {0xc7662000}, {0xc7664000}, {0xc7666000}, + {0xc7668000}, {0xc766a000}, {0xc766c000}, {0xc766e000}, + {0xc7670000}, {0xc7672000}, {0xc7674000}, {0xc7676000}, + {0xc7678000}, {0xc767a000}, {0xc767c000}, {0xc767e000}, + {0xc7680000}, {0xc7682000}, {0xc7684000}, {0xc7686000}, + {0xc7688000}, {0xc768a000}, {0xc768c000}, {0xc768e000}, + {0xc7690000}, {0xc7692000}, {0xc7694000}, {0xc7696000}, + {0xc7698000}, {0xc769a000}, {0xc769c000}, {0xc769e000}, + {0xc76a0000}, {0xc76a2000}, {0xc76a4000}, {0xc76a6000}, + {0xc76a8000}, {0xc76aa000}, {0xc76ac000}, {0xc76ae000}, + {0xc76b0000}, {0xc76b2000}, {0xc76b4000}, {0xc76b6000}, + {0xc76b8000}, {0xc76ba000}, {0xc76bc000}, {0xc76be000}, + {0xc76c0000}, {0xc76c2000}, {0xc76c4000}, {0xc76c6000}, + {0xc76c8000}, {0xc76ca000}, {0xc76cc000}, {0xc76ce000}, + {0xc76d0000}, {0xc76d2000}, {0xc76d4000}, {0xc76d6000}, + {0xc76d8000}, {0xc76da000}, {0xc76dc000}, {0xc76de000}, + {0xc76e0000}, {0xc76e2000}, {0xc76e4000}, {0xc76e6000}, + {0xc76e8000}, {0xc76ea000}, {0xc76ec000}, {0xc76ee000}, + {0xc76f0000}, {0xc76f2000}, {0xc76f4000}, {0xc76f6000}, + {0xc76f8000}, {0xc76fa000}, {0xc76fc000}, {0xc76fe000}, + {0xc7700000}, {0xc7702000}, {0xc7704000}, {0xc7706000}, + {0xc7708000}, {0xc770a000}, {0xc770c000}, {0xc770e000}, + {0xc7710000}, {0xc7712000}, {0xc7714000}, {0xc7716000}, + {0xc7718000}, {0xc771a000}, {0xc771c000}, {0xc771e000}, + {0xc7720000}, {0xc7722000}, {0xc7724000}, {0xc7726000}, + {0xc7728000}, {0xc772a000}, {0xc772c000}, {0xc772e000}, + {0xc7730000}, {0xc7732000}, {0xc7734000}, {0xc7736000}, + {0xc7738000}, {0xc773a000}, {0xc773c000}, {0xc773e000}, + {0xc7740000}, {0xc7742000}, {0xc7744000}, {0xc7746000}, + {0xc7748000}, {0xc774a000}, {0xc774c000}, {0xc774e000}, + {0xc7750000}, {0xc7752000}, {0xc7754000}, {0xc7756000}, + {0xc7758000}, {0xc775a000}, {0xc775c000}, {0xc775e000}, + {0xc7760000}, {0xc7762000}, {0xc7764000}, {0xc7766000}, + {0xc7768000}, {0xc776a000}, {0xc776c000}, {0xc776e000}, + {0xc7770000}, {0xc7772000}, {0xc7774000}, {0xc7776000}, + {0xc7778000}, {0xc777a000}, {0xc777c000}, {0xc777e000}, + {0xc7780000}, {0xc7782000}, {0xc7784000}, {0xc7786000}, + {0xc7788000}, {0xc778a000}, {0xc778c000}, {0xc778e000}, + {0xc7790000}, {0xc7792000}, {0xc7794000}, {0xc7796000}, + {0xc7798000}, {0xc779a000}, {0xc779c000}, {0xc779e000}, + {0xc77a0000}, {0xc77a2000}, {0xc77a4000}, {0xc77a6000}, + {0xc77a8000}, {0xc77aa000}, {0xc77ac000}, {0xc77ae000}, + {0xc77b0000}, {0xc77b2000}, {0xc77b4000}, {0xc77b6000}, + {0xc77b8000}, {0xc77ba000}, {0xc77bc000}, {0xc77be000}, + {0xc77c0000}, {0xc77c2000}, {0xc77c4000}, {0xc77c6000}, + {0xc77c8000}, {0xc77ca000}, {0xc77cc000}, {0xc77ce000}, + {0xc77d0000}, {0xc77d2000}, {0xc77d4000}, {0xc77d6000}, + {0xc77d8000}, {0xc77da000}, {0xc77dc000}, {0xc77de000}, + {0xc77e0000}, {0xc77e2000}, {0xc77e4000}, {0xc77e6000}, + {0xc77e8000}, {0xc77ea000}, {0xc77ec000}, {0xc77ee000}, + {0xc77f0000}, {0xc77f2000}, {0xc77f4000}, {0xc77f6000}, + {0xc77f8000}, {0xc77fa000}, {0xc77fc000}, {0xc77fe000}, + {0xff800000}, {0xff802000}, {0xff804000}, {0xff806000}, + {0xff808000}, {0xff80a000}, {0xff80c000}, {0xff80e000}, + {0xff810000}, {0xff812000}, {0xff814000}, {0xff816000}, + {0xff818000}, {0xff81a000}, {0xff81c000}, {0xff81e000}, + {0xff820000}, {0xff822000}, {0xff824000}, {0xff826000}, + {0xff828000}, {0xff82a000}, {0xff82c000}, {0xff82e000}, + {0xff830000}, {0xff832000}, {0xff834000}, {0xff836000}, + {0xff838000}, {0xff83a000}, {0xff83c000}, {0xff83e000}, + {0xff840000}, {0xff842000}, {0xff844000}, {0xff846000}, + {0xff848000}, {0xff84a000}, {0xff84c000}, {0xff84e000}, + {0xff850000}, {0xff852000}, {0xff854000}, {0xff856000}, + {0xff858000}, {0xff85a000}, {0xff85c000}, {0xff85e000}, + {0xff860000}, {0xff862000}, {0xff864000}, {0xff866000}, + {0xff868000}, {0xff86a000}, {0xff86c000}, {0xff86e000}, + {0xff870000}, {0xff872000}, {0xff874000}, {0xff876000}, + {0xff878000}, {0xff87a000}, {0xff87c000}, {0xff87e000}, + {0xff880000}, {0xff882000}, {0xff884000}, {0xff886000}, + {0xff888000}, {0xff88a000}, {0xff88c000}, {0xff88e000}, + {0xff890000}, {0xff892000}, {0xff894000}, {0xff896000}, + {0xff898000}, {0xff89a000}, {0xff89c000}, {0xff89e000}, + {0xff8a0000}, {0xff8a2000}, {0xff8a4000}, {0xff8a6000}, + {0xff8a8000}, {0xff8aa000}, {0xff8ac000}, {0xff8ae000}, + {0xff8b0000}, {0xff8b2000}, {0xff8b4000}, {0xff8b6000}, + {0xff8b8000}, {0xff8ba000}, {0xff8bc000}, {0xff8be000}, + {0xff8c0000}, {0xff8c2000}, {0xff8c4000}, {0xff8c6000}, + {0xff8c8000}, {0xff8ca000}, {0xff8cc000}, {0xff8ce000}, + {0xff8d0000}, {0xff8d2000}, {0xff8d4000}, {0xff8d6000}, + {0xff8d8000}, {0xff8da000}, {0xff8dc000}, {0xff8de000}, + {0xff8e0000}, {0xff8e2000}, {0xff8e4000}, {0xff8e6000}, + {0xff8e8000}, {0xff8ea000}, {0xff8ec000}, {0xff8ee000}, + {0xff8f0000}, {0xff8f2000}, {0xff8f4000}, {0xff8f6000}, + {0xff8f8000}, {0xff8fa000}, {0xff8fc000}, {0xff8fe000}, + {0xff900000}, {0xff902000}, {0xff904000}, {0xff906000}, + {0xff908000}, {0xff90a000}, {0xff90c000}, {0xff90e000}, + {0xff910000}, {0xff912000}, {0xff914000}, {0xff916000}, + {0xff918000}, {0xff91a000}, {0xff91c000}, {0xff91e000}, + {0xff920000}, {0xff922000}, {0xff924000}, {0xff926000}, + {0xff928000}, {0xff92a000}, {0xff92c000}, {0xff92e000}, + {0xff930000}, {0xff932000}, {0xff934000}, {0xff936000}, + {0xff938000}, {0xff93a000}, {0xff93c000}, {0xff93e000}, + {0xff940000}, {0xff942000}, {0xff944000}, {0xff946000}, + {0xff948000}, {0xff94a000}, {0xff94c000}, {0xff94e000}, + {0xff950000}, {0xff952000}, {0xff954000}, {0xff956000}, + {0xff958000}, {0xff95a000}, {0xff95c000}, {0xff95e000}, + {0xff960000}, {0xff962000}, {0xff964000}, {0xff966000}, + {0xff968000}, {0xff96a000}, {0xff96c000}, {0xff96e000}, + {0xff970000}, {0xff972000}, {0xff974000}, {0xff976000}, + {0xff978000}, {0xff97a000}, {0xff97c000}, {0xff97e000}, + {0xff980000}, {0xff982000}, {0xff984000}, {0xff986000}, + {0xff988000}, {0xff98a000}, {0xff98c000}, {0xff98e000}, + {0xff990000}, {0xff992000}, {0xff994000}, {0xff996000}, + {0xff998000}, {0xff99a000}, {0xff99c000}, {0xff99e000}, + {0xff9a0000}, {0xff9a2000}, {0xff9a4000}, {0xff9a6000}, + {0xff9a8000}, {0xff9aa000}, {0xff9ac000}, {0xff9ae000}, + {0xff9b0000}, {0xff9b2000}, {0xff9b4000}, {0xff9b6000}, + {0xff9b8000}, {0xff9ba000}, {0xff9bc000}, {0xff9be000}, + {0xff9c0000}, {0xff9c2000}, {0xff9c4000}, {0xff9c6000}, + {0xff9c8000}, {0xff9ca000}, {0xff9cc000}, {0xff9ce000}, + {0xff9d0000}, {0xff9d2000}, {0xff9d4000}, {0xff9d6000}, + {0xff9d8000}, {0xff9da000}, {0xff9dc000}, {0xff9de000}, + {0xff9e0000}, {0xff9e2000}, {0xff9e4000}, {0xff9e6000}, + {0xff9e8000}, {0xff9ea000}, {0xff9ec000}, {0xff9ee000}, + {0xff9f0000}, {0xff9f2000}, {0xff9f4000}, {0xff9f6000}, + {0xff9f8000}, {0xff9fa000}, {0xff9fc000}, {0xff9fe000}, + {0xffa00000}, {0xffa02000}, {0xffa04000}, {0xffa06000}, + {0xffa08000}, {0xffa0a000}, {0xffa0c000}, {0xffa0e000}, + {0xffa10000}, {0xffa12000}, {0xffa14000}, {0xffa16000}, + {0xffa18000}, {0xffa1a000}, {0xffa1c000}, {0xffa1e000}, + {0xffa20000}, {0xffa22000}, {0xffa24000}, {0xffa26000}, + {0xffa28000}, {0xffa2a000}, {0xffa2c000}, {0xffa2e000}, + {0xffa30000}, {0xffa32000}, {0xffa34000}, {0xffa36000}, + {0xffa38000}, {0xffa3a000}, {0xffa3c000}, {0xffa3e000}, + {0xffa40000}, {0xffa42000}, {0xffa44000}, {0xffa46000}, + {0xffa48000}, {0xffa4a000}, {0xffa4c000}, {0xffa4e000}, + {0xffa50000}, {0xffa52000}, {0xffa54000}, {0xffa56000}, + {0xffa58000}, {0xffa5a000}, {0xffa5c000}, {0xffa5e000}, + {0xffa60000}, {0xffa62000}, {0xffa64000}, {0xffa66000}, + {0xffa68000}, {0xffa6a000}, {0xffa6c000}, {0xffa6e000}, + {0xffa70000}, {0xffa72000}, {0xffa74000}, {0xffa76000}, + {0xffa78000}, {0xffa7a000}, {0xffa7c000}, {0xffa7e000}, + {0xffa80000}, {0xffa82000}, {0xffa84000}, {0xffa86000}, + {0xffa88000}, {0xffa8a000}, {0xffa8c000}, {0xffa8e000}, + {0xffa90000}, {0xffa92000}, {0xffa94000}, {0xffa96000}, + {0xffa98000}, {0xffa9a000}, {0xffa9c000}, {0xffa9e000}, + {0xffaa0000}, {0xffaa2000}, {0xffaa4000}, {0xffaa6000}, + {0xffaa8000}, {0xffaaa000}, {0xffaac000}, {0xffaae000}, + {0xffab0000}, {0xffab2000}, {0xffab4000}, {0xffab6000}, + {0xffab8000}, {0xffaba000}, {0xffabc000}, {0xffabe000}, + {0xffac0000}, {0xffac2000}, {0xffac4000}, {0xffac6000}, + {0xffac8000}, {0xffaca000}, {0xffacc000}, {0xfface000}, + {0xffad0000}, {0xffad2000}, {0xffad4000}, {0xffad6000}, + {0xffad8000}, {0xffada000}, {0xffadc000}, {0xffade000}, + {0xffae0000}, {0xffae2000}, {0xffae4000}, {0xffae6000}, + {0xffae8000}, {0xffaea000}, {0xffaec000}, {0xffaee000}, + {0xffaf0000}, {0xffaf2000}, {0xffaf4000}, {0xffaf6000}, + {0xffaf8000}, {0xffafa000}, {0xffafc000}, {0xffafe000}, + {0xffb00000}, {0xffb02000}, {0xffb04000}, {0xffb06000}, + {0xffb08000}, {0xffb0a000}, {0xffb0c000}, {0xffb0e000}, + {0xffb10000}, {0xffb12000}, {0xffb14000}, {0xffb16000}, + {0xffb18000}, {0xffb1a000}, {0xffb1c000}, {0xffb1e000}, + {0xffb20000}, {0xffb22000}, {0xffb24000}, {0xffb26000}, + {0xffb28000}, {0xffb2a000}, {0xffb2c000}, {0xffb2e000}, + {0xffb30000}, {0xffb32000}, {0xffb34000}, {0xffb36000}, + {0xffb38000}, {0xffb3a000}, {0xffb3c000}, {0xffb3e000}, + {0xffb40000}, {0xffb42000}, {0xffb44000}, {0xffb46000}, + {0xffb48000}, {0xffb4a000}, {0xffb4c000}, {0xffb4e000}, + {0xffb50000}, {0xffb52000}, {0xffb54000}, {0xffb56000}, + {0xffb58000}, {0xffb5a000}, {0xffb5c000}, {0xffb5e000}, + {0xffb60000}, {0xffb62000}, {0xffb64000}, {0xffb66000}, + {0xffb68000}, {0xffb6a000}, {0xffb6c000}, {0xffb6e000}, + {0xffb70000}, {0xffb72000}, {0xffb74000}, {0xffb76000}, + {0xffb78000}, {0xffb7a000}, {0xffb7c000}, {0xffb7e000}, + {0xffb80000}, {0xffb82000}, {0xffb84000}, {0xffb86000}, + {0xffb88000}, {0xffb8a000}, {0xffb8c000}, {0xffb8e000}, + {0xffb90000}, {0xffb92000}, {0xffb94000}, {0xffb96000}, + {0xffb98000}, {0xffb9a000}, {0xffb9c000}, {0xffb9e000}, + {0xffba0000}, {0xffba2000}, {0xffba4000}, {0xffba6000}, + {0xffba8000}, {0xffbaa000}, {0xffbac000}, {0xffbae000}, + {0xffbb0000}, {0xffbb2000}, {0xffbb4000}, {0xffbb6000}, + {0xffbb8000}, {0xffbba000}, {0xffbbc000}, {0xffbbe000}, + {0xffbc0000}, {0xffbc2000}, {0xffbc4000}, {0xffbc6000}, + {0xffbc8000}, {0xffbca000}, {0xffbcc000}, {0xffbce000}, + {0xffbd0000}, {0xffbd2000}, {0xffbd4000}, {0xffbd6000}, + {0xffbd8000}, {0xffbda000}, {0xffbdc000}, {0xffbde000}, + {0xffbe0000}, {0xffbe2000}, {0xffbe4000}, {0xffbe6000}, + {0xffbe8000}, {0xffbea000}, {0xffbec000}, {0xffbee000}, + {0xffbf0000}, {0xffbf2000}, {0xffbf4000}, {0xffbf6000}, + {0xffbf8000}, {0xffbfa000}, {0xffbfc000}, {0xffbfe000}, + {0xffc00000}, {0xffc02000}, {0xffc04000}, {0xffc06000}, + {0xffc08000}, {0xffc0a000}, {0xffc0c000}, {0xffc0e000}, + {0xffc10000}, {0xffc12000}, {0xffc14000}, {0xffc16000}, + {0xffc18000}, {0xffc1a000}, {0xffc1c000}, {0xffc1e000}, + {0xffc20000}, {0xffc22000}, {0xffc24000}, {0xffc26000}, + {0xffc28000}, {0xffc2a000}, {0xffc2c000}, {0xffc2e000}, + {0xffc30000}, {0xffc32000}, {0xffc34000}, {0xffc36000}, + {0xffc38000}, {0xffc3a000}, {0xffc3c000}, {0xffc3e000}, + {0xffc40000}, {0xffc42000}, {0xffc44000}, {0xffc46000}, + {0xffc48000}, {0xffc4a000}, {0xffc4c000}, {0xffc4e000}, + {0xffc50000}, {0xffc52000}, {0xffc54000}, {0xffc56000}, + {0xffc58000}, {0xffc5a000}, {0xffc5c000}, {0xffc5e000}, + {0xffc60000}, {0xffc62000}, {0xffc64000}, {0xffc66000}, + {0xffc68000}, {0xffc6a000}, {0xffc6c000}, {0xffc6e000}, + {0xffc70000}, {0xffc72000}, {0xffc74000}, {0xffc76000}, + {0xffc78000}, {0xffc7a000}, {0xffc7c000}, {0xffc7e000}, + {0xffc80000}, {0xffc82000}, {0xffc84000}, {0xffc86000}, + {0xffc88000}, {0xffc8a000}, {0xffc8c000}, {0xffc8e000}, + {0xffc90000}, {0xffc92000}, {0xffc94000}, {0xffc96000}, + {0xffc98000}, {0xffc9a000}, {0xffc9c000}, {0xffc9e000}, + {0xffca0000}, {0xffca2000}, {0xffca4000}, {0xffca6000}, + {0xffca8000}, {0xffcaa000}, {0xffcac000}, {0xffcae000}, + {0xffcb0000}, {0xffcb2000}, {0xffcb4000}, {0xffcb6000}, + {0xffcb8000}, {0xffcba000}, {0xffcbc000}, {0xffcbe000}, + {0xffcc0000}, {0xffcc2000}, {0xffcc4000}, {0xffcc6000}, + {0xffcc8000}, {0xffcca000}, {0xffccc000}, {0xffcce000}, + {0xffcd0000}, {0xffcd2000}, {0xffcd4000}, {0xffcd6000}, + {0xffcd8000}, {0xffcda000}, {0xffcdc000}, {0xffcde000}, + {0xffce0000}, {0xffce2000}, {0xffce4000}, {0xffce6000}, + {0xffce8000}, {0xffcea000}, {0xffcec000}, {0xffcee000}, + {0xffcf0000}, {0xffcf2000}, {0xffcf4000}, {0xffcf6000}, + {0xffcf8000}, {0xffcfa000}, {0xffcfc000}, {0xffcfe000}, + {0xffd00000}, {0xffd02000}, {0xffd04000}, {0xffd06000}, + {0xffd08000}, {0xffd0a000}, {0xffd0c000}, {0xffd0e000}, + {0xffd10000}, {0xffd12000}, {0xffd14000}, {0xffd16000}, + {0xffd18000}, {0xffd1a000}, {0xffd1c000}, {0xffd1e000}, + {0xffd20000}, {0xffd22000}, {0xffd24000}, {0xffd26000}, + {0xffd28000}, {0xffd2a000}, {0xffd2c000}, {0xffd2e000}, + {0xffd30000}, {0xffd32000}, {0xffd34000}, {0xffd36000}, + {0xffd38000}, {0xffd3a000}, {0xffd3c000}, {0xffd3e000}, + {0xffd40000}, {0xffd42000}, {0xffd44000}, {0xffd46000}, + {0xffd48000}, {0xffd4a000}, {0xffd4c000}, {0xffd4e000}, + {0xffd50000}, {0xffd52000}, {0xffd54000}, {0xffd56000}, + {0xffd58000}, {0xffd5a000}, {0xffd5c000}, {0xffd5e000}, + {0xffd60000}, {0xffd62000}, {0xffd64000}, {0xffd66000}, + {0xffd68000}, {0xffd6a000}, {0xffd6c000}, {0xffd6e000}, + {0xffd70000}, {0xffd72000}, {0xffd74000}, {0xffd76000}, + {0xffd78000}, {0xffd7a000}, {0xffd7c000}, {0xffd7e000}, + {0xffd80000}, {0xffd82000}, {0xffd84000}, {0xffd86000}, + {0xffd88000}, {0xffd8a000}, {0xffd8c000}, {0xffd8e000}, + {0xffd90000}, {0xffd92000}, {0xffd94000}, {0xffd96000}, + {0xffd98000}, {0xffd9a000}, {0xffd9c000}, {0xffd9e000}, + {0xffda0000}, {0xffda2000}, {0xffda4000}, {0xffda6000}, + {0xffda8000}, {0xffdaa000}, {0xffdac000}, {0xffdae000}, + {0xffdb0000}, {0xffdb2000}, {0xffdb4000}, {0xffdb6000}, + {0xffdb8000}, {0xffdba000}, {0xffdbc000}, {0xffdbe000}, + {0xffdc0000}, {0xffdc2000}, {0xffdc4000}, {0xffdc6000}, + {0xffdc8000}, {0xffdca000}, {0xffdcc000}, {0xffdce000}, + {0xffdd0000}, {0xffdd2000}, {0xffdd4000}, {0xffdd6000}, + {0xffdd8000}, {0xffdda000}, {0xffddc000}, {0xffdde000}, + {0xffde0000}, {0xffde2000}, {0xffde4000}, {0xffde6000}, + {0xffde8000}, {0xffdea000}, {0xffdec000}, {0xffdee000}, + {0xffdf0000}, {0xffdf2000}, {0xffdf4000}, {0xffdf6000}, + {0xffdf8000}, {0xffdfa000}, {0xffdfc000}, {0xffdfe000}, + {0xffe00000}, {0xffe02000}, {0xffe04000}, {0xffe06000}, + {0xffe08000}, {0xffe0a000}, {0xffe0c000}, {0xffe0e000}, + {0xffe10000}, {0xffe12000}, {0xffe14000}, {0xffe16000}, + {0xffe18000}, {0xffe1a000}, {0xffe1c000}, {0xffe1e000}, + {0xffe20000}, {0xffe22000}, {0xffe24000}, {0xffe26000}, + {0xffe28000}, {0xffe2a000}, {0xffe2c000}, {0xffe2e000}, + {0xffe30000}, {0xffe32000}, {0xffe34000}, {0xffe36000}, + {0xffe38000}, {0xffe3a000}, {0xffe3c000}, {0xffe3e000}, + {0xffe40000}, {0xffe42000}, {0xffe44000}, {0xffe46000}, + {0xffe48000}, {0xffe4a000}, {0xffe4c000}, {0xffe4e000}, + {0xffe50000}, {0xffe52000}, {0xffe54000}, {0xffe56000}, + {0xffe58000}, {0xffe5a000}, {0xffe5c000}, {0xffe5e000}, + {0xffe60000}, {0xffe62000}, {0xffe64000}, {0xffe66000}, + {0xffe68000}, {0xffe6a000}, {0xffe6c000}, {0xffe6e000}, + {0xffe70000}, {0xffe72000}, {0xffe74000}, {0xffe76000}, + {0xffe78000}, {0xffe7a000}, {0xffe7c000}, {0xffe7e000}, + {0xffe80000}, {0xffe82000}, {0xffe84000}, {0xffe86000}, + {0xffe88000}, {0xffe8a000}, {0xffe8c000}, {0xffe8e000}, + {0xffe90000}, {0xffe92000}, {0xffe94000}, {0xffe96000}, + {0xffe98000}, {0xffe9a000}, {0xffe9c000}, {0xffe9e000}, + {0xffea0000}, {0xffea2000}, {0xffea4000}, {0xffea6000}, + {0xffea8000}, {0xffeaa000}, {0xffeac000}, {0xffeae000}, + {0xffeb0000}, {0xffeb2000}, {0xffeb4000}, {0xffeb6000}, + {0xffeb8000}, {0xffeba000}, {0xffebc000}, {0xffebe000}, + {0xffec0000}, {0xffec2000}, {0xffec4000}, {0xffec6000}, + {0xffec8000}, {0xffeca000}, {0xffecc000}, {0xffece000}, + {0xffed0000}, {0xffed2000}, {0xffed4000}, {0xffed6000}, + {0xffed8000}, {0xffeda000}, {0xffedc000}, {0xffede000}, + {0xffee0000}, {0xffee2000}, {0xffee4000}, {0xffee6000}, + {0xffee8000}, {0xffeea000}, {0xffeec000}, {0xffeee000}, + {0xffef0000}, {0xffef2000}, {0xffef4000}, {0xffef6000}, + {0xffef8000}, {0xffefa000}, {0xffefc000}, {0xffefe000}, + {0xfff00000}, {0xfff02000}, {0xfff04000}, {0xfff06000}, + {0xfff08000}, {0xfff0a000}, {0xfff0c000}, {0xfff0e000}, + {0xfff10000}, {0xfff12000}, {0xfff14000}, {0xfff16000}, + {0xfff18000}, {0xfff1a000}, {0xfff1c000}, {0xfff1e000}, + {0xfff20000}, {0xfff22000}, {0xfff24000}, {0xfff26000}, + {0xfff28000}, {0xfff2a000}, {0xfff2c000}, {0xfff2e000}, + {0xfff30000}, {0xfff32000}, {0xfff34000}, {0xfff36000}, + {0xfff38000}, {0xfff3a000}, {0xfff3c000}, {0xfff3e000}, + {0xfff40000}, {0xfff42000}, {0xfff44000}, {0xfff46000}, + {0xfff48000}, {0xfff4a000}, {0xfff4c000}, {0xfff4e000}, + {0xfff50000}, {0xfff52000}, {0xfff54000}, {0xfff56000}, + {0xfff58000}, {0xfff5a000}, {0xfff5c000}, {0xfff5e000}, + {0xfff60000}, {0xfff62000}, {0xfff64000}, {0xfff66000}, + {0xfff68000}, {0xfff6a000}, {0xfff6c000}, {0xfff6e000}, + {0xfff70000}, {0xfff72000}, {0xfff74000}, {0xfff76000}, + {0xfff78000}, {0xfff7a000}, {0xfff7c000}, {0xfff7e000}, + {0xfff80000}, {0xfff82000}, {0xfff84000}, {0xfff86000}, + {0xfff88000}, {0xfff8a000}, {0xfff8c000}, {0xfff8e000}, + {0xfff90000}, {0xfff92000}, {0xfff94000}, {0xfff96000}, + {0xfff98000}, {0xfff9a000}, {0xfff9c000}, {0xfff9e000}, + {0xfffa0000}, {0xfffa2000}, {0xfffa4000}, {0xfffa6000}, + {0xfffa8000}, {0xfffaa000}, {0xfffac000}, {0xfffae000}, + {0xfffb0000}, {0xfffb2000}, {0xfffb4000}, {0xfffb6000}, + {0xfffb8000}, {0xfffba000}, {0xfffbc000}, {0xfffbe000}, + {0xfffc0000}, {0xfffc2000}, {0xfffc4000}, {0xfffc6000}, + {0xfffc8000}, {0xfffca000}, {0xfffcc000}, {0xfffce000}, + {0xfffd0000}, {0xfffd2000}, {0xfffd4000}, {0xfffd6000}, + {0xfffd8000}, {0xfffda000}, {0xfffdc000}, {0xfffde000}, + {0xfffe0000}, {0xfffe2000}, {0xfffe4000}, {0xfffe6000}, + {0xfffe8000}, {0xfffea000}, {0xfffec000}, {0xfffee000}, + {0xffff0000}, {0xffff2000}, {0xffff4000}, {0xffff6000}, + {0xffff8000}, {0xffffa000}, {0xffffc000}, {0xffffe000}, +}; diff --git a/Baikal/Utils/version.h b/Baikal/Utils/version.h new file mode 100644 index 00000000..a2ab2498 --- /dev/null +++ b/Baikal/Utils/version.h @@ -0,0 +1,24 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once + +#define BAIKAL_VERSION "0_5_0" diff --git a/Baikal/imgui.ini b/Baikal/imgui.ini index 1e8213fb..f33fdfa4 100644 --- a/Baikal/imgui.ini +++ b/Baikal/imgui.ini @@ -4,7 +4,7 @@ Size=200,150 Collapsed=0 [Baikal settings] -Pos=18,7 -Size=320,350 +Pos=133,-66 +Size=380,580 Collapsed=0 diff --git a/Baikal/main.cpp b/Baikal/main.cpp deleted file mode 100644 index 44ec1647..00000000 --- a/Baikal/main.cpp +++ /dev/null @@ -1,1153 +0,0 @@ -/********************************************************************** -Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. - -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 "OpenImageIO/imageio.h" - -#ifdef __APPLE__ -#include -#define GLFW_INCLUDE_GLCOREARB -#define GLFW_NO_GLU -#include "GLFW/glfw3.h" -#elif WIN32 -#define NOMINMAX -#include -#include "GL/glew.h" -#include "GLFW/glfw3.h" -#else -#include -#include -#include -#include "GLFW/glfw3.h" -#endif - -#include "ImGUI/imgui.h" -#include "ImGUI/imgui_impl_glfw_gl3.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define _USE_MATH_DEFINES -#include - -#ifdef RR_EMBED_KERNELS -#include "./CL/cache/kernels.h" -#endif - -#include "CLW.h" - -#include "math/mathutils.h" - -#include "Utils/tiny_obj_loader.h" -#include "SceneGraph/camera.h" -#include "Utils/shader_manager.h" -#include "SceneGraph/scene1.h" -#include "Renderers/PT/ptrenderer.h" -#include "Renderers/BDPT/bdptrenderer.h" -#include "CLW/clwoutput.h" -#include "Utils/config_manager.h" -#include "SceneGraph/scene1.h" -#include "SceneGraph/IO/scene_io.h" -#include "SceneGraph/IO/material_io.h" - -#ifdef ENABLE_DENOISER -#include "PostEffects/bilateral_denoiser.h" -#endif - -Baikal::Scene1 scene; - -using namespace RadeonRays; - -// Help message -char const* kHelpMessage = -"Baikal [-p path_to_models][-f model_name][-b][-r][-ns number_of_shadow_rays][-ao ao_radius][-w window_width][-h window_height][-nb number_of_indirect_bounces]"; -char const* g_path = -"../Resources/CornellBox"; -char const* g_modelname = "orig.objm"; -char const* g_envmapname = "../Resources/Textures/studio015.hdr"; - -std::unique_ptr g_shader_manager; -std::unique_ptr g_camera; - -GLuint g_vertex_buffer; -GLuint g_index_buffer; -GLuint g_texture; -GLuint g_vao; - -int g_window_width = 512; -int g_window_height = 512; -int g_num_shadow_rays = 1; -int g_num_ao_rays = 1; -int g_ao_enabled = false; -int g_progressive = false; -int g_num_bounces = 5; -int g_num_samples = -1; -int g_samplecount = 0; -float g_ao_radius = 1.f; -float g_envmapmul = 1.f; -float g_cspeed = 10.25f; - -float3 g_camera_pos = float3(0.f, 1.f, 3.f); -float3 g_camera_at = float3(0.f, 1.f, 0.f); -float3 g_camera_up = float3(0.f, 1.f, 0.f); - -float2 g_camera_sensor_size = float2(0.036f, 0.024f); // default full frame sensor 36x24 mm -float2 g_camera_zcap = float2(0.0f, 100000.f); -float g_camera_focal_length = 0.035f; // 35mm lens -float g_camera_focus_distance = 1.f; -float g_camera_aperture = 0.f; - -bool g_recording_enabled = false; -int g_frame_count = 0; -bool g_benchmark = false; -bool g_interop = true; -bool g_gui_visible = true; -ConfigManager::Mode g_mode = ConfigManager::Mode::kUseSingleGpu; -Baikal::Renderer::OutputType g_ouput_type = Baikal::Renderer::OutputType::kColor; - -using namespace tinyobj; - -#define CHECK_GL_ERROR assert(glGetError() == 0) - - -struct OutputData -{ - Baikal::ClwOutput* output; - -#ifdef ENABLE_DENOISER - Baikal::ClwOutput* output_position; - Baikal::ClwOutput* output_normal; - Baikal::ClwOutput* output_albedo; - Baikal::ClwOutput* output_denoised; - Baikal::BilateralDenoiser* denoiser; -#endif - - std::vector fdata; - std::vector udata; - CLWBuffer copybuffer; -}; - -struct ControlData -{ - std::atomic clear; - std::atomic stop; - std::atomic newdata; - std::mutex datamutex; - int idx; -}; - -std::vector g_cfgs; -std::vector g_outputs; -std::unique_ptr g_ctrl; -std::vector g_renderthreads; -int g_primary = -1; - - -std::unique_ptr g_scene; - -static bool g_is_left_pressed = false; -static bool g_is_right_pressed = false; -static bool g_is_fwd_pressed = false; -static bool g_is_back_pressed = false; -static bool g_is_home_pressed = false; -static bool g_is_end_pressed = false; -static bool g_is_mouse_tracking = false; -static float2 g_mouse_pos = float2(0, 0); -static float2 g_mouse_delta = float2(0, 0); - - -// CLW stuff -CLWImage2D g_cl_interop_image; - -char* GetCmdOption(char ** begin, char ** end, const std::string & option); -bool CmdOptionExists(char** begin, char** end, const std::string& option); -void ShowHelpAndDie(); -void SaveFrameBuffer(std::string const& name, float3 const* data); - -void Render(GLFWwindow* window) -{ - try - { - { - int w, h; - glfwGetFramebufferSize(window, &w, &h); CHECK_GL_ERROR; - glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR; - glViewport(0, 0, w, h); CHECK_GL_ERROR; - - - glClear(GL_COLOR_BUFFER_BIT); CHECK_GL_ERROR; - glBindVertexArray(g_vao); CHECK_GL_ERROR; - - GLuint program = g_shader_manager->GetProgram("../Baikal/GLSL/simple"); - glUseProgram(program); CHECK_GL_ERROR; - - GLuint texloc = glGetUniformLocation(program, "g_Texture"); - assert(texloc >= 0); - - glUniform1i(texloc, 0); CHECK_GL_ERROR; - - glActiveTexture(GL_TEXTURE0); CHECK_GL_ERROR; - glBindTexture(GL_TEXTURE_2D, g_texture); CHECK_GL_ERROR; - - - glEnableVertexAttribArray(0); CHECK_GL_ERROR; - glEnableVertexAttribArray(1); CHECK_GL_ERROR; - - glBindBuffer(GL_ARRAY_BUFFER, g_vertex_buffer); CHECK_GL_ERROR; - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_index_buffer); CHECK_GL_ERROR; - - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0); CHECK_GL_ERROR; - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (void*)(sizeof(float) * 3)); CHECK_GL_ERROR; - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr); - - glDisableVertexAttribArray(0); CHECK_GL_ERROR; - glDisableVertexAttribArray(1); CHECK_GL_ERROR; - glBindTexture(GL_TEXTURE_2D, 0); CHECK_GL_ERROR; - glBindBuffer(GL_ARRAY_BUFFER, 0); CHECK_GL_ERROR; - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); CHECK_GL_ERROR; - glUseProgram(0); CHECK_GL_ERROR; - glBindVertexArray(0); - - glFinish(); CHECK_GL_ERROR; - } - } - catch (std::runtime_error& e) - { - std::cout << e.what(); - exit(-1); - } -} - -void InitGraphics() -{ - g_shader_manager.reset(new ShaderManager()); - - glGetError(); - glClearColor(0.0, 0.5, 0.0, 0.0); CHECK_GL_ERROR; - glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR; - - glGenBuffers(1, &g_vertex_buffer); CHECK_GL_ERROR; - glGenBuffers(1, &g_index_buffer); CHECK_GL_ERROR; - - glGenVertexArrays(1, &g_vao); CHECK_GL_ERROR; - - // create Vertex buffer - glBindBuffer(GL_ARRAY_BUFFER, g_vertex_buffer); CHECK_GL_ERROR; - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_index_buffer); CHECK_GL_ERROR; - - float quad_vdata[] = - { - -1, -1, 0.5, 0, 0, - 1, -1, 0.5, 1, 0, - 1, 1, 0.5, 1, 1, - -1, 1, 0.5, 0, 1 - }; - - GLshort quad_idata[] = - { - 0, 1, 3, - 3, 1, 2 - }; - - // fill data - glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vdata), quad_vdata, GL_STATIC_DRAW); CHECK_GL_ERROR; - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quad_idata), quad_idata, GL_STATIC_DRAW); CHECK_GL_ERROR; - - glBindBuffer(GL_ARRAY_BUFFER, 0); CHECK_GL_ERROR; - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); CHECK_GL_ERROR; - - - glGenTextures(1, &g_texture); CHECK_GL_ERROR; - glBindTexture(GL_TEXTURE_2D, g_texture); CHECK_GL_ERROR; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); CHECK_GL_ERROR; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); CHECK_GL_ERROR; - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, g_window_width, g_window_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); CHECK_GL_ERROR; - - glBindTexture(GL_TEXTURE_2D, 0); CHECK_GL_ERROR; -} - -void InitCl() -{ - bool force_disable_itnerop = false; - - try - { - ConfigManager::CreateConfigs(g_mode, g_interop, g_cfgs, g_num_bounces); - } - catch (CLWException &) - { - force_disable_itnerop = true; - ConfigManager::CreateConfigs(g_mode, false, g_cfgs, g_num_bounces); - } - - - std::cout << "Running on devices: \n"; - - for (int i = 0; i < g_cfgs.size(); ++i) - { - std::cout << i << ": " << g_cfgs[i].context.GetDevice(g_cfgs[i].devidx).GetName() << "\n"; - } - - g_interop = false; - - g_outputs.resize(g_cfgs.size()); - g_ctrl.reset(new ControlData[g_cfgs.size()]); - - for (int i = 0; i < g_cfgs.size(); ++i) - { - if (g_cfgs[i].type == ConfigManager::kPrimary) - { - g_primary = i; - - if (g_cfgs[i].caninterop) - { - g_cl_interop_image = g_cfgs[i].context.CreateImage2DFromGLTexture(g_texture); - g_interop = true; - } - } - - g_ctrl[i].clear.store(1); - g_ctrl[i].stop.store(0); - g_ctrl[i].newdata.store(0); - g_ctrl[i].idx = i; - } - - if (force_disable_itnerop) - { - std::cout << "OpenGL interop is not supported, disabled, -interop flag is ignored\n"; - } - else - { - if (g_interop) - { - std::cout << "OpenGL interop mode enabled\n"; - } - else - { - std::cout << "OpenGL interop mode disabled\n"; - } - } -} - -void InitData() -{ - - rand_init(); - - // Load obj file - std::string basepath = g_path; - basepath += "/"; - std::string filename = basepath + g_modelname; - - { - // Load OBJ scene - std::unique_ptr scene_io(Baikal::SceneIo::CreateSceneIoObj()); - g_scene.reset(scene_io->LoadScene(filename, basepath)); - - // Enable this to generate new materal mapping for a model -#if 0 - std::unique_ptr material_io(Baikal::MaterialIo::CreateMaterialIoXML()); - material_io->SaveMaterialsFromScene(basepath + "materials.xml", *g_scene); - material_io->SaveIdentityMapping(basepath + "mapping.xml", *g_scene); -#endif - - // Check it we have material remapping - std::ifstream in_materials(basepath + "materials.xml"); - std::ifstream in_mapping(basepath + "mapping.xml"); - - if (in_materials && in_mapping) - { - in_materials.close(); - in_mapping.close(); - - std::unique_ptr material_io(Baikal::MaterialIo::CreateMaterialIoXML()); - - auto mats = material_io->LoadMaterials(basepath + "materials.xml"); - auto mapping = material_io->LoadMaterialMapping(basepath + "mapping.xml"); - - material_io->ReplaceSceneMaterials(*g_scene, *mats, mapping); - } - } - - g_camera.reset(new Baikal::PerspectiveCamera( - g_camera_pos - , g_camera_at - , g_camera_up)); - - g_scene->SetCamera(g_camera.get()); - - // Adjust sensor size based on current aspect ratio - float aspect = (float)g_window_width / g_window_height; - g_camera_sensor_size.y = g_camera_sensor_size.x / aspect; - - g_camera->SetSensorSize(g_camera_sensor_size); - g_camera->SetDepthRange(g_camera_zcap); - g_camera->SetFocalLength(g_camera_focal_length); - g_camera->SetFocusDistance(g_camera_focus_distance); - g_camera->SetAperture(g_camera_aperture); - - std::cout << "Camera type: " << (g_camera->GetAperture() > 0.f ? "Physical" : "Pinhole") << "\n"; - std::cout << "Lens focal length: " << g_camera->GetFocalLength() * 1000.f << "mm\n"; - std::cout << "Lens focus distance: " << g_camera->GetFocusDistance() << "m\n"; - std::cout << "F-Stop: " << 1.f / (g_camera->GetAperture() * 10.f) << "\n"; - std::cout << "Sensor size: " << g_camera_sensor_size.x * 1000.f << "x" << g_camera_sensor_size.y * 1000.f << "mm\n"; - - -#pragma omp parallel for - for (int i = 0; i < g_cfgs.size(); ++i) - { - g_outputs[i].output = (Baikal::ClwOutput*)g_cfgs[i].renderer->CreateOutput(g_window_width, g_window_height); - -#ifdef ENABLE_DENOISER - g_outputs[i].output_denoised = (Baikal::ClwOutput*)g_cfgs[i].renderer->CreateOutput(g_window_width, g_window_height); - g_outputs[i].output_normal = (Baikal::ClwOutput*)g_cfgs[i].renderer->CreateOutput(g_window_width, g_window_height); - g_outputs[i].output_position = (Baikal::ClwOutput*)g_cfgs[i].renderer->CreateOutput(g_window_width, g_window_height); - g_outputs[i].output_albedo = (Baikal::ClwOutput*)g_cfgs[i].renderer->CreateOutput(g_window_width, g_window_height); - g_outputs[i].denoiser = new Baikal::BilateralDenoiser(g_cfgs[i].context); -#endif - - g_cfgs[i].renderer->SetOutput(Baikal::Renderer::OutputType::kColor, g_outputs[i].output); - -#ifdef ENABLE_DENOISER - g_cfgs[i].renderer->SetOutput(Baikal::Renderer::OutputType::kWorldShadingNormal, g_outputs[i].output_normal); - g_cfgs[i].renderer->SetOutput(Baikal::Renderer::OutputType::kWorldPosition, g_outputs[i].output_position); - g_cfgs[i].renderer->SetOutput(Baikal::Renderer::OutputType::kAlbedo, g_outputs[i].output_albedo); -#endif - - g_outputs[i].fdata.resize(g_window_width * g_window_height); - g_outputs[i].udata.resize(g_window_width * g_window_height * 4); - - if (g_cfgs[i].type == ConfigManager::kPrimary) - { - g_outputs[i].copybuffer = g_cfgs[i].context.CreateBuffer(g_window_width * g_window_height, CL_MEM_READ_WRITE); - } - } - - g_cfgs[g_primary].renderer->Clear(float3(0, 0, 0), *g_outputs[g_primary].output); -} - -void OnMouseMove(GLFWwindow* window, double x, double y) -{ - if (g_is_mouse_tracking) - { - g_mouse_delta = float2((float)x, (float)y) - g_mouse_pos; - g_mouse_pos = float2((float)x, (float)y); - } -} - -void OnMouseButton(GLFWwindow* window, int button, int action, int mods) -{ - if (button == GLFW_MOUSE_BUTTON_RIGHT) - { - if (action == GLFW_PRESS) - { - g_is_mouse_tracking = true; - - double x, y; - glfwGetCursorPos(window, &x, &y); - g_mouse_pos = float2((float)x, (float)y); - g_mouse_delta = float2(0, 0); - } - else if (action == GLFW_RELEASE && g_is_mouse_tracking) - { - g_is_mouse_tracking = false; - g_mouse_delta = float2(0, 0); - } - } -} - -void OnKey(GLFWwindow* window, int key, int scancode, int action, int mods) -{ - switch (key) - { - case GLFW_KEY_UP: - g_is_fwd_pressed = action == GLFW_PRESS ? true : false; - break; - case GLFW_KEY_DOWN: - g_is_back_pressed = action == GLFW_PRESS ? true : false; - break; - case GLFW_KEY_LEFT: - g_is_left_pressed = action == GLFW_PRESS ? true : false; - break; - case GLFW_KEY_RIGHT: - g_is_right_pressed = action == GLFW_PRESS ? true : false; - break; - case GLFW_KEY_HOME: - g_is_home_pressed = action == GLFW_PRESS ? true : false; - break; - case GLFW_KEY_END: - g_is_end_pressed = action == GLFW_PRESS ? true : false; - break; - case GLFW_KEY_F1: - g_gui_visible = action == GLFW_PRESS ? !g_gui_visible : g_gui_visible; - break; - case GLFW_KEY_F3: - g_benchmark = action == GLFW_PRESS ? true : g_benchmark; - break; - default: - break; - } -} - -void Update(bool update_required) -{ - static auto prevtime = std::chrono::high_resolution_clock::now(); - auto time = std::chrono::high_resolution_clock::now(); - auto dt = std::chrono::duration_cast>(time - prevtime); - prevtime = time; - - bool update = update_required; - float camrotx = 0.f; - float camroty = 0.f; - - const float kMouseSensitivity = 0.001125f; - float2 delta = g_mouse_delta * float2(kMouseSensitivity, kMouseSensitivity); - camrotx = -delta.x; - camroty = -delta.y; - - if (std::abs(camroty) > 0.001f) - { - g_camera->Tilt(camroty); - //g_camera->ArcballRotateVertically(float3(0, 0, 0), camroty); - update = true; - } - - if (std::abs(camrotx) > 0.001f) - { - - g_camera->Rotate(camrotx); - //g_camera->ArcballRotateHorizontally(float3(0, 0, 0), camrotx); - update = true; - } - - const float kMovementSpeed = g_cspeed; - if (g_is_fwd_pressed) - { - g_camera->MoveForward((float)dt.count() * kMovementSpeed); - update = true; - } - - if (g_is_back_pressed) - { - g_camera->MoveForward(-(float)dt.count() * kMovementSpeed); - update = true; - } - - if (g_is_right_pressed) - { - g_camera->MoveRight((float)dt.count() * kMovementSpeed); - update = true; - } - - if (g_is_left_pressed) - { - g_camera->MoveRight(-(float)dt.count() * kMovementSpeed); - update = true; - } - - if (g_is_home_pressed) - { - g_camera->MoveUp((float)dt.count() * kMovementSpeed); - update = true; - } - - if (g_is_end_pressed) - { - g_camera->MoveUp(-(float)dt.count() * kMovementSpeed); - update = true; - } - - if (update) - { - //if (g_num_samples > -1) - { - g_samplecount = 0; - } - - for (int i = 0; i < g_cfgs.size(); ++i) - { - if (i == g_primary) - { - g_cfgs[i].renderer->Clear(float3(0, 0, 0), *g_outputs[i].output); - -#ifdef ENABLE_DENOISER - g_cfgs[i].renderer->Clear(float3(0, 0, 0), *g_outputs[i].output_normal); - g_cfgs[i].renderer->Clear(float3(0, 0, 0), *g_outputs[i].output_position); - g_cfgs[i].renderer->Clear(float3(0, 0, 0), *g_outputs[i].output_albedo); -#endif - - } - else - g_ctrl[i].clear.store(true); - } - - /* numbnc = 1; - for (int i = 0; i < g_cfgs.size(); ++i) - { - g_cfgs[i].renderer->SetNumBounces(numbnc); - }*/ - } - - if (g_num_samples == -1 || g_samplecount < g_num_samples) - { - g_cfgs[g_primary].renderer->Render(*g_scene.get()); - -#ifdef ENABLE_DENOISER - Baikal::PostEffect::InputSet input_set; - input_set[Baikal::Renderer::OutputType::kColor] = g_outputs[g_primary].output; - input_set[Baikal::Renderer::OutputType::kWorldShadingNormal] = g_outputs[g_primary].output_normal; - input_set[Baikal::Renderer::OutputType::kWorldPosition] = g_outputs[g_primary].output_position; - input_set[Baikal::Renderer::OutputType::kAlbedo] = g_outputs[g_primary].output_albedo; - auto radius = 10U - RadeonRays::clamp((g_samplecount / 32), 1U, 9U); - auto position_sensitivity = 5.f + 10.f * (radius / 10.f); - auto normal_sensitivity = 0.1f + (radius / 10.f) * 0.15f; - auto color_sensitivity = (radius / 10.f) * 5.f; - auto albedo_sensitivity = 0.05f + (radius / 10.f) * 0.1f; - g_outputs[g_primary].denoiser->SetParameter("radius", radius); - g_outputs[g_primary].denoiser->SetParameter("color_sensitivity", color_sensitivity); - g_outputs[g_primary].denoiser->SetParameter("normal_sensitivity", normal_sensitivity); - g_outputs[g_primary].denoiser->SetParameter("position_sensitivity", position_sensitivity); - g_outputs[g_primary].denoiser->SetParameter("albedo_sensitivity", albedo_sensitivity); - g_outputs[g_primary].denoiser->Apply(input_set, *g_outputs[g_primary].output_denoised); -#endif - - ++g_samplecount; - } - else if (g_samplecount == g_num_samples) - { - std::cout << "Target sample count reached\n"; - ++g_samplecount; - } - - //if (std::chrono::duration_cast(time - updatetime).count() > 1) - //{ - for (int i = 0; i < g_cfgs.size(); ++i) - { - if (g_cfgs[i].type == ConfigManager::kPrimary) - continue; - - int desired = 1; - if (std::atomic_compare_exchange_strong(&g_ctrl[i].newdata, &desired, 0)) - { - { - //std::unique_lock lock(g_ctrl[i].datamutex); - //std::cout << "Start updating acc buffer\n"; std::cout.flush(); - g_cfgs[g_primary].context.WriteBuffer(0, g_outputs[g_primary].copybuffer, &g_outputs[i].fdata[0], g_window_width * g_window_height); - //std::cout << "Finished updating acc buffer\n"; std::cout.flush(); - } - - CLWKernel acckernel = g_cfgs[g_primary].renderer->GetAccumulateKernel(); - - int argc = 0; - acckernel.SetArg(argc++, g_outputs[g_primary].copybuffer); - acckernel.SetArg(argc++, g_window_width * g_window_width); - acckernel.SetArg(argc++, g_outputs[g_primary].output->data()); - - int globalsize = g_window_width * g_window_height; - g_cfgs[g_primary].context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, acckernel); - } - } - - //updatetime = time; - //} - - if (!g_interop) - { -#ifdef ENABLE_DENOISER - g_outputs[g_primary].output_denoised->GetData(&g_outputs[g_primary].fdata[0]); -#else - g_outputs[g_primary].output->GetData(&g_outputs[g_primary].fdata[0]); -#endif - - float gamma = 2.2f; - for (int i = 0; i < (int)g_outputs[g_primary].fdata.size(); ++i) - { - g_outputs[g_primary].udata[4 * i] = (unsigned char)clamp(clamp(pow(g_outputs[g_primary].fdata[i].x / g_outputs[g_primary].fdata[i].w, 1.f / gamma), 0.f, 1.f) * 255, 0, 255); - g_outputs[g_primary].udata[4 * i + 1] = (unsigned char)clamp(clamp(pow(g_outputs[g_primary].fdata[i].y / g_outputs[g_primary].fdata[i].w, 1.f / gamma), 0.f, 1.f) * 255, 0, 255); - g_outputs[g_primary].udata[4 * i + 2] = (unsigned char)clamp(clamp(pow(g_outputs[g_primary].fdata[i].z / g_outputs[g_primary].fdata[i].w, 1.f / gamma), 0.f, 1.f) * 255, 0, 255); - g_outputs[g_primary].udata[4 * i + 3] = 1; - } - - - glActiveTexture(GL_TEXTURE0); - - glBindTexture(GL_TEXTURE_2D, g_texture); - - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, g_outputs[g_primary].output->width(), g_outputs[g_primary].output->height(), GL_RGBA, GL_UNSIGNED_BYTE, &g_outputs[g_primary].udata[0]); - - glBindTexture(GL_TEXTURE_2D, 0); - } - else - { - std::vector objects; - objects.push_back(g_cl_interop_image); - g_cfgs[g_primary].context.AcquireGLObjects(0, objects); - - CLWKernel copykernel = g_cfgs[g_primary].renderer->GetCopyKernel(); - -#ifdef ENABLE_DENOISER - auto output = g_outputs[g_primary].output_denoised; -#else - auto output = g_outputs[g_primary].output; -#endif - - int argc = 0; - copykernel.SetArg(argc++, output->data()); - copykernel.SetArg(argc++, output->width()); - copykernel.SetArg(argc++, output->height()); - copykernel.SetArg(argc++, 2.2f); - copykernel.SetArg(argc++, g_cl_interop_image); - - int globalsize = output->width() * output->height(); - g_cfgs[g_primary].context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, copykernel); - - g_cfgs[g_primary].context.ReleaseGLObjects(0, objects); - g_cfgs[g_primary].context.Finish(0); - } - - - if (g_benchmark) - { - auto const kNumBenchmarkPasses = 100U; - - Baikal::Renderer::BenchmarkStats stats; - g_cfgs[g_primary].renderer->RunBenchmark(*g_scene.get(), kNumBenchmarkPasses, stats); - - auto numrays = stats.resolution.x * stats.resolution.y; - std::cout << "Baikal renderer benchmark\n"; - std::cout << "Number of primary rays: " << numrays << "\n"; - std::cout << "Primary rays: " << (float)(numrays / (stats.primary_rays_time_in_ms * 0.001f) * 0.000001f) << "mrays/s ( " << stats.primary_rays_time_in_ms << "ms )\n"; - std::cout << "Secondary rays: " << (float)(numrays / (stats.secondary_rays_time_in_ms * 0.001f) * 0.000001f) << "mrays/s ( " << stats.secondary_rays_time_in_ms << "ms )\n"; - std::cout << "Shadow rays: " << (float)(numrays / (stats.shadow_rays_time_in_ms * 0.001f) * 0.000001f) << "mrays/s ( " << stats.shadow_rays_time_in_ms << "ms )\n"; - g_benchmark = false; - } -} - -void RenderThread(ControlData& cd) -{ - auto renderer = g_cfgs[cd.idx].renderer; - auto output = g_outputs[cd.idx].output; - - auto updatetime = std::chrono::high_resolution_clock::now(); - - while (!cd.stop.load()) - { - int result = 1; - bool update = false; - - if (std::atomic_compare_exchange_strong(&cd.clear, &result, 0)) - { - renderer->Clear(float3(0, 0, 0), *output); - update = true; - } - - renderer->Render(*g_scene.get()); - - auto now = std::chrono::high_resolution_clock::now(); - - update = update || (std::chrono::duration_cast(now - updatetime).count() > 1); - - if (update) - { - g_outputs[cd.idx].output->GetData(&g_outputs[cd.idx].fdata[0]); - updatetime = now; - cd.newdata.store(1); - } - - g_cfgs[cd.idx].context.Finish(0); - } -} - -void StartRenderThreads() -{ - for (int i = 0; i < g_cfgs.size(); ++i) - { - if (i != g_primary) - { - g_renderthreads.push_back(std::thread(RenderThread, std::ref(g_ctrl[i]))); - g_renderthreads.back().detach(); - } - } - - std::cout << g_cfgs.size() << " OpenCL submission threads started\n"; -} - - -void OnError(int error, const char* description) -{ - std::cout << description << "\n"; -} - -int main(int argc, char * argv[]) -{ - // Command line parsing - char* path = GetCmdOption(argv, argv + argc, "-p"); - g_path = path ? path : g_path; - - char* modelname = GetCmdOption(argv, argv + argc, "-f"); - g_modelname = modelname ? modelname : g_modelname; - - char* envmapname = GetCmdOption(argv, argv + argc, "-e"); - g_envmapname = envmapname ? envmapname : g_envmapname; - - char* width = GetCmdOption(argv, argv + argc, "-w"); - g_window_width = width ? atoi(width) : g_window_width; - - char* height = GetCmdOption(argv, argv + argc, "-h"); - g_window_height = width ? atoi(height) : g_window_height; - - char* aorays = GetCmdOption(argv, argv + argc, "-ao"); - g_ao_radius = aorays ? (float)atof(aorays) : g_ao_radius; - - char* bounces = GetCmdOption(argv, argv + argc, "-nb"); - g_num_bounces = bounces ? atoi(bounces) : g_num_bounces; - - char* camposx = GetCmdOption(argv, argv + argc, "-cpx"); - g_camera_pos.x = camposx ? (float)atof(camposx) : g_camera_pos.x; - - char* camposy = GetCmdOption(argv, argv + argc, "-cpy"); - g_camera_pos.y = camposy ? (float)atof(camposy) : g_camera_pos.y; - - char* camposz = GetCmdOption(argv, argv + argc, "-cpz"); - g_camera_pos.z = camposz ? (float)atof(camposz) : g_camera_pos.z; - - char* camatx = GetCmdOption(argv, argv + argc, "-tpx"); - g_camera_at.x = camatx ? (float)atof(camatx) : g_camera_at.x; - - char* camaty = GetCmdOption(argv, argv + argc, "-tpy"); - g_camera_at.y = camaty ? (float)atof(camaty) : g_camera_at.y; - - char* camatz = GetCmdOption(argv, argv + argc, "-tpz"); - g_camera_at.z = camatz ? (float)atof(camatz) : g_camera_at.z; - - char* envmapmul = GetCmdOption(argv, argv + argc, "-em"); - g_envmapmul = envmapmul ? (float)atof(envmapmul) : g_envmapmul; - - char* numsamples = GetCmdOption(argv, argv + argc, "-ns"); - g_num_samples = numsamples ? atoi(numsamples) : g_num_samples; - - char* camera_aperture = GetCmdOption(argv, argv + argc, "-a"); - g_camera_aperture = camera_aperture ? (float)atof(camera_aperture) : g_camera_aperture; - - char* camera_dist = GetCmdOption(argv, argv + argc, "-fd"); - g_camera_focus_distance = camera_dist ? (float)atof(camera_dist) : g_camera_focus_distance; - - char* camera_focal_length = GetCmdOption(argv, argv + argc, "-fl"); - g_camera_focal_length = camera_focal_length ? (float)atof(camera_focal_length) : g_camera_focal_length; - - char* interop = GetCmdOption(argv, argv + argc, "-interop"); - g_interop = interop ? (atoi(interop) > 0) : g_interop; - - char* cspeed = GetCmdOption(argv, argv + argc, "-cs"); - g_cspeed = cspeed ? (float)atof(cspeed) : g_cspeed; - - - char* cfg = GetCmdOption(argv, argv + argc, "-config"); - - if (cfg) - { - if (strcmp(cfg, "cpu") == 0) - g_mode = ConfigManager::Mode::kUseSingleCpu; - else if (strcmp(cfg, "gpu") == 0) - g_mode = ConfigManager::Mode::kUseSingleGpu; - else if (strcmp(cfg, "mcpu") == 0) - g_mode = ConfigManager::Mode::kUseCpus; - else if (strcmp(cfg, "mgpu") == 0) - g_mode = ConfigManager::Mode::kUseGpus; - else if (strcmp(cfg, "all") == 0) - g_mode = ConfigManager::Mode::kUseAll; - } - - if (aorays) - { - g_num_ao_rays = atoi(aorays); - g_ao_enabled = true; - } - - if (CmdOptionExists(argv, argv + argc, "-r")) - { - g_progressive = true; - } - - // Initialize GLFW - { - auto err = glfwInit(); - if (err != GLFW_TRUE) - { - std::cout << "GLFW initialization failed\n"; - return -1; - } - } - // Setup window - glfwSetErrorCallback(OnError); - glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); -#if __APPLE__ - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); -#endif - - // GLUT Window Initialization: - GLFWwindow* window = glfwCreateWindow(g_window_width, g_window_height, "Baikal standalone demo", nullptr, nullptr); - glfwMakeContextCurrent(window); - -#ifndef __APPLE__ - { - glewExperimental = GL_TRUE; - GLenum err = glewInit(); - if (err != GLEW_OK) - { - std::cout << "GLEW initialization failed\n"; - return -1; - } - } -#endif - - ImGui_ImplGlfwGL3_Init(window, true); - - try - { - InitGraphics(); - InitCl(); - InitData(); - glfwSetMouseButtonCallback(window, OnMouseButton); - glfwSetCursorPosCallback(window, OnMouseMove); - glfwSetKeyCallback(window, OnKey); - - StartRenderThreads(); - - // Collect some scene statistics - auto num_triangles = 0U; - auto num_instances = 0U; - { - std::unique_ptr shape_iter(g_scene->CreateShapeIterator()); - - for (; shape_iter->IsValid(); shape_iter->Next()) - { - auto shape = shape_iter->ItemAs(); - auto mesh = dynamic_cast(shape); - - if (mesh) - { - num_triangles += mesh->GetNumIndices() / 3; - } - else - { - ++num_instances; - } - } - } - - bool update = false; - while (!glfwWindowShouldClose(window)) - { - - ImGui_ImplGlfwGL3_NewFrame(); - Update(update); - Render(window); - update = false; - - static float aperture = 0.0f; - static float focal_length = 35.f; - static float focus_distance = 1.f; - static int num_bounces = 5; - static char const* outputs = - "Color\0" - "World position\0" - "Shading normal\0" - "Geometric normal\0" - "Texture coords\0" - "Wire\0" - "Albedo\0\0"; - - static int output = 0; - - if (g_gui_visible) - { - ImGui::SetNextWindowSizeConstraints(ImVec2(380, 400), ImVec2(380, 400)); - ImGui::Begin("Baikal settings"); - ImGui::Text("Use arrow keys to move"); - ImGui::Text("PgUp/Down to climb/descent"); - ImGui::Text("Mouse+RMB to look around"); - ImGui::Text("F1 to hide/show GUI"); - ImGui::Separator(); - ImGui::Text("Device vendor: %s", g_cfgs[g_primary].context.GetDevice(0).GetVendor().c_str()); - ImGui::Text("Device name: %s", g_cfgs[g_primary].context.GetDevice(0).GetName().c_str()); - ImGui::Text("OpenCL: %s", g_cfgs[g_primary].context.GetDevice(0).GetVersion().c_str()); - ImGui::Separator(); - ImGui::Text("Resolution: %dx%d ", g_window_width, g_window_height); - ImGui::Text("Scene: %s", g_modelname); - ImGui::Text("Unique triangles: %d", num_triangles); - ImGui::Text("Number of instances: %d", num_instances); - ImGui::Separator(); - ImGui::SliderInt("GI bounces", &num_bounces, 1, 10); - ImGui::SliderFloat("Aperture(mm)", &aperture, 0.0f, 100.0f); - ImGui::SliderFloat("Focal length(mm)", &focal_length, 5.f, 200.0f); - ImGui::SliderFloat("Focus distance(m)", &focus_distance, 0.05f, 20.f); - - if (aperture != g_camera_aperture * 1000.f) - { - g_camera_aperture = aperture / 1000.f; - g_camera->SetAperture(g_camera_aperture); - update = true; - } - - if (focus_distance != g_camera_focus_distance) - { - g_camera_focus_distance = focus_distance; - g_camera->SetFocusDistance(g_camera_focus_distance); - update = true; - } - - if (focal_length != g_camera_focal_length * 1000.f) - { - g_camera_focal_length = focal_length / 1000.f; - g_camera->SetFocalLength(g_camera_focal_length); - update = true; - } - - if (num_bounces != g_num_bounces) - { - g_num_bounces = num_bounces; - for (int i = 0; i < g_cfgs.size(); ++i) - { - g_cfgs[i].renderer->SetNumBounces(g_num_bounces); - } - update = true; - } - - if (static_cast(output) != g_ouput_type) - { - auto tmp = static_cast(output); - - for (int i = 0; i < g_cfgs.size(); ++i) - { - g_cfgs[i].renderer->SetOutput(g_ouput_type, nullptr); - g_cfgs[i].renderer->SetOutput(tmp, g_outputs[i].output); - g_ouput_type = tmp; - } - - update = true; - } - - ImGui::Combo("Output", &output, outputs); - ImGui::Text(" "); - ImGui::Text("Frame time %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); - ImGui::Text("Renderer performance %.3f Msamples/s", (ImGui::GetIO().Framerate * g_window_width * g_window_height) / 1000000.f); - ImGui::End(); - ImGui::Render(); - } - - glfwSwapBuffers(window); - glfwPollEvents(); - } - - for (int i = 0; i < g_cfgs.size(); ++i) - { - if (i == g_primary) - continue; - - g_ctrl[i].stop.store(true); - } - - glfwDestroyWindow(window); - } - catch (std::runtime_error& err) - { - glfwDestroyWindow(window); - std::cout << err.what(); - return -1; - } - - return 0; -} - -char* GetCmdOption(char ** begin, char ** end, const std::string & option) -{ - char ** itr = std::find(begin, end, option); - if (itr != end && ++itr != end) - { - return *itr; - } - return 0; -} - -bool CmdOptionExists(char** begin, char** end, const std::string& option) -{ - return std::find(begin, end, option) != end; -} - -void ShowHelpAndDie() -{ - std::cout << kHelpMessage << "\n"; -} - -void SaveImage(std::string const& name, float3 const* data, int w, int h) -{ - - -} - -void SaveFrameBuffer(std::string const& name, float3 const* data) -{ - OIIO_NAMESPACE_USING; - - std::vector tempbuf(g_window_width * g_window_height); - tempbuf.assign(data, data + g_window_width*g_window_height); - - for (auto y = 0; y < g_window_height; ++y) - for (auto x = 0; x < g_window_width; ++x) - { - - float3 val = data[(g_window_height - 1 - y) * g_window_width + x]; - tempbuf[y * g_window_width + x] = (1.f / val.w) * val; - - tempbuf[y * g_window_width + x].x = std::pow(tempbuf[y * g_window_width + x].x, 1.f / 2.2f); - tempbuf[y * g_window_width + x].y = std::pow(tempbuf[y * g_window_width + x].y, 1.f / 2.2f); - tempbuf[y * g_window_width + x].z = std::pow(tempbuf[y * g_window_width + x].z, 1.f / 2.2f); - } - - ImageOutput* out = ImageOutput::create(name); - - if (!out) - { - throw std::runtime_error("Can't create image file on disk"); - } - - ImageSpec spec(g_window_width, g_window_height, 3, TypeDesc::FLOAT); - - out->open(name, spec); - out->write_image(TypeDesc::FLOAT, &tempbuf[0], sizeof(float3)); - out->close(); -} diff --git a/BaikalDataGenerator/CMakeLists.txt b/BaikalDataGenerator/CMakeLists.txt new file mode 100644 index 00000000..6d1ad572 --- /dev/null +++ b/BaikalDataGenerator/CMakeLists.txt @@ -0,0 +1,83 @@ +# Library + +set(DATAGENERATOR_LIB_SOURCES + Source/data_generator.h + Source/data_generator.cpp + Source/devices.h + Source/devices.cpp + Source/filesystem.h + Source/data_generator_impl.h + Source/data_generator_impl.cpp + Source/utils.h +) + +add_library(BaikalDataGenerator SHARED ${DATAGENERATOR_LIB_SOURCES}) + +target_compile_features(BaikalDataGenerator PRIVATE cxx_std_17) + +target_compile_definitions(BaikalDataGenerator PRIVATE RPR_EXPORT_API) + +target_include_directories(BaikalDataGenerator + PRIVATE . + PRIVATE ${Baikal_SOURCE_DIR} + PRIVATE ${Baikal_SOURCE_DIR}/Rpr + PRIVATE ${Baikal_SOURCE_DIR}/RadeonRays/include +) + +target_link_libraries(BaikalDataGenerator PRIVATE RadeonProRender64 Baikal BaikalIO) +if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_link_libraries(BaikalDataGenerator PRIVATE stdc++fs) +endif() +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + target_link_libraries(BaikalDataGenerator PRIVATE c++experimental) +endif () + +set_target_properties(BaikalDataGenerator + PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${Baikal_SOURCE_DIR}/BaikalDataGenerator) + +add_dependencies(BaikalDataGenerator ResourcesDir Copy3rdParty) + +if (WIN32) + install(TARGETS BaikalDataGenerator RUNTIME DESTINATION bin) +else () + install(TARGETS BaikalDataGenerator LIBRARY DESTINATION lib) +endif () + + +# Application + +set(DATAGENERATOR_APP_SOURCES + Source/app_config.h + Source/cmd_line_parser.h + Source/cmd_line_parser.cpp + Source/devices.h + Source/devices.cpp + Source/filesystem.h + Source/object_loader.h + Source/object_loader.cpp + Source/logging.h + Source/logging.cpp + Source/main.cpp +) + +add_executable(BaikalDataGeneratorApp ${DATAGENERATOR_APP_SOURCES}) + +target_compile_features(BaikalDataGeneratorApp PRIVATE cxx_std_17) + +target_include_directories(BaikalDataGeneratorApp + PRIVATE ${Baikal_SOURCE_DIR} + PRIVATE . +) + +target_link_libraries(BaikalDataGeneratorApp PRIVATE BaikalDataGenerator RadeonProRender64 Baikal) +if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_link_libraries(BaikalDataGeneratorApp PRIVATE stdc++fs) +endif() +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + target_link_libraries(BaikalDataGeneratorApp PRIVATE c++experimental) +endif () + +set_target_properties(BaikalDataGeneratorApp + PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${Baikal_SOURCE_DIR}/BaikalDataGenerator) + +install(TARGETS BaikalDataGeneratorApp RUNTIME DESTINATION bin) diff --git a/BaikalDataGenerator/Source/app_config.h b/BaikalDataGenerator/Source/app_config.h new file mode 100644 index 00000000..7edaac1f --- /dev/null +++ b/BaikalDataGenerator/Source/app_config.h @@ -0,0 +1,24 @@ +#pragma once + +#include "filesystem.h" + +#include + +const int kDefaultStartOutputIndex = -1; + +struct AppConfig +{ + std::filesystem::path scene_file; + std::filesystem::path light_file; + std::filesystem::path camera_file; + std::filesystem::path spp_file; + std::filesystem::path output_dir; + unsigned width = 0; + unsigned height = 0; + unsigned split_num = 1; + unsigned split_idx = 0; + int start_output_idx = kDefaultStartOutputIndex; + unsigned num_bounces = 5; + unsigned device_idx = 0; + bool gamma_correction = false; +}; diff --git a/BaikalDataGenerator/Source/cmd_line_parser.cpp b/BaikalDataGenerator/Source/cmd_line_parser.cpp new file mode 100644 index 00000000..885529ea --- /dev/null +++ b/BaikalDataGenerator/Source/cmd_line_parser.cpp @@ -0,0 +1,96 @@ +/********************************************************************** +Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + +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 "cmd_line_parser.h" + +#include "utils.h" + +#include + +namespace +{ + constexpr char const* kHelpMessage = + "USAGE:\n\n" + "Show this help message:\n" + " BaikalDataGeneratorApp [-help]\n\n" + "List available devices:\n" + " BaikalDataGeneratorApp [-list_devices]\n\n" + "Run data generation:\n" + " BaikalDataGeneratorApp -width OUTPUT_IMAGES_WIDTH -height OUTPUT_IMAGES_HEIGHT\n" + " -scene_file SCENE_FILE_PATH -spp_file SPP_CONFIG_PATH\n" + " -light_file LIGHT_CONFIG_PATH -camera_file CAMERA_CONFIG_PATH\n" + " -output_dir OUTPUT_DIRECTORY [-device DEVICE_INDEX] [-gamma]\n" + " [-split_num CAMERA_SUBSET_NUMBER [-split_idx USE_CAMERA_SUBSET]]\n" + " [-start_output_idx CAMERA_START_OUTPUT_INDEX] [-nb BOUNCES_NUMBER]\n\n"; +} + +CmdLineParser::CmdLineParser(int argc, char* argv[]) + : m_cmd_parser(argc, argv) +{ } + +AppConfig CmdLineParser::Parse() const +{ + AppConfig config; + + config.device_idx = m_cmd_parser.GetOption("-device", config.device_idx); + + config.light_file = m_cmd_parser.GetOption("-light_file"); + + config.camera_file = m_cmd_parser.GetOption("-camera_file"); + + config.output_dir = m_cmd_parser.GetOption("-output_dir"); + + config.scene_file = m_cmd_parser.GetOption("-scene_file"); + + config.spp_file = m_cmd_parser.GetOption("-spp_file"); + + config.width = m_cmd_parser.GetOption("-width"); + + config.height = m_cmd_parser.GetOption("-height"); + + config.split_num = m_cmd_parser.GetOption("-split_num", config.split_num); + + config.split_idx = m_cmd_parser.GetOption("-split_idx", config.split_idx); + + config.start_output_idx = m_cmd_parser.GetOption("-start_output_idx", config.start_output_idx); + + config.gamma_correction = m_cmd_parser.OptionExists("-gamma"); + + config.num_bounces = m_cmd_parser.GetOption("-nb", config.num_bounces); + + return config; +} + +bool CmdLineParser::HasListDevicesOption() const +{ + return m_cmd_parser.OptionExists("-list_devices"); +} + +void CmdLineParser::ShowHelp() const +{ + std::cout << kHelpMessage; +} + +bool CmdLineParser::HasHelpOption() const +{ + return m_cmd_parser.OptionExists("-help"); +} \ No newline at end of file diff --git a/BaikalDataGenerator/Source/cmd_line_parser.h b/BaikalDataGenerator/Source/cmd_line_parser.h new file mode 100644 index 00000000..64e03dd0 --- /dev/null +++ b/BaikalDataGenerator/Source/cmd_line_parser.h @@ -0,0 +1,55 @@ +/********************************************************************** +Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ + +#pragma once + +#include "app_config.h" + +#include + +#include + + +class CmdLineParser +{ +public: + + // 'argc' - number of the command line arguments + // 'argv' - command line arguments string + CmdLineParser(int argc, char* argv[]); + + // Generate AppConfig from internal string + AppConfig Parse() const; + + // check whether device list is requested + bool HasListDevicesOption() const; + + // check if there is '-help' option + // returns true if there's a help option, false otherwise + bool HasHelpOption() const; + + // print help option + void ShowHelp() const; + +private: + Baikal::CmdParser m_cmd_parser; +}; \ No newline at end of file diff --git a/BaikalDataGenerator/Source/data_generator.cpp b/BaikalDataGenerator/Source/data_generator.cpp new file mode 100644 index 00000000..7bd8d33e --- /dev/null +++ b/BaikalDataGenerator/Source/data_generator.cpp @@ -0,0 +1,162 @@ +/********************************************************************** +Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + +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 "data_generator.h" + +#include "devices.h" +#include "data_generator_impl.h" +#include "utils.h" + +#include "Rpr/WrapObject/LightObject.h" +#include "Rpr/WrapObject/SceneObject.h" + + +DataGeneratorResult bdgGenerateDataset(DataGeneratorParams const* params) +try +{ + // Validate input parameters + + if (params == nullptr) + { + return kDataGeneratorBadParams; + } + + auto* scene = SceneObject::Cast(params->scene); + if (scene == nullptr) + { + return kDataGeneratorBadScene; + } + if (params->scene_name == nullptr) + { + return kDataGeneratorBadSceneName; + } + + if (params->cameras == nullptr || params->cameras_num == 0) + { + return kDataGeneratorBadCameras; + } + + if (params->lights == nullptr || params->lights_num == 0) + { + return kDataGeneratorBadLights; + } + + if (params->spp == nullptr || params->spp_num == 0) + { + return kDataGeneratorBadSpp; + } + // Sort SPP list and remove duplicates + std::vector sorted_spp(params->spp, params->spp + params->spp_num); + std::sort(sorted_spp.begin(), sorted_spp.end()); + sorted_spp.erase(std::unique(sorted_spp.begin(), sorted_spp.end()), sorted_spp.end()); + if (sorted_spp.front() == 0) + { + // Minimal SPP must be >= 1 + return kDataGeneratorBadSpp; + } + + if (params->width == 0 || params->height == 0) + { + return kDataGeneratorBadImgSize; + } + + if (params->bounces_num == 0) + { + return kDataGeneratorBadBouncesNum; + } + + if (params->device_idx >= GetDevices().size()) + { + return kDataGeneratorBadDeviceIdx; + } + + if (params->output_dir == nullptr) + { + return kDataGeneratorBadOutputDir; + } + std::filesystem::path output_dir = params->output_dir; + if (!exists(output_dir)) + { + create_directory(output_dir); + } + else if (!is_directory(output_dir)) + { + return kDataGeneratorBadOutputDir; + } + + // Attach given lights to the scene + for (size_t i = 0; i < params->lights_num; ++i) + { + auto* light = LightObject::Cast(params->lights[i]); + if (light == nullptr) + { + return kDataGeneratorBadLights; + } + scene->AttachLight(light); + } + + for (unsigned i = 0; i < params->cameras_num; ++i) + { + auto* camera = CameraObject::Cast(params->cameras[i]); + if (camera == nullptr) + { + return kDataGeneratorBadCameras; + } + } + + DataGeneratorImpl data_generator(scene, + params->scene_name, + params->width, + params->height, + params->bounces_num, + params->device_idx, + sorted_spp, + output_dir, + params->gamma_correction != 0); + + // Save settings and other info into a metadata file + data_generator.SaveMetadata(); + + for (unsigned i = 0; i < params->cameras_num; ++i) + { + auto* camera = CameraObject::Cast(params->cameras[i]); + + // Render outputs for every specified SPP at the given + // camera position and save them to separate files + unsigned camera_idx = params->cameras_start_output_idx + i; + data_generator.GenerateCameraData(camera, camera_idx); + + // Report the progress + if (params->progress_callback) + { + params->progress_callback(params->cameras_start_output_idx, + camera_idx, + params->cameras_start_output_idx + params->cameras_num - 1); + } + } + + return kDataGeneratorSuccess; +} +catch (...) +{ + return kDataGeneratorUnknownError; +} \ No newline at end of file diff --git a/BaikalDataGenerator/Source/data_generator.h b/BaikalDataGenerator/Source/data_generator.h new file mode 100644 index 00000000..cad74622 --- /dev/null +++ b/BaikalDataGenerator/Source/data_generator.h @@ -0,0 +1,81 @@ +/********************************************************************** +Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ + +#pragma once + +#include "Rpr/RadeonProRender.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct DataGeneratorParams +{ + rpr_scene scene; + char const* scene_name; + + rpr_light* lights; + unsigned lights_num; + + rpr_camera* cameras; + unsigned cameras_num; + unsigned cameras_start_output_idx; + + unsigned const* spp; + unsigned spp_num; + + unsigned width; + unsigned height; + + unsigned bounces_num; + unsigned device_idx; + + unsigned gamma_correction; /* 0 or 1 */ + + char const* output_dir; + + void(*progress_callback)(unsigned /* start_idx */, + unsigned /* current_idx */, + unsigned /* end_idx */); +}; + +enum DataGeneratorResult +{ + kDataGeneratorSuccess = 0, + kDataGeneratorBadParams, + kDataGeneratorBadOutputDir, + kDataGeneratorBadScene, + kDataGeneratorBadSceneName, + kDataGeneratorBadCameras, + kDataGeneratorBadLights, + kDataGeneratorBadSpp, + kDataGeneratorBadImgSize, + kDataGeneratorBadBouncesNum, + kDataGeneratorBadDeviceIdx, + kDataGeneratorUnknownError, +}; + +RPR_API_ENTRY DataGeneratorResult bdgGenerateDataset(DataGeneratorParams const* params); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/BaikalDataGenerator/Source/data_generator_impl.cpp b/BaikalDataGenerator/Source/data_generator_impl.cpp new file mode 100644 index 00000000..166a2275 --- /dev/null +++ b/BaikalDataGenerator/Source/data_generator_impl.cpp @@ -0,0 +1,316 @@ +/********************************************************************** +Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + +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 "data_generator_impl.h" + +#include "filesystem.h" +#include "devices.h" +#include "logging.h" +#include "utils.h" + +#include "Baikal/Output/clwoutput.h" +#include "Baikal/Renderers/monte_carlo_renderer.h" +#include "Baikal/Renderers/renderer.h" +#include "Baikal/RenderFactory/clw_render_factory.h" + +#include "OpenImageIO/imageio.h" + +#include "XML/tinyxml2.h" + +#include +#include +#include +#include + + +struct OutputInfo +{ + Baikal::Renderer::OutputType type; + std::string name; + // channels number can be only 1 or 3 + int channels_num; +}; + + +namespace { + + // if you need to add new output for saving to disk + // for iterations number counted in spp.xml file + // just put its description in this collection + const std::vector kMultipleIteratedOutputs + { + {Baikal::Renderer::OutputType::kColor, "color", 3}, + {Baikal::Renderer::OutputType::kAlbedo, "albedo", 3}, + {Baikal::Renderer::OutputType::kGloss, "gloss", 1} + }; + + // if you need to add new output for saving to disk + // only for the one time + // just put its description in this collection + const std::vector kSingleIteratedOutputs + { + {Baikal::Renderer::OutputType::kViewShadingNormal, "view_shading_normal", 3}, + {Baikal::Renderer::OutputType::kDepth, "view_shading_depth", 1} + }; + +} // namespace + + +DataGeneratorImpl::DataGeneratorImpl(SceneObject* scene, + std::string const& scene_name, + unsigned width, unsigned height, + unsigned num_bounces, + unsigned device_idx, + const std::vector& sorted_spp, + const std::filesystem::path& output_dir, + bool gamma_correction_enable) + : m_scene(scene), + m_scene_name(scene_name), + m_width(width), + m_height(height), + m_num_bounces(num_bounces), + m_device_idx(device_idx), + m_output_dir(output_dir), + m_sorted_spp(sorted_spp), + m_gamma_correction_enabled(gamma_correction_enable) +{ + auto devices = GetDevices(); + if (devices.empty()) + { + THROW_EX("Cannot find any device"); + } + if (device_idx >= devices.size()) + { + THROW_EX("Cannot find device with index " << device_idx); + } + + m_context = std::make_unique(CLWContext::Create(devices[device_idx])); + + m_factory = std::make_unique(*m_context, "cache"); + + auto render = m_factory->CreateRenderer( + Baikal::ClwRenderFactory::RendererType::kUnidirectionalPathTracer); + m_renderer.reset(dynamic_cast(render.release())); + + m_controller = m_factory->CreateSceneController(); + + for (auto& output_info : kMultipleIteratedOutputs) + { + m_outputs.push_back(m_factory->CreateOutput(width, height)); + m_renderer->SetOutput(output_info.type, m_outputs.back().get()); + } + for (auto& output_info : kSingleIteratedOutputs) + { + m_outputs.push_back(m_factory->CreateOutput(width, height)); + m_renderer->SetOutput(output_info.type, m_outputs.back().get()); + } + + m_renderer->SetMaxBounces(num_bounces); +} + +void DataGeneratorImpl::SaveMetadata() const +{ + tinyxml2::XMLDocument doc; + + auto bdg_metadata_file_name = m_output_dir; + bdg_metadata_file_name.append("metadata.xml"); + + auto* root = doc.NewElement("metadata"); + doc.InsertFirstChild(root); + + auto* scene = doc.NewElement("scene"); + scene->SetAttribute("file", m_scene_name.c_str()); + root->InsertEndChild(scene); + + auto* outputs_list = doc.NewElement("outputs"); + outputs_list->SetAttribute("width", m_width); + outputs_list->SetAttribute("height", m_height); + root->InsertEndChild(outputs_list); + + std::vector outputs = kSingleIteratedOutputs; + outputs.insert(outputs.end(), kMultipleIteratedOutputs.begin(), kMultipleIteratedOutputs.end()); + + for (const auto& output : outputs) + { + auto* outputs_item = doc.NewElement("output"); + outputs_item->SetAttribute("name", output.name.c_str()); + outputs_item->SetAttribute("type", "float32"); + outputs_item->SetAttribute("channels", output.channels_num); + if (output.type == Baikal::Renderer::OutputType::kColor) + { + outputs_item->SetAttribute("gamma_correction", m_gamma_correction_enabled); + } + outputs_list->InsertEndChild(outputs_item); + } + + // log render settings + auto* renderer_attribute = doc.NewElement("renderer"); + renderer_attribute->SetAttribute("num_bounces", m_num_bounces); + root->InsertEndChild(renderer_attribute); + + auto* device_attribute = doc.NewElement("device"); + auto device = GetDevices().at(m_device_idx); + device_attribute->SetAttribute("idx", m_device_idx); + device_attribute->SetAttribute("name", device.GetName().c_str()); + device_attribute->SetAttribute("vendor", device.GetVendor().c_str()); + device_attribute->SetAttribute("version", device.GetVersion().c_str()); + root->InsertEndChild(device_attribute); + + doc.SaveFile(bdg_metadata_file_name.string().c_str()); +} + +void DataGeneratorImpl::GenerateCameraData(CameraObject* camera, unsigned camera_idx) +{ + m_scene->SetCamera(camera); + + for (const auto& output : m_outputs) + { + output->Clear({}); + } + + // recompile scene cause of changing camera pos and settings + auto& scene = m_controller->CompileScene(m_scene->GetScene()); + + auto spp_iter = m_sorted_spp.begin(); + + for (auto spp = 1u; spp <= m_sorted_spp.back(); spp++) + { + m_renderer->Render(scene); + + if (spp == 1) + { + for (const auto& output : kSingleIteratedOutputs) + { + std::stringstream ss; + + ss << "cam_" << camera_idx << "_" + << output.name << ".bin"; + + SaveOutput(output, + ss.str(), + m_gamma_correction_enabled, + m_output_dir); + } + } + + if (*spp_iter == spp) + { + for (const auto& output : kMultipleIteratedOutputs) + { + std::stringstream ss; + + ss << "cam_" << camera_idx << "_" + << output.name << "_spp_" << spp << ".bin"; + + SaveOutput(output, + ss.str(), + m_gamma_correction_enabled, + m_output_dir); + } + ++spp_iter; + } + } +} + +void DataGeneratorImpl::SaveOutput(const OutputInfo& info, + const std::string& name, + bool gamma_correction_enabled, + const std::filesystem::path& output_dir) +{ + using RadeonRays::float3; + + OIIO_NAMESPACE_USING; + + auto output = m_renderer->GetOutput(info.type); + + assert(output); + + auto buffer = dynamic_cast(output)->data(); + + std::vector output_data(buffer.GetElementCount()); + + output->GetData(output_data.data()); + + std::vector image_data(info.channels_num * m_width * m_height); + + float* dst_row = image_data.data(); + + if (gamma_correction_enabled && + (info.type == Baikal::Renderer::OutputType::kColor) && + (info.channels_num == 3)) + { + for (auto y = 0u; y < m_height; ++y) + { + for (auto x = 0u; x < m_width; ++x) + { + float3 val = output_data[y * m_width + x]; + // "The 4-th pixel component is a count of accumulated samples. + // It can be different for every pixel in case of adaptive sampling. + // So, we need to normalize pixel values here". + val *= (1.f / val.w); + // gamma corection + dst_row[info.channels_num * x] = std::pow(val.x, 1.f / 2.2f); + dst_row[info.channels_num * x + 1] = std::pow(val.y, 1.f / 2.2f); + dst_row[info.channels_num * x + 2] = std::pow(val.z, 1.f / 2.2f); + } + dst_row += info.channels_num * m_width; + } + } + else + { + for (auto y = 0u; y < m_height; ++y) + { + for (auto x = 0u; x < m_width; ++x) + { + float3 val = output_data[y * m_width + x]; + // "The 4-th pixel component is a count of accumulated samples. + // It can be different for every pixel in case of adaptive sampling. + // So, we need to normalize pixel values here". + val *= (1.f / val.w); + + if (info.channels_num == 3) + { + // invert the image + dst_row[info.channels_num * x] = val.x; + dst_row[info.channels_num * x + 1] = val.y; + dst_row[info.channels_num * x + 2] = val.z; + } + else // info.channels_num = 1 + { + // invert the image + dst_row[x] = val.x; + } + } + dst_row += info.channels_num * m_width; + } + } + + auto file_name = output_dir / name; + + std::ofstream f (file_name.string(), std::ofstream::binary); + + f.write(reinterpret_cast(image_data.data()), + sizeof(float) * image_data.size()); +} + +// Enable forward declarations for types stored in unique_ptr +DataGeneratorImpl::~DataGeneratorImpl() = default; diff --git a/BaikalDataGenerator/Source/data_generator_impl.h b/BaikalDataGenerator/Source/data_generator_impl.h new file mode 100644 index 00000000..487b07c5 --- /dev/null +++ b/BaikalDataGenerator/Source/data_generator_impl.h @@ -0,0 +1,101 @@ +/********************************************************************** +Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ + +#pragma once + +#include "data_generator.h" +#include "filesystem.h" + +#include "Rpr/WrapObject/CameraObject.h" +#include "Rpr/WrapObject/LightObject.h" +#include "Rpr/WrapObject/SceneObject.h" + +#include +#include +#include + + +namespace Baikal +{ + struct ClwScene; + class ClwRenderFactory; + class Light; + class Output; + class Scene1; + class PerspectiveCamera; + class MonteCarloRenderer; + template + class SceneController; +} + +class CLWContext; +class CLWDevice; + +struct OutputInfo; + +class DataGeneratorImpl +{ +public: + // 'scene' - pointer to rpr SceneObject + // 'scene_name' - the name of the scene on disk + // 'width/height' - width/height of outputs which will be saved on disk + // 'num_bounces' - number of bounces for each ray + // 'device_idx' - index of the device to launch datagenerator on + // 'sorted_spp' - sorted collection of spp without duplications + // 'output_dir' - directory to save generated result + // 'gamma_correction_enable' - gamma correction enable flag + DataGeneratorImpl(SceneObject* scene, + std::string const& scene_name, + unsigned width, unsigned height, + unsigned num_bounces, + unsigned device_idx, + const std::vector& sorted_spp, + const std::filesystem::path& output_dir, + bool gamma_correction_enable); + + void SaveMetadata() const; + + void GenerateCameraData(CameraObject* camera, unsigned camera_idx); + + ~DataGeneratorImpl(); + +private: + void SaveOutput(const OutputInfo& info, + const std::string& name, + bool gamma_correction_enabled, + const std::filesystem::path& output_dir); + + SceneObject* m_scene = nullptr; + std::string m_scene_name; + unsigned m_width, m_height; + unsigned m_num_bounces; + unsigned m_device_idx; + std::filesystem::path m_output_dir; + std::vector m_sorted_spp; + bool m_gamma_correction_enabled; + + std::unique_ptr m_renderer; + std::unique_ptr m_factory; + std::unique_ptr> m_controller; + std::vector> m_outputs; + std::unique_ptr m_context; +}; diff --git a/BaikalDataGenerator/Source/devices.cpp b/BaikalDataGenerator/Source/devices.cpp new file mode 100644 index 00000000..aa5aa71a --- /dev/null +++ b/BaikalDataGenerator/Source/devices.cpp @@ -0,0 +1,22 @@ +#include "devices.h" + +std::vector GetDevices() +{ + std::vector devices; + + std::vector platforms; + CLWPlatform::CreateAllPlatforms(platforms); + + for (const auto& platform : platforms) + { + for (auto i = 0u; i < platform.GetDeviceCount(); i++) + { + if (platform.GetDevice(i).GetType() == CL_DEVICE_TYPE_GPU) + { + devices.push_back(platform.GetDevice(i)); + } + } + } + + return devices; +} diff --git a/BaikalDataGenerator/Source/devices.h b/BaikalDataGenerator/Source/devices.h new file mode 100644 index 00000000..fd12249e --- /dev/null +++ b/BaikalDataGenerator/Source/devices.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +#include + + +std::vector GetDevices(); diff --git a/BaikalDataGenerator/Source/filesystem.h b/BaikalDataGenerator/Source/filesystem.h new file mode 100644 index 00000000..5a3612df --- /dev/null +++ b/BaikalDataGenerator/Source/filesystem.h @@ -0,0 +1,19 @@ +#pragma once + +#if (defined(__GNUC__) && (__GNUC__ < 8)) +#include +#else +#include +#endif + +// Visual Studio 2015 and GCC 7 work-around ... +// std::filesystem was incorporated into C++-17 (which is obviously after VS +// 2015 was released). However, Microsoft implemented the draft standard in +// the std::exerimental namespace. To avoid nasty ripple effects when the +// compiler is updated, make it look like the standard here +#if (defined(_MSC_VER) && (_MSC_VER < 1900)) || (defined(__GNUC__) && (__GNUC__ < 8)) +namespace std +{ + namespace filesystem = experimental::filesystem::v1; +} +#endif \ No newline at end of file diff --git a/BaikalDataGenerator/Source/logging.cpp b/BaikalDataGenerator/Source/logging.cpp new file mode 100644 index 00000000..aaf616e9 --- /dev/null +++ b/BaikalDataGenerator/Source/logging.cpp @@ -0,0 +1,30 @@ +#include "logging.h" + +#include +#include + + +std::ostream& operator <<(std::ostream& lhs, Timestamp rhs) +{ + auto utc_time = std::time(nullptr); + auto* gm_time = std::gmtime(&utc_time); + std::array time_string; + std::strftime(time_string.data(), + time_string.size(), + rhs.format, + gm_time); + return lhs << time_string.data(); +} + +KeyValueType KeyValue(char const* key, char const* value) +{ + KeyValueType kv(key, value); + return KeyValueType(key, value); +} + +KeyValueStream operator<<(KeyValueStream lhs, KeyValueType const& rhs) +{ + *lhs.stream << lhs.delimiter << '"' << rhs.key << '"' << ": " << '"' << rhs.value << '"'; + lhs.delimiter = ", "; + return lhs; +} diff --git a/BaikalDataGenerator/Source/logging.h b/BaikalDataGenerator/Source/logging.h new file mode 100644 index 00000000..a5b6aac2 --- /dev/null +++ b/BaikalDataGenerator/Source/logging.h @@ -0,0 +1,76 @@ +#pragma once + +#include +#include + + +/** + * I/O maninpulator. Inserts a formatted daytime into an std::ostream. + * Replacement for std::put_time which is not yet supported by all compilers. + */ +struct Timestamp +{ + Timestamp(char const* format = "%Y-%m-%d %H:%M:%S") + : format(format) + { } + + char const* format; +}; + +std::ostream& operator <<(std::ostream& lhs, Timestamp rhs); + +// CEE is a JSON/XML structured log format. Search web for "cee format" for details +#define DG_LOG(INSERTERS) \ + std::cout << "[" << Timestamp() << "] @cee: {" << INSERTERS << "}" << std::endl; + + +/** + * I/O manipulator. Inserts a key string, expects a value as next string. + * All inserted values are formatted using JSON notation. + */ +template +struct KeyValueType +{ + KeyValueType(char const* key, Value value) : key(key), value(std::move(value)) { } + char const* key; + Value value; +}; + +template +KeyValueType KeyValue(char const* key, Value const& value) +{ + return KeyValueType(key, value); +} + +KeyValueType KeyValue(char const* key, char const* value); + +struct KeyValueStream +{ + explicit KeyValueStream(std::ostream& stream) : stream(&stream) { } + std::ostream* stream; + char const* delimiter = ""; +}; + +template +KeyValueStream operator<<(std::ostream& lhs, KeyValueType const& rhs) +{ + KeyValueStream stream(lhs); + return stream << rhs; +} + +template +KeyValueStream operator<<(KeyValueStream lhs, KeyValueType const& rhs) +{ + *lhs.stream << lhs.delimiter << '"' << rhs.key << '"' << ": " << rhs.value; + lhs.delimiter = ", "; + return lhs; +} + +KeyValueStream operator<<(KeyValueStream lhs, KeyValueType const& rhs); + +template +std::ostream& operator<<(KeyValueStream lhs, T const& rhs) +{ + *lhs.stream << rhs; + return *lhs.stream; +} diff --git a/BaikalDataGenerator/Source/main.cpp b/BaikalDataGenerator/Source/main.cpp new file mode 100644 index 00000000..c8236bd9 --- /dev/null +++ b/BaikalDataGenerator/Source/main.cpp @@ -0,0 +1,153 @@ +/********************************************************************** +Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + +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 "cmd_line_parser.h" +#include "data_generator.h" +#include "devices.h" +#include "logging.h" +#include "object_loader.h" +#include "utils.h" + +#include "Rpr/WrapObject/SceneObject.h" +#include "Rpr/WrapObject/CameraObject.h" +#include "Rpr/WrapObject/LightObject.h" + +#include "BaikalIO/scene_io.h" + +#include +#include + +#include "XML/tinyxml2.h" + +void SaveAppMetadata(const AppConfig& config, Range cameras_range) +{ + tinyxml2::XMLDocument doc; + + auto app_metadata_file_name = config.output_dir; + app_metadata_file_name.append("app_metadata.xml"); + + auto* root = doc.NewElement("app_metadata"); + doc.InsertFirstChild(root); + + auto* split = doc.NewElement("split"); + split->SetAttribute("split_idx", config.split_idx); + split->SetAttribute("split_num", config.split_num); + root->InsertEndChild(split); + + auto* cameras = doc.NewElement("cameras"); + cameras->SetAttribute("idx_offset", config.start_output_idx <= kDefaultStartOutputIndex ? + 0 : config.start_output_idx - static_cast(cameras_range.begin)); + cameras->SetAttribute("start_idx", static_cast(cameras_range.begin)); + cameras->SetAttribute("end_idx", static_cast(cameras_range.end - 1)); + + root->InsertEndChild(cameras); + + doc.SaveFile(app_metadata_file_name.string().c_str()); +} + +void Run(const AppConfig& config) +{ + ObjectLoader object_loader(config); + auto params = object_loader.GetDataGeneratorParams(); + bdgGenerateDataset(¶ms); +} + +int main(int argc, char* argv[]) +try +{ + auto OnCancel = [](int signal) + { + DG_LOG(KeyValue("status", "canceled") + << KeyValue("end_ts", std::time(nullptr)) + << KeyValue("signal", signal)); + std::exit(-1); + }; +#ifdef WIN32 + std::signal(SIGBREAK, OnCancel); +#endif + std::signal(SIGINT, OnCancel); + std::signal(SIGTERM, OnCancel); + + auto OnFailure = [](int signal) + { + DG_LOG(KeyValue("status", "failed") + << KeyValue("end_ts", std::time(nullptr)) + << KeyValue("signal", signal)); + }; + std::signal(SIGABRT, OnFailure); + std::signal(SIGFPE, OnFailure); + std::signal(SIGILL, OnFailure); + std::signal(SIGSEGV, OnFailure); + + CmdLineParser cmd_parser(argc, argv); + + if (cmd_parser.HasHelpOption()) + { + cmd_parser.ShowHelp(); + return 0; + } + + if (cmd_parser.HasListDevicesOption()) + { + std::cout << "Device list:\n"; + auto devices = GetDevices(); + for (std::size_t idx = 0; idx < devices.size(); ++idx) + { + DG_LOG(KeyValue("idx", idx) + << KeyValue("name", devices[idx].GetName()) + << KeyValue("vendor", devices[idx].GetVendor()) + << KeyValue("version", devices[idx].GetVersion())); + } + return 0; + } + + DG_LOG(KeyValue("status", "running") << KeyValue("start_ts", std::time(nullptr))); + + auto config = cmd_parser.Parse(); + ObjectLoader object_loader(config); + auto params = object_loader.GetDataGeneratorParams(); + + SaveAppMetadata(config, object_loader.GetCamerasRange()); + + auto progress_callback = [](unsigned, unsigned camera_idx, unsigned) + { + DG_LOG(KeyValue("event", "generated") + << KeyValue("status", "generating") + << KeyValue("camera_idx", camera_idx)); + }; + + params.progress_callback = progress_callback; + + auto result = bdgGenerateDataset(¶ms); + if (result != kDataGeneratorSuccess) + { + THROW_EX("Generation failed: result=" << result); + } + + DG_LOG(KeyValue("status", "finished") << KeyValue("end_ts", std::time(nullptr))); +} +catch (std::exception& ex) +{ + DG_LOG(KeyValue("status", "failed") << KeyValue("end_ts", std::time(nullptr))); + std::cout << ex.what() << std::endl; + return -1; +} diff --git a/BaikalDataGenerator/Source/object_loader.cpp b/BaikalDataGenerator/Source/object_loader.cpp new file mode 100644 index 00000000..4fc48e4c --- /dev/null +++ b/BaikalDataGenerator/Source/object_loader.cpp @@ -0,0 +1,394 @@ +/********************************************************************** +Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + +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 "object_loader.h" + +#include "Rpr/RadeonProRender.h" +#include "Rpr/WrapObject/Materials/MaterialObject.h" + +#include "BaikalIO/image_io.h" +#include "BaikalIO/material_io.h" +#include "BaikalIO/scene_io.h" + +#include "utils.h" + +#include "XML/tinyxml2.h" + +#include +#include +#include + + +// validation checks helper macroses to reduce copy paste +#define ASSERT_PATH(file_name) \ + if (file_name.empty()) \ + { \ + THROW_EX("Missing: " << file_name.string()) \ + } + +#define ASSERT_XML(file_name) \ + if (file_name.extension() != ".xml") \ + { \ + THROW_EX("Not and XML file: " << file_name.string()) \ + } + +#define ASSERT_FILE_EXISTS(file_name) \ + if (!std::filesystem::exists(file_name)) \ + { \ + THROW_EX("File not found: " << file_name.string()) \ + } \ + +namespace { + + const std::unordered_map kLightTypesMap + { + { "point", LightObject::Type::kPointLight }, + { "spot", LightObject::Type::kSpotLight }, + { "direct", LightObject::Type::kDirectionalLight }, + { "ibl", LightObject::Type::kEnvironmentLight }, + }; + + void ValidateConfig(const AppConfig& config) + { + // validate input config + ASSERT_PATH(config.camera_file); + ASSERT_PATH(config.light_file); + ASSERT_PATH(config.spp_file); + ASSERT_PATH(config.scene_file); + ASSERT_PATH(config.output_dir); + + // validate extensions + ASSERT_XML(config.camera_file) + ASSERT_XML(config.light_file) + ASSERT_XML(config.spp_file) + + // validate that files really exists + ASSERT_FILE_EXISTS(config.camera_file) + ASSERT_FILE_EXISTS(config.light_file) + ASSERT_FILE_EXISTS(config.spp_file) + ASSERT_FILE_EXISTS(config.scene_file) + + if (!std::filesystem::is_directory(config.output_dir)) + { + THROW_EX("Not a directory: " << config.output_dir.string()) + } + + if (config.split_num == 0) + { + THROW_EX("'split_num' should be positive"); + } + + if (config.split_idx >= config.split_num) + { + THROW_EX("'split_idx' must be less than split_num"); + } + } + + Range GetSplitByIdx(unsigned total_num, unsigned subrange_num, unsigned subrange_idx) + { + unsigned length = total_num / subrange_num; + unsigned remain = total_num % subrange_num; + + unsigned begin = 0; + unsigned end = 0; + + if (subrange_idx < remain) + { + begin = subrange_idx * (length + 1); + end = begin + length + 1; + } + else + { + begin = subrange_idx * length + remain; + end = begin + length; + } + return {begin, end}; + } + +} // namespace + + +ObjectLoader::ObjectLoader(const AppConfig& config) +: m_app_config(config) +{ + ValidateConfig(m_app_config); + + m_output_dir = m_app_config.output_dir.string(); + m_scene_name = m_app_config.scene_file.string(); + + LoadScene(); + LoadCameras(); + LoadLights(); + LoadSpp(); +} + +Range ObjectLoader::GetCamerasRange() const +{ + return m_cameras_idx_range; +} + +DataGeneratorParams ObjectLoader::GetDataGeneratorParams() +{ + DataGeneratorParams params{}; + + params.output_dir = m_output_dir.c_str(); + params.scene = &m_scene; + params.scene_name = m_scene_name.c_str(); + params.cameras = m_rpr_cameras.data(); + params.cameras_num = static_cast(m_rpr_cameras.size()); + params.cameras_start_output_idx = (m_app_config.start_output_idx <= kDefaultStartOutputIndex) ? + m_cameras_idx_range.begin : m_app_config.start_output_idx; + params.lights = m_rpr_lights.data(); + params.lights_num = static_cast(m_rpr_lights.size()); + params.spp = m_spp.data(); + params.spp_num = static_cast(m_spp.size()); + params.width = m_app_config.width; + params.height = m_app_config.height; + params.bounces_num = m_app_config.num_bounces; + params.device_idx = m_app_config.device_idx; + params.gamma_correction = m_app_config.gamma_correction ? 1 : 0; + + return params; +} + +void ObjectLoader::LoadScene() +{ + if (!std::filesystem::exists(m_app_config.scene_file)) + { + THROW_EX("There is no any scene file to load"); + } + + // workaround to avoid issues with tiny_object_loader + auto scene_dir = m_app_config.scene_file.parent_path().string(); + + // Baikal::SceneIO requires a trailing delimiter +#ifdef WIN32 + scene_dir.append("\\"); +#else + scene_dir.append("/"); +#endif + + m_scene.SetScene(Baikal::SceneIo::LoadScene(m_app_config.scene_file.string(), scene_dir)); + + // load materials.xml if it exists + auto materials_file = m_app_config.scene_file.parent_path() / "materials.xml"; + auto mapping_file = m_app_config.scene_file.parent_path() / "mapping.xml"; + + if (std::filesystem::exists(materials_file) && + std::filesystem::exists(mapping_file)) + { + auto material_io = Baikal::MaterialIo::CreateMaterialIoXML(); + auto materials = material_io->LoadMaterials(materials_file.string()); + auto mapping = material_io->LoadMaterialMapping(mapping_file.string()); + + material_io->ReplaceSceneMaterials(*m_scene.GetScene(), *materials, mapping); + } + else + { + std::cout << "WARNING: materials.xml or mapping.xml is missed" << std::endl; + } +} + +void ObjectLoader::LoadCameras() +{ + tinyxml2::XMLDocument doc; + doc.LoadFile(m_app_config.camera_file.string().c_str()); + + auto root = doc.FirstChildElement("cam_list"); + + if (!root) + { + THROW_EX("Failed to open cameras set file: " << m_app_config.camera_file.string()) + } + + auto* elem = root->FirstChildElement("camera"); + + while (elem) + { + RadeonRays::float3 eye; + eye.x = elem->FloatAttribute("cpx"); + eye.y = elem->FloatAttribute("cpy"); + eye.z = elem->FloatAttribute("cpz"); + + RadeonRays::float3 at; + at.x = elem->FloatAttribute("tpx"); + at.y = elem->FloatAttribute("tpy"); + at.z = elem->FloatAttribute("tpz"); + + RadeonRays::float3 up; + up.x = elem->FloatAttribute("upx"); + up.y = elem->FloatAttribute("upy"); + up.z = elem->FloatAttribute("upz"); + + if (up.sqnorm() == 0.f) + { + up = RadeonRays::float3(0.f, 1.f, 0.f); + } + + CameraObject camera; + camera.LookAt(eye, at, up); + + // default sensor width + float sensor_width = 0.036f; + float sensor_height = static_cast(m_app_config.height) / + m_app_config.width * sensor_width; + + camera.SetSensorSize(RadeonRays::float2(0.036f, sensor_height)); + camera.SetFocalLength(elem->FloatAttribute("focal_length")); + camera.SetFocusDistance(elem->FloatAttribute("focus_dist")); + camera.SetAperture(elem->FloatAttribute("aperture")); + m_cameras.push_back(std::move(camera)); + + elem = elem->NextSiblingElement("camera"); + } + + if (m_app_config.split_num > m_cameras.size()) + { + THROW_EX("'split_num': must be less than camera number") + } + + // Split cameras to split_num subsets and leave + // the subset with the index split_idx only + m_cameras_idx_range = GetSplitByIdx(static_cast(m_cameras.size()), + m_app_config.split_num, + m_app_config.split_idx); + m_cameras.erase(m_cameras.begin() + m_cameras_idx_range.end, m_cameras.end()); + m_cameras.erase(m_cameras.begin(), m_cameras.begin() + m_cameras_idx_range.begin); + for (auto& camera : m_cameras) + { + m_rpr_cameras.push_back(&camera); + } +} + +void ObjectLoader::LoadLights() +{ + tinyxml2::XMLDocument doc; + doc.LoadFile(m_app_config.light_file.string().c_str()); + auto root = doc.FirstChildElement("light_list"); + + if (!root) + { + THROW_EX("Failed to open lights set file: " << m_app_config.light_file.string()) + } + + auto* elem = root->FirstChildElement("light"); + + while (elem) + { + std::unique_ptr light; + + std::string type_name = elem->Attribute("type"); + try + { + auto light_type = kLightTypesMap.at(elem->Attribute("type")); + light = std::make_unique(light_type); + } + catch (std::out_of_range&) + { + THROW_EX("Unsupported light type: " << type_name) + } + + switch (light->GetType()) + { + case LightObject::Type::kSpotLight: + { + //this option available only for spot light + auto csx = elem->FloatAttribute("csx"); + auto csy = elem->FloatAttribute("csy"); + + light->SetSpotConeShape(RadeonRays::float2(csx, csy)); + break; + } + case LightObject::Type::kEnvironmentLight: + { + //this options available only for ibl + auto multiplier = elem->FloatAttribute("mul"); + std::filesystem::path texture_path = elem->Attribute("tex"); + // find texture path and check that it exists + if (texture_path.is_relative()) + { + auto lights_dir = m_app_config.light_file.parent_path(); + texture_path = lights_dir / texture_path; + } + if (!std::filesystem::exists(texture_path)) + { + THROW_EX("Texture image not found: " << texture_path.string()) + } + + auto texture = MaterialObject::CreateImage(texture_path.string()); + light->SetEnvTexture(texture); + light->SetEnvMultiplier(multiplier); + break; + } + default: + break; + } + + RadeonRays::float3 position; + position.x = elem->FloatAttribute("posx"); + position.y = elem->FloatAttribute("posy"); + position.z = elem->FloatAttribute("posz"); + light->SetPosition(position); + + RadeonRays::float3 direction; + direction.x = elem->FloatAttribute("dirx"); + direction.y = elem->FloatAttribute("diry"); + direction.z = elem->FloatAttribute("dirz"); + light->SetDirection(direction); + + RadeonRays::float3 radiance; + radiance.x = elem->FloatAttribute("radx"); + radiance.y = elem->FloatAttribute("rady"); + radiance.z = elem->FloatAttribute("radz"); + light->SetRadiantPower(radiance); + + m_lights.push_back(std::move(*light)); + + elem = elem->NextSiblingElement("light"); + } + + for (auto& light : m_lights) + { + m_rpr_lights.push_back(&light); + } +} + +void ObjectLoader::LoadSpp() +{ + tinyxml2::XMLDocument doc; + doc.LoadFile(m_app_config.spp_file.string().c_str()); + auto root = doc.FirstChildElement("spp_list"); + + if (!root) + { + THROW_EX("Failed to open SPP file: " << m_app_config.spp_file.string()) + } + + tinyxml2::XMLElement* elem = root->FirstChildElement("spp"); + + while (elem) + { + auto spp = elem->Int64Attribute("iter_num"); + m_spp.push_back(static_cast(spp)); + elem = elem->NextSiblingElement("spp"); + } +} \ No newline at end of file diff --git a/BaikalDataGenerator/Source/object_loader.h b/BaikalDataGenerator/Source/object_loader.h new file mode 100644 index 00000000..fdefee1a --- /dev/null +++ b/BaikalDataGenerator/Source/object_loader.h @@ -0,0 +1,69 @@ +/********************************************************************** +Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ + +#pragma once + +#include "app_config.h" +#include "data_generator.h" + +#include "Rpr/WrapObject/CameraObject.h" +#include "Rpr/WrapObject/LightObject.h" +#include "Rpr/WrapObject/SceneObject.h" + +#include + +#include + +struct Range +{ + unsigned begin; // inclusive + unsigned end; // exclusive +}; + +class ObjectLoader +{ +public: + explicit ObjectLoader(const AppConfig& config); + + DataGeneratorParams GetDataGeneratorParams(); + + Range GetCamerasRange() const; +private: + void LoadScene(); + void LoadCameras(); + void LoadLights(); + void LoadSpp(); + + AppConfig m_app_config; + SceneObject m_scene; + std::vector m_cameras; + std::vector m_lights; + std::vector m_spp; + + // DataGeneratorParams data cache + std::string m_output_dir; + std::string m_scene_name; + std::vector m_rpr_cameras; + std::vector m_rpr_lights; + + Range m_cameras_idx_range; +}; diff --git a/BaikalDataGenerator/Source/utils.h b/BaikalDataGenerator/Source/utils.h new file mode 100644 index 00000000..d654045a --- /dev/null +++ b/BaikalDataGenerator/Source/utils.h @@ -0,0 +1,34 @@ +/********************************************************************** +Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ + +#pragma once + +#include +#include + + +#define THROW_EX(insertions) \ + { \ + std::ostringstream stream; \ + stream << std::string(__func__) << ": " << insertions; \ + throw std::runtime_error(stream.str()); \ + } diff --git a/BaikalIO/CMakeLists.txt b/BaikalIO/CMakeLists.txt new file mode 100644 index 00000000..a5ac46f0 --- /dev/null +++ b/BaikalIO/CMakeLists.txt @@ -0,0 +1,48 @@ +set(SOURCES + image_io.cpp + image_io.h + material_io.cpp + material_io.h + scene_binary_io.cpp + scene_binary_io.h + scene_io.cpp + scene_io.h + scene_test_io.cpp + scene_obj_io.cpp + ) + +if (UNIX AND NOT APPLE) + list(APPEND SOURCES + file_utils.cpp + file_utils.h + ) +endif () + +if (BAIKAL_ENABLE_FBX) + list(APPEND SOURCES scene_fbx_io.cpp) +endif (BAIKAL_ENABLE_FBX) + +add_library(BaikalIO SHARED ${SOURCES}) + +target_compile_definitions(BaikalIO PRIVATE BAIKAL_EXPORT_API) +target_compile_features(BaikalIO PRIVATE cxx_std_14) +target_link_libraries(BaikalIO PUBLIC Baikal OpenImageIO::OpenImageIO) + +if (UNIX AND NOT APPLE) + target_link_libraries(BaikalIO PUBLIC stdc++fs) +endif () + +target_include_directories(BaikalIO PUBLIC "${Baikal_SOURCE_DIR}/BaikalIO" "${Baikal_SOURCE_DIR}/3rdparty/tinyobjloader/include") + +if (BAIKAL_ENABLE_FBX) + target_link_libraries(BaikalIO PUBLIC fbxsdk::fbxsdk) +endif (BAIKAL_ENABLE_FBX) + +add_dependencies(BaikalIO ResourcesDir Copy3rdParty) + +# Install target +if (WIN32) + install(TARGETS BaikalIO RUNTIME DESTINATION bin) +else () + install(TARGETS BaikalIO LIBRARY DESTINATION lib) +endif () diff --git a/BaikalIO/file_utils.cpp b/BaikalIO/file_utils.cpp new file mode 100644 index 00000000..477a0683 --- /dev/null +++ b/BaikalIO/file_utils.cpp @@ -0,0 +1,150 @@ +#include +#include +#include + +namespace Baikal +{ + inline bool is_dot(std::experimental::filesystem::path const &path) + { + std::string const &filename = path.string(); + return filename.size() == 1 && filename[0] == '.'; + } + + inline bool is_dotdot(std::experimental::filesystem::path const &path) + { + std::string const &filename = path.string(); + return filename.size() == 2 && filename[0] == '.' && filename[1] == '.'; + } + + bool FindFilenameFromCaseInsensitive(std::string const &req_filename, std::string &actual_filename, bool resolve_symlinks = true) + { + const std::experimental::filesystem::path file_path(req_filename); + + // First, check if file with required filename exists + if (std::experimental::filesystem::exists(file_path)) + { + actual_filename = req_filename; + return true; + } + + // Split path to components + std::deque components; + for (auto &f : file_path.relative_path()) + { + components.push_back(f); + } + + // Start from the current directory + std::experimental::filesystem::path result = std::experimental::filesystem::current_path(); + + while (!components.empty()) + { + // Get a path component + std::experimental::filesystem::path c = std::move(components.front()); + components.pop_front(); + + if (is_dot(c)) // /. + { + // Ensure that this is a directory and skip the dot + if (!std::experimental::filesystem::is_directory(result)) + { + // Is not a directory + return false; + } + } + else if (is_dotdot(c)) // /.. + { + result /= c; + if (!std::experimental::filesystem::exists(result)) + { + // Upper directory is not exist + return false; + } + } + else // / + { + // The path doesn't exist + if (!std::experimental::filesystem::exists(result / c)) + { + // Path in this letter case doesn't exist... + // But we'll try to find it in another case + bool component_found = false; + + if (!std::experimental::filesystem::is_directory(result)) + { + // Something went wrong, we're not in a directory + return false; + } + + for (auto const &entry : std::experimental::filesystem::directory_iterator(result)) + { + // Get only name of the folder/file + std::experimental::filesystem::path found_name = entry.path().filename(); + + // Move to lower case and compare path strings + std::string path_str = found_name.string(); + std::transform(path_str.begin(), path_str.end(), path_str.begin(), ::tolower); + + std::string req_str = c.string(); + std::transform(req_str.begin(), req_str.end(), req_str.begin(), ::tolower); + + if (path_str == req_str) + { + // Found! + component_found = true; + result /= found_name; + break; + } + } + + // Give up, the path really doesn't exist + if (!component_found) + { + return false; + } + } + else + { + // If the path exists, simply concatenate the result with the component + result /= c; + } + + // If the result is a symbolic link, resolve it + if (std::experimental::filesystem::is_symlink(result) && resolve_symlinks) + { + // Get a target of the link + std::experimental::filesystem::path target = std::experimental::filesystem::read_symlink(result); + + if (target.is_absolute()) + { + // The target is an absolute path + // Start from the root folder on the next iteration + result = target.root_path(); + // And remove the root folder + target = target.relative_path(); + } + else + { + // If the target is a relative path + // Start from the base folder of the link on the next iteration + result.remove_filename(); + } + + // Push resolved components of the link to the container + components.insert(components.begin(), target.begin(), target.end()); + } + } + } + + // Final check + if (!std::experimental::filesystem::exists(result)) + { + return false; + } + + actual_filename = result.string(); + + return true; + } + +} // namespace Baikal diff --git a/BaikalIO/file_utils.h b/BaikalIO/file_utils.h new file mode 100644 index 00000000..c3b0e03e --- /dev/null +++ b/BaikalIO/file_utils.h @@ -0,0 +1,6 @@ +#include + +namespace Baikal +{ + bool FindFilenameFromCaseInsensitive(std::string const& req_filename, std::string & actual_filename, bool resolve_symlinks = true); +} diff --git a/BaikalIO/image_io.cpp b/BaikalIO/image_io.cpp new file mode 100644 index 00000000..9dc9fb51 --- /dev/null +++ b/BaikalIO/image_io.cpp @@ -0,0 +1,154 @@ +#include "image_io.h" +#include "SceneGraph/texture.h" + +#include "OpenImageIO/imageio.h" + +#ifdef __linux__ +#include "file_utils.h" +#endif + +namespace Baikal +{ + class Oiio : public ImageIo + { + public: + Texture::Ptr LoadImage(std::string const& filename) const override; + void SaveImage(std::string const& filename, Texture::Ptr texture) const override; + }; + + static Texture::Format GetTextureFormat(OIIO_NAMESPACE::ImageSpec const& spec) + { + OIIO_NAMESPACE_USING + + if (spec.format.basetype == TypeDesc::UINT8) + return Texture::Format::kRgba8; + else if (spec.format.basetype == TypeDesc::HALF) + return Texture::Format::kRgba16; + else + return Texture::Format::kRgba32; + } + + static OIIO_NAMESPACE::TypeDesc GetTextureFormat(Texture::Format fmt) + { + OIIO_NAMESPACE_USING + + if (fmt == Texture::Format::kRgba8) + return TypeDesc::UINT8; + else if (fmt == Texture::Format::kRgba16) + return TypeDesc::HALF; + else + return TypeDesc::FLOAT; + } + + Texture::Ptr Oiio::LoadImage(const std::string &filename) const + { + OIIO_NAMESPACE_USING + + std::string actual_filename = filename; + +#ifdef __linux__ + if (!FindFilenameFromCaseInsensitive(filename, actual_filename)) + { + throw std::runtime_error("Image " + filename + " doesn't exist"); + } +#endif + + std::unique_ptr input{ImageInput::open(actual_filename)}; + + if (!input) + { + throw std::runtime_error("Can't load " + filename + " image"); + } + + ImageSpec const& spec = input->spec(); + + auto fmt = GetTextureFormat(spec); + char* texturedata = nullptr; + + if (fmt == Texture::Format::kRgba8) + { + auto size = spec.width * spec.height * spec.depth * 4; + + texturedata = new char[size]; + memset(texturedata, 0, size); + + // Read data to storage + input->read_image(TypeDesc::UINT8, texturedata, sizeof(char) * 4); + + if (spec.nchannels == 1) + { + // set B, G and A components to + for (auto i = 0; i < size; i += 4) + { + texturedata[i + 1] = texturedata[i]; + texturedata[i + 2] = texturedata[i]; + texturedata[i + 3] = texturedata[i]; + } + + } + + // Close handle + input->close(); + } + else if (fmt == Texture::Format::kRgba16) + { + auto size = spec.width * spec.height * spec.depth * sizeof(float) * 2; + + // Resize storage + texturedata = new char[size]; + memset(texturedata, 0, size); + + // Read data to storage + input->read_image(TypeDesc::HALF, texturedata, sizeof(float) * 2); + + // Close handle + input->close(); + } + else + { + auto size = spec.width * spec.height * spec.depth * sizeof(RadeonRays::float3); + + // Resize storage + texturedata = new char[size]; + memset(texturedata, 0, size); + + // Read data to storage + input->read_image(TypeDesc::FLOAT, texturedata, sizeof(RadeonRays::float3)); + + // Close handle + input->close(); + } + + auto tex = Texture::Create(texturedata, RadeonRays::int3(spec.width, spec.height, spec.depth), fmt);; + tex->SetName(filename); + return tex; + } + + void Oiio::SaveImage(std::string const& filename, Texture::Ptr texture) const + { + OIIO_NAMESPACE_USING; + + std::unique_ptr out{ImageOutput::create(filename)}; + + if (!out) + { + throw std::runtime_error("Can't create image file on disk"); + } + + auto dim = texture->GetSize(); + auto fmt = GetTextureFormat(texture->GetFormat()); + + ImageSpec spec(dim.x, dim.y, 4, fmt); + + out->open(filename, spec); + + out->write_image(fmt, texture->GetData()); + + out->close(); + } + + std::unique_ptr ImageIo::CreateImageIo() + { + return std::make_unique(); + } +} diff --git a/Baikal/SceneGraph/IO/scene_io.h b/BaikalIO/image_io.h similarity index 60% rename from Baikal/SceneGraph/IO/scene_io.h rename to BaikalIO/image_io.h index f8f7a36b..7308a629 100644 --- a/Baikal/SceneGraph/IO/scene_io.h +++ b/BaikalIO/image_io.h @@ -21,46 +21,56 @@ ********************************************************************/ /** - \file scene_io.h + \file image_io.h \author Dmitry Kozlov \version 1.0 - \brief Contains an interface for scene loading + \brief */ #pragma once #include +#include + +#include "SceneGraph/texture.h" + +#ifdef WIN32 +#ifdef BAIKAL_EXPORT_API +#define BAIKAL_API_ENTRY __declspec(dllexport) +#else +#define BAIKAL_API_ENTRY __declspec(dllimport) +#endif +#else +#define BAIKAL_API_ENTRY __attribute__((visibility ("default"))) +#endif namespace Baikal { - class Scene1; + class Texture; /** - \brief Interface for scene loading + \brief Interface for image loading and writing - SceneIO implementation is responsible for translation of various scene formats into Baikal. + ImageIO is responsible for texture loading from disk and keeping track of image reuse. */ - class SceneIo + class BAIKAL_API_ENTRY ImageIo { public: - // Create OBJ scene loader - static SceneIo* CreateSceneIoObj(); - // Create test scene loader - static SceneIo* CreateSceneIoTest(); - + // Create default image IO + static std::unique_ptr CreateImageIo(); + // Constructor - SceneIo() = default; + ImageIo() = default; // Destructor - virtual ~SceneIo() = 0; + virtual ~ImageIo() = default; - // Load the scene from file using resourse base path - virtual Scene1* LoadScene(std::string const& filename, std::string const& basepath) const = 0; + // Load texture from file + virtual Texture::Ptr LoadImage(std::string const& filename) const = 0; + virtual void SaveImage(std::string const& filename, Texture::Ptr texture) const = 0; // Disallow copying - SceneIo(SceneIo const&) = delete; - SceneIo& operator = (SceneIo const&) = delete; + ImageIo(ImageIo const&) = delete; + ImageIo& operator = (ImageIo const&) = delete; }; - inline SceneIo::~SceneIo() - { - } + } diff --git a/BaikalIO/material_io.cpp b/BaikalIO/material_io.cpp new file mode 100644 index 00000000..0261299e --- /dev/null +++ b/BaikalIO/material_io.cpp @@ -0,0 +1,844 @@ +#include "material_io.h" + +#include "SceneGraph/scene1.h" +#include "SceneGraph/iterator.h" +#include "SceneGraph/shape.h" +#include "SceneGraph/material.h" +#include "SceneGraph/Collector/collector.h" +#include "SceneGraph/uberv2material.h" +#include "SceneGraph/inputmaps.h" + +#include "image_io.h" + +#include "XML/tinyxml2.h" + +#include +#include +#include +#include +#include + +namespace Baikal +{ + using namespace tinyxml2; + + // XML based material IO implememtation + class MaterialIoXML : public MaterialIo + { + public: + // Save materials to disk + void SaveMaterials(std::string const& filename, Iterator& iterator) override; + + // Load materials from disk + std::unique_ptr LoadMaterials(std::string const& file_name) override; + + private: + // Write single material + void WriteMaterial(ImageIo& io, XMLPrinter& printer, Material::Ptr material); + // Write single InputMap + void WriteInputMap(ImageIo& io, XMLPrinter& printer, InputMap::Ptr inputMap); + + // Load inputs + InputMap::Ptr LoadInputMap(ImageIo& io, XMLElement* element, + const std::map &input_map_cache, + std::map &loaded_inputs); + // Load single material + Material::Ptr LoadMaterial(ImageIo& io, XMLElement& element, const std::map &loaded_inputs); + + // Texture to name map + std::map m_tex2name; + + std::map m_name2tex; + std::map m_id2mat; + std::set m_saved_inputs; + + struct ResolveRequest + { + Material::Ptr material; + std::string input; + std::uint64_t id; + + bool operator < (ResolveRequest const& rhs) const + { + return id < rhs.id; + } + }; + + std::set m_resolve_requests; + std::string m_base_path; + + template + InputMap::Ptr LoadTwoArgInput(ImageIo& io, XMLElement* element, + const std::map &input_map_cache, + std::map &loaded_inputs) + { + uint32_t arg1_id = element->UnsignedAttribute("input0"); + uint32_t arg2_id = element->UnsignedAttribute("input1"); + InputMap::Ptr arg1 = LoadInputMap(io, input_map_cache.at(arg1_id), input_map_cache, loaded_inputs); + InputMap::Ptr arg2 = LoadInputMap(io, input_map_cache.at(arg2_id), input_map_cache, loaded_inputs); + + return T::Create(arg1, arg2); + } + + template + InputMap::Ptr LoadOneArgInput(ImageIo& io, XMLElement* element, + const std::map &input_map_cache, + std::map &loaded_inputs) + { + uint32_t arg1_id = element->UnsignedAttribute("input0"); + InputMap::Ptr arg1 = LoadInputMap(io, input_map_cache.at(arg1_id), input_map_cache, loaded_inputs); + + return T::Create(arg1); + } + + }; + + std::unique_ptr MaterialIo::CreateMaterialIoXML() + { + return std::make_unique(); + } + + static std::string Float4ToString(RadeonRays::float3 const& v) + { + std::ostringstream oss; + oss << v.x << " " << v.y << " " << v.z << " " << v.w; + return oss.str(); + } + + static std::string MatrixToString(RadeonRays::matrix const& v) + { + std::ostringstream oss; + for (int i = 0; i < 4; ++i) + { + for (int j = 0; j < 4; ++j) + { + oss << v.m[i][j] << " "; + } + } + return oss.str(); + } + + static std::string ArrayToString(uint32_t *array, uint32_t size) + { + std::ostringstream oss; + for (auto a = 0u; a < size; ++a) + { + oss << array[a] << " "; + } + return oss.str(); + } + + void MaterialIoXML::WriteMaterial(ImageIo& io, XMLPrinter& printer, Material::Ptr material) + { + printer.OpenElement("Material"); + + printer.PushAttribute("name", material->GetName().c_str()); + printer.PushAttribute("id", (int)(reinterpret_cast(material.get()))); + printer.PushAttribute("thin", material->IsThin()); + + auto uberv2_material = std::dynamic_pointer_cast(material); + + if (uberv2_material) + { + //Write properties + printer.PushAttribute("refraction_link_ior", uberv2_material->IsLinkRefractionIOR()); + printer.PushAttribute("emission_doublesided", uberv2_material->isDoubleSided()); + printer.PushAttribute("sss_multyscatter", uberv2_material->IsMultiscatter()); + printer.PushAttribute("layers", uberv2_material->GetLayers()); + + auto num_inputs = uberv2_material->GetNumInputs(); + for (size_t a = 0; a < num_inputs; ++a) + { + auto input = uberv2_material->GetInput(static_cast(a)); + if (!uberv2_material->IsActive(input)) + { + continue; + } + printer.PushAttribute(input.info.name.c_str(), input.value.input_map_value->GetId()); + } + } + else + { + assert(!"Only UberV2 materials supported"); + } + + printer.CloseElement(); + } + + void MaterialIoXML::SaveMaterials(std::string const& filename, Iterator& mat_iter) + { + auto slash = filename.find_last_of('/'); + if (slash == std::string::npos) slash = filename.find_last_of('\\'); + if (slash != std::string::npos) + m_base_path.assign(filename.cbegin(), filename.cbegin() + slash + 1); + else + m_base_path.clear(); + + XMLDocument doc; + XMLPrinter printer; + + m_tex2name.clear(); + + auto image_io = ImageIo::CreateImageIo(); + + std::set input_maps; + + // Collect all unique material inputs + for (mat_iter.Reset(); mat_iter.IsValid(); mat_iter.Next()) + { + auto material = mat_iter.ItemAs(); + if (material) + { + auto input_map_iter = material->CreateInputMapsIterator(); + for (input_map_iter->Reset(); input_map_iter->IsValid(); input_map_iter->Next()) + { + auto input_map = input_map_iter->ItemAs(); + input_maps.insert(input_map); + } + } + } + printer.OpenElement("Inputs"); + for (auto input_map : input_maps) + { + WriteInputMap(*image_io, printer, input_map); + } + printer.CloseElement(); + + printer.OpenElement("Materials"); + for (mat_iter.Reset();mat_iter.IsValid(); mat_iter.Next()) + { + auto material = mat_iter.ItemAs(); + + if (material) + { + WriteMaterial(*image_io, printer, material); + } + } + printer.CloseElement(); + + doc.Parse(printer.CStr()); + + doc.SaveFile(filename.c_str()); + } + + Material::Ptr MaterialIoXML::LoadMaterial(ImageIo& io, XMLElement& element, const std::map &loaded_inputs) + { + std::string name(element.Attribute("name")); + + auto attribute_thin = element.Attribute("thin"); + std::string thin(attribute_thin ? attribute_thin : ""); + auto id = static_cast(std::atoi(element.Attribute("id"))); + + UberV2Material::Ptr material = UberV2Material::Create(); + material->SetLayers(std::atoi(element.Attribute("layers"))); + material->SetThin(thin == "true"); + material->SetDoubleSided(strcmp(element.Attribute("emission_doublesided"), "true") == 0); + material->LinkRefractionIOR(strcmp(element.Attribute("refraction_link_ior"), "true") == 0); + material->SetMultiscatter(strcmp(element.Attribute("sss_multyscatter"), "true") == 0); + material->SetName(name); + + auto num_inputs = material->GetNumInputs(); + for (std::size_t a = 0u; a < num_inputs; ++a) + { + auto inputs = material->GetInput(a); + if (!material->IsActive(inputs)) + { + continue; + } + uint32_t input_id = element.UnsignedAttribute(inputs.info.name.c_str()); + material->SetInputValue(inputs.info.name, loaded_inputs.at(input_id)); + } + + m_id2mat[id] = material; + + return material; + } + + std::unique_ptr MaterialIoXML::LoadMaterials(std::string const& file_name) + { + m_id2mat.clear(); + m_name2tex.clear(); + m_resolve_requests.clear(); + + auto slash = file_name.find_last_of('/'); + if (slash == std::string::npos) slash = file_name.find_last_of('\\'); + if (slash != std::string::npos) + m_base_path.assign(file_name.cbegin(), file_name.cbegin() + slash + 1); + else + m_base_path.clear(); + + XMLDocument doc; + doc.LoadFile(file_name.c_str()); + + auto image_io = ImageIo::CreateImageIo(); + + std::map input_map_cache; + auto inputs = doc.FirstChildElement("Inputs"); + for (auto element = inputs->FirstChildElement(); element; element = element->NextSiblingElement()) + { + uint32_t id = element->UnsignedAttribute("id"); + input_map_cache.insert(std::make_pair(id, element)); + } + + std::map loaded_elements; + for (auto element = inputs->FirstChildElement(); element; element = element->NextSiblingElement()) + { + LoadInputMap(*image_io, element, input_map_cache, loaded_elements); + } + + std::set materials; + auto materials_node = doc.FirstChildElement("Materials"); + for (auto element = materials_node->FirstChildElement(); element; element = element->NextSiblingElement()) + { + auto material = LoadMaterial(*image_io, *element, loaded_elements); + materials.insert(material); + } + + // Fix up non-resolved stuff + for (auto& i : m_resolve_requests) + { + i.material->SetInputValue(i.input, m_id2mat[i.id]); + } + + return std::make_unique>>(std::move(materials)); + } + + void MaterialIo::SaveMaterialsFromScene(std::string const& filename, Scene1 const& scene) + { + auto shape_iter = scene.CreateShapeIterator(); + + Collector mat_collector; + // Collect materials from shapes first + mat_collector.Collect(*shape_iter, + // This function adds all materials to resulting map + // recursively via Material dependency API + [](SceneObject::Ptr item) -> std::set + { + // Resulting material set + std::set mats; + // Material stack + std::stack material_stack; + + // Get material from current shape + auto shape = std::static_pointer_cast(item); + auto material = shape->GetMaterial(); + + if (material) + { + // Push to stack as an initializer + material_stack.push(material); + } + + // Drain the stack + while (!material_stack.empty()) + { + // Get current material + auto m = material_stack.top(); + material_stack.pop(); + + // Emplace into the set + mats.emplace(m); + + // Create dependency iterator + std::unique_ptr mat_iter = m->CreateMaterialIterator(); + + // Push all dependencies into the stack + for (; mat_iter->IsValid(); mat_iter->Next()) + { + material_stack.push(mat_iter->ItemAs()); + } + } + + // Return resulting set + return mats; + }); + + auto mat_iter = mat_collector.CreateIterator(); + + SaveMaterials(filename, *mat_iter); + } + + void MaterialIo::ReplaceSceneMaterials(Scene1& scene, Iterator& iterator, MaterialMap const& mapping) + { + std::map name2mat; + + for (iterator.Reset(); iterator.IsValid(); iterator.Next()) + { + auto material = iterator.ItemAs(); + auto name = material->GetName(); + name2mat[name] = material; + } + + auto shape_iter = scene.CreateShapeIterator(); + + for (; shape_iter->IsValid(); shape_iter->Next()) + { + auto shape = shape_iter->ItemAs(); + auto material = shape->GetMaterial(); + + if (!material) + continue; + + auto name = material->GetName(); + auto citer = mapping.find(name); + + if (citer != mapping.cend()) + { + auto mat_iter = name2mat.find(citer->second); + + if (mat_iter != name2mat.cend()) + { + shape->SetMaterial(mat_iter->second); + } + } + } + } + + MaterialIo::MaterialMap MaterialIo::LoadMaterialMapping(std::string const& filename) + { + MaterialMap map; + + XMLDocument doc; + doc.LoadFile(filename.c_str()); + + for (auto element = doc.FirstChildElement(); element; element = element->NextSiblingElement()) + { + std::string from(element->Attribute("from")); + std::string to(element->Attribute("to")); + map.emplace(from, to); + } + + return map; + } + + void MaterialIo::SaveIdentityMapping(std::string const& filename, Scene1 const& scene) + { + XMLDocument doc; + XMLPrinter printer; + + auto shape_iter = scene.CreateShapeIterator(); + std::set serialized_mats; + + for (; shape_iter->IsValid(); shape_iter->Next()) + { + auto material = shape_iter->ItemAs()->GetMaterial(); + + if (material && serialized_mats.find(material) == serialized_mats.cend()) + { + auto name = material->GetName(); + printer.OpenElement("Mapping"); + printer.PushAttribute("from", name.c_str()); + printer.PushAttribute("to", name.c_str()); + printer.CloseElement(); + serialized_mats.emplace(material); + } + } + + doc.Parse(printer.CStr()); + + doc.SaveFile(filename.c_str()); + } + + void MaterialIoXML::WriteInputMap(ImageIo& io, XMLPrinter& printer, InputMap::Ptr inputMap) + { + if (m_saved_inputs.find(inputMap) != m_saved_inputs.end()) + { + return; + } + else + { + m_saved_inputs.insert(inputMap); + } + + printer.OpenElement("Input"); + + printer.PushAttribute("name", inputMap->GetName().c_str()); + printer.PushAttribute("id", inputMap->GetId()); + printer.PushAttribute("type", static_cast(inputMap->m_type)); + switch (inputMap->m_type) + { + //Leafs + case InputMap::InputMapType::kConstantFloat: + { + InputMap_ConstantFloat *i = static_cast(inputMap.get()); + printer.PushAttribute("value", i->GetValue()); + printer.CloseElement(); + break; + } + case InputMap::InputMapType::kConstantFloat3: + { + InputMap_ConstantFloat3 *i = static_cast(inputMap.get()); + printer.PushAttribute("value", Float4ToString(i->GetValue()).c_str()); + printer.CloseElement(); + break; + } + case InputMap::InputMapType::kSampler: + case InputMap::InputMapType::kSamplerBumpmap: + { + InputMap_Sampler *i = static_cast(inputMap.get()); + + auto texture = i->GetTexture(); + auto iter = m_tex2name.find(texture); + + if (iter != m_tex2name.cend()) + { + printer.PushAttribute("value", iter->second.c_str()); + } + else + { + std::string texture_name = texture->GetName(); + if (texture_name.empty()) + { + std::ostringstream oss; + oss << (std::uint64_t)texture.get() << ".jpg"; + texture_name = oss.str(); + io.SaveImage(m_base_path + texture_name, texture); + } + + m_tex2name[texture] = texture_name; + + printer.PushAttribute("value", texture_name.c_str()); + } + printer.CloseElement(); + break; + } + + // Two inputs + case InputMap::InputMapType::kAdd: + case InputMap::InputMapType::kSub: + case InputMap::InputMapType::kMul: + case InputMap::InputMapType::kDiv: + case InputMap::InputMapType::kMin: + case InputMap::InputMapType::kMax: + case InputMap::InputMapType::kDot3: + case InputMap::InputMapType::kDot4: + case InputMap::InputMapType::kCross3: + case InputMap::InputMapType::kCross4: + case InputMap::InputMapType::kPow: + case InputMap::InputMapType::kMod: + { + //It's safe since all this types differs only in id value + InputMap_Add *i = static_cast(inputMap.get()); + printer.PushAttribute("input0", i->GetA()->GetId()); + printer.PushAttribute("input1", i->GetB()->GetId()); + printer.CloseElement(); + WriteInputMap(io, printer, i->GetA()); + WriteInputMap(io, printer, i->GetB()); + break; + } + //Single input + case InputMap::InputMapType::kSin: + case InputMap::InputMapType::kCos: + case InputMap::InputMapType::kTan: + case InputMap::InputMapType::kAsin: + case InputMap::InputMapType::kAcos: + case InputMap::InputMapType::kAtan: + case InputMap::InputMapType::kLength3: + case InputMap::InputMapType::kNormalize3: + case InputMap::InputMapType::kFloor: + case InputMap::InputMapType::kAbs: + { + //It's safe since all this types differs only in id value + InputMap_Sin *i = static_cast(inputMap.get()); + printer.PushAttribute("input0", i->GetArg()->GetId()); + printer.CloseElement(); + WriteInputMap(io, printer, i->GetArg()); + } + // Specials + case InputMap::InputMapType::kLerp: + { + InputMap_Lerp *i = static_cast(inputMap.get()); + printer.PushAttribute("input0", i->GetA()->GetId()); + printer.PushAttribute("input1", i->GetB()->GetId()); + printer.PushAttribute("control", i->GetControl()->GetId()); + printer.CloseElement(); + WriteInputMap(io, printer, i->GetA()); + WriteInputMap(io, printer, i->GetB()); + WriteInputMap(io, printer, i->GetControl()); + break; + } + case InputMap::InputMapType::kSelect: + { + InputMap_Select *i = static_cast(inputMap.get()); + printer.PushAttribute("input0", i->GetArg()->GetId()); + printer.PushAttribute("selection", static_cast(i->GetSelection())); + printer.CloseElement(); + WriteInputMap(io, printer, i->GetArg()); + break; + } + case InputMap::InputMapType::kShuffle: + { + InputMap_Shuffle *i = static_cast(inputMap.get()); + printer.PushAttribute("input0", i->GetArg()->GetId()); + auto mask = i->GetMask(); + printer.PushAttribute("mask", ArrayToString(mask.data(), static_cast(mask.size())).c_str()); + printer.CloseElement(); + WriteInputMap(io, printer, i->GetArg()); + break; + } + case InputMap::InputMapType::kShuffle2: + { + InputMap_Shuffle2 *i = static_cast(inputMap.get()); + printer.PushAttribute("input0", i->GetA()->GetId()); + printer.PushAttribute("input1", i->GetB()->GetId()); + auto mask = i->GetMask(); + printer.PushAttribute("mask", ArrayToString(mask.data(), static_cast(mask.size())).c_str()); + printer.CloseElement(); + WriteInputMap(io, printer, i->GetA()); + WriteInputMap(io, printer, i->GetB()); + break; + } + case InputMap::InputMapType::kMatMul: + { + InputMap_MatMul *i = static_cast(inputMap.get()); + printer.PushAttribute("input0", i->GetArg()->GetId()); + printer.PushAttribute("matrix", MatrixToString(i->GetMatrix()).c_str()); + printer.CloseElement(); + WriteInputMap(io, printer, i->GetArg()); + + break; + } + case InputMap::InputMapType::kRemap: + { + InputMap_Remap *i = static_cast(inputMap.get()); + printer.PushAttribute("src", i->GetSourceRange()->GetId()); + printer.PushAttribute("dst", i->GetDestinationRange()->GetId()); + printer.PushAttribute("data", i->GetData()->GetId()); + printer.CloseElement(); + WriteInputMap(io, printer, i->GetSourceRange()); + WriteInputMap(io, printer, i->GetDestinationRange()); + WriteInputMap(io, printer, i->GetData()); + break; + } + } + } + + InputMap::Ptr MaterialIoXML::LoadInputMap(ImageIo& io, XMLElement* element, + const std::map &input_map_cache, + std::map &loaded_inputs) + { + InputMap::InputMapType type = static_cast(element->UnsignedAttribute("type")); + std::string name = element->Attribute("name"); + int id = element->UnsignedAttribute("id"); + + auto input = loaded_inputs.find(id); + if (input != loaded_inputs.end()) + { + return input->second; + } + + InputMap::Ptr result; + + switch (type) + { + //Leafs + case InputMap::InputMapType::kConstantFloat: + { + result = InputMap_ConstantFloat::Create(element->FloatAttribute("value")); + break; + } + case InputMap::InputMapType::kConstantFloat3: + { + + std::istringstream iss(element->Attribute("value")); + RadeonRays::float3 value; + iss >> value.x >> value.y >> value.z; + + result = InputMap_ConstantFloat3::Create(value); + break; + } + case InputMap::InputMapType::kSampler: + { + std::string filename(element->Attribute("value")); + + auto iter = m_name2tex.find(filename); + Texture::Ptr texture; + + if (iter != m_name2tex.cend()) + { + texture = iter->second; + } + else + { + texture = io.LoadImage(m_base_path + filename); + m_name2tex[name] = texture; + } + + result = InputMap_Sampler::Create(texture); + + break; + } + case InputMap::InputMapType::kSamplerBumpmap: + { + std::string filename(element->Attribute("value")); + + auto iter = m_name2tex.find(filename); + Texture::Ptr texture; + + if (iter != m_name2tex.cend()) + { + texture = iter->second; + } + else + { + texture = io.LoadImage(m_base_path + filename); + m_name2tex[name] = texture; + } + + result = InputMap_SamplerBumpMap::Create(texture); + break; + } + + // Two inputs + case InputMap::InputMapType::kAdd: + result = LoadTwoArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kSub: + result = LoadTwoArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kMul: + result = LoadTwoArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kDiv: + result = LoadTwoArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kMin: + result = LoadTwoArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kMax: + result = LoadTwoArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kDot3: + result = LoadTwoArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kDot4: + result = LoadTwoArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kCross3: + result = LoadTwoArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kCross4: + result = LoadTwoArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kPow: + result = LoadTwoArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kMod: + result = LoadTwoArgInput(io, element, input_map_cache, loaded_inputs); + break; + //Single input + case InputMap::InputMapType::kSin: + result = LoadOneArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kCos: + result = LoadOneArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kTan: + result = LoadOneArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kAsin: + result = LoadOneArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kAcos: + result = LoadOneArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kAtan: + result = LoadOneArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kLength3: + result = LoadOneArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kNormalize3: + result = LoadOneArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kFloor: + result = LoadOneArgInput(io, element, input_map_cache, loaded_inputs); + break; + case InputMap::InputMapType::kAbs: + result = LoadOneArgInput(io, element, input_map_cache, loaded_inputs); + break; + // Specials + case InputMap::InputMapType::kLerp: + { + uint32_t arg1_id = element->UnsignedAttribute("input0"); + uint32_t arg2_id = element->UnsignedAttribute("input1"); + uint32_t control_id = element->UnsignedAttribute("control"); + InputMap::Ptr arg1 = LoadInputMap(io, input_map_cache.at(arg1_id), input_map_cache, loaded_inputs); + InputMap::Ptr arg2 = LoadInputMap(io, input_map_cache.at(arg2_id), input_map_cache, loaded_inputs); + InputMap::Ptr control = LoadInputMap(io, input_map_cache.at(control_id), input_map_cache, loaded_inputs); + + result = InputMap_Lerp::Create(arg1, arg2, control); + break; + } + case InputMap::InputMapType::kSelect: + { + uint32_t arg1_id = element->UnsignedAttribute("input0"); + InputMap::Ptr arg1 = LoadInputMap(io, input_map_cache.at(arg1_id), input_map_cache, loaded_inputs); + InputMap_Select::Selection selection = + static_cast(element->UnsignedAttribute("selection")); + + result = InputMap_Select::Create(arg1, selection); + break; + } + case InputMap::InputMapType::kShuffle: + { + uint32_t arg1_id = element->UnsignedAttribute("input0"); + InputMap::Ptr arg1 = LoadInputMap(io, input_map_cache.at(arg1_id), input_map_cache, loaded_inputs); + std::array mask; + std::istringstream iss(element->Attribute("mask")); + iss >> mask[0] >> mask[1] >> mask[2] >> mask[3]; + + result = InputMap_Shuffle::Create(arg1, mask); + break; + } + case InputMap::InputMapType::kShuffle2: + { + uint32_t arg1_id = element->UnsignedAttribute("input0"); + InputMap::Ptr arg1 = LoadInputMap(io, input_map_cache.at(arg1_id), input_map_cache, loaded_inputs); + uint32_t arg2_id = element->UnsignedAttribute("input1"); + InputMap::Ptr arg2 = LoadInputMap(io, input_map_cache.at(arg2_id), input_map_cache, loaded_inputs); + + std::array mask; + std::istringstream iss(element->Attribute("mask")); + iss >> mask[0] >> mask[1] >> mask[2] >> mask[3]; + + result = InputMap_Shuffle2::Create(arg1, arg2, mask); + break; + } + case InputMap::InputMapType::kMatMul: + { + uint32_t arg1_id = element->UnsignedAttribute("input0"); + InputMap::Ptr arg1 = LoadInputMap(io, input_map_cache.at(arg1_id), input_map_cache, loaded_inputs); + + RadeonRays::matrix mat; + std::istringstream iss(element->Attribute("matrix")); + for (int i = 0; i < 4; ++i) + { + for (int j = 0; j < 4; ++j) + { + iss >> mat.m[i][j]; + } + } + + result = InputMap_MatMul::Create(arg1, mat); + break; + } + case InputMap::InputMapType::kRemap: + { + uint32_t src_id = element->UnsignedAttribute("src"); + InputMap::Ptr src = LoadInputMap(io, input_map_cache.at(src_id), input_map_cache, loaded_inputs); + uint32_t dst_id = element->UnsignedAttribute("dst"); + InputMap::Ptr dst = LoadInputMap(io, input_map_cache.at(dst_id), input_map_cache, loaded_inputs); + uint32_t data_id = element->UnsignedAttribute("data"); + InputMap::Ptr data = LoadInputMap(io, input_map_cache.at(data_id), input_map_cache, loaded_inputs); + + result = InputMap_Remap::Create(src, dst, data); + break; + } + } + + result->SetName(name); + loaded_inputs.insert(std::make_pair(id, result)); + return result; + } +} diff --git a/BaikalIO/material_io.h b/BaikalIO/material_io.h new file mode 100644 index 00000000..1f880873 --- /dev/null +++ b/BaikalIO/material_io.h @@ -0,0 +1,94 @@ +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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 material_io.h + \author Dmitry Kozlov + \version 1.0 + \brief Contains an interface for material input & output + */ +#pragma once + +#include +#include +#include + +#ifdef WIN32 +#ifdef BAIKAL_EXPORT_API +#define BAIKAL_API_ENTRY __declspec(dllexport) +#else +#define BAIKAL_API_ENTRY __declspec(dllimport) +#endif +#else +#define BAIKAL_API_ENTRY __attribute__((visibility ("default"))) +#endif + +namespace Baikal +{ + class Scene1; + class Iterator; + + /** + \brief Interface for material loading and writing + + MaterialIO is responsible for material loading from disk. + */ + class BAIKAL_API_ENTRY MaterialIo + { + public: + // Create XML based material IO + static std::unique_ptr CreateMaterialIoXML(); + + using MaterialMap = std::map; + + // Constructor + MaterialIo() = default; + // Destructor + virtual ~MaterialIo() = 0; + + // Save materials from scene into a file + virtual void SaveMaterials(std::string const& file_name, Iterator& iterator) = 0; + + // Load materials from disk + virtual std::unique_ptr LoadMaterials(std::string const& file_name) = 0; + + // Helper method: save all materials in the scene + void SaveMaterialsFromScene(std::string const& filename, Scene1 const& scene); + + // Create identity mapping + void SaveIdentityMapping(std::string const& filename, Scene1 const& scene); + + // Helper methos: Replace scene materials using name mapping + void ReplaceSceneMaterials(Scene1& scene, Iterator& iterator, MaterialMap const& mapping); + + // Load material mapping from disk + MaterialMap LoadMaterialMapping(std::string const& filename); + + // Disallow copying + MaterialIo(MaterialIo const&) = delete; + MaterialIo& operator = (MaterialIo const&) = delete; + }; + + inline MaterialIo::~MaterialIo() + { + } +} diff --git a/BaikalIO/scene_binary_io.cpp b/BaikalIO/scene_binary_io.cpp new file mode 100644 index 00000000..fd30736a --- /dev/null +++ b/BaikalIO/scene_binary_io.cpp @@ -0,0 +1,243 @@ +#include "scene_binary_io.h" +#include "SceneGraph/scene1.h" +#include "SceneGraph/iterator.h" +#include "SceneGraph/shape.h" +#include "SceneGraph/material.h" +#include "SceneGraph/light.h" +#include "SceneGraph/texture.h" +#include "SceneGraph/uberv2material.h" +#include "image_io.h" +#include "math/mathutils.h" +#include "Utils/log.h" + +#include + +namespace Baikal +{ + // Create static object to register loader. This object will be used as loader + static SceneBinaryIo scene_binary_io_loader; + + Scene1::Ptr SceneBinaryIo::LoadScene(std::string const& filename, std::string const& basepath) const + { + auto scene = Scene1::Create(); + auto image_io(ImageIo::CreateImageIo()); + + std::map mats; + + struct less + { + bool operator ()(RadeonRays::float3 const& v1, RadeonRays::float3 const& v2) const { + return v1.x < v2.x; + } + }; + + std::map c2mats; + + std::string full_path = filename; + + std::ifstream in(full_path, std::ios::binary | std::ios::in); + + if (!in) + { + throw std::runtime_error("Cannot open file for reading"); + } + + std::uint32_t num_meshes = 0; + in.read((char*)&num_meshes, sizeof(std::uint32_t)); + + LogInfo("Number of objects: ", num_meshes, "\n"); + + for (auto i = 0U; i < num_meshes; ++i) + { + auto mesh = Mesh::Create(); + + std::uint32_t num_indices = 0; + in.read((char*)&num_indices, sizeof(std::uint32_t)); + + std::uint32_t num_vertices = 0; + in.read((char*)&num_vertices, sizeof(std::uint32_t)); + + + std::uint32_t num_normals = 0; + in.read((char*)&num_normals, sizeof(std::uint32_t)); + + + std::uint32_t num_uvs = 0; + in.read((char*)&num_uvs, sizeof(std::uint32_t)); + + { + std::vector indices(num_indices); + in.read((char*)&indices[0], num_indices * sizeof(std::uint32_t)); + + mesh->SetIndices(&indices[0], num_indices); + } + + { + std::vector vertices(num_vertices); + in.read((char*)&vertices[0], num_vertices * sizeof(RadeonRays::float3)); + + mesh->SetVertices(&vertices[0], num_vertices); + } + + { + std::vector normals(num_normals); + in.read((char*)&normals[0], num_normals * sizeof(RadeonRays::float3)); + + mesh->SetNormals(&normals[0], num_normals); + } + + { + std::vector uvs(num_uvs); + in.read((char*)&uvs[0], num_uvs * sizeof(RadeonRays::float2)); + + mesh->SetUVs(&uvs[0], num_uvs); + } + + + { + std::uint32_t flag = 0; + in.read(reinterpret_cast(&flag), sizeof(flag)); + + if (!flag) + { + RadeonRays::float3 albedo; + in.read(reinterpret_cast(&albedo.x), sizeof(RadeonRays::float3)); + + /*auto iter = c2mats.find(albedo); + + if (iter != c2mats.cend()) + { + material = iter->second; + } + else + { + material = new SingleBxdf(SingleBxdf::BxdfType::kLambert); + material->SetInputValue("albedo", albedo); + c2mats[albedo] = material; + scene->AttachAutoreleaseObject(material); + }*/ + } + else + { + std::uint32_t size = 0; + in.read(reinterpret_cast(&size), sizeof(size)); + + std::vector buff(size); + in.read(&buff[0], sizeof(char) * size); + + //std::string name(buff.cbegin(), buff.cend()); + + //auto iter = mats.find(name); + + //if (iter != mats.cend()) + //{ + // material = iter->second; + //} + //else + //{ + // LogInfo("Loading texture ", name, "\n"); + // auto texture = image_io->LoadImage(basepath + name); + // //material = new SingleBxdf(SingleBxdf::BxdfType::kLambert); + // //material->SetInputValue("albedo", texture); + // //mats[name] = material; + // //scene->AttachAutoreleaseObject(texture); + // //scene->AttachAutoreleaseObject(material); + //} + + } + + mesh->SetMaterial(nullptr); + } + + scene->AttachShape(mesh); + } + + auto ibl_texture = image_io->LoadImage("../Resources/Textures/Canopus_Ground_4k.exr"); + + auto ibl = ImageBasedLight::Create(); + ibl->SetTexture(ibl_texture); + ibl->SetMultiplier(1.f); + + // TODO: temporary code to add directional light + auto light = DirectionalLight::Create(); + light->SetDirection(RadeonRays::normalize(RadeonRays::float3(-1.1f, -0.6f, -0.4f))); + light->SetEmittedRadiance(7.f * RadeonRays::float3(1.f, 0.95f, 0.92f)); + + auto light1 = DirectionalLight::Create(); + light1->SetDirection(RadeonRays::float3(0.3f, -1.f, -0.5f)); + light1->SetEmittedRadiance(RadeonRays::float3(1.f, 0.8f, 0.65f)); + + scene->AttachLight(light); + //scene->AttachLight(light1); + scene->AttachLight(ibl); + + return scene; + } + + void SceneBinaryIo::SaveScene(Scene1 const& scene, std::string const& filename, std::string const& basepath) const + { + std::string full_path = filename; + + std::ofstream out(full_path, std::ios::binary | std::ios::out); + + if (!out) + { + throw std::runtime_error("Cannot open file for writing"); + } + + auto default_material = UberV2Material::Create(); + + auto num_shapes = (std::uint32_t)scene.GetNumShapes(); + out.write((char*)&num_shapes, sizeof(std::uint32_t)); + + auto shape_iter = scene.CreateShapeIterator(); + + for (; shape_iter->IsValid(); shape_iter->Next()) + { + auto mesh = shape_iter->ItemAs(); + auto num_indices = (std::uint32_t)mesh->GetNumIndices(); + out.write((char*)&num_indices, sizeof(std::uint32_t)); + + auto num_vertices = (std::uint32_t)mesh->GetNumVertices(); + out.write((char*)&num_vertices, sizeof(std::uint32_t)); + + auto num_normals = (std::uint32_t)mesh->GetNumNormals(); + out.write((char*)&num_normals, sizeof(std::uint32_t)); + + auto num_uvs = (std::uint32_t)mesh->GetNumUVs(); + out.write((char*)&num_uvs, sizeof(std::uint32_t)); + + out.write((char const*)mesh->GetIndices(), mesh->GetNumIndices() * sizeof(std::uint32_t)); + out.write((char const*)mesh->GetVertices(), mesh->GetNumVertices() * sizeof(RadeonRays::float3)); + out.write((char const*)mesh->GetNormals(), mesh->GetNumNormals() * sizeof(RadeonRays::float3)); + out.write((char const*)mesh->GetUVs(), mesh->GetNumUVs() * sizeof(RadeonRays::float2)); + + auto material = mesh->GetMaterial(); + + /*if (!material) + { + material = default_material; + } + + auto diffuse = std::dynamic_pointer_cast(material); + + if (!diffuse) + { + diffuse = std::dynamic_pointer_cast(material->GetInputValue("base_material").mat_value); + } + + if (!diffuse) + { + throw std::runtime_error("Material not supported"); + } + diffuse->GetInputValue("albedo"); + */ + + auto albedo = RadeonRays::float3(1.0f, 1.0f, 1.0f); + + std::uint32_t flag = 0; + out.write(reinterpret_cast(&flag), sizeof(flag)); + out.write(reinterpret_cast(&albedo.x), sizeof(RadeonRays::float3)); + } + } +} diff --git a/BaikalIO/scene_binary_io.h b/BaikalIO/scene_binary_io.h new file mode 100644 index 00000000..fe79aeea --- /dev/null +++ b/BaikalIO/scene_binary_io.h @@ -0,0 +1,41 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "scene_io.h" +#include +#include + +#define _USE_MATH_DEFINES +#include + +namespace Baikal +{ + // Create fake test IO + class SceneBinaryIo : public SceneIo::Loader + { + public: + SceneBinaryIo() : SceneIo::Loader("bin", this) + {} + // Load scene (this class uses filename to determine what scene to generate) + Scene1::Ptr LoadScene(std::string const& filename, std::string const& basepath) const override; + void SaveScene(Scene1 const& scene, std::string const& filename, std::string const& basepath) const override; + }; +} diff --git a/BaikalIO/scene_fbx_io.cpp b/BaikalIO/scene_fbx_io.cpp new file mode 100644 index 00000000..d12c3bc8 --- /dev/null +++ b/BaikalIO/scene_fbx_io.cpp @@ -0,0 +1,416 @@ +#include "scene_io.h" +#include "SceneGraph/scene1.h" +#include "SceneGraph/iterator.h" +#include "SceneGraph/shape.h" +#include "SceneGraph/material.h" +#include "SceneGraph/light.h" +#include "SceneGraph/texture.h" +#include "image_io.h" +#include "math/mathutils.h" + +#include "math/matrix.h" +#include "Utils/log.h" + +#include +#include +#include +#include + +#define FBXSDK_NEW_API +#define KFBX_DLLINFO +#include + +namespace Baikal +{ + // Create fake test IO + class SceneFbxIo : public SceneIo::Loader + { + public: + SceneFbxIo() : SceneIo::Loader("fbx", this) + {} + // Load scene (this class uses filename to determine what scene to generate) + Scene1::Ptr LoadScene(const std::string &filename, const std::string &basepath) const override; + + private: + void LoadMesh(FbxNode* node, std::string const& basepath, Scene1& scene, ImageIo& io) const; + void LoadLight(FbxNode* node, std::string const& basepath, Scene1& scene, ImageIo& io) const; + Material::Ptr TranslateMaterial(FbxSurfaceMaterial* material, std::string const& basepath, Scene1& scene, ImageIo& io) const; + Texture::Ptr GetTexture(FbxSurfaceMaterial* material, const char* textureType, std::string const& basepath, Scene1& scene, ImageIo& io) const; + + mutable std::map m_material_cache; + }; + + static SceneFbxIo scene_fbx_io_loader; + + static RadeonRays::matrix FbxToBaikalTransform(FbxAMatrix const& fbx_matrix) + { + RadeonRays::matrix res; + + for (int i = 0; i < 4; ++i) + { + auto row = fbx_matrix.GetRow(i); + res.m[0][i] = row[0]; + res.m[1][i] = row[1]; + res.m[2][i] = row[2]; + res.m[3][i] = row[3]; + } + + return res; + } + + Texture::Ptr SceneFbxIo::GetTexture(FbxSurfaceMaterial* material, const char* slot, std::string const& basepath, Scene1& scene, ImageIo& io) const + { + //return nullptr; + FbxProperty prop = material->FindProperty(slot); + + for (auto i = 0; i < prop.GetSrcObjectCount(); i++) + { + FbxFileTexture* texture = prop.GetSrcObject(i); + + if (!texture) + { + continue; + } + + std::string filepath = texture->GetRelativeFileName(); + std::string path = ""; + + try + { + if ((filepath.find(":") != std::string::npos) || (filepath.at(0) == '/')) + { + return LoadTexture(io, scene, "", filepath); + } + else + { + return LoadTexture(io, scene, basepath, filepath); + } + } + catch (std::exception& e) + { + return nullptr; + } + } + + return nullptr; + } + + Material::Ptr SceneFbxIo::TranslateMaterial(FbxSurfaceMaterial* material, std::string const& basepath, Scene1& scene, ImageIo& io) const + { + auto iter = m_material_cache.find(material); + + if (iter == m_material_cache.cend()) + { + auto base = SingleBxdf::Create(SingleBxdf::BxdfType::kLambert); + + Material::Ptr res = base; + base->SetName(material->GetName()); + + auto albedo = material->FindProperty(FbxSurfaceMaterial::sDiffuse).Get(); + auto mul = material->FindProperty(FbxSurfaceMaterial::sDiffuseFactor).Get(); + auto texture = GetTexture(material, FbxSurfaceMaterial::sDiffuse, basepath, scene, io); + auto normal = GetTexture(material, FbxSurfaceMaterial::sNormalMap, basepath, scene, io); + auto bump = GetTexture(material, FbxSurfaceMaterial::sBump, basepath, scene, io); + + if (texture) + { + base->SetInputValue("albedo", texture); + } + else + { + base->SetInputValue("albedo", mul * RadeonRays::float3(albedo[0], albedo[1], albedo[2])); + } + + if (normal) + { + base->SetInputValue("normal", normal); + } + else if (bump) + { + base->SetInputValue("bump", normal); + } + + auto specular_albedo = material->FindProperty(FbxSurfaceMaterial::sSpecular).Get(); + auto specular_mul = material->FindProperty(FbxSurfaceMaterial::sSpecularFactor).Get(); + auto shininess = material->FindProperty(FbxSurfaceMaterial::sShininess).Get(); + auto specular_texture = GetTexture(material, FbxSurfaceMaterial::sSpecular, basepath, scene, io); + + if (specular_mul > 0.f && (specular_albedo[0] > 0.f || + specular_albedo[1] > 0.f || specular_albedo[2] > 0.f)) + { + auto top = SingleBxdf::Create(shininess > 0.99f ? + SingleBxdf::BxdfType::kMicrofacetGGX : + SingleBxdf::BxdfType::kIdealReflect); + + if (specular_texture) + { + top->SetInputValue("albedo", specular_texture); + } + else + { + top->SetInputValue("albedo", specular_mul * RadeonRays::float3( + specular_albedo[0], + specular_albedo[1], + specular_albedo[2])); + } + + auto r = RadeonRays::clamp(1.f - shininess / 10.f, 0.001f, 999.f); + top->SetInputValue("roughness", RadeonRays::float3(r,r,r)); + + auto layered = MultiBxdf::Create(MultiBxdf::Type::kFresnelBlend); + layered->SetInputValue("base_material", base); + layered->SetInputValue("top_material", top); + layered->SetInputValue("ior", RadeonRays::float3(1.5f, 1.5f, 1.5f, 1.5f)); + res = layered; + + if (normal) + { + top->SetInputValue("normal", normal); + } + else if (bump) + { + top->SetInputValue("bump", normal); + } + + } + + m_material_cache[material] = res; + + return res; + } + else + { + return iter->second; + } + } + + void SceneFbxIo::LoadLight(FbxNode* node, std::string const& basepath, Scene1& scene, ImageIo& io) const + { + auto fbx_light = node->GetLight(); + auto transform = FbxMatrix(node->EvaluateGlobalTransform()); + + auto intensity = fbx_light->Intensity.Get(); + auto color = fbx_light->Color.Get(); + auto position = node->LclTranslation.Get(); + auto rotation = node->LclRotation.Get(); + + auto rotation_matrix = RadeonRays::rotation_x(rotation[0] / 180.f * PI) * + RadeonRays::rotation_y(rotation[2] / 180.f * PI) * + RadeonRays::rotation_z(-rotation[1] / 180.f * PI); + + switch (fbx_light->LightType.Get()) + { + case FbxLight::ePoint: + { + auto light = PointLight::Create(); + light->SetName(node->GetName()); + + light->SetEmittedRadiance(intensity * RadeonRays::float3(color[0], color[1], color[2])); + light->SetPosition(RadeonRays::float3(position[0], position[1], position[2])); + + scene.AttachLight(light); + return; + } + case FbxLight::eDirectional: + { + auto light = DirectionalLight::Create(); + light->SetName(node->GetName()); + + light->SetEmittedRadiance(intensity * RadeonRays::float3(color[0], color[1], color[2])); + light->SetDirection(rotation_matrix * RadeonRays::float3(0, -1, 0, 0)); + + scene.AttachLight(light); + return; + } + case FbxLight::eSpot: + { + auto light = SpotLight::Create(); + light->SetName(node->GetName()); + + light->SetEmittedRadiance(intensity * RadeonRays::float3(color[0], color[1], color[2])); + light->SetPosition(RadeonRays::float3(position[0], position[1], position[2])); + light->SetDirection(rotation_matrix * RadeonRays::float3(0, -1, 0, 0)); + + auto inner_angle = fbx_light->InnerAngle.Get(); + auto outer_angle = fbx_light->OuterAngle.Get(); + light->SetConeShape(RadeonRays::float2(std::cos(inner_angle / 180.f * PI), std::cos(outer_angle / 180.f * PI))); + + scene.AttachLight(light); + return; + } + } + } + + void SceneFbxIo::LoadMesh(FbxNode* node, std::string const& basepath, Scene1& scene, ImageIo& io) const + { + auto mesh = Mesh::Create(); + auto fbx_mesh = node->GetMesh(); + + auto transform = FbxMatrix(node->EvaluateGlobalTransform()); + auto invtransp = node->EvaluateGlobalTransform().Inverse().Transpose(); + + mesh->SetName(node->GetName()); + + // Vertices + { + auto num_triangles = fbx_mesh->GetPolygonCount(); + auto num_vertices = fbx_mesh->GetControlPointsCount(); + auto vertex_ptr = fbx_mesh->GetControlPoints(); + + std::vector vertices(num_vertices); + std::vector normals(num_vertices); + std::vector uvs(num_vertices); + std::vector indices(num_triangles * 3); + + FbxStringList uv_list; + fbx_mesh->GetUVSetNames(uv_list); + + for (auto i = 0; i < num_vertices; ++i) + { + auto vertex = vertex_ptr[i]; + vertex = transform.MultNormalize(vertex); + vertices[i] = RadeonRays::float3(vertex[0], vertex[1], vertex[2]); + } + + for (auto i = 0; i < num_triangles; ++i) + { + assert(fbx_mesh->GetPolygonSize(i) == 3); + + auto i0 = fbx_mesh->GetPolygonVertex(i, 0); + auto i1 = fbx_mesh->GetPolygonVertex(i, 1); + auto i2 = fbx_mesh->GetPolygonVertex(i, 2); + + FbxVector4 n0, n1, n2; + fbx_mesh->GetPolygonVertexNormal(i, 0, n0); + fbx_mesh->GetPolygonVertexNormal(i, 1, n1); + fbx_mesh->GetPolygonVertexNormal(i, 2, n2); + + n0 = invtransp.MultT(n0); + n1 = invtransp.MultT(n1); + n2 = invtransp.MultT(n2); + + normals[i0] = normalize(RadeonRays::float3(n0[0], n0[1], n0[2], 0)); + normals[i1] = normalize(RadeonRays::float3(n1[0], n1[1], n1[2], 0)); + normals[i2] = normalize(RadeonRays::float3(n2[0], n2[1], n2[2], 0)); + + indices[3 * i] = i0; + indices[3 * i + 1] = i1; + indices[3 * i + 2] = i2; + + if (uv_list.GetCount() > 0) + { + FbxVector2 uv0, uv1, uv2; + bool unmapped0, unmapped1, unmapped2; + fbx_mesh->GetPolygonVertexUV(i, 0, uv_list.GetStringAt(0), uv0, unmapped0); + fbx_mesh->GetPolygonVertexUV(i, 1, uv_list.GetStringAt(0), uv1, unmapped1); + fbx_mesh->GetPolygonVertexUV(i, 2, uv_list.GetStringAt(0), uv2, unmapped2); + + uvs[i0] = unmapped0 ? RadeonRays::float2() : RadeonRays::float2(uv0[0], uv0[1]); + uvs[i1] = unmapped1 ? RadeonRays::float2() : RadeonRays::float2(uv1[0], uv1[1]); + uvs[i2] = unmapped2 ? RadeonRays::float2() : RadeonRays::float2(uv2[0], uv2[1]);; + } + } + + FbxLayerElementArrayTemplate* material_indices = nullptr; + fbx_mesh->GetMaterialIndices(&material_indices); + + if (material_indices) + { + auto fbx_material = node->GetMaterial(material_indices->GetAt(0)); + mesh->SetMaterial(TranslateMaterial(fbx_material, basepath, scene, io)); + } + + mesh->SetVertices(std::move(vertices)); + mesh->SetNormals(std::move(normals)); + mesh->SetUVs(std::move(uvs)); + mesh->SetIndices(std::move(indices)); + + scene.AttachShape(mesh); + } + } + + Scene1::Ptr SceneFbxIo::LoadScene(std::string const& filename, std::string const& basepath) const + { + Scene1::Ptr scene = Scene1::Create(); + auto image_io(ImageIo::CreateImageIo()); + + auto fbx_manager = FbxManager::Create(); + auto fbx_importer = FbxImporter::Create(fbx_manager, "Baikal FBX Importer"); + auto fbx_scene = FbxScene::Create(fbx_manager, "Scene"); + + LogInfo("Loading FBX ", filename, "... "); + if (!fbx_importer->Initialize(filename.c_str())) + { + throw std::runtime_error(std::string("Unable to initialize FBX importer. Error: ") + fbx_importer->GetStatus().GetErrorString()); + } + if (!fbx_importer->Import(fbx_scene)) + { + throw std::runtime_error("Cannot load file: " + filename + "\n"); + } + + auto fbx_root_node = fbx_scene->GetRootNode(); + assert(fbx_root_node); + LogInfo("Success\n"); + + FbxGeometryConverter converter(fbx_manager); + converter.Triangulate(fbx_scene, true); + + std::stack node_stack; + + node_stack.push(fbx_root_node); + while (!node_stack.empty()) + { + auto node = node_stack.top(); + node_stack.pop(); + + for (auto c = 0; c < node->GetChildCount(); ++c) + { + node_stack.push(node->GetChild(c)); + } + + auto attribs = node->GetNodeAttribute(); + + if (!attribs) + { + continue; + } + + switch (attribs->GetAttributeType()) + { + case FbxNodeAttribute::eMesh: + LoadMesh(node, basepath, *scene, *image_io); + break; + case FbxNodeAttribute::eLight: + LoadLight(node, basepath, *scene, *image_io); + break; + } + } + + + fbx_importer->Destroy(); + fbx_manager->Destroy(); + + + Texture::Ptr ibl_texture = image_io->LoadImage("../Resources/Textures/Canopus_Ground_4k.exr"); + + auto ibl = ImageBasedLight::Create(); + ibl->SetTexture(ibl_texture); + ibl->SetMultiplier(3.f); + + // TODO: temporary code to add directional light + auto light = DirectionalLight::Create(); + light->SetDirection(RadeonRays::normalize(RadeonRays::float3(-1.1f, -0.6f, -0.4f))); + light->SetEmittedRadiance(7.f * RadeonRays::float3(1.f, 0.95f, 0.92f)); + + auto light1 = DirectionalLight::Create(); + light1->SetDirection(RadeonRays::float3(0.3f, -1.f, -0.5f)); + light1->SetEmittedRadiance(RadeonRays::float3(1.f, 0.8f, 0.65f)); + + scene->AttachLight(light); + //scene->AttachLight(light1); + scene->AttachLight(ibl); + + return scene; + } +} + diff --git a/BaikalIO/scene_io.cpp b/BaikalIO/scene_io.cpp new file mode 100644 index 00000000..846f63c9 --- /dev/null +++ b/BaikalIO/scene_io.cpp @@ -0,0 +1,104 @@ +#include "scene_io.h" +#include "image_io.h" +#include "SceneGraph/scene1.h" +#include "SceneGraph/shape.h" +#include "SceneGraph/material.h" +#include "SceneGraph/light.h" +#include "SceneGraph/texture.h" +#include "math/mathutils.h" + +#include +#include +#include +#include + +#include "Utils/log.h" + +namespace Baikal +{ + SceneIo* SceneIo::GetInstance() + { + static SceneIo instance; + return &instance; + } + + void SceneIo::RegisterLoader(const std::string& ext, SceneIo::Loader *loader) + { + GetInstance()->m_loaders[ext] = loader; + } + + void SceneIo::UnregisterLoader(const std::string& ext) + { + GetInstance()->m_loaders.erase(ext); + } + + Scene1::Ptr SceneIo::LoadScene(std::string const& filename, std::string const& basepath) + { + auto ext = filename.substr(filename.rfind(".") + 1); + + SceneIo *instance = GetInstance(); + auto loader_it = instance->m_loaders.find(ext); + if (loader_it == instance->m_loaders.end()) + { + throw std::runtime_error("No loader for \"" + filename + "\" has been found."); + } + + return loader_it->second->LoadScene(filename, basepath); + } + + void SceneIo::SaveScene(Scene1 const& scene, std::string const& filename, std::string const& basepath) + { + auto ext = filename.substr(filename.rfind(".")); + + SceneIo *instance = GetInstance(); + auto loader_it = instance->m_loaders.find(ext); + if (loader_it == instance->m_loaders.end()) + { + throw std::runtime_error("No serializer for \"" + filename + "\" has been found."); + } + + return loader_it->second->SaveScene(scene, filename, basepath); + } + + Texture::Ptr SceneIo::Loader::LoadTexture(ImageIo const& io, Scene1& scene, std::string const& basepath, std::string const& name) const + { + std::string fname = basepath + name; + std::replace(fname.begin(), fname.end(), '\\', '/'); + + auto iter = m_texture_cache.find(name); + + if (iter != m_texture_cache.cend()) + { + return iter->second; + } + else + { + try + { + LogInfo("Loading ", name, "\n"); + auto texture = io.LoadImage(fname); + texture->SetName(name); + m_texture_cache[name] = texture; + return texture; + } + catch (std::runtime_error &) + { + LogInfo("Missing texture: ", name, "\n"); + return nullptr; + } + } + } + + SceneIo::Loader::Loader(const std::string& ext, SceneIo::Loader *loader) : + m_ext(ext) + + { + SceneIo::RegisterLoader(m_ext, loader); + } + + SceneIo::Loader::~Loader() + { + SceneIo::UnregisterLoader(m_ext); + } + +} diff --git a/BaikalIO/scene_io.h b/BaikalIO/scene_io.h new file mode 100644 index 00000000..0e3ee2ad --- /dev/null +++ b/BaikalIO/scene_io.h @@ -0,0 +1,114 @@ +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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 scene_io.h + \author Dmitry Kozlov + \version 1.0 + \brief Contains an interface for scene loading + */ +#pragma once + +#include +#include +#include +#include "SceneGraph/texture.h" +#include "SceneGraph/scene1.h" + +#ifdef WIN32 +#ifdef BAIKAL_EXPORT_API +#define BAIKAL_API_ENTRY __declspec(dllexport) +#else +#define BAIKAL_API_ENTRY __declspec(dllimport) +#endif +#else +#define BAIKAL_API_ENTRY __attribute__((visibility ("default"))) +#endif + + +namespace Baikal +{ + class Scene1; + class Texture; + class ImageIo; + + /** + \brief Interface for scene loading + + SceneIO implementation is responsible for translation of various scene formats into Baikal. + */ + class SceneIo + { + public: + /** + \brief Interface for file format handler + + SceneIo::Loader is responsible for translation of various scene formats into Baikal. + */ + class Loader + { + public: + // Load the scene from file using resourse base path + virtual Scene1::Ptr LoadScene(const std::string &filename, const std::string &basepath) const = 0; + + virtual void SaveScene(const Scene1 &scene, const std::string &filename, const std::string &basepath) const {}; + + Loader(const std::string& ext, SceneIo::Loader *loader); + virtual ~Loader(); + + protected: + Texture::Ptr LoadTexture(ImageIo const& io, Scene1& scene, std::string const& basepath, std::string const& name) const; + + private: + Loader(const Loader &) = delete; + Loader& operator= (const Loader &) = delete; + + std::string m_ext; + mutable std::map m_texture_cache; + }; + + // Registers extension handler + static void BAIKAL_API_ENTRY RegisterLoader(const std::string& ext, SceneIo::Loader *loader); + // Deregisters extension handler + static void BAIKAL_API_ENTRY UnregisterLoader(const std::string& ext); + + // Load the scene from file using resourse base path + static Scene1::Ptr BAIKAL_API_ENTRY LoadScene(std::string const& filename, std::string const& basepath); + // Saves scene to file using resource base path + static void BAIKAL_API_ENTRY SaveScene(Scene1 const& scene, std::string const& filename, std::string const& basepath); + + + private: + static SceneIo* GetInstance(); + + // Constructor + SceneIo() = default; + // Destructor + virtual ~SceneIo() = default; + + // Disallow copying + SceneIo(SceneIo const&) = delete; + SceneIo& operator = (SceneIo const&) = delete; + + std::map m_loaders; + }; +} diff --git a/BaikalIO/scene_obj_io.cpp b/BaikalIO/scene_obj_io.cpp new file mode 100644 index 00000000..48d32baf --- /dev/null +++ b/BaikalIO/scene_obj_io.cpp @@ -0,0 +1,358 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "scene_io.h" +#include "image_io.h" +#include "SceneGraph/scene1.h" +#include "SceneGraph/shape.h" +#include "SceneGraph/material.h" +#include "SceneGraph/light.h" +#include "SceneGraph/texture.h" +#include "math/mathutils.h" + +#include "SceneGraph/uberv2material.h" +#include "SceneGraph/inputmaps.h" + +#include +#include +#include +#include + +#include "tiny_obj_loader.h" +#include "Utils/log.h" + +namespace Baikal +{ + // Obj scene loader + class SceneIoObj : public SceneIo::Loader + { + public: + // Load scene from file + Scene1::Ptr LoadScene(std::string const& filename, std::string const& basepath) const override; + SceneIoObj() : SceneIo::Loader("obj", this) + { + SceneIo::RegisterLoader("objm", this); + } + ~SceneIoObj() + { + SceneIo::UnregisterLoader("objm"); + } + + private: + Material::Ptr TranslateMaterialUberV2(ImageIo const& image_io, tinyobj::material_t const& mat, std::string const& basepath, Scene1& scene) const; + + mutable std::map m_material_cache; + }; + + // Create static object to register loader. This object will be used as loader + static SceneIoObj obj_loader; + + + Scene1::Ptr SceneIoObj::LoadScene(std::string const& filename, std::string const& basepath) const + { + using namespace tinyobj; + + auto image_io(ImageIo::CreateImageIo()); + + // Loader data + std::vector objshapes; + std::vector objmaterials; + attrib_t attrib; + + // Try loading file + LogInfo("Loading a scene from OBJ: ", filename, " ... "); + std::string err; + auto res = LoadObj(&attrib, &objshapes, &objmaterials, &err, filename.c_str(), basepath.c_str(), true); + if (!res) + { + throw std::runtime_error(err); + } + LogInfo("Success\n"); + + // Allocate scene + auto scene = Scene1::Create(); + + // Enumerate and translate materials + // Keep track of emissive subset + std::set emissives; + std::vector materials(objmaterials.size()); + for (int i = 0; i < (int)objmaterials.size(); ++i) + { + // Translate material + materials[i] = TranslateMaterialUberV2(*image_io, objmaterials[i], basepath, *scene); + + // Add to emissive subset if needed + if (materials[i]->HasEmission()) + { + emissives.insert(materials[i]); + } + } + + // Enumerate all shapes in the scene + for (int s = 0; s < (int)objshapes.size(); ++s) + { + const auto& shape = objshapes[s]; + + // Find all materials used by this shape. + std::set used_materials(std::begin(shape.mesh.material_ids), std::end(shape.mesh.material_ids)); + + // Split the mesh into multiple meshes, each with only one material. + for (int used_material : used_materials) + { + // Map from old index to new index. + auto index_comp = [](index_t const& a, index_t const& b) + { + return (a.vertex_index < b.vertex_index) + || (a.vertex_index == b.vertex_index && a.normal_index < b.normal_index) + || (a.vertex_index == b.vertex_index && a.normal_index == b.normal_index + && a.texcoord_index < b.texcoord_index); + }; + std::map used_indices(index_comp); + + // Remapped indices. + std::vector indices; + + // Collected vertex/normal/texcoord data. + std::vector vertices, normals, texcoords; + + // Go through each face in the mesh. + for (size_t i = 0; i < shape.mesh.material_ids.size(); ++i) + { + // Skip faces which don't use the current material. + if (shape.mesh.material_ids[i] != used_material) continue; + + const int num_face_vertices = shape.mesh.num_face_vertices[i]; + assert(num_face_vertices == 3 && "expected triangles"); + // For each vertex index of this face. + for (int j = 0; j < num_face_vertices; ++j) + { + index_t old_index = shape.mesh.indices[num_face_vertices * i + j]; + + // Collect vertex/normal/texcoord data. Avoid inserting the same data twice. + auto result = used_indices.emplace(old_index, (unsigned int)(vertices.size() / 3)); + if (result.second) // Did insert? + { + // Push the new data. + for (int k = 0; k < 3; ++k) + { + vertices.push_back(attrib.vertices[3 * old_index.vertex_index + k]); + } + + for (int k = 0; k < 3; ++k) + { + normals.push_back(attrib.normals[3 * old_index.normal_index + k]); + } + + for (int k = 0; k < 2; ++k) + { + // If an uv is present + if (old_index.texcoord_index != -1) + { + texcoords.push_back(attrib.texcoords[2 * old_index.texcoord_index + k]); + } + else + { + texcoords.push_back(0.0f); + } + } + + } + + const unsigned int new_index = result.first->second; + indices.push_back(new_index); + } + } + + // Create empty mesh + auto mesh = Mesh::Create(); + + // Set vertex and index data + auto num_vertices = vertices.size() / 3; + mesh->SetVertices(&vertices[0], num_vertices); + + auto num_normals = normals.size() / 3; + mesh->SetNormals(&normals[0], num_normals); + + auto num_uvs = texcoords.size() / 2; + mesh->SetUVs(&texcoords[0], num_uvs); + + // Set indices + auto num_indices = indices.size(); + mesh->SetIndices(reinterpret_cast(&indices[0]), num_indices); + + // Set material + + if (used_material >= 0) + { + mesh->SetMaterial(materials[used_material]); + } + + // Attach to the scene + scene->AttachShape(mesh); + + // If the mesh has emissive material we need to add area light for it + if (used_material >= 0 && emissives.find(materials[used_material]) != emissives.cend()) + { + // Add area light for each polygon of emissive mesh + for (std::size_t l = 0; l < mesh->GetNumIndices() / 3; ++l) + { + auto light = AreaLight::Create(mesh, l); + scene->AttachLight(light); + } + } + } + } + + // TODO: temporary code to add directional light + auto light = DirectionalLight::Create(); + light->SetDirection(RadeonRays::float3(.1f, -1.f, -.1f)); + light->SetEmittedRadiance(RadeonRays::float3(1.f, 1.f, 1.f)); + + scene->AttachLight(light); + + return scene; + } + Material::Ptr SceneIoObj::TranslateMaterialUberV2(ImageIo const& image_io, tinyobj::material_t const& mat, std::string const& basepath, Scene1& scene) const + { + auto iter = m_material_cache.find(mat.name); + + if (iter != m_material_cache.cend()) + { + return iter->second; + } + + UberV2Material::Ptr material = UberV2Material::Create(); + + RadeonRays::float3 emission(mat.emission[0], mat.emission[1], mat.emission[2]); + + bool apply_gamma = true; + + uint32_t material_layers = 0; + auto uberv2_set_texture = [](UberV2Material::Ptr material, const std::string input_name, Texture::Ptr texture, bool apply_gamma) + { + if (apply_gamma) + { + material->SetInputValue(input_name.c_str(), + InputMap_Pow::Create( + InputMap_Sampler::Create(texture), + InputMap_ConstantFloat::Create(2.2f))); + } + else + { + material->SetInputValue(input_name.c_str(), InputMap_Sampler::Create(texture)); + } + }; + auto uberv2_set_bump_texture = [](UberV2Material::Ptr material, Texture::Ptr texture) + { + auto bump_sampler = InputMap_SamplerBumpMap::Create(texture); + auto bump_remap = Baikal::InputMap_Remap::Create( + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3(0.f, 1.f, 0.f)), + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3(-1.f, 1.f, 0.f)), + bump_sampler); + material->SetInputValue("uberv2.shading_normal", bump_remap); + + }; + + // Check emission layer + if (emission.sqnorm() > 0) + { + material_layers |= UberV2Material::Layers::kEmissionLayer; + if (!mat.diffuse_texname.empty()) + { + auto texture = LoadTexture(image_io, scene, basepath, mat.diffuse_texname); + uberv2_set_texture(material, "uberv2.emission.color", texture, apply_gamma); + } + else + { + material->SetInputValue("uberv2.emission.color", InputMap_ConstantFloat3::Create(emission)); + } + } + + auto s = RadeonRays::float3(mat.specular[0], mat.specular[1], mat.specular[2]); + auto r = RadeonRays::float3(mat.transmittance[0], mat.transmittance[1], mat.transmittance[2]); + auto d = RadeonRays::float3(mat.diffuse[0], mat.diffuse[1], mat.diffuse[2]); + + auto default_ior = Baikal::InputMap_ConstantFloat::Create(3.0f); + auto default_roughness = Baikal::InputMap_ConstantFloat::Create(0.01f); + auto default_one = Baikal::InputMap_ConstantFloat::Create(1.0f); + + // Check refraction layer + if (r.sqnorm() > 0) + { + material_layers |= UberV2Material::Layers::kRefractionLayer; + material->SetInputValue("uberv2.refraction.ior", default_ior); + material->SetInputValue("uberv2.refraction.roughness", default_roughness); + material->SetInputValue("uberv2.refraction.color", InputMap_ConstantFloat3::Create(r)); + } + + // Check reflection layer + if (s.sqnorm() > 0) + { + material_layers |= UberV2Material::Layers::kReflectionLayer; + material->SetInputValue("uberv2.reflection.ior", default_ior); + material->SetInputValue("uberv2.reflection.roughness", default_roughness); + material->SetInputValue("uberv2.reflection.metalness", default_one); + + if (!mat.specular_texname.empty()) + { + auto texture = LoadTexture(image_io, scene, basepath, mat.specular_texname); + uberv2_set_texture(material, "uberv2.reflection.color", texture, apply_gamma); + } + else + { + material->SetInputValue("uberv2.reflection.color", InputMap_ConstantFloat3::Create(s)); + } + } + + // Check if we have bump map + if (!mat.bump_texname.empty()) + { + material_layers |= UberV2Material::Layers::kShadingNormalLayer; + + auto texture = LoadTexture(image_io, scene, basepath, mat.bump_texname); + uberv2_set_bump_texture(material, texture); + } + + // Finally add diffuse layer + { + material_layers |= UberV2Material::Layers::kDiffuseLayer; + + if (!mat.diffuse_texname.empty()) + { + auto texture = LoadTexture(image_io, scene, basepath, mat.diffuse_texname); + uberv2_set_texture(material, "uberv2.diffuse.color", texture, apply_gamma); + } + else + { + material->SetInputValue("uberv2.diffuse.color", InputMap_ConstantFloat3::Create(d)); + } + } + + // Set material name + material->SetName(mat.name); + material->SetLayers(material_layers); + + m_material_cache.emplace(std::make_pair(mat.name, material)); + + return material; + } +} diff --git a/BaikalIO/scene_test_io.cpp b/BaikalIO/scene_test_io.cpp new file mode 100644 index 00000000..9fe80810 --- /dev/null +++ b/BaikalIO/scene_test_io.cpp @@ -0,0 +1,671 @@ +#include "scene_io.h" +#include "image_io.h" +#include "SceneGraph/scene1.h" +#include "SceneGraph/shape.h" +#include "SceneGraph/material.h" +#include "SceneGraph/light.h" +#include "SceneGraph/texture.h" +#include "SceneGraph/uberv2material.h" +#include "SceneGraph/inputmaps.h" +#include "math/mathutils.h" + +#include +#include + +#define _USE_MATH_DEFINES +#include + +namespace Baikal +{ + // Create fake test IO + class SceneIoTest : public SceneIo::Loader + { + public: + // Load scene (this class uses filename to determine what scene to generate) + Scene1::Ptr LoadScene(std::string const& filename, std::string const& basepath) const override; + SceneIoTest() : SceneIo::Loader("test", this) + {} + }; + + // Create static object to register loader. This object will be used as loader + static SceneIoTest scene_io_test_loader; + + // Create spehere mesh + auto CreateSphere(std::uint32_t lat, std::uint32_t lon, float r, RadeonRays::float3 const& c) + { + auto num_verts = (lat - 2) * lon + 2; + auto num_tris = (lat - 2) * (lon - 1 ) * 2; + + std::vector vertices(num_verts); + std::vector normals(num_verts); + std::vector uvs(num_verts); + std::vector indices (num_tris * 3); + + auto t = 0U; + for(auto j = 1U; j < lat - 1; j++) + for(auto i = 0U; i < lon; i++) + { + float theta = float(j) / (lat - 1) * (float)M_PI; + float phi = float(i) / (lon - 1 ) * (float)M_PI * 2; + vertices[t].x = r * sinf(theta) * cosf(phi) + c.x; + vertices[t].y = r * cosf(theta) + c.y; + vertices[t].z = r * -sinf(theta) * sinf(phi) + c.z; + normals[t].x = sinf(theta) * cosf(phi); + normals[t].y = cosf(theta); + normals[t].z = -sinf(theta) * sinf(phi); + uvs[t].x = float(j) / (lat - 1); + uvs[t].y = float(i) / (lon - 1); + ++t; + } + + vertices[t].x=c.x; vertices[t].y = c.y + r; vertices[t].z = c.z; + normals[t].x=0; normals[t].y = 1; normals[t].z = 0; + uvs[t].x=0; uvs[t].y = 0; + ++t; + vertices[t].x=c.x; vertices[t].y = c.y-r; vertices[t].z = c.z; + normals[t].x=0; normals[t].y = -1; normals[t].z = 0; + uvs[t].x=1; uvs[t].y = 1; + ++t; + + t = 0U; + for(auto j = 0U; j < lat - 3; j++) + for(auto i = 0U; i < lon - 1; i++) + { + indices[t++] = j * lon + i; + indices[t++] = (j + 1) * lon + i + 1; + indices[t++] = j * lon + i + 1; + + indices[t++] = j * lon + i; + indices[t++] = (j + 1) * lon + i; + indices[t++] = (j + 1) * lon + i + 1; + } + + for(auto i = 0U; i < lon - 1; i++) + { + indices[t++] = (lat - 2) * lon; + indices[t++] = i; + indices[t++] = i + 1; + indices[t++] = (lat - 2) * lon + 1; + indices[t++] = (lat - 3) * lon + i + 1; + indices[t++] = (lat - 3) * lon + i; + } + + auto mesh = Mesh::Create(); + mesh->SetVertices(&vertices[0], vertices.size()); + mesh->SetNormals(&normals[0], normals.size()); + mesh->SetUVs(&uvs[0], uvs.size()); + mesh->SetIndices(&indices[0], indices.size()); + mesh->SetName("sphere"); + + return mesh; + } + + + // Create quad + auto CreateQuad(std::vector const& vertices, bool flip) + { + using namespace RadeonRays; + + auto u1 = normalize(vertices[1] - vertices[0]); + auto u2 = normalize(vertices[3] - vertices[0]); + auto n = -cross(u1, u2); + + if (flip) + { + n = -n; + } + + float3 normals[] = { n, n, n, n }; + + float2 uvs[] = + { + float2(0, 0), + float2(1, 0), + float2(1, 1), + float2(0, 1) + }; + + std::uint32_t indices[] = + { + 0, 1, 2, + 0, 2, 3 + }; + + auto mesh = Mesh::Create(); + mesh->SetVertices(&vertices[0], 4); + mesh->SetNormals(normals, 4); + mesh->SetUVs(uvs, 4); + mesh->SetIndices(indices, 6); + mesh->SetName("quad"); + + return mesh; + } + + Scene1::Ptr SceneIoTest::LoadScene(std::string const& filename, std::string const& basepath) const + { + using namespace RadeonRays; + + auto scene = Scene1::Create(); + auto image_io(ImageIo::CreateImageIo()); + std::string fname = filename.substr(0, filename.rfind(".test")); + fname = fname.substr(fname.find(basepath) + basepath.length()); + + if (fname == "quad+spot") + { + auto quad = CreateQuad( + { + RadeonRays::float3(-5, 0, -5), + RadeonRays::float3(5, 0, -5), + RadeonRays::float3(5, 0, 5), + RadeonRays::float3(-5, 0, 5), + } + , false); + + scene->AttachShape(quad); + + auto ibl_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); + + auto light = SpotLight::Create(); + light->SetPosition(RadeonRays::float3(0.f, 1.f, 0.f)); + light->SetEmittedRadiance(RadeonRays::float3(10.f, 10.f, 10.f)); + light->SetConeShape(RadeonRays::float2(0.05f, 0.1f)); + //light->SetConeShape + scene->AttachLight(light); + } + else if (fname == "quad+ibl") + { + auto quad = CreateQuad( + { + RadeonRays::float3(-5, 0, -5), + RadeonRays::float3(5, 0, -5), + RadeonRays::float3(5, 0, 5), + RadeonRays::float3(-5, 0, 5), + } + , false); + + scene->AttachShape(quad); + + auto ibl_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); + + auto ibl = ImageBasedLight::Create(); + ibl->SetTexture(ibl_texture); + ibl->SetMultiplier(1.f); + scene->AttachLight(ibl); + + auto mat = UberV2Material::Create(); + mat->SetLayers(UberV2Material::Layers::kDiffuseLayer | + UberV2Material::Layers::kReflectionLayer); + mat->SetInputValue("uberv2.diffuse.color", + InputMap_ConstantFloat3::Create(float3(0.1f, 0.2f, 0.1f))); + mat->SetInputValue("uberv2.reflection.color", + InputMap_ConstantFloat3::Create(float3(0.9f, 0.9f, 0.9f))); + mat->SetInputValue("uberv2.reflection.roughness", + InputMap_ConstantFloat::Create(0.002f)); + mat->SetInputValue("uberv2.reflection.ior", + InputMap_ConstantFloat::Create(1.33f)); + + quad->SetMaterial(mat); + } + else if (fname == "sphere+ibl") + { + auto mesh = CreateSphere(64, 32, 2.f, float3()); + + auto mat = UberV2Material::Create(); + mat->SetLayers(UberV2Material::Layers::kDiffuseLayer); + mat->SetInputValue("uberv2.diffuse.color", + InputMap_ConstantFloat3::Create(float3(0.8f, 0.8f, 0.8f))); + + mesh->SetMaterial(mat); + scene->AttachShape(mesh); + + auto ibl_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); + + auto ibl = ImageBasedLight::Create(); + ibl->SetTexture(ibl_texture); + ibl->SetMultiplier(1.f); + scene->AttachLight(ibl); + } + else if (fname == "sphere+plane") + { + auto mesh = CreateSphere(64, 32, 2.f, float3(0.f, 2.5f, 0.f)); + scene->AttachShape(mesh); + + auto mat = UberV2Material::Create(); + mat->SetLayers(UberV2Material::Layers::kDiffuseLayer); + mat->SetInputValue("uberv2.diffuse.color", + InputMap_ConstantFloat3::Create(float3(0.8f, 0.8f, 0.8f))); + + mesh->SetMaterial(mat); + + auto floor = CreateQuad( + { + RadeonRays::float3(-8, 0, -8), + RadeonRays::float3(8, 0, -8), + RadeonRays::float3(8, 0, 8), + RadeonRays::float3(-8, 0, 8), + } + , false); + floor->SetMaterial(mat); + scene->AttachShape(floor); + } + else if (fname == "sphere+plane+area") + { + auto mesh = CreateSphere(64, 32, 2.f, float3(0.f, 2.5f, 0.f)); + scene->AttachShape(mesh); + + auto floor = CreateQuad( + { + RadeonRays::float3(-8, 0, -8), + RadeonRays::float3(8, 0, -8), + RadeonRays::float3(8, 0, 8), + RadeonRays::float3(-8, 0, 8), + } + , false); + scene->AttachShape(floor); + + auto mat = UberV2Material::Create(); + mat->SetLayers(UberV2Material::Layers::kDiffuseLayer); + mat->SetInputValue("uberv2.diffuse.color", + InputMap_ConstantFloat3::Create(float3(0.8f, 0.8f, 0.8f))); + + floor->SetMaterial(mat); + mesh->SetMaterial(mat); + + auto emissive = UberV2Material::Create(); + emissive->SetLayers(UberV2Material::Layers::kEmissionLayer); + emissive->SetInputValue("uberv2.emission.color", + InputMap_ConstantFloat3::Create(1.f * float3(3.1f, 3.f, 2.8f))); + + auto light = CreateQuad( + { + RadeonRays::float3(-2, 6, -2), + RadeonRays::float3(2, 6, -2), + RadeonRays::float3(2, 6, 2), + RadeonRays::float3(-2, 6, 2), + } + , true); + scene->AttachShape(light); + + light->SetMaterial(emissive); + + auto l1 = AreaLight::Create(light, 0); + auto l2 = AreaLight::Create(light, 1); + + scene->AttachLight(l1); + scene->AttachLight(l2); + } + else if (fname == "env_override_spheres") + { + auto mesh1 = CreateSphere(64, 32, 2.f, float3(-3.f, 2.5f, 0.f)); + scene->AttachShape(mesh1); + auto mesh2 = CreateSphere(64, 32, 2.f, float3(0.f, 2.5f, 0.f)); + scene->AttachShape(mesh2); + auto mesh3 = CreateSphere(64, 32, 2.f, float3(3.f, 2.5f, 0.f)); + scene->AttachShape(mesh3); + + auto reflective = UberV2Material::Create(); + reflective->SetLayers(UberV2Material::Layers::kReflectionLayer); + reflective->SetInputValue("uberv2.reflection.color", + InputMap_ConstantFloat3::Create(float3(0.9f, 0.9f, 0.9f))); + reflective->SetInputValue("uberv2.reflection.roughness", + InputMap_ConstantFloat::Create(0.001f)); + reflective->SetInputValue("uberv2.reflection.ior", + InputMap_ConstantFloat::Create(1.33f)); + mesh1->SetMaterial(reflective); + + auto refractive = UberV2Material::Create(); + refractive->SetLayers(UberV2Material::Layers::kRefractionLayer); + refractive->SetInputValue("uberv2.refraction.color", + InputMap_ConstantFloat3::Create(float3(0.7f, 0.7f, 0.7f))); + refractive->SetInputValue("uberv2.refraction.ior", + InputMap_ConstantFloat3::Create(1.5f)); + refractive->SetInputValue("uberv2.refraction.roughness", + InputMap_ConstantFloat3::Create(0.001f)); + mesh2->SetMaterial(refractive); + + auto transparent = UberV2Material::Create(); + transparent->SetLayers(UberV2Material::Layers::kTransparencyLayer); + transparent->SetInputValue("uberv2.transparency", + InputMap_ConstantFloat3::Create(1.f)); + mesh3->SetMaterial(transparent); + + } + else if (fname == "sphere+plane+area+ibl") + { + auto mesh = CreateSphere(64, 32, 2.f, float3(0.f, 2.5f, 0.f)); + scene->AttachShape(mesh); + + auto floor = CreateQuad( + { + RadeonRays::float3(-8, 0, -8), + RadeonRays::float3(8, 0, -8), + RadeonRays::float3(8, 0, 8), + RadeonRays::float3(-8, 0, 8), + } + , false); + scene->AttachShape(floor); + + auto emissive = UberV2Material::Create(); + emissive->SetLayers(UberV2Material::Layers::kEmissionLayer); + emissive->SetInputValue("uberv2.emission.color", + InputMap_ConstantFloat3::Create(1.f * float3(3.1f, 3.f, 2.8f))); + + auto transparent = UberV2Material::Create(); + transparent->SetLayers(UberV2Material::Layers::kTransparencyLayer); + transparent->SetInputValue("uberv2.transparency", + InputMap_ConstantFloat3::Create(1.f)); + + mesh->SetMaterial(transparent); + + auto volume = VolumeMaterial::Create(); + volume->SetInputValue("scattering", float4(0.1f, 0.1f, 0.1f)); + volume->SetInputValue("absorption", float4(1.25f, 1.25f, 1.25f)); + volume->SetInputValue("emission", float4(1.2f, 0.2f, 0.2f)); + mesh->SetVolumeMaterial(volume); + + auto light = CreateQuad( + { + RadeonRays::float3(-2, 6, -2), + RadeonRays::float3(2, 6, -2), + RadeonRays::float3(2, 6, 2), + RadeonRays::float3(-2, 6, 2), + } + , true); + scene->AttachShape(light); + + light->SetMaterial(emissive); + + auto l1 = AreaLight::Create(light, 0); + auto l2 = AreaLight::Create(light, 1); + + scene->AttachLight(l1); + scene->AttachLight(l2); + + auto ibl_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); + + auto ibl = ImageBasedLight::Create(); + ibl->SetTexture(ibl_texture); + ibl->SetMultiplier(1.f); + scene->AttachLight(ibl); + } + else if (fname == "sphere+plane+ibl") + { + auto mesh = CreateSphere(64, 32, 2.f, float3(0.f, 2.2f, 0.f)); + scene->AttachShape(mesh); + + auto mix = UberV2Material::Create(); + mix->SetLayers(UberV2Material::Layers::kRefractionLayer/* | + UberV2Material::Layers::kReflectionLayer*/); + mix->SetInputValue("uberv2.refraction.color", + InputMap_ConstantFloat3::Create(float3(0.7f, 1.f, 0.7f))); + mix->SetInputValue("uberv2.refraction.ior", + InputMap_ConstantFloat3::Create(1.5f)); + mix->SetInputValue("uberv2.refraction.roughness", + InputMap_ConstantFloat3::Create(0.1f)); + mix->SetInputValue("uberv2.reflection.color", + InputMap_ConstantFloat3::Create(float3(0.7f, 1.f, 0.7f))); + mix->SetInputValue("uberv2.reflection.roughness", + InputMap_ConstantFloat3::Create(0.02f)); + mix->SetInputValue("uberv2.reflection.ior", + InputMap_ConstantFloat3::Create(1.5f)); + + mesh->SetMaterial(mix); + + auto floor = CreateQuad( + { + RadeonRays::float3(-8, 0, -8), + RadeonRays::float3(8, 0, -8), + RadeonRays::float3(8, 0, 8), + RadeonRays::float3(-8, 0, 8), + } + , false); + + scene->AttachShape(floor); + auto diffuse = UberV2Material::Create(); + diffuse->SetLayers(UberV2Material::Layers::kDiffuseLayer); + diffuse->SetInputValue("uberv2.diffuse.color", + InputMap_ConstantFloat3::Create(float3(0.8f, 0.8f, 0.8f))); + floor->SetMaterial(diffuse); + + auto ibl_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); + + auto ibl = ImageBasedLight::Create(); + ibl->SetTexture(ibl_texture); + ibl->SetMultiplier(1.f); + scene->AttachLight(ibl); + } + else if (fname == "uberv2_test_spheres") + { + auto mesh = CreateSphere(64, 32, 0.9f, float3(0.f, 1.0f, 0.f)); + scene->AttachShape(mesh); + auto roughness = InputMap_ConstantFloat::Create(0.05f); + + auto uberv2 = UberV2Material::Create(); + uberv2->SetInputValue("uberv2.diffuse.color", InputMap_ConstantFloat3::Create(float3(1.0f, 1.0f, 1.0f, 0.0f))); + uberv2->SetInputValue("uberv2.coating.color", InputMap_ConstantFloat3::Create(float3(1.0f, 0.0f, 0.0f, 0.0f))); + uberv2->SetInputValue("uberv2.reflection.roughness", roughness); + uberv2->SetInputValue("uberv2.reflection.color", InputMap_ConstantFloat3::Create(float3(0.0f, 1.0f, 0.0f, 0.0f))); + uberv2->SetInputValue("uberv2.refraction.color", InputMap_ConstantFloat3::Create(float3(0.0f, 0.0f, 1.0f, 0.0f))); + uberv2->SetInputValue("uberv2.refraction.roughness", roughness); + uberv2->SetLayers(UberV2Material::Layers::kDiffuseLayer | UberV2Material::Layers::kCoatingLayer | UberV2Material::Layers::kReflectionLayer | UberV2Material::Layers::kRefractionLayer); + mesh->SetMaterial(uberv2); + matrix t = RadeonRays::translation(float3(0, 0, -10.f)); + mesh->SetTransform(t); + + auto diffuse_color = InputMap_ConstantFloat3::Create(float3(1.0f, 0.0f, 0.0f, 0.0f)); + + for (int i = 0; i < 5; ++i) + { + for (int j = 0; j < 10; ++j) + { + uberv2 = UberV2Material::Create(); + + switch (i) + { + case 0: + uberv2->SetInputValue("uberv2.diffuse.color", diffuse_color); + uberv2->SetInputValue("uberv2.coating.ior", InputMap_ConstantFloat::Create(1.0f + (float)j/5.f)); + uberv2->SetLayers(UberV2Material::Layers::kDiffuseLayer | UberV2Material::Layers::kCoatingLayer); + break; + case 1: + uberv2->SetInputValue("uberv2.diffuse.color", diffuse_color); + uberv2->SetInputValue("uberv2.reflection.roughness", InputMap_ConstantFloat::Create((float)j/10.f)); + uberv2->SetLayers(UberV2Material::Layers::kDiffuseLayer | UberV2Material::Layers::kReflectionLayer); + break; + case 2: + uberv2->SetInputValue("uberv2.diffuse.color", diffuse_color); + uberv2->SetInputValue("uberv2.reflection.ior", InputMap_ConstantFloat::Create(1.0f + (float)j / 5.f)); + uberv2->SetInputValue("uberv2.reflection.roughness", roughness); + uberv2->SetLayers(UberV2Material::Layers::kDiffuseLayer | UberV2Material::Layers::kReflectionLayer); + break; + case 3: + uberv2->SetInputValue("uberv2.diffuse.color", diffuse_color); + uberv2->SetInputValue("uberv2.refraction.roughness", InputMap_ConstantFloat::Create((float)j / 10.f)); + uberv2->SetLayers(UberV2Material::Layers::kDiffuseLayer | UberV2Material::Layers::kRefractionLayer); + break; + case 4: + uberv2->SetInputValue("uberv2.diffuse.color", diffuse_color); + uberv2->SetInputValue("uberv2.transparency", InputMap_ConstantFloat::Create((float)j/9.f)); + uberv2->SetInputValue("uberv2.reflection.roughness", roughness); + uberv2->SetLayers(UberV2Material::Layers::kDiffuseLayer | UberV2Material::Layers::kReflectionLayer | UberV2Material::Layers::kTransparencyLayer); + break; + } + // Uncomment when instancing will be fixed + //auto instance = Instance::Create(mesh); + auto instance = CreateSphere(64, 32, 0.9f, float3(0.f, 1.0f, 0.f)); + t = RadeonRays::translation(float3(j * 2.f - 9.f, i * 2.f - 3.f, -10.f)); + instance->SetTransform(t); + scene->AttachShape(instance); + instance->SetMaterial(uberv2); + } + } + auto ibl_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); + + auto ibl = ImageBasedLight::Create(); + ibl->SetTexture(ibl_texture); + ibl->SetMultiplier(1.f); + scene->AttachLight(ibl); + } + else if (fname == "sphere+uberv2+ibl") + { + auto mesh = CreateSphere(64, 32, 2.f, float3()); + scene->AttachShape(mesh); + auto texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + auto sampler = InputMap_Sampler::Create(texture); + + auto roughness = InputMap_ConstantFloat::Create(0.05f); + auto gamma = InputMap_ConstantFloat::Create(2.2f); + auto diffuse_color = InputMap_Pow::Create(sampler, gamma); + + auto uberv2 = UberV2Material::Create(); + uberv2->SetInputValue("uberv2.diffuse.color", diffuse_color); + uberv2->SetInputValue("uberv2.coating.color", diffuse_color); + uberv2->SetInputValue("uberv2.reflection.roughness", roughness); + uberv2->SetInputValue("uberv2.reflection.color", diffuse_color); + uberv2->SetLayers(UberV2Material::Layers::kDiffuseLayer | + UberV2Material::Layers::kReflectionLayer); + mesh->SetMaterial(uberv2); + + + auto ibl_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); + + auto ibl = ImageBasedLight::Create(); + ibl->SetTexture(ibl_texture); + ibl->SetMultiplier(1.f); + scene->AttachLight(ibl); + + } + else if (fname == "shere+plane_uberv2+ibl+normalmap") + { + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto bump_texture = image_io->LoadImage("../Resources/Textures/test_normal.jpg"); + + auto bump_material = Baikal::UberV2Material::Create(); + auto bump_sampler = Baikal::InputMap_Sampler::Create(bump_texture); + auto bump_remap = Baikal::InputMap_Remap::Create( + Baikal::InputMap_ConstantFloat3::Create(float3(0.0f, 1.0f, 0.0f)), + Baikal::InputMap_ConstantFloat3::Create(float3(-1.0f, 1.0f, 0.0f)), + bump_sampler); + bump_material->SetInputValue("uberv2.shading_normal", bump_remap); + //bump_material->SetInputValue("uberv2.diffuse.color", bump_sampler); + bump_material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer | + Baikal::UberV2Material::Layers::kShadingNormalLayer); + + auto texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + auto sampler = InputMap_Sampler::Create(texture); + + auto roughness = InputMap_ConstantFloat::Create(0.05f); + auto gamma = InputMap_ConstantFloat::Create(2.2f); + auto diffuse_color = InputMap_Pow::Create(sampler, gamma); + + auto uberv2 = UberV2Material::Create(); + uberv2->SetInputValue("uberv2.diffuse.color", diffuse_color); + uberv2->SetInputValue("uberv2.coating.color", diffuse_color); + uberv2->SetInputValue("uberv2.reflection.roughness", roughness); + uberv2->SetInputValue("uberv2.reflection.color", diffuse_color); + uberv2->SetLayers(UberV2Material::Layers::kDiffuseLayer | + UberV2Material::Layers::kReflectionLayer); + + auto mesh = CreateSphere(64, 32, 2.f, float3(0.f, 2.2f, 0.f)); + scene->AttachShape(mesh); + mesh->SetMaterial(uberv2); + + auto floor = CreateQuad( + { + RadeonRays::float3(-8, 0, -8), + RadeonRays::float3(8, 0, -8), + RadeonRays::float3(8, 0, 8), + RadeonRays::float3(-8, 0, 8), + } + , false); + + scene->AttachShape(floor); + floor->SetMaterial(bump_material); + + auto light = SpotLight::Create(); + light->SetPosition(RadeonRays::float3(0.f, 20.f, 0.f)); + light->SetEmittedRadiance(RadeonRays::float3(100.f, 100.f, 100.f)); + light->SetConeShape(RadeonRays::float2(0.05f, 0.1f)); + scene->AttachLight(light); + } + else if (fname == "transparent_planes") + { + auto transparent_mtl = UberV2Material::Create(); + transparent_mtl->SetInputValue("uberv2.diffuse.color", InputMap_ConstantFloat3::Create(float3(1.0f, 0.0f, 0.0f, 0.0f))); + transparent_mtl->SetInputValue("uberv2.transparency", InputMap_ConstantFloat::Create(0.9f)); + transparent_mtl->SetLayers(UberV2Material::Layers::kDiffuseLayer | UberV2Material::Layers::kTransparencyLayer); + + for (int i = 0; i < 8; ++i) + { + auto wall = CreateQuad( + { + RadeonRays::float3(-8, 8, i * 2.0f), + RadeonRays::float3(-8, 0, i * 2.0f), + RadeonRays::float3( 8, 0, i * 2.0f), + RadeonRays::float3( 8, 8, i * 2.0f), + } + , false); + wall->SetMaterial(transparent_mtl); + scene->AttachShape(wall); + } + + auto floor_mtl = UberV2Material::Create(); + floor_mtl->SetInputValue("uberv2.diffuse.color", InputMap_ConstantFloat3::Create(float3(0.5f, 0.5f, 0.5f, 0.0f))); + floor_mtl->SetInputValue("uberv2.reflection.roughness", InputMap_ConstantFloat::Create(0.01f)); + floor_mtl->SetLayers(UberV2Material::Layers::kDiffuseLayer | UberV2Material::Layers::kReflectionLayer); + + auto floor = CreateQuad( + { + RadeonRays::float3(-8, 0, -8), + RadeonRays::float3(8, 0, -8), + RadeonRays::float3(8, 0, 8), + RadeonRays::float3(-8, 0, 8), + } + , false); + floor->SetMaterial(floor_mtl); + scene->AttachShape(floor); + + auto ibl_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); + auto ibl = ImageBasedLight::Create(); + ibl->SetTexture(ibl_texture); + ibl->SetMultiplier(1.f); + scene->AttachLight(ibl); + } + else if (fname == "4kmaterials") + { + auto mesh = CreateSphere(64, 32, 0.1f, float3(0.f, 0.0f, 0.f)); + scene->AttachShape(mesh); + auto roughness = InputMap_ConstantFloat::Create(0.05f); + + auto uberv2 = UberV2Material::Create(); + uberv2->SetInputValue("uberv2.diffuse.color", InputMap_ConstantFloat3::Create(float3(1.0f, 1.0f, 1.0f, 0.0f))); + uberv2->SetLayers(UberV2Material::Layers::kDiffuseLayer); + mesh->SetMaterial(uberv2); + matrix t = RadeonRays::translation(float3(0, 0, -10.f)); + mesh->SetTransform(t); + + for (int a = 0 ; a < 400; ++a) + { + auto instance = Instance::Create(mesh); + auto uberv2 = UberV2Material::Create(); + uberv2->SetInputValue("uberv2.diffuse.color", InputMap_ConstantFloat3::Create(float3(1.0f, 1.0f, 1.0f, 0.0f))); + uberv2->SetLayers(UberV2Material::Layers::kDiffuseLayer); + instance->SetMaterial(uberv2); + matrix t = RadeonRays::translation(float3((a/1024-512)/512.f, 0.f, -10.f)); + instance->SetTransform(t); + scene->AttachShape(instance); + } + + auto ibl_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); + + auto ibl = ImageBasedLight::Create(); + ibl->SetTexture(ibl_texture); + ibl->SetMultiplier(1.f); + scene->AttachLight(ibl); + } + + + return scene; + } +} + diff --git a/BaikalStandalone/Application/app_utils.cpp b/BaikalStandalone/Application/app_utils.cpp new file mode 100644 index 00000000..ef800676 --- /dev/null +++ b/BaikalStandalone/Application/app_utils.cpp @@ -0,0 +1,207 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "Application/app_utils.h" + +#include + +namespace +{ + char const* kHelpMessage = + "Baikal [-p path_to_models][-f model_name][-b][-r][-ns number_of_shadow_rays][-ao ao_radius][-w window_width][-h window_height][-nb number_of_indirect_bounces]"; +} + +namespace Baikal +{ + AppCliParser::AppCliParser(int argc, char * argv[]) + : m_cmd_parser(argc, argv) + { } + + AppSettings AppCliParser::Parse() + { + AppSettings s; + + s.path = m_cmd_parser.GetOption("-p", s.path); + + s.modelname = m_cmd_parser.GetOption("-f", s.modelname); + + s.envmapname = m_cmd_parser.GetOption("-e", s.envmapname); + + s.width = m_cmd_parser.GetOption("-w", s.width); + + s.height = m_cmd_parser.GetOption("-h", s.height); + + if (m_cmd_parser.OptionExists("-ao")) + { + s.ao_radius = m_cmd_parser.GetOption("-ao"); + s.num_ao_rays = (int)(s.ao_radius); + s.ao_enabled = true; + } + + s.num_bounces = m_cmd_parser.GetOption("-nb", s.num_bounces); + + s.camera_pos.x = m_cmd_parser.GetOption("-cpx", s.camera_pos.x); + + s.camera_pos.y = m_cmd_parser.GetOption("-cpy", s.camera_pos.y); + + s.camera_pos.z = m_cmd_parser.GetOption("-cpz", s.camera_pos.z); + + s.camera_at.x = m_cmd_parser.GetOption("-tpx", s.camera_at.x); + + s.camera_at.y = m_cmd_parser.GetOption("-tpy", s.camera_at.y); + + s.camera_at.z = m_cmd_parser.GetOption("-tpz", s.camera_at.z); + + s.envmapmul = m_cmd_parser.GetOption("-em", s.envmapmul); + + s.num_samples = m_cmd_parser.GetOption("-ns", s.num_samples); + + s.camera_aperture = m_cmd_parser.GetOption("-a", s.camera_aperture); + + s.camera_focus_distance = m_cmd_parser.GetOption("-fd", s.camera_focus_distance); + + s.camera_focal_length = m_cmd_parser.GetOption("-fl", s.camera_focal_length); + + s.camera_out_folder = m_cmd_parser.GetOption("-output_cam", s.camera_out_folder); + + s.camera_sensor_size.x = m_cmd_parser.GetOption("-ssx", s.camera_sensor_size.x); + + s.camera_sensor_size.y = m_cmd_parser.GetOption("-ssy", s.camera_sensor_size.y); + + s.base_image_file_name = m_cmd_parser.GetOption("-ifn", s.base_image_file_name); + + s.image_file_format = m_cmd_parser.GetOption("-iff", s.image_file_format); + + s.light_file = m_cmd_parser.GetOption("-lights", s.light_file); + + if (m_cmd_parser.OptionExists("-ct")) + { + auto camera_type = m_cmd_parser.GetOption("-ct"); + + if (camera_type == "perspective") + s.camera_type = CameraType::kPerspective; + else if (camera_type == "orthographic") + s.camera_type = CameraType::kOrthographic; + else + throw std::runtime_error("Unsupported camera type"); + } + + s.interop = m_cmd_parser.GetOption("-interop", s.interop); + + s.cspeed = m_cmd_parser.GetOption("-cs", s.cspeed); + + if (m_cmd_parser.OptionExists("-config")) + { + auto cfg = m_cmd_parser.GetOption("-config"); + + if (cfg == "cpu") + s.mode = ConfigManager::Mode::kUseSingleCpu; + else if (cfg == "gpu") + s.mode = ConfigManager::Mode::kUseSingleGpu; + else if (cfg == "mcpu") + s.mode = ConfigManager::Mode::kUseCpus; + else if (cfg == "mgpu") + s.mode = ConfigManager::Mode::kUseGpus; + else if (cfg == "all") + s.mode = ConfigManager::Mode::kUseAll; + } + + s.platform_index = m_cmd_parser.GetOption("-platform", s.platform_index); + + s.device_index = m_cmd_parser.GetOption("-device", s.device_index); + + if ((s.device_index >= 0) && (s.platform_index < 0)) + { + std::cout << + "Can not set device index, because platform index was not specified" << std::endl; + } + + if (m_cmd_parser.OptionExists("-r")) + { + s.progressive = true; + } + + if (m_cmd_parser.OptionExists("-nowindow")) + { + s.cmd_line_mode = true; + } + + return s; + } + + void AppCliParser::ShowHelp() + { + std::cout << kHelpMessage << "\n"; + } + + AppSettings::AppSettings() + : path("../Resources/CornellBox") + , modelname("orig.objm") + , envmapname("../Resources/Textures/studio015.hdr") + //render + , width(512) + , height(512) + , num_bounces(5) + , num_samples(-1) + , interop(true) + , cspeed(10.25f) + , mode(ConfigManager::Mode::kUseSingleGpu) + //ao + , ao_radius(1.f) + , num_ao_rays(1) + , ao_enabled(false) + + //camera + , camera_pos(0.f, 1.f, 3.f) + , camera_at(0.f, 1.f, 0.f) + , camera_up(0.f, 1.f, 0.f) + , camera_sensor_size(0.036f, 0.024f) // default full frame sensor 36x24 mm + , camera_zcap(0.0f, 100000.f) + , camera_aperture(0.f) + , camera_focus_distance(1.f) + , camera_focal_length(0.035f) // 35mm lens + , camera_type (CameraType::kPerspective) + , camera_out_folder(".") + + //app + , progressive(false) + , cmd_line_mode(false) + , recording_enabled(false) + , benchmark(false) + , gui_visible(true) + , time_benchmarked(false) + , rt_benchmarked(false) + , time_benchmark(false) + , time_benchmark_time(0.f) + + //imagefile + , base_image_file_name("out") + , image_file_format("png") + + //unused + , num_shadow_rays(1) + , samplecount(0) + , envmapmul(1.f) + , platform_index(-1) + , device_index(-1) + { + } +} \ No newline at end of file diff --git a/BaikalStandalone/Application/app_utils.h b/BaikalStandalone/Application/app_utils.h new file mode 100644 index 00000000..2febb9b2 --- /dev/null +++ b/BaikalStandalone/Application/app_utils.h @@ -0,0 +1,116 @@ + +/********************************************************************** + Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ +#pragma once + +#include + +#include "radeon_rays.h" +#include "Utils/config_manager.h" +#include "Utils/cmd_parser.h" +#include "Baikal/Renderers/renderer.h" +#include "Baikal/Estimators/estimator.h" + +namespace Baikal +{ + struct AppSettings + { + AppSettings(); + + //model load settings + std::string path; + std::string modelname; + std::string envmapname; + + //render + int width; + int height; + int num_bounces; + int num_samples; + bool interop; + float cspeed; + ConfigManager::Mode mode; + + //ao + float ao_radius; + int num_ao_rays; + bool ao_enabled; + + //camera + RadeonRays::float3 camera_pos; + RadeonRays::float3 camera_at; + RadeonRays::float3 camera_up; + RadeonRays::float2 camera_sensor_size; + RadeonRays::float2 camera_zcap; + float camera_aperture; + float camera_focus_distance; + float camera_focal_length; + CameraType camera_type; + + //folder to store camera position output + std::string camera_out_folder; + + //app + bool progressive; + bool cmd_line_mode; + bool recording_enabled; + bool benchmark; + bool gui_visible; + + //bencmark + Estimator::RayTracingStats stats; + bool time_benchmarked; + bool rt_benchmarked; + bool time_benchmark; + float time_benchmark_time; + + //image file + std::string base_image_file_name; + std::string image_file_format; + + //light file + std::string light_file; + + //unused + int num_shadow_rays; + int samplecount; + float envmapmul; + // OpenCL platform & device settings + int platform_index; + int device_index; + + }; + + class AppCliParser + { + public: + + AppCliParser(int argc, char * argv[]); + AppSettings Parse(); + + private: + + void ShowHelp(); + + CmdParser m_cmd_parser; + }; +} diff --git a/BaikalStandalone/Application/application.cpp b/BaikalStandalone/Application/application.cpp new file mode 100644 index 00000000..c0f7ef91 --- /dev/null +++ b/BaikalStandalone/Application/application.cpp @@ -0,0 +1,1057 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 +#ifdef __APPLE__ +#include +#define GLFW_INCLUDE_GLCOREARB +#define GLFW_NO_GLU +#include "GLFW/glfw3.h" +#elif WIN32 +#define NOMINMAX +#include +#include "GL/glew.h" +#include "GLFW/glfw3.h" +#else +#include +#include +#include +#include "GLFW/glfw3.h" +#endif + +#include "ImGUI/imgui.h" +#include "ImGUI/imgui_impl_glfw_gl3.h" + +#include "XML/tinyxml2.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define _USE_MATH_DEFINES +#include + +#ifdef RR_EMBED_KERNELS +#include "./CL/cache/kernels.h" +#endif + +#include "CLW.h" + +#include "math/mathutils.h" +#include "Application/application.h" +#include "material_io.h" +#include "Application/material_explorer.h" + +using namespace RadeonRays; + +namespace Baikal +{ + static bool g_is_left_pressed = false; + static bool g_is_right_pressed = false; + static bool g_is_fwd_pressed = false; + static bool g_is_back_pressed = false; + static bool g_is_climb_pressed = false; + static bool g_is_descent_pressed = false; + static bool g_is_mouse_tracking = false; + static bool g_is_double_click = false; + static bool g_is_f10_pressed = false; + static bool g_is_middle_pressed = false; // middle mouse button + static bool g_is_c_pressed = false; + static bool g_is_l_pressed = false; + static float2 g_mouse_pos = float2(0, 0); + static float2 g_mouse_delta = float2(0, 0); + static float2 g_scroll_delta = float2(0, 0); + + const std::string kCameraLogFile("camera.xml"); + //ls - light set + const std::string kLightLogFile("light.xml"); + + auto start = std::chrono::high_resolution_clock::now(); + + // helper functions (AppendCamera, AppendLight) to log camera position and light settings + void AppendCamera(Baikal::PerspectiveCamera const* cam, const char* xml) + { + //camera values + RadeonRays::float3 cam_pos = cam->GetPosition(); + RadeonRays::float3 cam_at = cam->GetForwardVector(); + RadeonRays::float3 cam_up = cam->GetUpVector(); + + float aperture = cam->GetAperture(); + float focus_dist = cam->GetFocusDistance(); + float focal_length = cam->GetFocalLength(); + + tinyxml2::XMLDocument doc; + + doc.LoadFile(xml); + auto root = doc.FirstChildElement("cam_list"); + if (!root) + { + root = doc.NewElement("cam_list"); + doc.InsertFirstChild(root); + } + + auto new_cam = doc.NewElement("camera"); + //position + new_cam->SetAttribute("cpx", cam_pos.x); + new_cam->SetAttribute("cpy", cam_pos.y); + new_cam->SetAttribute("cpz", cam_pos.z); + + //target + new_cam->SetAttribute("tpx", cam_at.x); + new_cam->SetAttribute("tpy", cam_at.y); + new_cam->SetAttribute("tpz", cam_at.z); + + //uo vector + new_cam->SetAttribute("upx", cam_up.x); + new_cam->SetAttribute("upy", cam_up.y); + new_cam->SetAttribute("upz", cam_up.z); + + //other values + new_cam->SetAttribute("aperture", aperture); + new_cam->SetAttribute("focus_dist", focus_dist); + new_cam->SetAttribute("focal_length", focal_length); + + root->InsertEndChild(new_cam); + doc.SaveFile(xml); + } + + void AppendLight(Baikal::Light::Ptr l, const char* xml) + { + //get light type + Baikal::ImageBasedLight* ibl = dynamic_cast(l.get()); + Baikal::PointLight* pointl = dynamic_cast(l.get()); + Baikal::DirectionalLight* directl = dynamic_cast(l.get()); + Baikal::SpotLight* spotl = dynamic_cast(l.get()); + Baikal::AreaLight* areal = dynamic_cast(l.get()); + + tinyxml2::XMLDocument doc; + + doc.LoadFile(xml); + auto root = doc.FirstChildElement("light_list"); + if (!root) + { + root = doc.NewElement("light_list"); + doc.InsertFirstChild(root); + } + + if (areal) + { + //area lights are created when materials load, so ignore it; + return; + } + + tinyxml2::XMLElement* light_elem = nullptr; + if (ibl) + { + light_elem = doc.NewElement("light"); + light_elem->SetAttribute("type", "ibl"); + light_elem->SetAttribute("tex", ibl->GetTexture()->GetName().c_str()); + light_elem->SetAttribute("mul", ibl->GetMultiplier()); + } + else if (spotl) + { + light_elem = doc.NewElement("light"); + light_elem->SetAttribute("type", "spot"); + light_elem->SetAttribute("csx", spotl->GetConeShape().x); + light_elem->SetAttribute("csy", spotl->GetConeShape().y); + } + else if (pointl) + { + light_elem = doc.NewElement("light"); + light_elem->SetAttribute("type", "point"); + } + else if (directl) + { + light_elem = doc.NewElement("light"); + light_elem->SetAttribute("type", "direct"); + } + + float3 p = l->GetPosition(); + float3 d = l->GetDirection(); + float3 r = l->GetEmittedRadiance(); + + light_elem->SetAttribute("posx", p.x); + light_elem->SetAttribute("posy", p.y); + light_elem->SetAttribute("posz", p.z); + + light_elem->SetAttribute("dirx", d.x); + light_elem->SetAttribute("diry", d.y); + light_elem->SetAttribute("dirz", d.z); + + light_elem->SetAttribute("radx", r.x); + light_elem->SetAttribute("rady", r.y); + light_elem->SetAttribute("radz", r.z); + + root->InsertEndChild(light_elem); + doc.SaveFile(xml); + } + + bool Application::InputSettings::HasMultiplier() const + { return m_multiplier.first; } + + float Application::InputSettings::GetMultiplier() const + { return m_multiplier.second; } + + void Application::InputSettings::SetMultiplier(float multiplier) + { + m_multiplier.first = true; + m_multiplier.second = multiplier; + } + + RadeonRays::float3 Application::InputSettings::GetColor() const + { return m_color.second; } + + void Application::InputSettings::SetColor(RadeonRays::float3 color) + { + m_color.first = true; + m_color.second = color; + } + + std::uint32_t Application::InputSettings::GetInteger() const + { return m_integer_input.second; } + + void Application::InputSettings::SetInteger(std::uint32_t integer) + { + m_integer_input.first= true; + m_integer_input.second = integer; + } + + std::string Application::InputSettings::GetTexturePath() const + { return m_texture_path.second; } + + void Application::InputSettings::SetTexturePath(std::string texture_path) + { + m_texture_path.first = true; + m_texture_path.second = texture_path; + } + + + void Application::OnMouseMove(GLFWwindow* window, double x, double y) + { + if (g_is_mouse_tracking) + { + g_mouse_delta = float2((float)x, (float)y) - g_mouse_pos; + g_mouse_pos = float2((float)x, (float)y); + } + } + + void Application::OnMouseScroll(GLFWwindow* window, double x, double y) + { + g_scroll_delta = float2((float)x, (float)y); + } + + void Application::OnMouseButton(GLFWwindow* window, int button, int action, int mods) + { + if ((button == GLFW_MOUSE_BUTTON_LEFT) || + (button == GLFW_MOUSE_BUTTON_RIGHT) || + (button == GLFW_MOUSE_BUTTON_MIDDLE)) + { + if (action == GLFW_PRESS) + { + + double x, y; + glfwGetCursorPos(window, &x, &y); + g_mouse_pos = float2((float)x, (float)y); + g_mouse_delta = float2(0, 0); + } + else if (action == GLFW_RELEASE && g_is_mouse_tracking) + { + g_is_mouse_tracking = false; + g_is_middle_pressed = false; + g_mouse_delta = float2(0, 0); + } + } + + if ((button == GLFW_MOUSE_BUTTON_RIGHT) && (action == GLFW_PRESS)) + { + g_is_mouse_tracking = true; + } + + if (button == GLFW_MOUSE_BUTTON_LEFT) + { + if (action == GLFW_PRESS) + { + double x, y; + glfwGetCursorPos(window, &x, &y); + g_mouse_pos = float2((float)x, (float)y); + + auto duration = std::chrono::duration_cast + (std::chrono::high_resolution_clock::now() - start); + g_is_double_click = (duration.count() < 200) ? (true) : (false); + start = std::chrono::high_resolution_clock::now(); + } + + else if (action == GLFW_RELEASE && g_is_mouse_tracking) + { + g_is_double_click = false; + } + } + + if (button == GLFW_MOUSE_BUTTON_MIDDLE) + { + if (action == GLFW_PRESS) + { + g_is_middle_pressed = true; + g_is_mouse_tracking = true; + } + } + } + + void Application::OnKey(GLFWwindow* window, int key, int scancode, int action, int mods) + { + ImGuiIO& io = ImGui::GetIO(); + Application* app = static_cast(glfwGetWindowUserPointer(window)); + + const bool press_or_repeat = action == GLFW_PRESS || action == GLFW_REPEAT; + + if (action == GLFW_PRESS) + io.KeysDown[key] = true; + if (action == GLFW_RELEASE) + io.KeysDown[key] = false; + + (void)mods; // Modifiers are not reliable across systems + io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL]; + io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT]; + io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT]; + io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; + + switch (key) + { + case GLFW_KEY_W: + g_is_fwd_pressed = press_or_repeat; + break; + case GLFW_KEY_S: + g_is_back_pressed = press_or_repeat; + break; + case GLFW_KEY_A: + g_is_left_pressed = press_or_repeat; + break; + case GLFW_KEY_D: + g_is_right_pressed = press_or_repeat; + break; + case GLFW_KEY_Q: + g_is_climb_pressed = press_or_repeat; + break; + case GLFW_KEY_E: + g_is_descent_pressed = press_or_repeat; + break; + case GLFW_KEY_F1: + app->m_settings.gui_visible = action == GLFW_PRESS ? !app->m_settings.gui_visible : app->m_settings.gui_visible; + break; + case GLFW_KEY_F3: + app->m_settings.benchmark = action == GLFW_PRESS ? true : app->m_settings.benchmark; + break; + case GLFW_KEY_F10: + g_is_f10_pressed = action == GLFW_PRESS; + break; + case GLFW_KEY_C: + g_is_c_pressed = action == GLFW_RELEASE ? true : false; + break; + case GLFW_KEY_L: + g_is_l_pressed = action == GLFW_RELEASE ? true : false; + default: + break; + } + } + + void Application::OnWindowResize(GLFWwindow* window, int /* width */, int /* height */) + { + Application* app = static_cast(glfwGetWindowUserPointer(window)); + glfwSetWindowSize(window, app->m_settings.width, app->m_settings.height); + } + + void Application::Update(bool update_required) + { + static auto prevtime = std::chrono::high_resolution_clock::now(); + auto time = std::chrono::high_resolution_clock::now(); + auto dt = std::chrono::duration_cast>(time - prevtime); + prevtime = time; + + bool update = update_required; + float camrotx = 0.f; + float camroty = 0.f; + + const float kMouseSensitivity = 0.001125f; + const float kScrollSensitivity = 0.05f; + auto camera = m_cl->GetCamera(); + if (!m_settings.benchmark && !m_settings.time_benchmark) + { + float2 delta = g_mouse_delta * float2(kMouseSensitivity, kMouseSensitivity); + float2 scroll_delta = g_scroll_delta * float2(kScrollSensitivity, kScrollSensitivity); + camrotx = -delta.x; + camroty = -delta.y; + + + if (!g_is_middle_pressed) + { + + if (std::abs(camroty) > 0.001f) + { + camera->Tilt(camroty); + update = true; + } + + if (std::abs(camrotx) > 0.001f) + { + + camera->Rotate(camrotx); + update = true; + } + } + + const float kMovementSpeed = m_settings.cspeed; + if (std::abs(scroll_delta.y) > 0.001f) + { + camera->Zoom(scroll_delta.y * kMovementSpeed); + g_scroll_delta = float2(); + update = true; + } + if (g_is_fwd_pressed) + { + camera->MoveForward((float)dt.count() * kMovementSpeed); + update = true; + } + + if (g_is_back_pressed) + { + camera->MoveForward(-(float)dt.count() * kMovementSpeed); + update = true; + } + + if (g_is_right_pressed) + { + camera->MoveRight((float)dt.count() * kMovementSpeed); + update = true; + } + + if (g_is_left_pressed) + { + camera->MoveRight(-(float)dt.count() * kMovementSpeed); + update = true; + } + + if (g_is_climb_pressed) + { + camera->MoveUp((float)dt.count() * kMovementSpeed); + update = true; + } + + if (g_is_descent_pressed) + { + camera->MoveUp(-(float)dt.count() * kMovementSpeed); + update = true; + } + + if (g_is_f10_pressed) + { + g_is_f10_pressed = false; //one time execution + SaveToFile(time); + } +#ifdef GENERATE_DATASET + //log camera props + if (g_is_c_pressed) + { + PerspectiveCamera* pcam = dynamic_cast(camera.get()); + AppendCamera(pcam, kCameraLogFile.c_str()); + + g_is_c_pressed = false; + } + //log scene lights + if (g_is_l_pressed) + { + auto scene = m_cl->GetScene(); + auto it = scene->CreateLightIterator(); + for (; it->IsValid(); it->Next()) + { + Light::Ptr l = it->ItemAs(); + AppendLight(l, kLightLogFile.c_str()); + } + + g_is_l_pressed = false; + } +#endif + if (g_is_middle_pressed) + { + float distance = (float)dt.count() * kMovementSpeed / 2.f; + float right_shift, up_shift; + right_shift = (delta.x) ? distance * delta.x / std::abs(delta.x) : 0; + up_shift = (delta.y) ? distance * delta.y / std::abs(delta.y) : 0; + camera->MoveRight(-right_shift); + camera->MoveUp(up_shift); + update = true; + g_mouse_delta = RadeonRays::float2(0, 0); + } + } + + if (update) + { + //if (g_num_samples > -1) + { + m_settings.samplecount = 0; + } + + m_cl->UpdateScene(); + } + + if (m_settings.num_samples == -1 || m_settings.samplecount < m_settings.num_samples) + { + m_cl->Render(m_settings.samplecount); + + } + else if (m_settings.samplecount == m_settings.num_samples) + { + m_cl->SaveFrameBuffer(m_settings); + std::cout << "Target sample count reached\n"; + } + + m_cl->Update(m_settings); + } + + void Application::SaveToFile(std::chrono::high_resolution_clock::time_point time) const + { + using namespace OIIO; + int w, h; + glfwGetFramebufferSize(m_window.get(), &w, &h); + assert(glGetError() == 0); + + const auto channels = 3; + auto *data = new GLubyte[channels * w * h]; + glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, data); + + //opengl coordinates to oiio coordinates + for (auto i = 0; i <= h / 2; ++i) + { + std::swap_ranges(data + channels * w * i, data + channels * w * (i + 1) - 1, data + channels * w * (h - (i + 1))); + } + + const auto filename = m_settings.path + "/" + m_settings.base_image_file_name + "-" + std::to_string(time.time_since_epoch().count()) + "." + m_settings.image_file_format; + + auto out = ImageOutput::create(filename); + if (out) + { + ImageSpec spec{ w, h, channels, TypeDesc::UINT8 }; + out->open(filename, spec); + out->write_image(TypeDesc::UINT8, data); + out->close(); + delete out; // ImageOutput::destroy not found + } + else + { + std::cout << "Wrong file format\n"; + } + + delete[] data; + } + + + void OnError(int error, const char* description) + { + std::cout << description << "\n"; + } + + bool GradeTimeBenchmarkResults(std::string const& scene, int time_in_sec, std::string& rating, ImVec4& color) + { + if (scene == "classroom.obj") + { + if (time_in_sec < 70) + { + rating = "Excellent"; + color = ImVec4(0.1f, 0.7f, 0.1f, 1.f); + } + else if (time_in_sec < 100) + { + rating = "Good"; + color = ImVec4(0.1f, 0.7f, 0.1f, 1.f); + } + else if (time_in_sec < 120) + { + rating = "Average"; + color = ImVec4(0.7f, 0.7f, 0.1f, 1.f); + } + else + { + rating = "Poor"; + color = ImVec4(0.7f, 0.1f, 0.1f, 1.f); + } + + return true; + } + + return false; + } + + Application::Application(int argc, char * argv[]) + : m_window(nullptr, glfwDestroyWindow) // Add custom deleter to shared_ptr + , m_num_triangles(0) + , m_num_instances(0) + { + // Command line parsing + AppCliParser cli(argc, argv); + m_settings = cli.Parse(); + + if (!m_settings.cmd_line_mode) + { + // Initialize GLFW + try + { + int err = glfwInit(); + + if (err != GL_TRUE) + { + throw std::runtime_error("Error code: " + std::to_string(err)); + } + + } + catch (std::runtime_error&) + { + std::cerr << "GLFW initialization failed!\n"; + throw; + } + + // Setup window + glfwSetErrorCallback(OnError); + glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + #if __APPLE__ + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + #endif + + // GLUT Window Initialization: + m_window.reset(glfwCreateWindow(m_settings.width, m_settings.height, "Baikal standalone demo", nullptr, nullptr)); + glfwMakeContextCurrent(m_window.get()); + + #ifndef __APPLE__ + try + { + glewExperimental = GL_TRUE; + GLenum err = glewInit(); + + if (err != GLEW_OK) + { + throw std::runtime_error((const char*)glewGetErrorString(err)); + } + + } + catch (std::runtime_error&) + { + std::cerr << "GLEW initialization failed!\n"; + throw; + } + #endif + + ImGui_ImplGlfwGL3_Init(m_window.get(), true); + + // Set callbacks + glfwSetWindowUserPointer(m_window.get(), this); + glfwSetMouseButtonCallback(m_window.get(), Application::OnMouseButton); + glfwSetCursorPosCallback(m_window.get(), Application::OnMouseMove); + glfwSetKeyCallback(m_window.get(), Application::OnKey); + glfwSetScrollCallback(m_window.get(), Application::OnMouseScroll); + glfwSetWindowSizeCallback(m_window.get(), Application::OnWindowResize); + + // Initialize AppGlRender and AppClRender + try + { + m_gl.reset(new AppGlRender(m_settings)); + m_cl.reset(new AppClRender(m_settings, m_gl->GetTexture())); + } + catch (std::runtime_error&) + { + std::cerr << "Error when inializing AppGlRender or AppClRender!\n"; + throw; + } + + } + else + { + m_settings.interop = false; + m_cl.reset(new AppClRender(m_settings, -1)); + } + } + + void Application::Run() + { + CollectSceneStats(); + + if (!m_settings.cmd_line_mode) + { + try + { + m_cl->StartRenderThreads(); + static bool update = true; + while (!glfwWindowShouldClose(m_window.get())) + { + ImGui_ImplGlfwGL3_NewFrame(); + Update(update); + m_gl->Render(m_window.get()); + update = UpdateGui(); + glfwSwapBuffers(m_window.get()); + glfwPollEvents(); + } + + m_cl->StopRenderThreads(); + + } + catch (std::runtime_error&) + { + std::cout << "Caught exception in Application::Run()\n"; + throw; + } + + } + else + { + m_cl.reset(new AppClRender(m_settings, -1)); + + std::cout << "Number of triangles: " << m_num_triangles << "\n"; + std::cout << "Number of instances: " << m_num_instances << "\n"; + + //compile scene + m_cl->UpdateScene(); + m_cl->RunBenchmark(m_settings); + + auto minutes = (int)(m_settings.time_benchmark_time / 60.f); + auto seconds = (int)(m_settings.time_benchmark_time - minutes * 60); + + std::cout << "General benchmark results:\n"; + std::cout << "\tRendering time: " << minutes << "min:" << seconds << "s\n"; + std::string rating; + ImVec4 color; + if (GradeTimeBenchmarkResults(m_settings.modelname, minutes * 60 + seconds, rating, color)) + { + std::cout << "\tRating: " << rating.c_str() << "\n"; + } + else + { + std::cout << "\tRating: N/A\n"; + } + + std::cout << "RT benchmark results:\n"; + std::cout << "\tPrimary: " << m_settings.stats.primary_throughput * 1e-6f << " Mrays/s\n"; + std::cout << "\tSecondary: " << m_settings.stats.secondary_throughput * 1e-6f << " Mrays/s\n"; + std::cout << "\tShadow: " << m_settings.stats.shadow_throughput * 1e-6f << " Mrays/s\n"; + } + } + + + + bool Application::UpdateGui() + { + static const ImVec2 win_size(380, 580); + static float aperture = 0.0f; + static float focal_length = 35.f; + static float focus_distance = 1.f; + static int num_bounces = 5; + static const std::vector> kBaikalOutputs = + { + { Renderer::OutputType::kColor, "Color" }, + { Renderer::OutputType::kOpacity, "Opacity" }, + { Renderer::OutputType::kVisibility, "Visibility" }, + { Renderer::OutputType::kWorldPosition, "World Position" }, + { Renderer::OutputType::kWorldShadingNormal, "Shading Normal" }, + { Renderer::OutputType::kWorldGeometricNormal, "Geometric Normal" }, + { Renderer::OutputType::kUv, "Texture Coordinates" }, + { Renderer::OutputType::kWireframe, "Wireframe" }, + { Renderer::OutputType::kAlbedo, "Albedo" }, + { Renderer::OutputType::kWorldTangent, "Tangent" }, + { Renderer::OutputType::kWorldBitangent, "Bitangent" }, + { Renderer::OutputType::kGloss, "Glossiness" }, + { Renderer::OutputType::kMeshID, "Object ID" }, + { Renderer::OutputType::kGroupID, "Object Group ID" }, + { Renderer::OutputType::kBackground, "Background" }, + { Renderer::OutputType::kDepth, "Depth" } + }; + + static int output = 0; + bool update = false; + if (m_settings.gui_visible) + { + ImGui::SetNextWindowSizeConstraints(win_size, win_size); + ImGui::Begin("Baikal settings"); + ImGui::Text("Use wsad keys to move"); + ImGui::Text("Q/E to climb/descent"); + ImGui::Text("Mouse+RMB to look around"); + ImGui::Text("F1 to hide/show GUI"); + ImGui::Separator(); + + auto const& configs = m_cl->GetConfigs(); + for (auto const& cfg : configs) + { + ImGui::Text("Device vendor: %s", cfg.context.GetDevice(0).GetVendor().c_str()); + ImGui::Text("Device name: %s", cfg.context.GetDevice(0).GetName().c_str()); + ImGui::Text("OpenCL: %s", cfg.context.GetDevice(0).GetVersion().c_str()); + ImGui::Separator(); + } + + ImGui::Text("Resolution: %dx%d ", m_settings.width, m_settings.height); + ImGui::Text("Scene: %s", m_settings.modelname.c_str()); + ImGui::Text("Unique triangles: %d", m_num_triangles); + ImGui::Text("Number of instances: %d", m_num_instances); + ImGui::Separator(); + ImGui::SliderInt("GI bounces", &num_bounces, 1, 10); + + auto camera = m_cl->GetCamera(); + + if (m_settings.camera_type == CameraType::kPerspective) + { + auto perspective_camera = std::dynamic_pointer_cast(camera); + + if (!perspective_camera) + { + throw std::runtime_error("Application::UpdateGui(...): can not cast to perspective camera"); + } + + if (aperture != m_settings.camera_aperture * 1000.f) + { + m_settings.camera_aperture = aperture / 1000.f; + perspective_camera->SetAperture(m_settings.camera_aperture); + update = true; + } + + if (focus_distance != m_settings.camera_focus_distance) + { + m_settings.camera_focus_distance = focus_distance; + perspective_camera->SetFocusDistance(m_settings.camera_focus_distance); + update = true; + } + + if (focal_length != m_settings.camera_focal_length * 1000.f) + { + m_settings.camera_focal_length = focal_length / 1000.f; + perspective_camera->SetFocalLength(m_settings.camera_focal_length); + update = true; + } + + ImGui::SliderFloat("Aperture(mm)", &aperture, 0.0f, 100.0f); + ImGui::SliderFloat("Focal length(mm)", &focal_length, 5.f, 200.0f); + ImGui::SliderFloat("Focus distance(m)", &focus_distance, 0.05f, 20.f); + } + + if (num_bounces != m_settings.num_bounces) + { + m_settings.num_bounces = num_bounces; + m_cl->SetNumBounces(num_bounces); + update = true; + } + + auto gui_out_type = kBaikalOutputs[output].first; + + if (gui_out_type != m_cl->GetOutputType()) + { + m_cl->SetOutputType(gui_out_type); + update = true; + } + + RadeonRays::float3 eye, at; + eye = camera->GetPosition(); + at = eye + camera->GetForwardVector(); + + ImGui::Combo("Output", &output, + [](void* , int idx, const char** out_text) + { + if (out_text) + *out_text = kBaikalOutputs[idx].second; + return true; + }, + nullptr, (int)kBaikalOutputs.size() + ); + ImGui::Text(" "); + ImGui::Text("Number of samples: %d", m_settings.samplecount); + ImGui::Text("Frame time %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + ImGui::Text("Renderer performance %.3f Msamples/s", (ImGui::GetIO().Framerate *m_settings.width * m_settings.height) / 1000000.f); + ImGui::Text("Eye: x = %.3f y = %.3f z = %.3f", eye.x, eye.y, eye.z); + ImGui::Text("At: x = %.3f y = %.3f z = %.3f", at.x, at.y, at.z); + ImGui::Separator(); + + if (m_settings.time_benchmark) + { + ImGui::ProgressBar(m_settings.samplecount / 512.f); + } + + static decltype(std::chrono::high_resolution_clock::now()) time_bench_start_time; + if (!m_settings.time_benchmark && !m_settings.benchmark) + { + if (ImGui::Button("Start benchmark") && m_settings.num_samples == -1) + { + time_bench_start_time = std::chrono::high_resolution_clock::now(); + m_settings.time_benchmark = true; + update = true; + } + + if (!m_settings.time_benchmark && ImGui::Button("Start RT benchmark")) + { + m_settings.benchmark = true; + } + } + + if (m_settings.time_benchmark && m_settings.samplecount > 511) + { + m_settings.time_benchmark = false; + auto delta = std::chrono::duration_cast + (std::chrono::high_resolution_clock::now() - time_bench_start_time).count(); + m_settings.time_benchmark_time = delta / 1000.f; + m_settings.time_benchmarked = true; + } + + if (m_settings.time_benchmarked) + { + auto minutes = (int)(m_settings.time_benchmark_time / 60.f); + auto seconds = (int)(m_settings.time_benchmark_time - minutes * 60); + ImGui::Separator(); + + ImVec4 color; + std::string rating; + ImGui::Text("Rendering time: %2dmin:%ds", minutes, seconds); + if (GradeTimeBenchmarkResults(m_settings.modelname, minutes * 60 + seconds, rating, color)) + { + ImGui::TextColored(color, "Rating: %s", rating.c_str()); + } + else + { + ImGui::Text("Rating: N/A"); + } + } + + if (m_settings.rt_benchmarked) + { + auto& stats = m_settings.stats; + + ImGui::Separator(); + ImGui::Text("Primary rays: %f Mrays/s", stats.primary_throughput * 1e-6f); + ImGui::Text("Secondary rays: %f Mrays/s", stats.secondary_throughput * 1e-6f); + ImGui::Text("Shadow rays: %f Mrays/s", stats.shadow_throughput * 1e-6f); + } + +#ifdef ENABLE_DENOISER + ImGui::Separator(); + + static float sigmaPosition = m_cl->GetDenoiserFloatParam("position_sensitivity").x; + static float sigmaNormal = m_cl->GetDenoiserFloatParam("normal_sensitivity").x; + static float sigmaColor = m_cl->GetDenoiserFloatParam("color_sensitivity").x; + + ImGui::Text("Denoiser settings"); + ImGui::SliderFloat("Position sigma", &sigmaPosition, 0.f, 0.3f); + ImGui::SliderFloat("Normal sigma", &sigmaNormal, 0.f, 5.f); + ImGui::SliderFloat("Color sigma", &sigmaColor, 0.f, 5.f); + + if (m_cl->GetDenoiserFloatParam("position_sensitivity").x != sigmaPosition || + m_cl->GetDenoiserFloatParam("normal_sensitivity").x != sigmaNormal || + m_cl->GetDenoiserFloatParam("color_sensitivity").x != sigmaColor) + { + m_cl->SetDenoiserFloatParam("position_sensitivity", sigmaPosition); + m_cl->SetDenoiserFloatParam("normal_sensitivity", sigmaNormal); + m_cl->SetDenoiserFloatParam("color_sensitivity", sigmaColor); + } +#endif + ImGui::End(); + + // Get shape/material info from renderer + if (m_shape_id_future.valid()) + { + m_current_shape_id = m_shape_id_future.get(); + auto shape = m_cl->GetShapeById(m_current_shape_id); + + if (shape) + { + // set basic material settings + m_material_id = m_current_shape_id; + + // can be nullptr + auto material = + std::dynamic_pointer_cast( + shape->GetMaterial()); + + if (!material) + { + throw std::runtime_error( + "Application::UpdateGui(...): dynamic cast failure"); + } + + m_material_explorer = MaterialExplorer::Create(material); + m_object_name = shape->GetName(); + } + } + + // Process double click event if it occured + if (g_is_double_click) + { + m_shape_id_future = m_cl->GetShapeId((std::uint32_t)g_mouse_pos.x, (std::uint32_t)g_mouse_pos.y); + g_is_double_click = false; + } + + + // draw material + if (m_material_explorer) + { + ImVec2 explorer_win_size(win_size.x, win_size.y); + bool status = m_material_explorer->DrawExplorer(explorer_win_size); + update = update ? true : status; + } + } + + ImGui::Render(); + + return update; + } + + void Application::CollectSceneStats() + { + // Collect some scene statistics + m_num_triangles = 0U; + m_num_instances = 0U; + { + auto scene = m_cl->GetScene(); + auto shape_iter = scene->CreateShapeIterator(); + + for (; shape_iter->IsValid(); shape_iter->Next()) + { + auto shape = shape_iter->ItemAs(); + auto mesh = std::dynamic_pointer_cast(shape); + + if (mesh) + { + m_num_triangles += (int)(mesh->GetNumIndices() / 3); + } + else + { + ++m_num_instances; + } + } + } + } + +} diff --git a/BaikalStandalone/Application/application.h b/BaikalStandalone/Application/application.h new file mode 100644 index 00000000..85457d7d --- /dev/null +++ b/BaikalStandalone/Application/application.h @@ -0,0 +1,102 @@ + +/********************************************************************** + Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ +#pragma once + +#include "Application/app_utils.h" +#include "Application/cl_render.h" +#include "Application/gl_render.h" +#include "Application/material_explorer.h" +#include "image_io.h" + +#include +#include +#include + +namespace Baikal +{ + + class Application + { + public: + Application(int argc, char * argv[]); + void Run(); + private: + void Update(bool update_required); + + // Update app state according to gui + // Return: true if scene update required + bool UpdateGui(); + void CollectSceneStats(); + + void SaveToFile(std::chrono::high_resolution_clock::time_point time) const; + + // Input callbacks + // Note: use glfwGetWindowUserPointer(window) to get app instance + static void OnKey(GLFWwindow* window, int key, int scancode, int action, int mods); + static void OnMouseMove(GLFWwindow* window, double x, double y); + static void OnMouseButton(GLFWwindow* window, int button, int action, int mods); + static void OnMouseScroll(GLFWwindow* window, double x, double y); + static void OnWindowResize(GLFWwindow* window, int /* width */, int /* height */); + + AppSettings m_settings; + + // Note: the following three members should be declared in strict order + std::unique_ptr m_window; + std::unique_ptr m_gl; + std::unique_ptr m_cl; + + // Scene stats stuff + int m_num_triangles; + int m_num_instances; + + int m_current_shape_id; + std::string m_object_name; + std::future m_shape_id_future; + + class InputSettings + { + public: + bool HasMultiplier() const; + float GetMultiplier() const; + void SetMultiplier(float multiplier); + + RadeonRays::float3 GetColor() const; + void SetColor(RadeonRays::float3 color); + + std::uint32_t GetInteger() const; + void SetInteger(std::uint32_t integer); + + std::string GetTexturePath() const; + void SetTexturePath(std::string texture_path); + + private: + std::pair m_multiplier; + std::pair m_color; + std::pair m_integer_input; + std::pair m_texture_path; + }; + + int m_material_id; + MaterialExplorer::Ptr m_material_explorer; + }; +} diff --git a/BaikalStandalone/Application/cl_render.cpp b/BaikalStandalone/Application/cl_render.cpp new file mode 100644 index 00000000..e5d325f0 --- /dev/null +++ b/BaikalStandalone/Application/cl_render.cpp @@ -0,0 +1,690 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "OpenImageIO/imageio.h" +#include "image_io.h" + +#include "Application/cl_render.h" +#include "Application/gl_render.h" + +#include "SceneGraph/scene1.h" +#include "SceneGraph/camera.h" +#include "SceneGraph/material.h" +#include "scene_io.h" +#include "material_io.h" +#include "SceneGraph/material.h" + +#include "Renderers/monte_carlo_renderer.h" +#include "Renderers/adaptive_renderer.h" + +#include +#include +#include +#include + +#include "Application/scene_load_utils.h" + +#ifdef ENABLE_DENOISER +#include "PostEffects/wavelet_denoiser.h" +#endif +#include "Utils/clw_class.h" + +namespace Baikal +{ + AppClRender::AppClRender(AppSettings& settings, GLuint tex) : m_tex(tex), m_output_type(Renderer::OutputType::kColor) + { + InitCl(settings, m_tex); + InitScene(settings); + } + + void AppClRender::InitCl(AppSettings& settings, GLuint tex) + { + // Create cl context + ConfigManager::CreateConfigs( + settings.mode, + settings.interop, + m_cfgs, + settings.num_bounces, + settings.platform_index, + settings.device_index); + + m_width = (std::uint32_t)settings.width; + m_height = (std::uint32_t)settings.height; + + std::cout << "Running on devices: \n"; + + for (std::size_t i = 0; i < m_cfgs.size(); ++i) + { + const auto& device = m_cfgs[i].context.GetDevice(0); + std::cout << i << ". name: " << device.GetName() + << ", vendor: " << device.GetVendor() + << ", version: " << device.GetVersion() + << "\n"; + } + + settings.interop = false; + + m_outputs.resize(m_cfgs.size()); + m_ctrl.reset(new ControlData[m_cfgs.size()]); + + for (std::size_t i = 0; i < m_cfgs.size(); ++i) + { + if (m_cfgs[i].type == ConfigManager::kPrimary) + { + m_primary = static_cast(i); + + if (m_cfgs[i].caninterop) + { + m_cl_interop_image = m_cfgs[i].context.CreateImage2DFromGLTexture(tex); + settings.interop = true; + } + } + + m_ctrl[i].clear.store(1); + m_ctrl[i].stop.store(0); + m_ctrl[i].newdata.store(0); + m_ctrl[i].idx = static_cast(i); + m_ctrl[i].scene_state = 0; + } + + if (settings.interop) + { + std::cout << "OpenGL interop mode enabled\n"; + } + else + { + std::cout << "OpenGL interop mode disabled\n"; + } + + //create renderer + for (std::size_t i = 0; i < m_cfgs.size(); ++i) + { + m_outputs[i].output = m_cfgs[i].factory->CreateOutput(m_width, m_height); + m_outputs[i].dummy_output = m_cfgs[i].factory->CreateOutput(m_width, m_height); + +#ifdef ENABLE_DENOISER + if (m_cfgs[i].type == ConfigManager::kPrimary) + { + CreateDenoiserOutputs(i, settings.width, settings.height); + SetDenoiserOutputs(i); + m_outputs[i].denoiser = m_cfgs[i].factory->CreatePostEffect(Baikal::RenderFactory::PostEffectType::kWaveletDenoiser); + } +#endif + m_cfgs[i].renderer->SetOutput(Baikal::Renderer::OutputType::kColor, m_outputs[i].output.get()); + + m_outputs[i].fdata.resize(settings.width * settings.height); + m_outputs[i].udata.resize(settings.width * settings.height * 4); + + if (m_cfgs[i].type == ConfigManager::kPrimary) + { + m_outputs[i].copybuffer = m_cfgs[i].context.CreateBuffer(m_width * m_height, CL_MEM_READ_WRITE); + } + } + + m_shape_id_data.output = m_cfgs[m_primary].factory->CreateOutput(m_width, m_height); + m_cfgs[m_primary].renderer->Clear(RadeonRays::float3(0, 0, 0), *m_outputs[m_primary].output); + m_cfgs[m_primary].renderer->Clear(RadeonRays::float3(0, 0, 0), *m_shape_id_data.output); + } + + + void AppClRender::InitScene(AppSettings& settings) + { + rand_init(); + + m_scene = LoadScene(settings); + + switch (settings.camera_type) + { + case CameraType::kPerspective: + m_camera = Baikal::PerspectiveCamera::Create( + settings.camera_pos + , settings.camera_at + , settings.camera_up); + + break; + case CameraType::kOrthographic: + m_camera = Baikal::OrthographicCamera::Create( + settings.camera_pos + , settings.camera_at + , settings.camera_up); + break; + default: + throw std::runtime_error("AppClRender::InitCl(...): unsupported camera type"); + } + + m_scene->SetCamera(m_camera); + + // Adjust sensor size based on current aspect ratio + float aspect = (float)settings.width / settings.height; + settings.camera_sensor_size.y = settings.camera_sensor_size.x / aspect; + + m_camera->SetSensorSize(settings.camera_sensor_size); + m_camera->SetDepthRange(settings.camera_zcap); + + auto perspective_camera = std::dynamic_pointer_cast(m_camera); + + // if camera mode is kPerspective + if (perspective_camera) + { + perspective_camera->SetFocalLength(settings.camera_focal_length); + perspective_camera->SetFocusDistance(settings.camera_focus_distance); + perspective_camera->SetAperture(settings.camera_aperture); + std::cout << "Camera type: " << (perspective_camera->GetAperture() > 0.f ? "Physical" : "Pinhole") << "\n"; + std::cout << "Lens focal length: " << perspective_camera->GetFocalLength() * 1000.f << "mm\n"; + std::cout << "Lens focus distance: " << perspective_camera->GetFocusDistance() << "m\n"; + std::cout << "F-Stop: " << 1.f / (perspective_camera->GetAperture() * 10.f) << "\n"; + } + + std::cout << "Sensor size: " << settings.camera_sensor_size.x * 1000.f << "x" << settings.camera_sensor_size.y * 1000.f << "mm\n"; + } + + void AppClRender::UpdateScene() + { + for (std::size_t i = 0; i < m_cfgs.size(); ++i) + { + if (i == static_cast(m_primary)) + { + m_cfgs[i].renderer->Clear(float3(0, 0, 0), *m_outputs[i].output); + m_cfgs[i].controller->CompileScene(m_scene); + ++m_ctrl[i].scene_state; + +#ifdef ENABLE_DENOISER + ClearDenoiserOutputs(i); +#endif + + } + else + m_ctrl[i].clear.store(true); + } + } + + void AppClRender::Update(AppSettings& settings) + { + ++settings.samplecount; + + for (std::size_t i = 0; i < m_cfgs.size(); ++i) + { + if (m_cfgs[i].type == ConfigManager::kPrimary) + continue; + + int desired = 1; + if (std::atomic_compare_exchange_strong(&m_ctrl[i].newdata, &desired, 0)) + { + if (m_ctrl[i].scene_state != m_ctrl[m_primary].scene_state) + { + // Skip update if worker has sent us non-actual data + continue; + } + + { + m_cfgs[m_primary].context.WriteBuffer(0, m_outputs[m_primary].copybuffer, &m_outputs[i].fdata[0], settings.width * settings.height); + } + + auto acckernel = static_cast(m_cfgs[m_primary].renderer.get())->GetAccumulateKernel(); + + int argc = 0; + acckernel.SetArg(argc++, m_outputs[m_primary].copybuffer); + acckernel.SetArg(argc++, settings.width * settings.width); + acckernel.SetArg(argc++, static_cast(m_outputs[m_primary].output.get())->data()); + + int globalsize = settings.width * settings.height; + m_cfgs[m_primary].context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, acckernel); + settings.samplecount += m_ctrl[i].new_samples_count; + } + } + + if (!settings.interop) + { +#ifdef ENABLE_DENOISER + m_outputs[m_primary].output_denoised->GetData(&m_outputs[m_primary].fdata[0]); +#else + m_outputs[m_primary].output->GetData(&m_outputs[m_primary].fdata[0]); +#endif + + float gamma = 2.2f; + for (int i = 0; i < (int)m_outputs[m_primary].fdata.size(); ++i) + { + m_outputs[m_primary].udata[4 * i] = (unsigned char)clamp(clamp(pow(m_outputs[m_primary].fdata[i].x / m_outputs[m_primary].fdata[i].w, 1.f / gamma), 0.f, 1.f) * 255, 0, 255); + m_outputs[m_primary].udata[4 * i + 1] = (unsigned char)clamp(clamp(pow(m_outputs[m_primary].fdata[i].y / m_outputs[m_primary].fdata[i].w, 1.f / gamma), 0.f, 1.f) * 255, 0, 255); + m_outputs[m_primary].udata[4 * i + 2] = (unsigned char)clamp(clamp(pow(m_outputs[m_primary].fdata[i].z / m_outputs[m_primary].fdata[i].w, 1.f / gamma), 0.f, 1.f) * 255, 0, 255); + m_outputs[m_primary].udata[4 * i + 3] = 1; + } + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_tex); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_outputs[m_primary].output->width(), m_outputs[m_primary].output->height(), GL_RGBA, GL_UNSIGNED_BYTE, &m_outputs[m_primary].udata[0]); + glBindTexture(GL_TEXTURE_2D, 0); + } + else + { + std::vector objects; + objects.push_back(m_cl_interop_image); + m_cfgs[m_primary].context.AcquireGLObjects(0, objects); + + auto copykernel = static_cast(m_cfgs[m_primary].renderer.get())->GetCopyKernel(); + +#ifdef ENABLE_DENOISER + auto output = m_outputs[m_primary].output_denoised.get(); +#else + auto output = m_outputs[m_primary].output.get(); +#endif + + int argc = 0; + + copykernel.SetArg(argc++, static_cast(output)->data()); + copykernel.SetArg(argc++, output->width()); + copykernel.SetArg(argc++, output->height()); + copykernel.SetArg(argc++, 2.2f); + copykernel.SetArg(argc++, m_cl_interop_image); + + int globalsize = output->width() * output->height(); + m_cfgs[m_primary].context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, copykernel); + + m_cfgs[m_primary].context.ReleaseGLObjects(0, objects); + m_cfgs[m_primary].context.Finish(0); + } + + + if (settings.benchmark) + { + auto& scene = m_cfgs[m_primary].controller->CompileScene(m_scene); + static_cast(m_cfgs[m_primary].renderer.get())->Benchmark(scene, settings.stats); + + settings.benchmark = false; + settings.rt_benchmarked = true; + } + + } + + void AppClRender::Render(int sample_cnt) + { +#ifdef ENABLE_DENOISER + WaveletDenoiser* wavelet_denoiser = dynamic_cast(m_outputs[m_primary].denoiser.get()); + + if (wavelet_denoiser != nullptr) + { + wavelet_denoiser->Update(static_cast(m_camera.get())); + } +#endif + + auto& scene = m_cfgs[m_primary].controller->GetCachedScene(m_scene); + m_cfgs[m_primary].renderer->Render(scene); + + if (m_shape_id_requested) + { + // offset in OpenCl memory till necessary item + auto offset = (std::uint32_t)(m_width * (m_height - m_shape_id_pos.y) + m_shape_id_pos.x); + // copy shape id elem from OpenCl + float4 shape_id; + m_shape_id_data.output->GetData((float3*)&shape_id, offset, 1); + m_promise.set_value(static_cast(shape_id.x)); + // clear output to stop tracking shape id map in openCl + m_cfgs[m_primary].renderer->SetOutput(Renderer::OutputType::kShapeId, nullptr); + m_shape_id_requested = false; + } + +#ifdef ENABLE_DENOISER + Baikal::PostEffect::InputSet input_set; + input_set[Baikal::Renderer::OutputType::kColor] = m_outputs[m_primary].output.get(); + input_set[Baikal::Renderer::OutputType::kWorldShadingNormal] = m_outputs[m_primary].output_normal.get(); + input_set[Baikal::Renderer::OutputType::kWorldPosition] = m_outputs[m_primary].output_position.get(); + input_set[Baikal::Renderer::OutputType::kAlbedo] = m_outputs[m_primary].output_albedo.get(); + input_set[Baikal::Renderer::OutputType::kMeshID] = m_outputs[m_primary].output_mesh_id.get(); + + auto radius = 10U - RadeonRays::clamp((sample_cnt / 16), 1U, 9U); + auto position_sensitivity = 5.f + 10.f * (radius / 10.f); + + const bool is_bilateral_denoiser = dynamic_cast(m_outputs[m_primary].denoiser.get()) != nullptr; + + if (is_bilateral_denoiser) + { + + auto normal_sensitivity = 0.1f + (radius / 10.f) * 0.15f; + auto color_sensitivity = (radius / 10.f) * 2.f; + auto albedo_sensitivity = 0.5f + (radius / 10.f) * 0.5f; + m_outputs[m_primary].denoiser->SetParameter("radius", static_cast(radius)); + m_outputs[m_primary].denoiser->SetParameter("color_sensitivity", color_sensitivity); + m_outputs[m_primary].denoiser->SetParameter("normal_sensitivity", normal_sensitivity); + m_outputs[m_primary].denoiser->SetParameter("position_sensitivity", position_sensitivity); + m_outputs[m_primary].denoiser->SetParameter("albedo_sensitivity", albedo_sensitivity); + } + + m_outputs[m_primary].denoiser->Apply(input_set, *m_outputs[m_primary].output_denoised); +#endif + } + + void AppClRender::SaveFrameBuffer(AppSettings& settings) + { + std::vector data; + + //read cl output in case of iterop + std::vector output_data; + if (settings.interop) + { + auto output = m_outputs[m_primary].output.get(); + auto buffer = static_cast(output)->data(); + output_data.resize(buffer.GetElementCount()); + m_cfgs[m_primary].context.ReadBuffer(0, static_cast(output)->data(), &output_data[0], output_data.size()).Wait(); + } + + //use already copied to CPU cl data in case of no interop + auto& fdata = settings.interop ? output_data : m_outputs[m_primary].fdata; + + data.resize(fdata.size()); + std::transform(fdata.cbegin(), fdata.cend(), data.begin(), + [](RadeonRays::float3 const& v) + { + float invw = 1.f / v.w; + return v * invw; + }); + + std::stringstream oss; + auto camera_position = m_camera->GetPosition(); + auto camera_direction = m_camera->GetForwardVector(); + oss << "../Output/" << settings.modelname << "_p" << camera_position.x << camera_position.y << camera_position.z << + "_d" << camera_direction.x << camera_direction.y << camera_direction.z << + "_s" << settings.num_samples << ".exr"; + + SaveImage(oss.str(), settings.width, settings.height, data.data()); + } + + void AppClRender::SaveImage(const std::string& name, int width, int height, const RadeonRays::float3* data) + { + OIIO_NAMESPACE_USING; + + std::vector tempbuf(width * height); + tempbuf.assign(data, data + width * height); + + for (auto y = 0; y < height; ++y) + for (auto x = 0; x < width; ++x) + { + + float3 val = data[(height - 1 - y) * width + x]; + tempbuf[y * width + x] = (1.f / val.w) * val; + + tempbuf[y * width + x].x = std::pow(tempbuf[y * width + x].x, 1.f / 2.2f); + tempbuf[y * width + x].y = std::pow(tempbuf[y * width + x].y, 1.f / 2.2f); + tempbuf[y * width + x].z = std::pow(tempbuf[y * width + x].z, 1.f / 2.2f); + } + + ImageOutput* out = ImageOutput::create(name); + + if (!out) + { + throw std::runtime_error("Can't create image file on disk"); + } + + ImageSpec spec(width, height, 3, TypeDesc::FLOAT); + + out->open(name, spec); + out->write_image(TypeDesc::FLOAT, &tempbuf[0], sizeof(float3)); + out->close(); + } + + void AppClRender::RenderThread(ControlData& cd) + { + auto renderer = m_cfgs[cd.idx].renderer.get(); + auto controller = m_cfgs[cd.idx].controller.get(); + auto output = m_outputs[cd.idx].output.get(); + + auto updatetime = std::chrono::high_resolution_clock::now(); + + std::uint32_t scene_state = 0; + std::uint32_t new_samples_count = 0; + + while (!cd.stop.load()) + { + int result = 1; + bool update = false; + if (std::atomic_compare_exchange_strong(&cd.clear, &result, 0)) + { + renderer->Clear(float3(0, 0, 0), *output); + controller->CompileScene(m_scene); + scene_state = m_ctrl[m_primary].scene_state; + update = true; + } + + auto& scene = controller->GetCachedScene(m_scene); + renderer->Render(scene); + ++new_samples_count; + + auto now = std::chrono::high_resolution_clock::now(); + + update = update || (std::chrono::duration_cast(now - updatetime).count() > 1); + + if (update) + { + m_outputs[cd.idx].output->GetData(&m_outputs[cd.idx].fdata[0]); + updatetime = now; + m_ctrl[cd.idx].scene_state = scene_state; + m_ctrl[cd.idx].new_samples_count = new_samples_count; + new_samples_count = 0; + cd.newdata.store(1); + } + + m_cfgs[cd.idx].context.Finish(0); + } + } + + void AppClRender::StartRenderThreads() + { + for (std::size_t i = 0; i < m_cfgs.size(); ++i) + { + if (i != static_cast(m_primary)) + { + m_renderthreads.push_back(std::thread(&AppClRender::RenderThread, this, std::ref(m_ctrl[i]))); + } + } + + std::cout << m_cfgs.size() << " OpenCL submission threads started\n"; + } + + void AppClRender::StopRenderThreads() + { + for (std::size_t i = 0; i < m_cfgs.size(); ++i) + { + if (i == static_cast(m_primary)) + { + continue; + } + + m_ctrl[i].stop.store(true); + } + + for (std::size_t i = 0; i < m_renderthreads.size(); ++i) + { + m_renderthreads[i].join(); + } + + } + + void AppClRender::RunBenchmark(AppSettings& settings) + { + std::cout << "Running general benchmark...\n"; + + auto time_bench_start_time = std::chrono::high_resolution_clock::now(); + for (auto i = 0U; i < 512; ++i) + { + Render(0); + } + + m_cfgs[m_primary].context.Finish(0); + + auto delta = std::chrono::duration_cast + (std::chrono::high_resolution_clock::now() - time_bench_start_time).count(); + + settings.time_benchmark_time = delta / 1000.f; + + m_outputs[m_primary].output->GetData(&m_outputs[m_primary].fdata[0]); + float gamma = 2.2f; + for (int i = 0; i < (int)m_outputs[m_primary].fdata.size(); ++i) + { + m_outputs[m_primary].udata[4 * i] = (unsigned char)clamp(clamp(pow(m_outputs[m_primary].fdata[i].x / m_outputs[m_primary].fdata[i].w, 1.f / gamma), 0.f, 1.f) * 255, 0, 255); + m_outputs[m_primary].udata[4 * i + 1] = (unsigned char)clamp(clamp(pow(m_outputs[m_primary].fdata[i].y / m_outputs[m_primary].fdata[i].w, 1.f / gamma), 0.f, 1.f) * 255, 0, 255); + m_outputs[m_primary].udata[4 * i + 2] = (unsigned char)clamp(clamp(pow(m_outputs[m_primary].fdata[i].z / m_outputs[m_primary].fdata[i].w, 1.f / gamma), 0.f, 1.f) * 255, 0, 255); + m_outputs[m_primary].udata[4 * i + 3] = 1; + } + + auto& fdata = m_outputs[m_primary].fdata; + std::vector data(fdata.size()); + std::transform(fdata.cbegin(), fdata.cend(), data.begin(), + [](RadeonRays::float3 const& v) + { + float invw = 1.f / v.w; + return v * invw; + }); + + std::stringstream oss; + oss << "../Output/" << settings.modelname << ".exr"; + + SaveImage(oss.str(), settings.width, settings.height, &data[0]); + + std::cout << "Running RT benchmark...\n"; + + auto& scene = m_cfgs[m_primary].controller->GetCachedScene(m_scene); + static_cast(m_cfgs[m_primary].renderer.get())->Benchmark(scene, settings.stats); + } + + void AppClRender::SetNumBounces(int num_bounces) + { + for (std::size_t i = 0; i < m_cfgs.size(); ++i) + { + static_cast(m_cfgs[i].renderer.get())->SetMaxBounces(num_bounces); + } + } + + void AppClRender::SetOutputType(Renderer::OutputType type) + { + for (std::size_t i = 0; i < m_cfgs.size(); ++i) + { +#ifdef ENABLE_DENOISER + RestoreDenoiserOutput(i, m_output_type); +#else + m_cfgs[i].renderer->SetOutput(m_output_type, nullptr); +#endif + if (type == Renderer::OutputType::kOpacity || type == Renderer::OutputType::kVisibility) + { + m_cfgs[i].renderer->SetOutput(Renderer::OutputType::kColor, m_outputs[i].dummy_output.get()); + } + else + { + m_cfgs[i].renderer->SetOutput(Renderer::OutputType::kColor, nullptr); + } + m_cfgs[i].renderer->SetOutput(type, m_outputs[i].output.get()); + } + m_output_type = type; + } + + + std::future AppClRender::GetShapeId(std::uint32_t x, std::uint32_t y) + { + m_promise = std::promise(); + if (x >= m_width || y >= m_height) + throw std::logic_error( + "AppClRender::GetShapeId(...): x or y cords beyond the size of image"); + + if (m_cfgs.empty()) + throw std::runtime_error("AppClRender::GetShapeId(...): config vector is empty"); + + // enable aov shape id output from OpenCl + m_cfgs[m_primary].renderer->SetOutput( + Renderer::OutputType::kShapeId, m_shape_id_data.output.get()); + m_shape_id_pos = RadeonRays::float2((float)x, (float)y); + // request shape id from render + m_shape_id_requested = true; + return m_promise.get_future(); + } + + Baikal::Shape::Ptr AppClRender::GetShapeById(int shape_id) + { + if (shape_id < 0) + return nullptr; + + // find shape in scene by its id + for (auto iter = m_scene->CreateShapeIterator(); iter->IsValid(); iter->Next()) + { + auto shape = iter->ItemAs(); + if (shape->GetId() == static_cast(shape_id)) + return shape; + } + return nullptr; + } + +#ifdef ENABLE_DENOISER + void AppClRender::SetDenoiserFloatParam(const std::string& name, const float4& value) + { + m_outputs[m_primary].denoiser->SetParameter(name, value); + } + + float4 AppClRender::GetDenoiserFloatParam(const std::string& name) + { + return m_outputs[m_primary].denoiser->GetParameter(name); + } + + void AppClRender::CreateDenoiserOutputs(std::size_t cfg_index, int width, int height) + { + m_outputs[cfg_index].output_denoised = m_cfgs[cfg_index].factory->CreateOutput(width, height); + m_outputs[cfg_index].output_normal = m_cfgs[cfg_index].factory->CreateOutput(width, height); + m_outputs[cfg_index].output_position = m_cfgs[cfg_index].factory->CreateOutput(width, height); + m_outputs[cfg_index].output_albedo = m_cfgs[cfg_index].factory->CreateOutput(width, height); + m_outputs[cfg_index].output_mesh_id = m_cfgs[cfg_index].factory->CreateOutput(width, height); + } + + void AppClRender::SetDenoiserOutputs(std::size_t cfg_index) const + { + m_cfgs[cfg_index].renderer->SetOutput(Renderer::OutputType::kWorldShadingNormal, m_outputs[cfg_index].output_normal.get()); + m_cfgs[cfg_index].renderer->SetOutput(Renderer::OutputType::kWorldPosition, m_outputs[cfg_index].output_position.get()); + m_cfgs[cfg_index].renderer->SetOutput(Renderer::OutputType::kAlbedo, m_outputs[cfg_index].output_albedo.get()); + m_cfgs[cfg_index].renderer->SetOutput(Renderer::OutputType::kMeshID, m_outputs[cfg_index].output_mesh_id.get()); + } + + void AppClRender::ClearDenoiserOutputs(std::size_t cfg_index) const + { + m_cfgs[cfg_index].renderer->Clear(float3(0, 0, 0), *m_outputs[cfg_index].output_normal); + m_cfgs[cfg_index].renderer->Clear(float3(0, 0, 0), *m_outputs[cfg_index].output_position); + m_cfgs[cfg_index].renderer->Clear(float3(0, 0, 0), *m_outputs[cfg_index].output_albedo); + m_cfgs[cfg_index].renderer->Clear(float3(0, 0, 0), *m_outputs[cfg_index].output_mesh_id); + } + + void AppClRender::RestoreDenoiserOutput(std::size_t cfg_index, Renderer::OutputType type) const + { + switch (type) + { + case Renderer::OutputType::kWorldShadingNormal: + m_cfgs[cfg_index].renderer->SetOutput(type, m_outputs[cfg_index].output_normal.get()); + break; + case Renderer::OutputType::kWorldPosition: + m_cfgs[cfg_index].renderer->SetOutput(type, m_outputs[cfg_index].output_position.get()); + break; + case Renderer::OutputType::kAlbedo: + m_cfgs[cfg_index].renderer->SetOutput(type, m_outputs[cfg_index].output_albedo.get()); + break; + case Renderer::OutputType::kMeshID: + m_cfgs[cfg_index].renderer->SetOutput(type, m_outputs[cfg_index].output_mesh_id.get()); + break; + default: + // Nothing to restore + m_cfgs[cfg_index].renderer->SetOutput(type, nullptr); + break; + } + } +#endif +} // Baikal diff --git a/BaikalStandalone/Application/cl_render.h b/BaikalStandalone/Application/cl_render.h new file mode 100644 index 00000000..7960b198 --- /dev/null +++ b/BaikalStandalone/Application/cl_render.h @@ -0,0 +1,140 @@ + +/********************************************************************** + Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ +#pragma once + +#include +#include +#include +#include + +#include "RenderFactory/render_factory.h" +#include "Renderers/monte_carlo_renderer.h" +#include "Output/clwoutput.h" +#include "Application/app_utils.h" +#include "Utils/config_manager.h" +#include "Application/gl_render.h" +#include "SceneGraph/camera.h" + +#ifdef ENABLE_DENOISER +#include "PostEffects/bilateral_denoiser.h" +#endif + + +namespace Baikal +{ + class AppClRender + { + struct OutputData + { + std::unique_ptr output; + std::unique_ptr dummy_output; + +#ifdef ENABLE_DENOISER + std::unique_ptr output_position; + std::unique_ptr output_normal; + std::unique_ptr output_albedo; + std::unique_ptr output_mesh_id; + std::unique_ptr output_denoised; + std::unique_ptr denoiser; +#endif + + std::vector fdata; + std::vector udata; + CLWBuffer copybuffer; + }; + + struct ControlData + { + std::atomic clear; + std::atomic stop; + std::atomic newdata; + int idx; + // This is used to reject non-actual data from a worker device + std::uint32_t scene_state; + // Number of samples in the new data that has sent from a worker device + std::uint32_t new_samples_count; + }; + + public: + AppClRender(AppSettings& settings, GLuint tex); + //copy data from to GL + void Update(AppSettings& settings); + + //compile scene + void UpdateScene(); + //render + void Render(int sample_cnt); + void StartRenderThreads(); + void StopRenderThreads(); + void RunBenchmark(AppSettings& settings); + + //save cl frame buffer to file + void SaveFrameBuffer(AppSettings& settings); + void SaveImage(const std::string& name, int width, int height, const RadeonRays::float3* data); + + inline Baikal::Camera::Ptr GetCamera() { return m_camera; }; + inline Baikal::Scene1::Ptr GetScene() { return m_scene; }; + inline const std::vector& GetConfigs() const { return m_cfgs; }; + inline Renderer::OutputType GetOutputType() { return m_output_type; }; + + void SetNumBounces(int num_bounces); + void SetOutputType(Renderer::OutputType type); + + std::future GetShapeId(std::uint32_t x, std::uint32_t y); + Baikal::Shape::Ptr GetShapeById(int shape_id); + +#ifdef ENABLE_DENOISER + // Denoiser + void SetDenoiserFloatParam(const std::string& name, const float4& value); + float4 GetDenoiserFloatParam(const std::string& name); + void CreateDenoiserOutputs(std::size_t cfg_index, int width, int height); + void SetDenoiserOutputs(std::size_t cfg_index) const; + void ClearDenoiserOutputs(std::size_t cfg_index) const; + void RestoreDenoiserOutput(std::size_t cfg_index, Renderer::OutputType type) const; +#endif + private: + void InitCl(AppSettings& settings, GLuint tex); + void InitScene(AppSettings& settings); + void RenderThread(ControlData& cd); + + Baikal::Scene1::Ptr m_scene; + Baikal::Camera::Ptr m_camera; + + std::promise m_promise; + bool m_shape_id_requested = false; + OutputData m_shape_id_data; + RadeonRays::float2 m_shape_id_pos; + std::vector m_cfgs; + std::vector m_outputs; + std::unique_ptr m_ctrl; + std::vector m_renderthreads; + int m_primary = -1; + std::uint32_t m_width, m_height; + + //if interop + CLWImage2D m_cl_interop_image; + //save GL tex for no interop case + GLuint m_tex; + Renderer::OutputType m_output_type; + }; +} diff --git a/BaikalStandalone/Application/gl_render.cpp b/BaikalStandalone/Application/gl_render.cpp new file mode 100644 index 00000000..dbf78e85 --- /dev/null +++ b/BaikalStandalone/Application/gl_render.cpp @@ -0,0 +1,134 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "Application/gl_render.h" +#include +#include + +#define CHECK_GL_ERROR assert(glGetError() == 0) + +namespace Baikal +{ + void AppGlRender::Render(GLFWwindow* window) + { + try + { + { + int w, h; + glfwGetFramebufferSize(window, &w, &h); CHECK_GL_ERROR; + glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR; + glViewport(0, 0, w, h); CHECK_GL_ERROR; + + + glClear(GL_COLOR_BUFFER_BIT); CHECK_GL_ERROR; + glBindVertexArray(m_vao); CHECK_GL_ERROR; + + GLuint program = m_shader_manager->GetProgram("../BaikalStandalone/Kernels/GLSL/simple"); + glUseProgram(program); CHECK_GL_ERROR; + + GLuint texloc = glGetUniformLocation(program, "g_Texture"); + assert(texloc >= 0); + + glUniform1i(texloc, 0); CHECK_GL_ERROR; + + glActiveTexture(GL_TEXTURE0); CHECK_GL_ERROR; + glBindTexture(GL_TEXTURE_2D, m_texture); CHECK_GL_ERROR; + + + glEnableVertexAttribArray(0); CHECK_GL_ERROR; + glEnableVertexAttribArray(1); CHECK_GL_ERROR; + + glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer); CHECK_GL_ERROR; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer); CHECK_GL_ERROR; + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0); CHECK_GL_ERROR; + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (void*)(sizeof(float) * 3)); CHECK_GL_ERROR; + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr); + + glDisableVertexAttribArray(0); CHECK_GL_ERROR; + glDisableVertexAttribArray(1); CHECK_GL_ERROR; + glBindTexture(GL_TEXTURE_2D, 0); CHECK_GL_ERROR; + glBindBuffer(GL_ARRAY_BUFFER, 0); CHECK_GL_ERROR; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); CHECK_GL_ERROR; + glUseProgram(0); CHECK_GL_ERROR; + glBindVertexArray(0); + + glFinish(); CHECK_GL_ERROR; + } + } + catch (std::runtime_error& e) + { + std::cout << e.what(); + exit(-1); + } + } + + AppGlRender::AppGlRender(const AppSettings& settings) + : m_window_width(settings.width) + , m_window_height(settings.height) + { + m_shader_manager.reset(new ShaderManager()); + + glGetError(); + glClearColor(0.0, 0.5, 0.0, 0.0); CHECK_GL_ERROR; + glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR; + + glGenBuffers(1, &m_vertex_buffer); CHECK_GL_ERROR; + glGenBuffers(1, &m_index_buffer); CHECK_GL_ERROR; + + glGenVertexArrays(1, &m_vao); CHECK_GL_ERROR; + + // create Vertex buffer + glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer); CHECK_GL_ERROR; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer); CHECK_GL_ERROR; + + float quad_vdata[] = + { + -1, -1, 0.5, 0, 0, + 1, -1, 0.5, 1, 0, + 1, 1, 0.5, 1, 1, + -1, 1, 0.5, 0, 1 + }; + + GLshort quad_idata[] = + { + 0, 1, 3, + 3, 1, 2 + }; + + // fill data + glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vdata), quad_vdata, GL_STATIC_DRAW); CHECK_GL_ERROR; + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quad_idata), quad_idata, GL_STATIC_DRAW); CHECK_GL_ERROR; + + glBindBuffer(GL_ARRAY_BUFFER, 0); CHECK_GL_ERROR; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); CHECK_GL_ERROR; + + + glGenTextures(1, &m_texture); CHECK_GL_ERROR; + glBindTexture(GL_TEXTURE_2D, m_texture); CHECK_GL_ERROR; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); CHECK_GL_ERROR; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); CHECK_GL_ERROR; + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_window_width, m_window_height, 0, GL_RGBA, GL_FLOAT, nullptr); CHECK_GL_ERROR; + + glBindTexture(GL_TEXTURE_2D, 0); CHECK_GL_ERROR; + } +} diff --git a/BaikalStandalone/Application/gl_render.h b/BaikalStandalone/Application/gl_render.h new file mode 100644 index 00000000..10e5e6d9 --- /dev/null +++ b/BaikalStandalone/Application/gl_render.h @@ -0,0 +1,65 @@ + +/********************************************************************** + Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ +#pragma once + +#include + +#ifdef __APPLE__ +#include +#define GLFW_INCLUDE_GLCOREARB +#define GLFW_NO_GLU +#include "GLFW/glfw3.h" +#elif WIN32 +#define NOMINMAX +#include +#include "GL/glew.h" +#include "GLFW/glfw3.h" +#else +#include +#include +#include +#include "GLFW/glfw3.h" +#endif + +#include "Utils/shader_manager.h" +#include "Application/app_utils.h" + +namespace Baikal +{ + class AppGlRender + { + public: + AppGlRender(const AppSettings& settings); + void Render(GLFWwindow* window); + + GLuint GetTexture() { return m_texture; }; + private: + std::unique_ptr m_shader_manager; + GLuint m_vertex_buffer; + GLuint m_index_buffer; + GLuint m_texture; + GLuint m_vao; + int m_window_width; + int m_window_height; + }; +} diff --git a/BaikalStandalone/Application/graph_scheme.cpp b/BaikalStandalone/Application/graph_scheme.cpp new file mode 100644 index 00000000..0b9748aa --- /dev/null +++ b/BaikalStandalone/Application/graph_scheme.cpp @@ -0,0 +1,288 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "graph_scheme.h" + +//////////////////////////////////////////////// +//// GraphScheme implemenataion +//////////////////////////////////////////////// + +using namespace Baikal; + +namespace { + struct GraphSchemeConcrete : public GraphScheme + { + GraphSchemeConcrete(UberTree::Ptr tree, RadeonRays::int2 root_pos, RadeonRays::int2 node_size) + : GraphScheme(tree, root_pos, node_size) + { } + }; +} + +GraphScheme::GraphScheme(UberTree::Ptr tree, RadeonRays::int2 root_pos, RadeonRays::int2 node_size) +{ + if (!tree) + { + throw std::logic_error("GraphScheme::GraphScheme(...): 'tree' is nullptr"); + } + + m_trees.push_back(tree); + RecomputeCoordinates(root_pos, node_size); +} + +GraphScheme::Ptr GraphScheme::Create(UberTree::Ptr tree, RadeonRays::int2 root_pos, RadeonRays::int2 node_size) +{ + return std::make_shared(GraphSchemeConcrete( + tree, root_pos, node_size)); +} + +void GraphScheme::RecomputeCoordinates(RadeonRays::int2 root_pos, RadeonRays::int2 node_size) +{ + const int x_offset = 180; + const int y_offset = 120; + + // primary tree + auto iter = UberTreeIterator::Create(m_trees[0]); + + int level = 0; + int level_item_counter = 0; + while (iter->IsValid()) + { + level_item_counter = (iter->GetLevel() == level) ? + (level_item_counter + 1) : (0); + level = iter->GetLevel(); + + RadeonRays::int2 position( + root_pos.x + level * x_offset, + root_pos.y + level_item_counter * y_offset); + + m_nodes.push_back(Node(iter->Item(), position, node_size)); + + if (iter->Item()->GetParentId() >= 0) + { + m_links.push_back( + Link(iter->Item()->GetParentId(), + iter->Item()->GetId())); + } + + iter->Next(); + } +} + +void GraphScheme::RemoveLink(std::uint32_t src_id, std::uint32_t dst_id) +{ + for (auto link = m_links.begin(); link != m_links.end(); ++link) + { + if (link->src_id == src_id && + link->dst_id == dst_id) + { + m_links.erase(link); + return; + } + } +} + +void GraphScheme::AddTree(UberTree::Ptr tree) +{ + throw std::runtime_error("Not implemented"); +} + +void GraphScheme::MergeTrees(UberTree::Ptr tree_1, UberTree::Ptr tree_2) +{ + throw std::runtime_error("Not implemented"); +} + +void GraphScheme::RemoveNode(std::uint32_t id) +{ + UberTree::Ptr tree = nullptr; + UberNode::Ptr node = nullptr; + // find tree + for (auto item : m_trees) + { + // nullptr if 'id' wasn't found + node = item->Find(id); + if (node) + { + tree = item; + break; + } + } + // thre is no such id + if (!tree) + return; + + auto trees_vector = tree->ExcludeNode(id); + + RemoveLink(node->GetParentId(), id); + + std::remove_if(m_links.begin(), m_links.end(), + [id](const Link &link) + { + return link.src_id == id; + }); + + std::remove_if(m_nodes.begin(), m_nodes.end(), + [id](const Node &node) + { + return node.id == id; + }); + + m_trees.insert(m_trees.end(), trees_vector.begin(), trees_vector.end()); +} + +void GraphScheme::UpdateNodePos(std::uint32_t id, RadeonRays::int2 pos) +{ + for (auto& node : m_nodes) + { + if (node.id == id) + { + node.pos.x = pos.x; + node.pos.y = pos.y; + } + } +} + +void GraphScheme::UpdateNodeSize(std::uint32_t id, RadeonRays::int2 size) +{ + for (auto& node : m_nodes) + { + if (node.id == id) + { + node.size.x = size.x; + node.size.y = size.y; + } + } +} + +//////////////////////////////////////////////// +//// Node implemenataion +//////////////////////////////////////////////// + +GraphScheme::Node::Node( + UberNode::Ptr node_, + RadeonRays::int2 pos_, + RadeonRays::int2 size_) + // initialize list + : id(node_->GetId()), pos(pos_), size(size_), + name (node_->GetDataTypeText()), node(node_) +{ + switch (node->GetDataType()) + { + case InputMap::InputMapType::kConstantFloat: + type = NodeType::kFloat; + return; + case InputMap::InputMapType::kConstantFloat3: + type = NodeType::kFloat3; + return; + case InputMap::InputMapType::kSampler: + type = NodeType::kTexture; + return; + default: + type = NodeType::kIntermidiate; + } +} + +float GraphScheme::Node::GetFloat() const +{ + if (node->GetDataType() != InputMap::InputMapType::kConstantFloat) + { + return 0.f; + } + + auto float_node = std::dynamic_pointer_cast(node); + + if (!float_node) + { + throw std::runtime_error("Node::GetFloat(...): dynamic_pointer_cast failure"); + } + + return float_node->GetValue(); +} + +void GraphScheme::Node::SetFloat(float value) +{ + if (node->GetDataType() != InputMap::InputMapType::kConstantFloat) + { + return; + } + + auto float_node = std::dynamic_pointer_cast(node); + + if (!float_node) + { + throw std::runtime_error( + "Node::SetFloat(...): dynamic_pointer_cast failure"); + } + + float_node->SetValue(value); +} + +RadeonRays::float3 GraphScheme::Node::GetFloat3() const +{ + if (node->GetDataType() != InputMap::InputMapType::kConstantFloat3) + { + return RadeonRays::float3(0); + } + + auto float_node = std::dynamic_pointer_cast(node); + + if (!float_node) + { + throw std::runtime_error( + "Node::GetFloat3(...): dynamic_pointer_cast failure"); + } + + return float_node->GetValue(); +} + +void GraphScheme::Node::SetFloat3(RadeonRays::float3 value) +{ + if (node->GetDataType() != InputMap::InputMapType::kConstantFloat3) + { + return; + } + + auto float_node = std::dynamic_pointer_cast(node); + + if (!float_node) + { + throw std::runtime_error("Node::SetFloat3(...): dynamic_pointer_cast failure"); + } + + float_node->SetValue(value); +} + +void GraphScheme::Node::SetTexture(Texture::Ptr texture) +{ + if (node->GetDataType() != InputMap::InputMapType::kSampler) + { + return; + } + + auto texture_node = std::dynamic_pointer_cast(node); + + if (!texture_node) + { + throw std::runtime_error("Node::SetTexture(...): dynamic_pointer_cast failure"); + } + + texture_node->SetValue(texture); +} \ No newline at end of file diff --git a/BaikalStandalone/Application/graph_scheme.h b/BaikalStandalone/Application/graph_scheme.h new file mode 100644 index 00000000..a5198223 --- /dev/null +++ b/BaikalStandalone/Application/graph_scheme.h @@ -0,0 +1,101 @@ +/********************************************************************** + Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. + + 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 "uber_tree.h" + +class GraphScheme +{ +public: + using Ptr = std::shared_ptr; + + struct Link + { + std::uint32_t src_id; + std::uint32_t dst_id; + + Link(std::uint32_t src_id_, std::uint32_t dst_id_) + : src_id(src_id_), dst_id(dst_id_) + { } + }; + + enum class NodeType + { + kIntermidiate = 0, + kFloat, + kFloat3, + kTexture + }; + + class Node + { + public: + Node(UberNode::Ptr node, + RadeonRays::int2 pos, + RadeonRays::int2 size); + + float GetFloat() const; + void SetFloat(float value); + RadeonRays::float3 GetFloat3() const; + void SetFloat3(RadeonRays::float3 value); + void SetTexture(Baikal::Texture::Ptr texture); + + // fields + std::uint32_t id; + NodeType type; + RadeonRays::int2 pos; // position of the top left corner + RadeonRays::int2 size; + std::string name; + + private: + UberNode::Ptr node; + }; + + static Ptr Create(UberTree::Ptr tree, + RadeonRays::int2 root_pos = RadeonRays::int2(0, 0), + RadeonRays::int2 node_size = RadeonRays::int2(120, 60)); + + void RemoveNode(std::uint32_t id); + void UpdateNodePos(std::uint32_t id, RadeonRays::int2 pos); + void UpdateNodeSize(std::uint32_t id, RadeonRays::int2 size); + void AddTree(UberTree::Ptr tree); + void MergeTrees(UberTree::Ptr tree_1, UberTree::Ptr tree_2); + + const std::vector& GetNodes() const + { return m_nodes; } + + const std::vector& GetLinks() const + { return m_links; } + +protected: + GraphScheme(UberTree::Ptr tree, + RadeonRays::int2 root_pos, + RadeonRays::int2 node_size); + +private: + void RemoveLink(std::uint32_t src_id, std::uint32_t dst_id); + void RecomputeCoordinates(RadeonRays::int2 root_pos, + RadeonRays::int2 node_size); + + std::vector m_trees; + std::vector m_nodes; + std::vector m_links; +}; \ No newline at end of file diff --git a/BaikalStandalone/Application/material_explorer.cpp b/BaikalStandalone/Application/material_explorer.cpp new file mode 100644 index 00000000..dbed58ad --- /dev/null +++ b/BaikalStandalone/Application/material_explorer.cpp @@ -0,0 +1,444 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "material_explorer.h" +#include "image_io.h" +#include + +using namespace Baikal; +static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) +{ + return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); +} + +//////////////////////////////////////////////////////// +//// MaterialExplorer implementation +//////////////////////////////////////////////////////// + +namespace +{ + struct MaterialExplorerConcrete : public MaterialExplorer + { + MaterialExplorerConcrete(UberV2Material::Ptr material) + : MaterialExplorer(material) + { } + }; +} + +MaterialExplorer::Ptr MaterialExplorer::Create(UberV2Material::Ptr material) +{ + return std::make_shared(MaterialExplorerConcrete(material)); +} + +MaterialExplorer::MaterialExplorer(UberV2Material::Ptr material): m_material(material) +{ + auto layers = m_material->GetLayers(); + auto layers_desc = GetUberLayersDesc(); + + auto find_layer = + [&layers_desc](UberV2Material::Layers layers) + { + return *(std::find_if( + layers_desc.begin(), layers_desc.end(), + [layers](LayerDesc desc) + { + if (desc.first == layers) + { + return true; + } + return false; + })); + }; + + // collect all supported layers + if (layers & UberV2Material::kEmissionLayer) + { + m_layers.push_back(find_layer(UberV2Material::kEmissionLayer)); + } + + if (layers & UberV2Material::kTransparencyLayer) + { + m_layers.push_back(find_layer(UberV2Material::kTransparencyLayer)); + } + + if (layers & UberV2Material::kCoatingLayer) + { + m_layers.push_back(find_layer(UberV2Material::kCoatingLayer)); + } + + if (layers & UberV2Material::kReflectionLayer) + { + m_layers.push_back(find_layer(UberV2Material::kReflectionLayer)); + } + + if (layers & UberV2Material::kDiffuseLayer) + { + m_layers.push_back(find_layer(UberV2Material::kDiffuseLayer)); + } + + if (layers & UberV2Material::kRefractionLayer) + { + m_layers.push_back(find_layer(UberV2Material::kRefractionLayer)); + } + + if (layers & UberV2Material::kSSSLayer) + { + m_layers.push_back(find_layer(UberV2Material::kSSSLayer)); + } + + if (layers & UberV2Material::kShadingNormalLayer) + { + m_layers.push_back(find_layer(UberV2Material::kShadingNormalLayer)); + } +} + +bool MaterialExplorer::DrawExplorer(ImVec2 win_size) +{ + bool is_changed = false; + + const ImVec2 NODE_WINDOW_PADDING(8.0f, 8.0f); + const int left_side_width = 150; + + // static variables + static bool show_grid = true; + static int input_selected = -1; + static ImVec2 scrolling = ImVec2(0.0f, 0.0f); + + ImGui::SetNextWindowSize(win_size, ImGuiSetCond_FirstUseEver); + + // Draw a list of layers on the left side + ImGui::BeginChild("layers_list", ImVec2((float)left_side_width, 0)); + ImGui::Text("Layers:"); + ImGui::Separator(); + + int selected_id = 0; + std::string input_name; + for (const auto& layer: m_layers) + { + for (const auto& input: layer.second) + { + if (ImGui::Selectable(input.c_str(), selected_id == input_selected)) + { + input_selected = selected_id; + input_name = input; + } + selected_id++; + } + } + + ImGui::EndChild(); + + ImGui::SameLine(); + ImGui::BeginGroup(); + + // draw canvas with inputs graph + ImGui::Text("Hold middle mouse button to scroll (%.2f,%.2f)", scrolling.x, scrolling.y); + ImGui::SameLine(ImGui::GetWindowWidth() - left_side_width); + ImGui::Checkbox("Show grid", &show_grid); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(1, 1)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); + ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, IM_COL32(60, 60, 70, 200)); + ImGui::BeginChild("scrolling_region", ImVec2(0, 0), true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoMove); + // ImGui::PushItemWidth(120.0f); + + if (!input_name.empty() && + m_selected_input != input_name) + { + auto input_map = m_material->GetInputValue(input_name).input_map_value; + + m_graph = GraphScheme::Create( + UberTree::Create(input_map), + RadeonRays::int2(left_side_width + 10, 100)); + + m_selected_input = input_name; + } + + ImVec2 offset = ImGui::GetCursorScreenPos() + scrolling; + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + + // show grid + if (show_grid) + { + ImU32 GRID_COLOR = IM_COL32(200, 200, 200, 40); + float GRID_SZ = 64.0f; + ImVec2 win_pos = ImGui::GetCursorScreenPos(); + ImVec2 canvas_sz = ImGui::GetWindowSize(); + + for (float x = fmodf(scrolling.x, GRID_SZ); x < canvas_sz.x; x += GRID_SZ) + { + draw_list->AddLine(ImVec2(x, 0.0f) + win_pos, ImVec2(x, canvas_sz.y) + win_pos, GRID_COLOR); + } + + for (float y = fmodf(scrolling.y, GRID_SZ); y < canvas_sz.y; y += GRID_SZ) + { + draw_list->AddLine(ImVec2(0.0f, y) + win_pos, ImVec2(canvas_sz.x, y) + win_pos, GRID_COLOR); + } + } + + + // Display nodes + if (m_graph) + { + // Display links + draw_list->ChannelsSplit(2); + draw_list->ChannelsSetCurrent(0); // Background + + auto nodes = m_graph->GetNodes(); + + for (auto& node: nodes) + { + auto top_left_corner = ImVec2((float)node.pos.x, (float)node.pos.y) + offset; + ImVec2 bottom_right_corner((float)(top_left_corner.x + node.size.x), + (float)(top_left_corner.y + node.size.y)); + + // display node content first + draw_list->ChannelsSetCurrent(1); // Foreground + ImGui::SetCursorScreenPos(top_left_corner + NODE_WINDOW_PADDING); + ImGui::BeginGroup(); // Lock horizontal position + + ImGui::PushItemWidth(.8f * (float)node.size.x); + switch (node.type) + { + case GraphScheme::NodeType::kFloat: + { + ImGui::Text("%s", node.name.c_str()); + float value = node.GetFloat(); + + if (ImGui::InputFloat("##value", &value, ImGuiInputTextFlags_EnterReturnsTrue)) + { + if (value != node.GetFloat()) + { + node.SetFloat(value); + is_changed = true; + } + } + + break; + } + case GraphScheme::NodeType::kFloat3: + { + ImGui::Text("%s", node.name.c_str()); + auto value = node.GetFloat3(); + ImVec4 color(value.x, value.y, value.z, value.w); + + if (ImGui::ColorEdit3("##color", &color.x)) + { + RadeonRays::float4 new_value(color.x, color.y, color.z); + + if ((value.x != new_value.x) || + (value.y != new_value.y) || + (value.z != new_value.z)) + { + node.SetFloat3(new_value); + is_changed = true; + } + } + + break; + } + case GraphScheme::NodeType::kTexture: + { + ImGui::Text("%s", node.name.c_str()); + const int bufer_size = 2048; + char text_buffer[2048] = { 0 }; + + if (ImGui::InputText("##text", text_buffer, bufer_size, ImGuiInputTextFlags_EnterReturnsTrue)) + { + auto image_io = ImageIo::CreateImageIo(); + auto texture = image_io->LoadImage(text_buffer); + if (texture) + { + node.SetTexture(texture); + is_changed = true; + } + } + + break; + } + case GraphScheme::NodeType::kIntermidiate: + default: + ImGui::Text("%s", node.name.c_str()); + } + ImGui::PopItemWidth(); + ImGui::EndGroup(); + + // draw node background rectangle + draw_list->ChannelsSetCurrent(0); // Background + + ImGui::SetCursorScreenPos(top_left_corner); + ImGui::InvisibleButton(std::to_string((int)node.id).c_str(), + ImVec2((float)node.size.x, (float)node.size.y)); + + bool node_hovered_in_scene = false; + + if (ImGui::IsItemHovered()) + { + node_hovered_in_scene = true; + } + + ImU32 node_bg_color = node_hovered_in_scene ? IM_COL32(75, 75, 75, 255) + : IM_COL32(60, 60, 60, 255); + + draw_list->AddRectFilled(top_left_corner, + bottom_right_corner, + node_bg_color, 4.0f); + + draw_list->AddRect(top_left_corner, + bottom_right_corner, + IM_COL32(100, 100, 100, 255), 4.0f); + + // enable node drag + bool node_moving_active = ImGui::IsItemActive(); + + if (node_moving_active && ImGui::IsMouseDragging(0)) + { + auto delta = ImGui::GetIO().MouseDelta; + + auto new_pos = RadeonRays::int2(node.pos.x + (int)delta.x, + node.pos.y + (int)delta.y); + + m_graph->UpdateNodePos(node.id, new_pos); + } + } + + // draw links + for (const auto link: m_graph->GetLinks()) + { + auto src_node_iter = std::find_if(nodes.begin(), nodes.end(), + [link](const GraphScheme::Node& node) + { + return node.id == link.src_id; + }); + + auto dst_node_iter = std::find_if(nodes.begin(), nodes.end(), + [link](const GraphScheme::Node& node) + { + return node.id == link.dst_id; + }); + + if (src_node_iter == nodes.end() || + dst_node_iter == nodes.end()) + { + throw std::logic_error( + "MaterialExplorer::DrawExplorer(...): incorrect links in material graph scheme"); + } + + ImVec2 src_p = offset; + src_p = src_p + ImVec2((float)(src_node_iter->pos.x + src_node_iter->size.x), + (float)(src_node_iter->pos.y + src_node_iter->size.y / 2)); + + ImVec2 dst_p = offset; + dst_p = dst_p + ImVec2((float)(dst_node_iter->pos.x), + (float)(dst_node_iter->pos.y + dst_node_iter->size.y / 2)); + + // draw link + draw_list->AddBezierCurve(src_p, + src_p + ImVec2(+50, 0), + dst_p + ImVec2(-50, 0), + dst_p, + IM_COL32(200, 200, 100, 255), 3.0f); + } + + draw_list->ChannelsMerge(); + } + + // Scrolling + if (ImGui::IsWindowHovered() && + !ImGui::IsAnyItemActive() && + ImGui::IsMouseDragging(2, 0.0f)) + { + scrolling = scrolling + ImGui::GetIO().MouseDelta; + } + + ImGui::EndChild(); + ImGui::PopStyleColor(); + ImGui::PopStyleVar(2); + ImGui::EndGroup(); + + return is_changed; +} + +std::vector MaterialExplorer::GetUberLayersDesc() +{ + return std::vector + { + { + UberV2Material::Layers::kEmissionLayer, + { "uberv2.emission.color" } + }, + { + UberV2Material::Layers::kCoatingLayer, + { "uberv2.coating.color", "uberv2.coating.ior" } + }, + { + UberV2Material::Layers::kReflectionLayer, + { + "uberv2.reflection.color", + "uberv2.reflection.roughness", + "uberv2.reflection.anisotropy", + "uberv2.reflection.anisotropy_rotation", + "uberv2.reflection.ior", + "uberv2.reflection.metalness", + } + }, + { + UberV2Material::Layers::kDiffuseLayer, + { "uberv2.diffuse.color" } + }, + { + UberV2Material::Layers::kRefractionLayer, + { + "uberv2.refraction.color", + "uberv2.refraction.roughness", + "uberv2.refraction.ior" + } + }, + { + UberV2Material::Layers::kTransparencyLayer, + { "uberv2.transparency" } + }, + { + UberV2Material::Layers::kShadingNormalLayer, + { "uberv2.shading_normal" } + }, + { + UberV2Material::Layers::kSSSLayer, + { + "uberv2.sss.absorption_color", + "uberv2.sss.scatter_color", + "uberv2.sss.subsurface_color", + "uberv2.sss.absorption_distance", + "uberv2.sss.scatter_distance", + "uberv2.sss.scatter_direction" + } + }, + }; +} + + +//////////////////////////////////////////////////////// +// MaterialExplorer::NodeLink implementation +//////////////////////////////////////////////////////// + +MaterialExplorer::NodeLink::NodeLink(int input_id_, int input_slot_, int output_id_, int output_slot_) + : input_id(input_id_), input_slot(input_slot_), output_id(output_id_), output_slot(output_slot_) +{ } \ No newline at end of file diff --git a/BaikalStandalone/Application/material_explorer.h b/BaikalStandalone/Application/material_explorer.h new file mode 100644 index 00000000..62c20c9c --- /dev/null +++ b/BaikalStandalone/Application/material_explorer.h @@ -0,0 +1,63 @@ + +/********************************************************************** + Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ + +#pragma once + +#include "ImGUI/imgui.h" +#include "SceneGraph/uberv2material.h" +#include "graph_scheme.h" + +class MaterialExplorer +{ +public: + using InputMap = Baikal::InputMap; + using UberV2Material = Baikal::UberV2Material; + using Ptr = std::shared_ptr; + using LayerDesc = std::pair>; + + static Ptr Create(UberV2Material::Ptr material); + + bool DrawExplorer(ImVec2 win_size); + +protected: + MaterialExplorer(UberV2Material::Ptr material); + +private: + + struct NodeLink + { + int input_id; + int input_slot; + int output_id; + int output_slot; + + NodeLink(int input_id_, int input_slot_, int output_id_, int output_slot_); + }; + + static std::vector GetUberLayersDesc(); + + UberV2Material::Ptr m_material; + std::string m_selected_input; + std::vector m_layers; + GraphScheme::Ptr m_graph; +}; \ No newline at end of file diff --git a/BaikalStandalone/Application/scene_load_utils.cpp b/BaikalStandalone/Application/scene_load_utils.cpp new file mode 100644 index 00000000..59a9b6ae --- /dev/null +++ b/BaikalStandalone/Application/scene_load_utils.cpp @@ -0,0 +1,148 @@ +/********************************************************************** + Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + + 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 "scene_load_utils.h" +#include +#include +#include +#include +#include "XML/tinyxml2.h" + +using namespace Baikal; + +namespace +{ + void LoadMaterials(std::string const& basepath, Scene1::Ptr scene) + { + // Check it we have material remapping + std::ifstream in_materials(basepath + "materials.xml"); + std::ifstream in_mapping(basepath + "mapping.xml"); + + if (!in_materials || !in_mapping) + return; + + auto material_io = Baikal::MaterialIo::CreateMaterialIoXML(); + auto mats = material_io->LoadMaterials(basepath + "materials.xml"); + auto mapping = material_io->LoadMaterialMapping(basepath + "mapping.xml"); + material_io->ReplaceSceneMaterials(*scene, *mats, mapping); + } + + void LoadLights(std::string const& light_file, Scene1::Ptr scene) + { + if (light_file.empty()) + { + return; + } + + tinyxml2::XMLDocument doc; + doc.LoadFile(light_file.c_str()); + + auto root = doc.FirstChildElement("light_list"); + + if (!root) + { + throw std::runtime_error("Failed to open lights set file."); + } + + auto elem = root->FirstChildElement("light"); + + while (elem) + { + Light::Ptr light; + std::string type = elem->Attribute("type"); + + if (type == "point") + { + light = PointLight::Create(); + } + else if (type == "spot") + { + auto spot = SpotLight::Create(); + RadeonRays::float2 cone_shape(elem->FloatAttribute("csx"), + elem->FloatAttribute("csy")); + spot->SetConeShape(cone_shape); + light = spot; + } + else if (type == "direct") + { + light = DirectionalLight::Create(); + } + else if (type == "ibl") + { + auto image_io = ImageIo::CreateImageIo(); + auto tex = image_io->LoadImage(elem->Attribute("tex")); + auto ibl = ImageBasedLight::Create(); + ibl->SetTexture(tex); + ibl->SetMultiplier(elem->FloatAttribute("mul")); + light = ibl; + } + else + { + throw std::runtime_error(std::string("Unknown light type: ") + type); + } + + RadeonRays::float3 rad; + + light->SetPosition({ + elem->FloatAttribute("posx"), + elem->FloatAttribute("posy"), + elem->FloatAttribute("posz")}); + + light->SetDirection({ + elem->FloatAttribute("dirx"), + elem->FloatAttribute("diry"), + elem->FloatAttribute("dirz")}); + + light->SetEmittedRadiance({ + elem->FloatAttribute("radx"), + elem->FloatAttribute("rady"), + elem->FloatAttribute("radz")}); + + scene->AttachLight(light); + + elem = elem->NextSiblingElement("light"); + } + } +} + + +Scene1::Ptr LoadScene(Baikal::AppSettings const& settings) +{ +#ifdef WIN32 + std::string basepath = settings.path + "\\"; +#else + std::string basepath = settings.path + "/"; +#endif + + std::string filename = basepath + settings.modelname; + + auto scene = Baikal::SceneIo::LoadScene(filename, basepath); + + if (scene == nullptr) + { + throw std::runtime_error("LoadScene(...): cannot create scene"); + } + + LoadMaterials(basepath, scene); + LoadLights(settings.light_file, scene); + return scene; +} \ No newline at end of file diff --git a/BaikalStandalone/Application/scene_load_utils.h b/BaikalStandalone/Application/scene_load_utils.h new file mode 100644 index 00000000..b0306d61 --- /dev/null +++ b/BaikalStandalone/Application/scene_load_utils.h @@ -0,0 +1,34 @@ + +/********************************************************************** + Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ + +#pragma once + +#include +#include "app_utils.h" + +namespace Baikal +{ + class Scene1; +} + +std::shared_ptr LoadScene(Baikal::AppSettings const& settings); diff --git a/BaikalStandalone/Application/uber_node.cpp b/BaikalStandalone/Application/uber_node.cpp new file mode 100644 index 00000000..b4a23d87 --- /dev/null +++ b/BaikalStandalone/Application/uber_node.cpp @@ -0,0 +1,931 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "uber_node.h" + +using namespace Baikal; + +//////////////////////////////////////// +// UberNode_OneArg implementation +//////////////////////////////////////// + +std::uint32_t UberNode::m_next_id = 0; + +#define GET_ONE_ARG(type, sufix)\ + {\ + auto input_map = std::dynamic_pointer_cast(m_input_map);\ + if (!input_map){\ + throw std::runtime_error("Dynamic_cast failure");\ + }\ + return input_map->Get##sufix();\ + }\ + +#define SET_ONE_ARG(param, type, sufix)\ + {\ + auto input_map_ = std::dynamic_pointer_cast(m_input_map);\ + if (!input_map_){\ + throw std::runtime_error("Dynamic_cast failure");\ + }\ + input_map_->Set##sufix(param);\ + break;\ + }\ + +#define GET_ARG(X) GET_ONE_ARG(X, Arg) +#define GET_ARG_A(X) GET_ONE_ARG(X, A) +#define GET_ARG_B(X) GET_ONE_ARG(X, B) +#define GET_ARG_C(X) GET_ONE_ARG(X, C) +#define SET_ARG(param, X) SET_ONE_ARG(param, X, Arg) +#define SET_ARG_A(param, X) SET_ONE_ARG(param, X, A) +#define SET_ARG_B(param, X) SET_ONE_ARG(param, X, B) +#define SET_ARG_C(param, X) SET_ONE_ARG(param, X, C) + +#define GET_ARG_HANDLER(input_type, sufix)\ + switch (input_type)\ + {\ + case InputMap::InputMapType::kAdd:\ + GET_ARG_##sufix(InputMap_Add);\ + case InputMap::InputMapType::kSub:\ + GET_ARG_##sufix(InputMap_Sub);\ + case InputMap::InputMapType::kMul:\ + GET_ARG_##sufix(InputMap_Mul);\ + case InputMap::InputMapType::kDiv:\ + GET_ARG_##sufix(InputMap_Div);\ + case InputMap::InputMapType::kMin:\ + GET_ARG_##sufix(InputMap_Min);\ + case InputMap::InputMapType::kMax:\ + GET_ARG_##sufix(InputMap_Max);\ + case InputMap::InputMapType::kDot3:\ + GET_ARG_##sufix(InputMap_Dot3);\ + case InputMap::InputMapType::kCross3:\ + GET_ARG_##sufix(InputMap_Cross3);\ + case InputMap::InputMapType::kDot4:\ + GET_ARG_##sufix(InputMap_Dot4);\ + case InputMap::InputMapType::kCross4:\ + GET_ARG_##sufix(InputMap_Cross4);\ + case InputMap::InputMapType::kPow:\ + GET_ARG_##sufix(InputMap_Pow);\ + case InputMap::InputMapType::kMod:\ + GET_ARG_##sufix(InputMap_Mod);\ + case InputMap::InputMapType::kLerp:\ + GET_ARG_##sufix(InputMap_TwoArg)\ + case InputMap::InputMapType::kShuffle2:\ + GET_ARG_##sufix(InputMap_TwoArg);\ + default:\ + return nullptr;\ + }\ + +#define SET_ARG_HANDLER(param, input_type, sufix)\ + switch (input_type)\ + {\ + case InputMap::InputMapType::kAdd:\ + SET_ARG_##sufix(param, InputMap_Add);\ + case InputMap::InputMapType::kSub:\ + SET_ARG_##sufix(param, InputMap_Sub);\ + case InputMap::InputMapType::kMul:\ + SET_ARG_##sufix(param, InputMap_Mul);\ + case InputMap::InputMapType::kDiv:\ + SET_ARG_##sufix(param, InputMap_Div);\ + case InputMap::InputMapType::kMin:\ + SET_ARG_##sufix(param, InputMap_Min);\ + case InputMap::InputMapType::kMax:\ + SET_ARG_##sufix(param, InputMap_Max);\ + case InputMap::InputMapType::kDot3:\ + SET_ARG_##sufix(param, InputMap_Dot3);\ + case InputMap::InputMapType::kCross3:\ + SET_ARG_##sufix(param,InputMap_Cross3);\ + case InputMap::InputMapType::kDot4:\ + SET_ARG_##sufix(param, InputMap_Dot4);\ + case InputMap::InputMapType::kCross4:\ + SET_ARG_##sufix(param, InputMap_Cross4);\ + case InputMap::InputMapType::kPow:\ + SET_ARG_##sufix(param, InputMap_Pow);\ + case InputMap::InputMapType::kMod:\ + SET_ARG_##sufix(param, InputMap_Mod);\ + case InputMap::InputMapType::kLerp:\ + SET_ARG_##sufix(param, InputMap_TwoArg)\ + case InputMap::InputMapType::kShuffle2:\ + SET_ARG_##sufix(param, InputMap_TwoArg);\ + default:\ + throw std::runtime_error("SET_ARG_HANDLER macros:"\ + "unxupported InputMapType for this operation");\ + }\ + +#define GET_ARG_HANDLER_A(input_type) GET_ARG_HANDLER(input_type, A) +#define GET_ARG_HANDLER_B(input_type) GET_ARG_HANDLER(input_type, B) +#define GET_ARG_HANDLER_C(input_type) GET_ARG_HANDLER(input_type, C) +#define SET_ARG_HANDLER_A(param, input_type) SET_ARG_HANDLER(param, input_type, A) +#define SET_ARG_HANDLER_B(param, input_type) SET_ARG_HANDLER(param, input_type, B) +#define SET_ARG_HANDLER_C(param, input_type) SET_ARG_HANDLER(param, input_type, C) + +InputMap::Ptr UberNode_Arg::GetArg(std::uint32_t arg_number) +{ + if (arg_number != 0) + { + throw std::logic_error( + "UberNode_Arg::GetArg(...): attempt to set arg_number distinguish"); + } + + if (m_children[arg_number] < 0) + { + return nullptr; + } + + switch (m_input_map->m_type) + { + case InputMap::InputMapType::kSin: + GET_ARG(InputMap_OneArg); + case InputMap::InputMapType::kCos: + GET_ARG(InputMap_OneArg); + case InputMap::InputMapType::kTan: + GET_ARG(InputMap_OneArg); + case InputMap::InputMapType::kAsin: + GET_ARG(InputMap_OneArg); + case InputMap::InputMapType::kAcos: + GET_ARG(InputMap_OneArg); + case InputMap::InputMapType::kAtan: + GET_ARG(InputMap_OneArg); + case InputMap::InputMapType::kLength3: + GET_ARG(InputMap_OneArg); + case InputMap::InputMapType::kNormalize3: + GET_ARG(InputMap_OneArg); + case InputMap::InputMapType::kFloor: + GET_ARG(InputMap_OneArg); + case InputMap::InputMapType::kAbs: + GET_ARG(InputMap_OneArg); + default: + return nullptr; + } +} + +void UberNode_Arg::SetArg(InputMap::Ptr input_map, std::uint32_t arg_number) +{ + if (arg_number != 0) + { + throw std::logic_error("UberNode_Arg::SetArg(...):" + "attempt to set arg_number distinguish"); + } + + if (!input_map) + { + return; + } + + switch (input_map->m_type) + { + case InputMap::InputMapType::kSin: + SET_ARG(input_map, InputMap_Sin); + case InputMap::InputMapType::kCos: + SET_ARG(input_map, InputMap_Cos); + case InputMap::InputMapType::kTan: + SET_ARG(input_map, InputMap_Tan); + case InputMap::InputMapType::kAsin: + SET_ARG(input_map, InputMap_Asin); + case InputMap::InputMapType::kAcos: + SET_ARG(input_map, InputMap_Acos); + case InputMap::InputMapType::kAtan: + SET_ARG(input_map, InputMap_Atan); + case InputMap::InputMapType::kLength3: + SET_ARG(input_map, InputMap_Length3); + case InputMap::InputMapType::kNormalize3: + SET_ARG(input_map, InputMap_Normalize3); + case InputMap::InputMapType::kFloor: + SET_ARG(input_map, InputMap_Floor); + case InputMap::InputMapType::kAbs: + SET_ARG(input_map, InputMap_Abs); + case InputMap::InputMapType::kSelect: + SET_ARG(input_map, InputMap_OneArg); + case InputMap::InputMapType::kShuffle: + SET_ARG(input_map, InputMap_OneArg); + case InputMap::InputMapType::kMatMul: + SET_ARG(input_map, InputMap_OneArg); + default: + throw std::runtime_error("UberNode_Arg::SetArg(...):" + "unxupported InputMapType for this operation"); + } +} + +bool UberNode::IsValid() const +{ + size_t arg_number = 0; + switch (GetType()) + { + case NodeType::kNoneArgs: + return true; + case NodeType::kOneArg: + arg_number = 1; + break; + case NodeType::kTwoArgs: + arg_number = 2; + break; + case NodeType::kThreeArgs: + arg_number = 3; + break; + } + + for (size_t i = 0; i < arg_number; i++) + { + if (m_children[i] < 0) + { + return false; + } + } + + return true; +} + +void UberNode::SetChild(std::uint32_t arg_number, Ptr child) +{ + if ((size_t)arg_number < m_children.size()) + { + m_children[arg_number] = child; + } +} + +//////////////////////////////////////// +// UberNode_Select implementation +//////////////////////////////////////// + +InputMap_Select::Selection UberNode_Select::GetSelection() +{ + auto input_map = std::dynamic_pointer_cast(m_input_map); + + if (!input_map) + { + throw std::runtime_error("UberNode_Select::GetSelection(...):" + "invalid dynamic_cast"); + } + + return input_map->GetSelection(); +} + +// set selection parametr (Not InputMap) +void UberNode_Select::SetSelection(Baikal::InputMap_Select::Selection selection) +{ + auto input_map = std::dynamic_pointer_cast(m_input_map); + + if (!input_map) + { + throw std::runtime_error("UberNode_Select::SetSelection(...):" + "invalid dynamic_cast"); + } + + input_map->SetSelection(selection); +} + +//////////////////////////////////////// +// UberNode_Shuffle implementation +//////////////////////////////////////// + +std::array UberNode_Shuffle::GetMask() const +{ + auto input_map = std::dynamic_pointer_cast(m_input_map); + + if (!input_map) + { + throw std::runtime_error("UberNode_Shuffle::GetMask(...):" + "invalid dynamic_cast"); + } + + return input_map->GetMask(); +} + +void UberNode_Shuffle::SetMask(const std::array& mask) +{ + auto input_map = std::dynamic_pointer_cast(m_input_map); + + if (!input_map) + { + throw std::runtime_error("UberNode_Shuffle::GetMask(...):" + "invalid dynamic_cast"); + } + + input_map->SetMask(mask); +} + +//////////////////////////////////////// +// UberNode_Matmul implementation +//////////////////////////////////////// + +RadeonRays::matrix UberNode_Matmul::GetMatrix() const +{ + auto input_map = std::dynamic_pointer_cast(m_input_map); + + if (!input_map) + { + throw std::runtime_error("UberNode_Matmul::GetMatrix(...):" + "invalid dynamic_cast"); + } + + return input_map->GetMatrix(); +} + +void UberNode_Matmul::SetMatrix(const RadeonRays::matrix &mat4) +{ + auto input_map = std::dynamic_pointer_cast(m_input_map); + if (!input_map) + { + throw std::runtime_error( + "UberNode_Matmul::SetMatrix(...): invalid dynamic_cast"); + } + input_map->SetMatrix(mat4); +} + +//////////////////////////////////////// +// UberNode_TwoArgs implementation +//////////////////////////////////////// + +InputMap::Ptr UberNode_TwoArgs::GetArg(std::uint32_t arg_number) +{ + if (arg_number > MAX_ARGS - 1) + { + throw std::logic_error("UberNode_TwoArgs::GetArg(...):" + "'arg_number' can not be bigger than 1"); + } + + if (arg_number == 0) + { + GET_ARG_HANDLER_A(m_input_map->m_type) + } + else + { + GET_ARG_HANDLER_B(m_input_map->m_type) + } +} + +void UberNode_TwoArgs::SetArg(InputMap::Ptr arg, std::uint32_t arg_number) +{ + if (arg_number > MAX_ARGS - 1) + { + throw std::logic_error("UberNode_TwoArgs::SetArg(...):" + "'arg_number' can not be bigger than 1"); + } + + if (!arg) + { + return; + } + + if (arg_number == 0) + { + SET_ARG_HANDLER_A(arg, m_input_map->m_type) + } + else + { + SET_ARG_HANDLER_B(arg, m_input_map->m_type) + } +} + +//////////////////////////////////////// +// UberNode_Lerp implementation +//////////////////////////////////////// + +// get control parameter (not child argument) +Baikal::InputMap::Ptr UberNode_Lerp::GetControl() +{ + auto input_map = std::dynamic_pointer_cast(m_input_map); + + if (!input_map) + { + throw std::runtime_error("UberNode_Lerp::GetControl(...):" + "invalid dynamic_cast"); + } + + return input_map->GetControl(); +} + +// set control parameter (not child argument) +void UberNode_Lerp::SetControl(Baikal::InputMap::Ptr control) +{ + auto input_map = std::dynamic_pointer_cast(m_input_map); + + if (!input_map) + { + throw std::runtime_error("UberNode_Lerp::GetControl(...):" + "invalid dynamic_cast"); + } + + return input_map->SetControl(control); +} + +//////////////////////////////////////// +// UberNode_Shuffle2 implementation +//////////////////////////////////////// + +// get mask parameter (Not InputMap) +std::array UberNode_Shuffle2::GetMask() const +{ + auto input_map = std::dynamic_pointer_cast(m_input_map); + + if (!input_map) + { + throw std::runtime_error("UberNode_Shuffle2::GetMask(...):" + "invalid dynamic_cast"); + } + + return input_map->GetMask(); +} + +// set mask parameter (Not InputMap) +void UberNode_Shuffle2::SetMask(const std::array& mask) +{ + auto input_map = std::dynamic_pointer_cast(m_input_map); + + if (!input_map) + { + throw std::runtime_error("UberNode_Shuffle2::GetMask(...):" + "invalid dynamic_cast"); + } + + input_map->SetMask(mask); +} + +//////////////////////////////////// +// UberNode_Float implementation +//////////////////////////////////// + +float UberNode_Float::GetValue() const +{ + auto input_map = std::dynamic_pointer_cast(m_input_map); + + if (!input_map) + { + throw std::runtime_error("UberNode_Float::GetValue(...):" + "invalid dynamic_cast"); + } + + return input_map->GetValue(); +} + +void UberNode_Float::SetValue(float value) +{ + auto input_map = std::dynamic_pointer_cast(m_input_map); + + if (!input_map) + { + throw std::runtime_error("UberNode_Float::SetValue(...):" + "invalid dynamic_cast"); + } + + input_map->SetValue(value); +} + +//////////////////////////////////// +// UberNode_Float3 implementation +//////////////////////////////////// + +RadeonRays::float3 UberNode_Float3::GetValue() const +{ + auto input_map = std::dynamic_pointer_cast(m_input_map); + + if (!input_map) + { + throw std::runtime_error("UberNode_Float3::GetValue(...):" + "invalid dynamic_cast"); + } + + return input_map->GetValue(); +} + +void UberNode_Float3::SetValue(RadeonRays::float3 value) +{ + auto input_map = std::dynamic_pointer_cast(m_input_map); + + if (!input_map) + { + throw std::runtime_error("UberNode_Float3::SetValue(...):" + "invalid dynamic_cast"); + } + + input_map->SetValue(value); +} + +//////////////////////////////////// +// UberNode_Sampler implementation +//////////////////////////////////// + +Texture::Ptr UberNode_Sampler::GetValue() const +{ + auto input_map = std::dynamic_pointer_cast(m_input_map); + + if (!input_map) + { + throw std::runtime_error("UberNode_Sampler::GetValue(...):" + "invalid dynamic_cast"); + } + + return input_map->GetTexture(); +} + +void UberNode_Sampler::SetValue(Texture::Ptr value) +{ + auto input_map = std::dynamic_pointer_cast(m_input_map); + + if (!input_map) + { + throw std::runtime_error("UberNode_Sampler::SetValue(...):" + "invalid dynamic_cast"); + } + + input_map->SetTexture(value); +} + +//////////////////////////////////// +// UberNode_ThreeArgs +//////////////////////////////////// + +InputMap::Ptr UberNode_ThreeArgs::GetArg(std::uint32_t arg_number) +{ + if (arg_number > MAX_ARGS - 1) + { + throw std::logic_error("UberNode_ThreeArgs::GetArg(...):" + "'arg_number can not be bigger than two"); + } + + auto input_map = std::dynamic_pointer_cast(m_input_map); + + if (!input_map) + { + throw std::runtime_error("UberNode_ThreeArgs::GetArg_(...):" + "Dynamic_cast failure"); + } + + if (arg_number == 0) + { + return input_map->GetSourceRange(); + } + else if (arg_number == 1) + { + return input_map->GetDestinationRange(); + } + else + { + return input_map->GetData(); + } +} + +// Set UberNode_ThreeArgs child +void UberNode_ThreeArgs::SetArg(InputMap::Ptr arg, std::uint32_t arg_number) +{ + if (arg_number > MAX_ARGS - 1) + { + throw std::logic_error("UberNode_ThreeArgs::SetArg(...):" + "'arg_number can not be bigger than two"); + } + + auto input_map = std::dynamic_pointer_cast(arg); + + if (!input_map) + { + throw std::runtime_error("UberNode_ThreeArgs::SetArg(...):" + "dynamic_cast failure"); + } + + if (arg_number == 0) + { + input_map->SetSourceRange(input_map); + } + else if (arg_number == 1) + { + input_map->SetDestinationRange(input_map); + } + else + { + input_map->SetData(input_map); + } +} + + +namespace { + struct UberNode_ArgConcrete : public UberNode_Arg + { + UberNode_ArgConcrete(InputMap::Ptr input_map, Ptr parent) + : UberNode_Arg(input_map, parent) {} + }; + + struct UberNode_SelectConcrete : public UberNode_Select + { + UberNode_SelectConcrete(InputMap::Ptr input_map, Ptr parent) + : UberNode_Select(input_map, parent) {} + }; + + struct UberNode_ShuffleConcrete : public UberNode_Shuffle + { + UberNode_ShuffleConcrete(InputMap::Ptr input_map, Ptr parent) + : UberNode_Shuffle(input_map, parent) {} + }; + + struct UberNode_MatmulConcrete : public UberNode_Matmul + { + UberNode_MatmulConcrete(InputMap::Ptr input_map, Ptr parent) + : UberNode_Matmul(input_map, parent) {} + }; + + struct UberNode_TwoArgsConcrete : public UberNode_TwoArgs + { + UberNode_TwoArgsConcrete(InputMap::Ptr input_map, Ptr parent) + : UberNode_TwoArgs(input_map, parent) {} + }; + + struct UberNode_LerpConcrete : public UberNode_Lerp + { + UberNode_LerpConcrete(InputMap::Ptr input_map, Ptr parent) + : UberNode_Lerp(input_map, parent) {} + }; + + struct UberNode_Shuffle2Concrete : public UberNode_Shuffle2 + { + UberNode_Shuffle2Concrete(InputMap::Ptr input_map, Ptr parent) + : UberNode_Shuffle2(input_map, parent) {} + }; + + struct UberNode_ThreeArgsConcrete : public UberNode_ThreeArgs + { + UberNode_ThreeArgsConcrete(InputMap::Ptr input_map, Ptr parent) + : UberNode_ThreeArgs(input_map, parent) {} + }; + + struct UberNode_FloatConcrete : public UberNode_Float + { + UberNode_FloatConcrete(InputMap::Ptr input_map, Ptr parent) + : UberNode_Float(input_map, parent) {} + }; + + struct UberNode_Float3Concrete : public UberNode_Float3 + { + UberNode_Float3Concrete(InputMap::Ptr input_map, Ptr parent) + : UberNode_Float3(input_map, parent) {} + }; + + struct UberNode_SamplerConcrete : public UberNode_Sampler + { + UberNode_SamplerConcrete(InputMap::Ptr input_map, Ptr parent) + : UberNode_Sampler(input_map, parent) {} + }; +} + +//////////////////////////////////// +// UberNode implementation +//////////////////////////////////// + +InputMap::Ptr UberNode::GetArg(std::uint32_t arg_number) +{ + return nullptr; +} + +void UberNode::SetArg(InputMap::Ptr, std::uint32_t) { } + +UberNode::Ptr UberNode::GetChildren(std::uint32_t arg_number) const +{ + if ((size_t)arg_number > m_children.size()) + { + throw std::logic_error("UberNode::GetChildren(...):" + "attempt to get nonexistent 'arg_number'"); + } + + return m_children[arg_number]; +} + +// input map data type accessor +InputMap::InputMapType UberNode::GetDataType() const +{ + return m_input_map->m_type; +} + +std::string UberNode::GetDataTypeText() const +{ + switch (m_input_map->m_type) + { + case InputMap::InputMapType::kConstantFloat3: + return "kConstantFloat3"; + case InputMap::InputMapType::kConstantFloat: + return "kConstantFloat"; + case InputMap::InputMapType::kSampler: + return "kSampler"; + case InputMap::InputMapType::kAdd: + return "kAdd"; + case InputMap::InputMapType::kSub: + return "kSub"; + case InputMap::InputMapType::kMul: + return "kMul"; + case InputMap::InputMapType::kDiv: + return "kDiv"; + case InputMap::InputMapType::kSin: + return "kSin"; + case InputMap::InputMapType::kCos: + return "kCos"; + case InputMap::InputMapType::kTan: + return "kTan"; + case InputMap::InputMapType::kSelect: + return "kSelect"; + case InputMap::InputMapType::kDot3: + return "kDot3"; + case InputMap::InputMapType::kCross3: + return "kCross3"; + case InputMap::InputMapType::kLength3: + return "kLength3"; + case InputMap::InputMapType::kNormalize3: + return "kNormalize3"; + case InputMap::InputMapType::kPow: + return "kPow"; + case InputMap::InputMapType::kAcos: + return "kAcos"; + case InputMap::InputMapType::kAsin: + return "kAsin"; + case InputMap::InputMapType::kAtan: + return "kAtan"; + case InputMap::InputMapType::kLerp: + return "kLerp"; + case InputMap::InputMapType::kMin: + return "kMin"; + case InputMap::InputMapType::kMax: + return "kMax"; + case InputMap::InputMapType::kFloor: + return "kFloor"; + case InputMap::InputMapType::kMod: + return "kMod"; + case InputMap::InputMapType::kAbs: + return "kAbs"; + case InputMap::InputMapType::kShuffle: + return "kShuffle"; + case InputMap::InputMapType::kShuffle2: + return "kShuffle2"; + case InputMap::InputMapType::kDot4: + return "kDot4"; + case InputMap::InputMapType::kCross4: + return "kCross4"; + case InputMap::InputMapType::kSamplerBumpmap: + return "kSamplerBumpmap"; + case InputMap::InputMapType::kMatMul: + return "kMatMul"; + case InputMap::InputMapType::kRemap: + return "kRemap"; + default: + return ""; // empty string + } +} + +std::uint32_t UberNode::GetArgNumber() +{ + switch (GetType()) + { + case NodeType::kNoneArgs: + return 0; + case NodeType::kOneArg: + return 1; + case NodeType::kTwoArgs: + return 2; + case NodeType::kThreeArgs: + return 3; + default: + return 0; + } +} + +int UberNode::GetParentId() const +{ + if (m_parent) + { + return m_parent->GetId(); + } + + return -1; +} + +UberNode::UberNode(InputMap::Ptr input_map, UberNode::Ptr parent) + :m_input_map(input_map), m_parent(parent), m_id(m_next_id++) +{ } + +UberNode::~UberNode() = default; + +UberNode_Arg::UberNode_Arg(InputMap::Ptr input_map, UberNode::Ptr parent) + : UberNode(input_map, parent) +{ + m_children.push_back(nullptr); +} + +UberNode_Select::UberNode_Select(InputMap::Ptr input_map, UberNode::Ptr parent) + : UberNode_Arg(input_map, parent) {} + +UberNode_Shuffle::UberNode_Shuffle(InputMap::Ptr input_map, UberNode::Ptr parent) + : UberNode_Arg(input_map, parent) {} + +UberNode_Matmul::UberNode_Matmul(InputMap::Ptr input_map, UberNode::Ptr parent) + : UberNode_Arg(input_map, parent) {} + +UberNode_TwoArgs::UberNode_TwoArgs(InputMap::Ptr input_map, UberNode::Ptr parent) + : UberNode(input_map, parent) +{ + m_children.push_back(nullptr); + m_children.push_back(nullptr); +} + +UberNode_Lerp::UberNode_Lerp(InputMap::Ptr input_map, UberNode::Ptr parent) + : UberNode_TwoArgs(input_map, parent) {} + +UberNode_Shuffle2::UberNode_Shuffle2(InputMap::Ptr input_map, UberNode::Ptr parent) + : UberNode_TwoArgs(input_map, parent) {} + +UberNode_ThreeArgs::UberNode_ThreeArgs(InputMap::Ptr input_map, UberNode::Ptr parent) + : UberNode(input_map, parent) +{ + m_children.push_back(nullptr); + m_children.push_back(nullptr); + m_children.push_back(nullptr); +} + +UberNode_Float::UberNode_Float(InputMap::Ptr input_map, UberNode::Ptr parent) + : UberNode(input_map, parent) {} + +UberNode_Float3::UberNode_Float3(InputMap::Ptr input_map, UberNode::Ptr parent) + : UberNode(input_map, parent) {} + +UberNode_Sampler::UberNode_Sampler(InputMap::Ptr input_map, UberNode::Ptr parent) + : UberNode(input_map, parent) {} + +UberNode::Ptr UberNode::Create(InputMap::Ptr input_map, Ptr parent) +{ + switch (input_map->m_type) + { + // one arg input maps + case InputMap::InputMapType::kSin: + case InputMap::InputMapType::kCos: + case InputMap::InputMapType::kTan: + case InputMap::InputMapType::kAsin: + case InputMap::InputMapType::kAcos: + case InputMap::InputMapType::kAtan: + case InputMap::InputMapType::kLength3: + case InputMap::InputMapType::kNormalize3: + case InputMap::InputMapType::kFloor: + case InputMap::InputMapType::kAbs: + return std::make_shared(input_map, parent); + case InputMap::InputMapType::kSelect: + return std::make_shared(input_map, parent); + case InputMap::InputMapType::kShuffle: + return std::make_shared(input_map, parent); + case InputMap::InputMapType::kMatMul: + return std::make_shared(input_map, parent); + // two args input maps + case InputMap::InputMapType::kAdd: + case InputMap::InputMapType::kSub: + case InputMap::InputMapType::kMul: + case InputMap::InputMapType::kDiv: + case InputMap::InputMapType::kMin: + case InputMap::InputMapType::kMax: + case InputMap::InputMapType::kDot3: + case InputMap::InputMapType::kCross3: + case InputMap::InputMapType::kDot4: + case InputMap::InputMapType::kCross4: + case InputMap::InputMapType::kPow: + case InputMap::InputMapType::kMod: + return std::make_shared(input_map, parent); + case InputMap::InputMapType::kLerp: + return std::make_shared(input_map, parent); + case InputMap::InputMapType::kShuffle2: + return std::make_shared(input_map, parent); + default: + { + if (std::dynamic_pointer_cast(input_map) != nullptr) + { + return std::make_shared(input_map, parent); + } + + // leaf input maps + if (std::dynamic_pointer_cast(input_map) != nullptr) + { + return std::make_shared(input_map, parent); + } + + if (std::dynamic_pointer_cast(input_map) != nullptr) + { + return std::make_shared(input_map, parent); + } + + if (std::dynamic_pointer_cast(input_map) != nullptr) + { + return std::make_shared(input_map, parent); + } + } + } + + return nullptr; +} \ No newline at end of file diff --git a/BaikalStandalone/Application/uber_node.h b/BaikalStandalone/Application/uber_node.h new file mode 100644 index 00000000..f426fa4f --- /dev/null +++ b/BaikalStandalone/Application/uber_node.h @@ -0,0 +1,239 @@ + +/********************************************************************** + Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ + +#pragma once + +#include "Baikal/SceneGraph/inputmap.h" +#include "Baikal/SceneGraph/inputmaps.h" + +// do not change the order +// if you want to add four, five and etc arguments +// than make it in increasing order +enum class NodeType +{ + kNoneArgs = 0, + kOneArg, + kTwoArgs, + kThreeArgs +}; + +class UberTree; +class UberTreeIterator; + +#define MAX_ARGS (3) +#define INVALID_ID (-1) + +class UberNode +{ + friend class UberTree; + friend class UberTreeIterator; +public: + using Ptr = std::shared_ptr; + using InputMap = Baikal::InputMap; + + // for root element parent is nullptr + static Ptr Create(InputMap::Ptr input_map, Ptr parent); + + bool IsValid() const; + virtual NodeType GetType() const = 0; + + // input map data type accessor + InputMap::InputMapType GetDataType() const; + std::string GetDataTypeText() const; + + // Get InputMap argument + virtual InputMap::Ptr GetArg(std::uint32_t arg_number = 0); + // Set InputMap argument + virtual void SetArg(InputMap::Ptr, std::uint32_t); + + std::uint32_t GetArgNumber(); + + std::uint32_t GetId() const { return m_id; } + + int GetParentId() const; + + virtual ~UberNode(); + +protected: + UberNode(InputMap::Ptr input_map, UberNode::Ptr parent); + + void SetChild(std::uint32_t arg_number, Ptr child); + Ptr GetChildren(std::uint32_t arg_number) const; + + // fields + std::vector m_children; + InputMap::Ptr m_input_map; + Ptr m_parent; + +private: + std::uint32_t m_id; + static std::uint32_t m_next_id; +}; + +// UberNode_OneArg common class +class UberNode_Arg : public UberNode +{ +public: + // Get InputMap_OneArg child + virtual InputMap::Ptr GetArg(std::uint32_t arg_number = 0) override; + // Set InputMap_OneArg child + virtual void SetArg(InputMap::Ptr arg, std::uint32_t arg_number = 0) override; + + NodeType GetType() const override + { return NodeType::kOneArg; } + +protected: + UberNode_Arg(InputMap::Ptr input_map, UberNode::Ptr parent); +}; + +// UberNode_OneArg specific classes +class UberNode_Select : public UberNode_Arg +{ +public: + // get selection parametr (Not InputMap) + Baikal::InputMap_Select::Selection GetSelection(); + // set selection parametr (Not InputMap) + void SetSelection(Baikal::InputMap_Select::Selection selection); + +protected: + UberNode_Select(InputMap::Ptr input_map, UberNode::Ptr parent); +}; + +class UberNode_Shuffle : public UberNode_Arg +{ +public: + // get mask parameter (Not InputMap) + std::array GetMask() const; + // set mask parameter (Not InputMap) + void SetMask(const std::array &mask); +protected: + UberNode_Shuffle(InputMap::Ptr input_map, UberNode::Ptr parent); +}; + +class UberNode_Matmul : public UberNode_Arg +{ +public: + // get matrix parameter + void SetMatrix(const RadeonRays::matrix &mat4); + // get matrix parameter + RadeonRays::matrix GetMatrix() const; +protected: + UberNode_Matmul(InputMap::Ptr input_map, UberNode::Ptr parent); +}; + +// UberNode_TwoArgs common class +class UberNode_TwoArgs : public UberNode +{ +public: + // Get InputMap_OneArg child + virtual InputMap::Ptr GetArg(std::uint32_t arg_number) override; + // Set InputMap_OneArg child + virtual void SetArg(InputMap::Ptr arg, std::uint32_t arg_number) override; + + NodeType GetType() const override + { return NodeType::kTwoArgs; } + +protected: + UberNode_TwoArgs(InputMap::Ptr input_map, UberNode::Ptr parent); +}; + +// UberNode_TwoArgs specific class +class UberNode_Lerp : public UberNode_TwoArgs +{ +public: + // get control parameter (not child argument) + Baikal::InputMap::Ptr GetControl(); + // set control parameter (not child argument) + void SetControl(Baikal::InputMap::Ptr control); + +protected: + UberNode_Lerp(InputMap::Ptr input_map, UberNode::Ptr parent); +}; + +class UberNode_Shuffle2 : public UberNode_TwoArgs +{ +public: + // get mask parameter (Not InputMap) + std::array GetMask() const; + // set mask parameter (Not InputMap) + void SetMask(const std::array &mask); + +protected: + UberNode_Shuffle2(InputMap::Ptr input_map, UberNode::Ptr parent); +}; + +// UberNode_ThreeArgs common class +class UberNode_ThreeArgs : public UberNode +{ +public: + NodeType GetType() const override + { return NodeType::kThreeArgs; } + + // Get InputMap_OneArg child + virtual InputMap::Ptr GetArg(std::uint32_t arg_number) override; + // Set InputMap_OneArg child + virtual void SetArg(InputMap::Ptr arg, std::uint32_t arg_number) override; + +protected: + UberNode_ThreeArgs(InputMap::Ptr input_map, UberNode::Ptr parent); +}; + +// lead nodes +class UberNode_Float : public UberNode +{ +public: + void SetValue(float value); + float GetValue() const; + +protected: + NodeType GetType() const override + { return NodeType::kNoneArgs; } + + UberNode_Float(InputMap::Ptr input_map, UberNode::Ptr parent); +}; + +class UberNode_Float3 : public UberNode +{ +public: + void SetValue(RadeonRays::float3 value); + RadeonRays::float3 GetValue() const; + +protected: + NodeType GetType() const override + { return NodeType::kNoneArgs; } + + UberNode_Float3(InputMap::Ptr input_map, UberNode::Ptr parent); +}; + +class UberNode_Sampler : public UberNode +{ +public: + void SetValue(Baikal::Texture::Ptr value); + Baikal::Texture::Ptr GetValue() const; + +protected: + NodeType GetType() const override + { return NodeType::kNoneArgs; } + + UberNode_Sampler(InputMap::Ptr input_map, UberNode::Ptr paren); +}; \ No newline at end of file diff --git a/BaikalStandalone/Application/uber_tree.cpp b/BaikalStandalone/Application/uber_tree.cpp new file mode 100644 index 00000000..94808ed3 --- /dev/null +++ b/BaikalStandalone/Application/uber_tree.cpp @@ -0,0 +1,263 @@ +/********************************************************************** +Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. + +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 "uber_tree.h" +#include + +//////////////////////////////////////////// +//// UberTree implementation +//////////////////////////////////////////// + +void UberTree::BuildTree(InputMap::Ptr input_map) +{ + auto root = UberNode::Create(input_map, nullptr); + std::queue queue; + + queue.push(root); + + while (!queue.empty()) + { + auto node = queue.front(); + + for (auto i = 0u; i < node->GetArgNumber(); i++) + { + auto child = UberNode::Create(node->GetArg(i), node); + node->SetChild(i, child); + queue.push(child); + } + + m_nodes.push_back(node); + queue.pop(); + } + +} + +bool UberTree::AddTree(std::uint32_t id, std::uint32_t arg_number, UberTree::Ptr tree) +{ + if (arg_number > MAX_ARGS - 1) + { + return false; + } + + UberNode::Ptr parent = nullptr; + + for (const auto& node : m_nodes) + { + if (node->GetId() == id) + { + parent = node; + } + } + + if (!parent) + { + return false; // there is no Node with such id (argument 'id') + } + + auto child = tree->m_nodes.begin(); + + m_nodes.insert(m_nodes.end(), + tree->m_nodes.begin(), + tree->m_nodes.end()); + + parent->SetChild(arg_number, *child); + (*child)->m_parent = parent; + tree = nullptr; + return true; +} + +std::vector UberTree::ExcludeNode(std::uint32_t id) +{ + UberNode::Ptr removed_node = nullptr; + + for (const auto& node : m_nodes) + { + if (node->GetId() == id) + { + removed_node = node; + } + } + + if (!removed_node) + { + throw std::logic_error("UberTree::ExcludeNode(...):" + "attempt to exclude nonexistent node"); + } + + auto parent = removed_node->m_parent; + + if (parent) + { + for (auto i = 0u; i < parent->GetArgNumber(); i++) + { + auto child = parent->m_children[i]; + + if (child->GetId() == id) + { + parent->m_children[i] = nullptr; + } + } + } + + std::vector trees; + for (auto i = 0u; i < removed_node->GetArgNumber(); i++) + { + std::vector tree; + auto child = removed_node->GetChildren(i); + child->m_parent = nullptr; + + std::queue queue; + queue.push(child); + + while (!queue.empty()) + { + for (auto j = 0u; j < queue.front()->GetArgNumber(); j++) + { + queue.push(queue.front()->m_children[j]); + } + + m_nodes.erase(std::find(m_nodes.begin(), m_nodes.end(), queue.front())); + tree.push_back(queue.front()); + queue.pop(); + } + + trees.push_back(std::make_shared(UberTree(tree))); + } + + return trees; +} + +bool UberTree::IsValid() const +{ + for (const auto& node : m_nodes) + { + if (!node->IsValid()) + { + return false; + } + } + return true; +} + +UberNode::Ptr UberTree::Find(std::uint32_t id) +{ + for (auto node : m_nodes) + { + if (node->GetId() == id) + { + return node; + } + } + + return nullptr; +} + +UberTree::UberTree(std::vector nodes) + : m_nodes(nodes) {} + +UberTree::UberTree(InputMap::Ptr input_map) +{ + BuildTree(input_map); +} + +namespace { + struct UberTreeConcrete: public UberTree + { + UberTreeConcrete(InputMap::Ptr node) + : UberTree(node) + { } + }; +} + +UberTree::Ptr UberTree::Create(InputMap::Ptr input_map) +{ + return std::make_shared(input_map); +} + +//////////////////////////////////////////// +//// UberTreeIterator implementation +//////////////////////////////////////////// + +UberTreeIterator::UberTreeIterator(UberTree::Ptr tree) : m_tree(tree) +{ + if (m_tree && (m_tree->m_nodes.size() > 0)) + { + m_queue.push(std::pair(0, m_tree->m_nodes[0])); + } +} + +bool UberTreeIterator::IsValid() const +{ + if (!m_tree) + { + return false; + } + + return !m_queue.empty(); +} + +UberNode::Ptr UberTreeIterator::Item() const +{ + return m_queue.front().second; +} + +int UberTreeIterator::GetLevel() const +{ + return m_queue.front().first; +} + +void UberTreeIterator::Reset() +{ + // clear queue + while (!m_queue.empty()) + { + m_queue.pop(); + } +} + +void UberTreeIterator::Next() +{ + int level = m_queue.front().first; + auto node = m_queue.front().second; + + for (auto i = 0u; i < node->GetArgNumber(); i++) + { + m_queue.push( + std::pair + (level + 1, node->GetChildren(i))); + } + + m_queue.pop(); +} + +namespace { + struct UberTreeIteratorConcrete : public UberTreeIterator + { + UberTreeIteratorConcrete(UberTree::Ptr tree) + : UberTreeIterator(tree) {} + }; +} + +UberTreeIterator::Ptr UberTreeIterator::Create(UberTree::Ptr tree) +{ + return std::make_shared(tree); +} \ No newline at end of file diff --git a/BaikalStandalone/Application/uber_tree.h b/BaikalStandalone/Application/uber_tree.h new file mode 100644 index 00000000..9ee0e26a --- /dev/null +++ b/BaikalStandalone/Application/uber_tree.h @@ -0,0 +1,91 @@ + +/********************************************************************** + Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ + +#pragma once + +#include +#include +#include "uber_node.h" +#include "SceneGraph/iterator.h" + +class UberTreeIterator; + +class UberTree +{ + friend class UberTreeIterator; + +public: + using Ptr = std::shared_ptr; + using InputMap = UberNode::InputMap; + + static Ptr Create(InputMap::Ptr input_map); + + // 'id' is an id ofthe node to add subtree ('node' or 'tree' arg) + // 'arg_number' is a number of the argument in + // parent node (id of this node is argument "id") which will be set + // this methods garanty adding items in Ubertree model, + // and only if input value and tree itself are valid than update baikal material + // Note: 'tree' arg will be nullptr if adding was successful + bool AddTree(std::uint32_t id, std::uint32_t arg_number, UberTree::Ptr tree); + + bool IsValid() const; + + UberNode::Ptr Find(std::uint32_t id); + + // returns vector of the new trees (primary tree not included) + std::vector ExcludeNode(std::uint32_t id); + +protected: + + UberTree(InputMap::Ptr input_map); + UberTree(std::vector nodes); + +private: + void BuildTree(InputMap::Ptr input_map); + + std::vector m_nodes; +}; + +class UberTreeIterator +{ +public: + using Ptr = std::shared_ptr; + + static Ptr Create(UberTree::Ptr tree); + + // operations + bool IsValid() const; + void Next(); + UberNode::Ptr Item() const; + void Reset(); + + // accessor + int GetLevel() const; + +protected: + UberTreeIterator(UberTree::Ptr tree); + +private: + UberTree::Ptr m_tree; + std::queue> m_queue; +}; \ No newline at end of file diff --git a/BaikalStandalone/CMakeLists.txt b/BaikalStandalone/CMakeLists.txt new file mode 100644 index 00000000..3b78d103 --- /dev/null +++ b/BaikalStandalone/CMakeLists.txt @@ -0,0 +1,105 @@ +set(APPLICATION_SOURCES + Application/application.cpp + Application/application.h + Application/app_utils.cpp + Application/app_utils.h + Application/cl_render.cpp + Application/cl_render.h + Application/gl_render.cpp + Application/gl_render.h + Application/uber_node.h + Application/uber_node.cpp + Application/uber_tree.h + Application/uber_tree.cpp + Application/graph_scheme.h + Application/graph_scheme.cpp + Application/material_explorer.h + Application/material_explorer.cpp + Application/scene_load_utils.h + Application/scene_load_utils.cpp) + +set(IMGUI_SORUCES + ImGUI/imconfig.h + ImGUI/imgui.cpp + ImGUI/imgui.h + ImGUI/imgui_demo.cpp + ImGUI/imgui_draw.cpp + ImGUI/imgui_impl_glfw_gl3.cpp + ImGUI/imgui_impl_glfw_gl3.h + ImGUI/imgui_internal.h + ImGUI/stb_rect_pack.h + ImGUI/stb_textedit.h + ImGUI/stb_truetype.h) + +set(MAIN_SOURCES + main.cpp) + +set(UTILS_SOURCES + Utils/config_manager.cpp + Utils/config_manager.h + Utils/shader_manager.cpp + Utils/shader_manager.h) + +set(KERNEL_SOURCES + Kernels/GLSL/simple.fsh + Kernels/GLSL/simple.vsh) + +set(SOURCES + ${APPLICATION_SOURCES} + ${IMGUI_SORUCES} + ${MAIN_SOURCES} + ${UTILS_SOURCES} + ${KERNEL_SOURCES}) + +source_group("Application" FILES ${APPLICATION_SOURCES}) +source_group("ImGUI" FILES ${IMGUI_SORUCES}) +source_group("Utils" FILES ${UTILS_SOURCES}) +source_group("Kernels\\GLSL" FILES ${KERNEL_SOURCES}) + +add_executable(BaikalStandalone ${SOURCES}) +target_compile_features(BaikalStandalone PRIVATE cxx_std_14) + +#Add project root since BaikalStandalone directly includes Baikal/* files +target_include_directories(BaikalStandalone + PRIVATE ${Baikal_SOURCE_DIR} + PRIVATE .) + +target_link_libraries(BaikalStandalone PRIVATE Baikal BaikalIO glfw3::glfw3 OpenGL::GL GLEW::GLEW) + +# Compile definitions +if (BAIKAL_ENABLE_DENOISER) + target_compile_definitions(BaikalStandalone PUBLIC ENABLE_DENOISER) +endif(BAIKAL_ENABLE_DENOISER) + +if (BAIKAL_ENABLE_GLTF) + target_link_libraries(BaikalStandalone PRIVATE RadeonProRender RprSupport) +endif (BAIKAL_ENABLE_GLTF) + +if (BAIKAL_ENABLE_DATAGENERATOR) + target_compile_definitions(BaikalStandalone PUBLIC GENERATE_DATASET) +endif (BAIKAL_ENABLE_DATAGENERATOR) + +set_target_properties(BaikalStandalone + PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${Baikal_SOURCE_DIR}/BaikalStandalone FOLDER Baikal) + +# Add symbolic link from binary to BaikalStandalone/Kernels directory +set(BAIKALSTANDALONE_KERNELS_DIR BaikalStandalone/Kernels) +file(TO_NATIVE_PATH ${Baikal_SOURCE_DIR}/${BAIKALSTANDALONE_KERNELS_DIR} BAIKALSTANDALONE_KERNELS_SRC) +file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR}/${BAIKALSTANDALONE_KERNELS_DIR} BAIKALSTANDALONE_KERNELS_DST) + +if (WIN32) + add_custom_target(BaikalStandaloneKernelsDir ALL + COMMAND IF NOT EXIST ${BAIKALSTANDALONE_KERNELS_DST} mklink /D ${BAIKALSTANDALONE_KERNELS_DST} ${BAIKALSTANDALONE_KERNELS_SRC} + ) +else () + add_custom_target(BaikalStandaloneKernelsDir ALL + COMMAND ${CMAKE_COMMAND} -E create_symlink ${BAIKALSTANDALONE_KERNELS_SRC} ${BAIKALSTANDALONE_KERNELS_DST} + ) +endif () + +add_dependencies(BaikalStandalone BaikalStandaloneKernelsDir ResourcesDir Copy3rdParty) + +# Install target +install(TARGETS BaikalStandalone RUNTIME DESTINATION bin) +file(TO_CMAKE_PATH ${BAIKALSTANDALONE_KERNELS_SRC} BAIKALSTANDALONE_KERNELS_SRC_CMAKE) +install(DIRECTORY ${BAIKALSTANDALONE_KERNELS_SRC_CMAKE} DESTINATION BaikalStandalone) diff --git a/BaikalStandalone/ImGUI/imconfig.h b/BaikalStandalone/ImGUI/imconfig.h new file mode 100644 index 00000000..50b7f471 --- /dev/null +++ b/BaikalStandalone/ImGUI/imconfig.h @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------------- +// COMPILE-TIME OPTIONS FOR DEAR IMGUI +// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure. +// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions. +//----------------------------------------------------------------------------- +// A) You may edit imconfig.h (and not overwrite it when updating imgui, or maintain a patch/branch with your modifications to imconfig.h) +// B) or add configuration directives in your own file and compile with #define IMGUI_USER_CONFIG "myfilename.h" +// If you do so you need to make sure that configuration settings are defined consistently _everywhere_ dear imgui is used, which include +// the imgui*.cpp files but also _any_ of your code that uses imgui. This is because some compile-time options have an affect on data structures. +// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. +// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using. +//----------------------------------------------------------------------------- + +#pragma once + +//---- Define assertion handler. Defaults to calling assert(). +//#define IM_ASSERT(_EXPR) MyAssert(_EXPR) +//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts + +//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows. +//#define IMGUI_API __declspec( dllexport ) +//#define IMGUI_API __declspec( dllimport ) + +//---- Don't define obsolete functions/enums names. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names. +//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS + +//---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty) +//---- It is very strongly recommended to NOT disable the demo windows during development. Please read the comments in imgui_demo.cpp. +//#define IMGUI_DISABLE_DEMO_WINDOWS + +//---- Don't implement some functions to reduce linkage requirements. +//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. +//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow. +//#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself if you don't want to link with vsnprintf. +//#define IMGUI_DISABLE_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 wrapper so you can implement them yourself. Declare your prototypes in imconfig.h. +//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). + +//---- Include imgui_user.h at the end of imgui.h as a convenience +//#define IMGUI_INCLUDE_IMGUI_USER_H + +//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another) +//#define IMGUI_USE_BGRA_PACKED_COLOR + +//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version +// By default the embedded implementations are declared static and not available outside of imgui cpp files. +//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" +//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" +//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION +//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION + +//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. +// This will be inlined as part of ImVec2 and ImVec4 class declarations. +/* +#define IM_VEC2_CLASS_EXTRA \ + ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ + operator MyVec2() const { return MyVec2(x,y); } + +#define IM_VEC4_CLASS_EXTRA \ + ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ + operator MyVec4() const { return MyVec4(x,y,z,w); } +*/ + +//---- Use 32-bit vertex indices (default is 16-bit) to allow meshes with more than 64K vertices. Render function needs to support it. +//#define ImDrawIdx unsigned int + +//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. +/* +namespace ImGui +{ + void MyFunction(const char* name, const MyMatrix44& v); +} +*/ diff --git a/BaikalStandalone/ImGUI/imgui.cpp b/BaikalStandalone/ImGUI/imgui.cpp new file mode 100644 index 00000000..7a02ed64 --- /dev/null +++ b/BaikalStandalone/ImGUI/imgui.cpp @@ -0,0 +1,14260 @@ +// dear imgui, v1.63 WIP +// (main code and documentation) + +// Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. +// Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase. +// Get latest version at https://github.com/ocornut/imgui +// Releases change-log at https://github.com/ocornut/imgui/releases +// Technical Support for Getting Started https://discourse.dearimgui.org/c/getting-started +// Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/1269 +// Developed by Omar Cornut and every direct or indirect contributors to the GitHub. +// This library is free but I need your support to sustain development and maintenance. +// If you work for a company, please consider financial support, see README. For individuals: https://www.patreon.com/imgui + +// It is recommended that you don't modify imgui.cpp! It will become difficult for you to update the library. +// Note that 'ImGui::' being a namespace, you can add functions into the namespace from your own source files, without +// modifying imgui.h or imgui.cpp. You may include imgui_internal.h to access internal data structures, but it doesn't +// come with any guarantee of forward compatibility. Discussing your changes on the GitHub Issue Tracker may lead you +// to a better solution or official support for them. + +/* + + Index + - MISSION STATEMENT + - END-USER GUIDE + - PROGRAMMER GUIDE (read me!) + - Read first + - How to update to a newer version of Dear ImGui + - Getting started with integrating Dear ImGui in your code/engine + - Using gamepad/keyboard navigation controls [BETA] + - API BREAKING CHANGES (read me when you update!) + - ISSUES & TODO LIST + - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS + - How can I tell whether to dispatch mouse/keyboard to imgui or to my application? + - How can I display an image? What is ImTextureID, how does it works? + - How can I have multiple widgets with the same label or without a label? A primer on labels and the ID Stack. + - How can I use my own math types instead of ImVec2/ImVec4? + - How can I load a different font than the default? + - How can I easily use icons in my application? + - How can I load multiple fonts? + - How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic? + - How can I use the drawing facilities without an ImGui window? (using ImDrawList API) + - I integrated Dear ImGui in my engine and the text or lines are blurry.. + - I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. + - How can I help? + - ISSUES & TODO-LIST + - CODE + + + MISSION STATEMENT + ================= + + - Easy to use to create code-driven and data-driven tools + - Easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools + - Easy to hack and improve + - Minimize screen real-estate usage + - Minimize setup and maintenance + - Minimize state storage on user side + - Portable, minimize dependencies, run on target (consoles, phones, etc.) + - Efficient runtime and memory consumption (NB- we do allocate when "growing" content e.g. creating a window, + opening a tree node for the first time, etc. but a typical frame should not allocate anything) + + Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes: + - Doesn't look fancy, doesn't animate + - Limited layout features, intricate layouts are typically crafted in code + + + END-USER GUIDE + ============== + + - Double-click on title bar to collapse window. + - Click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin(). + - Click and drag on lower right corner to resize window (double-click to auto fit window to its contents). + - Click and drag on any empty space to move window. + - TAB/SHIFT+TAB to cycle through keyboard editable fields. + - CTRL+Click on a slider or drag box to input value as text. + - Use mouse wheel to scroll. + - Text editor: + - Hold SHIFT or use mouse to select text. + - CTRL+Left/Right to word jump. + - CTRL+Shift+Left/Right to select words. + - CTRL+A our Double-Click to select all. + - CTRL+X,CTRL+C,CTRL+V to use OS clipboard/ + - CTRL+Z,CTRL+Y to undo/redo. + - ESCAPE to revert text to its original value. + - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!) + - Controls are automatically adjusted for OSX to match standard OSX text editing operations. + - General Keyboard controls: enable with ImGuiConfigFlags_NavEnableKeyboard. + - General Gamepad controls: enable with ImGuiConfigFlags_NavEnableGamepad. See suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at http://goo.gl/9LgVZW + + + PROGRAMMER GUIDE + ================ + + READ FIRST + + - Read the FAQ below this section! + - Your code creates the UI, if your code doesn't run the UI is gone! The UI can be highly dynamic, there are no construction + or destruction steps, less data retention on your side, less state duplication, less state synchronization, less bugs. + - Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features. + - You can learn about immediate-mode gui principles at http://www.johno.se/book/imgui.html or watch http://mollyrocket.com/861 + + HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI + + - Overwrite all the sources files except for imconfig.h (if you have made modification to your copy of imconfig.h) + - Read the "API BREAKING CHANGES" section (below). This is where we list occasional API breaking changes. + If a function/type has been renamed / or marked obsolete, try to fix the name in your code before it is permanently removed + from the public API. If you have a problem with a missing function/symbols, search for its name in the code, there will + likely be a comment about it. Please report any issue to the GitHub page! + - Try to keep your copy of dear imgui reasonably up to date. + + GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE + + - Run and study the examples and demo to get acquainted with the library. + - Add the Dear ImGui source files to your projects or using your preferred build system. + It is recommended you build the .cpp files as part of your project and not as a library. + - You can later customize the imconfig.h file to tweak some compilation time behavior, such as integrating imgui types with your own maths types. + - You may be able to grab and copy a ready made imgui_impl_*** file from the examples/ folder. + - When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them. + - Dear ImGui never touches or knows about your GPU state. The only function that knows about GPU is the draw function that you provide. + Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" + phases of your own application. All rendering informatioe are stored into command-lists that you will retrieve after calling ImGui::Render(). + - Refer to the bindings and demo applications in the examples/ folder for instruction on how to setup your code. + + THIS IS HOW A SIMPLE APPLICATION MAY LOOK LIKE + EXHIBIT 1: USING THE EXAMPLE BINDINGS (imgui_impl_XXX.cpp files from the examples/ folder) + + // Application init: create a dear imgui context, setup some options, load fonts + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + // TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls + // TODO: Fill optional settings of the io structure later. + // TODO: Load TTF/OTF fonts if you don't want to use the default font. + + // Initialize helper Platform and Renderer bindings (here we are using imgui_impl_win32 and imgui_impl_dx11) + ImGui_ImplWin32_Init(hwnd); + ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext); + + // Application main loop + while (true) + { + // Feed inputs to dear imgui, start new frame + ImGui_ImplDX11_NewFrame(); + ImGui_ImplWin32_NewFrame(); + ImGui::NewFrame(); + + // Any application code here + ImGui::Text("Hello, world!"); + + // Render dear imgui into screen + ImGui::Render(); + ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + g_pSwapChain->Present(1, 0); + } + + // Shutdown + ImGui_ImplDX11_Shutdown(); + ImGui_ImplWin32_Shutdown(); + ImGui::DestroyContext(); + + THIS IS HOW A SIMPLE APPLICATION MAY LOOK LIKE + EXHIBIT 2: IMPLEMENTING CUSTOM BINDING / CUSTOM ENGINE + + // Application init: create a dear imgui context, setup some options, load fonts + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + // TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls + // TODO: Fill optional settings of the io structure later. + // TODO: Load TTF/OTF fonts if you don't want to use the default font. + + // Build and load the texture atlas into a texture + // (In the examples/ app this is usually done within the ImGui_ImplXXX_Init() function from one of the demo Renderer) + int width, height; + unsigned char* pixels = NULL; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + + // At this point you've got the texture data and you need to upload that your your graphic system: + // After we have created the texture, store its pointer/identifier (_in whichever format your engine uses_) in 'io.Fonts->TexID'. + // This will be passed back to your via the renderer. Basically ImTextureID == void*. Read FAQ below for details about ImTextureID. + MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA32) + io.Fonts->TexID = (void*)texture; + + // Application main loop + while (true) + { + // Setup low-level inputs, e.g. on Win32: calling GetKeyboardState(), or write to those fields from your Windows message handlers, etc. + // (In the examples/ app this is usually done within the ImGui_ImplXXX_NewFrame() function from one of the demo Platform bindings) + io.DeltaTime = 1.0f/60.0f; // set the time elapsed since the previous frame (in seconds) + io.DisplaySize.x = 1920.0f; // set the current display width + io.DisplaySize.y = 1280.0f; // set the current display height here + io.MousePos = my_mouse_pos; // set the mouse position + io.MouseDown[0] = my_mouse_buttons[0]; // set the mouse button states + io.MouseDown[1] = my_mouse_buttons[1]; + + // Call NewFrame(), after this point you can use ImGui::* functions anytime + // (So you want to try calling NewFrame() as early as you can in your mainloop to be able to use imgui everywhere) + ImGui::NewFrame(); + + // Most of your application code here + ImGui::Text("Hello, world!"); + MyGameUpdate(); // may use any ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End(); + MyGameRender(); // may use any ImGui functions as well! + + // Render imgui, swap buffers + // (You want to try calling EndFrame/Render as late as you can, to be able to use imgui in your own game rendering code) + ImGui::EndFrame(); + ImGui::Render(); + ImDrawData* draw_data = ImGui::GetDrawData(); + MyImGuiRenderFunction(draw_data); + SwapBuffers(); + } + + // Shutdown + ImGui::DestroyContext(); + + THIS HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE + + void void MyImGuiRenderFunction(ImDrawData* draw_data) + { + // TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + // TODO: Setup viewport using draw_data->DisplaySize + // TODO: Setup orthographic projection matrix cover draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize + // TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragment shader sample color from 1 texture, multiply by vertex color. + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; // vertex buffer generated by ImGui + const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; // index buffer generated by ImGui + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + // The texture for the draw call is specified by pcmd->TextureId. + // The vast majority of draw calls with use the imgui texture atlas, which value you have set yourself during initialization. + MyEngineBindTexture(pcmd->TextureId); + + // We are using scissoring to clip some objects. All low-level graphics API should supports it. + // - If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches + // (some elements visible outside their bounds) but you can fix that once everywhere else works! + // - Clipping coordinates are provided in imgui coordinates space (from draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize) + // In a single viewport application, draw_data->DisplayPos will always be (0,0) and draw_data->DisplaySize will always be == io.DisplaySize. + // However, in the interest of supporting multi-viewport applications in the future, always subtract draw_data->DisplayPos from + // clipping bounds to convert them to your viewport space. + // - Note that pcmd->ClipRect contains Min+Max bounds. Some graphics API may use Min+Max, other may use Min+Size (size being Max-Min) + ImVec2 pos = draw_data->DisplayPos; + MyEngineScissor((int)(pcmd->ClipRect.x - pos.x), (int)(pcmd->ClipRect.y - pos.y), (int)(pcmd->ClipRect.z - pos.x), (int)(pcmd->ClipRect.w - pos.y)); + + // Render 'pcmd->ElemCount/3' indexed triangles. + // By default the indices ImDrawIdx are 16-bits, you can change them to 32-bits if your engine doesn't support 16-bits indices. + MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer, vtx_buffer); + } + idx_buffer += pcmd->ElemCount; + } + } + } + + - The examples/ folders contains many functional implementation of the pseudo-code above. + - When calling NewFrame(), the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags are updated. + They tell you if ImGui intends to use your inputs. When a flag is set you want to hide the corresponding inputs from the rest of your application. + In both cases you need to pass on the inputs to imgui. Read the FAQ below for more information about those flags. + - Please read the FAQ above. Amusingly, it is called a FAQ because people frequently have the same issues! + + USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS [BETA] + + - The gamepad/keyboard navigation is in Beta. Ask questions and report issues at https://github.com/ocornut/imgui/issues/787 + - The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable. + - Gamepad: + - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. + - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame(). + Note that io.NavInputs[] is cleared by EndFrame(). + - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. For each entry of io.NavInputs[], set the following values: + 0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks. + - We uses a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone. + Your code will probably need to transform your raw inputs (such as e.g. remapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, etc.). + - You can download PNG/PSD files depicting the gamepad controls for common controllers at: goo.gl/9LgVZW. + - If you need to share inputs between your game and the imgui parts, the easiest approach is to go all-or-nothing, with a buttons combo + to toggle the target. Please reach out if you think the game vs navigation input sharing could be improved. + - Keyboard: + - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. + NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays. + - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag + will be set. For more advanced uses, you may want to read from: + - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. + - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used). + - or query focus information with e.g. IsWindowFocused(ImGuiFocusedFlags_AnyWindow), IsItemFocused() etc. functions. + Please reach out if you think the game vs navigation input sharing could be improved. + - Mouse: + - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. + - Consoles/Tablet/Phone users: Consider using a Synergy 1.x server (on your PC) + uSynergy.c (on your console/tablet/phone app) to share your PC mouse/keyboard. + - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiConfigFlags_NavEnableSetMousePos flag. + Enabling ImGuiConfigFlags_NavEnableSetMousePos + ImGuiBackendFlags_HasSetMousePos instructs dear imgui to move your mouse cursor along with navigation movements. + When enabled, the NewFrame() function may alter 'io.MousePos' and set 'io.WantSetMousePos' to notify you that it wants the mouse cursor to be moved. + When that happens your back-end NEEDS to move the OS or underlying mouse cursor on the next frame. Some of the binding in examples/ do that. + (If you set the NavEnableSetMousePos flag but don't honor 'io.WantSetMousePos' properly, imgui will misbehave as it will see your mouse as moving back and forth!) + (In a setup when you may not have easy control over the mouse cursor, e.g. uSynergy.c doesn't expose moving remote mouse cursor, you may want + to set a boolean to ignore your other external mouse positions until the external source is moved again.) + + + API BREAKING CHANGES + ==================== + + Occasionally introducing changes that are breaking the API. We try to make the breakage minor and easy to fix. + Below is a change-log of API breaking changes only. If you are using one of the functions listed, expect to have to fix some code. + When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. + You can read releases logs https://github.com/ocornut/imgui/releases for more details. + + - 2018/08/01 (1.63) - removed per-window ImGuiWindowFlags_ResizeFromAnySide beta flag in favor of a global io.ConfigResizeWindowsFromEdges to enable the feature. + - 2018/08/01 (1.63) - renamed io.OptCursorBlink to io.ConfigCursorBlink, io.OptMacOSXBehaviors to ConfigMacOSXBehaviors for consistency. + - 2018/07/22 (1.63) - changed ImGui::GetTime() return value from float to double to avoid accumulating floating point imprecisions over time. + - 2018/07/08 (1.63) - style: renamed ImGuiCol_ModalWindowDarkening to ImGuiCol_ModalWindowDimBg for consistency with other features. Kept redirection enum (will obsolete). + - 2018/06/06 (1.62) - renamed GetGlyphRangesChinese() to GetGlyphRangesChineseFull() to distinguish other variants and discourage using the full set. + - 2018/06/06 (1.62) - TreeNodeEx()/TreeNodeBehavior(): the ImGuiTreeNodeFlags_CollapsingHeader helper now include the ImGuiTreeNodeFlags_NoTreePushOnOpen flag. See Changelog for details. + - 2018/05/03 (1.61) - DragInt(): the default compile-time format string has been changed from "%.0f" to "%d", as we are not using integers internally any more. + If you used DragInt() with custom format strings, make sure you change them to use %d or an integer-compatible format. + To honor backward-compatibility, the DragInt() code will currently parse and modify format strings to replace %*f with %d, giving time to users to upgrade their code. + If you have IMGUI_DISABLE_OBSOLETE_FUNCTIONS enabled, the code will instead assert! You may run a reg-exp search on your codebase for e.g. "DragInt.*%f" to help you find them. + - 2018/04/28 (1.61) - obsoleted InputFloat() functions taking an optional "int decimal_precision" in favor of an equivalent and more flexible "const char* format", + consistent with other functions. Kept redirection functions (will obsolete). + - 2018/04/09 (1.61) - IM_DELETE() helper function added in 1.60 doesn't clear the input _pointer_ reference, more consistent with expectation and allows passing r-value. + - 2018/03/20 (1.60) - renamed io.WantMoveMouse to io.WantSetMousePos for consistency and ease of understanding (was added in 1.52, _not_ used by core and only honored by some binding ahead of merging the Nav branch). + - 2018/03/12 (1.60) - removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered as the closing cross uses regular button colors now. + - 2018/03/08 (1.60) - changed ImFont::DisplayOffset.y to default to 0 instead of +1. Fixed rounding of Ascent/Descent to match TrueType renderer. If you were adding or subtracting to ImFont::DisplayOffset check if your fonts are correctly aligned vertically. + - 2018/03/03 (1.60) - renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums. + - 2018/02/18 (1.60) - BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is not really usable in many situations at the moment. + - 2018/02/16 (1.60) - obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). Use ImGui::GetDrawData() to retrieve the ImDrawData* to display. + - 2018/02/07 (1.60) - reorganized context handling to be more explicit, + - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. + - removed Shutdown() function, as DestroyContext() serve this purpose. + - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwise CreateContext() will create its own font atlas instance. + - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts. + - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts. + - 2018/01/31 (1.60) - moved sample TTF files from extra_fonts/ to misc/fonts/. If you loaded files directly from the imgui repo you may need to update your paths. + - 2018/01/11 (1.60) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete). + - 2018/01/11 (1.60) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete). + - 2018/01/03 (1.60) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. + - 2017/12/29 (1.60) - removed CalcItemRectClosestPoint() which was weird and not really used by anyone except demo code. If you need it it's easy to replicate on your side. + - 2017/12/24 (1.53) - renamed the emblematic ShowTestWindow() function to ShowDemoWindow(). Kept redirection function (will obsolete). + - 2017/12/21 (1.53) - ImDrawList: renamed style.AntiAliasedShapes to style.AntiAliasedFill for consistency and as a way to explicitly break code that manipulate those flag at runtime. You can now manipulate ImDrawList::Flags + - 2017/12/21 (1.53) - ImDrawList: removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Prefer manipulating ImDrawList::Flags if you need to toggle them during the frame. + - 2017/12/14 (1.53) - using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set. + - 2017/12/13 (1.53) - renamed GetItemsLineHeightWithSpacing() to GetFrameHeightWithSpacing(). Kept redirection function (will obsolete). + - 2017/12/13 (1.53) - obsoleted IsRootWindowFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Kept redirection function (will obsolete). + - obsoleted IsRootWindowOrAnyChildFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows). Kept redirection function (will obsolete). + - 2017/12/12 (1.53) - renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. Kept redirection enum (will obsolete). + - 2017/12/10 (1.53) - removed SetNextWindowContentWidth(), prefer using SetNextWindowContentSize(). Kept redirection function (will obsolete). + - 2017/11/27 (1.53) - renamed ImGuiTextBuffer::append() helper to appendf(), appendv() to appendfv(). If you copied the 'Log' demo in your code, it uses appendv() so that needs to be renamed. + - 2017/11/18 (1.53) - Style, Begin: removed ImGuiWindowFlags_ShowBorders window flag. Borders are now fully set up in the ImGuiStyle structure (see e.g. style.FrameBorderSize, style.WindowBorderSize). Use ImGui::ShowStyleEditor() to look them up. + Please note that the style system will keep evolving (hopefully stabilizing in Q1 2018), and so custom styles will probably subtly break over time. It is recommended you use the StyleColorsClassic(), StyleColorsDark(), StyleColorsLight() functions. + - 2017/11/18 (1.53) - Style: removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency. + - 2017/11/18 (1.53) - Style: renamed ImGuiCol_ChildWindowBg to ImGuiCol_ChildBg. + - 2017/11/18 (1.53) - Style: renamed style.ChildWindowRounding to style.ChildRounding, ImGuiStyleVar_ChildWindowRounding to ImGuiStyleVar_ChildRounding. + - 2017/11/02 (1.53) - obsoleted IsRootWindowOrAnyChildHovered() in favor of using IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); + - 2017/10/24 (1.52) - renamed IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS to IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS for consistency. + - 2017/10/20 (1.52) - changed IsWindowHovered() default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it. + - 2017/10/20 (1.52) - marked IsItemHoveredRect()/IsMouseHoveringWindow() as obsolete, in favor of using the newly introduced flags for IsItemHovered() and IsWindowHovered(). See https://github.com/ocornut/imgui/issues/1382 for details. + removed the IsItemRectHovered()/IsWindowRectHovered() names introduced in 1.51 since they were merely more consistent names for the two functions we are now obsoleting. + - 2017/10/17 (1.52) - marked the old 5-parameters version of Begin() as obsolete (still available). Use SetNextWindowSize()+Begin() instead! + - 2017/10/11 (1.52) - renamed AlignFirstTextHeightToWidgets() to AlignTextToFramePadding(). Kept inline redirection function (will obsolete). + - 2017/09/25 (1.52) - removed SetNextWindowPosCenter() because SetNextWindowPos() now has the optional pivot information to do the same and more. Kept redirection function (will obsolete). + - 2017/08/25 (1.52) - io.MousePos needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing. Previously ImVec2(-1,-1) was enough but we now accept negative mouse coordinates. In your binding if you need to support unavailable mouse, make sure to replace "io.MousePos = ImVec2(-1,-1)" with "io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX)". + - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). -> (1.52) use IsItemHovered(ImGuiHoveredFlags_RectOnly)! + - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete). + - renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete). + - 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency. + - 2017/08/20 (1.51) - added PushStyleColor(ImGuiCol idx, ImU32 col) overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix. + - 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame. + - 2017/08/15 (1.51) - changed parameter order for BeginPopupContextWindow() from (const char*,int buttons,bool also_over_items) to (const char*,int buttons,bool also_over_items). Note that most calls relied on default parameters completely. + - 2017/08/13 (1.51) - renamed ImGuiCol_Columns*** to ImGuiCol_Separator***. Kept redirection enums (will obsolete). + - 2017/08/11 (1.51) - renamed ImGuiSetCond_*** types and flags to ImGuiCond_***. Kept redirection enums (will obsolete). + - 2017/08/09 (1.51) - removed ValueColor() helpers, they are equivalent to calling Text(label) + SameLine() + ColorButton(). + - 2017/08/08 (1.51) - removed ColorEditMode() and ImGuiColorEditMode in favor of ImGuiColorEditFlags and parameters to the various Color*() functions. The SetColorEditOptions() allows to initialize default but the user can still change them with right-click context menu. + - changed prototype of 'ColorEdit4(const char* label, float col[4], bool show_alpha = true)' to 'ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0)', where passing flags = 0x01 is a safe no-op (hello dodgy backward compatibility!). - check and run the demo window, under "Color/Picker Widgets", to understand the various new options. + - changed prototype of rarely used 'ColorButton(ImVec4 col, bool small_height = false, bool outline_border = true)' to 'ColorButton(const char* desc_id, ImVec4 col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0,0))' + - 2017/07/20 (1.51) - removed IsPosHoveringAnyWindow(ImVec2), which was partly broken and misleading. ASSERT + redirect user to io.WantCaptureMouse + - 2017/05/26 (1.50) - removed ImFontConfig::MergeGlyphCenterV in favor of a more multipurpose ImFontConfig::GlyphOffset. + - 2017/05/01 (1.50) - renamed ImDrawList::PathFill() (rarely used directly) to ImDrawList::PathFillConvex() for clarity. + - 2016/11/06 (1.50) - BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple times to a same child from different locations of the stack id. If that's the case, generate an id with GetId() and use it instead of passing string to BeginChild(). + - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass io.ClipboardUserData to it. + - 2016/09/25 (1.50) - style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc. + - 2016/07/30 (1.50) - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully breakage should be minimal. + - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore. + If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you. + If your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar. + This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color. + ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col) + { + float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a; + return ImVec4((win_bg_col.x * win_bg_col.w + title_bg_col.x) * k, (win_bg_col.y * win_bg_col.w + title_bg_col.y) * k, (win_bg_col.z * win_bg_col.w + title_bg_col.z) * k, new_a); + } + If this is confusing, pick the RGB value from title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color. + - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext(). + - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection. + - 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the "default_open = true" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen). + - 2016/04/26 (1.49) - changed ImDrawList::PushClipRect(ImVec4 rect) to ImDrawList::PushClipRect(Imvec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false). Note that higher-level ImGui::PushClipRect() is preferable because it will clip at logic/widget level, whereas ImDrawList::PushClipRect() only affect your renderer. + - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337). + - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337) + - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete). + - 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert. + - 2016/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. if you had manual pixel-perfect alignment in place it might affect you. + - 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis. + - 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete. + - 2015/08/29 (1.45) - with the addition of horizontal scrollbar we made various fixes to inconsistencies with dealing with cursor position. + GetCursorPos()/SetCursorPos() functions now include the scrolled amount. It shouldn't affect the majority of users, but take note that SetCursorPosX(100.0f) puts you at +100 from the starting x position which may include scrolling, not at +100 from the window left side. + GetContentRegionMax()/GetWindowContentRegionMin()/GetWindowContentRegionMax() functions allow include the scrolled amount. Typically those were used in cases where no scrolling would happen so it may not be a problem, but watch out! + - 2015/08/29 (1.45) - renamed style.ScrollbarWidth to style.ScrollbarSize + - 2015/08/05 (1.44) - split imgui.cpp into extra files: imgui_demo.cpp imgui_draw.cpp imgui_internal.h that you need to add to your project. + - 2015/07/18 (1.44) - fixed angles in ImDrawList::PathArcTo(), PathArcToFast() (introduced in 1.43) being off by an extra PI for no justifiable reason + - 2015/07/14 (1.43) - add new ImFontAtlas::AddFont() API. For the old AddFont***, moved the 'font_no' parameter of ImFontAtlas::AddFont** functions to the ImFontConfig structure. + you need to render your textured triangles with bilinear filtering to benefit from sub-pixel positioning of text. + - 2015/07/08 (1.43) - switched rendering data to use indexed rendering. this is saving a fair amount of CPU/GPU and enables us to get anti-aliasing for a marginal cost. + this necessary change will break your rendering function! the fix should be very easy. sorry for that :( + - if you are using a vanilla copy of one of the imgui_impl_XXXX.cpp provided in the example, you just need to update your copy and you can ignore the rest. + - the signature of the io.RenderDrawListsFn handler has changed! + old: ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count) + new: ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data). + argument: 'cmd_lists' becomes 'draw_data->CmdLists', 'cmd_lists_count' becomes 'draw_data->CmdListsCount' + ImDrawList: 'commands' becomes 'CmdBuffer', 'vtx_buffer' becomes 'VtxBuffer', 'IdxBuffer' is new. + ImDrawCmd: 'vtx_count' becomes 'ElemCount', 'clip_rect' becomes 'ClipRect', 'user_callback' becomes 'UserCallback', 'texture_id' becomes 'TextureId'. + - each ImDrawList now contains both a vertex buffer and an index buffer. For each command, render ElemCount/3 triangles using indices from the index buffer. + - if you REALLY cannot render indexed primitives, you can call the draw_data->DeIndexAllBuffers() method to de-index the buffers. This is slow and a waste of CPU/GPU. Prefer using indexed rendering! + - refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. please upgrade! + - 2015/07/10 (1.43) - changed SameLine() parameters from int to float. + - 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete). + - 2015/07/02 (1.42) - renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion along with other scrolling functions, because positions (e.g. cursor position) are not equivalent to scrolling amount. + - 2015/06/14 (1.41) - changed ImageButton() default bg_col parameter from (0,0,0,1) (black) to (0,0,0,0) (transparent) - makes a difference when texture have transparence + - 2015/06/14 (1.41) - changed Selectable() API from (label, selected, size) to (label, selected, flags, size). Size override should have been rarely be used. Sorry! + - 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will obsolete). + - 2015/05/31 (1.40) - renamed IsRectClipped() to IsRectVisible() for consistency. Note that return value is opposite! Kept inline redirection function (will obsolete). + - 2015/05/27 (1.40) - removed the third 'repeat_if_held' parameter from Button() - sorry! it was rarely used and inconsistent. Use PushButtonRepeat(true) / PopButtonRepeat() to enable repeat on desired buttons. + - 2015/05/11 (1.40) - changed BeginPopup() API, takes a string identifier instead of a bool. ImGui needs to manage the open/closed state of popups. Call OpenPopup() to actually set the "open" state of a popup. BeginPopup() returns true if the popup is opened. + - 2015/05/03 (1.40) - removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same). + - 2015/04/13 (1.38) - renamed IsClipped() to IsRectClipped(). Kept inline redirection function until 1.50. + - 2015/04/09 (1.38) - renamed ImDrawList::AddArc() to ImDrawList::AddArcFast() for compatibility with future API + - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive. + - 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or Inputfloat() instead. + - 2015/03/17 (1.36) - renamed GetItemBoxMin()/GetItemBoxMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function until 1.50. + - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing + - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function until 1.50. + - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth (casing) + - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function until 1.50. + - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once. + - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now. + - 2015/02/10 (1.32) - renamed GetItemWidth() to CalcItemWidth() to clarify its evolving behavior + - 2015/02/08 (1.31) - renamed GetTextLineSpacing() to GetTextLineHeightWithSpacing() + - 2015/02/01 (1.31) - removed IO.MemReallocFn (unused) + - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions. + - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader. + (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels. + font init: const void* png_data; unsigned int png_size; ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); <..Upload texture to GPU..> + became: unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); <..Upload texture to GPU>; io.Fonts->TexId = YourTextureIdentifier; + you now more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs. + it is now recommended that you sample the font texture with bilinear interpolation. + (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID. + (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix) + (1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets + - 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, ImGuiSetCondition_FirstUseEver) + - 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, FontFallbackGlyph) + - 2014/11/26 (1.17) - reworked syntax of IMGUI_ONCE_UPON_A_FRAME helper macro to increase compiler compatibility + - 2014/11/07 (1.15) - renamed IsHovered() to IsItemHovered() + - 2014/10/02 (1.14) - renamed IMGUI_INCLUDE_IMGUI_USER_CPP to IMGUI_INCLUDE_IMGUI_USER_INL and imgui_user.cpp to imgui_user.inl (more IDE friendly) + - 2014/09/25 (1.13) - removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for simplicity) + - 2014/09/24 (1.12) - renamed SetFontScale() to SetWindowFontScale() + - 2014/09/24 (1.12) - moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn + - 2014/08/30 (1.09) - removed IO.FontHeight (now computed automatically) + - 2014/08/30 (1.09) - moved IMGUI_FONT_TEX_UV_FOR_WHITE preprocessor define to IO.FontTexUvForWhite + - 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes + + + ISSUES & TODO-LIST + ================== + See TODO.txt + + + FREQUENTLY ASKED QUESTIONS (FAQ), TIPS + ====================================== + + Q: How can I tell whether to dispatch mouse/keyboard to imgui or to my application? + A: You can read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags from the ImGuiIO structure (e.g. if (ImGui::GetIO().WantCaptureMouse) { ... } ) + - When 'io.WantCaptureMouse' is set, imgui wants to use your mouse state, and you may want to discard/hide the inputs from the rest of your application. + - When 'io.WantCaptureKeyboard' is set, imgui wants to use your keyboard state, and you may want to discard/hide the inputs from the rest of your application. + - When 'io.WantTextInput' is set to may want to notify your OS to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console OS). + Note: you should always pass your mouse/keyboard inputs to imgui, even when the io.WantCaptureXXX flag are set false. + This is because imgui needs to detect that you clicked in the void to unfocus its windows. + Note: The 'io.WantCaptureMouse' is more accurate that any attempt to "check if the mouse is hovering a window" (don't do that!). + It handle mouse dragging correctly (both dragging that started over your application or over an imgui window) and handle e.g. modal windows blocking inputs. + Those flags are updated by ImGui::NewFrame(). Preferably read the flags after calling NewFrame() if you can afford it, but reading them before is also + perfectly fine, as the bool toggle fairly rarely. If you have on a touch device, you might find use for an early call to UpdateHoveredWindowAndCaptureFlags(). + Note: Text input widget releases focus on "Return KeyDown", so the subsequent "Return KeyUp" event that your application receive will typically + have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs + were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.) + + Q: How can I display an image? What is ImTextureID, how does it works? + A: Short explanation: + - You may use functions such as ImGui::Image(), ImGui::ImageButton() or lower-level ImDrawList::AddImage() to emit draw calls that will use your own textures. + - Actual textures are identified in a way that is up to the user/engine. + - Loading image files from the disk and turning them into a texture is not within the scope of Dear ImGui (for a good reason). + Please read documentations or tutorials on your graphics API to understand how to display textures on the screen before moving onward. + + Long explanation: + - Dear ImGui's job is to create "meshes", defined in a renderer-agnostic format made of draw commands and vertices. + At the end of the frame those meshes (ImDrawList) will be displayed by your rendering function. They are made up of textured polygons and the code + to render them is generally fairly short (a few dozen lines). In the examples/ folder we provide functions for popular graphics API (OpenGL, DirectX, etc.). + - Each rendering function decides on a data type to represent "textures". The concept of what is a "texture" is entirely tied to your underlying engine/graphics API. + We carry the information to identify a "texture" in the ImTextureID type. + ImTextureID is nothing more that a void*, aka 4/8 bytes worth of data: just enough to store 1 pointer or 1 integer of your choice. + Dear ImGui doesn't know or understand what you are storing in ImTextureID, it merely pass ImTextureID values until they reach your rendering function. + - In the examples/ bindings, for each graphics API binding we decided on a type that is likely to be a good representation for specifying + an image from the end-user perspective. This is what the _examples_ rendering functions are using: + + OpenGL: ImTextureID = GLuint (see ImGui_ImplGlfwGL3_RenderDrawData() function in imgui_impl_glfw_gl3.cpp) + DirectX9: ImTextureID = LPDIRECT3DTEXTURE9 (see ImGui_ImplDX9_RenderDrawData() function in imgui_impl_dx9.cpp) + DirectX11: ImTextureID = ID3D11ShaderResourceView* (see ImGui_ImplDX11_RenderDrawData() function in imgui_impl_dx11.cpp) + DirectX12: ImTextureID = D3D12_GPU_DESCRIPTOR_HANDLE (see ImGui_ImplDX12_RenderDrawData() function in imgui_impl_dx12.cpp) + + For example, in the OpenGL example binding we store raw OpenGL texture identifier (GLuint) inside ImTextureID. + Whereas in the DirectX11 example binding we store a pointer to ID3D11ShaderResourceView inside ImTextureID, which is a higher-level structure + tying together both the texture and information about its format and how to read it. + - If you have a custom engine built over e.g. OpenGL, instead of passing GLuint around you may decide to use a high-level data type to carry information about + the texture as well as how to display it (shaders, etc.). The decision of what to use as ImTextureID can always be made better knowing how your codebase + is designed. If your engine has high-level data types for "textures" and "material" then you may want to use them. + If you are starting with OpenGL or DirectX or Vulkan and haven't built much of a rendering engine over them, keeping the default ImTextureID + representation suggested by the example bindings is probably the best choice. + (Advanced users may also decide to keep a low-level type in ImTextureID, and use ImDrawList callback and pass information to their renderer) + + User code may do: + + // Cast our texture type to ImTextureID / void* + MyTexture* texture = g_CoffeeTableTexture; + ImGui::Image((void*)texture, ImVec2(texture->Width, texture->Height)); + + The renderer function called after ImGui::Render() will receive that same value that the user code passed: + + // Cast ImTextureID / void* stored in the draw command as our texture type + MyTexture* texture = (MyTexture*)pcmd->TextureId; + MyEngineBindTexture2D(texture); + + Once you understand this design you will understand that loading image files and turning them into displayable textures is not within the scope of Dear ImGui. + This is by design and is actually a good thing, because it means your code has full control over your data types and how you display them. + If you want to display an image file (e.g. PNG file) into the screen, please refer to documentation and tutorials for the graphics API you are using. + + Here's a simplified OpenGL example using stb_image.h: + + // Use stb_image.h to load a PNG from disk and turn it into raw RGBA pixel data: + #define STB_IMAGE_IMPLEMENTATION + #include + [...] + int my_image_width, my_image_height; + unsigned char* my_image_data = stbi_load("my_image.png", &my_image_width, &my_image_height, NULL, 4); + + // Turn the RGBA pixel data into an OpenGL texture: + GLuint my_opengl_texture; + glGenTextures(1, &my_opengl_texture); + glBindTexture(GL_TEXTURE_2D, my_opengl_texture); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); + + // Now that we have an OpenGL texture, assuming our imgui rendering function (imgui_impl_xxx.cpp file) takes GLuint as ImTextureID, we can display it: + ImGui::Image((void*)(intptr_t)my_opengl_texture, ImVec2(my_image_width, my_image_height)); + + C/C++ tip: a void* is pointer-sized storage. You may safely store any pointer or integer into it by casting your value to ImTexture / void*, and vice-versa. + Because both end-points (user code and rendering function) are under your control, you know exactly what is stored inside the ImTexture / void*. + Examples: + + GLuint my_tex = XXX; + void* my_void_ptr; + my_void_ptr = (void*)(intptr_t)my_tex; // cast a GLuint into a void* (we don't take its address! we literally store the value inside the pointer) + my_tex = (GLuint)(intptr_t)my_void_ptr; // cast a void* into a GLuint + + ID3D11ShaderResourceView* my_dx11_srv = XXX; + void* my_void_ptr; + my_void_ptr = (void*)my_dx11_srv; // cast a ID3D11ShaderResourceView* into an opaque void* + my_dx11_srv = (ID3D11ShaderResourceView*)my_void_ptr; // cast a void* into a ID3D11ShaderResourceView* + + Finally, you may call ImGui::ShowMetricsWindow() to explore/visualize/understand how the ImDrawList are generated. + + Q: How can I have multiple widgets with the same label or without a label? + Q: I have multiple widgets with the same label, and only the first one works. Why is that? + A: A primer on labels and the ID Stack... + + Dear ImGui internally need to uniquely identify UI elements. + Elements that are typically not clickable (such as calls to the Text functions) don't need an ID. + Interactive widgets (such as calls to Button buttons) need a unique ID. + Unique ID are used internally to track active widgets and occasionally associate state to widgets. + Unique ID are implicitly built from the hash of multiple elements that identify the "path" to the UI element. + + - Unique ID are often derived from a string label: + + Button("OK"); // Label = "OK", ID = hash of (..., "OK") + Button("Cancel"); // Label = "Cancel", ID = hash of (..., "Cancel") + + - ID are uniquely scoped within windows, tree nodes, etc. which all pushes to the ID stack. Having + two buttons labeled "OK" in different windows or different tree locations is fine. + We used "..." above to signify whatever was already pushed to the ID stack previously: + + Begin("MyWindow"); + Button("OK"); // Label = "OK", ID = hash of ("MyWindow", "OK") + End(); + + - If you have a same ID twice in the same location, you'll have a conflict: + + Button("OK"); + Button("OK"); // ID collision! Interacting with either button will trigger the first one. + + Fear not! this is easy to solve and there are many ways to solve it! + + - Solving ID conflict in a simple/local context: + When passing a label you can optionally specify extra ID information within string itself. + Use "##" to pass a complement to the ID that won't be visible to the end-user. + This helps solving the simple collision cases when you know e.g. at compilation time which items + are going to be created: + + Begin("MyWindow"); + Button("Play"); // Label = "Play", ID = hash of ("MyWindow", "Play") + Button("Play##foo1"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo1") // Different from above + Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo2") // Different from above + End(); + + - If you want to completely hide the label, but still need an ID: + + Checkbox("##On", &b); // Label = "", ID = hash of (..., "##On") // No visible label! + + - Occasionally/rarely you might want change a label while preserving a constant ID. This allows + you to animate labels. For example you may want to include varying information in a window title bar, + but windows are uniquely identified by their ID. Use "###" to pass a label that isn't part of ID: + + Button("Hello###ID"; // Label = "Hello", ID = hash of (..., "ID") + Button("World###ID"; // Label = "World", ID = hash of (..., "ID") // Same as above, even though the label looks different + + sprintf(buf, "My game (%f FPS)###MyGame", fps); + Begin(buf); // Variable label, ID = hash of "MyGame" + + - Solving ID conflict in a more general manner: + Use PushID() / PopID() to create scopes and manipulate the ID stack, as to avoid ID conflicts + within the same window. This is the most convenient way of distinguishing ID when iterating and + creating many UI elements programmatically. + You can push a pointer, a string or an integer value into the ID stack. + Remember that ID are formed from the concatenation of _everything_ in the ID stack! + + Begin("Window"); + for (int i = 0; i < 100; i++) + { + PushID(i); // Push i to the id tack + Button("Click"); // Label = "Click", ID = Hash of ("Window", i, "Click") + PopID(); + } + for (int i = 0; i < 100; i++) + { + MyObject* obj = Objects[i]; + PushID(obj); + Button("Click"); // Label = "Click", ID = Hash of ("Window", obj pointer, "Click") + PopID(); + } + for (int i = 0; i < 100; i++) + { + MyObject* obj = Objects[i]; + PushID(obj->Name); + Button("Click"); // Label = "Click", ID = Hash of ("Window", obj->Name, "Click") + PopID(); + } + End(); + + - More example showing that you can stack multiple prefixes into the ID stack: + + Button("Click"); // Label = "Click", ID = hash of (..., "Click") + PushID("node"); + Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click") + PushID(my_ptr); + Button("Click"); // Label = "Click", ID = hash of (..., "node", my_ptr, "Click") + PopID(); + PopID(); + + - Tree nodes implicitly creates a scope for you by calling PushID(). + + Button("Click"); // Label = "Click", ID = hash of (..., "Click") + if (TreeNode("node")) + { + Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click") + TreePop(); + } + + - When working with trees, ID are used to preserve the open/close state of each tree node. + Depending on your use cases you may want to use strings, indices or pointers as ID. + e.g. when following a single pointer that may change over time, using a static string as ID + will preserve your node open/closed state when the targeted object change. + e.g. when displaying a list of objects, using indices or pointers as ID will preserve the + node open/closed state differently. See what makes more sense in your situation! + + Q: How can I use my own math types instead of ImVec2/ImVec4? + A: You can edit imconfig.h and setup the IM_VEC2_CLASS_EXTRA/IM_VEC4_CLASS_EXTRA macros to add implicit type conversions. + This way you'll be able to use your own types everywhere, e.g. passsing glm::vec2 to ImGui functions instead of ImVec2. + + Q: How can I load a different font than the default? + A: Use the font atlas to load the TTF/OTF file you want: + ImGuiIO& io = ImGui::GetIO(); + io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels); + io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() + (default is ProggyClean.ttf, rendered at size 13, embedded in dear imgui's source code) + + New programmers: remember that in C/C++ and most programming languages if you want to use a + backslash \ within a string literal, you need to write it double backslash "\\": + io.Fonts->AddFontFromFileTTF("MyDataFolder\MyFontFile.ttf", size_in_pixels); // WRONG (you are escape the M here!) + io.Fonts->AddFontFromFileTTF("MyDataFolder\\MyFontFile.ttf", size_in_pixels); // CORRECT + io.Fonts->AddFontFromFileTTF("MyDataFolder/MyFontFile.ttf", size_in_pixels); // ALSO CORRECT + + Q: How can I easily use icons in my application? + A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you + main font. Then you can refer to icons within your strings. Read 'How can I load multiple fonts?' + and the file 'misc/fonts/README.txt' for instructions and useful header files. + + Q: How can I load multiple fonts? + A: Use the font atlas to pack them into a single texture: + (Read misc/fonts/README.txt and the code in ImFontAtlas for more details.) + + ImGuiIO& io = ImGui::GetIO(); + ImFont* font0 = io.Fonts->AddFontDefault(); + ImFont* font1 = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels); + ImFont* font2 = io.Fonts->AddFontFromFileTTF("myfontfile2.ttf", size_in_pixels); + io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() + // the first loaded font gets used by default + // use ImGui::PushFont()/ImGui::PopFont() to change the font at runtime + + // Options + ImFontConfig config; + config.OversampleH = 3; + config.OversampleV = 1; + config.GlyphOffset.y -= 2.0f; // Move everything by 2 pixels up + config.GlyphExtraSpacing.x = 1.0f; // Increase spacing between characters + io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, &config); + + // Combine multiple fonts into one (e.g. for icon fonts) + ImWchar ranges[] = { 0xf000, 0xf3ff, 0 }; + ImFontConfig config; + config.MergeMode = true; + io.Fonts->AddFontDefault(); + io.Fonts->LoadFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); // Merge icon font + io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs + + Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic? + A: When loading a font, pass custom Unicode ranges to specify the glyphs to load. + + // Add default Japanese ranges + io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese()); + + // Or create your own custom ranges (e.g. for a game you can feed your entire game script and only build the characters the game need) + ImVector ranges; + ImFontAtlas::GlyphRangesBuilder builder; + builder.AddText("Hello world"); // Add a string (here "Hello world" contains 7 unique characters) + builder.AddChar(0x7262); // Add a specific character + builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges + builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted) + io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data); + + All your strings needs to use UTF-8 encoding. In C++11 you can encode a string literal in UTF-8 + by using the u8"hello" syntax. Specifying literal in your source code using a local code page + (such as CP-923 for Japanese or CP-1251 for Cyrillic) will NOT work! + Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. + + Text input: it is up to your application to pass the right character code by calling io.AddInputCharacter(). + The applications in examples/ are doing that. + Windows: you can use the WM_CHAR or WM_UNICHAR or WM_IME_CHAR message (depending if your app is built using Unicode or MultiByte mode). + You may also use MultiByteToWideChar() or ToUnicode() to retrieve Unicode codepoints from MultiByte characters or keyboard state. + Windows: if your language is relying on an Input Method Editor (IME), you copy the HWND of your window to io.ImeWindowHandle in order for + the default implementation of io.ImeSetInputScreenPosFn() to set your Microsoft IME position correctly. + + Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API) + A: - You can create a dummy window. Call SetNextWindowBgAlpha(0.0f), call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flags. + Then you can retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like. + - You can call ImGui::GetOverlayDrawList() and use this draw list to display contents over every other imgui windows. + - You can create your own ImDrawList instance. You'll need to initialize them ImGui::GetDrawListSharedData(), or create your own ImDrawListSharedData. + + Q: I integrated Dear ImGui in my engine and the text or lines are blurry.. + A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f). + Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension. + + Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. + A: You are probably mishandling the clipping rectangles in your render function. + Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height). + + Q: How can I help? + A: - If you are experienced with Dear ImGui and C++, look at the github issues, or TODO.txt and see how you want/can help! + - Convince your company to fund development time! Individual users: you can also become a Patron (patreon.com/imgui) or donate on PayPal! See README. + - Disclose your usage of dear imgui via a dev blog post, a tweet, a screenshot, a mention somewhere etc. + You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/1269). Visuals are ideal as they inspire other programmers. + But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions. + - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues (on github or privately). + + - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window. + this is also useful to set yourself in the context of another window (to get/set other settings) + - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug". + - tip: the ImGuiOnceUponAFrame helper will allow run the block of code only once a frame. You can use it to quickly add custom UI in the middle + of a deep nested inner loop in your code. + - tip: you can call Render() multiple times (e.g for VR renders). + - tip: call and read the ShowDemoWindow() code in imgui_demo.cpp for more example of how to use ImGui! + +*/ + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "imgui.h" +#ifndef IMGUI_DEFINE_MATH_OPERATORS +#define IMGUI_DEFINE_MATH_OPERATORS +#endif +#include "imgui_internal.h" + +#include // toupper, isprint +#include // vsnprintf, sscanf, printf +#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier +#include // intptr_t +#else +#include // intptr_t +#endif + +#define IMGUI_DEBUG_NAV_SCORING 0 +#define IMGUI_DEBUG_NAV_RECTS 0 + +// Visual Studio warnings +#ifdef _MSC_VER +#pragma warning (disable: 4127) // condition expression is constant +#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) +#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen +#endif + +// Clang warnings with -Weverything +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning : unknown warning group '-Wformat-pedantic *' // not all warnings are known by all clang versions.. so ignoring warnings triggers new warnings on some configuration. great! +#pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse. +#pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok. +#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning : format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code. +#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals. +#pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it. +#pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // +#pragma clang diagnostic ignored "-Wformat-pedantic" // warning : format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would lead to casting every %p arg to void*. probably enabled by -pedantic. +#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' +#elif defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used +#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size +#pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*' +#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function +#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value +#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked +#pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false +#if __GNUC__ >= 8 +#pragma GCC diagnostic ignored "-Wclass-memaccess" // warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead +#endif +#endif + +static const ImS32 IM_S32_MIN = INT_MIN; // (-2147483647 - 1), (0x80000000); +static const ImS32 IM_S32_MAX = INT_MAX; // (2147483647), (0x7FFFFFFF) +static const ImU32 IM_U32_MIN = 0; +static const ImU32 IM_U32_MAX = UINT_MAX; // (0xFFFFFFFF) +#ifdef LLONG_MIN +static const ImS64 IM_S64_MIN = LLONG_MIN; // (-9223372036854775807ll - 1ll); +static const ImS64 IM_S64_MAX = LLONG_MAX; // (9223372036854775807ll); +#else +static const ImS64 IM_S64_MIN = -9223372036854775807LL - 1; +static const ImS64 IM_S64_MAX = 9223372036854775807LL; +#endif +static const ImU64 IM_U64_MIN = 0; +#ifdef ULLONG_MAX +static const ImU64 IM_U64_MAX = ULLONG_MAX; // (0xFFFFFFFFFFFFFFFFull); +#else +static const ImU64 IM_U64_MAX = (2ULL * 9223372036854775807LL + 1); +#endif + +// When using CTRL+TAB (or Gamepad Square+L/R) we delay the visual a little in order to reduce visual noise doing a fast switch. +static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f; // Time before the highlight and screen dimming starts fading in +static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear + +//------------------------------------------------------------------------- +// Forward Declarations +//------------------------------------------------------------------------- + +static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true); + +static void SetCurrentWindow(ImGuiWindow* window); +static void SetWindowScrollX(ImGuiWindow* window, float new_scroll_x); +static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y); +static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond); +static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond); +static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond); +static void FindHoveredWindow(); +static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags); +static ImGuiWindowSettings* CreateNewWindowSettings(const char* name); +static void CheckStacksSize(ImGuiWindow* window, bool write); +static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges); + +static void AddDrawListToDrawData(ImVector* out_list, ImDrawList* draw_list); +static void AddWindowToDrawData(ImVector* out_list, ImGuiWindow* window); +static void AddWindowToSortedBuffer(ImVector* out_sorted_windows, ImGuiWindow* window); + +static ImRect GetViewportRect(); + +static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data); +static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end); +static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false); + +static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format); +static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg_1, const void* arg_2); +static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* format); + +namespace ImGui +{ +static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags); + +static void NavUpdate(); +static void NavUpdateWindowing(); +static void NavUpdateWindowingList(); +static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id); + +static void UpdateMouseInputs(); +static void UpdateMouseWheel(); +static void UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]); +static void FocusFrontMostActiveWindow(ImGuiWindow* ignore_window); + +// Template widget behaviors +template +static bool DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const TYPE v_min, const TYPE v_max, const char* format, float power); + +template +static bool SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, TYPE* v, const TYPE v_min, const TYPE v_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb); +} + +//----------------------------------------------------------------------------- +// Platform dependent default implementations +//----------------------------------------------------------------------------- + +static const char* GetClipboardTextFn_DefaultImpl(void* user_data); +static void SetClipboardTextFn_DefaultImpl(void* user_data, const char* text); +static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y); + +//----------------------------------------------------------------------------- +// Context and Memory Allocators +//----------------------------------------------------------------------------- + +// Current context pointer. Implicitly used by all ImGui functions. Always assumed to be != NULL. +// CreateContext() will automatically set this pointer if it is NULL. Change to a different context by calling ImGui::SetCurrentContext(). +// If you use DLL hotreloading you might need to call SetCurrentContext() after reloading code from this file. +// ImGui functions are not thread-safe because of this pointer. If you want thread-safety to allow N threads to access N different contexts, you can: +// - Change this variable to use thread local storage. You may #define GImGui in imconfig.h for that purpose. Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586 +// - Having multiple instances of the ImGui code compiled inside different namespace (easiest/safest, if you have a finite number of contexts) +#ifndef GImGui +ImGuiContext* GImGui = NULL; +#endif + +// Memory Allocator functions. Use SetAllocatorFunctions() to change them. +// If you use DLL hotreloading you might need to call SetAllocatorFunctions() after reloading code from this file. +// Otherwise, you probably don't want to modify them mid-program, and if you use global/static e.g. ImVector<> instances you may need to keep them accessible during program destruction. +#ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS +static void* MallocWrapper(size_t size, void* user_data) { (void)user_data; return malloc(size); } +static void FreeWrapper(void* ptr, void* user_data) { (void)user_data; free(ptr); } +#else +static void* MallocWrapper(size_t size, void* user_data) { (void)user_data; (void)size; IM_ASSERT(0); return NULL; } +static void FreeWrapper(void* ptr, void* user_data) { (void)user_data; (void)ptr; IM_ASSERT(0); } +#endif + +static void* (*GImAllocatorAllocFunc)(size_t size, void* user_data) = MallocWrapper; +static void (*GImAllocatorFreeFunc)(void* ptr, void* user_data) = FreeWrapper; +static void* GImAllocatorUserData = NULL; + +//----------------------------------------------------------------------------- +// User facing structures +//----------------------------------------------------------------------------- + +ImGuiStyle::ImGuiStyle() +{ + Alpha = 1.0f; // Global alpha applies to everything in ImGui + WindowPadding = ImVec2(8,8); // Padding within a window + WindowRounding = 7.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows + WindowBorderSize = 1.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested. + WindowMinSize = ImVec2(32,32); // Minimum window size + WindowTitleAlign = ImVec2(0.0f,0.5f);// Alignment for title bar text + ChildRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows + ChildBorderSize = 1.0f; // Thickness of border around child windows. Generally set to 0.0f or 1.0f. Other values not well tested. + PopupRounding = 0.0f; // Radius of popup window corners rounding. Set to 0.0f to have rectangular child windows + PopupBorderSize = 1.0f; // Thickness of border around popup or tooltip windows. Generally set to 0.0f or 1.0f. Other values not well tested. + FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets) + FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets). + FrameBorderSize = 0.0f; // Thickness of border around frames. Generally set to 0.0f or 1.0f. Other values not well tested. + ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines + ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) + TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! + IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). + ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns + ScrollbarSize = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar + ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar + GrabMinSize = 10.0f; // Minimum width/height of a grab box for slider/scrollbar + GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. + ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text. + DisplayWindowPadding = ImVec2(20,20); // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows. + DisplaySafeAreaPadding = ImVec2(3,3); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. + MouseCursorScale = 1.0f; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later. + AntiAliasedLines = true; // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU. + AntiAliasedFill = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) + CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. + + // Default theme + ImGui::StyleColorsDark(this); +} + +// To scale your entire UI (e.g. if you want your app to use High DPI or generally be DPI aware) you may use this helper function. Scaling the fonts is done separately and is up to you. +// Important: This operation is lossy because we round all sizes to integer. If you need to change your scale multiples, call this over a freshly initialized ImGuiStyle structure rather than scaling multiple times. +void ImGuiStyle::ScaleAllSizes(float scale_factor) +{ + WindowPadding = ImFloor(WindowPadding * scale_factor); + WindowRounding = ImFloor(WindowRounding * scale_factor); + WindowMinSize = ImFloor(WindowMinSize * scale_factor); + ChildRounding = ImFloor(ChildRounding * scale_factor); + PopupRounding = ImFloor(PopupRounding * scale_factor); + FramePadding = ImFloor(FramePadding * scale_factor); + FrameRounding = ImFloor(FrameRounding * scale_factor); + ItemSpacing = ImFloor(ItemSpacing * scale_factor); + ItemInnerSpacing = ImFloor(ItemInnerSpacing * scale_factor); + TouchExtraPadding = ImFloor(TouchExtraPadding * scale_factor); + IndentSpacing = ImFloor(IndentSpacing * scale_factor); + ColumnsMinSpacing = ImFloor(ColumnsMinSpacing * scale_factor); + ScrollbarSize = ImFloor(ScrollbarSize * scale_factor); + ScrollbarRounding = ImFloor(ScrollbarRounding * scale_factor); + GrabMinSize = ImFloor(GrabMinSize * scale_factor); + GrabRounding = ImFloor(GrabRounding * scale_factor); + DisplayWindowPadding = ImFloor(DisplayWindowPadding * scale_factor); + DisplaySafeAreaPadding = ImFloor(DisplaySafeAreaPadding * scale_factor); + MouseCursorScale = ImFloor(MouseCursorScale * scale_factor); +} + +ImGuiIO::ImGuiIO() +{ + // Most fields are initialized with zero + memset(this, 0, sizeof(*this)); + + // Settings + ConfigFlags = 0x00; + BackendFlags = 0x00; + DisplaySize = ImVec2(-1.0f, -1.0f); + DeltaTime = 1.0f/60.0f; + IniSavingRate = 5.0f; + IniFilename = "imgui.ini"; + LogFilename = "imgui_log.txt"; + MouseDoubleClickTime = 0.30f; + MouseDoubleClickMaxDist = 6.0f; + for (int i = 0; i < ImGuiKey_COUNT; i++) + KeyMap[i] = -1; + KeyRepeatDelay = 0.250f; + KeyRepeatRate = 0.050f; + UserData = NULL; + + Fonts = NULL; + FontGlobalScale = 1.0f; + FontDefault = NULL; + FontAllowUserScaling = false; + DisplayFramebufferScale = ImVec2(1.0f, 1.0f); + DisplayVisibleMin = DisplayVisibleMax = ImVec2(0.0f, 0.0f); + + // Miscellaneous configuration options +#ifdef __APPLE__ + ConfigMacOSXBehaviors = true; // Set Mac OS X style defaults based on __APPLE__ compile time flag +#else + ConfigMacOSXBehaviors = false; +#endif + ConfigCursorBlink = true; + ConfigResizeWindowsFromEdges = false; + + // Settings (User Functions) + GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations + SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; + ClipboardUserData = NULL; + ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl; + ImeWindowHandle = NULL; + +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + RenderDrawListsFn = NULL; +#endif + + // Input (NB: we already have memset zero the entire structure) + MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX); + MouseDragThreshold = 6.0f; + for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f; + for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f; + for (int i = 0; i < IM_ARRAYSIZE(NavInputsDownDuration); i++) NavInputsDownDuration[i] = -1.0f; +} + +// Pass in translated ASCII characters for text input. +// - with glfw you can get those from the callback set in glfwSetCharCallback() +// - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message +void ImGuiIO::AddInputCharacter(ImWchar c) +{ + const int n = ImStrlenW(InputCharacters); + if (n + 1 < IM_ARRAYSIZE(InputCharacters)) + { + InputCharacters[n] = c; + InputCharacters[n+1] = '\0'; + } +} + +void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars) +{ + // We can't pass more wchars than ImGuiIO::InputCharacters[] can hold so don't convert more + const int wchars_buf_len = sizeof(ImGuiIO::InputCharacters) / sizeof(ImWchar); + ImWchar wchars[wchars_buf_len]; + ImTextStrFromUtf8(wchars, wchars_buf_len, utf8_chars, NULL); + for (int i = 0; i < wchars_buf_len && wchars[i] != 0; i++) + AddInputCharacter(wchars[i]); +} + +//----------------------------------------------------------------------------- +// HELPERS +//----------------------------------------------------------------------------- + +#define IM_STATIC_ASSERT(_COND) typedef char static_assertion_##__line__[(_COND)?1:-1] +#define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose +#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255 + +ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p) +{ + ImVec2 ap = p - a; + ImVec2 ab_dir = b - a; + float dot = ap.x * ab_dir.x + ap.y * ab_dir.y; + if (dot < 0.0f) + return a; + float ab_len_sqr = ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y; + if (dot > ab_len_sqr) + return b; + return a + ab_dir * dot / ab_len_sqr; +} + +bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p) +{ + bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f; + bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f; + bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f; + return ((b1 == b2) && (b2 == b3)); +} + +void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w) +{ + ImVec2 v0 = b - a; + ImVec2 v1 = c - a; + ImVec2 v2 = p - a; + const float denom = v0.x * v1.y - v1.x * v0.y; + out_v = (v2.x * v1.y - v1.x * v2.y) / denom; + out_w = (v0.x * v2.y - v2.x * v0.y) / denom; + out_u = 1.0f - out_v - out_w; +} + +ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p) +{ + ImVec2 proj_ab = ImLineClosestPoint(a, b, p); + ImVec2 proj_bc = ImLineClosestPoint(b, c, p); + ImVec2 proj_ca = ImLineClosestPoint(c, a, p); + float dist2_ab = ImLengthSqr(p - proj_ab); + float dist2_bc = ImLengthSqr(p - proj_bc); + float dist2_ca = ImLengthSqr(p - proj_ca); + float m = ImMin(dist2_ab, ImMin(dist2_bc, dist2_ca)); + if (m == dist2_ab) + return proj_ab; + if (m == dist2_bc) + return proj_bc; + return proj_ca; +} + +int ImStricmp(const char* str1, const char* str2) +{ + int d; + while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } + return d; +} + +int ImStrnicmp(const char* str1, const char* str2, size_t count) +{ + int d = 0; + while (count > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; count--; } + return d; +} + +void ImStrncpy(char* dst, const char* src, size_t count) +{ + if (count < 1) return; + strncpy(dst, src, count); + dst[count-1] = 0; +} + +char* ImStrdup(const char *str) +{ + size_t len = strlen(str) + 1; + void* buf = ImGui::MemAlloc(len); + return (char*)memcpy(buf, (const void*)str, len); +} + +const char* ImStrchrRange(const char* str, const char* str_end, char c) +{ + for ( ; str < str_end; str++) + if (*str == c) + return str; + return NULL; +} + +int ImStrlenW(const ImWchar* str) +{ + int n = 0; + while (*str++) n++; + return n; +} + +const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line +{ + while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n') + buf_mid_line--; + return buf_mid_line; +} + +const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end) +{ + if (!needle_end) + needle_end = needle + strlen(needle); + + const char un0 = (char)toupper(*needle); + while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end)) + { + if (toupper(*haystack) == un0) + { + const char* b = needle + 1; + for (const char* a = haystack + 1; b < needle_end; a++, b++) + if (toupper(*a) != toupper(*b)) + break; + if (b == needle_end) + return haystack; + } + haystack++; + } + return NULL; +} + +// Trim str by offsetting contents when there's leading data + writing a \0 at the trailing position. We use this in situation where the cost is negligible. +void ImStrTrimBlanks(char* buf) +{ + char* p = buf; + while (p[0] == ' ' || p[0] == '\t') // Leading blanks + p++; + char* p_start = p; + while (*p != 0) // Find end of string + p++; + while (p > p_start && (p[-1] == ' ' || p[-1] == '\t')) // Trailing blanks + p--; + if (p_start != buf) // Copy memory if we had leading blanks + memmove(buf, p_start, p - p_start); + buf[p - p_start] = 0; // Zero terminate +} + +template +static const char* ImAtoi(const char* src, TYPE* output) +{ + int negative = 0; + if (*src == '-') { negative = 1; src++; } + if (*src == '+') { src++; } + TYPE v = 0; + while (*src >= '0' && *src <= '9') + v = (v * 10) + (*src++ - '0'); + *output = negative ? -v : v; + return src; +} + +// A) MSVC version appears to return -1 on overflow, whereas glibc appears to return total count (which may be >= buf_size). +// Ideally we would test for only one of those limits at runtime depending on the behavior the vsnprintf(), but trying to deduct it at compile time sounds like a pandora can of worm. +// B) When buf==NULL vsnprintf() will return the output size. +#ifndef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS + +#if defined(_MSC_VER) && !defined(vsnprintf) +#define vsnprintf _vsnprintf +#endif + +int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + int w = vsnprintf(buf, buf_size, fmt, args); + va_end(args); + if (buf == NULL) + return w; + if (w == -1 || w >= (int)buf_size) + w = (int)buf_size - 1; + buf[w] = 0; + return w; +} + +int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args) +{ + int w = vsnprintf(buf, buf_size, fmt, args); + if (buf == NULL) + return w; + if (w == -1 || w >= (int)buf_size) + w = (int)buf_size - 1; + buf[w] = 0; + return w; +} +#endif // #ifdef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS + +// Pass data_size==0 for zero-terminated strings +// FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements. +ImU32 ImHash(const void* data, int data_size, ImU32 seed) +{ + static ImU32 crc32_lut[256] = { 0 }; + if (!crc32_lut[1]) + { + const ImU32 polynomial = 0xEDB88320; + for (ImU32 i = 0; i < 256; i++) + { + ImU32 crc = i; + for (ImU32 j = 0; j < 8; j++) + crc = (crc >> 1) ^ (ImU32(-int(crc & 1)) & polynomial); + crc32_lut[i] = crc; + } + } + + seed = ~seed; + ImU32 crc = seed; + const unsigned char* current = (const unsigned char*)data; + + if (data_size > 0) + { + // Known size + while (data_size--) + crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *current++]; + } + else + { + // Zero-terminated string + while (unsigned char c = *current++) + { + // We support a syntax of "label###id" where only "###id" is included in the hash, and only "label" gets displayed. + // Because this syntax is rarely used we are optimizing for the common case. + // - If we reach ### in the string we discard the hash so far and reset to the seed. + // - We don't do 'current += 2; continue;' after handling ### to keep the code smaller. + if (c == '#' && current[0] == '#' && current[1] == '#') + crc = seed; + crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c]; + } + } + return ~crc; +} + +//----------------------------------------------------------------------------- +// ImText* helpers +//----------------------------------------------------------------------------- + +// Convert UTF-8 to 32-bits character, process single character input. +// Based on stb_from_utf8() from github.com/nothings/stb/ +// We handle UTF-8 decoding error by skipping forward. +int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end) +{ + unsigned int c = (unsigned int)-1; + const unsigned char* str = (const unsigned char*)in_text; + if (!(*str & 0x80)) + { + c = (unsigned int)(*str++); + *out_char = c; + return 1; + } + if ((*str & 0xe0) == 0xc0) + { + *out_char = 0xFFFD; // will be invalid but not end of string + if (in_text_end && in_text_end - (const char*)str < 2) return 1; + if (*str < 0xc2) return 2; + c = (unsigned int)((*str++ & 0x1f) << 6); + if ((*str & 0xc0) != 0x80) return 2; + c += (*str++ & 0x3f); + *out_char = c; + return 2; + } + if ((*str & 0xf0) == 0xe0) + { + *out_char = 0xFFFD; // will be invalid but not end of string + if (in_text_end && in_text_end - (const char*)str < 3) return 1; + if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 3; + if (*str == 0xed && str[1] > 0x9f) return 3; // str[1] < 0x80 is checked below + c = (unsigned int)((*str++ & 0x0f) << 12); + if ((*str & 0xc0) != 0x80) return 3; + c += (unsigned int)((*str++ & 0x3f) << 6); + if ((*str & 0xc0) != 0x80) return 3; + c += (*str++ & 0x3f); + *out_char = c; + return 3; + } + if ((*str & 0xf8) == 0xf0) + { + *out_char = 0xFFFD; // will be invalid but not end of string + if (in_text_end && in_text_end - (const char*)str < 4) return 1; + if (*str > 0xf4) return 4; + if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 4; + if (*str == 0xf4 && str[1] > 0x8f) return 4; // str[1] < 0x80 is checked below + c = (unsigned int)((*str++ & 0x07) << 18); + if ((*str & 0xc0) != 0x80) return 4; + c += (unsigned int)((*str++ & 0x3f) << 12); + if ((*str & 0xc0) != 0x80) return 4; + c += (unsigned int)((*str++ & 0x3f) << 6); + if ((*str & 0xc0) != 0x80) return 4; + c += (*str++ & 0x3f); + // utf-8 encodings of values used in surrogate pairs are invalid + if ((c & 0xFFFFF800) == 0xD800) return 4; + *out_char = c; + return 4; + } + *out_char = 0; + return 0; +} + +int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining) +{ + ImWchar* buf_out = buf; + ImWchar* buf_end = buf + buf_size; + while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text) + { + unsigned int c; + in_text += ImTextCharFromUtf8(&c, in_text, in_text_end); + if (c == 0) + break; + if (c < 0x10000) // FIXME: Losing characters that don't fit in 2 bytes + *buf_out++ = (ImWchar)c; + } + *buf_out = 0; + if (in_text_remaining) + *in_text_remaining = in_text; + return (int)(buf_out - buf); +} + +int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end) +{ + int char_count = 0; + while ((!in_text_end || in_text < in_text_end) && *in_text) + { + unsigned int c; + in_text += ImTextCharFromUtf8(&c, in_text, in_text_end); + if (c == 0) + break; + if (c < 0x10000) + char_count++; + } + return char_count; +} + +// Based on stb_to_utf8() from github.com/nothings/stb/ +static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c) +{ + if (c < 0x80) + { + buf[0] = (char)c; + return 1; + } + if (c < 0x800) + { + if (buf_size < 2) return 0; + buf[0] = (char)(0xc0 + (c >> 6)); + buf[1] = (char)(0x80 + (c & 0x3f)); + return 2; + } + if (c >= 0xdc00 && c < 0xe000) + { + return 0; + } + if (c >= 0xd800 && c < 0xdc00) + { + if (buf_size < 4) return 0; + buf[0] = (char)(0xf0 + (c >> 18)); + buf[1] = (char)(0x80 + ((c >> 12) & 0x3f)); + buf[2] = (char)(0x80 + ((c >> 6) & 0x3f)); + buf[3] = (char)(0x80 + ((c ) & 0x3f)); + return 4; + } + //else if (c < 0x10000) + { + if (buf_size < 3) return 0; + buf[0] = (char)(0xe0 + (c >> 12)); + buf[1] = (char)(0x80 + ((c>> 6) & 0x3f)); + buf[2] = (char)(0x80 + ((c ) & 0x3f)); + return 3; + } +} + +// Not optimal but we very rarely use this function. +int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end) +{ + unsigned int dummy = 0; + return ImTextCharFromUtf8(&dummy, in_text, in_text_end); +} + +static inline int ImTextCountUtf8BytesFromChar(unsigned int c) +{ + if (c < 0x80) return 1; + if (c < 0x800) return 2; + if (c >= 0xdc00 && c < 0xe000) return 0; + if (c >= 0xd800 && c < 0xdc00) return 4; + return 3; +} + +int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end) +{ + char* buf_out = buf; + const char* buf_end = buf + buf_size; + while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text) + { + unsigned int c = (unsigned int)(*in_text++); + if (c < 0x80) + *buf_out++ = (char)c; + else + buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end-buf_out-1), c); + } + *buf_out = 0; + return (int)(buf_out - buf); +} + +int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end) +{ + int bytes_count = 0; + while ((!in_text_end || in_text < in_text_end) && *in_text) + { + unsigned int c = (unsigned int)(*in_text++); + if (c < 0x80) + bytes_count++; + else + bytes_count += ImTextCountUtf8BytesFromChar(c); + } + return bytes_count; +} + +ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in) +{ + float s = 1.0f/255.0f; + return ImVec4( + ((in >> IM_COL32_R_SHIFT) & 0xFF) * s, + ((in >> IM_COL32_G_SHIFT) & 0xFF) * s, + ((in >> IM_COL32_B_SHIFT) & 0xFF) * s, + ((in >> IM_COL32_A_SHIFT) & 0xFF) * s); +} + +ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in) +{ + ImU32 out; + out = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT; + out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT; + out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT; + out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT; + return out; +} + +ImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul) +{ + ImGuiStyle& style = GImGui->Style; + ImVec4 c = style.Colors[idx]; + c.w *= style.Alpha * alpha_mul; + return ColorConvertFloat4ToU32(c); +} + +ImU32 ImGui::GetColorU32(const ImVec4& col) +{ + ImGuiStyle& style = GImGui->Style; + ImVec4 c = col; + c.w *= style.Alpha; + return ColorConvertFloat4ToU32(c); +} + +const ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx) +{ + ImGuiStyle& style = GImGui->Style; + return style.Colors[idx]; +} + +ImU32 ImGui::GetColorU32(ImU32 col) +{ + float style_alpha = GImGui->Style.Alpha; + if (style_alpha >= 1.0f) + return col; + ImU32 a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT; + a = (ImU32)(a * style_alpha); // We don't need to clamp 0..255 because Style.Alpha is in 0..1 range. + return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT); +} + +// Convert rgb floats ([0-1],[0-1],[0-1]) to hsv floats ([0-1],[0-1],[0-1]), from Foley & van Dam p592 +// Optimized http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv +void ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v) +{ + float K = 0.f; + if (g < b) + { + ImSwap(g, b); + K = -1.f; + } + if (r < g) + { + ImSwap(r, g); + K = -2.f / 6.f - K; + } + + const float chroma = r - (g < b ? g : b); + out_h = ImFabs(K + (g - b) / (6.f * chroma + 1e-20f)); + out_s = chroma / (r + 1e-20f); + out_v = r; +} + +// Convert hsv floats ([0-1],[0-1],[0-1]) to rgb floats ([0-1],[0-1],[0-1]), from Foley & van Dam p593 +// also http://en.wikipedia.org/wiki/HSL_and_HSV +void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b) +{ + if (s == 0.0f) + { + // gray + out_r = out_g = out_b = v; + return; + } + + h = ImFmod(h, 1.0f) / (60.0f/360.0f); + int i = (int)h; + float f = h - (float)i; + float p = v * (1.0f - s); + float q = v * (1.0f - s * f); + float t = v * (1.0f - s * (1.0f - f)); + + switch (i) + { + case 0: out_r = v; out_g = t; out_b = p; break; + case 1: out_r = q; out_g = v; out_b = p; break; + case 2: out_r = p; out_g = v; out_b = t; break; + case 3: out_r = p; out_g = q; out_b = v; break; + case 4: out_r = t; out_g = p; out_b = v; break; + case 5: default: out_r = v; out_g = p; out_b = q; break; + } +} + +FILE* ImFileOpen(const char* filename, const char* mode) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. Converting both strings from UTF-8 to wchar format (using a single allocation, because we can) + const int filename_wsize = ImTextCountCharsFromUtf8(filename, NULL) + 1; + const int mode_wsize = ImTextCountCharsFromUtf8(mode, NULL) + 1; + ImVector buf; + buf.resize(filename_wsize + mode_wsize); + ImTextStrFromUtf8(&buf[0], filename_wsize, filename, NULL); + ImTextStrFromUtf8(&buf[filename_wsize], mode_wsize, mode, NULL); + return _wfopen((wchar_t*)&buf[0], (wchar_t*)&buf[filename_wsize]); +#else + return fopen(filename, mode); +#endif +} + +// Load file content into memory +// Memory allocated with ImGui::MemAlloc(), must be freed by user using ImGui::MemFree() +void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, size_t* out_file_size, int padding_bytes) +{ + IM_ASSERT(filename && file_open_mode); + if (out_file_size) + *out_file_size = 0; + + FILE* f; + if ((f = ImFileOpen(filename, file_open_mode)) == NULL) + return NULL; + + long file_size_signed; + if (fseek(f, 0, SEEK_END) || (file_size_signed = ftell(f)) == -1 || fseek(f, 0, SEEK_SET)) + { + fclose(f); + return NULL; + } + + size_t file_size = (size_t)file_size_signed; + void* file_data = ImGui::MemAlloc(file_size + padding_bytes); + if (file_data == NULL) + { + fclose(f); + return NULL; + } + if (fread(file_data, 1, file_size, f) != file_size) + { + fclose(f); + ImGui::MemFree(file_data); + return NULL; + } + if (padding_bytes > 0) + memset((void*)(((char*)file_data) + file_size), 0, (size_t)padding_bytes); + + fclose(f); + if (out_file_size) + *out_file_size = file_size; + + return file_data; +} + +//----------------------------------------------------------------------------- +// ImGuiStorage +// Helper: Key->value storage +//----------------------------------------------------------------------------- + +// std::lower_bound but without the bullshit +static ImVector::iterator LowerBound(ImVector& data, ImGuiID key) +{ + ImVector::iterator first = data.begin(); + ImVector::iterator last = data.end(); + size_t count = (size_t)(last - first); + while (count > 0) + { + size_t count2 = count >> 1; + ImVector::iterator mid = first + count2; + if (mid->key < key) + { + first = ++mid; + count -= count2 + 1; + } + else + { + count = count2; + } + } + return first; +} + +// For quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once. +void ImGuiStorage::BuildSortByKey() +{ + struct StaticFunc + { + static int IMGUI_CDECL PairCompareByID(const void* lhs, const void* rhs) + { + // We can't just do a subtraction because qsort uses signed integers and subtracting our ID doesn't play well with that. + if (((const Pair*)lhs)->key > ((const Pair*)rhs)->key) return +1; + if (((const Pair*)lhs)->key < ((const Pair*)rhs)->key) return -1; + return 0; + } + }; + if (Data.Size > 1) + ImQsort(Data.Data, (size_t)Data.Size, sizeof(Pair), StaticFunc::PairCompareByID); +} + +int ImGuiStorage::GetInt(ImGuiID key, int default_val) const +{ + ImVector::iterator it = LowerBound(const_cast&>(Data), key); + if (it == Data.end() || it->key != key) + return default_val; + return it->val_i; +} + +bool ImGuiStorage::GetBool(ImGuiID key, bool default_val) const +{ + return GetInt(key, default_val ? 1 : 0) != 0; +} + +float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const +{ + ImVector::iterator it = LowerBound(const_cast&>(Data), key); + if (it == Data.end() || it->key != key) + return default_val; + return it->val_f; +} + +void* ImGuiStorage::GetVoidPtr(ImGuiID key) const +{ + ImVector::iterator it = LowerBound(const_cast&>(Data), key); + if (it == Data.end() || it->key != key) + return NULL; + return it->val_p; +} + +// References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer. +int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val) +{ + ImVector::iterator it = LowerBound(Data, key); + if (it == Data.end() || it->key != key) + it = Data.insert(it, Pair(key, default_val)); + return &it->val_i; +} + +bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val) +{ + return (bool*)GetIntRef(key, default_val ? 1 : 0); +} + +float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val) +{ + ImVector::iterator it = LowerBound(Data, key); + if (it == Data.end() || it->key != key) + it = Data.insert(it, Pair(key, default_val)); + return &it->val_f; +} + +void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val) +{ + ImVector::iterator it = LowerBound(Data, key); + if (it == Data.end() || it->key != key) + it = Data.insert(it, Pair(key, default_val)); + return &it->val_p; +} + +// FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on explicit interaction (maximum one a frame) +void ImGuiStorage::SetInt(ImGuiID key, int val) +{ + ImVector::iterator it = LowerBound(Data, key); + if (it == Data.end() || it->key != key) + { + Data.insert(it, Pair(key, val)); + return; + } + it->val_i = val; +} + +void ImGuiStorage::SetBool(ImGuiID key, bool val) +{ + SetInt(key, val ? 1 : 0); +} + +void ImGuiStorage::SetFloat(ImGuiID key, float val) +{ + ImVector::iterator it = LowerBound(Data, key); + if (it == Data.end() || it->key != key) + { + Data.insert(it, Pair(key, val)); + return; + } + it->val_f = val; +} + +void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val) +{ + ImVector::iterator it = LowerBound(Data, key); + if (it == Data.end() || it->key != key) + { + Data.insert(it, Pair(key, val)); + return; + } + it->val_p = val; +} + +void ImGuiStorage::SetAllInt(int v) +{ + for (int i = 0; i < Data.Size; i++) + Data[i].val_i = v; +} + +//----------------------------------------------------------------------------- +// ImGuiTextFilter +//----------------------------------------------------------------------------- + +// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" +ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) +{ + if (default_filter) + { + ImStrncpy(InputBuf, default_filter, IM_ARRAYSIZE(InputBuf)); + Build(); + } + else + { + InputBuf[0] = 0; + CountGrep = 0; + } +} + +bool ImGuiTextFilter::Draw(const char* label, float width) +{ + if (width != 0.0f) + ImGui::PushItemWidth(width); + bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf)); + if (width != 0.0f) + ImGui::PopItemWidth(); + if (value_changed) + Build(); + return value_changed; +} + +void ImGuiTextFilter::TextRange::split(char separator, ImVector* out) const +{ + out->resize(0); + const char* wb = b; + const char* we = wb; + while (we < e) + { + if (*we == separator) + { + out->push_back(TextRange(wb, we)); + wb = we + 1; + } + we++; + } + if (wb != we) + out->push_back(TextRange(wb, we)); +} + +void ImGuiTextFilter::Build() +{ + Filters.resize(0); + TextRange input_range(InputBuf, InputBuf+strlen(InputBuf)); + input_range.split(',', &Filters); + + CountGrep = 0; + for (int i = 0; i != Filters.Size; i++) + { + TextRange& f = Filters[i]; + while (f.b < f.e && ImCharIsBlankA(f.b[0])) + f.b++; + while (f.e > f.b && ImCharIsBlankA(f.e[-1])) + f.e--; + if (f.empty()) + continue; + if (Filters[i].b[0] != '-') + CountGrep += 1; + } +} + +bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const +{ + if (Filters.empty()) + return true; + + if (text == NULL) + text = ""; + + for (int i = 0; i != Filters.Size; i++) + { + const TextRange& f = Filters[i]; + if (f.empty()) + continue; + if (f.b[0] == '-') + { + // Subtract + if (ImStristr(text, text_end, f.begin()+1, f.end()) != NULL) + return false; + } + else + { + // Grep + if (ImStristr(text, text_end, f.begin(), f.end()) != NULL) + return true; + } + } + + // Implicit * grep + if (CountGrep == 0) + return true; + + return false; +} + +//----------------------------------------------------------------------------- +// ImGuiTextBuffer +//----------------------------------------------------------------------------- + +// On some platform vsnprintf() takes va_list by reference and modifies it. +// va_copy is the 'correct' way to copy a va_list but Visual Studio prior to 2013 doesn't have it. +#ifndef va_copy +#if defined(__GNUC__) || defined(__clang__) +#define va_copy(dest, src) __builtin_va_copy(dest, src) +#else +#define va_copy(dest, src) (dest = src) +#endif +#endif + +// Helper: Text buffer for logging/accumulating text +void ImGuiTextBuffer::appendfv(const char* fmt, va_list args) +{ + va_list args_copy; + va_copy(args_copy, args); + + int len = ImFormatStringV(NULL, 0, fmt, args); // FIXME-OPT: could do a first pass write attempt, likely successful on first pass. + if (len <= 0) + { + va_end(args_copy); + return; + } + + const int write_off = Buf.Size; + const int needed_sz = write_off + len; + if (write_off + len >= Buf.Capacity) + { + int double_capacity = Buf.Capacity * 2; + Buf.reserve(needed_sz > double_capacity ? needed_sz : double_capacity); + } + + Buf.resize(needed_sz); + ImFormatStringV(&Buf[write_off - 1], (size_t)len + 1, fmt, args_copy); + va_end(args_copy); +} + +void ImGuiTextBuffer::appendf(const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + appendfv(fmt, args); + va_end(args); +} + +//----------------------------------------------------------------------------- +// ImGuiSimpleColumns (internal use only) +//----------------------------------------------------------------------------- + +ImGuiMenuColumns::ImGuiMenuColumns() +{ + Count = 0; + Spacing = Width = NextWidth = 0.0f; + memset(Pos, 0, sizeof(Pos)); + memset(NextWidths, 0, sizeof(NextWidths)); +} + +void ImGuiMenuColumns::Update(int count, float spacing, bool clear) +{ + IM_ASSERT(Count <= IM_ARRAYSIZE(Pos)); + Count = count; + Width = NextWidth = 0.0f; + Spacing = spacing; + if (clear) memset(NextWidths, 0, sizeof(NextWidths)); + for (int i = 0; i < Count; i++) + { + if (i > 0 && NextWidths[i] > 0.0f) + Width += Spacing; + Pos[i] = (float)(int)Width; + Width += NextWidths[i]; + NextWidths[i] = 0.0f; + } +} + +float ImGuiMenuColumns::DeclColumns(float w0, float w1, float w2) // not using va_arg because they promote float to double +{ + NextWidth = 0.0f; + NextWidths[0] = ImMax(NextWidths[0], w0); + NextWidths[1] = ImMax(NextWidths[1], w1); + NextWidths[2] = ImMax(NextWidths[2], w2); + for (int i = 0; i < 3; i++) + NextWidth += NextWidths[i] + ((i > 0 && NextWidths[i] > 0.0f) ? Spacing : 0.0f); + return ImMax(Width, NextWidth); +} + +float ImGuiMenuColumns::CalcExtraSpace(float avail_w) +{ + return ImMax(0.0f, avail_w - Width); +} + +//----------------------------------------------------------------------------- +// ImGuiListClipper +//----------------------------------------------------------------------------- + +static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) +{ + // Set cursor position and a few other things so that SetScrollHere() and Columns() can work when seeking cursor. + // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue. + // The clipper should probably have a 4th step to display the last item in a regular manner. + ImGui::SetCursorPosY(pos_y); + ImGuiWindow* window = ImGui::GetCurrentWindow(); + window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHere() can properly function after the end of our clipper usage. + window->DC.PrevLineHeight = (line_height - GImGui->Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. + if (window->DC.ColumnsSet) + window->DC.ColumnsSet->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly +} + +// Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1 +// Use case B: Begin() called from constructor with items_height>0 +// FIXME-LEGACY: Ideally we should remove the Begin/End functions but they are part of the legacy API we still support. This is why some of the code in Step() calling Begin() and reassign some fields, spaghetti style. +void ImGuiListClipper::Begin(int count, float items_height) +{ + StartPosY = ImGui::GetCursorPosY(); + ItemsHeight = items_height; + ItemsCount = count; + StepNo = 0; + DisplayEnd = DisplayStart = -1; + if (ItemsHeight > 0.0f) + { + ImGui::CalcListClipping(ItemsCount, ItemsHeight, &DisplayStart, &DisplayEnd); // calculate how many to clip/display + if (DisplayStart > 0) + SetCursorPosYAndSetupDummyPrevLine(StartPosY + DisplayStart * ItemsHeight, ItemsHeight); // advance cursor + StepNo = 2; + } +} + +void ImGuiListClipper::End() +{ + if (ItemsCount < 0) + return; + // In theory here we should assert that ImGui::GetCursorPosY() == StartPosY + DisplayEnd * ItemsHeight, but it feels saner to just seek at the end and not assert/crash the user. + if (ItemsCount < INT_MAX) + SetCursorPosYAndSetupDummyPrevLine(StartPosY + ItemsCount * ItemsHeight, ItemsHeight); // advance cursor + ItemsCount = -1; + StepNo = 3; +} + +bool ImGuiListClipper::Step() +{ + if (ItemsCount == 0 || ImGui::GetCurrentWindowRead()->SkipItems) + { + ItemsCount = -1; + return false; + } + if (StepNo == 0) // Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height. + { + DisplayStart = 0; + DisplayEnd = 1; + StartPosY = ImGui::GetCursorPosY(); + StepNo = 1; + return true; + } + if (StepNo == 1) // Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element. + { + if (ItemsCount == 1) { ItemsCount = -1; return false; } + float items_height = ImGui::GetCursorPosY() - StartPosY; + IM_ASSERT(items_height > 0.0f); // If this triggers, it means Item 0 hasn't moved the cursor vertically + Begin(ItemsCount-1, items_height); + DisplayStart++; + DisplayEnd++; + StepNo = 3; + return true; + } + if (StepNo == 2) // Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user still call Step(). Does nothing and switch to Step 3. + { + IM_ASSERT(DisplayStart >= 0 && DisplayEnd >= 0); + StepNo = 3; + return true; + } + if (StepNo == 3) // Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop. + End(); + return false; +} + +//----------------------------------------------------------------------------- +// ImGuiWindow +//----------------------------------------------------------------------------- + +ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) + : DrawListInst(&context->DrawListSharedData) +{ + Name = ImStrdup(name); + ID = ImHash(name, 0); + IDStack.push_back(ID); + Flags = 0; + Pos = ImVec2(0.0f, 0.0f); + Size = SizeFull = ImVec2(0.0f, 0.0f); + SizeContents = SizeContentsExplicit = ImVec2(0.0f, 0.0f); + WindowPadding = ImVec2(0.0f, 0.0f); + WindowRounding = 0.0f; + WindowBorderSize = 0.0f; + MoveId = GetID("#MOVE"); + ChildId = 0; + Scroll = ImVec2(0.0f, 0.0f); + ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); + ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f); + ScrollbarSizes = ImVec2(0.0f, 0.0f); + ScrollbarX = ScrollbarY = false; + Active = WasActive = false; + WriteAccessed = false; + Collapsed = false; + WantCollapseToggle = false; + SkipItems = false; + Appearing = false; + Hidden = false; + HasCloseButton = false; + BeginOrderWithinParent = -1; + BeginOrderWithinContext = -1; + BeginCount = 0; + PopupId = 0; + AutoFitFramesX = AutoFitFramesY = -1; + AutoFitOnlyGrows = false; + AutoFitChildAxises = 0x00; + AutoPosLastDirection = ImGuiDir_None; + HiddenFramesRegular = HiddenFramesForResize = 0; + SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing; + SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX); + + LastFrameActive = -1; + ItemWidthDefault = 0.0f; + FontWindowScale = 1.0f; + SettingsIdx = -1; + + DrawList = &DrawListInst; + DrawList->_OwnerName = Name; + ParentWindow = NULL; + RootWindow = NULL; + RootWindowForTitleBarHighlight = NULL; + RootWindowForNav = NULL; + + NavLastIds[0] = NavLastIds[1] = 0; + NavRectRel[0] = NavRectRel[1] = ImRect(); + NavLastChildNavWindow = NULL; + + FocusIdxAllCounter = FocusIdxTabCounter = -1; + FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX; + FocusIdxAllRequestNext = FocusIdxTabRequestNext = INT_MAX; +} + +ImGuiWindow::~ImGuiWindow() +{ + IM_ASSERT(DrawList == &DrawListInst); + IM_DELETE(Name); + for (int i = 0; i != ColumnsStorage.Size; i++) + ColumnsStorage[i].~ImGuiColumnsSet(); +} + +ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end) +{ + ImGuiID seed = IDStack.back(); + ImGuiID id = ImHash(str, str_end ? (int)(str_end - str) : 0, seed); + ImGui::KeepAliveID(id); + return id; +} + +ImGuiID ImGuiWindow::GetID(const void* ptr) +{ + ImGuiID seed = IDStack.back(); + ImGuiID id = ImHash(&ptr, sizeof(void*), seed); + ImGui::KeepAliveID(id); + return id; +} + +ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end) +{ + ImGuiID seed = IDStack.back(); + return ImHash(str, str_end ? (int)(str_end - str) : 0, seed); +} + +ImGuiID ImGuiWindow::GetIDNoKeepAlive(const void* ptr) +{ + ImGuiID seed = IDStack.back(); + return ImHash(&ptr, sizeof(void*), seed); +} + +// This is only used in rare/specific situations to manufacture an ID out of nowhere. +ImGuiID ImGuiWindow::GetIDFromRectangle(const ImRect& r_abs) +{ + ImGuiID seed = IDStack.back(); + const int r_rel[4] = { (int)(r_abs.Min.x - Pos.x), (int)(r_abs.Min.y - Pos.y), (int)(r_abs.Max.x - Pos.x), (int)(r_abs.Max.y - Pos.y) }; + ImGuiID id = ImHash(&r_rel, sizeof(r_rel), seed); + ImGui::KeepAliveID(id); + return id; +} + +//----------------------------------------------------------------------------- +// Internal API exposed in imgui_internal.h +//----------------------------------------------------------------------------- + +static void SetCurrentWindow(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + g.CurrentWindow = window; + if (window) + g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize(); +} + +static void SetNavID(ImGuiID id, int nav_layer) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.NavWindow); + IM_ASSERT(nav_layer == 0 || nav_layer == 1); + g.NavId = id; + g.NavWindow->NavLastIds[nav_layer] = id; +} + +static void SetNavIDWithRectRel(ImGuiID id, int nav_layer, const ImRect& rect_rel) +{ + ImGuiContext& g = *GImGui; + SetNavID(id, nav_layer); + g.NavWindow->NavRectRel[nav_layer] = rect_rel; + g.NavMousePosDirty = true; + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; +} + +void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + g.ActiveIdIsJustActivated = (g.ActiveId != id); + if (g.ActiveIdIsJustActivated) + { + g.ActiveIdTimer = 0.0f; + g.ActiveIdValueChanged = false; + if (id != 0) + { + g.LastActiveId = id; + g.LastActiveIdTimer = 0.0f; + } + } + g.ActiveId = id; + g.ActiveIdAllowNavDirFlags = 0; + g.ActiveIdAllowOverlap = false; + g.ActiveIdWindow = window; + if (id) + { + g.ActiveIdIsAlive = id; + g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavJustTabbedId == id || g.NavJustMovedToId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; + } +} + +void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(id != 0); + + // Assume that SetFocusID() is called in the context where its NavLayer is the current layer, which is the case everywhere we call it. + const int nav_layer = window->DC.NavLayerCurrent; + if (g.NavWindow != window) + g.NavInitRequest = false; + g.NavId = id; + g.NavWindow = window; + g.NavLayer = nav_layer; + window->NavLastIds[nav_layer] = id; + if (window->DC.LastItemId == id) + window->NavRectRel[nav_layer] = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos); + + if (g.ActiveIdSource == ImGuiInputSource_Nav) + g.NavDisableMouseHover = true; + else + g.NavDisableHighlight = true; +} + +void ImGui::ClearActiveID() +{ + SetActiveID(0, NULL); +} + +void ImGui::SetHoveredID(ImGuiID id) +{ + ImGuiContext& g = *GImGui; + g.HoveredId = id; + g.HoveredIdAllowOverlap = false; + if (id != 0 && g.HoveredIdPreviousFrame != id) + g.HoveredIdTimer = 0.0f; +} + +ImGuiID ImGui::GetHoveredID() +{ + ImGuiContext& g = *GImGui; + return g.HoveredId ? g.HoveredId : g.HoveredIdPreviousFrame; +} + +void ImGui::KeepAliveID(ImGuiID id) +{ + ImGuiContext& g = *GImGui; + if (g.ActiveId == id) + g.ActiveIdIsAlive = id; + if (g.ActiveIdPreviousFrame == id) + g.ActiveIdPreviousFrameIsAlive = true; +} + +void ImGui::MarkItemValueChanged(ImGuiID id) +{ + // This marking is solely to be able to provide info for IsItemDeactivatedAfterChange(). + // ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need need to fill the data. + (void)id; // Avoid unused variable warnings when asserts are compiled out. + ImGuiContext& g = *GImGui; + IM_ASSERT(g.ActiveId == id || g.ActiveId == 0 || g.DragDropActive); + g.ActiveIdValueChanged = true; +} + +static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags) +{ + // An active popup disable hovering on other windows (apart from its own children) + // FIXME-OPT: This could be cached/stored within the window. + ImGuiContext& g = *GImGui; + if (g.NavWindow) + if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow) + if (focused_root_window->WasActive && focused_root_window != window->RootWindow) + { + // For the purpose of those flags we differentiate "standard popup" from "modal popup" + // NB: The order of those two tests is important because Modal windows are also Popups. + if (focused_root_window->Flags & ImGuiWindowFlags_Modal) + return false; + if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + return false; + } + + return true; +} + +// Advance cursor given item size for layout. +void ImGui::ItemSize(const ImVec2& size, float text_offset_y) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if (window->SkipItems) + return; + + // Always align ourselves on pixel boundaries + const float line_height = ImMax(window->DC.CurrentLineHeight, size.y); + const float text_base_offset = ImMax(window->DC.CurrentLineTextBaseOffset, text_offset_y); + //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG] + window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y); + window->DC.CursorPos = ImVec2((float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX), (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y)); + window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x); + window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y); + //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG] + + window->DC.PrevLineHeight = line_height; + window->DC.PrevLineTextBaseOffset = text_base_offset; + window->DC.CurrentLineHeight = window->DC.CurrentLineTextBaseOffset = 0.0f; + + // Horizontal layout mode + if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) + SameLine(); +} + +void ImGui::ItemSize(const ImRect& bb, float text_offset_y) +{ + ItemSize(bb.GetSize(), text_offset_y); +} + +static ImGuiDir inline NavScoreItemGetQuadrant(float dx, float dy) +{ + if (ImFabs(dx) > ImFabs(dy)) + return (dx > 0.0f) ? ImGuiDir_Right : ImGuiDir_Left; + return (dy > 0.0f) ? ImGuiDir_Down : ImGuiDir_Up; +} + +static float inline NavScoreItemDistInterval(float a0, float a1, float b0, float b1) +{ + if (a1 < b0) + return a1 - b0; + if (b1 < a0) + return a0 - b1; + return 0.0f; +} + +static void inline NavClampRectToVisibleAreaForMoveDir(ImGuiDir move_dir, ImRect& r, const ImRect& clip_rect) +{ + if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right) + { + r.Min.y = ImClamp(r.Min.y, clip_rect.Min.y, clip_rect.Max.y); + r.Max.y = ImClamp(r.Max.y, clip_rect.Min.y, clip_rect.Max.y); + } + else + { + r.Min.x = ImClamp(r.Min.x, clip_rect.Min.x, clip_rect.Max.x); + r.Max.x = ImClamp(r.Max.x, clip_rect.Min.x, clip_rect.Max.x); + } +} + +// Scoring function for directional navigation. Based on https://gist.github.com/rygorous/6981057 +static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if (g.NavLayer != window->DC.NavLayerCurrent) + return false; + + const ImRect& curr = g.NavScoringRectScreen; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having varied item width) + g.NavScoringCount++; + + // When entering through a NavFlattened border, we consider child window items as fully clipped for scoring + if (window->ParentWindow == g.NavWindow) + { + IM_ASSERT((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened); + if (!window->ClipRect.Contains(cand)) + return false; + cand.ClipWithFull(window->ClipRect); // This allows the scored item to not overlap other candidates in the parent window + } + + // We perform scoring on items bounding box clipped by the current clipping rectangle on the other axis (clipping on our movement axis would give us equal scores for all clipped items) + // For example, this ensure that items in one column are not reached when moving vertically from items in another column. + NavClampRectToVisibleAreaForMoveDir(g.NavMoveClipDir, cand, window->ClipRect); + + // Compute distance between boxes + // FIXME-NAV: Introducing biases for vertical navigation, needs to be removed. + float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x); + float dby = NavScoreItemDistInterval(ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f), ImLerp(curr.Min.y, curr.Max.y, 0.2f), ImLerp(curr.Min.y, curr.Max.y, 0.8f)); // Scale down on Y to keep using box-distance for vertically touching items + if (dby != 0.0f && dbx != 0.0f) + dbx = (dbx/1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f); + float dist_box = ImFabs(dbx) + ImFabs(dby); + + // Compute distance between centers (this is off by a factor of 2, but we only compare center distances with each other so it doesn't matter) + float dcx = (cand.Min.x + cand.Max.x) - (curr.Min.x + curr.Max.x); + float dcy = (cand.Min.y + cand.Max.y) - (curr.Min.y + curr.Max.y); + float dist_center = ImFabs(dcx) + ImFabs(dcy); // L1 metric (need this for our connectedness guarantee) + + // Determine which quadrant of 'curr' our candidate item 'cand' lies in based on distance + ImGuiDir quadrant; + float dax = 0.0f, day = 0.0f, dist_axial = 0.0f; + if (dbx != 0.0f || dby != 0.0f) + { + // For non-overlapping boxes, use distance between boxes + dax = dbx; + day = dby; + dist_axial = dist_box; + quadrant = NavScoreItemGetQuadrant(dbx, dby); + } + else if (dcx != 0.0f || dcy != 0.0f) + { + // For overlapping boxes with different centers, use distance between centers + dax = dcx; + day = dcy; + dist_axial = dist_center; + quadrant = NavScoreItemGetQuadrant(dcx, dcy); + } + else + { + // Degenerate case: two overlapping buttons with same center, break ties arbitrarily (note that LastItemId here is really the _previous_ item order, but it doesn't matter) + quadrant = (window->DC.LastItemId < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right; + } + +#if IMGUI_DEBUG_NAV_SCORING + char buf[128]; + if (ImGui::IsMouseHoveringRect(cand.Min, cand.Max)) + { + ImFormatString(buf, IM_ARRAYSIZE(buf), "dbox (%.2f,%.2f->%.4f)\ndcen (%.2f,%.2f->%.4f)\nd (%.2f,%.2f->%.4f)\nnav %c, quadrant %c", dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial, "WENS"[g.NavMoveDir], "WENS"[quadrant]); + ImDrawList* draw_list = ImGui::GetOverlayDrawList(); + draw_list->AddRect(curr.Min, curr.Max, IM_COL32(255,200,0,100)); + draw_list->AddRect(cand.Min, cand.Max, IM_COL32(255,255,0,200)); + draw_list->AddRectFilled(cand.Max-ImVec2(4,4), cand.Max+ImGui::CalcTextSize(buf)+ImVec2(4,4), IM_COL32(40,0,0,150)); + draw_list->AddText(g.IO.FontDefault, 13.0f, cand.Max, ~0U, buf); + } + else if (g.IO.KeyCtrl) // Hold to preview score in matching quadrant. Press C to rotate. + { + if (IsKeyPressedMap(ImGuiKey_C)) { g.NavMoveDirLast = (ImGuiDir)((g.NavMoveDirLast + 1) & 3); g.IO.KeysDownDuration[g.IO.KeyMap[ImGuiKey_C]] = 0.01f; } + if (quadrant == g.NavMoveDir) + { + ImFormatString(buf, IM_ARRAYSIZE(buf), "%.0f/%.0f", dist_box, dist_center); + ImDrawList* draw_list = ImGui::GetOverlayDrawList(); + draw_list->AddRectFilled(cand.Min, cand.Max, IM_COL32(255, 0, 0, 200)); + draw_list->AddText(g.IO.FontDefault, 13.0f, cand.Min, IM_COL32(255, 255, 255, 255), buf); + } + } + #endif + + // Is it in the quadrant we're interesting in moving to? + bool new_best = false; + if (quadrant == g.NavMoveDir) + { + // Does it beat the current best candidate? + if (dist_box < result->DistBox) + { + result->DistBox = dist_box; + result->DistCenter = dist_center; + return true; + } + if (dist_box == result->DistBox) + { + // Try using distance between center points to break ties + if (dist_center < result->DistCenter) + { + result->DistCenter = dist_center; + new_best = true; + } + else if (dist_center == result->DistCenter) + { + // Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" items + // (with higher index) to the right/downwards by an infinitesimal amount since we the current "best" button already (so it must have a lower index), + // this is fairly easy. This rule ensures that all buttons with dx==dy==0 will end up being linked in order of appearance along the x axis. + if (((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) ? dby : dbx) < 0.0f) // moving bj to the right/down decreases distance + new_best = true; + } + } + } + + // Axial check: if 'curr' has no link at all in some direction and 'cand' lies roughly in that direction, add a tentative link. This will only be kept if no "real" matches + // are found, so it only augments the graph produced by the above method using extra links. (important, since it doesn't guarantee strong connectedness) + // This is just to avoid buttons having no links in a particular direction when there's a suitable neighbor. you get good graphs without this too. + // 2017/09/29: FIXME: This now currently only enabled inside menu bars, ideally we'd disable it everywhere. Menus in particular need to catch failure. For general navigation it feels awkward. + // Disabling it may lead to disconnected graphs when nodes are very spaced out on different axis. Perhaps consider offering this as an option? + if (result->DistBox == FLT_MAX && dist_axial < result->DistAxial) // Check axial match + if (g.NavLayer == 1 && !(g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) + if ((g.NavMoveDir == ImGuiDir_Left && dax < 0.0f) || (g.NavMoveDir == ImGuiDir_Right && dax > 0.0f) || (g.NavMoveDir == ImGuiDir_Up && day < 0.0f) || (g.NavMoveDir == ImGuiDir_Down && day > 0.0f)) + { + result->DistAxial = dist_axial; + new_best = true; + } + + return new_best; +} + +static void NavSaveLastChildNavWindow(ImGuiWindow* child_window) +{ + ImGuiWindow* parent_window = child_window; + while (parent_window && (parent_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (parent_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0) + parent_window = parent_window->ParentWindow; + if (parent_window && parent_window != child_window) + parent_window->NavLastChildNavWindow = child_window; +} + +// Call when we are expected to land on Layer 0 after FocusWindow() +static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window) +{ + return window->NavLastChildNavWindow ? window->NavLastChildNavWindow : window; +} + +static void NavRestoreLayer(int layer) +{ + ImGuiContext& g = *GImGui; + g.NavLayer = layer; + if (layer == 0) + g.NavWindow = NavRestoreLastChildNavWindow(g.NavWindow); + if (layer == 0 && g.NavWindow->NavLastIds[0] != 0) + SetNavIDWithRectRel(g.NavWindow->NavLastIds[0], layer, g.NavWindow->NavRectRel[0]); + else + ImGui::NavInitWindow(g.NavWindow, true); +} + +static inline void NavUpdateAnyRequestFlag() +{ + ImGuiContext& g = *GImGui; + g.NavAnyRequest = g.NavMoveRequest || g.NavInitRequest || (IMGUI_DEBUG_NAV_SCORING && g.NavWindow != NULL); + if (g.NavAnyRequest) + IM_ASSERT(g.NavWindow != NULL); +} + +static bool NavMoveRequestButNoResultYet() +{ + ImGuiContext& g = *GImGui; + return g.NavMoveRequest && g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0; +} + +void ImGui::NavMoveRequestCancel() +{ + ImGuiContext& g = *GImGui; + g.NavMoveRequest = false; + NavUpdateAnyRequestFlag(); +} + +// We get there when either NavId == id, or when g.NavAnyRequest is set (which is updated by NavUpdateAnyRequestFlag above) +static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id) +{ + ImGuiContext& g = *GImGui; + //if (!g.IO.NavActive) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag. + // return; + + const ImGuiItemFlags item_flags = window->DC.ItemFlags; + const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); + + // Process Init Request + if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent) + { + // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback + if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus) || g.NavInitResultId == 0) + { + g.NavInitResultId = id; + g.NavInitResultRectRel = nav_bb_rel; + } + if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) + { + g.NavInitRequest = false; // Found a match, clear request + NavUpdateAnyRequestFlag(); + } + } + + // Process Move Request (scoring for navigation) + // FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRectScreen + scoring from a rect wrapped according to current wrapping policy) + if ((g.NavId != id || (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & ImGuiItemFlags_NoNav)) + { + ImGuiNavMoveResult* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther; +#if IMGUI_DEBUG_NAV_SCORING + // [DEBUG] Score all items in NavWindow at all times + if (!g.NavMoveRequest) + g.NavMoveDir = g.NavMoveDirLast; + bool new_best = NavScoreItem(result, nav_bb) && g.NavMoveRequest; +#else + bool new_best = g.NavMoveRequest && NavScoreItem(result, nav_bb); +#endif + if (new_best) + { + result->ID = id; + result->Window = window; + result->RectRel = nav_bb_rel; + } + + const float VISIBLE_RATIO = 0.70f; + if ((g.NavMoveRequestFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb)) + if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) - ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >= (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO) + if (NavScoreItem(&g.NavMoveResultLocalVisibleSet, nav_bb)) + { + result = &g.NavMoveResultLocalVisibleSet; + result->ID = id; + result->Window = window; + result->RectRel = nav_bb_rel; + } + } + + // Update window-relative bounding box of navigated item + if (g.NavId == id) + { + g.NavWindow = window; // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window. + g.NavLayer = window->DC.NavLayerCurrent; + g.NavIdIsAlive = true; + g.NavIdTabCounter = window->FocusIdxTabCounter; + window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; // Store item bounding box (relative to window position) + } +} + +// Declare item bounding box for clipping and interaction. +// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface +// declare their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd(). +bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + if (id != 0) + { + // Navigation processing runs prior to clipping early-out + // (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget + // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests unfortunately, but it is still limited to one window. + // it may not scale very well for windows with ten of thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame. + // We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) + window->DC.NavLayerActiveMaskNext |= window->DC.NavLayerCurrentMask; + if (g.NavId == id || g.NavAnyRequest) + if (g.NavWindow->RootWindowForNav == window->RootWindowForNav) + if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened)) + NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id); + } + + window->DC.LastItemId = id; + window->DC.LastItemRect = bb; + window->DC.LastItemStatusFlags = 0; + + // Clipping test + const bool is_clipped = IsClippedEx(bb, id, false); + if (is_clipped) + return false; + //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] + + // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them) + if (IsMouseHoveringRect(bb.Min, bb.Max)) + window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredRect; + return true; +} + +// This is roughly matching the behavior of internal-facing ItemHoverable() +// - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered() +// - this should work even for non-interactive items that have no ID, so we cannot use LastItemId +bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if (g.NavDisableMouseHover && !g.NavDisableHighlight) + return IsItemFocused(); + + // Test for bounding box overlap, as updated as ItemAdd() + if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect)) + return false; + IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0); // Flags not supported by this function + + // Test if we are hovering the right window (our window could be behind another window) + // [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable to use IsItemHovered() after EndChild() itself. + // Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was the test that has been running for a long while. + //if (g.HoveredWindow != window) + // return false; + if (g.HoveredRootWindow != window->RootWindow && !(flags & ImGuiHoveredFlags_AllowWhenOverlapped)) + return false; + + // Test if another item is active (e.g. being dragged) + if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) + if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId) + return false; + + // Test if interactions on this window are blocked by an active popup or modal + if (!IsWindowContentHoverable(window, flags)) + return false; + + // Test if the item is disabled + if ((window->DC.ItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled)) + return false; + + // Special handling for the 1st item after Begin() which represent the title bar. When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect tht case. + if (window->DC.LastItemId == window->MoveId && window->WriteAccessed) + return false; + return true; +} + +// Internal facing ItemHoverable() used when submitting widgets. Differs slightly from IsItemHovered(). +bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id) +{ + ImGuiContext& g = *GImGui; + if (g.HoveredId != 0 && g.HoveredId != id && !g.HoveredIdAllowOverlap) + return false; + + ImGuiWindow* window = g.CurrentWindow; + if (g.HoveredWindow != window) + return false; + if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap) + return false; + if (!IsMouseHoveringRect(bb.Min, bb.Max)) + return false; + if (g.NavDisableMouseHover || !IsWindowContentHoverable(window, ImGuiHoveredFlags_None)) + return false; + if (window->DC.ItemFlags & ImGuiItemFlags_Disabled) + return false; + + SetHoveredID(id); + return true; +} + +bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if (!bb.Overlaps(window->ClipRect)) + if (id == 0 || id != g.ActiveId) + if (clip_even_when_logged || !g.LogEnabled) + return true; + return false; +} + +bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop) +{ + ImGuiContext& g = *GImGui; + + const bool allow_keyboard_focus = (window->DC.ItemFlags & (ImGuiItemFlags_AllowKeyboardFocus | ImGuiItemFlags_Disabled)) == ImGuiItemFlags_AllowKeyboardFocus; + window->FocusIdxAllCounter++; + if (allow_keyboard_focus) + window->FocusIdxTabCounter++; + + // Process keyboard input at this point: TAB/Shift-TAB to tab out of the currently focused item. + // Note that we can always TAB out of a widget that doesn't allow tabbing in. + if (tab_stop && (g.ActiveId == id) && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab)) + window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (allow_keyboard_focus ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items. + + if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent) + return true; + if (allow_keyboard_focus && window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent) + { + g.NavJustTabbedId = id; + return true; + } + + return false; +} + +void ImGui::FocusableItemUnregister(ImGuiWindow* window) +{ + window->FocusIdxAllCounter--; + window->FocusIdxTabCounter--; +} + +ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y) +{ + ImGuiContext& g = *GImGui; + ImVec2 content_max; + if (size.x < 0.0f || size.y < 0.0f) + content_max = g.CurrentWindow->Pos + GetContentRegionMax(); + if (size.x <= 0.0f) + size.x = (size.x == 0.0f) ? default_x : ImMax(content_max.x - g.CurrentWindow->DC.CursorPos.x, 4.0f) + size.x; + if (size.y <= 0.0f) + size.y = (size.y == 0.0f) ? default_y : ImMax(content_max.y - g.CurrentWindow->DC.CursorPos.y, 4.0f) + size.y; + return size; +} + +float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x) +{ + if (wrap_pos_x < 0.0f) + return 0.0f; + + ImGuiWindow* window = GetCurrentWindowRead(); + if (wrap_pos_x == 0.0f) + wrap_pos_x = GetContentRegionMax().x + window->Pos.x; + else if (wrap_pos_x > 0.0f) + wrap_pos_x += window->Pos.x - window->Scroll.x; // wrap_pos_x is provided is window local space + + return ImMax(wrap_pos_x - pos.x, 1.0f); +} + +//----------------------------------------------------------------------------- + +void* ImGui::MemAlloc(size_t size) +{ + if (ImGuiContext* ctx = GImGui) + ctx->IO.MetricsActiveAllocations++; + return GImAllocatorAllocFunc(size, GImAllocatorUserData); +} + +void ImGui::MemFree(void* ptr) +{ + if (ptr) + if (ImGuiContext* ctx = GImGui) + ctx->IO.MetricsActiveAllocations--; + return GImAllocatorFreeFunc(ptr, GImAllocatorUserData); +} + +const char* ImGui::GetClipboardText() +{ + return GImGui->IO.GetClipboardTextFn ? GImGui->IO.GetClipboardTextFn(GImGui->IO.ClipboardUserData) : ""; +} + +void ImGui::SetClipboardText(const char* text) +{ + if (GImGui->IO.SetClipboardTextFn) + GImGui->IO.SetClipboardTextFn(GImGui->IO.ClipboardUserData, text); +} + +const char* ImGui::GetVersion() +{ + return IMGUI_VERSION; +} + +// Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself +// Note that we still point to some static data and members (such as GFontAtlas), so the state instance you end up using will point to the static data within its module +ImGuiContext* ImGui::GetCurrentContext() +{ + return GImGui; +} + +void ImGui::SetCurrentContext(ImGuiContext* ctx) +{ +#ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC + IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx); // For custom thread-based hackery you may want to have control over this. +#else + GImGui = ctx; +#endif +} + +// Helper function to verify that the type sizes are matching between the calling file's compilation unit and imgui.cpp's compilation unit +// If the user has inconsistent compilation settings, imgui configuration #define, packing pragma, etc. you may see different structures from what imgui.cpp sees which is highly problematic. +bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_vert) +{ + bool error = false; + if (strcmp(version, IMGUI_VERSION)!=0) { error = true; IM_ASSERT(strcmp(version,IMGUI_VERSION)==0 && "Mismatch version string!"); } + if (sz_io != sizeof(ImGuiIO)) { error = true; IM_ASSERT(sz_io == sizeof(ImGuiIO) && "Mismatched struct layout!"); } + if (sz_style != sizeof(ImGuiStyle)) { error = true; IM_ASSERT(sz_style == sizeof(ImGuiStyle) && "Mismatched struct layout!"); } + if (sz_vec2 != sizeof(ImVec2)) { error = true; IM_ASSERT(sz_vec2 == sizeof(ImVec2) && "Mismatched struct layout!"); } + if (sz_vec4 != sizeof(ImVec4)) { error = true; IM_ASSERT(sz_vec4 == sizeof(ImVec4) && "Mismatched struct layout!"); } + if (sz_vert != sizeof(ImDrawVert)) { error = true; IM_ASSERT(sz_vert == sizeof(ImDrawVert) && "Mismatched struct layout!"); } + return !error; +} + +void ImGui::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void(*free_func)(void* ptr, void* user_data), void* user_data) +{ + GImAllocatorAllocFunc = alloc_func; + GImAllocatorFreeFunc = free_func; + GImAllocatorUserData = user_data; +} + +ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas) +{ + ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas); + if (GImGui == NULL) + SetCurrentContext(ctx); + Initialize(ctx); + return ctx; +} + +void ImGui::DestroyContext(ImGuiContext* ctx) +{ + if (ctx == NULL) + ctx = GImGui; + Shutdown(ctx); + if (GImGui == ctx) + SetCurrentContext(NULL); + IM_DELETE(ctx); +} + +ImGuiIO& ImGui::GetIO() +{ + IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?"); + return GImGui->IO; +} + +ImGuiStyle& ImGui::GetStyle() +{ + IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?"); + return GImGui->Style; +} + +// Same value as passed to the old io.RenderDrawListsFn function. Valid after Render() and until the next call to NewFrame() +ImDrawData* ImGui::GetDrawData() +{ + ImGuiContext& g = *GImGui; + return g.DrawData.Valid ? &g.DrawData : NULL; +} + +double ImGui::GetTime() +{ + return GImGui->Time; +} + +int ImGui::GetFrameCount() +{ + return GImGui->FrameCount; +} + +ImDrawList* ImGui::GetOverlayDrawList() +{ + return &GImGui->OverlayDrawList; +} + +ImDrawListSharedData* ImGui::GetDrawListSharedData() +{ + return &GImGui->DrawListSharedData; +} + +// This needs to be called before we submit any widget (aka in or before Begin) +void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(window == g.NavWindow); + bool init_for_nav = false; + if (!(window->Flags & ImGuiWindowFlags_NoNavInputs)) + if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit) + init_for_nav = true; + if (init_for_nav) + { + SetNavID(0, g.NavLayer); + g.NavInitRequest = true; + g.NavInitRequestFromMove = false; + g.NavInitResultId = 0; + g.NavInitResultRectRel = ImRect(); + NavUpdateAnyRequestFlag(); + } + else + { + g.NavId = window->NavLastIds[0]; + } +} + +static ImVec2 NavCalcPreferredRefPos() +{ + ImGuiContext& g = *GImGui; + if (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow) + return ImFloor(g.IO.MousePos); + + // When navigation is active and mouse is disabled, decide on an arbitrary position around the bottom left of the currently navigated item + const ImRect& rect_rel = g.NavWindow->NavRectRel[g.NavLayer]; + ImVec2 pos = g.NavWindow->Pos + ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x*4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight())); + ImRect visible_rect = GetViewportRect(); + return ImFloor(ImClamp(pos, visible_rect.Min, visible_rect.Max)); // ImFloor() is important because non-integer mouse position application in back-end might be lossy and result in undesirable non-zero delta. +} + +static int FindWindowIndex(ImGuiWindow* window) // FIXME-OPT O(N) +{ + ImGuiContext& g = *GImGui; + for (int i = g.Windows.Size-1; i >= 0; i--) + if (g.Windows[i] == window) + return i; + return -1; +} + +static ImGuiWindow* FindWindowNavFocusable(int i_start, int i_stop, int dir) // FIXME-OPT O(N) +{ + ImGuiContext& g = *GImGui; + for (int i = i_start; i >= 0 && i < g.Windows.Size && i != i_stop; i += dir) + if (ImGui::IsWindowNavFocusable(g.Windows[i])) + return g.Windows[i]; + return NULL; +} + +float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode) +{ + ImGuiContext& g = *GImGui; + if (mode == ImGuiInputReadMode_Down) + return g.IO.NavInputs[n]; // Instant, read analog input (0.0f..1.0f, as provided by user) + + const float t = g.IO.NavInputsDownDuration[n]; + if (t < 0.0f && mode == ImGuiInputReadMode_Released) // Return 1.0f when just released, no repeat, ignore analog input. + return (g.IO.NavInputsDownDurationPrev[n] >= 0.0f ? 1.0f : 0.0f); + if (t < 0.0f) + return 0.0f; + if (mode == ImGuiInputReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input. + return (t == 0.0f) ? 1.0f : 0.0f; + if (mode == ImGuiInputReadMode_Repeat) + return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.80f); + if (mode == ImGuiInputReadMode_RepeatSlow) + return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 1.00f, g.IO.KeyRepeatRate * 2.00f); + if (mode == ImGuiInputReadMode_RepeatFast) + return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.30f); + return 0.0f; +} + +// Equivalent of IsKeyDown() for NavInputs[] +static bool IsNavInputDown(ImGuiNavInput n) +{ + return GImGui->IO.NavInputs[n] > 0.0f; +} + +// Equivalent of IsKeyPressed() for NavInputs[] +static bool IsNavInputPressed(ImGuiNavInput n, ImGuiInputReadMode mode) +{ + return ImGui::GetNavInputAmount(n, mode) > 0.0f; +} + +static bool IsNavInputPressedAnyOfTwo(ImGuiNavInput n1, ImGuiNavInput n2, ImGuiInputReadMode mode) +{ + return (ImGui::GetNavInputAmount(n1, mode) + ImGui::GetNavInputAmount(n2, mode)) > 0.0f; +} + +ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor, float fast_factor) +{ + ImVec2 delta(0.0f, 0.0f); + if (dir_sources & ImGuiNavDirSourceFlags_Keyboard) + delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight_, mode) - GetNavInputAmount(ImGuiNavInput_KeyLeft_, mode), GetNavInputAmount(ImGuiNavInput_KeyDown_, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp_, mode)); + if (dir_sources & ImGuiNavDirSourceFlags_PadDPad) + delta += ImVec2(GetNavInputAmount(ImGuiNavInput_DpadRight, mode) - GetNavInputAmount(ImGuiNavInput_DpadLeft, mode), GetNavInputAmount(ImGuiNavInput_DpadDown, mode) - GetNavInputAmount(ImGuiNavInput_DpadUp, mode)); + if (dir_sources & ImGuiNavDirSourceFlags_PadLStick) + delta += ImVec2(GetNavInputAmount(ImGuiNavInput_LStickRight, mode) - GetNavInputAmount(ImGuiNavInput_LStickLeft, mode), GetNavInputAmount(ImGuiNavInput_LStickDown, mode) - GetNavInputAmount(ImGuiNavInput_LStickUp, mode)); + if (slow_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakSlow)) + delta *= slow_factor; + if (fast_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakFast)) + delta *= fast_factor; + return delta; +} + +static void NavUpdateWindowingHighlightWindow(int focus_change_dir) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.NavWindowingTarget); + if (g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal) + return; + + const int i_current = FindWindowIndex(g.NavWindowingTarget); + ImGuiWindow* window_target = FindWindowNavFocusable(i_current + focus_change_dir, -INT_MAX, focus_change_dir); + if (!window_target) + window_target = FindWindowNavFocusable((focus_change_dir < 0) ? (g.Windows.Size - 1) : 0, i_current, focus_change_dir); + if (window_target) // Don't reset windowing target if there's a single window in the list + g.NavWindowingTarget = g.NavWindowingTargetAnim = window_target; + g.NavWindowingToggleLayer = false; +} + +// Window management mode (hold to: change focus/move/resize, tap to: toggle menu layer) +static void ImGui::NavUpdateWindowing() +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* apply_focus_window = NULL; + bool apply_toggle_layer = false; + + ImGuiWindow* modal_window = GetFrontMostPopupModal(); + if (modal_window != NULL) + { + g.NavWindowingTarget = NULL; + return; + } + + // Fade out + if (g.NavWindowingTargetAnim && g.NavWindowingTarget == NULL) + { + g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha - g.IO.DeltaTime * 10.0f, 0.0f); + if (g.DimBgRatio <= 0.0f && g.NavWindowingHighlightAlpha <= 0.0f) + g.NavWindowingTargetAnim = NULL; + } + + // Start CTRL-TAB or Square+L/R window selection + bool start_windowing_with_gamepad = !g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed); + bool start_windowing_with_keyboard = !g.NavWindowingTarget && g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard); + if (start_windowing_with_gamepad || start_windowing_with_keyboard) + if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.Windows.Size - 1, -INT_MAX, -1)) + { + g.NavWindowingTarget = g.NavWindowingTargetAnim = window; + g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f; + g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true; + g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_NavKeyboard : ImGuiInputSource_NavGamepad; + } + + // Gamepad update + g.NavWindowingTimer += g.IO.DeltaTime; + if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavGamepad) + { + // Highlight only appears after a brief time holding the button, so that a fast tap on PadMenu (to toggle NavLayer) doesn't add visual noise + g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); + + // Select window to focus + const int focus_change_dir = (int)IsNavInputPressed(ImGuiNavInput_FocusPrev, ImGuiInputReadMode_RepeatSlow) - (int)IsNavInputPressed(ImGuiNavInput_FocusNext, ImGuiInputReadMode_RepeatSlow); + if (focus_change_dir != 0) + { + NavUpdateWindowingHighlightWindow(focus_change_dir); + g.NavWindowingHighlightAlpha = 1.0f; + } + + // Single press toggles NavLayer, long press with L/R apply actual focus on release (until then the window was merely rendered front-most) + if (!IsNavInputDown(ImGuiNavInput_Menu)) + { + g.NavWindowingToggleLayer &= (g.NavWindowingHighlightAlpha < 1.0f); // Once button was held long enough we don't consider it a tap-to-toggle-layer press anymore. + if (g.NavWindowingToggleLayer && g.NavWindow) + apply_toggle_layer = true; + else if (!g.NavWindowingToggleLayer) + apply_focus_window = g.NavWindowingTarget; + g.NavWindowingTarget = NULL; + } + } + + // Keyboard: Focus + if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavKeyboard) + { + // Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise + g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // 1.0f + if (IsKeyPressedMap(ImGuiKey_Tab, true)) + NavUpdateWindowingHighlightWindow(g.IO.KeyShift ? +1 : -1); + if (!g.IO.KeyCtrl) + apply_focus_window = g.NavWindowingTarget; + } + + // Keyboard: Press and Release ALT to toggle menu layer + // FIXME: We lack an explicit IO variable for "is the imgui window focused", so compare mouse validity to detect the common case of back-end clearing releases all keys on ALT-TAB + if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && IsNavInputPressed(ImGuiNavInput_KeyMenu_, ImGuiInputReadMode_Released)) + if (IsMousePosValid(&g.IO.MousePos) == IsMousePosValid(&g.IO.MousePosPrev)) + apply_toggle_layer = true; + + // Move window + if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) + { + ImVec2 move_delta; + if (g.NavInputSource == ImGuiInputSource_NavKeyboard && !g.IO.KeyShift) + move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down); + if (g.NavInputSource == ImGuiInputSource_NavGamepad) + move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down); + if (move_delta.x != 0.0f || move_delta.y != 0.0f) + { + const float NAV_MOVE_SPEED = 800.0f; + const float move_speed = ImFloor(NAV_MOVE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); // FIXME: Doesn't code variable framerate very well + g.NavWindowingTarget->RootWindow->Pos += move_delta * move_speed; + g.NavDisableMouseHover = true; + MarkIniSettingsDirty(g.NavWindowingTarget); + } + } + + // Apply final focus + if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindow)) + { + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; + apply_focus_window = NavRestoreLastChildNavWindow(apply_focus_window); + ClosePopupsOverWindow(apply_focus_window); + FocusWindow(apply_focus_window); + if (apply_focus_window->NavLastIds[0] == 0) + NavInitWindow(apply_focus_window, false); + + // If the window only has a menu layer, select it directly + if (apply_focus_window->DC.NavLayerActiveMask == (1 << 1)) + g.NavLayer = 1; + } + if (apply_focus_window) + g.NavWindowingTarget = NULL; + + // Apply menu/layer toggle + if (apply_toggle_layer && g.NavWindow) + { + // Move to parent menu if necessary + ImGuiWindow* new_nav_window = g.NavWindow; + while ((new_nav_window->DC.NavLayerActiveMask & (1 << 1)) == 0 && (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0) + new_nav_window = new_nav_window->ParentWindow; + + if (new_nav_window != g.NavWindow) + { + ImGuiWindow* old_nav_window = g.NavWindow; + FocusWindow(new_nav_window); + new_nav_window->NavLastChildNavWindow = old_nav_window; + } + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; + NavRestoreLayer((g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) ? (g.NavLayer ^ 1) : 0); + } +} + +// Window has already passed the IsWindowNavFocusable() +static const char* GetFallbackWindowNameForWindowingList(ImGuiWindow* window) +{ + if (window->Flags & ImGuiWindowFlags_Popup) + return "(Popup)"; + if ((window->Flags & ImGuiWindowFlags_MenuBar) && strcmp(window->Name, "##MainMenuBar") == 0) + return "(Main menu bar)"; + return "(Untitled)"; +} + +// Overlay displayed when using CTRL+TAB. Called by EndFrame(). +void ImGui::NavUpdateWindowingList() +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.NavWindowingTarget != NULL); + + if (g.NavWindowingTimer < NAV_WINDOWING_LIST_APPEAR_DELAY) + return; + + if (g.NavWindowingList == NULL) + g.NavWindowingList = FindWindowByName("###NavWindowingList"); + SetNextWindowSizeConstraints(ImVec2(g.IO.DisplaySize.x * 0.20f, g.IO.DisplaySize.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX)); + SetNextWindowPos(g.IO.DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); + PushStyleVar(ImGuiStyleVar_WindowPadding, g.Style.WindowPadding * 2.0f); + Begin("###NavWindowingList", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings); + for (int n = g.Windows.Size - 1; n >= 0; n--) + { + ImGuiWindow* window = g.Windows[n]; + if (!IsWindowNavFocusable(window)) + continue; + const char* label = window->Name; + if (label == FindRenderedTextEnd(label)) + label = GetFallbackWindowNameForWindowingList(window); + Selectable(label, g.NavWindowingTarget == window); + } + End(); + PopStyleVar(); +} + +// Scroll to keep newly navigated item fully into view +// NB: We modify rect_rel by the amount we scrolled for, so it is immediately updated. +static void NavScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect) +{ + ImRect window_rect(window->InnerMainRect.Min - ImVec2(1, 1), window->InnerMainRect.Max + ImVec2(1, 1)); + //g.OverlayDrawList.AddRect(window_rect.Min, window_rect.Max, IM_COL32_WHITE); // [DEBUG] + if (window_rect.Contains(item_rect)) + return; + + ImGuiContext& g = *GImGui; + if (window->ScrollbarX && item_rect.Min.x < window_rect.Min.x) + { + window->ScrollTarget.x = item_rect.Min.x - window->Pos.x + window->Scroll.x - g.Style.ItemSpacing.x; + window->ScrollTargetCenterRatio.x = 0.0f; + } + else if (window->ScrollbarX && item_rect.Max.x >= window_rect.Max.x) + { + window->ScrollTarget.x = item_rect.Max.x - window->Pos.x + window->Scroll.x + g.Style.ItemSpacing.x; + window->ScrollTargetCenterRatio.x = 1.0f; + } + if (item_rect.Min.y < window_rect.Min.y) + { + window->ScrollTarget.y = item_rect.Min.y - window->Pos.y + window->Scroll.y - g.Style.ItemSpacing.y; + window->ScrollTargetCenterRatio.y = 0.0f; + } + else if (item_rect.Max.y >= window_rect.Max.y) + { + window->ScrollTarget.y = item_rect.Max.y - window->Pos.y + window->Scroll.y + g.Style.ItemSpacing.y; + window->ScrollTargetCenterRatio.y = 1.0f; + } +} + +static void ImGui::NavUpdate() +{ + ImGuiContext& g = *GImGui; + g.IO.WantSetMousePos = false; + +#if 0 + if (g.NavScoringCount > 0) printf("[%05d] NavScoringCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.FrameCount, g.NavScoringCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest); +#endif + + bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0; + bool nav_gamepad_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; + + // Set input source as Gamepad when buttons are pressed before we map Keyboard (some features differs when used with Gamepad vs Keyboard) + if (nav_gamepad_active) + if (g.IO.NavInputs[ImGuiNavInput_Activate] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Input] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Cancel] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Menu] > 0.0f) + g.NavInputSource = ImGuiInputSource_NavGamepad; + + // Update Keyboard->Nav inputs mapping + if (nav_keyboard_active) + { + #define NAV_MAP_KEY(_KEY, _NAV_INPUT) if (IsKeyDown(g.IO.KeyMap[_KEY])) { g.IO.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_NavKeyboard; } + NAV_MAP_KEY(ImGuiKey_Space, ImGuiNavInput_Activate ); + NAV_MAP_KEY(ImGuiKey_Enter, ImGuiNavInput_Input ); + NAV_MAP_KEY(ImGuiKey_Escape, ImGuiNavInput_Cancel ); + NAV_MAP_KEY(ImGuiKey_LeftArrow, ImGuiNavInput_KeyLeft_ ); + NAV_MAP_KEY(ImGuiKey_RightArrow,ImGuiNavInput_KeyRight_); + NAV_MAP_KEY(ImGuiKey_UpArrow, ImGuiNavInput_KeyUp_ ); + NAV_MAP_KEY(ImGuiKey_DownArrow, ImGuiNavInput_KeyDown_ ); + if (g.IO.KeyCtrl) g.IO.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f; + if (g.IO.KeyShift) g.IO.NavInputs[ImGuiNavInput_TweakFast] = 1.0f; + if (g.IO.KeyAlt) g.IO.NavInputs[ImGuiNavInput_KeyMenu_] = 1.0f; + #undef NAV_MAP_KEY + } + + memcpy(g.IO.NavInputsDownDurationPrev, g.IO.NavInputsDownDuration, sizeof(g.IO.NavInputsDownDuration)); + for (int i = 0; i < IM_ARRAYSIZE(g.IO.NavInputs); i++) + g.IO.NavInputsDownDuration[i] = (g.IO.NavInputs[i] > 0.0f) ? (g.IO.NavInputsDownDuration[i] < 0.0f ? 0.0f : g.IO.NavInputsDownDuration[i] + g.IO.DeltaTime) : -1.0f; + + // Process navigation init request (select first/default focus) + if (g.NavInitResultId != 0 && (!g.NavDisableHighlight || g.NavInitRequestFromMove)) + { + // Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called) + IM_ASSERT(g.NavWindow); + if (g.NavInitRequestFromMove) + SetNavIDWithRectRel(g.NavInitResultId, g.NavLayer, g.NavInitResultRectRel); + else + SetNavID(g.NavInitResultId, g.NavLayer); + g.NavWindow->NavRectRel[g.NavLayer] = g.NavInitResultRectRel; + } + g.NavInitRequest = false; + g.NavInitRequestFromMove = false; + g.NavInitResultId = 0; + g.NavJustMovedToId = 0; + + // Process navigation move request + if (g.NavMoveRequest && (g.NavMoveResultLocal.ID != 0 || g.NavMoveResultOther.ID != 0)) + { + // Select which result to use + ImGuiNavMoveResult* result = (g.NavMoveResultLocal.ID != 0) ? &g.NavMoveResultLocal : &g.NavMoveResultOther; + + // PageUp/PageDown behavior first jumps to the bottom/top mostly visible item, _otherwise_ use the result from the previous/next page. + if (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) + if (g.NavMoveResultLocalVisibleSet.ID != 0 && g.NavMoveResultLocalVisibleSet.ID != g.NavId) + result = &g.NavMoveResultLocalVisibleSet; + + // Maybe entering a flattened child from the outside? In this case solve the tie using the regular scoring rules. + if (result != &g.NavMoveResultOther && g.NavMoveResultOther.ID != 0 && g.NavMoveResultOther.Window->ParentWindow == g.NavWindow) + if ((g.NavMoveResultOther.DistBox < result->DistBox) || (g.NavMoveResultOther.DistBox == result->DistBox && g.NavMoveResultOther.DistCenter < result->DistCenter)) + result = &g.NavMoveResultOther; + IM_ASSERT(g.NavWindow && result->Window); + + // Scroll to keep newly navigated item fully into view. + if (g.NavLayer == 0) + { + ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos); + NavScrollToBringItemIntoView(result->Window, rect_abs); + + // Estimate upcoming scroll so we can offset our result position so mouse position can be applied immediately after in NavUpdate() + ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(result->Window, false); + ImVec2 delta_scroll = result->Window->Scroll - next_scroll; + result->RectRel.Translate(delta_scroll); + + // Also scroll parent window to keep us into view if necessary (we could/should technically recurse back the whole the parent hierarchy). + if (result->Window->Flags & ImGuiWindowFlags_ChildWindow) + NavScrollToBringItemIntoView(result->Window->ParentWindow, ImRect(rect_abs.Min + delta_scroll, rect_abs.Max + delta_scroll)); + } + + // Apply result from previous frame navigation directional move request + ClearActiveID(); + g.NavWindow = result->Window; + SetNavIDWithRectRel(result->ID, g.NavLayer, result->RectRel); + g.NavJustMovedToId = result->ID; + g.NavMoveFromClampedRefRect = false; + } + + // When a forwarded move request failed, we restore the highlight that we disabled during the forward frame + if (g.NavMoveRequestForward == ImGuiNavForward_ForwardActive) + { + IM_ASSERT(g.NavMoveRequest); + if (g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0) + g.NavDisableHighlight = false; + g.NavMoveRequestForward = ImGuiNavForward_None; + } + + // Apply application mouse position movement, after we had a chance to process move request result. + if (g.NavMousePosDirty && g.NavIdIsAlive) + { + // Set mouse position given our knowledge of the navigated item position from last frame + if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (g.IO.BackendFlags & ImGuiBackendFlags_HasSetMousePos)) + { + if (!g.NavDisableHighlight && g.NavDisableMouseHover && g.NavWindow) + { + g.IO.MousePos = g.IO.MousePosPrev = NavCalcPreferredRefPos(); + g.IO.WantSetMousePos = true; + } + } + g.NavMousePosDirty = false; + } + g.NavIdIsAlive = false; + g.NavJustTabbedId = 0; + IM_ASSERT(g.NavLayer == 0 || g.NavLayer == 1); + + // Store our return window (for returning from Layer 1 to Layer 0) and clear it as soon as we step back in our own Layer 0 + if (g.NavWindow) + NavSaveLastChildNavWindow(g.NavWindow); + if (g.NavWindow && g.NavWindow->NavLastChildNavWindow != NULL && g.NavLayer == 0) + g.NavWindow->NavLastChildNavWindow = NULL; + + NavUpdateWindowing(); + + // Set output flags for user application + g.IO.NavActive = (nav_keyboard_active || nav_gamepad_active) && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs); + g.IO.NavVisible = (g.IO.NavActive && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavInitRequest; + + // Process NavCancel input (to close a popup, get back to parent, clear focus) + if (IsNavInputPressed(ImGuiNavInput_Cancel, ImGuiInputReadMode_Pressed)) + { + if (g.ActiveId != 0) + { + ClearActiveID(); + } + else if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow) && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow) + { + // Exit child window + ImGuiWindow* child_window = g.NavWindow; + ImGuiWindow* parent_window = g.NavWindow->ParentWindow; + IM_ASSERT(child_window->ChildId != 0); + FocusWindow(parent_window); + SetNavID(child_window->ChildId, 0); + g.NavIdIsAlive = false; + if (g.NavDisableMouseHover) + g.NavMousePosDirty = true; + } + else if (g.OpenPopupStack.Size > 0) + { + // Close open popup/menu + if (!(g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal)) + ClosePopupToLevel(g.OpenPopupStack.Size - 1); + } + else if (g.NavLayer != 0) + { + // Leave the "menu" layer + NavRestoreLayer(0); + } + else + { + // Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were + if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup) || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow))) + g.NavWindow->NavLastIds[0] = 0; + g.NavId = 0; + } + } + + // Process manual activation request + g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavInputId = 0; + if (g.NavId != 0 && !g.NavDisableHighlight && !g.NavWindowingTarget && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) + { + bool activate_down = IsNavInputDown(ImGuiNavInput_Activate); + bool activate_pressed = activate_down && IsNavInputPressed(ImGuiNavInput_Activate, ImGuiInputReadMode_Pressed); + if (g.ActiveId == 0 && activate_pressed) + g.NavActivateId = g.NavId; + if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_down) + g.NavActivateDownId = g.NavId; + if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_pressed) + g.NavActivatePressedId = g.NavId; + if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && IsNavInputPressed(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed)) + g.NavInputId = g.NavId; + } + if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) + g.NavDisableHighlight = true; + if (g.NavActivateId != 0) + IM_ASSERT(g.NavActivateDownId == g.NavActivateId); + g.NavMoveRequest = false; + + // Process programmatic activation request + if (g.NavNextActivateId != 0) + g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavInputId = g.NavNextActivateId; + g.NavNextActivateId = 0; + + // Initiate directional inputs request + const int allowed_dir_flags = (g.ActiveId == 0) ? ~0 : g.ActiveIdAllowNavDirFlags; + if (g.NavMoveRequestForward == ImGuiNavForward_None) + { + g.NavMoveDir = ImGuiDir_None; + g.NavMoveRequestFlags = 0; + if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) + { + if ((allowed_dir_flags & (1<Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget && g.NavLayer == 0) + { + ImGuiWindow* window = g.NavWindow; + bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up)); + bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down)); + if ((page_up_held && !page_down_held) || (page_down_held && !page_up_held)) + { + if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll) + { + // Fallback manual-scroll when window has no navigable item + if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true)) + SetWindowScrollY(window, window->Scroll.y - window->InnerClipRect.GetHeight()); + else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true)) + SetWindowScrollY(window, window->Scroll.y + window->InnerClipRect.GetHeight()); + } + else + { + const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer]; + const float page_offset_y = ImMax(0.0f, window->InnerClipRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight()); + if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true)) + { + nav_scoring_rect_offset_y = -page_offset_y; + g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item) + g.NavMoveClipDir = ImGuiDir_Up; + g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet; + } + else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true)) + { + nav_scoring_rect_offset_y = +page_offset_y; + g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item) + g.NavMoveClipDir = ImGuiDir_Down; + g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet; + } + } + } + } + + if (g.NavMoveDir != ImGuiDir_None) + { + g.NavMoveRequest = true; + g.NavMoveDirLast = g.NavMoveDir; + } + + // If we initiate a movement request and have no current NavId, we initiate a InitDefautRequest that will be used as a fallback if the direction fails to find a match + if (g.NavMoveRequest && g.NavId == 0) + { + g.NavInitRequest = g.NavInitRequestFromMove = true; + g.NavInitResultId = 0; + g.NavDisableHighlight = false; + } + + NavUpdateAnyRequestFlag(); + + // Scrolling + if (g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget) + { + // *Fallback* manual-scroll with Nav directional keys when window has no navigable item + ImGuiWindow* window = g.NavWindow; + const float scroll_speed = ImFloor(window->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. + if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll && g.NavMoveRequest) + { + if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) + SetWindowScrollX(window, ImFloor(window->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed)); + if (g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) + SetWindowScrollY(window, ImFloor(window->Scroll.y + ((g.NavMoveDir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed)); + } + + // *Normal* Manual scroll with NavScrollXXX keys + // Next movement request will clamp the NavId reference rectangle to the visible area, so navigation will resume within those bounds. + ImVec2 scroll_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down, 1.0f/10.0f, 10.0f); + if (scroll_dir.x != 0.0f && window->ScrollbarX) + { + SetWindowScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed)); + g.NavMoveFromClampedRefRect = true; + } + if (scroll_dir.y != 0.0f) + { + SetWindowScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed)); + g.NavMoveFromClampedRefRect = true; + } + } + + // Reset search results + g.NavMoveResultLocal.Clear(); + g.NavMoveResultLocalVisibleSet.Clear(); + g.NavMoveResultOther.Clear(); + + // When we have manually scrolled (without using navigation) and NavId becomes out of bounds, we project its bounding box to the visible area to restart navigation within visible items + if (g.NavMoveRequest && g.NavMoveFromClampedRefRect && g.NavLayer == 0) + { + ImGuiWindow* window = g.NavWindow; + ImRect window_rect_rel(window->InnerMainRect.Min - window->Pos - ImVec2(1,1), window->InnerMainRect.Max - window->Pos + ImVec2(1,1)); + if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer])) + { + float pad = window->CalcFontSize() * 0.5f; + window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the intent of starting navigation from first fully visible item + window->NavRectRel[g.NavLayer].ClipWith(window_rect_rel); + g.NavId = 0; + } + g.NavMoveFromClampedRefRect = false; + } + + // For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items) + ImRect nav_rect_rel = (g.NavWindow && !g.NavWindow->NavRectRel[g.NavLayer].IsInverted()) ? g.NavWindow->NavRectRel[g.NavLayer] : ImRect(0,0,0,0); + g.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + nav_rect_rel.Min, g.NavWindow->Pos + nav_rect_rel.Max) : GetViewportRect(); + g.NavScoringRectScreen.TranslateY(nav_scoring_rect_offset_y); + g.NavScoringRectScreen.Min.x = ImMin(g.NavScoringRectScreen.Min.x + 1.0f, g.NavScoringRectScreen.Max.x); + g.NavScoringRectScreen.Max.x = g.NavScoringRectScreen.Min.x; + IM_ASSERT(!g.NavScoringRectScreen.IsInverted()); // Ensure if we have a finite, non-inverted bounding box here will allows us to remove extraneous ImFabs() calls in NavScoreItem(). + //g.OverlayDrawList.AddRect(g.NavScoringRectScreen.Min, g.NavScoringRectScreen.Max, IM_COL32(255,200,0,255)); // [DEBUG] + g.NavScoringCount = 0; +#if IMGUI_DEBUG_NAV_RECTS + if (g.NavWindow) { for (int layer = 0; layer < 2; layer++) GetOverlayDrawList()->AddRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Max, IM_COL32(255,200,0,255)); } // [DEBUG] + if (g.NavWindow) { ImU32 col = (g.NavWindow->HiddenFrames == 0) ? IM_COL32(255,0,255,255) : IM_COL32(255,0,0,255); ImVec2 p = NavCalcPreferredRefPos(); char buf[32]; ImFormatString(buf, 32, "%d", g.NavLayer); g.OverlayDrawList.AddCircleFilled(p, 3.0f, col); g.OverlayDrawList.AddText(NULL, 13.0f, p + ImVec2(8,-4), col, buf); } +#endif +} + +void ImGui::StartMouseMovingWindow(ImGuiWindow* window) +{ + // Set ActiveId even if the _NoMove flag is set. Without it, dragging away from a window with _NoMove would activate hover on other windows. + ImGuiContext& g = *GImGui; + FocusWindow(window); + SetActiveID(window->MoveId, window); + g.NavDisableHighlight = true; + g.ActiveIdClickOffset = g.IO.MousePos - window->RootWindow->Pos; + if (!(window->Flags & ImGuiWindowFlags_NoMove) && !(window->RootWindow->Flags & ImGuiWindowFlags_NoMove)) + g.MovingWindow = window; +} + +// Handle mouse moving window +// Note: moving window with the navigation keys (Square + d-pad / CTRL+TAB + Arrows) are processed in NavUpdateWindowing() +void ImGui::UpdateMouseMovingWindow() +{ + ImGuiContext& g = *GImGui; + if (g.MovingWindow != NULL) + { + // We actually want to move the root window. g.MovingWindow == window we clicked on (could be a child window). + // We track it to preserve Focus and so that generally ActiveIdWindow == MovingWindow and ActiveId == MovingWindow->MoveId for consistency. + KeepAliveID(g.ActiveId); + IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindow); + ImGuiWindow* moving_window = g.MovingWindow->RootWindow; + if (g.IO.MouseDown[0] && IsMousePosValid(&g.IO.MousePos)) + { + ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset; + if (moving_window->Pos.x != pos.x || moving_window->Pos.y != pos.y) + { + MarkIniSettingsDirty(moving_window); + SetWindowPos(moving_window, pos, ImGuiCond_Always); + } + FocusWindow(g.MovingWindow); + } + else + { + ClearActiveID(); + g.MovingWindow = NULL; + } + } + else + { + // When clicking/dragging from a window that has the _NoMove flag, we still set the ActiveId in order to prevent hovering others. + if (g.ActiveIdWindow && g.ActiveIdWindow->MoveId == g.ActiveId) + { + KeepAliveID(g.ActiveId); + if (!g.IO.MouseDown[0]) + ClearActiveID(); + } + } +} + +static bool IsWindowActiveAndVisible(ImGuiWindow* window) +{ + return (window->Active) && (!window->Hidden); +} + +static void ImGui::UpdateMouseInputs() +{ + ImGuiContext& g = *GImGui; + + // If mouse just appeared or disappeared (usually denoted by -FLT_MAX component, but in reality we test for -256000.0f) we cancel out movement in MouseDelta + if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MousePosPrev)) + g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev; + else + g.IO.MouseDelta = ImVec2(0.0f, 0.0f); + if (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f) + g.NavDisableMouseHover = false; + + g.IO.MousePosPrev = g.IO.MousePos; + for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) + { + g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f; + g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] >= 0.0f; + g.IO.MouseDownDurationPrev[i] = g.IO.MouseDownDuration[i]; + g.IO.MouseDownDuration[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f; + g.IO.MouseDoubleClicked[i] = false; + if (g.IO.MouseClicked[i]) + { + if ((float)(g.Time - g.IO.MouseClickedTime[i]) < g.IO.MouseDoubleClickTime) + { + ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f); + if (ImLengthSqr(delta_from_click_pos) < g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist) + g.IO.MouseDoubleClicked[i] = true; + g.IO.MouseClickedTime[i] = -FLT_MAX; // so the third click isn't turned into a double-click + } + else + { + g.IO.MouseClickedTime[i] = g.Time; + } + g.IO.MouseClickedPos[i] = g.IO.MousePos; + g.IO.MouseDragMaxDistanceAbs[i] = ImVec2(0.0f, 0.0f); + g.IO.MouseDragMaxDistanceSqr[i] = 0.0f; + } + else if (g.IO.MouseDown[i]) + { + // Maintain the maximum distance we reaching from the initial click position, which is used with dragging threshold + ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f); + g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(delta_from_click_pos)); + g.IO.MouseDragMaxDistanceAbs[i].x = ImMax(g.IO.MouseDragMaxDistanceAbs[i].x, delta_from_click_pos.x < 0.0f ? -delta_from_click_pos.x : delta_from_click_pos.x); + g.IO.MouseDragMaxDistanceAbs[i].y = ImMax(g.IO.MouseDragMaxDistanceAbs[i].y, delta_from_click_pos.y < 0.0f ? -delta_from_click_pos.y : delta_from_click_pos.y); + } + if (g.IO.MouseClicked[i]) // Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation + g.NavDisableMouseHover = false; + } +} + +void ImGui::UpdateMouseWheel() +{ + ImGuiContext& g = *GImGui; + if (!g.HoveredWindow || g.HoveredWindow->Collapsed) + return; + if (g.IO.MouseWheel == 0.0f && g.IO.MouseWheelH == 0.0f) + return; + + // If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent (unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set). + ImGuiWindow* window = g.HoveredWindow; + ImGuiWindow* scroll_window = window; + while ((scroll_window->Flags & ImGuiWindowFlags_ChildWindow) && (scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoScrollbar) && !(scroll_window->Flags & ImGuiWindowFlags_NoInputs) && scroll_window->ParentWindow) + scroll_window = scroll_window->ParentWindow; + const bool scroll_allowed = !(scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoInputs); + + if (g.IO.MouseWheel != 0.0f) + { + if (g.IO.KeyCtrl && g.IO.FontAllowUserScaling) + { + // Zoom / Scale window + const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); + const float scale = new_font_scale / window->FontWindowScale; + window->FontWindowScale = new_font_scale; + + const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size; + window->Pos += offset; + window->Size *= scale; + window->SizeFull *= scale; + } + else if (!g.IO.KeyCtrl && scroll_allowed) + { + // Mouse wheel vertical scrolling + float scroll_amount = 5 * scroll_window->CalcFontSize(); + scroll_amount = (float)(int)ImMin(scroll_amount, (scroll_window->ContentsRegionRect.GetHeight() + scroll_window->WindowPadding.y * 2.0f) * 0.67f); + SetWindowScrollY(scroll_window, scroll_window->Scroll.y - g.IO.MouseWheel * scroll_amount); + } + } + if (g.IO.MouseWheelH != 0.0f && scroll_allowed && !g.IO.KeyCtrl) + { + // Mouse wheel horizontal scrolling (for hardware that supports it) + float scroll_amount = scroll_window->CalcFontSize(); + SetWindowScrollX(scroll_window, scroll_window->Scroll.x - g.IO.MouseWheelH * scroll_amount); + } +} + +// The reason this is exposed in imgui_internal.h is: on touch-based system that don't have hovering, we want to dispatch inputs to the right target (imgui vs imgui+app) +void ImGui::UpdateHoveredWindowAndCaptureFlags() +{ + ImGuiContext& g = *GImGui; + + // Find the window hovered by mouse: + // - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow. + // - When moving a window we can skip the search, which also conveniently bypasses the fact that window->WindowRectClipped is lagging as this point of the frame. + // - We also support the moved window toggling the NoInputs flag after moving has started in order to be able to detect windows below it, which is useful for e.g. docking mechanisms. + FindHoveredWindow(); + + // Modal windows prevents cursor from hovering behind them. + ImGuiWindow* modal_window = GetFrontMostPopupModal(); + if (modal_window) + if (g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window)) + g.HoveredRootWindow = g.HoveredWindow = NULL; + + // Disabled mouse? + if (g.IO.ConfigFlags & ImGuiConfigFlags_NoMouse) + g.HoveredWindow = g.HoveredRootWindow = NULL; + + // We track click ownership. When clicked outside of a window the click is owned by the application and won't report hovering nor request capture even while dragging over our windows afterward. + int mouse_earliest_button_down = -1; + bool mouse_any_down = false; + for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) + { + if (g.IO.MouseClicked[i]) + g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenPopupStack.empty()); + mouse_any_down |= g.IO.MouseDown[i]; + if (g.IO.MouseDown[i]) + if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[i] < g.IO.MouseClickedTime[mouse_earliest_button_down]) + mouse_earliest_button_down = i; + } + const bool mouse_avail_to_imgui = (mouse_earliest_button_down == -1) || g.IO.MouseDownOwned[mouse_earliest_button_down]; + + // If mouse was first clicked outside of ImGui bounds we also cancel out hovering. + // FIXME: For patterns of drag and drop across OS windows, we may need to rework/remove this test (first committed 311c0ca9 on 2015/02) + const bool mouse_dragging_extern_payload = g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0; + if (!mouse_avail_to_imgui && !mouse_dragging_extern_payload) + g.HoveredWindow = g.HoveredRootWindow = NULL; + + // Update io.WantCaptureMouse for the user application (true = dispatch mouse info to imgui, false = dispatch mouse info to imgui + app) + if (g.WantCaptureMouseNextFrame != -1) + g.IO.WantCaptureMouse = (g.WantCaptureMouseNextFrame != 0); + else + g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (!g.OpenPopupStack.empty()); + + // Update io.WantCaptureKeyboard for the user application (true = dispatch keyboard info to imgui, false = dispatch keyboard info to imgui + app) + if (g.WantCaptureKeyboardNextFrame != -1) + g.IO.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != 0); + else + g.IO.WantCaptureKeyboard = (g.ActiveId != 0) || (modal_window != NULL); + if (g.IO.NavActive && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard)) + g.IO.WantCaptureKeyboard = true; + + // Update io.WantTextInput flag, this is to allow systems without a keyboard (e.g. mobile, hand-held) to show a software keyboard if possible + g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : false; +} + +void ImGui::NewFrame() +{ + IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?"); + ImGuiContext& g = *GImGui; + + // Check user data + // (We pass an error message in the assert expression to make it visible to programmers who are not using a debugger, as most assert handlers display their argument) + IM_ASSERT(g.Initialized); + IM_ASSERT(g.IO.DeltaTime >= 0.0f && "Need a positive DeltaTime (zero is tolerated but will cause some timing issues)"); + IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f && "Invalid DisplaySize value"); + IM_ASSERT(g.IO.Fonts->Fonts.Size > 0 && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?"); + IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded() && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?"); + IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting"); + IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting. Alpha cannot be negative (allows us to avoid a few clamps in color computations)"); + IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forgot to call Render() or EndFrame() at the end of the previous frame?"); + for (int n = 0; n < ImGuiKey_COUNT; n++) + IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)"); + + // Perform simple check for required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was only recently added in 1.60 WIP) + if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) + IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation."); + + // The beta io.ConfigResizeWindowsFromEdges option requires back-end to honor mouse cursor changes and set the ImGuiBackendFlags_HasMouseCursors flag accordingly. + if (g.IO.ConfigResizeWindowsFromEdges && !(g.IO.BackendFlags & ImGuiBackendFlags_HasMouseCursors)) + g.IO.ConfigResizeWindowsFromEdges = false; + + // Load settings on first frame (if not explicitly loaded manually before) + if (!g.SettingsLoaded) + { + IM_ASSERT(g.SettingsWindows.empty()); + if (g.IO.IniFilename) + LoadIniSettingsFromDisk(g.IO.IniFilename); + g.SettingsLoaded = true; + } + + // Save settings (with a delay after the last modification, so we don't spam disk too much) + if (g.SettingsDirtyTimer > 0.0f) + { + g.SettingsDirtyTimer -= g.IO.DeltaTime; + if (g.SettingsDirtyTimer <= 0.0f) + { + if (g.IO.IniFilename != NULL) + SaveIniSettingsToDisk(g.IO.IniFilename); + else + g.IO.WantSaveIniSettings = true; // Let user know they can call SaveIniSettingsToMemory(). user will need to clear io.WantSaveIniSettings themselves. + g.SettingsDirtyTimer = 0.0f; + } + } + + g.Time += g.IO.DeltaTime; + g.FrameScopeActive = true; + g.FrameCount += 1; + g.TooltipOverrideCount = 0; + g.WindowsActiveCount = 0; + + // Setup current font and draw list + g.IO.Fonts->Locked = true; + SetCurrentFont(GetDefaultFont()); + IM_ASSERT(g.Font->IsLoaded()); + g.DrawListSharedData.ClipRectFullscreen = ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y); + g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol; + + g.OverlayDrawList.Clear(); + g.OverlayDrawList.PushTextureID(g.IO.Fonts->TexID); + g.OverlayDrawList.PushClipRectFullScreen(); + g.OverlayDrawList.Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0); + + // Mark rendering data as invalid to prevent user who may have a handle on it to use it + g.DrawData.Clear(); + + // Drag and drop keep the source ID alive so even if the source disappear our state is consistent + if (g.DragDropActive && g.DragDropPayload.SourceId == g.ActiveId) + KeepAliveID(g.DragDropPayload.SourceId); + + // Clear reference to active widget if the widget isn't alive anymore + if (!g.HoveredIdPreviousFrame) + g.HoveredIdTimer = 0.0f; + if (g.HoveredId) + g.HoveredIdTimer += g.IO.DeltaTime; + g.HoveredIdPreviousFrame = g.HoveredId; + g.HoveredId = 0; + g.HoveredIdAllowOverlap = false; + if (g.ActiveIdIsAlive != g.ActiveId && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0) + ClearActiveID(); + if (g.ActiveId) + g.ActiveIdTimer += g.IO.DeltaTime; + g.LastActiveIdTimer += g.IO.DeltaTime; + g.ActiveIdPreviousFrame = g.ActiveId; + g.ActiveIdPreviousFrameWindow = g.ActiveIdWindow; + g.ActiveIdPreviousFrameValueChanged = g.ActiveIdValueChanged; + g.ActiveIdIsAlive = 0; + g.ActiveIdPreviousFrameIsAlive = false; + g.ActiveIdIsJustActivated = false; + if (g.ScalarAsInputTextId && g.ActiveId != g.ScalarAsInputTextId) + g.ScalarAsInputTextId = 0; + + // Drag and drop + g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr; + g.DragDropAcceptIdCurr = 0; + g.DragDropAcceptIdCurrRectSurface = FLT_MAX; + g.DragDropWithinSourceOrTarget = false; + + // Update keyboard input state + memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); + for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) + g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f; + + // Update gamepad/keyboard directional navigation + NavUpdate(); + + // Update mouse input state + UpdateMouseInputs(); + + // Calculate frame-rate for the user, as a purely luxurious feature + g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx]; + g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime; + g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame); + g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame))) : FLT_MAX; + + // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering) + UpdateMouseMovingWindow(); + UpdateHoveredWindowAndCaptureFlags(); + + // Background darkening/whitening + if (GetFrontMostPopupModal() != NULL || (g.NavWindowingTarget != NULL && g.NavWindowingHighlightAlpha > 0.0f)) + g.DimBgRatio = ImMin(g.DimBgRatio + g.IO.DeltaTime * 6.0f, 1.0f); + else + g.DimBgRatio = ImMax(g.DimBgRatio - g.IO.DeltaTime * 10.0f, 0.0f); + + g.MouseCursor = ImGuiMouseCursor_Arrow; + g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1; + g.PlatformImePos = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default + + // Mouse wheel scrolling, scale + UpdateMouseWheel(); + + // Pressing TAB activate widget focus + if (g.ActiveId == 0 && g.NavWindow != NULL && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab, false)) + { + if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX) + g.NavWindow->FocusIdxTabRequestNext = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1); + else + g.NavWindow->FocusIdxTabRequestNext = g.IO.KeyShift ? -1 : 0; + } + g.NavIdTabCounter = INT_MAX; + + // Mark all windows as not visible + for (int i = 0; i != g.Windows.Size; i++) + { + ImGuiWindow* window = g.Windows[i]; + window->WasActive = window->Active; + window->Active = false; + window->WriteAccessed = false; + } + + // Closing the focused window restore focus to the first active root window in descending z-order + if (g.NavWindow && !g.NavWindow->WasActive) + FocusFrontMostActiveWindow(NULL); + + // No window should be open at the beginning of the frame. + // But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear. + g.CurrentWindowStack.resize(0); + g.CurrentPopupStack.resize(0); + ClosePopupsOverWindow(g.NavWindow); + + // Create implicit window - we will only render it if the user has added something to it. + // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. + SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver); + Begin("Debug##Default"); +} + +static void* SettingsHandlerWindow_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name) +{ + ImGuiWindowSettings* settings = ImGui::FindWindowSettings(ImHash(name, 0)); + if (!settings) + settings = CreateNewWindowSettings(name); + return (void*)settings; +} + +static void SettingsHandlerWindow_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line) +{ + ImGuiWindowSettings* settings = (ImGuiWindowSettings*)entry; + float x, y; + int i; + if (sscanf(line, "Pos=%f,%f", &x, &y) == 2) settings->Pos = ImVec2(x, y); + else if (sscanf(line, "Size=%f,%f", &x, &y) == 2) settings->Size = ImMax(ImVec2(x, y), GImGui->Style.WindowMinSize); + else if (sscanf(line, "Collapsed=%d", &i) == 1) settings->Collapsed = (i != 0); +} + +static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) +{ + // Gather data from windows that were active during this session + ImGuiContext& g = *imgui_ctx; + for (int i = 0; i != g.Windows.Size; i++) + { + ImGuiWindow* window = g.Windows[i]; + if (window->Flags & ImGuiWindowFlags_NoSavedSettings) + continue; + + ImGuiWindowSettings* settings = (window->SettingsIdx != -1) ? &g.SettingsWindows[window->SettingsIdx] : ImGui::FindWindowSettings(window->ID); + if (!settings) + { + settings = CreateNewWindowSettings(window->Name); + window->SettingsIdx = g.SettingsWindows.index_from_pointer(settings); + } + IM_ASSERT(settings->ID == window->ID); + settings->Pos = window->Pos; + settings->Size = window->SizeFull; + settings->Collapsed = window->Collapsed; + } + + // Write a buffer + // If a window wasn't opened in this session we preserve its settings + buf->reserve(buf->size() + g.SettingsWindows.Size * 96); // ballpark reserve + for (int i = 0; i != g.SettingsWindows.Size; i++) + { + const ImGuiWindowSettings* settings = &g.SettingsWindows[i]; + if (settings->Pos.x == FLT_MAX) + continue; + const char* name = settings->Name; + if (const char* p = strstr(name, "###")) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID() + name = p; + buf->appendf("[%s][%s]\n", handler->TypeName, name); + buf->appendf("Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y); + buf->appendf("Size=%d,%d\n", (int)settings->Size.x, (int)settings->Size.y); + buf->appendf("Collapsed=%d\n", settings->Collapsed); + buf->appendf("\n"); + } +} + +void ImGui::Initialize(ImGuiContext* context) +{ + ImGuiContext& g = *context; + IM_ASSERT(!g.Initialized && !g.SettingsLoaded); + + // Add .ini handle for ImGuiWindow type + ImGuiSettingsHandler ini_handler; + ini_handler.TypeName = "Window"; + ini_handler.TypeHash = ImHash("Window", 0, 0); + ini_handler.ReadOpenFn = SettingsHandlerWindow_ReadOpen; + ini_handler.ReadLineFn = SettingsHandlerWindow_ReadLine; + ini_handler.WriteAllFn = SettingsHandlerWindow_WriteAll; + g.SettingsHandlers.push_front(ini_handler); + + g.Initialized = true; +} + +// This function is merely here to free heap allocations. +void ImGui::Shutdown(ImGuiContext* context) +{ + // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame) + ImGuiContext& g = *context; + if (g.IO.Fonts && g.FontAtlasOwnedByContext) + IM_DELETE(g.IO.Fonts); + g.IO.Fonts = NULL; + + // Cleanup of other data are conditional on actually having initialized ImGui. + if (!g.Initialized) + return; + + // Save settings (unless we haven't attempted to load them: CreateContext/DestroyContext without a call to NewFrame shouldn't save an empty file) + if (g.SettingsLoaded && g.IO.IniFilename != NULL) + SaveIniSettingsToDisk(g.IO.IniFilename); + + // Clear everything else + for (int i = 0; i < g.Windows.Size; i++) + IM_DELETE(g.Windows[i]); + g.Windows.clear(); + g.WindowsSortBuffer.clear(); + g.CurrentWindow = NULL; + g.CurrentWindowStack.clear(); + g.WindowsById.Clear(); + g.NavWindow = NULL; + g.HoveredWindow = NULL; + g.HoveredRootWindow = NULL; + g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL; + g.MovingWindow = NULL; + g.ColorModifiers.clear(); + g.StyleModifiers.clear(); + g.FontStack.clear(); + g.OpenPopupStack.clear(); + g.CurrentPopupStack.clear(); + g.DrawDataBuilder.ClearFreeMemory(); + g.OverlayDrawList.ClearFreeMemory(); + g.PrivateClipboard.clear(); + g.InputTextState.Text.clear(); + g.InputTextState.InitialText.clear(); + g.InputTextState.TempTextBuffer.clear(); + + for (int i = 0; i < g.SettingsWindows.Size; i++) + IM_DELETE(g.SettingsWindows[i].Name); + g.SettingsWindows.clear(); + g.SettingsHandlers.clear(); + + if (g.LogFile && g.LogFile != stdout) + { + fclose(g.LogFile); + g.LogFile = NULL; + } + g.LogClipboard.clear(); + + g.Initialized = false; +} + +ImGuiWindowSettings* ImGui::FindWindowSettings(ImGuiID id) +{ + ImGuiContext& g = *GImGui; + for (int i = 0; i != g.SettingsWindows.Size; i++) + if (g.SettingsWindows[i].ID == id) + return &g.SettingsWindows[i]; + return NULL; +} + +static ImGuiWindowSettings* CreateNewWindowSettings(const char* name) +{ + ImGuiContext& g = *GImGui; + g.SettingsWindows.push_back(ImGuiWindowSettings()); + ImGuiWindowSettings* settings = &g.SettingsWindows.back(); + settings->Name = ImStrdup(name); + settings->ID = ImHash(name, 0); + return settings; +} + +void ImGui::LoadIniSettingsFromDisk(const char* ini_filename) +{ + size_t file_data_size = 0; + char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", &file_data_size); + if (!file_data) + return; + LoadIniSettingsFromMemory(file_data, (size_t)file_data_size); + ImGui::MemFree(file_data); +} + +ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name) +{ + ImGuiContext& g = *GImGui; + const ImGuiID type_hash = ImHash(type_name, 0, 0); + for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) + if (g.SettingsHandlers[handler_n].TypeHash == type_hash) + return &g.SettingsHandlers[handler_n]; + return NULL; +} + +// Zero-tolerance, no error reporting, cheap .ini parsing +void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.Initialized); + IM_ASSERT(g.SettingsLoaded == false && g.FrameCount == 0); + + // For user convenience, we allow passing a non zero-terminated string (hence the ini_size parameter). + // For our convenience and to make the code simpler, we'll also write zero-terminators within the buffer. So let's create a writable copy.. + if (ini_size == 0) + ini_size = strlen(ini_data); + char* buf = (char*)ImGui::MemAlloc(ini_size + 1); + char* buf_end = buf + ini_size; + memcpy(buf, ini_data, ini_size); + buf[ini_size] = 0; + + void* entry_data = NULL; + ImGuiSettingsHandler* entry_handler = NULL; + + char* line_end = NULL; + for (char* line = buf; line < buf_end; line = line_end + 1) + { + // Skip new lines markers, then find end of the line + while (*line == '\n' || *line == '\r') + line++; + line_end = line; + while (line_end < buf_end && *line_end != '\n' && *line_end != '\r') + line_end++; + line_end[0] = 0; + + if (line[0] == '[' && line_end > line && line_end[-1] == ']') + { + // Parse "[Type][Name]". Note that 'Name' can itself contains [] characters, which is acceptable with the current format and parsing code. + line_end[-1] = 0; + const char* name_end = line_end - 1; + const char* type_start = line + 1; + char* type_end = (char*)(intptr_t)ImStrchrRange(type_start, name_end, ']'); + const char* name_start = type_end ? ImStrchrRange(type_end + 1, name_end, '[') : NULL; + if (!type_end || !name_start) + { + name_start = type_start; // Import legacy entries that have no type + type_start = "Window"; + } + else + { + *type_end = 0; // Overwrite first ']' + name_start++; // Skip second '[' + } + entry_handler = FindSettingsHandler(type_start); + entry_data = entry_handler ? entry_handler->ReadOpenFn(&g, entry_handler, name_start) : NULL; + } + else if (entry_handler != NULL && entry_data != NULL) + { + // Let type handler parse the line + entry_handler->ReadLineFn(&g, entry_handler, entry_data, line); + } + } + ImGui::MemFree(buf); + g.SettingsLoaded = true; +} + +void ImGui::SaveIniSettingsToDisk(const char* ini_filename) +{ + ImGuiContext& g = *GImGui; + g.SettingsDirtyTimer = 0.0f; + if (!ini_filename) + return; + + size_t ini_data_size = 0; + const char* ini_data = SaveIniSettingsToMemory(&ini_data_size); + FILE* f = ImFileOpen(ini_filename, "wt"); + if (!f) + return; + fwrite(ini_data, sizeof(char), ini_data_size, f); + fclose(f); +} + +// Call registered handlers (e.g. SettingsHandlerWindow_WriteAll() + custom handlers) to write their stuff into a text buffer +const char* ImGui::SaveIniSettingsToMemory(size_t* out_size) +{ + ImGuiContext& g = *GImGui; + g.SettingsDirtyTimer = 0.0f; + g.SettingsIniData.Buf.resize(0); + g.SettingsIniData.Buf.push_back(0); + for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) + { + ImGuiSettingsHandler* handler = &g.SettingsHandlers[handler_n]; + handler->WriteAllFn(&g, handler, &g.SettingsIniData); + } + if (out_size) + *out_size = (size_t)g.SettingsIniData.size(); + return g.SettingsIniData.c_str(); +} + +void ImGui::MarkIniSettingsDirty() +{ + ImGuiContext& g = *GImGui; + if (g.SettingsDirtyTimer <= 0.0f) + g.SettingsDirtyTimer = g.IO.IniSavingRate; +} + +void ImGui::MarkIniSettingsDirty(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings)) + if (g.SettingsDirtyTimer <= 0.0f) + g.SettingsDirtyTimer = g.IO.IniSavingRate; +} + +// FIXME: Add a more explicit sort order in the window structure. +static int IMGUI_CDECL ChildWindowComparer(const void* lhs, const void* rhs) +{ + const ImGuiWindow* const a = *(const ImGuiWindow* const *)lhs; + const ImGuiWindow* const b = *(const ImGuiWindow* const *)rhs; + if (int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup)) + return d; + if (int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip)) + return d; + return (a->BeginOrderWithinParent - b->BeginOrderWithinParent); +} + +static void AddWindowToSortedBuffer(ImVector* out_sorted_windows, ImGuiWindow* window) +{ + out_sorted_windows->push_back(window); + if (window->Active) + { + int count = window->DC.ChildWindows.Size; + if (count > 1) + ImQsort(window->DC.ChildWindows.begin(), (size_t)count, sizeof(ImGuiWindow*), ChildWindowComparer); + for (int i = 0; i < count; i++) + { + ImGuiWindow* child = window->DC.ChildWindows[i]; + if (child->Active) + AddWindowToSortedBuffer(out_sorted_windows, child); + } + } +} + +static void AddDrawListToDrawData(ImVector* out_list, ImDrawList* draw_list) +{ + if (draw_list->CmdBuffer.empty()) + return; + + // Remove trailing command if unused + ImDrawCmd& last_cmd = draw_list->CmdBuffer.back(); + if (last_cmd.ElemCount == 0 && last_cmd.UserCallback == NULL) + { + draw_list->CmdBuffer.pop_back(); + if (draw_list->CmdBuffer.empty()) + return; + } + + // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. May trigger for you if you are using PrimXXX functions incorrectly. + IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size); + IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size); + IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); + + // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window) + // If this assert triggers because you are drawing lots of stuff manually: + // A) Make sure you are coarse clipping, because ImDrawList let all your vertices pass. You can use the Metrics window to inspect draw list contents. + // B) If you need/want meshes with more than 64K vertices, uncomment the '#define ImDrawIdx unsigned int' line in imconfig.h to set the index size to 4 bytes. + // You'll need to handle the 4-bytes indices to your renderer. For example, the OpenGL example code detect index size at compile-time by doing: + // glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); + // Your own engine or render API may use different parameters or function calls to specify index sizes. 2 and 4 bytes indices are generally supported by most API. + // C) If for some reason you cannot use 4 bytes indices or don't want to, a workaround is to call BeginChild()/EndChild() before reaching the 64K limit to split your draw commands in multiple draw lists. + if (sizeof(ImDrawIdx) == 2) + IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above"); + + out_list->push_back(draw_list); +} + +static void AddWindowToDrawData(ImVector* out_render_list, ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + g.IO.MetricsRenderWindows++; + AddDrawListToDrawData(out_render_list, window->DrawList); + for (int i = 0; i < window->DC.ChildWindows.Size; i++) + { + ImGuiWindow* child = window->DC.ChildWindows[i]; + if (IsWindowActiveAndVisible(child)) // clipped children may have been marked not active + AddWindowToDrawData(out_render_list, child); + } +} + +static void AddWindowToDrawDataSelectLayer(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + if (window->Flags & ImGuiWindowFlags_Tooltip) + AddWindowToDrawData(&g.DrawDataBuilder.Layers[1], window); + else + AddWindowToDrawData(&g.DrawDataBuilder.Layers[0], window); +} + +void ImDrawDataBuilder::FlattenIntoSingleLayer() +{ + int n = Layers[0].Size; + int size = n; + for (int i = 1; i < IM_ARRAYSIZE(Layers); i++) + size += Layers[i].Size; + Layers[0].resize(size); + for (int layer_n = 1; layer_n < IM_ARRAYSIZE(Layers); layer_n++) + { + ImVector& layer = Layers[layer_n]; + if (layer.empty()) + continue; + memcpy(&Layers[0][n], &layer[0], layer.Size * sizeof(ImDrawList*)); + n += layer.Size; + layer.resize(0); + } +} + +static void SetupDrawData(ImVector* draw_lists, ImDrawData* out_draw_data) +{ + ImGuiIO& io = ImGui::GetIO(); + out_draw_data->Valid = true; + out_draw_data->CmdLists = (draw_lists->Size > 0) ? draw_lists->Data : NULL; + out_draw_data->CmdListsCount = draw_lists->Size; + out_draw_data->TotalVtxCount = out_draw_data->TotalIdxCount = 0; + out_draw_data->DisplayPos = ImVec2(0.0f, 0.0f); + out_draw_data->DisplaySize = io.DisplaySize; + for (int n = 0; n < draw_lists->Size; n++) + { + out_draw_data->TotalVtxCount += draw_lists->Data[n]->VtxBuffer.Size; + out_draw_data->TotalIdxCount += draw_lists->Data[n]->IdxBuffer.Size; + } +} + +// When using this function it is sane to ensure that float are perfectly rounded to integer values, to that e.g. (int)(max.x-min.x) in user's render produce correct result. +void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect) +{ + ImGuiWindow* window = GetCurrentWindow(); + window->DrawList->PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect); + window->ClipRect = window->DrawList->_ClipRectStack.back(); +} + +void ImGui::PopClipRect() +{ + ImGuiWindow* window = GetCurrentWindow(); + window->DrawList->PopClipRect(); + window->ClipRect = window->DrawList->_ClipRectStack.back(); +} + +// This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal. +void ImGui::EndFrame() +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.Initialized); + if (g.FrameCountEnded == g.FrameCount) // Don't process EndFrame() multiple times. + return; + IM_ASSERT(g.FrameScopeActive && "Forgot to call ImGui::NewFrame()"); + + // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME) + if (g.IO.ImeSetInputScreenPosFn && ImLengthSqr(g.PlatformImeLastPos - g.PlatformImePos) > 0.0001f) + { + g.IO.ImeSetInputScreenPosFn((int)g.PlatformImePos.x, (int)g.PlatformImePos.y); + g.PlatformImeLastPos = g.PlatformImePos; + } + + // Hide implicit "Debug" window if it hasn't been used + IM_ASSERT(g.CurrentWindowStack.Size == 1); // Mismatched Begin()/End() calls, did you forget to call end on g.CurrentWindow->Name? + if (g.CurrentWindow && !g.CurrentWindow->WriteAccessed) + g.CurrentWindow->Active = false; + End(); + + // Show CTRL+TAB list + if (g.NavWindowingTarget) + NavUpdateWindowingList(); + + // Drag and Drop: Elapse payload (if delivered, or if source stops being submitted) + if (g.DragDropActive) + { + bool is_delivered = g.DragDropPayload.Delivery; + bool is_elapsed = (g.DragDropPayload.DataFrameCount + 1 < g.FrameCount) && ((g.DragDropSourceFlags & ImGuiDragDropFlags_SourceAutoExpirePayload) || !IsMouseDown(g.DragDropMouseButton)); + if (is_delivered || is_elapsed) + ClearDragDrop(); + } + + // Drag and Drop: Fallback for source tooltip. This is not ideal but better than nothing. + if (g.DragDropActive && g.DragDropSourceFrameCount < g.FrameCount) + { + g.DragDropWithinSourceOrTarget = true; + SetTooltip("..."); + g.DragDropWithinSourceOrTarget = false; + } + + // Initiate moving window + if (g.ActiveId == 0 && g.HoveredId == 0) + { + if (!g.NavWindow || !g.NavWindow->Appearing) // Unless we just made a window/popup appear + { + // Click to focus window and start moving (after we're done with all our widgets) + if (g.IO.MouseClicked[0]) + { + if (g.HoveredRootWindow != NULL) + StartMouseMovingWindow(g.HoveredWindow); + else if (g.NavWindow != NULL && GetFrontMostPopupModal() == NULL) + FocusWindow(NULL); // Clicking on void disable focus + } + + // With right mouse button we close popups without changing focus + // (The left mouse button path calls FocusWindow which will lead NewFrame->ClosePopupsOverWindow to trigger) + if (g.IO.MouseClicked[1]) + { + // Find the top-most window between HoveredWindow and the front most Modal Window. + // This is where we can trim the popup stack. + ImGuiWindow* modal = GetFrontMostPopupModal(); + bool hovered_window_above_modal = false; + if (modal == NULL) + hovered_window_above_modal = true; + for (int i = g.Windows.Size - 1; i >= 0 && hovered_window_above_modal == false; i--) + { + ImGuiWindow* window = g.Windows[i]; + if (window == modal) + break; + if (window == g.HoveredWindow) + hovered_window_above_modal = true; + } + ClosePopupsOverWindow(hovered_window_above_modal ? g.HoveredWindow : modal); + } + } + } + + // Sort the window list so that all child windows are after their parent + // We cannot do that on FocusWindow() because childs may not exist yet + g.WindowsSortBuffer.resize(0); + g.WindowsSortBuffer.reserve(g.Windows.Size); + for (int i = 0; i != g.Windows.Size; i++) + { + ImGuiWindow* window = g.Windows[i]; + if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow)) // if a child is active its parent will add it + continue; + AddWindowToSortedBuffer(&g.WindowsSortBuffer, window); + } + + IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size); // we done something wrong + g.Windows.swap(g.WindowsSortBuffer); + g.IO.MetricsActiveWindows = g.WindowsActiveCount; + + // Unlock font atlas + g.IO.Fonts->Locked = false; + + // Clear Input data for next frame + g.IO.MouseWheel = g.IO.MouseWheelH = 0.0f; + memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters)); + memset(g.IO.NavInputs, 0, sizeof(g.IO.NavInputs)); + + g.FrameScopeActive = false; + g.FrameCountEnded = g.FrameCount; +} + +void ImGui::Render() +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.Initialized); + + if (g.FrameCountEnded != g.FrameCount) + ImGui::EndFrame(); + g.FrameCountRendered = g.FrameCount; + + // Gather ImDrawList to render (for each active window) + g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = g.IO.MetricsRenderWindows = 0; + g.DrawDataBuilder.Clear(); + ImGuiWindow* windows_to_render_front_most[2]; + windows_to_render_front_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindow : NULL; + windows_to_render_front_most[1] = g.NavWindowingTarget ? g.NavWindowingList : NULL; + for (int n = 0; n != g.Windows.Size; n++) + { + ImGuiWindow* window = g.Windows[n]; + if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_front_most[0] && window != windows_to_render_front_most[1]) + AddWindowToDrawDataSelectLayer(window); + } + for (int n = 0; n < IM_ARRAYSIZE(windows_to_render_front_most); n++) + if (windows_to_render_front_most[n] && IsWindowActiveAndVisible(windows_to_render_front_most[n])) // NavWindowingTarget is always temporarily displayed as the front-most window + AddWindowToDrawDataSelectLayer(windows_to_render_front_most[n]); + g.DrawDataBuilder.FlattenIntoSingleLayer(); + + // Draw software mouse cursor if requested + if (g.IO.MouseDrawCursor) + RenderMouseCursor(&g.OverlayDrawList, g.IO.MousePos, g.Style.MouseCursorScale, g.MouseCursor); + + if (!g.OverlayDrawList.VtxBuffer.empty()) + AddDrawListToDrawData(&g.DrawDataBuilder.Layers[0], &g.OverlayDrawList); + + // Setup ImDrawData structure for end-user + SetupDrawData(&g.DrawDataBuilder.Layers[0], &g.DrawData); + g.IO.MetricsRenderVertices = g.DrawData.TotalVtxCount; + g.IO.MetricsRenderIndices = g.DrawData.TotalIdxCount; + + // Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData() +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + if (g.DrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL) + g.IO.RenderDrawListsFn(&g.DrawData); +#endif +} + +const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end) +{ + const char* text_display_end = text; + if (!text_end) + text_end = (const char*)-1; + + while (text_display_end < text_end && *text_display_end != '\0' && (text_display_end[0] != '#' || text_display_end[1] != '#')) + text_display_end++; + return text_display_end; +} + +// Pass text data straight to log (without being displayed) +void ImGui::LogText(const char* fmt, ...) +{ + ImGuiContext& g = *GImGui; + if (!g.LogEnabled) + return; + + va_list args; + va_start(args, fmt); + if (g.LogFile) + vfprintf(g.LogFile, fmt, args); + else + g.LogClipboard.appendfv(fmt, args); + va_end(args); +} + +// Internal version that takes a position to decide on newline placement and pad items according to their depth. +// We split text into individual lines to add current tree level padding +static void LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end = NULL) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + if (!text_end) + text_end = ImGui::FindRenderedTextEnd(text, text_end); + + const bool log_new_line = ref_pos && (ref_pos->y > window->DC.LogLinePosY + 1); + if (ref_pos) + window->DC.LogLinePosY = ref_pos->y; + + const char* text_remaining = text; + if (g.LogStartDepth > window->DC.TreeDepth) // Re-adjust padding if we have popped out of our starting depth + g.LogStartDepth = window->DC.TreeDepth; + const int tree_depth = (window->DC.TreeDepth - g.LogStartDepth); + for (;;) + { + // Split the string. Each new line (after a '\n') is followed by spacing corresponding to the current depth of our log entry. + const char* line_end = text_remaining; + while (line_end < text_end) + if (*line_end == '\n') + break; + else + line_end++; + if (line_end >= text_end) + line_end = NULL; + + const bool is_first_line = (text == text_remaining); + bool is_last_line = false; + if (line_end == NULL) + { + is_last_line = true; + line_end = text_end; + } + if (line_end != NULL && !(is_last_line && (line_end - text_remaining)==0)) + { + const int char_count = (int)(line_end - text_remaining); + if (log_new_line || !is_first_line) + ImGui::LogText(IM_NEWLINE "%*s%.*s", tree_depth*4, "", char_count, text_remaining); + else + ImGui::LogText(" %.*s", char_count, text_remaining); + } + + if (is_last_line) + break; + text_remaining = line_end + 1; + } +} + +// Internal ImGui functions to render text +// RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText() +void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + // Hide anything after a '##' string + const char* text_display_end; + if (hide_text_after_hash) + { + text_display_end = FindRenderedTextEnd(text, text_end); + } + else + { + if (!text_end) + text_end = text + strlen(text); // FIXME-OPT + text_display_end = text_end; + } + + if (text != text_display_end) + { + window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end); + if (g.LogEnabled) + LogRenderedText(&pos, text, text_display_end); + } +} + +void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + if (!text_end) + text_end = text + strlen(text); // FIXME-OPT + + if (text != text_end) + { + window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width); + if (g.LogEnabled) + LogRenderedText(&pos, text, text_end); + } +} + +// Default clip_rect uses (pos_min,pos_max) +// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges) +void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect) +{ + // Hide anything after a '##' string + const char* text_display_end = FindRenderedTextEnd(text, text_end); + const int text_len = (int)(text_display_end - text); + if (text_len == 0) + return; + + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + // Perform CPU side clipping for single clipped element to avoid using scissor state + ImVec2 pos = pos_min; + const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_display_end, false, 0.0f); + + const ImVec2* clip_min = clip_rect ? &clip_rect->Min : &pos_min; + const ImVec2* clip_max = clip_rect ? &clip_rect->Max : &pos_max; + bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y); + if (clip_rect) // If we had no explicit clipping rectangle then pos==clip_min + need_clipping |= (pos.x < clip_min->x) || (pos.y < clip_min->y); + + // Align whole block. We should defer that to the better rendering function when we'll have support for individual line alignment. + if (align.x > 0.0f) pos.x = ImMax(pos.x, pos.x + (pos_max.x - pos.x - text_size.x) * align.x); + if (align.y > 0.0f) pos.y = ImMax(pos.y, pos.y + (pos_max.y - pos.y - text_size.y) * align.y); + + // Render + if (need_clipping) + { + ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y); + window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect); + } + else + { + window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL); + } + if (g.LogEnabled) + LogRenderedText(&pos, text, text_display_end); +} + +// Render a rectangle shaped with optional rounding and borders +void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, float rounding) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding); + const float border_size = g.Style.FrameBorderSize; + if (border && border_size > 0.0f) + { + window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size); + window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size); + } +} + +void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + const float border_size = g.Style.FrameBorderSize; + if (border_size > 0.0f) + { + window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size); + window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size); + } +} + +// Render an arrow aimed to be aligned with text (p_min is a position in the same space text would be positioned). To e.g. denote expanded/collapsed state +void ImGui::RenderArrow(ImVec2 p_min, ImGuiDir dir, float scale) +{ + ImGuiContext& g = *GImGui; + + const float h = g.FontSize * 1.00f; + float r = h * 0.40f * scale; + ImVec2 center = p_min + ImVec2(h * 0.50f, h * 0.50f * scale); + + ImVec2 a, b, c; + switch (dir) + { + case ImGuiDir_Up: + case ImGuiDir_Down: + if (dir == ImGuiDir_Up) r = -r; + a = ImVec2(+0.000f,+0.750f) * r; + b = ImVec2(-0.866f,-0.750f) * r; + c = ImVec2(+0.866f,-0.750f) * r; + break; + case ImGuiDir_Left: + case ImGuiDir_Right: + if (dir == ImGuiDir_Left) r = -r; + a = ImVec2(+0.750f,+0.000f) * r; + b = ImVec2(-0.750f,+0.866f) * r; + c = ImVec2(-0.750f,-0.866f) * r; + break; + case ImGuiDir_None: + case ImGuiDir_COUNT: + IM_ASSERT(0); + break; + } + + g.CurrentWindow->DrawList->AddTriangleFilled(center + a, center + b, center + c, GetColorU32(ImGuiCol_Text)); +} + +void ImGui::RenderBullet(ImVec2 pos) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + window->DrawList->AddCircleFilled(pos, GImGui->FontSize*0.20f, GetColorU32(ImGuiCol_Text), 8); +} + +void ImGui::RenderCheckMark(ImVec2 pos, ImU32 col, float sz) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + float thickness = ImMax(sz / 5.0f, 1.0f); + sz -= thickness*0.5f; + pos += ImVec2(thickness*0.25f, thickness*0.25f); + + float third = sz / 3.0f; + float bx = pos.x + third; + float by = pos.y + sz - third*0.5f; + window->DrawList->PathLineTo(ImVec2(bx - third, by - third)); + window->DrawList->PathLineTo(ImVec2(bx, by)); + window->DrawList->PathLineTo(ImVec2(bx + third*2, by - third*2)); + window->DrawList->PathStroke(col, false, thickness); +} + +void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags) +{ + ImGuiContext& g = *GImGui; + if (id != g.NavId) + return; + if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw)) + return; + ImGuiWindow* window = ImGui::GetCurrentWindow(); + if (window->DC.NavHideHighlightOneFrame) + return; + + float rounding = (flags & ImGuiNavHighlightFlags_NoRounding) ? 0.0f : g.Style.FrameRounding; + ImRect display_rect = bb; + display_rect.ClipWith(window->ClipRect); + if (flags & ImGuiNavHighlightFlags_TypeDefault) + { + const float THICKNESS = 2.0f; + const float DISTANCE = 3.0f + THICKNESS * 0.5f; + display_rect.Expand(ImVec2(DISTANCE,DISTANCE)); + bool fully_visible = window->ClipRect.Contains(display_rect); + if (!fully_visible) + window->DrawList->PushClipRect(display_rect.Min, display_rect.Max); + window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), display_rect.Max - ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), GetColorU32(ImGuiCol_NavHighlight), rounding, ImDrawCornerFlags_All, THICKNESS); + if (!fully_visible) + window->DrawList->PopClipRect(); + } + if (flags & ImGuiNavHighlightFlags_TypeThin) + { + window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, ~0, 1.0f); + } +} + +// Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker. +// CalcTextSize("") should return ImVec2(0.0f, GImGui->FontSize) +ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width) +{ + ImGuiContext& g = *GImGui; + + const char* text_display_end; + if (hide_text_after_double_hash) + text_display_end = FindRenderedTextEnd(text, text_end); // Hide anything after a '##' string + else + text_display_end = text_end; + + ImFont* font = g.Font; + const float font_size = g.FontSize; + if (text == text_display_end) + return ImVec2(0.0f, font_size); + ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL); + + // Cancel out character spacing for the last character of a line (it is baked into glyph->AdvanceX field) + const float font_scale = font_size / font->FontSize; + const float character_spacing_x = 1.0f * font_scale; + if (text_size.x > 0.0f) + text_size.x -= character_spacing_x; + text_size.x = (float)(int)(text_size.x + 0.95f); + + return text_size; +} + +// Helper to calculate coarse clipping of large list of evenly sized items. +// NB: Prefer using the ImGuiListClipper higher-level helper if you can! Read comments and instructions there on how those use this sort of pattern. +// NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX +void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if (g.LogEnabled) + { + // If logging is active, do not perform any clipping + *out_items_display_start = 0; + *out_items_display_end = items_count; + return; + } + if (window->SkipItems) + { + *out_items_display_start = *out_items_display_end = 0; + return; + } + + // We create the union of the ClipRect and the NavScoringRect which at worst should be 1 page away from ClipRect + ImRect unclipped_rect = window->ClipRect; + if (g.NavMoveRequest) + unclipped_rect.Add(g.NavScoringRectScreen); + + const ImVec2 pos = window->DC.CursorPos; + int start = (int)((unclipped_rect.Min.y - pos.y) / items_height); + int end = (int)((unclipped_rect.Max.y - pos.y) / items_height); + + // When performing a navigation request, ensure we have one item extra in the direction we are moving to + if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Up) + start--; + if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Down) + end++; + + start = ImClamp(start, 0, items_count); + end = ImClamp(end + 1, start, items_count); + *out_items_display_start = start; + *out_items_display_end = end; +} + +// Find window given position, search front-to-back +// FIXME: Note that we have a lag here because WindowRectClipped is updated in Begin() so windows moved by user via SetWindowPos() and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is called, aka before the next Begin(). Moving window thankfully isn't affected. +static void FindHoveredWindow() +{ + ImGuiContext& g = *GImGui; + + ImGuiWindow* hovered_window = NULL; + if (g.MovingWindow && !(g.MovingWindow->Flags & ImGuiWindowFlags_NoInputs)) + hovered_window = g.MovingWindow; + + for (int i = g.Windows.Size - 1; i >= 0 && hovered_window == NULL; i--) + { + ImGuiWindow* window = g.Windows[i]; + if (!window->Active || window->Hidden) + continue; + if (window->Flags & ImGuiWindowFlags_NoInputs) + continue; + + // Using the clipped AABB, a child window will typically be clipped by its parent (not always) + ImRect bb(window->OuterRectClipped.Min - g.Style.TouchExtraPadding, window->OuterRectClipped.Max + g.Style.TouchExtraPadding); + if (bb.Contains(g.IO.MousePos)) + { + if (hovered_window == NULL) + hovered_window = window; + if (hovered_window) + break; + } + } + + g.HoveredWindow = hovered_window; + g.HoveredRootWindow = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL; + +} + +// Test if mouse cursor is hovering given rectangle +// NB- Rectangle is clipped by our current clip setting +// NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style.TouchExtraPadding) +bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip) +{ + ImGuiContext& g = *GImGui; + + // Clip + ImRect rect_clipped(r_min, r_max); + if (clip) + rect_clipped.ClipWith(g.CurrentWindow->ClipRect); + + // Expand for touch input + const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, rect_clipped.Max + g.Style.TouchExtraPadding); + return rect_for_touch.Contains(g.IO.MousePos); +} + +static bool IsKeyPressedMap(ImGuiKey key, bool repeat) +{ + const int key_index = GImGui->IO.KeyMap[key]; + return (key_index >= 0) ? ImGui::IsKeyPressed(key_index, repeat) : false; +} + +int ImGui::GetKeyIndex(ImGuiKey imgui_key) +{ + IM_ASSERT(imgui_key >= 0 && imgui_key < ImGuiKey_COUNT); + return GImGui->IO.KeyMap[imgui_key]; +} + +// Note that imgui doesn't know the semantic of each entry of io.KeysDown[]. Use your own indices/enums according to how your back-end/engine stored them into io.KeysDown[]! +bool ImGui::IsKeyDown(int user_key_index) +{ + if (user_key_index < 0) return false; + IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(GImGui->IO.KeysDown)); + return GImGui->IO.KeysDown[user_key_index]; +} + +int ImGui::CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate) +{ + if (t == 0.0f) + return 1; + if (t <= repeat_delay || repeat_rate <= 0.0f) + return 0; + const int count = (int)((t - repeat_delay) / repeat_rate) - (int)((t_prev - repeat_delay) / repeat_rate); + return (count > 0) ? count : 0; +} + +int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_rate) +{ + ImGuiContext& g = *GImGui; + if (key_index < 0) return false; + IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown)); + const float t = g.IO.KeysDownDuration[key_index]; + return CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, repeat_delay, repeat_rate); +} + +bool ImGui::IsKeyPressed(int user_key_index, bool repeat) +{ + ImGuiContext& g = *GImGui; + if (user_key_index < 0) return false; + IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown)); + const float t = g.IO.KeysDownDuration[user_key_index]; + if (t == 0.0f) + return true; + if (repeat && t > g.IO.KeyRepeatDelay) + return GetKeyPressedAmount(user_key_index, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0; + return false; +} + +bool ImGui::IsKeyReleased(int user_key_index) +{ + ImGuiContext& g = *GImGui; + if (user_key_index < 0) return false; + IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown)); + return g.IO.KeysDownDurationPrev[user_key_index] >= 0.0f && !g.IO.KeysDown[user_key_index]; +} + +bool ImGui::IsMouseDown(int button) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); + return g.IO.MouseDown[button]; +} + +bool ImGui::IsAnyMouseDown() +{ + ImGuiContext& g = *GImGui; + for (int n = 0; n < IM_ARRAYSIZE(g.IO.MouseDown); n++) + if (g.IO.MouseDown[n]) + return true; + return false; +} + +bool ImGui::IsMouseClicked(int button, bool repeat) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); + const float t = g.IO.MouseDownDuration[button]; + if (t == 0.0f) + return true; + + if (repeat && t > g.IO.KeyRepeatDelay) + { + float delay = g.IO.KeyRepeatDelay, rate = g.IO.KeyRepeatRate; + if ((ImFmod(t - delay, rate) > rate*0.5f) != (ImFmod(t - delay - g.IO.DeltaTime, rate) > rate*0.5f)) + return true; + } + + return false; +} + +bool ImGui::IsMouseReleased(int button) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); + return g.IO.MouseReleased[button]; +} + +bool ImGui::IsMouseDoubleClicked(int button) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); + return g.IO.MouseDoubleClicked[button]; +} + +bool ImGui::IsMouseDragging(int button, float lock_threshold) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); + if (!g.IO.MouseDown[button]) + return false; + if (lock_threshold < 0.0f) + lock_threshold = g.IO.MouseDragThreshold; + return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold; +} + +ImVec2 ImGui::GetMousePos() +{ + return GImGui->IO.MousePos; +} + +// NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed! +ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup() +{ + ImGuiContext& g = *GImGui; + if (g.CurrentPopupStack.Size > 0) + return g.OpenPopupStack[g.CurrentPopupStack.Size-1].OpenMousePos; + return g.IO.MousePos; +} + +// We typically use ImVec2(-FLT_MAX,-FLT_MAX) to denote an invalid mouse position +bool ImGui::IsMousePosValid(const ImVec2* mouse_pos) +{ + if (mouse_pos == NULL) + mouse_pos = &GImGui->IO.MousePos; + const float MOUSE_INVALID = -256000.0f; + return mouse_pos->x >= MOUSE_INVALID && mouse_pos->y >= MOUSE_INVALID; +} + +// NB: This is only valid if IsMousePosValid(). Back-ends in theory should always keep mouse position valid when dragging even outside the client window. +ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); + if (lock_threshold < 0.0f) + lock_threshold = g.IO.MouseDragThreshold; + if (g.IO.MouseDown[button]) + if (g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold) + return g.IO.MousePos - g.IO.MouseClickedPos[button]; // Assume we can only get active with left-mouse button (at the moment). + return ImVec2(0.0f, 0.0f); +} + +void ImGui::ResetMouseDragDelta(int button) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); + // NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr + g.IO.MouseClickedPos[button] = g.IO.MousePos; +} + +ImGuiMouseCursor ImGui::GetMouseCursor() +{ + return GImGui->MouseCursor; +} + +void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type) +{ + GImGui->MouseCursor = cursor_type; +} + +void ImGui::CaptureKeyboardFromApp(bool capture) +{ + GImGui->WantCaptureKeyboardNextFrame = capture ? 1 : 0; +} + +void ImGui::CaptureMouseFromApp(bool capture) +{ + GImGui->WantCaptureMouseNextFrame = capture ? 1 : 0; +} + +bool ImGui::IsItemActive() +{ + ImGuiContext& g = *GImGui; + if (g.ActiveId) + { + ImGuiWindow* window = g.CurrentWindow; + return g.ActiveId == window->DC.LastItemId; + } + return false; +} + +bool ImGui::IsItemDeactivated() +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + return (g.ActiveIdPreviousFrame == window->DC.LastItemId && g.ActiveIdPreviousFrame != 0 && g.ActiveId != window->DC.LastItemId); +} + +bool ImGui::IsItemDeactivatedAfterChange() +{ + ImGuiContext& g = *GImGui; + return IsItemDeactivated() && (g.ActiveIdPreviousFrameValueChanged || (g.ActiveId == 0 && g.ActiveIdValueChanged)); +} + +bool ImGui::IsItemFocused() +{ + ImGuiContext& g = *GImGui; + return g.NavId && !g.NavDisableHighlight && g.NavId == g.CurrentWindow->DC.LastItemId; +} + +bool ImGui::IsItemClicked(int mouse_button) +{ + return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_None); +} + +bool ImGui::IsAnyItemHovered() +{ + ImGuiContext& g = *GImGui; + return g.HoveredId != 0 || g.HoveredIdPreviousFrame != 0; +} + +bool ImGui::IsAnyItemActive() +{ + ImGuiContext& g = *GImGui; + return g.ActiveId != 0; +} + +bool ImGui::IsAnyItemFocused() +{ + ImGuiContext& g = *GImGui; + return g.NavId != 0 && !g.NavDisableHighlight; +} + +bool ImGui::IsItemVisible() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->ClipRect.Overlaps(window->DC.LastItemRect); +} + +// Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority. +void ImGui::SetItemAllowOverlap() +{ + ImGuiContext& g = *GImGui; + if (g.HoveredId == g.CurrentWindow->DC.LastItemId) + g.HoveredIdAllowOverlap = true; + if (g.ActiveId == g.CurrentWindow->DC.LastItemId) + g.ActiveIdAllowOverlap = true; +} + +ImVec2 ImGui::GetItemRectMin() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->DC.LastItemRect.Min; +} + +ImVec2 ImGui::GetItemRectMax() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->DC.LastItemRect.Max; +} + +ImVec2 ImGui::GetItemRectSize() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->DC.LastItemRect.GetSize(); +} + +static ImRect GetViewportRect() +{ + ImGuiContext& g = *GImGui; + if (g.IO.DisplayVisibleMin.x != g.IO.DisplayVisibleMax.x && g.IO.DisplayVisibleMin.y != g.IO.DisplayVisibleMax.y) + return ImRect(g.IO.DisplayVisibleMin, g.IO.DisplayVisibleMax); + return ImRect(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y); +} + +// Not exposed publicly as BeginTooltip() because bool parameters are evil. Let's see if other needs arise first. +void ImGui::BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip) +{ + ImGuiContext& g = *GImGui; + char window_name[16]; + ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", g.TooltipOverrideCount); + if (override_previous_tooltip) + if (ImGuiWindow* window = FindWindowByName(window_name)) + if (window->Active) + { + // Hide previous tooltip from being displayed. We can't easily "reset" the content of a window so we create a new one. + window->Hidden = true; + window->HiddenFramesRegular = 1; + ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount); + } + ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoInputs|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoNav; + Begin(window_name, NULL, flags | extra_flags); +} + +void ImGui::SetTooltipV(const char* fmt, va_list args) +{ + ImGuiContext& g = *GImGui; + if (g.DragDropWithinSourceOrTarget) + BeginTooltip(); + else + BeginTooltipEx(0, true); + TextV(fmt, args); + EndTooltip(); +} + +void ImGui::SetTooltip(const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + SetTooltipV(fmt, args); + va_end(args); +} + +void ImGui::BeginTooltip() +{ + ImGuiContext& g = *GImGui; + if (g.DragDropWithinSourceOrTarget) + { + // The default tooltip position is a little offset to give space to see the context menu (it's also clamped within the current viewport/monitor) + // In the context of a dragging tooltip we try to reduce that offset and we enforce following the cursor. + // Whatever we do we want to call SetNextWindowPos() to enforce a tooltip position and disable clipping the tooltip without our display area, like regular tooltip do. + //ImVec2 tooltip_pos = g.IO.MousePos - g.ActiveIdClickOffset - g.Style.WindowPadding; + ImVec2 tooltip_pos = g.IO.MousePos + ImVec2(16 * g.Style.MouseCursorScale, 8 * g.Style.MouseCursorScale); + SetNextWindowPos(tooltip_pos); + SetNextWindowBgAlpha(g.Style.Colors[ImGuiCol_PopupBg].w * 0.60f); + //PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * 0.60f); // This would be nice but e.g ColorButton with checkboard has issue with transparent colors :( + BeginTooltipEx(0, true); + } + else + { + BeginTooltipEx(0, false); + } +} + +void ImGui::EndTooltip() +{ + IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip); // Mismatched BeginTooltip()/EndTooltip() calls + End(); +} + +// Mark popup as open (toggle toward open state). +// Popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. +// Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). +// One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL) +void ImGui::OpenPopupEx(ImGuiID id) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* parent_window = g.CurrentWindow; + int current_stack_size = g.CurrentPopupStack.Size; + ImGuiPopupRef popup_ref; // Tagged as new ref as Window will be set back to NULL if we write this into OpenPopupStack. + popup_ref.PopupId = id; + popup_ref.Window = NULL; + popup_ref.ParentWindow = parent_window; + popup_ref.OpenFrameCount = g.FrameCount; + popup_ref.OpenParentId = parent_window->IDStack.back(); + popup_ref.OpenMousePos = g.IO.MousePos; + popup_ref.OpenPopupPos = NavCalcPreferredRefPos(); + + //printf("[%05d] OpenPopupEx(0x%08X)\n", g.FrameCount, id); + if (g.OpenPopupStack.Size < current_stack_size + 1) + { + g.OpenPopupStack.push_back(popup_ref); + } + else + { + // Gently handle the user mistakenly calling OpenPopup() every frame. It is a programming mistake! However, if we were to run the regular code path, the ui + // would become completely unusable because the popup will always be in hidden-while-calculating-size state _while_ claiming focus. Which would be a very confusing + // situation for the programmer. Instead, we silently allow the popup to proceed, it will keep reappearing and the programming error will be more obvious to understand. + if (g.OpenPopupStack[current_stack_size].PopupId == id && g.OpenPopupStack[current_stack_size].OpenFrameCount == g.FrameCount - 1) + { + g.OpenPopupStack[current_stack_size].OpenFrameCount = popup_ref.OpenFrameCount; + } + else + { + // Close child popups if any, then flag popup for open/reopen + g.OpenPopupStack.resize(current_stack_size + 1); + g.OpenPopupStack[current_stack_size] = popup_ref; + } + + // When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by ClosePopupsOverWindow(). + // This is equivalent to what ClosePopupToLevel() does. + //if (g.OpenPopupStack[current_stack_size].PopupId == id) + // FocusWindow(parent_window); + } +} + +void ImGui::OpenPopup(const char* str_id) +{ + ImGuiContext& g = *GImGui; + OpenPopupEx(g.CurrentWindow->GetID(str_id)); +} + +void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window) +{ + ImGuiContext& g = *GImGui; + if (g.OpenPopupStack.empty()) + return; + + // When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it. + // Don't close our own child popup windows. + int n = 0; + if (ref_window) + { + for (n = 0; n < g.OpenPopupStack.Size; n++) + { + ImGuiPopupRef& popup = g.OpenPopupStack[n]; + if (!popup.Window) + continue; + IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0); + if (popup.Window->Flags & ImGuiWindowFlags_ChildWindow) + continue; + + // Trim the stack if popups are not direct descendant of the reference window (which is often the NavWindow) + bool has_focus = false; + for (int m = n; m < g.OpenPopupStack.Size && !has_focus; m++) + has_focus = (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == ref_window->RootWindow); + if (!has_focus) + break; + } + } + if (n < g.OpenPopupStack.Size) // This test is not required but it allows to set a convenient breakpoint on the block below + ClosePopupToLevel(n); +} + +ImGuiWindow* ImGui::GetFrontMostPopupModal() +{ + ImGuiContext& g = *GImGui; + for (int n = g.OpenPopupStack.Size-1; n >= 0; n--) + if (ImGuiWindow* popup = g.OpenPopupStack.Data[n].Window) + if (popup->Flags & ImGuiWindowFlags_Modal) + return popup; + return NULL; +} + +void ImGui::ClosePopupToLevel(int remaining) +{ + IM_ASSERT(remaining >= 0); + ImGuiContext& g = *GImGui; + ImGuiWindow* focus_window = (remaining > 0) ? g.OpenPopupStack[remaining-1].Window : g.OpenPopupStack[0].ParentWindow; + if (g.NavLayer == 0) + focus_window = NavRestoreLastChildNavWindow(focus_window); + FocusWindow(focus_window); + focus_window->DC.NavHideHighlightOneFrame = true; + g.OpenPopupStack.resize(remaining); +} + +void ImGui::ClosePopup(ImGuiID id) +{ + if (!IsPopupOpen(id)) + return; + ImGuiContext& g = *GImGui; + ClosePopupToLevel(g.OpenPopupStack.Size - 1); +} + +// Close the popup we have begin-ed into. +void ImGui::CloseCurrentPopup() +{ + ImGuiContext& g = *GImGui; + int popup_idx = g.CurrentPopupStack.Size - 1; + if (popup_idx < 0 || popup_idx >= g.OpenPopupStack.Size || g.CurrentPopupStack[popup_idx].PopupId != g.OpenPopupStack[popup_idx].PopupId) + return; + while (popup_idx > 0 && g.OpenPopupStack[popup_idx].Window && (g.OpenPopupStack[popup_idx].Window->Flags & ImGuiWindowFlags_ChildMenu)) + popup_idx--; + ClosePopupToLevel(popup_idx); +} + +bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags) +{ + ImGuiContext& g = *GImGui; + if (!IsPopupOpen(id)) + { + g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values + return false; + } + + char name[20]; + if (extra_flags & ImGuiWindowFlags_ChildMenu) + ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.CurrentPopupStack.Size); // Recycle windows based on depth + else + ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame + + bool is_open = Begin(name, NULL, extra_flags | ImGuiWindowFlags_Popup); + if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display) + EndPopup(); + + return is_open; +} + +bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags) +{ + ImGuiContext& g = *GImGui; + if (g.OpenPopupStack.Size <= g.CurrentPopupStack.Size) // Early out for performance + { + g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values + return false; + } + return BeginPopupEx(g.CurrentWindow->GetID(str_id), flags|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); +} + +bool ImGui::IsPopupOpen(ImGuiID id) +{ + ImGuiContext& g = *GImGui; + return g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].PopupId == id; +} + +bool ImGui::IsPopupOpen(const char* str_id) +{ + ImGuiContext& g = *GImGui; + return g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].PopupId == g.CurrentWindow->GetID(str_id); +} + +bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags flags) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + const ImGuiID id = window->GetID(name); + if (!IsPopupOpen(id)) + { + g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values + return false; + } + + // Center modal windows by default + // FIXME: Should test for (PosCond & window->SetWindowPosAllowFlags) with the upcoming window. + if (g.NextWindowData.PosCond == 0) + SetNextWindowPos(g.IO.DisplaySize * 0.5f, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); + + bool is_open = Begin(name, p_open, flags | ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings); + if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display) + { + EndPopup(); + if (is_open) + ClosePopup(id); + return false; + } + + return is_open; +} + +void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const ImRect& bb_rel, ImGuiNavMoveFlags move_flags) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_None); + ImGui::NavMoveRequestCancel(); + g.NavMoveDir = move_dir; + g.NavMoveClipDir = clip_dir; + g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued; + g.NavMoveRequestFlags = move_flags; + g.NavWindow->NavRectRel[g.NavLayer] = bb_rel; +} + +void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags) +{ + ImGuiContext& g = *GImGui; + if (g.NavWindow != window || !NavMoveRequestButNoResultYet() || g.NavMoveRequestForward != ImGuiNavForward_None || g.NavLayer != 0) + return; + IM_ASSERT(move_flags != 0); // No points calling this with no wrapping + ImRect bb_rel = window->NavRectRel[0]; + + ImGuiDir clip_dir = g.NavMoveDir; + if (g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX))) + { + bb_rel.Min.x = bb_rel.Max.x = ImMax(window->SizeFull.x, window->SizeContents.x) - window->Scroll.x; + if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(-bb_rel.GetHeight()); clip_dir = ImGuiDir_Up; } + NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags); + } + if (g.NavMoveDir == ImGuiDir_Right && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX))) + { + bb_rel.Min.x = bb_rel.Max.x = -window->Scroll.x; + if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(+bb_rel.GetHeight()); clip_dir = ImGuiDir_Down; } + NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags); + } + if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY))) + { + bb_rel.Min.y = bb_rel.Max.y = ImMax(window->SizeFull.y, window->SizeContents.y) - window->Scroll.y; + if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(-bb_rel.GetWidth()); clip_dir = ImGuiDir_Left; } + NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags); + } + if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY))) + { + bb_rel.Min.y = bb_rel.Max.y = -window->Scroll.y; + if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(+bb_rel.GetWidth()); clip_dir = ImGuiDir_Right; } + NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags); + } +} + +void ImGui::EndPopup() +{ + ImGuiContext& g = *GImGui; (void)g; + IM_ASSERT(g.CurrentWindow->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginPopup()/EndPopup() calls + IM_ASSERT(g.CurrentPopupStack.Size > 0); + + // Make all menus and popups wrap around for now, may need to expose that policy. + NavMoveRequestTryWrapping(g.CurrentWindow, ImGuiNavMoveFlags_LoopY); + + End(); +} + +bool ImGui::OpenPopupOnItemClick(const char* str_id, int mouse_button) +{ + ImGuiWindow* window = GImGui->CurrentWindow; + if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + { + ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! + IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) + OpenPopupEx(id); + return true; + } + return false; +} + +// This is a helper to handle the simplest case of associating one named popup to one given widget. +// You may want to handle this on user side if you have specific needs (e.g. tweaking IsItemHovered() parameters). +// You can pass a NULL str_id to use the identifier of the last item. +bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button) +{ + ImGuiWindow* window = GImGui->CurrentWindow; + ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! + IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) + if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + OpenPopupEx(id); + return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); +} + +bool ImGui::BeginPopupContextWindow(const char* str_id, int mouse_button, bool also_over_items) +{ + if (!str_id) + str_id = "window_context"; + ImGuiID id = GImGui->CurrentWindow->GetID(str_id); + if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + if (also_over_items || !IsAnyItemHovered()) + OpenPopupEx(id); + return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); +} + +bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) +{ + if (!str_id) + str_id = "void_context"; + ImGuiID id = GImGui->CurrentWindow->GetID(str_id); + if (IsMouseReleased(mouse_button) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow)) + OpenPopupEx(id); + return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); +} + +static bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* parent_window = g.CurrentWindow; + + flags |= ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow; + flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag + + // Size + const ImVec2 content_avail = GetContentRegionAvail(); + ImVec2 size = ImFloor(size_arg); + const int auto_fit_axises = ((size.x == 0.0f) ? (1 << ImGuiAxis_X) : 0x00) | ((size.y == 0.0f) ? (1 << ImGuiAxis_Y) : 0x00); + if (size.x <= 0.0f) + size.x = ImMax(content_avail.x + size.x, 4.0f); // Arbitrary minimum child size (0.0f causing too much issues) + if (size.y <= 0.0f) + size.y = ImMax(content_avail.y + size.y, 4.0f); + SetNextWindowSize(size); + + // Name + char title[256]; + if (name) + ImFormatString(title, IM_ARRAYSIZE(title), "%s/%s", parent_window->Name, name); + else + ImFormatString(title, IM_ARRAYSIZE(title), "%s/%08X", parent_window->Name, id); + + const float backup_border_size = g.Style.ChildBorderSize; + if (!border) + g.Style.ChildBorderSize = 0.0f; + bool ret = Begin(title, NULL, flags); + g.Style.ChildBorderSize = backup_border_size; + + ImGuiWindow* child_window = g.CurrentWindow; + child_window->ChildId = id; + child_window->AutoFitChildAxises = auto_fit_axises; + + // Process navigation-in immediately so NavInit can run on first frame + if (g.NavActivateId == id && !(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayerActiveMask != 0 || child_window->DC.NavHasScroll)) + { + FocusWindow(child_window); + NavInitWindow(child_window, false); + SetActiveID(id+1, child_window); // Steal ActiveId with a dummy id so that key-press won't activate child item + g.ActiveIdSource = ImGuiInputSource_Nav; + } + + return ret; +} + +bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) +{ + ImGuiWindow* window = GetCurrentWindow(); + return BeginChildEx(str_id, window->GetID(str_id), size_arg, border, extra_flags); +} + +bool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) +{ + IM_ASSERT(id != 0); + return BeginChildEx(NULL, id, size_arg, border, extra_flags); +} + +void ImGui::EndChild() +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() callss + if (window->BeginCount > 1) + { + End(); + } + else + { + ImVec2 sz = window->Size; + if (window->AutoFitChildAxises & (1 << ImGuiAxis_X)) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f + sz.x = ImMax(4.0f, sz.x); + if (window->AutoFitChildAxises & (1 << ImGuiAxis_Y)) + sz.y = ImMax(4.0f, sz.y); + End(); + + ImGuiWindow* parent_window = g.CurrentWindow; + ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz); + ItemSize(sz); + if ((window->DC.NavLayerActiveMask != 0 || window->DC.NavHasScroll) && !(window->Flags & ImGuiWindowFlags_NavFlattened)) + { + ItemAdd(bb, window->ChildId); + RenderNavHighlight(bb, window->ChildId); + + // When browsing a window that has no activable items (scroll only) we keep a highlight on the child + if (window->DC.NavLayerActiveMask == 0 && window == g.NavWindow) + RenderNavHighlight(ImRect(bb.Min - ImVec2(2,2), bb.Max + ImVec2(2,2)), g.NavId, ImGuiNavHighlightFlags_TypeThin); + } + else + { + // Not navigable into + ItemAdd(bb, 0); + } + } +} + +// Helper to create a child window / scrolling region that looks like a normal widget frame. +bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags) +{ + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]); + PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding); + PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize); + PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); + bool ret = BeginChild(id, size, true, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding | extra_flags); + PopStyleVar(3); + PopStyleColor(); + return ret; +} + +void ImGui::EndChildFrame() +{ + EndChild(); +} + +// Save and compare stack sizes on Begin()/End() to detect usage errors +static void CheckStacksSize(ImGuiWindow* window, bool write) +{ + // NOT checking: DC.ItemWidth, DC.AllowKeyboardFocus, DC.ButtonRepeat, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin) + ImGuiContext& g = *GImGui; + int* p_backup = &window->DC.StackSizesBackup[0]; + { int current = window->IDStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "PushID/PopID or TreeNode/TreePop Mismatch!"); p_backup++; } // Too few or too many PopID()/TreePop() + { int current = window->DC.GroupStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "BeginGroup/EndGroup Mismatch!"); p_backup++; } // Too few or too many EndGroup() + { int current = g.CurrentPopupStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "BeginMenu/EndMenu or BeginPopup/EndPopup Mismatch"); p_backup++;}// Too few or too many EndMenu()/EndPopup() + // For color, style and font stacks there is an incentive to use Push/Begin/Pop/.../End patterns, so we relax our checks a little to allow them. + { int current = g.ColorModifiers.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup >= current && "PushStyleColor/PopStyleColor Mismatch!"); p_backup++; } // Too few or too many PopStyleColor() + { int current = g.StyleModifiers.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup >= current && "PushStyleVar/PopStyleVar Mismatch!"); p_backup++; } // Too few or too many PopStyleVar() + { int current = g.FontStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup >= current && "PushFont/PopFont Mismatch!"); p_backup++; } // Too few or too many PopFont() + IM_ASSERT(p_backup == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup)); +} + +enum ImGuiPopupPositionPolicy +{ + ImGuiPopupPositionPolicy_Default, + ImGuiPopupPositionPolicy_ComboBox +}; + +static ImRect FindAllowedExtentRectForWindow(ImGuiWindow*) +{ + ImVec2 padding = GImGui->Style.DisplaySafeAreaPadding; + ImRect r_screen = GetViewportRect(); + r_screen.Expand(ImVec2((r_screen.GetWidth() > padding.x * 2) ? -padding.x : 0.0f, (r_screen.GetHeight() > padding.y * 2) ? -padding.y : 0.0f)); + return r_screen; +} + +// r_avoid = the rectangle to avoid (e.g. for tooltip it is a rectangle around the mouse cursor which we want to avoid. for popups it's a small point around the cursor.) +// r_outer = the visible area rectangle, minus safe area padding. If our popup size won't fit because of safe area padding we ignore it. +static ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy = ImGuiPopupPositionPolicy_Default) +{ + ImVec2 base_pos_clamped = ImClamp(ref_pos, r_outer.Min, r_outer.Max - size); + //GImGui->OverlayDrawList.AddRect(r_avoid.Min, r_avoid.Max, IM_COL32(255,0,0,255)); + //GImGui->OverlayDrawList.AddRect(r_outer.Min, r_outer.Max, IM_COL32(0,255,0,255)); + + // Combo Box policy (we want a connecting edge) + if (policy == ImGuiPopupPositionPolicy_ComboBox) + { + const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Down, ImGuiDir_Right, ImGuiDir_Left, ImGuiDir_Up }; + for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++) + { + const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n]; + if (n != -1 && dir == *last_dir) // Already tried this direction? + continue; + ImVec2 pos; + if (dir == ImGuiDir_Down) pos = ImVec2(r_avoid.Min.x, r_avoid.Max.y); // Below, Toward Right (default) + if (dir == ImGuiDir_Right) pos = ImVec2(r_avoid.Min.x, r_avoid.Min.y - size.y); // Above, Toward Right + if (dir == ImGuiDir_Left) pos = ImVec2(r_avoid.Max.x - size.x, r_avoid.Max.y); // Below, Toward Left + if (dir == ImGuiDir_Up) pos = ImVec2(r_avoid.Max.x - size.x, r_avoid.Min.y - size.y); // Above, Toward Left + if (!r_outer.Contains(ImRect(pos, pos + size))) + continue; + *last_dir = dir; + return pos; + } + } + + // Default popup policy + const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Right, ImGuiDir_Down, ImGuiDir_Up, ImGuiDir_Left }; + for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++) + { + const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n]; + if (n != -1 && dir == *last_dir) // Already tried this direction? + continue; + float avail_w = (dir == ImGuiDir_Left ? r_avoid.Min.x : r_outer.Max.x) - (dir == ImGuiDir_Right ? r_avoid.Max.x : r_outer.Min.x); + float avail_h = (dir == ImGuiDir_Up ? r_avoid.Min.y : r_outer.Max.y) - (dir == ImGuiDir_Down ? r_avoid.Max.y : r_outer.Min.y); + if (avail_w < size.x || avail_h < size.y) + continue; + ImVec2 pos; + pos.x = (dir == ImGuiDir_Left) ? r_avoid.Min.x - size.x : (dir == ImGuiDir_Right) ? r_avoid.Max.x : base_pos_clamped.x; + pos.y = (dir == ImGuiDir_Up) ? r_avoid.Min.y - size.y : (dir == ImGuiDir_Down) ? r_avoid.Max.y : base_pos_clamped.y; + *last_dir = dir; + return pos; + } + + // Fallback, try to keep within display + *last_dir = ImGuiDir_None; + ImVec2 pos = ref_pos; + pos.x = ImMax(ImMin(pos.x + size.x, r_outer.Max.x) - size.x, r_outer.Min.x); + pos.y = ImMax(ImMin(pos.y + size.y, r_outer.Max.y) - size.y, r_outer.Min.y); + return pos; +} + +static ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + + ImRect r_outer = FindAllowedExtentRectForWindow(window); + if (window->Flags & ImGuiWindowFlags_ChildMenu) + { + // Child menus typically request _any_ position within the parent menu item, and then our FindBestWindowPosForPopup() function will move the new menu outside the parent bounds. + // This is how we end up with child menus appearing (most-commonly) on the right of the parent menu. + IM_ASSERT(g.CurrentWindow == window); + ImGuiWindow* parent_window = g.CurrentWindowStack[g.CurrentWindowStack.Size - 2]; + float horizontal_overlap = g.Style.ItemSpacing.x; // We want some overlap to convey the relative depth of each menu (currently the amount of overlap is hard-coded to style.ItemSpacing.x). + ImRect r_avoid; + if (parent_window->DC.MenuBarAppending) + r_avoid = ImRect(-FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight(), FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight() + parent_window->MenuBarHeight()); + else + r_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX); + return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid); + } + if (window->Flags & ImGuiWindowFlags_Popup) + { + ImRect r_avoid = ImRect(window->Pos.x - 1, window->Pos.y - 1, window->Pos.x + 1, window->Pos.y + 1); + return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid); + } + if (window->Flags & ImGuiWindowFlags_Tooltip) + { + // Position tooltip (always follows mouse) + float sc = g.Style.MouseCursorScale; + ImVec2 ref_pos = NavCalcPreferredRefPos(); + ImRect r_avoid; + if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos)) + r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8); + else + r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * sc, ref_pos.y + 24 * sc); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important. + ImVec2 pos = FindBestWindowPosForPopupEx(ref_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid); + if (window->AutoPosLastDirection == ImGuiDir_None) + pos = ref_pos + ImVec2(2, 2); // If there's not enough room, for tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible. + return pos; + } + IM_ASSERT(0); + return window->Pos; +} + +static void SetWindowConditionAllowFlags(ImGuiWindow* window, ImGuiCond flags, bool enabled) +{ + window->SetWindowPosAllowFlags = enabled ? (window->SetWindowPosAllowFlags | flags) : (window->SetWindowPosAllowFlags & ~flags); + window->SetWindowSizeAllowFlags = enabled ? (window->SetWindowSizeAllowFlags | flags) : (window->SetWindowSizeAllowFlags & ~flags); + window->SetWindowCollapsedAllowFlags = enabled ? (window->SetWindowCollapsedAllowFlags | flags) : (window->SetWindowCollapsedAllowFlags & ~flags); +} + +ImGuiWindow* ImGui::FindWindowByName(const char* name) +{ + ImGuiContext& g = *GImGui; + ImGuiID id = ImHash(name, 0); + return (ImGuiWindow*)g.WindowsById.GetVoidPtr(id); +} + +static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags) +{ + ImGuiContext& g = *GImGui; + + // Create window the first time + ImGuiWindow* window = IM_NEW(ImGuiWindow)(&g, name); + window->Flags = flags; + g.WindowsById.SetVoidPtr(window->ID, window); + + // Default/arbitrary window position. Use SetNextWindowPos() with the appropriate condition flag to change the initial position of a window. + window->Pos = ImVec2(60, 60); + + // User can disable loading and saving of settings. Tooltip and child windows also don't store settings. + if (!(flags & ImGuiWindowFlags_NoSavedSettings)) + if (ImGuiWindowSettings* settings = ImGui::FindWindowSettings(window->ID)) + { + // Retrieve settings from .ini file + window->SettingsIdx = g.SettingsWindows.index_from_pointer(settings); + SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false); + window->Pos = ImFloor(settings->Pos); + window->Collapsed = settings->Collapsed; + if (ImLengthSqr(settings->Size) > 0.00001f) + size = ImFloor(settings->Size); + } + window->Size = window->SizeFull = window->SizeFullAtLastBegin = size; + window->DC.CursorMaxPos = window->Pos; // So first call to CalcSizeContents() doesn't return crazy values + + if ((flags & ImGuiWindowFlags_AlwaysAutoResize) != 0) + { + window->AutoFitFramesX = window->AutoFitFramesY = 2; + window->AutoFitOnlyGrows = false; + } + else + { + if (window->Size.x <= 0.0f) + window->AutoFitFramesX = 2; + if (window->Size.y <= 0.0f) + window->AutoFitFramesY = 2; + window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0); + } + + if (flags & ImGuiWindowFlags_NoBringToFrontOnFocus) + g.Windows.insert(g.Windows.begin(), window); // Quite slow but rare and only once + else + g.Windows.push_back(window); + return window; +} + +static ImVec2 CalcSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size) +{ + ImGuiContext& g = *GImGui; + if (g.NextWindowData.SizeConstraintCond != 0) + { + // Using -1,-1 on either X/Y axis to preserve the current size. + ImRect cr = g.NextWindowData.SizeConstraintRect; + new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x; + new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y; + if (g.NextWindowData.SizeCallback) + { + ImGuiSizeCallbackData data; + data.UserData = g.NextWindowData.SizeCallbackUserData; + data.Pos = window->Pos; + data.CurrentSize = window->SizeFull; + data.DesiredSize = new_size; + g.NextWindowData.SizeCallback(&data); + new_size = data.DesiredSize; + } + } + + // Minimum size + if (!(window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysAutoResize))) + { + new_size = ImMax(new_size, g.Style.WindowMinSize); + new_size.y = ImMax(new_size.y, window->TitleBarHeight() + window->MenuBarHeight() + ImMax(0.0f, g.Style.WindowRounding - 1.0f)); // Reduce artifacts with very small windows + } + return new_size; +} + +static ImVec2 CalcSizeContents(ImGuiWindow* window) +{ + ImVec2 sz; + sz.x = (float)(int)((window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : (window->DC.CursorMaxPos.x - window->Pos.x + window->Scroll.x)); + sz.y = (float)(int)((window->SizeContentsExplicit.y != 0.0f) ? window->SizeContentsExplicit.y : (window->DC.CursorMaxPos.y - window->Pos.y + window->Scroll.y)); + return sz + window->WindowPadding; +} + +static ImVec2 CalcSizeAutoFit(ImGuiWindow* window, const ImVec2& size_contents) +{ + ImGuiContext& g = *GImGui; + ImGuiStyle& style = g.Style; + if (window->Flags & ImGuiWindowFlags_Tooltip) + { + // Tooltip always resize + return size_contents; + } + else + { + // When the window cannot fit all contents (either because of constraints, either because screen is too small): we are growing the size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than DisplaySize-WindowPadding. + const bool is_popup = (window->Flags & ImGuiWindowFlags_Popup) != 0; + const bool is_menu = (window->Flags & ImGuiWindowFlags_ChildMenu) != 0; + ImVec2 size_min = style.WindowMinSize; + if (is_popup || is_menu) // Popups and menus bypass style.WindowMinSize by default, but we give then a non-zero minimum size to facilitate understanding problematic cases (e.g. empty popups) + size_min = ImMin(size_min, ImVec2(4.0f, 4.0f)); + ImVec2 size_auto_fit = ImClamp(size_contents, size_min, ImMax(size_min, g.IO.DisplaySize - style.DisplaySafeAreaPadding * 2.0f)); + ImVec2 size_auto_fit_after_constraint = CalcSizeAfterConstraint(window, size_auto_fit); + if (size_auto_fit_after_constraint.x < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar)) + size_auto_fit.y += style.ScrollbarSize; + if (size_auto_fit_after_constraint.y < size_contents.y && !(window->Flags & ImGuiWindowFlags_NoScrollbar)) + size_auto_fit.x += style.ScrollbarSize; + return size_auto_fit; + } +} + +static float GetScrollMaxX(ImGuiWindow* window) +{ + return ImMax(0.0f, window->SizeContents.x - (window->SizeFull.x - window->ScrollbarSizes.x)); +} + +static float GetScrollMaxY(ImGuiWindow* window) +{ + return ImMax(0.0f, window->SizeContents.y - (window->SizeFull.y - window->ScrollbarSizes.y)); +} + +static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges) +{ + ImGuiContext& g = *GImGui; + ImVec2 scroll = window->Scroll; + if (window->ScrollTarget.x < FLT_MAX) + { + float cr_x = window->ScrollTargetCenterRatio.x; + scroll.x = window->ScrollTarget.x - cr_x * (window->SizeFull.x - window->ScrollbarSizes.x); + } + if (window->ScrollTarget.y < FLT_MAX) + { + // 'snap_on_edges' allows for a discontinuity at the edge of scrolling limits to take account of WindowPadding so that scrolling to make the last item visible scroll far enough to see the padding. + float cr_y = window->ScrollTargetCenterRatio.y; + float target_y = window->ScrollTarget.y; + if (snap_on_edges && cr_y <= 0.0f && target_y <= window->WindowPadding.y) + target_y = 0.0f; + if (snap_on_edges && cr_y >= 1.0f && target_y >= window->SizeContents.y - window->WindowPadding.y + g.Style.ItemSpacing.y) + target_y = window->SizeContents.y; + scroll.y = target_y - (1.0f - cr_y) * (window->TitleBarHeight() + window->MenuBarHeight()) - cr_y * (window->SizeFull.y - window->ScrollbarSizes.y); + } + scroll = ImMax(scroll, ImVec2(0.0f, 0.0f)); + if (!window->Collapsed && !window->SkipItems) + { + scroll.x = ImMin(scroll.x, GetScrollMaxX(window)); + scroll.y = ImMin(scroll.y, GetScrollMaxY(window)); + } + return scroll; +} + +static ImGuiCol GetWindowBgColorIdxFromFlags(ImGuiWindowFlags flags) +{ + if (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) + return ImGuiCol_PopupBg; + if (flags & ImGuiWindowFlags_ChildWindow) + return ImGuiCol_ChildBg; + return ImGuiCol_WindowBg; +} + +static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, const ImVec2& corner_target, const ImVec2& corner_norm, ImVec2* out_pos, ImVec2* out_size) +{ + ImVec2 pos_min = ImLerp(corner_target, window->Pos, corner_norm); // Expected window upper-left + ImVec2 pos_max = ImLerp(window->Pos + window->Size, corner_target, corner_norm); // Expected window lower-right + ImVec2 size_expected = pos_max - pos_min; + ImVec2 size_constrained = CalcSizeAfterConstraint(window, size_expected); + *out_pos = pos_min; + if (corner_norm.x == 0.0f) + out_pos->x -= (size_constrained.x - size_expected.x); + if (corner_norm.y == 0.0f) + out_pos->y -= (size_constrained.y - size_expected.y); + *out_size = size_constrained; +} + +struct ImGuiResizeGripDef +{ + ImVec2 CornerPos; + ImVec2 InnerDir; + int AngleMin12, AngleMax12; +}; + +const ImGuiResizeGripDef resize_grip_def[4] = +{ + { ImVec2(1,1), ImVec2(-1,-1), 0, 3 }, // Lower right + { ImVec2(0,1), ImVec2(+1,-1), 3, 6 }, // Lower left + { ImVec2(0,0), ImVec2(+1,+1), 6, 9 }, // Upper left + { ImVec2(1,0), ImVec2(-1,+1), 9,12 }, // Upper right +}; + +static ImRect GetBorderRect(ImGuiWindow* window, int border_n, float perp_padding, float thickness) +{ + ImRect rect = window->Rect(); + if (thickness == 0.0f) rect.Max -= ImVec2(1,1); + if (border_n == 0) return ImRect(rect.Min.x + perp_padding, rect.Min.y, rect.Max.x - perp_padding, rect.Min.y + thickness); + if (border_n == 1) return ImRect(rect.Max.x - thickness, rect.Min.y + perp_padding, rect.Max.x, rect.Max.y - perp_padding); + if (border_n == 2) return ImRect(rect.Min.x + perp_padding, rect.Max.y - thickness, rect.Max.x - perp_padding, rect.Max.y); + if (border_n == 3) return ImRect(rect.Min.x, rect.Min.y + perp_padding, rect.Min.x + thickness, rect.Max.y - perp_padding); + IM_ASSERT(0); + return ImRect(); +} + +// Handle resize for: Resize Grips, Borders, Gamepad +static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]) +{ + ImGuiContext& g = *GImGui; + ImGuiWindowFlags flags = window->Flags; + if ((flags & ImGuiWindowFlags_NoResize) || (flags & ImGuiWindowFlags_AlwaysAutoResize) || window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) + return; + + const int resize_border_count = g.IO.ConfigResizeWindowsFromEdges ? 4 : 0; + const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f); + const float grip_hover_size = (float)(int)(grip_draw_size * 0.75f); + + ImVec2 pos_target(FLT_MAX, FLT_MAX); + ImVec2 size_target(FLT_MAX, FLT_MAX); + + // Manual resize grips + PushID("#RESIZE"); + for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++) + { + const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n]; + const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPos); + + // Using the FlattenChilds button flag we make the resize button accessible even if we are hovering over a child window + ImRect resize_rect(corner, corner + grip.InnerDir * grip_hover_size); + if (resize_rect.Min.x > resize_rect.Max.x) ImSwap(resize_rect.Min.x, resize_rect.Max.x); + if (resize_rect.Min.y > resize_rect.Max.y) ImSwap(resize_rect.Min.y, resize_rect.Max.y); + bool hovered, held; + ButtonBehavior(resize_rect, window->GetID((void*)(intptr_t)resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus); + if (hovered || held) + g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE; + + if (held && g.IO.MouseDoubleClicked[0] && resize_grip_n == 0) + { + // Manual auto-fit when double-clicking + size_target = CalcSizeAfterConstraint(window, size_auto_fit); + ClearActiveID(); + } + else if (held) + { + // Resize from any of the four corners + // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position + ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize() * grip.CornerPos; // Corner of the window corresponding to our corner grip + CalcResizePosSizeFromAnyCorner(window, corner_target, grip.CornerPos, &pos_target, &size_target); + } + if (resize_grip_n == 0 || held || hovered) + resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); + } + for (int border_n = 0; border_n < resize_border_count; border_n++) + { + const float BORDER_SIZE = 5.0f; // FIXME: Only works _inside_ window because of HoveredWindow check. + const float BORDER_APPEAR_TIMER = 0.05f; // Reduce visual noise + bool hovered, held; + ImRect border_rect = GetBorderRect(window, border_n, grip_hover_size, BORDER_SIZE); + ButtonBehavior(border_rect, window->GetID((void*)(intptr_t)(border_n + 4)), &hovered, &held, ImGuiButtonFlags_FlattenChildren); + if ((hovered && g.HoveredIdTimer > BORDER_APPEAR_TIMER) || held) + { + g.MouseCursor = (border_n & 1) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS; + if (held) *border_held = border_n; + } + if (held) + { + ImVec2 border_target = window->Pos; + ImVec2 border_posn; + if (border_n == 0) { border_posn = ImVec2(0, 0); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y); } + if (border_n == 1) { border_posn = ImVec2(1, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + BORDER_SIZE); } + if (border_n == 2) { border_posn = ImVec2(0, 1); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y + BORDER_SIZE); } + if (border_n == 3) { border_posn = ImVec2(0, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x); } + CalcResizePosSizeFromAnyCorner(window, border_target, border_posn, &pos_target, &size_target); + } + } + PopID(); + + // Navigation resize (keyboard/gamepad) + if (g.NavWindowingTarget && g.NavWindowingTarget->RootWindow == window) + { + ImVec2 nav_resize_delta; + if (g.NavInputSource == ImGuiInputSource_NavKeyboard && g.IO.KeyShift) + nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down); + if (g.NavInputSource == ImGuiInputSource_NavGamepad) + nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_Down); + if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f) + { + const float NAV_RESIZE_SPEED = 600.0f; + nav_resize_delta *= ImFloor(NAV_RESIZE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); + g.NavWindowingToggleLayer = false; + g.NavDisableMouseHover = true; + resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive); + // FIXME-NAV: Should store and accumulate into a separate size buffer to handle sizing constraints properly, right now a constraint will make us stuck. + size_target = CalcSizeAfterConstraint(window, window->SizeFull + nav_resize_delta); + } + } + + // Apply back modified position/size to window + if (size_target.x != FLT_MAX) + { + window->SizeFull = size_target; + MarkIniSettingsDirty(window); + } + if (pos_target.x != FLT_MAX) + { + window->Pos = ImFloor(pos_target); + MarkIniSettingsDirty(window); + } + + window->Size = window->SizeFull; +} + +void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window) +{ + window->ParentWindow = parent_window; + window->RootWindow = window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window; + if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip)) + window->RootWindow = parent_window->RootWindow; + if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) + window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight; + while (window->RootWindowForNav->Flags & ImGuiWindowFlags_NavFlattened) + window->RootWindowForNav = window->RootWindowForNav->ParentWindow; +} + +// Push a new ImGui window to add widgets to. +// - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair. +// - Begin/End can be called multiple times during the frame with the same window name to append content. +// - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file). +// You can use the "##" or "###" markers to use the same label with different id, or same id with different label. See documentation at the top of this file. +// - Return false when window is collapsed, so you can early out in your code. You always need to call ImGui::End() even if false is returned. +// - Passing 'bool* p_open' displays a Close button on the upper-right corner of the window, the pointed value will be set to false when the button is pressed. +bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) +{ + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + IM_ASSERT(name != NULL); // Window name required + IM_ASSERT(g.FrameScopeActive); // Forgot to call ImGui::NewFrame() + IM_ASSERT(g.FrameCountEnded != g.FrameCount); // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet + + // Find or create + ImGuiWindow* window = FindWindowByName(name); + const bool window_just_created = (window == NULL); + if (window_just_created) + { + ImVec2 size_on_first_use = (g.NextWindowData.SizeCond != 0) ? g.NextWindowData.SizeVal : ImVec2(0.0f, 0.0f); // Any condition flag will do since we are creating a new window here. + window = CreateNewWindow(name, size_on_first_use, flags); + } + + // Automatically disable manual moving/resizing when NoInputs is set + if (flags & ImGuiWindowFlags_NoInputs) + flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; + + if (flags & ImGuiWindowFlags_NavFlattened) + IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow); + + const int current_frame = g.FrameCount; + const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame); + if (first_begin_of_the_frame) + window->Flags = (ImGuiWindowFlags)flags; + else + flags = window->Flags; + + // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack + ImGuiWindow* parent_window_in_stack = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back(); + ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow; + IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); + window->HasCloseButton = (p_open != NULL); + + // Update the Appearing flag + bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on + const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesForResize > 0); + if (flags & ImGuiWindowFlags_Popup) + { + ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.CurrentPopupStack.Size]; + window_just_activated_by_user |= (window->PopupId != popup_ref.PopupId); // We recycle popups so treat window as activated if popup id changed + window_just_activated_by_user |= (window != popup_ref.Window); + } + window->Appearing = (window_just_activated_by_user || window_just_appearing_after_hidden_for_resize); + if (window->Appearing) + SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, true); + + // Add to stack + g.CurrentWindowStack.push_back(window); + SetCurrentWindow(window); + CheckStacksSize(window, true); + if (flags & ImGuiWindowFlags_Popup) + { + ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.CurrentPopupStack.Size]; + popup_ref.Window = window; + g.CurrentPopupStack.push_back(popup_ref); + window->PopupId = popup_ref.PopupId; + } + + if (window_just_appearing_after_hidden_for_resize && !(flags & ImGuiWindowFlags_ChildWindow)) + window->NavLastIds[0] = 0; + + // Process SetNextWindow***() calls + bool window_pos_set_by_api = false; + bool window_size_x_set_by_api = false, window_size_y_set_by_api = false; + if (g.NextWindowData.PosCond) + { + window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.NextWindowData.PosCond) != 0; + if (window_pos_set_by_api && ImLengthSqr(g.NextWindowData.PosPivotVal) > 0.00001f) + { + // May be processed on the next frame if this is our first frame and we are measuring size + // FIXME: Look into removing the branch so everything can go through this same code path for consistency. + window->SetWindowPosVal = g.NextWindowData.PosVal; + window->SetWindowPosPivot = g.NextWindowData.PosPivotVal; + window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); + } + else + { + SetWindowPos(window, g.NextWindowData.PosVal, g.NextWindowData.PosCond); + } + } + if (g.NextWindowData.SizeCond) + { + window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.x > 0.0f); + window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.y > 0.0f); + SetWindowSize(window, g.NextWindowData.SizeVal, g.NextWindowData.SizeCond); + } + if (g.NextWindowData.ContentSizeCond) + { + // Adjust passed "client size" to become a "window size" + window->SizeContentsExplicit = g.NextWindowData.ContentSizeVal; + if (window->SizeContentsExplicit.y != 0.0f) + window->SizeContentsExplicit.y += window->TitleBarHeight() + window->MenuBarHeight(); + } + else if (first_begin_of_the_frame) + { + window->SizeContentsExplicit = ImVec2(0.0f, 0.0f); + } + if (g.NextWindowData.CollapsedCond) + SetWindowCollapsed(window, g.NextWindowData.CollapsedVal, g.NextWindowData.CollapsedCond); + if (g.NextWindowData.FocusCond) + FocusWindow(window); + if (window->Appearing) + SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false); + + // When reusing window again multiple times a frame, just append content (don't need to setup again) + if (first_begin_of_the_frame) + { + // Initialize + const bool window_is_child_tooltip = (flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_Tooltip); // FIXME-WIP: Undocumented behavior of Child+Tooltip for pinned tooltip (#1345) + UpdateWindowParentAndRootLinks(window, flags, parent_window); + + window->Active = true; + window->BeginOrderWithinParent = 0; + window->BeginOrderWithinContext = g.WindowsActiveCount++; + window->BeginCount = 0; + window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX); + window->LastFrameActive = current_frame; + window->IDStack.resize(1); + + // UPDATE CONTENTS SIZE, UPDATE HIDDEN STATUS + + // Update contents size from last frame for auto-fitting (or use explicit size) + window->SizeContents = CalcSizeContents(window); + if (window->HiddenFramesRegular > 0) + window->HiddenFramesRegular--; + if (window->HiddenFramesForResize > 0) + window->HiddenFramesForResize--; + + // Hide new windows for one frame until they calculate their size + if (window_just_created && (!window_size_x_set_by_api || !window_size_y_set_by_api)) + window->HiddenFramesForResize = 1; + + // Hide popup/tooltip window when re-opening while we measure size (because we recycle the windows) + // We reset Size/SizeContents for reappearing popups/tooltips early in this function, so further code won't be tempted to use the old size. + if (window_just_activated_by_user && (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0) + { + window->HiddenFramesForResize = 1; + if (flags & ImGuiWindowFlags_AlwaysAutoResize) + { + if (!window_size_x_set_by_api) + window->Size.x = window->SizeFull.x = 0.f; + if (!window_size_y_set_by_api) + window->Size.y = window->SizeFull.y = 0.f; + window->SizeContents = ImVec2(0.f, 0.f); + } + } + + SetCurrentWindow(window); + + // Lock border size and padding for the frame (so that altering them doesn't cause inconsistencies) + window->WindowBorderSize = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildBorderSize : ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize; + window->WindowPadding = style.WindowPadding; + if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f) + window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f); + window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x); + window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y; + + // Collapse window by double-clicking on title bar + // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing + if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse)) + { + // We don't use a regular button+id to test for double-click on title bar (mostly due to legacy reason, could be fixed), so verify that we don't have items over the title bar. + ImRect title_bar_rect = window->TitleBarRect(); + if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseDoubleClicked[0]) + window->WantCollapseToggle = true; + if (window->WantCollapseToggle) + { + window->Collapsed = !window->Collapsed; + MarkIniSettingsDirty(window); + FocusWindow(window); + } + } + else + { + window->Collapsed = false; + } + window->WantCollapseToggle = false; + + // SIZE + + // Calculate auto-fit size, handle automatic resize + const ImVec2 size_auto_fit = CalcSizeAutoFit(window, window->SizeContents); + ImVec2 size_full_modified(FLT_MAX, FLT_MAX); + if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed) + { + // Using SetNextWindowSize() overrides ImGuiWindowFlags_AlwaysAutoResize, so it can be used on tooltips/popups, etc. + if (!window_size_x_set_by_api) + window->SizeFull.x = size_full_modified.x = size_auto_fit.x; + if (!window_size_y_set_by_api) + window->SizeFull.y = size_full_modified.y = size_auto_fit.y; + } + else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) + { + // Auto-fit may only grow window during the first few frames + // We still process initial auto-fit on collapsed windows to get a window width, but otherwise don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed. + if (!window_size_x_set_by_api && window->AutoFitFramesX > 0) + window->SizeFull.x = size_full_modified.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x; + if (!window_size_y_set_by_api && window->AutoFitFramesY > 0) + window->SizeFull.y = size_full_modified.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y; + if (!window->Collapsed) + MarkIniSettingsDirty(window); + } + + // Apply minimum/maximum window size constraints and final size + window->SizeFull = CalcSizeAfterConstraint(window, window->SizeFull); + window->Size = window->Collapsed && !(flags & ImGuiWindowFlags_ChildWindow) ? window->TitleBarRect().GetSize() : window->SizeFull; + + // SCROLLBAR STATUS + + // Update scrollbar status (based on the Size that was effective during last frame or the auto-resized Size). + if (!window->Collapsed) + { + // When reading the current size we need to read it after size constraints have been applied + float size_x_for_scrollbars = size_full_modified.x != FLT_MAX ? window->SizeFull.x : window->SizeFullAtLastBegin.x; + float size_y_for_scrollbars = size_full_modified.y != FLT_MAX ? window->SizeFull.y : window->SizeFullAtLastBegin.y; + window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar)); + window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); + if (window->ScrollbarX && !window->ScrollbarY) + window->ScrollbarY = (window->SizeContents.y > size_y_for_scrollbars - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar); + window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); + } + + // POSITION + + // Popup latch its initial position, will position itself when it appears next frame + if (window_just_activated_by_user) + { + window->AutoPosLastDirection = ImGuiDir_None; + if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api) + window->Pos = g.CurrentPopupStack.back().OpenPopupPos; + } + + // Position child window + if (flags & ImGuiWindowFlags_ChildWindow) + { + window->BeginOrderWithinParent = parent_window->DC.ChildWindows.Size; + parent_window->DC.ChildWindows.push_back(window); + if (!(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api && !window_is_child_tooltip) + window->Pos = parent_window->DC.CursorPos; + } + + const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFramesForResize == 0); + if (window_pos_with_pivot) + SetWindowPos(window, ImMax(style.DisplaySafeAreaPadding, window->SetWindowPosVal - window->SizeFull * window->SetWindowPosPivot), 0); // Position given a pivot (e.g. for centering) + else if ((flags & ImGuiWindowFlags_ChildMenu) != 0) + window->Pos = FindBestWindowPosForPopup(window); + else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize) + window->Pos = FindBestWindowPosForPopup(window); + else if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !window_is_child_tooltip) + window->Pos = FindBestWindowPosForPopup(window); + + // Clamp position so it stays visible + if (!(flags & ImGuiWindowFlags_ChildWindow)) + { + if (!window_pos_set_by_api && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing. + { + ImVec2 padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding); + window->Pos = ImMax(window->Pos + window->Size, padding) - window->Size; + window->Pos = ImMin(window->Pos, g.IO.DisplaySize - padding); + } + } + window->Pos = ImFloor(window->Pos); + + // Lock window rounding for the frame (so that altering them doesn't cause inconsistencies) + window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding; + + // Prepare for item focus requests + window->FocusIdxAllRequestCurrent = (window->FocusIdxAllRequestNext == INT_MAX || window->FocusIdxAllCounter == -1) ? INT_MAX : (window->FocusIdxAllRequestNext + (window->FocusIdxAllCounter+1)) % (window->FocusIdxAllCounter+1); + window->FocusIdxTabRequestCurrent = (window->FocusIdxTabRequestNext == INT_MAX || window->FocusIdxTabCounter == -1) ? INT_MAX : (window->FocusIdxTabRequestNext + (window->FocusIdxTabCounter+1)) % (window->FocusIdxTabCounter+1); + window->FocusIdxAllCounter = window->FocusIdxTabCounter = -1; + window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = INT_MAX; + + // Apply scrolling + window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window, true); + window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); + + // Apply window focus (new and reactivated windows are moved to front) + bool want_focus = false; + if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing)) + if (!(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip)) || (flags & ImGuiWindowFlags_Popup)) + want_focus = true; + + // Handle manual resize: Resize Grips, Borders, Gamepad + int border_held = -1; + ImU32 resize_grip_col[4] = { 0 }; + const int resize_grip_count = g.IO.ConfigResizeWindowsFromEdges ? 2 : 1; // 4 + const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f); + if (!window->Collapsed) + UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]); + + // Default item width. Make it proportional to window size if window manually resizes + if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize)) + window->ItemWidthDefault = (float)(int)(window->Size.x * 0.65f); + else + window->ItemWidthDefault = (float)(int)(g.FontSize * 16.0f); + + // DRAWING + + // Setup draw list and outer clipping rectangle + window->DrawList->Clear(); + window->DrawList->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0); + window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID); + ImRect viewport_rect(GetViewportRect()); + if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip) + PushClipRect(parent_window->ClipRect.Min, parent_window->ClipRect.Max, true); + else + PushClipRect(viewport_rect.Min, viewport_rect.Max, true); + + // Draw modal window background (darkens what is behind them, all viewports) + const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetFrontMostPopupModal() && window->HiddenFramesForResize <= 0; + const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && (window == g.NavWindowingTargetAnim->RootWindow); + if (dim_bg_for_modal || dim_bg_for_window_list) + { + const ImU32 dim_bg_col = GetColorU32(dim_bg_for_modal ? ImGuiCol_ModalWindowDimBg : ImGuiCol_NavWindowingDimBg, g.DimBgRatio); + window->DrawList->AddRectFilled(viewport_rect.Min, viewport_rect.Max, dim_bg_col); + } + + // Draw navigation selection/windowing rectangle background + if (dim_bg_for_window_list && window == g.NavWindowingTargetAnim) + { + ImRect bb = window->Rect(); + bb.Expand(g.FontSize); + if (!bb.Contains(viewport_rect)) // Avoid drawing if the window covers all the viewport anyway + window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha * 0.25f), g.Style.WindowRounding); + } + + // Draw window + handle manual resize + const float window_rounding = window->WindowRounding; + const float window_border_size = window->WindowBorderSize; + const ImGuiWindow* window_to_highlight = g.NavWindowingTarget ? g.NavWindowingTarget : g.NavWindow; + const bool title_bar_is_highlight = want_focus || (window_to_highlight && window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight); + const ImRect title_bar_rect = window->TitleBarRect(); + if (window->Collapsed) + { + // Title bar only + float backup_border_size = style.FrameBorderSize; + g.Style.FrameBorderSize = window->WindowBorderSize; + ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && !g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed); + RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, true, window_rounding); + g.Style.FrameBorderSize = backup_border_size; + } + else + { + // Window background + ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags)); + if (g.NextWindowData.BgAlphaCond != 0) + { + bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(g.NextWindowData.BgAlphaVal) << IM_COL32_A_SHIFT); + g.NextWindowData.BgAlphaCond = 0; + } + window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot); + + // Title bar + ImU32 title_bar_col = GetColorU32(window->Collapsed ? ImGuiCol_TitleBgCollapsed : title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg); + if (!(flags & ImGuiWindowFlags_NoTitleBar)) + window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawCornerFlags_Top); + + // Menu bar + if (flags & ImGuiWindowFlags_MenuBar) + { + ImRect menu_bar_rect = window->MenuBarRect(); + menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them. + window->DrawList->AddRectFilled(menu_bar_rect.Min, menu_bar_rect.Max, GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawCornerFlags_Top); + if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y) + window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize); + } + + // Scrollbars + if (window->ScrollbarX) + Scrollbar(ImGuiLayoutType_Horizontal); + if (window->ScrollbarY) + Scrollbar(ImGuiLayoutType_Vertical); + + // Render resize grips (after their input handling so we don't have a frame of latency) + if (!(flags & ImGuiWindowFlags_NoResize)) + { + for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++) + { + const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n]; + const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPos); + window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, grip_draw_size) : ImVec2(grip_draw_size, window_border_size))); + window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(grip_draw_size, window_border_size) : ImVec2(window_border_size, grip_draw_size))); + window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + window_border_size), corner.y + grip.InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.AngleMin12, grip.AngleMax12); + window->DrawList->PathFillConvex(resize_grip_col[resize_grip_n]); + } + } + + // Borders + if (window_border_size > 0.0f) + window->DrawList->AddRect(window->Pos, window->Pos + window->Size, GetColorU32(ImGuiCol_Border), window_rounding, ImDrawCornerFlags_All, window_border_size); + if (border_held != -1) + { + ImRect border = GetBorderRect(window, border_held, grip_draw_size, 0.0f); + window->DrawList->AddLine(border.Min, border.Max, GetColorU32(ImGuiCol_SeparatorActive), ImMax(1.0f, window_border_size)); + } + if (style.FrameBorderSize > 0 && !(flags & ImGuiWindowFlags_NoTitleBar)) + window->DrawList->AddLine(title_bar_rect.GetBL() + ImVec2(style.WindowBorderSize, -1), title_bar_rect.GetBR() + ImVec2(-style.WindowBorderSize, -1), GetColorU32(ImGuiCol_Border), style.FrameBorderSize); + } + + // Draw navigation selection/windowing rectangle border + if (g.NavWindowingTargetAnim == window) + { + float rounding = ImMax(window->WindowRounding, g.Style.WindowRounding); + ImRect bb = window->Rect(); + bb.Expand(g.FontSize); + if (bb.Contains(viewport_rect)) // If a window fits the entire viewport, adjust its highlight inward + { + bb.Expand(-g.FontSize - 1.0f); + rounding = window->WindowRounding; + } + window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), rounding, ~0, 3.0f); + } + + // Store a backup of SizeFull which we will use next frame to decide if we need scrollbars. + window->SizeFullAtLastBegin = window->SizeFull; + + // Update various regions. Variables they depends on are set above in this function. + // FIXME: window->ContentsRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it. + window->ContentsRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x; + window->ContentsRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + window->TitleBarHeight() + window->MenuBarHeight(); + window->ContentsRegionRect.Max.x = window->Pos.x - window->Scroll.x - window->WindowPadding.x + (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : (window->Size.x - window->ScrollbarSizes.x)); + window->ContentsRegionRect.Max.y = window->Pos.y - window->Scroll.y - window->WindowPadding.y + (window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : (window->Size.y - window->ScrollbarSizes.y)); + + // Setup drawing context + // (NB: That term "drawing context / DC" lost its meaning a long time ago. Initially was meant to hold transient data only. Nowadays difference between window-> and window->DC-> is dubious.) + window->DC.IndentX = 0.0f + window->WindowPadding.x - window->Scroll.x; + window->DC.GroupOffsetX = 0.0f; + window->DC.ColumnsOffsetX = 0.0f; + window->DC.CursorStartPos = window->Pos + ImVec2(window->DC.IndentX + window->DC.ColumnsOffsetX, window->TitleBarHeight() + window->MenuBarHeight() + window->WindowPadding.y - window->Scroll.y); + window->DC.CursorPos = window->DC.CursorStartPos; + window->DC.CursorPosPrevLine = window->DC.CursorPos; + window->DC.CursorMaxPos = window->DC.CursorStartPos; + window->DC.CurrentLineHeight = window->DC.PrevLineHeight = 0.0f; + window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f; + window->DC.NavHideHighlightOneFrame = false; + window->DC.NavHasScroll = (GetScrollMaxY() > 0.0f); + window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext; + window->DC.NavLayerActiveMaskNext = 0x00; + window->DC.MenuBarAppending = false; + window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; + window->DC.ChildWindows.resize(0); + window->DC.LayoutType = ImGuiLayoutType_Vertical; + window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical; + window->DC.ItemFlags = parent_window ? parent_window->DC.ItemFlags : ImGuiItemFlags_Default_; + window->DC.ItemWidth = window->ItemWidthDefault; + window->DC.TextWrapPos = -1.0f; // disabled + window->DC.ItemFlagsStack.resize(0); + window->DC.ItemWidthStack.resize(0); + window->DC.TextWrapPosStack.resize(0); + window->DC.ColumnsSet = NULL; + window->DC.TreeDepth = 0; + window->DC.TreeDepthMayJumpToParentOnPop = 0x00; + window->DC.StateStorage = &window->StateStorage; + window->DC.GroupStack.resize(0); + window->MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user); + + if ((flags & ImGuiWindowFlags_ChildWindow) && (window->DC.ItemFlags != parent_window->DC.ItemFlags)) + { + window->DC.ItemFlags = parent_window->DC.ItemFlags; + window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags); + } + + if (window->AutoFitFramesX > 0) + window->AutoFitFramesX--; + if (window->AutoFitFramesY > 0) + window->AutoFitFramesY--; + + // Apply focus (we need to call FocusWindow() AFTER setting DC.CursorStartPos so our initial navigation reference rectangle can start around there) + if (want_focus) + { + FocusWindow(window); + NavInitWindow(window, false); + } + + // Title bar + if (!(flags & ImGuiWindowFlags_NoTitleBar)) + { + // Close & collapse button are on layer 1 (same as menus) and don't default focus + const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags; + window->DC.ItemFlags |= ImGuiItemFlags_NoNavDefaultFocus; + window->DC.NavLayerCurrent++; + window->DC.NavLayerCurrentMask <<= 1; + + // Collapse button + if (!(flags & ImGuiWindowFlags_NoCollapse)) + if (CollapseButton(window->GetID("#COLLAPSE"), window->Pos)) + window->WantCollapseToggle = true; // Defer collapsing to next frame as we are too far in the Begin() function + + // Close button + if (p_open != NULL) + { + const float pad = style.FramePadding.y; + const float rad = g.FontSize * 0.5f; + if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-pad - rad, pad + rad), rad + 1)) + *p_open = false; + } + + window->DC.NavLayerCurrent--; + window->DC.NavLayerCurrentMask >>= 1; + window->DC.ItemFlags = item_flags_backup; + + // Title text (FIXME: refactor text alignment facilities along with RenderText helpers, this is too much code for what it does.) + ImVec2 text_size = CalcTextSize(name, NULL, true); + ImRect text_r = title_bar_rect; + float pad_left = (flags & ImGuiWindowFlags_NoCollapse) ? style.FramePadding.x : (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x); + float pad_right = (p_open == NULL) ? style.FramePadding.x : (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x); + if (style.WindowTitleAlign.x > 0.0f) + pad_right = ImLerp(pad_right, pad_left, style.WindowTitleAlign.x); + text_r.Min.x += pad_left; + text_r.Max.x -= pad_right; + ImRect clip_rect = text_r; + clip_rect.Max.x = window->Pos.x + window->Size.x - (p_open ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x); // Match the size of CloseButton() + RenderTextClipped(text_r.Min, text_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_rect); + } + + // Save clipped aabb so we can access it in constant-time in FindHoveredWindow() + window->OuterRectClipped = window->Rect(); + window->OuterRectClipped.ClipWith(window->ClipRect); + + // Pressing CTRL+C while holding on a window copy its content to the clipboard + // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope. + // Maybe we can support CTRL+C on every element? + /* + if (g.ActiveId == move_id) + if (g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_C)) + ImGui::LogToClipboard(); + */ + + // Inner rectangle + // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame + // Note that if our window is collapsed we will end up with an inverted (~null) clipping rectangle which is the correct behavior. + window->InnerMainRect.Min.x = title_bar_rect.Min.x + window->WindowBorderSize; + window->InnerMainRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize); + window->InnerMainRect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x - window->WindowBorderSize; + window->InnerMainRect.Max.y = window->Pos.y + window->Size.y - window->ScrollbarSizes.y - window->WindowBorderSize; + //window->DrawList->AddRect(window->InnerRect.Min, window->InnerRect.Max, IM_COL32_WHITE); + + // Inner clipping rectangle + // Force round operator last to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. + window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerMainRect.Min.x + ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - window->WindowBorderSize))); + window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerMainRect.Min.y); + window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerMainRect.Max.x - ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - window->WindowBorderSize))); + window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerMainRect.Max.y); + + // After Begin() we fill the last item / hovered data based on title bar data. It is a standard behavior (to allow creation of context menus on title bar only, etc.). + window->DC.LastItemId = window->MoveId; + window->DC.LastItemStatusFlags = IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0; + window->DC.LastItemRect = title_bar_rect; + } + + PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true); + + // Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused) + if (first_begin_of_the_frame) + window->WriteAccessed = false; + + window->BeginCount++; + g.NextWindowData.Clear(); + + if (flags & ImGuiWindowFlags_ChildWindow) + { + // Child window can be out of sight and have "negative" clip windows. + // Mark them as collapsed so commands are skipped earlier (we can't manually collapse them because they have no title bar). + IM_ASSERT((flags & ImGuiWindowFlags_NoTitleBar) != 0); + + if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) + if (window->OuterRectClipped.Min.x >= window->OuterRectClipped.Max.x || window->OuterRectClipped.Min.y >= window->OuterRectClipped.Max.y) + window->HiddenFramesRegular = 1; + + // Completely hide along with parent or if parent is collapsed + if (parent_window && (parent_window->Collapsed || parent_window->Hidden)) + window->HiddenFramesRegular = 1; + } + + // Don't render if style alpha is 0.0 at the time of Begin(). This is arbitrary and inconsistent but has been there for a long while (may remove at some point) + if (style.Alpha <= 0.0f) + window->HiddenFramesRegular = 1; + + // Update the Hidden flag + window->Hidden = (window->HiddenFramesRegular > 0) || (window->HiddenFramesForResize); + + // Return false if we don't intend to display anything to allow user to perform an early out optimization + window->SkipItems = (window->Collapsed || !window->Active || window->Hidden) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && window->HiddenFramesForResize <= 0; + + return !window->SkipItems; +} + +// Old Begin() API with 5 parameters, avoid calling this version directly! Use SetNextWindowSize()/SetNextWindowBgAlpha() + Begin() instead. +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS +bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_first_use, float bg_alpha_override, ImGuiWindowFlags flags) +{ + // Old API feature: we could pass the initial window size as a parameter. This was misleading because it only had an effect if the window didn't have data in the .ini file. + if (size_first_use.x != 0.0f || size_first_use.y != 0.0f) + ImGui::SetNextWindowSize(size_first_use, ImGuiCond_FirstUseEver); + + // Old API feature: override the window background alpha with a parameter. + if (bg_alpha_override >= 0.0f) + ImGui::SetNextWindowBgAlpha(bg_alpha_override); + + return ImGui::Begin(name, p_open, flags); +} +#endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS + +void ImGui::End() +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + if (window->DC.ColumnsSet != NULL) + EndColumns(); + PopClipRect(); // Inner window clip rectangle + + // Stop logging + if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging + LogFinish(); + + // Pop from window stack + g.CurrentWindowStack.pop_back(); + if (window->Flags & ImGuiWindowFlags_Popup) + g.CurrentPopupStack.pop_back(); + CheckStacksSize(window, false); + SetCurrentWindow(g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back()); +} + +// Vertical scrollbar +// The entire piece of code below is rather confusing because: +// - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab) +// - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar +// - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal. +void ImGui::Scrollbar(ImGuiLayoutType direction) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + const bool horizontal = (direction == ImGuiLayoutType_Horizontal); + const ImGuiStyle& style = g.Style; + const ImGuiID id = window->GetID(horizontal ? "#SCROLLX" : "#SCROLLY"); + + // Render background + bool other_scrollbar = (horizontal ? window->ScrollbarY : window->ScrollbarX); + float other_scrollbar_size_w = other_scrollbar ? style.ScrollbarSize : 0.0f; + const ImRect window_rect = window->Rect(); + const float border_size = window->WindowBorderSize; + ImRect bb = horizontal + ? ImRect(window->Pos.x + border_size, window_rect.Max.y - style.ScrollbarSize, window_rect.Max.x - other_scrollbar_size_w - border_size, window_rect.Max.y - border_size) + : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + border_size, window_rect.Max.x - border_size, window_rect.Max.y - other_scrollbar_size_w - border_size); + if (!horizontal) + bb.Min.y += window->TitleBarHeight() + ((window->Flags & ImGuiWindowFlags_MenuBar) ? window->MenuBarHeight() : 0.0f); + if (bb.GetWidth() <= 0.0f || bb.GetHeight() <= 0.0f) + return; + + int window_rounding_corners; + if (horizontal) + window_rounding_corners = ImDrawCornerFlags_BotLeft | (other_scrollbar ? 0 : ImDrawCornerFlags_BotRight); + else + window_rounding_corners = (((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImDrawCornerFlags_TopRight : 0) | (other_scrollbar ? 0 : ImDrawCornerFlags_BotRight); + window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_ScrollbarBg), window->WindowRounding, window_rounding_corners); + bb.Expand(ImVec2(-ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f))); + + // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar) + float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight(); + float scroll_v = horizontal ? window->Scroll.x : window->Scroll.y; + float win_size_avail_v = (horizontal ? window->SizeFull.x : window->SizeFull.y) - other_scrollbar_size_w; + float win_size_contents_v = horizontal ? window->SizeContents.x : window->SizeContents.y; + + // Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount) + // But we maintain a minimum size in pixel to allow for the user to still aim inside. + IM_ASSERT(ImMax(win_size_contents_v, win_size_avail_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers. + const float win_size_v = ImMax(ImMax(win_size_contents_v, win_size_avail_v), 1.0f); + const float grab_h_pixels = ImClamp(scrollbar_size_v * (win_size_avail_v / win_size_v), style.GrabMinSize, scrollbar_size_v); + const float grab_h_norm = grab_h_pixels / scrollbar_size_v; + + // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar(). + bool held = false; + bool hovered = false; + const bool previously_held = (g.ActiveId == id); + ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus); + + float scroll_max = ImMax(1.0f, win_size_contents_v - win_size_avail_v); + float scroll_ratio = ImSaturate(scroll_v / scroll_max); + float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; + if (held && grab_h_norm < 1.0f) + { + float scrollbar_pos_v = horizontal ? bb.Min.x : bb.Min.y; + float mouse_pos_v = horizontal ? g.IO.MousePos.x : g.IO.MousePos.y; + float* click_delta_to_grab_center_v = horizontal ? &g.ScrollbarClickDeltaToGrabCenter.x : &g.ScrollbarClickDeltaToGrabCenter.y; + + // Click position in scrollbar normalized space (0.0f->1.0f) + const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v); + SetHoveredID(id); + + bool seek_absolute = false; + if (!previously_held) + { + // On initial click calculate the distance between mouse and the center of the grab + if (clicked_v_norm >= grab_v_norm && clicked_v_norm <= grab_v_norm + grab_h_norm) + { + *click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm*0.5f; + } + else + { + seek_absolute = true; + *click_delta_to_grab_center_v = 0.0f; + } + } + + // Apply scroll + // It is ok to modify Scroll here because we are being called in Begin() after the calculation of SizeContents and before setting up our starting position + const float scroll_v_norm = ImSaturate((clicked_v_norm - *click_delta_to_grab_center_v - grab_h_norm*0.5f) / (1.0f - grab_h_norm)); + scroll_v = (float)(int)(0.5f + scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v)); + if (horizontal) + window->Scroll.x = scroll_v; + else + window->Scroll.y = scroll_v; + + // Update values for rendering + scroll_ratio = ImSaturate(scroll_v / scroll_max); + grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; + + // Update distance to grab now that we have seeked and saturated + if (seek_absolute) + *click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm*0.5f; + } + + // Render + const ImU32 grab_col = GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab); + ImRect grab_rect; + if (horizontal) + grab_rect = ImRect(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y, ImMin(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, window_rect.Max.x), bb.Max.y); + else + grab_rect = ImRect(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm), bb.Max.x, ImMin(ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels, window_rect.Max.y)); + window->DrawList->AddRectFilled(grab_rect.Min, grab_rect.Max, grab_col, style.ScrollbarRounding); +} + +void ImGui::BringWindowToFront(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* current_front_window = g.Windows.back(); + if (current_front_window == window || current_front_window->RootWindow == window) + return; + for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the front most window + if (g.Windows[i] == window) + { + g.Windows.erase(g.Windows.Data + i); + g.Windows.push_back(window); + break; + } +} + +void ImGui::BringWindowToBack(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + if (g.Windows[0] == window) + return; + for (int i = 0; i < g.Windows.Size; i++) + if (g.Windows[i] == window) + { + memmove(&g.Windows[1], &g.Windows[0], (size_t)i * sizeof(ImGuiWindow*)); + g.Windows[0] = window; + break; + } +} + +// Moving window to front of display and set focus (which happens to be back of our sorted list) +void ImGui::FocusWindow(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + + if (g.NavWindow != window) + { + g.NavWindow = window; + if (window && g.NavDisableMouseHover) + g.NavMousePosDirty = true; + g.NavInitRequest = false; + g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId + g.NavIdIsAlive = false; + g.NavLayer = 0; + //printf("[%05d] FocusWindow(\"%s\")\n", g.FrameCount, window ? window->Name : NULL); + } + + // Passing NULL allow to disable keyboard focus + if (!window) + return; + + // Move the root window to the top of the pile + if (window->RootWindow) + window = window->RootWindow; + + // Steal focus on active widgets + if (window->Flags & ImGuiWindowFlags_Popup) // FIXME: This statement should be unnecessary. Need further testing before removing it.. + if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != window) + ClearActiveID(); + + // Bring to front + if (!(window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) + BringWindowToFront(window); +} + +void ImGui::FocusFrontMostActiveWindow(ImGuiWindow* ignore_window) +{ + ImGuiContext& g = *GImGui; + for (int i = g.Windows.Size - 1; i >= 0; i--) + if (g.Windows[i] != ignore_window && g.Windows[i]->WasActive && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow)) + { + ImGuiWindow* focus_window = NavRestoreLastChildNavWindow(g.Windows[i]); + FocusWindow(focus_window); + return; + } +} + +void ImGui::PushItemWidth(float item_width) +{ + ImGuiWindow* window = GetCurrentWindow(); + window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width); + window->DC.ItemWidthStack.push_back(window->DC.ItemWidth); +} + +void ImGui::PushMultiItemsWidths(int components, float w_full) +{ + ImGuiWindow* window = GetCurrentWindow(); + const ImGuiStyle& style = GImGui->Style; + if (w_full <= 0.0f) + w_full = CalcItemWidth(); + const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); + const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); + window->DC.ItemWidthStack.push_back(w_item_last); + for (int i = 0; i < components-1; i++) + window->DC.ItemWidthStack.push_back(w_item_one); + window->DC.ItemWidth = window->DC.ItemWidthStack.back(); +} + +void ImGui::PopItemWidth() +{ + ImGuiWindow* window = GetCurrentWindow(); + window->DC.ItemWidthStack.pop_back(); + window->DC.ItemWidth = window->DC.ItemWidthStack.empty() ? window->ItemWidthDefault : window->DC.ItemWidthStack.back(); +} + +float ImGui::CalcItemWidth() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + float w = window->DC.ItemWidth; + if (w < 0.0f) + { + // Align to a right-side limit. We include 1 frame padding in the calculation because this is how the width is always used (we add 2 frame padding to it), but we could move that responsibility to the widget as well. + float width_to_right_edge = GetContentRegionAvail().x; + w = ImMax(1.0f, width_to_right_edge + w); + } + w = (float)(int)w; + return w; +} + +void ImGui::SetCurrentFont(ImFont* font) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(font && font->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? + IM_ASSERT(font->Scale > 0.0f); + g.Font = font; + g.FontBaseSize = g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale; + g.FontSize = g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f; + + ImFontAtlas* atlas = g.Font->ContainerAtlas; + g.DrawListSharedData.TexUvWhitePixel = atlas->TexUvWhitePixel; + g.DrawListSharedData.Font = g.Font; + g.DrawListSharedData.FontSize = g.FontSize; +} + +void ImGui::PushFont(ImFont* font) +{ + ImGuiContext& g = *GImGui; + if (!font) + font = GetDefaultFont(); + SetCurrentFont(font); + g.FontStack.push_back(font); + g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID); +} + +void ImGui::PopFont() +{ + ImGuiContext& g = *GImGui; + g.CurrentWindow->DrawList->PopTextureID(); + g.FontStack.pop_back(); + SetCurrentFont(g.FontStack.empty() ? GetDefaultFont() : g.FontStack.back()); +} + +void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (enabled) + window->DC.ItemFlags |= option; + else + window->DC.ItemFlags &= ~option; + window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags); +} + +void ImGui::PopItemFlag() +{ + ImGuiWindow* window = GetCurrentWindow(); + window->DC.ItemFlagsStack.pop_back(); + window->DC.ItemFlags = window->DC.ItemFlagsStack.empty() ? ImGuiItemFlags_Default_ : window->DC.ItemFlagsStack.back(); +} + +void ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus) +{ + PushItemFlag(ImGuiItemFlags_AllowKeyboardFocus, allow_keyboard_focus); +} + +void ImGui::PopAllowKeyboardFocus() +{ + PopItemFlag(); +} + +void ImGui::PushButtonRepeat(bool repeat) +{ + PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat); +} + +void ImGui::PopButtonRepeat() +{ + PopItemFlag(); +} + +void ImGui::PushTextWrapPos(float wrap_pos_x) +{ + ImGuiWindow* window = GetCurrentWindow(); + window->DC.TextWrapPos = wrap_pos_x; + window->DC.TextWrapPosStack.push_back(wrap_pos_x); +} + +void ImGui::PopTextWrapPos() +{ + ImGuiWindow* window = GetCurrentWindow(); + window->DC.TextWrapPosStack.pop_back(); + window->DC.TextWrapPos = window->DC.TextWrapPosStack.empty() ? -1.0f : window->DC.TextWrapPosStack.back(); +} + +// FIXME: This may incur a round-trip (if the end user got their data from a float4) but eventually we aim to store the in-flight colors as ImU32 +void ImGui::PushStyleColor(ImGuiCol idx, ImU32 col) +{ + ImGuiContext& g = *GImGui; + ImGuiColMod backup; + backup.Col = idx; + backup.BackupValue = g.Style.Colors[idx]; + g.ColorModifiers.push_back(backup); + g.Style.Colors[idx] = ColorConvertU32ToFloat4(col); +} + +void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col) +{ + ImGuiContext& g = *GImGui; + ImGuiColMod backup; + backup.Col = idx; + backup.BackupValue = g.Style.Colors[idx]; + g.ColorModifiers.push_back(backup); + g.Style.Colors[idx] = col; +} + +void ImGui::PopStyleColor(int count) +{ + ImGuiContext& g = *GImGui; + while (count > 0) + { + ImGuiColMod& backup = g.ColorModifiers.back(); + g.Style.Colors[backup.Col] = backup.BackupValue; + g.ColorModifiers.pop_back(); + count--; + } +} + +struct ImGuiStyleVarInfo +{ + ImGuiDataType Type; + ImU32 Count; + ImU32 Offset; + void* GetVarPtr(ImGuiStyle* style) const { return (void*)((unsigned char*)style + Offset); } +}; + +static const ImGuiStyleVarInfo GStyleVarInfo[] = +{ + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) }, // ImGuiStyleVar_WindowPadding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) }, // ImGuiStyleVar_WindowRounding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowBorderSize) }, // ImGuiStyleVar_WindowBorderSize + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) }, // ImGuiStyleVar_WindowMinSize + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowTitleAlign) }, // ImGuiStyleVar_WindowTitleAlign + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildRounding) }, // ImGuiStyleVar_ChildRounding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildBorderSize) }, // ImGuiStyleVar_ChildBorderSize + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupRounding) }, // ImGuiStyleVar_PopupRounding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupBorderSize) }, // ImGuiStyleVar_PopupBorderSize + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding) }, // ImGuiStyleVar_FramePadding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding) }, // ImGuiStyleVar_FrameRounding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameBorderSize) }, // ImGuiStyleVar_FrameBorderSize + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) }, // ImGuiStyleVar_ItemSpacing + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) }, // ImGuiStyleVar_ItemInnerSpacing + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) }, // ImGuiStyleVar_IndentSpacing + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarSize) }, // ImGuiStyleVar_ScrollbarSize + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign +}; + +static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx) +{ + IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT); + IM_ASSERT(IM_ARRAYSIZE(GStyleVarInfo) == ImGuiStyleVar_COUNT); + return &GStyleVarInfo[idx]; +} + +void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) +{ + const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); + if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1) + { + ImGuiContext& g = *GImGui; + float* pvar = (float*)var_info->GetVarPtr(&g.Style); + g.StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar)); + *pvar = val; + return; + } + IM_ASSERT(0); // Called function with wrong-type? Variable is not a float. +} + +void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) +{ + const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); + if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2) + { + ImGuiContext& g = *GImGui; + ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style); + g.StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar)); + *pvar = val; + return; + } + IM_ASSERT(0); // Called function with wrong-type? Variable is not a ImVec2. +} + +void ImGui::PopStyleVar(int count) +{ + ImGuiContext& g = *GImGui; + while (count > 0) + { + // We avoid a generic memcpy(data, &backup.Backup.., GDataTypeSize[info->Type] * info->Count), the overhead in Debug is not worth it. + ImGuiStyleMod& backup = g.StyleModifiers.back(); + const ImGuiStyleVarInfo* info = GetStyleVarInfo(backup.VarIdx); + void* data = info->GetVarPtr(&g.Style); + if (info->Type == ImGuiDataType_Float && info->Count == 1) { ((float*)data)[0] = backup.BackupFloat[0]; } + else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; } + g.StyleModifiers.pop_back(); + count--; + } +} + +const char* ImGui::GetStyleColorName(ImGuiCol idx) +{ + // Create switch-case from enum with regexp: ImGuiCol_{.*}, --> case ImGuiCol_\1: return "\1"; + switch (idx) + { + case ImGuiCol_Text: return "Text"; + case ImGuiCol_TextDisabled: return "TextDisabled"; + case ImGuiCol_WindowBg: return "WindowBg"; + case ImGuiCol_ChildBg: return "ChildBg"; + case ImGuiCol_PopupBg: return "PopupBg"; + case ImGuiCol_Border: return "Border"; + case ImGuiCol_BorderShadow: return "BorderShadow"; + case ImGuiCol_FrameBg: return "FrameBg"; + case ImGuiCol_FrameBgHovered: return "FrameBgHovered"; + case ImGuiCol_FrameBgActive: return "FrameBgActive"; + case ImGuiCol_TitleBg: return "TitleBg"; + case ImGuiCol_TitleBgActive: return "TitleBgActive"; + case ImGuiCol_TitleBgCollapsed: return "TitleBgCollapsed"; + case ImGuiCol_MenuBarBg: return "MenuBarBg"; + case ImGuiCol_ScrollbarBg: return "ScrollbarBg"; + case ImGuiCol_ScrollbarGrab: return "ScrollbarGrab"; + case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered"; + case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive"; + case ImGuiCol_CheckMark: return "CheckMark"; + case ImGuiCol_SliderGrab: return "SliderGrab"; + case ImGuiCol_SliderGrabActive: return "SliderGrabActive"; + case ImGuiCol_Button: return "Button"; + case ImGuiCol_ButtonHovered: return "ButtonHovered"; + case ImGuiCol_ButtonActive: return "ButtonActive"; + case ImGuiCol_Header: return "Header"; + case ImGuiCol_HeaderHovered: return "HeaderHovered"; + case ImGuiCol_HeaderActive: return "HeaderActive"; + case ImGuiCol_Separator: return "Separator"; + case ImGuiCol_SeparatorHovered: return "SeparatorHovered"; + case ImGuiCol_SeparatorActive: return "SeparatorActive"; + case ImGuiCol_ResizeGrip: return "ResizeGrip"; + case ImGuiCol_ResizeGripHovered: return "ResizeGripHovered"; + case ImGuiCol_ResizeGripActive: return "ResizeGripActive"; + case ImGuiCol_PlotLines: return "PlotLines"; + case ImGuiCol_PlotLinesHovered: return "PlotLinesHovered"; + case ImGuiCol_PlotHistogram: return "PlotHistogram"; + case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered"; + case ImGuiCol_TextSelectedBg: return "TextSelectedBg"; + case ImGuiCol_DragDropTarget: return "DragDropTarget"; + case ImGuiCol_NavHighlight: return "NavHighlight"; + case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight"; + case ImGuiCol_NavWindowingDimBg: return "NavWindowingDimBg"; + case ImGuiCol_ModalWindowDimBg: return "ModalWindowDimBg"; + } + IM_ASSERT(0); + return "Unknown"; +} + +bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent) +{ + if (window->RootWindow == potential_parent) + return true; + while (window != NULL) + { + if (window == potential_parent) + return true; + window = window->ParentWindow; + } + return false; +} + +bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) +{ + IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function + ImGuiContext& g = *GImGui; + + if (flags & ImGuiHoveredFlags_AnyWindow) + { + if (g.HoveredWindow == NULL) + return false; + } + else + { + switch (flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) + { + case ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows: + if (g.HoveredRootWindow != g.CurrentWindow->RootWindow) + return false; + break; + case ImGuiHoveredFlags_RootWindow: + if (g.HoveredWindow != g.CurrentWindow->RootWindow) + return false; + break; + case ImGuiHoveredFlags_ChildWindows: + if (g.HoveredWindow == NULL || !IsWindowChildOf(g.HoveredWindow, g.CurrentWindow)) + return false; + break; + default: + if (g.HoveredWindow != g.CurrentWindow) + return false; + break; + } + } + + if (!IsWindowContentHoverable(g.HoveredRootWindow, flags)) + return false; + if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) + if (g.ActiveId != 0 && !g.ActiveIdAllowOverlap && g.ActiveId != g.HoveredWindow->MoveId) + return false; + return true; +} + +bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() + + if (flags & ImGuiFocusedFlags_AnyWindow) + return g.NavWindow != NULL; + + switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows)) + { + case ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows: + return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow; + case ImGuiFocusedFlags_RootWindow: + return g.NavWindow == g.CurrentWindow->RootWindow; + case ImGuiFocusedFlags_ChildWindows: + return g.NavWindow && IsWindowChildOf(g.NavWindow, g.CurrentWindow); + default: + return g.NavWindow == g.CurrentWindow; + } +} + +// Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext) +bool ImGui::IsWindowNavFocusable(ImGuiWindow* window) +{ + return window->Active && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus); +} + +float ImGui::GetWindowWidth() +{ + ImGuiWindow* window = GImGui->CurrentWindow; + return window->Size.x; +} + +float ImGui::GetWindowHeight() +{ + ImGuiWindow* window = GImGui->CurrentWindow; + return window->Size.y; +} + +ImVec2 ImGui::GetWindowPos() +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + return window->Pos; +} + +static void SetWindowScrollX(ImGuiWindow* window, float new_scroll_x) +{ + window->DC.CursorMaxPos.x += window->Scroll.x; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it. + window->Scroll.x = new_scroll_x; + window->DC.CursorMaxPos.x -= window->Scroll.x; +} + +static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y) +{ + window->DC.CursorMaxPos.y += window->Scroll.y; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it. + window->Scroll.y = new_scroll_y; + window->DC.CursorMaxPos.y -= window->Scroll.y; +} + +static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond) +{ + // Test condition (NB: bit 0 is always true) and clear flags for next time + if (cond && (window->SetWindowPosAllowFlags & cond) == 0) + return; + + IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. + window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); + window->SetWindowPosVal = ImVec2(FLT_MAX, FLT_MAX); + + // Set + const ImVec2 old_pos = window->Pos; + window->Pos = ImFloor(pos); + window->DC.CursorPos += (window->Pos - old_pos); // As we happen to move the window while it is being appended to (which is a bad idea - will smear) let's at least offset the cursor + window->DC.CursorMaxPos += (window->Pos - old_pos); // And more importantly we need to adjust this so size calculation doesn't get affected. +} + +void ImGui::SetWindowPos(const ImVec2& pos, ImGuiCond cond) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + SetWindowPos(window, pos, cond); +} + +void ImGui::SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond) +{ + if (ImGuiWindow* window = FindWindowByName(name)) + SetWindowPos(window, pos, cond); +} + +ImVec2 ImGui::GetWindowSize() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->Size; +} + +static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond) +{ + // Test condition (NB: bit 0 is always true) and clear flags for next time + if (cond && (window->SetWindowSizeAllowFlags & cond) == 0) + return; + + IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. + window->SetWindowSizeAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); + + // Set + if (size.x > 0.0f) + { + window->AutoFitFramesX = 0; + window->SizeFull.x = size.x; + } + else + { + window->AutoFitFramesX = 2; + window->AutoFitOnlyGrows = false; + } + if (size.y > 0.0f) + { + window->AutoFitFramesY = 0; + window->SizeFull.y = size.y; + } + else + { + window->AutoFitFramesY = 2; + window->AutoFitOnlyGrows = false; + } +} + +void ImGui::SetWindowSize(const ImVec2& size, ImGuiCond cond) +{ + SetWindowSize(GImGui->CurrentWindow, size, cond); +} + +void ImGui::SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond) +{ + if (ImGuiWindow* window = FindWindowByName(name)) + SetWindowSize(window, size, cond); +} + +static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond) +{ + // Test condition (NB: bit 0 is always true) and clear flags for next time + if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0) + return; + window->SetWindowCollapsedAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); + + // Set + window->Collapsed = collapsed; +} + +void ImGui::SetWindowCollapsed(bool collapsed, ImGuiCond cond) +{ + SetWindowCollapsed(GImGui->CurrentWindow, collapsed, cond); +} + +bool ImGui::IsWindowCollapsed() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->Collapsed; +} + +bool ImGui::IsWindowAppearing() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->Appearing; +} + +void ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond) +{ + if (ImGuiWindow* window = FindWindowByName(name)) + SetWindowCollapsed(window, collapsed, cond); +} + +void ImGui::SetWindowFocus() +{ + FocusWindow(GImGui->CurrentWindow); +} + +void ImGui::SetWindowFocus(const char* name) +{ + if (name) + { + if (ImGuiWindow* window = FindWindowByName(name)) + FocusWindow(window); + } + else + { + FocusWindow(NULL); + } +} + +void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pivot) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. + g.NextWindowData.PosVal = pos; + g.NextWindowData.PosPivotVal = pivot; + g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always; +} + +void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. + g.NextWindowData.SizeVal = size; + g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always; +} + +void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback, void* custom_callback_user_data) +{ + ImGuiContext& g = *GImGui; + g.NextWindowData.SizeConstraintCond = ImGuiCond_Always; + g.NextWindowData.SizeConstraintRect = ImRect(size_min, size_max); + g.NextWindowData.SizeCallback = custom_callback; + g.NextWindowData.SizeCallbackUserData = custom_callback_user_data; +} + +void ImGui::SetNextWindowContentSize(const ImVec2& size) +{ + ImGuiContext& g = *GImGui; + g.NextWindowData.ContentSizeVal = size; // In Begin() we will add the size of window decorations (title bar, menu etc.) to that to form a SizeContents value. + g.NextWindowData.ContentSizeCond = ImGuiCond_Always; +} + +void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. + g.NextWindowData.CollapsedVal = collapsed; + g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always; +} + +void ImGui::SetNextWindowFocus() +{ + ImGuiContext& g = *GImGui; + g.NextWindowData.FocusCond = ImGuiCond_Always; // Using a Cond member for consistency (may transition all of them to single flag set for fast Clear() op) +} + +void ImGui::SetNextWindowBgAlpha(float alpha) +{ + ImGuiContext& g = *GImGui; + g.NextWindowData.BgAlphaVal = alpha; + g.NextWindowData.BgAlphaCond = ImGuiCond_Always; // Using a Cond member for consistency (may transition all of them to single flag set for fast Clear() op) +} + +// In window space (not screen space!) +ImVec2 ImGui::GetContentRegionMax() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + ImVec2 mx = window->ContentsRegionRect.Max - window->Pos; + if (window->DC.ColumnsSet) + mx.x = GetColumnOffset(window->DC.ColumnsSet->Current + 1) - window->WindowPadding.x; + return mx; +} + +ImVec2 ImGui::GetContentRegionAvail() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return GetContentRegionMax() - (window->DC.CursorPos - window->Pos); +} + +float ImGui::GetContentRegionAvailWidth() +{ + return GetContentRegionAvail().x; +} + +// In window space (not screen space!) +ImVec2 ImGui::GetWindowContentRegionMin() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->ContentsRegionRect.Min - window->Pos; +} + +ImVec2 ImGui::GetWindowContentRegionMax() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->ContentsRegionRect.Max - window->Pos; +} + +float ImGui::GetWindowContentRegionWidth() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->ContentsRegionRect.GetWidth(); +} + +float ImGui::GetTextLineHeight() +{ + ImGuiContext& g = *GImGui; + return g.FontSize; +} + +float ImGui::GetTextLineHeightWithSpacing() +{ + ImGuiContext& g = *GImGui; + return g.FontSize + g.Style.ItemSpacing.y; +} + +float ImGui::GetFrameHeight() +{ + ImGuiContext& g = *GImGui; + return g.FontSize + g.Style.FramePadding.y * 2.0f; +} + +float ImGui::GetFrameHeightWithSpacing() +{ + ImGuiContext& g = *GImGui; + return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y; +} + +ImDrawList* ImGui::GetWindowDrawList() +{ + ImGuiWindow* window = GetCurrentWindow(); + return window->DrawList; +} + +ImFont* ImGui::GetFont() +{ + return GImGui->Font; +} + +float ImGui::GetFontSize() +{ + return GImGui->FontSize; +} + +ImVec2 ImGui::GetFontTexUvWhitePixel() +{ + return GImGui->DrawListSharedData.TexUvWhitePixel; +} + +void ImGui::SetWindowFontScale(float scale) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + window->FontWindowScale = scale; + g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize(); +} + +// User generally sees positions in window coordinates. Internally we store CursorPos in absolute screen coordinates because it is more convenient. +// Conversion happens as we pass the value to user, but it makes our naming convention confusing because GetCursorPos() == (DC.CursorPos - window.Pos). May want to rename 'DC.CursorPos'. +ImVec2 ImGui::GetCursorPos() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->DC.CursorPos - window->Pos + window->Scroll; +} + +float ImGui::GetCursorPosX() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->DC.CursorPos.x - window->Pos.x + window->Scroll.x; +} + +float ImGui::GetCursorPosY() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->DC.CursorPos.y - window->Pos.y + window->Scroll.y; +} + +void ImGui::SetCursorPos(const ImVec2& local_pos) +{ + ImGuiWindow* window = GetCurrentWindow(); + window->DC.CursorPos = window->Pos - window->Scroll + local_pos; + window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos); +} + +void ImGui::SetCursorPosX(float x) +{ + ImGuiWindow* window = GetCurrentWindow(); + window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x; + window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPos.x); +} + +void ImGui::SetCursorPosY(float y) +{ + ImGuiWindow* window = GetCurrentWindow(); + window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y; + window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y); +} + +ImVec2 ImGui::GetCursorStartPos() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->DC.CursorStartPos - window->Pos; +} + +ImVec2 ImGui::GetCursorScreenPos() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->DC.CursorPos; +} + +void ImGui::SetCursorScreenPos(const ImVec2& screen_pos) +{ + ImGuiWindow* window = GetCurrentWindow(); + window->DC.CursorPos = screen_pos; + window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos); +} + +float ImGui::GetScrollX() +{ + return GImGui->CurrentWindow->Scroll.x; +} + +float ImGui::GetScrollY() +{ + return GImGui->CurrentWindow->Scroll.y; +} + +float ImGui::GetScrollMaxX() +{ + return GetScrollMaxX(GImGui->CurrentWindow); +} + +float ImGui::GetScrollMaxY() +{ + return GetScrollMaxY(GImGui->CurrentWindow); +} + +void ImGui::SetScrollX(float scroll_x) +{ + ImGuiWindow* window = GetCurrentWindow(); + window->ScrollTarget.x = scroll_x; + window->ScrollTargetCenterRatio.x = 0.0f; +} + +void ImGui::SetScrollY(float scroll_y) +{ + ImGuiWindow* window = GetCurrentWindow(); + window->ScrollTarget.y = scroll_y + window->TitleBarHeight() + window->MenuBarHeight(); // title bar height canceled out when using ScrollTargetRelY + window->ScrollTargetCenterRatio.y = 0.0f; +} + +void ImGui::SetScrollFromPosY(float pos_y, float center_y_ratio) +{ + // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size + ImGuiWindow* window = GetCurrentWindow(); + IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); + window->ScrollTarget.y = (float)(int)(pos_y + window->Scroll.y); + window->ScrollTargetCenterRatio.y = center_y_ratio; +} + +// center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item. +void ImGui::SetScrollHere(float center_y_ratio) +{ + ImGuiWindow* window = GetCurrentWindow(); + float target_y = window->DC.CursorPosPrevLine.y - window->Pos.y; // Top of last item, in window space + target_y += (window->DC.PrevLineHeight * center_y_ratio) + (GImGui->Style.ItemSpacing.y * (center_y_ratio - 0.5f) * 2.0f); // Precisely aim above, in the middle or below the last line. + SetScrollFromPosY(target_y, center_y_ratio); +} + +void ImGui::ActivateItem(ImGuiID id) +{ + ImGuiContext& g = *GImGui; + g.NavNextActivateId = id; +} + +void ImGui::SetKeyboardFocusHere(int offset) +{ + IM_ASSERT(offset >= -1); // -1 is allowed but not below + ImGuiWindow* window = GetCurrentWindow(); + window->FocusIdxAllRequestNext = window->FocusIdxAllCounter + 1 + offset; + window->FocusIdxTabRequestNext = INT_MAX; +} + +void ImGui::SetItemDefaultFocus() +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if (!window->Appearing) + return; + if (g.NavWindow == window->RootWindowForNav && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent) + { + g.NavInitRequest = false; + g.NavInitResultId = g.NavWindow->DC.LastItemId; + g.NavInitResultRectRel = ImRect(g.NavWindow->DC.LastItemRect.Min - g.NavWindow->Pos, g.NavWindow->DC.LastItemRect.Max - g.NavWindow->Pos); + NavUpdateAnyRequestFlag(); + if (!IsItemVisible()) + SetScrollHere(); + } +} + +void ImGui::SetStateStorage(ImGuiStorage* tree) +{ + ImGuiWindow* window = GetCurrentWindow(); + window->DC.StateStorage = tree ? tree : &window->StateStorage; +} + +ImGuiStorage* ImGui::GetStateStorage() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->DC.StateStorage; +} + +void ImGui::TextV(const char* fmt, va_list args) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + + ImGuiContext& g = *GImGui; + const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); + TextUnformatted(g.TempBuffer, text_end); +} + +void ImGui::Text(const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + TextV(fmt, args); + va_end(args); +} + +void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args) +{ + PushStyleColor(ImGuiCol_Text, col); + TextV(fmt, args); + PopStyleColor(); +} + +void ImGui::TextColored(const ImVec4& col, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + TextColoredV(col, fmt, args); + va_end(args); +} + +void ImGui::TextDisabledV(const char* fmt, va_list args) +{ + PushStyleColor(ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled]); + TextV(fmt, args); + PopStyleColor(); +} + +void ImGui::TextDisabled(const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + TextDisabledV(fmt, args); + va_end(args); +} + +void ImGui::TextWrappedV(const char* fmt, va_list args) +{ + bool need_wrap = (GImGui->CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position is one ia already set + if (need_wrap) PushTextWrapPos(0.0f); + TextV(fmt, args); + if (need_wrap) PopTextWrapPos(); +} + +void ImGui::TextWrapped(const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + TextWrappedV(fmt, args); + va_end(args); +} + +void ImGui::TextUnformatted(const char* text, const char* text_end) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + + ImGuiContext& g = *GImGui; + IM_ASSERT(text != NULL); + const char* text_begin = text; + if (text_end == NULL) + text_end = text + strlen(text); // FIXME-OPT + + const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrentLineTextBaseOffset); + const float wrap_pos_x = window->DC.TextWrapPos; + const bool wrap_enabled = wrap_pos_x >= 0.0f; + if (text_end - text > 2000 && !wrap_enabled) + { + // Long text! + // Perform manual coarse clipping to optimize for long multi-line text + // From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled. + // We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line. + const char* line = text; + const float line_height = GetTextLineHeight(); + const ImRect clip_rect = window->ClipRect; + ImVec2 text_size(0,0); + + if (text_pos.y <= clip_rect.Max.y) + { + ImVec2 pos = text_pos; + + // Lines to skip (can't skip when logging text) + if (!g.LogEnabled) + { + int lines_skippable = (int)((clip_rect.Min.y - text_pos.y) / line_height); + if (lines_skippable > 0) + { + int lines_skipped = 0; + while (line < text_end && lines_skipped < lines_skippable) + { + const char* line_end = strchr(line, '\n'); + if (!line_end) + line_end = text_end; + line = line_end + 1; + lines_skipped++; + } + pos.y += lines_skipped * line_height; + } + } + + // Lines to render + if (line < text_end) + { + ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height)); + while (line < text_end) + { + const char* line_end = strchr(line, '\n'); + if (IsClippedEx(line_rect, 0, false)) + break; + + const ImVec2 line_size = CalcTextSize(line, line_end, false); + text_size.x = ImMax(text_size.x, line_size.x); + RenderText(pos, line, line_end, false); + if (!line_end) + line_end = text_end; + line = line_end + 1; + line_rect.Min.y += line_height; + line_rect.Max.y += line_height; + pos.y += line_height; + } + + // Count remaining lines + int lines_skipped = 0; + while (line < text_end) + { + const char* line_end = strchr(line, '\n'); + if (!line_end) + line_end = text_end; + line = line_end + 1; + lines_skipped++; + } + pos.y += lines_skipped * line_height; + } + + text_size.y += (pos - text_pos).y; + } + + ImRect bb(text_pos, text_pos + text_size); + ItemSize(bb); + ItemAdd(bb, 0); + } + else + { + const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f; + const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width); + + // Account of baseline offset + ImRect bb(text_pos, text_pos + text_size); + ItemSize(text_size); + if (!ItemAdd(bb, 0)) + return; + + // Render (we don't hide text after ## in this end-user function) + RenderTextWrapped(bb.Min, text_begin, text_end, wrap_width); + } +} + +void ImGui::AlignTextToFramePadding() +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + + ImGuiContext& g = *GImGui; + window->DC.CurrentLineHeight = ImMax(window->DC.CurrentLineHeight, g.FontSize + g.Style.FramePadding.y * 2); + window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y); +} + +// Add a label+text combo aligned to other label+value widgets +void ImGui::LabelTextV(const char* label, const char* fmt, va_list args) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + const float w = CalcItemWidth(); + + const ImVec2 label_size = CalcTextSize(label, NULL, true); + const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2)); + const ImRect total_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y*2) + label_size); + ItemSize(total_bb, style.FramePadding.y); + if (!ItemAdd(total_bb, 0)) + return; + + // Render + const char* value_text_begin = &g.TempBuffer[0]; + const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); + RenderTextClipped(value_bb.Min, value_bb.Max, value_text_begin, value_text_end, NULL, ImVec2(0.0f,0.5f)); + if (label_size.x > 0.0f) + RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label); +} + +void ImGui::LabelText(const char* label, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + LabelTextV(label, fmt, args); + va_end(args); +} + +bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + + if (flags & ImGuiButtonFlags_Disabled) + { + if (out_hovered) *out_hovered = false; + if (out_held) *out_held = false; + if (g.ActiveId == id) ClearActiveID(); + return false; + } + + // Default behavior requires click+release on same spot + if ((flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick)) == 0) + flags |= ImGuiButtonFlags_PressedOnClickRelease; + + ImGuiWindow* backup_hovered_window = g.HoveredWindow; + if ((flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredRootWindow == window) + g.HoveredWindow = window; + + bool pressed = false; + bool hovered = ItemHoverable(bb, id); + + // Drag source doesn't report as hovered + if (hovered && g.DragDropActive && g.DragDropPayload.SourceId == id && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoDisableHover)) + hovered = false; + + // Special mode for Drag and Drop where holding button pressed for a long time while dragging another item triggers the button + if (g.DragDropActive && (flags & ImGuiButtonFlags_PressedOnDragDropHold) && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoHoldToOpenOthers)) + if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) + { + hovered = true; + SetHoveredID(id); + if (CalcTypematicPressedRepeatAmount(g.HoveredIdTimer + 0.0001f, g.HoveredIdTimer + 0.0001f - g.IO.DeltaTime, 0.01f, 0.70f)) // FIXME: Our formula for CalcTypematicPressedRepeatAmount() is fishy + { + pressed = true; + FocusWindow(window); + } + } + + if ((flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredRootWindow == window) + g.HoveredWindow = backup_hovered_window; + + // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one. + if (hovered && (flags & ImGuiButtonFlags_AllowItemOverlap) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) + hovered = false; + + // Mouse + if (hovered) + { + if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt)) + { + // | CLICKING | HOLDING with ImGuiButtonFlags_Repeat + // PressedOnClickRelease | * | .. (NOT on release) <-- MOST COMMON! (*) only if both click/release were over bounds + // PressedOnClick | | .. + // PressedOnRelease | | .. (NOT on release) + // PressedOnDoubleClick | | .. + // FIXME-NAV: We don't honor those different behaviors. + if ((flags & ImGuiButtonFlags_PressedOnClickRelease) && g.IO.MouseClicked[0]) + { + SetActiveID(id, window); + if (!(flags & ImGuiButtonFlags_NoNavFocus)) + SetFocusID(id, window); + FocusWindow(window); + } + if (((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0])) + { + pressed = true; + if (flags & ImGuiButtonFlags_NoHoldingActiveID) + ClearActiveID(); + else + SetActiveID(id, window); // Hold on ID + FocusWindow(window); + } + if ((flags & ImGuiButtonFlags_PressedOnRelease) && g.IO.MouseReleased[0]) + { + if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps + pressed = true; + ClearActiveID(); + } + + // 'Repeat' mode acts when held regardless of _PressedOn flags (see table above). + // Relies on repeat logic of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings. + if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && g.IO.MouseDownDuration[0] > 0.0f && IsMouseClicked(0, true)) + pressed = true; + } + + if (pressed) + g.NavDisableHighlight = true; + } + + // Gamepad/Keyboard navigation + // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse. + if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover && (g.ActiveId == 0 || g.ActiveId == id || g.ActiveId == window->MoveId)) + hovered = true; + + if (g.NavActivateDownId == id) + { + bool nav_activated_by_code = (g.NavActivateId == id); + bool nav_activated_by_inputs = IsNavInputPressed(ImGuiNavInput_Activate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiInputReadMode_Repeat : ImGuiInputReadMode_Pressed); + if (nav_activated_by_code || nav_activated_by_inputs) + pressed = true; + if (nav_activated_by_code || nav_activated_by_inputs || g.ActiveId == id) + { + // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button. + g.NavActivateId = id; // This is so SetActiveId assign a Nav source + SetActiveID(id, window); + if (!(flags & ImGuiButtonFlags_NoNavFocus)) + SetFocusID(id, window); + g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right) | (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); + } + } + + bool held = false; + if (g.ActiveId == id) + { + if (g.ActiveIdSource == ImGuiInputSource_Mouse) + { + if (g.ActiveIdIsJustActivated) + g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; + if (g.IO.MouseDown[0]) + { + held = true; + } + else + { + if (hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease)) + if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps + if (!g.DragDropActive) + pressed = true; + ClearActiveID(); + } + if (!(flags & ImGuiButtonFlags_NoNavFocus)) + g.NavDisableHighlight = true; + } + else if (g.ActiveIdSource == ImGuiInputSource_Nav) + { + if (g.NavActivateDownId != id) + ClearActiveID(); + } + } + + if (out_hovered) *out_hovered = hovered; + if (out_held) *out_held = held; + + return pressed; +} + +bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + const ImGuiID id = window->GetID(label); + const ImVec2 label_size = CalcTextSize(label, NULL, true); + + ImVec2 pos = window->DC.CursorPos; + if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrentLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag) + pos.y += window->DC.CurrentLineTextBaseOffset - style.FramePadding.y; + ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f); + + const ImRect bb(pos, pos + size); + ItemSize(bb, style.FramePadding.y); + if (!ItemAdd(bb, id)) + return false; + + if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) + flags |= ImGuiButtonFlags_Repeat; + bool hovered, held; + bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); + if (pressed) + MarkItemValueChanged(id); + + // Render + const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); + RenderNavHighlight(bb, id); + RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); + RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb); + + // Automatically close popups + //if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup)) + // CloseCurrentPopup(); + + return pressed; +} + +bool ImGui::Button(const char* label, const ImVec2& size_arg) +{ + return ButtonEx(label, size_arg, 0); +} + +// Small buttons fits within text without additional vertical spacing. +bool ImGui::SmallButton(const char* label) +{ + ImGuiContext& g = *GImGui; + float backup_padding_y = g.Style.FramePadding.y; + g.Style.FramePadding.y = 0.0f; + bool pressed = ButtonEx(label, ImVec2(0,0), ImGuiButtonFlags_AlignTextBaseLine); + g.Style.FramePadding.y = backup_padding_y; + return pressed; +} + +bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiButtonFlags flags) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiID id = window->GetID(str_id); + const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); + const float default_size = GetFrameHeight(); + ItemSize(bb, (size.y >= default_size) ? g.Style.FramePadding.y : 0.0f); + if (!ItemAdd(bb, id)) + return false; + + if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) + flags |= ImGuiButtonFlags_Repeat; + + bool hovered, held; + bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); + + // Render + const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); + RenderNavHighlight(bb, id); + RenderFrame(bb.Min, bb.Max, col, true, g.Style.FrameRounding); + RenderArrow(bb.Min + ImVec2(ImMax(0.0f, size.x - g.FontSize - g.Style.FramePadding.x), ImMax(0.0f, size.y - g.FontSize - g.Style.FramePadding.y)), dir); + + return pressed; +} + +bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir) +{ + float sz = GetFrameHeight(); + return ArrowButtonEx(str_id, dir, ImVec2(sz, sz), 0); +} + +// Tip: use ImGui::PushID()/PopID() to push indices or pointers in the ID stack. +// Then you can keep 'str_id' empty or the same for all your buttons (instead of creating a string based on a non-string id) +bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + // Cannot use zero-size for InvisibleButton(). Unlike Button() there is not way to fallback using the label size. + IM_ASSERT(size_arg.x != 0.0f && size_arg.y != 0.0f); + + const ImGuiID id = window->GetID(str_id); + ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f); + const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); + ItemSize(bb); + if (!ItemAdd(bb, id)) + return false; + + bool hovered, held; + bool pressed = ButtonBehavior(bb, id, &hovered, &held); + + return pressed; +} + +// Button to close a window +bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + // We intentionally allow interaction when clipped so that a mechanical Alt,Right,Validate sequence close a window. + // (this isn't the regular behavior of buttons, but it doesn't affect the user much because navigation tends to keep items visible). + const ImRect bb(pos - ImVec2(radius,radius), pos + ImVec2(radius,radius)); + bool is_clipped = !ItemAdd(bb, id); + + bool hovered, held; + bool pressed = ButtonBehavior(bb, id, &hovered, &held); + if (is_clipped) + return pressed; + + // Render + ImVec2 center = bb.GetCenter(); + if (hovered) + window->DrawList->AddCircleFilled(center, ImMax(2.0f, radius), GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered), 9); + + float cross_extent = (radius * 0.7071f) - 1.0f; + ImU32 cross_col = GetColorU32(ImGuiCol_Text); + center -= ImVec2(0.5f, 0.5f); + window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), cross_col, 1.0f); + window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), cross_col, 1.0f); + + return pressed; +} + +bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f); + ItemAdd(bb, id); + bool hovered, held; + bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_None); + + ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); + if (hovered || held) + window->DrawList->AddCircleFilled(bb.GetCenter() + ImVec2(0.0f, -0.5f), g.FontSize * 0.5f + 1.0f, col, 9); + RenderArrow(bb.Min + g.Style.FramePadding, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f); + + // Switch to moving the window after mouse is moved beyond the initial drag threshold + if (IsItemActive() && IsMouseDragging()) + StartMouseMovingWindow(window); + + return pressed; +} + +void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + + ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); + if (border_col.w > 0.0f) + bb.Max += ImVec2(2,2); + ItemSize(bb); + if (!ItemAdd(bb, 0)) + return; + + if (border_col.w > 0.0f) + { + window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(border_col), 0.0f); + window->DrawList->AddImage(user_texture_id, bb.Min+ImVec2(1,1), bb.Max-ImVec2(1,1), uv0, uv1, GetColorU32(tint_col)); + } + else + { + window->DrawList->AddImage(user_texture_id, bb.Min, bb.Max, uv0, uv1, GetColorU32(tint_col)); + } +} + +// frame_padding < 0: uses FramePadding from style (default) +// frame_padding = 0: no framing +// frame_padding > 0: set framing size +// The color used are the button colors. +bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + + // Default to using texture ID as ID. User can still push string/integer prefixes. + // We could hash the size/uv to create a unique ID but that would prevent the user from animating UV. + PushID((void*)user_texture_id); + const ImGuiID id = window->GetID("#image"); + PopID(); + + const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : style.FramePadding; + const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding*2); + const ImRect image_bb(window->DC.CursorPos + padding, window->DC.CursorPos + padding + size); + ItemSize(bb); + if (!ItemAdd(bb, id)) + return false; + + bool hovered, held; + bool pressed = ButtonBehavior(bb, id, &hovered, &held); + + // Render + const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); + RenderNavHighlight(bb, id); + RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, style.FrameRounding)); + if (bg_col.w > 0.0f) + window->DrawList->AddRectFilled(image_bb.Min, image_bb.Max, GetColorU32(bg_col)); + window->DrawList->AddImage(user_texture_id, image_bb.Min, image_bb.Max, uv0, uv1, GetColorU32(tint_col)); + + return pressed; +} + +// Start logging ImGui output to TTY +void ImGui::LogToTTY(int max_depth) +{ + ImGuiContext& g = *GImGui; + if (g.LogEnabled) + return; + ImGuiWindow* window = g.CurrentWindow; + + IM_ASSERT(g.LogFile == NULL); + g.LogFile = stdout; + g.LogEnabled = true; + g.LogStartDepth = window->DC.TreeDepth; + if (max_depth >= 0) + g.LogAutoExpandMaxDepth = max_depth; +} + +// Start logging ImGui output to given file +void ImGui::LogToFile(int max_depth, const char* filename) +{ + ImGuiContext& g = *GImGui; + if (g.LogEnabled) + return; + ImGuiWindow* window = g.CurrentWindow; + + if (!filename) + { + filename = g.IO.LogFilename; + if (!filename) + return; + } + + IM_ASSERT(g.LogFile == NULL); + g.LogFile = ImFileOpen(filename, "ab"); + if (!g.LogFile) + { + IM_ASSERT(g.LogFile != NULL); // Consider this an error + return; + } + g.LogEnabled = true; + g.LogStartDepth = window->DC.TreeDepth; + if (max_depth >= 0) + g.LogAutoExpandMaxDepth = max_depth; +} + +// Start logging ImGui output to clipboard +void ImGui::LogToClipboard(int max_depth) +{ + ImGuiContext& g = *GImGui; + if (g.LogEnabled) + return; + ImGuiWindow* window = g.CurrentWindow; + + IM_ASSERT(g.LogFile == NULL); + g.LogFile = NULL; + g.LogEnabled = true; + g.LogStartDepth = window->DC.TreeDepth; + if (max_depth >= 0) + g.LogAutoExpandMaxDepth = max_depth; +} + +void ImGui::LogFinish() +{ + ImGuiContext& g = *GImGui; + if (!g.LogEnabled) + return; + + LogText(IM_NEWLINE); + if (g.LogFile != NULL) + { + if (g.LogFile == stdout) + fflush(g.LogFile); + else + fclose(g.LogFile); + g.LogFile = NULL; + } + if (g.LogClipboard.size() > 1) + { + SetClipboardText(g.LogClipboard.begin()); + g.LogClipboard.clear(); + } + g.LogEnabled = false; +} + +// Helper to display logging buttons +void ImGui::LogButtons() +{ + ImGuiContext& g = *GImGui; + + PushID("LogButtons"); + const bool log_to_tty = Button("Log To TTY"); SameLine(); + const bool log_to_file = Button("Log To File"); SameLine(); + const bool log_to_clipboard = Button("Log To Clipboard"); SameLine(); + PushItemWidth(80.0f); + PushAllowKeyboardFocus(false); + SliderInt("Depth", &g.LogAutoExpandMaxDepth, 0, 9, NULL); + PopAllowKeyboardFocus(); + PopItemWidth(); + PopID(); + + // Start logging at the end of the function so that the buttons don't appear in the log + if (log_to_tty) + LogToTTY(g.LogAutoExpandMaxDepth); + if (log_to_file) + LogToFile(g.LogAutoExpandMaxDepth, g.IO.LogFilename); + if (log_to_clipboard) + LogToClipboard(g.LogAutoExpandMaxDepth); +} + +bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) +{ + if (flags & ImGuiTreeNodeFlags_Leaf) + return true; + + // We only write to the tree storage if the user clicks (or explicitly use SetNextTreeNode*** functions) + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + ImGuiStorage* storage = window->DC.StateStorage; + + bool is_open; + if (g.NextTreeNodeOpenCond != 0) + { + if (g.NextTreeNodeOpenCond & ImGuiCond_Always) + { + is_open = g.NextTreeNodeOpenVal; + storage->SetInt(id, is_open); + } + else + { + // We treat ImGuiCond_Once and ImGuiCond_FirstUseEver the same because tree node state are not saved persistently. + const int stored_value = storage->GetInt(id, -1); + if (stored_value == -1) + { + is_open = g.NextTreeNodeOpenVal; + storage->SetInt(id, is_open); + } + else + { + is_open = stored_value != 0; + } + } + g.NextTreeNodeOpenCond = 0; + } + else + { + is_open = storage->GetInt(id, (flags & ImGuiTreeNodeFlags_DefaultOpen) ? 1 : 0) != 0; + } + + // When logging is enabled, we automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior). + // NB- If we are above max depth we still allow manually opened nodes to be logged. + if (g.LogEnabled && !(flags & ImGuiTreeNodeFlags_NoAutoOpenOnLog) && window->DC.TreeDepth < g.LogAutoExpandMaxDepth) + is_open = true; + + return is_open; +} + +bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0; + const ImVec2 padding = (display_frame || (flags & ImGuiTreeNodeFlags_FramePadding)) ? style.FramePadding : ImVec2(style.FramePadding.x, 0.0f); + + if (!label_end) + label_end = FindRenderedTextEnd(label); + const ImVec2 label_size = CalcTextSize(label, label_end, false); + + // We vertically grow up to current line height up the typical widget height. + const float text_base_offset_y = ImMax(padding.y, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it + const float frame_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2); + ImRect frame_bb = ImRect(window->DC.CursorPos, ImVec2(window->Pos.x + GetContentRegionMax().x, window->DC.CursorPos.y + frame_height)); + if (display_frame) + { + // Framed header expand a little outside the default padding + frame_bb.Min.x -= (float)(int)(window->WindowPadding.x*0.5f) - 1; + frame_bb.Max.x += (float)(int)(window->WindowPadding.x*0.5f) - 1; + } + + const float text_offset_x = (g.FontSize + (display_frame ? padding.x*3 : padding.x*2)); // Collapser arrow width + Spacing + const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser + ItemSize(ImVec2(text_width, frame_height), text_base_offset_y); + + // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing + // (Ideally we'd want to add a flag for the user to specify if we want the hit test to be done up to the right side of the content or not) + const ImRect interact_bb = display_frame ? frame_bb : ImRect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + text_width + style.ItemSpacing.x*2, frame_bb.Max.y); + bool is_open = TreeNodeBehaviorIsOpen(id, flags); + + // Store a flag for the current depth to tell if we will allow closing this node when navigating one of its child. + // For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop(). + // This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero. + if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) + window->DC.TreeDepthMayJumpToParentOnPop |= (1 << window->DC.TreeDepth); + + bool item_add = ItemAdd(interact_bb, id); + window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HasDisplayRect; + window->DC.LastItemDisplayRect = frame_bb; + + if (!item_add) + { + if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) + TreePushRawID(id); + return is_open; + } + + // Flags that affects opening behavior: + // - 0(default) ..................... single-click anywhere to open + // - OpenOnDoubleClick .............. double-click anywhere to open + // - OpenOnArrow .................... single-click on arrow to open + // - OpenOnDoubleClick|OpenOnArrow .. single-click on arrow or double-click anywhere to open + ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowItemOverlap) ? ImGuiButtonFlags_AllowItemOverlap : 0); + if (!(flags & ImGuiTreeNodeFlags_Leaf)) + button_flags |= ImGuiButtonFlags_PressedOnDragDropHold; + if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) + button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); + + bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); + if (!(flags & ImGuiTreeNodeFlags_Leaf)) + { + bool toggled = false; + if (pressed) + { + toggled = !(flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) || (g.NavActivateId == id); + if (flags & ImGuiTreeNodeFlags_OpenOnArrow) + toggled |= IsMouseHoveringRect(interact_bb.Min, ImVec2(interact_bb.Min.x + text_offset_x, interact_bb.Max.y)) && (!g.NavDisableMouseHover); + if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) + toggled |= g.IO.MouseDoubleClicked[0]; + if (g.DragDropActive && is_open) // When using Drag and Drop "hold to open" we keep the node highlighted after opening, but never close it again. + toggled = false; + } + + if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Left && is_open) + { + toggled = true; + NavMoveRequestCancel(); + } + if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Right && !is_open) // If there's something upcoming on the line we may want to give it the priority? + { + toggled = true; + NavMoveRequestCancel(); + } + + if (toggled) + { + is_open = !is_open; + window->DC.StateStorage->SetInt(id, is_open); + } + } + if (flags & ImGuiTreeNodeFlags_AllowItemOverlap) + SetItemAllowOverlap(); + + // Render + const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); + const ImVec2 text_pos = frame_bb.Min + ImVec2(text_offset_x, text_base_offset_y); + if (display_frame) + { + // Framed type + RenderFrame(frame_bb.Min, frame_bb.Max, col, true, style.FrameRounding); + RenderNavHighlight(frame_bb, id, ImGuiNavHighlightFlags_TypeThin); + RenderArrow(frame_bb.Min + ImVec2(padding.x, text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f); + if (g.LogEnabled) + { + // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here. + const char log_prefix[] = "\n##"; + const char log_suffix[] = "##"; + LogRenderedText(&text_pos, log_prefix, log_prefix+3); + RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size); + LogRenderedText(&text_pos, log_suffix+1, log_suffix+3); + } + else + { + RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size); + } + } + else + { + // Unframed typed for tree nodes + if (hovered || (flags & ImGuiTreeNodeFlags_Selected)) + { + RenderFrame(frame_bb.Min, frame_bb.Max, col, false); + RenderNavHighlight(frame_bb, id, ImGuiNavHighlightFlags_TypeThin); + } + + if (flags & ImGuiTreeNodeFlags_Bullet) + RenderBullet(frame_bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y)); + else if (!(flags & ImGuiTreeNodeFlags_Leaf)) + RenderArrow(frame_bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f); + if (g.LogEnabled) + LogRenderedText(&text_pos, ">"); + RenderText(text_pos, label, label_end, false); + } + + if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) + TreePushRawID(id); + return is_open; +} + +// CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag). +// This is basically the same as calling TreeNodeEx(label, ImGuiTreeNodeFlags_CollapsingHeader). You can remove the _NoTreePushOnOpen flag if you want behavior closer to normal TreeNode(). +bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + return TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_CollapsingHeader, label); +} + +bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + if (p_open && !*p_open) + return false; + + ImGuiID id = window->GetID(label); + bool is_open = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | (p_open ? ImGuiTreeNodeFlags_AllowItemOverlap : 0), label); + if (p_open) + { + // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. + ImGuiContext& g = *GImGui; + ImGuiItemHoveredDataBackup last_item_backup; + float button_radius = g.FontSize * 0.5f; + ImVec2 button_center = ImVec2(ImMin(window->DC.LastItemRect.Max.x, window->ClipRect.Max.x) - g.Style.FramePadding.x - button_radius, window->DC.LastItemRect.GetCenter().y); + if (CloseButton(window->GetID((void*)(intptr_t)(id+1)), button_center, button_radius)) + *p_open = false; + last_item_backup.Restore(); + } + + return is_open; +} + +bool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + return TreeNodeBehavior(window->GetID(label), flags, label, NULL); +} + +bool ImGui::TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); + return TreeNodeBehavior(window->GetID(str_id), flags, g.TempBuffer, label_end); +} + +bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); + return TreeNodeBehavior(window->GetID(ptr_id), flags, g.TempBuffer, label_end); +} + +bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args) +{ + return TreeNodeExV(str_id, 0, fmt, args); +} + +bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args) +{ + return TreeNodeExV(ptr_id, 0, fmt, args); +} + +bool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + bool is_open = TreeNodeExV(str_id, flags, fmt, args); + va_end(args); + return is_open; +} + +bool ImGui::TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + bool is_open = TreeNodeExV(ptr_id, flags, fmt, args); + va_end(args); + return is_open; +} + +bool ImGui::TreeNode(const char* str_id, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + bool is_open = TreeNodeExV(str_id, 0, fmt, args); + va_end(args); + return is_open; +} + +bool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + bool is_open = TreeNodeExV(ptr_id, 0, fmt, args); + va_end(args); + return is_open; +} + +bool ImGui::TreeNode(const char* label) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + return TreeNodeBehavior(window->GetID(label), 0, label, NULL); +} + +void ImGui::TreeAdvanceToLabelPos() +{ + ImGuiContext& g = *GImGui; + g.CurrentWindow->DC.CursorPos.x += GetTreeNodeToLabelSpacing(); +} + +// Horizontal distance preceding label when using TreeNode() or Bullet() +float ImGui::GetTreeNodeToLabelSpacing() +{ + ImGuiContext& g = *GImGui; + return g.FontSize + (g.Style.FramePadding.x * 2.0f); +} + +void ImGui::SetNextTreeNodeOpen(bool is_open, ImGuiCond cond) +{ + ImGuiContext& g = *GImGui; + if (g.CurrentWindow->SkipItems) + return; + g.NextTreeNodeOpenVal = is_open; + g.NextTreeNodeOpenCond = cond ? cond : ImGuiCond_Always; +} + +void ImGui::PushID(const char* str_id) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + window->IDStack.push_back(window->GetIDNoKeepAlive(str_id)); +} + +void ImGui::PushID(const char* str_id_begin, const char* str_id_end) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + window->IDStack.push_back(window->GetIDNoKeepAlive(str_id_begin, str_id_end)); +} + +void ImGui::PushID(const void* ptr_id) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + window->IDStack.push_back(window->GetIDNoKeepAlive(ptr_id)); +} + +void ImGui::PushID(int int_id) +{ + const void* ptr_id = (void*)(intptr_t)int_id; + ImGuiWindow* window = GetCurrentWindowRead(); + window->IDStack.push_back(window->GetIDNoKeepAlive(ptr_id)); +} + +void ImGui::PopID() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + window->IDStack.pop_back(); +} + +ImGuiID ImGui::GetID(const char* str_id) +{ + return GImGui->CurrentWindow->GetID(str_id); +} + +ImGuiID ImGui::GetID(const char* str_id_begin, const char* str_id_end) +{ + return GImGui->CurrentWindow->GetID(str_id_begin, str_id_end); +} + +ImGuiID ImGui::GetID(const void* ptr_id) +{ + return GImGui->CurrentWindow->GetID(ptr_id); +} + +void ImGui::Bullet() +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + const float line_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + g.Style.FramePadding.y*2), g.FontSize); + const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize, line_height)); + ItemSize(bb); + if (!ItemAdd(bb, 0)) + { + SameLine(0, style.FramePadding.x*2); + return; + } + + // Render and stay on same line + RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f)); + SameLine(0, style.FramePadding.x*2); +} + +// Text with a little bullet aligned to the typical tree node. +void ImGui::BulletTextV(const char* fmt, va_list args) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + + const char* text_begin = g.TempBuffer; + const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); + const ImVec2 label_size = CalcTextSize(text_begin, text_end, false); + const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it + const float line_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + g.Style.FramePadding.y*2), g.FontSize); + const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x*2) : 0.0f), ImMax(line_height, label_size.y))); // Empty text doesn't add padding + ItemSize(bb); + if (!ItemAdd(bb, 0)) + return; + + // Render + RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f)); + RenderText(bb.Min+ImVec2(g.FontSize + style.FramePadding.x*2, text_base_offset_y), text_begin, text_end, false); +} + +void ImGui::BulletText(const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + BulletTextV(fmt, args); + va_end(args); +} + +static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format) +{ + if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32) // Signedness doesn't matter when pushing the argument + return ImFormatString(buf, buf_size, format, *(const ImU32*)data_ptr); + if (data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64) // Signedness doesn't matter when pushing the argument + return ImFormatString(buf, buf_size, format, *(const ImU64*)data_ptr); + if (data_type == ImGuiDataType_Float) + return ImFormatString(buf, buf_size, format, *(const float*)data_ptr); + if (data_type == ImGuiDataType_Double) + return ImFormatString(buf, buf_size, format, *(const double*)data_ptr); + IM_ASSERT(0); + return 0; +} + +// FIXME: Adding support for clamping on boundaries of the data type would be nice. +static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg1, const void* arg2) +{ + IM_ASSERT(op == '+' || op == '-'); + switch (data_type) + { + case ImGuiDataType_S32: + if (op == '+') *(int*)output = *(const int*)arg1 + *(const int*)arg2; + else if (op == '-') *(int*)output = *(const int*)arg1 - *(const int*)arg2; + return; + case ImGuiDataType_U32: + if (op == '+') *(unsigned int*)output = *(const unsigned int*)arg1 + *(const ImU32*)arg2; + else if (op == '-') *(unsigned int*)output = *(const unsigned int*)arg1 - *(const ImU32*)arg2; + return; + case ImGuiDataType_S64: + if (op == '+') *(ImS64*)output = *(const ImS64*)arg1 + *(const ImS64*)arg2; + else if (op == '-') *(ImS64*)output = *(const ImS64*)arg1 - *(const ImS64*)arg2; + return; + case ImGuiDataType_U64: + if (op == '+') *(ImU64*)output = *(const ImU64*)arg1 + *(const ImU64*)arg2; + else if (op == '-') *(ImU64*)output = *(const ImU64*)arg1 - *(const ImU64*)arg2; + return; + case ImGuiDataType_Float: + if (op == '+') *(float*)output = *(const float*)arg1 + *(const float*)arg2; + else if (op == '-') *(float*)output = *(const float*)arg1 - *(const float*)arg2; + return; + case ImGuiDataType_Double: + if (op == '+') *(double*)output = *(const double*)arg1 + *(const double*)arg2; + else if (op == '-') *(double*)output = *(const double*)arg1 - *(const double*)arg2; + return; + case ImGuiDataType_COUNT: break; + } + IM_ASSERT(0); +} + +struct ImGuiDataTypeInfo +{ + size_t Size; + const char* PrintFmt; // Unused + const char* ScanFmt; +}; + +static const ImGuiDataTypeInfo GDataTypeInfo[] = +{ + { sizeof(int), "%d", "%d" }, + { sizeof(unsigned int), "%u", "%u" }, +#ifdef _MSC_VER + { sizeof(ImS64), "%I64d","%I64d" }, + { sizeof(ImU64), "%I64u","%I64u" }, +#else + { sizeof(ImS64), "%lld", "%lld" }, + { sizeof(ImU64), "%llu", "%llu" }, +#endif + { sizeof(float), "%f", "%f" }, // float are promoted to double in va_arg + { sizeof(double), "%f", "%lf" }, +}; +IM_STATIC_ASSERT(IM_ARRAYSIZE(GDataTypeInfo) == ImGuiDataType_COUNT); + +// User can input math operators (e.g. +100) to edit a numerical values. +// NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess.. +static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* format) +{ + while (ImCharIsBlankA(*buf)) + buf++; + + // We don't support '-' op because it would conflict with inputing negative value. + // Instead you can use +-100 to subtract from an existing value + char op = buf[0]; + if (op == '+' || op == '*' || op == '/') + { + buf++; + while (ImCharIsBlankA(*buf)) + buf++; + } + else + { + op = 0; + } + if (!buf[0]) + return false; + + // Copy the value in an opaque buffer so we can compare at the end of the function if it changed at all. + IM_ASSERT(data_type < ImGuiDataType_COUNT); + int data_backup[2]; + IM_ASSERT(GDataTypeInfo[data_type].Size <= sizeof(data_backup)); + memcpy(data_backup, data_ptr, GDataTypeInfo[data_type].Size); + + if (format == NULL) + format = GDataTypeInfo[data_type].ScanFmt; + + int arg1i = 0; + if (data_type == ImGuiDataType_S32) + { + int* v = (int*)data_ptr; + int arg0i = *v; + float arg1f = 0.0f; + if (op && sscanf(initial_value_buf, format, &arg0i) < 1) + return false; + // Store operand in a float so we can use fractional value for multipliers (*1.1), but constant always parsed as integer so we can fit big integers (e.g. 2000000003) past float precision + if (op == '+') { if (sscanf(buf, "%d", &arg1i)) *v = (int)(arg0i + arg1i); } // Add (use "+-" to subtract) + else if (op == '*') { if (sscanf(buf, "%f", &arg1f)) *v = (int)(arg0i * arg1f); } // Multiply + else if (op == '/') { if (sscanf(buf, "%f", &arg1f) && arg1f != 0.0f) *v = (int)(arg0i / arg1f); } // Divide + else { if (sscanf(buf, format, &arg1i) == 1) *v = arg1i; } // Assign constant + } + else if (data_type == ImGuiDataType_U32 || data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64) + { + // Assign constant + // FIXME: We don't bother handling support for legacy operators since they are a little too crappy. Instead we may implement a proper expression evaluator in the future. + sscanf(buf, format, data_ptr); + } + else if (data_type == ImGuiDataType_Float) + { + // For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in + format = "%f"; + float* v = (float*)data_ptr; + float arg0f = *v, arg1f = 0.0f; + if (op && sscanf(initial_value_buf, format, &arg0f) < 1) + return false; + if (sscanf(buf, format, &arg1f) < 1) + return false; + if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract) + else if (op == '*') { *v = arg0f * arg1f; } // Multiply + else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide + else { *v = arg1f; } // Assign constant + } + else if (data_type == ImGuiDataType_Double) + { + format = "%lf"; // scanf differentiate float/double unlike printf which forces everything to double because of ellipsis + double* v = (double*)data_ptr; + double arg0f = *v, arg1f = 0.0; + if (op && sscanf(initial_value_buf, format, &arg0f) < 1) + return false; + if (sscanf(buf, format, &arg1f) < 1) + return false; + if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract) + else if (op == '*') { *v = arg0f * arg1f; } // Multiply + else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide + else { *v = arg1f; } // Assign constant + } + return memcmp(data_backup, data_ptr, GDataTypeInfo[data_type].Size) != 0; +} + +// Create text input in place of a slider (when CTRL+Clicking on slider) +// FIXME: Logic is messy and confusing. +bool ImGui::InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + + // Our replacement widget will override the focus ID (registered previously to allow for a TAB focus to happen) + // On the first frame, g.ScalarAsInputTextId == 0, then on subsequent frames it becomes == id + SetActiveID(g.ScalarAsInputTextId, window); + g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); + SetHoveredID(0); + FocusableItemUnregister(window); + + char fmt_buf[32]; + char data_buf[32]; + format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf)); + DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, data_ptr, format); + ImStrTrimBlanks(data_buf); + ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ((data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImGuiInputTextFlags_CharsScientific : ImGuiInputTextFlags_CharsDecimal); + bool value_changed = InputTextEx(label, data_buf, IM_ARRAYSIZE(data_buf), bb.GetSize(), flags); + if (g.ScalarAsInputTextId == 0) // First frame we started displaying the InputText widget + { + IM_ASSERT(g.ActiveId == id); // InputText ID expected to match the Slider ID + g.ScalarAsInputTextId = g.ActiveId; + SetHoveredID(id); + } + if (value_changed) + return DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialText.begin(), data_type, data_ptr, NULL); + return false; +} + +// We don't use strchr() because our strings are usually very short and often start with '%' +const char* ImParseFormatFindStart(const char* fmt) +{ + while (char c = fmt[0]) + { + if (c == '%' && fmt[1] != '%') + return fmt; + else if (c == '%') + fmt++; + fmt++; + } + return fmt; +} + +const char* ImParseFormatFindEnd(const char* fmt) +{ + // Printf/scanf types modifiers: I/L/h/j/l/t/w/z. Other uppercase letters qualify as types aka end of the format. + if (fmt[0] != '%') + return fmt; + const unsigned int ignored_uppercase_mask = (1 << ('I'-'A')) | (1 << ('L'-'A')); + const unsigned int ignored_lowercase_mask = (1 << ('h'-'a')) | (1 << ('j'-'a')) | (1 << ('l'-'a')) | (1 << ('t'-'a')) | (1 << ('w'-'a')) | (1 << ('z'-'a')); + for (char c; (c = *fmt) != 0; fmt++) + { + if (c >= 'A' && c <= 'Z' && ((1 << (c - 'A')) & ignored_uppercase_mask) == 0) + return fmt + 1; + if (c >= 'a' && c <= 'z' && ((1 << (c - 'a')) & ignored_lowercase_mask) == 0) + return fmt + 1; + } + return fmt; +} + +// Extract the format out of a format string with leading or trailing decorations +// fmt = "blah blah" -> return fmt +// fmt = "%.3f" -> return fmt +// fmt = "hello %.3f" -> return fmt + 6 +// fmt = "%.3f hello" -> return buf written with "%.3f" +const char* ImParseFormatTrimDecorations(const char* fmt, char* buf, int buf_size) +{ + const char* fmt_start = ImParseFormatFindStart(fmt); + if (fmt_start[0] != '%') + return fmt; + const char* fmt_end = ImParseFormatFindEnd(fmt_start); + if (fmt_end[0] == 0) // If we only have leading decoration, we don't need to copy the data. + return fmt_start; + ImStrncpy(buf, fmt_start, ImMin((int)(fmt_end + 1 - fmt_start), buf_size)); + return buf; +} + +// Parse display precision back from the display format string +// FIXME: This is still used by some navigation code path to infer a minimum tweak step, but we should aim to rework widgets so it isn't needed. +int ImParseFormatPrecision(const char* fmt, int default_precision) +{ + fmt = ImParseFormatFindStart(fmt); + if (fmt[0] != '%') + return default_precision; + fmt++; + while (*fmt >= '0' && *fmt <= '9') + fmt++; + int precision = INT_MAX; + if (*fmt == '.') + { + fmt = ImAtoi(fmt + 1, &precision); + if (precision < 0 || precision > 99) + precision = default_precision; + } + if (*fmt == 'e' || *fmt == 'E') // Maximum precision with scientific notation + precision = -1; + if ((*fmt == 'g' || *fmt == 'G') && precision == INT_MAX) + precision = -1; + return (precision == INT_MAX) ? default_precision : precision; +} + +static float GetMinimumStepAtDecimalPrecision(int decimal_precision) +{ + static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f }; + if (decimal_precision < 0) + return FLT_MIN; + return (decimal_precision >= 0 && decimal_precision < 10) ? min_steps[decimal_precision] : ImPow(10.0f, (float)-decimal_precision); +} + +template +static inline TYPE RoundScalarWithFormat(const char* format, ImGuiDataType data_type, TYPE v) +{ + const char* fmt_start = ImParseFormatFindStart(format); + if (fmt_start[0] != '%' || fmt_start[1] == '%') // Don't apply if the value is not visible in the format string + return v; + char v_str[64]; + ImFormatString(v_str, IM_ARRAYSIZE(v_str), fmt_start, v); + const char* p = v_str; + while (*p == ' ') + p++; + if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) + v = (TYPE)ImAtof(p); + else + ImAtoi(p, (SIGNEDTYPE*)&v); + return v; +} + +template +static inline float SliderBehaviorCalcRatioFromValue(ImGuiDataType data_type, TYPE v, TYPE v_min, TYPE v_max, float power, float linear_zero_pos) +{ + if (v_min == v_max) + return 0.0f; + + const bool is_power = (power != 1.0f) && (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double); + const TYPE v_clamped = (v_min < v_max) ? ImClamp(v, v_min, v_max) : ImClamp(v, v_max, v_min); + if (is_power) + { + if (v_clamped < 0.0f) + { + const float f = 1.0f - (float)((v_clamped - v_min) / (ImMin((TYPE)0, v_max) - v_min)); + return (1.0f - ImPow(f, 1.0f/power)) * linear_zero_pos; + } + else + { + const float f = (float)((v_clamped - ImMax((TYPE)0, v_min)) / (v_max - ImMax((TYPE)0, v_min))); + return linear_zero_pos + ImPow(f, 1.0f/power) * (1.0f - linear_zero_pos); + } + } + + // Linear slider + return (float)((FLOATTYPE)(v_clamped - v_min) / (FLOATTYPE)(v_max - v_min)); +} + +// FIXME: Move some of the code into SliderBehavior(). Current responsability is larger than what the equivalent DragBehaviorT<> does, we also do some rendering, etc. +template +static bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, TYPE* v, const TYPE v_min, const TYPE v_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb) +{ + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + + const bool is_horizontal = (flags & ImGuiSliderFlags_Vertical) == 0; + const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double); + const bool is_power = (power != 1.0f) && is_decimal; + + const float grab_padding = 2.0f; + const float slider_sz = is_horizontal ? (bb.GetWidth() - grab_padding * 2.0f) : (bb.GetHeight() - grab_padding * 2.0f); + float grab_sz = style.GrabMinSize; + SIGNEDTYPE v_range = (v_min < v_max ? v_max - v_min : v_min - v_max); + if (!is_decimal && v_range >= 0) // v_range < 0 may happen on integer overflows + grab_sz = ImMax((float)(slider_sz / (v_range + 1)), style.GrabMinSize); // For integer sliders: if possible have the grab size represent 1 unit + grab_sz = ImMin(grab_sz, slider_sz); + const float slider_usable_sz = slider_sz - grab_sz; + const float slider_usable_pos_min = (is_horizontal ? bb.Min.x : bb.Min.y) + grab_padding + grab_sz*0.5f; + const float slider_usable_pos_max = (is_horizontal ? bb.Max.x : bb.Max.y) - grab_padding - grab_sz*0.5f; + + // For power curve sliders that cross over sign boundary we want the curve to be symmetric around 0.0f + float linear_zero_pos; // 0.0->1.0f + if (is_power && v_min * v_max < 0.0f) + { + // Different sign + const FLOATTYPE linear_dist_min_to_0 = ImPow(v_min >= 0 ? (FLOATTYPE)v_min : -(FLOATTYPE)v_min, (FLOATTYPE)1.0f/power); + const FLOATTYPE linear_dist_max_to_0 = ImPow(v_max >= 0 ? (FLOATTYPE)v_max : -(FLOATTYPE)v_max, (FLOATTYPE)1.0f/power); + linear_zero_pos = (float)(linear_dist_min_to_0 / (linear_dist_min_to_0 + linear_dist_max_to_0)); + } + else + { + // Same sign + linear_zero_pos = v_min < 0.0f ? 1.0f : 0.0f; + } + + // Process interacting with the slider + bool value_changed = false; + if (g.ActiveId == id) + { + bool set_new_value = false; + float clicked_t = 0.0f; + if (g.ActiveIdSource == ImGuiInputSource_Mouse) + { + if (!g.IO.MouseDown[0]) + { + ClearActiveID(); + } + else + { + const float mouse_abs_pos = is_horizontal ? g.IO.MousePos.x : g.IO.MousePos.y; + clicked_t = (slider_usable_sz > 0.0f) ? ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) : 0.0f; + if (!is_horizontal) + clicked_t = 1.0f - clicked_t; + set_new_value = true; + } + } + else if (g.ActiveIdSource == ImGuiInputSource_Nav) + { + const ImVec2 delta2 = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 0.0f, 0.0f); + float delta = is_horizontal ? delta2.x : -delta2.y; + if (g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated) + { + ClearActiveID(); + } + else if (delta != 0.0f) + { + clicked_t = SliderBehaviorCalcRatioFromValue(data_type, *v, v_min, v_max, power, linear_zero_pos); + const int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 0; + if ((decimal_precision > 0) || is_power) + { + delta /= 100.0f; // Gamepad/keyboard tweak speeds in % of slider bounds + if (IsNavInputDown(ImGuiNavInput_TweakSlow)) + delta /= 10.0f; + } + else + { + if ((v_range >= -100.0f && v_range <= 100.0f) || IsNavInputDown(ImGuiNavInput_TweakSlow)) + delta = ((delta < 0.0f) ? -1.0f : +1.0f) / (float)v_range; // Gamepad/keyboard tweak speeds in integer steps + else + delta /= 100.0f; + } + if (IsNavInputDown(ImGuiNavInput_TweakFast)) + delta *= 10.0f; + set_new_value = true; + if ((clicked_t >= 1.0f && delta > 0.0f) || (clicked_t <= 0.0f && delta < 0.0f)) // This is to avoid applying the saturation when already past the limits + set_new_value = false; + else + clicked_t = ImSaturate(clicked_t + delta); + } + } + + if (set_new_value) + { + TYPE v_new; + if (is_power) + { + // Account for power curve scale on both sides of the zero + if (clicked_t < linear_zero_pos) + { + // Negative: rescale to the negative range before powering + float a = 1.0f - (clicked_t / linear_zero_pos); + a = ImPow(a, power); + v_new = ImLerp(ImMin(v_max, (TYPE)0), v_min, a); + } + else + { + // Positive: rescale to the positive range before powering + float a; + if (ImFabs(linear_zero_pos - 1.0f) > 1.e-6f) + a = (clicked_t - linear_zero_pos) / (1.0f - linear_zero_pos); + else + a = clicked_t; + a = ImPow(a, power); + v_new = ImLerp(ImMax(v_min, (TYPE)0), v_max, a); + } + } + else + { + // Linear slider + if (is_decimal) + { + v_new = ImLerp(v_min, v_max, clicked_t); + } + else + { + // For integer values we want the clicking position to match the grab box so we round above + // This code is carefully tuned to work with large values (e.g. high ranges of U64) while preserving this property.. + FLOATTYPE v_new_off_f = (v_max - v_min) * clicked_t; + TYPE v_new_off_floor = (TYPE)(v_new_off_f); + TYPE v_new_off_round = (TYPE)(v_new_off_f + (FLOATTYPE)0.5); + if (!is_decimal && v_new_off_floor < v_new_off_round) + v_new = v_min + v_new_off_round; + else + v_new = v_min + v_new_off_floor; + } + } + + // Round to user desired precision based on format string + v_new = RoundScalarWithFormat(format, data_type, v_new); + + // Apply result + if (*v != v_new) + { + *v = v_new; + value_changed = true; + } + } + } + + // Output grab position so it can be displayed by the caller + float grab_t = SliderBehaviorCalcRatioFromValue(data_type, *v, v_min, v_max, power, linear_zero_pos); + if (!is_horizontal) + grab_t = 1.0f - grab_t; + const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); + if (is_horizontal) + *out_grab_bb = ImRect(grab_pos - grab_sz*0.5f, bb.Min.y + grab_padding, grab_pos + grab_sz*0.5f, bb.Max.y - grab_padding); + else + *out_grab_bb = ImRect(bb.Min.x + grab_padding, grab_pos - grab_sz*0.5f, bb.Max.x - grab_padding, grab_pos + grab_sz*0.5f); + + return value_changed; +} + +// For 32-bits and larger types, slider bounds are limited to half the natural type range. +// So e.g. an integer Slider between INT_MAX-10 and INT_MAX will fail, but an integer Slider between INT_MAX/2-10 and INT_MAX/2 will be ok. +// It would be possible to lift that limitation with some work but it doesn't seem to be worth it for sliders. +bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb) +{ + switch (data_type) + { + case ImGuiDataType_S32: + IM_ASSERT(*(const ImS32*)v_min >= IM_S32_MIN/2 && *(const ImS32*)v_max <= IM_S32_MAX/2); + return SliderBehaviorT(bb, id, data_type, (ImS32*)v, *(const ImS32*)v_min, *(const ImS32*)v_max, format, power, flags, out_grab_bb); + case ImGuiDataType_U32: + IM_ASSERT(*(const ImU32*)v_min <= IM_U32_MAX/2); + return SliderBehaviorT(bb, id, data_type, (ImU32*)v, *(const ImU32*)v_min, *(const ImU32*)v_max, format, power, flags, out_grab_bb); + case ImGuiDataType_S64: + IM_ASSERT(*(const ImS64*)v_min >= IM_S64_MIN/2 && *(const ImS64*)v_max <= IM_S64_MAX/2); + return SliderBehaviorT(bb, id, data_type, (ImS64*)v, *(const ImS64*)v_min, *(const ImS64*)v_max, format, power, flags, out_grab_bb); + case ImGuiDataType_U64: + IM_ASSERT(*(const ImU64*)v_min <= IM_U64_MAX/2); + return SliderBehaviorT(bb, id, data_type, (ImU64*)v, *(const ImU64*)v_min, *(const ImU64*)v_max, format, power, flags, out_grab_bb); + case ImGuiDataType_Float: + IM_ASSERT(*(const float*)v_min >= -FLT_MAX/2.0f && *(const float*)v_max <= FLT_MAX/2.0f); + return SliderBehaviorT(bb, id, data_type, (float*)v, *(const float*)v_min, *(const float*)v_max, format, power, flags, out_grab_bb); + case ImGuiDataType_Double: + IM_ASSERT(*(const double*)v_min >= -DBL_MAX/2.0f && *(const double*)v_max <= DBL_MAX/2.0f); + return SliderBehaviorT(bb, id, data_type, (double*)v, *(const double*)v_min, *(const double*)v_max, format, power, flags, out_grab_bb); + case ImGuiDataType_COUNT: break; + } + IM_ASSERT(0); + return false; +} + +// FIXME-LEGACY: Prior to 1.61 our DragInt() function internally used floats and because of this the compile-time default value for format was "%.0f". +// Even though we changed the compile-time default, we expect users to have carried %f around, which would break the display of DragInt() calls. +// To honor backward compatibility we are rewriting the format string, unless IMGUI_DISABLE_OBSOLETE_FUNCTIONS is enabled. What could possibly go wrong?! +static const char* PatchFormatStringFloatToInt(const char* fmt) +{ + if (fmt[0] == '%' && fmt[1] == '.' && fmt[2] == '0' && fmt[3] == 'f' && fmt[4] == 0) // Fast legacy path for "%.0f" which is expected to be the most common case. + return "%d"; + const char* fmt_start = ImParseFormatFindStart(fmt); // Find % (if any, and ignore %%) + const char* fmt_end = ImParseFormatFindEnd(fmt_start); // Find end of format specifier, which itself is an exercise of confidence/recklessness (because snprintf is dependent on libc or user). + if (fmt_end > fmt_start && fmt_end[-1] == 'f') + { +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + if (fmt_start == fmt && fmt_end[0] == 0) + return "%d"; + ImGuiContext& g = *GImGui; + ImFormatString(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), "%.*s%%d%s", (int)(fmt_start - fmt), fmt, fmt_end); // Honor leading and trailing decorations, but lose alignment/precision. + return g.TempBuffer; +#else + IM_ASSERT(0 && "DragInt(): Invalid format string!"); // Old versions used a default parameter of "%.0f", please replace with e.g. "%d" +#endif + } + return fmt; +} + +bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + const ImGuiID id = window->GetID(label); + const float w = CalcItemWidth(); + + const ImVec2 label_size = CalcTextSize(label, NULL, true); + const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); + const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); + + // NB- we don't call ItemSize() yet because we may turn into a text edit box below + if (!ItemAdd(total_bb, id, &frame_bb)) + { + ItemSize(total_bb, style.FramePadding.y); + return false; + } + + // Default format string when passing NULL + // Patch old "%.0f" format string to use "%d", read function comments for more details. + IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT); + if (format == NULL) + format = GDataTypeInfo[data_type].PrintFmt; + else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0) + format = PatchFormatStringFloatToInt(format); + + // Tabbing or CTRL-clicking on Slider turns it into an input box + bool start_text_input = false; + const bool tab_focus_requested = FocusableItemRegister(window, id); + const bool hovered = ItemHoverable(frame_bb, id); + if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || (g.NavInputId == id && g.ScalarAsInputTextId != id)) + { + SetActiveID(id, window); + SetFocusID(id, window); + FocusWindow(window); + g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); + if (tab_focus_requested || g.IO.KeyCtrl || g.NavInputId == id) + { + start_text_input = true; + g.ScalarAsInputTextId = 0; + } + } + if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id)) + return InputScalarAsWidgetReplacement(frame_bb, id, label, data_type, v, format); + + ItemSize(total_bb, style.FramePadding.y); + + // Draw frame + const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); + RenderNavHighlight(frame_bb, id); + RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding); + + // Slider behavior + ImRect grab_bb; + const bool value_changed = SliderBehavior(frame_bb, id, data_type, v, v_min, v_max, format, power, ImGuiSliderFlags_None, &grab_bb); + if (value_changed) + MarkItemValueChanged(id); + + // Render grab + window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding); + + // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. + char value_buf[64]; + const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format); + RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.5f)); + + if (label_size.x > 0.0f) + RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); + + return value_changed; +} + +bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, float power) +{ + return SliderScalar(label, ImGuiDataType_Float, v, &v_min, &v_max, format, power); +} + +bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + const ImGuiID id = window->GetID(label); + + const ImVec2 label_size = CalcTextSize(label, NULL, true); + const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size); + const ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); + + ItemSize(bb, style.FramePadding.y); + if (!ItemAdd(frame_bb, id)) + return false; + + // Default format string when passing NULL + // Patch old "%.0f" format string to use "%d", read function comments for more details. + IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT); + if (format == NULL) + format = GDataTypeInfo[data_type].PrintFmt; + else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0) + format = PatchFormatStringFloatToInt(format); + + const bool hovered = ItemHoverable(frame_bb, id); + if ((hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavInputId == id) + { + SetActiveID(id, window); + SetFocusID(id, window); + FocusWindow(window); + g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); + } + + + // Draw frame + const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); + RenderNavHighlight(frame_bb, id); + RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding); + + // Slider behavior + ImRect grab_bb; + const bool value_changed = SliderBehavior(frame_bb, id, data_type, v, v_min, v_max, format, power, ImGuiSliderFlags_Vertical, &grab_bb); + if (value_changed) + MarkItemValueChanged(id); + + // Render grab + window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding); + + // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. + // For the vertical slider we allow centered text to overlap the frame padding + char value_buf[64]; + const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format); + RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.0f)); + if (label_size.x > 0.0f) + RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); + + return value_changed; +} + +bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, float v_degrees_max) +{ + float v_deg = (*v_rad) * 360.0f / (2*IM_PI); + bool value_changed = SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, "%.0f deg", 1.0f); + *v_rad = v_deg * (2*IM_PI) / 360.0f; + return value_changed; +} + +bool ImGui::SliderInt(const char* label, int* v, int v_min, int v_max, const char* format) +{ + return SliderScalar(label, ImGuiDataType_S32, v, &v_min, &v_max, format); +} + +bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format, float power) +{ + return VSliderScalar(label, size, ImGuiDataType_Float, v, &v_min, &v_max, format, power); +} + +bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format) +{ + return VSliderScalar(label, size, ImGuiDataType_S32, v, &v_min, &v_max, format); +} + +// Add multiple sliders on 1 line for compact edition of multiple components +bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format, float power) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + bool value_changed = false; + BeginGroup(); + PushID(label); + PushMultiItemsWidths(components); + size_t type_size = GDataTypeInfo[data_type].Size; + for (int i = 0; i < components; i++) + { + PushID(i); + value_changed |= SliderScalar("##v", data_type, v, v_min, v_max, format, power); + SameLine(0, g.Style.ItemInnerSpacing.x); + PopID(); + PopItemWidth(); + v = (void*)((char*)v + type_size); + } + PopID(); + + TextUnformatted(label, FindRenderedTextEnd(label)); + EndGroup(); + return value_changed; +} + +bool ImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, float power) +{ + return SliderScalarN(label, ImGuiDataType_Float, v, 2, &v_min, &v_max, format, power); +} + +bool ImGui::SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, float power) +{ + return SliderScalarN(label, ImGuiDataType_Float, v, 3, &v_min, &v_max, format, power); +} + +bool ImGui::SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format, float power) +{ + return SliderScalarN(label, ImGuiDataType_Float, v, 4, &v_min, &v_max, format, power); +} + +bool ImGui::SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format) +{ + return SliderScalarN(label, ImGuiDataType_S32, v, 2, &v_min, &v_max, format); +} + +bool ImGui::SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format) +{ + return SliderScalarN(label, ImGuiDataType_S32, v, 3, &v_min, &v_max, format); +} + +bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format) +{ + return SliderScalarN(label, ImGuiDataType_S32, v, 4, &v_min, &v_max, format); +} + +// This is called by DragBehavior() when the widget is active (held by mouse or being manipulated with Nav controls) +template +static bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const TYPE v_min, const TYPE v_max, const char* format, float power) +{ + ImGuiContext& g = *GImGui; + + // Default tweak speed + bool has_min_max = (v_min != v_max) && (v_max - v_max < FLT_MAX); + if (v_speed == 0.0f && has_min_max) + v_speed = (float)((v_max - v_min) * g.DragSpeedDefaultRatio); + + // Inputs accumulates into g.DragCurrentAccum, which is flushed into the current value as soon as it makes a difference with our precision settings + float adjust_delta = 0.0f; + if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid() && g.IO.MouseDragMaxDistanceSqr[0] > 1.0f*1.0f) + { + adjust_delta = g.IO.MouseDelta.x; + if (g.IO.KeyAlt) + adjust_delta *= 1.0f/100.0f; + if (g.IO.KeyShift) + adjust_delta *= 10.0f; + } + else if (g.ActiveIdSource == ImGuiInputSource_Nav) + { + int decimal_precision = (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImParseFormatPrecision(format, 3) : 0; + adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard|ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; + v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); + } + adjust_delta *= v_speed; + + // Clear current value on activation + // Avoid altering values and clamping when we are _already_ past the limits and heading in the same direction, so e.g. if range is 0..255, current value is 300 and we are pushing to the right side, keep the 300. + bool is_just_activated = g.ActiveIdIsJustActivated; + bool is_already_past_limits_and_pushing_outward = has_min_max && ((*v >= v_max && adjust_delta > 0.0f) || (*v <= v_min && adjust_delta < 0.0f)); + if (is_just_activated || is_already_past_limits_and_pushing_outward) + { + g.DragCurrentAccum = 0.0f; + g.DragCurrentAccumDirty = false; + } + else if (adjust_delta != 0.0f) + { + g.DragCurrentAccum += adjust_delta; + g.DragCurrentAccumDirty = true; + } + + if (!g.DragCurrentAccumDirty) + return false; + + TYPE v_cur = *v; + FLOATTYPE v_old_ref_for_accum_remainder = (FLOATTYPE)0.0f; + + const bool is_power = (power != 1.0f && (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) && has_min_max); + if (is_power) + { + // Offset + round to user desired precision, with a curve on the v_min..v_max range to get more precision on one side of the range + FLOATTYPE v_old_norm_curved = ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power); + FLOATTYPE v_new_norm_curved = v_old_norm_curved + (g.DragCurrentAccum / (v_max - v_min)); + v_cur = v_min + (TYPE)ImPow(ImSaturate((float)v_new_norm_curved), power) * (v_max - v_min); + v_old_ref_for_accum_remainder = v_old_norm_curved; + } + else + { + v_cur += (TYPE)g.DragCurrentAccum; + } + + // Round to user desired precision based on format string + v_cur = RoundScalarWithFormat(format, data_type, v_cur); + + // Preserve remainder after rounding has been applied. This also allow slow tweaking of values. + g.DragCurrentAccumDirty = false; + if (is_power) + { + FLOATTYPE v_cur_norm_curved = ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power); + g.DragCurrentAccum -= (float)(v_cur_norm_curved - v_old_ref_for_accum_remainder); + } + else + { + g.DragCurrentAccum -= (float)((SIGNEDTYPE)v_cur - (SIGNEDTYPE)*v); + } + + // Lose zero sign for float/double + if (v_cur == (TYPE)-0) + v_cur = (TYPE)0; + + // Clamp values (handle overflow/wrap-around) + if (*v != v_cur && has_min_max) + { + if (v_cur < v_min || (v_cur > *v && adjust_delta < 0.0f)) + v_cur = v_min; + if (v_cur > v_max || (v_cur < *v && adjust_delta > 0.0f)) + v_cur = v_max; + } + + // Apply result + if (*v == v_cur) + return false; + *v = v_cur; + return true; +} + +bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power) +{ + ImGuiContext& g = *GImGui; + if (g.ActiveId == id) + { + if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0]) + ClearActiveID(); + else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated) + ClearActiveID(); + } + if (g.ActiveId != id) + return false; + + switch (data_type) + { + case ImGuiDataType_S32: return DragBehaviorT(data_type, (ImS32*)v, v_speed, v_min ? *(const ImS32* )v_min : IM_S32_MIN, v_max ? *(const ImS32* )v_max : IM_S32_MAX, format, power); + case ImGuiDataType_U32: return DragBehaviorT(data_type, (ImU32*)v, v_speed, v_min ? *(const ImU32* )v_min : IM_U32_MIN, v_max ? *(const ImU32* )v_max : IM_U32_MAX, format, power); + case ImGuiDataType_S64: return DragBehaviorT(data_type, (ImS64*)v, v_speed, v_min ? *(const ImS64* )v_min : IM_S64_MIN, v_max ? *(const ImS64* )v_max : IM_S64_MAX, format, power); + case ImGuiDataType_U64: return DragBehaviorT(data_type, (ImU64*)v, v_speed, v_min ? *(const ImU64* )v_min : IM_U64_MIN, v_max ? *(const ImU64* )v_max : IM_U64_MAX, format, power); + case ImGuiDataType_Float: return DragBehaviorT(data_type, (float*)v, v_speed, v_min ? *(const float* )v_min : -FLT_MAX, v_max ? *(const float* )v_max : FLT_MAX, format, power); + case ImGuiDataType_Double: return DragBehaviorT(data_type, (double*)v, v_speed, v_min ? *(const double*)v_min : -DBL_MAX, v_max ? *(const double*)v_max : DBL_MAX, format, power); + case ImGuiDataType_COUNT: break; + } + IM_ASSERT(0); + return false; +} + +bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + if (power != 1.0f) + IM_ASSERT(v_min != NULL && v_max != NULL); // When using a power curve the drag needs to have known bounds + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + const ImGuiID id = window->GetID(label); + const float w = CalcItemWidth(); + + const ImVec2 label_size = CalcTextSize(label, NULL, true); + const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); + const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); + const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); + + // NB- we don't call ItemSize() yet because we may turn into a text edit box below + if (!ItemAdd(total_bb, id, &frame_bb)) + { + ItemSize(total_bb, style.FramePadding.y); + return false; + } + const bool hovered = ItemHoverable(frame_bb, id); + + // Default format string when passing NULL + // Patch old "%.0f" format string to use "%d", read function comments for more details. + IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT); + if (format == NULL) + format = GDataTypeInfo[data_type].PrintFmt; + else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0) + format = PatchFormatStringFloatToInt(format); + + // Tabbing or CTRL-clicking on Drag turns it into an input box + bool start_text_input = false; + const bool tab_focus_requested = FocusableItemRegister(window, id); + if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] || g.IO.MouseDoubleClicked[0])) || g.NavActivateId == id || (g.NavInputId == id && g.ScalarAsInputTextId != id)) + { + SetActiveID(id, window); + SetFocusID(id, window); + FocusWindow(window); + g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); + if (tab_focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0] || g.NavInputId == id) + { + start_text_input = true; + g.ScalarAsInputTextId = 0; + } + } + if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id)) + return InputScalarAsWidgetReplacement(frame_bb, id, label, data_type, v, format); + + // Actual drag behavior + ItemSize(total_bb, style.FramePadding.y); + const bool value_changed = DragBehavior(id, data_type, v, v_speed, v_min, v_max, format, power); + if (value_changed) + MarkItemValueChanged(id); + + // Draw frame + const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); + RenderNavHighlight(frame_bb, id); + RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); + + // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. + char value_buf[64]; + const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format); + RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f)); + + if (label_size.x > 0.0f) + RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label); + + return value_changed; +} + +bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* v, int components, float v_speed, const void* v_min, const void* v_max, const char* format, float power) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + bool value_changed = false; + BeginGroup(); + PushID(label); + PushMultiItemsWidths(components); + size_t type_size = GDataTypeInfo[data_type].Size; + for (int i = 0; i < components; i++) + { + PushID(i); + value_changed |= DragScalar("##v", data_type, v, v_speed, v_min, v_max, format, power); + SameLine(0, g.Style.ItemInnerSpacing.x); + PopID(); + PopItemWidth(); + v = (void*)((char*)v + type_size); + } + PopID(); + + TextUnformatted(label, FindRenderedTextEnd(label)); + EndGroup(); + return value_changed; +} + +bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* format, float power) +{ + return DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, format, power); +} + +bool ImGui::DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* format, float power) +{ + return DragScalarN(label, ImGuiDataType_Float, v, 2, v_speed, &v_min, &v_max, format, power); +} + +bool ImGui::DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* format, float power) +{ + return DragScalarN(label, ImGuiDataType_Float, v, 3, v_speed, &v_min, &v_max, format, power); +} + +bool ImGui::DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* format, float power) +{ + return DragScalarN(label, ImGuiDataType_Float, v, 4, v_speed, &v_min, &v_max, format, power); +} + +bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed, float v_min, float v_max, const char* format, const char* format_max, float power) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + PushID(label); + BeginGroup(); + PushMultiItemsWidths(2); + + bool value_changed = DragFloat("##min", v_current_min, v_speed, (v_min >= v_max) ? -FLT_MAX : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), format, power); + PopItemWidth(); + SameLine(0, g.Style.ItemInnerSpacing.x); + value_changed |= DragFloat("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? FLT_MAX : v_max, format_max ? format_max : format, power); + PopItemWidth(); + SameLine(0, g.Style.ItemInnerSpacing.x); + + TextUnformatted(label, FindRenderedTextEnd(label)); + EndGroup(); + PopID(); + return value_changed; +} + +// NB: v_speed is float to allow adjusting the drag speed with more precision +bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_max, const char* format) +{ + return DragScalar(label, ImGuiDataType_S32, v, v_speed, &v_min, &v_max, format); +} + +bool ImGui::DragInt2(const char* label, int v[2], float v_speed, int v_min, int v_max, const char* format) +{ + return DragScalarN(label, ImGuiDataType_S32, v, 2, v_speed, &v_min, &v_max, format); +} + +bool ImGui::DragInt3(const char* label, int v[3], float v_speed, int v_min, int v_max, const char* format) +{ + return DragScalarN(label, ImGuiDataType_S32, v, 3, v_speed, &v_min, &v_max, format); +} + +bool ImGui::DragInt4(const char* label, int v[4], float v_speed, int v_min, int v_max, const char* format) +{ + return DragScalarN(label, ImGuiDataType_S32, v, 4, v_speed, &v_min, &v_max, format); +} + +bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed, int v_min, int v_max, const char* format, const char* format_max) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + PushID(label); + BeginGroup(); + PushMultiItemsWidths(2); + + bool value_changed = DragInt("##min", v_current_min, v_speed, (v_min >= v_max) ? INT_MIN : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), format); + PopItemWidth(); + SameLine(0, g.Style.ItemInnerSpacing.x); + value_changed |= DragInt("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? INT_MAX : v_max, format_max ? format_max : format); + PopItemWidth(); + SameLine(0, g.Style.ItemInnerSpacing.x); + + TextUnformatted(label, FindRenderedTextEnd(label)); + EndGroup(); + PopID(); + + return value_changed; +} + +void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + + const ImVec2 label_size = CalcTextSize(label, NULL, true); + if (graph_size.x == 0.0f) + graph_size.x = CalcItemWidth(); + if (graph_size.y == 0.0f) + graph_size.y = label_size.y + (style.FramePadding.y * 2); + + const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(graph_size.x, graph_size.y)); + const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); + const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0)); + ItemSize(total_bb, style.FramePadding.y); + if (!ItemAdd(total_bb, 0, &frame_bb)) + return; + const bool hovered = ItemHoverable(inner_bb, 0); + + // Determine scale from values if not specified + if (scale_min == FLT_MAX || scale_max == FLT_MAX) + { + float v_min = FLT_MAX; + float v_max = -FLT_MAX; + for (int i = 0; i < values_count; i++) + { + const float v = values_getter(data, i); + v_min = ImMin(v_min, v); + v_max = ImMax(v_max, v); + } + if (scale_min == FLT_MAX) + scale_min = v_min; + if (scale_max == FLT_MAX) + scale_max = v_max; + } + + RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); + + if (values_count > 0) + { + int res_w = ImMin((int)graph_size.x, values_count) + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0); + int item_count = values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0); + + // Tooltip on hover + int v_hovered = -1; + if (hovered) + { + const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f); + const int v_idx = (int)(t * item_count); + IM_ASSERT(v_idx >= 0 && v_idx < values_count); + + const float v0 = values_getter(data, (v_idx + values_offset) % values_count); + const float v1 = values_getter(data, (v_idx + 1 + values_offset) % values_count); + if (plot_type == ImGuiPlotType_Lines) + SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx+1, v1); + else if (plot_type == ImGuiPlotType_Histogram) + SetTooltip("%d: %8.4g", v_idx, v0); + v_hovered = v_idx; + } + + const float t_step = 1.0f / (float)res_w; + const float inv_scale = (scale_min == scale_max) ? 0.0f : (1.0f / (scale_max - scale_min)); + + float v0 = values_getter(data, (0 + values_offset) % values_count); + float t0 = 0.0f; + ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) * inv_scale) ); // Point in the normalized space of our target rectangle + float histogram_zero_line_t = (scale_min * scale_max < 0.0f) ? (-scale_min * inv_scale) : (scale_min < 0.0f ? 0.0f : 1.0f); // Where does the zero line stands + + const ImU32 col_base = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram); + const ImU32 col_hovered = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered); + + for (int n = 0; n < res_w; n++) + { + const float t1 = t0 + t_step; + const int v1_idx = (int)(t0 * item_count + 0.5f); + IM_ASSERT(v1_idx >= 0 && v1_idx < values_count); + const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count); + const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) * inv_scale) ); + + // NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU. + ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0); + ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, histogram_zero_line_t)); + if (plot_type == ImGuiPlotType_Lines) + { + window->DrawList->AddLine(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base); + } + else if (plot_type == ImGuiPlotType_Histogram) + { + if (pos1.x >= pos0.x + 2.0f) + pos1.x -= 1.0f; + window->DrawList->AddRectFilled(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base); + } + + t0 = t1; + tp0 = tp1; + } + } + + // Text overlay + if (overlay_text) + RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, overlay_text, NULL, NULL, ImVec2(0.5f,0.0f)); + + if (label_size.x > 0.0f) + RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label); +} + +struct ImGuiPlotArrayGetterData +{ + const float* Values; + int Stride; + + ImGuiPlotArrayGetterData(const float* values, int stride) { Values = values; Stride = stride; } +}; + +static float Plot_ArrayGetter(void* data, int idx) +{ + ImGuiPlotArrayGetterData* plot_data = (ImGuiPlotArrayGetterData*)data; + const float v = *(const float*)(const void*)((const unsigned char*)plot_data->Values + (size_t)idx * plot_data->Stride); + return v; +} + +void ImGui::PlotLines(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride) +{ + ImGuiPlotArrayGetterData data(values, stride); + PlotEx(ImGuiPlotType_Lines, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); +} + +void ImGui::PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size) +{ + PlotEx(ImGuiPlotType_Lines, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); +} + +void ImGui::PlotHistogram(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride) +{ + ImGuiPlotArrayGetterData data(values, stride); + PlotEx(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); +} + +void ImGui::PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size) +{ + PlotEx(ImGuiPlotType_Histogram, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); +} + +// size_arg (for each axis) < 0.0f: align to end, 0.0f: auto, > 0.0f: specified size +void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* overlay) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + + ImVec2 pos = window->DC.CursorPos; + ImRect bb(pos, pos + CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y*2.0f)); + ItemSize(bb, style.FramePadding.y); + if (!ItemAdd(bb, 0)) + return; + + // Render + fraction = ImSaturate(fraction); + RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); + bb.Expand(ImVec2(-style.FrameBorderSize, -style.FrameBorderSize)); + const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y); + RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), 0.0f, fraction, style.FrameRounding); + + // Default displaying the fraction as percentage string, but user can override it + char overlay_buf[32]; + if (!overlay) + { + ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%.0f%%", fraction*100+0.01f); + overlay = overlay_buf; + } + + ImVec2 overlay_size = CalcTextSize(overlay, NULL); + if (overlay_size.x > 0.0f) + RenderTextClipped(ImVec2(ImClamp(fill_br.x + style.ItemSpacing.x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), bb.Min.y), bb.Max, overlay, NULL, &overlay_size, ImVec2(0.0f,0.5f), &bb); +} + +bool ImGui::Checkbox(const char* label, bool* v) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + const ImGuiID id = window->GetID(label); + const ImVec2 label_size = CalcTextSize(label, NULL, true); + + const ImRect check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y*2, label_size.y + style.FramePadding.y*2)); // We want a square shape to we use Y twice + ItemSize(check_bb, style.FramePadding.y); + + ImRect total_bb = check_bb; + if (label_size.x > 0) + SameLine(0, style.ItemInnerSpacing.x); + const ImRect text_bb(window->DC.CursorPos + ImVec2(0,style.FramePadding.y), window->DC.CursorPos + ImVec2(0,style.FramePadding.y) + label_size); + if (label_size.x > 0) + { + ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()), style.FramePadding.y); + total_bb = ImRect(ImMin(check_bb.Min, text_bb.Min), ImMax(check_bb.Max, text_bb.Max)); + } + + if (!ItemAdd(total_bb, id)) + return false; + + bool hovered, held; + bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); + if (pressed) + { + *v = !(*v); + MarkItemValueChanged(id); + } + + RenderNavHighlight(total_bb, id); + RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); + if (*v) + { + const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight()); + const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f)); + RenderCheckMark(check_bb.Min + ImVec2(pad,pad), GetColorU32(ImGuiCol_CheckMark), check_bb.GetWidth() - pad*2.0f); + } + + if (g.LogEnabled) + LogRenderedText(&text_bb.Min, *v ? "[x]" : "[ ]"); + if (label_size.x > 0.0f) + RenderText(text_bb.Min, label); + + return pressed; +} + +bool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value) +{ + bool v = ((*flags & flags_value) == flags_value); + bool pressed = Checkbox(label, &v); + if (pressed) + { + if (v) + *flags |= flags_value; + else + *flags &= ~flags_value; + } + + return pressed; +} + +bool ImGui::RadioButton(const char* label, bool active) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + const ImGuiID id = window->GetID(label); + const ImVec2 label_size = CalcTextSize(label, NULL, true); + + const ImRect check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y*2-1, label_size.y + style.FramePadding.y*2-1)); + ItemSize(check_bb, style.FramePadding.y); + + ImRect total_bb = check_bb; + if (label_size.x > 0) + SameLine(0, style.ItemInnerSpacing.x); + const ImRect text_bb(window->DC.CursorPos + ImVec2(0, style.FramePadding.y), window->DC.CursorPos + ImVec2(0, style.FramePadding.y) + label_size); + if (label_size.x > 0) + { + ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()), style.FramePadding.y); + total_bb.Add(text_bb); + } + + if (!ItemAdd(total_bb, id)) + return false; + + ImVec2 center = check_bb.GetCenter(); + center.x = (float)(int)center.x + 0.5f; + center.y = (float)(int)center.y + 0.5f; + const float radius = check_bb.GetHeight() * 0.5f; + + bool hovered, held; + bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); + if (pressed) + MarkItemValueChanged(id); + + RenderNavHighlight(total_bb, id); + window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16); + if (active) + { + const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight()); + const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f)); + window->DrawList->AddCircleFilled(center, radius-pad, GetColorU32(ImGuiCol_CheckMark), 16); + } + + if (style.FrameBorderSize > 0.0f) + { + window->DrawList->AddCircle(center+ImVec2(1,1), radius, GetColorU32(ImGuiCol_BorderShadow), 16, style.FrameBorderSize); + window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), 16, style.FrameBorderSize); + } + + if (g.LogEnabled) + LogRenderedText(&text_bb.Min, active ? "(x)" : "( )"); + if (label_size.x > 0.0f) + RenderText(text_bb.Min, label); + + return pressed; +} + +bool ImGui::RadioButton(const char* label, int* v, int v_button) +{ + const bool pressed = RadioButton(label, *v == v_button); + if (pressed) + *v = v_button; + return pressed; +} + +static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end) +{ + int line_count = 0; + const char* s = text_begin; + while (char c = *s++) // We are only matching for \n so we can ignore UTF-8 decoding + if (c == '\n') + line_count++; + s--; + if (s[0] != '\n' && s[0] != '\r') + line_count++; + *out_text_end = s; + return line_count; +} + +static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining, ImVec2* out_offset, bool stop_on_new_line) +{ + ImFont* font = GImGui->Font; + const float line_height = GImGui->FontSize; + const float scale = line_height / font->FontSize; + + ImVec2 text_size = ImVec2(0,0); + float line_width = 0.0f; + + const ImWchar* s = text_begin; + while (s < text_end) + { + unsigned int c = (unsigned int)(*s++); + if (c == '\n') + { + text_size.x = ImMax(text_size.x, line_width); + text_size.y += line_height; + line_width = 0.0f; + if (stop_on_new_line) + break; + continue; + } + if (c == '\r') + continue; + + const float char_width = font->GetCharAdvance((unsigned short)c) * scale; + line_width += char_width; + } + + if (text_size.x < line_width) + text_size.x = line_width; + + if (out_offset) + *out_offset = ImVec2(line_width, text_size.y + line_height); // offset allow for the possibility of sitting after a trailing \n + + if (line_width > 0 || text_size.y == 0.0f) // whereas size.y will ignore the trailing \n + text_size.y += line_height; + + if (remaining) + *remaining = s; + + return text_size; +} + +// Wrapper for stb_textedit.h to edit text (our wrapper is for: statically sized buffer, single-line, wchar characters. InputText converts between UTF-8 and wchar) +namespace ImGuiStb +{ + +static int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING* obj) { return obj->CurLenW; } +static ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING* obj, int idx) { return obj->Text[idx]; } +static float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING* obj, int line_start_idx, int char_idx) { ImWchar c = obj->Text[line_start_idx+char_idx]; if (c == '\n') return STB_TEXTEDIT_GETWIDTH_NEWLINE; return GImGui->Font->GetCharAdvance(c) * (GImGui->FontSize / GImGui->Font->FontSize); } +static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x10000 ? 0 : key; } +static ImWchar STB_TEXTEDIT_NEWLINE = '\n'; +static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* obj, int line_start_idx) +{ + const ImWchar* text = obj->Text.Data; + const ImWchar* text_remaining = NULL; + const ImVec2 size = InputTextCalcTextSizeW(text + line_start_idx, text + obj->CurLenW, &text_remaining, NULL, true); + r->x0 = 0.0f; + r->x1 = size.x; + r->baseline_y_delta = size.y; + r->ymin = 0.0f; + r->ymax = size.y; + r->num_chars = (int)(text_remaining - (text + line_start_idx)); +} + +static bool is_separator(unsigned int c) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; } +static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator( obj->Text[idx-1] ) && !is_separator( obj->Text[idx] ) ) : 1; } +static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; } +#ifdef __APPLE__ // FIXME: Move setting to IO structure +static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; } +static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; } +#else +static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; } +#endif +#define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h +#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_IMPL + +static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n) +{ + ImWchar* dst = obj->Text.Data + pos; + + // We maintain our buffer length in both UTF-8 and wchar formats + obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n); + obj->CurLenW -= n; + + // Offset remaining text + const ImWchar* src = obj->Text.Data + pos + n; + while (ImWchar c = *src++) + *dst++ = c; + *dst = '\0'; +} + +static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const ImWchar* new_text, int new_text_len) +{ + const int text_len = obj->CurLenW; + IM_ASSERT(pos <= text_len); + if (new_text_len + text_len + 1 > obj->Text.Size) + return false; + + const int new_text_len_utf8 = ImTextCountUtf8BytesFromStr(new_text, new_text + new_text_len); + if (new_text_len_utf8 + obj->CurLenA + 1 > obj->BufSizeA) + return false; + + ImWchar* text = obj->Text.Data; + if (pos != text_len) + memmove(text + pos + new_text_len, text + pos, (size_t)(text_len - pos) * sizeof(ImWchar)); + memcpy(text + pos, new_text, (size_t)new_text_len * sizeof(ImWchar)); + + obj->CurLenW += new_text_len; + obj->CurLenA += new_text_len_utf8; + obj->Text[obj->CurLenW] = '\0'; + + return true; +} + +// We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols) +#define STB_TEXTEDIT_K_LEFT 0x10000 // keyboard input to move cursor left +#define STB_TEXTEDIT_K_RIGHT 0x10001 // keyboard input to move cursor right +#define STB_TEXTEDIT_K_UP 0x10002 // keyboard input to move cursor up +#define STB_TEXTEDIT_K_DOWN 0x10003 // keyboard input to move cursor down +#define STB_TEXTEDIT_K_LINESTART 0x10004 // keyboard input to move cursor to start of line +#define STB_TEXTEDIT_K_LINEEND 0x10005 // keyboard input to move cursor to end of line +#define STB_TEXTEDIT_K_TEXTSTART 0x10006 // keyboard input to move cursor to start of text +#define STB_TEXTEDIT_K_TEXTEND 0x10007 // keyboard input to move cursor to end of text +#define STB_TEXTEDIT_K_DELETE 0x10008 // keyboard input to delete selection or character under cursor +#define STB_TEXTEDIT_K_BACKSPACE 0x10009 // keyboard input to delete selection or character left of cursor +#define STB_TEXTEDIT_K_UNDO 0x1000A // keyboard input to perform undo +#define STB_TEXTEDIT_K_REDO 0x1000B // keyboard input to perform redo +#define STB_TEXTEDIT_K_WORDLEFT 0x1000C // keyboard input to move cursor left one word +#define STB_TEXTEDIT_K_WORDRIGHT 0x1000D // keyboard input to move cursor right one word +#define STB_TEXTEDIT_K_SHIFT 0x20000 + +#define STB_TEXTEDIT_IMPLEMENTATION +#include "stb_textedit.h" + +} + +void ImGuiTextEditState::OnKeyPressed(int key) +{ + stb_textedit_key(this, &StbState, key); + CursorFollow = true; + CursorAnimReset(); +} + +// Public API to manipulate UTF-8 text +// We expose UTF-8 to the user (unlike the STB_TEXTEDIT_* functions which are manipulating wchar) +// FIXME: The existence of this rarely exercised code path is a bit of a nuisance. +void ImGuiTextEditCallbackData::DeleteChars(int pos, int bytes_count) +{ + IM_ASSERT(pos + bytes_count <= BufTextLen); + char* dst = Buf + pos; + const char* src = Buf + pos + bytes_count; + while (char c = *src++) + *dst++ = c; + *dst = '\0'; + + if (CursorPos + bytes_count >= pos) + CursorPos -= bytes_count; + else if (CursorPos >= pos) + CursorPos = pos; + SelectionStart = SelectionEnd = CursorPos; + BufDirty = true; + BufTextLen -= bytes_count; +} + +void ImGuiTextEditCallbackData::InsertChars(int pos, const char* new_text, const char* new_text_end) +{ + const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)strlen(new_text); + if (new_text_len + BufTextLen + 1 >= BufSize) + return; + + if (BufTextLen != pos) + memmove(Buf + pos + new_text_len, Buf + pos, (size_t)(BufTextLen - pos)); + memcpy(Buf + pos, new_text, (size_t)new_text_len * sizeof(char)); + Buf[BufTextLen + new_text_len] = '\0'; + + if (CursorPos >= pos) + CursorPos += new_text_len; + SelectionStart = SelectionEnd = CursorPos; + BufDirty = true; + BufTextLen += new_text_len; +} + +// Return false to discard a character. +static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data) +{ + unsigned int c = *p_char; + + if (c < 128 && c != ' ' && !isprint((int)(c & 0xFF))) + { + bool pass = false; + pass |= (c == '\n' && (flags & ImGuiInputTextFlags_Multiline)); + pass |= (c == '\t' && (flags & ImGuiInputTextFlags_AllowTabInput)); + if (!pass) + return false; + } + + if (c >= 0xE000 && c <= 0xF8FF) // Filter private Unicode range. I don't imagine anybody would want to input them. GLFW on OSX seems to send private characters for special keys like arrow keys. + return false; + + if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific)) + { + if (flags & ImGuiInputTextFlags_CharsDecimal) + if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/')) + return false; + + if (flags & ImGuiInputTextFlags_CharsScientific) + if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/') && (c != 'e') && (c != 'E')) + return false; + + if (flags & ImGuiInputTextFlags_CharsHexadecimal) + if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F')) + return false; + + if (flags & ImGuiInputTextFlags_CharsUppercase) + if (c >= 'a' && c <= 'z') + *p_char = (c += (unsigned int)('A'-'a')); + + if (flags & ImGuiInputTextFlags_CharsNoBlank) + if (ImCharIsBlankW(c)) + return false; + } + + if (flags & ImGuiInputTextFlags_CallbackCharFilter) + { + ImGuiTextEditCallbackData callback_data; + memset(&callback_data, 0, sizeof(ImGuiTextEditCallbackData)); + callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter; + callback_data.EventChar = (ImWchar)c; + callback_data.Flags = flags; + callback_data.UserData = user_data; + if (callback(&callback_data) != 0) + return false; + *p_char = callback_data.EventChar; + if (!callback_data.EventChar) + return false; + } + + return true; +} + +// Edit a string of text +// NB: when active, hold on a privately held copy of the text (and apply back to 'buf'). So changing 'buf' while active has no effect. +// FIXME: Rather messy function partly because we are doing UTF8 > u16 > UTF8 conversions on the go to more easily handle stb_textedit calls. Ideally we should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188 +bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackHistory) && (flags & ImGuiInputTextFlags_Multiline))); // Can't use both together (they both use up/down keys) + IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackCompletion) && (flags & ImGuiInputTextFlags_AllowTabInput))); // Can't use both together (they both use tab key) + + ImGuiContext& g = *GImGui; + const ImGuiIO& io = g.IO; + const ImGuiStyle& style = g.Style; + + const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0; + const bool is_editable = (flags & ImGuiInputTextFlags_ReadOnly) == 0; + const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0; + const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0; + + if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope, + BeginGroup(); + const ImGuiID id = window->GetID(label); + const ImVec2 label_size = CalcTextSize(label, NULL, true); + ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? GetTextLineHeight() * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line + const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size); + const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f)); + + ImGuiWindow* draw_window = window; + if (is_multiline) + { + ItemAdd(total_bb, id, &frame_bb); + if (!BeginChildFrame(id, frame_bb.GetSize())) + { + EndChildFrame(); + EndGroup(); + return false; + } + draw_window = GetCurrentWindow(); + draw_window->DC.NavLayerActiveMaskNext |= draw_window->DC.NavLayerCurrentMask; // This is to ensure that EndChild() will display a navigation highlight + size.x -= draw_window->ScrollbarSizes.x; + } + else + { + ItemSize(total_bb, style.FramePadding.y); + if (!ItemAdd(total_bb, id, &frame_bb)) + return false; + } + const bool hovered = ItemHoverable(frame_bb, id); + if (hovered) + g.MouseCursor = ImGuiMouseCursor_TextInput; + + // Password pushes a temporary font with only a fallback glyph + if (is_password) + { + const ImFontGlyph* glyph = g.Font->FindGlyph('*'); + ImFont* password_font = &g.InputTextPasswordFont; + password_font->FontSize = g.Font->FontSize; + password_font->Scale = g.Font->Scale; + password_font->DisplayOffset = g.Font->DisplayOffset; + password_font->Ascent = g.Font->Ascent; + password_font->Descent = g.Font->Descent; + password_font->ContainerAtlas = g.Font->ContainerAtlas; + password_font->FallbackGlyph = glyph; + password_font->FallbackAdvanceX = glyph->AdvanceX; + IM_ASSERT(password_font->Glyphs.empty() && password_font->IndexAdvanceX.empty() && password_font->IndexLookup.empty()); + PushFont(password_font); + } + + // NB: we are only allowed to access 'edit_state' if we are the active widget. + ImGuiTextEditState& edit_state = g.InputTextState; + + const bool focus_requested = FocusableItemRegister(window, id, (flags & (ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_AllowTabInput)) == 0); // Using completion callback disable keyboard tabbing + const bool focus_requested_by_code = focus_requested && (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent); + const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code; + + const bool user_clicked = hovered && io.MouseClicked[0]; + const bool user_scrolled = is_multiline && g.ActiveId == 0 && edit_state.Id == id && g.ActiveIdPreviousFrame == draw_window->GetIDNoKeepAlive("#SCROLLY"); + const bool user_nav_input_start = (g.ActiveId != id) && ((g.NavInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_NavKeyboard)); + + bool clear_active_id = false; + + bool select_all = (g.ActiveId != id) && ((flags & ImGuiInputTextFlags_AutoSelectAll) != 0 || user_nav_input_start) && (!is_multiline); + if (focus_requested || user_clicked || user_scrolled || user_nav_input_start) + { + if (g.ActiveId != id) + { + // Start edition + // Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar) + // From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode) + const int prev_len_w = edit_state.CurLenW; + edit_state.Text.resize(buf_size+1); // wchar count <= UTF-8 count. we use +1 to make sure that .Data isn't NULL so it doesn't crash. + edit_state.InitialText.resize(buf_size+1); // UTF-8. we use +1 to make sure that .Data isn't NULL so it doesn't crash. + ImStrncpy(edit_state.InitialText.Data, buf, edit_state.InitialText.Size); + const char* buf_end = NULL; + edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end); + edit_state.CurLenA = (int)(buf_end - buf); // We can't get the result from ImFormatString() above because it is not UTF-8 aware. Here we'll cut off malformed UTF-8. + edit_state.CursorAnimReset(); + + // Preserve cursor position and undo/redo stack if we come back to same widget + // FIXME: We should probably compare the whole buffer to be on the safety side. Comparing buf (utf8) and edit_state.Text (wchar). + const bool recycle_state = (edit_state.Id == id) && (prev_len_w == edit_state.CurLenW); + if (recycle_state) + { + // Recycle existing cursor/selection/undo stack but clamp position + // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler. + edit_state.CursorClamp(); + } + else + { + edit_state.Id = id; + edit_state.ScrollX = 0.0f; + stb_textedit_initialize_state(&edit_state.StbState, !is_multiline); + if (!is_multiline && focus_requested_by_code) + select_all = true; + } + if (flags & ImGuiInputTextFlags_AlwaysInsertMode) + edit_state.StbState.insert_mode = true; + if (!is_multiline && (focus_requested_by_tab || (user_clicked && io.KeyCtrl))) + select_all = true; + } + SetActiveID(id, window); + SetFocusID(id, window); + FocusWindow(window); + if (!is_multiline && !(flags & ImGuiInputTextFlags_CallbackHistory)) + g.ActiveIdAllowNavDirFlags |= ((1 << ImGuiDir_Up) | (1 << ImGuiDir_Down)); + } + else if (io.MouseClicked[0]) + { + // Release focus when we click outside + clear_active_id = true; + } + + bool value_changed = false; + bool enter_pressed = false; + + if (g.ActiveId == id) + { + if (!is_editable && !g.ActiveIdIsJustActivated) + { + // When read-only we always use the live data passed to the function + edit_state.Text.resize(buf_size+1); + const char* buf_end = NULL; + edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end); + edit_state.CurLenA = (int)(buf_end - buf); + edit_state.CursorClamp(); + } + + edit_state.BufSizeA = buf_size; + + // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget. + // Down the line we should have a cleaner library-wide concept of Selected vs Active. + g.ActiveIdAllowOverlap = !io.MouseDown[0]; + g.WantTextInputNextFrame = 1; + + // Edit in progress + const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX; + const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y - style.FramePadding.y) : (g.FontSize*0.5f)); + + const bool is_osx = io.ConfigMacOSXBehaviors; + if (select_all || (hovered && !is_osx && io.MouseDoubleClicked[0])) + { + edit_state.SelectAll(); + edit_state.SelectedAllMouseLock = true; + } + else if (hovered && is_osx && io.MouseDoubleClicked[0]) + { + // Double-click select a word only, OS X style (by simulating keystrokes) + edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT); + edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT); + } + else if (io.MouseClicked[0] && !edit_state.SelectedAllMouseLock) + { + if (hovered) + { + stb_textedit_click(&edit_state, &edit_state.StbState, mouse_x, mouse_y); + edit_state.CursorAnimReset(); + } + } + else if (io.MouseDown[0] && !edit_state.SelectedAllMouseLock && (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)) + { + stb_textedit_drag(&edit_state, &edit_state.StbState, mouse_x, mouse_y); + edit_state.CursorAnimReset(); + edit_state.CursorFollow = true; + } + if (edit_state.SelectedAllMouseLock && !io.MouseDown[0]) + edit_state.SelectedAllMouseLock = false; + + if (io.InputCharacters[0]) + { + // Process text input (before we check for Return because using some IME will effectively send a Return?) + // We ignore CTRL inputs, but need to allow ALT+CTRL as some keyboards (e.g. German) use AltGR (which _is_ Alt+Ctrl) to input certain characters. + bool ignore_inputs = (io.KeyCtrl && !io.KeyAlt) || (is_osx && io.KeySuper); + if (!ignore_inputs && is_editable && !user_nav_input_start) + for (int n = 0; n < IM_ARRAYSIZE(io.InputCharacters) && io.InputCharacters[n]; n++) + { + // Insert character if they pass filtering + unsigned int c = (unsigned int)io.InputCharacters[n]; + if (InputTextFilterCharacter(&c, flags, callback, user_data)) + edit_state.OnKeyPressed((int)c); + } + + // Consume characters + memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters)); + } + } + + bool cancel_edit = false; + if (g.ActiveId == id && !g.ActiveIdIsJustActivated && !clear_active_id) + { + // Handle key-presses + const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0); + const bool is_osx = io.ConfigMacOSXBehaviors; + const bool is_shortcut_key = (is_osx ? (io.KeySuper && !io.KeyCtrl) : (io.KeyCtrl && !io.KeySuper)) && !io.KeyAlt && !io.KeyShift; // OS X style: Shortcuts using Cmd/Super instead of Ctrl + const bool is_osx_shift_shortcut = is_osx && io.KeySuper && io.KeyShift && !io.KeyCtrl && !io.KeyAlt; + const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl + const bool is_startend_key_down = is_osx && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End + const bool is_ctrl_key_only = io.KeyCtrl && !io.KeyShift && !io.KeyAlt && !io.KeySuper; + const bool is_shift_key_only = io.KeyShift && !io.KeyCtrl && !io.KeyAlt && !io.KeySuper; + + const bool is_cut = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_X)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Delete))) && is_editable && !is_password && (!is_multiline || edit_state.HasSelection()); + const bool is_copy = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_C)) || (is_ctrl_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && !is_password && (!is_multiline || edit_state.HasSelection()); + const bool is_paste = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_V)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && is_editable; + const bool is_undo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Z)) && is_editable && is_undoable); + const bool is_redo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Y)) || (is_osx_shift_shortcut && IsKeyPressedMap(ImGuiKey_Z))) && is_editable && is_undoable; + + if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); } + else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); } + else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetWindowScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); } + else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetWindowScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); } + else if (IsKeyPressedMap(ImGuiKey_Home)) { edit_state.OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); } + else if (IsKeyPressedMap(ImGuiKey_End)) { edit_state.OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); } + else if (IsKeyPressedMap(ImGuiKey_Delete) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); } + else if (IsKeyPressedMap(ImGuiKey_Backspace) && is_editable) + { + if (!edit_state.HasSelection()) + { + if (is_wordmove_key_down) edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT|STB_TEXTEDIT_K_SHIFT); + else if (is_osx && io.KeySuper && !io.KeyAlt && !io.KeyCtrl) edit_state.OnKeyPressed(STB_TEXTEDIT_K_LINESTART|STB_TEXTEDIT_K_SHIFT); + } + edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); + } + else if (IsKeyPressedMap(ImGuiKey_Enter)) + { + bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0; + if (!is_multiline || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl)) + { + enter_pressed = clear_active_id = true; + } + else if (is_editable) + { + unsigned int c = '\n'; // Insert new line + if (InputTextFilterCharacter(&c, flags, callback, user_data)) + edit_state.OnKeyPressed((int)c); + } + } + else if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressedMap(ImGuiKey_Tab) && !io.KeyCtrl && !io.KeyShift && !io.KeyAlt && is_editable) + { + unsigned int c = '\t'; // Insert TAB + if (InputTextFilterCharacter(&c, flags, callback, user_data)) + edit_state.OnKeyPressed((int)c); + } + else if (IsKeyPressedMap(ImGuiKey_Escape)) + { + clear_active_id = cancel_edit = true; + } + else if (is_undo || is_redo) + { + edit_state.OnKeyPressed(is_undo ? STB_TEXTEDIT_K_UNDO : STB_TEXTEDIT_K_REDO); + edit_state.ClearSelection(); + } + else if (is_shortcut_key && IsKeyPressedMap(ImGuiKey_A)) + { + edit_state.SelectAll(); + edit_state.CursorFollow = true; + } + else if (is_cut || is_copy) + { + // Cut, Copy + if (io.SetClipboardTextFn) + { + const int ib = edit_state.HasSelection() ? ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end) : 0; + const int ie = edit_state.HasSelection() ? ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end) : edit_state.CurLenW; + edit_state.TempTextBuffer.resize((ie-ib) * 4 + 1); + ImTextStrToUtf8(edit_state.TempTextBuffer.Data, edit_state.TempTextBuffer.Size, edit_state.Text.Data+ib, edit_state.Text.Data+ie); + SetClipboardText(edit_state.TempTextBuffer.Data); + } + if (is_cut) + { + if (!edit_state.HasSelection()) + edit_state.SelectAll(); + edit_state.CursorFollow = true; + stb_textedit_cut(&edit_state, &edit_state.StbState); + } + } + else if (is_paste) + { + if (const char* clipboard = GetClipboardText()) + { + // Filter pasted buffer + const int clipboard_len = (int)strlen(clipboard); + ImWchar* clipboard_filtered = (ImWchar*)ImGui::MemAlloc((clipboard_len+1) * sizeof(ImWchar)); + int clipboard_filtered_len = 0; + for (const char* s = clipboard; *s; ) + { + unsigned int c; + s += ImTextCharFromUtf8(&c, s, NULL); + if (c == 0) + break; + if (c >= 0x10000 || !InputTextFilterCharacter(&c, flags, callback, user_data)) + continue; + clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c; + } + clipboard_filtered[clipboard_filtered_len] = 0; + if (clipboard_filtered_len > 0) // If everything was filtered, ignore the pasting operation + { + stb_textedit_paste(&edit_state, &edit_state.StbState, clipboard_filtered, clipboard_filtered_len); + edit_state.CursorFollow = true; + } + ImGui::MemFree(clipboard_filtered); + } + } + } + + if (g.ActiveId == id) + { + if (cancel_edit) + { + // Restore initial value. Only return true if restoring to the initial value changes the current buffer contents. + if (is_editable && strncmp(buf, edit_state.InitialText.Data, buf_size) != 0) + { + ImStrncpy(buf, edit_state.InitialText.Data, buf_size); + value_changed = true; + } + } + + // When using 'ImGuiInputTextFlags_EnterReturnsTrue' as a special case we reapply the live buffer back to the input buffer before clearing ActiveId, even though strictly speaking it wasn't modified on this frame. + // If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail. Also this allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage. + bool apply_edit_back_to_user_buffer = !cancel_edit || (enter_pressed && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0); + if (apply_edit_back_to_user_buffer) + { + // Apply new value immediately - copy modified buffer back + // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer + // FIXME: We actually always render 'buf' when calling DrawList->AddText, making the comment above incorrect. + // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks. + if (is_editable) + { + edit_state.TempTextBuffer.resize(edit_state.Text.Size * 4); + ImTextStrToUtf8(edit_state.TempTextBuffer.Data, edit_state.TempTextBuffer.Size, edit_state.Text.Data, NULL); + } + + // User callback + if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackAlways)) != 0) + { + IM_ASSERT(callback != NULL); + + // The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard TABBING at the moment. + ImGuiInputTextFlags event_flag = 0; + ImGuiKey event_key = ImGuiKey_COUNT; + if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && IsKeyPressedMap(ImGuiKey_Tab)) + { + event_flag = ImGuiInputTextFlags_CallbackCompletion; + event_key = ImGuiKey_Tab; + } + else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_UpArrow)) + { + event_flag = ImGuiInputTextFlags_CallbackHistory; + event_key = ImGuiKey_UpArrow; + } + else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_DownArrow)) + { + event_flag = ImGuiInputTextFlags_CallbackHistory; + event_key = ImGuiKey_DownArrow; + } + else if (flags & ImGuiInputTextFlags_CallbackAlways) + event_flag = ImGuiInputTextFlags_CallbackAlways; + + if (event_flag) + { + ImGuiTextEditCallbackData callback_data; + memset(&callback_data, 0, sizeof(ImGuiTextEditCallbackData)); + callback_data.EventFlag = event_flag; + callback_data.Flags = flags; + callback_data.UserData = user_data; + callback_data.ReadOnly = !is_editable; + + callback_data.EventKey = event_key; + callback_data.Buf = edit_state.TempTextBuffer.Data; + callback_data.BufTextLen = edit_state.CurLenA; + callback_data.BufSize = edit_state.BufSizeA; + callback_data.BufDirty = false; + + // We have to convert from wchar-positions to UTF-8-positions, which can be pretty slow (an incentive to ditch the ImWchar buffer, see https://github.com/nothings/stb/issues/188) + ImWchar* text = edit_state.Text.Data; + const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.cursor); + const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.select_start); + const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.select_end); + + // Call user code + callback(&callback_data); + + // Read back what user may have modified + IM_ASSERT(callback_data.Buf == edit_state.TempTextBuffer.Data); // Invalid to modify those fields + IM_ASSERT(callback_data.BufSize == edit_state.BufSizeA); + IM_ASSERT(callback_data.Flags == flags); + if (callback_data.CursorPos != utf8_cursor_pos) edit_state.StbState.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); + if (callback_data.SelectionStart != utf8_selection_start) edit_state.StbState.select_start = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); + if (callback_data.SelectionEnd != utf8_selection_end) edit_state.StbState.select_end = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); + if (callback_data.BufDirty) + { + IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text! + edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, callback_data.Buf, NULL); + edit_state.CurLenA = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen() + edit_state.CursorAnimReset(); + } + } + } + + // Copy back to user buffer + if (is_editable && strcmp(edit_state.TempTextBuffer.Data, buf) != 0) + { + ImStrncpy(buf, edit_state.TempTextBuffer.Data, buf_size); + value_changed = true; + } + } + } + + // Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value) + if (clear_active_id && g.ActiveId == id) + ClearActiveID(); + + // Render + // Select which buffer we are going to display. When ImGuiInputTextFlags_NoLiveEdit is set 'buf' might still be the old value. We set buf to NULL to prevent accidental usage from now on. + const char* buf_display = (g.ActiveId == id && is_editable) ? edit_state.TempTextBuffer.Data : buf; buf = NULL; + + if (!is_multiline) + { + RenderNavHighlight(frame_bb, id); + RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); + } + + const ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + size.x, frame_bb.Min.y + size.y); // Not using frame_bb.Max because we have adjusted size + ImVec2 render_pos = is_multiline ? draw_window->DC.CursorPos : frame_bb.Min + style.FramePadding; + ImVec2 text_size(0.f, 0.f); + const bool is_currently_scrolling = (edit_state.Id == id && is_multiline && g.ActiveId == draw_window->GetIDNoKeepAlive("#SCROLLY")); + if (g.ActiveId == id || is_currently_scrolling) + { + edit_state.CursorAnim += io.DeltaTime; + + // This is going to be messy. We need to: + // - Display the text (this alone can be more easily clipped) + // - Handle scrolling, highlight selection, display cursor (those all requires some form of 1d->2d cursor position calculation) + // - Measure text height (for scrollbar) + // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort) + // FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8. + const ImWchar* text_begin = edit_state.Text.Data; + ImVec2 cursor_offset, select_start_offset; + + { + // Count lines + find lines numbers straddling 'cursor' and 'select_start' position. + const ImWchar* searches_input_ptr[2]; + searches_input_ptr[0] = text_begin + edit_state.StbState.cursor; + searches_input_ptr[1] = NULL; + int searches_remaining = 1; + int searches_result_line_number[2] = { -1, -999 }; + if (edit_state.StbState.select_start != edit_state.StbState.select_end) + { + searches_input_ptr[1] = text_begin + ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end); + searches_result_line_number[1] = -1; + searches_remaining++; + } + + // Iterate all lines to find our line numbers + // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter. + searches_remaining += is_multiline ? 1 : 0; + int line_count = 0; + for (const ImWchar* s = text_begin; *s != 0; s++) + if (*s == '\n') + { + line_count++; + if (searches_result_line_number[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_number[0] = line_count; if (--searches_remaining <= 0) break; } + if (searches_result_line_number[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_number[1] = line_count; if (--searches_remaining <= 0) break; } + } + line_count++; + if (searches_result_line_number[0] == -1) searches_result_line_number[0] = line_count; + if (searches_result_line_number[1] == -1) searches_result_line_number[1] = line_count; + + // Calculate 2d position by finding the beginning of the line and measuring distance + cursor_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x; + cursor_offset.y = searches_result_line_number[0] * g.FontSize; + if (searches_result_line_number[1] >= 0) + { + select_start_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x; + select_start_offset.y = searches_result_line_number[1] * g.FontSize; + } + + // Store text height (note that we haven't calculated text width at all, see GitHub issues #383, #1224) + if (is_multiline) + text_size = ImVec2(size.x, line_count * g.FontSize); + } + + // Scroll + if (edit_state.CursorFollow) + { + // Horizontal scroll in chunks of quarter width + if (!(flags & ImGuiInputTextFlags_NoHorizontalScroll)) + { + const float scroll_increment_x = size.x * 0.25f; + if (cursor_offset.x < edit_state.ScrollX) + edit_state.ScrollX = (float)(int)ImMax(0.0f, cursor_offset.x - scroll_increment_x); + else if (cursor_offset.x - size.x >= edit_state.ScrollX) + edit_state.ScrollX = (float)(int)(cursor_offset.x - size.x + scroll_increment_x); + } + else + { + edit_state.ScrollX = 0.0f; + } + + // Vertical scroll + if (is_multiline) + { + float scroll_y = draw_window->Scroll.y; + if (cursor_offset.y - g.FontSize < scroll_y) + scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize); + else if (cursor_offset.y - size.y >= scroll_y) + scroll_y = cursor_offset.y - size.y; + draw_window->DC.CursorPos.y += (draw_window->Scroll.y - scroll_y); // To avoid a frame of lag + draw_window->Scroll.y = scroll_y; + render_pos.y = draw_window->DC.CursorPos.y; + } + } + edit_state.CursorFollow = false; + const ImVec2 render_scroll = ImVec2(edit_state.ScrollX, 0.0f); + + // Draw selection + if (edit_state.StbState.select_start != edit_state.StbState.select_end) + { + const ImWchar* text_selected_begin = text_begin + ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end); + const ImWchar* text_selected_end = text_begin + ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end); + + float bg_offy_up = is_multiline ? 0.0f : -1.0f; // FIXME: those offsets should be part of the style? they don't play so well with multi-line selection. + float bg_offy_dn = is_multiline ? 0.0f : 2.0f; + ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg); + ImVec2 rect_pos = render_pos + select_start_offset - render_scroll; + for (const ImWchar* p = text_selected_begin; p < text_selected_end; ) + { + if (rect_pos.y > clip_rect.w + g.FontSize) + break; + if (rect_pos.y < clip_rect.y) + { + while (p < text_selected_end) + if (*p++ == '\n') + break; + } + else + { + ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true); + if (rect_size.x <= 0.0f) rect_size.x = (float)(int)(g.Font->GetCharAdvance((unsigned short)' ') * 0.50f); // So we can see selected empty lines + ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos +ImVec2(rect_size.x, bg_offy_dn)); + rect.ClipWith(clip_rect); + if (rect.Overlaps(clip_rect)) + draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color); + } + rect_pos.x = render_pos.x - render_scroll.x; + rect_pos.y += g.FontSize; + } + } + + draw_window->DrawList->AddText(g.Font, g.FontSize, render_pos - render_scroll, GetColorU32(ImGuiCol_Text), buf_display, buf_display + edit_state.CurLenA, 0.0f, is_multiline ? NULL : &clip_rect); + + // Draw blinking cursor + bool cursor_is_visible = (!g.IO.ConfigCursorBlink) || (g.InputTextState.CursorAnim <= 0.0f) || ImFmod(g.InputTextState.CursorAnim, 1.20f) <= 0.80f; + ImVec2 cursor_screen_pos = render_pos + cursor_offset - render_scroll; + ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y-g.FontSize+0.5f, cursor_screen_pos.x+1.0f, cursor_screen_pos.y-1.5f); + if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect)) + draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text)); + + // Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.) + if (is_editable) + g.PlatformImePos = ImVec2(cursor_screen_pos.x - 1, cursor_screen_pos.y - g.FontSize); + } + else + { + // Render text only + const char* buf_end = NULL; + if (is_multiline) + text_size = ImVec2(size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_end) * g.FontSize); // We don't need width + draw_window->DrawList->AddText(g.Font, g.FontSize, render_pos, GetColorU32(ImGuiCol_Text), buf_display, buf_end, 0.0f, is_multiline ? NULL : &clip_rect); + } + + if (is_multiline) + { + Dummy(text_size + ImVec2(0.0f, g.FontSize)); // Always add room to scroll an extra line + EndChildFrame(); + EndGroup(); + } + + if (is_password) + PopFont(); + + // Log as text + if (g.LogEnabled && !is_password) + LogRenderedText(&render_pos, buf_display, NULL); + + if (label_size.x > 0) + RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); + + if (value_changed) + MarkItemValueChanged(id); + + if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0) + return enter_pressed; + else + return value_changed; +} + +bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data) +{ + IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline() + return InputTextEx(label, buf, (int)buf_size, ImVec2(0,0), flags, callback, user_data); +} + +bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data) +{ + return InputTextEx(label, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data); +} + +// NB: format here must be a simple "%xx" format string with no prefix/suffix (unlike the Drag/Slider functions "format" argument) +bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_ptr, const void* step, const void* step_fast, const char* format, ImGuiInputTextFlags extra_flags) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + + IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT); + if (format == NULL) + format = GDataTypeInfo[data_type].PrintFmt; + + char buf[64]; + DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, data_ptr, format); + + bool value_changed = false; + if ((extra_flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0) + extra_flags |= ImGuiInputTextFlags_CharsDecimal; + extra_flags |= ImGuiInputTextFlags_AutoSelectAll; + + if (step != NULL) + { + const float button_size = GetFrameHeight(); + + BeginGroup(); // The only purpose of the group here is to allow the caller to query item data e.g. IsItemActive() + PushID(label); + PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2)); + if (InputText("", buf, IM_ARRAYSIZE(buf), extra_flags)) // PushId(label) + "" gives us the expected ID from outside point of view + value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialText.Data, data_type, data_ptr, format); + PopItemWidth(); + + // Step buttons + SameLine(0, style.ItemInnerSpacing.x); + if (ButtonEx("-", ImVec2(button_size, button_size), ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) + { + DataTypeApplyOp(data_type, '-', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast ? step_fast : step); + value_changed = true; + } + SameLine(0, style.ItemInnerSpacing.x); + if (ButtonEx("+", ImVec2(button_size, button_size), ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) + { + DataTypeApplyOp(data_type, '+', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast ? step_fast : step); + value_changed = true; + } + SameLine(0, style.ItemInnerSpacing.x); + TextUnformatted(label, FindRenderedTextEnd(label)); + + PopID(); + EndGroup(); + } + else + { + if (InputText(label, buf, IM_ARRAYSIZE(buf), extra_flags)) + value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialText.Data, data_type, data_ptr, format); + } + + return value_changed; +} + +bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, const char* format, ImGuiInputTextFlags extra_flags) +{ + extra_flags |= ImGuiInputTextFlags_CharsScientific; + return InputScalar(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), format, extra_flags); +} + +bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags extra_flags) +{ + extra_flags |= ImGuiInputTextFlags_CharsScientific; + return InputScalar(label, ImGuiDataType_Double, (void*)v, (void*)(step>0.0 ? &step : NULL), (void*)(step_fast>0.0 ? &step_fast : NULL), format, extra_flags); +} + +bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags extra_flags) +{ + // Hexadecimal input provided as a convenience but the flag name is awkward. Typically you'd use InputText() to parse your own data, if you want to handle prefixes. + const char* format = (extra_flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d"; + return InputScalar(label, ImGuiDataType_S32, (void*)v, (void*)(step>0 ? &step : NULL), (void*)(step_fast>0 ? &step_fast : NULL), format, extra_flags); +} + +bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* step, const void* step_fast, const char* format, ImGuiInputTextFlags extra_flags) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + bool value_changed = false; + BeginGroup(); + PushID(label); + PushMultiItemsWidths(components); + size_t type_size = GDataTypeInfo[data_type].Size; + for (int i = 0; i < components; i++) + { + PushID(i); + value_changed |= InputScalar("##v", data_type, v, step, step_fast, format, extra_flags); + SameLine(0, g.Style.ItemInnerSpacing.x); + PopID(); + PopItemWidth(); + v = (void*)((char*)v + type_size); + } + PopID(); + + TextUnformatted(label, FindRenderedTextEnd(label)); + EndGroup(); + return value_changed; +} + +bool ImGui::InputFloat2(const char* label, float v[2], const char* format, ImGuiInputTextFlags extra_flags) +{ + return InputScalarN(label, ImGuiDataType_Float, v, 2, NULL, NULL, format, extra_flags); +} + +bool ImGui::InputFloat3(const char* label, float v[3], const char* format, ImGuiInputTextFlags extra_flags) +{ + return InputScalarN(label, ImGuiDataType_Float, v, 3, NULL, NULL, format, extra_flags); +} + +bool ImGui::InputFloat4(const char* label, float v[4], const char* format, ImGuiInputTextFlags extra_flags) +{ + return InputScalarN(label, ImGuiDataType_Float, v, 4, NULL, NULL, format, extra_flags); +} + +// Prefer using "const char* format" directly, which is more flexible and consistent with other API. +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS +bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags extra_flags) +{ + char format[16] = "%f"; + if (decimal_precision >= 0) + ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision); + return InputFloat(label, v, step, step_fast, format, extra_flags); +} + +bool ImGui::InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags extra_flags) +{ + char format[16] = "%f"; + if (decimal_precision >= 0) + ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision); + return InputScalarN(label, ImGuiDataType_Float, v, 2, NULL, NULL, format, extra_flags); +} + +bool ImGui::InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags extra_flags) +{ + char format[16] = "%f"; + if (decimal_precision >= 0) + ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision); + return InputScalarN(label, ImGuiDataType_Float, v, 3, NULL, NULL, format, extra_flags); +} + +bool ImGui::InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags extra_flags) +{ + char format[16] = "%f"; + if (decimal_precision >= 0) + ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision); + return InputScalarN(label, ImGuiDataType_Float, v, 4, NULL, NULL, format, extra_flags); +} +#endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS + +bool ImGui::InputInt2(const char* label, int v[2], ImGuiInputTextFlags extra_flags) +{ + return InputScalarN(label, ImGuiDataType_S32, v, 2, NULL, NULL, "%d", extra_flags); +} + +bool ImGui::InputInt3(const char* label, int v[3], ImGuiInputTextFlags extra_flags) +{ + return InputScalarN(label, ImGuiDataType_S32, v, 3, NULL, NULL, "%d", extra_flags); +} + +bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags extra_flags) +{ + return InputScalarN(label, ImGuiDataType_S32, v, 4, NULL, NULL, "%d", extra_flags); +} + +static float CalcMaxPopupHeightFromItemCount(int items_count) +{ + ImGuiContext& g = *GImGui; + if (items_count <= 0) + return FLT_MAX; + return (g.FontSize + g.Style.ItemSpacing.y) * items_count - g.Style.ItemSpacing.y + (g.Style.WindowPadding.y * 2); +} + +bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags) +{ + // Always consume the SetNextWindowSizeConstraint() call in our early return paths + ImGuiContext& g = *GImGui; + ImGuiCond backup_next_window_size_constraint = g.NextWindowData.SizeConstraintCond; + g.NextWindowData.SizeConstraintCond = 0; + + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together + + const ImGuiStyle& style = g.Style; + const ImGuiID id = window->GetID(label); + + const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight(); + const ImVec2 label_size = CalcTextSize(label, NULL, true); + const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : CalcItemWidth(); + const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); + const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); + ItemSize(total_bb, style.FramePadding.y); + if (!ItemAdd(total_bb, id, &frame_bb)) + return false; + + bool hovered, held; + bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held); + bool popup_open = IsPopupOpen(id); + + const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f)); + const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); + RenderNavHighlight(frame_bb, id); + if (!(flags & ImGuiComboFlags_NoPreview)) + window->DrawList->AddRectFilled(frame_bb.Min, ImVec2(frame_bb.Max.x - arrow_size, frame_bb.Max.y), frame_col, style.FrameRounding, ImDrawCornerFlags_Left); + if (!(flags & ImGuiComboFlags_NoArrowButton)) + { + window->DrawList->AddRectFilled(ImVec2(frame_bb.Max.x - arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button), style.FrameRounding, (w <= arrow_size) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Right); + RenderArrow(ImVec2(frame_bb.Max.x - arrow_size + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), ImGuiDir_Down); + } + RenderFrameBorder(frame_bb.Min, frame_bb.Max, style.FrameRounding); + if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview)) + RenderTextClipped(frame_bb.Min + style.FramePadding, value_bb.Max, preview_value, NULL, NULL, ImVec2(0.0f,0.0f)); + if (label_size.x > 0) + RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); + + if ((pressed || g.NavActivateId == id) && !popup_open) + { + if (window->DC.NavLayerCurrent == 0) + window->NavLastIds[0] = id; + OpenPopupEx(id); + popup_open = true; + } + + if (!popup_open) + return false; + + if (backup_next_window_size_constraint) + { + g.NextWindowData.SizeConstraintCond = backup_next_window_size_constraint; + g.NextWindowData.SizeConstraintRect.Min.x = ImMax(g.NextWindowData.SizeConstraintRect.Min.x, w); + } + else + { + if ((flags & ImGuiComboFlags_HeightMask_) == 0) + flags |= ImGuiComboFlags_HeightRegular; + IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiComboFlags_HeightMask_)); // Only one + int popup_max_height_in_items = -1; + if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8; + else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4; + else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20; + SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items))); + } + + char name[16]; + ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.CurrentPopupStack.Size); // Recycle windows based on depth + + // Peak into expected window size so we can position it + if (ImGuiWindow* popup_window = FindWindowByName(name)) + if (popup_window->WasActive) + { + ImVec2 size_contents = CalcSizeContents(popup_window); + ImVec2 size_expected = CalcSizeAfterConstraint(popup_window, CalcSizeAutoFit(popup_window, size_contents)); + if (flags & ImGuiComboFlags_PopupAlignLeft) + popup_window->AutoPosLastDirection = ImGuiDir_Left; + ImRect r_outer = FindAllowedExtentRectForWindow(popup_window); + ImVec2 pos = FindBestWindowPosForPopupEx(frame_bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, r_outer, frame_bb, ImGuiPopupPositionPolicy_ComboBox); + SetNextWindowPos(pos); + } + + // Horizontally align ourselves with the framed text + ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings; + PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(style.FramePadding.x, style.WindowPadding.y)); + bool ret = Begin(name, NULL, window_flags); + PopStyleVar(); + if (!ret) + { + EndPopup(); + IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above + return false; + } + return true; +} + +void ImGui::EndCombo() +{ + EndPopup(); +} + +// Getter for the old Combo() API: const char*[] +static bool Items_ArrayGetter(void* data, int idx, const char** out_text) +{ + const char* const* items = (const char* const*)data; + if (out_text) + *out_text = items[idx]; + return true; +} + +// Getter for the old Combo() API: "item1\0item2\0item3\0" +static bool Items_SingleStringGetter(void* data, int idx, const char** out_text) +{ + // FIXME-OPT: we could pre-compute the indices to fasten this. But only 1 active combo means the waste is limited. + const char* items_separated_by_zeros = (const char*)data; + int items_count = 0; + const char* p = items_separated_by_zeros; + while (*p) + { + if (idx == items_count) + break; + p += strlen(p) + 1; + items_count++; + } + if (!*p) + return false; + if (out_text) + *out_text = p; + return true; +} + +// Old API, prefer using BeginCombo() nowadays if you can. +bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int popup_max_height_in_items) +{ + ImGuiContext& g = *GImGui; + + // Call the getter to obtain the preview string which is a parameter to BeginCombo() + const char* preview_value = NULL; + if (*current_item >= 0 && *current_item < items_count) + items_getter(data, *current_item, &preview_value); + + // The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here. + if (popup_max_height_in_items != -1 && !g.NextWindowData.SizeConstraintCond) + SetNextWindowSizeConstraints(ImVec2(0,0), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items))); + + if (!BeginCombo(label, preview_value, ImGuiComboFlags_None)) + return false; + + // Display items + // FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed) + bool value_changed = false; + for (int i = 0; i < items_count; i++) + { + PushID((void*)(intptr_t)i); + const bool item_selected = (i == *current_item); + const char* item_text; + if (!items_getter(data, i, &item_text)) + item_text = "*Unknown item*"; + if (Selectable(item_text, item_selected)) + { + value_changed = true; + *current_item = i; + } + if (item_selected) + SetItemDefaultFocus(); + PopID(); + } + + EndCombo(); + return value_changed; +} + +// Combo box helper allowing to pass an array of strings. +bool ImGui::Combo(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items) +{ + const bool value_changed = Combo(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_in_items); + return value_changed; +} + +// Combo box helper allowing to pass all items in a single string literal holding multiple zero-terminated items "item1\0item2\0" +bool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items) +{ + int items_count = 0; + const char* p = items_separated_by_zeros; // FIXME-OPT: Avoid computing this, or at least only when combo is open + while (*p) + { + p += strlen(p) + 1; + items_count++; + } + bool value_changed = Combo(label, current_item, Items_SingleStringGetter, (void*)items_separated_by_zeros, items_count, height_in_items); + return value_changed; +} + +// Tip: pass an empty label (e.g. "##dummy") then you can use the space to draw other text or image. +// But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID or use ##unique_id. +bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) // FIXME-OPT: Avoid if vertically clipped. + PopClipRect(); + + ImGuiID id = window->GetID(label); + ImVec2 label_size = CalcTextSize(label, NULL, true); + ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y); + ImVec2 pos = window->DC.CursorPos; + pos.y += window->DC.CurrentLineTextBaseOffset; + ImRect bb_inner(pos, pos + size); + ItemSize(bb_inner); + + // Fill horizontal space. + ImVec2 window_padding = window->WindowPadding; + float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? GetWindowContentRegionMax().x : GetContentRegionMax().x; + float w_draw = ImMax(label_size.x, window->Pos.x + max_x - window_padding.x - window->DC.CursorPos.x); + ImVec2 size_draw((size_arg.x != 0 && !(flags & ImGuiSelectableFlags_DrawFillAvailWidth)) ? size_arg.x : w_draw, size_arg.y != 0.0f ? size_arg.y : size.y); + ImRect bb(pos, pos + size_draw); + if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_DrawFillAvailWidth)) + bb.Max.x += window_padding.x; + + // Selectables are tightly packed together, we extend the box to cover spacing between selectable. + float spacing_L = (float)(int)(style.ItemSpacing.x * 0.5f); + float spacing_U = (float)(int)(style.ItemSpacing.y * 0.5f); + float spacing_R = style.ItemSpacing.x - spacing_L; + float spacing_D = style.ItemSpacing.y - spacing_U; + bb.Min.x -= spacing_L; + bb.Min.y -= spacing_U; + bb.Max.x += spacing_R; + bb.Max.y += spacing_D; + if (!ItemAdd(bb, (flags & ImGuiSelectableFlags_Disabled) ? 0 : id)) + { + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) + PushColumnClipRect(); + return false; + } + + // We use NoHoldingActiveID on menus so user can click and _hold_ on a menu then drag to browse child entries + ImGuiButtonFlags button_flags = 0; + if (flags & ImGuiSelectableFlags_NoHoldingActiveID) button_flags |= ImGuiButtonFlags_NoHoldingActiveID; + if (flags & ImGuiSelectableFlags_PressedOnClick) button_flags |= ImGuiButtonFlags_PressedOnClick; + if (flags & ImGuiSelectableFlags_PressedOnRelease) button_flags |= ImGuiButtonFlags_PressedOnRelease; + if (flags & ImGuiSelectableFlags_Disabled) button_flags |= ImGuiButtonFlags_Disabled; + if (flags & ImGuiSelectableFlags_AllowDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; + bool hovered, held; + bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); + if (flags & ImGuiSelectableFlags_Disabled) + selected = false; + + // Hovering selectable with mouse updates NavId accordingly so navigation can be resumed with gamepad/keyboard (this doesn't happen on most widgets) + if (pressed || hovered) + if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent) + { + g.NavDisableHighlight = true; + SetNavID(id, window->DC.NavLayerCurrent); + } + if (pressed) + MarkItemValueChanged(id); + + // Render + if (hovered || selected) + { + const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); + RenderFrame(bb.Min, bb.Max, col, false, 0.0f); + RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); + } + + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) + { + PushColumnClipRect(); + bb.Max.x -= (GetContentRegionMax().x - max_x); + } + + if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); + RenderTextClipped(bb_inner.Min, bb.Max, label, NULL, &label_size, ImVec2(0.0f,0.0f)); + if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor(); + + // Automatically close popups + if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(window->DC.ItemFlags & ImGuiItemFlags_SelectableDontClosePopup)) + CloseCurrentPopup(); + return pressed; +} + +bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) +{ + if (Selectable(label, *p_selected, flags, size_arg)) + { + *p_selected = !*p_selected; + return true; + } + return false; +} + +// FIXME: Rename to BeginListBox() +// Helper to calculate the size of a listbox and display a label on the right. +// Tip: To have a list filling the entire window width, PushItemWidth(-1) and pass an empty label "##empty" +bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + const ImGuiStyle& style = GetStyle(); + const ImGuiID id = GetID(label); + const ImVec2 label_size = CalcTextSize(label, NULL, true); + + // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar. + ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y); + ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y)); + ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); + ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); + window->DC.LastItemRect = bb; // Forward storage for ListBoxFooter.. dodgy. + + BeginGroup(); + if (label_size.x > 0) + RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); + + BeginChildFrame(id, frame_bb.GetSize()); + return true; +} + +// FIXME: Rename to BeginListBox() +bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_items) +{ + // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar. + // We don't add +0.40f if items_count <= height_in_items. It is slightly dodgy, because it means a dynamic list of items will make the widget resize occasionally when it crosses that size. + // I am expecting that someone will come and complain about this behavior in a remote future, then we can advise on a better solution. + if (height_in_items < 0) + height_in_items = ImMin(items_count, 7); + float height_in_items_f = height_in_items < items_count ? (height_in_items + 0.40f) : (height_in_items + 0.00f); + + // We include ItemSpacing.y so that a list sized for the exact number of items doesn't make a scrollbar appears. We could also enforce that by passing a flag to BeginChild(). + ImVec2 size; + size.x = 0.0f; + size.y = GetTextLineHeightWithSpacing() * height_in_items_f + GetStyle().ItemSpacing.y; + return ListBoxHeader(label, size); +} + +// FIXME: Rename to EndListBox() +void ImGui::ListBoxFooter() +{ + ImGuiWindow* parent_window = GetCurrentWindow()->ParentWindow; + const ImRect bb = parent_window->DC.LastItemRect; + const ImGuiStyle& style = GetStyle(); + + EndChildFrame(); + + // Redeclare item size so that it includes the label (we have stored the full size in LastItemRect) + // We call SameLine() to restore DC.CurrentLine* data + SameLine(); + parent_window->DC.CursorPos = bb.Min; + ItemSize(bb, style.FramePadding.y); + EndGroup(); +} + +bool ImGui::ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_items) +{ + const bool value_changed = ListBox(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_items); + return value_changed; +} + +bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items) +{ + if (!ListBoxHeader(label, items_count, height_in_items)) + return false; + + // Assume all items have even height (= 1 line of text). If you need items of different or variable sizes you can create a custom version of ListBox() in your code without using the clipper. + bool value_changed = false; + ImGuiListClipper clipper(items_count, GetTextLineHeightWithSpacing()); // We know exactly our line height here so we pass it as a minor optimization, but generally you don't need to. + while (clipper.Step()) + for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) + { + const bool item_selected = (i == *current_item); + const char* item_text; + if (!items_getter(data, i, &item_text)) + item_text = "*Unknown item*"; + + PushID(i); + if (Selectable(item_text, item_selected)) + { + *current_item = i; + value_changed = true; + } + if (item_selected) + SetItemDefaultFocus(); + PopID(); + } + ListBoxFooter(); + return value_changed; +} + +bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, bool enabled) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + ImGuiStyle& style = g.Style; + ImVec2 pos = window->DC.CursorPos; + ImVec2 label_size = CalcTextSize(label, NULL, true); + + ImGuiSelectableFlags flags = ImGuiSelectableFlags_PressedOnRelease | (enabled ? 0 : ImGuiSelectableFlags_Disabled); + bool pressed; + if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) + { + // Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful + // Note that in this situation we render neither the shortcut neither the selected tick mark + float w = label_size.x; + window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); + PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f); + pressed = Selectable(label, false, flags, ImVec2(w, 0.0f)); + PopStyleVar(); + window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). + } + else + { + ImVec2 shortcut_size = shortcut ? CalcTextSize(shortcut, NULL) : ImVec2(0.0f, 0.0f); + float w = window->MenuColumns.DeclColumns(label_size.x, shortcut_size.x, (float)(int)(g.FontSize * 1.20f)); // Feedback for next frame + float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); + pressed = Selectable(label, false, flags | ImGuiSelectableFlags_DrawFillAvailWidth, ImVec2(w, 0.0f)); + if (shortcut_size.x > 0.0f) + { + PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); + RenderText(pos + ImVec2(window->MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false); + PopStyleColor(); + } + if (selected) + RenderCheckMark(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f); + } + return pressed; +} + +bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled) +{ + if (MenuItem(label, shortcut, p_selected ? *p_selected : false, enabled)) + { + if (p_selected) + *p_selected = !*p_selected; + return true; + } + return false; +} + +// For the main menu bar, which cannot be moved, we honor g.Style.DisplaySafeAreaPadding to ensure text can be visible on a TV set. +bool ImGui::BeginMainMenuBar() +{ + ImGuiContext& g = *GImGui; + g.NextWindowData.MenuBarOffsetMinVal = ImVec2(g.Style.DisplaySafeAreaPadding.x, ImMax(g.Style.DisplaySafeAreaPadding.y - g.Style.FramePadding.y, 0.0f)); + SetNextWindowPos(ImVec2(0.0f, 0.0f)); + SetNextWindowSize(ImVec2(g.IO.DisplaySize.x, g.NextWindowData.MenuBarOffsetMinVal.y + g.FontBaseSize + g.Style.FramePadding.y)); + PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); + PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0,0)); + ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar; + bool is_open = Begin("##MainMenuBar", NULL, window_flags) && BeginMenuBar(); + PopStyleVar(2); + g.NextWindowData.MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f); + if (!is_open) + { + End(); + return false; + } + return true; +} + +void ImGui::EndMainMenuBar() +{ + EndMenuBar(); + + // When the user has left the menu layer (typically: closed menus through activation of an item), we restore focus to the previous window + ImGuiContext& g = *GImGui; + if (g.CurrentWindow == g.NavWindow && g.NavLayer == 0) + FocusFrontMostActiveWindow(g.NavWindow); + + End(); +} + +bool ImGui::BeginMenuBar() +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + if (!(window->Flags & ImGuiWindowFlags_MenuBar)) + return false; + + IM_ASSERT(!window->DC.MenuBarAppending); + BeginGroup(); // Backup position on layer 0 + PushID("##menubar"); + + // We don't clip with current window clipping rectangle as it is already set to the area below. However we clip with window full rect. + // We remove 1 worth of rounding to Max.x to that text in long menus and small windows don't tend to display over the lower-right rounded area, which looks particularly glitchy. + ImRect bar_rect = window->MenuBarRect(); + ImRect clip_rect(ImFloor(bar_rect.Min.x + 0.5f), ImFloor(bar_rect.Min.y + window->WindowBorderSize + 0.5f), ImFloor(ImMax(bar_rect.Min.x, bar_rect.Max.x - window->WindowRounding) + 0.5f), ImFloor(bar_rect.Max.y + 0.5f)); + clip_rect.ClipWith(window->OuterRectClipped); + PushClipRect(clip_rect.Min, clip_rect.Max, false); + + window->DC.CursorPos = ImVec2(bar_rect.Min.x + window->DC.MenuBarOffset.x, bar_rect.Min.y + window->DC.MenuBarOffset.y); + window->DC.LayoutType = ImGuiLayoutType_Horizontal; + window->DC.NavLayerCurrent++; + window->DC.NavLayerCurrentMask <<= 1; + window->DC.MenuBarAppending = true; + AlignTextToFramePadding(); + return true; +} + +void ImGui::EndMenuBar() +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + ImGuiContext& g = *GImGui; + + // Nav: When a move request within one of our child menu failed, capture the request to navigate among our siblings. + if (NavMoveRequestButNoResultYet() && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) + { + ImGuiWindow* nav_earliest_child = g.NavWindow; + while (nav_earliest_child->ParentWindow && (nav_earliest_child->ParentWindow->Flags & ImGuiWindowFlags_ChildMenu)) + nav_earliest_child = nav_earliest_child->ParentWindow; + if (nav_earliest_child->ParentWindow == window && nav_earliest_child->DC.ParentLayoutType == ImGuiLayoutType_Horizontal && g.NavMoveRequestForward == ImGuiNavForward_None) + { + // To do so we claim focus back, restore NavId and then process the movement request for yet another frame. + // This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth the hassle/cost) + IM_ASSERT(window->DC.NavLayerActiveMaskNext & 0x02); // Sanity check + FocusWindow(window); + SetNavIDWithRectRel(window->NavLastIds[1], 1, window->NavRectRel[1]); + g.NavLayer = 1; + g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection. + g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued; + NavMoveRequestCancel(); + } + } + + IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar); + IM_ASSERT(window->DC.MenuBarAppending); + PopClipRect(); + PopID(); + window->DC.MenuBarOffset.x = window->DC.CursorPos.x - window->MenuBarRect().Min.x; // Save horizontal position so next append can reuse it. This is kinda equivalent to a per-layer CursorPos. + window->DC.GroupStack.back().AdvanceCursor = false; + EndGroup(); // Restore position on layer 0 + window->DC.LayoutType = ImGuiLayoutType_Vertical; + window->DC.NavLayerCurrent--; + window->DC.NavLayerCurrentMask >>= 1; + window->DC.MenuBarAppending = false; +} + +bool ImGui::BeginMenu(const char* label, bool enabled) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + const ImGuiID id = window->GetID(label); + + ImVec2 label_size = CalcTextSize(label, NULL, true); + + bool pressed; + bool menu_is_open = IsPopupOpen(id); + bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].OpenParentId == window->IDStack.back()); + ImGuiWindow* backed_nav_window = g.NavWindow; + if (menuset_is_open) + g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent) + + // The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu (using FindBestWindowPosForPopup). + ImVec2 popup_pos, pos = window->DC.CursorPos; + if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) + { + // Menu inside an horizontal menu bar + // Selectable extend their highlight by half ItemSpacing in each direction. + // For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin() + popup_pos = ImVec2(pos.x - window->WindowPadding.x, pos.y - style.FramePadding.y + window->MenuBarHeight()); + window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); + PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f); + float w = label_size.x; + pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_PressedOnClick | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); + PopStyleVar(); + window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). + } + else + { + // Menu inside a menu + popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y); + float w = window->MenuColumns.DeclColumns(label_size.x, 0.0f, (float)(int)(g.FontSize * 1.20f)); // Feedback to next frame + float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); + pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_PressedOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); + if (!enabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); + RenderArrow(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.30f, 0.0f), ImGuiDir_Right); + if (!enabled) PopStyleColor(); + } + + const bool hovered = enabled && ItemHoverable(window->DC.LastItemRect, id); + if (menuset_is_open) + g.NavWindow = backed_nav_window; + + bool want_open = false, want_close = false; + if (window->DC.LayoutType == ImGuiLayoutType_Vertical) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) + { + // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive. + bool moving_within_opened_triangle = false; + if (g.HoveredWindow == window && g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentWindow == window && !(window->Flags & ImGuiWindowFlags_MenuBar)) + { + if (ImGuiWindow* next_window = g.OpenPopupStack[g.CurrentPopupStack.Size].Window) + { + ImRect next_window_rect = next_window->Rect(); + ImVec2 ta = g.IO.MousePos - g.IO.MouseDelta; + ImVec2 tb = (window->Pos.x < next_window->Pos.x) ? next_window_rect.GetTL() : next_window_rect.GetTR(); + ImVec2 tc = (window->Pos.x < next_window->Pos.x) ? next_window_rect.GetBL() : next_window_rect.GetBR(); + float extra = ImClamp(ImFabs(ta.x - tb.x) * 0.30f, 5.0f, 30.0f); // add a bit of extra slack. + ta.x += (window->Pos.x < next_window->Pos.x) ? -0.5f : +0.5f; // to avoid numerical issues + tb.y = ta.y + ImMax((tb.y - extra) - ta.y, -100.0f); // triangle is maximum 200 high to limit the slope and the bias toward large sub-menus // FIXME: Multiply by fb_scale? + tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +100.0f); + moving_within_opened_triangle = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos); + //window->DrawList->PushClipRectFullScreen(); window->DrawList->AddTriangleFilled(ta, tb, tc, moving_within_opened_triangle ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); window->DrawList->PopClipRect(); // Debug + } + } + + want_close = (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_within_opened_triangle); + want_open = (!menu_is_open && hovered && !moving_within_opened_triangle) || (!menu_is_open && hovered && pressed); + + if (g.NavActivateId == id) + { + want_close = menu_is_open; + want_open = !menu_is_open; + } + if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open + { + want_open = true; + NavMoveRequestCancel(); + } + } + else + { + // Menu bar + if (menu_is_open && pressed && menuset_is_open) // Click an open menu again to close it + { + want_close = true; + want_open = menu_is_open = false; + } + else if (pressed || (hovered && menuset_is_open && !menu_is_open)) // First click to open, then hover to open others + { + want_open = true; + } + else if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Down) // Nav-Down to open + { + want_open = true; + NavMoveRequestCancel(); + } + } + + if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }' + want_close = true; + if (want_close && IsPopupOpen(id)) + ClosePopupToLevel(g.CurrentPopupStack.Size); + + if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.CurrentPopupStack.Size) + { + // Don't recycle same menu level in the same frame, first close the other menu and yield for a frame. + OpenPopup(label); + return false; + } + + menu_is_open |= want_open; + if (want_open) + OpenPopup(label); + + if (menu_is_open) + { + // Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu) + SetNextWindowPos(popup_pos, ImGuiCond_Always); + ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus; + if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) + flags |= ImGuiWindowFlags_ChildWindow; + menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) + } + + return menu_is_open; +} + +void ImGui::EndMenu() +{ + // Nav: When a left move request _within our child menu_ failed, close the menu. + // A menu doesn't close itself because EndMenuBar() wants the catch the last Left<>Right inputs. + // However, it means that with the current code, a BeginMenu() from outside another menu or a menu-bar won't be closable with the Left direction. + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet() && window->DC.LayoutType == ImGuiLayoutType_Vertical) + { + ClosePopupToLevel(g.OpenPopupStack.Size - 1); + NavMoveRequestCancel(); + } + + EndPopup(); +} + +// Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. +void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags) +{ + ImGuiContext& g = *GImGui; + + int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]); + BeginTooltipEx(0, true); + + const char* text_end = text ? FindRenderedTextEnd(text, NULL) : text; + if (text_end > text) + { + TextUnformatted(text, text_end); + Separator(); + } + + ImVec2 sz(g.FontSize * 3 + g.Style.FramePadding.y * 2, g.FontSize * 3 + g.Style.FramePadding.y * 2); + ColorButton("##preview", ImVec4(col[0], col[1], col[2], col[3]), (flags & (ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)) | ImGuiColorEditFlags_NoTooltip, sz); + SameLine(); + if (flags & ImGuiColorEditFlags_NoAlpha) + Text("#%02X%02X%02X\nR: %d, G: %d, B: %d\n(%.3f, %.3f, %.3f)", cr, cg, cb, cr, cg, cb, col[0], col[1], col[2]); + else + Text("#%02X%02X%02X%02X\nR:%d, G:%d, B:%d, A:%d\n(%.3f, %.3f, %.3f, %.3f)", cr, cg, cb, ca, cr, cg, cb, ca, col[0], col[1], col[2], col[3]); + EndTooltip(); +} + +static inline ImU32 ImAlphaBlendColor(ImU32 col_a, ImU32 col_b) +{ + float t = ((col_b >> IM_COL32_A_SHIFT) & 0xFF) / 255.f; + int r = ImLerp((int)(col_a >> IM_COL32_R_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_R_SHIFT) & 0xFF, t); + int g = ImLerp((int)(col_a >> IM_COL32_G_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_G_SHIFT) & 0xFF, t); + int b = ImLerp((int)(col_a >> IM_COL32_B_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_B_SHIFT) & 0xFF, t); + return IM_COL32(r, g, b, 0xFF); +} + +// NB: This is rather brittle and will show artifact when rounding this enabled if rounded corners overlap multiple cells. Caller currently responsible for avoiding that. +// I spent a non reasonable amount of time trying to getting this right for ColorButton with rounding+anti-aliasing+ImGuiColorEditFlags_HalfAlphaPreview flag + various grid sizes and offsets, and eventually gave up... probably more reasonable to disable rounding alltogether. +void ImGui::RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU32 col, float grid_step, ImVec2 grid_off, float rounding, int rounding_corners_flags) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (((col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) < 0xFF) + { + ImU32 col_bg1 = GetColorU32(ImAlphaBlendColor(IM_COL32(204,204,204,255), col)); + ImU32 col_bg2 = GetColorU32(ImAlphaBlendColor(IM_COL32(128,128,128,255), col)); + window->DrawList->AddRectFilled(p_min, p_max, col_bg1, rounding, rounding_corners_flags); + + int yi = 0; + for (float y = p_min.y + grid_off.y; y < p_max.y; y += grid_step, yi++) + { + float y1 = ImClamp(y, p_min.y, p_max.y), y2 = ImMin(y + grid_step, p_max.y); + if (y2 <= y1) + continue; + for (float x = p_min.x + grid_off.x + (yi & 1) * grid_step; x < p_max.x; x += grid_step * 2.0f) + { + float x1 = ImClamp(x, p_min.x, p_max.x), x2 = ImMin(x + grid_step, p_max.x); + if (x2 <= x1) + continue; + int rounding_corners_flags_cell = 0; + if (y1 <= p_min.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImDrawCornerFlags_TopLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImDrawCornerFlags_TopRight; } + if (y2 >= p_max.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImDrawCornerFlags_BotLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImDrawCornerFlags_BotRight; } + rounding_corners_flags_cell &= rounding_corners_flags; + window->DrawList->AddRectFilled(ImVec2(x1,y1), ImVec2(x2,y2), col_bg2, rounding_corners_flags_cell ? rounding : 0.0f, rounding_corners_flags_cell); + } + } + } + else + { + window->DrawList->AddRectFilled(p_min, p_max, col, rounding, rounding_corners_flags); + } +} + +void ImGui::SetColorEditOptions(ImGuiColorEditFlags flags) +{ + ImGuiContext& g = *GImGui; + if ((flags & ImGuiColorEditFlags__InputsMask) == 0) + flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__InputsMask; + if ((flags & ImGuiColorEditFlags__DataTypeMask) == 0) + flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__DataTypeMask; + if ((flags & ImGuiColorEditFlags__PickerMask) == 0) + flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__PickerMask; + IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__InputsMask))); // Check only 1 option is selected + IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__DataTypeMask))); // Check only 1 option is selected + IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__PickerMask))); // Check only 1 option is selected + g.ColorEditOptions = flags; +} + +// A little colored square. Return true when clicked. +// FIXME: May want to display/ignore the alpha component in the color display? Yet show it in the tooltip. +// 'desc_id' is not called 'label' because we don't display it next to the button, but only in the tooltip. +bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags, ImVec2 size) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiID id = window->GetID(desc_id); + float default_size = GetFrameHeight(); + if (size.x == 0.0f) + size.x = default_size; + if (size.y == 0.0f) + size.y = default_size; + const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); + ItemSize(bb, (size.y >= default_size) ? g.Style.FramePadding.y : 0.0f); + if (!ItemAdd(bb, id)) + return false; + + bool hovered, held; + bool pressed = ButtonBehavior(bb, id, &hovered, &held); + + if (flags & ImGuiColorEditFlags_NoAlpha) + flags &= ~(ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf); + + ImVec4 col_without_alpha(col.x, col.y, col.z, 1.0f); + float grid_step = ImMin(size.x, size.y) / 2.99f; + float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f); + ImRect bb_inner = bb; + float off = -0.75f; // The border (using Col_FrameBg) tends to look off when color is near-opaque and rounding is enabled. This offset seemed like a good middle ground to reduce those artifacts. + bb_inner.Expand(off); + if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col.w < 1.0f) + { + float mid_x = (float)(int)((bb_inner.Min.x + bb_inner.Max.x) * 0.5f + 0.5f); + RenderColorRectWithAlphaCheckerboard(ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawCornerFlags_TopRight| ImDrawCornerFlags_BotRight); + window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_without_alpha), rounding, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotLeft); + } + else + { + // Because GetColorU32() multiplies by the global style Alpha and we don't want to display a checkerboard if the source code had no alpha + ImVec4 col_source = (flags & ImGuiColorEditFlags_AlphaPreview) ? col : col_without_alpha; + if (col_source.w < 1.0f) + RenderColorRectWithAlphaCheckerboard(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), grid_step, ImVec2(off, off), rounding); + else + window->DrawList->AddRectFilled(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), rounding, ImDrawCornerFlags_All); + } + RenderNavHighlight(bb, id); + if (g.Style.FrameBorderSize > 0.0f) + RenderFrameBorder(bb.Min, bb.Max, rounding); + else + window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border + + // Drag and Drop Source + // NB: The ActiveId test is merely an optional micro-optimization, BeginDragDropSource() does the same test. + if (g.ActiveId == id && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropSource()) + { + if (flags & ImGuiColorEditFlags_NoAlpha) + SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F, &col, sizeof(float) * 3, ImGuiCond_Once); + else + SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, &col, sizeof(float) * 4, ImGuiCond_Once); + ColorButton(desc_id, col, flags); + SameLine(); + TextUnformatted("Color"); + EndDragDropSource(); + } + + // Tooltip + if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered) + ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)); + + if (pressed) + MarkItemValueChanged(id); + + return pressed; +} + +bool ImGui::ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags) +{ + return ColorEdit4(label, col, flags | ImGuiColorEditFlags_NoAlpha); +} + +void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags) +{ + bool allow_opt_inputs = !(flags & ImGuiColorEditFlags__InputsMask); + bool allow_opt_datatype = !(flags & ImGuiColorEditFlags__DataTypeMask); + if ((!allow_opt_inputs && !allow_opt_datatype) || !BeginPopup("context")) + return; + ImGuiContext& g = *GImGui; + ImGuiColorEditFlags opts = g.ColorEditOptions; + if (allow_opt_inputs) + { + if (RadioButton("RGB", (opts & ImGuiColorEditFlags_RGB) != 0)) opts = (opts & ~ImGuiColorEditFlags__InputsMask) | ImGuiColorEditFlags_RGB; + if (RadioButton("HSV", (opts & ImGuiColorEditFlags_HSV) != 0)) opts = (opts & ~ImGuiColorEditFlags__InputsMask) | ImGuiColorEditFlags_HSV; + if (RadioButton("HEX", (opts & ImGuiColorEditFlags_HEX) != 0)) opts = (opts & ~ImGuiColorEditFlags__InputsMask) | ImGuiColorEditFlags_HEX; + } + if (allow_opt_datatype) + { + if (allow_opt_inputs) Separator(); + if (RadioButton("0..255", (opts & ImGuiColorEditFlags_Uint8) != 0)) opts = (opts & ~ImGuiColorEditFlags__DataTypeMask) | ImGuiColorEditFlags_Uint8; + if (RadioButton("0.00..1.00", (opts & ImGuiColorEditFlags_Float) != 0)) opts = (opts & ~ImGuiColorEditFlags__DataTypeMask) | ImGuiColorEditFlags_Float; + } + + if (allow_opt_inputs || allow_opt_datatype) + Separator(); + if (Button("Copy as..", ImVec2(-1,0))) + OpenPopup("Copy"); + if (BeginPopup("Copy")) + { + int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]); + char buf[64]; + ImFormatString(buf, IM_ARRAYSIZE(buf), "(%.3ff, %.3ff, %.3ff, %.3ff)", col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); + if (Selectable(buf)) + SetClipboardText(buf); + ImFormatString(buf, IM_ARRAYSIZE(buf), "(%d,%d,%d,%d)", cr, cg, cb, ca); + if (Selectable(buf)) + SetClipboardText(buf); + if (flags & ImGuiColorEditFlags_NoAlpha) + ImFormatString(buf, IM_ARRAYSIZE(buf), "0x%02X%02X%02X", cr, cg, cb); + else + ImFormatString(buf, IM_ARRAYSIZE(buf), "0x%02X%02X%02X%02X", cr, cg, cb, ca); + if (Selectable(buf)) + SetClipboardText(buf); + EndPopup(); + } + + g.ColorEditOptions = opts; + EndPopup(); +} + +static void ColorPickerOptionsPopup(ImGuiColorEditFlags flags, const float* ref_col) +{ + bool allow_opt_picker = !(flags & ImGuiColorEditFlags__PickerMask); + bool allow_opt_alpha_bar = !(flags & ImGuiColorEditFlags_NoAlpha) && !(flags & ImGuiColorEditFlags_AlphaBar); + if ((!allow_opt_picker && !allow_opt_alpha_bar) || !ImGui::BeginPopup("context")) + return; + ImGuiContext& g = *GImGui; + if (allow_opt_picker) + { + ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (ImGui::GetFrameHeight() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function + ImGui::PushItemWidth(picker_size.x); + for (int picker_type = 0; picker_type < 2; picker_type++) + { + // Draw small/thumbnail version of each picker type (over an invisible button for selection) + if (picker_type > 0) ImGui::Separator(); + ImGui::PushID(picker_type); + ImGuiColorEditFlags picker_flags = ImGuiColorEditFlags_NoInputs|ImGuiColorEditFlags_NoOptions|ImGuiColorEditFlags_NoLabel|ImGuiColorEditFlags_NoSidePreview|(flags & ImGuiColorEditFlags_NoAlpha); + if (picker_type == 0) picker_flags |= ImGuiColorEditFlags_PickerHueBar; + if (picker_type == 1) picker_flags |= ImGuiColorEditFlags_PickerHueWheel; + ImVec2 backup_pos = ImGui::GetCursorScreenPos(); + if (ImGui::Selectable("##selectable", false, 0, picker_size)) // By default, Selectable() is closing popup + g.ColorEditOptions = (g.ColorEditOptions & ~ImGuiColorEditFlags__PickerMask) | (picker_flags & ImGuiColorEditFlags__PickerMask); + ImGui::SetCursorScreenPos(backup_pos); + ImVec4 dummy_ref_col; + memcpy(&dummy_ref_col.x, ref_col, sizeof(float) * (picker_flags & ImGuiColorEditFlags_NoAlpha ? 3 : 4)); + ImGui::ColorPicker4("##dummypicker", &dummy_ref_col.x, picker_flags); + ImGui::PopID(); + } + ImGui::PopItemWidth(); + } + if (allow_opt_alpha_bar) + { + if (allow_opt_picker) ImGui::Separator(); + ImGui::CheckboxFlags("Alpha Bar", (unsigned int*)&g.ColorEditOptions, ImGuiColorEditFlags_AlphaBar); + } + ImGui::EndPopup(); +} + +// Edit colors components (each component in 0.0f..1.0f range). +// See enum ImGuiColorEditFlags_ for available options. e.g. Only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. +// With typical options: Left-click on colored square to open color picker. Right-click to open option menu. CTRL-Click over input fields to edit them and TAB to go to next item. +bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + const float square_sz = GetFrameHeight(); + const float w_extra = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x); + const float w_items_all = CalcItemWidth() - w_extra; + const char* label_display_end = FindRenderedTextEnd(label); + + BeginGroup(); + PushID(label); + + // If we're not showing any slider there's no point in doing any HSV conversions + const ImGuiColorEditFlags flags_untouched = flags; + if (flags & ImGuiColorEditFlags_NoInputs) + flags = (flags & (~ImGuiColorEditFlags__InputsMask)) | ImGuiColorEditFlags_RGB | ImGuiColorEditFlags_NoOptions; + + // Context menu: display and modify options (before defaults are applied) + if (!(flags & ImGuiColorEditFlags_NoOptions)) + ColorEditOptionsPopup(col, flags); + + // Read stored options + if (!(flags & ImGuiColorEditFlags__InputsMask)) + flags |= (g.ColorEditOptions & ImGuiColorEditFlags__InputsMask); + if (!(flags & ImGuiColorEditFlags__DataTypeMask)) + flags |= (g.ColorEditOptions & ImGuiColorEditFlags__DataTypeMask); + if (!(flags & ImGuiColorEditFlags__PickerMask)) + flags |= (g.ColorEditOptions & ImGuiColorEditFlags__PickerMask); + flags |= (g.ColorEditOptions & ~(ImGuiColorEditFlags__InputsMask | ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__PickerMask)); + + const bool alpha = (flags & ImGuiColorEditFlags_NoAlpha) == 0; + const bool hdr = (flags & ImGuiColorEditFlags_HDR) != 0; + const int components = alpha ? 4 : 3; + + // Convert to the formats we need + float f[4] = { col[0], col[1], col[2], alpha ? col[3] : 1.0f }; + if (flags & ImGuiColorEditFlags_HSV) + ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); + int i[4] = { IM_F32_TO_INT8_UNBOUND(f[0]), IM_F32_TO_INT8_UNBOUND(f[1]), IM_F32_TO_INT8_UNBOUND(f[2]), IM_F32_TO_INT8_UNBOUND(f[3]) }; + + bool value_changed = false; + bool value_changed_as_float = false; + + if ((flags & (ImGuiColorEditFlags_RGB | ImGuiColorEditFlags_HSV)) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0) + { + // RGB/HSV 0..255 Sliders + const float w_item_one = ImMax(1.0f, (float)(int)((w_items_all - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); + const float w_item_last = ImMax(1.0f, (float)(int)(w_items_all - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); + + const bool hide_prefix = (w_item_one <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? "M:0.000" : "M:000").x); + const char* ids[4] = { "##X", "##Y", "##Z", "##W" }; + const char* fmt_table_int[3][4] = + { + { "%3d", "%3d", "%3d", "%3d" }, // Short display + { "R:%3d", "G:%3d", "B:%3d", "A:%3d" }, // Long display for RGBA + { "H:%3d", "S:%3d", "V:%3d", "A:%3d" } // Long display for HSVA + }; + const char* fmt_table_float[3][4] = + { + { "%0.3f", "%0.3f", "%0.3f", "%0.3f" }, // Short display + { "R:%0.3f", "G:%0.3f", "B:%0.3f", "A:%0.3f" }, // Long display for RGBA + { "H:%0.3f", "S:%0.3f", "V:%0.3f", "A:%0.3f" } // Long display for HSVA + }; + const int fmt_idx = hide_prefix ? 0 : (flags & ImGuiColorEditFlags_HSV) ? 2 : 1; + + PushItemWidth(w_item_one); + for (int n = 0; n < components; n++) + { + if (n > 0) + SameLine(0, style.ItemInnerSpacing.x); + if (n + 1 == components) + PushItemWidth(w_item_last); + if (flags & ImGuiColorEditFlags_Float) + value_changed = value_changed_as_float = value_changed | DragFloat(ids[n], &f[n], 1.0f/255.0f, 0.0f, hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]); + else + value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, hdr ? 0 : 255, fmt_table_int[fmt_idx][n]); + if (!(flags & ImGuiColorEditFlags_NoOptions)) + OpenPopupOnItemClick("context"); + } + PopItemWidth(); + PopItemWidth(); + } + else if ((flags & ImGuiColorEditFlags_HEX) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0) + { + // RGB Hexadecimal Input + char buf[64]; + if (alpha) + ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", ImClamp(i[0],0,255), ImClamp(i[1],0,255), ImClamp(i[2],0,255), ImClamp(i[3],0,255)); + else + ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp(i[0],0,255), ImClamp(i[1],0,255), ImClamp(i[2],0,255)); + PushItemWidth(w_items_all); + if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase)) + { + value_changed = true; + char* p = buf; + while (*p == '#' || ImCharIsBlankA(*p)) + p++; + i[0] = i[1] = i[2] = i[3] = 0; + if (alpha) + sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); // Treat at unsigned (%X is unsigned) + else + sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]); + } + if (!(flags & ImGuiColorEditFlags_NoOptions)) + OpenPopupOnItemClick("context"); + PopItemWidth(); + } + + ImGuiWindow* picker_active_window = NULL; + if (!(flags & ImGuiColorEditFlags_NoSmallPreview)) + { + if (!(flags & ImGuiColorEditFlags_NoInputs)) + SameLine(0, style.ItemInnerSpacing.x); + + const ImVec4 col_v4(col[0], col[1], col[2], alpha ? col[3] : 1.0f); + if (ColorButton("##ColorButton", col_v4, flags)) + { + if (!(flags & ImGuiColorEditFlags_NoPicker)) + { + // Store current color and open a picker + g.ColorPickerRef = col_v4; + OpenPopup("picker"); + SetNextWindowPos(window->DC.LastItemRect.GetBL() + ImVec2(-1,style.ItemSpacing.y)); + } + } + if (!(flags & ImGuiColorEditFlags_NoOptions)) + OpenPopupOnItemClick("context"); + + if (BeginPopup("picker")) + { + picker_active_window = g.CurrentWindow; + if (label != label_display_end) + { + TextUnformatted(label, label_display_end); + Separator(); + } + ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__PickerMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar; + ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags__InputsMask | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf; + PushItemWidth(square_sz * 12.0f); // Use 256 + bar sizes? + value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x); + PopItemWidth(); + EndPopup(); + } + } + + if (label != label_display_end && !(flags & ImGuiColorEditFlags_NoLabel)) + { + SameLine(0, style.ItemInnerSpacing.x); + TextUnformatted(label, label_display_end); + } + + // Convert back + if (picker_active_window == NULL) + { + if (!value_changed_as_float) + for (int n = 0; n < 4; n++) + f[n] = i[n] / 255.0f; + if (flags & ImGuiColorEditFlags_HSV) + ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); + if (value_changed) + { + col[0] = f[0]; + col[1] = f[1]; + col[2] = f[2]; + if (alpha) + col[3] = f[3]; + } + } + + PopID(); + EndGroup(); + + // Drag and Drop Target + // NB: The flag test is merely an optional micro-optimization, BeginDragDropTarget() does the same test. + if ((window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropTarget()) + { + if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) + { + memcpy((float*)col, payload->Data, sizeof(float) * 3); + value_changed = true; + } + if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F)) + { + memcpy((float*)col, payload->Data, sizeof(float) * components); + value_changed = true; + } + EndDragDropTarget(); + } + + // When picker is being actively used, use its active id so IsItemActive() will function on ColorEdit4(). + if (picker_active_window && g.ActiveId != 0 && g.ActiveIdWindow == picker_active_window) + window->DC.LastItemId = g.ActiveId; + + if (value_changed) + MarkItemValueChanged(window->DC.LastItemId); + + return value_changed; +} + +bool ImGui::ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags) +{ + float col4[4] = { col[0], col[1], col[2], 1.0f }; + if (!ColorPicker4(label, col4, flags | ImGuiColorEditFlags_NoAlpha)) + return false; + col[0] = col4[0]; col[1] = col4[1]; col[2] = col4[2]; + return true; +} + +static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w) +{ + ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x + 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Right, IM_COL32_BLACK); + ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x, pos.y), half_sz, ImGuiDir_Right, IM_COL32_WHITE); + ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x - 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Left, IM_COL32_BLACK); + ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x, pos.y), half_sz, ImGuiDir_Left, IM_COL32_WHITE); +} + +// ColorPicker +// Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. +// FIXME: we adjust the big color square height based on item width, which may cause a flickering feedback loop (if automatic height makes a vertical scrollbar appears, affecting automatic width..) +bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + ImDrawList* draw_list = window->DrawList; + + ImGuiStyle& style = g.Style; + ImGuiIO& io = g.IO; + + PushID(label); + BeginGroup(); + + if (!(flags & ImGuiColorEditFlags_NoSidePreview)) + flags |= ImGuiColorEditFlags_NoSmallPreview; + + // Context menu: display and store options. + if (!(flags & ImGuiColorEditFlags_NoOptions)) + ColorPickerOptionsPopup(flags, col); + + // Read stored options + if (!(flags & ImGuiColorEditFlags__PickerMask)) + flags |= ((g.ColorEditOptions & ImGuiColorEditFlags__PickerMask) ? g.ColorEditOptions : ImGuiColorEditFlags__OptionsDefault) & ImGuiColorEditFlags__PickerMask; + IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__PickerMask))); // Check that only 1 is selected + if (!(flags & ImGuiColorEditFlags_NoOptions)) + flags |= (g.ColorEditOptions & ImGuiColorEditFlags_AlphaBar); + + // Setup + int components = (flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4; + bool alpha_bar = (flags & ImGuiColorEditFlags_AlphaBar) && !(flags & ImGuiColorEditFlags_NoAlpha); + ImVec2 picker_pos = window->DC.CursorPos; + float square_sz = GetFrameHeight(); + float bars_width = square_sz; // Arbitrary smallish width of Hue/Alpha picking bars + float sv_picker_size = ImMax(bars_width * 1, CalcItemWidth() - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box + float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x; + float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x; + float bars_triangles_half_sz = (float)(int)(bars_width * 0.20f); + + float backup_initial_col[4]; + memcpy(backup_initial_col, col, components * sizeof(float)); + + float wheel_thickness = sv_picker_size * 0.08f; + float wheel_r_outer = sv_picker_size * 0.50f; + float wheel_r_inner = wheel_r_outer - wheel_thickness; + ImVec2 wheel_center(picker_pos.x + (sv_picker_size + bars_width)*0.5f, picker_pos.y + sv_picker_size*0.5f); + + // Note: the triangle is displayed rotated with triangle_pa pointing to Hue, but most coordinates stays unrotated for logic. + float triangle_r = wheel_r_inner - (int)(sv_picker_size * 0.027f); + ImVec2 triangle_pa = ImVec2(triangle_r, 0.0f); // Hue point. + ImVec2 triangle_pb = ImVec2(triangle_r * -0.5f, triangle_r * -0.866025f); // Black point. + ImVec2 triangle_pc = ImVec2(triangle_r * -0.5f, triangle_r * +0.866025f); // White point. + + float H,S,V; + ColorConvertRGBtoHSV(col[0], col[1], col[2], H, S, V); + + bool value_changed = false, value_changed_h = false, value_changed_sv = false; + + PushItemFlag(ImGuiItemFlags_NoNav, true); + if (flags & ImGuiColorEditFlags_PickerHueWheel) + { + // Hue wheel + SV triangle logic + InvisibleButton("hsv", ImVec2(sv_picker_size + style.ItemInnerSpacing.x + bars_width, sv_picker_size)); + if (IsItemActive()) + { + ImVec2 initial_off = g.IO.MouseClickedPos[0] - wheel_center; + ImVec2 current_off = g.IO.MousePos - wheel_center; + float initial_dist2 = ImLengthSqr(initial_off); + if (initial_dist2 >= (wheel_r_inner-1)*(wheel_r_inner-1) && initial_dist2 <= (wheel_r_outer+1)*(wheel_r_outer+1)) + { + // Interactive with Hue wheel + H = ImAtan2(current_off.y, current_off.x) / IM_PI*0.5f; + if (H < 0.0f) + H += 1.0f; + value_changed = value_changed_h = true; + } + float cos_hue_angle = ImCos(-H * 2.0f * IM_PI); + float sin_hue_angle = ImSin(-H * 2.0f * IM_PI); + if (ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, ImRotate(initial_off, cos_hue_angle, sin_hue_angle))) + { + // Interacting with SV triangle + ImVec2 current_off_unrotated = ImRotate(current_off, cos_hue_angle, sin_hue_angle); + if (!ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated)) + current_off_unrotated = ImTriangleClosestPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated); + float uu, vv, ww; + ImTriangleBarycentricCoords(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated, uu, vv, ww); + V = ImClamp(1.0f - vv, 0.0001f, 1.0f); + S = ImClamp(uu / V, 0.0001f, 1.0f); + value_changed = value_changed_sv = true; + } + } + if (!(flags & ImGuiColorEditFlags_NoOptions)) + OpenPopupOnItemClick("context"); + } + else if (flags & ImGuiColorEditFlags_PickerHueBar) + { + // SV rectangle logic + InvisibleButton("sv", ImVec2(sv_picker_size, sv_picker_size)); + if (IsItemActive()) + { + S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size-1)); + V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1)); + value_changed = value_changed_sv = true; + } + if (!(flags & ImGuiColorEditFlags_NoOptions)) + OpenPopupOnItemClick("context"); + + // Hue bar logic + SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y)); + InvisibleButton("hue", ImVec2(bars_width, sv_picker_size)); + if (IsItemActive()) + { + H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1)); + value_changed = value_changed_h = true; + } + } + + // Alpha bar logic + if (alpha_bar) + { + SetCursorScreenPos(ImVec2(bar1_pos_x, picker_pos.y)); + InvisibleButton("alpha", ImVec2(bars_width, sv_picker_size)); + if (IsItemActive()) + { + col[3] = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1)); + value_changed = true; + } + } + PopItemFlag(); // ImGuiItemFlags_NoNav + + if (!(flags & ImGuiColorEditFlags_NoSidePreview)) + { + SameLine(0, style.ItemInnerSpacing.x); + BeginGroup(); + } + + if (!(flags & ImGuiColorEditFlags_NoLabel)) + { + const char* label_display_end = FindRenderedTextEnd(label); + if (label != label_display_end) + { + if ((flags & ImGuiColorEditFlags_NoSidePreview)) + SameLine(0, style.ItemInnerSpacing.x); + TextUnformatted(label, label_display_end); + } + } + + if (!(flags & ImGuiColorEditFlags_NoSidePreview)) + { + PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true); + ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); + if ((flags & ImGuiColorEditFlags_NoLabel)) + Text("Current"); + ColorButton("##current", col_v4, (flags & (ImGuiColorEditFlags_HDR|ImGuiColorEditFlags_AlphaPreview|ImGuiColorEditFlags_AlphaPreviewHalf|ImGuiColorEditFlags_NoTooltip)), ImVec2(square_sz * 3, square_sz * 2)); + if (ref_col != NULL) + { + Text("Original"); + ImVec4 ref_col_v4(ref_col[0], ref_col[1], ref_col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : ref_col[3]); + if (ColorButton("##original", ref_col_v4, (flags & (ImGuiColorEditFlags_HDR|ImGuiColorEditFlags_AlphaPreview|ImGuiColorEditFlags_AlphaPreviewHalf|ImGuiColorEditFlags_NoTooltip)), ImVec2(square_sz * 3, square_sz * 2))) + { + memcpy(col, ref_col, components * sizeof(float)); + value_changed = true; + } + } + PopItemFlag(); + EndGroup(); + } + + // Convert back color to RGB + if (value_changed_h || value_changed_sv) + ColorConvertHSVtoRGB(H >= 1.0f ? H - 10 * 1e-6f : H, S > 0.0f ? S : 10*1e-6f, V > 0.0f ? V : 1e-6f, col[0], col[1], col[2]); + + // R,G,B and H,S,V slider color editor + if ((flags & ImGuiColorEditFlags_NoInputs) == 0) + { + PushItemWidth((alpha_bar ? bar1_pos_x : bar0_pos_x) + bars_width - picker_pos.x); + ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoSmallPreview | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf; + ImGuiColorEditFlags sub_flags = (flags & sub_flags_to_forward) | ImGuiColorEditFlags_NoPicker; + if (flags & ImGuiColorEditFlags_RGB || (flags & ImGuiColorEditFlags__InputsMask) == 0) + value_changed |= ColorEdit4("##rgb", col, sub_flags | ImGuiColorEditFlags_RGB); + if (flags & ImGuiColorEditFlags_HSV || (flags & ImGuiColorEditFlags__InputsMask) == 0) + value_changed |= ColorEdit4("##hsv", col, sub_flags | ImGuiColorEditFlags_HSV); + if (flags & ImGuiColorEditFlags_HEX || (flags & ImGuiColorEditFlags__InputsMask) == 0) + value_changed |= ColorEdit4("##hex", col, sub_flags | ImGuiColorEditFlags_HEX); + PopItemWidth(); + } + + // Try to cancel hue wrap (after ColorEdit), if any + if (value_changed) + { + float new_H, new_S, new_V; + ColorConvertRGBtoHSV(col[0], col[1], col[2], new_H, new_S, new_V); + if (new_H <= 0 && H > 0) + { + if (new_V <= 0 && V != new_V) + ColorConvertHSVtoRGB(H, S, new_V <= 0 ? V * 0.5f : new_V, col[0], col[1], col[2]); + else if (new_S <= 0) + ColorConvertHSVtoRGB(H, new_S <= 0 ? S * 0.5f : new_S, new_V, col[0], col[1], col[2]); + } + } + + ImVec4 hue_color_f(1, 1, 1, 1); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z); + ImU32 hue_color32 = ColorConvertFloat4ToU32(hue_color_f); + ImU32 col32_no_alpha = ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 1.0f)); + + const ImU32 hue_colors[6+1] = { IM_COL32(255,0,0,255), IM_COL32(255,255,0,255), IM_COL32(0,255,0,255), IM_COL32(0,255,255,255), IM_COL32(0,0,255,255), IM_COL32(255,0,255,255), IM_COL32(255,0,0,255) }; + ImVec2 sv_cursor_pos; + + if (flags & ImGuiColorEditFlags_PickerHueWheel) + { + // Render Hue Wheel + const float aeps = 1.5f / wheel_r_outer; // Half a pixel arc length in radians (2pi cancels out). + const int segment_per_arc = ImMax(4, (int)wheel_r_outer / 12); + for (int n = 0; n < 6; n++) + { + const float a0 = (n) /6.0f * 2.0f * IM_PI - aeps; + const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps; + const int vert_start_idx = draw_list->VtxBuffer.Size; + draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc); + draw_list->PathStroke(IM_COL32_WHITE, false, wheel_thickness); + const int vert_end_idx = draw_list->VtxBuffer.Size; + + // Paint colors over existing vertices + ImVec2 gradient_p0(wheel_center.x + ImCos(a0) * wheel_r_inner, wheel_center.y + ImSin(a0) * wheel_r_inner); + ImVec2 gradient_p1(wheel_center.x + ImCos(a1) * wheel_r_inner, wheel_center.y + ImSin(a1) * wheel_r_inner); + ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, hue_colors[n], hue_colors[n+1]); + } + + // Render Cursor + preview on Hue Wheel + float cos_hue_angle = ImCos(H * 2.0f * IM_PI); + float sin_hue_angle = ImSin(H * 2.0f * IM_PI); + ImVec2 hue_cursor_pos(wheel_center.x + cos_hue_angle * (wheel_r_inner+wheel_r_outer)*0.5f, wheel_center.y + sin_hue_angle * (wheel_r_inner+wheel_r_outer)*0.5f); + float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f; + int hue_cursor_segments = ImClamp((int)(hue_cursor_rad / 1.4f), 9, 32); + draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments); + draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad+1, IM_COL32(128,128,128,255), hue_cursor_segments); + draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, IM_COL32_WHITE, hue_cursor_segments); + + // Render SV triangle (rotated according to hue) + ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle); + ImVec2 trb = wheel_center + ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle); + ImVec2 trc = wheel_center + ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle); + ImVec2 uv_white = GetFontTexUvWhitePixel(); + draw_list->PrimReserve(6, 6); + draw_list->PrimVtx(tra, uv_white, hue_color32); + draw_list->PrimVtx(trb, uv_white, hue_color32); + draw_list->PrimVtx(trc, uv_white, IM_COL32_WHITE); + draw_list->PrimVtx(tra, uv_white, IM_COL32_BLACK_TRANS); + draw_list->PrimVtx(trb, uv_white, IM_COL32_BLACK); + draw_list->PrimVtx(trc, uv_white, IM_COL32_BLACK_TRANS); + draw_list->AddTriangle(tra, trb, trc, IM_COL32(128,128,128,255), 1.5f); + sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V)); + } + else if (flags & ImGuiColorEditFlags_PickerHueBar) + { + // Render SV Square + draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_WHITE, hue_color32, hue_color32, IM_COL32_WHITE); + draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_BLACK_TRANS, IM_COL32_BLACK_TRANS, IM_COL32_BLACK, IM_COL32_BLACK); + RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), 0.0f); + sv_cursor_pos.x = ImClamp((float)(int)(picker_pos.x + ImSaturate(S) * sv_picker_size + 0.5f), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2); // Sneakily prevent the circle to stick out too much + sv_cursor_pos.y = ImClamp((float)(int)(picker_pos.y + ImSaturate(1 - V) * sv_picker_size + 0.5f), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2); + + // Render Hue Bar + for (int i = 0; i < 6; ++i) + draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), hue_colors[i], hue_colors[i], hue_colors[i + 1], hue_colors[i + 1]); + float bar0_line_y = (float)(int)(picker_pos.y + H * sv_picker_size + 0.5f); + RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f); + RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f); + } + + // Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range) + float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f; + draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, col32_no_alpha, 12); + draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad+1, IM_COL32(128,128,128,255), 12); + draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, IM_COL32_WHITE, 12); + + // Render alpha bar + if (alpha_bar) + { + float alpha = ImSaturate(col[3]); + ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size); + RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, IM_COL32(0,0,0,0), bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f)); + draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, col32_no_alpha, col32_no_alpha, col32_no_alpha & ~IM_COL32_A_MASK, col32_no_alpha & ~IM_COL32_A_MASK); + float bar1_line_y = (float)(int)(picker_pos.y + (1.0f - alpha) * sv_picker_size + 0.5f); + RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f); + RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f); + } + + EndGroup(); + + if (value_changed && memcmp(backup_initial_col, col, components * sizeof(float)) == 0) + value_changed = false; + if (value_changed) + MarkItemValueChanged(window->DC.LastItemId); + + PopID(); + + return value_changed; +} + +// Horizontal/vertical separating line +void ImGui::Separator() +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + ImGuiContext& g = *GImGui; + + // Those flags should eventually be overridable by the user + ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal; + IM_ASSERT(ImIsPowerOfTwo((int)(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical)))); // Check that only 1 option is selected + if (flags & ImGuiSeparatorFlags_Vertical) + { + VerticalSeparator(); + return; + } + + // Horizontal Separator + if (window->DC.ColumnsSet) + PopClipRect(); + + float x1 = window->Pos.x; + float x2 = window->Pos.x + window->Size.x; + if (!window->DC.GroupStack.empty()) + x1 += window->DC.IndentX; + + const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y+1.0f)); + ItemSize(ImVec2(0.0f, 0.0f)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit, we don't provide height to not alter layout. + if (!ItemAdd(bb, 0)) + { + if (window->DC.ColumnsSet) + PushColumnClipRect(); + return; + } + + window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x,bb.Min.y), GetColorU32(ImGuiCol_Separator)); + + if (g.LogEnabled) + LogRenderedText(NULL, IM_NEWLINE "--------------------------------"); + + if (window->DC.ColumnsSet) + { + PushColumnClipRect(); + window->DC.ColumnsSet->LineMinY = window->DC.CursorPos.y; + } +} + +void ImGui::VerticalSeparator() +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + ImGuiContext& g = *GImGui; + + float y1 = window->DC.CursorPos.y; + float y2 = window->DC.CursorPos.y + window->DC.CurrentLineHeight; + const ImRect bb(ImVec2(window->DC.CursorPos.x, y1), ImVec2(window->DC.CursorPos.x + 1.0f, y2)); + ItemSize(ImVec2(bb.GetWidth(), 0.0f)); + if (!ItemAdd(bb, 0)) + return; + + window->DrawList->AddLine(ImVec2(bb.Min.x, bb.Min.y), ImVec2(bb.Min.x, bb.Max.y), GetColorU32(ImGuiCol_Separator)); + if (g.LogEnabled) + LogText(" |"); +} + +// Using 'hover_visibility_delay' allows us to hide the highlight and mouse cursor for a short time, which can be convenient to reduce visual noise. +bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend, float hover_visibility_delay) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags; + window->DC.ItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus; + bool item_add = ItemAdd(bb, id); + window->DC.ItemFlags = item_flags_backup; + if (!item_add) + return false; + + bool hovered, held; + ImRect bb_interact = bb; + bb_interact.Expand(axis == ImGuiAxis_Y ? ImVec2(0.0f, hover_extend) : ImVec2(hover_extend, 0.0f)); + ButtonBehavior(bb_interact, id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap); + if (g.ActiveId != id) + SetItemAllowOverlap(); + + if (held || (g.HoveredId == id && g.HoveredIdPreviousFrame == id && g.HoveredIdTimer >= hover_visibility_delay)) + SetMouseCursor(axis == ImGuiAxis_Y ? ImGuiMouseCursor_ResizeNS : ImGuiMouseCursor_ResizeEW); + + ImRect bb_render = bb; + if (held) + { + ImVec2 mouse_delta_2d = g.IO.MousePos - g.ActiveIdClickOffset - bb_interact.Min; + float mouse_delta = (axis == ImGuiAxis_Y) ? mouse_delta_2d.y : mouse_delta_2d.x; + + // Minimum pane size + float size_1_maximum_delta = ImMax(0.0f, *size1 - min_size1); + float size_2_maximum_delta = ImMax(0.0f, *size2 - min_size2); + if (mouse_delta < -size_1_maximum_delta) + mouse_delta = -size_1_maximum_delta; + if (mouse_delta > size_2_maximum_delta) + mouse_delta = size_2_maximum_delta; + + // Apply resize + if (mouse_delta != 0.0f) + { + if (mouse_delta < 0.0f) + IM_ASSERT(*size1 + mouse_delta >= min_size1); + if (mouse_delta > 0.0f) + IM_ASSERT(*size2 - mouse_delta >= min_size2); + *size1 += mouse_delta; + *size2 -= mouse_delta; + bb_render.Translate((axis == ImGuiAxis_X) ? ImVec2(mouse_delta, 0.0f) : ImVec2(0.0f, mouse_delta)); + MarkItemValueChanged(id); + } + } + + // Render + const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : (hovered && g.HoveredIdTimer >= hover_visibility_delay) ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); + window->DrawList->AddRectFilled(bb_render.Min, bb_render.Max, col, g.Style.FrameRounding); + + return held; +} + +void ImGui::Spacing() +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + ItemSize(ImVec2(0,0)); +} + +void ImGui::Dummy(const ImVec2& size) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + + const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); + ItemSize(bb); + ItemAdd(bb, 0); +} + +bool ImGui::IsRectVisible(const ImVec2& size) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size)); +} + +bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->ClipRect.Overlaps(ImRect(rect_min, rect_max)); +} + +// Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) +void ImGui::BeginGroup() +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + + window->DC.GroupStack.resize(window->DC.GroupStack.Size + 1); + ImGuiGroupData& group_data = window->DC.GroupStack.back(); + group_data.BackupCursorPos = window->DC.CursorPos; + group_data.BackupCursorMaxPos = window->DC.CursorMaxPos; + group_data.BackupIndentX = window->DC.IndentX; + group_data.BackupGroupOffsetX = window->DC.GroupOffsetX; + group_data.BackupCurrentLineHeight = window->DC.CurrentLineHeight; + group_data.BackupCurrentLineTextBaseOffset = window->DC.CurrentLineTextBaseOffset; + group_data.BackupLogLinePosY = window->DC.LogLinePosY; + group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive; + group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive; + group_data.AdvanceCursor = true; + + window->DC.GroupOffsetX = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffsetX; + window->DC.IndentX = window->DC.GroupOffsetX; + window->DC.CursorMaxPos = window->DC.CursorPos; + window->DC.CurrentLineHeight = 0.0f; + window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; // To enforce Log carriage return +} + +void ImGui::EndGroup() +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls + + ImGuiGroupData& group_data = window->DC.GroupStack.back(); + + ImRect group_bb(group_data.BackupCursorPos, window->DC.CursorMaxPos); + group_bb.Max = ImMax(group_bb.Min, group_bb.Max); + + window->DC.CursorPos = group_data.BackupCursorPos; + window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos); + window->DC.IndentX = group_data.BackupIndentX; + window->DC.GroupOffsetX = group_data.BackupGroupOffsetX; + window->DC.CurrentLineHeight = group_data.BackupCurrentLineHeight; + window->DC.CurrentLineTextBaseOffset = group_data.BackupCurrentLineTextBaseOffset; + window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; // To enforce Log carriage return + + if (group_data.AdvanceCursor) + { + window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrentLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now. + ItemSize(group_bb.GetSize(), group_data.BackupCurrentLineTextBaseOffset); + ItemAdd(group_bb, 0); + } + + // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive(), IsItemDeactivated() etc. will be functional on the entire group. + // It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but put a little more burden on individual widgets. + // (and if you grep for LastItemId you'll notice it is only used in that context. + if ((group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId) // && g.ActiveIdWindow->RootWindow == window->RootWindow) + window->DC.LastItemId = g.ActiveId; + else if (!group_data.BackupActiveIdPreviousFrameIsAlive && g.ActiveIdPreviousFrameIsAlive) // && g.ActiveIdPreviousFrameWindow->RootWindow == window->RootWindow) + window->DC.LastItemId = g.ActiveIdPreviousFrame; + window->DC.LastItemRect = group_bb; + + window->DC.GroupStack.pop_back(); + + //window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // [Debug] +} + +// Gets back to previous line and continue with horizontal layout +// pos_x == 0 : follow right after previous item +// pos_x != 0 : align to specified x position (relative to window/group left) +// spacing_w < 0 : use default spacing if pos_x == 0, no spacing if pos_x != 0 +// spacing_w >= 0 : enforce spacing amount +void ImGui::SameLine(float pos_x, float spacing_w) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + + ImGuiContext& g = *GImGui; + if (pos_x != 0.0f) + { + if (spacing_w < 0.0f) spacing_w = 0.0f; + window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + pos_x + spacing_w + window->DC.GroupOffsetX + window->DC.ColumnsOffsetX; + window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y; + } + else + { + if (spacing_w < 0.0f) spacing_w = g.Style.ItemSpacing.x; + window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w; + window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y; + } + window->DC.CurrentLineHeight = window->DC.PrevLineHeight; + window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset; +} + +void ImGui::NewLine() +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + + ImGuiContext& g = *GImGui; + const ImGuiLayoutType backup_layout_type = window->DC.LayoutType; + window->DC.LayoutType = ImGuiLayoutType_Vertical; + if (window->DC.CurrentLineHeight > 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height. + ItemSize(ImVec2(0,0)); + else + ItemSize(ImVec2(0.0f, g.FontSize)); + window->DC.LayoutType = backup_layout_type; +} + +void ImGui::NextColumn() +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems || window->DC.ColumnsSet == NULL) + return; + + ImGuiContext& g = *GImGui; + PopItemWidth(); + PopClipRect(); + + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y); + if (++columns->Current < columns->Count) + { + // Columns 1+ cancel out IndentX + window->DC.ColumnsOffsetX = GetColumnOffset(columns->Current) - window->DC.IndentX + g.Style.ItemSpacing.x; + window->DrawList->ChannelsSetCurrent(columns->Current); + } + else + { + window->DC.ColumnsOffsetX = 0.0f; + window->DrawList->ChannelsSetCurrent(0); + columns->Current = 0; + columns->LineMinY = columns->LineMaxY; + } + window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); + window->DC.CursorPos.y = columns->LineMinY; + window->DC.CurrentLineHeight = 0.0f; + window->DC.CurrentLineTextBaseOffset = 0.0f; + + PushColumnClipRect(); + PushItemWidth(GetColumnWidth() * 0.65f); // FIXME: Move on columns setup +} + +int ImGui::GetColumnIndex() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->DC.ColumnsSet ? window->DC.ColumnsSet->Current : 0; +} + +int ImGui::GetColumnsCount() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->DC.ColumnsSet ? window->DC.ColumnsSet->Count : 1; +} + +static float OffsetNormToPixels(const ImGuiColumnsSet* columns, float offset_norm) +{ + return offset_norm * (columns->MaxX - columns->MinX); +} + +static float PixelsToOffsetNorm(const ImGuiColumnsSet* columns, float offset) +{ + return offset / (columns->MaxX - columns->MinX); +} + +static inline float GetColumnsRectHalfWidth() { return 4.0f; } + +static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, int column_index) +{ + // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing + // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning. + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + IM_ASSERT(column_index > 0); // We are not supposed to drag column 0. + IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index)); + + float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + GetColumnsRectHalfWidth() - window->Pos.x; + x = ImMax(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing); + if ((columns->Flags & ImGuiColumnsFlags_NoPreserveWidths)) + x = ImMin(x, ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing); + + return x; +} + +float ImGui::GetColumnOffset(int column_index) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); + + if (column_index < 0) + column_index = columns->Current; + IM_ASSERT(column_index < columns->Columns.Size); + + const float t = columns->Columns[column_index].OffsetNorm; + const float x_offset = ImLerp(columns->MinX, columns->MaxX, t); + return x_offset; +} + +static float GetColumnWidthEx(ImGuiColumnsSet* columns, int column_index, bool before_resize = false) +{ + if (column_index < 0) + column_index = columns->Current; + + float offset_norm; + if (before_resize) + offset_norm = columns->Columns[column_index + 1].OffsetNormBeforeResize - columns->Columns[column_index].OffsetNormBeforeResize; + else + offset_norm = columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm; + return OffsetNormToPixels(columns, offset_norm); +} + +float ImGui::GetColumnWidth(int column_index) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); + + if (column_index < 0) + column_index = columns->Current; + return OffsetNormToPixels(columns, columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm); +} + +void ImGui::SetColumnOffset(int column_index, float offset) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); + + if (column_index < 0) + column_index = columns->Current; + IM_ASSERT(column_index < columns->Columns.Size); + + const bool preserve_width = !(columns->Flags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->Count-1); + const float width = preserve_width ? GetColumnWidthEx(columns, column_index, columns->IsBeingResized) : 0.0f; + + if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) + offset = ImMin(offset, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index)); + columns->Columns[column_index].OffsetNorm = PixelsToOffsetNorm(columns, offset - columns->MinX); + + if (preserve_width) + SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); +} + +void ImGui::SetColumnWidth(int column_index, float width) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); + + if (column_index < 0) + column_index = columns->Current; + SetColumnOffset(column_index + 1, GetColumnOffset(column_index) + width); +} + +void ImGui::PushColumnClipRect(int column_index) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + if (column_index < 0) + column_index = columns->Current; + + PushClipRect(columns->Columns[column_index].ClipRect.Min, columns->Columns[column_index].ClipRect.Max, false); +} + +static ImGuiColumnsSet* FindOrAddColumnsSet(ImGuiWindow* window, ImGuiID id) +{ + for (int n = 0; n < window->ColumnsStorage.Size; n++) + if (window->ColumnsStorage[n].ID == id) + return &window->ColumnsStorage[n]; + + window->ColumnsStorage.push_back(ImGuiColumnsSet()); + ImGuiColumnsSet* columns = &window->ColumnsStorage.back(); + columns->ID = id; + return columns; +} + +void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlags flags) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + + IM_ASSERT(columns_count > 1); + IM_ASSERT(window->DC.ColumnsSet == NULL); // Nested columns are currently not supported + + // Differentiate column ID with an arbitrary prefix for cases where users name their columns set the same as another widget. + // In addition, when an identifier isn't explicitly provided we include the number of columns in the hash to make it uniquer. + PushID(0x11223347 + (str_id ? 0 : columns_count)); + ImGuiID id = window->GetID(str_id ? str_id : "columns"); + PopID(); + + // Acquire storage for the columns set + ImGuiColumnsSet* columns = FindOrAddColumnsSet(window, id); + IM_ASSERT(columns->ID == id); + columns->Current = 0; + columns->Count = columns_count; + columns->Flags = flags; + window->DC.ColumnsSet = columns; + + // Set state for first column + const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->InnerClipRect.Max.x - window->Pos.x); + columns->MinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range + columns->MaxX = ImMax(content_region_width - window->Scroll.x, columns->MinX + 1.0f); + columns->StartPosY = window->DC.CursorPos.y; + columns->StartMaxPosX = window->DC.CursorMaxPos.x; + columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y; + window->DC.ColumnsOffsetX = 0.0f; + window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); + + // Clear data if columns count changed + if (columns->Columns.Size != 0 && columns->Columns.Size != columns_count + 1) + columns->Columns.resize(0); + + // Initialize defaults + columns->IsFirstFrame = (columns->Columns.Size == 0); + if (columns->Columns.Size == 0) + { + columns->Columns.reserve(columns_count + 1); + for (int n = 0; n < columns_count + 1; n++) + { + ImGuiColumnData column; + column.OffsetNorm = n / (float)columns_count; + columns->Columns.push_back(column); + } + } + + for (int n = 0; n < columns_count; n++) + { + // Compute clipping rectangle + ImGuiColumnData* column = &columns->Columns[n]; + float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n) - 1.0f); + float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n + 1) - 1.0f); + column->ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); + column->ClipRect.ClipWith(window->ClipRect); + } + + window->DrawList->ChannelsSplit(columns->Count); + PushColumnClipRect(); + PushItemWidth(GetColumnWidth() * 0.65f); +} + +void ImGui::EndColumns() +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); + + PopItemWidth(); + PopClipRect(); + window->DrawList->ChannelsMerge(); + + columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y); + window->DC.CursorPos.y = columns->LineMaxY; + if (!(columns->Flags & ImGuiColumnsFlags_GrowParentContentsSize)) + window->DC.CursorMaxPos.x = columns->StartMaxPosX; // Restore cursor max pos, as columns don't grow parent + + // Draw columns borders and handle resize + bool is_being_resized = false; + if (!(columns->Flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) + { + const float y1 = columns->StartPosY; + const float y2 = window->DC.CursorPos.y; + int dragging_column = -1; + for (int n = 1; n < columns->Count; n++) + { + float x = window->Pos.x + GetColumnOffset(n); + const ImGuiID column_id = columns->ID + ImGuiID(n); + const float column_hw = GetColumnsRectHalfWidth(); // Half-width for interaction + const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2)); + KeepAliveID(column_id); + if (IsClippedEx(column_rect, column_id, false)) + continue; + + bool hovered = false, held = false; + if (!(columns->Flags & ImGuiColumnsFlags_NoResize)) + { + ButtonBehavior(column_rect, column_id, &hovered, &held); + if (hovered || held) + g.MouseCursor = ImGuiMouseCursor_ResizeEW; + if (held && !(columns->Columns[n].Flags & ImGuiColumnsFlags_NoResize)) + dragging_column = n; + } + + // Draw column (we clip the Y boundaries CPU side because very long triangles are mishandled by some GPU drivers.) + const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); + const float xi = (float)(int)x; + window->DrawList->AddLine(ImVec2(xi, ImMax(y1 + 1.0f, window->ClipRect.Min.y)), ImVec2(xi, ImMin(y2, window->ClipRect.Max.y)), col); + } + + // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame. + if (dragging_column != -1) + { + if (!columns->IsBeingResized) + for (int n = 0; n < columns->Count + 1; n++) + columns->Columns[n].OffsetNormBeforeResize = columns->Columns[n].OffsetNorm; + columns->IsBeingResized = is_being_resized = true; + float x = GetDraggedColumnOffset(columns, dragging_column); + SetColumnOffset(dragging_column, x); + } + } + columns->IsBeingResized = is_being_resized; + + window->DC.ColumnsSet = NULL; + window->DC.ColumnsOffsetX = 0.0f; + window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); +} + +// [2018-03: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing] +void ImGui::Columns(int columns_count, const char* id, bool border) +{ + ImGuiWindow* window = GetCurrentWindow(); + IM_ASSERT(columns_count >= 1); + + ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder); + //flags |= ImGuiColumnsFlags_NoPreserveWidths; // NB: Legacy behavior + if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->Count == columns_count && window->DC.ColumnsSet->Flags == flags) + return; + + if (window->DC.ColumnsSet != NULL) + EndColumns(); + + if (columns_count != 1) + BeginColumns(id, columns_count, flags); +} + +void ImGui::Indent(float indent_w) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + window->DC.IndentX += (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing; + window->DC.CursorPos.x = window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX; +} + +void ImGui::Unindent(float indent_w) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + window->DC.IndentX -= (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing; + window->DC.CursorPos.x = window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX; +} + +void ImGui::TreePush(const char* str_id) +{ + ImGuiWindow* window = GetCurrentWindow(); + Indent(); + window->DC.TreeDepth++; + PushID(str_id ? str_id : "#TreePush"); +} + +void ImGui::TreePush(const void* ptr_id) +{ + ImGuiWindow* window = GetCurrentWindow(); + Indent(); + window->DC.TreeDepth++; + PushID(ptr_id ? ptr_id : (const void*)"#TreePush"); +} + +void ImGui::TreePushRawID(ImGuiID id) +{ + ImGuiWindow* window = GetCurrentWindow(); + Indent(); + window->DC.TreeDepth++; + window->IDStack.push_back(id); +} + +void ImGui::TreePop() +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + Unindent(); + + window->DC.TreeDepth--; + if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) + if (g.NavIdIsAlive && (window->DC.TreeDepthMayJumpToParentOnPop & (1 << window->DC.TreeDepth))) + { + SetNavID(window->IDStack.back(), g.NavLayer); + NavMoveRequestCancel(); + } + window->DC.TreeDepthMayJumpToParentOnPop &= (1 << window->DC.TreeDepth) - 1; + + IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much. + PopID(); +} + +void ImGui::Value(const char* prefix, bool b) +{ + Text("%s: %s", prefix, (b ? "true" : "false")); +} + +void ImGui::Value(const char* prefix, int v) +{ + Text("%s: %d", prefix, v); +} + +void ImGui::Value(const char* prefix, unsigned int v) +{ + Text("%s: %d", prefix, v); +} + +void ImGui::Value(const char* prefix, float v, const char* float_format) +{ + if (float_format) + { + char fmt[64]; + ImFormatString(fmt, IM_ARRAYSIZE(fmt), "%%s: %s", float_format); + Text(fmt, prefix, v); + } + else + { + Text("%s: %.3f", prefix, v); + } +} + +//----------------------------------------------------------------------------- +// DRAG AND DROP +//----------------------------------------------------------------------------- + +void ImGui::ClearDragDrop() +{ + ImGuiContext& g = *GImGui; + g.DragDropActive = false; + g.DragDropPayload.Clear(); + g.DragDropAcceptFlags = 0; + g.DragDropAcceptIdCurr = g.DragDropAcceptIdPrev = 0; + g.DragDropAcceptIdCurrRectSurface = FLT_MAX; + g.DragDropAcceptFrameCount = -1; + + g.DragDropPayloadBufHeap.clear(); + memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal)); +} + +// Call when current ID is active. +// When this returns true you need to: a) call SetDragDropPayload() exactly once, b) you may render the payload visual/description, c) call EndDragDropSource() +bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + bool source_drag_active = false; + ImGuiID source_id = 0; + ImGuiID source_parent_id = 0; + int mouse_button = 0; + if (!(flags & ImGuiDragDropFlags_SourceExtern)) + { + source_id = window->DC.LastItemId; + if (source_id != 0 && g.ActiveId != source_id) // Early out for most common case + return false; + if (g.IO.MouseDown[mouse_button] == false) + return false; + + if (source_id == 0) + { + // If you want to use BeginDragDropSource() on an item with no unique identifier for interaction, such as Text() or Image(), you need to: + // A) Read the explanation below, B) Use the ImGuiDragDropFlags_SourceAllowNullID flag, C) Swallow your programmer pride. + if (!(flags & ImGuiDragDropFlags_SourceAllowNullID)) + { + IM_ASSERT(0); + return false; + } + + // Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image() + // We build a throwaway ID based on current ID stack + relative AABB of items in window. + // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled. + // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive. + bool is_hovered = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) != 0; + if (!is_hovered && (g.ActiveId == 0 || g.ActiveIdWindow != window)) + return false; + source_id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect); + if (is_hovered) + SetHoveredID(source_id); + if (is_hovered && g.IO.MouseClicked[mouse_button]) + { + SetActiveID(source_id, window); + FocusWindow(window); + } + if (g.ActiveId == source_id) // Allow the underlying widget to display/return hovered during the mouse release frame, else we would get a flicker. + g.ActiveIdAllowOverlap = is_hovered; + } + else + { + g.ActiveIdAllowOverlap = false; + } + if (g.ActiveId != source_id) + return false; + source_parent_id = window->IDStack.back(); + source_drag_active = IsMouseDragging(mouse_button); + } + else + { + window = NULL; + source_id = ImHash("#SourceExtern", 0); + source_drag_active = true; + } + + if (source_drag_active) + { + if (!g.DragDropActive) + { + IM_ASSERT(source_id != 0); + ClearDragDrop(); + ImGuiPayload& payload = g.DragDropPayload; + payload.SourceId = source_id; + payload.SourceParentId = source_parent_id; + g.DragDropActive = true; + g.DragDropSourceFlags = flags; + g.DragDropMouseButton = mouse_button; + } + g.DragDropSourceFrameCount = g.FrameCount; + g.DragDropWithinSourceOrTarget = true; + + if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip)) + { + // Target can request the Source to not display its tooltip (we use a dedicated flag to make this request explicit) + // We unfortunately can't just modify the source flags and skip the call to BeginTooltip, as caller may be emitting contents. + BeginTooltip(); + if (g.DragDropActive && g.DragDropAcceptIdPrev && (g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip)) + { + ImGuiWindow* tooltip_window = g.CurrentWindow; + tooltip_window->SkipItems = true; + tooltip_window->HiddenFramesRegular = 1; + } + } + + if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern)) + window->DC.LastItemStatusFlags &= ~ImGuiItemStatusFlags_HoveredRect; + + return true; + } + return false; +} + +void ImGui::EndDragDropSource() +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.DragDropActive); + IM_ASSERT(g.DragDropWithinSourceOrTarget && "Not after a BeginDragDropSource()?"); + + if (!(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip)) + EndTooltip(); + + // Discard the drag if have not called SetDragDropPayload() + if (g.DragDropPayload.DataFrameCount == -1) + ClearDragDrop(); + g.DragDropWithinSourceOrTarget = false; +} + +// Use 'cond' to choose to submit payload on drag start or every frame +bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond) +{ + ImGuiContext& g = *GImGui; + ImGuiPayload& payload = g.DragDropPayload; + if (cond == 0) + cond = ImGuiCond_Always; + + IM_ASSERT(type != NULL); + IM_ASSERT(strlen(type) < IM_ARRAYSIZE(payload.DataType) && "Payload type can be at most 32 characters long"); + IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0)); + IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once); + IM_ASSERT(payload.SourceId != 0); // Not called between BeginDragDropSource() and EndDragDropSource() + + if (cond == ImGuiCond_Always || payload.DataFrameCount == -1) + { + // Copy payload + ImStrncpy(payload.DataType, type, IM_ARRAYSIZE(payload.DataType)); + g.DragDropPayloadBufHeap.resize(0); + if (data_size > sizeof(g.DragDropPayloadBufLocal)) + { + // Store in heap + g.DragDropPayloadBufHeap.resize((int)data_size); + payload.Data = g.DragDropPayloadBufHeap.Data; + memcpy(payload.Data, data, data_size); + } + else if (data_size > 0) + { + // Store locally + memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal)); + payload.Data = g.DragDropPayloadBufLocal; + memcpy(payload.Data, data, data_size); + } + else + { + payload.Data = NULL; + } + payload.DataSize = (int)data_size; + } + payload.DataFrameCount = g.FrameCount; + + return (g.DragDropAcceptFrameCount == g.FrameCount) || (g.DragDropAcceptFrameCount == g.FrameCount - 1); +} + +bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id) +{ + ImGuiContext& g = *GImGui; + if (!g.DragDropActive) + return false; + + ImGuiWindow* window = g.CurrentWindow; + if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow) + return false; + IM_ASSERT(id != 0); + if (!IsMouseHoveringRect(bb.Min, bb.Max) || (id == g.DragDropPayload.SourceId)) + return false; + if (window->SkipItems) + return false; + + IM_ASSERT(g.DragDropWithinSourceOrTarget == false); + g.DragDropTargetRect = bb; + g.DragDropTargetId = id; + g.DragDropWithinSourceOrTarget = true; + return true; +} + +// We don't use BeginDragDropTargetCustom() and duplicate its code because: +// 1) we use LastItemRectHoveredRect which handles items that pushes a temporarily clip rectangle in their code. Calling BeginDragDropTargetCustom(LastItemRect) would not handle them. +// 2) and it's faster. as this code may be very frequently called, we want to early out as fast as we can. +// Also note how the HoveredWindow test is positioned differently in both functions (in both functions we optimize for the cheapest early out case) +bool ImGui::BeginDragDropTarget() +{ + ImGuiContext& g = *GImGui; + if (!g.DragDropActive) + return false; + + ImGuiWindow* window = g.CurrentWindow; + if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect)) + return false; + if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow) + return false; + + const ImRect& display_rect = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? window->DC.LastItemDisplayRect : window->DC.LastItemRect; + ImGuiID id = window->DC.LastItemId; + if (id == 0) + id = window->GetIDFromRectangle(display_rect); + if (g.DragDropPayload.SourceId == id) + return false; + + IM_ASSERT(g.DragDropWithinSourceOrTarget == false); + g.DragDropTargetRect = display_rect; + g.DragDropTargetId = id; + g.DragDropWithinSourceOrTarget = true; + return true; +} + +bool ImGui::IsDragDropPayloadBeingAccepted() +{ + ImGuiContext& g = *GImGui; + return g.DragDropActive && g.DragDropAcceptIdPrev != 0; +} + +const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + ImGuiPayload& payload = g.DragDropPayload; + IM_ASSERT(g.DragDropActive); // Not called between BeginDragDropTarget() and EndDragDropTarget() ? + IM_ASSERT(payload.DataFrameCount != -1); // Forgot to call EndDragDropTarget() ? + if (type != NULL && !payload.IsDataType(type)) + return NULL; + + // Accept smallest drag target bounding box, this allows us to nest drag targets conveniently without ordering constraints. + // NB: We currently accept NULL id as target. However, overlapping targets requires a unique ID to function! + const bool was_accepted_previously = (g.DragDropAcceptIdPrev == g.DragDropTargetId); + ImRect r = g.DragDropTargetRect; + float r_surface = r.GetWidth() * r.GetHeight(); + if (r_surface < g.DragDropAcceptIdCurrRectSurface) + { + g.DragDropAcceptFlags = flags; + g.DragDropAcceptIdCurr = g.DragDropTargetId; + g.DragDropAcceptIdCurrRectSurface = r_surface; + } + + // Render default drop visuals + payload.Preview = was_accepted_previously; + flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that lives for 1 frame) + if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview) + { + // FIXME-DRAG: Settle on a proper default visuals for drop target. + r.Expand(3.5f); + bool push_clip_rect = !window->ClipRect.Contains(r); + if (push_clip_rect) window->DrawList->PushClipRect(r.Min-ImVec2(1,1), r.Max+ImVec2(1,1)); + window->DrawList->AddRect(r.Min, r.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, ~0, 2.0f); + if (push_clip_rect) window->DrawList->PopClipRect(); + } + + g.DragDropAcceptFrameCount = g.FrameCount; + payload.Delivery = was_accepted_previously && !IsMouseDown(g.DragDropMouseButton); // For extern drag sources affecting os window focus, it's easier to just test !IsMouseDown() instead of IsMouseReleased() + if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery)) + return NULL; + + return &payload; +} + +// We don't really use/need this now, but added it for the sake of consistency and because we might need it later. +void ImGui::EndDragDropTarget() +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.DragDropActive); + IM_ASSERT(g.DragDropWithinSourceOrTarget); + g.DragDropWithinSourceOrTarget = false; +} + +//----------------------------------------------------------------------------- +// PLATFORM DEPENDENT HELPERS +//----------------------------------------------------------------------------- + +#if defined(_WIN32) && !defined(_WINDOWS_) && (!defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) || !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)) +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef __MINGW32__ +#include +#else +#include +#endif +#endif + +// Win32 API clipboard implementation +#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) + +#ifdef _MSC_VER +#pragma comment(lib, "user32") +#endif + +static const char* GetClipboardTextFn_DefaultImpl(void*) +{ + static ImVector buf_local; + buf_local.clear(); + if (!::OpenClipboard(NULL)) + return NULL; + HANDLE wbuf_handle = ::GetClipboardData(CF_UNICODETEXT); + if (wbuf_handle == NULL) + { + ::CloseClipboard(); + return NULL; + } + if (ImWchar* wbuf_global = (ImWchar*)::GlobalLock(wbuf_handle)) + { + int buf_len = ImTextCountUtf8BytesFromStr(wbuf_global, NULL) + 1; + buf_local.resize(buf_len); + ImTextStrToUtf8(buf_local.Data, buf_len, wbuf_global, NULL); + } + ::GlobalUnlock(wbuf_handle); + ::CloseClipboard(); + return buf_local.Data; +} + +static void SetClipboardTextFn_DefaultImpl(void*, const char* text) +{ + if (!::OpenClipboard(NULL)) + return; + const int wbuf_length = ImTextCountCharsFromUtf8(text, NULL) + 1; + HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar)); + if (wbuf_handle == NULL) + { + ::CloseClipboard(); + return; + } + ImWchar* wbuf_global = (ImWchar*)::GlobalLock(wbuf_handle); + ImTextStrFromUtf8(wbuf_global, wbuf_length, text, NULL); + ::GlobalUnlock(wbuf_handle); + ::EmptyClipboard(); + if (::SetClipboardData(CF_UNICODETEXT, wbuf_handle) == NULL) + ::GlobalFree(wbuf_handle); + ::CloseClipboard(); +} + +#else + +// Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers +static const char* GetClipboardTextFn_DefaultImpl(void*) +{ + ImGuiContext& g = *GImGui; + return g.PrivateClipboard.empty() ? NULL : g.PrivateClipboard.begin(); +} + +// Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers +static void SetClipboardTextFn_DefaultImpl(void*, const char* text) +{ + ImGuiContext& g = *GImGui; + g.PrivateClipboard.clear(); + const char* text_end = text + strlen(text); + g.PrivateClipboard.resize((int)(text_end - text) + 1); + memcpy(&g.PrivateClipboard[0], text, (size_t)(text_end - text)); + g.PrivateClipboard[(int)(text_end - text)] = 0; +} + +#endif + +// Win32 API IME support (for Asian languages, etc.) +#if defined(_WIN32) && !defined(__GNUC__) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) + +#include +#ifdef _MSC_VER +#pragma comment(lib, "imm32") +#endif + +static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y) +{ + // Notify OS Input Method Editor of text input position + if (HWND hwnd = (HWND)GImGui->IO.ImeWindowHandle) + if (HIMC himc = ::ImmGetContext(hwnd)) + { + COMPOSITIONFORM cf; + cf.ptCurrentPos.x = x; + cf.ptCurrentPos.y = y; + cf.dwStyle = CFS_FORCE_POSITION; + ::ImmSetCompositionWindow(himc, &cf); + ::ImmReleaseContext(hwnd, himc); + } +} + +#else + +static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {} + +#endif + +//----------------------------------------------------------------------------- +// HELP, METRICS +//----------------------------------------------------------------------------- + +void ImGui::ShowMetricsWindow(bool* p_open) +{ + if (ImGui::Begin("ImGui Metrics", p_open)) + { + static bool show_draw_cmd_clip_rects = true; + static bool show_window_begin_order = false; + ImGuiIO& io = ImGui::GetIO(); + ImGui::Text("Dear ImGui %s", ImGui::GetVersion()); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); + ImGui::Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3); + ImGui::Text("%d active windows (%d visible)", io.MetricsActiveWindows, io.MetricsRenderWindows); + ImGui::Text("%d allocations", io.MetricsActiveAllocations); + ImGui::Checkbox("Show clipping rectangles when hovering draw commands", &show_draw_cmd_clip_rects); + ImGui::Checkbox("Ctrl shows window begin order", &show_window_begin_order); + + ImGui::Separator(); + + struct Funcs + { + static void NodeDrawList(ImGuiWindow* window, ImDrawList* draw_list, const char* label) + { + bool node_open = ImGui::TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, draw_list->CmdBuffer.Size); + if (draw_list == ImGui::GetWindowDrawList()) + { + ImGui::SameLine(); + ImGui::TextColored(ImColor(255,100,100), "CURRENTLY APPENDING"); // Can't display stats for active draw list! (we don't have the data double-buffered) + if (node_open) ImGui::TreePop(); + return; + } + + ImDrawList* overlay_draw_list = GetOverlayDrawList(); // Render additional visuals into the top-most draw list + if (window && IsItemHovered()) + overlay_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255)); + if (!node_open) + return; + + int elem_offset = 0; + for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.begin(); pcmd < draw_list->CmdBuffer.end(); elem_offset += pcmd->ElemCount, pcmd++) + { + if (pcmd->UserCallback == NULL && pcmd->ElemCount == 0) + continue; + if (pcmd->UserCallback) + { + ImGui::BulletText("Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData); + continue; + } + ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; + bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %4d %s vtx, tex 0x%p, clip_rect (%4.0f,%4.0f)-(%4.0f,%4.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); + if (show_draw_cmd_clip_rects && ImGui::IsItemHovered()) + { + ImRect clip_rect = pcmd->ClipRect; + ImRect vtxs_rect; + for (int i = elem_offset; i < elem_offset + (int)pcmd->ElemCount; i++) + vtxs_rect.Add(draw_list->VtxBuffer[idx_buffer ? idx_buffer[i] : i].pos); + clip_rect.Floor(); overlay_draw_list->AddRect(clip_rect.Min, clip_rect.Max, IM_COL32(255,255,0,255)); + vtxs_rect.Floor(); overlay_draw_list->AddRect(vtxs_rect.Min, vtxs_rect.Max, IM_COL32(255,0,255,255)); + } + if (!pcmd_node_open) + continue; + + // Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted. + ImGuiListClipper clipper(pcmd->ElemCount/3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible. + while (clipper.Step()) + for (int prim = clipper.DisplayStart, vtx_i = elem_offset + clipper.DisplayStart*3; prim < clipper.DisplayEnd; prim++) + { + char buf[300]; + char *buf_p = buf, *buf_end = buf + IM_ARRAYSIZE(buf); + ImVec2 triangles_pos[3]; + for (int n = 0; n < 3; n++, vtx_i++) + { + ImDrawVert& v = draw_list->VtxBuffer[idx_buffer ? idx_buffer[vtx_i] : vtx_i]; + triangles_pos[n] = v.pos; + buf_p += ImFormatString(buf_p, (int)(buf_end - buf_p), "%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n", (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); + } + ImGui::Selectable(buf, false); + if (ImGui::IsItemHovered()) + { + ImDrawListFlags backup_flags = overlay_draw_list->Flags; + overlay_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines at is more readable for very large and thin triangles. + overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f); + overlay_draw_list->Flags = backup_flags; + } + } + ImGui::TreePop(); + } + ImGui::TreePop(); + } + + static void NodeWindows(ImVector& windows, const char* label) + { + if (!ImGui::TreeNode(label, "%s (%d)", label, windows.Size)) + return; + for (int i = 0; i < windows.Size; i++) + Funcs::NodeWindow(windows[i], "Window"); + ImGui::TreePop(); + } + + static void NodeWindow(ImGuiWindow* window, const char* label) + { + if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, window->Active || window->WasActive, window)) + return; + ImGuiWindowFlags flags = window->Flags; + NodeDrawList(window, window->DrawList, "DrawList"); + ImGui::BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->SizeContents.x, window->SizeContents.y); + ImGui::BulletText("Flags: 0x%08X (%s%s%s%s%s%s%s%s..)", flags, + (flags & ImGuiWindowFlags_ChildWindow) ? "Child " : "", (flags & ImGuiWindowFlags_Tooltip) ? "Tooltip " : "", (flags & ImGuiWindowFlags_Popup) ? "Popup " : "", + (flags & ImGuiWindowFlags_Modal) ? "Modal " : "", (flags & ImGuiWindowFlags_ChildMenu) ? "ChildMenu " : "", (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : "", + (flags & ImGuiWindowFlags_NoInputs) ? "NoInputs":"", (flags & ImGuiWindowFlags_AlwaysAutoResize) ? "AlwaysAutoResize" : ""); + ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f)", window->Scroll.x, GetScrollMaxX(window), window->Scroll.y, GetScrollMaxY(window)); + ImGui::BulletText("Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1); + ImGui::BulletText("Appearing: %d, Hidden: %d (Reg %d Resize %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesRegular, window->HiddenFramesForResize, window->SkipItems); + ImGui::BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask); + ImGui::BulletText("NavLastChildNavWindow: %s", window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL"); + if (!window->NavRectRel[0].IsInverted()) + ImGui::BulletText("NavRectRel[0]: (%.1f,%.1f)(%.1f,%.1f)", window->NavRectRel[0].Min.x, window->NavRectRel[0].Min.y, window->NavRectRel[0].Max.x, window->NavRectRel[0].Max.y); + else + ImGui::BulletText("NavRectRel[0]: "); + if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); + if (window->ParentWindow != NULL) NodeWindow(window->ParentWindow, "ParentWindow"); + if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows"); + if (window->ColumnsStorage.Size > 0 && ImGui::TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size)) + { + for (int n = 0; n < window->ColumnsStorage.Size; n++) + { + const ImGuiColumnsSet* columns = &window->ColumnsStorage[n]; + if (ImGui::TreeNode((void*)(uintptr_t)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags)) + { + ImGui::BulletText("Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->MaxX - columns->MinX, columns->MinX, columns->MaxX); + for (int column_n = 0; column_n < columns->Columns.Size; column_n++) + ImGui::BulletText("Column %02d: OffsetNorm %.3f (= %.1f px)", column_n, columns->Columns[column_n].OffsetNorm, OffsetNormToPixels(columns, columns->Columns[column_n].OffsetNorm)); + ImGui::TreePop(); + } + } + ImGui::TreePop(); + } + ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair)); + ImGui::TreePop(); + } + }; + + // Access private state, we are going to display the draw lists from last frame + ImGuiContext& g = *GImGui; + Funcs::NodeWindows(g.Windows, "Windows"); + if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.DrawDataBuilder.Layers[0].Size)) + { + for (int i = 0; i < g.DrawDataBuilder.Layers[0].Size; i++) + Funcs::NodeDrawList(NULL, g.DrawDataBuilder.Layers[0][i], "DrawList"); + ImGui::TreePop(); + } + if (ImGui::TreeNode("Popups", "Popups (%d)", g.OpenPopupStack.Size)) + { + for (int i = 0; i < g.OpenPopupStack.Size; i++) + { + ImGuiWindow* window = g.OpenPopupStack[i].Window; + ImGui::BulletText("PopupID: %08x, Window: '%s'%s%s", g.OpenPopupStack[i].PopupId, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? " ChildWindow" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? " ChildMenu" : ""); + } + ImGui::TreePop(); + } + if (ImGui::TreeNode("Internal state")) + { + const char* input_source_names[] = { "None", "Mouse", "Nav", "NavKeyboard", "NavGamepad" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT); + ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); + ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); + ImGui::Text("HoveredId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not + ImGui::Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, input_source_names[g.ActiveIdSource]); + ImGui::Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); + ImGui::Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL"); + ImGui::Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL"); + ImGui::Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer); + ImGui::Text("NavInputSource: %s", input_source_names[g.NavInputSource]); + ImGui::Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible); + ImGui::Text("NavActivateId: 0x%08X, NavInputId: 0x%08X", g.NavActivateId, g.NavInputId); + ImGui::Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover); + ImGui::Text("NavWindowingTarget: '%s'", g.NavWindowingTarget ? g.NavWindowingTarget->Name : "NULL"); + ImGui::Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize); + ImGui::TreePop(); + } + + + if (g.IO.KeyCtrl && show_window_begin_order) + { + for (int n = 0; n < g.Windows.Size; n++) + { + ImGuiWindow* window = g.Windows[n]; + if ((window->Flags & ImGuiWindowFlags_ChildWindow) || !window->WasActive) + continue; + char buf[32]; + ImFormatString(buf, IM_ARRAYSIZE(buf), "%d", window->BeginOrderWithinContext); + float font_size = ImGui::GetFontSize() * 2; + ImDrawList* overlay_draw_list = GetOverlayDrawList(); + overlay_draw_list->AddRectFilled(window->Pos, window->Pos + ImVec2(font_size, font_size), IM_COL32(200, 100, 100, 255)); + overlay_draw_list->AddText(NULL, font_size, window->Pos, IM_COL32(255, 255, 255, 255), buf); + } + } + } + ImGui::End(); +} + +//----------------------------------------------------------------------------- + +// Include imgui_user.inl at the end of imgui.cpp to access private data/functions that aren't exposed. +// Prefer just including imgui_internal.h from your code rather than using this define. If a declaration is missing from imgui_internal.h add it or request it on the github. +#ifdef IMGUI_INCLUDE_IMGUI_USER_INL +#include "imgui_user.inl" +#endif + +//----------------------------------------------------------------------------- diff --git a/BaikalStandalone/ImGUI/imgui.h b/BaikalStandalone/ImGUI/imgui.h new file mode 100644 index 00000000..78f13568 --- /dev/null +++ b/BaikalStandalone/ImGUI/imgui.h @@ -0,0 +1,1944 @@ +// dear imgui, v1.63 WIP +// (headers) + +// See imgui.cpp file for documentation. +// Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. +// Read 'Programmer guide' in imgui.cpp for notes on how to setup ImGui in your codebase. +// Get latest version at https://github.com/ocornut/imgui + +#pragma once + +// Configuration file (edit imconfig.h or define IMGUI_USER_CONFIG to set your own filename) +#ifdef IMGUI_USER_CONFIG +#include IMGUI_USER_CONFIG +#endif +#if !defined(IMGUI_DISABLE_INCLUDE_IMCONFIG_H) || defined(IMGUI_INCLUDE_IMCONFIG_H) +#include "imconfig.h" +#endif + +#include // FLT_MAX +#include // va_list +#include // ptrdiff_t, NULL +#include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp + +// Version +#define IMGUI_VERSION "1.63 WIP" +#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert)) + +// Define attributes of all API symbols declarations (e.g. for DLL under Windows) +// IMGUI_API is used for core imgui functions, IMGUI_IMPL_API is used for the default bindings files (imgui_impl_xxx.h) +#ifndef IMGUI_API +#define IMGUI_API +#endif +#ifndef IMGUI_IMPL_API +#define IMGUI_IMPL_API IMGUI_API +#endif + +// Helpers +#ifndef IM_ASSERT +#include +#define IM_ASSERT(_EXPR) assert(_EXPR) // You can override the default assert handler by editing imconfig.h +#endif +#if defined(__clang__) || defined(__GNUC__) +#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) // Apply printf-style warnings to user functions. +#define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0))) +#else +#define IM_FMTARGS(FMT) +#define IM_FMTLIST(FMT) +#endif +#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) // Size of a static C-style array. Don't use on pointers! +#define IM_OFFSETOF(_TYPE,_MEMBER) ((size_t)&(((_TYPE*)0)->_MEMBER)) // Offset of _MEMBER within _TYPE. Standardized as offsetof() in modern C++. + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wold-style-cast" +#elif defined(__GNUC__) && __GNUC__ >= 8 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif + +// Forward declarations +struct ImDrawChannel; // Temporary storage for outputting drawing commands out of order, used by ImDrawList::ChannelsSplit() +struct ImDrawCmd; // A single draw command within a parent ImDrawList (generally maps to 1 GPU draw call) +struct ImDrawData; // All draw command lists required to render the frame +struct ImDrawList; // A single draw command list (generally one per window, conceptually you may see this as a dynamic "mesh" builder) +struct ImDrawListSharedData; // Data shared among multiple draw lists (typically owned by parent ImGui context, but you may create one yourself) +struct ImDrawVert; // A single vertex (20 bytes by default, override layout with IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT) +struct ImFont; // Runtime data for a single font within a parent ImFontAtlas +struct ImFontAtlas; // Runtime data for multiple fonts, bake multiple fonts into a single texture, TTF/OTF font loader +struct ImFontConfig; // Configuration data when adding a font or merging fonts +struct ImColor; // Helper functions to create a color that can be converted to either u32 or float4 (*obsolete* please avoid using) +struct ImGuiIO; // Main configuration and I/O between your application and ImGui +struct ImGuiOnceUponAFrame; // Simple helper for running a block of code not more than once a frame, used by IMGUI_ONCE_UPON_A_FRAME macro +struct ImGuiStorage; // Simple custom key value storage +struct ImGuiStyle; // Runtime data for styling/colors +struct ImGuiTextFilter; // Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" +struct ImGuiTextBuffer; // Text buffer for logging/accumulating text +struct ImGuiTextEditCallbackData; // Shared state of ImGui::InputText() when using custom ImGuiTextEditCallback (rare/advanced use) +struct ImGuiSizeCallbackData; // Structure used to constraint window size in custom ways when using custom ImGuiSizeCallback (rare/advanced use) +struct ImGuiListClipper; // Helper to manually clip large list of items +struct ImGuiPayload; // User data payload for drag and drop operations +struct ImGuiContext; // ImGui context (opaque) +#ifndef ImTextureID +typedef void* ImTextureID; // User data to identify a texture (this is whatever to you want it to be! read the FAQ about ImTextureID in imgui.cpp) +#endif + +// Typedefs and Enumerations (declared as int for compatibility with old C++ and to not pollute the top of this file) +// Use your programming IDE "Go to definition" facility on the names of the right-most columns to find the actual flags/enum lists. +typedef unsigned int ImGuiID; // Unique ID used by widgets (typically hashed from a stack of string) +typedef unsigned short ImWchar; // Character for keyboard input/display +typedef int ImGuiCol; // enum: a color identifier for styling // enum ImGuiCol_ +typedef int ImGuiDataType; // enum: a primary data type // enum ImGuiDataType_ +typedef int ImGuiDir; // enum: a cardinal direction // enum ImGuiDir_ +typedef int ImGuiCond; // enum: a condition for Set*() // enum ImGuiCond_ +typedef int ImGuiKey; // enum: a key identifier (ImGui-side enum) // enum ImGuiKey_ +typedef int ImGuiNavInput; // enum: an input identifier for navigation // enum ImGuiNavInput_ +typedef int ImGuiMouseCursor; // enum: a mouse cursor identifier // enum ImGuiMouseCursor_ +typedef int ImGuiStyleVar; // enum: a variable identifier for styling // enum ImGuiStyleVar_ +typedef int ImDrawCornerFlags; // flags: for ImDrawList::AddRect*() etc. // enum ImDrawCornerFlags_ +typedef int ImDrawListFlags; // flags: for ImDrawList // enum ImDrawListFlags_ +typedef int ImFontAtlasFlags; // flags: for ImFontAtlas // enum ImFontAtlasFlags_ +typedef int ImGuiBackendFlags; // flags: for io.BackendFlags // enum ImGuiBackendFlags_ +typedef int ImGuiColorEditFlags; // flags: for ColorEdit*(), ColorPicker*() // enum ImGuiColorEditFlags_ +typedef int ImGuiColumnsFlags; // flags: for *Columns*() // enum ImGuiColumnsFlags_ +typedef int ImGuiConfigFlags; // flags: for io.ConfigFlags // enum ImGuiConfigFlags_ +typedef int ImGuiComboFlags; // flags: for BeginCombo() // enum ImGuiComboFlags_ +typedef int ImGuiDragDropFlags; // flags: for *DragDrop*() // enum ImGuiDragDropFlags_ +typedef int ImGuiFocusedFlags; // flags: for IsWindowFocused() // enum ImGuiFocusedFlags_ +typedef int ImGuiHoveredFlags; // flags: for IsItemHovered() etc. // enum ImGuiHoveredFlags_ +typedef int ImGuiInputTextFlags; // flags: for InputText*() // enum ImGuiInputTextFlags_ +typedef int ImGuiSelectableFlags; // flags: for Selectable() // enum ImGuiSelectableFlags_ +typedef int ImGuiTreeNodeFlags; // flags: for TreeNode*(),CollapsingHeader()// enum ImGuiTreeNodeFlags_ +typedef int ImGuiWindowFlags; // flags: for Begin*() // enum ImGuiWindowFlags_ +typedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data); +typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); + +// Scalar data types +typedef signed int ImS32; // 32-bit signed integer == int +typedef unsigned int ImU32; // 32-bit unsigned integer (often used to store packed colors) +#if defined(_MSC_VER) && !defined(__clang__) +typedef signed __int64 ImS64; // 64-bit signed integer (pre and post C++11 with Visual Studio) +typedef unsigned __int64 ImU64; // 64-bit unsigned integer (pre and post C++11 with Visual Studio) +#elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100) +#include +typedef int64_t ImS64; // 64-bit signed integer (pre C++11) +typedef uint64_t ImU64; // 64-bit unsigned integer (pre C++11) +#else +typedef signed long long ImS64; // 64-bit signed integer (post C++11) +typedef unsigned long long ImU64; // 64-bit unsigned integer (post C++11) +#endif + +// 2D vector (often used to store positions, sizes, etc.) +struct ImVec2 +{ + float x, y; + ImVec2() { x = y = 0.0f; } + ImVec2(float _x, float _y) { x = _x; y = _y; } + float operator[] (size_t i) const { IM_ASSERT(i <= 1); return (&x)[i]; } // We very rarely use this [] operator, the assert overhead is fine. +#ifdef IM_VEC2_CLASS_EXTRA + IM_VEC2_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec2. +#endif +}; + +// 4D vector (often used to store floating-point colors) +struct ImVec4 +{ + float x, y, z, w; + ImVec4() { x = y = z = w = 0.0f; } + ImVec4(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; } +#ifdef IM_VEC4_CLASS_EXTRA + IM_VEC4_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec4. +#endif +}; + +// Dear ImGui end-user API +// (In a namespace so you can add extra functions in your own separate file. Please don't modify imgui.cpp/.h!) +namespace ImGui +{ + // Context creation and access + // Each context create its own ImFontAtlas by default. You may instance one yourself and pass it to CreateContext() to share a font atlas between imgui contexts. + // All those functions are not reliant on the current context. + IMGUI_API ImGuiContext* CreateContext(ImFontAtlas* shared_font_atlas = NULL); + IMGUI_API void DestroyContext(ImGuiContext* ctx = NULL); // NULL = destroy current context + IMGUI_API ImGuiContext* GetCurrentContext(); + IMGUI_API void SetCurrentContext(ImGuiContext* ctx); + IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert); + + // Main + IMGUI_API ImGuiIO& GetIO(); // access the IO structure (mouse/keyboard/gamepad inputs, time, various configuration options/flags) + IMGUI_API ImGuiStyle& GetStyle(); // access the Style structure (colors, sizes). Always use PushStyleCol(), PushStyleVar() to modify style mid-frame. + IMGUI_API void NewFrame(); // start a new ImGui frame, you can submit any command from this point until Render()/EndFrame(). + IMGUI_API void EndFrame(); // ends the ImGui frame. automatically called by Render(), you likely don't need to call that yourself directly. If you don't need to render data (skipping rendering) you may call EndFrame() but you'll have wasted CPU already! If you don't need to render, better to not create any imgui windows and not call NewFrame() at all! + IMGUI_API void Render(); // ends the ImGui frame, finalize the draw data. (Obsolete: optionally call io.RenderDrawListsFn if set. Nowadays, prefer calling your render function yourself.) + IMGUI_API ImDrawData* GetDrawData(); // valid after Render() and until the next call to NewFrame(). this is what you have to render. (Obsolete: this used to be passed to your io.RenderDrawListsFn() function.) + + // Demo, Debug, Information + IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create demo/test window (previously called ShowTestWindow). demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application! + IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create metrics window. display ImGui internals: draw commands (with individual draw calls and vertices), window list, basic internal state, etc. + IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // add style editor block (not a window). you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style) + IMGUI_API bool ShowStyleSelector(const char* label); // add style selector block (not a window), essentially a combo listing the default styles. + IMGUI_API void ShowFontSelector(const char* label); // add font selector block (not a window), essentially a combo listing the loaded fonts. + IMGUI_API void ShowUserGuide(); // add basic help/info block (not a window): how to manipulate ImGui as a end-user (mouse/keyboard controls). + IMGUI_API const char* GetVersion(); // get a version string e.g. "1.23" + + // Styles + IMGUI_API void StyleColorsDark(ImGuiStyle* dst = NULL); // new, recommended style (default) + IMGUI_API void StyleColorsClassic(ImGuiStyle* dst = NULL); // classic imgui style + IMGUI_API void StyleColorsLight(ImGuiStyle* dst = NULL); // best used with borders and a custom, thicker font + + // Windows + // (Begin = push window to the stack and start appending to it. End = pop window from the stack. You may append multiple times to the same window during the same frame) + // Begin()/BeginChild() return false to indicate the window being collapsed or fully clipped, so you may early out and omit submitting anything to the window. + // You need to always call a matching End()/EndChild() for a Begin()/BeginChild() call, regardless of its return value (this is due to legacy reason and is inconsistent with BeginMenu/EndMenu, BeginPopup/EndPopup and other functions where the End call should only be called if the corresponding Begin function returned true.) + // Passing 'bool* p_open != NULL' shows a close widget in the upper-right corner of the window, which when clicking will set the boolean to false. + // Use child windows to introduce independent scrolling/clipping regions within a host window. Child windows can embed their own child. + IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); + IMGUI_API void End(); + IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags flags = 0); // Begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400). + IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags flags = 0); + IMGUI_API void EndChild(); + + // Windows Utilities + IMGUI_API bool IsWindowAppearing(); + IMGUI_API bool IsWindowCollapsed(); + IMGUI_API bool IsWindowFocused(ImGuiFocusedFlags flags=0); // is current window focused? or its root/child, depending on flags. see flags for options. + IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags=0); // is current window hovered (and typically: not blocked by a popup/modal)? see flags for options. NB: If you are trying to check whether your mouse should be dispatched to imgui or to your app, you should use the 'io.WantCaptureMouse' boolean for that! Please read the FAQ! + IMGUI_API ImDrawList* GetWindowDrawList(); // get draw list associated to the window, to append your own drawing primitives + IMGUI_API ImVec2 GetWindowPos(); // get current window position in screen space (useful if you want to do your own drawing via the DrawList API) + IMGUI_API ImVec2 GetWindowSize(); // get current window size + IMGUI_API float GetWindowWidth(); // get current window width (shortcut for GetWindowSize().x) + IMGUI_API float GetWindowHeight(); // get current window height (shortcut for GetWindowSize().y) + IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates + IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos() + IMGUI_API float GetContentRegionAvailWidth(); // + IMGUI_API ImVec2 GetWindowContentRegionMin(); // content boundaries min (roughly (0,0)-Scroll), in window coordinates + IMGUI_API ImVec2 GetWindowContentRegionMax(); // content boundaries max (roughly (0,0)+Size-Scroll) where Size can be override with SetNextWindowContentSize(), in window coordinates + IMGUI_API float GetWindowContentRegionWidth(); // + + IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0, const ImVec2& pivot = ImVec2(0,0)); // set next window position. call before Begin(). use pivot=(0.5f,0.5f) to center on given point, etc. + IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin() + IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Use callback to apply non-trivial programmatic constraints. + IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (~ enforce the range of scrollbars). not including window decorations (title bar, menu bar, etc.). set an axis to 0.0f to leave it automatic. call before Begin() + IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // set next window collapsed state. call before Begin() + IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most. call before Begin() + IMGUI_API void SetNextWindowBgAlpha(float alpha); // set next window background color alpha. helper to easily modify ImGuiCol_WindowBg/ChildBg/PopupBg. + IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects. + IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0,0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. + IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). + IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / front-most. prefer using SetNextWindowFocus(). + IMGUI_API void SetWindowFontScale(float scale); // set font scale. Adjust IO.FontGlobalScale if you want to scale all windows + IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond = 0); // set named window position. + IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis. + IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0); // set named window collapsed state + IMGUI_API void SetWindowFocus(const char* name); // set named window to be focused / front-most. use NULL to remove focus. + + // Windows Scrolling + IMGUI_API float GetScrollX(); // get scrolling amount [0..GetScrollMaxX()] + IMGUI_API float GetScrollY(); // get scrolling amount [0..GetScrollMaxY()] + IMGUI_API float GetScrollMaxX(); // get maximum scrolling amount ~~ ContentSize.X - WindowSize.X + IMGUI_API float GetScrollMaxY(); // get maximum scrolling amount ~~ ContentSize.Y - WindowSize.Y + IMGUI_API void SetScrollX(float scroll_x); // set scrolling amount [0..GetScrollMaxX()] + IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0..GetScrollMaxY()] + IMGUI_API void SetScrollHere(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. When using to make a "default/current item" visible, consider using SetItemDefaultFocus() instead. + IMGUI_API void SetScrollFromPosY(float pos_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position valid. use GetCursorPos() or GetCursorStartPos()+offset to get valid positions. + + // Parameters stacks (shared) + IMGUI_API void PushFont(ImFont* font); // use NULL as a shortcut to push default font + IMGUI_API void PopFont(); + IMGUI_API void PushStyleColor(ImGuiCol idx, ImU32 col); + IMGUI_API void PushStyleColor(ImGuiCol idx, const ImVec4& col); + IMGUI_API void PopStyleColor(int count = 1); + IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); + IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val); + IMGUI_API void PopStyleVar(int count = 1); + IMGUI_API const ImVec4& GetStyleColorVec4(ImGuiCol idx); // retrieve style color as stored in ImGuiStyle structure. use to feed back into PushStyleColor(), otherwise use GetColorU32() to get style color with style alpha baked in. + IMGUI_API ImFont* GetFont(); // get current font + IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied + IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API + IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul = 1.0f); // retrieve given style color with style alpha applied and optional extra alpha multiplier + IMGUI_API ImU32 GetColorU32(const ImVec4& col); // retrieve given color with style alpha applied + IMGUI_API ImU32 GetColorU32(ImU32 col); // retrieve given color with style alpha applied + + // Parameters stacks (current window) + IMGUI_API void PushItemWidth(float item_width); // width of items for the common item+label case, pixels. 0.0f = default to ~2/3 of windows width, >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side) + IMGUI_API void PopItemWidth(); + IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position + IMGUI_API void PushTextWrapPos(float wrap_pos_x = 0.0f); // word-wrapping for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space + IMGUI_API void PopTextWrapPos(); + IMGUI_API void PushAllowKeyboardFocus(bool allow_keyboard_focus); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets + IMGUI_API void PopAllowKeyboardFocus(); + IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame. + IMGUI_API void PopButtonRepeat(); + + // Cursor / Layout + IMGUI_API void Separator(); // separator, generally horizontal. inside a menu bar or in horizontal layout mode, this becomes a vertical separator. + IMGUI_API void SameLine(float pos_x = 0.0f, float spacing_w = -1.0f); // call between widgets or groups to layout them horizontally + IMGUI_API void NewLine(); // undo a SameLine() + IMGUI_API void Spacing(); // add vertical spacing + IMGUI_API void Dummy(const ImVec2& size); // add a dummy item of given size + IMGUI_API void Indent(float indent_w = 0.0f); // move content position toward the right, by style.IndentSpacing or indent_w if != 0 + IMGUI_API void Unindent(float indent_w = 0.0f); // move content position back to the left, by style.IndentSpacing or indent_w if != 0 + IMGUI_API void BeginGroup(); // lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) + IMGUI_API void EndGroup(); + IMGUI_API ImVec2 GetCursorPos(); // cursor position is relative to window position + IMGUI_API float GetCursorPosX(); // " + IMGUI_API float GetCursorPosY(); // " + IMGUI_API void SetCursorPos(const ImVec2& local_pos); // " + IMGUI_API void SetCursorPosX(float x); // " + IMGUI_API void SetCursorPosY(float y); // " + IMGUI_API ImVec2 GetCursorStartPos(); // initial cursor position + IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute screen coordinates [0..io.DisplaySize] (useful to work with ImDrawList API) + IMGUI_API void SetCursorScreenPos(const ImVec2& screen_pos); // cursor position in absolute screen coordinates [0..io.DisplaySize] + IMGUI_API void AlignTextToFramePadding(); // vertically align upcoming text baseline to FramePadding.y so that it will align properly to regularly framed items (call if you have text on a line before a framed item) + IMGUI_API float GetTextLineHeight(); // ~ FontSize + IMGUI_API float GetTextLineHeightWithSpacing(); // ~ FontSize + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of text) + IMGUI_API float GetFrameHeight(); // ~ FontSize + style.FramePadding.y * 2 + IMGUI_API float GetFrameHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets) + + // ID stack/scopes + // Read the FAQ for more details about how ID are handled in dear imgui. If you are creating widgets in a loop you most + // likely want to push a unique identifier (e.g. object pointer, loop index) to uniquely differentiate them. + // You can also use the "##foobar" syntax within widget label to distinguish them from each others. + // In this header file we use the "label"/"name" terminology to denote a string that will be displayed and used as an ID, + // whereas "str_id" denote a string that is only used as an ID and not aimed to be displayed. + IMGUI_API void PushID(const char* str_id); // push identifier into the ID stack. IDs are hash of the entire stack! + IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end); + IMGUI_API void PushID(const void* ptr_id); + IMGUI_API void PushID(int int_id); + IMGUI_API void PopID(); + IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage yourself + IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end); + IMGUI_API ImGuiID GetID(const void* ptr_id); + + // Widgets: Text + IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Roughly equivalent to Text("%s", text) but: A) doesn't require null terminated string if 'text_end' is specified, B) it's faster, no memory copy is done, no buffer size limits, recommended for long chunks of text. + IMGUI_API void Text(const char* fmt, ...) IM_FMTARGS(1); // simple formatted text + IMGUI_API void TextV(const char* fmt, va_list args) IM_FMTLIST(1); + IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_FMTARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor(); + IMGUI_API void TextColoredV(const ImVec4& col, const char* fmt, va_list args) IM_FMTLIST(2); + IMGUI_API void TextDisabled(const char* fmt, ...) IM_FMTARGS(1); // shortcut for PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); Text(fmt, ...); PopStyleColor(); + IMGUI_API void TextDisabledV(const char* fmt, va_list args) IM_FMTLIST(1); + IMGUI_API void TextWrapped(const char* fmt, ...) IM_FMTARGS(1); // shortcut for PushTextWrapPos(0.0f); Text(fmt, ...); PopTextWrapPos();. Note that this won't work on an auto-resizing window if there's no other widgets to extend the window width, yoy may need to set a size using SetNextWindowSize(). + IMGUI_API void TextWrappedV(const char* fmt, va_list args) IM_FMTLIST(1); + IMGUI_API void LabelText(const char* label, const char* fmt, ...) IM_FMTARGS(2); // display text+label aligned the same way as value+label widgets + IMGUI_API void LabelTextV(const char* label, const char* fmt, va_list args) IM_FMTLIST(2); + IMGUI_API void BulletText(const char* fmt, ...) IM_FMTARGS(1); // shortcut for Bullet()+Text() + IMGUI_API void BulletTextV(const char* fmt, va_list args) IM_FMTLIST(1); + + // Widgets: Main + // Most widgets return true when the value has been changed or when pressed/selected + IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0)); // button + IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) to easily embed within text + IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size); // button behavior without the visuals, useful to build custom behaviors using the public api (along with IsItemActive, IsItemHovered, etc.) + IMGUI_API bool ArrowButton(const char* str_id, ImGuiDir dir); // square button with an arrow shape + IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0)); + IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1)); // <0 frame_padding uses default frame padding settings. 0 for no padding + IMGUI_API bool Checkbox(const char* label, bool* v); + IMGUI_API bool CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value); + IMGUI_API bool RadioButton(const char* label, bool active); // use with e.g. if (RadioButton("one", my_value==1)) { my_value = 1; } + IMGUI_API bool RadioButton(const char* label, int* v, int v_button); // shortcut to handle the above pattern when value is an integer + IMGUI_API void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float)); + IMGUI_API void PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0)); + IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float)); + IMGUI_API void PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0)); + IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-1,0), const char* overlay = NULL); + IMGUI_API void Bullet(); // draw a small circle and keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses + + // Widgets: Combo Box + // The new BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() items. + // The old Combo() api are helpers over BeginCombo()/EndCombo() which are kept available for convenience purpose. + IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0); + IMGUI_API void EndCombo(); // only call EndCombo() if BeginCombo() returns true! + IMGUI_API bool Combo(const char* label, int* current_item, const char* const items[], int items_count, int popup_max_height_in_items = -1); + IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int popup_max_height_in_items = -1); // Separate items with \0 within a string, end item-list with \0\0. e.g. "One\0Two\0Three\0" + IMGUI_API bool Combo(const char* label, int* current_item, bool(*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int popup_max_height_in_items = -1); + + // Widgets: Drags (tip: ctrl+click on a drag box to input with keyboard. manually input values aren't clamped, can go off-bounds) + // For all the Float2/Float3/Float4/Int2/Int3/Int4 versions of every functions, note that a 'float v[X]' function argument is the same as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. You can pass address of your first element out of a contiguous set, e.g. &myvector.x + // Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc. + // Speed are per-pixel of mouse movement (v_speed=0.2f: mouse needs to move by 5 pixels to increase value by 1). For gamepad/keyboard navigation, minimum speed is Max(v_speed, minimum_step_at_given_precision). + IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", float power = 1.0f); // If v_min >= v_max we have no bound + IMGUI_API bool DragFloat2(const char* label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", float power = 1.0f); + IMGUI_API bool DragFloat3(const char* label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", float power = 1.0f); + IMGUI_API bool DragFloat4(const char* label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", float power = 1.0f); + IMGUI_API bool DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", const char* format_max = NULL, float power = 1.0f); + IMGUI_API bool DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d"); // If v_min >= v_max we have no bound + IMGUI_API bool DragInt2(const char* label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d"); + IMGUI_API bool DragInt3(const char* label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d"); + IMGUI_API bool DragInt4(const char* label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d"); + IMGUI_API bool DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", const char* format_max = NULL); + IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* v, float v_speed, const void* v_min = NULL, const void* v_max = NULL, const char* format = NULL, float power = 1.0f); + IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* v, int components, float v_speed, const void* v_min = NULL, const void* v_max = NULL, const char* format = NULL, float power = 1.0f); + + // Widgets: Input with Keyboard + IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); + IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0,0), ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); + IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, const char* format = "%.3f", ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat2(const char* label, float v[2], const char* format = "%.3f", ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat3(const char* label, float v[3], const char* format = "%.3f", ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat4(const char* label, float v[4], const char* format = "%.3f", ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputInt2(const char* label, int v[2], ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputDouble(const char* label, double* v, double step = 0.0f, double step_fast = 0.0f, const char* format = "%.6f", ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputScalar(const char* label, ImGuiDataType data_type, void* v, const void* step = NULL, const void* step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* step = NULL, const void* step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags extra_flags = 0); + + // Widgets: Sliders (tip: ctrl+click on a slider to input with keyboard. manually input values aren't clamped, can go off-bounds) + // Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc. + IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f); // adjust format to decorate the value with a prefix or a suffix for in-slider labels or unit display. Use power!=1.0 for power curve sliders + IMGUI_API bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format = "%.3f", float power = 1.0f); + IMGUI_API bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format = "%.3f", float power = 1.0f); + IMGUI_API bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format = "%.3f", float power = 1.0f); + IMGUI_API bool SliderAngle(const char* label, float* v_rad, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f); + IMGUI_API bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* format = "%d"); + IMGUI_API bool SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format = "%d"); + IMGUI_API bool SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format = "%d"); + IMGUI_API bool SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format = "%d"); + IMGUI_API bool SliderScalar(const char* label, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format = NULL, float power = 1.0f); + IMGUI_API bool SliderScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format = NULL, float power = 1.0f); + IMGUI_API bool VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f); + IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format = "%d"); + IMGUI_API bool VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format = NULL, float power = 1.0f); + + // Widgets: Color Editor/Picker (tip: the ColorEdit* functions have a little colored preview square that can be left-clicked to open a picker, and right-clicked to open an option menu.) + // Note that a 'float v[X]' function argument is the same as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. You can the pass the address of a first float element out of a contiguous structure, e.g. &myvector.x + IMGUI_API bool ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags = 0); + IMGUI_API bool ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0); + IMGUI_API bool ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags = 0); + IMGUI_API bool ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = NULL); + IMGUI_API bool ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0,0)); // display a colored square/button, hover for details, return true when pressed. + IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // initialize current options (generally on application startup) if you want to select a default format, picker type, etc. User will be able to change many settings, unless you pass the _NoOptions flag to your calls. + + // Widgets: Trees + // TreeNode functions return true when the node is open, in which case you need to also call TreePop() when you are finished displaying the tree node contents. + IMGUI_API bool TreeNode(const char* label); + IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_FMTARGS(2); // helper variation to completely decorelate the id from the displayed string. Read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet(). + IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_FMTARGS(2); // " + IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args) IM_FMTLIST(2); + IMGUI_API bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args) IM_FMTLIST(2); + IMGUI_API bool TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags = 0); + IMGUI_API bool TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3); + IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3); + IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); + IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); + IMGUI_API void TreePush(const char* str_id); // ~ Indent()+PushId(). Already called by TreeNode() when returning true, but you can call TreePush/TreePop yourself if desired. + IMGUI_API void TreePush(const void* ptr_id = NULL); // " + IMGUI_API void TreePop(); // ~ Unindent()+PopId() + IMGUI_API void TreeAdvanceToLabelPos(); // advance cursor x position by GetTreeNodeToLabelSpacing() + IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode + IMGUI_API void SetNextTreeNodeOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state. + IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop(). + IMGUI_API bool CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close button on upper right of the header + + // Widgets: Selectable / Lists + IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height + IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper. + IMGUI_API bool ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items = -1); + IMGUI_API bool ListBox(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); + IMGUI_API bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0,0)); // use if you want to reimplement ListBox() will custom data or interactions. if the function return true, you can output elements then call ListBoxFooter() afterwards. + IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // " + IMGUI_API void ListBoxFooter(); // terminate the scrolling region. only call ListBoxFooter() if ListBoxHeader() returned true! + + // Widgets: Value() Helpers. Output single value in "name: value" format (tip: freely declare more in your code to handle your types. you can add functions to the ImGui namespace) + IMGUI_API void Value(const char* prefix, bool b); + IMGUI_API void Value(const char* prefix, int v); + IMGUI_API void Value(const char* prefix, unsigned int v); + IMGUI_API void Value(const char* prefix, float v, const char* float_format = NULL); + + // Tooltips + IMGUI_API void BeginTooltip(); // begin/append a tooltip window. to create full-featured tooltip (with any kind of items). + IMGUI_API void EndTooltip(); + IMGUI_API void SetTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip, typically use with ImGui::IsItemHovered(). overidde any previous call to SetTooltip(). + IMGUI_API void SetTooltipV(const char* fmt, va_list args) IM_FMTLIST(1); + + // Menus + IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar. + IMGUI_API void EndMainMenuBar(); // only call EndMainMenuBar() if BeginMainMenuBar() returns true! + IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set on parent window). + IMGUI_API void EndMenuBar(); // only call EndMenuBar() if BeginMenuBar() returns true! + IMGUI_API bool BeginMenu(const char* label, bool enabled = true); // create a sub-menu entry. only call EndMenu() if this returns true! + IMGUI_API void EndMenu(); // only call EndMenu() if BeginMenu() returns true! + IMGUI_API bool MenuItem(const char* label, const char* shortcut = NULL, bool selected = false, bool enabled = true); // return true when activated. shortcuts are displayed for convenience but not processed by ImGui at the moment + IMGUI_API bool MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL + + // Popups + IMGUI_API void OpenPopup(const char* str_id); // call to mark popup as open (don't call every frame!). popups are closed when user click outside, or if CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. By default, Selectable()/MenuItem() are calling CloseCurrentPopup(). Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). + IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returns true! + IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked on last item. if you can pass a NULL str_id only if the previous item had an id. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! + IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, int mouse_button = 1, bool also_over_items = true); // helper to open and begin popup when clicked on current window. + IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked in void (where there are no imgui windows). + IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // modal dialog (regular window with title bar, block interactions behind the modal window, can't close the modal window by clicking outside) + IMGUI_API void EndPopup(); // only call EndPopup() if BeginPopupXXX() returns true! + IMGUI_API bool OpenPopupOnItemClick(const char* str_id = NULL, int mouse_button = 1); // helper to open popup when clicked on last item. return true when just opened. + IMGUI_API bool IsPopupOpen(const char* str_id); // return true if the popup is open + IMGUI_API void CloseCurrentPopup(); // close the popup we have begin-ed into. clicking on a MenuItem or Selectable automatically close the current popup. + + // Columns + // You can also use SameLine(pos_x) for simplified columns. The columns API is still work-in-progress and rather lacking. + IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); + IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished + IMGUI_API int GetColumnIndex(); // get current column index + IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column + IMGUI_API void SetColumnWidth(int column_index, float width); // set column width (in pixels). pass -1 to use current column + IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is typically 0.0f + IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column + IMGUI_API int GetColumnsCount(); + + // Logging/Capture: all text output from interface is captured to tty/file/clipboard. By default, tree nodes are automatically opened during logging. + IMGUI_API void LogToTTY(int max_depth = -1); // start logging to tty + IMGUI_API void LogToFile(int max_depth = -1, const char* filename = NULL); // start logging to file + IMGUI_API void LogToClipboard(int max_depth = -1); // start logging to OS clipboard + IMGUI_API void LogFinish(); // stop logging (close file, etc.) + IMGUI_API void LogButtons(); // helper to display buttons for logging to tty/file/clipboard + IMGUI_API void LogText(const char* fmt, ...) IM_FMTARGS(1); // pass text data straight to log (without being displayed) + + // Drag and Drop + // [BETA API] Missing Demo code. API may evolve. + IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0); // call when the current item is active. If this return true, you can call SetDragDropPayload() + EndDragDropSource() + IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t size, ImGuiCond cond = 0);// type is a user defined string of maximum 32 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. + IMGUI_API void EndDragDropSource(); // only call EndDragDropSource() if BeginDragDropSource() returns true! + IMGUI_API bool BeginDragDropTarget(); // call after submitting an item that may receive an item. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget() + IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released. + IMGUI_API void EndDragDropTarget(); // only call EndDragDropTarget() if BeginDragDropTarget() returns true! + + // Clipping + IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect); + IMGUI_API void PopClipRect(); + + // Focus, Activation + // (Prefer using "SetItemDefaultFocus()" over "if (IsWindowAppearing()) SetScrollHere()" when applicable, to make your code more forward compatible when navigation branch is merged) + IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a window. Please use instead of "if (IsWindowAppearing()) SetScrollHere()" to signify "default item". + IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget. + + // Utilities + IMGUI_API bool IsItemHovered(ImGuiHoveredFlags flags = 0); // is the last item hovered? (and usable, aka not blocked by a popup, etc.). See ImGuiHoveredFlags for more options. + IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited. This will continuously return true while holding mouse button on an item. Items that don't interact will always return false) + IMGUI_API bool IsItemFocused(); // is the last item focused for keyboard/gamepad navigation? + IMGUI_API bool IsItemClicked(int mouse_button = 0); // is the last item clicked? (e.g. button/node just clicked on) == IsMouseClicked(mouse_button) && IsItemHovered() + IMGUI_API bool IsItemVisible(); // is the last item visible? (items may be out of sight because of clipping/scrolling) + IMGUI_API bool IsItemDeactivated(); // was the last item just made inactive (item was previously active). Useful for Undo/Redo patterns with widgets that requires continuous editing. + IMGUI_API bool IsItemDeactivatedAfterChange(); // was the last item just made inactive and made a value change when it was active? (e.g. Slider/Drag moved). Useful for Undo/Redo patterns with widgets that requires continuous editing. Note that you may get false positives (some widgets such as Combo()/ListBox()/Selectable() will return true even when clicking an already selected item). + IMGUI_API bool IsAnyItemHovered(); + IMGUI_API bool IsAnyItemActive(); + IMGUI_API bool IsAnyItemFocused(); + IMGUI_API ImVec2 GetItemRectMin(); // get bounding rectangle of last item, in screen space + IMGUI_API ImVec2 GetItemRectMax(); // " + IMGUI_API ImVec2 GetItemRectSize(); // get size of last item, in screen space + IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. + IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped. + IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side. + IMGUI_API double GetTime(); + IMGUI_API int GetFrameCount(); + IMGUI_API ImDrawList* GetOverlayDrawList(); // this draw list will be the last rendered one, useful to quickly draw overlays shapes/text + IMGUI_API ImDrawListSharedData* GetDrawListSharedData(); // you may use this when creating your own ImDrawList instances + IMGUI_API const char* GetStyleColorName(ImGuiCol idx); + IMGUI_API void SetStateStorage(ImGuiStorage* storage); // replace current window storage with our own (if you want to manipulate it yourself, typically clear subsection of it) + IMGUI_API ImGuiStorage* GetStateStorage(); + IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); + IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can. + + IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame + IMGUI_API void EndChildFrame(); // always call EndChildFrame() regardless of BeginChildFrame() return values (which indicates a collapsed/clipped window) + + IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in); + IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4& in); + IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v); + IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b); + + // Inputs + IMGUI_API int GetKeyIndex(ImGuiKey imgui_key); // map ImGuiKey_* values into user's key index. == io.KeyMap[key] + IMGUI_API bool IsKeyDown(int user_key_index); // is key being held. == io.KeysDown[user_key_index]. note that imgui doesn't know the semantic of each entry of io.KeysDown[]. Use your own indices/enums according to how your backend/engine stored them into io.KeysDown[]! + IMGUI_API bool IsKeyPressed(int user_key_index, bool repeat = true); // was key pressed (went from !Down to Down). if repeat=true, uses io.KeyRepeatDelay / KeyRepeatRate + IMGUI_API bool IsKeyReleased(int user_key_index); // was key released (went from Down to !Down).. + IMGUI_API int GetKeyPressedAmount(int key_index, float repeat_delay, float rate); // uses provided repeat rate/delay. return a count, most often 0 or 1 but might be >1 if RepeatRate is small enough that DeltaTime > RepeatRate + IMGUI_API bool IsMouseDown(int button); // is mouse button held (0=left, 1=right, 2=middle) + IMGUI_API bool IsAnyMouseDown(); // is any mouse button held + IMGUI_API bool IsMouseClicked(int button, bool repeat = false); // did mouse button clicked (went from !Down to Down) (0=left, 1=right, 2=middle) + IMGUI_API bool IsMouseDoubleClicked(int button); // did mouse button double-clicked. a double-click returns false in IsMouseClicked(). uses io.MouseDoubleClickTime. + IMGUI_API bool IsMouseReleased(int button); // did mouse button released (went from Down to !Down) + IMGUI_API bool IsMouseDragging(int button = 0, float lock_threshold = -1.0f); // is mouse dragging. if lock_threshold < -1.0f uses io.MouseDraggingThreshold + IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true); // is mouse hovering given bounding rect (in screen space). clipped by current clipping settings. disregarding of consideration of focus/window ordering/blocked by a popup. + IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); // + IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls + IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve backup of mouse position at the time of opening popup we have BeginPopup() into + IMGUI_API ImVec2 GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f); // dragging amount since clicking. if lock_threshold < -1.0f uses io.MouseDraggingThreshold + IMGUI_API void ResetMouseDragDelta(int button = 0); // + IMGUI_API ImGuiMouseCursor GetMouseCursor(); // get desired cursor type, reset in ImGui::NewFrame(), this is updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you + IMGUI_API void SetMouseCursor(ImGuiMouseCursor type); // set desired cursor type + IMGUI_API void CaptureKeyboardFromApp(bool capture = true); // manually override io.WantCaptureKeyboard flag next frame (said flag is entirely left for your application to handle). e.g. force capture keyboard when your widget is being hovered. + IMGUI_API void CaptureMouseFromApp(bool capture = true); // manually override io.WantCaptureMouse flag next frame (said flag is entirely left for your application to handle). + + // Clipboard Utilities (also see the LogToClipboard() function to capture or output text data to the clipboard) + IMGUI_API const char* GetClipboardText(); + IMGUI_API void SetClipboardText(const char* text); + + // Settings/.Ini Utilities + // The disk functions are automatically called if io.IniFilename != NULL (default is "imgui.ini"). + // Set io.IniFilename to NULL to load/save manually. Read io.WantSaveIniSettings description about handling .ini saving manually. + IMGUI_API void LoadIniSettingsFromDisk(const char* ini_filename); // call after CreateContext() and before the first call to NewFrame(). NewFrame() automatically calls LoadIniSettingsFromDisk(io.IniFilename). + IMGUI_API void LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size=0); // call after CreateContext() and before the first call to NewFrame() to provide .ini data from your own data source. + IMGUI_API void SaveIniSettingsToDisk(const char* ini_filename); + IMGUI_API const char* SaveIniSettingsToMemory(size_t* out_ini_size = NULL); // return a zero-terminated string with the .ini data which you can save by your own mean. call when io.WantSaveIniSettings is set, then save data by your own mean and clear io.WantSaveIniSettings. + + // Memory Utilities + // All those functions are not reliant on the current context. + // If you reload the contents of imgui.cpp at runtime, you may need to call SetCurrentContext() + SetAllocatorFunctions() again. + IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void(*free_func)(void* ptr, void* user_data), void* user_data = NULL); + IMGUI_API void* MemAlloc(size_t size); + IMGUI_API void MemFree(void* ptr); + +} // namespace ImGui + +// Flags for ImGui::Begin() +enum ImGuiWindowFlags_ +{ + ImGuiWindowFlags_None = 0, + ImGuiWindowFlags_NoTitleBar = 1 << 0, // Disable title-bar + ImGuiWindowFlags_NoResize = 1 << 1, // Disable user resizing with the lower-right grip + ImGuiWindowFlags_NoMove = 1 << 2, // Disable user moving the window + ImGuiWindowFlags_NoScrollbar = 1 << 3, // Disable scrollbars (window can still scroll with mouse or programatically) + ImGuiWindowFlags_NoScrollWithMouse = 1 << 4, // Disable user vertically scrolling with mouse wheel. On child window, mouse wheel will be forwarded to the parent unless NoScrollbar is also set. + ImGuiWindowFlags_NoCollapse = 1 << 5, // Disable user collapsing window by double-clicking on it + ImGuiWindowFlags_AlwaysAutoResize = 1 << 6, // Resize every window to its content every frame + ImGuiWindowFlags_NoSavedSettings = 1 << 8, // Never load/save settings in .ini file + ImGuiWindowFlags_NoInputs = 1 << 9, // Disable catching mouse or keyboard inputs, hovering test with pass through. + ImGuiWindowFlags_MenuBar = 1 << 10, // Has a menu-bar + ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You may use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section. + ImGuiWindowFlags_NoFocusOnAppearing = 1 << 12, // Disable taking focus when transitioning from hidden to visible state + ImGuiWindowFlags_NoBringToFrontOnFocus = 1 << 13, // Disable bringing window to front when taking focus (e.g. clicking on it or programatically giving it focus) + ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) + ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) + ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) + ImGuiWindowFlags_NoNavInputs = 1 << 18, // No gamepad/keyboard navigation within the window + ImGuiWindowFlags_NoNavFocus = 1 << 19, // No focusing toward this window with gamepad/keyboard navigation (e.g. skipped by CTRL+TAB) + ImGuiWindowFlags_NoNav = ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, + + // [Internal] + ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!) + ImGuiWindowFlags_ChildWindow = 1 << 24, // Don't use! For internal use by BeginChild() + ImGuiWindowFlags_Tooltip = 1 << 25, // Don't use! For internal use by BeginTooltip() + ImGuiWindowFlags_Popup = 1 << 26, // Don't use! For internal use by BeginPopup() + ImGuiWindowFlags_Modal = 1 << 27, // Don't use! For internal use by BeginPopupModal() + ImGuiWindowFlags_ChildMenu = 1 << 28 // Don't use! For internal use by BeginMenu() + + // [Obsolete] + //ImGuiWindowFlags_ShowBorders = 1 << 7, // --> Set style.FrameBorderSize=1.0f / style.WindowBorderSize=1.0f to enable borders around windows and items + //ImGuiWindowFlags_ResizeFromAnySide = 1 << 17, // --> Set io.ConfigResizeWindowsFromEdges and make sure mouse cursors are supported by back-end (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) +}; + +// Flags for ImGui::InputText() +enum ImGuiInputTextFlags_ +{ + ImGuiInputTextFlags_None = 0, + ImGuiInputTextFlags_CharsDecimal = 1 << 0, // Allow 0123456789.+-*/ + ImGuiInputTextFlags_CharsHexadecimal = 1 << 1, // Allow 0123456789ABCDEFabcdef + ImGuiInputTextFlags_CharsUppercase = 1 << 2, // Turn a..z into A..Z + ImGuiInputTextFlags_CharsNoBlank = 1 << 3, // Filter out spaces, tabs + ImGuiInputTextFlags_AutoSelectAll = 1 << 4, // Select entire text when first taking mouse focus + ImGuiInputTextFlags_EnterReturnsTrue = 1 << 5, // Return 'true' when Enter is pressed (as opposed to when the value was modified) + ImGuiInputTextFlags_CallbackCompletion = 1 << 6, // Call user function on pressing TAB (for completion handling) + ImGuiInputTextFlags_CallbackHistory = 1 << 7, // Call user function on pressing Up/Down arrows (for history handling) + ImGuiInputTextFlags_CallbackAlways = 1 << 8, // Call user function every time. User code may query cursor position, modify text buffer. + ImGuiInputTextFlags_CallbackCharFilter = 1 << 9, // Call user function to filter character. Modify data->EventChar to replace/filter input, or return 1 to discard character. + ImGuiInputTextFlags_AllowTabInput = 1 << 10, // Pressing TAB input a '\t' character into the text field + ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 11, // In multi-line mode, unfocus with Enter, add new line with Ctrl+Enter (default is opposite: unfocus with Ctrl+Enter, add line with Enter). + ImGuiInputTextFlags_NoHorizontalScroll = 1 << 12, // Disable following the cursor horizontally + ImGuiInputTextFlags_AlwaysInsertMode = 1 << 13, // Insert mode + ImGuiInputTextFlags_ReadOnly = 1 << 14, // Read-only mode + ImGuiInputTextFlags_Password = 1 << 15, // Password mode, display all characters as '*' + ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID(). + ImGuiInputTextFlags_CharsScientific = 1 << 17, // Allow 0123456789.+-*/eE (Scientific notation input) + // [Internal] + ImGuiInputTextFlags_Multiline = 1 << 20 // For internal use by InputTextMultiline() +}; + +// Flags for ImGui::TreeNodeEx(), ImGui::CollapsingHeader*() +enum ImGuiTreeNodeFlags_ +{ + ImGuiTreeNodeFlags_None = 0, + ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected + ImGuiTreeNodeFlags_Framed = 1 << 1, // Full colored frame (e.g. for CollapsingHeader) + ImGuiTreeNodeFlags_AllowItemOverlap = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one + ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack + ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes) + ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open + ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Need double-click to open node + ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open. + ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). + ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow + ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding(). + //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 11, // FIXME: TODO: Extend hit box horizontally even if not framed + //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 12, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible + ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 13, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop) + ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog + + // Obsolete names (will be removed) +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + , ImGuiTreeNodeFlags_AllowOverlapMode = ImGuiTreeNodeFlags_AllowItemOverlap +#endif +}; + +// Flags for ImGui::Selectable() +enum ImGuiSelectableFlags_ +{ + ImGuiSelectableFlags_None = 0, + ImGuiSelectableFlags_DontClosePopups = 1 << 0, // Clicking this don't close parent popup window + ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Selectable frame can span all columns (text will still fit in current column) + ImGuiSelectableFlags_AllowDoubleClick = 1 << 2, // Generate press events on double clicks too + ImGuiSelectableFlags_Disabled = 1 << 3 // Cannot be selected, display greyed out text +}; + +// Flags for ImGui::BeginCombo() +enum ImGuiComboFlags_ +{ + ImGuiComboFlags_None = 0, + ImGuiComboFlags_PopupAlignLeft = 1 << 0, // Align the popup toward the left by default + ImGuiComboFlags_HeightSmall = 1 << 1, // Max ~4 items visible. Tip: If you want your combo popup to be a specific size you can use SetNextWindowSizeConstraints() prior to calling BeginCombo() + ImGuiComboFlags_HeightRegular = 1 << 2, // Max ~8 items visible (default) + ImGuiComboFlags_HeightLarge = 1 << 3, // Max ~20 items visible + ImGuiComboFlags_HeightLargest = 1 << 4, // As many fitting items as possible + ImGuiComboFlags_NoArrowButton = 1 << 5, // Display on the preview box without the square arrow button + ImGuiComboFlags_NoPreview = 1 << 6, // Display only a square arrow button + ImGuiComboFlags_HeightMask_ = ImGuiComboFlags_HeightSmall | ImGuiComboFlags_HeightRegular | ImGuiComboFlags_HeightLarge | ImGuiComboFlags_HeightLargest +}; + +// Flags for ImGui::IsWindowFocused() +enum ImGuiFocusedFlags_ +{ + ImGuiFocusedFlags_None = 0, + ImGuiFocusedFlags_ChildWindows = 1 << 0, // IsWindowFocused(): Return true if any children of the window is focused + ImGuiFocusedFlags_RootWindow = 1 << 1, // IsWindowFocused(): Test from root window (top most parent of the current hierarchy) + ImGuiFocusedFlags_AnyWindow = 1 << 2, // IsWindowFocused(): Return true if any window is focused + ImGuiFocusedFlags_RootAndChildWindows = ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows +}; + +// Flags for ImGui::IsItemHovered(), ImGui::IsWindowHovered() +// Note: if you are trying to check whether your mouse should be dispatched to imgui or to your app, you should use the 'io.WantCaptureMouse' boolean for that. Please read the FAQ! +// Note: windows with the ImGuiWindowFlags_NoInputs flag are ignored by IsWindowHovered() calls. +enum ImGuiHoveredFlags_ +{ + ImGuiHoveredFlags_None = 0, // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them. + ImGuiHoveredFlags_ChildWindows = 1 << 0, // IsWindowHovered() only: Return true if any children of the window is hovered + ImGuiHoveredFlags_RootWindow = 1 << 1, // IsWindowHovered() only: Test from root window (top most parent of the current hierarchy) + ImGuiHoveredFlags_AnyWindow = 1 << 2, // IsWindowHovered() only: Return true if any window is hovered + ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 3, // Return true even if a popup window is normally blocking access to this item/window + //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 4, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. + ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 5, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns. + ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 6, // Return true even if the position is overlapped by another window + ImGuiHoveredFlags_AllowWhenDisabled = 1 << 7, // Return true even if the item is disabled + ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped, + ImGuiHoveredFlags_RootAndChildWindows = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows +}; + +// Flags for ImGui::BeginDragDropSource(), ImGui::AcceptDragDropPayload() +enum ImGuiDragDropFlags_ +{ + ImGuiDragDropFlags_None = 0, + // BeginDragDropSource() flags + ImGuiDragDropFlags_SourceNoPreviewTooltip = 1 << 0, // By default, a successful call to BeginDragDropSource opens a tooltip so you can display a preview or description of the source contents. This flag disable this behavior. + ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return false, to avoid subsequent user code submitting tooltips. This flag disable this behavior so you can still call IsItemHovered() on the source item. + ImGuiDragDropFlags_SourceNoHoldToOpenOthers = 1 << 2, // Disable the behavior that allows to open tree nodes and collapsing header by holding over them while dragging a source item. + ImGuiDragDropFlags_SourceAllowNullID = 1 << 3, // Allow items such as Text(), Image() that have no unique identifier to be used as drag source, by manufacturing a temporary identifier based on their window-relative position. This is extremely unusual within the dear imgui ecosystem and so we made it explicit. + ImGuiDragDropFlags_SourceExtern = 1 << 4, // External source (from outside of imgui), won't attempt to read current item/window info. Will always return true. Only one Extern source can be active simultaneously. + ImGuiDragDropFlags_SourceAutoExpirePayload = 1 << 5, // Automatically expire the payload if the source cease to be submitted (otherwise payloads are persisting while being dragged) + // AcceptDragDropPayload() flags + ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, // AcceptDragDropPayload() will returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered. + ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, // Do not draw the default highlight rectangle when hovering over target. + ImGuiDragDropFlags_AcceptNoPreviewTooltip = 1 << 12, // Request hiding the BeginDragDropSource tooltip from the BeginDragDropTarget site. + ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect // For peeking ahead and inspecting the payload before delivery. +}; + +// Standard Drag and Drop payload types. You can define you own payload types using short strings. Types starting with '_' are defined by Dear ImGui. +#define IMGUI_PAYLOAD_TYPE_COLOR_3F "_COL3F" // float[3]: Standard type for colors, without alpha. User code may use this type. +#define IMGUI_PAYLOAD_TYPE_COLOR_4F "_COL4F" // float[4]: Standard type for colors. User code may use this type. + +// A primary data type +enum ImGuiDataType_ +{ + ImGuiDataType_S32, // int + ImGuiDataType_U32, // unsigned int + ImGuiDataType_S64, // long long, __int64 + ImGuiDataType_U64, // unsigned long long, unsigned __int64 + ImGuiDataType_Float, // float + ImGuiDataType_Double, // double + ImGuiDataType_COUNT +}; + +// A cardinal direction +enum ImGuiDir_ +{ + ImGuiDir_None = -1, + ImGuiDir_Left = 0, + ImGuiDir_Right = 1, + ImGuiDir_Up = 2, + ImGuiDir_Down = 3, + ImGuiDir_COUNT +}; + +// User fill ImGuiIO.KeyMap[] array with indices into the ImGuiIO.KeysDown[512] array +enum ImGuiKey_ +{ + ImGuiKey_Tab, + ImGuiKey_LeftArrow, + ImGuiKey_RightArrow, + ImGuiKey_UpArrow, + ImGuiKey_DownArrow, + ImGuiKey_PageUp, + ImGuiKey_PageDown, + ImGuiKey_Home, + ImGuiKey_End, + ImGuiKey_Insert, + ImGuiKey_Delete, + ImGuiKey_Backspace, + ImGuiKey_Space, + ImGuiKey_Enter, + ImGuiKey_Escape, + ImGuiKey_A, // for text edit CTRL+A: select all + ImGuiKey_C, // for text edit CTRL+C: copy + ImGuiKey_V, // for text edit CTRL+V: paste + ImGuiKey_X, // for text edit CTRL+X: cut + ImGuiKey_Y, // for text edit CTRL+Y: redo + ImGuiKey_Z, // for text edit CTRL+Z: undo + ImGuiKey_COUNT +}; + +// [BETA] Gamepad/Keyboard directional navigation +// Keyboard: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays. +// Gamepad: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. Back-end: set ImGuiBackendFlags_HasGamepad and fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). +// Read instructions in imgui.cpp for more details. Download PNG/PSD at goo.gl/9LgVZW. +enum ImGuiNavInput_ +{ + // Gamepad Mapping + ImGuiNavInput_Activate, // activate / open / toggle / tweak value // e.g. Cross (PS4), A (Xbox), A (Switch), Space (Keyboard) + ImGuiNavInput_Cancel, // cancel / close / exit // e.g. Circle (PS4), B (Xbox), B (Switch), Escape (Keyboard) + ImGuiNavInput_Input, // text input / on-screen keyboard // e.g. Triang.(PS4), Y (Xbox), X (Switch), Return (Keyboard) + ImGuiNavInput_Menu, // tap: toggle menu / hold: focus, move, resize // e.g. Square (PS4), X (Xbox), Y (Switch), Alt (Keyboard) + ImGuiNavInput_DpadLeft, // move / tweak / resize window (w/ PadMenu) // e.g. D-pad Left/Right/Up/Down (Gamepads), Arrow keys (Keyboard) + ImGuiNavInput_DpadRight, // + ImGuiNavInput_DpadUp, // + ImGuiNavInput_DpadDown, // + ImGuiNavInput_LStickLeft, // scroll / move window (w/ PadMenu) // e.g. Left Analog Stick Left/Right/Up/Down + ImGuiNavInput_LStickRight, // + ImGuiNavInput_LStickUp, // + ImGuiNavInput_LStickDown, // + ImGuiNavInput_FocusPrev, // next window (w/ PadMenu) // e.g. L1 or L2 (PS4), LB or LT (Xbox), L or ZL (Switch) + ImGuiNavInput_FocusNext, // prev window (w/ PadMenu) // e.g. R1 or R2 (PS4), RB or RT (Xbox), R or ZL (Switch) + ImGuiNavInput_TweakSlow, // slower tweaks // e.g. L1 or L2 (PS4), LB or LT (Xbox), L or ZL (Switch) + ImGuiNavInput_TweakFast, // faster tweaks // e.g. R1 or R2 (PS4), RB or RT (Xbox), R or ZL (Switch) + + // [Internal] Don't use directly! This is used internally to differentiate keyboard from gamepad inputs for behaviors that require to differentiate them. + // Keyboard behavior that have no corresponding gamepad mapping (e.g. CTRL+TAB) will be directly reading from io.KeysDown[] instead of io.NavInputs[]. + ImGuiNavInput_KeyMenu_, // toggle menu // = io.KeyAlt + ImGuiNavInput_KeyLeft_, // move left // = Arrow keys + ImGuiNavInput_KeyRight_, // move right + ImGuiNavInput_KeyUp_, // move up + ImGuiNavInput_KeyDown_, // move down + ImGuiNavInput_COUNT, + ImGuiNavInput_InternalStart_ = ImGuiNavInput_KeyMenu_ +}; + +// Configuration flags stored in io.ConfigFlags. Set by user/application. +enum ImGuiConfigFlags_ +{ + ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.KeysDown[]. + ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui back-end to fill io.NavInputs[]. Back-end also needs to set ImGuiBackendFlags_HasGamepad. + ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Instruct navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. + ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Instruct navigation to not set the io.WantCaptureKeyboard flag when io.NavActive is set. + ImGuiConfigFlags_NoMouse = 1 << 4, // Instruct imgui to clear mouse position/buttons in NewFrame(). This allows ignoring the mouse information set by the back-end. + ImGuiConfigFlags_NoMouseCursorChange = 1 << 5, // Instruct back-end to not alter mouse cursor shape and visibility. Use if the back-end cursor changes are interfering with yours and you don't want to use SetMouseCursor() to change mouse cursor. You may want to honor requests from imgui by reading GetMouseCursor() yourself instead. + + // User storage (to allow your back-end/engine to communicate to code that may be shared between multiple projects. Those flags are not used by core ImGui) + ImGuiConfigFlags_IsSRGB = 1 << 20, // Application is SRGB-aware. + ImGuiConfigFlags_IsTouchScreen = 1 << 21 // Application is using a touch screen instead of a mouse. +}; + +// Back-end capabilities flags stored in io.BackendFlags. Set by imgui_impl_xxx or custom back-end. +enum ImGuiBackendFlags_ +{ + ImGuiBackendFlags_HasGamepad = 1 << 0, // Back-end supports gamepad and currently has one connected. + ImGuiBackendFlags_HasMouseCursors = 1 << 1, // Back-end supports honoring GetMouseCursor() value to change the OS cursor shape. + ImGuiBackendFlags_HasSetMousePos = 1 << 2 // Back-end supports io.WantSetMousePos requests to reposition the OS mouse position (only used if ImGuiConfigFlags_NavEnableSetMousePos is set). +}; + +// Enumeration for PushStyleColor() / PopStyleColor() +enum ImGuiCol_ +{ + ImGuiCol_Text, + ImGuiCol_TextDisabled, + ImGuiCol_WindowBg, // Background of normal windows + ImGuiCol_ChildBg, // Background of child windows + ImGuiCol_PopupBg, // Background of popups, menus, tooltips windows + ImGuiCol_Border, + ImGuiCol_BorderShadow, + ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input + ImGuiCol_FrameBgHovered, + ImGuiCol_FrameBgActive, + ImGuiCol_TitleBg, + ImGuiCol_TitleBgActive, + ImGuiCol_TitleBgCollapsed, + ImGuiCol_MenuBarBg, + ImGuiCol_ScrollbarBg, + ImGuiCol_ScrollbarGrab, + ImGuiCol_ScrollbarGrabHovered, + ImGuiCol_ScrollbarGrabActive, + ImGuiCol_CheckMark, + ImGuiCol_SliderGrab, + ImGuiCol_SliderGrabActive, + ImGuiCol_Button, + ImGuiCol_ButtonHovered, + ImGuiCol_ButtonActive, + ImGuiCol_Header, + ImGuiCol_HeaderHovered, + ImGuiCol_HeaderActive, + ImGuiCol_Separator, + ImGuiCol_SeparatorHovered, + ImGuiCol_SeparatorActive, + ImGuiCol_ResizeGrip, + ImGuiCol_ResizeGripHovered, + ImGuiCol_ResizeGripActive, + ImGuiCol_PlotLines, + ImGuiCol_PlotLinesHovered, + ImGuiCol_PlotHistogram, + ImGuiCol_PlotHistogramHovered, + ImGuiCol_TextSelectedBg, + ImGuiCol_DragDropTarget, + ImGuiCol_NavHighlight, // Gamepad/keyboard: current highlighted item + ImGuiCol_NavWindowingHighlight, // Highlight window when using CTRL+TAB + ImGuiCol_NavWindowingDimBg, // Darken/colorize entire screen behind the CTRL+TAB window list, when active + ImGuiCol_ModalWindowDimBg, // Darken/colorize entire screen behind a modal window, when one is active + ImGuiCol_COUNT + + // Obsolete names (will be removed) +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + , ImGuiCol_ChildWindowBg = ImGuiCol_ChildBg, ImGuiCol_Column = ImGuiCol_Separator, ImGuiCol_ColumnHovered = ImGuiCol_SeparatorHovered, ImGuiCol_ColumnActive = ImGuiCol_SeparatorActive + , ImGuiCol_ModalWindowDarkening = ImGuiCol_ModalWindowDimBg + //ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered, // [unused since 1.60+] the close button now uses regular button colors. + //ImGuiCol_ComboBg, // [unused since 1.53+] ComboBg has been merged with PopupBg, so a redirect isn't accurate. +#endif +}; + +// Enumeration for PushStyleVar() / PopStyleVar() to temporarily modify the ImGuiStyle structure. +// NB: the enum only refers to fields of ImGuiStyle which makes sense to be pushed/popped inside UI code. During initialization, feel free to just poke into ImGuiStyle directly. +// NB: if changing this enum, you need to update the associated internal table GStyleVarInfo[] accordingly. This is where we link enum values to members offset/type. +enum ImGuiStyleVar_ +{ + // Enum name ......................// Member in ImGuiStyle structure (see ImGuiStyle for descriptions) + ImGuiStyleVar_Alpha, // float Alpha + ImGuiStyleVar_WindowPadding, // ImVec2 WindowPadding + ImGuiStyleVar_WindowRounding, // float WindowRounding + ImGuiStyleVar_WindowBorderSize, // float WindowBorderSize + ImGuiStyleVar_WindowMinSize, // ImVec2 WindowMinSize + ImGuiStyleVar_WindowTitleAlign, // ImVec2 WindowTitleAlign + ImGuiStyleVar_ChildRounding, // float ChildRounding + ImGuiStyleVar_ChildBorderSize, // float ChildBorderSize + ImGuiStyleVar_PopupRounding, // float PopupRounding + ImGuiStyleVar_PopupBorderSize, // float PopupBorderSize + ImGuiStyleVar_FramePadding, // ImVec2 FramePadding + ImGuiStyleVar_FrameRounding, // float FrameRounding + ImGuiStyleVar_FrameBorderSize, // float FrameBorderSize + ImGuiStyleVar_ItemSpacing, // ImVec2 ItemSpacing + ImGuiStyleVar_ItemInnerSpacing, // ImVec2 ItemInnerSpacing + ImGuiStyleVar_IndentSpacing, // float IndentSpacing + ImGuiStyleVar_ScrollbarSize, // float ScrollbarSize + ImGuiStyleVar_ScrollbarRounding, // float ScrollbarRounding + ImGuiStyleVar_GrabMinSize, // float GrabMinSize + ImGuiStyleVar_GrabRounding, // float GrabRounding + ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign + ImGuiStyleVar_COUNT + + // Obsolete names (will be removed) +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + , ImGuiStyleVar_Count_ = ImGuiStyleVar_COUNT, ImGuiStyleVar_ChildWindowRounding = ImGuiStyleVar_ChildRounding +#endif +}; + +// Enumeration for ColorEdit3() / ColorEdit4() / ColorPicker3() / ColorPicker4() / ColorButton() +enum ImGuiColorEditFlags_ +{ + ImGuiColorEditFlags_None = 0, + ImGuiColorEditFlags_NoAlpha = 1 << 1, // // ColorEdit, ColorPicker, ColorButton: ignore Alpha component (read 3 components from the input pointer). + ImGuiColorEditFlags_NoPicker = 1 << 2, // // ColorEdit: disable picker when clicking on colored square. + ImGuiColorEditFlags_NoOptions = 1 << 3, // // ColorEdit: disable toggling options menu when right-clicking on inputs/small preview. + ImGuiColorEditFlags_NoSmallPreview = 1 << 4, // // ColorEdit, ColorPicker: disable colored square preview next to the inputs. (e.g. to show only the inputs) + ImGuiColorEditFlags_NoInputs = 1 << 5, // // ColorEdit, ColorPicker: disable inputs sliders/text widgets (e.g. to show only the small preview colored square). + ImGuiColorEditFlags_NoTooltip = 1 << 6, // // ColorEdit, ColorPicker, ColorButton: disable tooltip when hovering the preview. + ImGuiColorEditFlags_NoLabel = 1 << 7, // // ColorEdit, ColorPicker: disable display of inline text label (the label is still forwarded to the tooltip and picker). + ImGuiColorEditFlags_NoSidePreview = 1 << 8, // // ColorPicker: disable bigger color preview on right side of the picker, use small colored square preview instead. + ImGuiColorEditFlags_NoDragDrop = 1 << 9, // // ColorEdit: disable drag and drop target. ColorButton: disable drag and drop source. + + // User Options (right-click on widget to change some of them). You can set application defaults using SetColorEditOptions(). The idea is that you probably don't want to override them in most of your calls, let the user choose and/or call SetColorEditOptions() during startup. + ImGuiColorEditFlags_AlphaBar = 1 << 16, // // ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker. + ImGuiColorEditFlags_AlphaPreview = 1 << 17, // // ColorEdit, ColorPicker, ColorButton: display preview as a transparent color over a checkerboard, instead of opaque. + ImGuiColorEditFlags_AlphaPreviewHalf= 1 << 18, // // ColorEdit, ColorPicker, ColorButton: display half opaque / half checkerboard, instead of opaque. + ImGuiColorEditFlags_HDR = 1 << 19, // // (WIP) ColorEdit: Currently only disable 0.0f..1.0f limits in RGBA edition (note: you probably want to use ImGuiColorEditFlags_Float flag as well). + ImGuiColorEditFlags_RGB = 1 << 20, // [Inputs] // ColorEdit: choose one among RGB/HSV/HEX. ColorPicker: choose any combination using RGB/HSV/HEX. + ImGuiColorEditFlags_HSV = 1 << 21, // [Inputs] // " + ImGuiColorEditFlags_HEX = 1 << 22, // [Inputs] // " + ImGuiColorEditFlags_Uint8 = 1 << 23, // [DataType] // ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0..255. + ImGuiColorEditFlags_Float = 1 << 24, // [DataType] // ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0.0f..1.0f floats instead of 0..255 integers. No round-trip of value via integers. + ImGuiColorEditFlags_PickerHueBar = 1 << 25, // [PickerMode] // ColorPicker: bar for Hue, rectangle for Sat/Value. + ImGuiColorEditFlags_PickerHueWheel = 1 << 26, // [PickerMode] // ColorPicker: wheel for Hue, triangle for Sat/Value. + + // [Internal] Masks + ImGuiColorEditFlags__InputsMask = ImGuiColorEditFlags_RGB|ImGuiColorEditFlags_HSV|ImGuiColorEditFlags_HEX, + ImGuiColorEditFlags__DataTypeMask = ImGuiColorEditFlags_Uint8|ImGuiColorEditFlags_Float, + ImGuiColorEditFlags__PickerMask = ImGuiColorEditFlags_PickerHueWheel|ImGuiColorEditFlags_PickerHueBar, + ImGuiColorEditFlags__OptionsDefault = ImGuiColorEditFlags_Uint8|ImGuiColorEditFlags_RGB|ImGuiColorEditFlags_PickerHueBar // Change application default using SetColorEditOptions() +}; + +// Enumeration for GetMouseCursor() +// User code may request binding to display given cursor by calling SetMouseCursor(), which is why we have some cursors that are marked unused here +enum ImGuiMouseCursor_ +{ + ImGuiMouseCursor_None = -1, + ImGuiMouseCursor_Arrow = 0, + ImGuiMouseCursor_TextInput, // When hovering over InputText, etc. + ImGuiMouseCursor_ResizeAll, // (Unused by imgui functions) + ImGuiMouseCursor_ResizeNS, // When hovering over an horizontal border + ImGuiMouseCursor_ResizeEW, // When hovering over a vertical border or a column + ImGuiMouseCursor_ResizeNESW, // When hovering over the bottom-left corner of a window + ImGuiMouseCursor_ResizeNWSE, // When hovering over the bottom-right corner of a window + ImGuiMouseCursor_Hand, // (Unused by imgui functions. Use for e.g. hyperlinks) + ImGuiMouseCursor_COUNT + + // Obsolete names (will be removed) +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + , ImGuiMouseCursor_Count_ = ImGuiMouseCursor_COUNT +#endif +}; + +// Condition for ImGui::SetWindow***(), SetNextWindow***(), SetNextTreeNode***() functions +// Important: Treat as a regular enum! Do NOT combine multiple values using binary operators! All the functions above treat 0 as a shortcut to ImGuiCond_Always. +enum ImGuiCond_ +{ + ImGuiCond_Always = 1 << 0, // Set the variable + ImGuiCond_Once = 1 << 1, // Set the variable once per runtime session (only the first call with succeed) + ImGuiCond_FirstUseEver = 1 << 2, // Set the variable if the object/window has no persistently saved data (no entry in .ini file) + ImGuiCond_Appearing = 1 << 3 // Set the variable if the object/window is appearing after being hidden/inactive (or the first time) + + // Obsolete names (will be removed) +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + , ImGuiSetCond_Always = ImGuiCond_Always, ImGuiSetCond_Once = ImGuiCond_Once, ImGuiSetCond_FirstUseEver = ImGuiCond_FirstUseEver, ImGuiSetCond_Appearing = ImGuiCond_Appearing +#endif +}; + +// You may modify the ImGui::GetStyle() main instance during initialization and before NewFrame(). +// During the frame, use ImGui::PushStyleVar(ImGuiStyleVar_XXXX)/PopStyleVar() to alter the main style values, and ImGui::PushStyleColor(ImGuiCol_XXX)/PopStyleColor() for colors. +struct ImGuiStyle +{ + float Alpha; // Global alpha applies to everything in ImGui. + ImVec2 WindowPadding; // Padding within a window. + float WindowRounding; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. + float WindowBorderSize; // Thickness of border around windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). + ImVec2 WindowMinSize; // Minimum window size. This is a global setting. If you want to constraint individual windows, use SetNextWindowSizeConstraints(). + ImVec2 WindowTitleAlign; // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered. + float ChildRounding; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows. + float ChildBorderSize; // Thickness of border around child windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). + float PopupRounding; // Radius of popup window corners rounding. (Note that tooltip windows use WindowRounding) + float PopupBorderSize; // Thickness of border around popup/tooltip windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). + ImVec2 FramePadding; // Padding within a framed rectangle (used by most widgets). + float FrameRounding; // Radius of frame corners rounding. Set to 0.0f to have rectangular frame (used by most widgets). + float FrameBorderSize; // Thickness of border around frames. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). + ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines. + ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label). + ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! + float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). + float ColumnsMinSpacing; // Minimum horizontal spacing between two columns. + float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar. + float ScrollbarRounding; // Radius of grab corners for scrollbar. + float GrabMinSize; // Minimum width/height of a grab box for slider/scrollbar. + float GrabRounding; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. + ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f,0.5f) for horizontally+vertically centered. + ImVec2 DisplayWindowPadding; // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows. + ImVec2 DisplaySafeAreaPadding; // If you cannot see the edges of your screen (e.g. on a TV) increase the safe area padding. Apply to popups/tooltips as well regular windows. NB: Prefer configuring your TV sets correctly! + float MouseCursorScale; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later. + bool AntiAliasedLines; // Enable anti-aliasing on lines/borders. Disable if you are really tight on CPU/GPU. + bool AntiAliasedFill; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) + float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. + ImVec4 Colors[ImGuiCol_COUNT]; + + IMGUI_API ImGuiStyle(); + IMGUI_API void ScaleAllSizes(float scale_factor); +}; + +// This is where your app communicate with ImGui. Access via ImGui::GetIO(). +// Read 'Programmer guide' section in .cpp file for general usage. +struct ImGuiIO +{ + //------------------------------------------------------------------ + // Settings (fill once) // Default value: + //------------------------------------------------------------------ + + ImGuiConfigFlags ConfigFlags; // = 0 // See ImGuiConfigFlags_ enum. Set by user/application. Gamepad/keyboard navigation options, etc. + ImGuiBackendFlags BackendFlags; // = 0 // Set ImGuiBackendFlags_ enum. Set by imgui_impl_xxx files or custom back-end to communicate features supported by the back-end. + ImVec2 DisplaySize; // // Display size, in pixels. For clamping windows positions. + float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. + float IniSavingRate; // = 5.0f // Minimum time between saving positions/sizes to .ini file, in seconds. + const char* IniFilename; // = "imgui.ini" // Path to .ini file. Set NULL to disable automatic .ini loading/saving, if e.g. you want to manually load/save from memory. + const char* LogFilename; // = "imgui_log.txt" // Path to .log file (default parameter to ImGui::LogToFile when no file is specified). + float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds. + float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels. + float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging. + int KeyMap[ImGuiKey_COUNT]; // // Map of indices into the KeysDown[512] entries array which represent your "native" keyboard state. + float KeyRepeatDelay; // = 0.250f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.). + float KeyRepeatRate; // = 0.050f // When holding a key/button, rate at which it repeats, in seconds. + void* UserData; // = NULL // Store your own data for retrieval by callbacks. + + ImFontAtlas* Fonts; // // Load and assemble one or more fonts into a single tightly packed texture. Output to Fonts array. + float FontGlobalScale; // = 1.0f // Global scale all fonts + bool FontAllowUserScaling; // = false // Allow user scaling text of individual window with CTRL+Wheel. + ImFont* FontDefault; // = NULL // Font to use on NewFrame(). Use NULL to uses Fonts->Fonts[0]. + ImVec2 DisplayFramebufferScale; // = (1.0f,1.0f) // For retina display or other situations where window coordinates are different from framebuffer coordinates. User storage only, presently not used by ImGui. + ImVec2 DisplayVisibleMin; // (0.0f,0.0f) // If you use DisplaySize as a virtual space larger than your screen, set DisplayVisibleMin/Max to the visible area. + ImVec2 DisplayVisibleMax; // (0.0f,0.0f) // If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize + + // Miscellaneous configuration options + bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl (was called io.OptMacOSXBehaviors prior to 1.63) + bool ConfigCursorBlink; // = true // Set to false to disable blinking cursor, for users who consider it distracting. (was called: io.OptCursorBlink prior to 1.63) + bool ConfigResizeWindowsFromEdges; // = false // [BETA] Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be the ImGuiWindowFlags_ResizeFromAnySide flag) + + //------------------------------------------------------------------ + // Settings (User Functions) + //------------------------------------------------------------------ + + // Optional: access OS clipboard + // (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures) + const char* (*GetClipboardTextFn)(void* user_data); + void (*SetClipboardTextFn)(void* user_data, const char* text); + void* ClipboardUserData; + + // Optional: notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME in Windows) + // (default to use native imm32 api on Windows) + void (*ImeSetInputScreenPosFn)(int x, int y); + void* ImeWindowHandle; // (Windows) Set this to your HWND to get automatic IME cursor positioning. + +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + // [OBSOLETE] Rendering function, will be automatically called in Render(). Please call your rendering function yourself now! + // You can obtain the ImDrawData* by calling ImGui::GetDrawData() after Render(). See example applications if you are unsure of how to implement this. + void (*RenderDrawListsFn)(ImDrawData* data); +#else + // This is only here to keep ImGuiIO the same size, so that IMGUI_DISABLE_OBSOLETE_FUNCTIONS can exceptionally be used outside of imconfig.h. + void* RenderDrawListsFnDummy; +#endif + + //------------------------------------------------------------------ + // Input - Fill before calling NewFrame() + //------------------------------------------------------------------ + + ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX,-FLT_MAX) if mouse is unavailable (on another screen, etc.) + bool MouseDown[5]; // Mouse buttons: 0=left, 1=right, 2=middle + extras. ImGui itself mostly only uses left button (BeginPopupContext** are using right button). Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. + float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text. + float MouseWheelH; // Mouse wheel Horizontal. Most users don't have a mouse with an horizontal wheel, may not be filled by all back-ends. + bool MouseDrawCursor; // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). + bool KeyCtrl; // Keyboard modifier pressed: Control + bool KeyShift; // Keyboard modifier pressed: Shift + bool KeyAlt; // Keyboard modifier pressed: Alt + bool KeySuper; // Keyboard modifier pressed: Cmd/Super/Windows + bool KeysDown[512]; // Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). + ImWchar InputCharacters[16+1]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper. + float NavInputs[ImGuiNavInput_COUNT]; // Gamepad inputs (keyboard keys will be auto-mapped and be written here by ImGui::NewFrame, all values will be cleared back to zero in ImGui::EndFrame) + + // Functions + IMGUI_API void AddInputCharacter(ImWchar c); // Add new character into InputCharacters[] + IMGUI_API void AddInputCharactersUTF8(const char* utf8_chars); // Add new characters into InputCharacters[] from an UTF-8 string + inline void ClearInputCharacters() { InputCharacters[0] = 0; } // Clear the text input buffer manually + + //------------------------------------------------------------------ + // Output - Retrieve after calling NewFrame() + //------------------------------------------------------------------ + + bool WantCaptureMouse; // When io.WantCaptureMouse is true, imgui will use the mouse inputs, do not dispatch them to your main game/application (in both cases, always pass on mouse inputs to imgui). (e.g. unclicked mouse is hovering over an imgui window, widget is active, mouse was clicked over an imgui window, etc.). + bool WantCaptureKeyboard; // When io.WantCaptureKeyboard is true, imgui will use the keyboard inputs, do not dispatch them to your main game/application (in both cases, always pass keyboard inputs to imgui). (e.g. InputText active, or an imgui window is focused and navigation is enabled, etc.). + bool WantTextInput; // Mobile/console: when io.WantTextInput is true, you may display an on-screen keyboard. This is set by ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active). + bool WantSetMousePos; // MousePos has been altered, back-end should reposition mouse on next frame. Set only when ImGuiConfigFlags_NavEnableSetMousePos flag is enabled. + bool WantSaveIniSettings; // When manual .ini load/save is active (io.IniFilename == NULL), this will be set to notify your application that you can call SaveIniSettingsToMemory() and save yourself. IMPORTANT: You need to clear io.WantSaveIniSettings yourself. + bool NavActive; // Directional navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag. + bool NavVisible; // Directional navigation is visible and allowed (will handle ImGuiKey_NavXXX events). + float Framerate; // Application framerate estimation, in frame per second. Solely for convenience. Rolling average estimation based on IO.DeltaTime over 120 frames + int MetricsRenderVertices; // Vertices output during last call to Render() + int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3 + int MetricsRenderWindows; // Number of visible windows + int MetricsActiveWindows; // Number of active windows + int MetricsActiveAllocations; // Number of active allocations, updated by MemAlloc/MemFree based on current context. May be off if you have multiple imgui contexts. + ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are invalid (-FLT_MAX,-FLT_MAX), so a disappearing/reappearing mouse won't have a huge delta. + + //------------------------------------------------------------------ + // [Internal] ImGui will maintain those fields. Forward compatibility not guaranteed! + //------------------------------------------------------------------ + + ImVec2 MousePosPrev; // Previous mouse position temporary storage (nb: not for public use, set to MousePos in NewFrame()) + ImVec2 MouseClickedPos[5]; // Position at time of clicking + double MouseClickedTime[5]; // Time of last click (used to figure out double-click) + bool MouseClicked[5]; // Mouse button went from !Down to Down + bool MouseDoubleClicked[5]; // Has mouse button been double-clicked? + bool MouseReleased[5]; // Mouse button went from Down to !Down + bool MouseDownOwned[5]; // Track if button was clicked inside a window. We don't request mouse capture from the application if click started outside ImGui bounds. + float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked) + float MouseDownDurationPrev[5]; // Previous time the mouse button has been down + ImVec2 MouseDragMaxDistanceAbs[5]; // Maximum distance, absolute, on each axis, of how much mouse has traveled from the clicking point + float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the clicking point + float KeysDownDuration[512]; // Duration the keyboard key has been down (0.0f == just pressed) + float KeysDownDurationPrev[512]; // Previous duration the key has been down + float NavInputsDownDuration[ImGuiNavInput_COUNT]; + float NavInputsDownDurationPrev[ImGuiNavInput_COUNT]; + + IMGUI_API ImGuiIO(); +}; + +//----------------------------------------------------------------------------- +// Obsolete functions (Will be removed! Read 'API BREAKING CHANGES' section in imgui.cpp for details) +//----------------------------------------------------------------------------- + +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS +namespace ImGui +{ + // OBSOLETED in 1.61 (from Apr 2018) + IMGUI_API bool InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags extra_flags = 0); // Use the 'const char* format' version instead of 'decimal_precision'! + IMGUI_API bool InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags extra_flags = 0); + // OBSOLETED in 1.60 (from Dec 2017) + static inline bool IsAnyWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_AnyWindow); } + static inline bool IsAnyWindowHovered() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } + static inline ImVec2 CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge = false, float outward = 0.f) { (void)on_edge; (void)outward; IM_ASSERT(0); return pos; } + // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017) + static inline void ShowTestWindow() { return ShowDemoWindow(); } + static inline bool IsRootWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootWindow); } + static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); } + static inline void SetNextWindowContentWidth(float w) { SetNextWindowContentSize(ImVec2(w, 0.0f)); } + static inline float GetItemsLineHeightWithSpacing() { return GetFrameHeightWithSpacing(); } + // OBSOLETED in 1.52 (between Aug 2017 and Oct 2017) + IMGUI_API bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // Use SetNextWindowSize(size, ImGuiCond_FirstUseEver) + SetNextWindowBgAlpha() instead. + static inline bool IsRootWindowOrAnyChildHovered() { return IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); } + static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } + static inline void SetNextWindowPosCenter(ImGuiCond c=0) { ImGuiIO& io = GetIO(); SetNextWindowPos(ImVec2(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f), c, ImVec2(0.5f, 0.5f)); } + // OBSOLETED in 1.51 (between Jun 2017 and Aug 2017) + static inline bool IsItemHoveredRect() { return IsItemHovered(ImGuiHoveredFlags_RectOnly); } + static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // This was misleading and partly broken. You probably want to use the ImGui::GetIO().WantCaptureMouse flag instead. + static inline bool IsMouseHoveringAnyWindow() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } + static inline bool IsMouseHoveringWindow() { return IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); } + // OBSOLETED IN 1.49 (between Apr 2016 and May 2016) + static inline bool CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1 << 5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } +} +#endif + +//----------------------------------------------------------------------------- +// Helpers +//----------------------------------------------------------------------------- + +// Helper: Lightweight std::vector<> like class to avoid dragging dependencies (also: Windows implementation of STL with debug enabled is absurdly slow, so let's bypass it so our code runs fast in debug). +// *Important* Our implementation does NOT call C++ constructors/destructors. This is intentional, we do not require it but you have to be mindful of that. Do _not_ use this class as a std::vector replacement in your code! +template +class ImVector +{ +public: + int Size; + int Capacity; + T* Data; + + typedef T value_type; + typedef value_type* iterator; + typedef const value_type* const_iterator; + + inline ImVector() { Size = Capacity = 0; Data = NULL; } + inline ~ImVector() { if (Data) ImGui::MemFree(Data); } + inline ImVector(const ImVector& src) { Size = Capacity = 0; Data = NULL; operator=(src); } + inline ImVector& operator=(const ImVector& src) { clear(); resize(src.Size); memcpy(Data, src.Data, (size_t)Size * sizeof(value_type)); return *this; } + + inline bool empty() const { return Size == 0; } + inline int size() const { return Size; } + inline int capacity() const { return Capacity; } + inline value_type& operator[](int i) { IM_ASSERT(i < Size); return Data[i]; } + inline const value_type& operator[](int i) const { IM_ASSERT(i < Size); return Data[i]; } + + inline void clear() { if (Data) { Size = Capacity = 0; ImGui::MemFree(Data); Data = NULL; } } + inline iterator begin() { return Data; } + inline const_iterator begin() const { return Data; } + inline iterator end() { return Data + Size; } + inline const_iterator end() const { return Data + Size; } + inline value_type& front() { IM_ASSERT(Size > 0); return Data[0]; } + inline const value_type& front() const { IM_ASSERT(Size > 0); return Data[0]; } + inline value_type& back() { IM_ASSERT(Size > 0); return Data[Size - 1]; } + inline const value_type& back() const { IM_ASSERT(Size > 0); return Data[Size - 1]; } + inline void swap(ImVector& rhs) { int rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; int rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; } + + inline int _grow_capacity(int sz) const { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > sz ? new_capacity : sz; } + inline void resize(int new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; } + inline void resize(int new_size,const value_type& v){ if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) memcpy(&Data[n], &v, sizeof(v)); Size = new_size; } + inline void reserve(int new_capacity) + { + if (new_capacity <= Capacity) + return; + value_type* new_data = (value_type*)ImGui::MemAlloc((size_t)new_capacity * sizeof(value_type)); + if (Data) + { + memcpy(new_data, Data, (size_t)Size * sizeof(value_type)); + ImGui::MemFree(Data); + } + Data = new_data; + Capacity = new_capacity; + } + + // NB: It is forbidden to call push_back/push_front/insert with a reference pointing inside the ImVector data itself! e.g. v.push_back(v[10]) is forbidden. + inline void push_back(const value_type& v) { if (Size == Capacity) reserve(_grow_capacity(Size + 1)); memcpy(&Data[Size], &v, sizeof(v)); Size++; } + inline void pop_back() { IM_ASSERT(Size > 0); Size--; } + inline void push_front(const value_type& v) { if (Size == 0) push_back(v); else insert(Data, v); } + inline iterator erase(const_iterator it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(value_type)); Size--; return Data + off; } + inline iterator erase(const_iterator it, const_iterator it_last){ IM_ASSERT(it >= Data && it < Data+Size && it_last > it && it_last <= Data+Size); const ptrdiff_t count = it_last - it; const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + count, ((size_t)Size - (size_t)off - count) * sizeof(value_type)); Size -= (int)count; return Data + off; } + inline iterator erase_unsorted(const_iterator it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; if (it < Data+Size-1) memcpy(Data + off, Data + Size - 1, sizeof(value_type)); Size--; return Data + off; } + inline iterator insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(value_type)); memcpy(&Data[off], &v, sizeof(v)); Size++; return Data + off; } + inline bool contains(const value_type& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; } + inline int index_from_pointer(const_iterator it) const { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; return (int)off; } +}; + +// Helper: IM_NEW(), IM_PLACEMENT_NEW(), IM_DELETE() macros to call MemAlloc + Placement New, Placement Delete + MemFree +// We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax. +// Defining a custom placement new() with a dummy parameter allows us to bypass including which on some platforms complains when user has disabled exceptions. +struct ImNewDummy {}; +inline void* operator new(size_t, ImNewDummy, void* ptr) { return ptr; } +inline void operator delete(void*, ImNewDummy, void*) {} // This is only required so we can use the symetrical new() +#define IM_PLACEMENT_NEW(_PTR) new(ImNewDummy(), _PTR) +#define IM_NEW(_TYPE) new(ImNewDummy(), ImGui::MemAlloc(sizeof(_TYPE))) _TYPE +template void IM_DELETE(T* p) { if (p) { p->~T(); ImGui::MemFree(p); } } + +// Helper: Execute a block of code at maximum once a frame. Convenient if you want to quickly create an UI within deep-nested code that runs multiple times every frame. +// Usage: static ImGuiOnceUponAFrame oaf; if (oaf) ImGui::Text("This will be called only once per frame"); +struct ImGuiOnceUponAFrame +{ + ImGuiOnceUponAFrame() { RefFrame = -1; } + mutable int RefFrame; + operator bool() const { int current_frame = ImGui::GetFrameCount(); if (RefFrame == current_frame) return false; RefFrame = current_frame; return true; } +}; + +// Helper: Macro for ImGuiOnceUponAFrame. Attention: The macro expands into 2 statement so make sure you don't use it within e.g. an if() statement without curly braces. +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // Will obsolete +#define IMGUI_ONCE_UPON_A_FRAME static ImGuiOnceUponAFrame imgui_oaf; if (imgui_oaf) +#endif + +// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" +struct ImGuiTextFilter +{ + IMGUI_API ImGuiTextFilter(const char* default_filter = ""); + IMGUI_API bool Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build + IMGUI_API bool PassFilter(const char* text, const char* text_end = NULL) const; + IMGUI_API void Build(); + void Clear() { InputBuf[0] = 0; Build(); } + bool IsActive() const { return !Filters.empty(); } + + // [Internal] + struct TextRange + { + const char* b; + const char* e; + + TextRange() { b = e = NULL; } + TextRange(const char* _b, const char* _e) { b = _b; e = _e; } + const char* begin() const { return b; } + const char* end () const { return e; } + bool empty() const { return b == e; } + IMGUI_API void split(char separator, ImVector* out) const; + }; + char InputBuf[256]; + ImVector Filters; + int CountGrep; +}; + +// Helper: Text buffer for logging/accumulating text +struct ImGuiTextBuffer +{ + ImVector Buf; + + ImGuiTextBuffer() { Buf.push_back(0); } + inline char operator[](int i) { return Buf.Data[i]; } + const char* begin() const { return &Buf.front(); } + const char* end() const { return &Buf.back(); } // Buf is zero-terminated, so end() will point on the zero-terminator + int size() const { return Buf.Size - 1; } + bool empty() { return Buf.Size <= 1; } + void clear() { Buf.clear(); Buf.push_back(0); } + void reserve(int capacity) { Buf.reserve(capacity); } + const char* c_str() const { return Buf.Data; } + IMGUI_API void appendf(const char* fmt, ...) IM_FMTARGS(2); + IMGUI_API void appendfv(const char* fmt, va_list args) IM_FMTLIST(2); +}; + +// Helper: Simple Key->value storage +// Typically you don't have to worry about this since a storage is held within each Window. +// We use it to e.g. store collapse state for a tree (Int 0/1) +// This is optimized for efficient lookup (dichotomy into a contiguous buffer) and rare insertion (typically tied to user interactions aka max once a frame) +// You can use it as custom user storage for temporary values. Declare your own storage if, for example: +// - You want to manipulate the open/close state of a particular sub-tree in your interface (tree node uses Int 0/1 to store their state). +// - You want to store custom debug data easily without adding or editing structures in your code (probably not efficient, but convenient) +// Types are NOT stored, so it is up to you to make sure your Key don't collide with different types. +struct ImGuiStorage +{ + struct Pair + { + ImGuiID key; + union { int val_i; float val_f; void* val_p; }; + Pair(ImGuiID _key, int _val_i) { key = _key; val_i = _val_i; } + Pair(ImGuiID _key, float _val_f) { key = _key; val_f = _val_f; } + Pair(ImGuiID _key, void* _val_p) { key = _key; val_p = _val_p; } + }; + ImVector Data; + + // - Get***() functions find pair, never add/allocate. Pairs are sorted so a query is O(log N) + // - Set***() functions find pair, insertion on demand if missing. + // - Sorted insertion is costly, paid once. A typical frame shouldn't need to insert any new pair. + void Clear() { Data.clear(); } + IMGUI_API int GetInt(ImGuiID key, int default_val = 0) const; + IMGUI_API void SetInt(ImGuiID key, int val); + IMGUI_API bool GetBool(ImGuiID key, bool default_val = false) const; + IMGUI_API void SetBool(ImGuiID key, bool val); + IMGUI_API float GetFloat(ImGuiID key, float default_val = 0.0f) const; + IMGUI_API void SetFloat(ImGuiID key, float val); + IMGUI_API void* GetVoidPtr(ImGuiID key) const; // default_val is NULL + IMGUI_API void SetVoidPtr(ImGuiID key, void* val); + + // - Get***Ref() functions finds pair, insert on demand if missing, return pointer. Useful if you intend to do Get+Set. + // - References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer. + // - A typical use case where this is convenient for quick hacking (e.g. add storage during a live Edit&Continue session if you can't modify existing struct) + // float* pvar = ImGui::GetFloatRef(key); ImGui::SliderFloat("var", pvar, 0, 100.0f); some_var += *pvar; + IMGUI_API int* GetIntRef(ImGuiID key, int default_val = 0); + IMGUI_API bool* GetBoolRef(ImGuiID key, bool default_val = false); + IMGUI_API float* GetFloatRef(ImGuiID key, float default_val = 0.0f); + IMGUI_API void** GetVoidPtrRef(ImGuiID key, void* default_val = NULL); + + // Use on your own storage if you know only integer are being stored (open/close all tree nodes) + IMGUI_API void SetAllInt(int val); + + // For quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once. + IMGUI_API void BuildSortByKey(); +}; + +// Shared state of InputText(), passed to callback when a ImGuiInputTextFlags_Callback* flag is used and the corresponding callback is triggered. +struct ImGuiTextEditCallbackData +{ + ImGuiInputTextFlags EventFlag; // One of ImGuiInputTextFlags_Callback* // Read-only + ImGuiInputTextFlags Flags; // What user passed to InputText() // Read-only + void* UserData; // What user passed to InputText() // Read-only + bool ReadOnly; // Read-only mode // Read-only + + // CharFilter event: + ImWchar EventChar; // Character input // Read-write (replace character or set to zero) + + // Completion,History,Always events: + // If you modify the buffer contents make sure you update 'BufTextLen' and set 'BufDirty' to true. + ImGuiKey EventKey; // Key pressed (Up/Down/TAB) // Read-only + char* Buf; // Current text buffer // Read-write (pointed data only, can't replace the actual pointer) + int BufTextLen; // Current text length in bytes // Read-write + int BufSize; // Maximum text length in bytes // Read-only + bool BufDirty; // Set if you modify Buf/BufTextLen!! // Write + int CursorPos; // // Read-write + int SelectionStart; // // Read-write (== to SelectionEnd when no selection) + int SelectionEnd; // // Read-write + + // NB: Helper functions for text manipulation. Calling those function loses selection. + IMGUI_API void DeleteChars(int pos, int bytes_count); + IMGUI_API void InsertChars(int pos, const char* text, const char* text_end = NULL); + bool HasSelection() const { return SelectionStart != SelectionEnd; } +}; + +// Resizing callback data to apply custom constraint. As enabled by SetNextWindowSizeConstraints(). Callback is called during the next Begin(). +// NB: For basic min/max size constraint on each axis you don't need to use the callback! The SetNextWindowSizeConstraints() parameters are enough. +struct ImGuiSizeCallbackData +{ + void* UserData; // Read-only. What user passed to SetNextWindowSizeConstraints() + ImVec2 Pos; // Read-only. Window position, for reference. + ImVec2 CurrentSize; // Read-only. Current window size. + ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing. +}; + +// Data payload for Drag and Drop operations +struct ImGuiPayload +{ + // Members + void* Data; // Data (copied and owned by dear imgui) + int DataSize; // Data size + + // [Internal] + ImGuiID SourceId; // Source item id + ImGuiID SourceParentId; // Source parent id (if available) + int DataFrameCount; // Data timestamp + char DataType[32+1]; // Data type tag (short user-supplied string, 32 characters max) + bool Preview; // Set when AcceptDragDropPayload() was called and mouse has been hovering the target item (nb: handle overlapping drag targets) + bool Delivery; // Set when AcceptDragDropPayload() was called and mouse button is released over the target item. + + ImGuiPayload() { Clear(); } + void Clear() { SourceId = SourceParentId = 0; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Preview = Delivery = false; } + bool IsDataType(const char* type) const { return DataFrameCount != -1 && strcmp(type, DataType) == 0; } + bool IsPreview() const { return Preview; } + bool IsDelivery() const { return Delivery; } +}; + +// Helpers macros to generate 32-bits encoded colors +#ifdef IMGUI_USE_BGRA_PACKED_COLOR +#define IM_COL32_R_SHIFT 16 +#define IM_COL32_G_SHIFT 8 +#define IM_COL32_B_SHIFT 0 +#define IM_COL32_A_SHIFT 24 +#define IM_COL32_A_MASK 0xFF000000 +#else +#define IM_COL32_R_SHIFT 0 +#define IM_COL32_G_SHIFT 8 +#define IM_COL32_B_SHIFT 16 +#define IM_COL32_A_SHIFT 24 +#define IM_COL32_A_MASK 0xFF000000 +#endif +#define IM_COL32(R,G,B,A) (((ImU32)(A)<>IM_COL32_R_SHIFT)&0xFF) * sc; Value.y = (float)((rgba>>IM_COL32_G_SHIFT)&0xFF) * sc; Value.z = (float)((rgba>>IM_COL32_B_SHIFT)&0xFF) * sc; Value.w = (float)((rgba>>IM_COL32_A_SHIFT)&0xFF) * sc; } + ImColor(float r, float g, float b, float a = 1.0f) { Value.x = r; Value.y = g; Value.z = b; Value.w = a; } + ImColor(const ImVec4& col) { Value = col; } + inline operator ImU32() const { return ImGui::ColorConvertFloat4ToU32(Value); } + inline operator ImVec4() const { return Value; } + + // FIXME-OBSOLETE: May need to obsolete/cleanup those helpers. + inline void SetHSV(float h, float s, float v, float a = 1.0f){ ImGui::ColorConvertHSVtoRGB(h, s, v, Value.x, Value.y, Value.z); Value.w = a; } + static ImColor HSV(float h, float s, float v, float a = 1.0f) { float r,g,b; ImGui::ColorConvertHSVtoRGB(h, s, v, r, g, b); return ImColor(r,g,b,a); } +}; + +// Helper: Manually clip large list of items. +// If you are submitting lots of evenly spaced items and you have a random access to the list, you can perform coarse clipping based on visibility to save yourself from processing those items at all. +// The clipper calculates the range of visible items and advance the cursor to compensate for the non-visible items we have skipped. +// ImGui already clip items based on their bounds but it needs to measure text size to do so. Coarse clipping before submission makes this cost and your own data fetching/submission cost null. +// Usage: +// ImGuiListClipper clipper(1000); // we have 1000 elements, evenly spaced. +// while (clipper.Step()) +// for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) +// ImGui::Text("line number %d", i); +// - Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height (step skipped if we passed a known height as second arg to constructor). +// - Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element. +// - (Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user call Step(). Does nothing and switch to Step 3.) +// - Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop. +struct ImGuiListClipper +{ + float StartPosY; + float ItemsHeight; + int ItemsCount, StepNo, DisplayStart, DisplayEnd; + + // items_count: Use -1 to ignore (you can call Begin later). Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step). + // items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing(). + // If you don't specify an items_height, you NEED to call Step(). If you specify items_height you may call the old Begin()/End() api directly, but prefer calling Step(). + ImGuiListClipper(int items_count = -1, float items_height = -1.0f) { Begin(items_count, items_height); } // NB: Begin() initialize every fields (as we allow user to call Begin/End multiple times on a same instance if they want). + ~ImGuiListClipper() { IM_ASSERT(ItemsCount == -1); } // Assert if user forgot to call End() or Step() until false. + + IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items. + IMGUI_API void Begin(int items_count, float items_height = -1.0f); // Automatically called by constructor if you passed 'items_count' or by Step() in Step 1. + IMGUI_API void End(); // Automatically called on the last call of Step() that returns false. +}; + +//----------------------------------------------------------------------------- +// Draw List +// Hold a series of drawing commands. The user provides a renderer for ImDrawData which essentially contains an array of ImDrawList. +//----------------------------------------------------------------------------- + +// Draw callbacks for advanced uses. +// NB- You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering (you can poke into the draw list for that) +// Draw callback may be useful for example, A) Change your GPU render state, B) render a complex 3D scene inside a UI element (without an intermediate texture/render target), etc. +// The expected behavior from your rendering function is 'if (cmd.UserCallback != NULL) cmd.UserCallback(parent_list, cmd); else RenderTriangles()' +typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd); + +// Typically, 1 command = 1 GPU draw call (unless command is a callback) +struct ImDrawCmd +{ + unsigned int ElemCount; // Number of indices (multiple of 3) to be rendered as triangles. Vertices are stored in the callee ImDrawList's vtx_buffer[] array, indices in idx_buffer[]. + ImVec4 ClipRect; // Clipping rectangle (x1, y1, x2, y2). Subtract ImDrawData->DisplayPos to get clipping rectangle in "viewport" coordinates + ImTextureID TextureId; // User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() functions. Ignore if never using images or multiple fonts atlas. + ImDrawCallback UserCallback; // If != NULL, call the function instead of rendering the vertices. clip_rect and texture_id will be set normally. + void* UserCallbackData; // The draw callback code can access this. + + ImDrawCmd() { ElemCount = 0; ClipRect.x = ClipRect.y = ClipRect.z = ClipRect.w = 0.0f; TextureId = NULL; UserCallback = NULL; UserCallbackData = NULL; } +}; + +// Vertex index (override with '#define ImDrawIdx unsigned int' inside in imconfig.h) +#ifndef ImDrawIdx +typedef unsigned short ImDrawIdx; +#endif + +// Vertex layout +#ifndef IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT +struct ImDrawVert +{ + ImVec2 pos; + ImVec2 uv; + ImU32 col; +}; +#else +// You can override the vertex format layout by defining IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT in imconfig.h +// The code expect ImVec2 pos (8 bytes), ImVec2 uv (8 bytes), ImU32 col (4 bytes), but you can re-order them or add other fields as needed to simplify integration in your engine. +// The type has to be described within the macro (you can either declare the struct or use a typedef) +// NOTE: IMGUI DOESN'T CLEAR THE STRUCTURE AND DOESN'T CALL A CONSTRUCTOR SO ANY CUSTOM FIELD WILL BE UNINITIALIZED. IF YOU ADD EXTRA FIELDS (SUCH AS A 'Z' COORDINATES) YOU WILL NEED TO CLEAR THEM DURING RENDER OR TO IGNORE THEM. +IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT; +#endif + +// Draw channels are used by the Columns API to "split" the render list into different channels while building, so items of each column can be batched together. +// You can also use them to simulate drawing layers and submit primitives in a different order than how they will be rendered. +struct ImDrawChannel +{ + ImVector CmdBuffer; + ImVector IdxBuffer; +}; + +enum ImDrawCornerFlags_ +{ + ImDrawCornerFlags_TopLeft = 1 << 0, // 0x1 + ImDrawCornerFlags_TopRight = 1 << 1, // 0x2 + ImDrawCornerFlags_BotLeft = 1 << 2, // 0x4 + ImDrawCornerFlags_BotRight = 1 << 3, // 0x8 + ImDrawCornerFlags_Top = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_TopRight, // 0x3 + ImDrawCornerFlags_Bot = ImDrawCornerFlags_BotLeft | ImDrawCornerFlags_BotRight, // 0xC + ImDrawCornerFlags_Left = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotLeft, // 0x5 + ImDrawCornerFlags_Right = ImDrawCornerFlags_TopRight | ImDrawCornerFlags_BotRight, // 0xA + ImDrawCornerFlags_All = 0xF // In your function calls you may use ~0 (= all bits sets) instead of ImDrawCornerFlags_All, as a convenience +}; + +enum ImDrawListFlags_ +{ + ImDrawListFlags_AntiAliasedLines = 1 << 0, + ImDrawListFlags_AntiAliasedFill = 1 << 1 +}; + +// Draw command list +// This is the low-level list of polygons that ImGui functions are filling. At the end of the frame, all command lists are passed to your ImGuiIO::RenderDrawListFn function for rendering. +// Each ImGui window contains its own ImDrawList. You can use ImGui::GetWindowDrawList() to access the current window draw list and draw custom primitives. +// You can interleave normal ImGui:: calls and adding primitives to the current draw list. +// All positions are generally in pixel coordinates (top-left at (0,0), bottom-right at io.DisplaySize), but you are totally free to apply whatever transformation matrix to want to the data (if you apply such transformation you'll want to apply it to ClipRect as well) +// Important: Primitives are always added to the list and not culled (culling is done at higher-level by ImGui:: functions), if you use this API a lot consider coarse culling your drawn objects. +struct ImDrawList +{ + // This is what you have to render + ImVector CmdBuffer; // Draw commands. Typically 1 command = 1 GPU draw call, unless the command is a callback. + ImVector IdxBuffer; // Index buffer. Each command consume ImDrawCmd::ElemCount of those + ImVector VtxBuffer; // Vertex buffer. + ImDrawListFlags Flags; // Flags, you may poke into these to adjust anti-aliasing settings per-primitive. + + // [Internal, used while building lists] + const ImDrawListSharedData* _Data; // Pointer to shared draw data (you can use ImGui::GetDrawListSharedData() to get the one from current ImGui context) + const char* _OwnerName; // Pointer to owner window's name for debugging + unsigned int _VtxCurrentIdx; // [Internal] == VtxBuffer.Size + ImDrawVert* _VtxWritePtr; // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> operators too much) + ImDrawIdx* _IdxWritePtr; // [Internal] point within IdxBuffer.Data after each add command (to avoid using the ImVector<> operators too much) + ImVector _ClipRectStack; // [Internal] + ImVector _TextureIdStack; // [Internal] + ImVector _Path; // [Internal] current path building + int _ChannelsCurrent; // [Internal] current channel number (0) + int _ChannelsCount; // [Internal] number of active channels (1+) + ImVector _Channels; // [Internal] draw channels for columns API (not resized down so _ChannelsCount may be smaller than _Channels.Size) + + // If you want to create ImDrawList instances, pass them ImGui::GetDrawListSharedData() or create and use your own ImDrawListSharedData (so you can use ImDrawList without ImGui) + ImDrawList(const ImDrawListSharedData* shared_data) { _Data = shared_data; _OwnerName = NULL; Clear(); } + ~ImDrawList() { ClearFreeMemory(); } + IMGUI_API void PushClipRect(ImVec2 clip_rect_min, ImVec2 clip_rect_max, bool intersect_with_current_clip_rect = false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) + IMGUI_API void PushClipRectFullScreen(); + IMGUI_API void PopClipRect(); + IMGUI_API void PushTextureID(ImTextureID texture_id); + IMGUI_API void PopTextureID(); + inline ImVec2 GetClipRectMin() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.x, cr.y); } + inline ImVec2 GetClipRectMax() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.z, cr.w); } + + // Primitives + IMGUI_API void AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness = 1.0f); + IMGUI_API void AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners_flags = ImDrawCornerFlags_All, float thickness = 1.0f); // a: upper-left, b: lower-right, rounding_corners_flags: 4-bits corresponding to which corner to round + IMGUI_API void AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners_flags = ImDrawCornerFlags_All); // a: upper-left, b: lower-right + IMGUI_API void AddRectFilledMultiColor(const ImVec2& a, const ImVec2& b, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left); + IMGUI_API void AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col, float thickness = 1.0f); + IMGUI_API void AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col); + IMGUI_API void AddTriangle(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col, float thickness = 1.0f); + IMGUI_API void AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col); + IMGUI_API void AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments = 12, float thickness = 1.0f); + IMGUI_API void AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments = 12); + IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL); + IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); + IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,1), ImU32 col = 0xFFFFFFFF); + IMGUI_API void AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,0), const ImVec2& uv_c = ImVec2(1,1), const ImVec2& uv_d = ImVec2(0,1), ImU32 col = 0xFFFFFFFF); + IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col, float rounding, int rounding_corners = ImDrawCornerFlags_All); + IMGUI_API void AddPolyline(const ImVec2* points, const int num_points, ImU32 col, bool closed, float thickness); + IMGUI_API void AddConvexPolyFilled(const ImVec2* points, const int num_points, ImU32 col); // Note: Anti-aliased filling requires points to be in clockwise order. + IMGUI_API void AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments = 0); + + // Stateful path API, add points then finish with PathFillConvex() or PathStroke() + inline void PathClear() { _Path.resize(0); } + inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } + inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path[_Path.Size-1], &pos, 8) != 0) _Path.push_back(pos); } + inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col); PathClear(); } // Note: Anti-aliased filling requires points to be in clockwise order. + inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness); PathClear(); } + IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10); + IMGUI_API void PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle + IMGUI_API void PathBezierCurveTo(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, int num_segments = 0); + IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, int rounding_corners_flags = ImDrawCornerFlags_All); + + // Channels + // - Use to simulate layers. By switching channels to can render out-of-order (e.g. submit foreground primitives before background primitives) + // - Use to minimize draw calls (e.g. if going back-and-forth between multiple non-overlapping clipping rectangles, prefer to append into separate channels then merge at the end) + IMGUI_API void ChannelsSplit(int channels_count); + IMGUI_API void ChannelsMerge(); + IMGUI_API void ChannelsSetCurrent(int channel_index); + + // Advanced + IMGUI_API void AddCallback(ImDrawCallback callback, void* callback_data); // Your rendering function must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles. + IMGUI_API void AddDrawCmd(); // This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending). Otherwise primitives are merged into the same draw-call as much as possible + IMGUI_API ImDrawList* CloneOutput() const; // Create a clone of the CmdBuffer/IdxBuffer/VtxBuffer. + + // Internal helpers + // NB: all primitives needs to be reserved via PrimReserve() beforehand! + IMGUI_API void Clear(); + IMGUI_API void ClearFreeMemory(); + IMGUI_API void PrimReserve(int idx_count, int vtx_count); + IMGUI_API void PrimRect(const ImVec2& a, const ImVec2& b, ImU32 col); // Axis aligned rectangle (composed of two triangles) + IMGUI_API void PrimRectUV(const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col); + IMGUI_API void PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col); + inline void PrimWriteVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col){ _VtxWritePtr->pos = pos; _VtxWritePtr->uv = uv; _VtxWritePtr->col = col; _VtxWritePtr++; _VtxCurrentIdx++; } + inline void PrimWriteIdx(ImDrawIdx idx) { *_IdxWritePtr = idx; _IdxWritePtr++; } + inline void PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); PrimWriteVtx(pos, uv, col); } + IMGUI_API void UpdateClipRect(); + IMGUI_API void UpdateTextureID(); +}; + +// All draw data to render an ImGui frame +// (NB: the style and the naming convention here is a little inconsistent but we preserve them for backward compatibility purpose) +struct ImDrawData +{ + bool Valid; // Only valid after Render() is called and before the next NewFrame() is called. + ImDrawList** CmdLists; // Array of ImDrawList* to render. The ImDrawList are owned by ImGuiContext and only pointed to from here. + int CmdListsCount; // Number of ImDrawList* to render + int TotalIdxCount; // For convenience, sum of all ImDrawList's IdxBuffer.Size + int TotalVtxCount; // For convenience, sum of all ImDrawList's VtxBuffer.Size + ImVec2 DisplayPos; // Upper-left position of the viewport to render (== upper-left of the orthogonal projection matrix to use) + ImVec2 DisplaySize; // Size of the viewport to render (== io.DisplaySize for the main viewport) (DisplayPos + DisplaySize == lower-right of the orthogonal projection matrix to use) + + // Functions + ImDrawData() { Valid = false; Clear(); } + ~ImDrawData() { Clear(); } + void Clear() { Valid = false; CmdLists = NULL; CmdListsCount = TotalVtxCount = TotalIdxCount = 0; DisplayPos = DisplaySize = ImVec2(0.f, 0.f); } // The ImDrawList are owned by ImGuiContext! + IMGUI_API void DeIndexAllBuffers(); // Helper to convert all buffers from indexed to non-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering! + IMGUI_API void ScaleClipRects(const ImVec2& sc); // Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution. +}; + +struct ImFontConfig +{ + void* FontData; // // TTF/OTF data + int FontDataSize; // // TTF/OTF data size + bool FontDataOwnedByAtlas; // true // TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself). + int FontNo; // 0 // Index of font within TTF/OTF file + float SizePixels; // // Size in pixels for rasterizer (more or less maps to the resulting font height). + int OversampleH; // 3 // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel positions on the Y axis. + int OversampleV; // 1 // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel positions on the Y axis. + bool PixelSnapH; // false // Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1. + ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs. Only X axis is supported for now. + ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input. + const ImWchar* GlyphRanges; // NULL // Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. + float GlyphMinAdvanceX; // 0 // Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font + float GlyphMaxAdvanceX; // FLT_MAX // Maximum AdvanceX for glyphs + bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights. + unsigned int RasterizerFlags; // 0x00 // Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one. + float RasterizerMultiply; // 1.0f // Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. + + // [Internal] + char Name[40]; // Name (strictly to ease debugging) + ImFont* DstFont; + + IMGUI_API ImFontConfig(); +}; + +struct ImFontGlyph +{ + ImWchar Codepoint; // 0x0000..0xFFFF + float AdvanceX; // Distance to next character (= data from font + ImFontConfig::GlyphExtraSpacing.x baked in) + float X0, Y0, X1, Y1; // Glyph corners + float U0, V0, U1, V1; // Texture coordinates +}; + +enum ImFontAtlasFlags_ +{ + ImFontAtlasFlags_NoPowerOfTwoHeight = 1 << 0, // Don't round the height to next power of two + ImFontAtlasFlags_NoMouseCursors = 1 << 1 // Don't build software mouse cursors into the atlas +}; + +// Load and rasterize multiple TTF/OTF fonts into a same texture. +// Sharing a texture for multiple fonts allows us to reduce the number of draw calls during rendering. +// We also add custom graphic data into the texture that serves for ImGui. +// 1. (Optional) Call AddFont*** functions. If you don't call any, the default font will be loaded for you. +// 2. Call GetTexDataAsAlpha8() or GetTexDataAsRGBA32() to build and retrieve pixels data. +// 3. Upload the pixels data into a texture within your graphics system. +// 4. Call SetTexID(my_tex_id); and pass the pointer/identifier to your texture. This value will be passed back to you during rendering to identify the texture. +// IMPORTANT: If you pass a 'glyph_ranges' array to AddFont*** functions, you need to make sure that your array persist up until the ImFont is build (when calling GetTexData*** or Build()). We only copy the pointer, not the data. +struct ImFontAtlas +{ + IMGUI_API ImFontAtlas(); + IMGUI_API ~ImFontAtlas(); + IMGUI_API ImFont* AddFont(const ImFontConfig* font_cfg); + IMGUI_API ImFont* AddFontDefault(const ImFontConfig* font_cfg = NULL); + IMGUI_API ImFont* AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); + IMGUI_API ImFont* AddFontFromMemoryTTF(void* font_data, int font_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after Build(). Set font_cfg->FontDataOwnedByAtlas to false to keep ownership. + IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp. + IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter. + IMGUI_API void ClearInputData(); // Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts. + IMGUI_API void ClearTexData(); // Clear output texture data (CPU side). Saves RAM once the texture has been copied to graphics memory. + IMGUI_API void ClearFonts(); // Clear output font data (glyphs storage, UV coordinates). + IMGUI_API void Clear(); // Clear all input and output. + + // Build atlas, retrieve pixel data. + // User is in charge of copying the pixels into graphics memory (e.g. create a texture with your engine). Then store your texture handle with SetTexID(). + // RGBA32 format is provided for convenience and compatibility, but note that unless you use CustomRect to draw color data, the RGB pixels emitted from Fonts will all be white (~75% of waste). + // Pitch = Width * BytesPerPixels + IMGUI_API bool Build(); // Build pixels data. This is called automatically for you by the GetTexData*** functions. + IMGUI_API bool IsBuilt() { return Fonts.Size > 0 && (TexPixelsAlpha8 != NULL || TexPixelsRGBA32 != NULL); } + IMGUI_API void GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 1 byte per-pixel + IMGUI_API void GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 4 bytes-per-pixel + void SetTexID(ImTextureID id) { TexID = id; } + + //------------------------------------------- + // Glyph Ranges + //------------------------------------------- + + // Helpers to retrieve list of common Unicode ranges (2 value per range, values are inclusive, zero-terminated list) + // NB: Make sure that your string are UTF-8 and NOT in your local code page. In C++11, you can create UTF-8 string literal using the u8"Hello world" syntax. See FAQ for details. + // NB: Consider using GlyphRangesBuilder to build glyph ranges from textual data. + IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin + IMGUI_API const ImWchar* GetGlyphRangesKorean(); // Default + Korean characters + IMGUI_API const ImWchar* GetGlyphRangesJapanese(); // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs + IMGUI_API const ImWchar* GetGlyphRangesChineseFull(); // Default + Half-Width + Japanese Hiragana/Katakana + full set of about 21000 CJK Unified Ideographs + IMGUI_API const ImWchar* GetGlyphRangesChineseSimplifiedCommon();// Default + Half-Width + Japanese Hiragana/Katakana + set of 2500 CJK Unified Ideographs for common simplified Chinese + IMGUI_API const ImWchar* GetGlyphRangesCyrillic(); // Default + about 400 Cyrillic characters + IMGUI_API const ImWchar* GetGlyphRangesThai(); // Default + Thai characters + + // Helpers to build glyph ranges from text data. Feed your application strings/characters to it then call BuildRanges(). + struct GlyphRangesBuilder + { + ImVector UsedChars; // Store 1-bit per Unicode code point (0=unused, 1=used) + GlyphRangesBuilder() { UsedChars.resize(0x10000 / 8); memset(UsedChars.Data, 0, 0x10000 / 8); } + bool GetBit(int n) const { return (UsedChars[n >> 3] & (1 << (n & 7))) != 0; } + void SetBit(int n) { UsedChars[n >> 3] |= 1 << (n & 7); } // Set bit 'c' in the array + void AddChar(ImWchar c) { SetBit(c); } // Add character + IMGUI_API void AddText(const char* text, const char* text_end = NULL); // Add string (each character of the UTF-8 string are added) + IMGUI_API void AddRanges(const ImWchar* ranges); // Add ranges, e.g. builder.AddRanges(ImFontAtlas::GetGlyphRangesDefault()) to force add all of ASCII/Latin+Ext + IMGUI_API void BuildRanges(ImVector* out_ranges); // Output new ranges + }; + + //------------------------------------------- + // Custom Rectangles/Glyphs API + //------------------------------------------- + + // You can request arbitrary rectangles to be packed into the atlas, for your own purposes. After calling Build(), you can query the rectangle position and render your pixels. + // You can also request your rectangles to be mapped as font glyph (given a font + Unicode point), so you can render e.g. custom colorful icons and use them as regular glyphs. + struct CustomRect + { + unsigned int ID; // Input // User ID. Use <0x10000 to map into a font glyph, >=0x10000 for other/internal/custom texture data. + unsigned short Width, Height; // Input // Desired rectangle dimension + unsigned short X, Y; // Output // Packed position in Atlas + float GlyphAdvanceX; // Input // For custom font glyphs only (ID<0x10000): glyph xadvance + ImVec2 GlyphOffset; // Input // For custom font glyphs only (ID<0x10000): glyph display offset + ImFont* Font; // Input // For custom font glyphs only (ID<0x10000): target font + CustomRect() { ID = 0xFFFFFFFF; Width = Height = 0; X = Y = 0xFFFF; GlyphAdvanceX = 0.0f; GlyphOffset = ImVec2(0,0); Font = NULL; } + bool IsPacked() const { return X != 0xFFFF; } + }; + + IMGUI_API int AddCustomRectRegular(unsigned int id, int width, int height); // Id needs to be >= 0x10000. Id >= 0x80000000 are reserved for ImGui and ImDrawList + IMGUI_API int AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset = ImVec2(0,0)); // Id needs to be < 0x10000 to register a rectangle to map into a specific font. + const CustomRect* GetCustomRectByIndex(int index) const { if (index < 0) return NULL; return &CustomRects[index]; } + + // [Internal] + IMGUI_API void CalcCustomRectUV(const CustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max); + IMGUI_API bool GetMouseCursorTexData(ImGuiMouseCursor cursor, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]); + + //------------------------------------------- + // Members + //------------------------------------------- + + bool Locked; // Marked as Locked by ImGui::NewFrame() so attempt to modify the atlas will assert. + ImFontAtlasFlags Flags; // Build flags (see ImFontAtlasFlags_) + ImTextureID TexID; // User data to refer to the texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure. + int TexDesiredWidth; // Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height. + int TexGlyphPadding; // Padding between glyphs within texture in pixels. Defaults to 1. + + // [Internal] + // NB: Access texture data via GetTexData*() calls! Which will setup a default font for you. + unsigned char* TexPixelsAlpha8; // 1 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight + unsigned int* TexPixelsRGBA32; // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4 + int TexWidth; // Texture width calculated during Build(). + int TexHeight; // Texture height calculated during Build(). + ImVec2 TexUvScale; // = (1.0f/TexWidth, 1.0f/TexHeight) + ImVec2 TexUvWhitePixel; // Texture coordinates to a white pixel + ImVector Fonts; // Hold all the fonts returned by AddFont*. Fonts[0] is the default font upon calling ImGui::NewFrame(), use ImGui::PushFont()/PopFont() to change the current font. + ImVector CustomRects; // Rectangles for packing custom texture data into the atlas. + ImVector ConfigData; // Internal data + int CustomRectIds[1]; // Identifiers of custom texture rectangle used by ImFontAtlas/ImDrawList +}; + +// Font runtime data and rendering +// ImFontAtlas automatically loads a default embedded font for you when you call GetTexDataAsAlpha8() or GetTexDataAsRGBA32(). +struct ImFont +{ + // Members: Hot ~62/78 bytes + float FontSize; // // Height of characters, set during loading (don't change after loading) + float Scale; // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetFontScale() + ImVec2 DisplayOffset; // = (0.f,0.f) // Offset font rendering by xx pixels + ImVector Glyphs; // // All glyphs. + ImVector IndexAdvanceX; // // Sparse. Glyphs->AdvanceX in a directly indexable way (more cache-friendly, for CalcTextSize functions which are often bottleneck in large UI). + ImVector IndexLookup; // // Sparse. Index glyphs by Unicode code-point. + const ImFontGlyph* FallbackGlyph; // == FindGlyph(FontFallbackChar) + float FallbackAdvanceX; // == FallbackGlyph->AdvanceX + ImWchar FallbackChar; // = '?' // Replacement glyph if one isn't found. Only set via SetFallbackChar() + + // Members: Cold ~18/26 bytes + short ConfigDataCount; // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont. + ImFontConfig* ConfigData; // // Pointer within ContainerAtlas->ConfigData + ImFontAtlas* ContainerAtlas; // // What we has been loaded into + float Ascent, Descent; // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] + bool DirtyLookupTables; + int MetricsTotalSurface;// // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) + + // Methods + IMGUI_API ImFont(); + IMGUI_API ~ImFont(); + IMGUI_API void ClearOutputData(); + IMGUI_API void BuildLookupTable(); + IMGUI_API const ImFontGlyph*FindGlyph(ImWchar c) const; + IMGUI_API const ImFontGlyph*FindGlyphNoFallback(ImWchar c) const; + IMGUI_API void SetFallbackChar(ImWchar c); + float GetCharAdvance(ImWchar c) const { return ((int)c < IndexAdvanceX.Size) ? IndexAdvanceX[(int)c] : FallbackAdvanceX; } + bool IsLoaded() const { return ContainerAtlas != NULL; } + const char* GetDebugName() const { return ConfigData ? ConfigData->Name : ""; } + + // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable. + // 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable. + IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end = NULL, const char** remaining = NULL) const; // utf8 + IMGUI_API const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const; + IMGUI_API void RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, unsigned short c) const; + IMGUI_API void RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, bool cpu_fine_clip = false) const; + + // [Internal] + IMGUI_API void GrowIndex(int new_size); + IMGUI_API void AddGlyph(ImWchar c, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x); + IMGUI_API void AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built. + +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + typedef ImFontGlyph Glyph; // OBSOLETE 1.52+ +#endif +}; + +#if defined(__clang__) +#pragma clang diagnostic pop +#elif defined(__GNUC__) && __GNUC__ >= 8 +#pragma GCC diagnostic pop +#endif + +// Include imgui_user.h at the end of imgui.h (convenient for user to only explicitly include vanilla imgui.h) +#ifdef IMGUI_INCLUDE_IMGUI_USER_H +#include "imgui_user.h" +#endif diff --git a/BaikalStandalone/ImGUI/imgui_demo.cpp b/BaikalStandalone/ImGUI/imgui_demo.cpp new file mode 100644 index 00000000..ff262107 --- /dev/null +++ b/BaikalStandalone/ImGUI/imgui_demo.cpp @@ -0,0 +1,3503 @@ +// dear imgui, v1.63 WIP +// (demo code) + +// Message to the person tempted to delete this file when integrating ImGui into their code base: +// Don't do it! Do NOT remove this file from your project! It is useful reference code that you and other users will want to refer to. +// Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow(). +// During development, you can call ImGui::ShowDemoWindow() in your code to learn about various features of ImGui. Have it wired in a debug menu! +// Removing this file from your project is hindering access to documentation for everyone in your team, likely leading you to poorer usage of the library. +// Note that you can #define IMGUI_DISABLE_DEMO_WINDOWS in imconfig.h for the same effect. +// If you want to link core ImGui in your final builds but not those demo windows, #define IMGUI_DISABLE_DEMO_WINDOWS in imconfig.h and those functions will be empty. +// In other situation, when you have ImGui available you probably want this to be available for reference and execution. +// Thank you, +// -Your beloved friend, imgui_demo.cpp (that you won't delete) + +// Message to beginner C/C++ programmers about the meaning of the 'static' keyword: in this demo code, we frequently we use 'static' variables inside functions. +// A static variable persist across calls, so it is essentially like a global variable but declared inside the scope of the function. +// We do this as a way to gather code and data in the same place, just to make the demo code faster to read, faster to write, and use less code. +// It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be reentrant or used in threads. +// This might be a pattern you occasionally want to use in your code, but most of the real data you would be editing is likely to be stored outside your functions. + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "imgui.h" +#include // toupper, isprint +#include // INT_MIN, INT_MAX +#include // sqrtf, powf, cosf, sinf, floorf, ceilf +#include // vsnprintf, sscanf, printf +#include // NULL, malloc, free, atoi +#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier +#include // intptr_t +#else +#include // intptr_t +#endif + +#ifdef _MSC_VER +#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen +#define snprintf _snprintf +#define vsnprintf _vsnprintf +#endif +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse. +#pragma clang diagnostic ignored "-Wdeprecated-declarations" // warning : 'xx' is deprecated: The POSIX name for this item.. // for strdup used in demo code (so user can copy & paste the code) +#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' +#pragma clang diagnostic ignored "-Wformat-security" // warning : warning: format string is not a string literal +#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals. +#if __has_warning("-Wreserved-id-macro") +#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier // +#endif +#elif defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size +#pragma GCC diagnostic ignored "-Wformat-security" // warning : format string is not a string literal (potentially insecure) +#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function +#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value +#if (__GNUC__ >= 6) +#pragma GCC diagnostic ignored "-Wmisleading-indentation" // warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on GitHub. +#endif +#endif + +// Play it nice with Windows users. Notepad in 2017 still doesn't display text data with Unix-style \n. +#ifdef _WIN32 +#define IM_NEWLINE "\r\n" +#else +#define IM_NEWLINE "\n" +#endif + +#define IM_MAX(_A,_B) (((_A) >= (_B)) ? (_A) : (_B)) + +//----------------------------------------------------------------------------- +// DEMO CODE +//----------------------------------------------------------------------------- + +#if !defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS) && defined(IMGUI_DISABLE_TEST_WINDOWS) && !defined(IMGUI_DISABLE_DEMO_WINDOWS) // Obsolete name since 1.53, TEST->DEMO +#define IMGUI_DISABLE_DEMO_WINDOWS +#endif + +#if !defined(IMGUI_DISABLE_DEMO_WINDOWS) + +// Forward Declarations +static void ShowExampleAppMainMenuBar(); +static void ShowExampleAppConsole(bool* p_open); +static void ShowExampleAppLog(bool* p_open); +static void ShowExampleAppLayout(bool* p_open); +static void ShowExampleAppPropertyEditor(bool* p_open); +static void ShowExampleAppLongText(bool* p_open); +static void ShowExampleAppAutoResize(bool* p_open); +static void ShowExampleAppConstrainedResize(bool* p_open); +static void ShowExampleAppSimpleOverlay(bool* p_open); +static void ShowExampleAppWindowTitles(bool* p_open); +static void ShowExampleAppCustomRendering(bool* p_open); +static void ShowExampleMenuFile(); + +// Helper to display a little (?) mark which shows a tooltip when hovered. +static void ShowHelpMarker(const char* desc) +{ + ImGui::TextDisabled("(?)"); + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::TextUnformatted(desc); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } +} + +// Helper to display basic user controls. +void ImGui::ShowUserGuide() +{ + ImGui::BulletText("Double-click on title bar to collapse window."); + ImGui::BulletText("Click and drag on lower right corner to resize window\n(double-click to auto fit window to its contents)."); + ImGui::BulletText("Click and drag on any empty space to move window."); + ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields."); + ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text."); + if (ImGui::GetIO().FontAllowUserScaling) + ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents."); + ImGui::BulletText("Mouse Wheel to scroll."); + ImGui::BulletText("While editing text:\n"); + ImGui::Indent(); + ImGui::BulletText("Hold SHIFT or use mouse to select text."); + ImGui::BulletText("CTRL+Left/Right to word jump."); + ImGui::BulletText("CTRL+A or double-click to select all."); + ImGui::BulletText("CTRL+X,CTRL+C,CTRL+V to use clipboard."); + ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo."); + ImGui::BulletText("ESCAPE to revert."); + ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract."); + ImGui::Unindent(); +} + +// Demonstrate most Dear ImGui features (this is big function!) +// You may execute this function to experiment with the UI and understand what it does. You may then search for keywords in the code when you are interested by a specific feature. +void ImGui::ShowDemoWindow(bool* p_open) +{ + // Examples Apps (accessible from the "Examples" menu) + static bool show_app_main_menu_bar = false; + static bool show_app_console = false; + static bool show_app_log = false; + static bool show_app_layout = false; + static bool show_app_property_editor = false; + static bool show_app_long_text = false; + static bool show_app_auto_resize = false; + static bool show_app_constrained_resize = false; + static bool show_app_simple_overlay = false; + static bool show_app_window_titles = false; + static bool show_app_custom_rendering = false; + + if (show_app_main_menu_bar) ShowExampleAppMainMenuBar(); + if (show_app_console) ShowExampleAppConsole(&show_app_console); + if (show_app_log) ShowExampleAppLog(&show_app_log); + if (show_app_layout) ShowExampleAppLayout(&show_app_layout); + if (show_app_property_editor) ShowExampleAppPropertyEditor(&show_app_property_editor); + if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text); + if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize); + if (show_app_constrained_resize) ShowExampleAppConstrainedResize(&show_app_constrained_resize); + if (show_app_simple_overlay) ShowExampleAppSimpleOverlay(&show_app_simple_overlay); + if (show_app_window_titles) ShowExampleAppWindowTitles(&show_app_window_titles); + if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering); + + // Dear ImGui Apps (accessible from the "Help" menu) + static bool show_app_metrics = false; + static bool show_app_style_editor = false; + static bool show_app_about = false; + + if (show_app_metrics) { ImGui::ShowMetricsWindow(&show_app_metrics); } + if (show_app_style_editor) { ImGui::Begin("Style Editor", &show_app_style_editor); ImGui::ShowStyleEditor(); ImGui::End(); } + if (show_app_about) + { + ImGui::Begin("About Dear ImGui", &show_app_about, ImGuiWindowFlags_AlwaysAutoResize); + ImGui::Text("Dear ImGui, %s", ImGui::GetVersion()); + ImGui::Separator(); + ImGui::Text("By Omar Cornut and all dear imgui contributors."); + ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information."); + ImGui::End(); + } + + // Demonstrate the various window flags. Typically you would just use the default! + static bool no_titlebar = false; + static bool no_scrollbar = false; + static bool no_menu = false; + static bool no_move = false; + static bool no_resize = false; + static bool no_collapse = false; + static bool no_close = false; + static bool no_nav = false; + + ImGuiWindowFlags window_flags = 0; + if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar; + if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar; + if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar; + if (no_move) window_flags |= ImGuiWindowFlags_NoMove; + if (no_resize) window_flags |= ImGuiWindowFlags_NoResize; + if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse; + if (no_nav) window_flags |= ImGuiWindowFlags_NoNav; + if (no_close) p_open = NULL; // Don't pass our bool* to Begin + + // We specify a default position/size in case there's no data in the .ini file. Typically this isn't required! We only do it to make the Demo applications a little more welcoming. + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver); + + // Main body of the Demo window starts here. + if (!ImGui::Begin("ImGui Demo", p_open, window_flags)) + { + // Early out if the window is collapsed, as an optimization. + ImGui::End(); + return; + } + ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION); + + // Most "big" widgets share a common width settings by default. + //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f); // Use 2/3 of the space for widgets and 1/3 for labels (default) + ImGui::PushItemWidth(ImGui::GetFontSize() * -12); // Use fixed width for labels (by passing a negative value), the rest goes to widgets. We choose a width proportional to our font size. + + // Menu + if (ImGui::BeginMenuBar()) + { + if (ImGui::BeginMenu("Menu")) + { + ShowExampleMenuFile(); + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Examples")) + { + ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar); + ImGui::MenuItem("Console", NULL, &show_app_console); + ImGui::MenuItem("Log", NULL, &show_app_log); + ImGui::MenuItem("Simple layout", NULL, &show_app_layout); + ImGui::MenuItem("Property editor", NULL, &show_app_property_editor); + ImGui::MenuItem("Long text display", NULL, &show_app_long_text); + ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize); + ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize); + ImGui::MenuItem("Simple overlay", NULL, &show_app_simple_overlay); + ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles); + ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering); + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Help")) + { + ImGui::MenuItem("Metrics", NULL, &show_app_metrics); + ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor); + ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about); + ImGui::EndMenu(); + } + ImGui::EndMenuBar(); + } + + ImGui::Spacing(); + if (ImGui::CollapsingHeader("Help")) + { + ImGui::TextWrapped("This window is being created by the ShowDemoWindow() function. Please refer to the code in imgui_demo.cpp for reference.\n\n"); + ImGui::Text("USER GUIDE:"); + ImGui::ShowUserGuide(); + } + + if (ImGui::CollapsingHeader("Window options")) + { + ImGui::Checkbox("No titlebar", &no_titlebar); ImGui::SameLine(150); + ImGui::Checkbox("No scrollbar", &no_scrollbar); ImGui::SameLine(300); + ImGui::Checkbox("No menu", &no_menu); + ImGui::Checkbox("No move", &no_move); ImGui::SameLine(150); + ImGui::Checkbox("No resize", &no_resize); ImGui::SameLine(300); + ImGui::Checkbox("No collapse", &no_collapse); + ImGui::Checkbox("No close", &no_close); ImGui::SameLine(150); + ImGui::Checkbox("No nav", &no_nav); + + if (ImGui::TreeNode("Style")) + { + ImGui::ShowStyleEditor(); + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Capture/Logging")) + { + ImGui::TextWrapped("The logging API redirects all text output so you can easily capture the content of a window or a block. Tree nodes can be automatically expanded. You can also call ImGui::LogText() to output directly to the log without a visual output."); + ImGui::LogButtons(); + ImGui::TreePop(); + } + } + + if (ImGui::CollapsingHeader("Widgets")) + { + if (ImGui::TreeNode("Basic")) + { + static int clicked = 0; + if (ImGui::Button("Button")) + clicked++; + if (clicked & 1) + { + ImGui::SameLine(); + ImGui::Text("Thanks for clicking me!"); + } + + static bool check = true; + ImGui::Checkbox("checkbox", &check); + + static int e = 0; + ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine(); + ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine(); + ImGui::RadioButton("radio c", &e, 2); + + // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style. + for (int i = 0; i < 7; i++) + { + if (i > 0) ImGui::SameLine(); + ImGui::PushID(i); + ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.6f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.7f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i/7.0f, 0.8f, 0.8f)); + ImGui::Button("Click"); + ImGui::PopStyleColor(3); + ImGui::PopID(); + } + + // Arrow buttons + static int counter = 0; + float spacing = ImGui::GetStyle().ItemInnerSpacing.x; + ImGui::PushButtonRepeat(true); + if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { counter--; } + ImGui::SameLine(0.0f, spacing); + if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { counter++; } + ImGui::PopButtonRepeat(); + ImGui::SameLine(); + ImGui::Text("%d", counter); + + ImGui::Text("Hover over me"); + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("I am a tooltip"); + + ImGui::SameLine(); + ImGui::Text("- or me"); + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text("I am a fancy tooltip"); + static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f }; + ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr)); + ImGui::EndTooltip(); + } + + ImGui::Separator(); + + ImGui::LabelText("label", "Value"); + + { + // Using the _simplified_ one-liner Combo() api here + // See "Combo" section for examples of how to use the more complete BeginCombo()/EndCombo() api. + const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; + static int item_current = 0; + ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items)); + ImGui::SameLine(); ShowHelpMarker("Refer to the \"Combo\" section below for an explanation of the full BeginCombo/EndCombo API, and demonstration of various flags.\n"); + } + + { + static char str0[128] = "Hello, world!"; + static int i0 = 123; + ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0)); + ImGui::SameLine(); ShowHelpMarker("Hold SHIFT or use mouse to select text.\n" "CTRL+Left/Right to word jump.\n" "CTRL+A or double-click to select all.\n" "CTRL+X,CTRL+C,CTRL+V clipboard.\n" "CTRL+Z,CTRL+Y undo/redo.\n" "ESCAPE to revert.\n"); + + ImGui::InputInt("input int", &i0); + ImGui::SameLine(); ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n"); + + static float f0 = 0.001f; + ImGui::InputFloat("input float", &f0, 0.01f, 1.0f); + + static double d0 = 999999.00000001; + ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.8f"); + + static float f1 = 1.e10f; + ImGui::InputFloat("input scientific", &f1, 0.0f, 0.0f, "%e"); + ImGui::SameLine(); ShowHelpMarker("You can input value using the scientific notation,\n e.g. \"1e+8\" becomes \"100000000\".\n"); + + static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f }; + ImGui::InputFloat3("input float3", vec4a); + } + + { + static int i1 = 50, i2 = 42; + ImGui::DragInt("drag int", &i1, 1); + ImGui::SameLine(); ShowHelpMarker("Click and drag to edit value.\nHold SHIFT/ALT for faster/slower edit.\nDouble-click or CTRL+click to input value."); + + ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%"); + + static float f1=1.00f, f2=0.0067f; + ImGui::DragFloat("drag float", &f1, 0.005f); + ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns"); + } + + { + static int i1=0; + ImGui::SliderInt("slider int", &i1, -1, 3); + ImGui::SameLine(); ShowHelpMarker("CTRL+click to input value."); + + static float f1=0.123f, f2=0.0f; + ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f"); + ImGui::SliderFloat("slider float (curve)", &f2, -10.0f, 10.0f, "%.4f", 2.0f); + static float angle = 0.0f; + ImGui::SliderAngle("slider angle", &angle); + } + + { + static float col1[3] = { 1.0f,0.0f,0.2f }; + static float col2[4] = { 0.4f,0.7f,0.0f,0.5f }; + ImGui::ColorEdit3("color 1", col1); + ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nClick and hold to use drag and drop.\nRight-click on the colored square to show options.\nCTRL+click on individual component to input value.\n"); + + ImGui::ColorEdit4("color 2", col2); + } + + { + // List box + const char* listbox_items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" }; + static int listbox_item_current = 1; + ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4); + + //static int listbox_item_current2 = 2; + //ImGui::PushItemWidth(-1); + //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4); + //ImGui::PopItemWidth(); + } + + ImGui::TreePop(); + } + + // Testing ImGuiOnceUponAFrame helper. + //static ImGuiOnceUponAFrame once; + //for (int i = 0; i < 5; i++) + // if (once) + // ImGui::Text("This will be displayed only once."); + + if (ImGui::TreeNode("Trees")) + { + if (ImGui::TreeNode("Basic trees")) + { + for (int i = 0; i < 5; i++) + if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i)) + { + ImGui::Text("blah blah"); + ImGui::SameLine(); + if (ImGui::SmallButton("button")) { }; + ImGui::TreePop(); + } + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Advanced, with Selectable nodes")) + { + ShowHelpMarker("This is a more standard looking tree with selectable nodes.\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open."); + static bool align_label_with_current_x_position = false; + ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position); + ImGui::Text("Hello!"); + if (align_label_with_current_x_position) + ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing()); + + static int selection_mask = (1 << 2); // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit. + int node_clicked = -1; // Temporary storage of what node we have clicked to process selection at the end of the loop. May be a pointer to your own node type, etc. + ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize()*3); // Increase spacing to differentiate leaves from expanded contents. + for (int i = 0; i < 6; i++) + { + // Disable the default open on single-click behavior and pass in Selected flag according to our selection state. + ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0); + if (i < 3) + { + // Node + bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i); + if (ImGui::IsItemClicked()) + node_clicked = i; + if (node_open) + { + ImGui::Text("Blah blah\nBlah Blah"); + ImGui::TreePop(); + } + } + else + { + // Leaf: The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use BulletText() or TreeAdvanceToLabelPos()+Text(). + node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet + ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i); + if (ImGui::IsItemClicked()) + node_clicked = i; + } + } + if (node_clicked != -1) + { + // Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame. + if (ImGui::GetIO().KeyCtrl) + selection_mask ^= (1 << node_clicked); // CTRL+click to toggle + else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, this commented bit preserve selection when clicking on item that is part of the selection + selection_mask = (1 << node_clicked); // Click to single-select + } + ImGui::PopStyleVar(); + if (align_label_with_current_x_position) + ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing()); + ImGui::TreePop(); + } + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Collapsing Headers")) + { + static bool closable_group = true; + ImGui::Checkbox("Enable extra group", &closable_group); + if (ImGui::CollapsingHeader("Header")) + { + ImGui::Text("IsItemHovered: %d", IsItemHovered()); + for (int i = 0; i < 5; i++) + ImGui::Text("Some content %d", i); + } + if (ImGui::CollapsingHeader("Header with a close button", &closable_group)) + { + ImGui::Text("IsItemHovered: %d", IsItemHovered()); + for (int i = 0; i < 5; i++) + ImGui::Text("More content %d", i); + } + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Bullets")) + { + ImGui::BulletText("Bullet point 1"); + ImGui::BulletText("Bullet point 2\nOn multiple lines"); + ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)"); + ImGui::Bullet(); ImGui::SmallButton("Button"); + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Text")) + { + if (ImGui::TreeNode("Colored Text")) + { + // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility. + ImGui::TextColored(ImVec4(1.0f,0.0f,1.0f,1.0f), "Pink"); + ImGui::TextColored(ImVec4(1.0f,1.0f,0.0f,1.0f), "Yellow"); + ImGui::TextDisabled("Disabled"); + ImGui::SameLine(); ShowHelpMarker("The TextDisabled color is stored in ImGuiStyle."); + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Word Wrapping")) + { + // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility. + ImGui::TextWrapped("This text should automatically wrap on the edge of the window. The current implementation for text wrapping follows simple rules suitable for English and possibly other languages."); + ImGui::Spacing(); + + static float wrap_width = 200.0f; + ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f"); + + ImGui::Text("Test paragraph 1:"); + ImVec2 pos = ImGui::GetCursorScreenPos(); + ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255,0,255,255)); + ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width); + ImGui::Text("The lazy dog is a good dog. This paragraph is made to fit within %.0f pixels. Testing a 1 character word. The quick brown fox jumps over the lazy dog.", wrap_width); + ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255)); + ImGui::PopTextWrapPos(); + + ImGui::Text("Test paragraph 2:"); + pos = ImGui::GetCursorScreenPos(); + ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255,0,255,255)); + ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width); + ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee ffffffff. gggggggg!hhhhhhhh"); + ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255)); + ImGui::PopTextWrapPos(); + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("UTF-8 Text")) + { + // UTF-8 test with Japanese characters + // (Needs a suitable font, try Noto, or Arial Unicode, or M+ fonts. Read misc/fonts/README.txt for details.) + // - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8 + // - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. Visual Studio save your file as 'UTF-8 without signature') + // - FOR THIS DEMO FILE ONLY, BECAUSE WE WANT TO SUPPORT OLD COMPILERS, WE ARE *NOT* INCLUDING RAW UTF-8 CHARACTERS IN THIS SOURCE FILE. + // Instead we are encoding a few strings with hexadecimal constants. Don't do this in your application! + // Please use u8"text in any language" in your application! + // Note that characters values are preserved even by InputText() if the font cannot be displayed, so you can safely copy & paste garbled characters into another application. + ImGui::TextWrapped("CJK text will only appears if the font was loaded with the appropriate CJK character ranges. Call io.Font->LoadFromFileTTF() manually to load extra character ranges. Read misc/fonts/README.txt for details."); + ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)"); // Normally we would use u8"blah blah" with the proper characters directly in the string. + ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)"); + static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"; + //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis + ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf)); + ImGui::TreePop(); + } + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Images")) + { + ImGuiIO& io = ImGui::GetIO(); + ImGui::TextWrapped("Below we are displaying the font texture (which is the only texture we have access to in this demo). Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. Hover the texture for a zoomed view!"); + + // Here we are grabbing the font texture because that's the only one we have access to inside the demo code. + // Remember that ImTextureID is just storage for whatever you want it to be, it is essentially a value that will be passed to the render function inside the ImDrawCmd structure. + // If you use one of the default imgui_impl_XXXX.cpp renderer, they all have comments at the top of their file to specify what they expect to be stored in ImTextureID. + // (for example, the imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer. The imgui_impl_glfw_gl3.cpp renderer expect a GLuint OpenGL texture identifier etc.) + // If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers to ImGui::Image(), and gather width/height through your own functions, etc. + // Using ShowMetricsWindow() as a "debugger" to inspect the draw data that are being passed to your render will help you debug issues if you are confused about this. + // Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage(). + ImTextureID my_tex_id = io.Fonts->TexID; + float my_tex_w = (float)io.Fonts->TexWidth; + float my_tex_h = (float)io.Fonts->TexHeight; + + ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h); + ImVec2 pos = ImGui::GetCursorScreenPos(); + ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128)); + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + float region_sz = 32.0f; + float region_x = io.MousePos.x - pos.x - region_sz * 0.5f; if (region_x < 0.0f) region_x = 0.0f; else if (region_x > my_tex_w - region_sz) region_x = my_tex_w - region_sz; + float region_y = io.MousePos.y - pos.y - region_sz * 0.5f; if (region_y < 0.0f) region_y = 0.0f; else if (region_y > my_tex_h - region_sz) region_y = my_tex_h - region_sz; + float zoom = 4.0f; + ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y); + ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz); + ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h); + ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h); + ImGui::Image(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, ImColor(255,255,255,255), ImColor(255,255,255,128)); + ImGui::EndTooltip(); + } + ImGui::TextWrapped("And now some textured buttons.."); + static int pressed_count = 0; + for (int i = 0; i < 8; i++) + { + ImGui::PushID(i); + int frame_padding = -1 + i; // -1 = uses default padding + if (ImGui::ImageButton(my_tex_id, ImVec2(32,32), ImVec2(0,0), ImVec2(32.0f/my_tex_w,32/my_tex_h), frame_padding, ImColor(0,0,0,255))) + pressed_count += 1; + ImGui::PopID(); + ImGui::SameLine(); + } + ImGui::NewLine(); + ImGui::Text("Pressed %d times.", pressed_count); + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Combo")) + { + // Expose flags as checkbox for the demo + static ImGuiComboFlags flags = 0; + ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", (unsigned int*)&flags, ImGuiComboFlags_PopupAlignLeft); + if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", (unsigned int*)&flags, ImGuiComboFlags_NoArrowButton)) + flags &= ~ImGuiComboFlags_NoPreview; // Clear the other flag, as we cannot combine both + if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", (unsigned int*)&flags, ImGuiComboFlags_NoPreview)) + flags &= ~ImGuiComboFlags_NoArrowButton; // Clear the other flag, as we cannot combine both + + // General BeginCombo() API, you have full control over your selection data and display type. + // (your selection data could be an index, a pointer to the object, an id for the object, a flag stored in the object itself, etc.) + const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; + static const char* item_current = items[0]; // Here our selection is a single pointer stored outside the object. + if (ImGui::BeginCombo("combo 1", item_current, flags)) // The second parameter is the label previewed before opening the combo. + { + for (int n = 0; n < IM_ARRAYSIZE(items); n++) + { + bool is_selected = (item_current == items[n]); + if (ImGui::Selectable(items[n], is_selected)) + item_current = items[n]; + if (is_selected) + ImGui::SetItemDefaultFocus(); // Set the initial focus when opening the combo (scrolling + for keyboard navigation support in the upcoming navigation branch) + } + ImGui::EndCombo(); + } + + // Simplified one-liner Combo() API, using values packed in a single constant string + static int item_current_2 = 0; + ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); + + // Simplified one-liner Combo() using an array of const char* + static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview + ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items)); + + // Simplified one-liner Combo() using an accessor function + struct FuncHolder { static bool ItemGetter(void* data, int idx, const char** out_str) { *out_str = ((const char**)data)[idx]; return true; } }; + static int item_current_4 = 0; + ImGui::Combo("combo 4 (function)", &item_current_4, &FuncHolder::ItemGetter, items, IM_ARRAYSIZE(items)); + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Selectables")) + { + // Selectable() has 2 overloads: + // - The one taking "bool selected" as a read-only selection information. When Selectable() has been clicked is returns true and you can alter selection state accordingly. + // - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases) + // The earlier is more flexible, as in real application your selection may be stored in a different manner (in flags within objects, as an external list, etc). + if (ImGui::TreeNode("Basic")) + { + static bool selection[5] = { false, true, false, false, false }; + ImGui::Selectable("1. I am selectable", &selection[0]); + ImGui::Selectable("2. I am selectable", &selection[1]); + ImGui::Text("3. I am not selectable"); + ImGui::Selectable("4. I am selectable", &selection[3]); + if (ImGui::Selectable("5. I am double clickable", selection[4], ImGuiSelectableFlags_AllowDoubleClick)) + if (ImGui::IsMouseDoubleClicked(0)) + selection[4] = !selection[4]; + ImGui::TreePop(); + } + if (ImGui::TreeNode("Selection State: Single Selection")) + { + static int selected = -1; + for (int n = 0; n < 5; n++) + { + char buf[32]; + sprintf(buf, "Object %d", n); + if (ImGui::Selectable(buf, selected == n)) + selected = n; + } + ImGui::TreePop(); + } + if (ImGui::TreeNode("Selection State: Multiple Selection")) + { + ShowHelpMarker("Hold CTRL and click to select multiple items."); + static bool selection[5] = { false, false, false, false, false }; + for (int n = 0; n < 5; n++) + { + char buf[32]; + sprintf(buf, "Object %d", n); + if (ImGui::Selectable(buf, selection[n])) + { + if (!ImGui::GetIO().KeyCtrl) // Clear selection when CTRL is not held + memset(selection, 0, sizeof(selection)); + selection[n] ^= 1; + } + } + ImGui::TreePop(); + } + if (ImGui::TreeNode("Rendering more text into the same line")) + { + // Using the Selectable() override that takes "bool* p_selected" parameter and toggle your booleans automatically. + static bool selected[3] = { false, false, false }; + ImGui::Selectable("main.c", &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes"); + ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(300); ImGui::Text("12,345 bytes"); + ImGui::Selectable("Hello.h", &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes"); + ImGui::TreePop(); + } + if (ImGui::TreeNode("In columns")) + { + ImGui::Columns(3, NULL, false); + static bool selected[16] = { 0 }; + for (int i = 0; i < 16; i++) + { + char label[32]; sprintf(label, "Item %d", i); + if (ImGui::Selectable(label, &selected[i])) {} + ImGui::NextColumn(); + } + ImGui::Columns(1); + ImGui::TreePop(); + } + if (ImGui::TreeNode("Grid")) + { + static bool selected[16] = { true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true }; + for (int i = 0; i < 16; i++) + { + ImGui::PushID(i); + if (ImGui::Selectable("Sailor", &selected[i], 0, ImVec2(50,50))) + { + int x = i % 4, y = i / 4; + if (x > 0) selected[i - 1] ^= 1; + if (x < 3) selected[i + 1] ^= 1; + if (y > 0) selected[i - 4] ^= 1; + if (y < 3) selected[i + 4] ^= 1; + } + if ((i % 4) < 3) ImGui::SameLine(); + ImGui::PopID(); + } + ImGui::TreePop(); + } + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Filtered Text Input")) + { + static char buf1[64] = ""; ImGui::InputText("default", buf1, 64); + static char buf2[64] = ""; ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal); + static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase); + static char buf4[64] = ""; ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase); + static char buf5[64] = ""; ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank); + struct TextFilters { static int FilterImGuiLetters(ImGuiTextEditCallbackData* data) { if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) return 0; return 1; } }; + static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters); + + ImGui::Text("Password input"); + static char bufpass[64] = "password123"; + ImGui::InputText("password", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank); + ImGui::SameLine(); ShowHelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n"); + ImGui::InputText("password (clear)", bufpass, 64, ImGuiInputTextFlags_CharsNoBlank); + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Multi-line Text Input")) + { + static bool read_only = false; + static char text[1024*16] = + "/*\n" + " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n" + " the hexadecimal encoding of one offending instruction,\n" + " more formally, the invalid operand with locked CMPXCHG8B\n" + " instruction bug, is a design flaw in the majority of\n" + " Intel Pentium, Pentium MMX, and Pentium OverDrive\n" + " processors (all in the P5 microarchitecture).\n" + "*/\n\n" + "label:\n" + "\tlock cmpxchg8b eax\n"; + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0)); + ImGui::Checkbox("Read-only", &read_only); + ImGui::PopStyleVar(); + ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), ImGuiInputTextFlags_AllowTabInput | (read_only ? ImGuiInputTextFlags_ReadOnly : 0)); + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Plots Widgets")) + { + static bool animate = true; + ImGui::Checkbox("Animate", &animate); + + static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f }; + ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr)); + + // Create a dummy array of contiguous float values to plot + // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float and the sizeof() of your structure in the Stride parameter. + static float values[90] = { 0 }; + static int values_offset = 0; + static double refresh_time = 0.0; + if (!animate || refresh_time == 0.0f) + refresh_time = ImGui::GetTime(); + while (refresh_time < ImGui::GetTime()) // Create dummy data at fixed 60 hz rate for the demo + { + static float phase = 0.0f; + values[values_offset] = cosf(phase); + values_offset = (values_offset+1) % IM_ARRAYSIZE(values); + phase += 0.10f*values_offset; + refresh_time += 1.0f/60.0f; + } + ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,80)); + ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,80)); + + // Use functions to generate output + // FIXME: This is rather awkward because current plot API only pass in indices. We probably want an API passing floats and user provide sample rate/count. + struct Funcs + { + static float Sin(void*, int i) { return sinf(i * 0.1f); } + static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; } + }; + static int func_type = 0, display_count = 70; + ImGui::Separator(); + ImGui::PushItemWidth(100); ImGui::Combo("func", &func_type, "Sin\0Saw\0"); ImGui::PopItemWidth(); + ImGui::SameLine(); + ImGui::SliderInt("Sample count", &display_count, 1, 400); + float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw; + ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80)); + ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80)); + ImGui::Separator(); + + // Animate a simple progress bar + static float progress = 0.0f, progress_dir = 1.0f; + if (animate) + { + progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime; + if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; } + if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; } + } + + // Typically we would use ImVec2(-1.0f,0.0f) to use all available width, or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth. + ImGui::ProgressBar(progress, ImVec2(0.0f,0.0f)); + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); + ImGui::Text("Progress Bar"); + + float progress_saturated = (progress < 0.0f) ? 0.0f : (progress > 1.0f) ? 1.0f : progress; + char buf[32]; + sprintf(buf, "%d/%d", (int)(progress_saturated*1753), 1753); + ImGui::ProgressBar(progress, ImVec2(0.f,0.f), buf); + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Color/Picker Widgets")) + { + static ImVec4 color = ImColor(114, 144, 154, 200); + + static bool alpha_preview = true; + static bool alpha_half_preview = false; + static bool drag_and_drop = true; + static bool options_menu = true; + static bool hdr = false; + ImGui::Checkbox("With Alpha Preview", &alpha_preview); + ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview); + ImGui::Checkbox("With Drag and Drop", &drag_and_drop); + ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); ShowHelpMarker("Right-click on the individual color widget to show options."); + ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); ShowHelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets."); + int misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (drag_and_drop ? 0 : ImGuiColorEditFlags_NoDragDrop) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions); + + ImGui::Text("Color widget:"); + ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nCTRL+click on individual component to input value.\n"); + ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags); + + ImGui::Text("Color widget HSV with Alpha:"); + ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_HSV | misc_flags); + + ImGui::Text("Color widget with Float Display:"); + ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags); + + ImGui::Text("Color button with Picker:"); + ImGui::SameLine(); ShowHelpMarker("With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\nWith the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only be used for the tooltip and picker popup."); + ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags); + + ImGui::Text("Color button with Custom Picker Popup:"); + + // Generate a dummy palette + static bool saved_palette_inited = false; + static ImVec4 saved_palette[32]; + if (!saved_palette_inited) + for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) + { + ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f, saved_palette[n].x, saved_palette[n].y, saved_palette[n].z); + saved_palette[n].w = 1.0f; // Alpha + } + saved_palette_inited = true; + + static ImVec4 backup_color; + bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags); + ImGui::SameLine(); + open_popup |= ImGui::Button("Palette"); + if (open_popup) + { + ImGui::OpenPopup("mypicker"); + backup_color = color; + } + if (ImGui::BeginPopup("mypicker")) + { + // FIXME: Adding a drag and drop example here would be perfect! + ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!"); + ImGui::Separator(); + ImGui::ColorPicker4("##picker", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview); + ImGui::SameLine(); + ImGui::BeginGroup(); + ImGui::Text("Current"); + ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60,40)); + ImGui::Text("Previous"); + if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60,40))) + color = backup_color; + ImGui::Separator(); + ImGui::Text("Palette"); + for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) + { + ImGui::PushID(n); + if ((n % 8) != 0) + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y); + if (ImGui::ColorButton("##palette", saved_palette[n], ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip, ImVec2(20,20))) + color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha! + + if (ImGui::BeginDragDropTarget()) + { + if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) + memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3); + if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F)) + memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4); + EndDragDropTarget(); + } + + ImGui::PopID(); + } + ImGui::EndGroup(); + ImGui::EndPopup(); + } + + ImGui::Text("Color button only:"); + ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags, ImVec2(80,80)); + + ImGui::Text("Color picker:"); + static bool alpha = true; + static bool alpha_bar = true; + static bool side_preview = true; + static bool ref_color = false; + static ImVec4 ref_color_v(1.0f,0.0f,1.0f,0.5f); + static int inputs_mode = 2; + static int picker_mode = 0; + ImGui::Checkbox("With Alpha", &alpha); + ImGui::Checkbox("With Alpha Bar", &alpha_bar); + ImGui::Checkbox("With Side Preview", &side_preview); + if (side_preview) + { + ImGui::SameLine(); + ImGui::Checkbox("With Ref Color", &ref_color); + if (ref_color) + { + ImGui::SameLine(); + ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags); + } + } + ImGui::Combo("Inputs Mode", &inputs_mode, "All Inputs\0No Inputs\0RGB Input\0HSV Input\0HEX Input\0"); + ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0Hue bar + SV rect\0Hue wheel + SV triangle\0"); + ImGui::SameLine(); ShowHelpMarker("User can right-click the picker to change mode."); + ImGuiColorEditFlags flags = misc_flags; + if (!alpha) flags |= ImGuiColorEditFlags_NoAlpha; // This is by default if you call ColorPicker3() instead of ColorPicker4() + if (alpha_bar) flags |= ImGuiColorEditFlags_AlphaBar; + if (!side_preview) flags |= ImGuiColorEditFlags_NoSidePreview; + if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar; + if (picker_mode == 2) flags |= ImGuiColorEditFlags_PickerHueWheel; + if (inputs_mode == 1) flags |= ImGuiColorEditFlags_NoInputs; + if (inputs_mode == 2) flags |= ImGuiColorEditFlags_RGB; + if (inputs_mode == 3) flags |= ImGuiColorEditFlags_HSV; + if (inputs_mode == 4) flags |= ImGuiColorEditFlags_HEX; + ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL); + + ImGui::Text("Programmatically set defaults:"); + ImGui::SameLine(); ShowHelpMarker("SetColorEditOptions() is designed to allow you to set boot-time default.\nWe don't have Push/Pop functions because you can force options on a per-widget basis if needed, and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid encouraging you to persistently save values that aren't forward-compatible."); + if (ImGui::Button("Default: Uint8 + HSV + Hue Bar")) + ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_HSV | ImGuiColorEditFlags_PickerHueBar); + if (ImGui::Button("Default: Float + HDR + Hue Wheel")) + ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel); + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Range Widgets")) + { + static float begin = 10, end = 90; + static int begin_i = 100, end_i = 1000; + ImGui::DragFloatRange2("range", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%"); + ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %d units", "Max: %d units"); + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Data Types")) + { + // The DragScalar/InputScalar/SliderScalar functions allow various data types: signed/unsigned int/long long and float/double + // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum to pass the type, + // and passing all arguments by address. + // This is the reason the test code below creates local variables to hold "zero" "one" etc. for each types. + // In practice, if you frequently use a given type that is not covered by the normal API entry points, you can wrap it + // yourself inside a 1 line function which can take typed argument as value instead of void*, and then pass their address + // to the generic function. For example: + // bool MySliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld") + // { + // return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format); + // } + + // Limits (as helper variables that we can take the address of) + // Note that the SliderScalar function has a maximum usable range of half the natural type maximum, hence the /2 below. + #ifndef LLONG_MIN + ImS64 LLONG_MIN = -9223372036854775807LL - 1; + ImS64 LLONG_MAX = 9223372036854775807LL; + ImU64 ULLONG_MAX = (2ULL * 9223372036854775807LL + 1); + #endif + const ImS32 s32_zero = 0, s32_one = 1, s32_fifty = 50, s32_min = INT_MIN/2, s32_max = INT_MAX/2, s32_hi_a = INT_MAX/2 - 100, s32_hi_b = INT_MAX/2; + const ImU32 u32_zero = 0, u32_one = 1, u32_fifty = 50, u32_min = 0, u32_max = UINT_MAX/2, u32_hi_a = UINT_MAX/2 - 100, u32_hi_b = UINT_MAX/2; + const ImS64 s64_zero = 0, s64_one = 1, s64_fifty = 50, s64_min = LLONG_MIN/2, s64_max = LLONG_MAX/2, s64_hi_a = LLONG_MAX/2 - 100, s64_hi_b = LLONG_MAX/2; + const ImU64 u64_zero = 0, u64_one = 1, u64_fifty = 50, u64_min = 0, u64_max = ULLONG_MAX/2, u64_hi_a = ULLONG_MAX/2 - 100, u64_hi_b = ULLONG_MAX/2; + const float f32_zero = 0.f, f32_one = 1.f, f32_lo_a = -10000000000.0f, f32_hi_a = +10000000000.0f; + const double f64_zero = 0., f64_one = 1., f64_lo_a = -1000000000000000.0, f64_hi_a = +1000000000000000.0; + + // State + static ImS32 s32_v = -1; + static ImU32 u32_v = (ImU32)-1; + static ImS64 s64_v = -1; + static ImU64 u64_v = (ImU64)-1; + static float f32_v = 0.123f; + static double f64_v = 90000.01234567890123456789; + + const float drag_speed = 0.2f; + static bool drag_clamp = false; + ImGui::Text("Drags:"); + ImGui::Checkbox("Clamp integers to 0..50", &drag_clamp); ImGui::SameLine(); ShowHelpMarker("As with every widgets in dear imgui, we never modify values unless there is a user interaction.\nYou can override the clamping limits by using CTRL+Click to input a value."); + ImGui::DragScalar("drag s32", ImGuiDataType_S32, &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL); + ImGui::DragScalar("drag u32", ImGuiDataType_U32, &u32_v, drag_speed, drag_clamp ? &u32_zero : NULL, drag_clamp ? &u32_fifty : NULL, "%u ms"); + ImGui::DragScalar("drag s64", ImGuiDataType_S64, &s64_v, drag_speed, drag_clamp ? &s64_zero : NULL, drag_clamp ? &s64_fifty : NULL); + ImGui::DragScalar("drag u64", ImGuiDataType_U64, &u64_v, drag_speed, drag_clamp ? &u64_zero : NULL, drag_clamp ? &u64_fifty : NULL); + ImGui::DragScalar("drag float", ImGuiDataType_Float, &f32_v, 0.005f, &f32_zero, &f32_one, "%f", 1.0f); + ImGui::DragScalar("drag float ^2", ImGuiDataType_Float, &f32_v, 0.005f, &f32_zero, &f32_one, "%f", 2.0f); ImGui::SameLine(); ShowHelpMarker("You can use the 'power' parameter to increase tweaking precision on one side of the range."); + ImGui::DragScalar("drag double", ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, NULL, "%.10f grams", 1.0f); + ImGui::DragScalar("drag double ^2", ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, &f64_one, "0 < %.10f < 1", 2.0f); + + ImGui::Text("Sliders"); + ImGui::SliderScalar("slider s32 low", ImGuiDataType_S32, &s32_v, &s32_zero, &s32_fifty,"%d"); + ImGui::SliderScalar("slider s32 high", ImGuiDataType_S32, &s32_v, &s32_hi_a, &s32_hi_b, "%d"); + ImGui::SliderScalar("slider s32 full", ImGuiDataType_S32, &s32_v, &s32_min, &s32_max, "%d"); + ImGui::SliderScalar("slider u32 low", ImGuiDataType_U32, &u32_v, &u32_zero, &u32_fifty,"%u"); + ImGui::SliderScalar("slider u32 high", ImGuiDataType_U32, &u32_v, &u32_hi_a, &u32_hi_b, "%u"); + ImGui::SliderScalar("slider u32 full", ImGuiDataType_U32, &u32_v, &u32_min, &u32_max, "%u"); + ImGui::SliderScalar("slider s64 low", ImGuiDataType_S64, &s64_v, &s64_zero, &s64_fifty,"%I64d"); + ImGui::SliderScalar("slider s64 high", ImGuiDataType_S64, &s64_v, &s64_hi_a, &s64_hi_b, "%I64d"); + ImGui::SliderScalar("slider s64 full", ImGuiDataType_S64, &s64_v, &s64_min, &s64_max, "%I64d"); + ImGui::SliderScalar("slider u64 low", ImGuiDataType_U64, &u64_v, &u64_zero, &u64_fifty,"%I64u ms"); + ImGui::SliderScalar("slider u64 high", ImGuiDataType_U64, &u64_v, &u64_hi_a, &u64_hi_b, "%I64u ms"); + ImGui::SliderScalar("slider u64 full", ImGuiDataType_U64, &u64_v, &u64_min, &u64_max, "%I64u ms"); + ImGui::SliderScalar("slider float low", ImGuiDataType_Float, &f32_v, &f32_zero, &f32_one); + ImGui::SliderScalar("slider float low^2", ImGuiDataType_Float, &f32_v, &f32_zero, &f32_one, "%.10f", 2.0f); + ImGui::SliderScalar("slider float high", ImGuiDataType_Float, &f32_v, &f32_lo_a, &f32_hi_a, "%e"); + ImGui::SliderScalar("slider double low", ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one, "%.10f grams", 1.0f); + ImGui::SliderScalar("slider double low^2",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one, "%.10f", 2.0f); + ImGui::SliderScalar("slider double high", ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams", 1.0f); + + static bool inputs_step = true; + ImGui::Text("Inputs"); + ImGui::Checkbox("Show step buttons", &inputs_step); + ImGui::InputScalar("input s32", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d"); + ImGui::InputScalar("input s32 hex", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal); + ImGui::InputScalar("input u32", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u"); + ImGui::InputScalar("input u32 hex", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal); + ImGui::InputScalar("input s64", ImGuiDataType_S64, &s64_v, inputs_step ? &s64_one : NULL); + ImGui::InputScalar("input u64", ImGuiDataType_U64, &u64_v, inputs_step ? &u64_one : NULL); + ImGui::InputScalar("input float", ImGuiDataType_Float, &f32_v, inputs_step ? &f32_one : NULL); + ImGui::InputScalar("input double", ImGuiDataType_Double, &f64_v, inputs_step ? &f64_one : NULL); + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Multi-component Widgets")) + { + static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f }; + static int vec4i[4] = { 1, 5, 100, 255 }; + + ImGui::InputFloat2("input float2", vec4f); + ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f); + ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f); + ImGui::InputInt2("input int2", vec4i); + ImGui::DragInt2("drag int2", vec4i, 1, 0, 255); + ImGui::SliderInt2("slider int2", vec4i, 0, 255); + ImGui::Spacing(); + + ImGui::InputFloat3("input float3", vec4f); + ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f); + ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f); + ImGui::InputInt3("input int3", vec4i); + ImGui::DragInt3("drag int3", vec4i, 1, 0, 255); + ImGui::SliderInt3("slider int3", vec4i, 0, 255); + ImGui::Spacing(); + + ImGui::InputFloat4("input float4", vec4f); + ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f); + ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f); + ImGui::InputInt4("input int4", vec4i); + ImGui::DragInt4("drag int4", vec4i, 1, 0, 255); + ImGui::SliderInt4("slider int4", vec4i, 0, 255); + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Vertical Sliders")) + { + const float spacing = 4; + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing)); + + static int int_value = 0; + ImGui::VSliderInt("##int", ImVec2(18,160), &int_value, 0, 5); + ImGui::SameLine(); + + static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f }; + ImGui::PushID("set1"); + for (int i = 0; i < 7; i++) + { + if (i > 0) ImGui::SameLine(); + ImGui::PushID(i); + ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i/7.0f, 0.5f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i/7.0f, 0.9f, 0.9f)); + ImGui::VSliderFloat("##v", ImVec2(18,160), &values[i], 0.0f, 1.0f, ""); + if (ImGui::IsItemActive() || ImGui::IsItemHovered()) + ImGui::SetTooltip("%.3f", values[i]); + ImGui::PopStyleColor(4); + ImGui::PopID(); + } + ImGui::PopID(); + + ImGui::SameLine(); + ImGui::PushID("set2"); + static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f }; + const int rows = 3; + const ImVec2 small_slider_size(18, (160.0f-(rows-1)*spacing)/rows); + for (int nx = 0; nx < 4; nx++) + { + if (nx > 0) ImGui::SameLine(); + ImGui::BeginGroup(); + for (int ny = 0; ny < rows; ny++) + { + ImGui::PushID(nx*rows+ny); + ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, ""); + if (ImGui::IsItemActive() || ImGui::IsItemHovered()) + ImGui::SetTooltip("%.3f", values2[nx]); + ImGui::PopID(); + } + ImGui::EndGroup(); + } + ImGui::PopID(); + + ImGui::SameLine(); + ImGui::PushID("set3"); + for (int i = 0; i < 4; i++) + { + if (i > 0) ImGui::SameLine(); + ImGui::PushID(i); + ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40); + ImGui::VSliderFloat("##v", ImVec2(40,160), &values[i], 0.0f, 1.0f, "%.2f\nsec"); + ImGui::PopStyleVar(); + ImGui::PopID(); + } + ImGui::PopID(); + ImGui::PopStyleVar(); + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Drag and Drop")) + { + { + // ColorEdit widgets automatically act as drag source and drag target. + // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F to allow your own widgets + // to use colors in their drag and drop interaction. Also see the demo in Color Picker -> Palette demo. + ImGui::BulletText("Drag and drop in standard widgets"); + ImGui::Indent(); + static float col1[3] = { 1.0f,0.0f,0.2f }; + static float col2[4] = { 0.4f,0.7f,0.0f,0.5f }; + ImGui::ColorEdit3("color 1", col1); + ImGui::ColorEdit4("color 2", col2); + ImGui::Unindent(); + } + + { + ImGui::BulletText("Drag and drop to copy/swap items"); + ImGui::Indent(); + enum Mode + { + Mode_Copy, + Mode_Move, + Mode_Swap + }; + static int mode = 0; + if (ImGui::RadioButton("Copy", mode == Mode_Copy)) { mode = Mode_Copy; } ImGui::SameLine(); + if (ImGui::RadioButton("Move", mode == Mode_Move)) { mode = Mode_Move; } ImGui::SameLine(); + if (ImGui::RadioButton("Swap", mode == Mode_Swap)) { mode = Mode_Swap; } + static const char* names[9] = { "Bobby", "Beatrice", "Betty", "Brianna", "Barry", "Bernard", "Bibi", "Blaine", "Bryn" }; + for (int n = 0; n < IM_ARRAYSIZE(names); n++) + { + ImGui::PushID(n); + if ((n % 3) != 0) + ImGui::SameLine(); + ImGui::Button(names[n], ImVec2(60,60)); + + // Our buttons are both drag sources and drag targets here! + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) + { + ImGui::SetDragDropPayload("DND_DEMO_CELL", &n, sizeof(int)); // Set payload to carry the index of our item (could be anything) + if (mode == Mode_Copy) { ImGui::Text("Copy %s", names[n]); } // Display preview (could be anything, e.g. when dragging an image we could decide to display the filename and a small preview of the image, etc.) + if (mode == Mode_Move) { ImGui::Text("Move %s", names[n]); } + if (mode == Mode_Swap) { ImGui::Text("Swap %s", names[n]); } + ImGui::EndDragDropSource(); + } + if (ImGui::BeginDragDropTarget()) + { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DEMO_CELL")) + { + IM_ASSERT(payload->DataSize == sizeof(int)); + int payload_n = *(const int*)payload->Data; + if (mode == Mode_Copy) + { + names[n] = names[payload_n]; + } + if (mode == Mode_Move) + { + names[n] = names[payload_n]; + names[payload_n] = ""; + } + if (mode == Mode_Swap) + { + const char* tmp = names[n]; + names[n] = names[payload_n]; + names[payload_n] = tmp; + } + } + ImGui::EndDragDropTarget(); + } + ImGui::PopID(); + } + ImGui::Unindent(); + } + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Active, Focused, Hovered & Focused Tests")) + { + // Display the value of IsItemHovered() and other common item state functions. Note that the flags can be combined. + // (because BulletText is an item itself and that would affect the output of IsItemHovered() we pass all state in a single call to simplify the code). + static int item_type = 1; + static bool b = false; + static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f }; + ImGui::RadioButton("Text", &item_type, 0); ImGui::SameLine(); + ImGui::RadioButton("Button", &item_type, 1); ImGui::SameLine(); + ImGui::RadioButton("CheckBox", &item_type, 2); ImGui::SameLine(); + ImGui::RadioButton("SliderFloat", &item_type, 3); ImGui::SameLine(); + ImGui::RadioButton("ColorEdit4", &item_type, 4); ImGui::SameLine(); + ImGui::RadioButton("ListBox", &item_type, 5); + bool ret = false; + if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction + if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); } // Testing button + if (item_type == 2) { ret = ImGui::Checkbox("ITEM: CheckBox", &b); } // Testing checkbox + if (item_type == 3) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); } // Testing basic item + if (item_type == 4) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) + if (item_type == 5) { const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } + ImGui::BulletText( + "Return value = %d\n" + "IsItemFocused() = %d\n" + "IsItemHovered() = %d\n" + "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n" + "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n" + "IsItemHovered(_AllowWhenOverlapped) = %d\n" + "IsItemHovered(_RectOnly) = %d\n" + "IsItemActive() = %d\n" + "IsItemDeactivated() = %d\n" + "IsItemDeactivatedAfterChange() = %d\n" + "IsItemVisible() = %d\n", + ret, + ImGui::IsItemFocused(), + ImGui::IsItemHovered(), + ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), + ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), + ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped), + ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly), + ImGui::IsItemActive(), + ImGui::IsItemDeactivated(), + ImGui::IsItemDeactivatedAfterChange(), + ImGui::IsItemVisible() + ); + + static bool embed_all_inside_a_child_window = false; + ImGui::Checkbox("Embed everything inside a child window (for additional testing)", &embed_all_inside_a_child_window); + if (embed_all_inside_a_child_window) + ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20), true); + + // Testing IsWindowFocused() function with its various flags. Note that the flags can be combined. + ImGui::BulletText( + "IsWindowFocused() = %d\n" + "IsWindowFocused(_ChildWindows) = %d\n" + "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n" + "IsWindowFocused(_RootWindow) = %d\n" + "IsWindowFocused(_AnyWindow) = %d\n", + ImGui::IsWindowFocused(), + ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows), + ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow), + ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow), + ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow)); + + // Testing IsWindowHovered() function with its various flags. Note that the flags can be combined. + ImGui::BulletText( + "IsWindowHovered() = %d\n" + "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n" + "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n" + "IsWindowHovered(_ChildWindows) = %d\n" + "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n" + "IsWindowHovered(_RootWindow) = %d\n" + "IsWindowHovered(_AnyWindow) = %d\n", + ImGui::IsWindowHovered(), + ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), + ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), + ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows), + ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow), + ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow), + ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow)); + + ImGui::BeginChild("child", ImVec2(0, 50), true); + ImGui::Text("This is another child window for testing with the _ChildWindows flag."); + ImGui::EndChild(); + if (embed_all_inside_a_child_window) + EndChild(); + + // Calling IsItemHovered() after begin returns the hovered status of the title bar. + // This is useful in particular if you want to create a context menu (with BeginPopupContextItem) associated to the title bar of a window. + static bool test_window = false; + ImGui::Checkbox("Hovered/Active tests after Begin() for title bar testing", &test_window); + if (test_window) + { + ImGui::Begin("Title bar Hovered/Active tests", &test_window); + if (ImGui::BeginPopupContextItem()) // <-- This is using IsItemHovered() + { + if (ImGui::MenuItem("Close")) { test_window = false; } + ImGui::EndPopup(); + } + ImGui::Text( + "IsItemHovered() after begin = %d (== is title bar hovered)\n" + "IsItemActive() after begin = %d (== is window being clicked/moved)\n", + ImGui::IsItemHovered(), ImGui::IsItemActive()); + ImGui::End(); + } + + ImGui::TreePop(); + } + } + + if (ImGui::CollapsingHeader("Layout")) + { + if (ImGui::TreeNode("Child regions")) + { + static bool disable_mouse_wheel = false; + static bool disable_menu = false; + ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel); + ImGui::Checkbox("Disable Menu", &disable_menu); + + static int line = 50; + bool goto_line = ImGui::Button("Goto"); + ImGui::SameLine(); + ImGui::PushItemWidth(100); + goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue); + ImGui::PopItemWidth(); + + // Child 1: no border, enable horizontal scrollbar + { + ImGui::BeginChild("Child1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 300), false, ImGuiWindowFlags_HorizontalScrollbar | (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0)); + for (int i = 0; i < 100; i++) + { + ImGui::Text("%04d: scrollable region", i); + if (goto_line && line == i) + ImGui::SetScrollHere(); + } + if (goto_line && line >= 100) + ImGui::SetScrollHere(); + ImGui::EndChild(); + } + + ImGui::SameLine(); + + // Child 2: rounded border + { + ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f); + ImGui::BeginChild("Child2", ImVec2(0,300), true, (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0) | (disable_menu ? 0 : ImGuiWindowFlags_MenuBar)); + if (!disable_menu && ImGui::BeginMenuBar()) + { + if (ImGui::BeginMenu("Menu")) + { + ShowExampleMenuFile(); + ImGui::EndMenu(); + } + ImGui::EndMenuBar(); + } + ImGui::Columns(2); + for (int i = 0; i < 100; i++) + { + char buf[32]; + sprintf(buf, "%03d", i); + ImGui::Button(buf, ImVec2(-1.0f, 0.0f)); + ImGui::NextColumn(); + } + ImGui::EndChild(); + ImGui::PopStyleVar(); + } + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Widgets Width")) + { + static float f = 0.0f; + ImGui::Text("PushItemWidth(100)"); + ImGui::SameLine(); ShowHelpMarker("Fixed width."); + ImGui::PushItemWidth(100); + ImGui::DragFloat("float##1", &f); + ImGui::PopItemWidth(); + + ImGui::Text("PushItemWidth(GetWindowWidth() * 0.5f)"); + ImGui::SameLine(); ShowHelpMarker("Half of window width."); + ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f); + ImGui::DragFloat("float##2", &f); + ImGui::PopItemWidth(); + + ImGui::Text("PushItemWidth(GetContentRegionAvailWidth() * 0.5f)"); + ImGui::SameLine(); ShowHelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)"); + ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() * 0.5f); + ImGui::DragFloat("float##3", &f); + ImGui::PopItemWidth(); + + ImGui::Text("PushItemWidth(-100)"); + ImGui::SameLine(); ShowHelpMarker("Align to right edge minus 100"); + ImGui::PushItemWidth(-100); + ImGui::DragFloat("float##4", &f); + ImGui::PopItemWidth(); + + ImGui::Text("PushItemWidth(-1)"); + ImGui::SameLine(); ShowHelpMarker("Align to right edge"); + ImGui::PushItemWidth(-1); + ImGui::DragFloat("float##5", &f); + ImGui::PopItemWidth(); + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Basic Horizontal Layout")) + { + ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)"); + + // Text + ImGui::Text("Two items: Hello"); ImGui::SameLine(); + ImGui::TextColored(ImVec4(1,1,0,1), "Sailor"); + + // Adjust spacing + ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20); + ImGui::TextColored(ImVec4(1,1,0,1), "Sailor"); + + // Button + ImGui::AlignTextToFramePadding(); + ImGui::Text("Normal buttons"); ImGui::SameLine(); + ImGui::Button("Banana"); ImGui::SameLine(); + ImGui::Button("Apple"); ImGui::SameLine(); + ImGui::Button("Corniflower"); + + // Button + ImGui::Text("Small buttons"); ImGui::SameLine(); + ImGui::SmallButton("Like this one"); ImGui::SameLine(); + ImGui::Text("can fit within a text block."); + + // Aligned to arbitrary position. Easy/cheap column. + ImGui::Text("Aligned"); + ImGui::SameLine(150); ImGui::Text("x=150"); + ImGui::SameLine(300); ImGui::Text("x=300"); + ImGui::Text("Aligned"); + ImGui::SameLine(150); ImGui::SmallButton("x=150"); + ImGui::SameLine(300); ImGui::SmallButton("x=300"); + + // Checkbox + static bool c1=false,c2=false,c3=false,c4=false; + ImGui::Checkbox("My", &c1); ImGui::SameLine(); + ImGui::Checkbox("Tailor", &c2); ImGui::SameLine(); + ImGui::Checkbox("Is", &c3); ImGui::SameLine(); + ImGui::Checkbox("Rich", &c4); + + // Various + static float f0=1.0f, f1=2.0f, f2=3.0f; + ImGui::PushItemWidth(80); + const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" }; + static int item = -1; + ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine(); + ImGui::SliderFloat("X", &f0, 0.0f,5.0f); ImGui::SameLine(); + ImGui::SliderFloat("Y", &f1, 0.0f,5.0f); ImGui::SameLine(); + ImGui::SliderFloat("Z", &f2, 0.0f,5.0f); + ImGui::PopItemWidth(); + + ImGui::PushItemWidth(80); + ImGui::Text("Lists:"); + static int selection[4] = { 0, 1, 2, 3 }; + for (int i = 0; i < 4; i++) + { + if (i > 0) ImGui::SameLine(); + ImGui::PushID(i); + ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items)); + ImGui::PopID(); + //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i); + } + ImGui::PopItemWidth(); + + // Dummy + ImVec2 button_sz(40,40); + ImGui::Button("A", button_sz); ImGui::SameLine(); + ImGui::Dummy(button_sz); ImGui::SameLine(); + ImGui::Button("B", button_sz); + + // Manually wrapping (we should eventually provide this as an automatic layout feature, but for now you can do it manually) + ImGui::Text("Manually wrapping:"); + ImGuiStyle& style = ImGui::GetStyle(); + int buttons_count = 20; + float window_visible_x2 = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x; + for (int n = 0; n < buttons_count; n++) + { + ImGui::PushID(n); + ImGui::Button("Box", button_sz); + float last_button_x2 = ImGui::GetItemRectMax().x; + float next_button_x2 = last_button_x2 + style.ItemSpacing.x + button_sz.x; // Expected position if next button was on same line + if (n + 1 < buttons_count && next_button_x2 < window_visible_x2) + ImGui::SameLine(); + ImGui::PopID(); + } + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Groups")) + { + ImGui::TextWrapped("(Using ImGui::BeginGroup()/EndGroup() to layout items. BeginGroup() basically locks the horizontal position. EndGroup() bundles the whole group so that you can use functions such as IsItemHovered() on it.)"); + ImGui::BeginGroup(); + { + ImGui::BeginGroup(); + ImGui::Button("AAA"); + ImGui::SameLine(); + ImGui::Button("BBB"); + ImGui::SameLine(); + ImGui::BeginGroup(); + ImGui::Button("CCC"); + ImGui::Button("DDD"); + ImGui::EndGroup(); + ImGui::SameLine(); + ImGui::Button("EEE"); + ImGui::EndGroup(); + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("First group hovered"); + } + // Capture the group size and create widgets using the same size + ImVec2 size = ImGui::GetItemRectSize(); + const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f }; + ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size); + + ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y)); + ImGui::SameLine(); + ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y)); + ImGui::EndGroup(); + ImGui::SameLine(); + + ImGui::Button("LEVERAGE\nBUZZWORD", size); + ImGui::SameLine(); + + if (ImGui::ListBoxHeader("List", size)) + { + ImGui::Selectable("Selected", true); + ImGui::Selectable("Not Selected", false); + ImGui::ListBoxFooter(); + } + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Text Baseline Alignment")) + { + ImGui::TextWrapped("(This is testing the vertical alignment that occurs on text to keep it at the same baseline as widgets. Lines only composed of text or \"small\" widgets fit in less vertical spaces than lines with normal widgets)"); + + ImGui::Text("One\nTwo\nThree"); ImGui::SameLine(); + ImGui::Text("Hello\nWorld"); ImGui::SameLine(); + ImGui::Text("Banana"); + + ImGui::Text("Banana"); ImGui::SameLine(); + ImGui::Text("Hello\nWorld"); ImGui::SameLine(); + ImGui::Text("One\nTwo\nThree"); + + ImGui::Button("HOP##1"); ImGui::SameLine(); + ImGui::Text("Banana"); ImGui::SameLine(); + ImGui::Text("Hello\nWorld"); ImGui::SameLine(); + ImGui::Text("Banana"); + + ImGui::Button("HOP##2"); ImGui::SameLine(); + ImGui::Text("Hello\nWorld"); ImGui::SameLine(); + ImGui::Text("Banana"); + + ImGui::Button("TEST##1"); ImGui::SameLine(); + ImGui::Text("TEST"); ImGui::SameLine(); + ImGui::SmallButton("TEST##2"); + + ImGui::AlignTextToFramePadding(); // If your line starts with text, call this to align it to upcoming widgets. + ImGui::Text("Text aligned to Widget"); ImGui::SameLine(); + ImGui::Button("Widget##1"); ImGui::SameLine(); + ImGui::Text("Widget"); ImGui::SameLine(); + ImGui::SmallButton("Widget##2"); ImGui::SameLine(); + ImGui::Button("Widget##3"); + + // Tree + const float spacing = ImGui::GetStyle().ItemInnerSpacing.x; + ImGui::Button("Button##1"); + ImGui::SameLine(0.0f, spacing); + if (ImGui::TreeNode("Node##1")) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data + + ImGui::AlignTextToFramePadding(); // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. Otherwise you can use SmallButton (smaller fit). + bool node_open = ImGui::TreeNode("Node##2"); // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add child content. + ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2"); + if (node_open) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data + + // Bullet + ImGui::Button("Button##3"); + ImGui::SameLine(0.0f, spacing); + ImGui::BulletText("Bullet text"); + + ImGui::AlignTextToFramePadding(); + ImGui::BulletText("Node"); + ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4"); + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Scrolling")) + { + ImGui::TextWrapped("(Use SetScrollHere() or SetScrollFromPosY() to scroll to a given position.)"); + static bool track = true; + static int track_line = 50, scroll_to_px = 200; + ImGui::Checkbox("Track", &track); + ImGui::PushItemWidth(100); + ImGui::SameLine(130); track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 99, "Line = %d"); + bool scroll_to = ImGui::Button("Scroll To Pos"); + ImGui::SameLine(130); scroll_to |= ImGui::DragInt("##pos_y", &scroll_to_px, 1.00f, 0, 9999, "Y = %d px"); + ImGui::PopItemWidth(); + if (scroll_to) track = false; + + for (int i = 0; i < 5; i++) + { + if (i > 0) ImGui::SameLine(); + ImGui::BeginGroup(); + ImGui::Text("%s", i == 0 ? "Top" : i == 1 ? "25%" : i == 2 ? "Center" : i == 3 ? "75%" : "Bottom"); + ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true); + if (scroll_to) + ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f); + for (int line = 0; line < 100; line++) + { + if (track && line == track_line) + { + ImGui::TextColored(ImColor(255,255,0), "Line %d", line); + ImGui::SetScrollHere(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom + } + else + { + ImGui::Text("Line %d", line); + } + } + float scroll_y = ImGui::GetScrollY(), scroll_max_y = ImGui::GetScrollMaxY(); + ImGui::EndChild(); + ImGui::Text("%.0f/%0.f", scroll_y, scroll_max_y); + ImGui::EndGroup(); + } + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Horizontal Scrolling")) + { + ImGui::Bullet(); ImGui::TextWrapped("Horizontal scrolling for a window has to be enabled explicitly via the ImGuiWindowFlags_HorizontalScrollbar flag."); + ImGui::Bullet(); ImGui::TextWrapped("You may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin()."); + static int lines = 7; + ImGui::SliderInt("Lines", &lines, 1, 15); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f)); + ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetFrameHeightWithSpacing()*7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar); + for (int line = 0; line < lines; line++) + { + // Display random stuff (for the sake of this trivial demo we are using basic Button+SameLine. If you want to create your own time line for a real application you may be better off + // manipulating the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets yourself. You may also want to use the lower-level ImDrawList API) + int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3); + for (int n = 0; n < num_buttons; n++) + { + if (n > 0) ImGui::SameLine(); + ImGui::PushID(n + line * 1000); + char num_buf[16]; + sprintf(num_buf, "%d", n); + const char* label = (!(n%15)) ? "FizzBuzz" : (!(n%3)) ? "Fizz" : (!(n%5)) ? "Buzz" : num_buf; + float hue = n*0.05f; + ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f)); + ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f)); + ImGui::PopStyleColor(3); + ImGui::PopID(); + } + } + float scroll_x = ImGui::GetScrollX(), scroll_max_x = ImGui::GetScrollMaxX(); + ImGui::EndChild(); + ImGui::PopStyleVar(2); + float scroll_x_delta = 0.0f; + ImGui::SmallButton("<<"); if (ImGui::IsItemActive()) scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f; ImGui::SameLine(); + ImGui::Text("Scroll from code"); ImGui::SameLine(); + ImGui::SmallButton(">>"); if (ImGui::IsItemActive()) scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f; ImGui::SameLine(); + ImGui::Text("%.0f/%.0f", scroll_x, scroll_max_x); + if (scroll_x_delta != 0.0f) + { + ImGui::BeginChild("scrolling"); // Demonstrate a trick: you can use Begin to set yourself in the context of another window (here we are already out of your child window) + ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta); + ImGui::End(); + } + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Clipping")) + { + static ImVec2 size(100, 100), offset(50, 20); + ImGui::TextWrapped("On a per-widget basis we are occasionally clipping text CPU-side if it won't fit in its frame. Otherwise we are doing coarser clipping + passing a scissor rectangle to the renderer. The system is designed to try minimizing both execution and CPU/GPU rendering cost."); + ImGui::DragFloat2("size", (float*)&size, 0.5f, 0.0f, 200.0f, "%.0f"); + ImGui::TextWrapped("(Click and drag)"); + ImVec2 pos = ImGui::GetCursorScreenPos(); + ImVec4 clip_rect(pos.x, pos.y, pos.x+size.x, pos.y+size.y); + ImGui::InvisibleButton("##dummy", size); + if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; } + ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x+size.x,pos.y+size.y), IM_COL32(90,90,120,255)); + ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize()*2.0f, ImVec2(pos.x+offset.x,pos.y+offset.y), IM_COL32(255,255,255,255), "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect); + ImGui::TreePop(); + } + } + + if (ImGui::CollapsingHeader("Popups & Modal windows")) + { + if (ImGui::TreeNode("Popups")) + { + ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it."); + + static int selected_fish = -1; + const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" }; + static bool toggles[] = { true, false, false, false, false }; + + // Simple selection popup + // (If you want to show the current selection inside the Button itself, you may want to build a string using the "###" operator to preserve a constant ID with a variable label) + if (ImGui::Button("Select..")) + ImGui::OpenPopup("select"); + ImGui::SameLine(); + ImGui::TextUnformatted(selected_fish == -1 ? "" : names[selected_fish]); + if (ImGui::BeginPopup("select")) + { + ImGui::Text("Aquarium"); + ImGui::Separator(); + for (int i = 0; i < IM_ARRAYSIZE(names); i++) + if (ImGui::Selectable(names[i])) + selected_fish = i; + ImGui::EndPopup(); + } + + // Showing a menu with toggles + if (ImGui::Button("Toggle..")) + ImGui::OpenPopup("toggle"); + if (ImGui::BeginPopup("toggle")) + { + for (int i = 0; i < IM_ARRAYSIZE(names); i++) + ImGui::MenuItem(names[i], "", &toggles[i]); + if (ImGui::BeginMenu("Sub-menu")) + { + ImGui::MenuItem("Click me"); + ImGui::EndMenu(); + } + + ImGui::Separator(); + ImGui::Text("Tooltip here"); + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("I am a tooltip over a popup"); + + if (ImGui::Button("Stacked Popup")) + ImGui::OpenPopup("another popup"); + if (ImGui::BeginPopup("another popup")) + { + for (int i = 0; i < IM_ARRAYSIZE(names); i++) + ImGui::MenuItem(names[i], "", &toggles[i]); + if (ImGui::BeginMenu("Sub-menu")) + { + ImGui::MenuItem("Click me"); + ImGui::EndMenu(); + } + ImGui::EndPopup(); + } + ImGui::EndPopup(); + } + + if (ImGui::Button("Popup Menu..")) + ImGui::OpenPopup("FilePopup"); + if (ImGui::BeginPopup("FilePopup")) + { + ShowExampleMenuFile(); + ImGui::EndPopup(); + } + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Context menus")) + { + // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing: + // if (IsItemHovered() && IsMouseClicked(0)) + // OpenPopup(id); + // return BeginPopup(id); + // For more advanced uses you may want to replicate and cuztomize this code. This the comments inside BeginPopupContextItem() implementation. + static float value = 0.5f; + ImGui::Text("Value = %.3f (<-- right-click here)", value); + if (ImGui::BeginPopupContextItem("item context menu")) + { + if (ImGui::Selectable("Set to zero")) value = 0.0f; + if (ImGui::Selectable("Set to PI")) value = 3.1415f; + ImGui::PushItemWidth(-1); + ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f); + ImGui::PopItemWidth(); + ImGui::EndPopup(); + } + + static char name[32] = "Label1"; + char buf[64]; sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label + ImGui::Button(buf); + if (ImGui::BeginPopupContextItem()) // When used after an item that has an ID (here the Button), we can skip providing an ID to BeginPopupContextItem(). + { + ImGui::Text("Edit name:"); + ImGui::InputText("##edit", name, IM_ARRAYSIZE(name)); + if (ImGui::Button("Close")) + ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); + } + ImGui::SameLine(); ImGui::Text("(<-- right-click here)"); + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Modals")) + { + ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside the window."); + + if (ImGui::Button("Delete..")) + ImGui::OpenPopup("Delete?"); + if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize)) + { + ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n"); + ImGui::Separator(); + + //static int dummy_i = 0; + //ImGui::Combo("Combo", &dummy_i, "Delete\0Delete harder\0"); + + static bool dont_ask_me_next_time = false; + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0)); + ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time); + ImGui::PopStyleVar(); + + if (ImGui::Button("OK", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); } + ImGui::SetItemDefaultFocus(); + ImGui::SameLine(); + if (ImGui::Button("Cancel", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); } + ImGui::EndPopup(); + } + + if (ImGui::Button("Stacked modals..")) + ImGui::OpenPopup("Stacked 1"); + if (ImGui::BeginPopupModal("Stacked 1")) + { + ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDimBg] behind it."); + static int item = 1; + ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); + static float color[4] = { 0.4f,0.7f,0.0f,0.5f }; + ImGui::ColorEdit4("color", color); // This is to test behavior of stacked regular popups over a modal + + if (ImGui::Button("Add another modal..")) + ImGui::OpenPopup("Stacked 2"); + if (ImGui::BeginPopupModal("Stacked 2")) + { + ImGui::Text("Hello from Stacked The Second!"); + if (ImGui::Button("Close")) + ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); + } + + if (ImGui::Button("Close")) + ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); + } + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Menus inside a regular window")) + { + ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!"); + ImGui::Separator(); + // NB: As a quirk in this very specific example, we want to differentiate the parent of this menu from the parent of the various popup menus above. + // To do so we are encloding the items in a PushID()/PopID() block to make them two different menusets. If we don't, opening any popup above and hovering our menu here + // would open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it, which is the desired behavior for regular menus. + ImGui::PushID("foo"); + ImGui::MenuItem("Menu item", "CTRL+M"); + if (ImGui::BeginMenu("Menu inside a regular window")) + { + ShowExampleMenuFile(); + ImGui::EndMenu(); + } + ImGui::PopID(); + ImGui::Separator(); + ImGui::TreePop(); + } + } + + if (ImGui::CollapsingHeader("Columns")) + { + ImGui::PushID("Columns"); + + // Basic columns + if (ImGui::TreeNode("Basic")) + { + ImGui::Text("Without border:"); + ImGui::Columns(3, "mycolumns3", false); // 3-ways, no border + ImGui::Separator(); + for (int n = 0; n < 14; n++) + { + char label[32]; + sprintf(label, "Item %d", n); + if (ImGui::Selectable(label)) {} + //if (ImGui::Button(label, ImVec2(-1,0))) {} + ImGui::NextColumn(); + } + ImGui::Columns(1); + ImGui::Separator(); + + ImGui::Text("With border:"); + ImGui::Columns(4, "mycolumns"); // 4-ways, with border + ImGui::Separator(); + ImGui::Text("ID"); ImGui::NextColumn(); + ImGui::Text("Name"); ImGui::NextColumn(); + ImGui::Text("Path"); ImGui::NextColumn(); + ImGui::Text("Hovered"); ImGui::NextColumn(); + ImGui::Separator(); + const char* names[3] = { "One", "Two", "Three" }; + const char* paths[3] = { "/path/one", "/path/two", "/path/three" }; + static int selected = -1; + for (int i = 0; i < 3; i++) + { + char label[32]; + sprintf(label, "%04d", i); + if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns)) + selected = i; + bool hovered = ImGui::IsItemHovered(); + ImGui::NextColumn(); + ImGui::Text(names[i]); ImGui::NextColumn(); + ImGui::Text(paths[i]); ImGui::NextColumn(); + ImGui::Text("%d", hovered); ImGui::NextColumn(); + } + ImGui::Columns(1); + ImGui::Separator(); + ImGui::TreePop(); + } + + // Create multiple items in a same cell before switching to next column + if (ImGui::TreeNode("Mixed items")) + { + ImGui::Columns(3, "mixed"); + ImGui::Separator(); + + ImGui::Text("Hello"); + ImGui::Button("Banana"); + ImGui::NextColumn(); + + ImGui::Text("ImGui"); + ImGui::Button("Apple"); + static float foo = 1.0f; + ImGui::InputFloat("red", &foo, 0.05f, 0, "%.3f"); + ImGui::Text("An extra line here."); + ImGui::NextColumn(); + + ImGui::Text("Sailor"); + ImGui::Button("Corniflower"); + static float bar = 1.0f; + ImGui::InputFloat("blue", &bar, 0.05f, 0, "%.3f"); + ImGui::NextColumn(); + + if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn(); + if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn(); + if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn(); + ImGui::Columns(1); + ImGui::Separator(); + ImGui::TreePop(); + } + + // Word wrapping + if (ImGui::TreeNode("Word-wrapping")) + { + ImGui::Columns(2, "word-wrapping"); + ImGui::Separator(); + ImGui::TextWrapped("The quick brown fox jumps over the lazy dog."); + ImGui::TextWrapped("Hello Left"); + ImGui::NextColumn(); + ImGui::TextWrapped("The quick brown fox jumps over the lazy dog."); + ImGui::TextWrapped("Hello Right"); + ImGui::Columns(1); + ImGui::Separator(); + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Borders")) + { + // NB: Future columns API should allow automatic horizontal borders. + static bool h_borders = true; + static bool v_borders = true; + ImGui::Checkbox("horizontal", &h_borders); + ImGui::SameLine(); + ImGui::Checkbox("vertical", &v_borders); + ImGui::Columns(4, NULL, v_borders); + for (int i = 0; i < 4*3; i++) + { + if (h_borders && ImGui::GetColumnIndex() == 0) + ImGui::Separator(); + ImGui::Text("%c%c%c", 'a'+i, 'a'+i, 'a'+i); + ImGui::Text("Width %.2f\nOffset %.2f", ImGui::GetColumnWidth(), ImGui::GetColumnOffset()); + ImGui::NextColumn(); + } + ImGui::Columns(1); + if (h_borders) + ImGui::Separator(); + ImGui::TreePop(); + } + + // Scrolling columns + /* + if (ImGui::TreeNode("Vertical Scrolling")) + { + ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y)); + ImGui::Columns(3); + ImGui::Text("ID"); ImGui::NextColumn(); + ImGui::Text("Name"); ImGui::NextColumn(); + ImGui::Text("Path"); ImGui::NextColumn(); + ImGui::Columns(1); + ImGui::Separator(); + ImGui::EndChild(); + ImGui::BeginChild("##scrollingregion", ImVec2(0, 60)); + ImGui::Columns(3); + for (int i = 0; i < 10; i++) + { + ImGui::Text("%04d", i); ImGui::NextColumn(); + ImGui::Text("Foobar"); ImGui::NextColumn(); + ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn(); + } + ImGui::Columns(1); + ImGui::EndChild(); + ImGui::TreePop(); + } + */ + + if (ImGui::TreeNode("Horizontal Scrolling")) + { + ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f)); + ImGui::BeginChild("##ScrollingRegion", ImVec2(0, ImGui::GetFontSize() * 20), false, ImGuiWindowFlags_HorizontalScrollbar); + ImGui::Columns(10); + int ITEMS_COUNT = 2000; + ImGuiListClipper clipper(ITEMS_COUNT); // Also demonstrate using the clipper for large list + while (clipper.Step()) + { + for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) + for (int j = 0; j < 10; j++) + { + ImGui::Text("Line %d Column %d...", i, j); + ImGui::NextColumn(); + } + } + ImGui::Columns(1); + ImGui::EndChild(); + ImGui::TreePop(); + } + + bool node_open = ImGui::TreeNode("Tree within single cell"); + ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell. There's no storage of state per-cell."); + if (node_open) + { + ImGui::Columns(2, "tree items"); + ImGui::Separator(); + if (ImGui::TreeNode("Hello")) { ImGui::BulletText("Sailor"); ImGui::TreePop(); } ImGui::NextColumn(); + if (ImGui::TreeNode("Bonjour")) { ImGui::BulletText("Marin"); ImGui::TreePop(); } ImGui::NextColumn(); + ImGui::Columns(1); + ImGui::Separator(); + ImGui::TreePop(); + } + ImGui::PopID(); + } + + if (ImGui::CollapsingHeader("Filtering")) + { + static ImGuiTextFilter filter; + ImGui::Text("Filter usage:\n" + " \"\" display all lines\n" + " \"xxx\" display lines containing \"xxx\"\n" + " \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n" + " \"-xxx\" hide lines containing \"xxx\""); + filter.Draw(); + const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" }; + for (int i = 0; i < IM_ARRAYSIZE(lines); i++) + if (filter.PassFilter(lines[i])) + ImGui::BulletText("%s", lines[i]); + } + + if (ImGui::CollapsingHeader("Inputs, Navigation & Focus")) + { + ImGuiIO& io = ImGui::GetIO(); + + ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse); + ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard); + ImGui::Text("WantTextInput: %d", io.WantTextInput); + ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos); + ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible); + + ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor); + ImGui::SameLine(); ShowHelpMarker("Instruct ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something)."); + + ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad [beta]", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad); + ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard [beta]", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard); + ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos); + ImGui::SameLine(); ShowHelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos."); + ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange); + ImGui::SameLine(); ShowHelpMarker("Instruct back-end to not alter mouse cursor shape and visibility."); + ImGui::Checkbox("io.ConfigCursorBlink", &io.ConfigCursorBlink); + ImGui::SameLine(); ShowHelpMarker("Set to false to disable blinking cursor, for users who consider it distracting"); + ImGui::Checkbox("io.ConfigResizeWindowsFromEdges [beta]", &io.ConfigResizeWindowsFromEdges); + ImGui::SameLine(); ShowHelpMarker("Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback."); + + if (ImGui::TreeNode("Keyboard, Mouse & Navigation State")) + { + if (ImGui::IsMousePosValid()) + ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y); + else + ImGui::Text("Mouse pos: "); + ImGui::Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y); + ImGui::Text("Mouse down:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); } + ImGui::Text("Mouse clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } + ImGui::Text("Mouse dbl-clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } + ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } + ImGui::Text("Mouse wheel: %.1f", io.MouseWheel); + + ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]); } + ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } + ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } + ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); + + ImGui::Text("NavInputs down:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputs[i]); } + ImGui::Text("NavInputs pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f) { ImGui::SameLine(); ImGui::Text("[%d]", i); } + ImGui::Text("NavInputs duration:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputsDownDuration[i]); } + + ImGui::Button("Hovering me sets the\nkeyboard capture flag"); + if (ImGui::IsItemHovered()) + ImGui::CaptureKeyboardFromApp(true); + ImGui::SameLine(); + ImGui::Button("Holding me clears the\nthe keyboard capture flag"); + if (ImGui::IsItemActive()) + ImGui::CaptureKeyboardFromApp(false); + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Tabbing")) + { + ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields."); + static char buf[32] = "dummy"; + ImGui::InputText("1", buf, IM_ARRAYSIZE(buf)); + ImGui::InputText("2", buf, IM_ARRAYSIZE(buf)); + ImGui::InputText("3", buf, IM_ARRAYSIZE(buf)); + ImGui::PushAllowKeyboardFocus(false); + ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf)); + //ImGui::SameLine(); ShowHelperMarker("Use ImGui::PushAllowKeyboardFocus(bool)\nto disable tabbing through certain widgets."); + ImGui::PopAllowKeyboardFocus(); + ImGui::InputText("5", buf, IM_ARRAYSIZE(buf)); + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Focus from code")) + { + bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine(); + bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine(); + bool focus_3 = ImGui::Button("Focus on 3"); + int has_focus = 0; + static char buf[128] = "click on a button to set focus"; + + if (focus_1) ImGui::SetKeyboardFocusHere(); + ImGui::InputText("1", buf, IM_ARRAYSIZE(buf)); + if (ImGui::IsItemActive()) has_focus = 1; + + if (focus_2) ImGui::SetKeyboardFocusHere(); + ImGui::InputText("2", buf, IM_ARRAYSIZE(buf)); + if (ImGui::IsItemActive()) has_focus = 2; + + ImGui::PushAllowKeyboardFocus(false); + if (focus_3) ImGui::SetKeyboardFocusHere(); + ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf)); + if (ImGui::IsItemActive()) has_focus = 3; + ImGui::PopAllowKeyboardFocus(); + + if (has_focus) + ImGui::Text("Item with focus: %d", has_focus); + else + ImGui::Text("Item with focus: "); + + // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item + static float f3[3] = { 0.0f, 0.0f, 0.0f }; + int focus_ahead = -1; + if (ImGui::Button("Focus on X")) focus_ahead = 0; ImGui::SameLine(); + if (ImGui::Button("Focus on Y")) focus_ahead = 1; ImGui::SameLine(); + if (ImGui::Button("Focus on Z")) focus_ahead = 2; + if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead); + ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f); + + ImGui::TextWrapped("NB: Cursor & selection are preserved when refocusing last used item in code."); + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Dragging")) + { + ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget."); + for (int button = 0; button < 3; button++) + ImGui::Text("IsMouseDragging(%d):\n w/ default threshold: %d,\n w/ zero threshold: %d\n w/ large threshold: %d", + button, ImGui::IsMouseDragging(button), ImGui::IsMouseDragging(button, 0.0f), ImGui::IsMouseDragging(button, 20.0f)); + ImGui::Button("Drag Me"); + if (ImGui::IsItemActive()) + { + // Draw a line between the button and the mouse cursor + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + draw_list->PushClipRectFullScreen(); + draw_list->AddLine(io.MouseClickedPos[0], io.MousePos, ImGui::GetColorU32(ImGuiCol_Button), 4.0f); + draw_list->PopClipRect(); + + // Drag operations gets "unlocked" when the mouse has moved past a certain threshold (the default threshold is stored in io.MouseDragThreshold) + // You can request a lower or higher threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta() + ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f); + ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0); + ImVec2 mouse_delta = io.MouseDelta; + ImGui::SameLine(); ImGui::Text("Raw (%.1f, %.1f), WithLockThresold (%.1f, %.1f), MouseDelta (%.1f, %.1f)", value_raw.x, value_raw.y, value_with_lock_threshold.x, value_with_lock_threshold.y, mouse_delta.x, mouse_delta.y); + } + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Mouse cursors")) + { + const char* mouse_cursors_names[] = { "Arrow", "TextInput", "Move", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand" }; + IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT); + + ImGui::Text("Current mouse cursor = %d: %s", ImGui::GetMouseCursor(), mouse_cursors_names[ImGui::GetMouseCursor()]); + ImGui::Text("Hover to see mouse cursors:"); + ImGui::SameLine(); ShowHelpMarker("Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, otherwise your backend needs to handle it."); + for (int i = 0; i < ImGuiMouseCursor_COUNT; i++) + { + char label[32]; + sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]); + ImGui::Bullet(); ImGui::Selectable(label, false); + if (ImGui::IsItemHovered() || ImGui::IsItemFocused()) + ImGui::SetMouseCursor(i); + } + ImGui::TreePop(); + } + } + + // End of ShowDemoWindow() + ImGui::End(); +} + +// Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options. +// Here we use the simplified Combo() api that packs items into a single literal string. Useful for quick combo boxes where the choices are known locally. +bool ImGui::ShowStyleSelector(const char* label) +{ + static int style_idx = -1; + if (ImGui::Combo(label, &style_idx, "Classic\0Dark\0Light\0")) + { + switch (style_idx) + { + case 0: ImGui::StyleColorsClassic(); break; + case 1: ImGui::StyleColorsDark(); break; + case 2: ImGui::StyleColorsLight(); break; + } + return true; + } + return false; +} + +// Demo helper function to select among loaded fonts. +// Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one. +void ImGui::ShowFontSelector(const char* label) +{ + ImGuiIO& io = ImGui::GetIO(); + ImFont* font_current = ImGui::GetFont(); + if (ImGui::BeginCombo(label, font_current->GetDebugName())) + { + for (int n = 0; n < io.Fonts->Fonts.Size; n++) + if (ImGui::Selectable(io.Fonts->Fonts[n]->GetDebugName(), io.Fonts->Fonts[n] == font_current)) + io.FontDefault = io.Fonts->Fonts[n]; + ImGui::EndCombo(); + } + ImGui::SameLine(); + ShowHelpMarker( + "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n" + "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n" + "- Read FAQ and documentation in misc/fonts/ for more details.\n" + "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame()."); +} + +void ImGui::ShowStyleEditor(ImGuiStyle* ref) +{ + // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to an internally stored reference) + ImGuiStyle& style = ImGui::GetStyle(); + static ImGuiStyle ref_saved_style; + + // Default to using internal storage as reference + static bool init = true; + if (init && ref == NULL) + ref_saved_style = style; + init = false; + if (ref == NULL) + ref = &ref_saved_style; + + ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f); + + if (ImGui::ShowStyleSelector("Colors##Selector")) + ref_saved_style = style; + ImGui::ShowFontSelector("Fonts##Selector"); + + // Simplified Settings + if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f")) + style.GrabRounding = style.FrameRounding; // Make GrabRounding always the same value as FrameRounding + { bool window_border = (style.WindowBorderSize > 0.0f); if (ImGui::Checkbox("WindowBorder", &window_border)) style.WindowBorderSize = window_border ? 1.0f : 0.0f; } + ImGui::SameLine(); + { bool frame_border = (style.FrameBorderSize > 0.0f); if (ImGui::Checkbox("FrameBorder", &frame_border)) style.FrameBorderSize = frame_border ? 1.0f : 0.0f; } + ImGui::SameLine(); + { bool popup_border = (style.PopupBorderSize > 0.0f); if (ImGui::Checkbox("PopupBorder", &popup_border)) style.PopupBorderSize = popup_border ? 1.0f : 0.0f; } + + // Save/Revert button + if (ImGui::Button("Save Ref")) + *ref = ref_saved_style = style; + ImGui::SameLine(); + if (ImGui::Button("Revert Ref")) + style = *ref; + ImGui::SameLine(); + ShowHelpMarker("Save/Revert in local non-persistent storage. Default Colors definition are not affected. Use \"Export Colors\" below to save them somewhere."); + + if (ImGui::TreeNode("Rendering")) + { + ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines); ImGui::SameLine(); ShowHelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well."); + ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill); + ImGui::PushItemWidth(100); + ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, NULL, 2.0f); + if (style.CurveTessellationTol < 0.0f) style.CurveTessellationTol = 0.10f; + ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero. + ImGui::PopItemWidth(); + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Settings")) + { + ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f"); + ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 16.0f, "%.0f"); + ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f"); + ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f"); + ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f"); + ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f"); + ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f"); + ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f"); + ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f"); + ImGui::Text("BorderSize"); + ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f"); + ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f"); + ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f"); + ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f"); + ImGui::Text("Rounding"); + ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 14.0f, "%.0f"); + ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 16.0f, "%.0f"); + ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"); + ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f"); + ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f"); + ImGui::Text("Alignment"); + ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f"); + ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); ShowHelpMarker("Alignment applies when a button is larger than its text content."); + ImGui::Text("Safe Area Padding"); ImGui::SameLine(); ShowHelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured)."); + ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f"); + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Colors")) + { + static int output_dest = 0; + static bool output_only_modified = true; + if (ImGui::Button("Export Unsaved")) + { + if (output_dest == 0) + ImGui::LogToClipboard(); + else + ImGui::LogToTTY(); + ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE); + for (int i = 0; i < ImGuiCol_COUNT; i++) + { + const ImVec4& col = style.Colors[i]; + const char* name = ImGui::GetStyleColorName(i); + if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0) + ImGui::LogText("colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE, name, 23-(int)strlen(name), "", col.x, col.y, col.z, col.w); + } + ImGui::LogFinish(); + } + ImGui::SameLine(); ImGui::PushItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0"); ImGui::PopItemWidth(); + ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified); + + ImGui::Text("Tip: Left-click on colored square to open color picker,\nRight-click to open edit options menu."); + + static ImGuiTextFilter filter; + filter.Draw("Filter colors", 200); + + static ImGuiColorEditFlags alpha_flags = 0; + ImGui::RadioButton("Opaque", &alpha_flags, 0); ImGui::SameLine(); + ImGui::RadioButton("Alpha", &alpha_flags, ImGuiColorEditFlags_AlphaPreview); ImGui::SameLine(); + ImGui::RadioButton("Both", &alpha_flags, ImGuiColorEditFlags_AlphaPreviewHalf); + + ImGui::BeginChild("#colors", ImVec2(0, 300), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened); + ImGui::PushItemWidth(-160); + for (int i = 0; i < ImGuiCol_COUNT; i++) + { + const char* name = ImGui::GetStyleColorName(i); + if (!filter.PassFilter(name)) + continue; + ImGui::PushID(i); + ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags); + if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0) + { + // Tips: in a real user application, you may want to merge and use an icon font into the main font, so instead of "Save"/"Revert" you'd use icons. + // Read the FAQ and misc/fonts/README.txt about using icon fonts. It's really easy and super convenient! + ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i]; + ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) style.Colors[i] = ref->Colors[i]; + } + ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); + ImGui::TextUnformatted(name); + ImGui::PopID(); + } + ImGui::PopItemWidth(); + ImGui::EndChild(); + + ImGui::TreePop(); + } + + bool fonts_opened = ImGui::TreeNode("Fonts", "Fonts (%d)", ImGui::GetIO().Fonts->Fonts.Size); + if (fonts_opened) + { + ImFontAtlas* atlas = ImGui::GetIO().Fonts; + if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight)) + { + ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128)); + ImGui::TreePop(); + } + ImGui::PushItemWidth(100); + for (int i = 0; i < atlas->Fonts.Size; i++) + { + ImFont* font = atlas->Fonts[i]; + ImGui::PushID(font); + bool font_details_opened = ImGui::TreeNode(font, "Font %d: \'%s\', %.2f px, %d glyphs", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size); + ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) ImGui::GetIO().FontDefault = font; + if (font_details_opened) + { + ImGui::PushFont(font); + ImGui::Text("The quick brown fox jumps over the lazy dog"); + ImGui::PopFont(); + ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); // Scale only this font + ImGui::SameLine(); ShowHelpMarker("Note than the default embedded font is NOT meant to be scaled.\n\nFont are currently rendered into bitmaps at a given size at the time of building the atlas. You may oversample them to get some flexibility with scaling. You can also render at multiple sizes and select which one to use at runtime.\n\n(Glimmer of hope: the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)"); + ImGui::InputFloat("Font offset", &font->DisplayOffset.y, 1, 1, "%.0f"); + ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent); + ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar); + ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)sqrtf((float)font->MetricsTotalSurface), (int)sqrtf((float)font->MetricsTotalSurface)); + for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) + if (ImFontConfig* cfg = &font->ConfigData[config_i]) + ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH); + if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size)) + { + // Display all glyphs of the fonts in separate pages of 256 characters + for (int base = 0; base < 0x10000; base += 256) + { + int count = 0; + for (int n = 0; n < 256; n++) + count += font->FindGlyphNoFallback((ImWchar)(base + n)) ? 1 : 0; + if (count > 0 && ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base+255, count, count > 1 ? "glyphs" : "glyph")) + { + float cell_size = font->FontSize * 1; + float cell_spacing = style.ItemSpacing.y; + ImVec2 base_pos = ImGui::GetCursorScreenPos(); + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + for (int n = 0; n < 256; n++) + { + ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing)); + ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size); + const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base+n)); + draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255,255,255,100) : IM_COL32(255,255,255,50)); + if (glyph) + font->RenderChar(draw_list, cell_size, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), (ImWchar)(base+n)); // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions available to generate a string. + if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2)) + { + ImGui::BeginTooltip(); + ImGui::Text("Codepoint: U+%04X", base+n); + ImGui::Separator(); + ImGui::Text("AdvanceX: %.1f", glyph->AdvanceX); + ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1); + ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1); + ImGui::EndTooltip(); + } + } + ImGui::Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16)); + ImGui::TreePop(); + } + } + ImGui::TreePop(); + } + ImGui::TreePop(); + } + ImGui::PopID(); + } + static float window_scale = 1.0f; + ImGui::DragFloat("this window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale only this window + ImGui::DragFloat("global scale", &ImGui::GetIO().FontGlobalScale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale everything + ImGui::PopItemWidth(); + ImGui::SetWindowFontScale(window_scale); + ImGui::TreePop(); + } + + ImGui::PopItemWidth(); +} + +//----------------------------------------------------------------------------- +// EXAMPLE APP CODE: MAIN MENU BAR +//----------------------------------------------------------------------------- + +// Demonstrate creating a fullscreen menu bar and populating it. +static void ShowExampleAppMainMenuBar() +{ + if (ImGui::BeginMainMenuBar()) + { + if (ImGui::BeginMenu("File")) + { + ShowExampleMenuFile(); + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Edit")) + { + if (ImGui::MenuItem("Undo", "CTRL+Z")) {} + if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item + ImGui::Separator(); + if (ImGui::MenuItem("Cut", "CTRL+X")) {} + if (ImGui::MenuItem("Copy", "CTRL+C")) {} + if (ImGui::MenuItem("Paste", "CTRL+V")) {} + ImGui::EndMenu(); + } + ImGui::EndMainMenuBar(); + } +} + +static void ShowExampleMenuFile() +{ + ImGui::MenuItem("(dummy menu)", NULL, false, false); + if (ImGui::MenuItem("New")) {} + if (ImGui::MenuItem("Open", "Ctrl+O")) {} + if (ImGui::BeginMenu("Open Recent")) + { + ImGui::MenuItem("fish_hat.c"); + ImGui::MenuItem("fish_hat.inl"); + ImGui::MenuItem("fish_hat.h"); + if (ImGui::BeginMenu("More..")) + { + ImGui::MenuItem("Hello"); + ImGui::MenuItem("Sailor"); + if (ImGui::BeginMenu("Recurse..")) + { + ShowExampleMenuFile(); + ImGui::EndMenu(); + } + ImGui::EndMenu(); + } + ImGui::EndMenu(); + } + if (ImGui::MenuItem("Save", "Ctrl+S")) {} + if (ImGui::MenuItem("Save As..")) {} + ImGui::Separator(); + if (ImGui::BeginMenu("Options")) + { + static bool enabled = true; + ImGui::MenuItem("Enabled", "", &enabled); + ImGui::BeginChild("child", ImVec2(0, 60), true); + for (int i = 0; i < 10; i++) + ImGui::Text("Scrolling Text %d", i); + ImGui::EndChild(); + static float f = 0.5f; + static int n = 0; + static bool b = true; + ImGui::SliderFloat("Value", &f, 0.0f, 1.0f); + ImGui::InputFloat("Input", &f, 0.1f); + ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0"); + ImGui::Checkbox("Check", &b); + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Colors")) + { + float sz = ImGui::GetTextLineHeight(); + for (int i = 0; i < ImGuiCol_COUNT; i++) + { + const char* name = ImGui::GetStyleColorName((ImGuiCol)i); + ImVec2 p = ImGui::GetCursorScreenPos(); + ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x+sz, p.y+sz), ImGui::GetColorU32((ImGuiCol)i)); + ImGui::Dummy(ImVec2(sz, sz)); + ImGui::SameLine(); + ImGui::MenuItem(name); + } + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Disabled", false)) // Disabled + { + IM_ASSERT(0); + } + if (ImGui::MenuItem("Checked", NULL, true)) {} + if (ImGui::MenuItem("Quit", "Alt+F4")) {} +} + +//----------------------------------------------------------------------------- +// EXAMPLE APP CODE: CONSOLE +//----------------------------------------------------------------------------- + +// Demonstrating creating a simple console window, with scrolling, filtering, completion and history. +// For the console example, here we are using a more C++ like approach of declaring a class to hold the data and the functions. +struct ExampleAppConsole +{ + char InputBuf[256]; + ImVector Items; + bool ScrollToBottom; + ImVector History; + int HistoryPos; // -1: new line, 0..History.Size-1 browsing history. + ImVector Commands; + + ExampleAppConsole() + { + ClearLog(); + memset(InputBuf, 0, sizeof(InputBuf)); + HistoryPos = -1; + Commands.push_back("HELP"); + Commands.push_back("HISTORY"); + Commands.push_back("CLEAR"); + Commands.push_back("CLASSIFY"); // "classify" is only here to provide an example of "C"+[tab] completing to "CL" and displaying matches. + AddLog("Welcome to Dear ImGui!"); + } + ~ExampleAppConsole() + { + ClearLog(); + for (int i = 0; i < History.Size; i++) + free(History[i]); + } + + // Portable helpers + static int Stricmp(const char* str1, const char* str2) { int d; while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } return d; } + static int Strnicmp(const char* str1, const char* str2, int n) { int d = 0; while (n > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; n--; } return d; } + static char* Strdup(const char *str) { size_t len = strlen(str) + 1; void* buff = malloc(len); return (char*)memcpy(buff, (const void*)str, len); } + static void Strtrim(char* str) { char* str_end = str + strlen(str); while (str_end > str && str_end[-1] == ' ') str_end--; *str_end = 0; } + + void ClearLog() + { + for (int i = 0; i < Items.Size; i++) + free(Items[i]); + Items.clear(); + ScrollToBottom = true; + } + + void AddLog(const char* fmt, ...) IM_FMTARGS(2) + { + // FIXME-OPT + char buf[1024]; + va_list args; + va_start(args, fmt); + vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args); + buf[IM_ARRAYSIZE(buf)-1] = 0; + va_end(args); + Items.push_back(Strdup(buf)); + ScrollToBottom = true; + } + + void Draw(const char* title, bool* p_open) + { + ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver); + if (!ImGui::Begin(title, p_open)) + { + ImGui::End(); + return; + } + + // As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar. So e.g. IsItemHovered() will return true when hovering the title bar. + // Here we create a context menu only available from the title bar. + if (ImGui::BeginPopupContextItem()) + { + if (ImGui::MenuItem("Close Console")) + *p_open = false; + ImGui::EndPopup(); + } + + ImGui::TextWrapped("This example implements a console with basic coloring, completion and history. A more elaborate implementation may want to store entries along with extra data such as timestamp, emitter, etc."); + ImGui::TextWrapped("Enter 'HELP' for help, press TAB to use text completion."); + + // TODO: display items starting from the bottom + + if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine(); + if (ImGui::SmallButton("Add Dummy Error")) { AddLog("[error] something went wrong"); } ImGui::SameLine(); + if (ImGui::SmallButton("Clear")) { ClearLog(); } ImGui::SameLine(); + bool copy_to_clipboard = ImGui::SmallButton("Copy"); ImGui::SameLine(); + if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom = true; + //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); } + + ImGui::Separator(); + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0)); + static ImGuiTextFilter filter; + filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180); + ImGui::PopStyleVar(); + ImGui::Separator(); + + const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); // 1 separator, 1 input text + ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), false, ImGuiWindowFlags_HorizontalScrollbar); // Leave room for 1 separator + 1 InputText + if (ImGui::BeginPopupContextWindow()) + { + if (ImGui::Selectable("Clear")) ClearLog(); + ImGui::EndPopup(); + } + + // Display every line as a separate entry so we can change their color or add custom widgets. If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end()); + // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping to only process visible items. + // You can seek and display only the lines that are visible using the ImGuiListClipper helper, if your elements are evenly spaced and you have cheap random access to the elements. + // To use the clipper we could replace the 'for (int i = 0; i < Items.Size; i++)' loop with: + // ImGuiListClipper clipper(Items.Size); + // while (clipper.Step()) + // for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) + // However, note that you can not use this code as is if a filter is active because it breaks the 'cheap random-access' property. We would need random-access on the post-filtered list. + // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices that passed the filtering test, recomputing this array when user changes the filter, + // and appending newly elements as they are inserted. This is left as a task to the user until we can manage to improve this example code! + // If your items are of variable size you may want to implement code similar to what ImGuiListClipper does. Or split your data into fixed height items to allow random-seeking into your list. + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing + if (copy_to_clipboard) + ImGui::LogToClipboard(); + ImVec4 col_default_text = ImGui::GetStyleColorVec4(ImGuiCol_Text); + for (int i = 0; i < Items.Size; i++) + { + const char* item = Items[i]; + if (!filter.PassFilter(item)) + continue; + ImVec4 col = col_default_text; + if (strstr(item, "[error]")) col = ImColor(1.0f,0.4f,0.4f,1.0f); + else if (strncmp(item, "# ", 2) == 0) col = ImColor(1.0f,0.78f,0.58f,1.0f); + ImGui::PushStyleColor(ImGuiCol_Text, col); + ImGui::TextUnformatted(item); + ImGui::PopStyleColor(); + } + if (copy_to_clipboard) + ImGui::LogFinish(); + if (ScrollToBottom) + ImGui::SetScrollHere(1.0f); + ScrollToBottom = false; + ImGui::PopStyleVar(); + ImGui::EndChild(); + ImGui::Separator(); + + // Command-line + bool reclaim_focus = false; + if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this)) + { + Strtrim(InputBuf); + if (InputBuf[0]) + ExecCommand(InputBuf); + strcpy(InputBuf, ""); + reclaim_focus = true; + } + + // Demonstrate keeping focus on the input box + ImGui::SetItemDefaultFocus(); + if (reclaim_focus) + ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget + + ImGui::End(); + } + + void ExecCommand(const char* command_line) + { + AddLog("# %s\n", command_line); + + // Insert into history. First find match and delete it so it can be pushed to the back. This isn't trying to be smart or optimal. + HistoryPos = -1; + for (int i = History.Size-1; i >= 0; i--) + if (Stricmp(History[i], command_line) == 0) + { + free(History[i]); + History.erase(History.begin() + i); + break; + } + History.push_back(Strdup(command_line)); + + // Process command + if (Stricmp(command_line, "CLEAR") == 0) + { + ClearLog(); + } + else if (Stricmp(command_line, "HELP") == 0) + { + AddLog("Commands:"); + for (int i = 0; i < Commands.Size; i++) + AddLog("- %s", Commands[i]); + } + else if (Stricmp(command_line, "HISTORY") == 0) + { + int first = History.Size - 10; + for (int i = first > 0 ? first : 0; i < History.Size; i++) + AddLog("%3d: %s\n", i, History[i]); + } + else + { + AddLog("Unknown command: '%s'\n", command_line); + } + } + + static int TextEditCallbackStub(ImGuiTextEditCallbackData* data) // In C++11 you are better off using lambdas for this sort of forwarding callbacks + { + ExampleAppConsole* console = (ExampleAppConsole*)data->UserData; + return console->TextEditCallback(data); + } + + int TextEditCallback(ImGuiTextEditCallbackData* data) + { + //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd); + switch (data->EventFlag) + { + case ImGuiInputTextFlags_CallbackCompletion: + { + // Example of TEXT COMPLETION + + // Locate beginning of current word + const char* word_end = data->Buf + data->CursorPos; + const char* word_start = word_end; + while (word_start > data->Buf) + { + const char c = word_start[-1]; + if (c == ' ' || c == '\t' || c == ',' || c == ';') + break; + word_start--; + } + + // Build a list of candidates + ImVector candidates; + for (int i = 0; i < Commands.Size; i++) + if (Strnicmp(Commands[i], word_start, (int)(word_end-word_start)) == 0) + candidates.push_back(Commands[i]); + + if (candidates.Size == 0) + { + // No match + AddLog("No match for \"%.*s\"!\n", (int)(word_end-word_start), word_start); + } + else if (candidates.Size == 1) + { + // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing + data->DeleteChars((int)(word_start-data->Buf), (int)(word_end-word_start)); + data->InsertChars(data->CursorPos, candidates[0]); + data->InsertChars(data->CursorPos, " "); + } + else + { + // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY" + int match_len = (int)(word_end - word_start); + for (;;) + { + int c = 0; + bool all_candidates_matches = true; + for (int i = 0; i < candidates.Size && all_candidates_matches; i++) + if (i == 0) + c = toupper(candidates[i][match_len]); + else if (c == 0 || c != toupper(candidates[i][match_len])) + all_candidates_matches = false; + if (!all_candidates_matches) + break; + match_len++; + } + + if (match_len > 0) + { + data->DeleteChars((int)(word_start - data->Buf), (int)(word_end-word_start)); + data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len); + } + + // List matches + AddLog("Possible matches:\n"); + for (int i = 0; i < candidates.Size; i++) + AddLog("- %s\n", candidates[i]); + } + + break; + } + case ImGuiInputTextFlags_CallbackHistory: + { + // Example of HISTORY + const int prev_history_pos = HistoryPos; + if (data->EventKey == ImGuiKey_UpArrow) + { + if (HistoryPos == -1) + HistoryPos = History.Size - 1; + else if (HistoryPos > 0) + HistoryPos--; + } + else if (data->EventKey == ImGuiKey_DownArrow) + { + if (HistoryPos != -1) + if (++HistoryPos >= History.Size) + HistoryPos = -1; + } + + // A better implementation would preserve the data on the current input line along with cursor position. + if (prev_history_pos != HistoryPos) + { + data->CursorPos = data->SelectionStart = data->SelectionEnd = data->BufTextLen = (int)snprintf(data->Buf, (size_t)data->BufSize, "%s", (HistoryPos >= 0) ? History[HistoryPos] : ""); + data->BufDirty = true; + } + } + } + return 0; + } +}; + +static void ShowExampleAppConsole(bool* p_open) +{ + static ExampleAppConsole console; + console.Draw("Example: Console", p_open); +} + +//----------------------------------------------------------------------------- +// EXAMPLE APP CODE: LOG +//----------------------------------------------------------------------------- + +// Usage: +// static ExampleAppLog my_log; +// my_log.AddLog("Hello %d world\n", 123); +// my_log.Draw("title"); +struct ExampleAppLog +{ + ImGuiTextBuffer Buf; + ImGuiTextFilter Filter; + ImVector LineOffsets; // Index to lines offset + bool ScrollToBottom; + + void Clear() { Buf.clear(); LineOffsets.clear(); } + + void AddLog(const char* fmt, ...) IM_FMTARGS(2) + { + int old_size = Buf.size(); + va_list args; + va_start(args, fmt); + Buf.appendfv(fmt, args); + va_end(args); + for (int new_size = Buf.size(); old_size < new_size; old_size++) + if (Buf[old_size] == '\n') + LineOffsets.push_back(old_size); + ScrollToBottom = true; + } + + void Draw(const char* title, bool* p_open = NULL) + { + ImGui::SetNextWindowSize(ImVec2(500,400), ImGuiCond_FirstUseEver); + if (!ImGui::Begin(title, p_open)) + { + ImGui::End(); + return; + } + if (ImGui::Button("Clear")) Clear(); + ImGui::SameLine(); + bool copy = ImGui::Button("Copy"); + ImGui::SameLine(); + Filter.Draw("Filter", -100.0f); + ImGui::Separator(); + ImGui::BeginChild("scrolling", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar); + if (copy) ImGui::LogToClipboard(); + + if (Filter.IsActive()) + { + const char* buf_begin = Buf.begin(); + const char* line = buf_begin; + for (int line_no = 0; line != NULL; line_no++) + { + const char* line_end = (line_no < LineOffsets.Size) ? buf_begin + LineOffsets[line_no] : NULL; + if (Filter.PassFilter(line, line_end)) + ImGui::TextUnformatted(line, line_end); + line = line_end && line_end[1] ? line_end + 1 : NULL; + } + } + else + { + ImGui::TextUnformatted(Buf.begin()); + } + + if (ScrollToBottom) + ImGui::SetScrollHere(1.0f); + ScrollToBottom = false; + ImGui::EndChild(); + ImGui::End(); + } +}; + +// Demonstrate creating a simple log window with basic filtering. +static void ShowExampleAppLog(bool* p_open) +{ + static ExampleAppLog log; + + // Demo: add random items (unless Ctrl is held) + static double last_time = -1.0; + double time = ImGui::GetTime(); + if (time - last_time >= 0.20f && !ImGui::GetIO().KeyCtrl) + { + const char* random_words[] = { "system", "info", "warning", "error", "fatal", "notice", "log" }; + log.AddLog("[%s] Hello, time is %.1f, frame count is %d\n", random_words[rand() % IM_ARRAYSIZE(random_words)], time, ImGui::GetFrameCount()); + last_time = time; + } + + log.Draw("Example: Log", p_open); +} + +//----------------------------------------------------------------------------- +// EXAMPLE APP CODE: SIMPLE LAYOUT +//----------------------------------------------------------------------------- + +// Demonstrate create a window with multiple child windows. +static void ShowExampleAppLayout(bool* p_open) +{ + ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver); + if (ImGui::Begin("Example: Layout", p_open, ImGuiWindowFlags_MenuBar)) + { + if (ImGui::BeginMenuBar()) + { + if (ImGui::BeginMenu("File")) + { + if (ImGui::MenuItem("Close")) *p_open = false; + ImGui::EndMenu(); + } + ImGui::EndMenuBar(); + } + + // left + static int selected = 0; + ImGui::BeginChild("left pane", ImVec2(150, 0), true); + for (int i = 0; i < 100; i++) + { + char label[128]; + sprintf(label, "MyObject %d", i); + if (ImGui::Selectable(label, selected == i)) + selected = i; + } + ImGui::EndChild(); + ImGui::SameLine(); + + // right + ImGui::BeginGroup(); + ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us + ImGui::Text("MyObject: %d", selected); + ImGui::Separator(); + ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "); + ImGui::EndChild(); + if (ImGui::Button("Revert")) {} + ImGui::SameLine(); + if (ImGui::Button("Save")) {} + ImGui::EndGroup(); + } + ImGui::End(); +} + +//----------------------------------------------------------------------------- +// EXAMPLE APP CODE: PROPERTY EDITOR +//----------------------------------------------------------------------------- + +// Demonstrate create a simple property editor. +static void ShowExampleAppPropertyEditor(bool* p_open) +{ + ImGui::SetNextWindowSize(ImVec2(430,450), ImGuiCond_FirstUseEver); + if (!ImGui::Begin("Example: Property editor", p_open)) + { + ImGui::End(); + return; + } + + ShowHelpMarker("This example shows how you may implement a property editor using two columns.\nAll objects/fields data are dummies here.\nRemember that in many simple cases, you can use ImGui::SameLine(xxx) to position\nyour cursor horizontally instead of using the Columns() API."); + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2,2)); + ImGui::Columns(2); + ImGui::Separator(); + + struct funcs + { + static void ShowDummyObject(const char* prefix, int uid) + { + ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID. + ImGui::AlignTextToFramePadding(); // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high. + bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid); + ImGui::NextColumn(); + ImGui::AlignTextToFramePadding(); + ImGui::Text("my sailor is rich"); + ImGui::NextColumn(); + if (node_open) + { + static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f }; + for (int i = 0; i < 8; i++) + { + ImGui::PushID(i); // Use field index as identifier. + if (i < 2) + { + ShowDummyObject("Child", 424242); + } + else + { + // Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well) + ImGui::AlignTextToFramePadding(); + ImGui::TreeNodeEx("Field", ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Bullet, "Field_%d", i); + ImGui::NextColumn(); + ImGui::PushItemWidth(-1); + if (i >= 5) + ImGui::InputFloat("##value", &dummy_members[i], 1.0f); + else + ImGui::DragFloat("##value", &dummy_members[i], 0.01f); + ImGui::PopItemWidth(); + ImGui::NextColumn(); + } + ImGui::PopID(); + } + ImGui::TreePop(); + } + ImGui::PopID(); + } + }; + + // Iterate dummy objects with dummy members (all the same data) + for (int obj_i = 0; obj_i < 3; obj_i++) + funcs::ShowDummyObject("Object", obj_i); + + ImGui::Columns(1); + ImGui::Separator(); + ImGui::PopStyleVar(); + ImGui::End(); +} + +//----------------------------------------------------------------------------- +// EXAMPLE APP CODE: LONG TEXT +//----------------------------------------------------------------------------- + +// Demonstrate/test rendering huge amount of text, and the incidence of clipping. +static void ShowExampleAppLongText(bool* p_open) +{ + ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver); + if (!ImGui::Begin("Example: Long text display", p_open)) + { + ImGui::End(); + return; + } + + static int test_type = 0; + static ImGuiTextBuffer log; + static int lines = 0; + ImGui::Text("Printing unusually long amount of text."); + ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped (slow)\0"); + ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size()); + if (ImGui::Button("Clear")) { log.clear(); lines = 0; } + ImGui::SameLine(); + if (ImGui::Button("Add 1000 lines")) + { + for (int i = 0; i < 1000; i++) + log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines+i); + lines += 1000; + } + ImGui::BeginChild("Log"); + switch (test_type) + { + case 0: + // Single call to TextUnformatted() with a big buffer + ImGui::TextUnformatted(log.begin(), log.end()); + break; + case 1: + { + // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper. + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0)); + ImGuiListClipper clipper(lines); + while (clipper.Step()) + for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) + ImGui::Text("%i The quick brown fox jumps over the lazy dog", i); + ImGui::PopStyleVar(); + break; + } + case 2: + // Multiple calls to Text(), not clipped (slow) + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0)); + for (int i = 0; i < lines; i++) + ImGui::Text("%i The quick brown fox jumps over the lazy dog", i); + ImGui::PopStyleVar(); + break; + } + ImGui::EndChild(); + ImGui::End(); +} + +//----------------------------------------------------------------------------- +// EXAMPLE APP CODE: AUTO RESIZE +//----------------------------------------------------------------------------- + +// Demonstrate creating a window which gets auto-resized according to its content. +static void ShowExampleAppAutoResize(bool* p_open) +{ + if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize)) + { + ImGui::End(); + return; + } + + static int lines = 10; + ImGui::Text("Window will resize every-frame to the size of its content.\nNote that you probably don't want to query the window size to\noutput your content because that would create a feedback loop."); + ImGui::SliderInt("Number of lines", &lines, 1, 20); + for (int i = 0; i < lines; i++) + ImGui::Text("%*sThis is line %d", i * 4, "", i); // Pad with space to extend size horizontally + ImGui::End(); +} + +//----------------------------------------------------------------------------- +// EXAMPLE APP CODE: CONSTRAINED RESIZE +//----------------------------------------------------------------------------- + +// Demonstrate creating a window with custom resize constraints. +static void ShowExampleAppConstrainedResize(bool* p_open) +{ + struct CustomConstraints // Helper functions to demonstrate programmatic constraints + { + static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); } + static void Step(ImGuiSizeCallbackData* data) { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); } + }; + + static bool auto_resize = false; + static int type = 0; + static int display_lines = 10; + if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Vertical only + if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Horizontal only + if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100 + if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1), ImVec2(500, -1)); // Width 400-500 + if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400), ImVec2(-1, 500)); // Height 400-500 + if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square + if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);// Fixed Step + + ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0; + if (ImGui::Begin("Example: Constrained Resize", p_open, flags)) + { + const char* desc[] = + { + "Resize vertical only", + "Resize horizontal only", + "Width > 100, Height > 100", + "Width 400-500", + "Height 400-500", + "Custom: Always Square", + "Custom: Fixed Steps (100)", + }; + if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine(); + if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine(); + if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); } + ImGui::PushItemWidth(200); + ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc)); + ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100); + ImGui::PopItemWidth(); + ImGui::Checkbox("Auto-resize", &auto_resize); + for (int i = 0; i < display_lines; i++) + ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, ""); + } + ImGui::End(); +} + +//----------------------------------------------------------------------------- +// EXAMPLE APP CODE: SIMPLE OVERLAY +//----------------------------------------------------------------------------- + +// Demonstrate creating a simple static window with no decoration + a context-menu to choose which corner of the screen to use. +static void ShowExampleAppSimpleOverlay(bool* p_open) +{ + const float DISTANCE = 10.0f; + static int corner = 0; + ImVec2 window_pos = ImVec2((corner & 1) ? ImGui::GetIO().DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? ImGui::GetIO().DisplaySize.y - DISTANCE : DISTANCE); + ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f); + if (corner != -1) + ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot); + ImGui::SetNextWindowBgAlpha(0.3f); // Transparent background + if (ImGui::Begin("Example: Simple Overlay", p_open, (corner != -1 ? ImGuiWindowFlags_NoMove : 0) | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) + { + ImGui::Text("Simple overlay\n" "in the corner of the screen.\n" "(right-click to change position)"); + ImGui::Separator(); + if (ImGui::IsMousePosValid()) + ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y); + else + ImGui::Text("Mouse Position: "); + if (ImGui::BeginPopupContextWindow()) + { + if (ImGui::MenuItem("Custom", NULL, corner == -1)) corner = -1; + if (ImGui::MenuItem("Top-left", NULL, corner == 0)) corner = 0; + if (ImGui::MenuItem("Top-right", NULL, corner == 1)) corner = 1; + if (ImGui::MenuItem("Bottom-left", NULL, corner == 2)) corner = 2; + if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3; + if (p_open && ImGui::MenuItem("Close")) *p_open = false; + ImGui::EndPopup(); + } + } + ImGui::End(); +} + +//----------------------------------------------------------------------------- +// EXAMPLE APP CODE: WINDOW TITLES +//----------------------------------------------------------------------------- + +// Demonstrate using "##" and "###" in identifiers to manipulate ID generation. +// This apply to all regular items as well. Read FAQ section "How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs." for details. +static void ShowExampleAppWindowTitles(bool*) +{ + // By default, Windows are uniquely identified by their title. + // You can use the "##" and "###" markers to manipulate the display/ID. + + // Using "##" to display same title but have unique identifier. + ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver); + ImGui::Begin("Same title as another window##1"); + ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique."); + ImGui::End(); + + ImGui::SetNextWindowPos(ImVec2(100, 200), ImGuiCond_FirstUseEver); + ImGui::Begin("Same title as another window##2"); + ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique."); + ImGui::End(); + + // Using "###" to display a changing title but keep a static identifier "AnimatedTitle" + char buf[128]; + sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount()); + ImGui::SetNextWindowPos(ImVec2(100, 300), ImGuiCond_FirstUseEver); + ImGui::Begin(buf); + ImGui::Text("This window has a changing title."); + ImGui::End(); +} + +//----------------------------------------------------------------------------- +// EXAMPLE APP CODE: CUSTOM RENDERING +//----------------------------------------------------------------------------- + +// Demonstrate using the low-level ImDrawList to draw custom shapes. +static void ShowExampleAppCustomRendering(bool* p_open) +{ + ImGui::SetNextWindowSize(ImVec2(350, 560), ImGuiCond_FirstUseEver); + if (!ImGui::Begin("Example: Custom rendering", p_open)) + { + ImGui::End(); + return; + } + + // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of overloaded operators, etc. + // Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your types and ImVec2/ImVec4. + // ImGui defines overloaded operators but they are internal to imgui.cpp and not exposed outside (to avoid messing with your types) + // In this example we are not using the maths operators! + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + + // Primitives + ImGui::Text("Primitives"); + static float sz = 36.0f; + static float thickness = 4.0f; + static ImVec4 col = ImVec4(1.0f, 1.0f, 0.4f, 1.0f); + ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f"); + ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f"); + ImGui::ColorEdit3("Color", &col.x); + { + const ImVec2 p = ImGui::GetCursorScreenPos(); + const ImU32 col32 = ImColor(col); + float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f; + for (int n = 0; n < 2; n++) + { + float curr_thickness = (n == 0) ? 1.0f : thickness; + draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 20, curr_thickness); x += sz+spacing; + draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 0.0f, ImDrawCornerFlags_All, curr_thickness); x += sz+spacing; + draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_All, curr_thickness); x += sz+spacing; + draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight, curr_thickness); x += sz+spacing; + draw_list->AddTriangle(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32, curr_thickness); x += sz+spacing; + draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y ), col32, curr_thickness); x += sz+spacing; // Horizontal line (note: drawing a filled rectangle will be faster!) + draw_list->AddLine(ImVec2(x, y), ImVec2(x, y+sz), col32, curr_thickness); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!) + draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, curr_thickness); x += sz+spacing; // Diagonal line + draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x+sz*1.3f,y+sz*0.3f), ImVec2(x+sz-sz*1.3f,y+sz-sz*0.3f), ImVec2(x+sz, y+sz), col32, curr_thickness); + x = p.x + 4; + y += sz+spacing; + } + draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 32); x += sz+spacing; + draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32); x += sz+spacing; + draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f); x += sz+spacing; + draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight); x += sz+spacing; + draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32); x += sz+spacing; + draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+thickness), col32); x += sz+spacing; // Horizontal line (faster than AddLine, but only handle integer thickness) + draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+thickness, y+sz), col32); x += spacing+spacing; // Vertical line (faster than AddLine, but only handle integer thickness) + draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+1, y+1), col32); x += sz; // Pixel (faster than AddLine) + draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x+sz, y+sz), IM_COL32(0,0,0,255), IM_COL32(255,0,0,255), IM_COL32(255,255,0,255), IM_COL32(0,255,0,255)); + ImGui::Dummy(ImVec2((sz+spacing)*8, (sz+spacing)*3)); + } + ImGui::Separator(); + { + static ImVector points; + static bool adding_line = false; + ImGui::Text("Canvas example"); + if (ImGui::Button("Clear")) points.clear(); + if (points.Size >= 2) { ImGui::SameLine(); if (ImGui::Button("Undo")) { points.pop_back(); points.pop_back(); } } + ImGui::Text("Left-click and drag to add lines,\nRight-click to undo"); + + // Here we are using InvisibleButton() as a convenience to 1) advance the cursor and 2) allows us to use IsItemHovered() + // But you can also draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() and SetCursorPos(). + // If you only use the ImDrawList API, you can notify the owner window of its extends by using SetCursorPos(max). + ImVec2 canvas_pos = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates! + ImVec2 canvas_size = ImGui::GetContentRegionAvail(); // Resize canvas to what's available + if (canvas_size.x < 50.0f) canvas_size.x = 50.0f; + if (canvas_size.y < 50.0f) canvas_size.y = 50.0f; + draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(50, 50, 50, 255), IM_COL32(50, 50, 60, 255), IM_COL32(60, 60, 70, 255), IM_COL32(50, 50, 60, 255)); + draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(255, 255, 255, 255)); + + bool adding_preview = false; + ImGui::InvisibleButton("canvas", canvas_size); + ImVec2 mouse_pos_in_canvas = ImVec2(ImGui::GetIO().MousePos.x - canvas_pos.x, ImGui::GetIO().MousePos.y - canvas_pos.y); + if (adding_line) + { + adding_preview = true; + points.push_back(mouse_pos_in_canvas); + if (!ImGui::IsMouseDown(0)) + adding_line = adding_preview = false; + } + if (ImGui::IsItemHovered()) + { + if (!adding_line && ImGui::IsMouseClicked(0)) + { + points.push_back(mouse_pos_in_canvas); + adding_line = true; + } + if (ImGui::IsMouseClicked(1) && !points.empty()) + { + adding_line = adding_preview = false; + points.pop_back(); + points.pop_back(); + } + } + draw_list->PushClipRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), true); // clip lines within the canvas (if we resize it, etc.) + for (int i = 0; i < points.Size - 1; i += 2) + draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), ImVec2(canvas_pos.x + points[i + 1].x, canvas_pos.y + points[i + 1].y), IM_COL32(255, 255, 0, 255), 2.0f); + draw_list->PopClipRect(); + if (adding_preview) + points.pop_back(); + } + ImGui::End(); +} + +// End of Demo code +#else + +void ImGui::ShowDemoWindow(bool*) {} +void ImGui::ShowUserGuide() {} +void ImGui::ShowStyleEditor(ImGuiStyle*) {} + +#endif diff --git a/Baikal/ImGUI/imgui_draw.cpp b/BaikalStandalone/ImGUI/imgui_draw.cpp similarity index 54% rename from Baikal/ImGUI/imgui_draw.cpp rename to BaikalStandalone/ImGUI/imgui_draw.cpp index b0931b60..073c1c8a 100644 --- a/Baikal/ImGUI/imgui_draw.cpp +++ b/BaikalStandalone/ImGUI/imgui_draw.cpp @@ -1,10 +1,12 @@ -// dear imgui, v1.50 WIP +// dear imgui, v1.63 WIP // (drawing and font code) // Contains implementation for +// - Default styles // - ImDrawList // - ImDrawData // - ImFontAtlas +// - Internal Render Helpers // - ImFont // - Default font data @@ -13,25 +15,28 @@ #endif #include "imgui.h" +#ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS -#define IMGUI_DEFINE_PLACEMENT_NEW +#endif #include "imgui_internal.h" #include // vsnprintf, sscanf, printf #if !defined(alloca) -#ifdef _WIN32 +#if defined(__GLIBC__) || defined(__sun) || defined(__CYGWIN__) +#include // alloca (glibc uses . Note that Cygwin may have _WIN32 defined, so the order matters here) +#elif defined(_WIN32) #include // alloca -#elif (defined(__FreeBSD__) || defined(FreeBSD_kernel) || defined(__DragonFly__)) && !defined(__GLIBC__) -#include // alloca. FreeBSD uses stdlib.h unless GLIBC +#if !defined(alloca) +#define alloca _alloca // for clang with MS Codegen +#endif #else -#include // alloca +#include // alloca #endif #endif #ifdef _MSC_VER #pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen -#define snprintf _snprintf #endif #ifdef __clang__ @@ -39,23 +44,34 @@ #pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants ok. #pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it. #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // +#if __has_warning("-Wcomma") +#pragma clang diagnostic ignored "-Wcomma" // warning : possible misuse of comma operator here // +#endif #if __has_warning("-Wreserved-id-macro") #pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier // #endif +#if __has_warning("-Wdouble-promotion") +#pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function +#endif #elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value -#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers +#if __GNUC__ >= 8 +#pragma GCC diagnostic ignored "-Wclass-memaccess" // warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead +#endif #endif //------------------------------------------------------------------------- // STB libraries implementation //------------------------------------------------------------------------- -//#define IMGUI_STB_NAMESPACE ImGuiStb -//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION +// Compile time options: +//#define IMGUI_STB_NAMESPACE ImGuiStb +//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" +//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION +//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION #ifdef IMGUI_STB_NAMESPACE namespace IMGUI_STB_NAMESPACE @@ -69,33 +85,54 @@ namespace IMGUI_STB_NAMESPACE #ifdef __clang__ #pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse. #pragma clang diagnostic ignored "-Wunused-function" #pragma clang diagnostic ignored "-Wmissing-prototypes" +#pragma clang diagnostic ignored "-Wimplicit-fallthrough" +#pragma clang diagnostic ignored "-Wcast-qual" // warning : cast from 'const xxxx *' to 'xxx *' drops const qualifier // #endif #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wtype-limits" // warning: comparison is always true due to limited range of data type [-Wtype-limits] +#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers #endif -#define STBRP_ASSERT(x) IM_ASSERT(x) +#ifndef STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds) #ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION #define STBRP_STATIC +#define STBRP_ASSERT(x) IM_ASSERT(x) +#define STBRP_SORT ImQsort #define STB_RECT_PACK_IMPLEMENTATION #endif +#ifdef IMGUI_STB_RECT_PACK_FILENAME +#include IMGUI_STB_RECT_PACK_FILENAME +#else #include "stb_rect_pack.h" +#endif +#endif -#define STBTT_malloc(x,u) ((void)(u), ImGui::MemAlloc(x)) -#define STBTT_free(x,u) ((void)(u), ImGui::MemFree(x)) -#define STBTT_assert(x) IM_ASSERT(x) +#ifndef STB_TRUETYPE_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds) #ifndef IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION +#define STBTT_malloc(x,u) ((void)(u), ImGui::MemAlloc(x)) +#define STBTT_free(x,u) ((void)(u), ImGui::MemFree(x)) +#define STBTT_assert(x) IM_ASSERT(x) +#define STBTT_fmod(x,y) ImFmod(x,y) +#define STBTT_sqrt(x) ImSqrt(x) +#define STBTT_pow(x,y) ImPow(x,y) +#define STBTT_fabs(x) ImFabs(x) +#define STBTT_ifloor(x) ((int)ImFloorStd(x)) +#define STBTT_iceil(x) ((int)ImCeil(x)) #define STBTT_STATIC #define STB_TRUETYPE_IMPLEMENTATION #else #define STBTT_DEF extern #endif +#ifdef IMGUI_STB_TRUETYPE_FILENAME +#include IMGUI_STB_TRUETYPE_FILENAME +#else #include "stb_truetype.h" +#endif +#endif #ifdef __GNUC__ #pragma GCC diagnostic pop @@ -115,16 +152,189 @@ using namespace IMGUI_STB_NAMESPACE; #endif //----------------------------------------------------------------------------- -// ImDrawList +// Style functions +//----------------------------------------------------------------------------- + +void ImGui::StyleColorsDark(ImGuiStyle* dst) +{ + ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); + ImVec4* colors = style->Colors; + + colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); + colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); + colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f); + colors[ImGuiCol_ChildBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.00f); + colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f); + colors[ImGuiCol_Border] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f); + colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + colors[ImGuiCol_FrameBg] = ImVec4(0.16f, 0.29f, 0.48f, 0.54f); + colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); + colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); + colors[ImGuiCol_TitleBg] = ImVec4(0.04f, 0.04f, 0.04f, 1.00f); + colors[ImGuiCol_TitleBgActive] = ImVec4(0.16f, 0.29f, 0.48f, 1.00f); + colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f); + colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); + colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f); + colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f); + colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f); + colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f); + colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_SliderGrab] = ImVec4(0.24f, 0.52f, 0.88f, 1.00f); + colors[ImGuiCol_SliderGrabActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); + colors[ImGuiCol_ButtonHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f); + colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f); + colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f); + colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_Separator] = colors[ImGuiCol_Border]; + colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f); + colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f); + colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f); + colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); + colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); + colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f); + colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); + colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); + colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); + colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); + colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); + colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); + colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); + colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); +} + +void ImGui::StyleColorsClassic(ImGuiStyle* dst) +{ + ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); + ImVec4* colors = style->Colors; + + colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); + colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); + colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f); + colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + colors[ImGuiCol_PopupBg] = ImVec4(0.11f, 0.11f, 0.14f, 0.92f); + colors[ImGuiCol_Border] = ImVec4(0.50f, 0.50f, 0.50f, 0.50f); + colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + colors[ImGuiCol_FrameBg] = ImVec4(0.43f, 0.43f, 0.43f, 0.39f); + colors[ImGuiCol_FrameBgHovered] = ImVec4(0.47f, 0.47f, 0.69f, 0.40f); + colors[ImGuiCol_FrameBgActive] = ImVec4(0.42f, 0.41f, 0.64f, 0.69f); + colors[ImGuiCol_TitleBg] = ImVec4(0.27f, 0.27f, 0.54f, 0.83f); + colors[ImGuiCol_TitleBgActive] = ImVec4(0.32f, 0.32f, 0.63f, 0.87f); + colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f); + colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.80f); + colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.25f, 0.30f, 0.60f); + colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f); + colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f); + colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f); + colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f); + colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f); + colors[ImGuiCol_SliderGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f); + colors[ImGuiCol_Button] = ImVec4(0.35f, 0.40f, 0.61f, 0.62f); + colors[ImGuiCol_ButtonHovered] = ImVec4(0.40f, 0.48f, 0.71f, 0.79f); + colors[ImGuiCol_ButtonActive] = ImVec4(0.46f, 0.54f, 0.80f, 1.00f); + colors[ImGuiCol_Header] = ImVec4(0.40f, 0.40f, 0.90f, 0.45f); + colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.90f, 0.80f); + colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.87f, 0.80f); + colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); + colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.60f, 0.70f, 1.00f); + colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.70f, 0.90f, 1.00f); + colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.16f); + colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f); + colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.82f, 1.00f, 0.90f); + colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); + colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); + colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); + colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); + colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); + colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); + colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered]; + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); + colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); + colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); +} + +// Those light colors are better suited with a thicker font than the default one + FrameBorder +void ImGui::StyleColorsLight(ImGuiStyle* dst) +{ + ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); + ImVec4* colors = style->Colors; + + colors[ImGuiCol_Text] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); + colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); + colors[ImGuiCol_WindowBg] = ImVec4(0.94f, 0.94f, 0.94f, 1.00f); + colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + colors[ImGuiCol_PopupBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.98f); + colors[ImGuiCol_Border] = ImVec4(0.00f, 0.00f, 0.00f, 0.30f); + colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + colors[ImGuiCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); + colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); + colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); + colors[ImGuiCol_TitleBg] = ImVec4(0.96f, 0.96f, 0.96f, 1.00f); + colors[ImGuiCol_TitleBgActive] = ImVec4(0.82f, 0.82f, 0.82f, 1.00f); + colors[ImGuiCol_TitleBgCollapsed] = ImVec4(1.00f, 1.00f, 1.00f, 0.51f); + colors[ImGuiCol_MenuBarBg] = ImVec4(0.86f, 0.86f, 0.86f, 1.00f); + colors[ImGuiCol_ScrollbarBg] = ImVec4(0.98f, 0.98f, 0.98f, 0.53f); + colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.69f, 0.69f, 0.69f, 0.80f); + colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.49f, 0.49f, 0.49f, 0.80f); + colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.49f, 0.49f, 0.49f, 1.00f); + colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_SliderGrab] = ImVec4(0.26f, 0.59f, 0.98f, 0.78f); + colors[ImGuiCol_SliderGrabActive] = ImVec4(0.46f, 0.54f, 0.80f, 0.60f); + colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); + colors[ImGuiCol_ButtonHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f); + colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f); + colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f); + colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_Separator] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f); + colors[ImGuiCol_SeparatorHovered] = ImVec4(0.14f, 0.44f, 0.80f, 0.78f); + colors[ImGuiCol_SeparatorActive] = ImVec4(0.14f, 0.44f, 0.80f, 1.00f); + colors[ImGuiCol_ResizeGrip] = ImVec4(0.80f, 0.80f, 0.80f, 0.56f); + colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); + colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); + colors[ImGuiCol_PlotLines] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f); + colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); + colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); + colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.45f, 0.00f, 1.00f); + colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); + colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); + colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered]; + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.70f, 0.70f, 0.70f, 0.70f); + colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.20f); + colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); +} + +//----------------------------------------------------------------------------- +// ImDrawListData //----------------------------------------------------------------------------- -static const ImVec4 GNullClipRect(-8192.0f, -8192.0f, +8192.0f, +8192.0f); // Large values that are easy to encode in a few bits+shift +ImDrawListSharedData::ImDrawListSharedData() +{ + Font = NULL; + FontSize = 0.0f; + CurveTessellationTol = 0.0f; + ClipRectFullscreen = ImVec4(-8192.0f, -8192.0f, +8192.0f, +8192.0f); + + // Const data + for (int i = 0; i < IM_ARRAYSIZE(CircleVtx12); i++) + { + const float a = ((float)i * 2 * IM_PI) / (float)IM_ARRAYSIZE(CircleVtx12); + CircleVtx12[i] = ImVec2(ImCos(a), ImSin(a)); + } +} + +//----------------------------------------------------------------------------- +// ImDrawList +//----------------------------------------------------------------------------- void ImDrawList::Clear() { CmdBuffer.resize(0); IdxBuffer.resize(0); VtxBuffer.resize(0); + Flags = ImDrawListFlags_AntiAliasedLines | ImDrawListFlags_AntiAliasedFill; _VtxCurrentIdx = 0; _VtxWritePtr = NULL; _IdxWritePtr = NULL; @@ -158,8 +368,18 @@ void ImDrawList::ClearFreeMemory() _Channels.clear(); } -// Use macros because C++ is a terrible language, we want guaranteed inline, no code in header, and no overhead in Debug mode -#define GetCurrentClipRect() (_ClipRectStack.Size ? _ClipRectStack.Data[_ClipRectStack.Size-1] : GNullClipRect) +ImDrawList* ImDrawList::CloneOutput() const +{ + ImDrawList* dst = IM_NEW(ImDrawList(NULL)); + dst->CmdBuffer = CmdBuffer; + dst->IdxBuffer = IdxBuffer; + dst->VtxBuffer = VtxBuffer; + dst->Flags = Flags; + return dst; +} + +// Using macros because C++ is a terrible language, we want guaranteed inline, no code in header, and no overhead in Debug builds +#define GetCurrentClipRect() (_ClipRectStack.Size ? _ClipRectStack.Data[_ClipRectStack.Size-1] : _Data->ClipRectFullscreen) #define GetCurrentTextureId() (_TextureIdStack.Size ? _TextureIdStack.Data[_TextureIdStack.Size-1] : NULL) void ImDrawList::AddDrawCmd() @@ -220,7 +440,7 @@ void ImDrawList::UpdateTextureID() // Try to merge with previous command if it matches, else use current command ImDrawCmd* prev_cmd = CmdBuffer.Size > 1 ? curr_cmd - 1 : NULL; - if (prev_cmd && prev_cmd->TextureId == curr_texture_id && memcmp(&prev_cmd->ClipRect, &GetCurrentClipRect(), sizeof(ImVec4)) == 0 && prev_cmd->UserCallback == NULL) + if (curr_cmd->ElemCount == 0 && prev_cmd && prev_cmd->TextureId == curr_texture_id && memcmp(&prev_cmd->ClipRect, &GetCurrentClipRect(), sizeof(ImVec4)) == 0 && prev_cmd->UserCallback == NULL) CmdBuffer.pop_back(); else curr_cmd->TextureId = curr_texture_id; @@ -250,8 +470,7 @@ void ImDrawList::PushClipRect(ImVec2 cr_min, ImVec2 cr_max, bool intersect_with_ void ImDrawList::PushClipRectFullScreen() { - PushClipRect(ImVec2(GNullClipRect.x, GNullClipRect.y), ImVec2(GNullClipRect.z, GNullClipRect.w)); - //PushClipRect(GetVisibleRect()); // FIXME-OPT: This would be more correct but we're not supposed to access ImGuiContext from here? + PushClipRect(ImVec2(_Data->ClipRectFullscreen.x, _Data->ClipRectFullscreen.y), ImVec2(_Data->ClipRectFullscreen.z, _Data->ClipRectFullscreen.w)); } void ImDrawList::PopClipRect() @@ -261,7 +480,7 @@ void ImDrawList::PopClipRect() UpdateClipRect(); } -void ImDrawList::PushTextureID(const ImTextureID& texture_id) +void ImDrawList::PushTextureID(ImTextureID texture_id) { _TextureIdStack.push_back(texture_id); UpdateTextureID(); @@ -282,7 +501,7 @@ void ImDrawList::ChannelsSplit(int channels_count) _Channels.resize(channels_count); _ChannelsCount = channels_count; - // _Channels[] (24 bytes each) hold storage that we'll swap with this->_CmdBuffer/_IdxBuffer + // _Channels[] (24/32 bytes each) hold storage that we'll swap with this->_CmdBuffer/_IdxBuffer // The content of _Channels[0] at this point doesn't matter. We clear it to make state tidy in a debugger but we don't strictly need to. // When we switch to the next channel, we'll copy _CmdBuffer/_IdxBuffer into _Channels[0] and then _Channels[1] into _CmdBuffer/_IdxBuffer memset(&_Channels[0], 0, sizeof(ImDrawChannel)); @@ -337,7 +556,7 @@ void ImDrawList::ChannelsMerge() if (int sz = ch.CmdBuffer.Size) { memcpy(cmd_write, ch.CmdBuffer.Data, sz * sizeof(ImDrawCmd)); cmd_write += sz; } if (int sz = ch.IdxBuffer.Size) { memcpy(_IdxWritePtr, ch.IdxBuffer.Data, sz * sizeof(ImDrawIdx)); _IdxWritePtr += sz; } } - AddDrawCmd(); + UpdateClipRect(); // We call this instead of AddDrawCmd(), so that empty channels won't produce an extra draw call. _ChannelsCount = 1; } @@ -359,19 +578,19 @@ void ImDrawList::PrimReserve(int idx_count, int vtx_count) ImDrawCmd& draw_cmd = CmdBuffer.Data[CmdBuffer.Size-1]; draw_cmd.ElemCount += idx_count; - int vtx_buffer_size = VtxBuffer.Size; - VtxBuffer.resize(vtx_buffer_size + vtx_count); - _VtxWritePtr = VtxBuffer.Data + vtx_buffer_size; + int vtx_buffer_old_size = VtxBuffer.Size; + VtxBuffer.resize(vtx_buffer_old_size + vtx_count); + _VtxWritePtr = VtxBuffer.Data + vtx_buffer_old_size; - int idx_buffer_size = IdxBuffer.Size; - IdxBuffer.resize(idx_buffer_size + idx_count); - _IdxWritePtr = IdxBuffer.Data + idx_buffer_size; + int idx_buffer_old_size = IdxBuffer.Size; + IdxBuffer.resize(idx_buffer_old_size + idx_count); + _IdxWritePtr = IdxBuffer.Data + idx_buffer_old_size; } // Fully unrolled with inline call to keep our debug builds decently fast. void ImDrawList::PrimRect(const ImVec2& a, const ImVec2& c, ImU32 col) { - ImVec2 b(c.x, a.y), d(a.x, c.y), uv(GImGui->FontTexUvWhitePixel); + ImVec2 b(c.x, a.y), d(a.x, c.y), uv(_Data->TexUvWhitePixel); ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx; _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2); _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3); @@ -414,25 +633,23 @@ void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, c } // TODO: Thickness anti-aliased lines cap are missing their AA fringe. -void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, bool closed, float thickness, bool anti_aliased) +void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, bool closed, float thickness) { if (points_count < 2) return; - const ImVec2 uv = GImGui->FontTexUvWhitePixel; - anti_aliased &= GImGui->Style.AntiAliasedLines; - //if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug + const ImVec2 uv = _Data->TexUvWhitePixel; int count = points_count; if (!closed) count = points_count-1; const bool thick_line = thickness > 1.0f; - if (anti_aliased) + if (Flags & ImDrawListFlags_AntiAliasedLines) { // Anti-aliased stroke const float AA_SIZE = 1.0f; - const ImU32 col_trans = col & IM_COL32(255,255,255,0); + const ImU32 col_trans = col & ~IM_COL32_A_MASK; const int idx_count = thick_line ? count*18 : count*12; const int vtx_count = thick_line ? points_count*4 : points_count*3; @@ -595,17 +812,15 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 } } -void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col, bool anti_aliased) +void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col) { - const ImVec2 uv = GImGui->FontTexUvWhitePixel; - anti_aliased &= GImGui->Style.AntiAliasedShapes; - //if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug + const ImVec2 uv = _Data->TexUvWhitePixel; - if (anti_aliased) + if (Flags & ImDrawListFlags_AntiAliasedFill) { // Anti-aliased Fill const float AA_SIZE = 1.0f; - const ImU32 col_trans = col & IM_COL32(255,255,255,0); + const ImU32 col_trans = col & ~IM_COL32_A_MASK; const int idx_count = (points_count-2)*3 + points_count*6; const int vtx_count = (points_count*2); PrimReserve(idx_count, vtx_count); @@ -678,47 +893,33 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun } } -void ImDrawList::PathArcToFast(const ImVec2& centre, float radius, int amin, int amax) +void ImDrawList::PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12) { - static ImVec2 circle_vtx[12]; - static bool circle_vtx_builds = false; - const int circle_vtx_count = IM_ARRAYSIZE(circle_vtx); - if (!circle_vtx_builds) - { - for (int i = 0; i < circle_vtx_count; i++) - { - const float a = ((float)i / (float)circle_vtx_count) * 2*IM_PI; - circle_vtx[i].x = cosf(a); - circle_vtx[i].y = sinf(a); - } - circle_vtx_builds = true; - } - - if (amin > amax) return; - if (radius == 0.0f) + if (radius == 0.0f || a_min_of_12 > a_max_of_12) { _Path.push_back(centre); + return; } - else + _Path.reserve(_Path.Size + (a_max_of_12 - a_min_of_12 + 1)); + for (int a = a_min_of_12; a <= a_max_of_12; a++) { - _Path.reserve(_Path.Size + (amax - amin + 1)); - for (int a = amin; a <= amax; a++) - { - const ImVec2& c = circle_vtx[a % circle_vtx_count]; - _Path.push_back(ImVec2(centre.x + c.x * radius, centre.y + c.y * radius)); - } + const ImVec2& c = _Data->CircleVtx12[a % IM_ARRAYSIZE(_Data->CircleVtx12)]; + _Path.push_back(ImVec2(centre.x + c.x * radius, centre.y + c.y * radius)); } } -void ImDrawList::PathArcTo(const ImVec2& centre, float radius, float amin, float amax, int num_segments) +void ImDrawList::PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments) { if (radius == 0.0f) + { _Path.push_back(centre); + return; + } _Path.reserve(_Path.Size + (num_segments + 1)); for (int i = 0; i <= num_segments; i++) { - const float a = amin + ((float)i / (float)num_segments) * (amax - amin); - _Path.push_back(ImVec2(centre.x + cosf(a) * radius, centre.y + sinf(a) * radius)); + const float a = a_min + ((float)i / (float)num_segments) * (a_max - a_min); + _Path.push_back(ImVec2(centre.x + ImCos(a) * radius, centre.y + ImSin(a) * radius)); } } @@ -754,7 +955,7 @@ void ImDrawList::PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImV if (num_segments == 0) { // Auto-tessellated - PathBezierToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, GImGui->Style.CurveTessellationTol, 0); + PathBezierToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, _Data->CurveTessellationTol, 0); } else { @@ -774,27 +975,26 @@ void ImDrawList::PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImV void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int rounding_corners) { - float r = rounding; - r = ImMin(r, fabsf(b.x-a.x) * ( ((rounding_corners&(1|2))==(1|2)) || ((rounding_corners&(4|8))==(4|8)) ? 0.5f : 1.0f ) - 1.0f); - r = ImMin(r, fabsf(b.y-a.y) * ( ((rounding_corners&(1|8))==(1|8)) || ((rounding_corners&(2|4))==(2|4)) ? 0.5f : 1.0f ) - 1.0f); + rounding = ImMin(rounding, ImFabs(b.x - a.x) * ( ((rounding_corners & ImDrawCornerFlags_Top) == ImDrawCornerFlags_Top) || ((rounding_corners & ImDrawCornerFlags_Bot) == ImDrawCornerFlags_Bot) ? 0.5f : 1.0f ) - 1.0f); + rounding = ImMin(rounding, ImFabs(b.y - a.y) * ( ((rounding_corners & ImDrawCornerFlags_Left) == ImDrawCornerFlags_Left) || ((rounding_corners & ImDrawCornerFlags_Right) == ImDrawCornerFlags_Right) ? 0.5f : 1.0f ) - 1.0f); - if (r <= 0.0f || rounding_corners == 0) + if (rounding <= 0.0f || rounding_corners == 0) { PathLineTo(a); - PathLineTo(ImVec2(b.x,a.y)); + PathLineTo(ImVec2(b.x, a.y)); PathLineTo(b); - PathLineTo(ImVec2(a.x,b.y)); + PathLineTo(ImVec2(a.x, b.y)); } else { - const float r0 = (rounding_corners & 1) ? r : 0.0f; - const float r1 = (rounding_corners & 2) ? r : 0.0f; - const float r2 = (rounding_corners & 4) ? r : 0.0f; - const float r3 = (rounding_corners & 8) ? r : 0.0f; - PathArcToFast(ImVec2(a.x+r0,a.y+r0), r0, 6, 9); - PathArcToFast(ImVec2(b.x-r1,a.y+r1), r1, 9, 12); - PathArcToFast(ImVec2(b.x-r2,b.y-r2), r2, 0, 3); - PathArcToFast(ImVec2(a.x+r3,b.y-r3), r3, 3, 6); + const float rounding_tl = (rounding_corners & ImDrawCornerFlags_TopLeft) ? rounding : 0.0f; + const float rounding_tr = (rounding_corners & ImDrawCornerFlags_TopRight) ? rounding : 0.0f; + const float rounding_br = (rounding_corners & ImDrawCornerFlags_BotRight) ? rounding : 0.0f; + const float rounding_bl = (rounding_corners & ImDrawCornerFlags_BotLeft) ? rounding : 0.0f; + PathArcToFast(ImVec2(a.x + rounding_tl, a.y + rounding_tl), rounding_tl, 6, 9); + PathArcToFast(ImVec2(b.x - rounding_tr, a.y + rounding_tr), rounding_tr, 9, 12); + PathArcToFast(ImVec2(b.x - rounding_br, b.y - rounding_br), rounding_br, 0, 3); + PathArcToFast(ImVec2(a.x + rounding_bl, b.y - rounding_bl), rounding_bl, 3, 6); } } @@ -812,7 +1012,10 @@ void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float roun { if ((col & IM_COL32_A_MASK) == 0) return; - PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.5f,0.5f), rounding, rounding_corners_flags); + if (Flags & ImDrawListFlags_AntiAliasedLines) + PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.50f,0.50f), rounding, rounding_corners_flags); + else + PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.49f,0.49f), rounding, rounding_corners_flags); // Better looking lower-right corner and rounded non-AA shapes. PathStroke(col, true, thickness); } @@ -823,7 +1026,7 @@ void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, floa if (rounding > 0.0f) { PathRect(a, b, rounding, rounding_corners_flags); - PathFill(col); + PathFillConvex(col); } else { @@ -837,7 +1040,7 @@ void ImDrawList::AddRectFilledMultiColor(const ImVec2& a, const ImVec2& c, ImU32 if (((col_upr_left | col_upr_right | col_bot_right | col_bot_left) & IM_COL32_A_MASK) == 0) return; - const ImVec2 uv = GImGui->FontTexUvWhitePixel; + const ImVec2 uv = _Data->TexUvWhitePixel; PrimReserve(6, 4); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+1)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+2)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+2)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+3)); @@ -868,7 +1071,7 @@ void ImDrawList::AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c PathLineTo(b); PathLineTo(c); PathLineTo(d); - PathFill(col); + PathFillConvex(col); } void ImDrawList::AddTriangle(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col, float thickness) @@ -890,7 +1093,7 @@ void ImDrawList::AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec PathLineTo(a); PathLineTo(b); PathLineTo(c); - PathFill(col); + PathFillConvex(col); } void ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments, float thickness) @@ -910,7 +1113,7 @@ void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments; PathArcTo(centre, radius, 0.0f, a_max, num_segments); - PathFill(col); + PathFillConvex(col); } void ImDrawList::AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments) @@ -933,12 +1136,11 @@ void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, if (text_begin == text_end) return; - // Note: This is one of the few instance of breaking the encapsulation of ImDrawList, as we pull this from ImGui state, but it is just SO useful. - // Might just move Font/FontSize to ImDrawList? + // Pull default font/size from the shared ImDrawListSharedData instance if (font == NULL) - font = GImGui->Font; + font = _Data->Font; if (font_size == 0.0f) - font_size = GImGui->FontSize; + font_size = _Data->FontSize; IM_ASSERT(font->ContainerAtlas->TexID == _TextureIdStack.back()); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font. @@ -955,21 +1157,61 @@ void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end) { - AddText(GImGui->Font, GImGui->FontSize, pos, col, text_begin, text_end); + AddText(NULL, 0.0f, pos, col, text_begin, text_end); +} + +void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col) +{ + if ((col & IM_COL32_A_MASK) == 0) + return; + + const bool push_texture_id = _TextureIdStack.empty() || user_texture_id != _TextureIdStack.back(); + if (push_texture_id) + PushTextureID(user_texture_id); + + PrimReserve(6, 4); + PrimRectUV(a, b, uv_a, uv_b, col); + + if (push_texture_id) + PopTextureID(); } -void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv0, const ImVec2& uv1, ImU32 col) +void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col) { if ((col & IM_COL32_A_MASK) == 0) return; - // FIXME-OPT: This is wasting draw calls. const bool push_texture_id = _TextureIdStack.empty() || user_texture_id != _TextureIdStack.back(); if (push_texture_id) PushTextureID(user_texture_id); PrimReserve(6, 4); - PrimRectUV(a, b, uv0, uv1, col); + PrimQuadUV(a, b, c, d, uv_a, uv_b, uv_c, uv_d, col); + + if (push_texture_id) + PopTextureID(); +} + +void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col, float rounding, int rounding_corners) +{ + if ((col & IM_COL32_A_MASK) == 0) + return; + + if (rounding <= 0.0f || (rounding_corners & ImDrawCornerFlags_All) == 0) + { + AddImage(user_texture_id, a, b, uv_a, uv_b, col); + return; + } + + const bool push_texture_id = _TextureIdStack.empty() || user_texture_id != _TextureIdStack.back(); + if (push_texture_id) + PushTextureID(user_texture_id); + + int vert_start_idx = VtxBuffer.Size; + PathRect(a, b, rounding, rounding_corners); + PathFillConvex(col); + int vert_end_idx = VtxBuffer.Size; + ImGui::ShadeVertsLinearUV(this, vert_start_idx, vert_end_idx, a, b, uv_a, uv_b, true); if (push_texture_id) PopTextureID(); @@ -1013,7 +1255,54 @@ void ImDrawData::ScaleClipRects(const ImVec2& scale) } //----------------------------------------------------------------------------- -// ImFontAtlas +// Shade functions +//----------------------------------------------------------------------------- + +// Generic linear color gradient, write to RGB fields, leave A untouched. +void ImGui::ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1) +{ + ImVec2 gradient_extent = gradient_p1 - gradient_p0; + float gradient_inv_length2 = 1.0f / ImLengthSqr(gradient_extent); + ImDrawVert* vert_start = draw_list->VtxBuffer.Data + vert_start_idx; + ImDrawVert* vert_end = draw_list->VtxBuffer.Data + vert_end_idx; + for (ImDrawVert* vert = vert_start; vert < vert_end; vert++) + { + float d = ImDot(vert->pos - gradient_p0, gradient_extent); + float t = ImClamp(d * gradient_inv_length2, 0.0f, 1.0f); + int r = ImLerp((int)(col0 >> IM_COL32_R_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_R_SHIFT) & 0xFF, t); + int g = ImLerp((int)(col0 >> IM_COL32_G_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_G_SHIFT) & 0xFF, t); + int b = ImLerp((int)(col0 >> IM_COL32_B_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_B_SHIFT) & 0xFF, t); + vert->col = (r << IM_COL32_R_SHIFT) | (g << IM_COL32_G_SHIFT) | (b << IM_COL32_B_SHIFT) | (vert->col & IM_COL32_A_MASK); + } +} + +// Distribute UV over (a, b) rectangle +void ImGui::ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp) +{ + const ImVec2 size = b - a; + const ImVec2 uv_size = uv_b - uv_a; + const ImVec2 scale = ImVec2( + size.x != 0.0f ? (uv_size.x / size.x) : 0.0f, + size.y != 0.0f ? (uv_size.y / size.y) : 0.0f); + + ImDrawVert* vert_start = draw_list->VtxBuffer.Data + vert_start_idx; + ImDrawVert* vert_end = draw_list->VtxBuffer.Data + vert_end_idx; + if (clamp) + { + const ImVec2 min = ImMin(uv_a, uv_b); + const ImVec2 max = ImMax(uv_a, uv_b); + for (ImDrawVert* vertex = vert_start; vertex < vert_end; ++vertex) + vertex->uv = ImClamp(uv_a + ImMul(ImVec2(vertex->pos.x, vertex->pos.y) - a, scale), min, max); + } + else + { + for (ImDrawVert* vertex = vert_start; vertex < vert_end; ++vertex) + vertex->uv = uv_a + ImMul(ImVec2(vertex->pos.x, vertex->pos.y) - a, scale); + } +} + +//----------------------------------------------------------------------------- +// ImFontConfig //----------------------------------------------------------------------------- ImFontConfig::ImFontConfig() @@ -1027,29 +1316,96 @@ ImFontConfig::ImFontConfig() OversampleV = 1; PixelSnapH = false; GlyphExtraSpacing = ImVec2(0.0f, 0.0f); + GlyphOffset = ImVec2(0.0f, 0.0f); GlyphRanges = NULL; + GlyphMinAdvanceX = 0.0f; + GlyphMaxAdvanceX = FLT_MAX; MergeMode = false; - MergeGlyphCenterV = false; - DstFont = NULL; + RasterizerFlags = 0x00; + RasterizerMultiply = 1.0f; memset(Name, 0, sizeof(Name)); + DstFont = NULL; } +//----------------------------------------------------------------------------- +// ImFontAtlas +//----------------------------------------------------------------------------- + +// A work of art lies ahead! (. = white layer, X = black layer, others are blank) +// The white texels on the top left are the ones we'll use everywhere in ImGui to render filled shapes. +const int FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF = 108; +const int FONT_ATLAS_DEFAULT_TEX_DATA_H = 27; +const unsigned int FONT_ATLAS_DEFAULT_TEX_DATA_ID = 0x80000000; +static const char FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * FONT_ATLAS_DEFAULT_TEX_DATA_H + 1] = +{ + "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX- XX " + "..- -X.....X- X.X - X.X -X.....X - X.....X- X..X " + "--- -XXX.XXX- X...X - X...X -X....X - X....X- X..X " + "X - X.X - X.....X - X.....X -X...X - X...X- X..X " + "XX - X.X -X.......X- X.......X -X..X.X - X.X..X- X..X " + "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X- X..XXX " + "X..X - X.X - X.X - X.X -XX X.X - X.X XX- X..X..XXX " + "X...X - X.X - X.X - XX X.X XX - X.X - X.X - X..X..X..XX " + "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X - X..X..X..X.X " + "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X -XXX X..X..X..X..X" + "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X -X..XX........X..X" + "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X -X...X...........X" + "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X - X..............X" + "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X - X.............X" + "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X - X.............X" + "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X - X............X" + "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX - X...........X " + "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------- X..........X " + "X.X X..X - -X.......X- X.......X - XX XX - - X..........X " + "XX X..X - - X.....X - X.....X - X.X X.X - - X........X " + " X..X - X...X - X...X - X..X X..X - - X........X " + " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - - XXXXXXXXXX " + "------------ - X - X -X.....................X- ------------------" + " ----------------------------------- X...XXXXXXXXXXXXX...X - " + " - X..X X..X - " + " - X.X X.X - " + " - XX XX - " +}; + +static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_COUNT][3] = +{ + // Pos ........ Size ......... Offset ...... + { ImVec2( 0,3), ImVec2(12,19), ImVec2( 0, 0) }, // ImGuiMouseCursor_Arrow + { ImVec2(13,0), ImVec2( 7,16), ImVec2( 1, 8) }, // ImGuiMouseCursor_TextInput + { ImVec2(31,0), ImVec2(23,23), ImVec2(11,11) }, // ImGuiMouseCursor_ResizeAll + { ImVec2(21,0), ImVec2( 9,23), ImVec2( 4,11) }, // ImGuiMouseCursor_ResizeNS + { ImVec2(55,18),ImVec2(23, 9), ImVec2(11, 4) }, // ImGuiMouseCursor_ResizeEW + { ImVec2(73,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNESW + { ImVec2(55,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNWSE + { ImVec2(91,0), ImVec2(17,22), ImVec2( 5, 0) }, // ImGuiMouseCursor_Hand +}; + ImFontAtlas::ImFontAtlas() { + Locked = false; + Flags = 0x00; TexID = NULL; + TexDesiredWidth = 0; + TexGlyphPadding = 1; + TexPixelsAlpha8 = NULL; TexPixelsRGBA32 = NULL; - TexWidth = TexHeight = TexDesiredWidth = 0; - TexUvWhitePixel = ImVec2(0, 0); + TexWidth = TexHeight = 0; + TexUvScale = ImVec2(0.0f, 0.0f); + TexUvWhitePixel = ImVec2(0.0f, 0.0f); + for (int n = 0; n < IM_ARRAYSIZE(CustomRectIds); n++) + CustomRectIds[n] = -1; } ImFontAtlas::~ImFontAtlas() { + IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); Clear(); } void ImFontAtlas::ClearInputData() { + IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); for (int i = 0; i < ConfigData.Size; i++) if (ConfigData[i].FontData && ConfigData[i].FontDataOwnedByAtlas) { @@ -1065,10 +1421,14 @@ void ImFontAtlas::ClearInputData() Fonts[i]->ConfigDataCount = 0; } ConfigData.clear(); + CustomRects.clear(); + for (int n = 0; n < IM_ARRAYSIZE(CustomRectIds); n++) + CustomRectIds[n] = -1; } void ImFontAtlas::ClearTexData() { + IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); if (TexPixelsAlpha8) ImGui::MemFree(TexPixelsAlpha8); if (TexPixelsRGBA32) @@ -1079,11 +1439,9 @@ void ImFontAtlas::ClearTexData() void ImFontAtlas::ClearFonts() { + IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); for (int i = 0; i < Fonts.Size; i++) - { - Fonts[i]->~ImFont(); - ImGui::MemFree(Fonts[i]); - } + IM_DELETE(Fonts[i]); Fonts.clear(); } @@ -1116,13 +1474,16 @@ void ImFontAtlas::GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_wid // Although it is likely to be the most commonly used format, our font rendering is 1 channel / 8 bpp if (!TexPixelsRGBA32) { - unsigned char* pixels; + unsigned char* pixels = NULL; GetTexDataAsAlpha8(&pixels, NULL, NULL); - TexPixelsRGBA32 = (unsigned int*)ImGui::MemAlloc((size_t)(TexWidth * TexHeight * 4)); - const unsigned char* src = pixels; - unsigned int* dst = TexPixelsRGBA32; - for (int n = TexWidth * TexHeight; n > 0; n--) - *dst++ = IM_COL32(255, 255, 255, (unsigned int)(*src++)); + if (pixels) + { + TexPixelsRGBA32 = (unsigned int*)ImGui::MemAlloc((size_t)(TexWidth * TexHeight * 4)); + const unsigned char* src = pixels; + unsigned int* dst = TexPixelsRGBA32; + for (int n = TexWidth * TexHeight; n > 0; n--) + *dst++ = IM_COL32(255, 255, 255, (unsigned int)(*src++)); + } } *out_pixels = (unsigned char*)TexPixelsRGBA32; @@ -1133,25 +1494,20 @@ void ImFontAtlas::GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_wid ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) { + IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); IM_ASSERT(font_cfg->FontData != NULL && font_cfg->FontDataSize > 0); IM_ASSERT(font_cfg->SizePixels > 0.0f); // Create new font if (!font_cfg->MergeMode) - { - ImFont* font = (ImFont*)ImGui::MemAlloc(sizeof(ImFont)); - IM_PLACEMENT_NEW(font) ImFont(); - Fonts.push_back(font); - } + Fonts.push_back(IM_NEW(ImFont)); else - { - IM_ASSERT(!Fonts.empty()); // When using MergeMode make sure that a font has already been added before. You can use ImGui::AddFontDefault() to add the default imgui font. - } + IM_ASSERT(!Fonts.empty()); // When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font. ConfigData.push_back(*font_cfg); ImFontConfig& new_font_cfg = ConfigData.back(); - if (!new_font_cfg.DstFont) - new_font_cfg.DstFont = Fonts.back(); + if (!new_font_cfg.DstFont) + new_font_cfg.DstFont = Fonts.back(); if (!new_font_cfg.FontDataOwnedByAtlas) { new_font_cfg.FontData = ImGui::MemAlloc(new_font_cfg.FontDataSize); @@ -1164,9 +1520,9 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) return new_font_cfg.DstFont; } -// Default font TTF is compressed with stb_compress then base85 encoded (see extra_fonts/binary_to_compressed_c.cpp for encoder) -static unsigned int stb_decompress_length(unsigned char *input); -static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsigned int length); +// Default font TTF is compressed with stb_compress then base85 encoded (see misc/fonts/binary_to_compressed_c.cpp for encoder) +static unsigned int stb_decompress_length(const unsigned char *input); +static unsigned int stb_decompress(unsigned char *output, const unsigned char *input, unsigned int length); static const char* GetDefaultCompressedFontDataTTFBase85(); static unsigned int Decode85Byte(char c) { return c >= '\\' ? c-36 : c-35; } static void Decode85(const unsigned char* src, unsigned char* dst) @@ -1190,15 +1546,19 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template) font_cfg.PixelSnapH = true; } if (font_cfg.Name[0] == '\0') strcpy(font_cfg.Name, "ProggyClean.ttf, 13px"); + if (font_cfg.SizePixels <= 0.0f) font_cfg.SizePixels = 13.0f; const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85(); - ImFont* font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, 13.0f, &font_cfg, GetGlyphRangesDefault()); + const ImWchar* glyph_ranges = font_cfg.GlyphRanges != NULL ? font_cfg.GlyphRanges : GetGlyphRangesDefault(); + ImFont* font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_cfg.SizePixels, &font_cfg, glyph_ranges); + font->DisplayOffset.y = 1.0f; return font; } ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges) { - int data_size = 0; + IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); + size_t data_size = 0; void* data = ImFileLoadToMemory(filename, "rb", &data_size, 0); if (!data) { @@ -1211,14 +1571,15 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, // Store a short copy of filename into into the font name for convenience const char* p; for (p = filename + strlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--) {} - snprintf(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "%s, %.0fpx", p, size_pixels); + ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "%s, %.0fpx", p, size_pixels); } - return AddFontFromMemoryTTF(data, data_size, size_pixels, &font_cfg, glyph_ranges); + return AddFontFromMemoryTTF(data, (int)data_size, size_pixels, &font_cfg, glyph_ranges); } -// NBM Transfer ownership of 'ttf_data' to ImFontAtlas, unless font_cfg_template->FontDataOwnedByAtlas == false. Owned TTF buffer will be deleted after Build(). +// NB: Transfer ownership of 'ttf_data' to ImFontAtlas, unless font_cfg_template->FontDataOwnedByAtlas == false. Owned TTF buffer will be deleted after Build(). ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges) { + IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); IM_ASSERT(font_cfg.FontData == NULL); font_cfg.FontData = ttf_data; @@ -1231,9 +1592,9 @@ ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float si ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges) { - const unsigned int buf_decompressed_size = stb_decompress_length((unsigned char*)compressed_ttf_data); + const unsigned int buf_decompressed_size = stb_decompress_length((const unsigned char*)compressed_ttf_data); unsigned char* buf_decompressed_data = (unsigned char *)ImGui::MemAlloc(buf_decompressed_size); - stb_decompress(buf_decompressed_data, (unsigned char*)compressed_ttf_data, (unsigned int)compressed_ttf_size); + stb_decompress(buf_decompressed_data, (const unsigned char*)compressed_ttf_data, (unsigned int)compressed_ttf_size); ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); IM_ASSERT(font_cfg.FontData == NULL); @@ -1251,92 +1612,177 @@ ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* compressed return font; } +int ImFontAtlas::AddCustomRectRegular(unsigned int id, int width, int height) +{ + IM_ASSERT(id >= 0x10000); + IM_ASSERT(width > 0 && width <= 0xFFFF); + IM_ASSERT(height > 0 && height <= 0xFFFF); + CustomRect r; + r.ID = id; + r.Width = (unsigned short)width; + r.Height = (unsigned short)height; + CustomRects.push_back(r); + return CustomRects.Size - 1; // Return index +} + +int ImFontAtlas::AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset) +{ + IM_ASSERT(font != NULL); + IM_ASSERT(width > 0 && width <= 0xFFFF); + IM_ASSERT(height > 0 && height <= 0xFFFF); + CustomRect r; + r.ID = id; + r.Width = (unsigned short)width; + r.Height = (unsigned short)height; + r.GlyphAdvanceX = advance_x; + r.GlyphOffset = offset; + r.Font = font; + CustomRects.push_back(r); + return CustomRects.Size - 1; // Return index +} + +void ImFontAtlas::CalcCustomRectUV(const CustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max) +{ + IM_ASSERT(TexWidth > 0 && TexHeight > 0); // Font atlas needs to be built before we can calculate UV coordinates + IM_ASSERT(rect->IsPacked()); // Make sure the rectangle has been packed + *out_uv_min = ImVec2((float)rect->X * TexUvScale.x, (float)rect->Y * TexUvScale.y); + *out_uv_max = ImVec2((float)(rect->X + rect->Width) * TexUvScale.x, (float)(rect->Y + rect->Height) * TexUvScale.y); +} + +bool ImFontAtlas::GetMouseCursorTexData(ImGuiMouseCursor cursor_type, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]) +{ + if (cursor_type <= ImGuiMouseCursor_None || cursor_type >= ImGuiMouseCursor_COUNT) + return false; + if (Flags & ImFontAtlasFlags_NoMouseCursors) + return false; + + IM_ASSERT(CustomRectIds[0] != -1); + ImFontAtlas::CustomRect& r = CustomRects[CustomRectIds[0]]; + IM_ASSERT(r.ID == FONT_ATLAS_DEFAULT_TEX_DATA_ID); + ImVec2 pos = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][0] + ImVec2((float)r.X, (float)r.Y); + ImVec2 size = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][1]; + *out_size = size; + *out_offset = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][2]; + out_uv_border[0] = (pos) * TexUvScale; + out_uv_border[1] = (pos + size) * TexUvScale; + pos.x += FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1; + out_uv_fill[0] = (pos) * TexUvScale; + out_uv_fill[1] = (pos + size) * TexUvScale; + return true; +} + bool ImFontAtlas::Build() { - IM_ASSERT(ConfigData.Size > 0); + IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); + return ImFontAtlasBuildWithStbTruetype(this); +} - TexID = NULL; - TexWidth = TexHeight = 0; - TexUvWhitePixel = ImVec2(0, 0); - ClearTexData(); +void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_brighten_factor) +{ + for (unsigned int i = 0; i < 256; i++) + { + unsigned int value = (unsigned int)(i * in_brighten_factor); + out_table[i] = value > 255 ? 255 : (value & 0xFF); + } +} +void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride) +{ + unsigned char* data = pixels + x + y * stride; + for (int j = h; j > 0; j--, data += stride) + for (int i = 0; i < w; i++) + data[i] = table[data[i]]; +} + +bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) +{ + IM_ASSERT(atlas->ConfigData.Size > 0); + + ImFontAtlasBuildRegisterDefaultCustomRects(atlas); + + atlas->TexID = NULL; + atlas->TexWidth = atlas->TexHeight = 0; + atlas->TexUvScale = ImVec2(0.0f, 0.0f); + atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f); + atlas->ClearTexData(); + + // Count glyphs/ranges + int total_glyphs_count = 0; + int total_ranges_count = 0; + for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++) + { + ImFontConfig& cfg = atlas->ConfigData[input_i]; + if (!cfg.GlyphRanges) + cfg.GlyphRanges = atlas->GetGlyphRangesDefault(); + for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2, total_ranges_count++) + total_glyphs_count += (in_range[1] - in_range[0]) + 1; + } + + // We need a width for the skyline algorithm. Using a dumb heuristic here to decide of width. User can override TexDesiredWidth and TexGlyphPadding if they wish. + // Width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height. + atlas->TexWidth = (atlas->TexDesiredWidth > 0) ? atlas->TexDesiredWidth : (total_glyphs_count > 4000) ? 4096 : (total_glyphs_count > 2000) ? 2048 : (total_glyphs_count > 1000) ? 1024 : 512; + atlas->TexHeight = 0; + + // Start packing + const int max_tex_height = 1024*32; + stbtt_pack_context spc = {}; + if (!stbtt_PackBegin(&spc, NULL, atlas->TexWidth, max_tex_height, 0, atlas->TexGlyphPadding, NULL)) + return false; + stbtt_PackSetOversampling(&spc, 1, 1); + + // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values). + ImFontAtlasBuildPackCustomRects(atlas, spc.pack_info); + + // Initialize font information (so we can error without any cleanup) struct ImFontTempBuildData { stbtt_fontinfo FontInfo; stbrp_rect* Rects; + int RectsCount; stbtt_pack_range* Ranges; int RangesCount; }; - ImFontTempBuildData* tmp_array = (ImFontTempBuildData*)ImGui::MemAlloc((size_t)ConfigData.Size * sizeof(ImFontTempBuildData)); - - // Initialize font information early (so we can error without any cleanup) + count glyphs - int total_glyph_count = 0; - int total_glyph_range_count = 0; - for (int input_i = 0; input_i < ConfigData.Size; input_i++) + ImFontTempBuildData* tmp_array = (ImFontTempBuildData*)ImGui::MemAlloc((size_t)atlas->ConfigData.Size * sizeof(ImFontTempBuildData)); + for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++) { - ImFontConfig& cfg = ConfigData[input_i]; + ImFontConfig& cfg = atlas->ConfigData[input_i]; ImFontTempBuildData& tmp = tmp_array[input_i]; + IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas)); - IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == this)); const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)cfg.FontData, cfg.FontNo); - IM_ASSERT(font_offset >= 0); + IM_ASSERT(font_offset >= 0 && "FontData is incorrect, or FontNo cannot be found."); if (!stbtt_InitFont(&tmp.FontInfo, (unsigned char*)cfg.FontData, font_offset)) - return false; - - // Count glyphs - if (!cfg.GlyphRanges) - cfg.GlyphRanges = GetGlyphRangesDefault(); - for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2) { - total_glyph_count += (in_range[1] - in_range[0]) + 1; - total_glyph_range_count++; + atlas->TexWidth = atlas->TexHeight = 0; // Reset output on failure + ImGui::MemFree(tmp_array); + return false; } } - // Start packing. We need a known width for the skyline algorithm. Using a cheap heuristic here to decide of width. User can override TexDesiredWidth if they wish. - // After packing is done, width shouldn't matter much, but some API/GPU have texture size limitations and increasing width can decrease height. - TexWidth = (TexDesiredWidth > 0) ? TexDesiredWidth : (total_glyph_count > 4000) ? 4096 : (total_glyph_count > 2000) ? 2048 : (total_glyph_count > 1000) ? 1024 : 512; - TexHeight = 0; - const int max_tex_height = 1024*32; - stbtt_pack_context spc; - stbtt_PackBegin(&spc, NULL, TexWidth, max_tex_height, 0, 1, NULL); - - // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values). - ImVector extra_rects; - RenderCustomTexData(0, &extra_rects); - stbtt_PackSetOversampling(&spc, 1, 1); - stbrp_pack_rects((stbrp_context*)spc.pack_info, &extra_rects[0], extra_rects.Size); - for (int i = 0; i < extra_rects.Size; i++) - if (extra_rects[i].was_packed) - TexHeight = ImMax(TexHeight, extra_rects[i].y + extra_rects[i].h); - // Allocate packing character data and flag packed characters buffer as non-packed (x0=y0=x1=y1=0) int buf_packedchars_n = 0, buf_rects_n = 0, buf_ranges_n = 0; - stbtt_packedchar* buf_packedchars = (stbtt_packedchar*)ImGui::MemAlloc(total_glyph_count * sizeof(stbtt_packedchar)); - stbrp_rect* buf_rects = (stbrp_rect*)ImGui::MemAlloc(total_glyph_count * sizeof(stbrp_rect)); - stbtt_pack_range* buf_ranges = (stbtt_pack_range*)ImGui::MemAlloc(total_glyph_range_count * sizeof(stbtt_pack_range)); - memset(buf_packedchars, 0, total_glyph_count * sizeof(stbtt_packedchar)); - memset(buf_rects, 0, total_glyph_count * sizeof(stbrp_rect)); // Unnecessary but let's clear this for the sake of sanity. - memset(buf_ranges, 0, total_glyph_range_count * sizeof(stbtt_pack_range)); + stbtt_packedchar* buf_packedchars = (stbtt_packedchar*)ImGui::MemAlloc(total_glyphs_count * sizeof(stbtt_packedchar)); + stbrp_rect* buf_rects = (stbrp_rect*)ImGui::MemAlloc(total_glyphs_count * sizeof(stbrp_rect)); + stbtt_pack_range* buf_ranges = (stbtt_pack_range*)ImGui::MemAlloc(total_ranges_count * sizeof(stbtt_pack_range)); + memset(buf_packedchars, 0, total_glyphs_count * sizeof(stbtt_packedchar)); + memset(buf_rects, 0, total_glyphs_count * sizeof(stbrp_rect)); // Unnecessary but let's clear this for the sake of sanity. + memset(buf_ranges, 0, total_ranges_count * sizeof(stbtt_pack_range)); // First font pass: pack all glyphs (no rendering at this point, we are working with rectangles in an infinitely tall texture at this point) - for (int input_i = 0; input_i < ConfigData.Size; input_i++) + for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++) { - ImFontConfig& cfg = ConfigData[input_i]; + ImFontConfig& cfg = atlas->ConfigData[input_i]; ImFontTempBuildData& tmp = tmp_array[input_i]; // Setup ranges - int glyph_count = 0; - int glyph_ranges_count = 0; - for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2) - { - glyph_count += (in_range[1] - in_range[0]) + 1; - glyph_ranges_count++; - } + int font_glyphs_count = 0; + int font_ranges_count = 0; + for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2, font_ranges_count++) + font_glyphs_count += (in_range[1] - in_range[0]) + 1; tmp.Ranges = buf_ranges + buf_ranges_n; - tmp.RangesCount = glyph_ranges_count; - buf_ranges_n += glyph_ranges_count; - for (int i = 0; i < glyph_ranges_count; i++) + tmp.RangesCount = font_ranges_count; + buf_ranges_n += font_ranges_count; + for (int i = 0; i < font_ranges_count; i++) { const ImWchar* in_range = &cfg.GlyphRanges[i * 2]; stbtt_pack_range& range = tmp.Ranges[i]; @@ -1347,36 +1793,62 @@ bool ImFontAtlas::Build() buf_packedchars_n += range.num_chars; } - // Pack + // Gather the sizes of all rectangle we need tmp.Rects = buf_rects + buf_rects_n; - buf_rects_n += glyph_count; + tmp.RectsCount = font_glyphs_count; + buf_rects_n += font_glyphs_count; stbtt_PackSetOversampling(&spc, cfg.OversampleH, cfg.OversampleV); int n = stbtt_PackFontRangesGatherRects(&spc, &tmp.FontInfo, tmp.Ranges, tmp.RangesCount, tmp.Rects); + IM_ASSERT(n == font_glyphs_count); + + // Detect missing glyphs and replace them with a zero-sized box instead of relying on the default glyphs + // This allows us merging overlapping icon fonts more easily. + int rect_i = 0; + for (int range_i = 0; range_i < tmp.RangesCount; range_i++) + for (int char_i = 0; char_i < tmp.Ranges[range_i].num_chars; char_i++, rect_i++) + if (stbtt_FindGlyphIndex(&tmp.FontInfo, tmp.Ranges[range_i].first_unicode_codepoint_in_range + char_i) == 0) + tmp.Rects[rect_i].w = tmp.Rects[rect_i].h = 0; + + // Pack stbrp_pack_rects((stbrp_context*)spc.pack_info, tmp.Rects, n); // Extend texture height + // Also mark missing glyphs as non-packed so we don't attempt to render into them for (int i = 0; i < n; i++) + { + if (tmp.Rects[i].w == 0 && tmp.Rects[i].h == 0) + tmp.Rects[i].was_packed = 0; if (tmp.Rects[i].was_packed) - TexHeight = ImMax(TexHeight, tmp.Rects[i].y + tmp.Rects[i].h); + atlas->TexHeight = ImMax(atlas->TexHeight, tmp.Rects[i].y + tmp.Rects[i].h); + } } - IM_ASSERT(buf_rects_n == total_glyph_count); - IM_ASSERT(buf_packedchars_n == total_glyph_count); - IM_ASSERT(buf_ranges_n == total_glyph_range_count); + IM_ASSERT(buf_rects_n == total_glyphs_count); + IM_ASSERT(buf_packedchars_n == total_glyphs_count); + IM_ASSERT(buf_ranges_n == total_ranges_count); // Create texture - TexHeight = ImUpperPowerOfTwo(TexHeight); - TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(TexWidth * TexHeight); - memset(TexPixelsAlpha8, 0, TexWidth * TexHeight); - spc.pixels = TexPixelsAlpha8; - spc.height = TexHeight; - - // Second pass: render characters - for (int input_i = 0; input_i < ConfigData.Size; input_i++) + atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight); + atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight); + atlas->TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(atlas->TexWidth * atlas->TexHeight); + memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight); + spc.pixels = atlas->TexPixelsAlpha8; + spc.height = atlas->TexHeight; + + // Second pass: render font characters + for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++) { - ImFontConfig& cfg = ConfigData[input_i]; + ImFontConfig& cfg = atlas->ConfigData[input_i]; ImFontTempBuildData& tmp = tmp_array[input_i]; stbtt_PackSetOversampling(&spc, cfg.OversampleH, cfg.OversampleV); stbtt_PackFontRangesRenderIntoRects(&spc, &tmp.FontInfo, tmp.Ranges, tmp.RangesCount, tmp.Rects); + if (cfg.RasterizerMultiply != 1.0f) + { + unsigned char multiply_table[256]; + ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply); + for (const stbrp_rect* r = tmp.Rects; r != tmp.Rects + tmp.RectsCount; r++) + if (r->was_packed) + ImFontAtlasBuildMultiplyRectAlpha8(multiply_table, spc.pixels, r->x, r->y, r->w, r->h, spc.stride_in_bytes); + } tmp.Rects = NULL; } @@ -1386,33 +1858,24 @@ bool ImFontAtlas::Build() buf_rects = NULL; // Third pass: setup ImFont and glyphs for runtime - for (int input_i = 0; input_i < ConfigData.Size; input_i++) + for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++) { - ImFontConfig& cfg = ConfigData[input_i]; + ImFontConfig& cfg = atlas->ConfigData[input_i]; ImFontTempBuildData& tmp = tmp_array[input_i]; ImFont* dst_font = cfg.DstFont; // We can have multiple input fonts writing into a same destination font (when using MergeMode=true) + if (cfg.MergeMode) + dst_font->BuildLookupTable(); - float font_scale = stbtt_ScaleForPixelHeight(&tmp.FontInfo, cfg.SizePixels); + const float font_scale = stbtt_ScaleForPixelHeight(&tmp.FontInfo, cfg.SizePixels); int unscaled_ascent, unscaled_descent, unscaled_line_gap; stbtt_GetFontVMetrics(&tmp.FontInfo, &unscaled_ascent, &unscaled_descent, &unscaled_line_gap); - float ascent = unscaled_ascent * font_scale; - float descent = unscaled_descent * font_scale; - if (!cfg.MergeMode) - { - dst_font->ContainerAtlas = this; - dst_font->ConfigData = &cfg; - dst_font->ConfigDataCount = 0; - dst_font->FontSize = cfg.SizePixels; - dst_font->Ascent = ascent; - dst_font->Descent = descent; - dst_font->Glyphs.resize(0); - dst_font->MetricsTotalSurface = 0; - } - dst_font->ConfigDataCount++; - float off_y = (cfg.MergeMode && cfg.MergeGlyphCenterV) ? (ascent - dst_font->Ascent) * 0.5f : 0.0f; + const float ascent = ImFloor(unscaled_ascent * font_scale + ((unscaled_ascent > 0.0f) ? +1 : -1)); + const float descent = ImFloor(unscaled_descent * font_scale + ((unscaled_descent > 0.0f) ? +1 : -1)); + ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); + const float font_off_x = cfg.GlyphOffset.x; + const float font_off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f); - dst_font->FallbackGlyph = NULL; // Always clear fallback so FindGlyph can return NULL. It will be set again in BuildLookupTable() for (int i = 0; i < tmp.RangesCount; i++) { stbtt_pack_range& range = tmp.Ranges[i]; @@ -1423,27 +1886,21 @@ bool ImFontAtlas::Build() continue; const int codepoint = range.first_unicode_codepoint_in_range + char_idx; - if (cfg.MergeMode && dst_font->FindGlyph((unsigned short)codepoint)) + if (cfg.MergeMode && dst_font->FindGlyphNoFallback((unsigned short)codepoint)) continue; + float char_advance_x_org = pc.xadvance; + float char_advance_x_mod = ImClamp(char_advance_x_org, cfg.GlyphMinAdvanceX, cfg.GlyphMaxAdvanceX); + float char_off_x = font_off_x; + if (char_advance_x_org != char_advance_x_mod) + char_off_x += cfg.PixelSnapH ? (float)(int)((char_advance_x_mod - char_advance_x_org) * 0.5f) : (char_advance_x_mod - char_advance_x_org) * 0.5f; + stbtt_aligned_quad q; float dummy_x = 0.0f, dummy_y = 0.0f; - stbtt_GetPackedQuad(range.chardata_for_range, TexWidth, TexHeight, char_idx, &dummy_x, &dummy_y, &q, 0); - - dst_font->Glyphs.resize(dst_font->Glyphs.Size + 1); - ImFont::Glyph& glyph = dst_font->Glyphs.back(); - glyph.Codepoint = (ImWchar)codepoint; - glyph.X0 = q.x0; glyph.Y0 = q.y0; glyph.X1 = q.x1; glyph.Y1 = q.y1; - glyph.U0 = q.s0; glyph.V0 = q.t0; glyph.U1 = q.s1; glyph.V1 = q.t1; - glyph.Y0 += (float)(int)(dst_font->Ascent + off_y + 0.5f); - glyph.Y1 += (float)(int)(dst_font->Ascent + off_y + 0.5f); - glyph.XAdvance = (pc.xadvance + cfg.GlyphExtraSpacing.x); // Bake spacing into XAdvance - if (cfg.PixelSnapH) - glyph.XAdvance = (float)(int)(glyph.XAdvance + 0.5f); - dst_font->MetricsTotalSurface += (int)(glyph.X1 - glyph.X0 + 1.99f) * (int)(glyph.Y1 - glyph.Y0 + 1.99f); // +1 to account for average padding, +0.99 to round + stbtt_GetPackedQuad(range.chardata_for_range, atlas->TexWidth, atlas->TexHeight, char_idx, &dummy_x, &dummy_y, &q, 0); + dst_font->AddGlyph((ImWchar)codepoint, q.x0 + char_off_x, q.y0 + font_off_y, q.x1 + char_off_x, q.y1 + font_off_y, q.s0, q.t0, q.s1, q.t1, char_advance_x_mod); } } - cfg.DstFont->BuildLookupTable(); } // Cleanup temporaries @@ -1451,102 +1908,114 @@ bool ImFontAtlas::Build() ImGui::MemFree(buf_ranges); ImGui::MemFree(tmp_array); - // Render into our custom data block - RenderCustomTexData(1, &extra_rects); + ImFontAtlasBuildFinish(atlas); return true; } -void ImFontAtlas::RenderCustomTexData(int pass, void* p_rects) -{ - // A work of art lies ahead! (. = white layer, X = black layer, others are blank) - // The white texels on the top left are the ones we'll use everywhere in ImGui to render filled shapes. - const int TEX_DATA_W = 90; - const int TEX_DATA_H = 27; - const char texture_data[TEX_DATA_W*TEX_DATA_H+1] = - { - "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX" - "..- -X.....X- X.X - X.X -X.....X - X.....X" - "--- -XXX.XXX- X...X - X...X -X....X - X....X" - "X - X.X - X.....X - X.....X -X...X - X...X" - "XX - X.X -X.......X- X.......X -X..X.X - X.X..X" - "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X" - "X..X - X.X - X.X - X.X -XX X.X - X.X XX" - "X...X - X.X - X.X - XX X.X XX - X.X - X.X " - "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X " - "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X " - "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X " - "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X " - "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X " - "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X " - "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X " - "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X " - "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX " - "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------" - "X.X X..X - -X.......X- X.......X - XX XX - " - "XX X..X - - X.....X - X.....X - X.X X.X - " - " X..X - X...X - X...X - X..X X..X - " - " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - " - "------------ - X - X -X.....................X- " - " ----------------------------------- X...XXXXXXXXXXXXX...X - " - " - X..X X..X - " - " - X.X X.X - " - " - XX XX - " - }; +void ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas) +{ + if (atlas->CustomRectIds[0] >= 0) + return; + if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors)) + atlas->CustomRectIds[0] = atlas->AddCustomRectRegular(FONT_ATLAS_DEFAULT_TEX_DATA_ID, FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF*2+1, FONT_ATLAS_DEFAULT_TEX_DATA_H); + else + atlas->CustomRectIds[0] = atlas->AddCustomRectRegular(FONT_ATLAS_DEFAULT_TEX_DATA_ID, 2, 2); +} - ImVector& rects = *(ImVector*)p_rects; - if (pass == 0) +void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent) +{ + if (!font_config->MergeMode) { - // Request rectangles - stbrp_rect r; - memset(&r, 0, sizeof(r)); - r.w = (TEX_DATA_W*2)+1; - r.h = TEX_DATA_H+1; - rects.push_back(r); + font->ClearOutputData(); + font->FontSize = font_config->SizePixels; + font->ConfigData = font_config; + font->ContainerAtlas = atlas; + font->Ascent = ascent; + font->Descent = descent; } - else if (pass == 1) + font->ConfigDataCount++; +} + +void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* pack_context_opaque) +{ + stbrp_context* pack_context = (stbrp_context*)pack_context_opaque; + + ImVector& user_rects = atlas->CustomRects; + IM_ASSERT(user_rects.Size >= 1); // We expect at least the default custom rects to be registered, else something went wrong. + + ImVector pack_rects; + pack_rects.resize(user_rects.Size); + memset(pack_rects.Data, 0, sizeof(stbrp_rect) * user_rects.Size); + for (int i = 0; i < user_rects.Size; i++) + { + pack_rects[i].w = user_rects[i].Width; + pack_rects[i].h = user_rects[i].Height; + } + stbrp_pack_rects(pack_context, &pack_rects[0], pack_rects.Size); + for (int i = 0; i < pack_rects.Size; i++) + if (pack_rects[i].was_packed) + { + user_rects[i].X = pack_rects[i].x; + user_rects[i].Y = pack_rects[i].y; + IM_ASSERT(pack_rects[i].w == user_rects[i].Width && pack_rects[i].h == user_rects[i].Height); + atlas->TexHeight = ImMax(atlas->TexHeight, pack_rects[i].y + pack_rects[i].h); + } +} + +static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas) +{ + IM_ASSERT(atlas->CustomRectIds[0] >= 0); + IM_ASSERT(atlas->TexPixelsAlpha8 != NULL); + ImFontAtlas::CustomRect& r = atlas->CustomRects[atlas->CustomRectIds[0]]; + IM_ASSERT(r.ID == FONT_ATLAS_DEFAULT_TEX_DATA_ID); + IM_ASSERT(r.IsPacked()); + + const int w = atlas->TexWidth; + if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors)) { // Render/copy pixels - const stbrp_rect& r = rects[0]; - for (int y = 0, n = 0; y < TEX_DATA_H; y++) - for (int x = 0; x < TEX_DATA_W; x++, n++) + IM_ASSERT(r.Width == FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * 2 + 1 && r.Height == FONT_ATLAS_DEFAULT_TEX_DATA_H); + for (int y = 0, n = 0; y < FONT_ATLAS_DEFAULT_TEX_DATA_H; y++) + for (int x = 0; x < FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF; x++, n++) { - const int offset0 = (int)(r.x + x) + (int)(r.y + y) * TexWidth; - const int offset1 = offset0 + 1 + TEX_DATA_W; - TexPixelsAlpha8[offset0] = texture_data[n] == '.' ? 0xFF : 0x00; - TexPixelsAlpha8[offset1] = texture_data[n] == 'X' ? 0xFF : 0x00; + const int offset0 = (int)(r.X + x) + (int)(r.Y + y) * w; + const int offset1 = offset0 + FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1; + atlas->TexPixelsAlpha8[offset0] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == '.' ? 0xFF : 0x00; + atlas->TexPixelsAlpha8[offset1] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == 'X' ? 0xFF : 0x00; } - const ImVec2 tex_uv_scale(1.0f / TexWidth, 1.0f / TexHeight); - TexUvWhitePixel = ImVec2((r.x + 0.5f) * tex_uv_scale.x, (r.y + 0.5f) * tex_uv_scale.y); + } + else + { + IM_ASSERT(r.Width == 2 && r.Height == 2); + const int offset = (int)(r.X) + (int)(r.Y) * w; + atlas->TexPixelsAlpha8[offset] = atlas->TexPixelsAlpha8[offset + 1] = atlas->TexPixelsAlpha8[offset + w] = atlas->TexPixelsAlpha8[offset + w + 1] = 0xFF; + } + atlas->TexUvWhitePixel = ImVec2((r.X + 0.5f) * atlas->TexUvScale.x, (r.Y + 0.5f) * atlas->TexUvScale.y); +} - // Setup mouse cursors - const ImVec2 cursor_datas[ImGuiMouseCursor_Count_][3] = - { - // Pos ........ Size ......... Offset ...... - { ImVec2(0,3), ImVec2(12,19), ImVec2( 0, 0) }, // ImGuiMouseCursor_Arrow - { ImVec2(13,0), ImVec2(7,16), ImVec2( 4, 8) }, // ImGuiMouseCursor_TextInput - { ImVec2(31,0), ImVec2(23,23), ImVec2(11,11) }, // ImGuiMouseCursor_Move - { ImVec2(21,0), ImVec2( 9,23), ImVec2( 5,11) }, // ImGuiMouseCursor_ResizeNS - { ImVec2(55,18),ImVec2(23, 9), ImVec2(11, 5) }, // ImGuiMouseCursor_ResizeEW - { ImVec2(73,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNESW - { ImVec2(55,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNWSE - }; - - for (int type = 0; type < ImGuiMouseCursor_Count_; type++) - { - ImGuiMouseCursorData& cursor_data = GImGui->MouseCursorData[type]; - ImVec2 pos = cursor_datas[type][0] + ImVec2((float)r.x, (float)r.y); - const ImVec2 size = cursor_datas[type][1]; - cursor_data.Type = type; - cursor_data.Size = size; - cursor_data.HotOffset = cursor_datas[type][2]; - cursor_data.TexUvMin[0] = (pos) * tex_uv_scale; - cursor_data.TexUvMax[0] = (pos + size) * tex_uv_scale; - pos.x += TEX_DATA_W+1; - cursor_data.TexUvMin[1] = (pos) * tex_uv_scale; - cursor_data.TexUvMax[1] = (pos + size) * tex_uv_scale; - } +void ImFontAtlasBuildFinish(ImFontAtlas* atlas) +{ + // Render into our custom data block + ImFontAtlasBuildRenderDefaultTexData(atlas); + + // Register custom rectangle glyphs + for (int i = 0; i < atlas->CustomRects.Size; i++) + { + const ImFontAtlas::CustomRect& r = atlas->CustomRects[i]; + if (r.Font == NULL || r.ID > 0x10000) + continue; + + IM_ASSERT(r.Font->ContainerAtlas == atlas); + ImVec2 uv0, uv1; + atlas->CalcCustomRectUV(&r, &uv0, &uv1); + r.Font->AddGlyph((ImWchar)r.ID, r.GlyphOffset.x, r.GlyphOffset.y, r.GlyphOffset.x + r.Width, r.GlyphOffset.y + r.Height, uv0.x, uv0.y, uv1.x, uv1.y, r.GlyphAdvanceX); } + + // Build all fonts lookup tables + for (int i = 0; i < atlas->Fonts.Size; i++) + if (atlas->Fonts[i]->DirtyLookupTables) + atlas->Fonts[i]->BuildLookupTable(); } // Retrieve list of range (2 int per range, values are inclusive) @@ -1572,7 +2041,7 @@ const ImWchar* ImFontAtlas::GetGlyphRangesKorean() return &ranges[0]; } -const ImWchar* ImFontAtlas::GetGlyphRangesChinese() +const ImWchar* ImFontAtlas::GetGlyphRangesChineseFull() { static const ImWchar ranges[] = { @@ -1586,64 +2055,136 @@ const ImWchar* ImFontAtlas::GetGlyphRangesChinese() return &ranges[0]; } +static void UnpackAccumulativeOffsetsIntoRanges(int base_codepoint, const short* accumulative_offsets, int accumulative_offsets_count, ImWchar* out_ranges) +{ + for (int n = 0; n < accumulative_offsets_count; n++, out_ranges += 2) + { + out_ranges[0] = out_ranges[1] = (ImWchar)(base_codepoint + accumulative_offsets[n]); + base_codepoint += accumulative_offsets[n]; + } + out_ranges[0] = 0; +} + +const ImWchar* ImFontAtlas::GetGlyphRangesChineseSimplifiedCommon() +{ + // Store 2500 regularly used characters for Simplified Chinese. + // Sourced from https://zh.wiktionary.org/wiki/%E9%99%84%E5%BD%95:%E7%8E%B0%E4%BB%A3%E6%B1%89%E8%AF%AD%E5%B8%B8%E7%94%A8%E5%AD%97%E8%A1%A8 + // This table covers 97.97% of all characters used during the month in July, 1987. + // You can use ImFontAtlas::GlyphRangesBuilder to create your own ranges derived from this, by merging existing ranges or adding new characters. + // (Stored as accumulative offsets from the initial unicode codepoint 0x4E00. This encoding is designed to helps us compact the source code size.) + static const short accumulative_offsets_from_0x4E00[] = + { + 0,1,2,4,1,1,1,1,2,1,3,2,1,2,2,1,1,1,1,1,5,2,1,2,3,3,3,2,2,4,1,1,1,2,1,5,2,3,1,2,1,2,1,1,2,1,1,2,2,1,4,1,1,1,1,5,10,1,2,19,2,1,2,1,2,1,2,1,2, + 1,5,1,6,3,2,1,2,2,1,1,1,4,8,5,1,1,4,1,1,3,1,2,1,5,1,2,1,1,1,10,1,1,5,2,4,6,1,4,2,2,2,12,2,1,1,6,1,1,1,4,1,1,4,6,5,1,4,2,2,4,10,7,1,1,4,2,4, + 2,1,4,3,6,10,12,5,7,2,14,2,9,1,1,6,7,10,4,7,13,1,5,4,8,4,1,1,2,28,5,6,1,1,5,2,5,20,2,2,9,8,11,2,9,17,1,8,6,8,27,4,6,9,20,11,27,6,68,2,2,1,1, + 1,2,1,2,2,7,6,11,3,3,1,1,3,1,2,1,1,1,1,1,3,1,1,8,3,4,1,5,7,2,1,4,4,8,4,2,1,2,1,1,4,5,6,3,6,2,12,3,1,3,9,2,4,3,4,1,5,3,3,1,3,7,1,5,1,1,1,1,2, + 3,4,5,2,3,2,6,1,1,2,1,7,1,7,3,4,5,15,2,2,1,5,3,22,19,2,1,1,1,1,2,5,1,1,1,6,1,1,12,8,2,9,18,22,4,1,1,5,1,16,1,2,7,10,15,1,1,6,2,4,1,2,4,1,6, + 1,1,3,2,4,1,6,4,5,1,2,1,1,2,1,10,3,1,3,2,1,9,3,2,5,7,2,19,4,3,6,1,1,1,1,1,4,3,2,1,1,1,2,5,3,1,1,1,2,2,1,1,2,1,1,2,1,3,1,1,1,3,7,1,4,1,1,2,1, + 1,2,1,2,4,4,3,8,1,1,1,2,1,3,5,1,3,1,3,4,6,2,2,14,4,6,6,11,9,1,15,3,1,28,5,2,5,5,3,1,3,4,5,4,6,14,3,2,3,5,21,2,7,20,10,1,2,19,2,4,28,28,2,3, + 2,1,14,4,1,26,28,42,12,40,3,52,79,5,14,17,3,2,2,11,3,4,6,3,1,8,2,23,4,5,8,10,4,2,7,3,5,1,1,6,3,1,2,2,2,5,28,1,1,7,7,20,5,3,29,3,17,26,1,8,4, + 27,3,6,11,23,5,3,4,6,13,24,16,6,5,10,25,35,7,3,2,3,3,14,3,6,2,6,1,4,2,3,8,2,1,1,3,3,3,4,1,1,13,2,2,4,5,2,1,14,14,1,2,2,1,4,5,2,3,1,14,3,12, + 3,17,2,16,5,1,2,1,8,9,3,19,4,2,2,4,17,25,21,20,28,75,1,10,29,103,4,1,2,1,1,4,2,4,1,2,3,24,2,2,2,1,1,2,1,3,8,1,1,1,2,1,1,3,1,1,1,6,1,5,3,1,1, + 1,3,4,1,1,5,2,1,5,6,13,9,16,1,1,1,1,3,2,3,2,4,5,2,5,2,2,3,7,13,7,2,2,1,1,1,1,2,3,3,2,1,6,4,9,2,1,14,2,14,2,1,18,3,4,14,4,11,41,15,23,15,23, + 176,1,3,4,1,1,1,1,5,3,1,2,3,7,3,1,1,2,1,2,4,4,6,2,4,1,9,7,1,10,5,8,16,29,1,1,2,2,3,1,3,5,2,4,5,4,1,1,2,2,3,3,7,1,6,10,1,17,1,44,4,6,2,1,1,6, + 5,4,2,10,1,6,9,2,8,1,24,1,2,13,7,8,8,2,1,4,1,3,1,3,3,5,2,5,10,9,4,9,12,2,1,6,1,10,1,1,7,7,4,10,8,3,1,13,4,3,1,6,1,3,5,2,1,2,17,16,5,2,16,6, + 1,4,2,1,3,3,6,8,5,11,11,1,3,3,2,4,6,10,9,5,7,4,7,4,7,1,1,4,2,1,3,6,8,7,1,6,11,5,5,3,24,9,4,2,7,13,5,1,8,82,16,61,1,1,1,4,2,2,16,10,3,8,1,1, + 6,4,2,1,3,1,1,1,4,3,8,4,2,2,1,1,1,1,1,6,3,5,1,1,4,6,9,2,1,1,1,2,1,7,2,1,6,1,5,4,4,3,1,8,1,3,3,1,3,2,2,2,2,3,1,6,1,2,1,2,1,3,7,1,8,2,1,2,1,5, + 2,5,3,5,10,1,2,1,1,3,2,5,11,3,9,3,5,1,1,5,9,1,2,1,5,7,9,9,8,1,3,3,3,6,8,2,3,2,1,1,32,6,1,2,15,9,3,7,13,1,3,10,13,2,14,1,13,10,2,1,3,10,4,15, + 2,15,15,10,1,3,9,6,9,32,25,26,47,7,3,2,3,1,6,3,4,3,2,8,5,4,1,9,4,2,2,19,10,6,2,3,8,1,2,2,4,2,1,9,4,4,4,6,4,8,9,2,3,1,1,1,1,3,5,5,1,3,8,4,6, + 2,1,4,12,1,5,3,7,13,2,5,8,1,6,1,2,5,14,6,1,5,2,4,8,15,5,1,23,6,62,2,10,1,1,8,1,2,2,10,4,2,2,9,2,1,1,3,2,3,1,5,3,3,2,1,3,8,1,1,1,11,3,1,1,4, + 3,7,1,14,1,2,3,12,5,2,5,1,6,7,5,7,14,11,1,3,1,8,9,12,2,1,11,8,4,4,2,6,10,9,13,1,1,3,1,5,1,3,2,4,4,1,18,2,3,14,11,4,29,4,2,7,1,3,13,9,2,2,5, + 3,5,20,7,16,8,5,72,34,6,4,22,12,12,28,45,36,9,7,39,9,191,1,1,1,4,11,8,4,9,2,3,22,1,1,1,1,4,17,1,7,7,1,11,31,10,2,4,8,2,3,2,1,4,2,16,4,32,2, + 3,19,13,4,9,1,5,2,14,8,1,1,3,6,19,6,5,1,16,6,2,10,8,5,1,2,3,1,5,5,1,11,6,6,1,3,3,2,6,3,8,1,1,4,10,7,5,7,7,5,8,9,2,1,3,4,1,1,3,1,3,3,2,6,16, + 1,4,6,3,1,10,6,1,3,15,2,9,2,10,25,13,9,16,6,2,2,10,11,4,3,9,1,2,6,6,5,4,30,40,1,10,7,12,14,33,6,3,6,7,3,1,3,1,11,14,4,9,5,12,11,49,18,51,31, + 140,31,2,2,1,5,1,8,1,10,1,4,4,3,24,1,10,1,3,6,6,16,3,4,5,2,1,4,2,57,10,6,22,2,22,3,7,22,6,10,11,36,18,16,33,36,2,5,5,1,1,1,4,10,1,4,13,2,7, + 5,2,9,3,4,1,7,43,3,7,3,9,14,7,9,1,11,1,1,3,7,4,18,13,1,14,1,3,6,10,73,2,2,30,6,1,11,18,19,13,22,3,46,42,37,89,7,3,16,34,2,2,3,9,1,7,1,1,1,2, + 2,4,10,7,3,10,3,9,5,28,9,2,6,13,7,3,1,3,10,2,7,2,11,3,6,21,54,85,2,1,4,2,2,1,39,3,21,2,2,5,1,1,1,4,1,1,3,4,15,1,3,2,4,4,2,3,8,2,20,1,8,7,13, + 4,1,26,6,2,9,34,4,21,52,10,4,4,1,5,12,2,11,1,7,2,30,12,44,2,30,1,1,3,6,16,9,17,39,82,2,2,24,7,1,7,3,16,9,14,44,2,1,2,1,2,3,5,2,4,1,6,7,5,3, + 2,6,1,11,5,11,2,1,18,19,8,1,3,24,29,2,1,3,5,2,2,1,13,6,5,1,46,11,3,5,1,1,5,8,2,10,6,12,6,3,7,11,2,4,16,13,2,5,1,1,2,2,5,2,28,5,2,23,10,8,4, + 4,22,39,95,38,8,14,9,5,1,13,5,4,3,13,12,11,1,9,1,27,37,2,5,4,4,63,211,95,2,2,2,1,3,5,2,1,1,2,2,1,1,1,3,2,4,1,2,1,1,5,2,2,1,1,2,3,1,3,1,1,1, + 3,1,4,2,1,3,6,1,1,3,7,15,5,3,2,5,3,9,11,4,2,22,1,6,3,8,7,1,4,28,4,16,3,3,25,4,4,27,27,1,4,1,2,2,7,1,3,5,2,28,8,2,14,1,8,6,16,25,3,3,3,14,3, + 3,1,1,2,1,4,6,3,8,4,1,1,1,2,3,6,10,6,2,3,18,3,2,5,5,4,3,1,5,2,5,4,23,7,6,12,6,4,17,11,9,5,1,1,10,5,12,1,1,11,26,33,7,3,6,1,17,7,1,5,12,1,11, + 2,4,1,8,14,17,23,1,2,1,7,8,16,11,9,6,5,2,6,4,16,2,8,14,1,11,8,9,1,1,1,9,25,4,11,19,7,2,15,2,12,8,52,7,5,19,2,16,4,36,8,1,16,8,24,26,4,6,2,9, + 5,4,36,3,28,12,25,15,37,27,17,12,59,38,5,32,127,1,2,9,17,14,4,1,2,1,1,8,11,50,4,14,2,19,16,4,17,5,4,5,26,12,45,2,23,45,104,30,12,8,3,10,2,2, + 3,3,1,4,20,7,2,9,6,15,2,20,1,3,16,4,11,15,6,134,2,5,59,1,2,2,2,1,9,17,3,26,137,10,211,59,1,2,4,1,4,1,1,1,2,6,2,3,1,1,2,3,2,3,1,3,4,4,2,3,3, + 1,4,3,1,7,2,2,3,1,2,1,3,3,3,2,2,3,2,1,3,14,6,1,3,2,9,6,15,27,9,34,145,1,1,2,1,1,1,1,2,1,1,1,1,2,2,2,3,1,2,1,1,1,2,3,5,8,3,5,2,4,1,3,2,2,2,12, + 4,1,1,1,10,4,5,1,20,4,16,1,15,9,5,12,2,9,2,5,4,2,26,19,7,1,26,4,30,12,15,42,1,6,8,172,1,1,4,2,1,1,11,2,2,4,2,1,2,1,10,8,1,2,1,4,5,1,2,5,1,8, + 4,1,3,4,2,1,6,2,1,3,4,1,2,1,1,1,1,12,5,7,2,4,3,1,1,1,3,3,6,1,2,2,3,3,3,2,1,2,12,14,11,6,6,4,12,2,8,1,7,10,1,35,7,4,13,15,4,3,23,21,28,52,5, + 26,5,6,1,7,10,2,7,53,3,2,1,1,1,2,163,532,1,10,11,1,3,3,4,8,2,8,6,2,2,23,22,4,2,2,4,2,1,3,1,3,3,5,9,8,2,1,2,8,1,10,2,12,21,20,15,105,2,3,1,1, + 3,2,3,1,1,2,5,1,4,15,11,19,1,1,1,1,5,4,5,1,1,2,5,3,5,12,1,2,5,1,11,1,1,15,9,1,4,5,3,26,8,2,1,3,1,1,15,19,2,12,1,2,5,2,7,2,19,2,20,6,26,7,5, + 2,2,7,34,21,13,70,2,128,1,1,2,1,1,2,1,1,3,2,2,2,15,1,4,1,3,4,42,10,6,1,49,85,8,1,2,1,1,4,4,2,3,6,1,5,7,4,3,211,4,1,2,1,2,5,1,2,4,2,2,6,5,6, + 10,3,4,48,100,6,2,16,296,5,27,387,2,2,3,7,16,8,5,38,15,39,21,9,10,3,7,59,13,27,21,47,5,21,6 + }; + static ImWchar base_ranges[] = // not zero-terminated + { + 0x0020, 0x00FF, // Basic Latin + Latin Supplement + 0x3000, 0x30FF, // Punctuations, Hiragana, Katakana + 0x31F0, 0x31FF, // Katakana Phonetic Extensions + 0xFF00, 0xFFEF, // Half-width characters + }; + static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00) * 2 + 1] = { 0 }; + if (!full_ranges[0]) + { + memcpy(full_ranges, base_ranges, sizeof(base_ranges)); + UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_ARRAYSIZE(accumulative_offsets_from_0x4E00), full_ranges + IM_ARRAYSIZE(base_ranges)); + } + return &full_ranges[0]; +} + const ImWchar* ImFontAtlas::GetGlyphRangesJapanese() { - // Store the 1946 ideograms code points as successive offsets from the initial unicode codepoint 0x4E00. Each offset has an implicit +1. - // This encoding helps us reduce the source code size. - static const short offsets_from_0x4E00[] = - { - -1,0,1,3,0,0,0,0,1,0,5,1,1,0,7,4,6,10,0,1,9,9,7,1,3,19,1,10,7,1,0,1,0,5,1,0,6,4,2,6,0,0,12,6,8,0,3,5,0,1,0,9,0,0,8,1,1,3,4,5,13,0,0,8,2,17, - 4,3,1,1,9,6,0,0,0,2,1,3,2,22,1,9,11,1,13,1,3,12,0,5,9,2,0,6,12,5,3,12,4,1,2,16,1,1,4,6,5,3,0,6,13,15,5,12,8,14,0,0,6,15,3,6,0,18,8,1,6,14,1, - 5,4,12,24,3,13,12,10,24,0,0,0,1,0,1,1,2,9,10,2,2,0,0,3,3,1,0,3,8,0,3,2,4,4,1,6,11,10,14,6,15,3,4,15,1,0,0,5,2,2,0,0,1,6,5,5,6,0,3,6,5,0,0,1,0, - 11,2,2,8,4,7,0,10,0,1,2,17,19,3,0,2,5,0,6,2,4,4,6,1,1,11,2,0,3,1,2,1,2,10,7,6,3,16,0,8,24,0,0,3,1,1,3,0,1,6,0,0,0,2,0,1,5,15,0,1,0,0,2,11,19, - 1,4,19,7,6,5,1,0,0,0,0,5,1,0,1,9,0,0,5,0,2,0,1,0,3,0,11,3,0,2,0,0,0,0,0,9,3,6,4,12,0,14,0,0,29,10,8,0,14,37,13,0,31,16,19,0,8,30,1,20,8,3,48, - 21,1,0,12,0,10,44,34,42,54,11,18,82,0,2,1,2,12,1,0,6,2,17,2,12,7,0,7,17,4,2,6,24,23,8,23,39,2,16,23,1,0,5,1,2,15,14,5,6,2,11,0,8,6,2,2,2,14, - 20,4,15,3,4,11,10,10,2,5,2,1,30,2,1,0,0,22,5,5,0,3,1,5,4,1,0,0,2,2,21,1,5,1,2,16,2,1,3,4,0,8,4,0,0,5,14,11,2,16,1,13,1,7,0,22,15,3,1,22,7,14, - 22,19,11,24,18,46,10,20,64,45,3,2,0,4,5,0,1,4,25,1,0,0,2,10,0,0,0,1,0,1,2,0,0,9,1,2,0,0,0,2,5,2,1,1,5,5,8,1,1,1,5,1,4,9,1,3,0,1,0,1,1,2,0,0, - 2,0,1,8,22,8,1,0,0,0,0,4,2,1,0,9,8,5,0,9,1,30,24,2,6,4,39,0,14,5,16,6,26,179,0,2,1,1,0,0,0,5,2,9,6,0,2,5,16,7,5,1,1,0,2,4,4,7,15,13,14,0,0, - 3,0,1,0,0,0,2,1,6,4,5,1,4,9,0,3,1,8,0,0,10,5,0,43,0,2,6,8,4,0,2,0,0,9,6,0,9,3,1,6,20,14,6,1,4,0,7,2,3,0,2,0,5,0,3,1,0,3,9,7,0,3,4,0,4,9,1,6,0, - 9,0,0,2,3,10,9,28,3,6,2,4,1,2,32,4,1,18,2,0,3,1,5,30,10,0,2,2,2,0,7,9,8,11,10,11,7,2,13,7,5,10,0,3,40,2,0,1,6,12,0,4,5,1,5,11,11,21,4,8,3,7, - 8,8,33,5,23,0,0,19,8,8,2,3,0,6,1,1,1,5,1,27,4,2,5,0,3,5,6,3,1,0,3,1,12,5,3,3,2,0,7,7,2,1,0,4,0,1,1,2,0,10,10,6,2,5,9,7,5,15,15,21,6,11,5,20, - 4,3,5,5,2,5,0,2,1,0,1,7,28,0,9,0,5,12,5,5,18,30,0,12,3,3,21,16,25,32,9,3,14,11,24,5,66,9,1,2,0,5,9,1,5,1,8,0,8,3,3,0,1,15,1,4,8,1,2,7,0,7,2, - 8,3,7,5,3,7,10,2,1,0,0,2,25,0,6,4,0,10,0,4,2,4,1,12,5,38,4,0,4,1,10,5,9,4,0,14,4,2,5,18,20,21,1,3,0,5,0,7,0,3,7,1,3,1,1,8,1,0,0,0,3,2,5,2,11, - 6,0,13,1,3,9,1,12,0,16,6,2,1,0,2,1,12,6,13,11,2,0,28,1,7,8,14,13,8,13,0,2,0,5,4,8,10,2,37,42,19,6,6,7,4,14,11,18,14,80,7,6,0,4,72,12,36,27, - 7,7,0,14,17,19,164,27,0,5,10,7,3,13,6,14,0,2,2,5,3,0,6,13,0,0,10,29,0,4,0,3,13,0,3,1,6,51,1,5,28,2,0,8,0,20,2,4,0,25,2,10,13,10,0,16,4,0,1,0, - 2,1,7,0,1,8,11,0,0,1,2,7,2,23,11,6,6,4,16,2,2,2,0,22,9,3,3,5,2,0,15,16,21,2,9,20,15,15,5,3,9,1,0,0,1,7,7,5,4,2,2,2,38,24,14,0,0,15,5,6,24,14, - 5,5,11,0,21,12,0,3,8,4,11,1,8,0,11,27,7,2,4,9,21,59,0,1,39,3,60,62,3,0,12,11,0,3,30,11,0,13,88,4,15,5,28,13,1,4,48,17,17,4,28,32,46,0,16,0, - 18,11,1,8,6,38,11,2,6,11,38,2,0,45,3,11,2,7,8,4,30,14,17,2,1,1,65,18,12,16,4,2,45,123,12,56,33,1,4,3,4,7,0,0,0,3,2,0,16,4,2,4,2,0,7,4,5,2,26, - 2,25,6,11,6,1,16,2,6,17,77,15,3,35,0,1,0,5,1,0,38,16,6,3,12,3,3,3,0,9,3,1,3,5,2,9,0,18,0,25,1,3,32,1,72,46,6,2,7,1,3,14,17,0,28,1,40,13,0,20, - 15,40,6,38,24,12,43,1,1,9,0,12,6,0,6,2,4,19,3,7,1,48,0,9,5,0,5,6,9,6,10,15,2,11,19,3,9,2,0,1,10,1,27,8,1,3,6,1,14,0,26,0,27,16,3,4,9,6,2,23, - 9,10,5,25,2,1,6,1,1,48,15,9,15,14,3,4,26,60,29,13,37,21,1,6,4,0,2,11,22,23,16,16,2,2,1,3,0,5,1,6,4,0,0,4,0,0,8,3,0,2,5,0,7,1,7,3,13,2,4,10, - 3,0,2,31,0,18,3,0,12,10,4,1,0,7,5,7,0,5,4,12,2,22,10,4,2,15,2,8,9,0,23,2,197,51,3,1,1,4,13,4,3,21,4,19,3,10,5,40,0,4,1,1,10,4,1,27,34,7,21, - 2,17,2,9,6,4,2,3,0,4,2,7,8,2,5,1,15,21,3,4,4,2,2,17,22,1,5,22,4,26,7,0,32,1,11,42,15,4,1,2,5,0,19,3,1,8,6,0,10,1,9,2,13,30,8,2,24,17,19,1,4, - 4,25,13,0,10,16,11,39,18,8,5,30,82,1,6,8,18,77,11,13,20,75,11,112,78,33,3,0,0,60,17,84,9,1,1,12,30,10,49,5,32,158,178,5,5,6,3,3,1,3,1,4,7,6, - 19,31,21,0,2,9,5,6,27,4,9,8,1,76,18,12,1,4,0,3,3,6,3,12,2,8,30,16,2,25,1,5,5,4,3,0,6,10,2,3,1,0,5,1,19,3,0,8,1,5,2,6,0,0,0,19,1,2,0,5,1,2,5, - 1,3,7,0,4,12,7,3,10,22,0,9,5,1,0,2,20,1,1,3,23,30,3,9,9,1,4,191,14,3,15,6,8,50,0,1,0,0,4,0,0,1,0,2,4,2,0,2,3,0,2,0,2,2,8,7,0,1,1,1,3,3,17,11, - 91,1,9,3,2,13,4,24,15,41,3,13,3,1,20,4,125,29,30,1,0,4,12,2,21,4,5,5,19,11,0,13,11,86,2,18,0,7,1,8,8,2,2,22,1,2,6,5,2,0,1,2,8,0,2,0,5,2,1,0, - 2,10,2,0,5,9,2,1,2,0,1,0,4,0,0,10,2,5,3,0,6,1,0,1,4,4,33,3,13,17,3,18,6,4,7,1,5,78,0,4,1,13,7,1,8,1,0,35,27,15,3,0,0,0,1,11,5,41,38,15,22,6, - 14,14,2,1,11,6,20,63,5,8,27,7,11,2,2,40,58,23,50,54,56,293,8,8,1,5,1,14,0,1,12,37,89,8,8,8,2,10,6,0,0,0,4,5,2,1,0,1,1,2,7,0,3,3,0,4,6,0,3,2, - 19,3,8,0,0,0,4,4,16,0,4,1,5,1,3,0,3,4,6,2,17,10,10,31,6,4,3,6,10,126,7,3,2,2,0,9,0,0,5,20,13,0,15,0,6,0,2,5,8,64,50,3,2,12,2,9,0,0,11,8,20, - 109,2,18,23,0,0,9,61,3,0,28,41,77,27,19,17,81,5,2,14,5,83,57,252,14,154,263,14,20,8,13,6,57,39,38, + // 1946 common ideograms code points for Japanese + // Sourced from http://theinstructionlimit.com/common-kanji-character-ranges-for-xna-spritefont-rendering + // FIXME: Source a list of the revised 2136 Joyo Kanji list from 2010 and rebuild this. + // You can use ImFontAtlas::GlyphRangesBuilder to create your own ranges derived from this, by merging existing ranges or adding new characters. + // (Stored as accumulative offsets from the initial unicode codepoint 0x4E00. This encoding is designed to helps us compact the source code size.) + static const short accumulative_offsets_from_0x4E00[] = + { + 0,1,2,4,1,1,1,1,2,1,6,2,2,1,8,5,7,11,1,2,10,10,8,2,4,20,2,11,8,2,1,2,1,6,2,1,7,5,3,7,1,1,13,7,9,1,4,6,1,2,1,10,1,1,9,2,2,4,5,6,14,1,1,9,3,18, + 5,4,2,2,10,7,1,1,1,3,2,4,3,23,2,10,12,2,14,2,4,13,1,6,10,3,1,7,13,6,4,13,5,2,3,17,2,2,5,7,6,4,1,7,14,16,6,13,9,15,1,1,7,16,4,7,1,19,9,2,7,15, + 2,6,5,13,25,4,14,13,11,25,1,1,1,2,1,2,2,3,10,11,3,3,1,1,4,4,2,1,4,9,1,4,3,5,5,2,7,12,11,15,7,16,4,5,16,2,1,1,6,3,3,1,1,2,7,6,6,7,1,4,7,6,1,1, + 2,1,12,3,3,9,5,8,1,11,1,2,3,18,20,4,1,3,6,1,7,3,5,5,7,2,2,12,3,1,4,2,3,2,3,11,8,7,4,17,1,9,25,1,1,4,2,2,4,1,2,7,1,1,1,3,1,2,6,16,1,2,1,1,3,12, + 20,2,5,20,8,7,6,2,1,1,1,1,6,2,1,2,10,1,1,6,1,3,1,2,1,4,1,12,4,1,3,1,1,1,1,1,10,4,7,5,13,1,15,1,1,30,11,9,1,15,38,14,1,32,17,20,1,9,31,2,21,9, + 4,49,22,2,1,13,1,11,45,35,43,55,12,19,83,1,3,2,3,13,2,1,7,3,18,3,13,8,1,8,18,5,3,7,25,24,9,24,40,3,17,24,2,1,6,2,3,16,15,6,7,3,12,1,9,7,3,3, + 3,15,21,5,16,4,5,12,11,11,3,6,3,2,31,3,2,1,1,23,6,6,1,4,2,6,5,2,1,1,3,3,22,2,6,2,3,17,3,2,4,5,1,9,5,1,1,6,15,12,3,17,2,14,2,8,1,23,16,4,2,23, + 8,15,23,20,12,25,19,47,11,21,65,46,4,3,1,5,6,1,2,5,26,2,1,1,3,11,1,1,1,2,1,2,3,1,1,10,2,3,1,1,1,3,6,3,2,2,6,6,9,2,2,2,6,2,5,10,2,4,1,2,1,2,2, + 3,1,1,3,1,2,9,23,9,2,1,1,1,1,5,3,2,1,10,9,6,1,10,2,31,25,3,7,5,40,1,15,6,17,7,27,180,1,3,2,2,1,1,1,6,3,10,7,1,3,6,17,8,6,2,2,1,3,5,5,8,16,14, + 15,1,1,4,1,2,1,1,1,3,2,7,5,6,2,5,10,1,4,2,9,1,1,11,6,1,44,1,3,7,9,5,1,3,1,1,10,7,1,10,4,2,7,21,15,7,2,5,1,8,3,4,1,3,1,6,1,4,2,1,4,10,8,1,4,5, + 1,5,10,2,7,1,10,1,1,3,4,11,10,29,4,7,3,5,2,3,33,5,2,19,3,1,4,2,6,31,11,1,3,3,3,1,8,10,9,12,11,12,8,3,14,8,6,11,1,4,41,3,1,2,7,13,1,5,6,2,6,12, + 12,22,5,9,4,8,9,9,34,6,24,1,1,20,9,9,3,4,1,7,2,2,2,6,2,28,5,3,6,1,4,6,7,4,2,1,4,2,13,6,4,4,3,1,8,8,3,2,1,5,1,2,2,3,1,11,11,7,3,6,10,8,6,16,16, + 22,7,12,6,21,5,4,6,6,3,6,1,3,2,1,2,8,29,1,10,1,6,13,6,6,19,31,1,13,4,4,22,17,26,33,10,4,15,12,25,6,67,10,2,3,1,6,10,2,6,2,9,1,9,4,4,1,2,16,2, + 5,9,2,3,8,1,8,3,9,4,8,6,4,8,11,3,2,1,1,3,26,1,7,5,1,11,1,5,3,5,2,13,6,39,5,1,5,2,11,6,10,5,1,15,5,3,6,19,21,22,2,4,1,6,1,8,1,4,8,2,4,2,2,9,2, + 1,1,1,4,3,6,3,12,7,1,14,2,4,10,2,13,1,17,7,3,2,1,3,2,13,7,14,12,3,1,29,2,8,9,15,14,9,14,1,3,1,6,5,9,11,3,38,43,20,7,7,8,5,15,12,19,15,81,8,7, + 1,5,73,13,37,28,8,8,1,15,18,20,165,28,1,6,11,8,4,14,7,15,1,3,3,6,4,1,7,14,1,1,11,30,1,5,1,4,14,1,4,2,7,52,2,6,29,3,1,9,1,21,3,5,1,26,3,11,14, + 11,1,17,5,1,2,1,3,2,8,1,2,9,12,1,1,2,3,8,3,24,12,7,7,5,17,3,3,3,1,23,10,4,4,6,3,1,16,17,22,3,10,21,16,16,6,4,10,2,1,1,2,8,8,6,5,3,3,3,39,25, + 15,1,1,16,6,7,25,15,6,6,12,1,22,13,1,4,9,5,12,2,9,1,12,28,8,3,5,10,22,60,1,2,40,4,61,63,4,1,13,12,1,4,31,12,1,14,89,5,16,6,29,14,2,5,49,18,18, + 5,29,33,47,1,17,1,19,12,2,9,7,39,12,3,7,12,39,3,1,46,4,12,3,8,9,5,31,15,18,3,2,2,66,19,13,17,5,3,46,124,13,57,34,2,5,4,5,8,1,1,1,4,3,1,17,5, + 3,5,3,1,8,5,6,3,27,3,26,7,12,7,2,17,3,7,18,78,16,4,36,1,2,1,6,2,1,39,17,7,4,13,4,4,4,1,10,4,2,4,6,3,10,1,19,1,26,2,4,33,2,73,47,7,3,8,2,4,15, + 18,1,29,2,41,14,1,21,16,41,7,39,25,13,44,2,2,10,1,13,7,1,7,3,5,20,4,8,2,49,1,10,6,1,6,7,10,7,11,16,3,12,20,4,10,3,1,2,11,2,28,9,2,4,7,2,15,1, + 27,1,28,17,4,5,10,7,3,24,10,11,6,26,3,2,7,2,2,49,16,10,16,15,4,5,27,61,30,14,38,22,2,7,5,1,3,12,23,24,17,17,3,3,2,4,1,6,2,7,5,1,1,5,1,1,9,4, + 1,3,6,1,8,2,8,4,14,3,5,11,4,1,3,32,1,19,4,1,13,11,5,2,1,8,6,8,1,6,5,13,3,23,11,5,3,16,3,9,10,1,24,3,198,52,4,2,2,5,14,5,4,22,5,20,4,11,6,41, + 1,5,2,2,11,5,2,28,35,8,22,3,18,3,10,7,5,3,4,1,5,3,8,9,3,6,2,16,22,4,5,5,3,3,18,23,2,6,23,5,27,8,1,33,2,12,43,16,5,2,3,6,1,20,4,2,9,7,1,11,2, + 10,3,14,31,9,3,25,18,20,2,5,5,26,14,1,11,17,12,40,19,9,6,31,83,2,7,9,19,78,12,14,21,76,12,113,79,34,4,1,1,61,18,85,10,2,2,13,31,11,50,6,33,159, + 179,6,6,7,4,4,2,4,2,5,8,7,20,32,22,1,3,10,6,7,28,5,10,9,2,77,19,13,2,5,1,4,4,7,4,13,3,9,31,17,3,26,2,6,6,5,4,1,7,11,3,4,2,1,6,2,20,4,1,9,2,6, + 3,7,1,1,1,20,2,3,1,6,2,3,6,2,4,8,1,5,13,8,4,11,23,1,10,6,2,1,3,21,2,2,4,24,31,4,10,10,2,5,192,15,4,16,7,9,51,1,2,1,1,5,1,1,2,1,3,5,3,1,3,4,1, + 3,1,3,3,9,8,1,2,2,2,4,4,18,12,92,2,10,4,3,14,5,25,16,42,4,14,4,2,21,5,126,30,31,2,1,5,13,3,22,5,6,6,20,12,1,14,12,87,3,19,1,8,2,9,9,3,3,23,2, + 3,7,6,3,1,2,3,9,1,3,1,6,3,2,1,3,11,3,1,6,10,3,2,3,1,2,1,5,1,1,11,3,6,4,1,7,2,1,2,5,5,34,4,14,18,4,19,7,5,8,2,6,79,1,5,2,14,8,2,9,2,1,36,28,16, + 4,1,1,1,2,12,6,42,39,16,23,7,15,15,3,2,12,7,21,64,6,9,28,8,12,3,3,41,59,24,51,55,57,294,9,9,2,6,2,15,1,2,13,38,90,9,9,9,3,11,7,1,1,1,5,6,3,2, + 1,2,2,3,8,1,4,4,1,5,7,1,4,3,20,4,9,1,1,1,5,5,17,1,5,2,6,2,4,1,4,5,7,3,18,11,11,32,7,5,4,7,11,127,8,4,3,3,1,10,1,1,6,21,14,1,16,1,7,1,3,6,9,65, + 51,4,3,13,3,10,1,1,12,9,21,110,3,19,24,1,1,10,62,4,1,29,42,78,28,20,18,82,6,3,15,6,84,58,253,15,155,264,15,21,9,14,7,58,40,39, }; - static ImWchar base_ranges[] = + static ImWchar base_ranges[] = // not zero-terminated { 0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x3000, 0x30FF, // Punctuations, Hiragana, Katakana 0x31F0, 0x31FF, // Katakana Phonetic Extensions 0xFF00, 0xFFEF, // Half-width characters }; - static bool full_ranges_unpacked = false; - static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(offsets_from_0x4E00)*2 + 1]; - if (!full_ranges_unpacked) + static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00)*2 + 1] = { 0 }; + if (!full_ranges[0]) { - // Unpack - int codepoint = 0x4e00; memcpy(full_ranges, base_ranges, sizeof(base_ranges)); - ImWchar* dst = full_ranges + IM_ARRAYSIZE(base_ranges);; - for (int n = 0; n < IM_ARRAYSIZE(offsets_from_0x4E00); n++, dst += 2) - dst[0] = dst[1] = (ImWchar)(codepoint += (offsets_from_0x4E00[n] + 1)); - dst[0] = 0; - full_ranges_unpacked = true; + UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_ARRAYSIZE(accumulative_offsets_from_0x4E00), full_ranges + IM_ARRAYSIZE(base_ranges)); } return &full_ranges[0]; } @@ -1666,12 +2207,51 @@ const ImWchar* ImFontAtlas::GetGlyphRangesThai() static const ImWchar ranges[] = { 0x0020, 0x00FF, // Basic Latin + 0x2010, 0x205E, // Punctuations 0x0E00, 0x0E7F, // Thai 0, }; return &ranges[0]; } +//----------------------------------------------------------------------------- +// ImFontAtlas::GlyphRangesBuilder +//----------------------------------------------------------------------------- + +void ImFontAtlas::GlyphRangesBuilder::AddText(const char* text, const char* text_end) +{ + while (text_end ? (text < text_end) : *text) + { + unsigned int c = 0; + int c_len = ImTextCharFromUtf8(&c, text, text_end); + text += c_len; + if (c_len == 0) + break; + if (c < 0x10000) + AddChar((ImWchar)c); + } +} + +void ImFontAtlas::GlyphRangesBuilder::AddRanges(const ImWchar* ranges) +{ + for (; ranges[0]; ranges += 2) + for (ImWchar c = ranges[0]; c <= ranges[1]; c++) + AddChar(c); +} + +void ImFontAtlas::GlyphRangesBuilder::BuildRanges(ImVector* out_ranges) +{ + for (int n = 0; n < 0x10000; n++) + if (GetBit(n)) + { + out_ranges->push_back((ImWchar)n); + while (n < 0x10000 && GetBit(n + 1)) + n++; + out_ranges->push_back((ImWchar)n); + } + out_ranges->push_back(0); +} + //----------------------------------------------------------------------------- // ImFont //----------------------------------------------------------------------------- @@ -1680,7 +2260,8 @@ ImFont::ImFont() { Scale = 1.0f; FallbackChar = (ImWchar)'?'; - Clear(); + DisplayOffset = ImVec2(0.0f, 0.0f); + ClearOutputData(); } ImFont::~ImFont() @@ -1693,22 +2274,22 @@ ImFont::~ImFont() if (g.Font == this) g.Font = NULL; */ - Clear(); + ClearOutputData(); } -void ImFont::Clear() +void ImFont::ClearOutputData() { FontSize = 0.0f; - DisplayOffset = ImVec2(0.0f, 1.0f); Glyphs.clear(); - IndexXAdvance.clear(); + IndexAdvanceX.clear(); IndexLookup.clear(); FallbackGlyph = NULL; - FallbackXAdvance = 0.0f; + FallbackAdvanceX = 0.0f; ConfigDataCount = 0; ConfigData = NULL; ContainerAtlas = NULL; Ascent = Descent = 0.0f; + DirtyLookupTables = true; MetricsTotalSurface = 0; } @@ -1719,13 +2300,14 @@ void ImFont::BuildLookupTable() max_codepoint = ImMax(max_codepoint, (int)Glyphs[i].Codepoint); IM_ASSERT(Glyphs.Size < 0xFFFF); // -1 is reserved - IndexXAdvance.clear(); + IndexAdvanceX.clear(); IndexLookup.clear(); + DirtyLookupTables = false; GrowIndex(max_codepoint + 1); for (int i = 0; i < Glyphs.Size; i++) { int codepoint = (int)Glyphs[i].Codepoint; - IndexXAdvance[codepoint] = Glyphs[i].XAdvance; + IndexAdvanceX[codepoint] = Glyphs[i].AdvanceX; IndexLookup[codepoint] = (unsigned short)i; } @@ -1735,20 +2317,19 @@ void ImFont::BuildLookupTable() { if (Glyphs.back().Codepoint != '\t') // So we can call this function multiple times Glyphs.resize(Glyphs.Size + 1); - ImFont::Glyph& tab_glyph = Glyphs.back(); + ImFontGlyph& tab_glyph = Glyphs.back(); tab_glyph = *FindGlyph((unsigned short)' '); tab_glyph.Codepoint = '\t'; - tab_glyph.XAdvance *= 4; - IndexXAdvance[(int)tab_glyph.Codepoint] = (float)tab_glyph.XAdvance; + tab_glyph.AdvanceX *= 4; + IndexAdvanceX[(int)tab_glyph.Codepoint] = (float)tab_glyph.AdvanceX; IndexLookup[(int)tab_glyph.Codepoint] = (unsigned short)(Glyphs.Size-1); } - FallbackGlyph = NULL; - FallbackGlyph = FindGlyph(FallbackChar); - FallbackXAdvance = FallbackGlyph ? FallbackGlyph->XAdvance : 0.0f; + FallbackGlyph = FindGlyphNoFallback(FallbackChar); + FallbackAdvanceX = FallbackGlyph ? FallbackGlyph->AdvanceX : 0.0f; for (int i = 0; i < max_codepoint + 1; i++) - if (IndexXAdvance[i] < 0.0f) - IndexXAdvance[i] = FallbackXAdvance; + if (IndexAdvanceX[i] < 0.0f) + IndexAdvanceX[i] = FallbackAdvanceX; } void ImFont::SetFallbackChar(ImWchar c) @@ -1759,17 +2340,36 @@ void ImFont::SetFallbackChar(ImWchar c) void ImFont::GrowIndex(int new_size) { - IM_ASSERT(IndexXAdvance.Size == IndexLookup.Size); - int old_size = IndexLookup.Size; - if (new_size <= old_size) + IM_ASSERT(IndexAdvanceX.Size == IndexLookup.Size); + if (new_size <= IndexLookup.Size) return; - IndexXAdvance.resize(new_size); - IndexLookup.resize(new_size); - for (int i = old_size; i < new_size; i++) - { - IndexXAdvance[i] = -1.0f; - IndexLookup[i] = (unsigned short)-1; - } + IndexAdvanceX.resize(new_size, -1.0f); + IndexLookup.resize(new_size, (unsigned short)-1); +} + +// x0/y0/x1/y1 are offset from the character upper-left layout position, in pixels. Therefore x0/y0 are often fairly close to zero. +// Not to be mistaken with texture coordinates, which are held by u0/v0/u1/v1 in normalized format (0.0..1.0 on each texture axis). +void ImFont::AddGlyph(ImWchar codepoint, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x) +{ + Glyphs.resize(Glyphs.Size + 1); + ImFontGlyph& glyph = Glyphs.back(); + glyph.Codepoint = (ImWchar)codepoint; + glyph.X0 = x0; + glyph.Y0 = y0; + glyph.X1 = x1; + glyph.Y1 = y1; + glyph.U0 = u0; + glyph.V0 = v0; + glyph.U1 = u1; + glyph.V1 = v1; + glyph.AdvanceX = advance_x + ConfigData->GlyphExtraSpacing.x; // Bake spacing into AdvanceX + + if (ConfigData->PixelSnapH) + glyph.AdvanceX = (float)(int)(glyph.AdvanceX + 0.5f); + + // Compute rough surface usage metrics (+1 to account for average padding, +0.99 to round) + DirtyLookupTables = true; + MetricsTotalSurface += (int)((glyph.U1 - glyph.U0) * ContainerAtlas->TexWidth + 1.99f) * (int)((glyph.V1 - glyph.V0) * ContainerAtlas->TexHeight + 1.99f); } void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst) @@ -1784,18 +2384,27 @@ void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst) GrowIndex(dst + 1); IndexLookup[dst] = (src < index_size) ? IndexLookup.Data[src] : (unsigned short)-1; - IndexXAdvance[dst] = (src < index_size) ? IndexXAdvance.Data[src] : 1.0f; + IndexAdvanceX[dst] = (src < index_size) ? IndexAdvanceX.Data[src] : 1.0f; } -const ImFont::Glyph* ImFont::FindGlyph(unsigned short c) const +const ImFontGlyph* ImFont::FindGlyph(ImWchar c) const { - if (c < IndexLookup.Size) - { - const unsigned short i = IndexLookup[c]; - if (i != (unsigned short)-1) - return &Glyphs.Data[i]; - } - return FallbackGlyph; + if (c >= IndexLookup.Size) + return FallbackGlyph; + const unsigned short i = IndexLookup[c]; + if (i == (unsigned short)-1) + return FallbackGlyph; + return &Glyphs.Data[i]; +} + +const ImFontGlyph* ImFont::FindGlyphNoFallback(ImWchar c) const +{ + if (c >= IndexLookup.Size) + return NULL; + const unsigned short i = IndexLookup[c]; + if (i == (unsigned short)-1) + return NULL; + return &Glyphs.Data[i]; } const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const @@ -1818,6 +2427,7 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c float line_width = 0.0f; float word_width = 0.0f; float blank_width = 0.0f; + wrap_width /= scale; // We work with unscaled widths to avoid scaling every characters const char* word_end = text; const char* prev_word_end = NULL; @@ -1851,8 +2461,8 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c } } - const float char_width = ((int)c < IndexXAdvance.Size ? IndexXAdvance[(int)c] : FallbackXAdvance) * scale; - if (ImCharIsSpace(c)) + const float char_width = ((int)c < IndexAdvanceX.Size ? IndexAdvanceX[(int)c] : FallbackAdvanceX); + if (ImCharIsBlankW(c)) { if (inside_word) { @@ -1935,7 +2545,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons while (s < text_end) { const char c = *s; - if (ImCharIsSpace(c)) { s++; } else if (c == '\n') { s++; break; } else { break; } + if (ImCharIsBlankA(c)) { s++; } else if (c == '\n') { s++; break; } else { break; } } continue; } @@ -1968,7 +2578,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons continue; } - const float char_width = ((int)c < IndexXAdvance.Size ? IndexXAdvance[(int)c] : FallbackXAdvance) * scale; + const float char_width = ((int)c < IndexAdvanceX.Size ? IndexAdvanceX[(int)c] : FallbackAdvanceX) * scale; if (line_width + char_width >= max_width) { s = prev_s; @@ -1994,15 +2604,13 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col { if (c == ' ' || c == '\t' || c == '\n' || c == '\r') // Match behavior of RenderText(), those 4 codepoints are hard-coded. return; - if (const Glyph* glyph = FindGlyph(c)) + if (const ImFontGlyph* glyph = FindGlyph(c)) { float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f; pos.x = (float)(int)pos.x + DisplayOffset.x; pos.y = (float)(int)pos.y + DisplayOffset.y; - ImVec2 pos_tl(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale); - ImVec2 pos_br(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale); draw_list->PrimReserve(6, 4); - draw_list->PrimRectUV(pos_tl, pos_br, ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col); + draw_list->PrimRectUV(ImVec2(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale), ImVec2(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col); } } @@ -2062,7 +2670,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col while (s < text_end) { const char c = *s; - if (ImCharIsSpace(c)) { s++; } else if (c == '\n') { s++; break; } else { break; } + if (ImCharIsBlankA(c)) { s++; } else if (c == '\n') { s++; break; } else { break; } } continue; } @@ -2100,9 +2708,9 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col } float char_width = 0.0f; - if (const Glyph* glyph = FindGlyph((unsigned short)c)) + if (const ImFontGlyph* glyph = FindGlyph((unsigned short)c)) { - char_width = glyph->XAdvance * scale; + char_width = glyph->AdvanceX * scale; // Arbitrarily assume that both space and tabs are empty glyphs as an optimization if (c != ' ' && c != '\t') @@ -2150,8 +2758,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col } } - // We are NOT calling PrimRectUV() here because non-inlined causes too much overhead in a debug build. - // Inlined here: + // We are NOT calling PrimRectUV() here because non-inlined causes too much overhead in a debug builds. Inlined here: { idx_write[0] = (ImDrawIdx)(vtx_current_idx); idx_write[1] = (ImDrawIdx)(vtx_current_idx+1); idx_write[2] = (ImDrawIdx)(vtx_current_idx+2); idx_write[3] = (ImDrawIdx)(vtx_current_idx); idx_write[4] = (ImDrawIdx)(vtx_current_idx+2); idx_write[5] = (ImDrawIdx)(vtx_current_idx+3); @@ -2179,35 +2786,152 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col draw_list->_VtxCurrentIdx = (unsigned int)draw_list->VtxBuffer.Size; } +//----------------------------------------------------------------------------- +// Internals Render Helpers +// (progressively moved from imgui.cpp to here when they are redesigned to stop accessing ImGui global state) +//----------------------------------------------------------------------------- +// RenderMouseCursor() +// RenderArrowPointingAt() +// RenderRectFilledRangeH() +//----------------------------------------------------------------------------- + +void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor) +{ + if (mouse_cursor == ImGuiMouseCursor_None) + return; + IM_ASSERT(mouse_cursor > ImGuiMouseCursor_None && mouse_cursor < ImGuiMouseCursor_COUNT); + + const ImU32 col_shadow = IM_COL32(0, 0, 0, 48); + const ImU32 col_border = IM_COL32(0, 0, 0, 255); // Black + const ImU32 col_fill = IM_COL32(255, 255, 255, 255); // White + + ImFontAtlas* font_atlas = draw_list->_Data->Font->ContainerAtlas; + ImVec2 offset, size, uv[4]; + if (font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2])) + { + pos -= offset; + const ImTextureID tex_id = font_atlas->TexID; + draw_list->PushTextureID(tex_id); + draw_list->AddImage(tex_id, pos + ImVec2(1,0)*scale, pos + ImVec2(1,0)*scale + size*scale, uv[2], uv[3], col_shadow); + draw_list->AddImage(tex_id, pos + ImVec2(2,0)*scale, pos + ImVec2(2,0)*scale + size*scale, uv[2], uv[3], col_shadow); + draw_list->AddImage(tex_id, pos, pos + size*scale, uv[2], uv[3], col_border); + draw_list->AddImage(tex_id, pos, pos + size*scale, uv[0], uv[1], col_fill); + draw_list->PopTextureID(); + } +} + +// Render an arrow. 'pos' is position of the arrow tip. half_sz.x is length from base to tip. half_sz.y is length on each side. +void ImGui::RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col) +{ + switch (direction) + { + case ImGuiDir_Left: draw_list->AddTriangleFilled(ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), ImVec2(pos.x + half_sz.x, pos.y + half_sz.y), pos, col); return; + case ImGuiDir_Right: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), pos, col); return; + case ImGuiDir_Up: draw_list->AddTriangleFilled(ImVec2(pos.x + half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), pos, col); return; + case ImGuiDir_Down: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), pos, col); return; + case ImGuiDir_None: case ImGuiDir_COUNT: break; // Fix warnings + } +} + +static inline float ImAcos01(float x) +{ + if (x <= 0.0f) return IM_PI * 0.5f; + if (x >= 1.0f) return 0.0f; + return ImAcos(x); + //return (-0.69813170079773212f * x * x - 0.87266462599716477f) * x + 1.5707963267948966f; // Cheap approximation, may be enough for what we do. +} + +// FIXME: Cleanup and move code to ImDrawList. +void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding) +{ + if (x_end_norm == x_start_norm) + return; + if (x_start_norm > x_end_norm) + ImSwap(x_start_norm, x_end_norm); + + ImVec2 p0 = ImVec2(ImLerp(rect.Min.x, rect.Max.x, x_start_norm), rect.Min.y); + ImVec2 p1 = ImVec2(ImLerp(rect.Min.x, rect.Max.x, x_end_norm), rect.Max.y); + if (rounding == 0.0f) + { + draw_list->AddRectFilled(p0, p1, col, 0.0f); + return; + } + + rounding = ImClamp(ImMin((rect.Max.x - rect.Min.x) * 0.5f, (rect.Max.y - rect.Min.y) * 0.5f) - 1.0f, 0.0f, rounding); + const float inv_rounding = 1.0f / rounding; + const float arc0_b = ImAcos01(1.0f - (p0.x - rect.Min.x) * inv_rounding); + const float arc0_e = ImAcos01(1.0f - (p1.x - rect.Min.x) * inv_rounding); + const float x0 = ImMax(p0.x, rect.Min.x + rounding); + if (arc0_b == arc0_e) + { + draw_list->PathLineTo(ImVec2(x0, p1.y)); + draw_list->PathLineTo(ImVec2(x0, p0.y)); + } + else if (arc0_b == 0.0f && arc0_e == IM_PI*0.5f) + { + draw_list->PathArcToFast(ImVec2(x0, p1.y - rounding), rounding, 3, 6); // BL + draw_list->PathArcToFast(ImVec2(x0, p0.y + rounding), rounding, 6, 9); // TR + } + else + { + draw_list->PathArcTo(ImVec2(x0, p1.y - rounding), rounding, IM_PI - arc0_e, IM_PI - arc0_b, 3); // BL + draw_list->PathArcTo(ImVec2(x0, p0.y + rounding), rounding, IM_PI + arc0_b, IM_PI + arc0_e, 3); // TR + } + if (p1.x > rect.Min.x + rounding) + { + const float arc1_b = ImAcos01(1.0f - (rect.Max.x - p1.x) * inv_rounding); + const float arc1_e = ImAcos01(1.0f - (rect.Max.x - p0.x) * inv_rounding); + const float x1 = ImMin(p1.x, rect.Max.x - rounding); + if (arc1_b == arc1_e) + { + draw_list->PathLineTo(ImVec2(x1, p0.y)); + draw_list->PathLineTo(ImVec2(x1, p1.y)); + } + else if (arc1_b == 0.0f && arc1_e == IM_PI*0.5f) + { + draw_list->PathArcToFast(ImVec2(x1, p0.y + rounding), rounding, 9, 12); // TR + draw_list->PathArcToFast(ImVec2(x1, p1.y - rounding), rounding, 0, 3); // BR + } + else + { + draw_list->PathArcTo(ImVec2(x1, p0.y + rounding), rounding, -arc1_e, -arc1_b, 3); // TR + draw_list->PathArcTo(ImVec2(x1, p1.y - rounding), rounding, +arc1_b, +arc1_e, 3); // BR + } + } + draw_list->PathFillConvex(col); +} + //----------------------------------------------------------------------------- // DEFAULT FONT DATA //----------------------------------------------------------------------------- -// Compressed with stb_compress() then converted to a C array. -// Use the program in extra_fonts/binary_to_compressed_c.cpp to create the array from a TTF file. +// Compressed with stb_compress() then converted to a C array and encoded as base85. +// Use the program in misc/fonts/binary_to_compressed_c.cpp to create the array from a TTF file. +// The purpose of encoding as base85 instead of "0x00,0x01,..." style is only save on _source code_ size. // Decompression from stb.h (public domain) by Sean Barrett https://github.com/nothings/stb/blob/master/stb.h //----------------------------------------------------------------------------- -static unsigned int stb_decompress_length(unsigned char *input) +static unsigned int stb_decompress_length(const unsigned char *input) { return (input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]; } -static unsigned char *stb__barrier, *stb__barrier2, *stb__barrier3, *stb__barrier4; +static unsigned char *stb__barrier_out_e, *stb__barrier_out_b; +static const unsigned char *stb__barrier_in_b; static unsigned char *stb__dout; -static void stb__match(unsigned char *data, unsigned int length) +static void stb__match(const unsigned char *data, unsigned int length) { // INVERSE of memmove... write each byte before copying the next... - IM_ASSERT (stb__dout + length <= stb__barrier); - if (stb__dout + length > stb__barrier) { stb__dout += length; return; } - if (data < stb__barrier4) { stb__dout = stb__barrier+1; return; } + IM_ASSERT(stb__dout + length <= stb__barrier_out_e); + if (stb__dout + length > stb__barrier_out_e) { stb__dout += length; return; } + if (data < stb__barrier_out_b) { stb__dout = stb__barrier_out_e+1; return; } while (length--) *stb__dout++ = *data++; } -static void stb__lit(unsigned char *data, unsigned int length) +static void stb__lit(const unsigned char *data, unsigned int length) { - IM_ASSERT (stb__dout + length <= stb__barrier); - if (stb__dout + length > stb__barrier) { stb__dout += length; return; } - if (data < stb__barrier2) { stb__dout = stb__barrier+1; return; } + IM_ASSERT(stb__dout + length <= stb__barrier_out_e); + if (stb__dout + length > stb__barrier_out_e) { stb__dout += length; return; } + if (data < stb__barrier_in_b) { stb__dout = stb__barrier_out_e+1; return; } memcpy(stb__dout, data, length); stb__dout += length; } @@ -2216,7 +2940,7 @@ static void stb__lit(unsigned char *data, unsigned int length) #define stb__in3(x) ((i[x] << 16) + stb__in2((x)+1)) #define stb__in4(x) ((i[x] << 24) + stb__in3((x)+1)) -static unsigned char *stb_decompress_token(unsigned char *i) +static const unsigned char *stb_decompress_token(const unsigned char *i) { if (*i >= 0x20) { // use fewer if's for cases that expand small if (*i >= 0x80) stb__match(stb__dout-i[1]-1, i[0] - 0x80 + 1), i += 2; @@ -2264,21 +2988,20 @@ static unsigned int stb_adler32(unsigned int adler32, unsigned char *buffer, uns return (unsigned int)(s2 << 16) + (unsigned int)s1; } -static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsigned int length) +static unsigned int stb_decompress(unsigned char *output, const unsigned char *i, unsigned int /*length*/) { unsigned int olen; if (stb__in4(0) != 0x57bC0000) return 0; if (stb__in4(4) != 0) return 0; // error! stream is > 4GB olen = stb_decompress_length(i); - stb__barrier2 = i; - stb__barrier3 = i+length; - stb__barrier = output + olen; - stb__barrier4 = output; + stb__barrier_in_b = i; + stb__barrier_out_e = output + olen; + stb__barrier_out_b = output; i += 16; stb__dout = output; for (;;) { - unsigned char *old_i = i; + const unsigned char *old_i = i; i = stb_decompress_token(i); if (i == old_i) { if (*i == 0x05 && i[1] == 0xfa) { @@ -2305,7 +3028,8 @@ static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsi // Download and more information at http://upperbounds.net //----------------------------------------------------------------------------- // File: 'ProggyClean.ttf' (41208 bytes) -// Exported using binary_to_compressed_c.cpp +// Exported using misc/fonts/binary_to_compressed_c.cpp (with compression + base85 string encoding). +// The purpose of encoding as base85 instead of "0x00,0x01,..." style is only save on _source code_ size. //----------------------------------------------------------------------------- static const char proggy_clean_ttf_compressed_data_base85[11980+1] = "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/" diff --git a/Baikal/ImGUI/imgui_impl_glfw_gl3.cpp b/BaikalStandalone/ImGUI/imgui_impl_glfw_gl3.cpp similarity index 99% rename from Baikal/ImGUI/imgui_impl_glfw_gl3.cpp rename to BaikalStandalone/ImGUI/imgui_impl_glfw_gl3.cpp index cd1f3f3e..d7332225 100644 --- a/Baikal/ImGUI/imgui_impl_glfw_gl3.cpp +++ b/BaikalStandalone/ImGUI/imgui_impl_glfw_gl3.cpp @@ -320,6 +320,8 @@ bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks) { g_Window = window; + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; @@ -363,7 +365,7 @@ bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks) void ImGui_ImplGlfwGL3_Shutdown() { ImGui_ImplGlfwGL3_InvalidateDeviceObjects(); - ImGui::Shutdown(); + ImGui::DestroyContext(); } void ImGui_ImplGlfwGL3_NewFrame() diff --git a/Baikal/ImGUI/imgui_impl_glfw_gl3.h b/BaikalStandalone/ImGUI/imgui_impl_glfw_gl3.h similarity index 100% rename from Baikal/ImGUI/imgui_impl_glfw_gl3.h rename to BaikalStandalone/ImGUI/imgui_impl_glfw_gl3.h diff --git a/BaikalStandalone/ImGUI/imgui_internal.h b/BaikalStandalone/ImGUI/imgui_internal.h new file mode 100644 index 00000000..485aceda --- /dev/null +++ b/BaikalStandalone/ImGUI/imgui_internal.h @@ -0,0 +1,1236 @@ +// dear imgui, v1.63 WIP +// (internals) + +// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! +// Set: +// #define IMGUI_DEFINE_MATH_OPERATORS +// To implement maths operators for ImVec2 (disabled by default to not collide with using IM_VEC2_CLASS_EXTRA along with your own math types+operators) + +#pragma once + +#ifndef IMGUI_VERSION +#error Must include imgui.h before imgui_internal.h +#endif + +#include // FILE* +#include // NULL, malloc, free, qsort, atoi, atof +#include // sqrtf, fabsf, fmodf, powf, floorf, ceilf, cosf, sinf +#include // INT_MIN, INT_MAX + +#ifdef _MSC_VER +#pragma warning (push) +#pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport) +#endif + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" // for stb_textedit.h +#pragma clang diagnostic ignored "-Wmissing-prototypes" // for stb_textedit.h +#pragma clang diagnostic ignored "-Wold-style-cast" +#endif + +//----------------------------------------------------------------------------- +// Forward Declarations +//----------------------------------------------------------------------------- + +struct ImRect; // An axis-aligned rectangle (2 points) +struct ImDrawDataBuilder; // Helper to build a ImDrawData instance +struct ImDrawListSharedData; // Data shared between all ImDrawList instances +struct ImGuiColMod; // Stacked color modifier, backup of modified data so we can restore it +struct ImGuiColumnData; // Storage data for a single column +struct ImGuiColumnsSet; // Storage data for a columns set +struct ImGuiContext; // Main imgui context +struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup() +struct ImGuiItemHoveredDataBackup; // Backup and restore IsItemHovered() internal data +struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only +struct ImGuiNavMoveResult; // Result of a directional navigation move query result +struct ImGuiNextWindowData; // Storage for SetNexWindow** functions +struct ImGuiPopupRef; // Storage for current popup stack +struct ImGuiSettingsHandler; +struct ImGuiStyleMod; // Stacked style modifier, backup of modified data so we can restore it +struct ImGuiTextEditState; // Internal state of the currently focused/edited text input box +struct ImGuiWindow; // Storage for one window +struct ImGuiWindowTempData; // Temporary storage for one, that's the data which in theory we could ditch at the end of the frame +struct ImGuiWindowSettings; // Storage for window settings stored in .ini file (we keep one of those even if the actual window wasn't instanced during this session) + +typedef int ImGuiLayoutType; // enum: horizontal or vertical // enum ImGuiLayoutType_ +typedef int ImGuiButtonFlags; // flags: for ButtonEx(), ButtonBehavior() // enum ImGuiButtonFlags_ +typedef int ImGuiItemFlags; // flags: for PushItemFlag() // enum ImGuiItemFlags_ +typedef int ImGuiItemStatusFlags; // flags: storage for DC.LastItemXXX // enum ImGuiItemStatusFlags_ +typedef int ImGuiNavHighlightFlags; // flags: for RenderNavHighlight() // enum ImGuiNavHighlightFlags_ +typedef int ImGuiNavDirSourceFlags; // flags: for GetNavInputAmount2d() // enum ImGuiNavDirSourceFlags_ +typedef int ImGuiNavMoveFlags; // flags: for navigation requests // enum ImGuiNavMoveFlags_ +typedef int ImGuiSeparatorFlags; // flags: for Separator() - internal // enum ImGuiSeparatorFlags_ +typedef int ImGuiSliderFlags; // flags: for SliderBehavior() // enum ImGuiSliderFlags_ + +//------------------------------------------------------------------------- +// STB libraries +//------------------------------------------------------------------------- + +namespace ImGuiStb +{ + +#undef STB_TEXTEDIT_STRING +#undef STB_TEXTEDIT_CHARTYPE +#define STB_TEXTEDIT_STRING ImGuiTextEditState +#define STB_TEXTEDIT_CHARTYPE ImWchar +#define STB_TEXTEDIT_GETWIDTH_NEWLINE -1.0f +#include "stb_textedit.h" + +} // namespace ImGuiStb + +//----------------------------------------------------------------------------- +// Context +//----------------------------------------------------------------------------- + +#ifndef GImGui +extern IMGUI_API ImGuiContext* GImGui; // Current implicit ImGui context pointer +#endif + +//----------------------------------------------------------------------------- +// Helpers +//----------------------------------------------------------------------------- + +#define IM_PI 3.14159265358979323846f +#ifdef _WIN32 +#define IM_NEWLINE "\r\n" // Play it nice with Windows users (2018/05 news: Microsoft announced that Notepad will finally display Unix-style carriage returns!) +#else +#define IM_NEWLINE "\n" +#endif + +// Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall +#ifdef _MSC_VER +#define IMGUI_CDECL __cdecl +#else +#define IMGUI_CDECL +#endif + +// Helpers: UTF-8 <> wchar +IMGUI_API int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count +IMGUI_API int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // read one character. return input UTF-8 bytes count +IMGUI_API int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL); // return input UTF-8 bytes count +IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count) +IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end); // return number of bytes to express one char in UTF-8 +IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8 + +// Helpers: Misc +IMGUI_API ImU32 ImHash(const void* data, int data_size, ImU32 seed = 0); // Pass data_size==0 for zero-terminated strings +IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, size_t* out_file_size = NULL, int padding_bytes = 0); +IMGUI_API FILE* ImFileOpen(const char* filename, const char* file_open_mode); +static inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; } +static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; } +static inline bool ImIsPowerOfTwo(int v) { return v != 0 && (v & (v - 1)) == 0; } +static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; } +#define ImQsort qsort + +// Helpers: Geometry +IMGUI_API ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p); +IMGUI_API bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p); +IMGUI_API ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p); +IMGUI_API void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w); + +// Helpers: String +IMGUI_API int ImStricmp(const char* str1, const char* str2); +IMGUI_API int ImStrnicmp(const char* str1, const char* str2, size_t count); +IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count); +IMGUI_API char* ImStrdup(const char* str); +IMGUI_API const char* ImStrchrRange(const char* str_begin, const char* str_end, char c); +IMGUI_API int ImStrlenW(const ImWchar* str); +IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line +IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end); +IMGUI_API void ImStrTrimBlanks(char* str); +IMGUI_API int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) IM_FMTARGS(3); +IMGUI_API int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args) IM_FMTLIST(3); +IMGUI_API const char* ImParseFormatFindStart(const char* format); +IMGUI_API const char* ImParseFormatFindEnd(const char* format); +IMGUI_API const char* ImParseFormatTrimDecorations(const char* format, char* buf, int buf_size); +IMGUI_API int ImParseFormatPrecision(const char* format, int default_value); + +// Helpers: ImVec2/ImVec4 operators +// We are keeping those disabled by default so they don't leak in user space, to allow user enabling implicit cast operators between ImVec2 and their own types (using IM_VEC2_CLASS_EXTRA etc.) +// We unfortunately don't have a unary- operator for ImVec2 because this would needs to be defined inside the class itself. +#ifdef IMGUI_DEFINE_MATH_OPERATORS +static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x*rhs, lhs.y*rhs); } +static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x/rhs, lhs.y/rhs); } +static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x+rhs.x, lhs.y+rhs.y); } +static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x-rhs.x, lhs.y-rhs.y); } +static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x*rhs.x, lhs.y*rhs.y); } +static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x/rhs.x, lhs.y/rhs.y); } +static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; } +static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; } +static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; } +static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; } +static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z, lhs.w+rhs.w); } +static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z, lhs.w-rhs.w); } +static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x*rhs.x, lhs.y*rhs.y, lhs.z*rhs.z, lhs.w*rhs.w); } +#endif + +// Helpers: Maths +// - Wrapper for standard libs functions. (Note that imgui_demo.cpp does _not_ use them to keep the code easy to copy) +#ifndef IMGUI_DISABLE_MATH_FUNCTIONS +static inline float ImFabs(float x) { return fabsf(x); } +static inline float ImSqrt(float x) { return sqrtf(x); } +static inline float ImPow(float x, float y) { return powf(x, y); } +static inline double ImPow(double x, double y) { return pow(x, y); } +static inline float ImFmod(float x, float y) { return fmodf(x, y); } +static inline double ImFmod(double x, double y) { return fmod(x, y); } +static inline float ImCos(float x) { return cosf(x); } +static inline float ImSin(float x) { return sinf(x); } +static inline float ImAcos(float x) { return acosf(x); } +static inline float ImAtan2(float y, float x) { return atan2f(y, x); } +static inline double ImAtof(const char* s) { return atof(s); } +static inline float ImFloorStd(float x) { return floorf(x); } // we already uses our own ImFloor() { return (float)(int)v } internally so the standard one wrapper is named differently (it's used by stb_truetype) +static inline float ImCeil(float x) { return ceilf(x); } +#endif +// - ImMin/ImMax/ImClamp/ImLerp/ImSwap are used by widgets which support for variety of types: signed/unsigned int/long long float/double, using templates here but we could also redefine them 6 times +template static inline T ImMin(T lhs, T rhs) { return lhs < rhs ? lhs : rhs; } +template static inline T ImMax(T lhs, T rhs) { return lhs >= rhs ? lhs : rhs; } +template static inline T ImClamp(T v, T mn, T mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } +template static inline T ImLerp(T a, T b, float t) { return (T)(a + (b - a) * t); } +template static inline void ImSwap(T& a, T& b) { T tmp = a; a = b; b = tmp; } +// - Misc maths helpers +static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x < rhs.x ? lhs.x : rhs.x, lhs.y < rhs.y ? lhs.y : rhs.y); } +static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x >= rhs.x ? lhs.x : rhs.x, lhs.y >= rhs.y ? lhs.y : rhs.y); } +static inline ImVec2 ImClamp(const ImVec2& v, const ImVec2& mn, ImVec2 mx) { return ImVec2((v.x < mn.x) ? mn.x : (v.x > mx.x) ? mx.x : v.x, (v.y < mn.y) ? mn.y : (v.y > mx.y) ? mx.y : v.y); } +static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, float t) { return ImVec2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t); } +static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); } +static inline ImVec4 ImLerp(const ImVec4& a, const ImVec4& b, float t) { return ImVec4(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t, a.w + (b.w - a.w) * t); } +static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; } +static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; } +static inline float ImLengthSqr(const ImVec4& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y + lhs.z*lhs.z + lhs.w*lhs.w; } +static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / ImSqrt(d); return fail_value; } +static inline float ImFloor(float f) { return (float)(int)f; } +static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)v.x, (float)(int)v.y); } +static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; } +static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); } +static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; } +static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); } + +//----------------------------------------------------------------------------- +// Types +//----------------------------------------------------------------------------- + +enum ImGuiButtonFlags_ +{ + ImGuiButtonFlags_None = 0, + ImGuiButtonFlags_Repeat = 1 << 0, // hold to repeat + ImGuiButtonFlags_PressedOnClickRelease = 1 << 1, // return true on click + release on same item [DEFAULT if no PressedOn* flag is set] + ImGuiButtonFlags_PressedOnClick = 1 << 2, // return true on click (default requires click+release) + ImGuiButtonFlags_PressedOnRelease = 1 << 3, // return true on release (default requires click+release) + ImGuiButtonFlags_PressedOnDoubleClick = 1 << 4, // return true on double-click (default requires click+release) + ImGuiButtonFlags_FlattenChildren = 1 << 5, // allow interactions even if a child window is overlapping + ImGuiButtonFlags_AllowItemOverlap = 1 << 6, // require previous frame HoveredId to either match id or be null before being usable, use along with SetItemAllowOverlap() + ImGuiButtonFlags_DontClosePopups = 1 << 7, // disable automatically closing parent popup on press // [UNUSED] + ImGuiButtonFlags_Disabled = 1 << 8, // disable interactions + ImGuiButtonFlags_AlignTextBaseLine = 1 << 9, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine + ImGuiButtonFlags_NoKeyModifiers = 1 << 10, // disable interaction if a key modifier is held + ImGuiButtonFlags_NoHoldingActiveID = 1 << 11, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) + ImGuiButtonFlags_PressedOnDragDropHold = 1 << 12, // press when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers) + ImGuiButtonFlags_NoNavFocus = 1 << 13 // don't override navigation focus when activated +}; + +enum ImGuiSliderFlags_ +{ + ImGuiSliderFlags_None = 0, + ImGuiSliderFlags_Vertical = 1 << 0 +}; + +enum ImGuiColumnsFlags_ +{ + // Default: 0 + ImGuiColumnsFlags_None = 0, + ImGuiColumnsFlags_NoBorder = 1 << 0, // Disable column dividers + ImGuiColumnsFlags_NoResize = 1 << 1, // Disable resizing columns when clicking on the dividers + ImGuiColumnsFlags_NoPreserveWidths = 1 << 2, // Disable column width preservation when adjusting columns + ImGuiColumnsFlags_NoForceWithinWindow = 1 << 3, // Disable forcing columns to fit within window + ImGuiColumnsFlags_GrowParentContentsSize= 1 << 4 // (WIP) Restore pre-1.51 behavior of extending the parent window contents size but _without affecting the columns width at all_. Will eventually remove. +}; + +enum ImGuiSelectableFlagsPrivate_ +{ + // NB: need to be in sync with last value of ImGuiSelectableFlags_ + ImGuiSelectableFlags_NoHoldingActiveID = 1 << 10, + ImGuiSelectableFlags_PressedOnClick = 1 << 11, + ImGuiSelectableFlags_PressedOnRelease = 1 << 12, + ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 13 +}; + +enum ImGuiSeparatorFlags_ +{ + ImGuiSeparatorFlags_None = 0, + ImGuiSeparatorFlags_Horizontal = 1 << 0, // Axis default to current layout type, so generally Horizontal unless e.g. in a menu bar + ImGuiSeparatorFlags_Vertical = 1 << 1 +}; + +// Storage for LastItem data +enum ImGuiItemStatusFlags_ +{ + ImGuiItemStatusFlags_None = 0, + ImGuiItemStatusFlags_HoveredRect = 1 << 0, + ImGuiItemStatusFlags_HasDisplayRect = 1 << 1 +}; + +// FIXME: this is in development, not exposed/functional as a generic feature yet. +enum ImGuiLayoutType_ +{ + ImGuiLayoutType_Vertical, + ImGuiLayoutType_Horizontal +}; + +enum ImGuiAxis +{ + ImGuiAxis_None = -1, + ImGuiAxis_X = 0, + ImGuiAxis_Y = 1 +}; + +enum ImGuiPlotType +{ + ImGuiPlotType_Lines, + ImGuiPlotType_Histogram +}; + +enum ImGuiInputSource +{ + ImGuiInputSource_None = 0, + ImGuiInputSource_Mouse, + ImGuiInputSource_Nav, + ImGuiInputSource_NavKeyboard, // Only used occasionally for storage, not tested/handled by most code + ImGuiInputSource_NavGamepad, // " + ImGuiInputSource_COUNT +}; + +// FIXME-NAV: Clarify/expose various repeat delay/rate +enum ImGuiInputReadMode +{ + ImGuiInputReadMode_Down, + ImGuiInputReadMode_Pressed, + ImGuiInputReadMode_Released, + ImGuiInputReadMode_Repeat, + ImGuiInputReadMode_RepeatSlow, + ImGuiInputReadMode_RepeatFast +}; + +enum ImGuiNavHighlightFlags_ +{ + ImGuiNavHighlightFlags_None = 0, + ImGuiNavHighlightFlags_TypeDefault = 1 << 0, + ImGuiNavHighlightFlags_TypeThin = 1 << 1, + ImGuiNavHighlightFlags_AlwaysDraw = 1 << 2, + ImGuiNavHighlightFlags_NoRounding = 1 << 3 +}; + +enum ImGuiNavDirSourceFlags_ +{ + ImGuiNavDirSourceFlags_None = 0, + ImGuiNavDirSourceFlags_Keyboard = 1 << 0, + ImGuiNavDirSourceFlags_PadDPad = 1 << 1, + ImGuiNavDirSourceFlags_PadLStick = 1 << 2 +}; + +enum ImGuiNavMoveFlags_ +{ + ImGuiNavMoveFlags_None = 0, + ImGuiNavMoveFlags_LoopX = 1 << 0, // On failed request, restart from opposite side + ImGuiNavMoveFlags_LoopY = 1 << 1, + ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left) + ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful for provided for completeness + ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place) + ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5 // Store alternate result in NavMoveResultLocalVisibleSet that only comprise elements that are already fully visible. +}; + +enum ImGuiNavForward +{ + ImGuiNavForward_None, + ImGuiNavForward_ForwardQueued, + ImGuiNavForward_ForwardActive +}; + +// 2D axis aligned bounding-box +// NB: we can't rely on ImVec2 math operators being available here +struct IMGUI_API ImRect +{ + ImVec2 Min; // Upper-left + ImVec2 Max; // Lower-right + + ImRect() : Min(FLT_MAX,FLT_MAX), Max(-FLT_MAX,-FLT_MAX) {} + ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {} + ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {} + ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {} + + ImVec2 GetCenter() const { return ImVec2((Min.x + Max.x) * 0.5f, (Min.y + Max.y) * 0.5f); } + ImVec2 GetSize() const { return ImVec2(Max.x - Min.x, Max.y - Min.y); } + float GetWidth() const { return Max.x - Min.x; } + float GetHeight() const { return Max.y - Min.y; } + ImVec2 GetTL() const { return Min; } // Top-left + ImVec2 GetTR() const { return ImVec2(Max.x, Min.y); } // Top-right + ImVec2 GetBL() const { return ImVec2(Min.x, Max.y); } // Bottom-left + ImVec2 GetBR() const { return Max; } // Bottom-right + bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; } + bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x <= Max.x && r.Max.y <= Max.y; } + bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; } + void Add(const ImVec2& p) { if (Min.x > p.x) Min.x = p.x; if (Min.y > p.y) Min.y = p.y; if (Max.x < p.x) Max.x = p.x; if (Max.y < p.y) Max.y = p.y; } + void Add(const ImRect& r) { if (Min.x > r.Min.x) Min.x = r.Min.x; if (Min.y > r.Min.y) Min.y = r.Min.y; if (Max.x < r.Max.x) Max.x = r.Max.x; if (Max.y < r.Max.y) Max.y = r.Max.y; } + void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; } + void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; } + void Translate(const ImVec2& d) { Min.x += d.x; Min.y += d.y; Max.x += d.x; Max.y += d.y; } + void TranslateX(float dx) { Min.x += dx; Max.x += dx; } + void TranslateY(float dy) { Min.y += dy; Max.y += dy; } + void ClipWith(const ImRect& r) { Min = ImMax(Min, r.Min); Max = ImMin(Max, r.Max); } // Simple version, may lead to an inverted rectangle, which is fine for Contains/Overlaps test but not for display. + void ClipWithFull(const ImRect& r) { Min = ImClamp(Min, r.Min, r.Max); Max = ImClamp(Max, r.Min, r.Max); } // Full version, ensure both points are fully clipped. + void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } + bool IsInverted() const { return Min.x > Max.x || Min.y > Max.y; } +}; + +// Stacked color modifier, backup of modified data so we can restore it +struct ImGuiColMod +{ + ImGuiCol Col; + ImVec4 BackupValue; +}; + +// Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable. +struct ImGuiStyleMod +{ + ImGuiStyleVar VarIdx; + union { int BackupInt[2]; float BackupFloat[2]; }; + ImGuiStyleMod(ImGuiStyleVar idx, int v) { VarIdx = idx; BackupInt[0] = v; } + ImGuiStyleMod(ImGuiStyleVar idx, float v) { VarIdx = idx; BackupFloat[0] = v; } + ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v) { VarIdx = idx; BackupFloat[0] = v.x; BackupFloat[1] = v.y; } +}; + +// Stacked storage data for BeginGroup()/EndGroup() +struct ImGuiGroupData +{ + ImVec2 BackupCursorPos; + ImVec2 BackupCursorMaxPos; + float BackupIndentX; + float BackupGroupOffsetX; + float BackupCurrentLineHeight; + float BackupCurrentLineTextBaseOffset; + float BackupLogLinePosY; + ImGuiID BackupActiveIdIsAlive; + bool BackupActiveIdPreviousFrameIsAlive; + bool AdvanceCursor; +}; + +// Simple column measurement, currently used for MenuItem() only.. This is very short-sighted/throw-away code and NOT a generic helper. +struct IMGUI_API ImGuiMenuColumns +{ + int Count; + float Spacing; + float Width, NextWidth; + float Pos[4], NextWidths[4]; + + ImGuiMenuColumns(); + void Update(int count, float spacing, bool clear); + float DeclColumns(float w0, float w1, float w2); + float CalcExtraSpace(float avail_w); +}; + +// Internal state of the currently focused/edited text input box +struct IMGUI_API ImGuiTextEditState +{ + ImGuiID Id; // widget id owning the text state + ImVector Text; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer. + ImVector InitialText; // backup of end-user buffer at the time of focus (in UTF-8, unaltered) + ImVector TempTextBuffer; + int CurLenA, CurLenW; // we need to maintain our buffer length in both UTF-8 and wchar format. + int BufSizeA; // end-user buffer size + float ScrollX; + ImGuiStb::STB_TexteditState StbState; + float CursorAnim; + bool CursorFollow; + bool SelectedAllMouseLock; + + ImGuiTextEditState() { memset(this, 0, sizeof(*this)); } + void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking + void CursorClamp() { StbState.cursor = ImMin(StbState.cursor, CurLenW); StbState.select_start = ImMin(StbState.select_start, CurLenW); StbState.select_end = ImMin(StbState.select_end, CurLenW); } + bool HasSelection() const { return StbState.select_start != StbState.select_end; } + void ClearSelection() { StbState.select_start = StbState.select_end = StbState.cursor; } + void SelectAll() { StbState.select_start = 0; StbState.cursor = StbState.select_end = CurLenW; StbState.has_preferred_x = false; } + void OnKeyPressed(int key); +}; + +// Windows data saved in imgui.ini file +struct ImGuiWindowSettings +{ + char* Name; + ImGuiID ID; + ImVec2 Pos; + ImVec2 Size; + bool Collapsed; + + ImGuiWindowSettings() { Name = NULL; ID = 0; Pos = Size = ImVec2(0,0); Collapsed = false; } +}; + +struct ImGuiSettingsHandler +{ + const char* TypeName; // Short description stored in .ini file. Disallowed characters: '[' ']' + ImGuiID TypeHash; // == ImHash(TypeName, 0, 0) + void* (*ReadOpenFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, const char* name); // Read: Called when entering into a new ini entry e.g. "[Window][Name]" + void (*ReadLineFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, void* entry, const char* line); // Read: Called for every line of text within an ini entry + void (*WriteAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* out_buf); // Write: Output every entries into 'out_buf' + void* UserData; + + ImGuiSettingsHandler() { memset(this, 0, sizeof(*this)); } +}; + +// Storage for current popup stack +struct ImGuiPopupRef +{ + ImGuiID PopupId; // Set on OpenPopup() + ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() + ImGuiWindow* ParentWindow; // Set on OpenPopup() + int OpenFrameCount; // Set on OpenPopup() + ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differenciate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) + ImVec2 OpenPopupPos; // Set on OpenPopup(), preferred popup position (typically == OpenMousePos when using mouse) + ImVec2 OpenMousePos; // Set on OpenPopup(), copy of mouse position at the time of opening popup +}; + +struct ImGuiColumnData +{ + float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) + float OffsetNormBeforeResize; + ImGuiColumnsFlags Flags; // Not exposed + ImRect ClipRect; + + ImGuiColumnData() { OffsetNorm = OffsetNormBeforeResize = 0.0f; Flags = 0; } +}; + +struct ImGuiColumnsSet +{ + ImGuiID ID; + ImGuiColumnsFlags Flags; + bool IsFirstFrame; + bool IsBeingResized; + int Current; + int Count; + float MinX, MaxX; + float LineMinY, LineMaxY; + float StartPosY; // Copy of CursorPos + float StartMaxPosX; // Copy of CursorMaxPos + ImVector Columns; + + ImGuiColumnsSet() { Clear(); } + void Clear() + { + ID = 0; + Flags = 0; + IsFirstFrame = false; + IsBeingResized = false; + Current = 0; + Count = 1; + MinX = MaxX = 0.0f; + LineMinY = LineMaxY = 0.0f; + StartPosY = 0.0f; + StartMaxPosX = 0.0f; + Columns.clear(); + } +}; + +// Data shared between all ImDrawList instances +struct IMGUI_API ImDrawListSharedData +{ + ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas + ImFont* Font; // Current/default font (optional, for simplified AddText overload) + float FontSize; // Current/default font size (optional, for simplified AddText overload) + float CurveTessellationTol; + ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen() + + // Const data + // FIXME: Bake rounded corners fill/borders in atlas + ImVec2 CircleVtx12[12]; + + ImDrawListSharedData(); +}; + +struct ImDrawDataBuilder +{ + ImVector Layers[2]; // Global layers for: regular, tooltip + + void Clear() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].resize(0); } + void ClearFreeMemory() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].clear(); } + IMGUI_API void FlattenIntoSingleLayer(); +}; + +struct ImGuiNavMoveResult +{ + ImGuiID ID; // Best candidate + ImGuiWindow* Window; // Best candidate window + float DistBox; // Best candidate box distance to current NavId + float DistCenter; // Best candidate center distance to current NavId + float DistAxial; + ImRect RectRel; // Best candidate bounding box in window relative space + + ImGuiNavMoveResult() { Clear(); } + void Clear() { ID = 0; Window = NULL; DistBox = DistCenter = DistAxial = FLT_MAX; RectRel = ImRect(); } +}; + +// Storage for SetNexWindow** functions +struct ImGuiNextWindowData +{ + ImGuiCond PosCond; + ImGuiCond SizeCond; + ImGuiCond ContentSizeCond; + ImGuiCond CollapsedCond; + ImGuiCond SizeConstraintCond; + ImGuiCond FocusCond; + ImGuiCond BgAlphaCond; + ImVec2 PosVal; + ImVec2 PosPivotVal; + ImVec2 SizeVal; + ImVec2 ContentSizeVal; + bool CollapsedVal; + ImRect SizeConstraintRect; + ImGuiSizeCallback SizeCallback; + void* SizeCallbackUserData; + float BgAlphaVal; + ImVec2 MenuBarOffsetMinVal; // This is not exposed publicly, so we don't clear it. + + ImGuiNextWindowData() + { + PosCond = SizeCond = ContentSizeCond = CollapsedCond = SizeConstraintCond = FocusCond = BgAlphaCond = 0; + PosVal = PosPivotVal = SizeVal = ImVec2(0.0f, 0.0f); + ContentSizeVal = ImVec2(0.0f, 0.0f); + CollapsedVal = false; + SizeConstraintRect = ImRect(); + SizeCallback = NULL; + SizeCallbackUserData = NULL; + BgAlphaVal = FLT_MAX; + MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f); + } + + void Clear() + { + PosCond = SizeCond = ContentSizeCond = CollapsedCond = SizeConstraintCond = FocusCond = BgAlphaCond = 0; + } +}; + +// Main imgui context +struct ImGuiContext +{ + bool Initialized; + bool FrameScopeActive; // Set by NewFrame(), cleared by EndFrame()/Render() + bool FontAtlasOwnedByContext; // Io.Fonts-> is owned by the ImGuiContext and will be destructed along with it. + ImGuiIO IO; + ImGuiStyle Style; + ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() + float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window. + float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height. + ImDrawListSharedData DrawListSharedData; + + double Time; + int FrameCount; + int FrameCountEnded; + int FrameCountRendered; + ImVector Windows; + ImVector WindowsSortBuffer; + ImVector CurrentWindowStack; + ImGuiStorage WindowsById; + int WindowsActiveCount; + ImGuiWindow* CurrentWindow; // Being drawn into + ImGuiWindow* HoveredWindow; // Will catch mouse inputs + ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only) + ImGuiID HoveredId; // Hovered widget + bool HoveredIdAllowOverlap; + ImGuiID HoveredIdPreviousFrame; + float HoveredIdTimer; + ImGuiID ActiveId; // Active widget + ImGuiID ActiveIdPreviousFrame; + ImGuiID ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame) + float ActiveIdTimer; + bool ActiveIdIsJustActivated; // Set at the time of activation for one frame + bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always) + bool ActiveIdValueChanged; + bool ActiveIdPreviousFrameIsAlive; + bool ActiveIdPreviousFrameValueChanged; + int ActiveIdAllowNavDirFlags; // Active widget allows using directional navigation (e.g. can activate a button and move away from it) + ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) + ImGuiWindow* ActiveIdWindow; + ImGuiWindow* ActiveIdPreviousFrameWindow; + ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard) + ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation. + float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation. + ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actually window that is moved is generally MovingWindow->RootWindow. + ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() + ImVector StyleModifiers; // Stack for PushStyleVar()/PopStyleVar() + ImVector FontStack; // Stack for PushFont()/PopFont() + ImVector OpenPopupStack; // Which popups are open (persistent) + ImVector CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame) + ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions + bool NextTreeNodeOpenVal; // Storage for SetNextTreeNode** functions + ImGuiCond NextTreeNodeOpenCond; + + // Navigation data (for gamepad/keyboard) + ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusWindow' + ImGuiID NavId; // Focused item for navigation + ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0, also set when calling ActivateItem() + ImGuiID NavActivateDownId; // ~~ IsNavInputDown(ImGuiNavInput_Activate) ? NavId : 0 + ImGuiID NavActivatePressedId; // ~~ IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0 + ImGuiID NavInputId; // ~~ IsNavInputPressed(ImGuiNavInput_Input) ? NavId : 0 + ImGuiID NavJustTabbedId; // Just tabbed to this id. + ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest) + ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame + ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? + ImRect NavScoringRectScreen; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring. + int NavScoringCount; // Metrics for debugging + ImGuiWindow* NavWindowingTarget; // When selecting a window (holding Menu+FocusPrev/Next, or equivalent of CTRL-TAB) this window is temporarily displayed front-most. + ImGuiWindow* NavWindowingTargetAnim; // Record of last valid NavWindowingTarget until DimBgRatio and NavWindowingHighlightAlpha becomes 0.0f + ImGuiWindow* NavWindowingList; + float NavWindowingTimer; + float NavWindowingHighlightAlpha; + bool NavWindowingToggleLayer; + int NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. + int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing + bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRefRectRel is valid + bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default) + bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover) + bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again. + bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest + bool NavInitRequest; // Init request for appearing window to select first item + bool NavInitRequestFromMove; + ImGuiID NavInitResultId; + ImRect NavInitResultRectRel; + bool NavMoveFromClampedRefRect; // Set by manual scrolling, if we scroll to a point where NavId isn't visible we reset navigation from visible items + bool NavMoveRequest; // Move request for this frame + ImGuiNavMoveFlags NavMoveRequestFlags; + ImGuiNavForward NavMoveRequestForward; // None / ForwardQueued / ForwardActive (this is used to navigate sibling parent menus from a child menu) + ImGuiDir NavMoveDir, NavMoveDirLast; // Direction of the move request (left/right/up/down), direction of the previous move request + ImGuiDir NavMoveClipDir; + ImGuiNavMoveResult NavMoveResultLocal; // Best move request candidate within NavWindow + ImGuiNavMoveResult NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag) + ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag) + + // Render + ImDrawData DrawData; // Main ImDrawData instance to pass render information to the user + ImDrawDataBuilder DrawDataBuilder; + float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list) + ImDrawList OverlayDrawList; // Optional software render of mouse cursors, if io.MouseDrawCursor is set + a few debug overlays + ImGuiMouseCursor MouseCursor; + + // Drag and Drop + bool DragDropActive; + bool DragDropWithinSourceOrTarget; + ImGuiDragDropFlags DragDropSourceFlags; + int DragDropSourceFrameCount; + int DragDropMouseButton; + ImGuiPayload DragDropPayload; + ImRect DragDropTargetRect; + ImGuiID DragDropTargetId; + ImGuiDragDropFlags DragDropAcceptFlags; + float DragDropAcceptIdCurrRectSurface; // Target item surface (we resolve overlapping targets by prioritizing the smaller surface) + ImGuiID DragDropAcceptIdCurr; // Target item id (set at the time of accepting the payload) + ImGuiID DragDropAcceptIdPrev; // Target item id from previous frame (we need to store this to allow for overlapping drag and drop targets) + int DragDropAcceptFrameCount; // Last time a target expressed a desire to accept the source + ImVector DragDropPayloadBufHeap; // We don't expose the ImVector<> directly + unsigned char DragDropPayloadBufLocal[8]; // Local buffer for small payloads + + // Widget state + ImGuiTextEditState InputTextState; + ImFont InputTextPasswordFont; + ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. + ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets + ImVec4 ColorPickerRef; + bool DragCurrentAccumDirty; + float DragCurrentAccum; // Accumulator for dragging modification. Always high-precision, not rounded by end-user precision settings + float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio + ImVec2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage? + int TooltipOverrideCount; + ImVector PrivateClipboard; // If no custom clipboard handler is defined + ImVec2 PlatformImePos, PlatformImeLastPos; // Cursor position request & last passed to the OS Input Method Editor + + // Settings + bool SettingsLoaded; + float SettingsDirtyTimer; // Save .ini Settings to memory when time reaches zero + ImGuiTextBuffer SettingsIniData; // In memory .ini settings + ImVector SettingsHandlers; // List of .ini settings handlers + ImVector SettingsWindows; // ImGuiWindow .ini settings entries (parsed from the last loaded .ini file and maintained on saving) + + // Logging + bool LogEnabled; + FILE* LogFile; // If != NULL log to stdout/ file + ImGuiTextBuffer LogClipboard; // Accumulation buffer when log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators. + int LogStartDepth; + int LogAutoExpandMaxDepth; + + // Misc + float FramerateSecPerFrame[120]; // Calculate estimate of framerate for user over the last 2 seconds. + int FramerateSecPerFrameIdx; + float FramerateSecPerFrameAccum; + int WantCaptureMouseNextFrame; // Explicit capture via CaptureKeyboardFromApp()/CaptureMouseFromApp() sets those flags + int WantCaptureKeyboardNextFrame; + int WantTextInputNextFrame; + char TempBuffer[1024*3+1]; // Temporary text buffer + + ImGuiContext(ImFontAtlas* shared_font_atlas) : OverlayDrawList(NULL) + { + Initialized = false; + FrameScopeActive = false; + Font = NULL; + FontSize = FontBaseSize = 0.0f; + FontAtlasOwnedByContext = shared_font_atlas ? false : true; + IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)(); + + Time = 0.0f; + FrameCount = 0; + FrameCountEnded = FrameCountRendered = -1; + WindowsActiveCount = 0; + CurrentWindow = NULL; + HoveredWindow = NULL; + HoveredRootWindow = NULL; + HoveredId = 0; + HoveredIdAllowOverlap = false; + HoveredIdPreviousFrame = 0; + HoveredIdTimer = 0.0f; + ActiveId = 0; + ActiveIdPreviousFrame = 0; + ActiveIdIsAlive = 0; + ActiveIdTimer = 0.0f; + ActiveIdIsJustActivated = false; + ActiveIdAllowOverlap = false; + ActiveIdValueChanged = false; + ActiveIdPreviousFrameIsAlive = false; + ActiveIdPreviousFrameValueChanged = false; + ActiveIdAllowNavDirFlags = 0; + ActiveIdClickOffset = ImVec2(-1,-1); + ActiveIdWindow = ActiveIdPreviousFrameWindow = NULL; + ActiveIdSource = ImGuiInputSource_None; + LastActiveId = 0; + LastActiveIdTimer = 0.0f; + MovingWindow = NULL; + NextTreeNodeOpenVal = false; + NextTreeNodeOpenCond = 0; + + NavWindow = NULL; + NavId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavInputId = 0; + NavJustTabbedId = NavJustMovedToId = NavNextActivateId = 0; + NavInputSource = ImGuiInputSource_None; + NavScoringRectScreen = ImRect(); + NavScoringCount = 0; + NavWindowingTarget = NavWindowingTargetAnim = NavWindowingList = NULL; + NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f; + NavWindowingToggleLayer = false; + NavLayer = 0; + NavIdTabCounter = INT_MAX; + NavIdIsAlive = false; + NavMousePosDirty = false; + NavDisableHighlight = true; + NavDisableMouseHover = false; + NavAnyRequest = false; + NavInitRequest = false; + NavInitRequestFromMove = false; + NavInitResultId = 0; + NavMoveFromClampedRefRect = false; + NavMoveRequest = false; + NavMoveRequestFlags = 0; + NavMoveRequestForward = ImGuiNavForward_None; + NavMoveDir = NavMoveDirLast = NavMoveClipDir = ImGuiDir_None; + + DimBgRatio = 0.0f; + OverlayDrawList._Data = &DrawListSharedData; + OverlayDrawList._OwnerName = "##Overlay"; // Give it a name for debugging + MouseCursor = ImGuiMouseCursor_Arrow; + + DragDropActive = DragDropWithinSourceOrTarget = false; + DragDropSourceFlags = 0; + DragDropSourceFrameCount = -1; + DragDropMouseButton = -1; + DragDropTargetId = 0; + DragDropAcceptFlags = 0; + DragDropAcceptIdCurrRectSurface = 0.0f; + DragDropAcceptIdPrev = DragDropAcceptIdCurr = 0; + DragDropAcceptFrameCount = -1; + memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal)); + + ScalarAsInputTextId = 0; + ColorEditOptions = ImGuiColorEditFlags__OptionsDefault; + DragCurrentAccumDirty = false; + DragCurrentAccum = 0.0f; + DragSpeedDefaultRatio = 1.0f / 100.0f; + ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f); + TooltipOverrideCount = 0; + PlatformImePos = PlatformImeLastPos = ImVec2(FLT_MAX, FLT_MAX); + + SettingsLoaded = false; + SettingsDirtyTimer = 0.0f; + + LogEnabled = false; + LogFile = NULL; + LogStartDepth = 0; + LogAutoExpandMaxDepth = 2; + + memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame)); + FramerateSecPerFrameIdx = 0; + FramerateSecPerFrameAccum = 0.0f; + WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1; + memset(TempBuffer, 0, sizeof(TempBuffer)); + } +}; + +// Transient per-window flags, reset at the beginning of the frame. For child window, inherited from parent on first Begin(). +// This is going to be exposed in imgui.h when stabilized enough. +enum ImGuiItemFlags_ +{ + ImGuiItemFlags_AllowKeyboardFocus = 1 << 0, // true + ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings. + ImGuiItemFlags_Disabled = 1 << 2, // false // [BETA] Disable interactions but doesn't affect visuals yet. See github.com/ocornut/imgui/issues/211 + ImGuiItemFlags_NoNav = 1 << 3, // false + ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false + ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // MenuItem/Selectable() automatically closes current Popup window + ImGuiItemFlags_Default_ = ImGuiItemFlags_AllowKeyboardFocus +}; + +// Transient per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the DC variable name in ImGuiWindow. +// FIXME: That's theory, in practice the delimitation between ImGuiWindow and ImGuiWindowTempData is quite tenuous and could be reconsidered. +struct IMGUI_API ImGuiWindowTempData +{ + ImVec2 CursorPos; + ImVec2 CursorPosPrevLine; + ImVec2 CursorStartPos; + ImVec2 CursorMaxPos; // Used to implicitly calculate the size of our contents, always growing during the frame. Turned into window->SizeContents at the beginning of next frame + float CurrentLineHeight; + float CurrentLineTextBaseOffset; + float PrevLineHeight; + float PrevLineTextBaseOffset; + float LogLinePosY; + int TreeDepth; + ImU32 TreeDepthMayJumpToParentOnPop; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31 + ImGuiID LastItemId; + ImGuiItemStatusFlags LastItemStatusFlags; + ImRect LastItemRect; // Interaction rect + ImRect LastItemDisplayRect; // End-user display rect (only valid if LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) + bool NavHideHighlightOneFrame; + bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) + int NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) + int NavLayerCurrentMask; // = (1 << NavLayerCurrent) used by ItemAdd prior to clipping. + int NavLayerActiveMask; // Which layer have been written to (result from previous frame) + int NavLayerActiveMaskNext; // Which layer have been written to (buffer for current frame) + bool MenuBarAppending; // FIXME: Remove this + ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs. + ImVector ChildWindows; + ImGuiStorage* StateStorage; + ImGuiLayoutType LayoutType; + ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin() + + // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. + ImGuiItemFlags ItemFlags; // == ItemFlagsStack.back() [empty == ImGuiItemFlags_Default] + float ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window + float TextWrapPos; // == TextWrapPosStack.back() [empty == -1.0f] + ImVectorItemFlagsStack; + ImVector ItemWidthStack; + ImVector TextWrapPosStack; + ImVectorGroupStack; + int StackSizesBackup[6]; // Store size of various stacks for asserting + + float IndentX; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) + float GroupOffsetX; + float ColumnsOffsetX; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. + ImGuiColumnsSet* ColumnsSet; // Current columns set + + ImGuiWindowTempData() + { + CursorPos = CursorPosPrevLine = CursorStartPos = CursorMaxPos = ImVec2(0.0f, 0.0f); + CurrentLineHeight = PrevLineHeight = 0.0f; + CurrentLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f; + LogLinePosY = -1.0f; + TreeDepth = 0; + TreeDepthMayJumpToParentOnPop = 0x00; + LastItemId = 0; + LastItemStatusFlags = 0; + LastItemRect = LastItemDisplayRect = ImRect(); + NavHideHighlightOneFrame = false; + NavHasScroll = false; + NavLayerActiveMask = NavLayerActiveMaskNext = 0x00; + NavLayerCurrent = 0; + NavLayerCurrentMask = 1 << 0; + MenuBarAppending = false; + MenuBarOffset = ImVec2(0.0f, 0.0f); + StateStorage = NULL; + LayoutType = ParentLayoutType = ImGuiLayoutType_Vertical; + ItemWidth = 0.0f; + ItemFlags = ImGuiItemFlags_Default_; + TextWrapPos = -1.0f; + memset(StackSizesBackup, 0, sizeof(StackSizesBackup)); + + IndentX = 0.0f; + GroupOffsetX = 0.0f; + ColumnsOffsetX = 0.0f; + ColumnsSet = NULL; + } +}; + +// Storage for one window +struct IMGUI_API ImGuiWindow +{ + char* Name; + ImGuiID ID; // == ImHash(Name) + ImGuiWindowFlags Flags; // See enum ImGuiWindowFlags_ + ImVec2 Pos; // Position (always rounded-up to nearest pixel) + ImVec2 Size; // Current size (==SizeFull or collapsed title bar size) + ImVec2 SizeFull; // Size when non collapsed + ImVec2 SizeFullAtLastBegin; // Copy of SizeFull at the end of Begin. This is the reference value we'll use on the next frame to decide if we need scrollbars. + ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame. Include decoration, window title, border, menu, etc. + ImVec2 SizeContentsExplicit; // Size of contents explicitly set by the user via SetNextWindowContentSize() + ImVec2 WindowPadding; // Window padding at the time of begin. + float WindowRounding; // Window rounding at the time of begin. + float WindowBorderSize; // Window border size at the time of begin. + ImGuiID MoveId; // == window->GetID("#MOVE") + ImGuiID ChildId; // ID of corresponding item in parent window (for navigation to return from child window to parent window) + ImVec2 Scroll; + ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change) + ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered + ImVec2 ScrollbarSizes; // Size taken by scrollbars on each axis + bool ScrollbarX, ScrollbarY; + bool Active; // Set to true on Begin(), unless Collapsed + bool WasActive; + bool WriteAccessed; // Set to true when any widget access the current window + bool Collapsed; // Set when collapsing window to become only title-bar + bool WantCollapseToggle; + bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed) + bool Appearing; // Set during the frame where the window is appearing (or re-appearing) + bool Hidden; // Do not display (== (HiddenFramesForResize > 0) || + bool HasCloseButton; // Set when the window has a close button (p_open != NULL) + int BeginOrderWithinParent; // Order within immediate parent window, if we are a child window. Otherwise 0. + int BeginOrderWithinContext; // Order within entire imgui context. This is mostly used for debugging submission order related issues. + int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) + ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) + int AutoFitFramesX, AutoFitFramesY; + bool AutoFitOnlyGrows; + int AutoFitChildAxises; + ImGuiDir AutoPosLastDirection; + int HiddenFramesRegular; // Hide the window for N frames + int HiddenFramesForResize; // Hide the window for N frames while allowing items to be submitted so we can measure their size + ImGuiCond SetWindowPosAllowFlags; // store acceptable condition flags for SetNextWindowPos() use. + ImGuiCond SetWindowSizeAllowFlags; // store acceptable condition flags for SetNextWindowSize() use. + ImGuiCond SetWindowCollapsedAllowFlags; // store acceptable condition flags for SetNextWindowCollapsed() use. + ImVec2 SetWindowPosVal; // store window position when using a non-zero Pivot (position set needs to be processed when we know the window size) + ImVec2 SetWindowPosPivot; // store window pivot for positioning. ImVec2(0,0) when positioning from top-left corner; ImVec2(0.5f,0.5f) for centering; ImVec2(1,1) for bottom right. + + ImGuiWindowTempData DC; // Temporary per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the "DC" variable name. + ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack + ImRect ClipRect; // Current clipping rectangle. = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2. + ImRect OuterRectClipped; // = WindowRect just after setup in Begin(). == window->Rect() for root window. + ImRect InnerMainRect, InnerClipRect; + ImRect ContentsRegionRect; // FIXME: This is currently confusing/misleading. Maximum visible content position ~~ Pos + (SizeContentsExplicit ? SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis + int LastFrameActive; // Last frame number the window was Active. + float ItemWidthDefault; + ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items + ImGuiStorage StateStorage; + ImVector ColumnsStorage; + float FontWindowScale; // User scale multiplier per-window + int SettingsIdx; // Index into SettingsWindow[] (indices are always valid as we only grow the array from the back) + + ImDrawList* DrawList; // == &DrawListInst (for backward compatibility reason with code using imgui_internal.h we keep this a pointer) + ImDrawList DrawListInst; + ImGuiWindow* ParentWindow; // If we are a child _or_ popup window, this is pointing to our parent. Otherwise NULL. + ImGuiWindow* RootWindow; // Point to ourself or first ancestor that is not a child window. + ImGuiWindow* RootWindowForTitleBarHighlight; // Point to ourself or first ancestor which will display TitleBgActive color when this window is active. + ImGuiWindow* RootWindowForNav; // Point to ourself or first ancestor which doesn't have the NavFlattened flag. + + ImGuiWindow* NavLastChildNavWindow; // When going to the menu bar, we remember the child window we came from. (This could probably be made implicit if we kept g.Windows sorted by last focused including child window.) + ImGuiID NavLastIds[2]; // Last known NavId for this window, per layer (0/1) + ImRect NavRectRel[2]; // Reference rectangle, in window relative space + + // Navigation / Focus + // FIXME-NAV: Merge all this with the new Nav system, at least the request variables should be moved to ImGuiContext + int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister() + int FocusIdxTabCounter; // (same, but only count widgets which you can Tab through) + int FocusIdxAllRequestCurrent; // Item being requested for focus + int FocusIdxTabRequestCurrent; // Tab-able item being requested for focus + int FocusIdxAllRequestNext; // Item being requested for focus, for next update (relies on layout to be stable between the frame pressing TAB and the next frame) + int FocusIdxTabRequestNext; // " + +public: + ImGuiWindow(ImGuiContext* context, const char* name); + ~ImGuiWindow(); + + ImGuiID GetID(const char* str, const char* str_end = NULL); + ImGuiID GetID(const void* ptr); + ImGuiID GetIDNoKeepAlive(const char* str, const char* str_end = NULL); + ImGuiID GetIDNoKeepAlive(const void* ptr); + ImGuiID GetIDFromRectangle(const ImRect& r_abs); + + // We don't use g.FontSize because the window may be != g.CurrentWidow. + ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); } + float CalcFontSize() const { return GImGui->FontBaseSize * FontWindowScale; } + float TitleBarHeight() const { return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f; } + ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); } + float MenuBarHeight() const { return (Flags & ImGuiWindowFlags_MenuBar) ? DC.MenuBarOffset.y + CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f : 0.0f; } + ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); } +}; + +// Backup and restore just enough data to be able to use IsItemHovered() on item A after another B in the same window has overwritten the data. +struct ImGuiItemHoveredDataBackup +{ + ImGuiID LastItemId; + ImGuiItemStatusFlags LastItemStatusFlags; + ImRect LastItemRect; + ImRect LastItemDisplayRect; + + ImGuiItemHoveredDataBackup() { Backup(); } + void Backup() { ImGuiWindow* window = GImGui->CurrentWindow; LastItemId = window->DC.LastItemId; LastItemStatusFlags = window->DC.LastItemStatusFlags; LastItemRect = window->DC.LastItemRect; LastItemDisplayRect = window->DC.LastItemDisplayRect; } + void Restore() const { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemStatusFlags = LastItemStatusFlags; window->DC.LastItemRect = LastItemRect; window->DC.LastItemDisplayRect = LastItemDisplayRect; } +}; + +//----------------------------------------------------------------------------- +// Internal API +// No guarantee of forward compatibility here. +//----------------------------------------------------------------------------- + +namespace ImGui +{ + // We should always have a CurrentWindow in the stack (there is an implicit "Debug" window) + // If this ever crash because g.CurrentWindow is NULL it means that either + // - ImGui::NewFrame() has never been called, which is illegal. + // - You are calling ImGui functions after ImGui::EndFrame()/ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal. + inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; } + inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; } + IMGUI_API ImGuiWindow* FindWindowByName(const char* name); + IMGUI_API void FocusWindow(ImGuiWindow* window); + IMGUI_API void BringWindowToFront(ImGuiWindow* window); + IMGUI_API void BringWindowToBack(ImGuiWindow* window); + IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window); + IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent); + IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window); + IMGUI_API void SetCurrentFont(ImFont* font); + inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; } + + // Init + IMGUI_API void Initialize(ImGuiContext* context); + IMGUI_API void Shutdown(ImGuiContext* context); // Since 1.60 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext(). + + // NewFrame + IMGUI_API void UpdateHoveredWindowAndCaptureFlags(); + IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window); + IMGUI_API void UpdateMouseMovingWindow(); + + // Settings + IMGUI_API void MarkIniSettingsDirty(); + IMGUI_API void MarkIniSettingsDirty(ImGuiWindow* window); + IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name); + IMGUI_API ImGuiWindowSettings* FindWindowSettings(ImGuiID id); + + // Basic Accessors + inline ImGuiID GetItemID() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemId; } + inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; } + inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; } + IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); + IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window); + IMGUI_API void ClearActiveID(); + IMGUI_API ImGuiID GetHoveredID(); + IMGUI_API void SetHoveredID(ImGuiID id); + IMGUI_API void KeepAliveID(ImGuiID id); + IMGUI_API void MarkItemValueChanged(ImGuiID id); + + // Basic Helpers for widget code + IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f); + IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f); + IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL); + IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id); + IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged); + IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop = true); // Return true if focus is requested + IMGUI_API void FocusableItemUnregister(ImGuiWindow* window); + IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y); + IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); + IMGUI_API void PushMultiItemsWidths(int components, float width_full = 0.0f); + IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); + IMGUI_API void PopItemFlag(); + + // Popups, Modals, Tooltips + IMGUI_API void OpenPopupEx(ImGuiID id); + IMGUI_API void ClosePopup(ImGuiID id); + IMGUI_API void ClosePopupToLevel(int remaining); + IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window); + IMGUI_API bool IsPopupOpen(ImGuiID id); + IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags); + IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip = true); + IMGUI_API ImGuiWindow* GetFrontMostPopupModal(); + + // Navigation + IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit); + IMGUI_API void NavMoveRequestCancel(); + IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const ImRect& bb_rel, ImGuiNavMoveFlags move_flags); + IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); + IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode); + IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f); + IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate); + IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. + + // Drag and Drop + IMGUI_API bool BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id); + IMGUI_API void ClearDragDrop(); + IMGUI_API bool IsDragDropPayloadBeingAccepted(); + + // New Columns API (FIXME-WIP) + IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). + IMGUI_API void EndColumns(); // close columns + IMGUI_API void PushColumnClipRect(int column_index = -1); + + // Render helpers + // AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT. + // NB: All position are in absolute pixels coordinates (we are never using window coordinates internally) + IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); + IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width); + IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0,0), const ImRect* clip_rect = NULL); + IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); + IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f); + IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, int rounding_corners_flags = ~0); + IMGUI_API void RenderArrow(ImVec2 pos, ImGuiDir dir, float scale = 1.0f); + IMGUI_API void RenderBullet(ImVec2 pos); + IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col, float sz); + IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_TypeDefault); // Navigation highlight + IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. + + // Render helpers (those functions don't access any ImGui state!) + IMGUI_API void RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor = ImGuiMouseCursor_Arrow); + IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col); + IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding); + + // Widgets + IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0); + IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos, float radius); + IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2& pos); + IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags); + IMGUI_API void Scrollbar(ImGuiLayoutType direction); + IMGUI_API void VerticalSeparator(); // Vertical separator, for menu bars (use current line height). Not exposed because it is misleading and it doesn't have an effect on regular layout. + + // Widgets low-level behaviors + IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0); + IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power); + IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb); + IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f); + IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); + IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging + IMGUI_API void TreePushRawID(ImGuiID id); + + IMGUI_API bool InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); + IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format); + + IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags); + IMGUI_API void ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags); + + IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size); + + // Shade functions (write over already created vertices) + IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1); + IMGUI_API void ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp); + +} // namespace ImGui + +// ImFontAtlas internals +IMGUI_API bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas); +IMGUI_API void ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas); +IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent); +IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* spc); +IMGUI_API void ImFontAtlasBuildFinish(ImFontAtlas* atlas); +IMGUI_API void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_multiply_factor); +IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride); + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#ifdef _MSC_VER +#pragma warning (pop) +#endif diff --git a/Baikal/ImGUI/stb_rect_pack.h b/BaikalStandalone/ImGUI/stb_rect_pack.h similarity index 81% rename from Baikal/ImGUI/stb_rect_pack.h rename to BaikalStandalone/ImGUI/stb_rect_pack.h index c75527da..2b07dcc8 100644 --- a/Baikal/ImGUI/stb_rect_pack.h +++ b/BaikalStandalone/ImGUI/stb_rect_pack.h @@ -1,4 +1,4 @@ -// stb_rect_pack.h - v0.10 - public domain - rectangle packing +// stb_rect_pack.h - v0.11 - public domain - rectangle packing // Sean Barrett 2014 // // Useful for e.g. packing rectangular textures into an atlas. @@ -27,11 +27,14 @@ // Sean Barrett // Minor features // Martins Mozeiko +// github:IntellectualKitty +// // Bugfixes / warning fixes // Jeremy Jaussaud // // Version history: // +// 0.11 (2017-03-03) return packing success/fail result // 0.10 (2016-10-25) remove cast-away-const to avoid warnings // 0.09 (2016-08-27) fix compiler warnings // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) @@ -43,9 +46,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for license information. ////////////////////////////////////////////////////////////////////////////// // @@ -77,7 +78,7 @@ typedef int stbrp_coord; typedef unsigned short stbrp_coord; #endif -STBRP_DEF void stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); +STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); // Assign packed locations to rectangles. The rectangles are of type // 'stbrp_rect' defined below, stored in the array 'rects', and there // are 'num_rects' many of them. @@ -98,6 +99,9 @@ STBRP_DEF void stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int // arrays will probably produce worse packing results than calling it // a single time with the full rectangle array, but the option is // available. +// +// The function returns 1 if all of the rectangles were successfully +// packed and 0 otherwise. struct stbrp_rect { @@ -202,8 +206,10 @@ struct stbrp_context #ifdef _MSC_VER #define STBRP__NOTUSED(v) (void)(v) +#define STBRP__CDECL __cdecl #else #define STBRP__NOTUSED(v) (void)sizeof(v) +#define STBRP__CDECL #endif enum @@ -488,17 +494,14 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i STBRP_ASSERT(cur->next == NULL); { - stbrp_node *L1 = NULL, *L2 = NULL; int count=0; cur = context->active_head; while (cur) { - L1 = cur; cur = cur->next; ++count; } cur = context->free_head; while (cur) { - L2 = cur; cur = cur->next; ++count; } @@ -509,7 +512,7 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i return res; } -static int rect_height_compare(const void *a, const void *b) +static int STBRP__CDECL rect_height_compare(const void *a, const void *b) { const stbrp_rect *p = (const stbrp_rect *) a; const stbrp_rect *q = (const stbrp_rect *) b; @@ -520,18 +523,7 @@ static int rect_height_compare(const void *a, const void *b) return (p->w > q->w) ? -1 : (p->w < q->w); } -static int rect_width_compare(const void *a, const void *b) -{ - const stbrp_rect *p = (const stbrp_rect *) a; - const stbrp_rect *q = (const stbrp_rect *) b; - if (p->w > q->w) - return -1; - if (p->w < q->w) - return 1; - return (p->h > q->h) ? -1 : (p->h < q->h); -} - -static int rect_original_order(const void *a, const void *b) +static int STBRP__CDECL rect_original_order(const void *a, const void *b) { const stbrp_rect *p = (const stbrp_rect *) a; const stbrp_rect *q = (const stbrp_rect *) b; @@ -544,9 +536,9 @@ static int rect_original_order(const void *a, const void *b) #define STBRP__MAXVAL 0xffff #endif -STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) +STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) { - int i; + int i, all_rects_packed = 1; // we use the 'was_packed' field internally to allow sorting/unsorting for (i=0; i < num_rects; ++i) { @@ -576,8 +568,56 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n // unsort STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); - // set was_packed flags - for (i=0; i < num_rects; ++i) + // set was_packed flags and all_rects_packed status + for (i=0; i < num_rects; ++i) { rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); + if (!rects[i].was_packed) + all_rects_packed = 0; + } + + // return the all_rects_packed status + return all_rects_packed; } #endif + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +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. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +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 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. +------------------------------------------------------------------------------ +*/ diff --git a/Baikal/ImGUI/stb_textedit.h b/BaikalStandalone/ImGUI/stb_textedit.h similarity index 87% rename from Baikal/ImGUI/stb_textedit.h rename to BaikalStandalone/ImGUI/stb_textedit.h index 4b731a0c..9e12469b 100644 --- a/Baikal/ImGUI/stb_textedit.h +++ b/BaikalStandalone/ImGUI/stb_textedit.h @@ -1,10 +1,9 @@ -// [ImGui] this is a slightly modified version of stb_truetype.h 1.9. Those changes would need to be pushed into nothings/sb -// [ImGui] - fixed linestart handler when over last character of multi-line buffer + simplified existing code (#588, #815) -// [ImGui] - fixed a state corruption/crash bug in stb_text_redo and stb_textedit_discard_redo (#715) -// [ImGui] - fixed a crash bug in stb_textedit_discard_redo (#681) +// [ImGui] this is a slightly modified version of stb_textedit.h 1.12. Those changes would need to be pushed into nothings/stb +// [ImGui] - 2018-06: fixed undo/redo after pasting large amount of text (over 32 kb). Redo will still fail when undo buffers are exhausted, but text won't be corrupted (see nothings/stb issue #620) +// [ImGui] - 2018-06: fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321) // [ImGui] - fixed some minor warnings -// stb_textedit.h - v1.9 - public domain - Sean Barrett +// stb_textedit.h - v1.12 - public domain - Sean Barrett // Development of this library was sponsored by RAD Game Tools // // This C header file implements the guts of a multi-line text-editing @@ -23,9 +22,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for license information. // // // DEPENDENCIES @@ -37,6 +34,9 @@ // // VERSION HISTORY // +// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash +// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield +// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual // 1.9 (2016-08-27) customizable move-by-word // 1.8 (2016-04-02) better keyboard handling when mouse button is down // 1.7 (2015-09-13) change y range handling in case baseline is non-0 @@ -55,12 +55,13 @@ // // Ulf Winklemann: move-by-word in 1.1 // Fabian Giesen: secondary key inputs in 1.5 -// Martins Mozeiko: STB_TEXTEDIT_memmove +// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6 // // Bugfixes: // Scott Graham // Daniel Keller // Omar Cornut +// Dan Thompson // // USAGE // @@ -90,8 +91,8 @@ // moderate sizes. The undo system does no memory allocations, so // it grows STB_TexteditState by the worst-case storage which is (in bytes): // -// [4 + sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT -// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT +// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT +// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT // // // Implementation mode: @@ -114,7 +115,7 @@ // Symbols that must be the same in header-file and implementation mode: // // STB_TEXTEDIT_CHARTYPE the character type -// STB_TEXTEDIT_POSITIONTYPE small type that a valid cursor position +// STB_TEXTEDIT_POSITIONTYPE small type that is a valid cursor position // STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow // STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer // @@ -203,7 +204,7 @@ // void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) // int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) // int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len) -// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int key) +// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key) // // Each of these functions potentially updates the string and updates the // state. @@ -237,7 +238,9 @@ // inputs, set a high bit to distinguish the two; then you can define the // various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit // set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is -// clear. +// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to +// anything other type you wante before including. +// // // When rendering, you can read the cursor position and selection state from // the STB_TexteditState. @@ -297,9 +300,9 @@ typedef struct { // private data STB_TEXTEDIT_POSITIONTYPE where; - short insert_length; - short delete_length; - short char_storage; + STB_TEXTEDIT_POSITIONTYPE insert_length; + STB_TEXTEDIT_POSITIONTYPE delete_length; + int char_storage; } StbUndoRecord; typedef struct @@ -308,7 +311,7 @@ typedef struct StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT]; STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT]; short undo_point, redo_point; - short undo_char_point, redo_char_point; + int undo_char_point, redo_char_point; } StbUndoState; typedef struct @@ -450,6 +453,15 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y) // API click: on mouse down, move the cursor to the clicked location, and reset the selection static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) { + // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse + // goes off the top or bottom of the text + if( state->single_line ) + { + StbTexteditRow r; + STB_TEXTEDIT_LAYOUTROW(&r, str, 0); + y = r.ymin; + } + state->cursor = stb_text_locate_coord(str, x, y); state->select_start = state->cursor; state->select_end = state->cursor; @@ -459,9 +471,21 @@ static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *stat // API drag: on mouse drag, move the cursor and selection endpoint to the clicked location static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) { - int p = stb_text_locate_coord(str, x, y); + int p = 0; + + // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse + // goes off the top or bottom of the text + if( state->single_line ) + { + StbTexteditRow r; + STB_TEXTEDIT_LAYOUTROW(&r, str, 0); + y = r.ymin; + } + if (state->select_start == state->select_end) state->select_start = state->cursor; + + p = stb_text_locate_coord(str, x, y); state->cursor = state->select_end = p; } @@ -677,9 +701,8 @@ static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) } // API paste: replace existing selection with passed-in text -static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len) +static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len) { - STB_TEXTEDIT_CHARTYPE *text = (STB_TEXTEDIT_CHARTYPE *) ctext; // if there's a selection, the paste should delete it stb_textedit_clamp(str, state); stb_textedit_delete_selection(str,state); @@ -696,8 +719,12 @@ static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state return 0; } +#ifndef STB_TEXTEDIT_KEYTYPE +#define STB_TEXTEDIT_KEYTYPE int +#endif + // API key: process a keyboard input -static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int key) +static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key) { retry: switch (key) { @@ -1074,14 +1101,14 @@ static void stb_textedit_discard_undo(StbUndoState *state) if (state->undo_rec[0].char_storage >= 0) { int n = state->undo_rec[0].insert_length, i; // delete n characters from all other records - state->undo_char_point = state->undo_char_point - (short) n; // vsnet05 - STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) ((size_t)state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE))); + state->undo_char_point -= n; + STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE))); for (i=0; i < state->undo_point; ++i) if (state->undo_rec[i].char_storage >= 0) - state->undo_rec[i].char_storage = state->undo_rec[i].char_storage - (short) n; // vsnet05 // @OPTIMIZE: get rid of char_storage and infer it + state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it } --state->undo_point; - STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) ((size_t)state->undo_point*sizeof(state->undo_rec[0]))); + STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0]))); } } @@ -1097,14 +1124,17 @@ static void stb_textedit_discard_redo(StbUndoState *state) // if the k'th undo state has characters, clean those up if (state->undo_rec[k].char_storage >= 0) { int n = state->undo_rec[k].insert_length, i; - // delete n characters from all other records - state->redo_char_point = state->redo_char_point + (short) n; // vsnet05 - STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((size_t)(STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE))); + // move the remaining redo character data to the end of the buffer + state->redo_char_point += n; + STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE))); + // adjust the position of all the other records to account for above memmove for (i=state->redo_point; i < k; ++i) if (state->undo_rec[i].char_storage >= 0) - state->undo_rec[i].char_storage = state->undo_rec[i].char_storage + (short) n; // vsnet05 + state->undo_rec[i].char_storage += n; } - STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point, state->undo_rec + state->redo_point-1, (size_t) ((size_t)(STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0]))); + // now move all the redo records towards the end of the buffer; the first one is at 'redo_point' + STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0]))); + // now move redo_point to point to the new one ++state->redo_point; } } @@ -1140,15 +1170,15 @@ static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, return NULL; r->where = pos; - r->insert_length = (short) insert_len; - r->delete_length = (short) delete_len; + r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len; + r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len; if (insert_len == 0) { r->char_storage = -1; return NULL; } else { r->char_storage = state->undo_char_point; - state->undo_char_point = state->undo_char_point + (short) insert_len; + state->undo_char_point += insert_len; return &state->undo_char[r->char_storage]; } } @@ -1188,16 +1218,16 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) // there's definitely room to store the characters eventually while (s->undo_char_point + u.delete_length > s->redo_char_point) { - // there's currently not enough room, so discard a redo record - stb_textedit_discard_redo(s); // should never happen: if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) return; + // there's currently not enough room, so discard a redo record + stb_textedit_discard_redo(s); } r = &s->undo_rec[s->redo_point-1]; r->char_storage = s->redo_char_point - u.delete_length; - s->redo_char_point = s->redo_char_point - (short) u.delete_length; + s->redo_char_point = s->redo_char_point - u.delete_length; // now save the characters for (i=0; i < u.delete_length; ++i) @@ -1319,4 +1349,61 @@ static void stb_textedit_initialize_state(STB_TexteditState *state, int is_singl { stb_textedit_clear_state(state, is_single_line); } + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif + +static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len) +{ + return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE *) ctext, len); +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + #endif//STB_TEXTEDIT_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +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. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +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 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. +------------------------------------------------------------------------------ +*/ diff --git a/Baikal/ImGUI/stb_truetype.h b/BaikalStandalone/ImGUI/stb_truetype.h similarity index 78% rename from Baikal/ImGUI/stb_truetype.h rename to BaikalStandalone/ImGUI/stb_truetype.h index 92b9a875..f65deb50 100644 --- a/Baikal/ImGUI/stb_truetype.h +++ b/BaikalStandalone/ImGUI/stb_truetype.h @@ -1,4 +1,4 @@ -// stb_truetype.h - v1.14 - public domain +// stb_truetype.h - v1.19 - public domain // authored from 2009-2016 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: @@ -6,6 +6,7 @@ // extract glyph metrics // extract glyph shapes // render glyphs to one-channel bitmaps with antialiasing (box filter) +// render glyphs to one-channel SDF bitmaps (signed-distance field/function) // // Todo: // non-MS cmaps @@ -21,39 +22,40 @@ // Mikko Mononen: compound shape support, more cmap formats // Tor Andersson: kerning, subpixel rendering // Dougall Johnson: OpenType / Type 2 font handling +// Daniel Ribeiro Maciel: basic GPOS-based kerning // // Misc other: // Ryan Gordon // Simon Glass // github:IntellectualKitty +// Imanol Celaya +// Daniel Ribeiro Maciel // // Bug/warning reports/fixes: -// "Zer" on mollyrocket (with fix) -// Cass Everitt -// stoiko (Haemimont Games) -// Brian Hook -// Walter van Niftrik -// David Gow -// David Given -// Ivan-Assen Ivanov -// Anthony Pesch -// Johan Duparc -// Hou Qiming -// Fabian "ryg" Giesen -// Martins Mozeiko -// Cap Petschulat -// Omar Cornut -// github:aloucks -// Peter LaValle -// Sergey Popov -// Giumo X. Clanjor -// Higor Euripedes -// Thomas Fields -// Derek Vinyard -// +// "Zer" on mollyrocket Fabian "ryg" Giesen +// Cass Everitt Martins Mozeiko +// stoiko (Haemimont Games) Cap Petschulat +// Brian Hook Omar Cornut +// Walter van Niftrik github:aloucks +// David Gow Peter LaValle +// David Given Sergey Popov +// Ivan-Assen Ivanov Giumo X. Clanjor +// Anthony Pesch Higor Euripedes +// Johan Duparc Thomas Fields +// Hou Qiming Derek Vinyard +// Rob Loach Cort Stratton +// Kenney Phillis Jr. github:oyvindjam +// Brian Costabile github:vassvik +// // VERSION HISTORY // -// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts, num-fonts-in-TTC function +// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts // 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual // 1.11 (2016-04-02) fix unused-variable warning // 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef @@ -69,9 +71,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for license information. // // USAGE // @@ -91,7 +91,7 @@ // Improved 3D API (more shippable): // #include "stb_rect_pack.h" -- optional, but you really want it // stbtt_PackBegin() -// stbtt_PackSetOversample() -- for improved quality on small fonts +// stbtt_PackSetOversampling() -- for improved quality on small fonts // stbtt_PackFontRanges() -- pack and renders // stbtt_PackEnd() // stbtt_GetPackedQuad() @@ -109,6 +109,7 @@ // Character advance/positioning // stbtt_GetCodepointHMetrics() // stbtt_GetFontVMetrics() +// stbtt_GetFontVMetricsOS2() // stbtt_GetCodepointKernAdvance() // // Starting with version 1.06, the rasterizer was replaced with a new, @@ -164,7 +165,7 @@ // measurement for describing font size, defined as 72 points per inch. // stb_truetype provides a point API for compatibility. However, true // "per inch" conventions don't make much sense on computer displays -// since they different monitors have different number of pixels per +// since different monitors have different number of pixels per // inch. For example, Windows traditionally uses a convention that // there are 96 pixels per inch, thus making 'inch' measurements have // nothing to do with inches, and thus effectively defining a point to @@ -174,6 +175,39 @@ // for non-commercial fonts, thus making fonts scaled in points // according to the TrueType spec incoherently sized in practice. // +// DETAILED USAGE: +// +// Scale: +// Select how high you want the font to be, in points or pixels. +// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute +// a scale factor SF that will be used by all other functions. +// +// Baseline: +// You need to select a y-coordinate that is the baseline of where +// your text will appear. Call GetFontBoundingBox to get the baseline-relative +// bounding box for all characters. SF*-y0 will be the distance in pixels +// that the worst-case character could extend above the baseline, so if +// you want the top edge of characters to appear at the top of the +// screen where y=0, then you would set the baseline to SF*-y0. +// +// Current point: +// Set the current point where the first character will appear. The +// first character could extend left of the current point; this is font +// dependent. You can either choose a current point that is the leftmost +// point and hope, or add some padding, or check the bounding box or +// left-side-bearing of the first character to be displayed and set +// the current point based on that. +// +// Displaying a character: +// Compute the bounding box of the character. It will contain signed values +// relative to . I.e. if it returns x0,y0,x1,y1, +// then the character should be displayed in the rectangle from +// to #define STBTT_ifloor(x) ((int) floor(x)) @@ -406,6 +441,18 @@ int main(int arg, char **argv) #ifndef STBTT_sqrt #include #define STBTT_sqrt(x) sqrt(x) + #define STBTT_pow(x,y) pow(x,y) + #endif + + #ifndef STBTT_fmod + #include + #define STBTT_fmod(x,y) fmod(x,y) + #endif + + #ifndef STBTT_cos + #include + #define STBTT_cos(x) cos(x) + #define STBTT_acos(x) acos(x) #endif #ifndef STBTT_fabs @@ -431,7 +478,7 @@ int main(int arg, char **argv) #endif #ifndef STBTT_memcpy - #include + #include #define STBTT_memcpy memcpy #define STBTT_memset memset #endif @@ -494,7 +541,7 @@ typedef struct float x1,y1,s1,t1; // bottom-right } stbtt_aligned_quad; -STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // same data as above +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above int char_index, // character to display float *xpos, float *ypos, // pointers to current position in screen pixel space stbtt_aligned_quad *q, // output: quad to draw @@ -547,7 +594,7 @@ STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); #define STBTT_POINT_SIZE(x) (-(x)) -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); // Creates character bitmaps from the font_index'th font found in fontdata (use // font_index=0 if you don't know what that is). It creates num_chars_in_range @@ -572,7 +619,7 @@ typedef struct unsigned char h_oversample, v_oversample; // don't set these, they're used internally } stbtt_pack_range; -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); // Creates character bitmaps from multiple ranges of characters stored in // ranges. This will usually create a better-packed bitmap than multiple // calls to stbtt_PackFontRange. Note that you can call this multiple @@ -594,7 +641,7 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h // To use with PackFontRangesGather etc., you must set it before calls // call to PackFontRangesGatherRects. -STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, // same data as above +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above int char_index, // character to display float *xpos, float *ypos, // pointers to current position in screen pixel space stbtt_aligned_quad *q, // output: quad to draw @@ -657,7 +704,7 @@ struct stbtt_fontinfo int numGlyphs; // number of glyphs, needed for range checking - int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf + int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf int index_map; // a cmap mapping for our chosen character encoding int indexToLocFormat; // format needed to map from glyph index to glyph @@ -714,6 +761,12 @@ STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, in // these are expressed in unscaled coordinates, so you must multiply by // the scale factor for a given size +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); +// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 +// table (specific to MS/Windows TTF files). +// +// Returns 1 on success (table present), 0 on failure. + STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); // the bounding box around all possible characters @@ -808,6 +861,10 @@ STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, uns // same as stbtt_MakeCodepointBitmap, but you can specify a subpixel // shift for the character +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint); +// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering +// is performed (see stbtt_PackSetOversampling) + STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); // get the bbox of the bitmap centered around the glyph origin; so the // bitmap width is ix1-ix0, height is iy1-iy0, and location to place @@ -825,6 +882,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); @@ -847,6 +905,64 @@ STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap int invert, // if non-zero, vertically flip shape void *userdata); // context for to STBTT_MALLOC +////////////////////////////////////////////////////////////////////////////// +// +// Signed Distance Function (or Field) rendering + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); +// frees the SDF bitmap allocated below + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +// These functions compute a discretized SDF field for a single character, suitable for storing +// in a single-channel texture, sampling with bilinear filtering, and testing against +// larger than some threshhold to produce scalable fonts. +// info -- the font +// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap +// glyph/codepoint -- the character to generate the SDF for +// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), +// which allows effects like bit outlines +// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) +// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) +// if positive, > onedge_value is inside; if negative, < onedge_value is inside +// width,height -- output height & width of the SDF bitmap (including padding) +// xoff,yoff -- output origin of the character +// return value -- a 2D array of bytes 0..255, width*height in size +// +// pixel_dist_scale & onedge_value are a scale & bias that allows you to make +// optimal use of the limited 0..255 for your application, trading off precision +// and special effects. SDF values outside the range 0..255 are clamped to 0..255. +// +// Example: +// scale = stbtt_ScaleForPixelHeight(22) +// padding = 5 +// onedge_value = 180 +// pixel_dist_scale = 180/5.0 = 36.0 +// +// This will create an SDF bitmap in which the character is about 22 pixels +// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled +// shape, sample the SDF at each pixel and fill the pixel if the SDF value +// is greater than or equal to 180/255. (You'll actually want to antialias, +// which is beyond the scope of this example.) Additionally, you can compute +// offset outlines (e.g. to stroke the character border inside & outside, +// or only outside). For example, to fill outside the character up to 3 SDF +// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above +// choice of variables maps a range from 5 pixels outside the shape to +// 2 pixels inside the shape to 0..255; this is intended primarily for apply +// outside effects only (the interior range is needed to allow proper +// antialiasing of the font at *smaller* sizes) +// +// The function computes the SDF analytically at each SDF pixel, not by e.g. +// building a higher-res bitmap and approximating it. In theory the quality +// should be as high as possible for an SDF of this size & representation, but +// unclear if this is true in practice (perhaps building a higher-res bitmap +// and computing from that can allow drop-out prevention). +// +// The algorithm has not been optimized at all, so expect it to be slow +// if computing lots of characters or very large sizes. + + + ////////////////////////////////////////////////////////////////////////////// // // Finding the right font... @@ -1231,6 +1347,7 @@ static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, in info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required info->kern = stbtt__find_table(data, fontstart, "kern"); // not required + info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required if (!cmap || !info->head || !info->hhea || !info->hmtx) return 0; @@ -2084,7 +2201,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st // push immediate if (b0 == 255) { - f = (float)stbtt__buf_get32(&b) / 0x10000; + f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; } else { stbtt__buf_skip(&b, -1); f = (float)(stbtt_int16)stbtt__cff_int(&b); @@ -2122,12 +2239,10 @@ static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, in { stbtt__csctx c = STBTT__CSCTX_INIT(1); int r = stbtt__run_charstring(info, glyph_index, &c); - if (x0) { - *x0 = r ? c.min_x : 0; - *y0 = r ? c.min_y : 0; - *x1 = r ? c.max_x : 0; - *y1 = r ? c.max_y : 0; - } + if (x0) *x0 = r ? c.min_x : 0; + if (y0) *y0 = r ? c.min_y : 0; + if (x1) *x1 = r ? c.max_x : 0; + if (y1) *y1 = r ? c.max_y : 0; return r ? c.num_vertices : 0; } @@ -2151,7 +2266,7 @@ STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_inde } } -STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) { stbtt_uint8 *data = info->data + info->kern; stbtt_uint32 needle, straw; @@ -2181,9 +2296,261 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, return 0; } +static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) +{ + stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); + switch(coverageFormat) { + case 1: { + stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); + + // Binary search. + stbtt_int32 l=0, r=glyphCount-1, m; + int straw, needle=glyph; + while (l <= r) { + stbtt_uint8 *glyphArray = coverageTable + 4; + stbtt_uint16 glyphID; + m = (l + r) >> 1; + glyphID = ttUSHORT(glyphArray + 2 * m); + straw = glyphID; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + return m; + } + } + } break; + + case 2: { + stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); + stbtt_uint8 *rangeArray = coverageTable + 4; + + // Binary search. + stbtt_int32 l=0, r=rangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *rangeRecord; + m = (l + r) >> 1; + rangeRecord = rangeArray + 6 * m; + strawStart = ttUSHORT(rangeRecord); + strawEnd = ttUSHORT(rangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else { + stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); + return startCoverageIndex + glyph - strawStart; + } + } + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + } break; + } + + return -1; +} + +static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) +{ + stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); + switch(classDefFormat) + { + case 1: { + stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); + stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); + stbtt_uint8 *classDef1ValueArray = classDefTable + 6; + + if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) + return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); + + classDefTable = classDef1ValueArray + 2 * glyphCount; + } break; + + case 2: { + stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); + stbtt_uint8 *classRangeRecords = classDefTable + 4; + + // Binary search. + stbtt_int32 l=0, r=classRangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *classRangeRecord; + m = (l + r) >> 1; + classRangeRecord = classRangeRecords + 6 * m; + strawStart = ttUSHORT(classRangeRecord); + strawEnd = ttUSHORT(classRangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else + return (stbtt_int32)ttUSHORT(classRangeRecord + 4); + } + + classDefTable = classRangeRecords + 6 * classRangeCount; + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + } break; + } + + return -1; +} + +// Define to STBTT_assert(x) if you want to break on unimplemented formats. +#define STBTT_GPOS_TODO_assert(x) + +static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint16 lookupListOffset; + stbtt_uint8 *lookupList; + stbtt_uint16 lookupCount; + stbtt_uint8 *data; + stbtt_int32 i; + + if (!info->gpos) return 0; + + data = info->data + info->gpos; + + if (ttUSHORT(data+0) != 1) return 0; // Major version 1 + if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 + + lookupListOffset = ttUSHORT(data+8); + lookupList = data + lookupListOffset; + lookupCount = ttUSHORT(lookupList); + + for (i=0; i> 1; + pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; + secondGlyph = ttUSHORT(pairValue); + straw = secondGlyph; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + stbtt_int16 xAdvance = ttSHORT(pairValue + 2); + return xAdvance; + } + } + } break; + + case 2: { + stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); + stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); + + stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); + stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); + int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); + int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); + + stbtt_uint16 class1Count = ttUSHORT(table + 12); + stbtt_uint16 class2Count = ttUSHORT(table + 14); + STBTT_assert(glyph1class < class1Count); + STBTT_assert(glyph2class < class2Count); + + // TODO: Support more formats. + STBTT_GPOS_TODO_assert(valueFormat1 == 4); + if (valueFormat1 != 4) return 0; + STBTT_GPOS_TODO_assert(valueFormat2 == 0); + if (valueFormat2 != 0) return 0; + + if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) { + stbtt_uint8 *class1Records = table + 16; + stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count); + stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class); + return xAdvance; + } + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + break; + }; + } + } + break; + }; + + default: + // TODO: Implement other stuff. + break; + } + } + + return 0; +} + +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) +{ + int xAdvance = 0; + + if (info->gpos) + xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); + + if (info->kern) + xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); + + return xAdvance; +} + STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) { - if (!info->kern) // if no kerning table, don't waste time looking up both codepoint->glyphs + if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs return 0; return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); } @@ -2200,6 +2567,17 @@ STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, in if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); } +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap) +{ + int tab = stbtt__find_table(info->data, info->fontstart, "OS/2"); + if (!tab) + return 0; + if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); + if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); + if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); + return 1; +} + STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) { *x0 = ttSHORT(info->data + info->head + 36); @@ -2296,7 +2674,7 @@ static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) hh->num_remaining_in_head_chunk = count; } --hh->num_remaining_in_head_chunk; - return (char *) (hh->head) + size * hh->num_remaining_in_head_chunk; + return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; } } @@ -2692,19 +3070,18 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, // from the other y segment, and it might ignored as an empty segment. to avoid // that, we need to explicitly produce segments based on x positions. - // rename variables to clear pairs + // rename variables to clearly-defined pairs float y0 = y_top; float x1 = (float) (x); float x2 = (float) (x+1); float x3 = xb; float y3 = y_bottom; - float y1,y2; // x = e->x + e->dx * (y-y_top) // (y-y_top) = (x - e->x) / e->dx // y = (x - e->x) / e->dx + y_top - y1 = (x - x0) / dx + y_top; - y2 = (x+1 - x0) / dx + y_top; + float y1 = (x - x0) / dx + y_top; + float y2 = (x+1 - x0) / dx + y_top; if (x0 < x1 && x3 > x2) { // three segments descending down-right stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); @@ -3131,8 +3508,9 @@ static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) { - float scale = scale_x > scale_y ? scale_y : scale_x; - int winding_count, *winding_lengths; + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count = 0; + int *winding_lengths = NULL; stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); if (windings) { stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); @@ -3220,6 +3598,11 @@ STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo * return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); } +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint)); +} + STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) { stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); @@ -3287,11 +3670,11 @@ static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // fo return bottom_y; } -STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) { float d3d_bias = opengl_fillrule ? 0 : -0.5f; float ipw = 1.0f / pw, iph = 1.0f / ph; - stbtt_bakedchar *b = chardata + char_index; + const stbtt_bakedchar *b = chardata + char_index; int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); @@ -3599,6 +3982,29 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb return k; } +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, + output, + out_w - (prefilter_x - 1), + out_h - (prefilter_y - 1), + out_stride, + scale_x, + scale_y, + shift_x, + shift_y, + glyph); + + if (prefilter_x > 1) + stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x); + + if (prefilter_y > 1) + stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y); + + *sub_x = stbtt__oversample_shift(prefilter_x); + *sub_y = stbtt__oversample_shift(prefilter_y); +} + // rects array must be big enough to accommodate all characters in the given ranges STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) { @@ -3687,7 +4093,7 @@ STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); } -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) { stbtt_fontinfo info; int i,j,n, return_value = 1; @@ -3723,7 +4129,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontd return return_value; } -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) { stbtt_pack_range range; @@ -3735,10 +4141,10 @@ STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontda return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); } -STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) { float ipw = 1.0f / pw, iph = 1.0f / ph; - stbtt_packedchar *b = chardata + char_index; + const stbtt_packedchar *b = chardata + char_index; if (align_to_integer) { float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); @@ -3762,6 +4168,387 @@ STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, i *xpos += b->xadvance; } +////////////////////////////////////////////////////////////////////////////// +// +// sdf computation +// + +#define STBTT_min(a,b) ((a) < (b) ? (a) : (b)) +#define STBTT_max(a,b) ((a) < (b) ? (b) : (a)) + +static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) +{ + float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; + float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; + float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; + float roperp = orig[1]*ray[0] - orig[0]*ray[1]; + + float a = q0perp - 2*q1perp + q2perp; + float b = q1perp - q0perp; + float c = q0perp - roperp; + + float s0 = 0., s1 = 0.; + int num_s = 0; + + if (a != 0.0) { + float discr = b*b - a*c; + if (discr > 0.0) { + float rcpna = -1 / a; + float d = (float) STBTT_sqrt(discr); + s0 = (b+d) * rcpna; + s1 = (b-d) * rcpna; + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { + if (num_s == 0) s0 = s1; + ++num_s; + } + } + } else { + // 2*b*s + c = 0 + // s = -c / (2*b) + s0 = c / (-2 * b); + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + } + + if (num_s == 0) + return 0; + else { + float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); + float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; + + float q0d = q0[0]*rayn_x + q0[1]*rayn_y; + float q1d = q1[0]*rayn_x + q1[1]*rayn_y; + float q2d = q2[0]*rayn_x + q2[1]*rayn_y; + float rod = orig[0]*rayn_x + orig[1]*rayn_y; + + float q10d = q1d - q0d; + float q20d = q2d - q0d; + float q0rd = q0d - rod; + + hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; + hits[0][1] = a*s0+b; + + if (num_s > 1) { + hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; + hits[1][1] = a*s1+b; + return 2; + } else { + return 1; + } + } +} + +static int equal(float *a, float *b) +{ + return (a[0] == b[0] && a[1] == b[1]); +} + +static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) +{ + int i; + float orig[2], ray[2] = { 1, 0 }; + float y_frac; + int winding = 0; + + orig[0] = x; + orig[1] = y; + + // make sure y never passes through a vertex of the shape + y_frac = (float) STBTT_fmod(y, 1.0f); + if (y_frac < 0.01f) + y += 0.01f; + else if (y_frac > 0.99f) + y -= 0.01f; + orig[1] = y; + + // test a ray from (-infinity,y) to (x,y) + for (i=0; i < nverts; ++i) { + if (verts[i].type == STBTT_vline) { + int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; + int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } + if (verts[i].type == STBTT_vcurve) { + int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; + int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; + int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; + int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); + int by = STBTT_max(y0,STBTT_max(y1,y2)); + if (y > ay && y < by && x > ax) { + float q0[2],q1[2],q2[2]; + float hits[2][2]; + q0[0] = (float)x0; + q0[1] = (float)y0; + q1[0] = (float)x1; + q1[1] = (float)y1; + q2[0] = (float)x2; + q2[1] = (float)y2; + if (equal(q0,q1) || equal(q1,q2)) { + x0 = (int)verts[i-1].x; + y0 = (int)verts[i-1].y; + x1 = (int)verts[i ].x; + y1 = (int)verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } else { + int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); + if (num_hits >= 1) + if (hits[0][0] < 0) + winding += (hits[0][1] < 0 ? -1 : 1); + if (num_hits >= 2) + if (hits[1][0] < 0) + winding += (hits[1][1] < 0 ? -1 : 1); + } + } + } + } + return winding; +} + +static float stbtt__cuberoot( float x ) +{ + if (x<0) + return -(float) STBTT_pow(-x,1.0f/3.0f); + else + return (float) STBTT_pow( x,1.0f/3.0f); +} + +// x^3 + c*x^2 + b*x + a = 0 +static int stbtt__solve_cubic(float a, float b, float c, float* r) +{ + float s = -a / 3; + float p = b - a*a / 3; + float q = a * (2*a*a - 9*b) / 27 + c; + float p3 = p*p*p; + float d = q*q + 4*p3 / 27; + if (d >= 0) { + float z = (float) STBTT_sqrt(d); + float u = (-q + z) / 2; + float v = (-q - z) / 2; + u = stbtt__cuberoot(u); + v = stbtt__cuberoot(v); + r[0] = s + u + v; + return 1; + } else { + float u = (float) STBTT_sqrt(-p/3); + float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative + float m = (float) STBTT_cos(v); + float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; + r[0] = s + u * 2 * m; + r[1] = s - u * (m + n); + r[2] = s - u * (m - n); + + //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? + //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); + //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); + return 3; + } +} + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + float scale_x = scale, scale_y = scale; + int ix0,iy0,ix1,iy1; + int w,h; + unsigned char *data; + + // if one scale is 0, use same scale for both + if (scale_x == 0) scale_x = scale_y; + if (scale_y == 0) { + if (scale_x == 0) return NULL; // if both scales are 0, return NULL + scale_y = scale_x; + } + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); + + // if empty, return NULL + if (ix0 == ix1 || iy0 == iy1) + return NULL; + + ix0 -= padding; + iy0 -= padding; + ix1 += padding; + iy1 += padding; + + w = (ix1 - ix0); + h = (iy1 - iy0); + + if (width ) *width = w; + if (height) *height = h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + // invert for y-downwards bitmaps + scale_y = -scale_y; + + { + int x,y,i,j; + float *precompute; + stbtt_vertex *verts; + int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); + data = (unsigned char *) STBTT_malloc(w * h, info->userdata); + precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); + + for (i=0,j=num_verts-1; i < num_verts; j=i++) { + if (verts[i].type == STBTT_vline) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; + float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); + precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist; + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; + float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; + float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float len2 = bx*bx + by*by; + if (len2 != 0.0f) + precompute[i] = 1.0f / (bx*bx + by*by); + else + precompute[i] = 0.0f; + } else + precompute[i] = 0.0f; + } + + for (y=iy0; y < iy1; ++y) { + for (x=ix0; x < ix1; ++x) { + float val; + float min_dist = 999999.0f; + float sx = (float) x + 0.5f; + float sy = (float) y + 0.5f; + float x_gspace = (sx / scale_x); + float y_gspace = (sy / scale_y); + + int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path + + for (i=0; i < num_verts; ++i) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + + // check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve + float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + if (verts[i].type == STBTT_vline) { + float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; + + // coarse culling against bbox + //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && + // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) + float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; + STBTT_assert(i != 0); + if (dist < min_dist) { + // check position along line + // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) + // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) + float dx = x1-x0, dy = y1-y0; + float px = x0-sx, py = y0-sy; + // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy + // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve + float t = -(px*dx + py*dy) / (dx*dx + dy*dy); + if (t >= 0.0f && t <= 1.0f) + min_dist = dist; + } + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; + float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; + float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); + float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); + float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); + float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); + // coarse culling against bbox to avoid computing cubic unnecessarily + if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { + int num=0; + float ax = x1-x0, ay = y1-y0; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float mx = x0 - sx, my = y0 - sy; + float res[3],px,py,t,it; + float a_inv = precompute[i]; + if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula + float a = 3*(ax*bx + ay*by); + float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); + float c = mx*ax+my*ay; + if (a == 0.0) { // if a is 0, it's linear + if (b != 0.0) { + res[num++] = -c/b; + } + } else { + float discriminant = b*b - 4*a*c; + if (discriminant < 0) + num = 0; + else { + float root = (float) STBTT_sqrt(discriminant); + res[0] = (-b - root)/(2*a); + res[1] = (-b + root)/(2*a); + num = 2; // don't bother distinguishing 1-solution case, as code below will still work + } + } + } else { + float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point + float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; + float d = (mx*ax+my*ay) * a_inv; + num = stbtt__solve_cubic(b, c, d, res); + } + if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { + t = res[0], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { + t = res[1], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { + t = res[2], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + } + } + } + if (winding == 0) + min_dist = -min_dist; // if outside the shape, value is negative + val = onedge_value + pixel_dist_scale * min_dist; + if (val < 0) + val = 0; + else if (val > 255) + val = 255; + data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; + } + } + STBTT_free(precompute, info->userdata); + STBTT_free(verts, info->userdata); + } + return data; +} + +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} ////////////////////////////////////////////////////////////////////////////// // @@ -3969,6 +4756,13 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const // FULL VERSION HISTORY // +// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts // 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual // 1.11 (2016-04-02) fix unused-variable warning // 1.10 (2016-04-02) allow user-defined fabs() replacement @@ -4016,3 +4810,45 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const // 0.2 (2009-03-11) Fix unsigned/signed char warnings // 0.1 (2009-03-09) First public release // + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +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. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +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 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. +------------------------------------------------------------------------------ +*/ diff --git a/Baikal/GLSL/simple.fsh b/BaikalStandalone/Kernels/GLSL/simple.fsh similarity index 100% rename from Baikal/GLSL/simple.fsh rename to BaikalStandalone/Kernels/GLSL/simple.fsh diff --git a/Baikal/GLSL/simple.vsh b/BaikalStandalone/Kernels/GLSL/simple.vsh similarity index 100% rename from Baikal/GLSL/simple.vsh rename to BaikalStandalone/Kernels/GLSL/simple.vsh diff --git a/BaikalStandalone/Utils/config_manager.cpp b/BaikalStandalone/Utils/config_manager.cpp new file mode 100644 index 00000000..20f9d70f --- /dev/null +++ b/BaikalStandalone/Utils/config_manager.cpp @@ -0,0 +1,247 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "config_manager.h" + +#include "CLW.h" +#include "RenderFactory/render_factory.h" + +#ifndef APP_BENCHMARK + +#ifdef __APPLE__ +#include +#include +#elif WIN32 +#define NOMINMAX +#include +#include "GL/glew.h" +#else +#include +#include +#include +#endif + +void ConfigManager::CreateConfigs( + Mode mode, + bool interop, + std::vector& configs, + int initial_num_bounces, + int req_platform_index, + int req_device_index) +{ + std::vector platforms; + + CLWPlatform::CreateAllPlatforms(platforms); + + if (platforms.size() == 0) + { + throw std::runtime_error("No OpenCL platforms installed."); + } + + configs.clear(); + + if (req_platform_index >= (int)platforms.size()) + throw std::runtime_error("There is no such platform index"); + else if ((req_platform_index > 0) && + (req_device_index >= (int)platforms[req_platform_index].GetDeviceCount())) + throw std::runtime_error("There is no such device index"); + + bool hasprimary = false; + + int i = (req_platform_index >= 0) ? (req_platform_index) : 0; + + int platforms_end = (req_platform_index >= 0) ? + (req_platform_index + 1) : ((int)platforms.size()); + + for (; i < platforms_end; ++i) + { + int d = (req_device_index >= 0) ? (req_device_index) : 0; + int device_end = 0; + + if (req_platform_index < 0 || req_device_index < 0) + device_end = (int)platforms[i].GetDeviceCount(); + else + device_end = req_device_index + 1; + + for (; d < device_end; ++d) + { + if (req_platform_index < 0) + { + if ((mode == kUseGpus || mode == kUseSingleGpu) && platforms[i].GetDevice(d).GetType() != CL_DEVICE_TYPE_GPU) + continue; + + if ((mode == kUseCpus || mode == kUseSingleCpu) && platforms[i].GetDevice(d).GetType() != CL_DEVICE_TYPE_CPU) + continue; + } + + Config cfg; + cfg.caninterop = false; + bool create_without_interop = true; + + if (platforms[i].GetDevice(d).HasGlInterop() && !hasprimary && interop) + { +#ifdef WIN32 + cl_context_properties props[] = + { + //OpenCL platform + CL_CONTEXT_PLATFORM, (cl_context_properties)((cl_platform_id)platforms[i]), + //OpenGL context + CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(), + //HDC used to create the OpenGL context + CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC(), + 0 + }; +#elif __linux__ + cl_context_properties props[] = + { + //OpenCL platform + CL_CONTEXT_PLATFORM, (cl_context_properties)((cl_platform_id)platforms[i]), + //OpenGL context + CL_GL_CONTEXT_KHR, (cl_context_properties)glXGetCurrentContext(), + //HDC used to create the OpenGL context + CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay(), + 0 + }; +#elif __APPLE__ + CGLContextObj kCGLContext = CGLGetCurrentContext(); + CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext); + // Create CL context properties, add handle & share-group enum ! + cl_context_properties props[] = { + CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, + (cl_context_properties)kCGLShareGroup, 0 + }; +#endif + try + { + cfg.context = CLWContext::Create(platforms[i].GetDevice(d), props); + cfg.type = kPrimary; + cfg.caninterop = true; + hasprimary = true; + create_without_interop = false; + } + catch (CLWException& ex) + { + // CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR (code -1000) means that + // CL and GL interop not on the same device. + // If we've got another error, throw it up, else simply + // continue execution and get to next 'if' block + if (ex.errcode_ != -1000) + { + throw; + } + + } + } + + if (create_without_interop) + { + cfg.context = CLWContext::Create(platforms[i].GetDevice(d)); + cfg.type = kSecondary; + } + + configs.push_back(std::move(cfg)); + + if (mode == kUseSingleGpu || mode == kUseSingleCpu) + break; + } + + if (configs.size() == 1 && (mode == kUseSingleGpu || mode == kUseSingleCpu)) + break; + } + + if (configs.size() == 0) + { + throw std::runtime_error( + "No devices was selected (probably device index type does not correspond with real device type)."); + } + + if (!hasprimary) + { + configs[0].type = kPrimary; + } + + for (std::size_t i = 0; i < configs.size(); ++i) + { + configs[i].factory = std::make_unique(configs[i].context, "cache"); + configs[i].controller = configs[i].factory->CreateSceneController(); + configs[i].renderer = configs[i].factory->CreateRenderer(Baikal::ClwRenderFactory::RendererType::kUnidirectionalPathTracer); + } +} + +#else +void ConfigManager::CreateConfigs( + Mode mode, + bool interop, + std::vector& configs, + int initial_num_bounces, + int req_platform_index, + int req_device_index) +{ + std::vector platforms; + + CLWPlatform::CreateAllPlatforms(platforms); + + if (platforms.size() == 0) + { + throw std::runtime_error("No OpenCL platforms installed."); + } + + configs.clear(); + + bool hasprimary = false; + for (int i = 0; i < (int)platforms.size(); ++i) + { + for (int d = 0; d < (int)platforms[i].GetDeviceCount(); ++d) + { + if ((mode == kUseGpus || mode == kUseSingleGpu) && platforms[i].GetDevice(d).GetType() != CL_DEVICE_TYPE_GPU) + continue; + + if ((mode == kUseCpus || mode == kUseSingleCpu) && platforms[i].GetDevice(d).GetType() != CL_DEVICE_TYPE_CPU) + continue; + + Config cfg; + cfg.caninterop = false; + cfg.context = CLWContext::Create(platforms[i].GetDevice(d)); + cfg.type = kSecondary; + + configs.push_back(std::move(cfg)); + + if (mode == kUseSingleGpu || mode == kUseSingleCpu) + break; + } + + if (configs.size() == 1 && (mode == kUseSingleGpu || mode == kUseSingleCpu)) + break; + } + + if (!hasprimary) + { + configs[0].type = kPrimary; + } + + for (int i = 0; i < configs.size(); ++i) + { + configs[i].factory = std::make_unique(configs[i].context); + configs[i].controller = configs[i].factory->CreateSceneController(); + configs[i].renderer = configs[i].factory->CreateRenderer(Baikal::ClwRenderFactory::RendererType::kUnidirectionalPathTracer); + } +} +#endif //APP_BENCHMARK diff --git a/BaikalStandalone/Utils/config_manager.h b/BaikalStandalone/Utils/config_manager.h new file mode 100644 index 00000000..e91c619c --- /dev/null +++ b/BaikalStandalone/Utils/config_manager.h @@ -0,0 +1,85 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 CONFIG_MANAGER_H +#define CONFIG_MANAGER_H + +#include "CLW.h" +#include "RenderFactory/clw_render_factory.h" +#include "Renderers/renderer.h" +#include +#include + +namespace Baikal +{ + class Renderer; +} + +class ConfigManager +{ +public: + + enum DeviceType + { + kPrimary, + kSecondary + }; + + enum Mode + { + kUseAll, + kUseGpus, + kUseSingleGpu, + kUseSingleCpu, + kUseCpus + }; + + struct Config + { + DeviceType type; + std::unique_ptr renderer; + std::unique_ptr> controller; + std::unique_ptr> factory; + CLWContext context; + bool caninterop; + + Config() = default; + + Config(Config&& cfg) = default; + + ~Config() + { + } + }; + + static void CreateConfigs( + Mode mode, + bool interop, + std::vector& renderers, + int initial_num_bounces, + int req_platform_index = -1, + int req_device_index = -1); + +private: + +}; + +#endif // CONFIG_MANAGER_H diff --git a/Baikal/Utils/shader_manager.cpp b/BaikalStandalone/Utils/shader_manager.cpp similarity index 100% rename from Baikal/Utils/shader_manager.cpp rename to BaikalStandalone/Utils/shader_manager.cpp diff --git a/Baikal/Utils/shader_manager.h b/BaikalStandalone/Utils/shader_manager.h similarity index 100% rename from Baikal/Utils/shader_manager.h rename to BaikalStandalone/Utils/shader_manager.h diff --git a/BaikalStandalone/cache/placeholder.txt b/BaikalStandalone/cache/placeholder.txt new file mode 100644 index 00000000..cb0bb35c --- /dev/null +++ b/BaikalStandalone/cache/placeholder.txt @@ -0,0 +1 @@ +placeholder for output images \ No newline at end of file diff --git a/BaikalStandalone/main.cpp b/BaikalStandalone/main.cpp new file mode 100644 index 00000000..c7a82ed6 --- /dev/null +++ b/BaikalStandalone/main.cpp @@ -0,0 +1,47 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "Application/application.h" + +int main(int argc, char * argv[]) +{ + try + { + Baikal::Application app(argc, argv); + app.Run(); + + } + catch (CLWException& ex) + { + std::cerr << ex.what() << " (OpenCL error code: " + << ex.errcode_ << ")" << std::endl; + return -1; + + } + catch (std::exception& ex) + { + std::cerr << ex.what() << std::endl; + return -1; + + } + + return 0; +} diff --git a/BaikalTest/CMakeLists.txt b/BaikalTest/CMakeLists.txt new file mode 100644 index 00000000..61c6dd8c --- /dev/null +++ b/BaikalTest/CMakeLists.txt @@ -0,0 +1,49 @@ +set(SOURCES + aov.h + basic.h + camera.h + input_maps.h + internal.h + light.h + main.cpp + material.h + test_scenes.h + uberv2.h) + +add_executable(BaikalTest ${SOURCES}) +target_compile_features(BaikalTest PRIVATE cxx_std_14) + +target_include_directories(BaikalTest PRIVATE .) +target_link_libraries(BaikalTest PRIVATE Baikal BaikalIO GTest) + +set_target_properties(BaikalTest + PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${Baikal_SOURCE_DIR}/BaikalTest FOLDER Baikal) +target_compile_definitions(BaikalTest PRIVATE _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING=1) + +# Add symbolic links to BaikalTest/OutputImages and BaikalTest/ReferenceImages directory +set(BAIKALTEST_REFERENCEIMAGES_DIR ReferenceImages) +FILE(TO_NATIVE_PATH ${Baikal_SOURCE_DIR}/BaikalTest/${BAIKALTEST_REFERENCEIMAGES_DIR} BAIKALTEST_REFERENCEIMAGES_SRC) +FILE(TO_NATIVE_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${BAIKALTEST_REFERENCEIMAGES_DIR} BAIKALTEST_REFERENCEIMAGES_DST) + +set(BAIKALTEST_OUTPUTIMAGES_DIR OutputImages) +FILE(TO_NATIVE_PATH ${Baikal_SOURCE_DIR}/BaikalTest/${BAIKALTEST_OUTPUTIMAGES_DIR} BAIKALTEST_OUTPUTIMAGES_SRC) +FILE(TO_NATIVE_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${BAIKALTEST_OUTPUTIMAGES_DIR} BAIKALTEST_OUTPUTIMAGES_DST) + +if (WIN32) + add_custom_target(BaikalTestImagesDir ALL + COMMAND IF NOT EXIST ${BAIKALTEST_REFERENCEIMAGES_DST} mklink /D ${BAIKALTEST_REFERENCEIMAGES_DST} ${BAIKALTEST_REFERENCEIMAGES_SRC} + COMMAND IF NOT EXIST ${BAIKALTEST_OUTPUTIMAGES_DST} mklink /D ${BAIKALTEST_OUTPUTIMAGES_DST} ${BAIKALTEST_OUTPUTIMAGES_SRC} + ) +else () + add_custom_target(BaikalTestImagesDir ALL + COMMAND ${CMAKE_COMMAND} -E create_symlink ${BAIKALTEST_REFERENCEIMAGES_SRC} ${BAIKALTEST_REFERENCEIMAGES_DST} + COMMAND ${CMAKE_COMMAND} -E create_symlink ${BAIKALTEST_OUTPUTIMAGES_SRC} ${BAIKALTEST_OUTPUTIMAGES_DST} + ) +endif () + +add_dependencies(BaikalTest BaikalTestImagesDir ResourcesDir) + +# Install target +install(TARGETS BaikalTest RUNTIME DESTINATION bin) +install(DIRECTORY DESTINATION bin/${BAIKALTEST_REFERENCEIMAGES_DIR}) +install(DIRECTORY DESTINATION bin/${BAIKALTEST_OUTPUTIMAGES_DIR}) diff --git a/BaikalTest/OutputImages/placeholder.txt b/BaikalTest/OutputImages/placeholder.txt new file mode 100644 index 00000000..cb0bb35c --- /dev/null +++ b/BaikalTest/OutputImages/placeholder.txt @@ -0,0 +1 @@ +placeholder for output images \ No newline at end of file diff --git a/BaikalTest/ReferenceImages/placeholder.txt b/BaikalTest/ReferenceImages/placeholder.txt new file mode 100644 index 00000000..a63c445f --- /dev/null +++ b/BaikalTest/ReferenceImages/placeholder.txt @@ -0,0 +1,2 @@ +placeholder for output images + diff --git a/BaikalTest/aov.h b/BaikalTest/aov.h new file mode 100644 index 00000000..13017e04 --- /dev/null +++ b/BaikalTest/aov.h @@ -0,0 +1,501 @@ +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ +#pragma once + +#include "basic.h" +#include "SceneGraph/light.h" + +class AovTest : public BasicTest +{ }; + +TEST_F(AovTest, Aov_WorldPosition) +{ + auto output_ws = m_factory->CreateOutput( + m_output->width(), m_output->height() + ); + + m_renderer->SetOutput(Baikal::Renderer::OutputType::kWorldPosition, + output_ws.get()); + + ClearOutput(output_ws.get()); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str(), output_ws.get()); + ASSERT_TRUE(CompareToReference(oss.str())); +} + +TEST_F(AovTest, Aov_WorldNormal) +{ + auto output_ws = m_factory->CreateOutput( + m_output->width(), m_output->height() + ); + + m_renderer->SetOutput(Baikal::Renderer::OutputType::kWorldGeometricNormal, + output_ws.get()); + + ClearOutput(output_ws.get()); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str(), output_ws.get()); + ASSERT_TRUE(CompareToReference(oss.str())); +} + +TEST_F(AovTest, Aov_ShadingNormal) +{ + auto output_ws = m_factory->CreateOutput( + m_output->width(), m_output->height() + ); + + m_renderer->SetOutput(Baikal::Renderer::OutputType::kWorldShadingNormal, + output_ws.get()); + + ClearOutput(output_ws.get()); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str(), output_ws.get()); + ASSERT_TRUE(CompareToReference(oss.str())); +} + +TEST_F(AovTest, Aov_Tangent) +{ + auto output_ws = m_factory->CreateOutput( + m_output->width(), m_output->height() + ); + + m_renderer->SetOutput(Baikal::Renderer::OutputType::kWorldTangent, + output_ws.get()); + + ClearOutput(output_ws.get()); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str(), output_ws.get()); + ASSERT_TRUE(CompareToReference(oss.str())); +} + +TEST_F(AovTest, Aov_Bitangent) +{ + auto output_ws = m_factory->CreateOutput( + m_output->width(), m_output->height() + ); + + m_renderer->SetOutput(Baikal::Renderer::OutputType::kWorldBitangent, + output_ws.get()); + + ClearOutput(output_ws.get()); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str(), output_ws.get()); + ASSERT_TRUE(CompareToReference(oss.str())); +} + +TEST_F(AovTest, Aov_Albedo) +{ + auto output_ws = m_factory->CreateOutput( + m_output->width(), m_output->height() + ); + + m_renderer->SetOutput(Baikal::Renderer::OutputType::kAlbedo, + output_ws.get()); + + ClearOutput(output_ws.get()); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str(), output_ws.get()); + ASSERT_TRUE(CompareToReference(oss.str())); +} + +TEST_F(AovTest, Aov_Uv) +{ + auto output_ws = m_factory->CreateOutput( + m_output->width(), m_output->height() + ); + + m_renderer->SetOutput(Baikal::Renderer::OutputType::kUv, + output_ws.get()); + + ClearOutput(output_ws.get()); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str(), output_ws.get()); + ASSERT_TRUE(CompareToReference(oss.str())); +} + +TEST_F(AovTest, Aov_ObjectId) +{ + auto output_ws = m_factory->CreateOutput( + m_output->width(), m_output->height() + ); + + m_renderer->SetOutput(Baikal::Renderer::OutputType::kMeshID, + output_ws.get()); + + m_scene = Baikal::SceneIo::LoadScene("sphere+plane+ibl.test", ""); + m_camera = Baikal::PerspectiveCamera::Create( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + m_camera->SetSensorSize(RadeonRays::float2(0.036f, 0.036f)); + m_camera->SetDepthRange(RadeonRays::float2(0.0f, 100000.f)); + m_camera->SetFocalLength(0.035f); + m_camera->SetFocusDistance(1.f); + + m_scene->SetCamera(m_camera); + + ClearOutput(output_ws.get()); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str(), output_ws.get()); + ASSERT_TRUE(CompareToReference(oss.str())); +} + +TEST_F(AovTest, Aov_GroupId) +{ + auto output_ws = m_factory->CreateOutput( + m_output->width(), m_output->height() + ); + + m_renderer->SetOutput(Baikal::Renderer::OutputType::kGroupID, + output_ws.get()); + + m_scene = Baikal::SceneIo::LoadScene("sphere+plane+ibl.test", ""); + m_camera = Baikal::PerspectiveCamera::Create( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + m_camera->SetSensorSize(RadeonRays::float2(0.036f, 0.036f)); + m_camera->SetDepthRange(RadeonRays::float2(0.0f, 100000.f)); + m_camera->SetFocalLength(0.035f); + m_camera->SetFocusDistance(1.f); + + m_scene->SetCamera(m_camera); + + auto SetMeshGroupId = [&](uint32_t sphere_id, uint32_t quad_id) + { + for (auto iter = m_scene->CreateShapeIterator(); + iter->IsValid(); + iter->Next()) + { + auto mesh = iter->ItemAs(); + if (mesh->GetName() == "sphere") + { + mesh->SetGroupId(sphere_id); + } + if (mesh->GetName() == "quad") + { + mesh->SetGroupId(quad_id); + } + } + }; + + // Move meshes to the same group + SetMeshGroupId(0, 0); + + ClearOutput(output_ws.get()); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + { + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + } + + { + std::ostringstream oss; + oss << test_name() << "_1" << ".png"; + SaveOutput(oss.str(), output_ws.get()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + + // Move meshes to different groups + SetMeshGroupId(0, 1); + + ClearOutput(output_ws.get()); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + { + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + } + + { + std::ostringstream oss; + oss << test_name() << "_2" << ".png"; + SaveOutput(oss.str(), output_ws.get()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(AovTest, Aov_Background) +{ + auto output_ws = m_factory->CreateOutput( + m_output->width(), m_output->height() + ); + + m_renderer->SetOutput(Baikal::Renderer::OutputType::kBackground, + output_ws.get()); + + std::vector intensities = + { + 0.1f, 0.5f, 1.0f, 2.0f, 5.0f + }; + + // Get image based light + auto light = m_scene->CreateLightIterator()->ItemAs(); + + for (float intensity : intensities) + { + light->SetMultiplier(intensity); + ClearOutput(output_ws.get()); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_"<< intensity <<".png"; + SaveOutput(oss.str(), output_ws.get()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } + + // Test background override + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto background_texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + light->SetBackgroundTexture(background_texture); + light->SetMultiplier(1.0f); + + ClearOutput(output_ws.get()); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + { + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + } + + { + std::ostringstream oss; + oss << test_name() << "_bgOverride.png"; + SaveOutput(oss.str(), output_ws.get()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + + // Test no image based light => black image + m_scene->DetachLight(light); + auto point_light = Baikal::PointLight::Create(); + point_light->SetPosition(float3(5.0f, 5.0f, 5.0f)); + m_scene->AttachLight(point_light); + + ClearOutput(output_ws.get()); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + { + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + } + + { + std::ostringstream oss; + oss << test_name() << "_noIBL.png"; + SaveOutput(oss.str(), output_ws.get()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + + // Test background image + m_scene->SetBackgroundImage(background_texture); + + ClearOutput(output_ws.get()); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + { + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + } + + { + std::ostringstream oss; + oss << test_name() << "_BackgroundImage.png"; + SaveOutput(oss.str(), output_ws.get()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(AovTest, Aov_Visibility) +{ + auto output_ws = m_factory->CreateOutput( + m_output->width(), m_output->height() + ); + + m_renderer->SetOutput(Baikal::Renderer::OutputType::kVisibility, + output_ws.get()); + + ClearOutput(output_ws.get()); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str(), output_ws.get()); + ASSERT_TRUE(CompareToReference(oss.str())); +} + +TEST_F(AovTest, Aov_Opacity) +{ + auto output_ws = m_factory->CreateOutput( + m_output->width(), m_output->height() + ); + + auto output_dummy = m_factory->CreateOutput( + m_output->width(), m_output->height() + ); + + m_renderer->SetOutput(Baikal::Renderer::OutputType::kColor, + output_dummy.get()); + + m_renderer->SetOutput(Baikal::Renderer::OutputType::kOpacity, + output_ws.get()); + + m_camera = Baikal::PerspectiveCamera::Create( + RadeonRays::float3(0.f, 2.f, -15.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + m_camera->SetSensorSize(RadeonRays::float2(0.036f, 0.036f)); + m_camera->SetDepthRange(RadeonRays::float2(0.0f, 100000.f)); + m_camera->SetFocalLength(0.035f); + m_camera->SetFocusDistance(1.f); + + m_scene = Baikal::SceneIo::LoadScene("transparent_planes.test", ""); + m_scene->SetCamera(m_camera); + + ClearOutput(output_ws.get()); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str(), output_ws.get()); + ASSERT_TRUE(CompareToReference(oss.str())); +} diff --git a/BaikalTest/basic.h b/BaikalTest/basic.h new file mode 100644 index 00000000..b69e8418 --- /dev/null +++ b/BaikalTest/basic.h @@ -0,0 +1,345 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once + +#include "gtest/gtest.h" + +#include "CLW.h" +#include "Renderers/renderer.h" +#include "RenderFactory/clw_render_factory.h" +#include "Output/output.h" +#include "SceneGraph/camera.h" +#include "scene_io.h" + +#include "OpenImageIO/imageio.h" + +#include +#include +#include +#include +#include +#include + +extern int g_argc; +extern char** g_argv; + +class BasicTest : public ::testing::Test +{ +public: + static std::uint32_t constexpr kMaxPlatforms = 5; + static std::uint32_t constexpr kOutputWidth = 256; + static std::uint32_t constexpr kOutputHeight = 256; + static std::uint32_t constexpr kNumIterations = 32; + + virtual void SetUp() + { + std::vector platforms; + + ASSERT_NO_THROW(CLWPlatform::CreateAllPlatforms(platforms)); + ASSERT_GT(platforms.size(), 0u); + + char* device_index_option = GetCmdOption(g_argv, g_argv + g_argc, "-device"); + char* platform_index_option = GetCmdOption(g_argv, g_argv + g_argc, "-platform"); + char* generate_option = GetCmdOption(g_argv, g_argv + g_argc, "-genref"); + char* tolerance_option = GetCmdOption(g_argv, g_argv + g_argc, "-tolerance"); + char* refpath_option = GetCmdOption(g_argv, g_argv + g_argc, "-ref"); + char* outpath_option = GetCmdOption(g_argv, g_argv + g_argc, "-out"); + + auto platform_index = platform_index_option ? (int)atoi(platform_index_option) : -1; + auto device_index = device_index_option ? (int)atoi(device_index_option) : -1; + m_generate = generate_option ? true : false; + m_tolerance = tolerance_option ? (int)atoi(tolerance_option) : 20; + m_reference_path = refpath_option ? refpath_option : "ReferenceImages"; + m_output_path = outpath_option ? outpath_option : "OutputImages"; + m_reference_path.append("/"); + m_output_path.append("/"); + + Baikal::SceneObject::ResetId(); + Baikal::SceneController::ResetId(); + + // Prefer GPU devices if nothing has been specified + if (platform_index == -1) + { + platform_index = 0; + + for (auto j = 0u; j < platforms.size(); ++j) + { + for (auto i = 0u; i < platforms[j].GetDeviceCount(); ++i) + { + if (platforms[j].GetDevice(i).GetType() == CL_DEVICE_TYPE_GPU) + { + platform_index = j; + break; + } + } + } + } + + + if (device_index == -1) + { + device_index = 0; + + for (auto i = 0u; i < platforms[platform_index].GetDeviceCount(); ++i) + { + if (platforms[platform_index].GetDevice(i).GetType() == CL_DEVICE_TYPE_GPU) + { + device_index = i; + break; + } + } + } + + ASSERT_LT((std::size_t)platform_index, platforms.size()); + ASSERT_LT((std::uint32_t)device_index, platforms[platform_index].GetDeviceCount()); + + auto platform = platforms[platform_index]; + auto device = platform.GetDevice(device_index); + auto context = CLWContext::Create(device); + + ASSERT_NO_THROW(m_factory = std::make_unique(context, "cache")); + ASSERT_NO_THROW(m_renderer = m_factory->CreateRenderer(Baikal::ClwRenderFactory::RendererType::kUnidirectionalPathTracer)); + ASSERT_NO_THROW(m_controller = m_factory->CreateSceneController()); + ASSERT_NO_THROW(m_output = m_factory->CreateOutput(kOutputWidth, kOutputHeight)); + m_output->Clear(RadeonRays::float3(0.0f)); + ASSERT_NO_THROW(m_renderer->SetOutput(Baikal::Renderer::OutputType::kColor, m_output.get())); + + ASSERT_NO_THROW(LoadTestScene()); + ASSERT_NO_THROW(SetupCamera()); + + ASSERT_NO_THROW(m_renderer->SetRandomSeed(0)); + } + + virtual void TearDown() + { + } + + virtual void ClearOutput(Baikal::Output* optional_output = nullptr) const + { + if (optional_output != nullptr) + { + ASSERT_NO_THROW(m_renderer->Clear(RadeonRays::float3(), *optional_output)); + } + + ASSERT_NO_THROW(m_renderer->Clear(RadeonRays::float3(), *m_output)); + } + + virtual void LoadTestScene() + { + m_scene = Baikal::SceneIo::LoadScene("sphere+ibl.test", ""); + } + + virtual void SetupCamera() + { + m_camera = Baikal::PerspectiveCamera::Create( + RadeonRays::float3(0.f, 0.f, -6.f), + RadeonRays::float3(0.f, 0.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + m_camera->SetSensorSize(RadeonRays::float2(0.036f, 0.036f)); + m_camera->SetDepthRange(RadeonRays::float2(0.0f, 100000.f)); + m_camera->SetFocalLength(0.035f); + m_camera->SetFocusDistance(1.f); + m_camera->SetAperture(0.f); + + m_scene->SetCamera(m_camera); + } + + void SaveOutput(std::string const& file_name, Baikal::Output* optional_output = nullptr) const + { + std::string path = m_generate ? m_reference_path : m_output_path; + path.append(file_name); + + OIIO_NAMESPACE_USING; + using namespace RadeonRays; + + auto width = m_output->width(); + auto height = m_output->height(); + std::vector data(width * height); + std::vector data1(width * height); + + if (optional_output != nullptr) + { + optional_output->GetData(&data[0]); + } + else + { + m_output->GetData(&data[0]); + } + + for (auto y = 0u; y < height; ++y) + for (auto x = 0u; x < width; ++x) + { + + float3 val = data[(height - 1 - y) * width + x]; + val *= (1.f / val.w); + data1[y * width + x].x = std::pow(val.x, 1.f / 2.2f); + data1[y * width + x].y = std::pow(val.y, 1.f / 2.2f); + data1[y * width + x].z = std::pow(val.z, 1.f / 2.2f); + } + + ImageOutput* out = ImageOutput::create(path); + + if (!out) + { + throw std::runtime_error("Can't create image file on disk"); + } + + ImageSpec spec(width, height, 3, TypeDesc::FLOAT); + + out->open(path, spec); + out->write_image(TypeDesc::FLOAT, &data1[0], sizeof(float3)); + out->close(); + + delete out; + } + + void LoadImage(std::string const& file_name, std::vector& data) + { + OIIO_NAMESPACE_USING + + ImageInput* input = ImageInput::open(file_name); + + ImageSpec const& spec = input->spec(); + + auto size = spec.width * spec.height * spec.depth * 4; + + data.resize(size); + + // Read data to storage + input->read_image(TypeDesc::UINT8, &data[0], sizeof(char) * 4); + + // Close handle + input->close(); + + delete input; + } + + void ApplyMaterialToObject( + std::string const& name, + Baikal::Material::Ptr material + ) + { + for (auto iter = m_scene->CreateShapeIterator(); + iter->IsValid(); + iter->Next()) + { + auto mesh = iter->ItemAs(); + if (mesh->GetName() == name) + { + mesh->SetMaterial(material); + } + } + } + + bool CompareToReference(std::string const& file_name) + { + if (m_generate) + return true; + + std::string path_to_output = m_output_path; + path_to_output.append(file_name); + std::string path_to_reference = m_reference_path; + path_to_reference.append(file_name); + + std::vector output_data; + std::vector reference_data; + + LoadImage(path_to_output, output_data); + LoadImage(path_to_reference, reference_data); + + auto num_values = output_data.size(); + auto difference = 0u; + for (auto i = 0u; i < num_values; ++i) + { + if (output_data[i] != reference_data[i]) + { + ++difference; + } + } + + return difference <= m_tolerance; + } + + + + std::string test_name() const + { + return ::testing::UnitTest::GetInstance()->current_test_info()->name(); + } + + static char* GetCmdOption(char ** begin, char ** end, const std::string & option) + { + char ** itr = std::find(begin, end, option); + if (itr != end && ++itr != end) + { + return *itr; + } + return 0; + } + + static bool CmdOptionExists(char** begin, char** end, const std::string& option) + { + return std::find(begin, end, option) != end; + } + + std::unique_ptr m_renderer; + std::unique_ptr> m_controller; + std::unique_ptr> m_factory; + std::unique_ptr m_output; + Baikal::Scene1::Ptr m_scene; + Baikal::PerspectiveCamera::Ptr m_camera; + + std::string m_reference_path; + std::string m_output_path; + + bool m_generate; + std::uint32_t m_tolerance; +}; + + +// Test renderer instance creation +TEST_F(BasicTest, Init) +{ + ASSERT_TRUE(true); +} + +TEST_F(BasicTest, RenderTestScene) +{ + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + SaveOutput(test_name() + ".png"); + ASSERT_TRUE(CompareToReference(test_name() + ".png")); +} + + + + diff --git a/BaikalTest/cache/placeholder.txt b/BaikalTest/cache/placeholder.txt new file mode 100644 index 00000000..cb0bb35c --- /dev/null +++ b/BaikalTest/cache/placeholder.txt @@ -0,0 +1 @@ +placeholder for output images \ No newline at end of file diff --git a/BaikalTest/camera.h b/BaikalTest/camera.h new file mode 100644 index 00000000..05725ddb --- /dev/null +++ b/BaikalTest/camera.h @@ -0,0 +1,137 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once + +#include "basic.h" + +class CameraTest : public BasicTest +{ + +}; + +TEST_F(CameraTest, Camera_FocalLength) +{ + std::vector values = { 0.014f, 0.035f, 0.05f, 0.085f, 0.135f }; + + for (auto v : values) + { + ClearOutput(); + m_camera->SetFocalLength(v); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + std::ostringstream oss; + oss << test_name() << v << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(CameraTest, Camera_SensorSize) +{ + std::vector> values = + { + { 0.0167f, 0.0251f }, // APS-C + { 0.024f, 0.036f }, // Full frame + { 0.036f, 0.036f } // Mid frame + }; + + for (auto v : values) + { + ClearOutput(); + m_camera->SetSensorSize(RadeonRays::float2(v.first, v.second)); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + std::ostringstream oss; + oss << test_name() << "_" << v.first << "_" << v.second << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(CameraTest, Camera_Aperture) +{ + std::vector values = { 0.1f, 0.01f, 0.05f, 0.025f }; + + m_camera->SetFocusDistance(6.f); + + for (auto v : values) + { + ClearOutput(); + m_camera->SetAperture(v); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + std::ostringstream oss; + oss << test_name() << v << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(CameraTest, Camera_FocusDistance) +{ + std::vector values = { 1.f, 3.f, 6.f, 9.f }; + + m_camera->SetAperture(0.15f); + + for (auto v : values) + { + ClearOutput(); + m_camera->SetFocusDistance(v); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + std::ostringstream oss; + oss << test_name() << v << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} diff --git a/BaikalTest/input_maps.h b/BaikalTest/input_maps.h new file mode 100644 index 00000000..e95b34bc --- /dev/null +++ b/BaikalTest/input_maps.h @@ -0,0 +1,631 @@ +/********************************************************************** + C opyright (c*) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ +#pragma once + +#include "basic.h" +#include "SceneGraph/light.h" +#include "SceneGraph/shape.h" +#include "SceneGraph/material.h" +#include "image_io.h" +#include "SceneGraph/uberv2material.h" +#include "SceneGraph/inputmaps.h" + + +#define _USE_MATH_DEFINES +#include +#include + +using namespace RadeonRays; + +class InputMapsTest : public BasicTest +{ + +protected: + + void LoadTestScene() override + { + m_scene = Baikal::SceneIo::LoadScene("sphere+plane+ibl.test", ""); + } + + void SetUp() override + { + BasicTest::SetUp(); + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + } + + void RunAndSave(Baikal::UberV2Material::Ptr material, std::string object_name = "sphere") + { + ClearOutput(); + + ApplyMaterialToObject(object_name, material); + ApplyMaterialToObject("sphere", material); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } + +}; + +TEST_F(InputMapsTest, InputMap_ConstFloat4) +{ + auto material = Baikal::UberV2Material::Create(); + auto diffuse_color = Baikal::InputMap_ConstantFloat3::Create(float3(0.0f, 0.0f, 0.0f, 0.0f)); + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + std::vector colors = + { + float3(1.0f, 0.0f, 0.0f), + float3(0.0f, 1.0f, 0.0f), + float3(0.0f, 0.0f, 1.0f) + }; + + for (auto& c : colors) + { + diffuse_color->SetValue(c); + ClearOutput(); + + ApplyMaterialToObject("sphere", material); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_" << c.x << "_" << c.y << "_" << c.z << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } +} + +TEST_F(InputMapsTest, InputMap_ConstFloat) +{ + auto material = Baikal::UberV2Material::Create(); + auto diffuse_color = Baikal::InputMap_ConstantFloat3::Create(float3(1.0f, 1.0f, 0.0f, 0.0f)); + auto ior = Baikal::InputMap_ConstantFloat::Create(1.0f); + material->SetInputValue("uberv2.coating.color", diffuse_color); + material->SetInputValue("uberv2.coating.ior", ior); + material->SetLayers(Baikal::UberV2Material::Layers::kCoatingLayer); + + std::vector iors = { 0.0f, 0.05f, 0.1f, 0.5f, 1.0f}; + + for (auto& c : iors) + { + ior->SetValue(c); + ClearOutput(); + + ApplyMaterialToObject("sphere", material); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_" << c << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } +} + +TEST_F(InputMapsTest, InputMap_Add) +{ + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_ConstantFloat3::Create(float3(1.0f, 0.0f, 0.0f, 0.0f)); + auto color2 = Baikal::InputMap_ConstantFloat3::Create(float3(0.0f, 1.0f, 0.0f, 0.0f)); + auto diffuse_color = Baikal::InputMap_Add::Create(color1, color2); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_Sub) +{ + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_ConstantFloat3::Create(float3(1.0f, 1.0f, 0.0f, 0.0f)); + auto color2 = Baikal::InputMap_ConstantFloat3::Create(float3(0.0f, 1.0f, 0.0f, 0.0f)); + auto diffuse_color = Baikal::InputMap_Sub::Create(color1, color2); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_Mul) +{ + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_ConstantFloat3::Create(float3(1.0f, 1.0f, 0.0f, 0.0f)); + auto color2 = Baikal::InputMap_ConstantFloat3::Create(float3(0.0f, 1.0f, 0.0f, 0.0f)); + auto diffuse_color = Baikal::InputMap_Mul::Create(color1, color2); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_Div) +{ + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_ConstantFloat3::Create(float3(2.0f, 1.0f, 0.0f, 0.0f)); + auto color2 = Baikal::InputMap_ConstantFloat3::Create(float3(2.0f, 100.0f, 0.0f, 0.0f)); + auto diffuse_color = Baikal::InputMap_Div::Create(color1, color2); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_Sin) +{ + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_Sampler::Create(texture); + auto diffuse_color = Baikal::InputMap_Sin::Create(color1); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_Cos) +{ + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_Sampler::Create(texture); + auto diffuse_color = Baikal::InputMap_Cos::Create(color1); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_Tan) +{ + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_Sampler::Create(texture); + auto diffuse_color = Baikal::InputMap_Tan::Create(color1); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_ASin) +{ + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_Sampler::Create(texture); + auto diffuse_color = Baikal::InputMap_Asin::Create(color1); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_ACos) +{ + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_Sampler::Create(texture); + auto diffuse_color = Baikal::InputMap_Acos::Create(color1); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_ATan) +{ + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_Sampler::Create(texture); + auto diffuse_color = Baikal::InputMap_Atan::Create(color1); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_Select) +{ + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_Sampler::Create(texture); + std::shared_ptr diffuse_color = Baikal::InputMap_Select::Create(color1, Baikal::InputMap_Select::Selection::kX); + + std::vector selections = + { + Baikal::InputMap_Select::Selection::kX, + Baikal::InputMap_Select::Selection::kY, + Baikal::InputMap_Select::Selection::kZ, + Baikal::InputMap_Select::Selection::kW + }; + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + for (auto c : selections) + { + diffuse_color->SetSelection(c); + + ClearOutput(); + + ApplyMaterialToObject("sphere", material); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_"<<(static_cast(c))<< ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } +} + +TEST_F(InputMapsTest, InputMap_Dot3) +{ + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_ConstantFloat3::Create(float3(1.0f, 1.0f, 1.0f)); + auto color2 = Baikal::InputMap_ConstantFloat3::Create(float3(1.0f, 1.0f, 1.0f)); + + auto diffuse_color = Baikal::InputMap_Dot3::Create(color1, color2); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} +TEST_F(InputMapsTest, InputMap_Dot4) +{ + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_ConstantFloat3::Create(float3(1.0f, 1.0f, 1.0f)); + auto color2 = Baikal::InputMap_ConstantFloat3::Create(float3(1.0f, 1.0f, 1.0f)); + + auto diffuse_color = Baikal::InputMap_Dot4::Create(color1, color2); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} +TEST_F(InputMapsTest, InputMap_Cross3) +{ + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_ConstantFloat3::Create(float3(1.0f, 0.0f, 0.0f)); + auto color2 = Baikal::InputMap_ConstantFloat3::Create(float3(0.0f, 1.0f, 0.0f)); + + auto diffuse_color = Baikal::InputMap_Cross3::Create(color1, color2); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} +TEST_F(InputMapsTest, InputMap_Cross4) +{ + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_ConstantFloat3::Create(float3(1.0f, 0.0f, 0.0f)); + auto color2 = Baikal::InputMap_ConstantFloat3::Create(float3(0.0f, 1.0f, 0.0f)); + + auto diffuse_color = Baikal::InputMap_Cross4::Create(color1, color2); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_Min) +{ + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_Sampler::Create(texture); + auto color2 = Baikal::InputMap_ConstantFloat3::Create(float3(0.0f, 1.0f, 0.0f)); + auto diffuse_color = Baikal::InputMap_Min::Create(color1, color2); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} +TEST_F(InputMapsTest, InputMap_Max) +{ + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_Sampler::Create(texture); + auto color2 = Baikal::InputMap_ConstantFloat3::Create(float3(0.0f, 1.0f, 0.0f)); + auto diffuse_color = Baikal::InputMap_Max::Create(color1, color2); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_Pow) +{ + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_Sampler::Create(texture); + auto color2 = Baikal::InputMap_ConstantFloat::Create(2.2f); + auto diffuse_color = Baikal::InputMap_Pow::Create(color1, color2); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_Abs) +{ + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_ConstantFloat3::Create(float3(-1.0f, -1.0f, -1.0f)); + auto diffuse_color = Baikal::InputMap_Abs::Create(color1); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_Length3) +{ + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_ConstantFloat3::Create(float3(-1.0f, 0.0f, 0.0f)); + auto diffuse_color = Baikal::InputMap_Length3::Create(color1); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_Normalize3) +{ + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_ConstantFloat3::Create(float3(1.0f, 1.0f, 1.0f)); + auto diffuse_color = Baikal::InputMap_Normalize3::Create(color1); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_Lerp) +{ + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto texture1 = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + auto texture2 = image_io->LoadImage("../Resources/Textures/test_albedo3.jpg"); + + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_Sampler::Create(texture1); + auto color2 = Baikal::InputMap_ConstantFloat3::Create(float3(1.0f, 0.0f, 0.0f));; + auto control = Baikal::InputMap_Sampler::Create(texture2); + auto diffuse_color = Baikal::InputMap_Lerp::Create(color1, color2, control); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material, "quad"); +} + +TEST_F(InputMapsTest, InputMap_Floor) +{ + auto material = Baikal::UberV2Material::Create(); + auto color = Baikal::InputMap_ConstantFloat3::Create(float3(0.0f, 0.0f, 0.0f, 0.0f)); + auto diffuse_color = Baikal::InputMap_Floor::Create(color); + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + std::vector colors = + { + float3(1.8f, 1.7f, 1.6f), + float3(0.1f, 0.2f, 0.8f) + }; + + for (auto& c : colors) + { + color->SetValue(c); + ClearOutput(); + + ApplyMaterialToObject("sphere", material); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_" << c.x << "_" << c.y << "_" << c.z << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } +} + +TEST_F(InputMapsTest, InputMap_Mod) +{ + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_ConstantFloat3::Create(float3(5.0f, 4.0f, 3.0f)); + auto color2 = Baikal::InputMap_ConstantFloat3::Create(float3(2.0f, 2.1f, 3.0f)); + auto diffuse_color = Baikal::InputMap_Mod::Create(color1, color2); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_Shuffle) +{ + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_ConstantFloat3::Create(float3(1.0f, 0.0f, 0.0f)); + auto diffuse_color = Baikal::InputMap_Shuffle::Create(color1, {{0, 0, 0, 0}}); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_Shuffle2) +{ + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_ConstantFloat3::Create(float3(1.0f, 0.0f, 0.0f)); + auto color2 = Baikal::InputMap_ConstantFloat3::Create(float3(0.0f, 1.0f, 0.0f)); + auto diffuse_color = Baikal::InputMap_Shuffle2::Create(color1, color2, {{0, 5, 1, 6}}); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_MatMul) +{ + auto material = Baikal::UberV2Material::Create(); + auto color1 = Baikal::InputMap_ConstantFloat3::Create(float3(1.0f, 0.0f, 0.0f)); + RadeonRays::matrix mat( + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f + ); + + auto diffuse_color = Baikal::InputMap_MatMul::Create(color1, mat); + + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + + RunAndSave(material); +} + +TEST_F(InputMapsTest, InputMap_Bump) +{ + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto bump_texture= image_io->LoadImage("../Resources/Textures/test_bump.jpg"); + + auto material = Baikal::UberV2Material::Create(); + auto bump_sampler = Baikal::InputMap_SamplerBumpMap::Create(bump_texture); + auto remap = Baikal::InputMap_Remap::Create( + Baikal::InputMap_ConstantFloat3::Create(float3(0.0f, 1.0f, 0.0f)), + Baikal::InputMap_ConstantFloat3::Create(float3(-1.0f, 1.0f, 0.0f)), + bump_sampler); + material->SetInputValue("uberv2.shading_normal", remap); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer | + Baikal::UberV2Material::Layers::kShadingNormalLayer); + + RunAndSave(material, "quad"); +} + +TEST_F(InputMapsTest, InputMap_Normal) +{ + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto normal_texture = image_io->LoadImage("../Resources/Textures/test_normal.jpg"); + + auto material = Baikal::UberV2Material::Create(); + auto normal_sampler = Baikal::InputMap_Sampler::Create(normal_texture); + auto remap = Baikal::InputMap_Remap::Create( + Baikal::InputMap_ConstantFloat3::Create(float3(0.0f, 1.0f, 0.0f)), + Baikal::InputMap_ConstantFloat3::Create(float3(-1.0f, 1.0f, 0.0f)), + normal_sampler); + material->SetInputValue("uberv2.shading_normal", remap); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer | + Baikal::UberV2Material::Layers::kShadingNormalLayer); + + RunAndSave(material, "quad"); +} diff --git a/BaikalTest/internal.h b/BaikalTest/internal.h new file mode 100644 index 00000000..dbf69e39 --- /dev/null +++ b/BaikalTest/internal.h @@ -0,0 +1,49 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "gtest/gtest.h" + +#include "Utils/distribution1d.h" +#include "math/mathutils.h" + +class InternalTest : public ::testing::Test +{ + +}; + +TEST_F(InternalTest, Distribuiton1D) +{ + float vals[] = { 2, 4, 6, 8 }; + Baikal::Distribution1D dist(vals, 4); + + int cnts[]{ 0, 0, 0, 0 }; + + for (auto i = 0u; i < 1000; ++i) + { + float pdf = 0.f; + float v = dist.Sample1D(RadeonRays::rand_float(), pdf); + + int idx = std::min((int)(v * 4), 3); + ++cnts[idx]; + } + + cnts[0] += cnts[1]; +} diff --git a/BaikalTest/light.h b/BaikalTest/light.h new file mode 100644 index 00000000..41021279 --- /dev/null +++ b/BaikalTest/light.h @@ -0,0 +1,1084 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once + +#include "basic.h" +#include "SceneGraph/light.h" +#include "SceneGraph/shape.h" +#include "SceneGraph/material.h" +#include "SceneGraph/uberv2material.h" +#include "SceneGraph/inputmaps.h" + +#include "image_io.h" + +#define _USE_MATH_DEFINES +#include + +using namespace RadeonRays; + +class LightTest: public BasicTest +{ +public: + void LoadTestScene() override + { + m_scene = Baikal::SceneIo::LoadScene("sphere+plane.test", ""); + } +}; + +TEST_F(LightTest, Light_PointLight) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + + std::vector positions{ + float3(3.f, 6.f, 0.f), + float3(-2.f, 6.f, -1.f), + float3(0.f, 6.f, -3.f) + }; + + std::vector colors{ + float3(3.f, 0.1f, 0.1f), + float3(0.1f, 3.f, 0.1f), + float3(0.1f, 0.1f, 3.f) + }; + + for (auto i = 0u; i < 3; ++i) + { + auto light = Baikal::PointLight::Create(); + light->SetPosition(positions[i]); + light->SetEmittedRadiance(colors[i]); + m_scene->AttachLight(light); + } + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_1.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + + auto iter = m_scene->CreateLightIterator(); + m_scene->DetachLight(iter->ItemAs()); + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene1 = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene1)); + } + + { + std::ostringstream oss; + oss << test_name() << "_2.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(LightTest, Light_PointLightMany) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + + auto num_lights = 16u; + std::vector positions; + std::vector colors; + + float step = (float)(2.f * M_PI / num_lights); + for (auto i = 0u; i < num_lights; ++i) + { + auto x = 5.f * std::cos(i * step); + auto y = 5.f; + auto z = 5.f * std::sin(i * step); + positions.push_back(float3(x, y, z)); + + auto f = (float)i / num_lights; + auto color = f * float3(1.f, 0.f, 0.f) + (1.f - f) * float3(0.f, 1.f, 0.f); + colors.push_back(6.f * color); + } + + for (auto i = 0u; i < num_lights; ++i) + { + auto light = Baikal::PointLight::Create(); + light->SetPosition(positions[i]); + light->SetEmittedRadiance(colors[i]); + m_scene->AttachLight(light); + } + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < num_lights * kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(LightTest, Light_DirectionalLight) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + + std::vector direction{ + float3(-1.f, -1.f, -1.f), + float3(1.f, -1.f, -1.f), + float3(1.f, -1.f, 1.f) + }; + + std::vector colors{ + float3(3.f, 0.1f, 0.1f), + float3(0.1f, 3.f, 0.1f), + float3(0.1f, 0.1f, 3.f) + }; + + for (auto i = 0u; i < 3; ++i) + { + auto light = Baikal::DirectionalLight::Create(); + light->SetDirection(direction[i]); + light->SetEmittedRadiance(colors[i]); + m_scene->AttachLight(light); + } + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_1.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + + auto iter = m_scene->CreateLightIterator(); + m_scene->DetachLight(iter->ItemAs ()); + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene1 = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene1)); + } + + { + std::ostringstream oss; + oss << test_name() << "_2.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(LightTest, Light_SpotLight) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + + std::vector direction{ + float3(-1.f, -1.f, -1.f), + float3(1.f, -1.f, -1.f), + float3(1.f, -1.f, 1.f) + }; + + std::vector colors{ + float3(3.f, 0.1f, 0.1f), + float3(0.1f, 3.f, 0.1f), + float3(0.1f, 0.1f, 3.f) + }; + + std::vector positions{ + float3(3.f, 6.f, 0.f), + float3(-2.f, 6.f, -1.f), + float3(0.f, 6.f, -3.f) + }; + + for (auto i = 0u; i < 3; ++i) + { + auto light = Baikal::SpotLight::Create(); + light->SetPosition(positions[i]); + light->SetDirection(direction[i]); + light->SetEmittedRadiance(colors[i]); + m_scene->AttachLight(light); + } + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_1.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + + auto iter = m_scene->CreateLightIterator(); + m_scene->DetachLight(iter->ItemAs()); + + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene1 = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene1)); + } + + { + std::ostringstream oss; + oss << test_name() << "_2.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(LightTest, Light_AreaLight) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + m_scene = Baikal::SceneIo::LoadScene("sphere+plane+area.test", ""); + m_scene->SetCamera(m_camera); + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + + +TEST_F(LightTest, Light_DirectionalAndAreaLight) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + m_scene = Baikal::SceneIo::LoadScene("sphere+plane+area.test", ""); + m_scene->SetCamera(m_camera); + + std::vector direction{ + float3(-1.f, -1.f, -1.f), + float3(1.f, -1.f, -1.f), + float3(1.f, -1.f, 1.f) + }; + + std::vector colors{ + float3(1.f, 0.1f, 0.1f), + float3(0.1f, 1.f, 0.1f), + float3(0.1f, 0.1f, 1.f) + }; + + for (auto i = 0u; i < 3; ++i) + { + auto light = Baikal::DirectionalLight::Create(); + light->SetDirection(direction[i]); + light->SetEmittedRadiance(colors[i]); + m_scene->AttachLight(light); + } + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(LightTest, Light_PointAndAreaLight) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + m_scene = Baikal::SceneIo::LoadScene("sphere+plane+area.test", ""); + m_scene->SetCamera(m_camera); + + std::vector positions{ + float3(3.f, 6.f, 0.f), + float3(-2.f, 6.f, -1.f), + float3(0.f, 6.f, -3.f) + }; + + std::vector colors{ + float3(3.f, 0.1f, 0.1f), + float3(0.1f, 3.f, 0.1f), + float3(0.1f, 0.1f, 3.f) + }; + + for (auto i = 0u; i < 3; ++i) + { + auto light = Baikal::PointLight::Create(); + light->SetPosition(positions[i]); + light->SetEmittedRadiance(colors[i]); + m_scene->AttachLight(light); + } + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(LightTest, Light_SpotAndAreaLight) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + m_scene = Baikal::SceneIo::LoadScene("sphere+plane+area.test", ""); + m_scene->SetCamera(m_camera); + + std::vector direction{ + float3(-1.f, -1.f, -1.f), + float3(1.f, -1.f, -1.f), + float3(1.f, -1.f, 1.f) + }; + + std::vector colors{ + float3(3.f, 0.1f, 0.1f), + float3(0.1f, 3.f, 0.1f), + float3(0.1f, 0.1f, 3.f) + }; + + std::vector positions{ + float3(3.f, 6.f, 0.f), + float3(-2.f, 6.f, -1.f), + float3(0.f, 6.f, -3.f) + }; + + for (auto i = 0u; i < 3; ++i) + { + auto light = Baikal::SpotLight::Create(); + light->SetPosition(positions[i]); + light->SetDirection(direction[i]); + light->SetEmittedRadiance(colors[i]); + m_scene->AttachLight(light); + } + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(LightTest, Light_EmissiveSphere) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + ClearOutput(); + + m_scene = Baikal::SceneIo::LoadScene("sphere+plane.test", ""); + m_scene->SetCamera(m_camera); + + auto emission = Baikal::UberV2Material::Create(); + emission->SetLayers(Baikal::UberV2Material::Layers::kEmissionLayer); + emission->SetInputValue("uberv2.emission.color", + Baikal::InputMap_ConstantFloat3::Create(float3(2.f, 2.f, 2.f))); + + auto iter = m_scene->CreateShapeIterator(); + + for (; iter->IsValid(); iter->Next()) + { + auto mesh = iter->ItemAs(); + if (mesh->GetName() == "sphere") + { + mesh->SetMaterial(emission); + + for (auto i = 0u; i < mesh->GetNumIndices() / 3; ++i) + { + auto light = Baikal::AreaLight::Create(mesh, i); + m_scene->AttachLight(light); + } + } + } + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(LightTest, Light_DirectionalAndEmissiveSphere) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + m_scene = Baikal::SceneIo::LoadScene("sphere+plane.test", ""); + m_scene->SetCamera(m_camera); + + auto light = Baikal::DirectionalLight::Create(); + light->SetDirection(float3(-0.5, -1.f, -0.5f)); + light->SetEmittedRadiance(5.f * float3(1.f, 0.f, 0.f)); + m_scene->AttachLight(light); + + auto emission = Baikal::UberV2Material::Create(); + emission->SetLayers(Baikal::UberV2Material::Layers::kEmissionLayer); + emission->SetInputValue("uberv2.emission.color", + Baikal::InputMap_ConstantFloat3::Create(float3(2.f, 2.f, 2.f))); + + auto iter = m_scene->CreateShapeIterator(); + + for (; iter->IsValid(); iter->Next()) + { + auto mesh = iter->ItemAs(); + if (mesh->GetName() == "sphere") + { + mesh->SetMaterial(emission); + + for (auto i = 0u; i < mesh->GetNumIndices() / 3; ++i) + { + auto light = Baikal::AreaLight::Create(mesh, i); + m_scene->AttachLight(light); + } + } + } + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(LightTest, Light_ImageBasedLight) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + LoadTestScene(); + m_scene->SetCamera(m_camera); + + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto light_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); + auto light = Baikal::ImageBasedLight::Create(); + + light->SetTexture(light_texture); + light->SetMultiplier(1.f); + m_scene->AttachLight(light); + + ASSERT_TRUE(m_scene->GetNumLights() == 1); + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (std::uint32_t i = 0; i < kNumIterations; i++) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_1.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + + // reset texture and params to be sure that render reset its params + auto another_light_texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + light->SetTexture(another_light_texture); + light->SetMultiplier(2.f); + + m_scene->DetachLight(light); + ASSERT_TRUE(m_scene->GetNumLights() == 0); + m_scene->AttachLight(light); + ASSERT_TRUE(m_scene->GetNumLights() == 1); + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + for (std::uint32_t i = 0; i < kNumIterations; i++) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_2.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(LightTest, Light_ImageBasedLightAndLightChanging) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + LoadTestScene(); + m_scene->SetCamera(m_camera); + + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto light_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); + + // image based light initialization + auto image_based_light = Baikal::ImageBasedLight::Create(); + + image_based_light->SetTexture(light_texture); + image_based_light->SetMultiplier(1.f); + m_scene->AttachLight(image_based_light); + + // spot light initialization + auto spot_light = Baikal::SpotLight::Create(); + spot_light->SetDirection(float3(-1.f, -1.f, -1.f)); + spot_light->SetEmittedRadiance(float3(3.f, 0.1f, 0.1f)); + spot_light->SetPosition(float3(3.f, 6.f, 0.f)); + m_scene->AttachLight(spot_light); + + // point light initialization + auto point_light = Baikal::PointLight::Create(); + point_light->SetPosition(float3(0.f, 6.f, -3.f)); + point_light->SetEmittedRadiance(float3(0.1f, 0.1f, 3.f)); + m_scene->AttachLight(point_light); + + ClearOutput(); + + ASSERT_TRUE(m_scene->GetNumLights() == 3); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (std::uint32_t i = 0; i < kNumIterations; i++) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_1.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + + m_scene->DetachLight(spot_light); + m_scene->DetachLight(point_light); + + ASSERT_TRUE(m_scene->GetNumLights() == 1); + + // directional light initialization + auto light = Baikal::DirectionalLight::Create(); + light->SetDirection(float3(1.f, -1.f, -1.f)); + light->SetEmittedRadiance(float3(0.1f, 3.f, 0.1f)); + m_scene->AttachLight(light); + + ASSERT_TRUE(m_scene->GetNumLights() == 2); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + for (std::uint32_t i = 0; i < kNumIterations; i++) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_2.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(LightTest, Light_ImageBasedLightAndEmissiveQuad) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + m_scene = Baikal::SceneIo::LoadScene("sphere+plane+area.test", ""); + m_scene->SetCamera(m_camera); + + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto light_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); + auto light = Baikal::ImageBasedLight::Create(); + + light->SetTexture(light_texture); + light->SetMultiplier(1.f); + m_scene->AttachLight(light); + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (std::uint32_t i = 0; i < kNumIterations; i++) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_1.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + + m_scene->GetNumShapes(); + light->SetMultiplier(2.f); + + auto shape_iter = m_scene->CreateShapeIterator(); + for (; shape_iter->IsValid(); shape_iter->Next()) + { + if (shape_iter->Item()->GetName() == "quad") + break; + } + + ASSERT_TRUE(shape_iter->IsValid()); + auto shape = shape_iter->ItemAs(); + + auto matrix = translation(float3(0, -2, 0)) * rotation_y(PI / 4); + shape->SetTransform(matrix); + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + for (std::uint32_t i = 0; i < kNumIterations; i++) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_2.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(LightTest, Light_IblReflectionOverride) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + LoadTestScene(); + + auto material = Baikal::UberV2Material::Create(); + material->SetLayers(Baikal::UberV2Material::Layers::kReflectionLayer); + material->SetInputValue("uberv2.reflection.roughness", + Baikal::InputMap_ConstantFloat::Create(0.07f)); + + ApplyMaterialToObject("sphere", material); + + m_scene->SetCamera(m_camera); + + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto light_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); + auto reflection_texture = image_io->LoadImage("../Resources/Textures/sky.hdr"); + auto light = Baikal::ImageBasedLight::Create(); + + light->SetTexture(nullptr); + light->SetReflectionTexture(reflection_texture); + light->SetMultiplier(1.f); + m_scene->AttachLight(light); + + ClearOutput(); + + ASSERT_TRUE(m_scene->GetNumLights() == 1); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (std::uint32_t i = 0; i < kNumIterations; i++) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_1.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + + // reset texture and params to be sure that render reset its params + auto another_light_texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + light->SetBackgroundTexture(another_light_texture); + light->SetMultiplier(2.f); + + m_scene->DetachLight(light); + ASSERT_TRUE(m_scene->GetNumLights() == 0); + m_scene->AttachLight(light); + ASSERT_TRUE(m_scene->GetNumLights() == 1); + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + for (std::uint32_t i = 0; i < kNumIterations; i++) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_2.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(LightTest, Light_IblRefractionOverride) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + LoadTestScene(); + + auto material = Baikal::UberV2Material::Create(); + material->SetLayers(Baikal::UberV2Material::Layers::kRefractionLayer); + material->SetInputValue("uberv2.refraction.ior", + Baikal::InputMap_ConstantFloat::Create(2.f)); + + ApplyMaterialToObject("sphere", material); + + m_scene->SetCamera(m_camera); + + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto light_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); + auto refraction_texture = image_io->LoadImage("../Resources/Textures/sky.hdr"); + auto light = Baikal::ImageBasedLight::Create(); + + light->SetTexture(nullptr); + light->SetRefractionTexture(refraction_texture); + light->SetMultiplier(1.f); + m_scene->AttachLight(light); + + ClearOutput(); + + ASSERT_TRUE(m_scene->GetNumLights() == 1); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (std::uint32_t i = 0; i < kNumIterations; i++) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_1.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + + // reset texture and params to be sure that render reset its params + auto another_light_texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + light->SetBackgroundTexture(another_light_texture); + light->SetMultiplier(2.f); + + m_scene->DetachLight(light); + ASSERT_TRUE(m_scene->GetNumLights() == 0); + m_scene->AttachLight(light); + ASSERT_TRUE(m_scene->GetNumLights() == 1); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + for (std::uint32_t i = 0; i < kNumIterations; i++) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_2.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(LightTest, Light_IblTransparencyOverride) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + LoadTestScene(); + + auto material = Baikal::UberV2Material::Create(); + material->SetLayers(Baikal::UberV2Material::Layers::kTransparencyLayer); + material->SetInputValue("uberv2.transparency", + Baikal::InputMap_ConstantFloat::Create(1.0f)); + + ApplyMaterialToObject("sphere", material); + + m_scene->SetCamera(m_camera); + + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto light_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); + auto refraction_texture = image_io->LoadImage("../Resources/Textures/sky.hdr"); + auto light = Baikal::ImageBasedLight::Create(); + + light->SetTexture(nullptr); + light->SetTransparencyTexture(refraction_texture); + light->SetMultiplier(1.f); + m_scene->AttachLight(light); + + ClearOutput(); + + ASSERT_TRUE(m_scene->GetNumLights() == 1); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (std::uint32_t i = 0; i < kNumIterations; i++) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_1.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + + // reset texture and params to be sure that render reset its params + auto another_light_texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + light->SetBackgroundTexture(another_light_texture); + light->SetMultiplier(2.f); + + m_scene->DetachLight(light); + ASSERT_TRUE(m_scene->GetNumLights() == 0); + m_scene->AttachLight(light); + ASSERT_TRUE(m_scene->GetNumLights() == 1); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + for (std::uint32_t i = 0; i < kNumIterations; i++) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_2.png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} + +TEST_F(LightTest, Light_IblDifferentOverrides) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + m_scene = Baikal::SceneIo::LoadScene("env_override_spheres.test", ""); + + m_scene->SetCamera(m_camera); + + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto reflection_texture = image_io->LoadImage("../Resources/Textures/studio015.hdr"); + auto refraction_texture = image_io->LoadImage("../Resources/Textures/sky.hdr"); + auto transparency_texture = image_io->LoadImage("../Resources/Textures/test_albedo2.jpg"); + auto background_texture = image_io->LoadImage("../Resources/Textures/test_albedo1.jpg"); + auto light = Baikal::ImageBasedLight::Create(); + + light->SetTexture(nullptr); + light->SetReflectionTexture(reflection_texture); + light->SetRefractionTexture(refraction_texture); + light->SetTransparencyTexture(transparency_texture); + light->SetBackgroundTexture(background_texture); + light->SetMultiplier(1.f); + m_scene->AttachLight(light); + + ClearOutput(); + + ASSERT_TRUE(m_scene->GetNumLights() == 1); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (std::uint32_t i = 0; i < kNumIterations; i++) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + +} diff --git a/BaikalTest/main.cpp b/BaikalTest/main.cpp new file mode 100644 index 00000000..b3e908b5 --- /dev/null +++ b/BaikalTest/main.cpp @@ -0,0 +1,46 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "gtest/gtest.h" + +#include "CLW.h" + +#include "internal.h" +#include "basic.h" +#include "camera.h" +#include "light.h" +#include "material.h" +#include "aov.h" +#include "test_scenes.h" + +#include "uberv2.h" +#include "input_maps.h" + +int g_argc; +char** g_argv; + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + g_argc = argc; + g_argv = argv; + return RUN_ALL_TESTS(); +} diff --git a/BaikalTest/material.h b/BaikalTest/material.h new file mode 100644 index 00000000..5f44f465 --- /dev/null +++ b/BaikalTest/material.h @@ -0,0 +1,955 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once + +#include "basic.h" +#include "SceneGraph/light.h" +#include "SceneGraph/shape.h" +#include "SceneGraph/material.h" +#include "image_io.h" + +#define _USE_MATH_DEFINES +#include + +using namespace RadeonRays; + +class MaterialTest : public BasicTest +{ + +protected: + + void LoadTestScene() override + { + m_scene = Baikal::SceneIo::LoadScene("sphere+plane+ibl.test", ""); + } + + void MaterialTestHelperFunction( + const std::string& test_name, + const std::vector &iors, + std::function(float ior)> produce_material) + { + using namespace Baikal; + + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + for (auto ior : iors) + { + auto material = produce_material(ior); + + ApplyMaterialToObject("sphere", material); + + ClearOutput(); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + + if (iors.size() == 1 && iors[0] == 0) + oss << test_name << ".png"; + else + oss << test_name << "_" << ior << ".png"; + + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } + } +}; + +TEST_F(MaterialTest, Material_Diffuse) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + std::vector colors = + { + RadeonRays::float3(0.9f, 0.2f, 0.1f), + RadeonRays::float3(0.1f, 0.9f, 0.1f), + RadeonRays::float3(0.3f, 0.2f, 0.8f) + }; + + std::string resource_dir = "../Resources/Textures/"; + std::string ext = ".jpg"; + std::vector texture_names = + { + "test_albedo1", + "test_albedo2", + "test_albedo3" + }; + auto material = Baikal::UberV2Material::Create(); + material->SetLayers(Baikal::UberV2Material::Layers::kDiffuseLayer); + auto diffuse_color = Baikal::InputMap_ConstantFloat3::Create(float3(0.f, 0.f, 0.f)); + material->SetInputValue("uberv2.diffuse.color", diffuse_color); + + + for (auto& c : colors) + { + ClearOutput(); + + diffuse_color->SetValue(c); + + ApplyMaterialToObject("sphere", material); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_" << c.x << "_" << c.y << "_" << c.z << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } + + auto image_io = Baikal::ImageIo::CreateImageIo(); + auto texture = image_io->LoadImage(resource_dir + texture_names[0] + ext); + auto diffuse_texture = Baikal::InputMap_Sampler::Create(texture); + material->SetInputValue("uberv2.diffuse.color", diffuse_texture); + + for (auto& t : texture_names) + { + ClearOutput(); + + auto texture = image_io->LoadImage(resource_dir + t + ext); + diffuse_texture->SetTexture(texture); + + ApplyMaterialToObject("sphere", material); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_" << t << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } +} + +TEST_F(MaterialTest, Material_Reflect) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + std::vector colors = + { + RadeonRays::float3(0.9f, 0.2f, 0.1f), + RadeonRays::float3(0.1f, 0.9f, 0.1f), + RadeonRays::float3(0.3f, 0.2f, 0.8f) + }; + + std::vector iors = + { + 0.f, 1.1f, 1.3f, 1.6f, 2.2f, 5.f + }; + + std::string resource_dir = "../Resources/Textures/"; + std::string ext = ".jpg"; + std::vector texture_names = + { + "test_albedo1", + "test_albedo2", + "test_albedo3" + }; + + auto material = Baikal::UberV2Material::Create(); + material->SetLayers(Baikal::UberV2Material::Layers::kReflectionLayer); + auto reflection_color = Baikal::InputMap_ConstantFloat3::Create(float3()); + auto reflection_ior = Baikal::InputMap_ConstantFloat::Create(0.f); + material->SetInputValue("uberv2.reflection.color", reflection_color); + material->SetInputValue("uberv2.reflection.metalness", + Baikal::InputMap_ConstantFloat::Create(1.f)); + material->SetInputValue("uberv2.reflection.ior", reflection_ior); + material->SetInputValue("uberv2.reflection.roughness", + Baikal::InputMap_ConstantFloat::Create(0.f)); + + for (auto& c : colors) + { + for (auto& ior : iors) + { + ClearOutput(); + + reflection_color->SetValue(c); + reflection_ior->SetValue(ior); + + ApplyMaterialToObject("sphere", material); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << ior << + "_" << c.x << "_" << c.y << "_" << c.z << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } + } + + + auto image_io = Baikal::ImageIo::CreateImageIo(); + + auto texture = image_io->LoadImage(resource_dir + texture_names[0] + ext); + + auto reflection_texture = Baikal::InputMap_Sampler::Create(texture); + material->SetInputValue("uberv2.reflection.color", reflection_texture); + + + for (auto& t : texture_names) + { + for (auto& ior : iors) + { + ClearOutput(); + + auto texture = image_io->LoadImage(resource_dir + t + ext); + + reflection_texture->SetTexture(texture); + reflection_ior->SetValue(ior); + + ApplyMaterialToObject("sphere", material); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_" << ior << "_" << t << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } + } +} + +TEST_F(MaterialTest, Material_MicrofacetGGX) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + std::vector colors = + { + RadeonRays::float3(0.9f, 0.2f, 0.1f), + RadeonRays::float3(0.1f, 0.9f, 0.1f), + RadeonRays::float3(0.3f, 0.2f, 0.8f) + }; + + std::vector iors = + { + 0.f, 1.1f, 1.3f, 1.6f, 2.2f, 5.f + }; + + std::vector roughnesses = + { + 0.0001f, 0.01f, 0.1f, 0.4f + }; + + std::string resource_dir = "../Resources/Textures/"; + std::string ext = ".jpg"; + std::vector texture_names = + { + "test_albedo1", + "test_albedo2", + "test_albedo3" + }; + + auto material = Baikal::UberV2Material::Create(); + material->SetLayers(Baikal::UberV2Material::Layers::kReflectionLayer); + + auto reflection_color = Baikal::InputMap_ConstantFloat3::Create(float3()); + auto reflection_ior = Baikal::InputMap_ConstantFloat::Create(0.f); + auto reflection_roughness = Baikal::InputMap_ConstantFloat::Create(0.f); + + material->SetInputValue("uberv2.reflection.color", reflection_color); + material->SetInputValue("uberv2.reflection.metalness", + Baikal::InputMap_ConstantFloat::Create(1.f)); + material->SetInputValue("uberv2.reflection.ior", reflection_ior); + material->SetInputValue("uberv2.reflection.roughness", reflection_roughness); + + + for (auto& r : roughnesses) + { + for (auto& c : colors) + { + for (auto& ior : iors) + { + ClearOutput(); + + reflection_color->SetValue(c); + reflection_ior->SetValue(ior); + reflection_roughness->SetValue(r); + + ApplyMaterialToObject("sphere", material); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_" << r << "_" << ior << + "_" << c.x << "_" << c.y << "_" << c.z << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } + } + } + + + auto image_io = Baikal::ImageIo::CreateImageIo(); + + auto texture = image_io->LoadImage(resource_dir + texture_names[0] + ext); + + auto reflection_texture = Baikal::InputMap_Sampler::Create(texture); + material->SetInputValue("uberv2.reflection.color", reflection_texture); + + for (auto& r : roughnesses) + { + for (auto& t : texture_names) + { + for (auto& ior : iors) + { + ClearOutput(); + + auto texture = image_io->LoadImage(resource_dir + t + ext); + + reflection_texture->SetTexture(texture); + reflection_ior->SetValue(ior); + reflection_roughness->SetValue(r); + + ApplyMaterialToObject("sphere", material); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_" << r << "_" << ior << "_" << t << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } + } + } +} + +TEST_F(MaterialTest, Material_Refract) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + std::vector colors = + { + RadeonRays::float3(0.9f, 0.2f, 0.1f), + RadeonRays::float3(0.1f, 0.9f, 0.1f), + RadeonRays::float3(0.3f, 0.2f, 0.8f) + }; + + std::vector iors = + { + 1.1f, 1.3f, 1.6f, 2.2f, 5.f + }; + + std::string resource_dir = "../Resources/Textures/"; + std::string ext = ".jpg"; + std::vector texture_names = + { + "test_albedo1", + "test_albedo2", + "test_albedo3" + }; + + auto material = Baikal::UberV2Material::Create(); + material->SetLayers(Baikal::UberV2Material::Layers::kRefractionLayer); + + auto refraction_color = Baikal::InputMap_ConstantFloat3::Create(float3()); + auto refraction_ior = Baikal::InputMap_ConstantFloat::Create(0.f); + + material->SetInputValue("uberv2.refraction.color", refraction_color); + material->SetInputValue("uberv2.refraction.ior", refraction_ior); + material->SetInputValue("uberv2.refraction.roughness", + Baikal::InputMap_ConstantFloat::Create(0.f)); + + + for (auto& c : colors) + { + for (auto& ior : iors) + { + ClearOutput(); + + refraction_color->SetValue(c); + refraction_ior->SetValue(ior); + + ApplyMaterialToObject("sphere", material); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << ior << + "_" << c.x << "_" << c.y << "_" << c.z << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } + } + + + auto image_io = Baikal::ImageIo::CreateImageIo(); + auto texture = image_io->LoadImage(resource_dir + texture_names[0] + ext); + auto refraction_texture = Baikal::InputMap_Sampler::Create(texture); + material->SetInputValue("uberv2.refraction.color", refraction_texture); + + for (auto& t : texture_names) + { + for (auto& ior : iors) + { + ClearOutput(); + + auto texture = image_io->LoadImage(resource_dir + t + ext); + + refraction_texture->SetTexture(texture); + refraction_ior->SetValue(ior); + + ApplyMaterialToObject("sphere", material); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_" << ior << "_" << t << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } + } +} + +TEST_F(MaterialTest, Material_MicrofacetRefractGGX) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + std::vector colors = + { + RadeonRays::float3(0.9f, 0.2f, 0.1f), + RadeonRays::float3(0.1f, 0.9f, 0.1f), + RadeonRays::float3(0.3f, 0.2f, 0.8f) + }; + + std::vector iors = + { + 1.1f, 1.3f, 1.6f, 2.2f, 5.f + }; + + std::vector roughnesses = + { + 0.0001f, 0.01f, 0.1f, 0.4f + }; + + std::string resource_dir = "../Resources/Textures/"; + std::string ext = ".jpg"; + std::vector texture_names = + { + "test_albedo1", + "test_albedo2", + "test_albedo3" + }; + + auto material = Baikal::UberV2Material::Create(); + material->SetLayers(Baikal::UberV2Material::Layers::kRefractionLayer); + + auto refraction_color = Baikal::InputMap_ConstantFloat3::Create(float3()); + auto refraction_ior = Baikal::InputMap_ConstantFloat::Create(0.f); + auto refraction_roughness = Baikal::InputMap_ConstantFloat::Create(0.f); + + material->SetInputValue("uberv2.refraction.color", refraction_color); + material->SetInputValue("uberv2.refraction.ior", refraction_ior); + material->SetInputValue("uberv2.refraction.roughness", refraction_roughness); + + for (auto& r : roughnesses) + { + for (auto& c : colors) + { + for (auto& ior : iors) + { + ClearOutput(); + + refraction_color->SetValue(c); + refraction_ior->SetValue(ior); + refraction_roughness->SetValue(r); + + ApplyMaterialToObject("sphere", material); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_" << r << "_" << ior << + "_" << c.x << "_" << c.y << "_" << c.z << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } + } + } + + + auto image_io = Baikal::ImageIo::CreateImageIo(); + + auto texture = image_io->LoadImage(resource_dir + texture_names[0] + ext); + auto refraction_texture = Baikal::InputMap_Sampler::Create(texture); + material->SetInputValue("uberv2.refraction.color", refraction_texture); + + for (auto& r : roughnesses) + { + for (auto& t : texture_names) + { + for (auto& ior : iors) + { + ClearOutput(); + + auto texture = image_io->LoadImage(resource_dir + t + ext); + + refraction_texture->SetTexture(texture); + refraction_ior->SetValue(ior); + refraction_roughness->SetValue(r); + + ApplyMaterialToObject("sphere", material); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_" << r << "_" << ior << "_" << t << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } + } + } +} + +TEST_F(MaterialTest, Material_DiffuseAndMicrofacet) +{ + using namespace Baikal; + + std::vector iors = + { + 1.1f, 1.3f, 1.6f, 2.2f, 3.f + }; + + auto material = UberV2Material::Create(); + material->SetLayers(UberV2Material::Layers::kDiffuseLayer | + Baikal::UberV2Material::Layers::kReflectionLayer); + + material->SetInputValue("uberv2.diffuse.color", + Baikal::InputMap_ConstantFloat3::Create(float3(0.9f, 0.2f, 0.1f))); + + material->SetInputValue("uberv2.reflection.color", + Baikal::InputMap_ConstantFloat3::Create(float3(0.1f, 0.9f, 0.1f))); + material->SetInputValue("uberv2.reflection.roughness", + Baikal::InputMap_ConstantFloat::Create(0.002f)); + + auto reflection_ior = Baikal::InputMap_ConstantFloat::Create(1.1f); + + material->SetInputValue("uberv2.reflection.ior", reflection_ior); + + MaterialTestHelperFunction( + test_name(), + iors, + [&](float ior) + { + using namespace Baikal; + + reflection_ior->SetValue(ior); + + return material; + }); +} + +TEST_F(MaterialTest, Material_RefractionAndMicrofacet) +{ + using namespace Baikal; + + std::vector iors = + { + 1.1f, 1.3f, 1.6f, 2.2f, 3.f + }; + + auto material = UberV2Material::Create(); + material->SetLayers(UberV2Material::Layers::kRefractionLayer | + Baikal::UberV2Material::Layers::kReflectionLayer); + + material->SetInputValue("uberv2.refraction.color", + Baikal::InputMap_ConstantFloat3::Create(float3(1.f, 1.f, 1.f))); + material->SetInputValue("uberv2.refraction.roughness", + Baikal::InputMap_ConstantFloat::Create(0.f)); + material->SetInputValue("uberv2.reflection.color", + Baikal::InputMap_ConstantFloat3::Create(float3(1.f, 1.f, 1.f))); + material->SetInputValue("uberv2.reflection.roughness", + Baikal::InputMap_ConstantFloat::Create(0.002f)); + + auto ior_input = Baikal::InputMap_ConstantFloat::Create(1.1f); + + material->SetInputValue("uberv2.refraction.ior", ior_input); + material->SetInputValue("uberv2.reflection.ior", ior_input); + + MaterialTestHelperFunction( + test_name(), + iors, + [&](float ior) + { + using namespace Baikal; + + ior_input->SetValue(ior); + + return material; + }); +} + +TEST_F(MaterialTest, Material_VolumeScattering) +{ + using namespace Baikal; + + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + std::vector scattering = + { + RadeonRays::float3(0.9f, 0.2f, 0.1f), + RadeonRays::float3(0.1f, 0.9f, 0.1f), + RadeonRays::float3(0.3f, 0.2f, 0.8f) + }; + + auto material = UberV2Material::Create(); + material->SetLayers(UberV2Material::Layers::kTransparencyLayer); + + for (auto scatter : scattering) + { + ClearOutput(); + + auto volume = VolumeMaterial::Create(); + + volume->SetInputValue("absorption", RadeonRays::float4(.1f, .1f, .1f, .1f)); + volume->SetInputValue("scattering", scatter); + volume->SetInputValue("emission", RadeonRays::float4(.0f, .0f, .0f, .0f)); + volume->SetInputValue("g", RadeonRays::float4(.0f, .0f, .0f, .0f)); + + for (auto iter = m_scene->CreateShapeIterator(); + iter->IsValid(); + iter->Next()) + { + auto mesh = iter->ItemAs(); + if (mesh->GetName() == "sphere") + { + mesh->SetMaterial(material); + mesh->SetVolumeMaterial(volume); + } + } + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_" << scatter.x << "_" << scatter.y << "_" << scatter.z << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } +} + +TEST_F(MaterialTest, Material_VolumeAbsorption) +{ + using namespace Baikal; + + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + std::vector absorptions = + { + RadeonRays::float3(0.9f, 0.2f, 0.1f), + RadeonRays::float3(1.1f, 1.9f, 0.1f), + RadeonRays::float3(0.3f, 1.2f, 1.8f) + }; + + auto material = UberV2Material::Create(); + material->SetLayers(UberV2Material::Layers::kTransparencyLayer); + + for (auto absorption : absorptions) + { + ClearOutput(); + + auto volume = VolumeMaterial::Create(); + + volume->SetInputValue("absorption", absorption); + volume->SetInputValue("scattering", RadeonRays::float4(.1f, .1f, .1f, .1f)); + volume->SetInputValue("emission", RadeonRays::float4(.0f, .0f, .0f, .0f)); + volume->SetInputValue("g", RadeonRays::float4(.0f, .0f, .0f, .0f)); + + for (auto iter = m_scene->CreateShapeIterator(); + iter->IsValid(); + iter->Next()) + { + auto mesh = iter->ItemAs(); + if (mesh->GetName() == "sphere") + { + mesh->SetMaterial(material); + mesh->SetVolumeMaterial(volume); + } + } + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_" << absorption.x << "_" << absorption.y << "_" << absorption.z << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } +} + +TEST_F(MaterialTest, Material_VolumeEmission) +{ + using namespace Baikal; + + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + std::vector emissions = + { + RadeonRays::float3(0.9f, 0.2f, 0.1f), + RadeonRays::float3(1.1f, 1.9f, 0.1f), + RadeonRays::float3(0.3f, 1.2f, 1.8f) + }; + + auto material = UberV2Material::Create(); + material->SetLayers(UberV2Material::Layers::kTransparencyLayer); + + for (auto emission : emissions) + { + ClearOutput(); + + auto volume = VolumeMaterial::Create(); + + volume->SetInputValue("absorption", RadeonRays::float4(.1f, .1f, .1f, .1f)); + volume->SetInputValue("scattering", RadeonRays::float4(.1f, .1f, .1f, .1f)); + volume->SetInputValue("emission", emission); + volume->SetInputValue("g", RadeonRays::float4(.0f, .0f, .0f, .0f)); + + for (auto iter = m_scene->CreateShapeIterator(); + iter->IsValid(); + iter->Next()) + { + auto mesh = iter->ItemAs(); + if (mesh->GetName() == "sphere") + { + mesh->SetMaterial(material); + mesh->SetVolumeMaterial(volume); + } + } + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_" << emission.x << "_" << emission.y << "_" << emission.z << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } +} + +TEST_F(MaterialTest, Material_PhaseFunction) +{ + using namespace Baikal; + + m_camera->LookAt( + RadeonRays::float3(0.f, 2.f, -10.f), + RadeonRays::float3(0.f, 2.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + std::vector gs = + { + RadeonRays::float3(0.f), + RadeonRays::float3(-0.5f), + RadeonRays::float3(0.5f), + RadeonRays::float3(-1.f), + RadeonRays::float3(1.f), + }; + + auto material = UberV2Material::Create(); + material->SetLayers(UberV2Material::Layers::kTransparencyLayer); + + for (auto g : gs) + { + ClearOutput(); + + auto volume = VolumeMaterial::Create(); + + volume->SetInputValue("absorption", RadeonRays::float4(.1f, .1f, .1f, .1f)); + volume->SetInputValue("scattering", RadeonRays::float4(.1f, .1f, .1f, .1f)); + volume->SetInputValue("emission", RadeonRays::float4(.0f, .0f, .0f, .0f)); + volume->SetInputValue("g", g); + + for (auto iter = m_scene->CreateShapeIterator(); + iter->IsValid(); + iter->Next()) + { + auto mesh = iter->ItemAs(); + if (mesh->GetName() == "sphere") + { + mesh->SetMaterial(material); + mesh->SetVolumeMaterial(volume); + } + } + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << "_" << g.x << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + } +} + diff --git a/BaikalTest/test_scenes.h b/BaikalTest/test_scenes.h new file mode 100644 index 00000000..d0dbd11d --- /dev/null +++ b/BaikalTest/test_scenes.h @@ -0,0 +1,191 @@ +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ +#pragma once + +#include "basic.h" + +class TestScenesTest : public BasicTest +{ +protected: + bool PrepeareScene(const std::string &file_name, const std::string file_path) + { + try + { + m_scene = Baikal::SceneIo::LoadScene(file_name, file_path); + } + catch (std::exception &) + { + return false; + } + + m_camera->SetSensorSize(RadeonRays::float2(0.036f, 0.036f)); + m_camera->SetDepthRange(RadeonRays::float2(0.0f, 100000.f)); + m_camera->SetFocalLength(0.035f); + m_camera->SetFocusDistance(1.f); + m_camera->SetAperture(0.f); + + m_scene->SetCamera(m_camera); + + return true; + } + + void AttachLight( + float direction_light_multiplier = 1.f, + float ibl_multiplier = 30.f) + { + auto image_io(Baikal::ImageIo::CreateImageIo()); + auto light_texture = image_io->LoadImage("../Resources/Textures/sky.hdr"); + auto image_based_light = Baikal::ImageBasedLight::Create(); + + // image based light initialization + image_based_light->SetTexture(light_texture); + image_based_light->SetMultiplier(ibl_multiplier); + m_scene->AttachLight(image_based_light); + + // directional light initialization + auto directional_light = Baikal::DirectionalLight::Create(); + directional_light->SetDirection(float3(.1f, -1.f, -.1f)); + directional_light->SetEmittedRadiance(float3(1.f, 1.f, 1.f) * direction_light_multiplier); + m_scene->AttachLight(directional_light); + } + + void DrawScene(uint32_t iterations_number = kNumIterations) + { + ClearOutput(); + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < iterations_number; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +}; + +TEST_F(TestScenesTest, TestScenes_CornellBox) +{ + m_camera = Baikal::PerspectiveCamera::Create( + RadeonRays::float3(0.f, 1.f, 3.f), + RadeonRays::float3(0.f, 1.f, 0.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + if (!PrepeareScene( + "../Resources/TestData/CornellBox/orig.objm", + "../Resources/TestData/CornellBox/")) + { + std::cout << "There's no CornellBox test set" << std::endl; + return; + } + + DrawScene(128); +} + +TEST_F(TestScenesTest, TestScenes_Sponza) +{ + + m_camera = Baikal::PerspectiveCamera::Create( + RadeonRays::float3(110.7f, 460.2f, -32.297f), + RadeonRays::float3(112.8f, 460.1f, -32.304f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + if (!PrepeareScene( + "../Resources/TestData/Sponza/sponza.obj", + "../Resources/TestData/Sponza/")) + { + std::cout << "There's no Sponza test set" << std::endl; + return; + } + + AttachLight(30.f); + + DrawScene(128); +} + +TEST_F(TestScenesTest, TestScenes_Classroom) +{ + + m_camera = Baikal::PerspectiveCamera::Create( + RadeonRays::float3(.0f, 1.f, 3.f), + RadeonRays::float3(.244f, 1.021f, 2.030f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + if (!PrepeareScene( + "../Resources/TestData/Classroom/classroom.obj", + "../Resources/TestData/Classroom/")) + { + std::cout << "There's no Classroom test set" << std::endl; + return; + } + + + AttachLight(30.f); + + DrawScene(128); +} + +TEST_F(TestScenesTest, TestScenes_Rungholt) +{ + + m_camera = Baikal::PerspectiveCamera::Create( + RadeonRays::float3(150.065f, 35.42f, 187.448f), + RadeonRays::float3(149.232f, 35.311f, 186.906f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + if (!PrepeareScene( + "../Resources/TestData/Rungholt/rungholt.obj", + "../Resources/TestData/Rungholt/")) + { + std::cout << "There's no Rungholt test set" << std::endl; + return; + } + + AttachLight(5.f, 5.f); + + DrawScene(128); +} + +TEST_F(TestScenesTest, TestScenes_San_Miguel) +{ + + m_camera = Baikal::PerspectiveCamera::Create( + RadeonRays::float3(8.891f, 2.029f, 6.702f), + RadeonRays::float3(9.658f, 2.020f, 6.060f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + if (!PrepeareScene( + "../Resources/TestData/San_Miguel/san-miguel.obj", + "../Resources/TestData/San_Miguel/")) + { + std::cout << "There's no San Miguel test set" << std::endl; + return; + } + + AttachLight(30.f); + + DrawScene(); +} \ No newline at end of file diff --git a/BaikalTest/uberv2.h b/BaikalTest/uberv2.h new file mode 100644 index 00000000..029b0822 --- /dev/null +++ b/BaikalTest/uberv2.h @@ -0,0 +1,72 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once + +#include "basic.h" +#include "SceneGraph/light.h" +#include "SceneGraph/shape.h" +#include "SceneGraph/material.h" +#include "image_io.h" + +#define _USE_MATH_DEFINES +#include + +using namespace RadeonRays; + +class UberV2Test : public BasicTest +{ + +protected: + + void LoadTestScene() override + { + ASSERT_NO_THROW(m_output = m_factory->CreateOutput(1024, 1024)); + m_output->Clear(RadeonRays::float3(0.0f)); + ASSERT_NO_THROW(m_renderer->SetOutput(Baikal::Renderer::OutputType::kColor, m_output.get())); + + m_scene = Baikal::SceneIo::LoadScene("uberv2_test_spheres.test", ""); + } +}; + +TEST_F(UberV2Test, UberV2_Basic) +{ + m_camera->LookAt( + RadeonRays::float3(0.f, 0.f, 10.f), + RadeonRays::float3(0.f, 0.f, 9.f), + RadeonRays::float3(0.f, 1.f, 0.f)); + + ASSERT_NO_THROW(m_controller->CompileScene(m_scene)); + + auto& scene = m_controller->GetCachedScene(m_scene); + + for (auto i = 0u; i < kNumIterations; ++i) + { + ASSERT_NO_THROW(m_renderer->Render(scene)); + } + + { + std::ostringstream oss; + oss << test_name() << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } +} diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..3176756a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,150 @@ +cmake_minimum_required(VERSION 3.8) + +project(Baikal CXX) + +option(BAIKAL_ENABLE_RAYMASK "Enable visibility flags for shapes (slows down an intersector)" OFF) +option(BAIKAL_ENABLE_DENOISER "Use denoising on output" OFF) +option(BAIKAL_ENABLE_RPR "Enable RadeonProRender API lib" OFF) +option(BAIKAL_ENABLE_TESTS "Enable tests" ON) +option(BAIKAL_ENABLE_STANDALONE "Enable standalone application build" ON) +option(BAIKAL_ENABLE_DATAGENERATOR "Enable data generator application build" ON) +option(BAIKAL_ENABLE_IO "Enable IO library build" ON) +option(BAIKAL_ENABLE_FBX "Enable FBX import in BaikalIO. Requires BaikalIO to be turned ON" OFF) +option(BAIKAL_ENABLE_MATERIAL_CONVERTER "Enable materials.xml converter from old to uberv2 version" OFF) +option(BAIKAL_EMBED_KERNELS "Embed CL kernels into binary module" OFF) + +#Sanity checks +if (BAIKAL_ENABLE_GLTF AND NOT BAIKAL_ENABLE_RPR) + message(FATAL_ERROR "glTF support requires RPR but it's disabled") +endif (BAIKAL_ENABLE_GLTF AND NOT BAIKAL_ENABLE_RPR) + +#global settings +if (WIN32) + add_definitions(/MP -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS) +elseif (UNIX) + add_definitions(-fvisibility=hidden -Wno-ignored-attributes) +endif (WIN32) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +#Find required packages +find_package(Threads REQUIRED) +find_package(OIIO REQUIRED) + +if (BAIKAL_ENABLE_STANDALONE OR BAIKAL_ENABLE_RPR) + find_package(OpenGL REQUIRED) +endif (BAIKAL_ENABLE_STANDALONE OR BAIKAL_ENABLE_RPR) + +#Configure RadeonRays build +set(RR_EMBED_KERNELS ON CACHE BOOL "Embed CL kernels into binary module") +set(RR_ALLOW_CPU_DEVICES OFF CACHE BOOL "Allows CPU Devices") +set(RR_USE_OPENCL ON CACHE BOOL "Use OpenCL for GPU hit testing") +set(RR_USE_EMBREE OFF CACHE BOOL "Use Intel(R) Embree for CPU hit testing") +set(RR_USE_VULKAN OFF CACHE BOOL "Use vulkan for GPU hit testing") +set(RR_NO_TESTS ON CACHE BOOL "Don't add any unit tests and remove any test functionality from the library") +set(RR_ENABLE_STATIC OFF CACHE BOOL "Create static libraries rather than dynamic") +set(RR_SHARED_CALC OFF CACHE BOOL "Link Calc(compute abstraction layer) dynamically") +set(RR_ENABLE_RAYMASK $BAIKAL_ENABLE_RAYMASK CACHE BOOL "Enable ray masking in intersection kernels") +set(RR_TUTORIALS OFF CACHE BOOL "Add tutorials projects") +set(RR_SAFE_MATH OFF CACHE BOOL "use safe math") + +# Sanity checks +if (BAIKAL_ENABLE_STANDALONE AND NOT BAIKAL_ENABLE_IO) + message(FATAL_ERROR "BAIKAL_ENABLE_STANDALONE option requires BAIKAL_ENABLE_IO to be turned ON but it is OFF") +endif (BAIKAL_ENABLE_STANDALONE AND NOT BAIKAL_ENABLE_IO) + +if (BAIKAL_ENABLE_STANDALONE OR BAIKAL_ENABLE_RPR) + find_package(GLEW REQUIRED) +endif (BAIKAL_ENABLE_STANDALONE OR BAIKAL_ENABLE_RPR) + +add_subdirectory(RadeonRays) + +add_subdirectory(Baikal) + +if (BAIKAL_ENABLE_IO) + if (BAIKAL_ENABLE_FBX) + find_package(FBX_SDK REQUIRED) + endif (BAIKAL_ENABLE_FBX) + add_subdirectory(BaikalIO) +endif (BAIKAL_ENABLE_IO) + +if (BAIKAL_ENABLE_DATAGENERATOR) + set(BAIKAL_ENABLE_RPR ON) + add_subdirectory(BaikalDataGenerator) +endif (BAIKAL_ENABLE_DATAGENERATOR) + +if (BAIKAL_ENABLE_RPR) + set(RprSupport_HEADER "${Baikal_SOURCE_DIR}/3rdparty/RprSupport/include/") + add_subdirectory(Rpr) + add_subdirectory(RprSupport) +endif (BAIKAL_ENABLE_RPR) + +if (BAIKAL_ENABLE_MATERIAL_CONVERTER) + add_subdirectory(Tools/MaterialConverter) +endif (BAIKAL_ENABLE_MATERIAL_CONVERTER) + +if (BAIKAL_ENABLE_STANDALONE) + find_package(GLFW3 REQUIRED) + add_subdirectory(BaikalStandalone) +endif (BAIKAL_ENABLE_STANDALONE) + +if (BAIKAL_ENABLE_TESTS) + add_subdirectory(Gtest) + add_subdirectory(BaikalTest) + if (BAIKAL_ENABLE_RPR) + add_subdirectory(RprTest) + endif (BAIKAL_ENABLE_RPR) +endif (BAIKAL_ENABLE_TESTS) + +# Copy 3rd party dlls on Windows +if (WIN32) + set (THIRDPARTY_DLLS + "${Baikal_SOURCE_DIR}/3rdparty/glew/bin/x64/glew32.dll" + "${Baikal_SOURCE_DIR}/3rdparty/glfw/bin/x64/glfw3.dll" + "${Baikal_SOURCE_DIR}/3rdparty/oiio/bin/x64/OpenImageIO.dll" + "${Baikal_SOURCE_DIR}/3rdparty/oiio/bin/x64/OpenImageIOD.dll" + ) + + add_custom_target(Copy3rdParty ALL + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${THIRDPARTY_DLLS} "$" + ) +else () + # Empty dummy target + add_custom_target(Copy3rdParty) +endif () + +# Add symbolic link from binary to Resources directory +set(RESOURCES_DIR Resources) +file(TO_NATIVE_PATH ${Baikal_SOURCE_DIR}/${RESOURCES_DIR} RESOURCES_SRC) +file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR}/${RESOURCES_DIR} RESOURCES_DST) + +if (WIN32) + add_custom_target(ResourcesDir ALL + COMMAND IF NOT EXIST ${RESOURCES_DST} mklink /D ${RESOURCES_DST} ${RESOURCES_SRC} + ) +else () + add_custom_target(ResourcesDir ALL + COMMAND ${CMAKE_COMMAND} -E create_symlink ${RESOURCES_SRC} ${RESOURCES_DST} + ) +endif () + +# Install Resources folder +file(TO_CMAKE_PATH ${RESOURCES_SRC} RESOURCES_SRC_CMAKE) +install(DIRECTORY ${RESOURCES_SRC_CMAKE} DESTINATION .) + +# TODO: the following should be added to CMakeLists.txt of RadeonRays +#if (WIN32) +# install(TARGETS RadeonRays RUNTIME DESTINATION bin) +#else () +# install(TARGETS RadeonRays LIBRARY DESTINATION lib) +#endif () + +# TODO: the following should be removed after the above being add to CMakeLists.txt of RadeonRays +if (WIN32) + install(FILES $ DESTINATION bin) +else () + install(FILES $ DESTINATION lib) +endif () diff --git a/Doc/Images/1.jpg b/Doc/Images/1.jpg index f5a96004..597c4750 100644 Binary files a/Doc/Images/1.jpg and b/Doc/Images/1.jpg differ diff --git a/Doc/Images/4.png b/Doc/Images/4.png new file mode 100644 index 00000000..6bcb6753 Binary files /dev/null and b/Doc/Images/4.png differ diff --git a/Doc/Images/5.jpg b/Doc/Images/5.jpg new file mode 100644 index 00000000..597c4750 Binary files /dev/null and b/Doc/Images/5.jpg differ diff --git a/Gtest/CMakeLists.txt b/Gtest/CMakeLists.txt new file mode 100644 index 00000000..7776a005 --- /dev/null +++ b/Gtest/CMakeLists.txt @@ -0,0 +1,12 @@ +project(GTest) + +set(SOURCES + src/gtest-all.cc + src/gtest_main.cc) + +add_library(GTest STATIC ${SOURCES}) + +target_include_directories(GTest PUBLIC include) +target_include_directories(GTest PRIVATE .) +target_compile_definitions(GTest PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING) +target_link_libraries(GTest PUBLIC Threads::Threads) diff --git a/Gtest/gtest.lua b/Gtest/gtest.lua deleted file mode 100644 index e8bbb5ec..00000000 --- a/Gtest/gtest.lua +++ /dev/null @@ -1,22 +0,0 @@ -project "Gtest" - location "../Gtest" - kind "StaticLib" - includedirs { ".", "include" } - defines { "GTEST_HAS_PTHREAD=0" } - files { "src/gtest-all.cc", "src/gtest_main.cc" } - buildoptions { "-g", "-Wall" } - - if _ACTION == "vs2012" then - defines{ "GTEST_HAS_TR1_TUPLE=0" } - end - - - configuration {"x32", "Debug"} - targetdir "../Bin/Debug/x86" - configuration {"x64", "Debug"} - targetdir "../Bin/Debug/x64" - configuration {"x32", "Release"} - targetdir "../Bin/Release/x86" - configuration {"x64", "Release"} - targetdir "../Bin/Release/x64" - configuration {} diff --git a/OpenCLSearch.lua b/OpenCLSearch.lua deleted file mode 100644 index 72e47896..00000000 --- a/OpenCLSearch.lua +++ /dev/null @@ -1,113 +0,0 @@ - if os.is("windows") then - local amdopenclpath = os.getenv("AMDAPPSDKROOT") - if( amdopenclpath ) then - amdopenclpath = string.gsub(amdopenclpath, "\\", "/"); - local clIncludePath = string.format("%s/include",amdopenclpath); - local clLibPath = string.format("%s/lib/x86",amdopenclpath); - local clLibPath64 = string.format("%s/lib/x86_64",amdopenclpath); - print("OpenCL_Path(AMD)", amdopenclpath) - if (amdopenclpath) then - includedirs {clIncludePath} - -- libdirs {clLibPath} - configuration "x64" - libdirs {clLibPath64} - configuration "x32" - libdirs {clLibPath} - configuration {} - links {"OpenCL"} - end - end - - local nvidiaopenclpath = os.getenv("CUDA_PATH") - if( nvidiaopenclpath ) then - defines { "OPENCL_10" } - nvidiaopenclpath = string.gsub(nvidiaopenclpath, "\\", "/"); - local clIncludePath = string.format("%s/include",nvidiaopenclpath); - local clLibPath = string.format("%s/lib/Win32",nvidiaopenclpath); - local clLibPath64 = string.format("%s/lib/x64",nvidiaopenclpath); - print("OpenCL_Path(Nvidia)", nvidiaopenclpath) - if (nvidiaopenclpath) then - includedirs {clIncludePath} - -- libdirs {clLibPath} - configuration "x64" - libdirs {clLibPath64} - configuration "x32" - libdirs {clLibPath} - configuration {} - links {"OpenCL"} - end - end - - local intelopenclpath = os.getenv("INTELOCLSDKROOT") - if( intelopenclpath ) then - defines { "INTEL_BUG_WORKROUND" } - intelopenclpath = string.gsub(intelopenclpath, "\\", "/"); - local clIncludePath = string.format("%s/include",intelopenclpath); - local clLibPath = string.format("%s/lib/x86",intelopenclpath); - local clLibPath64 = string.format("%s/lib/x64",intelopenclpath); - print("OpenCL_Path(Intel)", intelopenclpath) - if (intelopenclpath) then - includedirs {clIncludePath} - -- libdirs {clLibPath} - configuration "x64" - libdirs {clLibPath64} - configuration "x32" - libdirs {clLibPath} - configuration {} - links {"OpenCL"} - end - end - end - - if os.is("macosx") then - linkoptions{ "-framework OpenCL" } - end - - if os.is("linux") then - local amdopenclpath = os.getenv("AMDAPPSDKROOT") - local nvidiaopenclpath = os.getenv("CUDA_PATH") - if( amdopenclpath ) then - amdopenclpath = string.gsub(amdopenclpath, "\\", "/"); - local clIncludePath = string.format("%s/include",amdopenclpath); - local clLibPath = string.format("%s/lib/x86",amdopenclpath); - local clLibPath64 = string.format("%s/lib/x86_64",amdopenclpath); - print("OpenCL_Path(AMD)", amdopenclpath) - if (amdopenclpath) then - includedirs {clIncludePath} - -- libdirs {clLibPath} - configuration "x64" - libdirs {clLibPath64} - configuration "x32" - libdirs {clLibPath} - configuration {} - links {"OpenCL"} - end - elseif( nvidiaopenclpath ) then - defines { "OPENCL_10" } - nvidiaopenclpath = string.gsub(nvidiaopenclpath, "\\", "/"); - local clIncludePath = string.format("%s/include",nvidiaopenclpath); - local clLibPath = string.format("%s/lib/Win32",nvidiaopenclpath); - local clLibPath64 = string.format("%s/lib/x64",nvidiaopenclpath); - print("OpenCL_Path(Nvidia)", nvidiaopenclpath) - if (nvidiaopenclpath) then - includedirs {clIncludePath} - -- libdirs {clLibPath} - configuration "x64" - libdirs {clLibPath64} - configuration "x32" - libdirs {clLibPath} - configuration {} - links {"OpenCL"} - end - else - configuration "x64" - libdirs {"/usr/lib/x86_64-linux-gnu"} - configuration "x32" - libdirs {"/usr/lib/i386-linux-gnu"} - configuration {} - links {"OpenCL", "pthread"} - end - end - - - diff --git a/README.md b/README.md index b4180b97..cef78063 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,203 @@ -# Summary +# Summary Baikal initiative has been started as a sample application demonstrating the usage of AMD® RadeonRays intersection engine, but evolved into a fully functional rendering engine aimed at graphics researchers, educational institutions and open-source enthusiasts in general. Baikal is fast and efficient GPU-based global illumination renderer implemented using OpenCL and relying on AMD® RadeonRays intersection engine. It is cross-platform and vendor independent. The only requirement it imposes on the hardware is OpenCL 1.2 support. Baikal maintains high level of performance across all vendors, but it is specifically optimized for AMD® GPUs and APUs. -![Image](https://github.com/GPUOpen-LibrariesAndSDKs/RadeonProRender-Baikal/blob/master/Doc/Images/1.jpg) -“Science Fiction†scene is a courtesy of Juan Carlos Silva, 3drender.com. +![Image](https://github.com/GPUOpen-LibrariesAndSDKs/RadeonProRender-Baikal/blob/master/Doc/Images/5.jpg) + +# Build +## System requirements +The renderer is cross-platform and the following compilers are supported: + +- Visual Studio 2015 and later + +- Xcode 4 and later + +- GCC 4.8 and later + +- CMake 3.8 and later + +The following packages are required to build the renderer: + +- Python 2.7 +- OpenImageIO (for MacOS/Linux builds) +- glew (for MacOS/Linux builds) +- GLFW3 (for MacOS/Linux builds) +- AMD APP SDK or CUDA SDK + +## Build instructions + +Baikal is using git submodules, use the following command line to recursively clone the repo including submodules: + +``` +git clone --recursive https://github.com/GPUOpen-LibrariesAndSDKs/RadeonProRender-Baikal.git +``` + +### Windows +- Create Visual Studio 2015 Solution + +`cmake -G "Visual Studio 14 2015 Win64"` + +### OSX + +- Install Homebrew + +`/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"` + +- Install OpenImageIO + +`brew install homebrew/science/openimageio` + +- Install GLFW3 + +`brew install glfw3` + +- Make build folder and generate make files + +`mkdir build` + +`cd build` + +`cmake -DCMAKE_BUILD_TYPE= ..` + +`make` + +### Linux(Ubuntu) + +- Install complementary libraries + +`sudo apt-get install g++` + +- Install build dependencies + +`sudo apt-get install libopenimageio-dev libglew-dev libglfw3-dev` + +- Create the Makefile and build + +`mkdir build` + +`cd build` + +`cmake -DCMAKE_BUILD_TYPE= ..` + +`make` + +### Options + +Available premake options: + +- `BAIKAL_ENABLE_DENOISER` enables EAW denoiser in interactive output: + +- `BAIKAL_ENABLE_RPR` generates RadeonProRender API implemenatiton C-library and couple of RPR tutorials. + +## Run + +## Run Baikal standalone app + - `export LD_LIBRARY_PATH=/build/bin/:${LD_LIBRARY_PATH}` + - `cd BaikalStandalone` + - `../build/bin/BaikalStandalone` + +Possible command line args: +- `-platform index` select specific OpenCL platform +- `-device index` select specific OpenCL device +- `-p path` path to mesh/material files +- `-f file` mesh file to render +- `-w` set window width +- `-h` set window height +- `-ns num` limit the number of samples per pixel +- `-cs speed` set camera movement speed +- `-cpx x -cpy y -cpz z` set camera position +- `-tpx x -tpy y -tpz z` set camera target +- `-interop [0|1]` disable | enable OpenGL interop (enabled by default, might be broken on some Linux systems) +- `-config [gpu|cpu|mgpu|mcpu|all]` set device configuration to run on: single gpu (default) | single cpu | all available gpus | all available cpus | all devices + +The list of supported texture formats: + +- png +- bmp +- jpg +- gif +- exr +- hdr +- tx +- dds (limited support) +- tga + +You can download additional test scenes from [RadeonProRender-Tests](https://github.com/GPUOpen-LibrariesAndSDKs/RadeonProRender-Tests). Once extracted, you can load e.g. the Classroom example like this: + +`../build/bin/BaikalStandalone -p /path/to/extracted/folder/Classroom/ -f classroom.obj` + +The path can be absolute or relative to `BaikalStandalone`. + +## Run BaikalDataGenerator + - `export LD_LIBRARY_PATH=/build/bin/:${LD_LIBRARY_PATH}` + - `cd BaikalStandalone` + - `../build/bin/BaikalStandalone` + +Mandatory command line args: +- `-light_file` full path to config file with light description +- `-camera_file` full path to config file with camera states description +- `-spp_file` full path to config file with necessary sampling per pixel enumeration +- `-scene_file` full path to scene +- `-output_dir` directory to store generated dataset +- `-width` generated ouput width +- `-height` generated ouput height + +Possible command line args: +- `-gamma` enables gamma corection for 3 chanel color output. '-gamma 1' means that gamma correction is enabled, otherwise disabled + +## Run unit tests +- `export LD_LIBRARY_PATH=/build/bin/:${LD_LIBRARY_PATH}` + - `cd BaikalTest` + - `../build/bin/BaikalTest` + +Unit tests are producing test images into BaikalTest/OutputImages and compare them to reference images expected to be at BaikalTest/ReferenceImages. + +Possible command line args: +- `-genref 1` generate reference images + + +# Hardware support + +The renderer has been tested on the following hardware and OSes: + +## Linux + - Ubuntu Linux 14.04 + - AMD FirePro driver 15.201: W9100, W8100, W9000, W7000, W7100, S9300x2, W5100 + - AMD Radeon driver 15.302: R9 Nano, R9 Fury X, R9 290 + - NVIDIA driver 352.79: GeForce GTX970, Titan X + +## Windows + - Windows 7/8.1/10 + - AMD FirePro driver 15.201: W9100, W8100, W9000, W7000, W7100, S9300x2, W5100 + - AMD Radeon driver 16.4: R9 Nano, R9 Fury X, R9 290, Pro Duo + - NVIDIA driver 364.72: GeForce GTX970, Titan X +## OSX + - OSX High Sierra + - Mac Pro (Late 2013) AMD FirePro D500 x2 + - Macbook Pro Retina 13" (Early 2013) Intel HD 4300 + - Macbook Pro Retina 13" (2017) Intel Iris + - Macbook 12" (Early 2015) Intel HD 5300 + +# Known Issues + +## Windows + + - BaikalStandalone hangs sometimes on Windows on Nvidia cards. The issue is caused by ImGUI incompatibility with GL/CL interop. Removing ImGUI render call fixes the issue. + + ## Linux + + - If is missing try to specify OpenCL SDK location. + - If your are experiencing problems creating your CL context with a default config chances are CL-GL interop is broken on your system, try running the sample app with -interop 0 command line option (expect performance drop). + +AMD: +`export $AMDAPPSDKROOT=` +NVIDIA: +`export $CUDA_PATH=` + +--- # Features Being more of an experimental renderer, than a production rendering solution, Baikal still maintains a good set of features. @@ -72,17 +263,7 @@ In addition Baikal is using multiple importance sampling to reduce variance for Baikal is based on split-kernel architecture to avoid VGPR occupancy bottlenecks and broadly uses GPU-optimized parallel primitives to restructure the work to better fit massively parallel GPU architecture. First, the renderer is designed for progressive preview and has synchronous nature. Meaning it has Render function which is getting called by the user in the loop and every call to this function adds a single sample to each pixel refining the image. This model allows to keep the latency under control and manipulate the scene and the camera while doing rendering. Inside the Render function each OpenCL work item is assigned a single pixel, but as iterations(bounces) progress, less and less rays remain alive, so Render function compacts the work to minimize GPU thread divergence. -Each call to Render function results in the following sequence of kernel calls: - -* Spawn primary rays into ray buffer -* Trace ray buffer -* Apply potential volumetric scattering events (some ray misses might become hits here) -* Compact sparse hits buffer -* Evaluate volume material -* Evaluate surface material and generate light samples and shadow rays -* Trace shadow rays and add contributing light samples -* Sample surface and generate extension rays into rays buffer -* Go to step 2 (if bounces limits is not reached) +![Image](https://github.com/GPUOpen-LibrariesAndSDKs/RadeonProRender-Baikal/blob/master/Doc/Images/4.png) ## Performance In terms of latency the renderer is capable of maintaining high FPS while doing progressive rendering for moderately sized scenes. For example on the following “Science Fiction†scene (775K triangles) Baikal is producing 15 FPS in full HD resolution on R9 Nano card. @@ -134,135 +315,4 @@ We provide an implementation of RPR API with Baikal, which is still in an early * Post-processing * Analytic sky system -# Instructions & requirements -## System requirements -The renderer is cross-platform and the following compilers are supported: - -- Visual Studio 2015 and later - -- Xcode 4 and later - -- GCC 4.8 and later - -The following packages are required to build the renderer: - -- Python (for --embed_kernels option only) - -- AMD OpenCL APP SDK 2.0+ is also required for the standalone app build. - -## Build - -### Windows -- Create Visual Studio 2015 Solution - -`./Tools/premake/win/premake5.exe vs2015` - -### OSX -- Install Homebrew - -`/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"` - -- Install OpenImageIO - -`brew install homebrew/science/openimageio` - -- Create Xcode project - -`./Tools/premake/osx/premake5 xcode4` - -- Alternatively use gmake version - -`./Tools/premake/osx/premake5 gmake` - -`make config=release_x64` - -### Linux -on Ubuntu: -install complementary libraries: - -`sudo apt-get install g++` - -install build dependencies: - -`sudo apt-get install libopenimageio-dev libglew-dev libglfw3-dev` - -Also make sure you have the `opencl-dev` headers installed. Then create the Makefile: - -`./Tools/premake/linux64/premake5 gmake` - -`make config=release_x64` - -### Options -Available premake options: - - `--denoiser` enable simple bilateral denoiser in interactive output: - `./Tools/premake/win/premake5.exe --package` - -- `--rpr` will generate RadeonProRender API implemenatiton C-library and couple of RPR tutorials. - -## Run - -## Run Baikal standalone app - - `export LD_LIBRARY_PATH=/Radeon Rays/lib/x64/:${LD_LIBRARY_PATH}` - - `cd Baikal` - - `../Bin/Release/x64/Baikal64` - -Possible command line args: - -- `-p path` path to mesh/material files -- `-f file` mesh file to render -- `-w` set window width -- `-h` set window height -- `-ns num` limit the number of samples per pixel -- `-cs speed` set camera movement speed -- `-cpx x -cpy y -cpz z` set camera position -- `-tpx x -tpy y -tpz z` set camera target -- `-interop [0|1]` disable | enable OpenGL interop (enabled by default, might be broken on some Linux systems) -- `-config [gpu|cpu|mgpu|mcpu|all]` set device configuration to run on: single gpu (default) | single cpu | all available gpus | all available cpus | all devices - -The app only supports loading of pure triangle .obj meshes. The list of supported texture formats: - -- png -- bmp -- jpg -- gif -- exr -- hdr -- tx -- dds (limited support) -- tga - - -# Hardware support - -The renderer has been tested on the following hardware and OSes: - -## Linux - - Ubuntu Linux 14.04 - - AMD FirePro driver 15.201: W9100, W8100, W9000, W7000, W7100, S9300x2, W5100 - - AMD Radeon driver 15.302: R9 Nano, R9 Fury X, R9 290 - - NVIDIA driver 352.79: GeForce GTX970, Titan X - -## Windows - - Windows 7/8.1/10 - - AMD FirePro driver 15.201: W9100, W8100, W9000, W7000, W7100, S9300x2, W5100 - - AMD Radeon driver 16.4: R9 Nano, R9 Fury X, R9 290, Pro Duo - - NVIDIA driver 364.72: GeForce GTX970, Titan X - -## OSX - - OSX El Capitan 10.11.4 - - Mac Pro (Late 2013) AMD FirePro D500 x2 - - Macbook Pro Retina 13" (Early 2013) Intel HD 4300 - - Macbook 12" (Early 2015) Intel HD 5300 - ---- -# Known Issues -## Linux - - - If is missing try to specify OpenCL SDK location. - - If your are experiencing problems creating your CL context with a default config chances are CL-GL interop is broken on your system, try running the sample app with -interop 0 command line option (expect performance drop). - -AMD: -`export $AMDAPPSDKROOT=` -NVIDIA: -`export $CUDA_PATH=` diff --git a/RadeonRays b/RadeonRays index 41c391f2..cecd0c45 160000 --- a/RadeonRays +++ b/RadeonRays @@ -1 +1 @@ -Subproject commit 41c391f294151cc2207c12b3900e5c2630360937 +Subproject commit cecd0c452987457adff0d3be8cf4ed347e754364 diff --git a/RadeonRaysPremakeAdapter/CLW.lua b/RadeonRaysPremakeAdapter/CLW.lua deleted file mode 100644 index 2b1e7af5..00000000 --- a/RadeonRaysPremakeAdapter/CLW.lua +++ /dev/null @@ -1,30 +0,0 @@ -project "CLW" - kind "StaticLib" - location "../RadeonRays/CLW" - includedirs { "../RadeonRays/CLW", "../RadeonRays" } - files { "../RadeonRays/CLW/**.h", "../RadeonRays/CLW/**.cpp", "../RadeonRays/CLW/CL/CLW.cl" } - - if os.is("macosx") then - buildoptions "-std=c++11 -stdlib=libc++" - else if os.is("linux") then - buildoptions "-std=c++11 -fPIC" - os.execute("rm -rf obj"); - end - end - - configuration {} - - defines {"RR_EMBED_KERNELS=1"} - os.execute( "python ../Tools/scripts/stringify.py " .. - os.getcwd() .. "/../RadeonRays/CLW/CL/ " .. - ".cl " .. - "opencl " .. - "> ../RadeonRays/CLW/kernelcache/clwkernels_cl.h" - ) - print ">> CLW: CL kernels embedded" - - configuration {"x64", "Debug"} - targetdir "../Bin/Debug/x64" - configuration {"x64", "Release"} - targetdir "../Bin/Release/x64" - configuration {} diff --git a/RadeonRaysPremakeAdapter/Calc.lua b/RadeonRaysPremakeAdapter/Calc.lua deleted file mode 100644 index 0224129d..00000000 --- a/RadeonRaysPremakeAdapter/Calc.lua +++ /dev/null @@ -1,38 +0,0 @@ -project "Calc" - if not _OPTIONS["shared_calc"] then - kind "StaticLib" - defines {"CALC_STATIC_LIBRARY"} - - if os.is("linux") then - buildoptions "-std=c++11 -fPIC" - os.execute("rm -rf obj") - elseif os.is("macosx") then - buildoptions "-std=c++11 -stdlib=libc++" - end - else - kind "SharedLib" - defines {"CALC_EXPORT_API"} - - if os.is("linux") then - linkoptions {"-Wl,--no-undefined"} - buildoptions "-std=c++11 -fPIC" - os.execute("rm -rf obj") - elseif os.is("macosx") then - buildoptions "-std=c++11 -stdlib=libc++" - filter { "kind:SharedLib", "system:macosx" } - linkoptions { '-Wl,-install_name', '-Wl,@loader_path/%{cfg.linktarget.name}' } - end - - end - - location "../RadeonRays/Calc" - includedirs { "../RadeonRays/Calc", "../RadeonRays/Calc/inc", "../RadeonRays/CLW" } - files { "../RadeonRays/Calc/**.h", "../RadeonRays/Calc/**.cpp"} - - links {"CLW"} - - configuration {"x64", "Debug"} - targetdir "../Bin/Debug/x64" - configuration {"x64", "Release"} - targetdir "../Bin/Release/x64" - configuration {} diff --git a/RadeonRaysPremakeAdapter/RadeonRays.lua b/RadeonRaysPremakeAdapter/RadeonRays.lua deleted file mode 100644 index e204c65c..00000000 --- a/RadeonRaysPremakeAdapter/RadeonRays.lua +++ /dev/null @@ -1,94 +0,0 @@ -project "RadeonRays" - if( _OPTIONS["static_library"]) then - kind "StaticLib" - else - kind "SharedLib" - end - - location "../RadeonRays/RadeonRays" - includedirs { "../RadeonRays", "../RadeonRays/RadeonRays/include", "../RadeonRays/RadeonRays/src", "../RadeonRays/Calc/inc" } - - if _OPTIONS["shared_calc"] then - defines {"CALC_IMPORT_API"}; - links {"dl"} - else - defines {"CALC_STATIC_LIBRARY"} - links {"Calc"} - links {"CLW"} - end - - defines {"EXPORT_API"} - - files { "../RadeonRays/RadeonRays/**.h", "../RadeonRays/RadeonRays/**.cpp","../RadeonRays/RadeonRays/src/kernels/CL/**.cl", "../RadeonRays/RadeonRays/src/kernels/GLSL/**.comp"} - - excludes {"../RadeonRays/RadeonRays/src/device/embree*"} - - if os.is("macosx") then - buildoptions "-std=c++11 -stdlib=libc++" - filter { "kind:SharedLib", "system:macosx" } - linkoptions { '-Wl,-install_name', '-Wl,@loader_path/%{cfg.linktarget.name}' } - elseif os.is("linux") then - buildoptions "-std=c++11 -fPIC" - linkoptions {"-Wl,--no-undefined"} - - --get API version from header. - local handle = io.popen("grep -r RADEONRAYS_API_VERSION ../RadeonRays/include/radeon_rays.h | cut -d \" \" -f 3") - local lib_version = (handle:read("*a")):gsub("\n", "") - handle:close() - - --specify soname for linker - configuration {"x64", "Debug"} - linkoptions {"-Wl,-soname,libRadeonRays64D.so." .. lib_version} - configuration {"x64", "Release"} - linkoptions {"-Wl,-soname,libRadeonRays64.so." .. lib_version} - configuration{} - - --replacing lib by soft link - postbuildcommands {"mv $(TARGET) $(TARGET)." .. lib_version} - postbuildcommands {"ln -s `basename $(TARGET)." .. lib_version .. "` $(TARGET)"} - end - - configuration {} - - defines {"RR_EMBED_KERNELS=1"} - - - os.execute( "python ../Tools/scripts/stringify.py " .. - os.getcwd() .. "/../RadeonRays/RadeonRays/src/kernels/CL/ " .. - ".cl " .. - "opencl " .. - "> ../RadeonRays/RadeonRays/src/kernelcache/kernels_cl.h" - ) - print ">> RadeonRays: CL kernels embedded" - - if _OPTIONS["use_embree"] then - files {"../RadeonRays/src/device/embree*"} - defines {"USE_EMBREE=1"} - includedirs {"../3rdParty/embree/include"} - - configuration {"x32"} - libdirs { "../3rdParty/embree/lib/x86"} - configuration {"x64"} - libdirs { "../3rdParty/embree/lib/x64"} - configuration {} - - if os.is("macosx") then - links {"embree.2"} - elseif os.is("linux") then - buildoptions {"-msse3"} - links {"embree"} - elseif os.is("windows") then - links {"embree"} - end - end - - if _OPTIONS["enable_raymask"] then - configuration {} - defines {"RR_RAY_MASK"} - end - - configuration {"x64", "Debug"} - targetdir "../Bin/Debug/x64" - configuration {"x64", "Release"} - targetdir "../Bin/Release/x64" - configuration {} diff --git a/Resources/Textures/AreaMap33.dds b/Resources/Textures/AreaMap33.dds new file mode 100644 index 00000000..c1fd4ead Binary files /dev/null and b/Resources/Textures/AreaMap33.dds differ diff --git a/Resources/Textures/sky.hdr b/Resources/Textures/sky.hdr new file mode 100644 index 00000000..45de50cf Binary files /dev/null and b/Resources/Textures/sky.hdr differ diff --git a/Resources/Textures/studio015.hdr b/Resources/Textures/studio015.hdr old mode 100644 new mode 100755 diff --git a/Resources/Textures/test_albedo1.jpg b/Resources/Textures/test_albedo1.jpg new file mode 100644 index 00000000..cb487b08 Binary files /dev/null and b/Resources/Textures/test_albedo1.jpg differ diff --git a/Resources/Textures/test_albedo2.jpg b/Resources/Textures/test_albedo2.jpg new file mode 100644 index 00000000..6ebb3939 Binary files /dev/null and b/Resources/Textures/test_albedo2.jpg differ diff --git a/Resources/Textures/test_albedo3.jpg b/Resources/Textures/test_albedo3.jpg new file mode 100644 index 00000000..5d0f65b2 Binary files /dev/null and b/Resources/Textures/test_albedo3.jpg differ diff --git a/Resources/Textures/test_bump.jpg b/Resources/Textures/test_bump.jpg new file mode 100644 index 00000000..f86cd1b7 Binary files /dev/null and b/Resources/Textures/test_bump.jpg differ diff --git a/Resources/Textures/test_normal.jpg b/Resources/Textures/test_normal.jpg new file mode 100644 index 00000000..cb3626c1 Binary files /dev/null and b/Resources/Textures/test_normal.jpg differ diff --git a/Rpr/CMakeLists.txt b/Rpr/CMakeLists.txt new file mode 100644 index 00000000..9d6fe93c --- /dev/null +++ b/Rpr/CMakeLists.txt @@ -0,0 +1,62 @@ +set(SOURCES + Export.cpp + Export.h + RadeonProRender.cpp + RadeonProRender.h + RadeonProRender_CL.h + RadeonProRender_GL.h + Wrap.cpp) + +set(WRAP_OBJECT_SOURCES + WrapObject/CameraObject.cpp + WrapObject/CameraObject.h + WrapObject/ContextObject.cpp + WrapObject/ContextObject.h + WrapObject/Exception.h + WrapObject/FramebufferObject.cpp + WrapObject/FramebufferObject.h + WrapObject/LightObject.cpp + WrapObject/LightObject.h + WrapObject/Materials/ArithmeticMaterialObject.cpp + WrapObject/Materials/ArithmeticMaterialObject.h + WrapObject/Materials/ImageMaterialObject.cpp + WrapObject/Materials/ImageMaterialObject.h + WrapObject/Materials/MaterialObject.cpp + WrapObject/Materials/MaterialObject.h + WrapObject/Materials/TextureMaterialObject.cpp + WrapObject/Materials/TextureMaterialObject.h + WrapObject/Materials/UberMaterialObject.cpp + WrapObject/Materials/UberMaterialObject.h + WrapObject/Materials/UnsupportedMaterialObject.cpp + WrapObject/Materials/UnsupportedMaterialObject.h + WrapObject/MatSysObject.cpp + WrapObject/MatSysObject.h + WrapObject/SceneObject.cpp + WrapObject/SceneObject.h + WrapObject/ShapeObject.cpp + WrapObject/ShapeObject.h + WrapObject/WrapObject.h) + +set(UTILS_SOURCES + Utils/config_manager.cpp + Utils/config_manager.h +) + +source_group("WrapObject" FILES ${WRAP_OBJECT_SOURCES}) +source_group("Utils" FILES ${UTILS_SOURCES}) + +list(APPEND SOURCES ${WRAP_OBJECT_SOURCES} ${UTILS_SOURCES}) + +add_library(RadeonProRender64 SHARED ${SOURCES}) +target_compile_definitions(RadeonProRender64 PRIVATE RPR_EXPORT_API) +target_compile_features(RadeonProRender64 PRIVATE cxx_std_14) +target_include_directories(RadeonProRender64 PUBLIC ${Baikal_SOURCE_DIR}/Rpr) +target_link_libraries(RadeonProRender64 PUBLIC Baikal BaikalIO OpenGL::GL GLEW::GLEW) + +# Install target +if (WIN32) + target_compile_options(RadeonProRender64 PUBLIC /wd4251) + install(TARGETS RadeonProRender64 RUNTIME DESTINATION bin) +else () + install(TARGETS RadeonProRender64 LIBRARY DESTINATION lib) +endif () diff --git a/Rpr/Export.cpp b/Rpr/Export.cpp new file mode 100644 index 00000000..7447c106 --- /dev/null +++ b/Rpr/Export.cpp @@ -0,0 +1,36 @@ +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ + +//methods to export baikal classes from RPR wrap + +#include "RadeonProRender.h" +#include "SceneGraph/scene1.h" + +#include "WrapObject/SceneObject.h" + +Baikal::Scene1::Ptr ExportFromRpr(rpr_scene scene) +{ + SceneObject* scene_obj = WrapObject::Cast(scene); + + return scene_obj ? scene_obj->GetScene() : nullptr; +} + diff --git a/Rpr/Export.h b/Rpr/Export.h new file mode 100644 index 00000000..47024089 --- /dev/null +++ b/Rpr/Export.h @@ -0,0 +1,28 @@ +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ +#pragma once + + +#include "RadeonProRender.h" +#include "SceneGraph/scene1.h" + +Baikal::Scene1::Ptr ExportFromRpr(rpr_scene scene); diff --git a/Rpr/RadeonProRender.cpp b/Rpr/RadeonProRender.cpp index 21087850..cd1e616a 100644 --- a/Rpr/RadeonProRender.cpp +++ b/Rpr/RadeonProRender.cpp @@ -25,7 +25,7 @@ THE SOFTWARE. #include "WrapObject/CameraObject.h" #include "WrapObject/FramebufferObject.h" #include "WrapObject/LightObject.h" -#include "WrapObject/MaterialObject.h" +#include "WrapObject/Materials/MaterialObject.h" #include "WrapObject/MatSysObject.h" #include "WrapObject/SceneObject.h" #include "WrapObject/ShapeObject.h" @@ -35,18 +35,57 @@ THE SOFTWARE. #include "math/matrix.h" #include "math/mathutils.h" -//defines behaviour for unimplemented API part +//defines behavior for unimplemented API part //#define UNIMLEMENTED_FUNCTION return RPR_SUCCESS; #define UNIMLEMENTED_FUNCTION return RPR_ERROR_UNIMPLEMENTED; #define UNSUPPORTED_FUNCTION return RPR_SUCCESS; //#define UNSUPPORTED_FUNCTION return RPR_ERROR_UNSUPPORTED; -rpr_int rprRegisterPlugin(rpr_char const * path) +static const std::map kRPRInputStrings = +{ + { RPR_UBER_MATERIAL_DIFFUSE_COLOR, "uberv2.diffuse.color" }, + { RPR_UBER_MATERIAL_LAYERS, "uberv2.layers" }, + { RPR_UBER_MATERIAL_REFLECTION_COLOR, "uberv2.reflection.color" }, + { RPR_UBER_MATERIAL_REFLECTION_ROUGHNESS, "uberv2.reflection.roughness" }, + { RPR_UBER_MATERIAL_REFLECTION_ANISOTROPY, "uberv2.reflection.anisotropy" }, + { RPR_UBER_MATERIAL_REFLECTION_ANISOTROPY_ROTATION, "uberv2.reflection.anisotropy_rotation" }, + { RPR_UBER_MATERIAL_REFLECTION_IOR, "uberv2.reflection.ior" }, + { RPR_UBER_MATERIAL_REFLECTION_METALNESS, "uberv2.reflection.metalness" }, + { RPR_UBER_MATERIAL_REFRACTION_COLOR, "uberv2.refraction.color" }, + { RPR_UBER_MATERIAL_REFRACTION_ROUGHNESS, "uberv2.refraction.roughness" }, + { RPR_UBER_MATERIAL_REFRACTION_IOR, "uberv2.refraction.ior" }, + { RPR_UBER_MATERIAL_REFRACTION_IOR_MODE, "uberv2.refraction.ior_mode" }, + { RPR_UBER_MATERIAL_REFRACTION_THIN_SURFACE, "uberv2.refraction.thin_surface" }, + { RPR_UBER_MATERIAL_COATING_COLOR, "uberv2.coating.color" }, + { RPR_UBER_MATERIAL_COATING_IOR, "uberv2.coating.ior" }, + { RPR_UBER_MATERIAL_EMISSION_COLOR, "uberv2.emission.color" }, + { RPR_UBER_MATERIAL_EMISSION_WEIGHT, "uberv2.emission.weight" }, + { RPR_UBER_MATERIAL_EMISSION_MODE, "uberv2.emission.mode" }, + { RPR_UBER_MATERIAL_TRANSPARENCY, "uberv2.transparency" }, + { RPR_UBER_MATERIAL_NORMAL, "uberv2.normal" }, + { RPR_UBER_MATERIAL_BUMP, "uberv2.bump" }, + { RPR_UBER_MATERIAL_DISPLACEMENT, "uberv2.displacement" }, + { RPR_UBER_MATERIAL_SSS_ABSORPTION_COLOR, "uberv2.sss.absorption_color" }, + { RPR_UBER_MATERIAL_SSS_SCATTER_COLOR, "uberv2.sss.scatter_color" }, + { RPR_UBER_MATERIAL_SSS_ABSORPTION_DISTANCE, "uberv2.sss.absorption_distance" }, + { RPR_UBER_MATERIAL_SSS_SCATTER_DISTANCE, "uberv2.sss.scatter_distance" }, + { RPR_UBER_MATERIAL_SSS_SCATTER_DIRECTION, "uberv2.sss.scatter_direction" }, + { RPR_UBER_MATERIAL_SSS_SUBSURFACE_COLOR, "uberv2.sss.subsurface_color" }, + { RPR_UBER_MATERIAL_SSS_MULTISCATTER, "uberv2.sss.multiscatter" } +}; + +rpr_int rprLightSetGroupId(rpr_light light, rpr_uint groupId) { UNIMLEMENTED_FUNCTION } + +rpr_int rprRegisterPlugin(rpr_char const * path) +{ + UNSUPPORTED_FUNCTION +} + rpr_int rprCreateContext(rpr_int api_version, rpr_int * pluginIDs, size_t pluginCount, rpr_creation_flags creation_flags, rpr_context_properties const * props, rpr_char const * cache_path, rpr_context * out_context) { if (api_version != RPR_API_VERSION) @@ -69,7 +108,7 @@ rpr_int rprCreateContext(rpr_int api_version, rpr_int * pluginIDs, size_t plugin rpr_int rprContextSetActivePlugin(rpr_context context, rpr_int pluginID) { - UNIMLEMENTED_FUNCTION + UNSUPPORTED_FUNCTION } rpr_int rprContextGetInfo(rpr_context in_context, rpr_context_info in_context_info, size_t in_size, void * out_data, size_t * out_size_ret) @@ -205,22 +244,13 @@ rpr_int rprContextSetParameter1u(rpr_context in_context, rpr_char const * name, return RPR_ERROR_INVALID_CONTEXT; } - //TODO: handle context parameters - return RPR_SUCCESS; - - if (!strcmp(name, "rendermode")) + try { - switch (x) - { - case RPR_RENDER_MODE_GLOBAL_ILLUMINATION: - break; - default: - UNIMLEMENTED_FUNCTION - } + context->SetParameter(name, x); } - else + catch (Exception& e) { - UNIMLEMENTED_FUNCTION + return e.m_error; } return RPR_SUCCESS; @@ -354,7 +384,7 @@ rpr_int rprContextCreateImage(rpr_context in_context, rpr_image_format const in_ rpr_int result = RPR_SUCCESS; try { - *out_image = context->CreateTexture(in_format, in_image_desc, in_data); + *out_image = context->CreateImage(in_format, in_image_desc, in_data); } catch (Exception& e) { @@ -364,6 +394,12 @@ rpr_int rprContextCreateImage(rpr_context in_context, rpr_image_format const in_ return result; } +rpr_int rprContextCreateBuffer(rpr_context context, rpr_buffer_desc const * buffer_desc, void const * data, rpr_buffer * out_buffer) +{ + UNIMLEMENTED_FUNCTION +} + + rpr_int rprContextCreateImageFromFile(rpr_context in_context, rpr_char const * in_path, rpr_image * out_image) { //cast data @@ -375,7 +411,7 @@ rpr_int rprContextCreateImageFromFile(rpr_context in_context, rpr_char const * i rpr_int result = RPR_SUCCESS; try { - *out_image = context->CreateTextureFromFile(in_path); + *out_image = context->CreateImageFromFile(in_path); } catch (Exception& e) { @@ -472,15 +508,13 @@ rpr_int rprContextCreateMesh(rpr_context in_context, } rpr_int rprContextCreateMeshEx(rpr_context context, - rpr_float const * vertices, size_t num_vertices, rpr_int vertex_stride, - rpr_float const * normals, size_t num_normals, rpr_int normal_stride, - rpr_int const * perVertexFlag, size_t num_perVertexFlags, rpr_int perVertexFlag_stride, - rpr_int numberOfTexCoordLayers, - rpr_float const ** texcoords, size_t * num_texcoords, rpr_int * texcoord_stride, - rpr_int const * vertex_indices, rpr_int vidx_stride, - rpr_int const * normal_indices, rpr_int nidx_stride, - rpr_int const ** texcoord_indices, rpr_int * tidx_stride, - rpr_int const * num_face_vertices, size_t num_faces, rpr_shape * out_mesh) + rpr_float const * vertices, size_t num_vertices, rpr_int vertex_stride, + rpr_float const * normals, size_t num_normals, rpr_int normal_stride, + rpr_int const * perVertexFlag, size_t num_perVertexFlags, rpr_int perVertexFlag_stride, rpr_int numberOfTexCoordLayers, + rpr_float const ** texcoords, size_t const * num_texcoords, rpr_int const * texcoord_stride, + rpr_int const * vertex_indices, rpr_int vidx_stride, rpr_int const * normal_indices, rpr_int nidx_stride, + rpr_int const ** texcoord_indices, rpr_int const * tidx_stride, + rpr_int const * num_face_vertices, size_t num_faces, rpr_shape * out_mesh) { if (num_perVertexFlags == 0 && numberOfTexCoordLayers == 1) { @@ -497,6 +531,27 @@ rpr_int rprContextCreateMeshEx(rpr_context context, UNIMLEMENTED_FUNCTION } +rpr_int rprContextCreateMeshEx2(rpr_context context, + rpr_float const * vertices, size_t num_vertices, rpr_int vertex_stride, + rpr_float const * normals, size_t num_normals, rpr_int normal_stride, + rpr_int const * perVertexFlag, size_t num_perVertexFlags, rpr_int perVertexFlag_stride, rpr_int numberOfTexCoordLayers, + rpr_float const ** texcoords, size_t const * num_texcoords, rpr_int const * texcoord_stride, + rpr_int const * vertex_indices, rpr_int vidx_stride, rpr_int const * normal_indices, rpr_int nidx_stride, + rpr_int const ** texcoord_indices, rpr_int const * tidx_stride, + rpr_int const * num_face_vertices, size_t num_faces, + rpr_mesh_info const * mesh_properties, rpr_shape * out_mesh) +{ + return rprContextCreateMeshEx(context, + vertices, num_vertices, vertex_stride, + normals, num_normals, normal_stride, + perVertexFlag, num_perVertexFlags, perVertexFlag_stride, numberOfTexCoordLayers, + texcoords, num_texcoords, texcoord_stride, + vertex_indices, vidx_stride, normal_indices, nidx_stride, + texcoord_indices, tidx_stride, + num_face_vertices, num_faces, + out_mesh); +} + rpr_int rprContextCreateCamera(rpr_context in_context, rpr_camera * out_camera) { //cast data @@ -541,6 +596,30 @@ rpr_int rprContextCreateFrameBuffer(rpr_context in_context, rpr_framebuffer_form return RPR_SUCCESS; } +rpr_int rprContextCreateFramebufferFromGLTexture2D(rpr_context in_context, rpr_GLenum target, rpr_GLint miplevel, rpr_GLuint texture, rpr_framebuffer * out_fb) +{ + //cast data + ContextObject* context = WrapObject::Cast(in_context); + if (!context) + { + return RPR_ERROR_INVALID_CONTEXT; + } + + rpr_int result = RPR_SUCCESS; + try + { + *out_fb = context->CreateFrameBufferFromGLTexture(target, miplevel, texture); + } + catch (Exception& e) + { + result = e.m_error; + } + return result; + + return RPR_SUCCESS; +} + + rpr_int rprCameraGetInfo(rpr_camera in_camera, rpr_camera_info in_camera_info, size_t in_size, void * out_data, size_t * out_size_ret) { CameraObject* cam = WrapObject::Cast(in_camera); @@ -580,7 +659,7 @@ rpr_int rprCameraGetInfo(rpr_camera in_camera, rpr_camera_info in_camera_info, s case RPR_CAMERA_MODE: { //TODO: only prespective camera supported now - rpr_camera_mode value = RPR_CAMERA_MODE_PERSPECTIVE; + rpr_camera_mode value = cam->GetMode(); size_ret = sizeof(value); data.resize(size_ret); memcpy(&data[0], &value, size_ret); @@ -636,14 +715,27 @@ rpr_int rprCameraGetInfo(rpr_camera in_camera, rpr_camera_info in_camera_info, s memcpy(&data[0], name.c_str(), size_ret); break; } + case RPR_CAMERA_ORTHO_WIDTH: + { + rpr_float value = cam->GetOrthoWidth(); + size_ret = sizeof(value); + data.resize(size_ret); + memcpy(&data[0], &value, size_ret); + break; + } + case RPR_CAMERA_ORTHO_HEIGHT: + { + rpr_float value = cam->GetOrthoHeight(); + size_ret = sizeof(value); + data.resize(size_ret); + memcpy(&data[0], &value, size_ret); + break; + } case RPR_CAMERA_APERTURE_BLADES: case RPR_CAMERA_EXPOSURE: - case RPR_CAMERA_ORTHO_WIDTH: case RPR_CAMERA_FOCAL_TILT: case RPR_CAMERA_IPD: case RPR_CAMERA_LENS_SHIFT: - case RPR_CAMERA_ORTHO_HEIGHT: - UNSUPPORTED_FUNCTION break; default: @@ -692,24 +784,24 @@ rpr_int rprCameraSetFocusDistance(rpr_camera in_camera, rpr_float fdist) rpr_int rprCameraSetTransform(rpr_camera in_camera, rpr_bool transpose, rpr_float * transform) { - //cast data - CameraObject* camera = WrapObject::Cast(in_camera); - if (!camera) - { - return RPR_ERROR_INVALID_PARAMETER; - } + //cast data + CameraObject* camera = WrapObject::Cast(in_camera); + if (!camera) + { + return RPR_ERROR_INVALID_PARAMETER; + } - RadeonRays::matrix m; - //fill matrix - memcpy(m.m, transform, 16 * sizeof(rpr_float)); + RadeonRays::matrix m; + //fill matrix + memcpy(m.m, transform, 16 * sizeof(rpr_float)); - if (!transpose) - { - m = m.transpose(); - } + if (!transpose) + { + m = m.transpose(); + } - camera->SetTransform(m); - return RPR_SUCCESS; + camera->SetTransform(m); + return RPR_SUCCESS; } rpr_int rprCameraSetSensorSize(rpr_camera in_camera, rpr_float in_width, rpr_float in_height) @@ -784,6 +876,8 @@ rpr_int rprCameraSetMode(rpr_camera in_camera, rpr_camera_mode mode) switch (mode) { case RPR_CAMERA_MODE_PERSPECTIVE: + case RPR_CAMERA_MODE_ORTHOGRAPHIC: + camera->SetMode(mode); break; default: UNIMLEMENTED_FUNCTION @@ -792,9 +886,16 @@ rpr_int rprCameraSetMode(rpr_camera in_camera, rpr_camera_mode mode) return RPR_SUCCESS; } -rpr_int rprCameraSetOrthoWidth(rpr_camera camera, rpr_float width) +rpr_int rprCameraSetOrthoWidth(rpr_camera in_camera, rpr_float width) { - UNSUPPORTED_FUNCTION + CameraObject* camera = WrapObject::Cast(in_camera); + if (!camera) + { + return RPR_ERROR_INVALID_PARAMETER; + } + + camera->SetOrthoWidth(width); + return RPR_SUCCESS; } rpr_int rprCameraSetFocalTilt(rpr_camera camera, rpr_float tilt) @@ -812,11 +913,35 @@ rpr_int rprCameraSetLensShift(rpr_camera camera, rpr_float shiftx, rpr_float shi UNSUPPORTED_FUNCTION } -rpr_int rprCameraSetOrthoHeight(rpr_camera camera, rpr_float height) +rpr_int rprCameraSetTiltCorrection(rpr_camera camera, rpr_float tiltX, rpr_float tiltY) +{ + UNSUPPORTED_FUNCTION +} + +rpr_int rprCameraSetFarPlane(rpr_camera camera, rpr_float far) +{ + UNSUPPORTED_FUNCTION +} + + +rpr_int rprCameraSetNearPlane(rpr_camera camera, rpr_float near) { UNSUPPORTED_FUNCTION } +rpr_int rprCameraSetOrthoHeight(rpr_camera in_camera, rpr_float height) +{ + CameraObject* camera = WrapObject::Cast(in_camera); + if (!camera) + { + return RPR_ERROR_INVALID_PARAMETER; + } + + camera->SetOrthoHeight(height); + return RPR_SUCCESS; + +} + rpr_int rprImageGetInfo(rpr_image in_image, rpr_image_info in_image_info, size_t in_size, void * in_data, size_t * in_size_ret) { MaterialObject* img = WrapObject::Cast(in_image); @@ -832,7 +957,7 @@ rpr_int rprImageGetInfo(rpr_image in_image, rpr_image_info in_image_info, size_t case RPR_IMAGE_FORMAT: { //texture data always stored as 4 component FLOAT32 - rpr_image_format value = img->GetTextureFormat(); + rpr_image_format value = img->GetImageFormat(); size_ret = sizeof(value); data.resize(size_ret); memcpy(&data[0], &value, size_ret); @@ -840,7 +965,7 @@ rpr_int rprImageGetInfo(rpr_image in_image, rpr_image_info in_image_info, size_t } case RPR_IMAGE_DESC: { - rpr_image_desc value = img->GetTextureDesc(); + rpr_image_desc value = img->GetImageDesc(); size_ret = sizeof(value); data.resize(size_ret); memcpy(&data[0], &value, size_ret); @@ -848,8 +973,8 @@ rpr_int rprImageGetInfo(rpr_image in_image, rpr_image_info in_image_info, size_t } case RPR_IMAGE_DATA: { - rpr_image_desc desc = img->GetTextureDesc(); - const char* value = img->GetTextureData(); + rpr_image_desc desc = img->GetImageDesc(); + const char* value = img->GetImageData(); size_ret = desc.image_width * desc.image_height * desc.image_depth; data.resize(size_ret); memcpy(&data[0], value, size_ret); @@ -905,6 +1030,12 @@ rpr_int rprShapeSetTransform(rpr_shape in_shape, rpr_bool transpose, rpr_float c m = m.transpose(); } + RadeonRays::matrix rtol(-1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + m = rtol * m; + shape->SetTransform(m); return RPR_SUCCESS; } @@ -930,10 +1061,29 @@ rpr_int rprShapeSetDisplacementScale(rpr_shape shape, rpr_float minscale, rpr_fl } rpr_int rprShapeSetObjectGroupID(rpr_shape shape, rpr_uint objectGroupID) +{ + //cast data + ShapeObject* mesh = WrapObject::Cast(shape); + if (!shape) + { + return RPR_ERROR_INVALID_PARAMETER; + } + + mesh->GetShape()->SetGroupId(objectGroupID); + return RPR_SUCCESS; +} + +rpr_int rprShapeSetDisplacementMaterial(rpr_shape shape, rpr_material_node materialNode) { UNSUPPORTED_FUNCTION } +rpr_int rprShapeSetMaterialFaces(rpr_shape shape, rpr_material_node node, rpr_int* face_indices, size_t num_faces) +{ + UNSUPPORTED_FUNCTION +} + + rpr_int rprShapeSetDisplacementImage(rpr_shape shape, rpr_image image) { UNSUPPORTED_FUNCTION @@ -982,6 +1132,12 @@ rpr_int rprShapeSetAngularMotion(rpr_shape shape, rpr_float x, rpr_float y, rpr_ UNSUPPORTED_FUNCTION } +rpr_int rprShapeSetScaleMotion(rpr_shape shape, rpr_float x, rpr_float y, rpr_float z) +{ + UNSUPPORTED_FUNCTION +} + + rpr_int rprShapeSetVisibility(rpr_shape shape, rpr_bool visible) { UNSUPPORTED_FUNCTION @@ -1021,6 +1177,12 @@ rpr_int rprLightSetTransform(rpr_light in_light, rpr_bool in_transpose, rpr_floa m = m.transpose(); } + RadeonRays::matrix rtol(-1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + m = rtol * m; + light->SetTransform(m); return RPR_SUCCESS; @@ -1082,7 +1244,12 @@ rpr_int rprShapeGetInfo(rpr_shape in_shape, rpr_shape_info in_info, size_t in_si case RPR_SHAPE_SUBDIVISION_BOUNDARYINTEROP: case RPR_SHAPE_DISPLACEMENT_SCALE: case RPR_SHAPE_OBJECT_GROUP_ID: - case RPR_SHAPE_DISPLACEMENT_IMAGE: + case RPR_SHAPE_VIDMEM_USAGE: + case RPR_SHAPE_VISIBILITY_PRIMARY_ONLY_FLAG: + case RPR_SHAPE_VISIBILITY_IN_SPECULAR_FLAG: + case RPR_SHAPE_VOLUME_MATERIAL: + case RPR_SHAPE_DISPLACEMENT_MATERIAL: + case RPR_SHAPE_MATERIALS_PER_FACE: UNSUPPORTED_FUNCTION default: UNIMLEMENTED_FUNCTION @@ -1417,6 +1584,16 @@ rpr_int rprEnvironmentLightSetIntensityScale(rpr_light in_env_light, rpr_float i return RPR_SUCCESS; } +rpr_int rprEnvironmentLightAttachPortal(rpr_scene scene, rpr_light env_light, rpr_shape portal) +{ + UNIMLEMENTED_FUNCTION +} + +rpr_int rprEnvironmentLightDetachPortal(rpr_scene scene, rpr_light env_light, rpr_shape portal) +{ + UNIMLEMENTED_FUNCTION +} + rpr_int rprEnvironmentLightAttachPortal(rpr_light env_light, rpr_shape portal) { UNIMLEMENTED_FUNCTION @@ -1447,6 +1624,17 @@ rpr_int rprSkyLightSetScale(rpr_light skylight, rpr_float scale) UNIMLEMENTED_FUNCTION } +rpr_int rprSkyLightAttachPortal(rpr_scene scene, rpr_light skylight, rpr_shape portal) +{ + UNIMLEMENTED_FUNCTION +} + +rpr_int rprSkyLightDetachPortal(rpr_scene scene, rpr_light skylight, rpr_shape portal) +{ + UNIMLEMENTED_FUNCTION +} + + rpr_int rprSkyLightAttachPortal(rpr_light skylight, rpr_shape portal) { UNIMLEMENTED_FUNCTION @@ -1622,6 +1810,16 @@ rpr_int rprSceneDetachShape(rpr_scene in_scene, rpr_shape in_shape) return RPR_SUCCESS; } +rpr_int rprSceneAttachHeteroVolume(rpr_scene scene, rpr_hetero_volume heteroVolume) +{ + UNIMLEMENTED_FUNCTION +} + +rpr_int rprSceneDetachHeteroVolume(rpr_scene scene, rpr_hetero_volume heteroVolume) +{ + UNIMLEMENTED_FUNCTION +} + rpr_int rprSceneAttachLight(rpr_scene in_scene, rpr_light in_light) { //cast @@ -1656,13 +1854,13 @@ rpr_int rprSceneDetachLight(rpr_scene in_scene, rpr_light in_light) rpr_int rprSceneGetInfo(rpr_scene in_scene, rpr_scene_info in_info, size_t in_size, void * out_data, size_t * out_size_ret) { - //cast - SceneObject* scene = WrapObject::Cast(in_scene); - if (!scene) - { - return RPR_ERROR_INVALID_PARAMETER; - } - + //cast + SceneObject* scene = WrapObject::Cast(in_scene); + if (!scene) + { + return RPR_ERROR_INVALID_PARAMETER; + } + std::vector data; size_t size_ret = 0; switch (in_info) @@ -1715,12 +1913,22 @@ rpr_int rprSceneGetInfo(rpr_scene in_scene, rpr_scene_info in_info, size_t in_si memcpy(&data[0], name.c_str(), size_ret); break; } + case RPR_SCENE_AABB: + { + RadeonRays::bbox bb = scene->GetBBox(); + size_ret = 6 * sizeof(float); + data.resize(size_ret); + memcpy(&data[0], &bb.pmin.x, size_ret/2); // copy pmin + memcpy(data.data() + size_ret/2, &bb.pmax.x, size_ret/2); //copy pmax + + break; + } case RPR_SCENE_BACKGROUND_IMAGE: case RPR_SCENE_ENVIRONMENT_OVERRIDE_REFLECTION: case RPR_SCENE_ENVIRONMENT_OVERRIDE_REFRACTION: case RPR_SCENE_ENVIRONMENT_OVERRIDE_TRANSPARENCY: case RPR_SCENE_ENVIRONMENT_OVERRIDE_BACKGROUND: - case RPR_SCENE_AXIS_ALIGNED_BOUNDING_BOX: + UNSUPPORTED_FUNCTION default: UNIMLEMENTED_FUNCTION @@ -1738,24 +1946,122 @@ rpr_int rprSceneGetInfo(rpr_scene in_scene, rpr_scene_info in_info, size_t in_si return RPR_SUCCESS; } -rpr_int rprSceneGetEnvironmentOverride(rpr_scene scene, rpr_environment_override overrride, rpr_light * out_light) +rpr_int rprSceneGetEnvironmentOverride(rpr_scene in_scene, rpr_environment_override overrride, rpr_light * out_light) { - UNSUPPORTED_FUNCTION + SceneObject* scene = WrapObject::Cast(in_scene); + + if (!scene) + { + return RPR_ERROR_INVALID_PARAMETER; + } + + static const std::map override_type_conversion = + { + { RPR_SCENE_ENVIRONMENT_OVERRIDE_BACKGROUND, SceneObject::OverrideType::kBackground }, + { RPR_SCENE_ENVIRONMENT_OVERRIDE_REFLECTION, SceneObject::OverrideType::kReflection }, + { RPR_SCENE_ENVIRONMENT_OVERRIDE_REFRACTION, SceneObject::OverrideType::kRefraction }, + { RPR_SCENE_ENVIRONMENT_OVERRIDE_TRANSPARENCY, SceneObject::OverrideType::kTransparency } + }; + + auto overryde_type = override_type_conversion.find(overrride); + if (overryde_type == override_type_conversion.end()) + return RPR_ERROR_INVALID_PARAMETER; + + try + { + *out_light = scene->GetEnvironmentOverride(overryde_type->second); + } + catch (Exception& e) + { + return e.m_error; + } + + return RPR_SUCCESS; } -rpr_int rprSceneSetEnvironmentOverride(rpr_scene scene, rpr_environment_override overrride, rpr_light light) +rpr_int rprSceneSetEnvironmentOverride(rpr_scene in_scene, rpr_environment_override overrride, rpr_light in_light) { - UNSUPPORTED_FUNCTION + SceneObject* scene = WrapObject::Cast(in_scene); + LightObject* light = WrapObject::Cast(in_light); + + if (!scene) + { + return RPR_ERROR_INVALID_PARAMETER; + } + + static const std::map override_type_conversion = + { + { RPR_SCENE_ENVIRONMENT_OVERRIDE_BACKGROUND, SceneObject::OverrideType::kBackground }, + { RPR_SCENE_ENVIRONMENT_OVERRIDE_REFLECTION, SceneObject::OverrideType::kReflection }, + { RPR_SCENE_ENVIRONMENT_OVERRIDE_REFRACTION, SceneObject::OverrideType::kRefraction }, + { RPR_SCENE_ENVIRONMENT_OVERRIDE_TRANSPARENCY, SceneObject::OverrideType::kTransparency } + }; + + auto override_type = override_type_conversion.find(overrride); + if (override_type == override_type_conversion.end()) + return RPR_ERROR_INVALID_PARAMETER; + + try + { + if ((overrride == RPR_SCENE_ENVIRONMENT_OVERRIDE_BACKGROUND) && light) + { + rprSceneSetBackgroundImage(scene, light->GetEnvTexture()); + } + else + { + scene->SetEnvironmentOverride(override_type->second, light); + } + } + catch (Exception& e) + { + return e.m_error; + } + + return RPR_SUCCESS; } -rpr_int rprSceneSetBackgroundImage(rpr_scene scene, rpr_image image) +rpr_int rprSceneSetBackgroundImage(rpr_scene in_scene, rpr_image in_image) { - UNSUPPORTED_FUNCTION + MaterialObject* img = WrapObject::Cast(in_image); + SceneObject* scene = WrapObject::Cast(in_scene); + if (!scene) + { + return RPR_ERROR_INVALID_PARAMETER; + } + + try + { + if (img) + rprSceneSetEnvironmentOverride(scene, RPR_SCENE_ENVIRONMENT_OVERRIDE_BACKGROUND, nullptr); + scene->SetBackgroundImage(img); + } + catch (Exception& e) + { + return e.m_error; + } + + return RPR_SUCCESS; } -rpr_int rprSceneGetBackgroundImage(rpr_scene scene, rpr_image * out_image) +rpr_int rprSceneGetBackgroundImage(rpr_scene in_scene, rpr_image * out_image) { - UNSUPPORTED_FUNCTION + SceneObject* scene = WrapObject::Cast(in_scene); + + if (!scene || !out_image) + { + return RPR_ERROR_INVALID_PARAMETER; + } + + try + { + *out_image = scene->GetBackgroundImage(); + } + catch (Exception& e) + { + return e.m_error; + } + + return RPR_SUCCESS; } rpr_int rprSceneSetCamera(rpr_scene in_scene, rpr_camera in_camera) @@ -1795,7 +2101,7 @@ rpr_int rprFrameBufferGetInfo(rpr_framebuffer in_frame_buffer, rpr_framebuffer_i { return RPR_ERROR_INVALID_PARAMETER; } - int buff_size = sizeof(RadeonRays::float3) * buff->GetWidth() * buff->GetHeight(); + std::size_t buff_size = sizeof(RadeonRays::float3) * buff->Width() * buff->Height(); switch (in_info) { case RPR_FRAMEBUFFER_DATA: @@ -1872,6 +2178,12 @@ rpr_int rprContextCreateMaterialSystem(rpr_context in_context, rpr_material_syst return RPR_SUCCESS; } +rpr_int rprMaterialSystemGetSize(rpr_context in_context, rpr_uint * out_size) +{ + UNIMLEMENTED_FUNCTION +} + + rpr_int rprMaterialSystemCreateNode(rpr_material_system in_matsys, rpr_material_node_type in_type, rpr_material_node * out_node) { //cast @@ -1906,7 +2218,7 @@ rpr_int rprMaterialNodeSetInputN(rpr_material_node in_node, rpr_char const * in_ try { - mat->SetInputMaterial(in_input, input_node); + mat->SetInputValue(in_input, input_node); } catch (Exception& e) { @@ -1939,7 +2251,22 @@ rpr_int rprMaterialNodeSetInputF(rpr_material_node in_node, rpr_char const * in_ rpr_int rprMaterialNodeSetInputU(rpr_material_node in_node, rpr_char const * in_input, rpr_uint in_value) { - UNIMLEMENTED_FUNCTION + //cast + MaterialObject* mat = WrapObject::Cast(in_node); + if (!mat) + { + return RPR_ERROR_INVALID_PARAMETER; + } + + try + { + mat->SetInputValue(in_input, in_value); + } + catch (Exception& e) + { + return e.m_error; + } + return RPR_SUCCESS; } rpr_int rprMaterialNodeSetInputImageData(rpr_material_node in_node, rpr_char const * in_input, rpr_image in_image) @@ -1954,7 +2281,7 @@ rpr_int rprMaterialNodeSetInputImageData(rpr_material_node in_node, rpr_char con try { - mat->SetInputMaterial(in_input, img); + mat->SetInputValue(in_input, img); } catch (Exception& e) { @@ -1964,6 +2291,12 @@ rpr_int rprMaterialNodeSetInputImageData(rpr_material_node in_node, rpr_char con return RPR_SUCCESS; } +rpr_int rprMaterialNodeSetInputBufferData(rpr_material_node in_node, rpr_char const * in_input, rpr_buffer buffer) +{ + UNIMLEMENTED_FUNCTION +} + + rpr_int rprMaterialNodeGetInfo(rpr_material_node in_node, rpr_material_node_info in_info, size_t in_size, void * out_data, size_t * out_size) { MaterialObject* mat = WrapObject::Cast(in_node); @@ -2065,6 +2398,45 @@ rpr_int rprMaterialNodeGetInputInfo(rpr_material_node in_node, rpr_int in_input_ return RPR_SUCCESS; } +rpr_int rprContextCreateComposite(rpr_context context, rpr_composite_type in_type, rpr_composite * out_composite) +{ + UNIMLEMENTED_FUNCTION +} +rpr_int rprCompositeSetInputFb(rpr_composite composite, const char * inputName, rpr_framebuffer input) +{ + UNIMLEMENTED_FUNCTION +} + +rpr_int rprCompositeSetInputC(rpr_composite composite, const char * inputName, rpr_composite input) +{ + UNIMLEMENTED_FUNCTION +} + +rpr_int rprCompositeSetInput4f(rpr_composite composite, const char * inputName, float x, float y, float z, float w) +{ + UNIMLEMENTED_FUNCTION +} + +rpr_int rprCompositeSetInput1u(rpr_composite composite, const char * inputName, unsigned int value) +{ + UNIMLEMENTED_FUNCTION +} + +rpr_int rprCompositeSetInputOp(rpr_composite composite, const char * inputName, rpr_material_node_arithmetic_operation op) +{ + UNIMLEMENTED_FUNCTION +} + +rpr_int rprCompositeCompute(rpr_composite composite, rpr_framebuffer fb) +{ + UNIMLEMENTED_FUNCTION +} + +rpr_int rprCompositeGetInfo(rpr_composite composite, rpr_composite_info composite_info, size_t size, void * data, size_t * size_ret) +{ + UNIMLEMENTED_FUNCTION +} + rpr_int rprObjectDelete(void * in_obj) { WrapObject* obj = static_cast(in_obj); @@ -2127,3 +2499,118 @@ rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, rpr_char const * nam { UNIMLEMENTED_FUNCTION } + +rpr_int rprContextGetAttachedPostEffectCount(rpr_context context, rpr_uint * nb) +{ + UNIMLEMENTED_FUNCTION +} + +rpr_int rprContextGetAttachedPostEffect(rpr_context context, rpr_uint i, rpr_post_effect * out_effect) +{ + UNIMLEMENTED_FUNCTION +} + +rpr_int rprPostEffectGetInfo(rpr_post_effect effect, rpr_post_effect_info info, size_t size, void * data, size_t * size_ret) +{ + UNIMLEMENTED_FUNCTION +} + +rpr_int rprContextCreateHeteroVolume(rpr_context context, rpr_hetero_volume * out_heteroVolume, size_t gridSizeX, size_t gridSizeY, size_t gridSizeZ, void * indicesList, size_t numberOfIndices, rpr_hetero_volume_indices_topology indicesListTopology, void * gridData, size_t gridDataSizeByte, rpr_uint gridDataTopology___unused) +{ + UNIMLEMENTED_FUNCTION +} +rpr_int rprShapeSetHeteroVolume(rpr_shape shape, rpr_hetero_volume heteroVolume) +{ + UNIMLEMENTED_FUNCTION +} + +rpr_int rprHeteroVolumeSetTransform(rpr_hetero_volume out_heteroVolume, rpr_bool transpose, rpr_float const * transform) +{ + UNIMLEMENTED_FUNCTION +} + +rpr_int rprMaterialNodeSetInputN_ext(rpr_material_node in_node, rpr_material_node_input in_input, rpr_material_node in_input_node) +{ + auto name_it = kRPRInputStrings.find(in_input); + return name_it != kRPRInputStrings.end() ? + rprMaterialNodeSetInputN(in_node, name_it->second.c_str(), in_input_node) + : RPR_ERROR_UNSUPPORTED; +} +rpr_int rprMaterialNodeSetInputF_ext(rpr_material_node in_node, rpr_material_node_input in_input, rpr_float in_value_x, rpr_float in_value_y, rpr_float in_value_z, rpr_float in_value_w) +{ + auto name_it = kRPRInputStrings.find(in_input); + return name_it != kRPRInputStrings.end() ? + rprMaterialNodeSetInputF(in_node, name_it->second.c_str(), in_value_x, in_value_y, in_value_z, in_value_w) + : RPR_ERROR_UNSUPPORTED; +} +rpr_int rprMaterialNodeSetInputU_ext(rpr_material_node in_node, rpr_material_node_input in_input, rpr_uint in_value) +{ + auto name_it = kRPRInputStrings.find(in_input); + return name_it != kRPRInputStrings.end() ? + rprMaterialNodeSetInputU(in_node, name_it->second.c_str(), in_value) + : RPR_ERROR_UNSUPPORTED; +} +rpr_int rprMaterialNodeSetInputImageData_ext(rpr_material_node in_node, rpr_material_node_input in_input, rpr_image image) +{ + auto name_it = kRPRInputStrings.find(in_input); + return name_it != kRPRInputStrings.end() ? + rprMaterialNodeSetInputImageData(in_node, name_it->second.c_str(), image) + : RPR_ERROR_UNSUPPORTED; +} +rpr_int rprMaterialNodeSetInputBufferData_ext(rpr_material_node in_node, rpr_material_node_input in_input, rpr_buffer buffer) +{ + auto name_it = kRPRInputStrings.find(in_input); + return name_it != kRPRInputStrings.end() ? + rprMaterialNodeSetInputBufferData(in_node, name_it->second.c_str(), buffer) + : RPR_ERROR_UNSUPPORTED; +} + +rpr_int rprShapeSetLayerMask(rpr_shape shape, rpr_uint layerMask) +{ + UNIMLEMENTED_FUNCTION +} + +rpr_int rprContextCreateHeteroVolume(rpr_context context, rpr_hetero_volume * out_heteroVolume, size_t gridSizeX, size_t gridSizeY, size_t gridSizeZ, void const * indicesList, size_t numberOfIndices, rpr_hetero_volume_indices_topology indicesListTopology, void const * gridData, size_t gridDataSizeByte, rpr_uint gridDataTopology___unused) +{ + UNSUPPORTED_FUNCTION +} + +rpr_int rprImageSetGamma(rpr_image image, rpr_float type) +{ + UNSUPPORTED_FUNCTION +} + +rpr_int rprImageSetMipmapEnabled(rpr_image image, rpr_bool enabled) +{ + UNSUPPORTED_FUNCTION +} + +rpr_int rprImageSetFilter(rpr_image image, rpr_image_filter_type type) +{ + UNSUPPORTED_FUNCTION +} + +RPR_API_ENTRY rpr_int rprHeteroVolumeSetFilter(rpr_hetero_volume heteroVolume, rpr_hetero_volume_filter filter) +{ + UNSUPPORTED_FUNCTION +} + +RPR_API_ENTRY rpr_int rprHeteroVolumeSetEmission(rpr_hetero_volume heteroVolume, rpr_float r, rpr_float g, rpr_float b) +{ + UNSUPPORTED_FUNCTION +} + +RPR_API_ENTRY rpr_int rprHeteroVolumeSetAlbedo(rpr_hetero_volume heteroVolume, rpr_float r, rpr_float g, rpr_float b) +{ + UNSUPPORTED_FUNCTION +} + +RPR_API_ENTRY rpr_int rprHeteroVolumeGetInfo(rpr_hetero_volume heteroVol, rpr_hetero_volume_parameter heteroVol_info, size_t size, void * data, size_t * size_ret) +{ + UNSUPPORTED_FUNCTION +} + +RPR_API_ENTRY rpr_int rprBufferGetInfo(rpr_buffer buffer, rpr_buffer_info buffer_info, size_t size, void * data, size_t * size_ret) +{ + UNSUPPORTED_FUNCTION +} diff --git a/Rpr/RadeonProRender.def b/Rpr/RadeonProRender.def index 9470e6cf..92c9a132 100644 --- a/Rpr/RadeonProRender.def +++ b/Rpr/RadeonProRender.def @@ -1,5 +1,7 @@ EXPORTS +ExportFromRpr + rprRegisterPlugin rprCreateContext rprContextSetActivePlugin @@ -18,16 +20,19 @@ rprContextRender rprContextRenderTile rprContextClearMemory rprContextCreateImage +rprContextCreateBuffer rprContextCreateImageFromFile rprContextCreateScene rprContextCreateInstance rprContextCreateMesh rprContextCreateMeshEx +rprContextCreateMeshEx2 rprContextCreateCamera rprContextCreateFrameBuffer rprCameraGetInfo rprCameraSetFocalLength rprCameraSetFocusDistance +rprImageSetOption rprCameraSetTransform rprCameraSetSensorSize rprCameraLookAt @@ -39,7 +44,10 @@ rprCameraSetOrthoWidth rprCameraSetFocalTilt rprCameraSetIPD rprCameraSetLensShift +rprCameraSetTiltCorrection rprCameraSetOrthoHeight +rprCameraSetNearPlane +rprCameraSetFarPlane rprImageGetInfo rprImageSetWrap rprShapeSetTransform @@ -48,12 +56,13 @@ rprShapeSetSubdivisionCreaseWeight rprShapeSetSubdivisionBoundaryInterop rprShapeSetDisplacementScale rprShapeSetObjectGroupID -rprShapeSetDisplacementImage +rprShapeSetDisplacementMaterial rprShapeSetMaterial -rprShapeSetMaterialOverride +rprShapeSetMaterialFaces rprShapeSetVolumeMaterial rprShapeSetLinearMotion rprShapeSetAngularMotion +rprShapeSetScaleMotion rprShapeSetVisibility rprShapeSetVisibilityPrimaryOnly rprShapeSetVisibilityInSpecular @@ -91,6 +100,8 @@ rprLightGetInfo rprSceneClear rprSceneAttachShape rprSceneDetachShape +rprSceneAttachHeteroVolume +rprSceneDetachHeteroVolume rprSceneAttachLight rprSceneDetachLight rprSceneGetInfo @@ -105,13 +116,23 @@ rprFrameBufferClear rprFrameBufferSaveToFile rprContextResolveFrameBuffer rprContextCreateMaterialSystem +rprMaterialSystemGetSize rprMaterialSystemCreateNode rprMaterialNodeSetInputN rprMaterialNodeSetInputF rprMaterialNodeSetInputU rprMaterialNodeSetInputImageData +rprMaterialNodeSetInputBufferData rprMaterialNodeGetInfo rprMaterialNodeGetInputInfo +rprContextCreateComposite +rprCompositeSetInputFb +rprCompositeSetInputC +rprCompositeSetInput4f +rprCompositeSetInput1u +rprCompositeSetInputOp +rprCompositeCompute +rprCompositeGetInfo rprObjectDelete rprObjectSetName rprContextCreatePostEffect @@ -121,6 +142,13 @@ rprPostEffectSetParameter1u rprPostEffectSetParameter1f rprPostEffectSetParameter3f rprPostEffectSetParameter4f +rprContextGetAttachedPostEffectCount +rprContextGetAttachedPostEffect +rprPostEffectGetInfo +rprContextCreateHeteroVolume +rprShapeSetHeteroVolume +rprHeteroVolumeSetTransform +rprContextCreateFramebufferFromGLTexture2D frRegisterPlugin frCreateContext frContextSetActivePlugin @@ -139,16 +167,19 @@ frContextRender frContextRenderTile frContextClearMemory frContextCreateImage +frContextCreateBuffer frContextCreateImageFromFile frContextCreateScene frContextCreateInstance frContextCreateMesh frContextCreateMeshEx +frContextCreateMeshEx2 frContextCreateCamera frContextCreateFrameBuffer frCameraGetInfo frCameraSetFocalLength frCameraSetFocusDistance +frImageSetOption frCameraSetTransform frCameraSetSensorSize frCameraLookAt @@ -160,7 +191,10 @@ frCameraSetOrthoWidth frCameraSetFocalTilt frCameraSetIPD frCameraSetLensShift +frCameraSetTiltCorrection frCameraSetOrthoHeight +frCameraSetNearPlane +frCameraSetFarPlane frImageGetInfo frImageSetWrap frShapeSetTransform @@ -169,12 +203,13 @@ frShapeSetSubdivisionCreaseWeight frShapeSetSubdivisionBoundaryInterop frShapeSetDisplacementScale frShapeSetObjectGroupID -frShapeSetDisplacementImage +frShapeSetDisplacementMaterial frShapeSetMaterial -frShapeSetMaterialOverride +frShapeSetMaterialFaces frShapeSetVolumeMaterial frShapeSetLinearMotion frShapeSetAngularMotion +frShapeSetScaleMotion frShapeSetVisibility frShapeSetVisibilityPrimaryOnly frShapeSetVisibilityInSpecular @@ -212,6 +247,8 @@ frLightGetInfo frSceneClear frSceneAttachShape frSceneDetachShape +frSceneAttachHeteroVolume +frSceneDetachHeteroVolume frSceneAttachLight frSceneDetachLight frSceneGetInfo @@ -226,13 +263,23 @@ frFrameBufferClear frFrameBufferSaveToFile frContextResolveFrameBuffer frContextCreateMaterialSystem +frMaterialSystemGetSize frMaterialSystemCreateNode frMaterialNodeSetInputN frMaterialNodeSetInputF frMaterialNodeSetInputU frMaterialNodeSetInputImageData +frMaterialNodeSetInputBufferData frMaterialNodeGetInfo frMaterialNodeGetInputInfo +frContextCreateComposite +frCompositeSetInputFb +frCompositeSetInputC +frCompositeSetInput4f +frCompositeSetInput1u +frCompositeSetInputOp +frCompositeCompute +frCompositeGetInfo frObjectDelete frObjectSetName frContextCreatePostEffect @@ -242,3 +289,16 @@ frPostEffectSetParameter1u frPostEffectSetParameter1f frPostEffectSetParameter3f frPostEffectSetParameter4f +frContextGetAttachedPostEffectCount +frContextGetAttachedPostEffect +frPostEffectGetInfo +frContextCreateHeteroVolume +frShapeSetHeteroVolume +frHeteroVolumeSetTransform +frContextCreateFramebufferFromGLTexture2D + +rprMaterialNodeSetInputN_ext +rprMaterialNodeSetInputF_ext +rprMaterialNodeSetInputU_ext +rprMaterialNodeSetInputImageData_ext +rprMaterialNodeSetInputBufferData_ext diff --git a/Rpr/RadeonProRender.h b/Rpr/RadeonProRender.h index 93ccc4e2..5ce9acb7 100644 --- a/Rpr/RadeonProRender.h +++ b/Rpr/RadeonProRender.h @@ -1,11 +1,11 @@ -/*****************************************************************************\ + /*****************************************************************************\ * * Module Name FireRender.h * Project FireRender Engine * * Description Fire Render Interface header * -* Copyright 2015 Advanced Micro Devices, Inc. +* Copyright 2017 Advanced Micro Devices, Inc. * * All rights reserved. This notice is intended as a precaution against * inadvertent publication and does not imply publication or any waiver @@ -15,21 +15,35 @@ * @author Takahiro Harada (takahiro.harada@amd.com) * @bug No known bugs. * + + \*****************************************************************************/ + #ifndef __RADEONPRORENDER_H #define __RADEONPRORENDER_H -#define RPR_API_ENTRY + +#include + +#ifdef WIN32 + #ifdef RPR_EXPORT_API + #define RPR_API_ENTRY __declspec(dllexport) + #else + #define RPR_API_ENTRY __declspec(dllimport) + #endif +#else + #define RPR_API_ENTRY __attribute__((visibility ("default"))) +#endif + #ifdef __cplusplus extern "C" { #endif -#include "cstddef" -#define RPR_API_VERSION 0x010000252 +#define RPR_API_VERSION 0x010030200 -/* rpr_status */ +/*rpr_status*/ #define RPR_SUCCESS 0 #define RPR_ERROR_COMPUTE_API_NOT_SUPPORTED -1 #define RPR_ERROR_OUT_OF_SYSTEM_MEMORY -2 @@ -54,8 +68,11 @@ extern "C" { #define RPR_ERROR_INVALID_PARAMETER_TYPE -22 #define RPR_ERROR_UNSUPPORTED -23 #define RPR_ERROR_OPENCL_OUT_OF_HOST_MEMORY -24 - -/* rpr_parameter_type */ +#define RPR_ERROR_OPENGL -25 +#define RPR_ERROR_OPENCL -26 +#define RPR_ERROR_NULLPTR -27 +#define RPR_ERROR_NODETYPE -28 +/*rpr_parameter_type*/ #define RPR_PARAMETER_TYPE_FLOAT 0x1 #define RPR_PARAMETER_TYPE_FLOAT2 0x2 #define RPR_PARAMETER_TYPE_FLOAT3 0x3 @@ -64,20 +81,7 @@ extern "C" { #define RPR_PARAMETER_TYPE_STRING 0x6 #define RPR_PARAMETER_TYPE_SHADER 0x7 #define RPR_PARAMETER_TYPE_UINT 0x8 - -/* rpr_image_type */ -#define RPR_IMAGE_TYPE_1D 0x1 -#define RPR_IMAGE_TYPE_2D 0x2 -#define RPR_IMAGE_TYPE_3D 0x3 - -/* rpr_context_type */ -#define RPR_CONTEXT_OPENCL (1 << 0) -#define RPR_CONTEXT_DIRECTCOMPUTE (1 << 1) -#define RPR_CONTEXT_REFERENCE (1 << 2) -#define RPR_CONTEXT_OPENGL (1 << 3) -#define RPR_CONTEXT_METAL (1 << 4) - -/* rpr_creation_flags */ +/*rpr_creation_flags*/ #define RPR_CREATION_FLAGS_ENABLE_GPU0 (1 << 0) #define RPR_CREATION_FLAGS_ENABLE_GPU1 (1 << 1) #define RPR_CREATION_FLAGS_ENABLE_GPU2 (1 << 2) @@ -88,20 +92,19 @@ extern "C" { #define RPR_CREATION_FLAGS_ENABLE_GPU5 (1 << 7) #define RPR_CREATION_FLAGS_ENABLE_GPU6 (1 << 8) #define RPR_CREATION_FLAGS_ENABLE_GPU7 (1 << 9) - -/* rpr_aa_filter */ +#define RPR_CREATION_FLAGS_ENABLE_METAL (1 << 10) +/*rpr_aa_filter*/ +#define RPR_FILTER_NONE 0x0 #define RPR_FILTER_BOX 0x1 #define RPR_FILTER_TRIANGLE 0x2 #define RPR_FILTER_GAUSSIAN 0x3 #define RPR_FILTER_MITCHELL 0x4 #define RPR_FILTER_LANCZOS 0x5 #define RPR_FILTER_BLACKMANHARRIS 0x6 - -/* rpr_shape_type */ +/*rpr_shape_type*/ #define RPR_SHAPE_TYPE_MESH 0x1 #define RPR_SHAPE_TYPE_INSTANCE 0x2 - -/* rpr_light_type */ +/*rpr_light_type*/ #define RPR_LIGHT_TYPE_POINT 0x1 #define RPR_LIGHT_TYPE_DIRECTIONAL 0x2 #define RPR_LIGHT_TYPE_SPOT 0x3 @@ -112,7 +115,12 @@ extern "C" { /* rpr_object_info */ #define RPR_OBJECT_NAME 0x777777 -/* rpr_context_info */ +/* rpr_context_properties */ +#define RPR_CONTEXT_CREATEPROP_CPU_THREAD_LIMIT 0x600 +#define RPR_CONTEXT_CREATEPROP_COMPILE_CALLBACK 0x601 +#define RPR_CONTEXT_CREATEPROP_COMPILE_USER_DATA 0x602 + +/*rpr_context_info*/ #define RPR_CONTEXT_CREATION_FLAGS 0x102 #define RPR_CONTEXT_CACHE_PATH 0x103 #define RPR_CONTEXT_RENDER_STATUS 0x104 @@ -123,6 +131,7 @@ extern "C" { #define RPR_CONTEXT_SCENE 0x109 #define RPR_CONTEXT_AA_CELL_SIZE 0x10A #define RPR_CONTEXT_AA_SAMPLES 0x10B +#define RPR_CONTEXT_ITERATIONS 0x10B #define RPR_CONTEXT_IMAGE_FILTER_TYPE 0x10C #define RPR_CONTEXT_IMAGE_FILTER_BOX_RADIUS 0x10D #define RPR_CONTEXT_IMAGE_FILTER_GAUSSIAN_RADIUS 0x10E @@ -161,11 +170,27 @@ extern "C" { #define RPR_CONTEXT_GPU7_NAME 0x12F #define RPR_CONTEXT_TONE_MAPPING_EXPONENTIAL_INTENSITY 0x130 #define RPR_CONTEXT_FRAMECOUNT 0x131 +#define RPR_CONTEXT_TEXTURE_COMPRESSION 0x132 +#define RPR_CONTEXT_AO_RAY_LENGTH 0x133 +#define RPR_CONTEXT_OOC_TEXTURE_CACHE 0x134 +#define RPR_CONTEXT_PREVIEW 0x135 +#define RPR_CONTEXT_CPU_THREAD_LIMIT 0x136 +#define RPR_CONTEXT_LAST_ERROR_MESSAGE 0x137 +#define RPR_CONTEXT_MAX_DEPTH_DIFFUSE 0x138 +#define RPR_CONTEXT_MAX_DEPTH_GLOSSY 0x139 +#define RPR_CONTEXT_OOC_CACHE_PATH 0x13a +#define RPR_CONTEXT_MAX_DEPTH_REFRACTION 0x13B +#define RPR_CONTEXT_MAX_DEPTH_GLOSSY_REFRACTION 0x13C +#define RPR_CONTEXT_RENDER_LAYER_MASK 0x13D +#define RPR_CONTEXT_SINGLE_LEVEL_BVH_ENABLED 0x13E +#define RPR_CONTEXT_TRANSPARENT_BACKGROUND 0x13F +#define RPR_CONTEXT_MAX_DEPTH_SHADOW 0x140 +#define RPR_CONTEXT_RANDOM_SEED 0x141 /* last of the RPR_CONTEXT_* */ -#define RPR_CONTEXT_MAX 0x132 +#define RPR_CONTEXT_MAX 0x142 -/* rpr_camera_info */ +/*rpr_camera_info*/ #define RPR_CAMERA_TRANSFORM 0x201 #define RPR_CAMERA_FSTOP 0x202 #define RPR_CAMERA_APERTURE_BLADES 0x203 @@ -183,15 +208,24 @@ extern "C" { #define RPR_CAMERA_FOCAL_TILT 0x20F #define RPR_CAMERA_LENS_SHIFT 0x210 #define RPR_CAMERA_IPD 0x211 - -/* rpr_image_info */ +#define RPR_CAMERA_TILT_CORRECTION 0x212 +#define RPR_CAMERA_NEAR_PLANE 0x213 +#define RPR_CAMERA_FAR_PLANE 0x214 +#define RPR_CAMERA_LINEAR_MOTION 0x215 +#define RPR_CAMERA_ANGULAR_MOTION 0x216 +/*rpr_image_info*/ #define RPR_IMAGE_FORMAT 0x301 #define RPR_IMAGE_DESC 0x302 #define RPR_IMAGE_DATA 0x303 #define RPR_IMAGE_DATA_SIZEBYTE 0x304 #define RPR_IMAGE_WRAP 0x305 - -/* rpr_shape_info */ +#define RPR_IMAGE_FILTER 0x306 +#define RPR_IMAGE_GAMMA 0x307 +#define RPR_IMAGE_MIPMAP_ENABLED 0x308 +/*rpr_buffer_info*/ +#define RPR_BUFFER_DESC 0x350 +#define RPR_BUFFER_DATA 0x351 +/*rpr_shape_info*/ #define RPR_SHAPE_TYPE 0x401 #define RPR_SHAPE_VIDMEM_USAGE 0x402 #define RPR_SHAPE_TRANSFORM 0x403 @@ -199,10 +233,9 @@ extern "C" { #define RPR_SHAPE_LINEAR_MOTION 0x405 #define RPR_SHAPE_ANGULAR_MOTION 0x406 #define RPR_SHAPE_VISIBILITY_FLAG 0x407 -#define RPR_SHAPE_SHADOW_FLAG 0x408 +#define RPR_SHAPE_SHADOW_FLAG 0x408 #define RPR_SHAPE_SUBDIVISION_FACTOR 0x409 #define RPR_SHAPE_DISPLACEMENT_SCALE 0x40A -#define RPR_SHAPE_DISPLACEMENT_IMAGE 0X40B #define RPR_SHAPE_VISIBILITY_PRIMARY_ONLY_FLAG 0x40C #define RPR_SHAPE_VISIBILITY_IN_SPECULAR_FLAG 0x40D #define RPR_SHAPE_SHADOW_CATCHER_FLAG 0x40E @@ -210,9 +243,12 @@ extern "C" { #define RPR_SHAPE_OBJECT_GROUP_ID 0x410 #define RPR_SHAPE_SUBDIVISION_CREASEWEIGHT 0x411 #define RPR_SHAPE_SUBDIVISION_BOUNDARYINTEROP 0x412 -#define RPR_SHAPE_MATERIAL_OVERRIDE 0x413 - -/* rpr_mesh_info */ +#define RPR_SHAPE_DISPLACEMENT_MATERIAL 0x413 +#define RPR_SHAPE_MATERIALS_PER_FACE 0x415 +#define RPR_SHAPE_SCALE_MOTION 0x416 +#define RPR_SHAPE_HETERO_VOLUME 0x417 +#define RPR_SHAPE_LAYER_MASK 0x418 +/*rpr_mesh_info*/ #define RPR_MESH_POLYGON_COUNT 0x501 #define RPR_MESH_VERTEX_COUNT 0x502 #define RPR_MESH_NORMAL_COUNT 0x503 @@ -235,8 +271,8 @@ extern "C" { #define RPR_MESH_UV2_INDEX_ARRAY 0x515 #define RPR_MESH_UV2_STRIDE 0x516 #define RPR_MESH_UV2_INDEX_STRIDE 0x517 - -/* rpr_scene_info */ +#define RPR_MESH_UV_DIM 0x518 +/*rpr_scene_info*/ #define RPR_SCENE_SHAPE_COUNT 0x701 #define RPR_SCENE_LIGHT_COUNT 0x702 #define RPR_SCENE_SHAPE_LIST 0x704 @@ -247,59 +283,62 @@ extern "C" { #define RPR_SCENE_ENVIRONMENT_OVERRIDE_REFRACTION 0x70A #define RPR_SCENE_ENVIRONMENT_OVERRIDE_TRANSPARENCY 0x70B #define RPR_SCENE_ENVIRONMENT_OVERRIDE_BACKGROUND 0x70C -#define RPR_SCENE_AXIS_ALIGNED_BOUNDING_BOX 0x70D - -/* rpr_light_info */ +#define RPR_SCENE_AABB 0x70D +#define RPR_SCENE_HETEROVOLUME_LIST 0x70E +#define RPR_SCENE_HETEROVOLUME_COUNT 0x70F +/*rpr_lut_info*/ +#define RPR_LUT_FILENAME 0x850 +#define RPR_LUT_DATA 0x851 +/*rpr_light_info*/ #define RPR_LIGHT_TYPE 0x801 #define RPR_LIGHT_TRANSFORM 0x803 +#define RPR_LIGHT_GROUP_ID 0x805 + -/* rpr_light_info - point light */ #define RPR_POINT_LIGHT_RADIANT_POWER 0x804 -/* rpr_light_info - directional light */ + #define RPR_DIRECTIONAL_LIGHT_RADIANT_POWER 0x808 #define RPR_DIRECTIONAL_LIGHT_SHADOW_SOFTNESS 0x809 -/* rpr_light_info - spot light */ + #define RPR_SPOT_LIGHT_RADIANT_POWER 0x80B #define RPR_SPOT_LIGHT_CONE_SHAPE 0x80C -/* rpr_light_info - environment light */ + #define RPR_ENVIRONMENT_LIGHT_IMAGE 0x80F #define RPR_ENVIRONMENT_LIGHT_INTENSITY_SCALE 0x810 #define RPR_ENVIRONMENT_LIGHT_PORTAL_LIST 0x818 #define RPR_ENVIRONMENT_LIGHT_PORTAL_COUNT 0x819 -/* rpr_light_info - sky light */ + #define RPR_SKY_LIGHT_TURBIDITY 0x812 #define RPR_SKY_LIGHT_ALBEDO 0x813 #define RPR_SKY_LIGHT_SCALE 0x814 +#define RPR_SKY_LIGHT_DIRECTION 0x815 #define RPR_SKY_LIGHT_PORTAL_LIST 0x820 #define RPR_SKY_LIGHT_PORTAL_COUNT 0x821 -/* rpr_light_info - IES light */ + #define RPR_IES_LIGHT_RADIANT_POWER 0x816 #define RPR_IES_LIGHT_IMAGE_DESC 0x817 - -/* rpr_parameter_info */ +/*rpr_parameter_info*/ #define RPR_PARAMETER_NAME 0x1201 #define RPR_PARAMETER_NAME_STRING 0x1202 #define RPR_PARAMETER_TYPE 0x1203 #define RPR_PARAMETER_DESCRIPTION 0x1204 #define RPR_PARAMETER_VALUE 0x1205 - -/* rpr_framebuffer_info */ +/*rpr_framebuffer_info*/ #define RPR_FRAMEBUFFER_FORMAT 0x1301 #define RPR_FRAMEBUFFER_DESC 0x1302 #define RPR_FRAMEBUFFER_DATA 0x1303 #define RPR_FRAMEBUFFER_GL_TARGET 0x1304 #define RPR_FRAMEBUFFER_GL_MIPLEVEL 0x1305 #define RPR_FRAMEBUFFER_GL_TEXTURE 0x1306 - -/* rpr_mesh_polygon_info */ +/*rpr_mesh_polygon_info*/ #define RPR_MESH_POLYGON_VERTEX_COUNT 0x1401 -/* rpr_mesh_polygon_vertex_info */ + #define RPR_MESH_POLYGON_VERTEX_POSITION 0x1501 #define RPR_MESH_POLYGON_VERTEX_NORMAL 0x1502 #define RPR_MESH_POLYGON_VERTEX_TEXCOORD 0x1503 @@ -307,13 +346,14 @@ extern "C" { /* rpr_instance_info */ #define RPR_INSTANCE_PARENT_SHAPE 0x1601 -/* rpr_image_format */ -/* rpr_component_type */ +/*rpr_component_type*/ #define RPR_COMPONENT_TYPE_UINT8 0x1 #define RPR_COMPONENT_TYPE_FLOAT16 0x2 #define RPR_COMPONENT_TYPE_FLOAT32 0x3 - -/* rpr_render_mode */ +/*rpr_buffer_element_type*/ +#define RPR_BUFFER_ELEMENT_TYPE_INT32 0x1 +#define RPR_BUFFER_ELEMENT_TYPE_FLOAT32 0x2 +/*rpr_render_mode*/ #define RPR_RENDER_MODE_GLOBAL_ILLUMINATION 0x1 #define RPR_RENDER_MODE_DIRECT_ILLUMINATION 0x2 #define RPR_RENDER_MODE_DIRECT_ILLUMINATION_NO_SHADOW 0x3 @@ -323,16 +363,16 @@ extern "C" { #define RPR_RENDER_MODE_NORMAL 0x7 #define RPR_RENDER_MODE_TEXCOORD 0x8 #define RPR_RENDER_MODE_AMBIENT_OCCLUSION 0x9 - -/* rpr_camera_mode */ +#define RPR_RENDER_MODE_DIFFUSE 0x0a +/*rpr_camera_mode*/ #define RPR_CAMERA_MODE_PERSPECTIVE 0x1 #define RPR_CAMERA_MODE_ORTHOGRAPHIC 0x2 #define RPR_CAMERA_MODE_LATITUDE_LONGITUDE_360 0x3 #define RPR_CAMERA_MODE_LATITUDE_LONGITUDE_STEREO 0x4 #define RPR_CAMERA_MODE_CUBEMAP 0x5 #define RPR_CAMERA_MODE_CUBEMAP_STEREO 0x6 - -/* rpr_tonemapping_operator */ +#define RPR_CAMERA_MODE_FISHEYE 0x7 +/*rpr_tonemapping_operator*/ #define RPR_TONEMAPPING_OPERATOR_NONE 0x0 #define RPR_TONEMAPPING_OPERATOR_LINEAR 0x1 #define RPR_TONEMAPPING_OPERATOR_PHOTOLINEAR 0x2 @@ -340,25 +380,21 @@ extern "C" { #define RPR_TONEMAPPING_OPERATOR_MAXWHITE 0x4 #define RPR_TONEMAPPING_OPERATOR_REINHARD02 0x5 #define RPR_TONEMAPPING_OPERATOR_EXPONENTIAL 0x6 - -/* rpr_volume_type */ +/*rpr_volume_type*/ #define RPR_VOLUME_TYPE_NONE 0xFFFF #define RPR_VOLUME_TYPE_HOMOGENEOUS 0x0 #define RPR_VOLUME_TYPE_HETEROGENEOUS 0x1 - -/* rpr_material_node_info*/ +/*rpr_material_node_info*/ #define RPR_MATERIAL_NODE_TYPE 0x1101 #define RPR_MATERIAL_NODE_SYSTEM 0x1102 #define RPR_MATERIAL_NODE_INPUT_COUNT 0x1103 - -/* rpr_material_node_input_info */ +/*rpr_material_node_input_info*/ #define RPR_MATERIAL_NODE_INPUT_NAME 0x1103 #define RPR_MATERIAL_NODE_INPUT_NAME_STRING 0x1104 #define RPR_MATERIAL_NODE_INPUT_DESCRIPTION 0x1105 #define RPR_MATERIAL_NODE_INPUT_VALUE 0x1106 #define RPR_MATERIAL_NODE_INPUT_TYPE 0x1107 - -/* rpr_material_node_type */ +/*rpr_material_node_type*/ #define RPR_MATERIAL_NODE_DIFFUSE 0x1 #define RPR_MATERIAL_NODE_MICROFACET 0x2 #define RPR_MATERIAL_NODE_REFLECTION 0x3 @@ -387,8 +423,17 @@ extern "C" { #define RPR_MATERIAL_NODE_DIFFUSE_REFRACTION 0x1B #define RPR_MATERIAL_NODE_BUMP_MAP 0x1C #define RPR_MATERIAL_NODE_VOLUME 0x1D - -/* rpr_material_node_input */ +#define RPR_MATERIAL_NODE_MICROFACET_ANISOTROPIC_REFLECTION 0x1E +#define RPR_MATERIAL_NODE_MICROFACET_ANISOTROPIC_REFRACTION 0x1F +#define RPR_MATERIAL_NODE_TWOSIDED 0x20 +#define RPR_MATERIAL_NODE_UV_PROCEDURAL 0x21 +#define RPR_MATERIAL_NODE_MICROFACET_BECKMANN 0x22 +#define RPR_MATERIAL_NODE_PHONG 0x23 +#define RPR_MATERIAL_NODE_BUFFER_SAMPLER 0x24 +#define RPR_MATERIAL_NODE_UV_TRIPLANAR 0x25 +#define RPR_MATERIAL_NODE_UBERV2 0x26 +#define RPR_MATERIAL_NODE_AO_MAP 0x27 +/*rpr_material_node_input*/ #define RPR_MATERIAL_INPUT_COLOR 0x0 #define RPR_MATERIAL_INPUT_COLOR0 0x1 #define RPR_MATERIAL_INPUT_COLOR1 0x2 @@ -414,9 +459,19 @@ extern "C" { #define RPR_MATERIAL_INPUT_MULTISCATTER 0x16 #define RPR_MATERIAL_INPUT_COLOR2 0x17 #define RPR_MATERIAL_INPUT_COLOR3 0x18 -#define RPR_MATERIAL_INPUT_MAX 0x19 - - +#define RPR_MATERIAL_INPUT_ANISOTROPIC 0x19 +#define RPR_MATERIAL_INPUT_FRONTFACE 0x1a +#define RPR_MATERIAL_INPUT_BACKFACE 0x1b +#define RPR_MATERIAL_INPUT_ORIGIN 0x1c +#define RPR_MATERIAL_INPUT_ZAXIS 0x1d +#define RPR_MATERIAL_INPUT_XAXIS 0x1e +#define RPR_MATERIAL_INPUT_THRESHOLD 0x1f +#define RPR_MATERIAL_INPUT_OFFSET 0x20 +#define RPR_MATERIAL_INPUT_UV_TYPE 0x21 +#define RPR_MATERIAL_INPUT_RADIUS 0x22 +#define RPR_MATERIAL_INPUT_SIDE 0x23 +#define RPR_MATERIAL_INPUT_MAX 0x24 +/*rpr_material_node_input*/ #define RPR_MATERIAL_STANDARD_INPUT_DIFFUSE_COLOR 0x112 #define RPR_MATERIAL_STANDARD_INPUT_DIFFUSE_NORMAL 0x113 #define RPR_MATERIAL_STANDARD_INPUT_GLOSSY_COLOR 0x114 @@ -447,7 +502,53 @@ extern "C" { #define RPR_MATERIAL_INPUT_RASTER_COLOR 0x90C #define RPR_MATERIAL_INPUT_RASTER_NORMAL 0x90D -/* rpr_material_node_arithmetic_operation */ +#define RPR_UBER_MATERIAL_DIFFUSE_COLOR 0x200U +#define RPR_UBER_MATERIAL_LAYERS 0x201U +#define RPR_UBER_MATERIAL_REFLECTION_COLOR 0x203U +#define RPR_UBER_MATERIAL_REFLECTION_ROUGHNESS 0x205U +#define RPR_UBER_MATERIAL_REFLECTION_ANISOTROPY 0x206U +#define RPR_UBER_MATERIAL_REFLECTION_ANISOTROPY_ROTATION 0x207U +#define RPR_UBER_MATERIAL_REFLECTION_IOR 0x208U +#define RPR_UBER_MATERIAL_REFLECTION_METALNESS 0x209U +#define RPR_UBER_MATERIAL_REFRACTION_COLOR 0x20AU +#define RPR_UBER_MATERIAL_REFRACTION_ROUGHNESS 0x20CU +#define RPR_UBER_MATERIAL_REFRACTION_IOR 0x20DU +#define RPR_UBER_MATERIAL_REFRACTION_IOR_MODE 0x20EU +#define RPR_UBER_MATERIAL_REFRACTION_THIN_SURFACE 0x20FU +#define RPR_UBER_MATERIAL_COATING_COLOR 0x210U +#define RPR_UBER_MATERIAL_COATING_IOR 0x213U +#define RPR_UBER_MATERIAL_EMISSION_COLOR 0x215U +#define RPR_UBER_MATERIAL_EMISSION_WEIGHT 0x216U +#define RPR_UBER_MATERIAL_EMISSION_MODE 0x217U +#define RPR_UBER_MATERIAL_TRANSPARENCY 0x218U +#define RPR_UBER_MATERIAL_NORMAL 0x219U +#define RPR_UBER_MATERIAL_BUMP 0x21AU +#define RPR_UBER_MATERIAL_DISPLACEMENT 0x21BU +#define RPR_UBER_MATERIAL_SSS_ABSORPTION_COLOR 0x21CU +#define RPR_UBER_MATERIAL_SSS_SCATTER_COLOR 0x21DU +#define RPR_UBER_MATERIAL_SSS_ABSORPTION_DISTANCE 0x21EU +#define RPR_UBER_MATERIAL_SSS_SCATTER_DISTANCE 0x21FU +#define RPR_UBER_MATERIAL_SSS_SCATTER_DIRECTION 0x220U +#define RPR_UBER_MATERIAL_SSS_SUBSURFACE_COLOR 0x222U +#define RPR_UBER_MATERIAL_SSS_MULTISCATTER 0x223U + +#define RPR_UBER_MATERIAL_REFRACTION_MODE_SEPARATE 0x1U +#define RPR_UBER_MATERIAL_REFRACTION_MODE_LINKED 0x2U + +#define RPR_UBER_MATERIAL_EMISSION_MODE_SINGLESIDED 0x1U +#define RPR_UBER_MATERIAL_EMISSION_MODE_DOUBLESIDED 0x2U + +/* rpr uber material layers */ +#define RPR_UBER_MATERIAL_LAYER_EMISSION 0x1 +#define RPR_UBER_MATERIAL_LAYER_TRANSPARENCY 0x2 +#define RPR_UBER_MATERIAL_LAYER_COATING 0x4 +#define RPR_UBER_MATERIAL_LAYER_REFLECTION 0x8 +#define RPR_UBER_MATERIAL_LAYER_DIFFUSE 0x10 +#define RPR_UBER_MATERIAL_LAYER_REFRACTION 0x20 +#define RPR_UBER_MATERIAL_LAYER_SSS 0x40 +#define RPR_UBER_MATERIAL_LAYER_SHADING_NORMAL 0x80 + +/*rpr_material_node_arithmetic_operation*/ #define RPR_MATERIAL_NODE_OP_ADD 0x00 #define RPR_MATERIAL_NODE_OP_SUB 0x01 #define RPR_MATERIAL_NODE_OP_MUL 0x02 @@ -458,49 +559,48 @@ extern "C" { #define RPR_MATERIAL_NODE_OP_SELECT_X 0x07 #define RPR_MATERIAL_NODE_OP_SELECT_Y 0x08 #define RPR_MATERIAL_NODE_OP_SELECT_Z 0x09 -#define RPR_MATERIAL_NODE_OP_SELECT_W 0x0A -#define RPR_MATERIAL_NODE_OP_COMBINE 0x0B -#define RPR_MATERIAL_NODE_OP_DOT3 0x0C -#define RPR_MATERIAL_NODE_OP_DOT4 0x0D -#define RPR_MATERIAL_NODE_OP_CROSS3 0x0E -#define RPR_MATERIAL_NODE_OP_LENGTH3 0x0F -#define RPR_MATERIAL_NODE_OP_NORMALIZE3 0x10 -#define RPR_MATERIAL_NODE_OP_POW 0x11 -#define RPR_MATERIAL_NODE_OP_ACOS 0x12 -#define RPR_MATERIAL_NODE_OP_ASIN 0x13 -#define RPR_MATERIAL_NODE_OP_ATAN 0x14 -#define RPR_MATERIAL_NODE_OP_AVERAGE_XYZ 0x15 -#define RPR_MATERIAL_NODE_OP_AVERAGE 0x16 -#define RPR_MATERIAL_NODE_OP_MIN 0x17 -#define RPR_MATERIAL_NODE_OP_MAX 0x18 -#define RPR_MATERIAL_NODE_OP_FLOOR 0x19 -#define RPR_MATERIAL_NODE_OP_MOD 0x1A -#define RPR_MATERIAL_NODE_OP_ABS 0x1B -#define RPR_MATERIAL_NODE_OP_SHUFFLE_YZWX 0x1C -#define RPR_MATERIAL_NODE_OP_SHUFFLE_ZWXY 0x1D -#define RPR_MATERIAL_NODE_OP_SHUFFLE_WXYZ 0x1E -#define RPR_MATERIAL_NODE_OP_MAT_MUL 0x1F - -/* rpr_material_node_lookup_value */ +#define RPR_MATERIAL_NODE_OP_COMBINE 0x0A +#define RPR_MATERIAL_NODE_OP_DOT3 0x0B +#define RPR_MATERIAL_NODE_OP_CROSS3 0x0C +#define RPR_MATERIAL_NODE_OP_LENGTH3 0x0D +#define RPR_MATERIAL_NODE_OP_NORMALIZE3 0x0E +#define RPR_MATERIAL_NODE_OP_POW 0x0F +#define RPR_MATERIAL_NODE_OP_ACOS 0x10 +#define RPR_MATERIAL_NODE_OP_ASIN 0x11 +#define RPR_MATERIAL_NODE_OP_ATAN 0x12 +#define RPR_MATERIAL_NODE_OP_AVERAGE_XYZ 0x13 +#define RPR_MATERIAL_NODE_OP_AVERAGE 0x14 +#define RPR_MATERIAL_NODE_OP_MIN 0x15 +#define RPR_MATERIAL_NODE_OP_MAX 0x16 +#define RPR_MATERIAL_NODE_OP_FLOOR 0x17 +#define RPR_MATERIAL_NODE_OP_MOD 0x18 +#define RPR_MATERIAL_NODE_OP_ABS 0x19 +#define RPR_MATERIAL_NODE_OP_SHUFFLE_YZWX 0x1a +#define RPR_MATERIAL_NODE_OP_SHUFFLE_ZWXY 0x1b +#define RPR_MATERIAL_NODE_OP_SHUFFLE_WXYZ 0x1c +#define RPR_MATERIAL_NODE_OP_MAT_MUL 0x1d +#define RPR_MATERIAL_NODE_OP_SELECT_W 0x1e +#define RPR_MATERIAL_NODE_OP_DOT4 0x1f +#define RPR_MATERIAL_NODE_OP_LOG 0x20 +/*rpr_material_node_lookup_value*/ #define RPR_MATERIAL_NODE_LOOKUP_UV 0x0 #define RPR_MATERIAL_NODE_LOOKUP_N 0x1 #define RPR_MATERIAL_NODE_LOOKUP_P 0x2 #define RPR_MATERIAL_NODE_LOOKUP_INVEC 0x3 #define RPR_MATERIAL_NODE_LOOKUP_OUTVEC 0x4 #define RPR_MATERIAL_NODE_LOOKUP_UV1 0x5 - -/* rpr_post_effect_info */ +/*rpr_material_node_uvtype_value*/ +#define RPR_MATERIAL_NODE_UVTYPE_PLANAR 0x0 +#define RPR_MATERIAL_NODE_UVTYPE_CYLINDICAL 0x1 +#define RPR_MATERIAL_NODE_UVTYPE_SPHERICAL 0x2 +#define RPR_MATERIAL_NODE_UVTYPE_PROJECT 0x3 +/*rpr_post_effect_info*/ #define RPR_POST_EFFECT_TYPE 0x0 -#define RPR_POST_EFFECT_PARAMETER_COUNT 0x1 - -/* rpr_post_effect_type - white balance */ -#define RPR_POST_EFFECT_WHITE_BALANCE_COLOR_SPACE 0x1 -#define RPR_POST_EFFECT_WHITE_BALANCE_COLOR_TEMPERATURE 0x2 - -/* rpr_post_effect_type - simple tonemap */ -#define RPR_POST_EFFECT_SIMPLE_TONEMAP_EXPOSURE 0x1 -#define RPR_POST_EFFECT_SIMPLE_TONEMAP_CONTRAST 0x2 - +#define RPR_POST_EFFECT_WHITE_BALANCE_COLOR_SPACE 0x4 +#define RPR_POST_EFFECT_WHITE_BALANCE_COLOR_TEMPERATURE 0x5 +#define RPR_POST_EFFECT_SIMPLE_TONEMAP_EXPOSURE 0x6 +#define RPR_POST_EFFECT_SIMPLE_TONEMAP_CONTRAST 0x7 +#define RPR_POST_EFFECT_SIMPLE_TONEMAP_ENABLE_TONEMAP 0x8 /*rpr_aov*/ #define RPR_AOV_COLOR 0x0 #define RPR_AOV_OPACITY 0x1 @@ -512,284 +612,411 @@ extern "C" { #define RPR_AOV_DEPTH 0x7 #define RPR_AOV_OBJECT_ID 0x8 #define RPR_AOV_OBJECT_GROUP_ID 0x9 -#define RPR_AOV_MAX 0xa - +#define RPR_AOV_SHADOW_CATCHER 0x0a +#define RPR_AOV_BACKGROUND 0x0b +#define RPR_AOV_EMISSION 0x0c +#define RPR_AOV_VELOCITY 0x0d +#define RPR_AOV_DIRECT_ILLUMINATION 0x0e +#define RPR_AOV_INDIRECT_ILLUMINATION 0x0f +#define RPR_AOV_AO 0x10 +#define RPR_AOV_DIRECT_DIFFUSE 0x11 +#define RPR_AOV_DIRECT_REFLECT 0x12 +#define RPR_AOV_INDIRECT_DIFFUSE 0x13 +#define RPR_AOV_INDIRECT_REFLECT 0x14 +#define RPR_AOV_REFRACT 0x15 +#define RPR_AOV_VOLUME 0x16 +#define RPR_AOV_LIGHT_GROUP0 0x17 +#define RPR_AOV_LIGHT_GROUP1 0x18 +#define RPR_AOV_LIGHT_GROUP2 0x19 +#define RPR_AOV_LIGHT_GROUP3 0x1a +#define RPR_AOV_MAX 0x1b /*rpr_post_effect_type*/ #define RPR_POST_EFFECT_TONE_MAP 0x0 #define RPR_POST_EFFECT_WHITE_BALANCE 0x1 #define RPR_POST_EFFECT_SIMPLE_TONEMAP 0x2 #define RPR_POST_EFFECT_NORMALIZATION 0x3 #define RPR_POST_EFFECT_GAMMA_CORRECTION 0x4 - /*rpr_color_space*/ #define RPR_COLOR_SPACE_SRGB 0x1 #define RPR_COLOR_SPACE_ADOBE_RGB 0x2 #define RPR_COLOR_SPACE_REC2020 0x3 #define RPR_COLOR_SPACE_DCIP3 0x4 +/*rpr_material_node_input_type*/ + -/* rpr_material_node_type */ #define RPR_MATERIAL_NODE_INPUT_TYPE_FLOAT4 0x1 #define RPR_MATERIAL_NODE_INPUT_TYPE_UINT 0x2 #define RPR_MATERIAL_NODE_INPUT_TYPE_NODE 0x3 #define RPR_MATERIAL_NODE_INPUT_TYPE_IMAGE 0x4 - -/* Additional Raster context properties ("raster.shadows.filter") */ -#define RPR_RASTER_SHADOWS_FILTER_NONE 0x90E -#define RPR_RASTER_SHADOWS_FILTER_PCF 0x90F -#define RPR_RASTER_SHADOWS_FILTER_PCSS 0x910 - -/* Additional Raster context properties ("raster.shadows.sampling") */ -#define RPR_RASTER_SHADOWS_SAMPLING_BILINEAR 0x911 -#define RPR_RASTER_SHADOWS_SAMPLING_HAMMERSLEY 0x912 -#define RPR_RASTER_SHADOWS_SAMPLING_MULTIJITTERED 0x913 - -/* rpr_subdiv_boundary_interfop_type */ +#define RPR_MATERIAL_NODE_INPUT_TYPE_BUFFER 0x5 +/*rpr_subdiv_boundary_interfop_type*/ #define RPR_SUBDIV_BOUNDARY_INTERFOP_TYPE_EDGE_AND_CORNER 0x1 #define RPR_SUBDIV_BOUNDARY_INTERFOP_TYPE_EDGE_ONLY 0x2 - -/* rpr_image_wrap_type */ +/*rpr_image_wrap_type*/ #define RPR_IMAGE_WRAP_TYPE_REPEAT 0x1 #define RPR_IMAGE_WRAP_TYPE_MIRRORED_REPEAT 0x2 #define RPR_IMAGE_WRAP_TYPE_CLAMP_TO_EDGE 0x3 #define RPR_IMAGE_WRAP_TYPE_CLAMP_TO_BORDER 0x4 +#define RPR_IMAGE_WRAP_TYPE_CLAMP_ZERO 0x5 +#define RPR_IMAGE_WRAP_TYPE_CLAMP_ONE 0x6 +/*rpr_image_filter_type*/ +#define RPR_IMAGE_FILTER_TYPE_NEAREST 0x1 +#define RPR_IMAGE_FILTER_TYPE_LINEAR 0x2 /* Constants */ -#define RPR_MAX_AA_SAMPLES 32 -#define RPR_MAX_AA_GRID_SIZE 16 +/*rpr_composite_info*/ +#define RPR_COMPOSITE_TYPE 0x1 +#define RPR_COMPOSITE_FRAMEBUFFER_INPUT_FB 0x2 +#define RPR_COMPOSITE_NORMALIZE_INPUT_COLOR 0x3 +#define RPR_COMPOSITE_NORMALIZE_INPUT_SHADOWCATCHER 0x4 +#define RPR_COMPOSITE_CONSTANT_INPUT_VALUE 0x5 +#define RPR_COMPOSITE_LERP_VALUE_INPUT_COLOR0 0x6 +#define RPR_COMPOSITE_LERP_VALUE_INPUT_COLOR1 0x7 +#define RPR_COMPOSITE_LERP_VALUE_INPUT_WEIGHT 0x8 +#define RPR_COMPOSITE_ARITHMETIC_INPUT_COLOR0 0x9 +#define RPR_COMPOSITE_ARITHMETIC_INPUT_COLOR1 0x0a +#define RPR_COMPOSITE_ARITHMETIC_INPUT_OP 0x0b +#define RPR_COMPOSITE_GAMMA_CORRECTION_INPUT_COLOR 0x0c +#define RPR_COMPOSITE_LUT_INPUT_LUT 0x0d +#define RPR_COMPOSITE_LUT_INPUT_COLOR 0x0e +/*rpr_composite_type*/ +#define RPR_COMPOSITE_ARITHMETIC 0x1 +#define RPR_COMPOSITE_LERP_VALUE 0x2 +#define RPR_COMPOSITE_INVERSE 0x3 +#define RPR_COMPOSITE_NORMALIZE 0x4 +#define RPR_COMPOSITE_GAMMA_CORRECTION 0x5 +#define RPR_COMPOSITE_EXPOSURE 0x6 +#define RPR_COMPOSITE_CONTRAST 0x7 +#define RPR_COMPOSITE_SIDE_BY_SIDE 0x8 +#define RPR_COMPOSITE_TONEMAP_ACES 0x9 +#define RPR_COMPOSITE_TONEMAP_REINHARD 0xa +#define RPR_COMPOSITE_TONEMAP_LINEAR 0xb +#define RPR_COMPOSITE_FRAMEBUFFER 0xc +#define RPR_COMPOSITE_CONSTANT 0xd +#define RPR_COMPOSITE_LUT 0xe + +/*rpr_hetero_volume_parameter*/ +/*rpr_hetero_volume_parameter*/ +#define RPR_HETEROVOLUME_SIZE_X 0x730 +#define RPR_HETEROVOLUME_SIZE_Y 0x731 +#define RPR_HETEROVOLUME_SIZE_Z 0x732 +#define RPR_HETEROVOLUME_DATA 0x733 +#define RPR_HETEROVOLUME_DATA_SIZEBYTE 0x734 +#define RPR_HETEROVOLUME_TRANSFORM 0x735 +#define RPR_HETEROVOLUME_INDICES 0x736 +#define RPR_HETEROVOLUME_INDICES_NUMBER 0x737 +#define RPR_HETEROVOLUME_INDICES_TOPOLOGY 0x738 +#define RPR_HETEROVOLUME_EMISSION 0x739 +#define RPR_HETEROVOLUME_ALBEDO 0x73a +#define RPR_HETEROVOLUME_FILTER 0x73b +/*rpr_hetero_volume_indices_topology*/ +#define RPR_HETEROVOLUME_INDICES_TOPOLOGY_I_U64 0x750 +#define RPR_HETEROVOLUME_INDICES_TOPOLOGY_XYZ_U32 0x751 +#define RPR_HETEROVOLUME_INDICES_TOPOLOGY_I_S64 0x752 +#define RPR_HETEROVOLUME_INDICES_TOPOLOGY_XYZ_S32 0x753 +/*rpr_hetero_volume_filter*/ +#define RPR_HETEROVOLUME_FILTER_NEAREST 0x760 +#define RPR_HETEROVOLUME_FILTER_LINEAR 0x761 /* rpr_bool */ #define RPR_FALSE 0 #define RPR_TRUE 1 -/* Library types */ -/* This is going to be moved to rpr_platform.h or similar */ -typedef char rpr_char; -typedef unsigned char rpr_uchar; -typedef int rpr_int; -typedef unsigned int rpr_uint; -typedef long int rpr_long; -typedef long unsigned int rpr_ulong; -typedef short int rpr_short; -typedef short unsigned int rpr_ushort; -typedef float rpr_float; -typedef double rpr_double; -typedef long long int rpr_longlong; -typedef int rpr_bool; -typedef rpr_uint rpr_bitfield; -typedef void * rpr_context; -typedef void * rpr_camera; -typedef void * rpr_shape; -typedef void * rpr_light; -typedef void * rpr_scene; -typedef void * rpr_image; -typedef void * rpr_framebuffer; -typedef void * rpr_material_system; -typedef void * rpr_material_node; -typedef void * rpr_post_effect; -typedef void * rpr_context_properties; -typedef rpr_uint rpr_light_type; -typedef rpr_uint rpr_image_type; -typedef rpr_uint rpr_shape_type; -typedef rpr_uint rpr_context_type; -typedef rpr_bitfield rpr_creation_flags; -typedef rpr_uint rpr_aa_filter; -typedef rpr_uint rpr_context_info; -typedef rpr_uint rpr_camera_info; -typedef rpr_uint rpr_image_info; -typedef rpr_uint rpr_shape_info; -typedef rpr_uint rpr_mesh_info; -typedef rpr_uint rpr_mesh_polygon_info; -typedef rpr_uint rpr_mesh_polygon_vertex_info; -typedef rpr_uint rpr_light_info; -typedef rpr_uint rpr_scene_info; -typedef rpr_uint rpr_parameter_info; -typedef rpr_uint rpr_framebuffer_info; -typedef rpr_uint rpr_channel_order; -typedef rpr_uint rpr_channel_type; -typedef rpr_uint rpr_parameter_type; -typedef rpr_uint rpr_render_mode; -typedef rpr_uint rpr_component_type; -typedef rpr_uint rpr_camera_mode; -typedef rpr_uint rpr_tonemapping_operator; -typedef rpr_uint rpr_volume_type; -typedef rpr_uint rpr_material_system_type; -typedef rpr_uint rpr_material_node_type; -typedef rpr_uint rpr_material_node_input; -typedef rpr_uint rpr_material_node_info; -typedef rpr_uint rpr_material_node_input_info; -typedef rpr_uint rpr_aov; -typedef rpr_uint rpr_post_effect_type; -typedef rpr_uint rpr_post_effect_info; -typedef rpr_uint rpr_color_space; -typedef rpr_uint rpr_environment_override; -typedef rpr_uint rpr_subdiv_boundary_interfop_type; -typedef rpr_uint rpr_material_node_lookup_value; -typedef rpr_uint rpr_image_wrap_type; - -struct _rpr_image_desc -{ - rpr_uint image_width; - rpr_uint image_height; - rpr_uint image_depth; - rpr_uint image_row_pitch; - rpr_uint image_slice_pitch; -}; - -typedef _rpr_image_desc rpr_image_desc; - -struct _rpr_framebuffer_desc -{ - rpr_uint fb_width; - rpr_uint fb_height; -}; - -typedef _rpr_framebuffer_desc rpr_framebuffer_desc; - -struct _rpr_render_statistics -{ - rpr_longlong gpumem_usage; - rpr_longlong gpumem_total; - rpr_longlong gpumem_max_allocation; -}; - -typedef _rpr_render_statistics rpr_render_statistics; - -struct _rpr_image_format -{ - rpr_uint num_components; - rpr_component_type type; -}; - -typedef _rpr_image_format rpr_image_format; - -struct _rpr_ies_image_desc -{ - rpr_int w; - rpr_int h; - rpr_char const * data; - rpr_char const * filename; -}; - -typedef _rpr_ies_image_desc rpr_ies_image_desc; -typedef rpr_image_format rpr_framebuffer_format; - -/* API functions */ -/** @brief Register rendering plugin -* -* -* -* @param path Path of plugin to load -* @return unique identifier of plugin, -1 otherwise -*/ -extern RPR_API_ENTRY rpr_int rprRegisterPlugin(rpr_char const * path); - -/** @brief Create rendering context - * - * Rendering context is a root concept encapsulating the render states and responsible - * for execution control. All the entities in FireRender are created for a particular rendering context. - * Entities created for some context can't be used with other contexts. Possible error codes for this call are: - * - * RPR_ERROR_COMPUTE_API_NOT_SUPPORTED - * RPR_ERROR_OUT_OF_SYSTEM_MEMORY - * RPR_ERROR_OUT_OF_VIDEO_MEMORY - * RPR_ERROR_INVALID_API_VERSION - * RPR_ERROR_INVALID_PARAMETER - * - * @param api_version Api version constant - * @param context_type Determines compute API to use, OPENCL only is supported for now - * @param creation_flags Determines multi-gpu or cpu-gpu configuration - * @param props Context properties, reserved for future use - * @param cache_path Full path to kernel cache created by FireRender, NULL means to use current folder - * @param out_context Pointer to context object - * @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprCreateContext(rpr_int api_version, rpr_int * pluginIDs, size_t pluginCount, rpr_creation_flags creation_flags, rpr_context_properties const * props, rpr_char const * cache_path, rpr_context * out_context); - -/** @breif Set active context plugin -* -*/ -extern RPR_API_ENTRY rpr_int rprContextSetActivePlugin(rpr_context context, rpr_int pluginID); - -/** @brief Query information about a context - * - * The workflow is usually two-step: query with the data == NULL and size = 0 to get the required buffer size in size_ret, - * then query with size_ret == NULL to fill the buffer with the data. - * Possible error codes: - * RPR_ERROR_INVALID_PARAMETER - * - * @param context The context to query - * @param context_info The type of info to query - * @param size The size of the buffer pointed by data - * @param data The buffer to store queried info - * @param size_ret Returns the size in bytes of the data being queried - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprContextGetInfo(rpr_context context, rpr_context_info context_info, size_t size, void * data, size_t * size_ret); - -/** @brief Query information about a context parameter -* -* The workflow is usually two-step: query with the data == NULL and size = 0 to get the required buffer size in size_ret, -* then query with size_ret == NULL to fill the buffer with the data -* Possible error codes: -* RPR_ERROR_INVALID_PARAMETER -* -* @param context The context to query -* @param param_idx The index of the parameter -* @param parameter_info The type of info to query -* @param size The size of the buffer pointed by data -* @param data The buffer to store queried info -* @param size_ret Returns the size in bytes of the data being queried -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprContextGetParameterInfo(rpr_context context, int param_idx, rpr_parameter_info parameter_info, size_t size, void * data, size_t * size_ret); - -/** @brief Query the AOV - * - * @param context The context to get a frame buffer from - * @param out_fb Pointer to framebuffer object - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprContextGetAOV(rpr_context context, rpr_aov aov, rpr_framebuffer * out_fb); - -/** @brief Set AOV - * - * @param context The context to set AOV - * @param aov AOV - * @param frame_buffer Frame buffer object to set - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprContextSetAOV(rpr_context context, rpr_aov aov, rpr_framebuffer frame_buffer); - -/** @brief Set the scene - * - * The scene is a collection of objects and lights - * along with all the data required to shade those. The scene is - * used by the context to render the image. - * - * @param context The context to set the scene - * @param scene The scene to set - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprContextSetScene(rpr_context context, rpr_scene scene); - -/** @brief Get the current scene - * - * The scene is a collection of objects and lights - * along with all the data required to shade those. The scene is - * used by the context ro render the image. - * - * @param context The context to get the scene from - * @param out_scene Pointer to scene object - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprContextGetScene(rpr_context arg0, rpr_scene * out_scene); - -/** @brief Set context parameter - * - * Parameters are used to control rendering modes, global sampling and AA settings, etc - * - * @param context The context to set the value to - * @param name Param name, can be: + /* Library types */ + /* This is going to be moved to rpr_platform.h or similar */ + typedef char rpr_char; + typedef unsigned char rpr_uchar; + typedef int rpr_int; + typedef unsigned int rpr_uint; + typedef long int rpr_long; + typedef long unsigned int rpr_ulong; + typedef short int rpr_short; + typedef short unsigned int rpr_ushort; + typedef float rpr_float; + typedef double rpr_double; + typedef long long int rpr_longlong; + typedef int rpr_bool; + typedef rpr_uint rpr_bitfield; + typedef rpr_int rpr_status; + typedef void * rpr_context; + typedef void * rpr_camera; + typedef void * rpr_shape; + typedef void * rpr_light; + typedef void * rpr_scene; + typedef void * rpr_image; + typedef void * rpr_buffer; + typedef void * rpr_hetero_volume; + typedef void * rpr_framebuffer; + typedef void * rpr_material_system; + typedef void * rpr_material_node; + typedef void * rpr_post_effect; + typedef void * rpr_context_properties; + typedef void * rpr_composite; + typedef void * rpr_lut; + typedef rpr_uint rpr_light_type; + typedef rpr_uint rpr_image_option; + typedef rpr_uint rpr_shape_type; + typedef rpr_uint rpr_context_type; + typedef rpr_bitfield rpr_creation_flags; + typedef rpr_uint rpr_aa_filter; + typedef rpr_uint rpr_context_info; + typedef rpr_uint rpr_camera_info; + typedef rpr_uint rpr_image_info; + typedef rpr_uint rpr_buffer_info; + typedef rpr_uint rpr_shape_info; + typedef rpr_uint rpr_mesh_info; + typedef rpr_uint rpr_mesh_polygon_info; + typedef rpr_uint rpr_mesh_polygon_vertex_info; + typedef rpr_uint rpr_light_info; + typedef rpr_uint rpr_lut_info; + typedef rpr_uint rpr_scene_info; + typedef rpr_uint rpr_parameter_info; + typedef rpr_uint rpr_framebuffer_info; + typedef rpr_uint rpr_channel_order; + typedef rpr_uint rpr_channel_type; + typedef rpr_uint rpr_parameter_type; + typedef rpr_uint rpr_render_mode; + typedef rpr_uint rpr_component_type; + typedef rpr_uint rpr_buffer_element_type; + typedef rpr_uint rpr_camera_mode; + typedef rpr_uint rpr_tonemapping_operator; + typedef rpr_uint rpr_volume_type; + typedef rpr_uint rpr_material_system_type; + typedef rpr_uint rpr_material_node_type; + typedef rpr_uint rpr_material_node_input; + typedef rpr_uint rpr_material_node_input_type; + typedef rpr_uint rpr_material_node_info; + typedef rpr_uint rpr_material_node_input_info; + typedef rpr_uint rpr_aov; + typedef rpr_uint rpr_post_effect_type; + typedef rpr_uint rpr_post_effect_info; + typedef rpr_uint rpr_composite_info; + typedef rpr_uint rpr_composite_type; + typedef rpr_uint rpr_color_space; + typedef rpr_uint rpr_environment_override; + typedef rpr_uint rpr_subdiv_boundary_interfop_type; + typedef rpr_uint rpr_material_node_lookup_value; + typedef rpr_uint rpr_material_node_uvtype_value; + typedef rpr_uint rpr_image_wrap_type; + typedef rpr_uint rpr_image_filter_type; + typedef rpr_uint rpr_material_node_arithmetic_operation; + typedef rpr_uint rpr_hetero_volume_parameter; + typedef rpr_uint rpr_hetero_volume_indices_topology; + typedef rpr_uint rpr_hetero_volume_filter; + + struct _rpr_image_desc + { + rpr_uint image_width; + rpr_uint image_height; + rpr_uint image_depth; + rpr_uint image_row_pitch; + rpr_uint image_slice_pitch; + }; + + typedef _rpr_image_desc rpr_image_desc; + + struct _rpr_buffer_desc + { + rpr_uint nb_element; + rpr_buffer_element_type element_type; + rpr_uint element_channel_size; + }; + + typedef _rpr_buffer_desc rpr_buffer_desc; + + struct _rpr_framebuffer_desc + { + rpr_uint fb_width; + rpr_uint fb_height; + }; + + typedef _rpr_framebuffer_desc rpr_framebuffer_desc; + + struct _rpr_render_statistics + { + rpr_longlong gpumem_usage; + rpr_longlong gpumem_total; + rpr_longlong gpumem_max_allocation; + rpr_longlong sysmem_usage; + }; + + typedef _rpr_render_statistics rpr_render_statistics; + + struct _rpr_image_format + { + rpr_uint num_components; + rpr_component_type type; + }; + + typedef _rpr_image_format rpr_image_format; + + struct _rpr_ies_image_desc + { + rpr_int w; + rpr_int h; + rpr_char const * data; + rpr_char const * filename; + }; + + typedef _rpr_ies_image_desc rpr_ies_image_desc; + typedef rpr_image_format rpr_framebuffer_format; + + /* API functions */ + + /** @brief Register rendering plugin + * + * + * + * @param path Path of plugin to load + * @return unique identifier of plugin, -1 otherwise + */ + + extern RPR_API_ENTRY rpr_int rprRegisterPlugin(rpr_char const * path); + + + /** @brief Create rendering context + * + * Rendering context is a root concept encapsulating the render states and responsible + * for execution control. All the entities in FireRender are created for a particular rendering context. + * Entities created for some context can't be used with other contexts. Possible error codes for this call are: + * + * RPR_ERROR_COMPUTE_API_NOT_SUPPORTED + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * RPR_ERROR_INVALID_API_VERSION + * RPR_ERROR_INVALID_PARAMETER + * + * @param api_version Api version constant + * @param context_type Determines compute API to use, OPENCL only is supported for now + * @param creation_flags Determines multi-gpu or cpu-gpu configuration + * @param props Context creation properties. Specifies a list of context property names and their corresponding values. + * Each property name is immediately followed by the corresponding desired value. + * The list is terminated with 0. + * @param cache_path Full path to kernel cache created by FireRender, NULL means to use current folder + * @param cpu_thread_limit Limit for the number of threads used for CPU rendering + * @param out_context Pointer to context object + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprCreateContext(rpr_int api_version, rpr_int * pluginIDs, size_t pluginCount, rpr_creation_flags creation_flags, rpr_context_properties const * props, rpr_char const * cache_path, rpr_context * out_context); + + + /** @breif Set active context plugin + * + */ + + extern RPR_API_ENTRY rpr_int rprContextSetActivePlugin(rpr_context context, rpr_int pluginID); + + + /** @brief Query information about a context + * + * The workflow is usually two-step: query with the data == NULL and size = 0 to get the required buffer size in size_ret, + * then query with size_ret == NULL to fill the buffer with the data. + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param context The context to query + * @param context_info The type of info to query + * @param size The size of the buffer pointed by data + * @param data The buffer to store queried info + * @param size_ret Returns the size in bytes of the data being queried + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextGetInfo(rpr_context context, rpr_context_info context_info, size_t size, void * data, size_t * size_ret); + + + /** @brief Query information about a context parameter + * + * The workflow is usually two-step: query with the data == NULL and size = 0 to get the required buffer size in size_ret, + * then query with size_ret == NULL to fill the buffer with the data + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param context The context to query + * @param param_idx The index of the parameter + * @param parameter_info The type of info to query + * @param size The size of the buffer pointed by data + * @param data The buffer to store queried info + * @param size_ret Returns the size in bytes of the data being queried + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextGetParameterInfo(rpr_context context, int param_idx, rpr_parameter_info parameter_info, size_t size, void * data, size_t * size_ret); + + + /** @brief Query the AOV + * + * @param context The context to get a frame buffer from + * @param out_fb Pointer to framebuffer object + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextGetAOV(rpr_context context, rpr_aov aov, rpr_framebuffer * out_fb); + + + /** @brief Set AOV + * + * @param context The context to set AOV + * @param aov AOV + * @param frame_buffer Frame buffer object to set + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextSetAOV(rpr_context context, rpr_aov aov, rpr_framebuffer frame_buffer); + + + /** @brief Set AOV Index Lookup Color + * change the color of AOV rendering IDs, like : RPR_AOV_MATERIAL_IDX , RPR_AOV_OBJECT_ID, RPR_AOV_OBJECT_GROUP_ID. + * for example, you can render all the shapes with ObjectGroupID=4 in the Red color inside the RPR_AOV_OBJECT_GROUP_ID AOV + * + * @param context The context to set AOV index lookup + * @param key id + * @param colorR red channel + * @param colorG green channel + * @param colorB blue channel + * @param colorA alpha channel + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextSetAOVindexLookup(rpr_context context, rpr_int key, rpr_float colorR, rpr_float colorG, rpr_float colorB, rpr_float colorA); + + + /** @brief Set the scene + * + * The scene is a collection of objects and lights + * along with all the data required to shade those. The scene is + * used by the context to render the image. + * + * @param context The context to set the scene + * @param scene The scene to set + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextSetScene(rpr_context context, rpr_scene scene); + + + /** @brief Get the current scene + * + * The scene is a collection of objects and lights + * along with all the data required to shade those. The scene is + * used by the context ro render the image. + * + * @param context The context to get the scene from + * @param out_scene Pointer to scene object + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextGetScene(rpr_context arg0, rpr_scene * out_scene); + + + /** @brief Set context parameter + * + * Parameters are used to control rendering modes, global sampling and AA settings, etc + * + * @param context The context to set the value to + * @param name Param name, can be: + * aacellsize ft_float * aasamples ft_float @@ -802,7 +1029,7 @@ extern RPR_API_ENTRY rpr_int rprContextGetScene(rpr_context arg0, rpr_scene * ou * imagefilter.lanczos.radius ft_float * imagefilter.blackmanharris.radius ft_float - * tonemapping.type rpr_tonemapping_operator + * tonemapping.type rpr_tonemapping_operator * tonemapping.linear.scale ft_float * tonemapping.photolinear.sensitivity ft_float * tonemapping.photolinear.exposure ft_float @@ -811,1130 +1038,1576 @@ extern RPR_API_ENTRY rpr_int rprContextGetScene(rpr_context arg0, rpr_scene * ou * tonemapping.reinhard02.postscale ft_float * tonemapping.reinhard02.burn ft_float - * @param x,y,z,w Parameter value - - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprContextSetParameter1u(rpr_context context, rpr_char const * name, rpr_uint x); -extern RPR_API_ENTRY rpr_int rprContextSetParameter1f(rpr_context context, rpr_char const * name, rpr_float x); -extern RPR_API_ENTRY rpr_int rprContextSetParameter3f(rpr_context context, rpr_char const * name, rpr_float x, rpr_float y, rpr_float z); -extern RPR_API_ENTRY rpr_int rprContextSetParameter4f(rpr_context context, rpr_char const * name, rpr_float x, rpr_float y, rpr_float z, rpr_float w); -extern RPR_API_ENTRY rpr_int rprContextSetParameterString(rpr_context context, rpr_char const * name, rpr_char const * value); - -/** @brief Perform evaluation and accumulation of a single sample (or number of AA samples if AA is enabled) - * - * The call is blocking and the image is ready when returned. The context accumulates the samples in order - * to progressively refine the image and enable interactive response. So each new call to Render refines the - * resultin image with 1 (or num aa samples) color samples. Call rprFramebufferClear if you want to start rendering new image - * instead of refining the previous one. - * - * Possible error codes: - * RPR_ERROR_OUT_OF_VIDEO_MEMORY - * RPR_ERROR_OUT_OF_SYSTEM_MEMORY - * RPR_ERROR_INTERNAL_ERROR - * RPR_ERROR_MATERIAL_STACK_OVERFLOW - * - * if you have the RPR_ERROR_MATERIAL_STACK_OVERFLOW error, you have created a shader graph with too many nodes. - * you can check the nodes limit with rprContextGetInfo(,RPR_CONTEXT_MATERIAL_STACK_SIZE,) - * - * @param context The context object - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprContextRender(rpr_context context); - -/** @brief Perform evaluation and accumulation of a single sample (or number of AA samples if AA is enabled) on the part of the image - * - * The call is blocking and the image is ready when returned. The context accumulates the samples in order - * to progressively refine the image and enable interactive response. So each new call to Render refines the - * resultin image with 1 (or num aa samples) color samples. Call rprFramebufferClear if you want to start rendering new image - * instead of refining the previous one. Possible error codes are: - * - * RPR_ERROR_OUT_OF_VIDEO_MEMORY - * RPR_ERROR_OUT_OF_SYSTEM_MEMORY - * RPR_ERROR_INTERNAL_ERROR - * - * @param context The context to use for the rendering - * @param xmin X coordinate of the top left corner of a tile - * @param xmax X coordinate of the bottom right corner of a tile - * @param ymin Y coordinate of the top left corner of a tile - * @param ymax Y coordinate of the bottom right corner of a tile - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprContextRenderTile(rpr_context context, rpr_uint xmin, rpr_uint xmax, rpr_uint ymin, rpr_uint ymax); - -/** @brief Clear all video memory used by the context - * - * This function should be called after all context objects have been destroyed. - * It guarantees that all context memory is freed and returns the context into its initial state. - * Will be removed later. Possible error codes are: - * - * RPR_ERROR_INTERNAL_ERROR - * - * @param context The context to wipe out - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprContextClearMemory(rpr_context context); - -/** @brief Create an image from memory data - * - * Images are used as HDRI maps or inputs for various shading system nodes. - * Possible error codes are: - * - * RPR_ERROR_OUT_OF_SYSTEM_MEMORY - * RPR_ERROR_OUT_OF_VIDEO_MEMORY - * RPR_ERROR_UNSUPPORTED_IMAGE_FORMAT - * RPR_ERROR_INVALID_PARAMETER - * - * @param context The context to create image - * @param format Image format - * @param image_desc Image layout description - * @param data Image data in system memory, can be NULL in which case the memory is allocated - * @param out_image Pointer to image object - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprContextCreateImage(rpr_context context, rpr_image_format const format, rpr_image_desc const * image_desc, void const * data, rpr_image * out_image); - -/** @brief Create an image from file - * - * Images are used as HDRI maps or inputs for various shading system nodes. - * - * The following image formats are supported: - * PNG, JPG, TGA, BMP, TIFF, TX(0-mip), HDR, EXR - * - * Possible error codes are: - * - * RPR_ERROR_OUT_OF_SYSTEM_MEMORY - * RPR_ERROR_OUT_OF_VIDEO_MEMORY - * RPR_ERROR_UNSUPPORTED_IMAGE_FORMAT - * RPR_ERROR_INVALID_PARAMETER - * RPR_ERROR_IO_ERROR - * - * @param context The context to create image - * @param path NULL terminated path to an image file (can be relative) - * @param out_image Pointer to image object - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprContextCreateImageFromFile(rpr_context context, rpr_char const * path, rpr_image * out_image); - -/** @brief Create a scene - * - * Scene serves as a container for lights and objects. - * - * Possible error codes are: - * - * RPR_ERROR_OUT_OF_SYSTEM_MEMORY - * - * @param out_scene Pointer to scene object - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprContextCreateScene(rpr_context context, rpr_scene * out_scene); - -/** @brief Create an instance of an object - * - * Possible error codes are: - * - * RPR_ERROR_OUT_OF_SYSTEM_MEMORY - * RPR_ERROR_OUT_OF_VIDEO_MEMORY - * RPR_ERROR_INVALID_PARAMETER - * - * @param context The context to create an instance for - * @param shape Parent shape for an instance - * @param out_instance Pointer to instance object - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprContextCreateInstance(rpr_context context, rpr_shape shape, rpr_shape * out_instance); - -/** @brief Create a mesh - * - * FireRender supports mixed meshes consisting of triangles and quads. - * - * Possible error codes are: - * - * RPR_ERROR_OUT_OF_SYSTEM_MEMORY - * RPR_ERROR_OUT_OF_VIDEO_MEMORY - * RPR_ERROR_INVALID_PARAMETER - * - * @param vertices Pointer to position data (each position is described with 3 rpr_float numbers) - * @param num_vertices Number of entries in position array - * @param vertex_stride Number of bytes between the beginnings of two successive position entries - * @param normals Pointer to normal data (each normal is described with 3 rpr_float numbers), can be NULL - * @param num_normals Number of entries in normal array - * @param normal_stride Number of bytes between the beginnings of two successive normal entries - * @param texcoord Pointer to texcoord data (each texcoord is described with 2 rpr_float numbers), can be NULL - * @param num_texcoords Number of entries in texcoord array - * @param texcoord_stride Number of bytes between the beginnings of two successive texcoord entries - * @param vertex_indices Pointer to an array of vertex indices - * @param vidx_stride Number of bytes between the beginnings of two successive vertex index entries - * @param normal_indices Pointer to an array of normal indices - * @param nidx_stride Number of bytes between the beginnings of two successive normal index entries - * @param texcoord_indices Pointer to an array of texcoord indices - * @param tidx_stride Number of bytes between the beginnings of two successive texcoord index entries - * @param num_face_vertices Pointer to an array of num_faces numbers describing number of vertices for each face (can be 3(triangle) or 4(quad)) - * @param num_faces Number of faces in the mesh - * @param out_mesh Pointer to mesh object - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprContextCreateMesh(rpr_context context, rpr_float const * vertices, size_t num_vertices, rpr_int vertex_stride, rpr_float const * normals, size_t num_normals, rpr_int normal_stride, rpr_float const * texcoords, size_t num_texcoords, rpr_int texcoord_stride, rpr_int const * vertex_indices, rpr_int vidx_stride, rpr_int const * normal_indices, rpr_int nidx_stride, rpr_int const * texcoord_indices, rpr_int tidx_stride, rpr_int const * num_face_vertices, size_t num_faces, rpr_shape * out_mesh); - -/* @brief Create a mesh - * - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprContextCreateMeshEx(rpr_context context, rpr_float const * vertices, size_t num_vertices, rpr_int vertex_stride, rpr_float const * normals, size_t num_normals, rpr_int normal_stride, rpr_int const * perVertexFlag, size_t num_perVertexFlags, rpr_int perVertexFlag_stride, rpr_int numberOfTexCoordLayers, rpr_float const ** texcoords, size_t * num_texcoords, rpr_int * texcoord_stride, rpr_int const * vertex_indices, rpr_int vidx_stride, rpr_int const * normal_indices, rpr_int nidx_stride, rpr_int const ** texcoord_indices, rpr_int * tidx_stride, rpr_int const * num_face_vertices, size_t num_faces, rpr_shape * out_mesh); - -/** @brief Create a camera - * - * There are several camera types supported by a single rpr_camera type. - * Possible error codes are: - * - * RPR_ERROR_OUT_OF_SYSTEM_MEMORY - * RPR_ERROR_OUT_OF_VIDEO_MEMORY - * - * @param context The context to create a camera for - * @param out_camera Pointer to camera object - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprContextCreateCamera(rpr_context context, rpr_camera * out_camera); - -/** @brief Create framebuffer object - * - * Framebuffer is used to store final rendering result. - * - * Possible error codes are: - * - * RPR_ERROR_OUT_OF_SYSTEM_MEMORY - * RPR_ERROR_OUT_OF_VIDEO_MEMORY - * - * @param context The context to create framebuffer - * @param format Framebuffer format - * @param fb_desc Framebuffer layout description - * @param status Pointer to framebuffer object - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprContextCreateFrameBuffer(rpr_context context, rpr_framebuffer_format const format, rpr_framebuffer_desc const * fb_desc, rpr_framebuffer * out_fb); - -/* rpr_camera */ -/** @brief Query information about a camera - * - * The workflow is usually two-step: query with the data == NULL to get the required buffer size, - * then query with size_ret == NULL to fill the buffer with the data. - * Possible error codes: - * RPR_ERROR_INVALID_PARAMETER - * - * @param camera The camera to query - * @param camera_info The type of info to query - * @param size The size of the buffer pointed by data - * @param data The buffer to store queried info - * @param size_ret Returns the size in bytes of the data being queried - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprCameraGetInfo(rpr_camera camera, rpr_camera_info camera_info, size_t size, void * data, size_t * size_ret); - -/** @brief Set camera focal length. - * - * @param camera The camera to set focal length - * @param flength Focal length in millimeters, default is 35mm - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprCameraSetFocalLength(rpr_camera camera, rpr_float flength); - -/** @brief Set camera focus distance - * - * @param camera The camera to set focus distance - * @param fdist Focus distance in meters, default is 1m - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprCameraSetFocusDistance(rpr_camera camera, rpr_float fdist); - -/** @brief Set world transform for the camera - * - * @param camera The camera to set transform for - * @param transpose Determines whether the basis vectors are in columns(false) or in rows(true) of the matrix - * @param transform Array of 16 rpr_float values (row-major form) - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprCameraSetTransform(rpr_camera camera, rpr_bool transpose, rpr_float * transform); - -/** @brief Set sensor size for the camera - * - * Default sensor size is the one corresponding to full frame 36x24mm sensor - * - * @param camera The camera to set transform for - * @param width Sensor width in millimeters - * @param height Sensor height in millimeters - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprCameraSetSensorSize(rpr_camera camera, rpr_float width, rpr_float height); - -/** @brief Set camera transform in lookat form - * - * @param camera The camera to set transform for - * @param posx X component of the position - * @param posy Y component of the position - * @param posz Z component of the position - * @param atx X component of the center point - * @param aty Y component of the center point - * @param atz Z component of the center point - * @param upx X component of the up vector - * @param upy Y component of the up vector - * @param upz Z component of the up vector - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprCameraLookAt(rpr_camera camera, rpr_float posx, rpr_float posy, rpr_float posz, rpr_float atx, rpr_float aty, rpr_float atz, rpr_float upx, rpr_float upy, rpr_float upz); - -/** @brief Set f-stop for the camera - * - * @param camera The camera to set f-stop for - * @param fstop f-stop value in mm^-1, default is FLT_MAX - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprCameraSetFStop(rpr_camera camera, rpr_float fstop); - -/** @brief Set the number of aperture blades - * - * Possible error codes: - * RPR_ERROR_INVALID_PARAMETER - * - * @param camera The camera to set aperture blades for - * @param num_blades Number of aperture blades 4 to 32 - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprCameraSetApertureBlades(rpr_camera camera, rpr_uint num_blades); - -/** @brief Set the exposure of a camera - * - * Possible error codes: - * RPR_ERROR_INVALID_PARAMETER - * - * @param camera The camera to set aperture blades for - * @param exposure Exposure value 0.0 - 1.0 - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprCameraSetExposure(rpr_camera camera, rpr_float exposure); - -/** @brief Set camera mode - * - * Camera modes include: - * RPR_CAMERA_MODE_PERSPECTIVE - * RPR_CAMERA_MODE_ORTHOGRAPHIC - * RPR_CAMERA_MODE_LATITUDE_LONGITUDE_360 - * RPR_CAMERA_MODE_LATITUDE_LONGITUDE_STEREO - * RPR_CAMERA_MODE_CUBEMAP - * RPR_CAMERA_MODE_CUBEMAP_STEREO - * - * @param camera The camera to set mode for - * @param mode Camera mode, default is RPR_CAMERA_MODE_PERSPECTIVE - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprCameraSetMode(rpr_camera camera, rpr_camera_mode mode); - -/** @brief Set orthographic view volume width - * - * @param camera The camera to set volume width for - * @param width View volume width in meters, default is 1 meter - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprCameraSetOrthoWidth(rpr_camera camera, rpr_float width); -extern RPR_API_ENTRY rpr_int rprCameraSetFocalTilt(rpr_camera camera, rpr_float tilt); -extern RPR_API_ENTRY rpr_int rprCameraSetIPD(rpr_camera camera, rpr_float ipd); -extern RPR_API_ENTRY rpr_int rprCameraSetLensShift(rpr_camera camera, rpr_float shiftx, rpr_float shifty); - -/** @brief Set orthographic view volume height -* -* @param camera The camera to set volume height for -* @param width View volume height in meters, default is 1 meter -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprCameraSetOrthoHeight(rpr_camera camera, rpr_float height); - -/* rpr_image*/ -/** @brief Query information about an image - * - * The workflow is usually two-step: query with the data == NULL to get the required buffer size, - * then query with size_ret == NULL to fill the buffer with the data - * Possible error codes: - * RPR_ERROR_INVALID_PARAMETER - * - * @param image An image object to query - * @param image_info The type of info to query - * @param size The size of the buffer pointed by data - * @param data The buffer to store queried info - * @param size_ret Returns the size in bytes of the data being queried - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprImageGetInfo(rpr_image image, rpr_image_info image_info, size_t size, void * data, size_t * size_ret); - -/** @brief -* -* -* @param image The image to set wrap for -* @param type -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprImageSetWrap(rpr_image image, rpr_image_wrap_type type); - -/* rpr_shape */ -/** @brief Set shape world transform - * - * - * @param shape The shape to set transform for - * @param transpose Determines whether the basis vectors are in columns(false) or in rows(true) of the matrix - * @param transform Array of 16 rpr_float values (row-major form) - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprShapeSetTransform(rpr_shape shape, rpr_bool transpose, rpr_float const * transform); - -/** @brief Set shape subdivision -* -* -* @param shape The shape to set subdivision for -* @param factor Number of subdivision steps to do -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprShapeSetSubdivisionFactor(rpr_shape shape, rpr_uint factor); -/** @brief -* -* -* @param shape The shape to set subdivision for -* @param factor -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprShapeSetSubdivisionCreaseWeight(rpr_shape shape, rpr_float factor); + * @param x,y,z,w Parameter value + + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextSetParameter1u(rpr_context context, rpr_char const * name, rpr_uint x); + extern RPR_API_ENTRY rpr_int rprContextSetParameter1f(rpr_context context, rpr_char const * name, rpr_float x); + extern RPR_API_ENTRY rpr_int rprContextSetParameter3f(rpr_context context, rpr_char const * name, rpr_float x, rpr_float y, rpr_float z); + extern RPR_API_ENTRY rpr_int rprContextSetParameter4f(rpr_context context, rpr_char const * name, rpr_float x, rpr_float y, rpr_float z, rpr_float w); + extern RPR_API_ENTRY rpr_int rprContextSetParameterString(rpr_context context, rpr_char const * name, rpr_char const * value); + + + /** @brief Perform evaluation and accumulation of a single sample (or number of AA samples if AA is enabled) + * + * The call is blocking and the image is ready when returned. The context accumulates the samples in order + * to progressively refine the image and enable interactive response. So each new call to Render refines the + * resultin image with 1 (or num aa samples) color samples. Call rprFramebufferClear if you want to start rendering new image + * instead of refining the previous one. + * + * Possible error codes: + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_INTERNAL_ERROR + * RPR_ERROR_MATERIAL_STACK_OVERFLOW + * + * if you have the RPR_ERROR_MATERIAL_STACK_OVERFLOW error, you have created a shader graph with too many nodes. + * you can check the nodes limit with rprContextGetInfo(,RPR_CONTEXT_MATERIAL_STACK_SIZE,) + * + * @param context The context object + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextRender(rpr_context context); + + + /** @brief Perform evaluation and accumulation of a single sample (or number of AA samples if AA is enabled) on the part of the image + * + * The call is blocking and the image is ready when returned. The context accumulates the samples in order + * to progressively refine the image and enable interactive response. So each new call to Render refines the + * resultin image with 1 (or num aa samples) color samples. Call rprFramebufferClear if you want to start rendering new image + * instead of refining the previous one. Possible error codes are: + * + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_INTERNAL_ERROR + * + * @param context The context to use for the rendering + * @param xmin X coordinate of the top left corner of a tile + * @param xmax X coordinate of the bottom right corner of a tile + * @param ymin Y coordinate of the top left corner of a tile + * @param ymax Y coordinate of the bottom right corner of a tile + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextRenderTile(rpr_context context, rpr_uint xmin, rpr_uint xmax, rpr_uint ymin, rpr_uint ymax); + + + /** @brief Clear all video memory used by the context + * + * This function should be called after all context objects have been destroyed. + * It guarantees that all context memory is freed and returns the context into its initial state. + * Will be removed later. Possible error codes are: + * + * RPR_ERROR_INTERNAL_ERROR + * + * @param context The context to wipe out + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextClearMemory(rpr_context context); + + + /** @brief Create an image from memory data + * + * Images are used as HDRI maps or inputs for various shading system nodes. + * Possible error codes are: + * + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * RPR_ERROR_UNSUPPORTED_IMAGE_FORMAT + * RPR_ERROR_INVALID_PARAMETER + * + * @param context The context to create image + * @param format Image format + * @param image_desc Image layout description + * @param data Image data in system memory, can be NULL in which case the memory is allocated + * @param out_image Pointer to image object + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextCreateImage(rpr_context context, rpr_image_format const format, rpr_image_desc const * image_desc, void const * data, rpr_image * out_image); + + + /** @brief Create a buffer from memory data + * + * Buffers are used as arbitrary input for other nodes + * + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * RPR_ERROR_UNSUPPORTED_IMAGE_FORMAT + * RPR_ERROR_INVALID_PARAMETER + * + * @param context The context to create image + * @param buffer_desc Buffer layout description + * @param data Image data in system memory, can be NULL in which case the memory is allocated + * @param out_buffer Pointer to buffer object + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextCreateBuffer(rpr_context context, rpr_buffer_desc const * buffer_desc, void const * data, rpr_buffer * out_buffer); + + + /** @brief Create an image from file + * + * Images are used as HDRI maps or inputs for various shading system nodes. + * + * The following image formats are supported: + * PNG, JPG, TGA, BMP, TIFF, TX(0-mip), HDR, EXR + * + * Possible error codes are: + * + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * RPR_ERROR_UNSUPPORTED_IMAGE_FORMAT + * RPR_ERROR_INVALID_PARAMETER + * RPR_ERROR_IO_ERROR + * + * @param context The context to create image + * @param path NULL terminated path to an image file (can be relative) + * @param out_image Pointer to image object + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextCreateImageFromFile(rpr_context context, rpr_char const * path, rpr_image * out_image); + + + /** @brief Create a scene + * + * Scene serves as a container for lights and objects. + * + * Possible error codes are: + * + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * + * @param out_scene Pointer to scene object + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextCreateScene(rpr_context context, rpr_scene * out_scene); + + + /** @brief Create an instance of an object + * + * Possible error codes are: + * + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * RPR_ERROR_INVALID_PARAMETER + * + * @param context The context to create an instance for + * @param shape Parent shape for an instance + * @param out_instance Pointer to instance object + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextCreateInstance(rpr_context context, rpr_shape shape, rpr_shape * out_instance); + + + /** @brief Create a mesh + * + * FireRender supports mixed meshes consisting of triangles and quads. + * + * Possible error codes are: + * + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * RPR_ERROR_INVALID_PARAMETER + * + * @param vertices Pointer to position data (each position is described with 3 rpr_float numbers) + * @param num_vertices Number of entries in position array + * @param vertex_stride Number of bytes between the beginnings of two successive position entries + * @param normals Pointer to normal data (each normal is described with 3 rpr_float numbers), can be NULL + * @param num_normals Number of entries in normal array + * @param normal_stride Number of bytes between the beginnings of two successive normal entries + * @param texcoord Pointer to texcoord data (each texcoord is described with 2 rpr_float numbers), can be NULL + * @param num_texcoords Number of entries in texcoord array + * @param texcoord_stride Number of bytes between the beginnings of two successive texcoord entries + * @param vertex_indices Pointer to an array of vertex indices + * @param vidx_stride Number of bytes between the beginnings of two successive vertex index entries + * @param normal_indices Pointer to an array of normal indices + * @param nidx_stride Number of bytes between the beginnings of two successive normal index entries + * @param texcoord_indices Pointer to an array of texcoord indices + * @param tidx_stride Number of bytes between the beginnings of two successive texcoord index entries + * @param num_face_vertices Pointer to an array of num_faces numbers describing number of vertices for each face (can be 3(triangle) or 4(quad)) + * @param num_faces Number of faces in the mesh + * @param out_mesh Pointer to mesh object + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextCreateMesh(rpr_context context, rpr_float const * vertices, size_t num_vertices, rpr_int vertex_stride, rpr_float const * normals, size_t num_normals, rpr_int normal_stride, rpr_float const * texcoords, size_t num_texcoords, rpr_int texcoord_stride, rpr_int const * vertex_indices, rpr_int vidx_stride, rpr_int const * normal_indices, rpr_int nidx_stride, rpr_int const * texcoord_indices, rpr_int tidx_stride, rpr_int const * num_face_vertices, size_t num_faces, rpr_shape * out_mesh); + + + /* @brief Create a mesh + * + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextCreateMeshEx(rpr_context context, rpr_float const * vertices, size_t num_vertices, rpr_int vertex_stride, rpr_float const * normals, size_t num_normals, rpr_int normal_stride, rpr_int const * perVertexFlag, size_t num_perVertexFlags, rpr_int perVertexFlag_stride, rpr_int numberOfTexCoordLayers, rpr_float const ** texcoords, size_t const * num_texcoords, rpr_int const * texcoord_stride, rpr_int const * vertex_indices, rpr_int vidx_stride, rpr_int const * normal_indices, rpr_int nidx_stride, rpr_int const ** texcoord_indices, rpr_int const * tidx_stride, rpr_int const * num_face_vertices, size_t num_faces, rpr_shape * out_mesh); + + + /* @brief Create a mesh + * + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextCreateMeshEx2(rpr_context context, rpr_float const * vertices, size_t num_vertices, rpr_int vertex_stride, rpr_float const * normals, size_t num_normals, rpr_int normal_stride, rpr_int const * perVertexFlag, size_t num_perVertexFlags, rpr_int perVertexFlag_stride, rpr_int numberOfTexCoordLayers, rpr_float const ** texcoords, size_t const * num_texcoords, rpr_int const * texcoord_stride, rpr_int const * vertex_indices, rpr_int vidx_stride, rpr_int const * normal_indices, rpr_int nidx_stride, rpr_int const ** texcoord_indices, rpr_int const * tidx_stride, rpr_int const * num_face_vertices, size_t num_faces, rpr_mesh_info const * mesh_properties, rpr_shape * out_mesh); + + + /** @brief Create a camera + * + * There are several camera types supported by a single rpr_camera type. + * Possible error codes are: + * + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * + * @param context The context to create a camera for + * @param out_camera Pointer to camera object + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextCreateCamera(rpr_context context, rpr_camera * out_camera); + + + /** @brief Create framebuffer object + * + * Framebuffer is used to store final rendering result. + * + * Possible error codes are: + * + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * + * @param context The context to create framebuffer + * @param format Framebuffer format + * @param fb_desc Framebuffer layout description + * @param status Pointer to framebuffer object + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprContextCreateFrameBuffer(rpr_context context, rpr_framebuffer_format const format, rpr_framebuffer_desc const * fb_desc, rpr_framebuffer * out_fb); + + /* rpr_camera */ + + /** @brief Query information about a camera + * + * The workflow is usually two-step: query with the data == NULL to get the required buffer size, + * then query with size_ret == NULL to fill the buffer with the data. + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param camera The camera to query + * @param camera_info The type of info to query + * @param size The size of the buffer pointed by data + * @param data The buffer to store queried info + * @param size_ret Returns the size in bytes of the data being queried + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprCameraGetInfo(rpr_camera camera, rpr_camera_info camera_info, size_t size, void * data, size_t * size_ret); + + + /** @brief Set camera focal length. + * + * @param camera The camera to set focal length + * @param flength Focal length in millimeters, default is 35mm + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprCameraSetFocalLength(rpr_camera camera, rpr_float flength); + + + /** @brief Set camera linear motion. + * + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprCameraSetLinearMotion(rpr_camera camera, rpr_float x, rpr_float y, rpr_float z); + + + /** @brief Set camera angular motion. + * + * x,y,z : vector - w : angle in radian + * + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprCameraSetAngularMotion(rpr_camera camera, rpr_float x, rpr_float y, rpr_float z, rpr_float w); + + + /** @brief Set camera focus distance + * + * @param camera The camera to set focus distance + * @param fdist Focus distance in meters, default is 1m + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprCameraSetFocusDistance(rpr_camera camera, rpr_float fdist); + + + /** @brief Set world transform for the camera + * + * @param camera The camera to set transform for + * @param transpose Determines whether the basis vectors are in columns(false) or in rows(true) of the matrix + * @param transform Array of 16 rpr_float values (row-major form) + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprCameraSetTransform(rpr_camera camera, rpr_bool transpose, rpr_float * transform); + + + /** @brief Set sensor size for the camera + * + * Default sensor size is the one corresponding to full frame 36x24mm sensor + * + * @param camera The camera to set transform for + * @param width Sensor width in millimeters + * @param height Sensor height in millimeters + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprCameraSetSensorSize(rpr_camera camera, rpr_float width, rpr_float height); + + + /** @brief Set camera transform in lookat form + * + * @param camera The camera to set transform for + * @param posx X component of the position + * @param posy Y component of the position + * @param posz Z component of the position + * @param atx X component of the center point + * @param aty Y component of the center point + * @param atz Z component of the center point + * @param upx X component of the up vector + * @param upy Y component of the up vector + * @param upz Z component of the up vector + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprCameraLookAt(rpr_camera camera, rpr_float posx, rpr_float posy, rpr_float posz, rpr_float atx, rpr_float aty, rpr_float atz, rpr_float upx, rpr_float upy, rpr_float upz); + -/** @brief -* -* -* @param shape The shape to set subdivision for -* @param type -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprShapeSetSubdivisionBoundaryInterop(rpr_shape shape, rpr_subdiv_boundary_interfop_type type); + /** @brief Set f-stop for the camera + * + * @param camera The camera to set f-stop for + * @param fstop f-stop value in mm^-1, default is FLT_MAX + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprCameraSetFStop(rpr_camera camera, rpr_float fstop); + + + /** @brief Set the number of aperture blades + * + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param camera The camera to set aperture blades for + * @param num_blades Number of aperture blades 4 to 32 + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprCameraSetApertureBlades(rpr_camera camera, rpr_uint num_blades); + + + /** @brief Set the exposure of a camera + * + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param camera The camera to set aperture blades for + * @param exposure Exposure value 0.0 - 1.0 + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprCameraSetExposure(rpr_camera camera, rpr_float exposure); + + + /** @brief Set camera mode + * + * Camera modes include: + * RPR_CAMERA_MODE_PERSPECTIVE + * RPR_CAMERA_MODE_ORTHOGRAPHIC + * RPR_CAMERA_MODE_LATITUDE_LONGITUDE_360 + * RPR_CAMERA_MODE_LATITUDE_LONGITUDE_STEREO + * RPR_CAMERA_MODE_CUBEMAP + * RPR_CAMERA_MODE_CUBEMAP_STEREO + * RPR_CAMERA_MODE_FISHEYE + * + * @param camera The camera to set mode for + * @param mode Camera mode, default is RPR_CAMERA_MODE_PERSPECTIVE + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprCameraSetMode(rpr_camera camera, rpr_camera_mode mode); + + + /** @brief Set orthographic view volume width + * + * @param camera The camera to set volume width for + * @param width View volume width in meters, default is 1 meter + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprCameraSetOrthoWidth(rpr_camera camera, rpr_float width); + extern RPR_API_ENTRY rpr_int rprCameraSetFocalTilt(rpr_camera camera, rpr_float tilt); + extern RPR_API_ENTRY rpr_int rprCameraSetIPD(rpr_camera camera, rpr_float ipd); + extern RPR_API_ENTRY rpr_int rprCameraSetLensShift(rpr_camera camera, rpr_float shiftx, rpr_float shifty); + extern RPR_API_ENTRY rpr_int rprCameraSetTiltCorrection(rpr_camera camera, rpr_float tiltX, rpr_float tiltY); + + + /** @brief Set orthographic view volume height + * + * @param camera The camera to set volume height for + * @param width View volume height in meters, default is 1 meter + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprCameraSetOrthoHeight(rpr_camera camera, rpr_float height); + + + /** @brief Set near plane of a camear + * + * @param camera The camera to set near plane for + * @param near Near plane distance in meters, default is 0.01f + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprCameraSetNearPlane(rpr_camera camera, rpr_float near); + + + /** @brief Set far plane of a camear + * + * @param camera The camera to set far plane for + * @param far Far plane distance in meters, default is 100000000.f + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprCameraSetFarPlane(rpr_camera camera, rpr_float far); + + /* rpr_image*/ + + /** @brief Query information about an image + * + * The workflow is usually two-step: query with the data == NULL to get the required buffer size, + * then query with size_ret == NULL to fill the buffer with the data + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param image An image object to query + * @param image_info The type of info to query + * @param size The size of the buffer pointed by data + * @param data The buffer to store queried info + * @param size_ret Returns the size in bytes of the data being queried + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprImageGetInfo(rpr_image image, rpr_image_info image_info, size_t size, void * data, size_t * size_ret); + + + /** @brief + * + * + * @param image The image to set wrap for + * @param type + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprImageSetWrap(rpr_image image, rpr_image_wrap_type type); + + + /** @brief + * + * + * @param image The image to set filter for + * @param type + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprImageSetFilter(rpr_image image, rpr_image_filter_type type); + + /** @brief + * + * @param image The image to set gamma for + * @param type + * @return RPR_SUCCESS in case of success, error code otherwise + */ + extern RPR_API_ENTRY rpr_int rprImageSetGamma(rpr_image image, rpr_float type); + + /** @brief + * + * @param image The image to set mipmap for + * @param enabled true (enable) or false (disable) + * @return RPR_SUCCESS in case of success, error code otherwise + */ + extern RPR_API_ENTRY rpr_int rprImageSetMipmapEnabled(rpr_image image, rpr_bool enabled); + + /* rpr_shape */ + + /** @brief Set shape world transform + * + * + * @param shape The shape to set transform for + * @param transpose Determines whether the basis vectors are in columns(false) or in rows(true) of the matrix + * @param transform Array of 16 rpr_float values (row-major form) + * @return RPR_SUCCESS in case of success, error code otherwise + */ -/** @brief Set displacement scale -* -* -* @param shape The shape to set subdivision for -* @param scale The amount of displacement applied -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprShapeSetDisplacementScale(rpr_shape shape, rpr_float minscale, rpr_float maxscale); + extern RPR_API_ENTRY rpr_int rprShapeSetTransform(rpr_shape shape, rpr_bool transpose, rpr_float const * transform); -/** @brief Set object group ID (mainly for debugging). -* -* -* @param shape The shape to set -* @param objectGroupID The ID -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprShapeSetObjectGroupID(rpr_shape shape, rpr_uint objectGroupID); -/** @brief Set displacement texture -* -* -* @param shape The shape to set subdivision for -* @param image Displacement texture (scalar displacement, only x component is used) -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprShapeSetDisplacementImage(rpr_shape shape, rpr_image image); - -/* rpr_shape */ -/** @brief Set shape material -* -*/ -extern RPR_API_ENTRY rpr_int rprShapeSetMaterial(rpr_shape shape, rpr_material_node node); + /** @brief Set shape subdivision + * + * + * @param shape The shape to set subdivision for + * @param factor Number of subdivision steps to do + * @return RPR_SUCCESS in case of success, error code otherwise + */ -/** @brief Set shape material override -* -*/ -extern RPR_API_ENTRY rpr_int rprShapeSetMaterialOverride(rpr_shape shape, rpr_material_node node); + extern RPR_API_ENTRY rpr_int rprShapeSetSubdivisionFactor(rpr_shape shape, rpr_uint factor); -/** @brief Set shape volume material -* -*/ -extern RPR_API_ENTRY rpr_int rprShapeSetVolumeMaterial(rpr_shape shape, rpr_material_node node); - -/** @brief Set shape linear motion - * - * @param shape The shape to set linear motion for - * @param x X component of a motion vector - * @param y Y component of a motion vector - * @param z Z component of a motion vector - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprShapeSetLinearMotion(rpr_shape shape, rpr_float x, rpr_float y, rpr_float z); - -/** @brief Set angular linear motion - * - * @param shape The shape to set linear motion for - * @param x X component of the rotation axis - * @param y Y component of the rotation axis - * @param z Z component of the rotation axis - * @param w W rotation angle in radians - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprShapeSetAngularMotion(rpr_shape shape, rpr_float x, rpr_float y, rpr_float z, rpr_float w); - -/** @brief Set visibility flag - * - * @param shape The shape to set visibility for - * @param visible Determines if the shape is visible or not - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprShapeSetVisibility(rpr_shape shape, rpr_bool visible); - -/** @brief Set visibility flag for primary rays -* -* @param shape The shape to set visibility for -* @param visible Determines if the shape is visible or not -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprShapeSetVisibilityPrimaryOnly(rpr_shape shape, rpr_bool visible); -/** @brief Set visibility flag for specular refleacted\refracted rays -* -* @param shape The shape to set visibility for -* @param visible Determines if the shape is visible or not -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprShapeSetVisibilityInSpecular(rpr_shape shape, rpr_bool visible); + /** @brief + * + * + * @param shape The shape to set subdivision for + * @param factor + * @return RPR_SUCCESS in case of success, error code otherwise + */ -/** @brief Set shadow catcher flag -* -* @param shape The shape to set shadow catcher flag for -* @param shadowCatcher Determines if the shape behaves as shadow catcher -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprShapeSetShadowCatcher(rpr_shape shape, rpr_bool shadowCatcher); + extern RPR_API_ENTRY rpr_int rprShapeSetSubdivisionCreaseWeight(rpr_shape shape, rpr_float factor); -/** @brief Set shadow flag -* -* @param shape The shape to set shadow flag for -* @param visible Determines if the shape casts shadow -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprShapeSetShadow(rpr_shape shape, rpr_bool casts_shadow); - -/** @brief Set light world transform - * - * - * @param light The light to set transform for - * @param transpose Determines whether the basis vectors are in columns(false) or in rows(true) of the matrix - * @param transform Array of 16 rpr_float values (row-major form) - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprLightSetTransform(rpr_light light, rpr_bool transpose, rpr_float const * transform); - -/** @brief Query information about a shape - * - * The workflow is usually two-step: query with the data == NULL to get the required buffer size, - * then query with size_ret == NULL to fill the buffer with the data - * Possible error codes: - * RPR_ERROR_INVALID_PARAMETER - * - * @param shape The shape object to query - * @param material_info The type of info to query - * @param size The size of the buffer pointed by data - * @param data The buffer to store queried info - * @param size_ret Returns the size in bytes of the data being queried - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprShapeGetInfo(rpr_shape arg0, rpr_shape_info arg1, size_t arg2, void * arg3, size_t * arg4); - -/* rpr_shape - mesh */ -/** @brief Query information about a mesh - * - * The workflow is usually two-step: query with the data == NULL to get the required buffer size, - * then query with size_ret == NULL to fill the buffer with the data - * Possible error codes: - * RPR_ERROR_INVALID_PARAMETER - * - * @param shape The mesh to query - * @param mesh_info The type of info to query - * @param size The size of the buffer pointed by data - * @param data The buffer to store queried info - * @param size_ret Returns the size in bytes of the data being queried - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprMeshGetInfo(rpr_shape mesh, rpr_mesh_info mesh_info, size_t size, void * data, size_t * size_ret); - -/** @brief Query information about a mesh polygon - * - * The workflow is usually two-step: query with the data == NULL to get the required buffer size, - * then query with size_ret == NULL to fill the buffer with the data - * - * Possible error codes: - * RPR_ERROR_INVALID_PARAMETER - * - * @param mesh The mesh to query - * @param polygon_index The index of a polygon - * @param polygon_info The type of info to query - * @param size The size of the buffer pointed by data - * @param data The buffer to store queried info - * @param size_ret Returns the size in bytes of the data being queried - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprMeshPolygonGetInfo(rpr_shape mesh, size_t polygon_index, rpr_mesh_polygon_info polygon_info, size_t size, void * data, size_t * size_ret); - -/** @brief Get the parent shape for an instance - * - * Possible error codes: - * RPR_ERROR_INVALID_PARAMETER - * - * @param shape The shape to get a parent shape from - * @param status RPR_SUCCESS in case of success, error code otherwise - * @return Shape object - */ -extern RPR_API_ENTRY rpr_int rprInstanceGetBaseShape(rpr_shape shape, rpr_shape * out_shape); - -/* rpr_light - point */ -/** @brief Create point light - * - * Create analytic point light represented by a point in space. - * Possible error codes: - * RPR_ERROR_OUT_OF_VIDEO_MEMORY - * RPR_ERROR_OUT_OF_SYSTEM_MEMORY - * - * @param context The context to create a light for - * @param status RPR_SUCCESS in case of success, error code otherwise - * @return Light object - */ -extern RPR_API_ENTRY rpr_int rprContextCreatePointLight(rpr_context context, rpr_light * out_light); - -/** @brief Set radiant power of a point light source - * - * @param r R component of a radiant power vector - * @param g G component of a radiant power vector - * @param b B component of a radiant power vector - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprPointLightSetRadiantPower3f(rpr_light light, rpr_float r, rpr_float g, rpr_float b); - -/* rpr_light - spot */ -/** @brief Create spot light - * - * Create analytic spot light - * - * Possible error codes: - * RPR_ERROR_OUT_OF_VIDEO_MEMORY - * RPR_ERROR_OUT_OF_SYSTEM_MEMORY - * - * @param context The context to create a light for - * @param status RPR_SUCCESS in case of success, error code otherwise - * @return Light object - */ -extern RPR_API_ENTRY rpr_int rprContextCreateSpotLight(rpr_context context, rpr_light * light); - -/** @brief Set radiant power of a spot light source - * - * @param r R component of a radiant power vector - * @param g G component of a radiant power vector - * @param b B component of a radiant power vector - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprSpotLightSetRadiantPower3f(rpr_light light, rpr_float r, rpr_float g, rpr_float b); - -/** @brief Set cone shape for a spot light - * - * Spot light produces smooth penumbra in a region between inner and outer circles, - * the area inside the inner cicrle receives full power while the area outside the - * outer one is fully in shadow. - * - * @param iangle Inner angle of a cone in radians - * @param oangle Outer angle of a coner in radians, should be greater that or equal to inner angle - * @return status RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprSpotLightSetConeShape(rpr_light light, rpr_float iangle, rpr_float oangle); - -/* rpr_light - directional */ -/** @brief Create directional light - * - * Create analytic directional light. - * Possible error codes: - * RPR_ERROR_OUT_OF_VIDEO_MEMORY - * RPR_ERROR_OUT_OF_SYSTEM_MEMORY - * - * @param context The context to create a light for - * @param status RPR_SUCCESS in case of success, error code otherwise - * @return light id of a newly created light - */ -extern RPR_API_ENTRY rpr_int rprContextCreateDirectionalLight(rpr_context context, rpr_light * out_light); - -/** @brief Set radiant power of a directional light source - * - * @param r R component of a radiant power vector - * @param g G component of a radiant power vector - * @param b B component of a radiant power vector - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprDirectionalLightSetRadiantPower3f(rpr_light light, rpr_float r, rpr_float g, rpr_float b); - -/** @brief Set softness of shadow produced by the light - * - * @param coeff value between [0;1]. 0.0 is sharp - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprDirectionalLightSetShadowSoftness(rpr_light light, rpr_float coeff); - -/* rpr_light - environment */ -/** @brief Create an environment light - * - * Environment light is a light based on lightprobe. - * Possible error codes: - * RPR_ERROR_OUT_OF_VIDEO_MEMORY - * RPR_ERROR_OUT_OF_SYSTEM_MEMORY - * - * @param context The context to create a light for - * @param status RPR_SUCCESS in case of success, error code otherwise - * @return Light object - */ -extern RPR_API_ENTRY rpr_int rprContextCreateEnvironmentLight(rpr_context context, rpr_light * out_light); - -/** @brief Set image for an environment light - * - * Possible error codes: - * RPR_ERROR_INVALID_PARAMETER - * RPR_ERROR_UNSUPPORTED_IMAGE_FORMAT - * - * @param env_light Environment light - * @param image Image object to set - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprEnvironmentLightSetImage(rpr_light env_light, rpr_image image); - -/** @brief Set intensity scale or an env light - * - * @param env_light Environment light - * @param intensity_scale Intensity scale - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprEnvironmentLightSetIntensityScale(rpr_light env_light, rpr_float intensity_scale); - -/** @brief Set portal for environment light to accelerate convergence of indoor scenes -* -* Possible error codes: -* RPR_ERROR_INVALID_PARAMETER -* -* @param env_light Environment light -* @param portal Portal mesh, might have multiple components -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprEnvironmentLightAttachPortal(rpr_light env_light, rpr_shape portal); -/** @brief Remove portal for environment light. -* -* Possible error codes: -* RPR_ERROR_INVALID_PARAMETER -* -* @param env_light Environment light -* @param portal Portal mesh, that have been added to light. -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprEnvironmentLightDetachPortal(rpr_light env_light, rpr_shape portal); - -/* rpr_light - sky */ -/** @brief Create sky light -* -* Analytical sky model -* Possible error codes: -* RPR_ERROR_OUT_OF_VIDEO_MEMORY -* RPR_ERROR_OUT_OF_SYSTEM_MEMORY -* -* @param context The context to create a light for -* @param status RPR_SUCCESS in case of success, error code otherwise -* @return Light object -*/ -extern RPR_API_ENTRY rpr_int rprContextCreateSkyLight(rpr_context context, rpr_light * out_light); + /** @brief + * + * + * @param shape The shape to set subdivision for + * @param type + * @return RPR_SUCCESS in case of success, error code otherwise + */ -/** @brief Set turbidity of a sky light -* -* @param skylight Sky light -* @param turbidity Turbidity value -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprSkyLightSetTurbidity(rpr_light skylight, rpr_float turbidity); + extern RPR_API_ENTRY rpr_int rprShapeSetSubdivisionBoundaryInterop(rpr_shape shape, rpr_subdiv_boundary_interfop_type type); -/** @brief Set albedo of a sky light -* -* @param skylight Sky light -* @param albedo Albedo value -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprSkyLightSetAlbedo(rpr_light skylight, rpr_float albedo); -/** @brief Set scale of a sky light -* -* @param skylight Sky light -* @param scale Scale value -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprSkyLightSetScale(rpr_light skylight, rpr_float scale); + /** @brief Call this function to automatically set the Subdivision Factor depending on the camera position, frame buffer size. + * You can retrieve the internally computed factor with rprShapeGetInfo(...,RPR_SHAPE_SUBDIVISION_FACTOR,...) + * You have to call this function each time you want to re-adapt the Subdivision Factor : + * internally the factor will NOT be automatically re-computed when camera/shape/framebuffer changes. + * + * @param shape The shape to set subdivision for + * @param framebuffer frame buffer used for factor adaptation + * @param camera camera used for factor adaptation + * @param factor factor to regulate the intensity of adaptation + * @return RPR_SUCCESS in case of success, error code otherwise + */ -/** @brief Set portal for sky light to accelerate convergence of indoor scenes -* -* Possible error codes: -* RPR_ERROR_INVALID_PARAMETER -* -* @param skylight Sky light -* @param portal Portal mesh, might have multiple components -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprSkyLightAttachPortal(rpr_light skylight, rpr_shape portal); + extern RPR_API_ENTRY rpr_int rprShapeAutoAdaptSubdivisionFactor(rpr_shape shape, rpr_framebuffer framebuffer, rpr_camera camera, rpr_int factor); -/** @brief Remove portal for Sky light. -* -* Possible error codes: -* RPR_ERROR_INVALID_PARAMETER -* -* @param env_light Sky light -* @param portal Portal mesh, that have been added to light. -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprSkyLightDetachPortal(rpr_light skylight, rpr_shape portal); -/** @brief Create IES light -* -* Create IES light -* -* Possible error codes: -* RPR_ERROR_OUT_OF_VIDEO_MEMORY -* RPR_ERROR_OUT_OF_SYSTEM_MEMORY -* -* @param context The context to create a light for -* @param status RPR_SUCCESS in case of success, error code otherwise -* @return Light object -*/ -extern RPR_API_ENTRY rpr_int rprContextCreateIESLight(rpr_context context, rpr_light * light); + /** @brief Set displacement scale + * + * + * @param shape The shape to set subdivision for + * @param scale The amount of displacement applied + * @return RPR_SUCCESS in case of success, error code otherwise + */ -/** @brief Set radiant power of a IES light source -* -* @param r R component of a radiant power vector -* @param g G component of a radiant power vector -* @param b B component of a radiant power vector -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprIESLightSetRadiantPower3f(rpr_light light, rpr_float r, rpr_float g, rpr_float b); - -/** @brief Set image for an IES light -* -* Possible error codes: -* RPR_ERROR_INVALID_PARAMETER -* RPR_ERROR_UNSUPPORTED_IMAGE_FORMAT : If the format of the IES file is not supported by Radeon ProRender. -* RPR_ERROR_IO_ERROR : If the IES image path file doesn't exist. -* -* @param env_light Environment light -* @param imagePath Image path to set -* @param nx resolution X of the IES image -* @param ny resolution Y of the IES image -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprIESLightSetImageFromFile(rpr_light env_light, rpr_char const * imagePath, rpr_int nx, rpr_int ny); - -/** @brief Set image for an IES light -* -* Possible error codes: -* RPR_ERROR_INVALID_PARAMETER -* RPR_ERROR_UNSUPPORTED_IMAGE_FORMAT : If the format of the IES data is not supported by Radeon ProRender. -* -* @param env_light Environment light -* @param iesData Image data string defining the IES. null terminated string. IES format. -* @param nx resolution X of the IES image -* @param ny resolution Y of the IES image -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprIESLightSetImageFromIESdata(rpr_light env_light, rpr_char const * iesData, rpr_int nx, rpr_int ny); - -/* rpr_light */ -/** @brief Query information about a light - * - * The workflow is usually two-step: query with the data == NULL to get the required buffer size, - * then query with size_ret == NULL to fill the buffer with the data - * Possible error codes: - * RPR_ERROR_INVALID_PARAMETER - * - * @param light The light to query - * @param light_info The type of info to query - * @param size The size of the buffer pointed by data - * @param data The buffer to store queried info - * @param size_ret Returns the size in bytes of the data being queried - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprLightGetInfo(rpr_light light, rpr_light_info info, size_t size, void * data, size_t * size_ret); - -/* rpr_scene */ -/** @brief Remove all objects from a scene - * - * A scene is essentially a collection of shapes, lights and volume regions. - * - * @param scene The scene to clear - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprSceneClear(rpr_scene scene); - -/** @brief Attach a shape to the scene - * - * A scene is essentially a collection of shapes, lights and volume regions. - * - * @param scene The scene to attach - * @param shape The shape to attach - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprSceneAttachShape(rpr_scene scene, rpr_shape shape); - -/** @brief Detach a shape from the scene - * - * A scene is essentially a collection of shapes, lights and volume regions. - * - * @param scene The scene to dettach from - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprSceneDetachShape(rpr_scene scene, rpr_shape shape); - -/** @brief Attach a light to the scene - * - * A scene is essentially a collection of shapes, lights and volume regions - * - * @param scene The scene to attach - * @param light The light to attach - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprSceneAttachLight(rpr_scene scene, rpr_light light); - -/** @brief Detach a light from the scene - * - * A scene is essentially a collection of shapes, lights and volume regions - * - * @param scene The scene to dettach from - * @param light The light to detach - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprSceneDetachLight(rpr_scene scene, rpr_light light); - -/** @brief Query information about a scene - * - * The workflow is usually two-step: query with the data == NULL to get the required buffer size, - * then query with size_ret == NULL to fill the buffer with the data - * Possible error codes: - * RPR_ERROR_INVALID_PARAMETER - * - * @param scene The scene to query - * @param info The type of info to query - * @param size The size of the buffer pointed by data - * @param data The buffer to store queried info - * @param size_ret Returns the size in bytes of the data being queried - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprSceneGetInfo(rpr_scene scene, rpr_scene_info info, size_t size, void * data, size_t * size_ret); - -/** @brief Get background override light -* Possible error codes: -* RPR_ERROR_INVALID_PARAMETER -* -* @param scene The scene to set background for -* @param overrride overrride type -* @param out_light light returned -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprSceneGetEnvironmentOverride(rpr_scene scene, rpr_environment_override overrride, rpr_light * out_light); - -/** @brief Set background light for the scene which does not affect the scene lighting, -* but gets shown as a background image -* Possible error codes: -* RPR_ERROR_INVALID_PARAMETER -* -* @param scene The scene to set background for -* @param light Background light -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprSceneSetEnvironmentOverride(rpr_scene scene, rpr_environment_override overrride, rpr_light light); - -/** @brief Set background image for the scene which does not affect the scene lighting, -* it is shown as view-independent rectangular background -* Possible error codes: -* RPR_ERROR_INVALID_PARAMETER -* -* @param scene The scene to set background for -* @param image Background image -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprSceneSetBackgroundImage(rpr_scene scene, rpr_image image); + extern RPR_API_ENTRY rpr_int rprShapeSetDisplacementScale(rpr_shape shape, rpr_float minscale, rpr_float maxscale); -/** @brief Get background image -* -* @param scene The scene to get background image from -* @param status RPR_SUCCESS in case of success, error code otherwise -* @return Image object -*/ -extern RPR_API_ENTRY rpr_int rprSceneGetBackgroundImage(rpr_scene scene, rpr_image * out_image); - -/** @brief Set camera for the scene - * - * This is the main camera which for rays generation for the scene. - * - * @param scene The scene to set camera for - * @param camera Camera - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprSceneSetCamera(rpr_scene scene, rpr_camera camera); - -/** @brief Get camera for the scene - * - * @param scene The scene to get camera for - * @param status RPR_SUCCESS in case of success, error code otherwise - * @return camera id for the camera if any, NULL otherwise - */ -extern RPR_API_ENTRY rpr_int rprSceneGetCamera(rpr_scene scene, rpr_camera * out_camera); - -/* rpr_framebuffer*/ -/** @brief Query information about a framebuffer - * - * The workflow is usually two-step: query with the data == NULL to get the required buffer size, - * then query with size_ret == NULL to fill the buffer with the data - * Possible error codes: - * RPR_ERROR_INVALID_PARAMETER - * - * @param framebuffer Framebuffer object to query - * @param info The type of info to query - * @param size The size of the buffer pointed by data - * @param data The buffer to store queried info - * @param size_ret Returns the size in bytes of the data being queried - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprFrameBufferGetInfo(rpr_framebuffer framebuffer, rpr_framebuffer_info info, size_t size, void * data, size_t * size_ret); - -/** @brief Clear contents of a framebuffer to zero - * - * Possible error codes: - * RPR_ERROR_OUT_OF_SYSTEM_MEMORY - * RPR_ERROR_OUT_OF_VIDEO_MEMORY - * - * The call is blocking and the image is ready when returned - * - * @param frame_buffer Framebuffer to clear - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprFrameBufferClear(rpr_framebuffer frame_buffer); - -/** @brief Save frame buffer to file - * - * Possible error codes: - * RPR_ERROR_OUT_OF_SYSTEM_MEMORY - * RPR_ERROR_OUT_OF_VIDEO_MEMORY - * - * @param frame_buffer Frame buffer to save - * @param path Path to file - * @return RPR_SUCCESS in case of success, error code otherwise - */ -extern RPR_API_ENTRY rpr_int rprFrameBufferSaveToFile(rpr_framebuffer frame_buffer, rpr_char const * file_path); - -/** @brief Resolve framebuffer -* -* Resolve applies AA filters and tonemapping operators to the framebuffer data -* -* Possible error codes: -* RPR_ERROR_OUT_OF_SYSTEM_MEMORY -* RPR_ERROR_OUT_OF_VIDEO_MEMORY -*/ -extern RPR_API_ENTRY rpr_int rprContextResolveFrameBuffer(rpr_context context, rpr_framebuffer src_frame_buffer, rpr_framebuffer dst_frame_buffer, rpr_bool normalizeOnly = false); -/** @brief Create material system -* -* Possible error codes: -* RPR_ERROR_OUT_OF_SYSTEM_MEMORY -* RPR_ERROR_OUT_OF_VIDEO_MEMORY -* -*/ -extern RPR_API_ENTRY rpr_int rprContextCreateMaterialSystem(rpr_context in_context, rpr_material_system_type type, rpr_material_system * out_matsys); + /** @brief Set object group ID (mainly for debugging). + * + * + * @param shape The shape to set + * @param objectGroupID The ID + * @return RPR_SUCCESS in case of success, error code otherwise + */ -/** @brief Create material node -* -* Possible error codes: -* RPR_ERROR_OUT_OF_SYSTEM_MEMORY -* RPR_ERROR_OUT_OF_VIDEO_MEMORY -* -*/ -extern RPR_API_ENTRY rpr_int rprMaterialSystemCreateNode(rpr_material_system in_matsys, rpr_material_node_type in_type, rpr_material_node * out_node); + extern RPR_API_ENTRY rpr_int rprShapeSetObjectGroupID(rpr_shape shape, rpr_uint objectGroupID); -/** @brief Connect nodes -* -* Possible error codes: -* RPR_ERROR_OUT_OF_SYSTEM_MEMORY -* RPR_ERROR_OUT_OF_VIDEO_MEMORY -* -*/ -extern RPR_API_ENTRY rpr_int rprMaterialNodeSetInputN(rpr_material_node in_node, rpr_char const * in_input, rpr_material_node in_input_node); -/** @brief Set float input value -* -* Possible error codes: -* RPR_ERROR_OUT_OF_SYSTEM_MEMORY -* RPR_ERROR_OUT_OF_VIDEO_MEMORY -* -*/ -extern RPR_API_ENTRY rpr_int rprMaterialNodeSetInputF(rpr_material_node in_node, rpr_char const * in_input, rpr_float in_value_x, rpr_float in_value_y, rpr_float in_value_z, rpr_float in_value_w); + /** @brief Set object rendering layer mask + * then, use rprContextSetParameter1u(context,"renderLayerMask",mask) + * in order to render only a group of shape + * + * @param shape The shape to set + * @param layerMask The render mask + * @return RPR_SUCCESS in case of success, error code otherwise + */ -/** @brief Set uint input value -* -* Possible error codes: -* RPR_ERROR_OUT_OF_SYSTEM_MEMORY -* RPR_ERROR_OUT_OF_VIDEO_MEMORY -* -*/ -extern RPR_API_ENTRY rpr_int rprMaterialNodeSetInputU(rpr_material_node in_node, rpr_char const * in_input, rpr_uint in_value); + extern RPR_API_ENTRY rpr_int rprShapeSetLayerMask(rpr_shape shape, rpr_uint layerMask); -/** @brief Set image input value -* -* Possible error codes: -* RPR_ERROR_OUT_OF_SYSTEM_MEMORY -* RPR_ERROR_OUT_OF_VIDEO_MEMORY -* -*/ -extern RPR_API_ENTRY rpr_int rprMaterialNodeSetInputImageData(rpr_material_node in_node, rpr_char const * in_input, rpr_image image); -extern RPR_API_ENTRY rpr_int rprMaterialNodeGetInfo(rpr_material_node in_node, rpr_material_node_info in_info, size_t in_size, void * in_data, size_t * out_size); -extern RPR_API_ENTRY rpr_int rprMaterialNodeGetInputInfo(rpr_material_node in_node, rpr_int in_input_idx, rpr_material_node_input_info in_info, size_t in_size, void * in_data, size_t * out_size); -/** @brief Delete object -* -* rprObjectDelete(obj) deletes 'obj' from memory. -* User has to make sure that 'obj' will not be used anymore after this call. -* -* Possible error codes: -* RPR_ERROR_OUT_OF_SYSTEM_MEMORY -* RPR_ERROR_OUT_OF_VIDEO_MEMORY -* -*/ -extern RPR_API_ENTRY rpr_int rprObjectDelete(void * obj); + /** @brief Set displacement texture + * + * + * @param shape The shape to set subdivision for + * @param materialNode Displacement texture , as material. + * @return RPR_SUCCESS in case of success, error code otherwise + */ -/** @brief Set material node name -* -* -* @param node Node to set the name for -* @param name NULL terminated string name -* @return RPR_SUCCESS in case of success, error code otherwise -*/ -extern RPR_API_ENTRY rpr_int rprObjectSetName(void * node, rpr_char const * name); - -/* rpr_post_effect */ -/** @brief Create post effect -* -* Create analytic point light represented by a point in space. -* Possible error codes: -* RPR_ERROR_OUT_OF_VIDEO_MEMORY -* RPR_ERROR_OUT_OF_SYSTEM_MEMORY -* -* @param context The context to create a light for -* @param status RPR_SUCCESS in case of success, error code otherwise -* @return Light object -*/ -extern RPR_API_ENTRY rpr_int rprContextCreatePostEffect(rpr_context context, rpr_post_effect_type type, rpr_post_effect * out_effect); -extern RPR_API_ENTRY rpr_int rprContextAttachPostEffect(rpr_context context, rpr_post_effect effect); -extern RPR_API_ENTRY rpr_int rprContextDetachPostEffect(rpr_context context, rpr_post_effect effect); -extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter1u(rpr_post_effect effect, rpr_char const * name, rpr_uint x); -extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter1f(rpr_post_effect effect, rpr_char const * name, rpr_float x); -extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter3f(rpr_post_effect effect, rpr_char const * name, rpr_float x, rpr_float y, rpr_float z); -extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, rpr_char const * name, rpr_float x, rpr_float y, rpr_float z, rpr_float w); -/***************compatibility part***************/ -#define FR_API_VERSION 0x010000252 + extern RPR_API_ENTRY rpr_int rprShapeSetDisplacementMaterial(rpr_shape shape, rpr_material_node materialNode); + + + /** @brief Set shape material + * + */ + + extern RPR_API_ENTRY rpr_int rprShapeSetMaterial(rpr_shape shape, rpr_material_node node); + + + /** @brief Set shape materials for specific faces + * + * @param shape The shape to set the material for + * @param node The material to set + * @param face_indices + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprShapeSetMaterialFaces(rpr_shape shape, rpr_material_node node, rpr_int* face_indices, size_t num_faces); + + + + + + /** @brief Set shape volume material + * + */ + + extern RPR_API_ENTRY rpr_int rprShapeSetVolumeMaterial(rpr_shape shape, rpr_material_node node); + + + /** @brief Set shape linear motion + * + * @param shape The shape to set linear motion for + * @param x X component of a motion vector + * @param y Y component of a motion vector + * @param z Z component of a motion vector + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprShapeSetLinearMotion(rpr_shape shape, rpr_float x, rpr_float y, rpr_float z); + + + /** @brief Set angular linear motion + * + * @param shape The shape to set linear motion for + * @param x X component of the rotation axis + * @param y Y component of the rotation axis + * @param z Z component of the rotation axis + * @param w W rotation angle in radians + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprShapeSetAngularMotion(rpr_shape shape, rpr_float x, rpr_float y, rpr_float z, rpr_float w); + + + /** @brief Set scale linear motion + * + * @param shape The shape to set linear motion for + * @param x X component of the scale + * @param y Y component of the scale + * @param z Z component of the scale + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprShapeSetScaleMotion(rpr_shape shape, rpr_float x, rpr_float y, rpr_float z); + + + /** @brief Set visibility flag + * + * @param shape The shape to set visibility for + * @param visible Determines if the shape is visible or not + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprShapeSetVisibility(rpr_shape shape, rpr_bool visible); + + + /** @brief Set visibility flag for primary rays + * + * @param shape The shape to set visibility for + * @param visible Determines if the shape is visible or not + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprShapeSetVisibilityPrimaryOnly(rpr_shape shape, rpr_bool visible); + + + /** @brief Set visibility flag for specular refleacted\refracted rays + * + * @param shape The shape to set visibility for + * @param visible Determines if the shape is visible or not + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprShapeSetVisibilityInSpecular(rpr_shape shape, rpr_bool visible); + + + /** @brief Set shadow catcher flag + * + * @param shape The shape to set shadow catcher flag for + * @param shadowCatcher Determines if the shape behaves as shadow catcher + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprShapeSetShadowCatcher(rpr_shape shape, rpr_bool shadowCatcher); + + + /** @brief Set shadow flag + * + * @param shape The shape to set shadow flag for + * @param visible Determines if the shape casts shadow + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprShapeSetShadow(rpr_shape shape, rpr_bool casts_shadow); + + + /** @brief Set light world transform + * + * + * @param light The light to set transform for + * @param transpose Determines whether the basis vectors are in columns(false) or in rows(true) of the matrix + * @param transform Array of 16 rpr_float values (row-major form) + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprLightSetTransform(rpr_light light, rpr_bool transpose, rpr_float const * transform); + + + /** @brief Set light group ID. This parameter can be used with RPR_AOV_LIGHT_GROUP0, RPR_AOV_LIGHT_GROUP1, RPR_AOV_LIGHT_GROUP2, RPR_AOV_LIGHT_GROUP3 + * + * @param light The light to set transform for + * @param groupId -1 to remove the group. or a value between 0 and 3. + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprLightSetGroupId(rpr_light light, rpr_uint groupId); + + + /** @brief Query information about a shape + * + * The workflow is usually two-step: query with the data == NULL to get the required buffer size, + * then query with size_ret == NULL to fill the buffer with the data + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param shape The shape object to query + * @param material_info The type of info to query + * @param size The size of the buffer pointed by data + * @param data The buffer to store queried info + * @param size_ret Returns the size in bytes of the data being queried + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprShapeGetInfo(rpr_shape arg0, rpr_shape_info arg1, size_t arg2, void * arg3, size_t * arg4); + + /* rpr_shape - mesh */ + + /** @brief Query information about a mesh + * + * The workflow is usually two-step: query with the data == NULL to get the required buffer size, + * then query with size_ret == NULL to fill the buffer with the data + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param shape The mesh to query + * @param mesh_info The type of info to query + * @param size The size of the buffer pointed by data + * @param data The buffer to store queried info + * @param size_ret Returns the size in bytes of the data being queried + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprMeshGetInfo(rpr_shape mesh, rpr_mesh_info mesh_info, size_t size, void * data, size_t * size_ret); + + + /** @brief Query information about a hetero volume + * + * The workflow is usually two-step: query with the data == NULL to get the required buffer size, + * then query with size_ret == NULL to fill the buffer with the data + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param heteroVol The heteroVolume to query + * @param heteroVol_info The type of info to query + * @param size The size of the buffer pointed by data + * @param data The buffer to store queried info + * @param size_ret Returns the size in bytes of the data being queried + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprHeteroVolumeGetInfo(rpr_hetero_volume heteroVol, rpr_hetero_volume_parameter heteroVol_info, size_t size, void * data, size_t * size_ret); + + + /** @brief Query information about a Buffer + * + * The workflow is usually two-step: query with the data == NULL to get the required buffer size, + * then query with size_ret == NULL to fill the buffer with the data + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param buffer The heteroVolume to query + * @param buffer_info The type of info to query + * @param size The size of the buffer pointed by data + * @param data The buffer to store queried info + * @param size_ret Returns the size in bytes of the data being queried + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprBufferGetInfo(rpr_buffer buffer, rpr_buffer_info buffer_info, size_t size, void * data, size_t * size_ret); + + + /** @brief Query information about a mesh polygon + * + * The workflow is usually two-step: query with the data == NULL to get the required buffer size, + * then query with size_ret == NULL to fill the buffer with the data + * + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param mesh The mesh to query + * @param polygon_index The index of a polygon + * @param polygon_info The type of info to query + * @param size The size of the buffer pointed by data + * @param data The buffer to store queried info + * @param size_ret Returns the size in bytes of the data being queried + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprMeshPolygonGetInfo(rpr_shape mesh, size_t polygon_index, rpr_mesh_polygon_info polygon_info, size_t size, void * data, size_t * size_ret); + + + /** @brief Get the parent shape for an instance + * + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param shape The shape to get a parent shape from + * @param status RPR_SUCCESS in case of success, error code otherwise + * @return Shape object + */ + + extern RPR_API_ENTRY rpr_int rprInstanceGetBaseShape(rpr_shape shape, rpr_shape * out_shape); + + /* rpr_light - point */ + + /** @brief Create point light + * + * Create analytic point light represented by a point in space. + * Possible error codes: + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * + * @param context The context to create a light for + * @param status RPR_SUCCESS in case of success, error code otherwise + * @return Light object + */ + + extern RPR_API_ENTRY rpr_int rprContextCreatePointLight(rpr_context context, rpr_light * out_light); + + + /** @brief Set radiant power of a point light source + * + * @param r R component of a radiant power vector + * @param g G component of a radiant power vector + * @param b B component of a radiant power vector + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprPointLightSetRadiantPower3f(rpr_light light, rpr_float r, rpr_float g, rpr_float b); + + /* rpr_light - spot */ + + /** @brief Create spot light + * + * Create analytic spot light + * + * Possible error codes: + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * + * @param context The context to create a light for + * @param status RPR_SUCCESS in case of success, error code otherwise + * @return Light object + */ + + extern RPR_API_ENTRY rpr_int rprContextCreateSpotLight(rpr_context context, rpr_light * light); + + + /** @brief Set radiant power of a spot light source + * + * @param r R component of a radiant power vector + * @param g G component of a radiant power vector + * @param b B component of a radiant power vector + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSpotLightSetRadiantPower3f(rpr_light light, rpr_float r, rpr_float g, rpr_float b); + + + /** @brief Set cone shape for a spot light + * + * Spot light produces smooth penumbra in a region between inner and outer circles, + * the area inside the inner cicrle receives full power while the area outside the + * outer one is fully in shadow. + * + * @param iangle Inner angle of a cone in radians + * @param oangle Outer angle of a coner in radians, should be greater that or equal to inner angle + * @return status RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSpotLightSetConeShape(rpr_light light, rpr_float iangle, rpr_float oangle); + + /* rpr_light - directional */ + + /** @brief Create directional light + * + * Create analytic directional light. + * Possible error codes: + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * + * @param context The context to create a light for + * @param status RPR_SUCCESS in case of success, error code otherwise + * @return light id of a newly created light + */ + + extern RPR_API_ENTRY rpr_int rprContextCreateDirectionalLight(rpr_context context, rpr_light * out_light); + + + /** @brief Set radiant power of a directional light source + * + * @param r R component of a radiant power vector + * @param g G component of a radiant power vector + * @param b B component of a radiant power vector + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprDirectionalLightSetRadiantPower3f(rpr_light light, rpr_float r, rpr_float g, rpr_float b); + + + /** @brief Set softness of shadow produced by the light + * + * @param coeff value between [0;1]. 0.0 is sharp + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprDirectionalLightSetShadowSoftness(rpr_light light, rpr_float coeff); + + /* rpr_light - environment */ + + /** @brief Create an environment light + * + * Environment light is a light based on lightprobe. + * Possible error codes: + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * + * @param context The context to create a light for + * @param status RPR_SUCCESS in case of success, error code otherwise + * @return Light object + */ + + extern RPR_API_ENTRY rpr_int rprContextCreateEnvironmentLight(rpr_context context, rpr_light * out_light); + + + /** @brief Set image for an environment light + * + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * RPR_ERROR_UNSUPPORTED_IMAGE_FORMAT + * + * @param env_light Environment light + * @param image Image object to set + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprEnvironmentLightSetImage(rpr_light env_light, rpr_image image); + + + /** @brief Set intensity scale or an env light + * + * @param env_light Environment light + * @param intensity_scale Intensity scale + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprEnvironmentLightSetIntensityScale(rpr_light env_light, rpr_float intensity_scale); + + + /** @brief Set portal for environment light to accelerate convergence of indoor scenes + * + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param env_light Environment light + * @param portal Portal mesh, might have multiple components + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprEnvironmentLightAttachPortal(rpr_scene scene, rpr_light env_light, rpr_shape portal); + + + /** @brief Remove portal for environment light. + * + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param env_light Environment light + * @param portal Portal mesh, that have been added to light. + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprEnvironmentLightDetachPortal(rpr_scene scene, rpr_light env_light, rpr_shape portal); + + /* rpr_light - sky */ + + /** @brief Create sky light + * + * Analytical sky model + * Possible error codes: + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * + * @param context The context to create a light for + * @param status RPR_SUCCESS in case of success, error code otherwise + * @return Light object + */ + + extern RPR_API_ENTRY rpr_int rprContextCreateSkyLight(rpr_context context, rpr_light * out_light); + + + /** @brief Set turbidity of a sky light + * + * @param skylight Sky light + * @param turbidity Turbidity value + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSkyLightSetTurbidity(rpr_light skylight, rpr_float turbidity); + + + /** @brief Set albedo of a sky light + * + * @param skylight Sky light + * @param albedo Albedo value + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSkyLightSetAlbedo(rpr_light skylight, rpr_float albedo); + + + /** @brief Set scale of a sky light + * + * @param skylight Sky light + * @param scale Scale value + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSkyLightSetScale(rpr_light skylight, rpr_float scale); + + + /** @brief Set the direction of the sky light + * + * @param skylight Sky light + * @param x direction x + * @param y direction y + * @param z direction z + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSkyLightSetDirection(rpr_light skylight, rpr_float x, rpr_float y, rpr_float z); + + + /** @brief Set portal for sky light to accelerate convergence of indoor scenes + * + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param skylight Sky light + * @param portal Portal mesh, might have multiple components + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSkyLightAttachPortal(rpr_scene scene, rpr_light skylight, rpr_shape portal); + + + /** @brief Remove portal for Sky light. + * + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param env_light Sky light + * @param portal Portal mesh, that have been added to light. + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSkyLightDetachPortal(rpr_scene scene, rpr_light skylight, rpr_shape portal); + + + /** @brief Create IES light + * + * Create IES light + * + * Possible error codes: + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * + * @param context The context to create a light for + * @param status RPR_SUCCESS in case of success, error code otherwise + * @return Light object + */ + + extern RPR_API_ENTRY rpr_int rprContextCreateIESLight(rpr_context context, rpr_light * light); + + + /** @brief Set radiant power of a IES light source + * + * @param r R component of a radiant power vector + * @param g G component of a radiant power vector + * @param b B component of a radiant power vector + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprIESLightSetRadiantPower3f(rpr_light light, rpr_float r, rpr_float g, rpr_float b); + + + /** @brief Set image for an IES light + * + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * RPR_ERROR_UNSUPPORTED_IMAGE_FORMAT : If the format of the IES file is not supported by Radeon ProRender. + * RPR_ERROR_IO_ERROR : If the IES image path file doesn't exist. + * + * @param env_light Environment light + * @param imagePath Image path to set + * @param nx resolution X of the IES image + * @param ny resolution Y of the IES image + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprIESLightSetImageFromFile(rpr_light env_light, rpr_char const * imagePath, rpr_int nx, rpr_int ny); + + + /** @brief Set image for an IES light + * + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * RPR_ERROR_UNSUPPORTED_IMAGE_FORMAT : If the format of the IES data is not supported by Radeon ProRender. + * + * @param env_light Environment light + * @param iesData Image data string defining the IES. null terminated string. IES format. + * @param nx resolution X of the IES image + * @param ny resolution Y of the IES image + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprIESLightSetImageFromIESdata(rpr_light env_light, rpr_char const * iesData, rpr_int nx, rpr_int ny); + + /* rpr_light */ + + /** @brief Query information about a light + * + * The workflow is usually two-step: query with the data == NULL to get the required buffer size, + * then query with size_ret == NULL to fill the buffer with the data + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param light The light to query + * @param light_info The type of info to query + * @param size The size of the buffer pointed by data + * @param data The buffer to store queried info + * @param size_ret Returns the size in bytes of the data being queried + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprLightGetInfo(rpr_light light, rpr_light_info info, size_t size, void * data, size_t * size_ret); + + /* rpr_scene */ + + /** @brief Remove all objects from a scene + * Also detaches the camera + * + * A scene is essentially a collection of shapes, lights and volume regions. + * + * @param scene The scene to clear + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSceneClear(rpr_scene scene); + + + /** @brief Attach a shape to the scene + * + * A scene is essentially a collection of shapes, lights and volume regions. + * + * @param scene The scene to attach + * @param shape The shape to attach + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSceneAttachShape(rpr_scene scene, rpr_shape shape); + + + /** @brief Detach a shape from the scene + * + * A scene is essentially a collection of shapes, lights and volume regions. + * + * @param scene The scene to dettach from + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSceneDetachShape(rpr_scene scene, rpr_shape shape); + + + /** @brief Attach a heteroVolume to the scene + * + * A scene is essentially a collection of shapes, lights and volume regions. + * + * @param scene The scene to attach + * @param heteroVolume The heteroVolume to attach + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSceneAttachHeteroVolume(rpr_scene scene, rpr_hetero_volume heteroVolume); + + + /** @brief Detach a heteroVolume from the scene + * + * A scene is essentially a collection of shapes, lights and volume regions. + * + * @param scene The scene to dettach from + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSceneDetachHeteroVolume(rpr_scene scene, rpr_hetero_volume heteroVolume); + + + /** @brief Attach a light to the scene + * + * A scene is essentially a collection of shapes, lights and volume regions + * + * @param scene The scene to attach + * @param light The light to attach + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSceneAttachLight(rpr_scene scene, rpr_light light); + + + /** @brief Detach a light from the scene + * + * A scene is essentially a collection of shapes, lights and volume regions + * + * @param scene The scene to dettach from + * @param light The light to detach + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSceneDetachLight(rpr_scene scene, rpr_light light); + + + /** @brief Query information about a scene + * + * The workflow is usually two-step: query with the data == NULL to get the required buffer size, + * then query with size_ret == NULL to fill the buffer with the data + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param scene The scene to query + * @param info The type of info to query + * @param size The size of the buffer pointed by data + * @param data The buffer to store queried info + * @param size_ret Returns the size in bytes of the data being queried + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSceneGetInfo(rpr_scene scene, rpr_scene_info info, size_t size, void * data, size_t * size_ret); + + + /** @brief Get background override light + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param scene The scene to set background for + * @param overrride overrride type + * @param out_light light returned + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSceneGetEnvironmentOverride(rpr_scene scene, rpr_environment_override overrride, rpr_light * out_light); + + + /** @brief Set background light for the scene which does not affect the scene lighting, + * but gets shown as a background image + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param scene The scene to set background for + * @param light Background light + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSceneSetEnvironmentOverride(rpr_scene scene, rpr_environment_override overrride, rpr_light light); + + + /** @brief Set background image for the scene which does not affect the scene lighting, + * it is shown as view-independent rectangular background + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param scene The scene to set background for + * @param image Background image + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSceneSetBackgroundImage(rpr_scene scene, rpr_image image); + + + /** @brief Get background image + * + * @param scene The scene to get background image from + * @param status RPR_SUCCESS in case of success, error code otherwise + * @return Image object + */ + + extern RPR_API_ENTRY rpr_int rprSceneGetBackgroundImage(rpr_scene scene, rpr_image * out_image); + + + /** @brief Set camera for the scene + * + * This is the main camera which for rays generation for the scene. + * + * @param scene The scene to set camera for + * @param camera Camera + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSceneSetCamera(rpr_scene scene, rpr_camera camera); + + + /** @brief Get camera for the scene + * + * @param scene The scene to get camera for + * @param status RPR_SUCCESS in case of success, error code otherwise + * @return camera id for the camera if any, NULL otherwise + */ + + extern RPR_API_ENTRY rpr_int rprSceneGetCamera(rpr_scene scene, rpr_camera * out_camera); + + + /** @brief Query information about a framebuffer + * + * The workflow is usually two-step: query with the data == NULL to get the required buffer size, + * then query with size_ret == NULL to fill the buffer with the data + * Possible error codes: + * RPR_ERROR_INVALID_PARAMETER + * + * @param framebuffer Framebuffer object to query + * @param info The type of info to query + * @param size The size of the buffer pointed by data + * @param data The buffer to store queried info + * @param size_ret Returns the size in bytes of the data being queried + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprFrameBufferGetInfo(rpr_framebuffer framebuffer, rpr_framebuffer_info info, size_t size, void * data, size_t * size_ret); + + + /** @brief Clear contents of a framebuffer to zero + * + * Possible error codes: + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * + * The call is blocking and the image is ready when returned + * + * @param frame_buffer Framebuffer to clear + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprFrameBufferClear(rpr_framebuffer frame_buffer); + + + /** @brief Save frame buffer to file + * + * Possible error codes: + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * + * @param frame_buffer Frame buffer to save + * @param path Path to file + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprFrameBufferSaveToFile(rpr_framebuffer frame_buffer, rpr_char const * file_path); + + + /** @brief Resolve framebuffer + * + * Resolve applies AA filters and tonemapping operators to the framebuffer data + * + * Possible error codes: + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + */ + + extern RPR_API_ENTRY rpr_int rprContextResolveFrameBuffer(rpr_context context, rpr_framebuffer src_frame_buffer, rpr_framebuffer dst_frame_buffer, rpr_bool normalizeOnly = false); + + + /** @brief Create material system + * + * Possible error codes: + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * + */ + + extern RPR_API_ENTRY rpr_int rprContextCreateMaterialSystem(rpr_context in_context, rpr_material_system_type type, rpr_material_system * out_matsys); + + + /** @brief Create material node + * + * Possible error codes: + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * + */ + + extern RPR_API_ENTRY rpr_int rprMaterialSystemGetSize(rpr_context in_context, rpr_uint * out_size); + + + /** @brief Returns the number of material nodes for a given material system + * + * Possible error codes: + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * + */ + + extern RPR_API_ENTRY rpr_int rprMaterialSystemCreateNode(rpr_material_system in_matsys, rpr_material_node_type in_type, rpr_material_node * out_node); + + + /** @brief Connect nodes + * + * Possible error codes: + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * + */ + + extern RPR_API_ENTRY rpr_int rprMaterialNodeSetInputN(rpr_material_node in_node, rpr_char const * in_input, rpr_material_node in_input_node); + + + /** @brief Set float input value + * + * Possible error codes: + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * + */ + + extern RPR_API_ENTRY rpr_int rprMaterialNodeSetInputF(rpr_material_node in_node, rpr_char const * in_input, rpr_float in_value_x, rpr_float in_value_y, rpr_float in_value_z, rpr_float in_value_w); + + + /** @brief Set uint input value + * + * Possible error codes: + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * + */ + + extern RPR_API_ENTRY rpr_int rprMaterialNodeSetInputU(rpr_material_node in_node, rpr_char const * in_input, rpr_uint in_value); + + + /** @brief Set image input value + * + * Possible error codes: + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * + */ + + extern RPR_API_ENTRY rpr_int rprMaterialNodeSetInputImageData(rpr_material_node in_node, rpr_char const * in_input, rpr_image image); + extern RPR_API_ENTRY rpr_int rprMaterialNodeSetInputBufferData(rpr_material_node in_node, rpr_char const * in_input, rpr_buffer buffer); + extern RPR_API_ENTRY rpr_int rprMaterialNodeGetInfo(rpr_material_node in_node, rpr_material_node_info in_info, size_t in_size, void * in_data, size_t * out_size); + extern RPR_API_ENTRY rpr_int rprMaterialNodeGetInputInfo(rpr_material_node in_node, rpr_int in_input_idx, rpr_material_node_input_info in_info, size_t in_size, void * in_data, size_t * out_size); + extern RPR_API_ENTRY rpr_int rprContextCreateComposite(rpr_context context, rpr_composite_type in_type, rpr_composite * out_composite); + extern RPR_API_ENTRY rpr_int rprContextCreateLUTFromFile(rpr_context context, const rpr_char * fileLutPath, rpr_lut * out_lut); + extern RPR_API_ENTRY rpr_int rprContextCreateLUTFromData(rpr_context context, const rpr_char * lutData, rpr_lut * out_lut); + extern RPR_API_ENTRY rpr_int rprCompositeSetInputFb(rpr_composite composite, const rpr_char * inputName, rpr_framebuffer input); + extern RPR_API_ENTRY rpr_int rprCompositeSetInputC(rpr_composite composite, const rpr_char * inputName, rpr_composite input); + extern RPR_API_ENTRY rpr_int rprCompositeSetInputLUT(rpr_composite composite, const rpr_char * inputName, rpr_lut input); + extern RPR_API_ENTRY rpr_int rprCompositeSetInput4f(rpr_composite composite, const rpr_char * inputName, float x, float y, float z, float w); + extern RPR_API_ENTRY rpr_int rprCompositeSetInput1u(rpr_composite composite, const rpr_char * inputName, unsigned int value); + extern RPR_API_ENTRY rpr_int rprCompositeSetInputOp(rpr_composite composite, const rpr_char * inputName, rpr_material_node_arithmetic_operation op); + extern RPR_API_ENTRY rpr_int rprCompositeCompute(rpr_composite composite, rpr_framebuffer fb); + extern RPR_API_ENTRY rpr_int rprCompositeGetInfo(rpr_composite composite, rpr_composite_info composite_info, size_t size, void * data, size_t * size_ret); + + + /** @brief Delete object + * + * rprObjectDelete(obj) deletes 'obj' from memory. + * User has to make sure that 'obj' will not be used anymore after this call. + * + * Possible error codes: + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * + */ + + extern RPR_API_ENTRY rpr_int rprObjectDelete(void * obj); + + + /** @brief Set material node name + * + * + * @param node Node to set the name for + * @param name NULL terminated string name + * @return RPR_SUCCESS in case of success, error code otherwise + */ + + extern RPR_API_ENTRY rpr_int rprObjectSetName(void * node, rpr_char const * name); + + /* rpr_post_effect */ + + /** @brief Create post effect + * + * Create analytic point light represented by a point in space. + * Possible error codes: + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * + * @param context The context to create a light for + * @param status RPR_SUCCESS in case of success, error code otherwise + * @return Light object + */ + + extern RPR_API_ENTRY rpr_int rprContextCreatePostEffect(rpr_context context, rpr_post_effect_type type, rpr_post_effect * out_effect); + extern RPR_API_ENTRY rpr_int rprContextAttachPostEffect(rpr_context context, rpr_post_effect effect); + extern RPR_API_ENTRY rpr_int rprContextDetachPostEffect(rpr_context context, rpr_post_effect effect); + extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter1u(rpr_post_effect effect, rpr_char const * name, rpr_uint x); + extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter1f(rpr_post_effect effect, rpr_char const * name, rpr_float x); + extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter3f(rpr_post_effect effect, rpr_char const * name, rpr_float x, rpr_float y, rpr_float z); + extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, rpr_char const * name, rpr_float x, rpr_float y, rpr_float z, rpr_float w); + extern RPR_API_ENTRY rpr_int rprContextGetAttachedPostEffectCount(rpr_context context, rpr_uint * nb); + extern RPR_API_ENTRY rpr_int rprContextGetAttachedPostEffect(rpr_context context, rpr_uint i, rpr_post_effect * out_effect); + extern RPR_API_ENTRY rpr_int rprPostEffectGetInfo(rpr_post_effect effect, rpr_post_effect_info info, size_t size, void * data, size_t * size_ret); + extern RPR_API_ENTRY rpr_int rprContextCreateHeteroVolume(rpr_context context, rpr_hetero_volume * out_heteroVolume, size_t gridSizeX, size_t gridSizeY, size_t gridSizeZ, void const * indicesList, size_t numberOfIndices, rpr_hetero_volume_indices_topology indicesListTopology, void const * gridData, size_t gridDataSizeByte, rpr_uint gridDataTopology___unused); + extern RPR_API_ENTRY rpr_int rprShapeSetHeteroVolume(rpr_shape shape, rpr_hetero_volume heteroVolume); + extern RPR_API_ENTRY rpr_int rprHeteroVolumeSetTransform(rpr_hetero_volume heteroVolume, rpr_bool transpose, rpr_float const * transform); + extern RPR_API_ENTRY rpr_int rprHeteroVolumeSetEmission(rpr_hetero_volume heteroVolume, rpr_float r, rpr_float g, rpr_float b); + extern RPR_API_ENTRY rpr_int rprHeteroVolumeSetAlbedo(rpr_hetero_volume heteroVolume, rpr_float r, rpr_float g, rpr_float b); + extern RPR_API_ENTRY rpr_int rprHeteroVolumeSetFilter(rpr_hetero_volume heteroVolume, rpr_hetero_volume_filter filter); + /***************compatibility part***************/ +#define FR_API_VERSION 0x010030200 #define FR_SUCCESS 0 #define FR_ERROR_COMPUTE_API_NOT_SUPPORTED -1 #define FR_ERROR_OUT_OF_SYSTEM_MEMORY -2 @@ -1959,6 +2632,10 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_ERROR_INVALID_PARAMETER_TYPE -22 #define FR_ERROR_UNSUPPORTED -23 #define FR_ERROR_OPENCL_OUT_OF_HOST_MEMORY -24 +#define FR_ERROR_OPENGL -25 +#define FR_ERROR_OPENCL -26 +#define FR_ERROR_NULLPTR -27 +#define FR_ERROR_NODETYPE -28 #define FR_PARAMETER_TYPE_FLOAT 0x1 #define FR_PARAMETER_TYPE_FLOAT2 0x2 #define FR_PARAMETER_TYPE_FLOAT3 0x3 @@ -1967,14 +2644,6 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_PARAMETER_TYPE_STRING 0x6 #define FR_PARAMETER_TYPE_SHADER 0x7 #define FR_PARAMETER_TYPE_UINT 0x8 -#define FR_IMAGE_TYPE_1D 0x1 -#define FR_IMAGE_TYPE_2D 0x2 -#define FR_IMAGE_TYPE_3D 0x3 -#define FR_CONTEXT_OPENCL (1 << 0) -#define FR_CONTEXT_DIRECTCOMPUTE (1 << 1) -#define FR_CONTEXT_REFERENCE (1 << 2) -#define FR_CONTEXT_OPENGL (1 << 3) -#define FR_CONTEXT_METAL (1 << 4) #define FR_CREATION_FLAGS_ENABLE_GPU0 (1 << 0) #define FR_CREATION_FLAGS_ENABLE_GPU1 (1 << 1) #define FR_CREATION_FLAGS_ENABLE_GPU2 (1 << 2) @@ -1985,6 +2654,8 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_CREATION_FLAGS_ENABLE_GPU5 (1 << 7) #define FR_CREATION_FLAGS_ENABLE_GPU6 (1 << 8) #define FR_CREATION_FLAGS_ENABLE_GPU7 (1 << 9) +#define FR_CREATION_FLAGS_ENABLE_METAL (1 << 10) +#define FR_FILTER_NONE 0x0 #define FR_FILTER_BOX 0x1 #define FR_FILTER_TRIANGLE 0x2 #define FR_FILTER_GAUSSIAN 0x3 @@ -2000,6 +2671,9 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_LIGHT_TYPE_SKY 0x5 #define FR_LIGHT_TYPE_IES 0x6 #define FR_OBJECT_NAME 0x777777 +#define FR_CONTEXT_CREATEPROP_CPU_THREAD_LIMIT 0x600 +#define FR_CONTEXT_CREATEPROP_COMPILE_CALLBACK 0x601 +#define FR_CONTEXT_CREATEPROP_COMPILE_USER_DATA 0x602 #define FR_CONTEXT_CREATION_FLAGS 0x102 #define FR_CONTEXT_CACHE_PATH 0x103 #define FR_CONTEXT_RENDER_STATUS 0x104 @@ -2010,6 +2684,7 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_CONTEXT_SCENE 0x109 #define FR_CONTEXT_AA_CELL_SIZE 0x10A #define FR_CONTEXT_AA_SAMPLES 0x10B +#define FR_CONTEXT_ITERATIONS 0x10B #define FR_CONTEXT_IMAGE_FILTER_TYPE 0x10C #define FR_CONTEXT_IMAGE_FILTER_BOX_RADIUS 0x10D #define FR_CONTEXT_IMAGE_FILTER_GAUSSIAN_RADIUS 0x10E @@ -2048,7 +2723,23 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_CONTEXT_GPU7_NAME 0x12F #define FR_CONTEXT_TONE_MAPPING_EXPONENTIAL_INTENSITY 0x130 #define FR_CONTEXT_FRAMECOUNT 0x131 -#define FR_CONTEXT_MAX 0x132 +#define FR_CONTEXT_TEXTURE_COMPRESSION 0x132 +#define FR_CONTEXT_AO_RAY_LENGTH 0x133 +#define FR_CONTEXT_OOC_TEXTURE_CACHE 0x134 +#define FR_CONTEXT_PREVIEW 0x135 +#define FR_CONTEXT_CPU_THREAD_LIMIT 0x136 +#define FR_CONTEXT_LAST_ERROR_MESSAGE 0x137 +#define FR_CONTEXT_MAX_DEPTH_DIFFUSE 0x138 +#define FR_CONTEXT_MAX_DEPTH_GLOSSY 0x139 +#define FR_CONTEXT_OOC_CACHE_PATH 0x13a +#define FR_CONTEXT_MAX_DEPTH_REFRACTION 0x13B +#define FR_CONTEXT_MAX_DEPTH_GLOSSY_REFRACTION 0x13C +#define FR_CONTEXT_RENDER_LAYER_MASK 0x13D +#define FR_CONTEXT_SINGLE_LEVEL_BVH_ENABLED 0x13E +#define FR_CONTEXT_TRANSPARENT_BACKGROUND 0x13F +#define FR_CONTEXT_MAX_DEPTH_SHADOW 0x140 +#define FR_CONTEXT_API_VERSION 0x141 +#define FR_CONTEXT_MAX 0x142 #define FR_CAMERA_TRANSFORM 0x201 #define FR_CAMERA_FSTOP 0x202 #define FR_CAMERA_APERTURE_BLADES 0x203 @@ -2066,11 +2757,21 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_CAMERA_FOCAL_TILT 0x20F #define FR_CAMERA_LENS_SHIFT 0x210 #define FR_CAMERA_IPD 0x211 +#define FR_CAMERA_TILT_CORRECTION 0x212 +#define FR_CAMERA_NEAR_PLANE 0x213 +#define FR_CAMERA_FAR_PLANE 0x214 +#define FR_CAMERA_LINEAR_MOTION 0x215 +#define FR_CAMERA_ANGULAR_MOTION 0x216 #define FR_IMAGE_FORMAT 0x301 #define FR_IMAGE_DESC 0x302 #define FR_IMAGE_DATA 0x303 #define FR_IMAGE_DATA_SIZEBYTE 0x304 #define FR_IMAGE_WRAP 0x305 +#define FR_IMAGE_FILTER 0x306 +#define FR_IMAGE_GAMMA 0x307 +#define FR_IMAGE_MIPMAP_ENABLED 0x308 +#define FR_BUFFER_DESC 0x350 +#define FR_BUFFER_DATA 0x351 #define FR_SHAPE_TYPE 0x401 #define FR_SHAPE_VIDMEM_USAGE 0x402 #define FR_SHAPE_TRANSFORM 0x403 @@ -2078,10 +2779,9 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_SHAPE_LINEAR_MOTION 0x405 #define FR_SHAPE_ANGULAR_MOTION 0x406 #define FR_SHAPE_VISIBILITY_FLAG 0x407 -#define FR_SHAPE_SHADOW_FLAG 0x408 +#define FR_SHAPE_SHADOW_FLAG 0x408 #define FR_SHAPE_SUBDIVISION_FACTOR 0x409 #define FR_SHAPE_DISPLACEMENT_SCALE 0x40A -#define FR_SHAPE_DISPLACEMENT_IMAGE 0X40B #define FR_SHAPE_VISIBILITY_PRIMARY_ONLY_FLAG 0x40C #define FR_SHAPE_VISIBILITY_IN_SPECULAR_FLAG 0x40D #define FR_SHAPE_SHADOW_CATCHER_FLAG 0x40E @@ -2089,7 +2789,11 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_SHAPE_OBJECT_GROUP_ID 0x410 #define FR_SHAPE_SUBDIVISION_CREASEWEIGHT 0x411 #define FR_SHAPE_SUBDIVISION_BOUNDARYINTEROP 0x412 -#define FR_SHAPE_MATERIAL_OVERRIDE 0x413 +#define FR_SHAPE_DISPLACEMENT_MATERIAL 0x413 +#define FR_SHAPE_MATERIALS_PER_FACE 0x415 +#define FR_SHAPE_SCALE_MOTION 0x416 +#define FR_SHAPE_HETERO_VOLUME 0x417 +#define FR_SHAPE_LAYER_MASK 0x418 #define FR_MESH_POLYGON_COUNT 0x501 #define FR_MESH_VERTEX_COUNT 0x502 #define FR_MESH_NORMAL_COUNT 0x503 @@ -2112,6 +2816,7 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_MESH_UV2_INDEX_ARRAY 0x515 #define FR_MESH_UV2_STRIDE 0x516 #define FR_MESH_UV2_INDEX_STRIDE 0x517 +#define FR_MESH_UV_DIM 0x518 #define FR_SCENE_SHAPE_COUNT 0x701 #define FR_SCENE_LIGHT_COUNT 0x702 #define FR_SCENE_SHAPE_LIST 0x704 @@ -2122,9 +2827,14 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_SCENE_ENVIRONMENT_OVERRIDE_REFRACTION 0x70A #define FR_SCENE_ENVIRONMENT_OVERRIDE_TRANSPARENCY 0x70B #define FR_SCENE_ENVIRONMENT_OVERRIDE_BACKGROUND 0x70C -#define FR_SCENE_AXIS_ALIGNED_BOUNDING_BOX 0x70D +#define FR_SCENE_AABB 0x70D +#define FR_SCENE_HETEROVOLUME_LIST 0x70E +#define FR_SCENE_HETEROVOLUME_COUNT 0x70F +#define FR_LUT_FILENAME 0x850 +#define FR_LUT_DATA 0x851 #define FR_LIGHT_TYPE 0x801 #define FR_LIGHT_TRANSFORM 0x803 +#define FR_LIGHT_GROUP_ID 0x805 #define FR_POINT_LIGHT_RADIANT_POWER 0x804 #define FR_DIRECTIONAL_LIGHT_RADIANT_POWER 0x808 #define FR_DIRECTIONAL_LIGHT_SHADOW_SOFTNESS 0x809 @@ -2137,6 +2847,7 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_SKY_LIGHT_TURBIDITY 0x812 #define FR_SKY_LIGHT_ALBEDO 0x813 #define FR_SKY_LIGHT_SCALE 0x814 +#define FR_SKY_LIGHT_DIRECTION 0x815 #define FR_SKY_LIGHT_PORTAL_LIST 0x820 #define FR_SKY_LIGHT_PORTAL_COUNT 0x821 #define FR_IES_LIGHT_RADIANT_POWER 0x816 @@ -2160,6 +2871,8 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_COMPONENT_TYPE_UINT8 0x1 #define FR_COMPONENT_TYPE_FLOAT16 0x2 #define FR_COMPONENT_TYPE_FLOAT32 0x3 +#define FR_BUFFER_ELEMENT_TYPE_INT32 0x1 +#define FR_BUFFER_ELEMENT_TYPE_FLOAT32 0x2 #define FR_RENDER_MODE_GLOBAL_ILLUMINATION 0x1 #define FR_RENDER_MODE_DIRECT_ILLUMINATION 0x2 #define FR_RENDER_MODE_DIRECT_ILLUMINATION_NO_SHADOW 0x3 @@ -2169,12 +2882,14 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_RENDER_MODE_NORMAL 0x7 #define FR_RENDER_MODE_TEXCOORD 0x8 #define FR_RENDER_MODE_AMBIENT_OCCLUSION 0x9 +#define FR_RENDER_MODE_DIFFUSE 0x0a #define FR_CAMERA_MODE_PERSPECTIVE 0x1 #define FR_CAMERA_MODE_ORTHOGRAPHIC 0x2 #define FR_CAMERA_MODE_LATITUDE_LONGITUDE_360 0x3 #define FR_CAMERA_MODE_LATITUDE_LONGITUDE_STEREO 0x4 #define FR_CAMERA_MODE_CUBEMAP 0x5 #define FR_CAMERA_MODE_CUBEMAP_STEREO 0x6 +#define FR_CAMERA_MODE_FISHEYE 0x7 #define FR_TONEMAPPING_OPERATOR_NONE 0x0 #define FR_TONEMAPPING_OPERATOR_LINEAR 0x1 #define FR_TONEMAPPING_OPERATOR_PHOTOLINEAR 0x2 @@ -2221,6 +2936,16 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_MATERIAL_NODE_DIFFUSE_REFRACTION 0x1B #define FR_MATERIAL_NODE_BUMP_MAP 0x1C #define FR_MATERIAL_NODE_VOLUME 0x1D +#define FR_MATERIAL_NODE_MICROFACET_ANISOTROPIC_REFLECTION 0x1E +#define FR_MATERIAL_NODE_MICROFACET_ANISOTROPIC_REFRACTION 0x1F +#define FR_MATERIAL_NODE_TWOSIDED 0x20 +#define FR_MATERIAL_NODE_UV_PROCEDURAL 0x21 +#define FR_MATERIAL_NODE_MICROFACET_BECKMANN 0x22 +#define FR_MATERIAL_NODE_PHONG 0x23 +#define FR_MATERIAL_NODE_BUFFER_SAMPLER 0x24 +#define FR_MATERIAL_NODE_UV_TRIPLANAR 0x25 +#define FR_MATERIAL_NODE_UBERV2 0x26 +#define FR_MATERIAL_NODE_AO_MAP 0x27 #define FR_MATERIAL_INPUT_COLOR 0x0 #define FR_MATERIAL_INPUT_COLOR0 0x1 #define FR_MATERIAL_INPUT_COLOR1 0x2 @@ -2246,7 +2971,18 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_MATERIAL_INPUT_MULTISCATTER 0x16 #define FR_MATERIAL_INPUT_COLOR2 0x17 #define FR_MATERIAL_INPUT_COLOR3 0x18 -#define FR_MATERIAL_INPUT_MAX 0x19 +#define FR_MATERIAL_INPUT_ANISOTROPIC 0x19 +#define FR_MATERIAL_INPUT_FRONTFACE 0x1a +#define FR_MATERIAL_INPUT_BACKFACE 0x1b +#define FR_MATERIAL_INPUT_ORIGIN 0x1c +#define FR_MATERIAL_INPUT_ZAXIS 0x1d +#define FR_MATERIAL_INPUT_XAXIS 0x1e +#define FR_MATERIAL_INPUT_THRESHOLD 0x1f +#define FR_MATERIAL_INPUT_OFFSET 0x20 +#define FR_MATERIAL_INPUT_UV_TYPE 0x21 +#define FR_MATERIAL_INPUT_RADIUS 0x22 +#define FR_MATERIAL_INPUT_SIDE 0x23 +#define FR_MATERIAL_INPUT_MAX 0x24 #define FR_MATERIAL_STANDARD_INPUT_DIFFUSE_COLOR 0x112 #define FR_MATERIAL_STANDARD_INPUT_DIFFUSE_NORMAL 0x113 #define FR_MATERIAL_STANDARD_INPUT_GLOSSY_COLOR 0x114 @@ -2286,40 +3022,45 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_MATERIAL_NODE_OP_SELECT_X 0x07 #define FR_MATERIAL_NODE_OP_SELECT_Y 0x08 #define FR_MATERIAL_NODE_OP_SELECT_Z 0x09 -#define FR_MATERIAL_NODE_OP_SELECT_W 0x0A -#define FR_MATERIAL_NODE_OP_COMBINE 0x0B -#define FR_MATERIAL_NODE_OP_DOT3 0x0C -#define FR_MATERIAL_NODE_OP_DOT4 0x0D -#define FR_MATERIAL_NODE_OP_CROSS3 0x0E -#define FR_MATERIAL_NODE_OP_LENGTH3 0x0F -#define FR_MATERIAL_NODE_OP_NORMALIZE3 0x10 -#define FR_MATERIAL_NODE_OP_POW 0x11 -#define FR_MATERIAL_NODE_OP_ACOS 0x12 -#define FR_MATERIAL_NODE_OP_ASIN 0x13 -#define FR_MATERIAL_NODE_OP_ATAN 0x14 -#define FR_MATERIAL_NODE_OP_AVERAGE_XYZ 0x15 -#define FR_MATERIAL_NODE_OP_AVERAGE 0x16 -#define FR_MATERIAL_NODE_OP_MIN 0x17 -#define FR_MATERIAL_NODE_OP_MAX 0x18 -#define FR_MATERIAL_NODE_OP_FLOOR 0x19 -#define FR_MATERIAL_NODE_OP_MOD 0x1A -#define FR_MATERIAL_NODE_OP_ABS 0x1B -#define FR_MATERIAL_NODE_OP_SHUFFLE_YZWX 0x1C -#define FR_MATERIAL_NODE_OP_SHUFFLE_ZWXY 0x1D -#define FR_MATERIAL_NODE_OP_SHUFFLE_WXYZ 0x1E -#define FR_MATERIAL_NODE_OP_MAT_MUL 0x1F +#define FR_MATERIAL_NODE_OP_COMBINE 0x0A +#define FR_MATERIAL_NODE_OP_DOT3 0x0B +#define FR_MATERIAL_NODE_OP_CROSS3 0x0C +#define FR_MATERIAL_NODE_OP_LENGTH3 0x0D +#define FR_MATERIAL_NODE_OP_NORMALIZE3 0x0E +#define FR_MATERIAL_NODE_OP_POW 0x0F +#define FR_MATERIAL_NODE_OP_ACOS 0x10 +#define FR_MATERIAL_NODE_OP_ASIN 0x11 +#define FR_MATERIAL_NODE_OP_ATAN 0x12 +#define FR_MATERIAL_NODE_OP_AVERAGE_XYZ 0x13 +#define FR_MATERIAL_NODE_OP_AVERAGE 0x14 +#define FR_MATERIAL_NODE_OP_MIN 0x15 +#define FR_MATERIAL_NODE_OP_MAX 0x16 +#define FR_MATERIAL_NODE_OP_FLOOR 0x17 +#define FR_MATERIAL_NODE_OP_MOD 0x18 +#define FR_MATERIAL_NODE_OP_ABS 0x19 +#define FR_MATERIAL_NODE_OP_SHUFFLE_YZWX 0x1a +#define FR_MATERIAL_NODE_OP_SHUFFLE_ZWXY 0x1b +#define FR_MATERIAL_NODE_OP_SHUFFLE_WXYZ 0x1c +#define FR_MATERIAL_NODE_OP_MAT_MUL 0x1d +#define FR_MATERIAL_NODE_OP_SELECT_W 0x1e +#define FR_MATERIAL_NODE_OP_DOT4 0x1f +#define FR_MATERIAL_NODE_OP_LOG 0x20 #define FR_MATERIAL_NODE_LOOKUP_UV 0x0 #define FR_MATERIAL_NODE_LOOKUP_N 0x1 #define FR_MATERIAL_NODE_LOOKUP_P 0x2 #define FR_MATERIAL_NODE_LOOKUP_INVEC 0x3 #define FR_MATERIAL_NODE_LOOKUP_OUTVEC 0x4 #define FR_MATERIAL_NODE_LOOKUP_UV1 0x5 +#define FR_MATERIAL_NODE_UVTYPE_PLANAR 0x0 +#define FR_MATERIAL_NODE_UVTYPE_CYLINDICAL 0x1 +#define FR_MATERIAL_NODE_UVTYPE_SPHERICAL 0x2 +#define FR_MATERIAL_NODE_UVTYPE_PROJECT 0x3 #define FR_POST_EFFECT_TYPE 0x0 -#define FR_POST_EFFECT_PARAMETER_COUNT 0x1 -#define FR_POST_EFFECT_WHITE_BALANCE_COLOR_SPACE 0x1 -#define FR_POST_EFFECT_WHITE_BALANCE_COLOR_TEMPERATURE 0x2 -#define FR_POST_EFFECT_SIMPLE_TONEMAP_EXPOSURE 0x1 -#define FR_POST_EFFECT_SIMPLE_TONEMAP_CONTRAST 0x2 +#define FR_POST_EFFECT_WHITE_BALANCE_COLOR_SPACE 0x4 +#define FR_POST_EFFECT_WHITE_BALANCE_COLOR_TEMPERATURE 0x5 +#define FR_POST_EFFECT_SIMPLE_TONEMAP_EXPOSURE 0x6 +#define FR_POST_EFFECT_SIMPLE_TONEMAP_CONTRAST 0x7 +#define FR_POST_EFFECT_SIMPLE_TONEMAP_ENABLE_TONEMAP 0x8 #define FR_AOV_COLOR 0x0 #define FR_AOV_OPACITY 0x1 #define FR_AOV_WORLD_COORDINATE 0x2 @@ -2330,7 +3071,24 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_AOV_DEPTH 0x7 #define FR_AOV_OBJECT_ID 0x8 #define FR_AOV_OBJECT_GROUP_ID 0x9 -#define FR_AOV_MAX 0xa +#define FR_AOV_SHADOW_CATCHER 0x0a +#define FR_AOV_BACKGROUND 0x0b +#define FR_AOV_EMISSION 0x0c +#define FR_AOV_VELOCITY 0x0d +#define FR_AOV_DIRECT_ILLUMINATION 0x0e +#define FR_AOV_INDIRECT_ILLUMINATION 0x0f +#define FR_AOV_AO 0x10 +#define FR_AOV_DIRECT_DIFFUSE 0x11 +#define FR_AOV_DIRECT_REFLECT 0x12 +#define FR_AOV_INDIRECT_DIFFUSE 0x13 +#define FR_AOV_INDIRECT_REFLECT 0x14 +#define FR_AOV_REFRACT 0x15 +#define FR_AOV_VOLUME 0x16 +#define FR_AOV_LIGHT_GROUP0 0x17 +#define FR_AOV_LIGHT_GROUP1 0x18 +#define FR_AOV_LIGHT_GROUP2 0x19 +#define FR_AOV_LIGHT_GROUP3 0x1a +#define FR_AOV_MAX 0x1b #define FR_POST_EFFECT_TONE_MAP 0x0 #define FR_POST_EFFECT_WHITE_BALANCE 0x1 #define FR_POST_EFFECT_SIMPLE_TONEMAP 0x2 @@ -2344,216 +3102,335 @@ extern RPR_API_ENTRY rpr_int rprPostEffectSetParameter4f(rpr_post_effect effect, #define FR_MATERIAL_NODE_INPUT_TYPE_UINT 0x2 #define FR_MATERIAL_NODE_INPUT_TYPE_NODE 0x3 #define FR_MATERIAL_NODE_INPUT_TYPE_IMAGE 0x4 -#define FR_RASTER_SHADOWS_FILTER_NONE 0x90E -#define FR_RASTER_SHADOWS_FILTER_PCF 0x90F -#define FR_RASTER_SHADOWS_FILTER_PCSS 0x910 -#define FR_RASTER_SHADOWS_SAMPLING_BILINEAR 0x911 -#define FR_RASTER_SHADOWS_SAMPLING_HAMMERSLEY 0x912 -#define FR_RASTER_SHADOWS_SAMPLING_MULTIJITTERED 0x913 +#define FR_MATERIAL_NODE_INPUT_TYPE_BUFFER 0x5 #define FR_SUBDIV_BOUNDARY_INTERFOP_TYPE_EDGE_AND_CORNER 0x1 #define FR_SUBDIV_BOUNDARY_INTERFOP_TYPE_EDGE_ONLY 0x2 #define FR_IMAGE_WRAP_TYPE_REPEAT 0x1 #define FR_IMAGE_WRAP_TYPE_MIRRORED_REPEAT 0x2 #define FR_IMAGE_WRAP_TYPE_CLAMP_TO_EDGE 0x3 #define FR_IMAGE_WRAP_TYPE_CLAMP_TO_BORDER 0x4 -#define FR_MAX_AA_SAMPLES 32 -#define FR_MAX_AA_GRID_SIZE 16 +#define FR_IMAGE_WRAP_TYPE_CLAMP_ZERO 0x5 +#define FR_IMAGE_WRAP_TYPE_CLAMP_ONE 0x6 +#define FR_IMAGE_FILTER_TYPE_NEAREST 0x1 +#define FR_IMAGE_FILTER_TYPE_LINEAR 0x2 +#define FR_COMPOSITE_TYPE 0x1 +#define FR_COMPOSITE_FRAMEBUFFER_INPUT_FB 0x2 +#define FR_COMPOSITE_NORMALIZE_INPUT_COLOR 0x3 +#define FR_COMPOSITE_NORMALIZE_INPUT_SHADOWCATCHER 0x4 +#define FR_COMPOSITE_CONSTANT_INPUT_VALUE 0x5 +#define FR_COMPOSITE_LERP_VALUE_INPUT_COLOR0 0x6 +#define FR_COMPOSITE_LERP_VALUE_INPUT_COLOR1 0x7 +#define FR_COMPOSITE_LERP_VALUE_INPUT_WEIGHT 0x8 +#define FR_COMPOSITE_ARITHMETIC_INPUT_COLOR0 0x9 +#define FR_COMPOSITE_ARITHMETIC_INPUT_COLOR1 0x0a +#define FR_COMPOSITE_ARITHMETIC_INPUT_OP 0x0b +#define FR_COMPOSITE_GAMMA_CORRECTION_INPUT_COLOR 0x0c +#define FR_COMPOSITE_LUT_INPUT_LUT 0x0d +#define FR_COMPOSITE_LUT_INPUT_COLOR 0x0e +#define FR_COMPOSITE_ARITHMETIC 0x1 +#define FR_COMPOSITE_LERP_VALUE 0x2 +#define FR_COMPOSITE_INVERSE 0x3 +#define FR_COMPOSITE_NORMALIZE 0x4 +#define FR_COMPOSITE_GAMMA_CORRECTION 0x5 +#define FR_COMPOSITE_EXPOSURE 0x6 +#define FR_COMPOSITE_CONTRAST 0x7 +#define FR_COMPOSITE_SIDE_BY_SIDE 0x8 +#define FR_COMPOSITE_TONEMAP_ACES 0x9 +#define FR_COMPOSITE_TONEMAP_REINHARD 0xa +#define FR_COMPOSITE_TONEMAP_LINEAR 0xb +#define FR_COMPOSITE_FRAMEBUFFER 0xc +#define FR_COMPOSITE_CONSTANT 0xd +#define FR_COMPOSITE_LUT 0xe +#define FR_HETEROVOLUME_SIZE_X 0x730 +#define FR_HETEROVOLUME_SIZE_Y 0x731 +#define FR_HETEROVOLUME_SIZE_Z 0x732 +#define FR_HETEROVOLUME_DATA 0x733 +#define FR_HETEROVOLUME_DATA_SIZEBYTE 0x734 +#define FR_HETEROVOLUME_TRANSFORM 0x735 +#define FR_HETEROVOLUME_INDICES 0x736 +#define FR_HETEROVOLUME_INDICES_NUMBER 0x737 +#define FR_HETEROVOLUME_INDICES_TOPOLOGY 0x738 +#define FR_HETEROVOLUME_EMISSION 0x739 +#define FR_HETEROVOLUME_ALBEDO 0x73a +#define FR_HETEROVOLUME_FILTER 0x73b +#define FR_HETEROVOLUME_INDICES_TOPOLOGY_I_U64 0x750 +#define FR_HETEROVOLUME_INDICES_TOPOLOGY_XYZ_U32 0x751 +#define FR_HETEROVOLUME_INDICES_TOPOLOGY_I_S64 0x752 +#define FR_HETEROVOLUME_INDICES_TOPOLOGY_XYZ_S32 0x753 +#define FR_HETEROVOLUME_FILTER_NEAREST 0x760 +#define FR_HETEROVOLUME_FILTER_LINEAR 0x761 #define FR_FALSE 0 #define FR_TRUE 1 -typedef rpr_char fr_char; -typedef rpr_uchar fr_uchar; -typedef rpr_int fr_int; -typedef rpr_uint fr_uint; -typedef rpr_long fr_long; -typedef rpr_ulong fr_ulong; -typedef rpr_short fr_short; -typedef rpr_ushort fr_ushort; -typedef rpr_float fr_float; -typedef rpr_double fr_double; -typedef rpr_longlong fr_longlong; -typedef rpr_bool fr_bool; -typedef rpr_bitfield fr_bitfield; -typedef rpr_context fr_context; -typedef rpr_camera fr_camera; -typedef rpr_shape fr_shape; -typedef rpr_light fr_light; -typedef rpr_scene fr_scene; -typedef rpr_image fr_image; -typedef rpr_framebuffer fr_framebuffer; -typedef rpr_material_system fr_material_system; -typedef rpr_material_node fr_material_node; -typedef rpr_post_effect fr_post_effect; -typedef rpr_context_properties fr_context_properties; -typedef rpr_light_type fr_light_type; -typedef rpr_image_type fr_image_type; -typedef rpr_shape_type fr_shape_type; -typedef rpr_context_type fr_context_type; -typedef rpr_creation_flags fr_creation_flags; -typedef rpr_aa_filter fr_aa_filter; -typedef rpr_context_info fr_context_info; -typedef rpr_camera_info fr_camera_info; -typedef rpr_image_info fr_image_info; -typedef rpr_shape_info fr_shape_info; -typedef rpr_mesh_info fr_mesh_info; -typedef rpr_mesh_polygon_info fr_mesh_polygon_info; -typedef rpr_mesh_polygon_vertex_info fr_mesh_polygon_vertex_info; -typedef rpr_light_info fr_light_info; -typedef rpr_scene_info fr_scene_info; -typedef rpr_parameter_info fr_parameter_info; -typedef rpr_framebuffer_info fr_framebuffer_info; -typedef rpr_channel_order fr_channel_order; -typedef rpr_channel_type fr_channel_type; -typedef rpr_parameter_type fr_parameter_type; -typedef rpr_render_mode fr_render_mode; -typedef rpr_component_type fr_component_type; -typedef rpr_camera_mode fr_camera_mode; -typedef rpr_tonemapping_operator fr_tonemapping_operator; -typedef rpr_volume_type fr_volume_type; -typedef rpr_material_system_type fr_material_system_type; -typedef rpr_material_node_type fr_material_node_type; -typedef rpr_material_node_input fr_material_node_input; -typedef rpr_material_node_info fr_material_node_info; -typedef rpr_material_node_input_info fr_material_node_input_info; -typedef rpr_aov fr_aov; -typedef rpr_post_effect_type fr_post_effect_type; -typedef rpr_post_effect_info fr_post_effect_info; -typedef rpr_color_space fr_color_space; -typedef rpr_environment_override fr_environment_override; -typedef rpr_subdiv_boundary_interfop_type fr_subdiv_boundary_interfop_type; -typedef rpr_material_node_lookup_value fr_material_node_lookup_value; -typedef rpr_image_wrap_type fr_image_wrap_type; -typedef _rpr_image_desc _fr_image_desc; -typedef rpr_image_desc fr_image_desc; -typedef _rpr_framebuffer_desc _fr_framebuffer_desc; -typedef rpr_framebuffer_desc fr_framebuffer_desc; -typedef _rpr_render_statistics _fr_render_statistics; -typedef rpr_render_statistics fr_render_statistics; -typedef _rpr_image_format _fr_image_format; -typedef rpr_image_format fr_image_format; -typedef _rpr_ies_image_desc _fr_ies_image_desc; -typedef rpr_ies_image_desc fr_ies_image_desc; -typedef rpr_framebuffer_format fr_framebuffer_format; -extern RPR_API_ENTRY fr_int frRegisterPlugin(fr_char const * path); -extern RPR_API_ENTRY fr_int frCreateContext(fr_int api_version, fr_int * pluginIDs, size_t pluginCount, fr_creation_flags creation_flags, fr_context_properties const * props, fr_char const * cache_path, fr_context * out_context); -extern RPR_API_ENTRY fr_int frContextSetActivePlugin(fr_context context, fr_int pluginID); -extern RPR_API_ENTRY fr_int frContextGetInfo(fr_context context, fr_context_info context_info, size_t size, void * data, size_t * size_ret); -extern RPR_API_ENTRY fr_int frContextGetParameterInfo(fr_context context, int param_idx, fr_parameter_info parameter_info, size_t size, void * data, size_t * size_ret); -extern RPR_API_ENTRY fr_int frContextGetAOV(fr_context context, fr_aov aov, fr_framebuffer * out_fb); -extern RPR_API_ENTRY fr_int frContextSetAOV(fr_context context, fr_aov aov, fr_framebuffer frame_buffer); -extern RPR_API_ENTRY fr_int frContextSetScene(fr_context context, fr_scene scene); -extern RPR_API_ENTRY fr_int frContextGetScene(fr_context arg0, fr_scene * out_scene); -extern RPR_API_ENTRY fr_int frContextSetParameter1u(fr_context context, fr_char const * name, fr_uint x); -extern RPR_API_ENTRY fr_int frContextSetParameter1f(fr_context context, fr_char const * name, fr_float x); -extern RPR_API_ENTRY fr_int frContextSetParameter3f(fr_context context, fr_char const * name, fr_float x, fr_float y, fr_float z); -extern RPR_API_ENTRY fr_int frContextSetParameter4f(fr_context context, fr_char const * name, fr_float x, fr_float y, fr_float z, fr_float w); -extern RPR_API_ENTRY fr_int frContextSetParameterString(fr_context context, fr_char const * name, fr_char const * value); -extern RPR_API_ENTRY fr_int frContextRender(fr_context context); -extern RPR_API_ENTRY fr_int frContextRenderTile(fr_context context, fr_uint xmin, fr_uint xmax, fr_uint ymin, fr_uint ymax); -extern RPR_API_ENTRY fr_int frContextClearMemory(fr_context context); -extern RPR_API_ENTRY fr_int frContextCreateImage(fr_context context, fr_image_format const format, fr_image_desc const * image_desc, void const * data, fr_image * out_image); -extern RPR_API_ENTRY fr_int frContextCreateImageFromFile(fr_context context, fr_char const * path, fr_image * out_image); -extern RPR_API_ENTRY fr_int frContextCreateScene(fr_context context, fr_scene * out_scene); -extern RPR_API_ENTRY fr_int frContextCreateInstance(fr_context context, fr_shape shape, fr_shape * out_instance); -extern RPR_API_ENTRY fr_int frContextCreateMesh(fr_context context, fr_float const * vertices, size_t num_vertices, fr_int vertex_stride, fr_float const * normals, size_t num_normals, fr_int normal_stride, fr_float const * texcoords, size_t num_texcoords, fr_int texcoord_stride, fr_int const * vertex_indices, fr_int vidx_stride, fr_int const * normal_indices, fr_int nidx_stride, fr_int const * texcoord_indices, fr_int tidx_stride, fr_int const * num_face_vertices, size_t num_faces, fr_shape * out_mesh); -extern RPR_API_ENTRY fr_int frContextCreateMeshEx(fr_context context, fr_float const * vertices, size_t num_vertices, fr_int vertex_stride, fr_float const * normals, size_t num_normals, fr_int normal_stride, fr_int const * perVertexFlag, size_t num_perVertexFlags, fr_int perVertexFlag_stride, fr_int numberOfTexCoordLayers, fr_float const ** texcoords, size_t * num_texcoords, fr_int * texcoord_stride, fr_int const * vertex_indices, fr_int vidx_stride, fr_int const * normal_indices, fr_int nidx_stride, fr_int const ** texcoord_indices, fr_int * tidx_stride, fr_int const * num_face_vertices, size_t num_faces, fr_shape * out_mesh); -extern RPR_API_ENTRY fr_int frContextCreateCamera(fr_context context, fr_camera * out_camera); -extern RPR_API_ENTRY fr_int frContextCreateFrameBuffer(fr_context context, fr_framebuffer_format const format, fr_framebuffer_desc const * fb_desc, fr_framebuffer * out_fb); -extern RPR_API_ENTRY fr_int frCameraGetInfo(fr_camera camera, fr_camera_info camera_info, size_t size, void * data, size_t * size_ret); -extern RPR_API_ENTRY fr_int frCameraSetFocalLength(fr_camera camera, fr_float flength); -extern RPR_API_ENTRY fr_int frCameraSetFocusDistance(fr_camera camera, fr_float fdist); -extern RPR_API_ENTRY fr_int frCameraSetTransform(fr_camera camera, fr_bool transpose, fr_float * transform); -extern RPR_API_ENTRY fr_int frCameraSetSensorSize(fr_camera camera, fr_float width, fr_float height); -extern RPR_API_ENTRY fr_int frCameraLookAt(fr_camera camera, fr_float posx, fr_float posy, fr_float posz, fr_float atx, fr_float aty, fr_float atz, fr_float upx, fr_float upy, fr_float upz); -extern RPR_API_ENTRY fr_int frCameraSetFStop(fr_camera camera, fr_float fstop); -extern RPR_API_ENTRY fr_int frCameraSetApertureBlades(fr_camera camera, fr_uint num_blades); -extern RPR_API_ENTRY fr_int frCameraSetExposure(fr_camera camera, fr_float exposure); -extern RPR_API_ENTRY fr_int frCameraSetMode(fr_camera camera, fr_camera_mode mode); -extern RPR_API_ENTRY fr_int frCameraSetOrthoWidth(fr_camera camera, fr_float width); -extern RPR_API_ENTRY fr_int frCameraSetFocalTilt(fr_camera camera, fr_float tilt); -extern RPR_API_ENTRY fr_int frCameraSetIPD(fr_camera camera, fr_float ipd); -extern RPR_API_ENTRY fr_int frCameraSetLensShift(fr_camera camera, fr_float shiftx, fr_float shifty); -extern RPR_API_ENTRY fr_int frCameraSetOrthoHeight(fr_camera camera, fr_float height); -extern RPR_API_ENTRY fr_int frImageGetInfo(fr_image image, fr_image_info image_info, size_t size, void * data, size_t * size_ret); -extern RPR_API_ENTRY fr_int frImageSetWrap(fr_image image, fr_image_wrap_type type); -extern RPR_API_ENTRY fr_int frShapeSetTransform(fr_shape shape, fr_bool transpose, fr_float const * transform); -extern RPR_API_ENTRY fr_int frShapeSetSubdivisionFactor(fr_shape shape, fr_uint factor); -extern RPR_API_ENTRY fr_int frShapeSetSubdivisionCreaseWeight(fr_shape shape, fr_float factor); -extern RPR_API_ENTRY fr_int frShapeSetSubdivisionBoundaryInterop(fr_shape shape, fr_subdiv_boundary_interfop_type type); -extern RPR_API_ENTRY fr_int frShapeSetDisplacementScale(fr_shape shape, fr_float minscale, fr_float maxscale); -extern RPR_API_ENTRY fr_int frShapeSetObjectGroupID(fr_shape shape, fr_uint objectGroupID); -extern RPR_API_ENTRY fr_int frShapeSetDisplacementImage(fr_shape shape, fr_image image); -extern RPR_API_ENTRY fr_int frShapeSetMaterial(fr_shape shape, fr_material_node node); -extern RPR_API_ENTRY fr_int frShapeSetMaterialOverride(fr_shape shape, fr_material_node node); -extern RPR_API_ENTRY fr_int frShapeSetVolumeMaterial(fr_shape shape, fr_material_node node); -extern RPR_API_ENTRY fr_int frShapeSetLinearMotion(fr_shape shape, fr_float x, fr_float y, fr_float z); -extern RPR_API_ENTRY fr_int frShapeSetAngularMotion(fr_shape shape, fr_float x, fr_float y, fr_float z, fr_float w); -extern RPR_API_ENTRY fr_int frShapeSetVisibility(fr_shape shape, fr_bool visible); -extern RPR_API_ENTRY fr_int frShapeSetVisibilityPrimaryOnly(fr_shape shape, fr_bool visible); -extern RPR_API_ENTRY fr_int frShapeSetVisibilityInSpecular(fr_shape shape, fr_bool visible); -extern RPR_API_ENTRY fr_int frShapeSetShadowCatcher(fr_shape shape, fr_bool shadowCatcher); -extern RPR_API_ENTRY fr_int frShapeSetShadow(fr_shape shape, fr_bool casts_shadow); -extern RPR_API_ENTRY fr_int frLightSetTransform(fr_light light, fr_bool transpose, fr_float const * transform); -extern RPR_API_ENTRY fr_int frShapeGetInfo(fr_shape arg0, fr_shape_info arg1, size_t arg2, void * arg3, size_t * arg4); -extern RPR_API_ENTRY fr_int frMeshGetInfo(fr_shape mesh, fr_mesh_info mesh_info, size_t size, void * data, size_t * size_ret); -extern RPR_API_ENTRY fr_int frMeshPolygonGetInfo(fr_shape mesh, size_t polygon_index, fr_mesh_polygon_info polygon_info, size_t size, void * data, size_t * size_ret); -extern RPR_API_ENTRY fr_int frInstanceGetBaseShape(fr_shape shape, fr_shape * out_shape); -extern RPR_API_ENTRY fr_int frContextCreatePointLight(fr_context context, fr_light * out_light); -extern RPR_API_ENTRY fr_int frPointLightSetRadiantPower3f(fr_light light, fr_float r, fr_float g, fr_float b); -extern RPR_API_ENTRY fr_int frContextCreateSpotLight(fr_context context, fr_light * light); -extern RPR_API_ENTRY fr_int frSpotLightSetRadiantPower3f(fr_light light, fr_float r, fr_float g, fr_float b); -extern RPR_API_ENTRY fr_int frSpotLightSetConeShape(fr_light light, fr_float iangle, fr_float oangle); -extern RPR_API_ENTRY fr_int frContextCreateDirectionalLight(fr_context context, fr_light * out_light); -extern RPR_API_ENTRY fr_int frDirectionalLightSetRadiantPower3f(fr_light light, fr_float r, fr_float g, fr_float b); -extern RPR_API_ENTRY fr_int frDirectionalLightSetShadowSoftness(fr_light light, fr_float coeff); -extern RPR_API_ENTRY fr_int frContextCreateEnvironmentLight(fr_context context, fr_light * out_light); -extern RPR_API_ENTRY fr_int frEnvironmentLightSetImage(fr_light env_light, fr_image image); -extern RPR_API_ENTRY fr_int frEnvironmentLightSetIntensityScale(fr_light env_light, fr_float intensity_scale); -extern RPR_API_ENTRY fr_int frEnvironmentLightAttachPortal(fr_light env_light, fr_shape portal); -extern RPR_API_ENTRY fr_int frEnvironmentLightDetachPortal(fr_light env_light, fr_shape portal); -extern RPR_API_ENTRY fr_int frContextCreateSkyLight(fr_context context, fr_light * out_light); -extern RPR_API_ENTRY fr_int frSkyLightSetTurbidity(fr_light skylight, fr_float turbidity); -extern RPR_API_ENTRY fr_int frSkyLightSetAlbedo(fr_light skylight, fr_float albedo); -extern RPR_API_ENTRY fr_int frSkyLightSetScale(fr_light skylight, fr_float scale); -extern RPR_API_ENTRY fr_int frSkyLightAttachPortal(fr_light skylight, fr_shape portal); -extern RPR_API_ENTRY fr_int frSkyLightDetachPortal(fr_light skylight, fr_shape portal); -extern RPR_API_ENTRY fr_int frContextCreateIESLight(fr_context context, fr_light * light); -extern RPR_API_ENTRY fr_int frIESLightSetRadiantPower3f(fr_light light, fr_float r, fr_float g, fr_float b); -extern RPR_API_ENTRY fr_int frIESLightSetImageFromFile(fr_light env_light, fr_char const * imagePath, fr_int nx, fr_int ny); -extern RPR_API_ENTRY fr_int frIESLightSetImageFromIESdata(fr_light env_light, fr_char const * iesData, fr_int nx, fr_int ny); -extern RPR_API_ENTRY fr_int frLightGetInfo(fr_light light, fr_light_info info, size_t size, void * data, size_t * size_ret); -extern RPR_API_ENTRY fr_int frSceneClear(fr_scene scene); -extern RPR_API_ENTRY fr_int frSceneAttachShape(fr_scene scene, fr_shape shape); -extern RPR_API_ENTRY fr_int frSceneDetachShape(fr_scene scene, fr_shape shape); -extern RPR_API_ENTRY fr_int frSceneAttachLight(fr_scene scene, fr_light light); -extern RPR_API_ENTRY fr_int frSceneDetachLight(fr_scene scene, fr_light light); -extern RPR_API_ENTRY fr_int frSceneGetInfo(fr_scene scene, fr_scene_info info, size_t size, void * data, size_t * size_ret); -extern RPR_API_ENTRY fr_int frSceneGetEnvironmentOverride(fr_scene scene, fr_environment_override overrride, fr_light * out_light); -extern RPR_API_ENTRY fr_int frSceneSetEnvironmentOverride(fr_scene scene, fr_environment_override overrride, fr_light light); -extern RPR_API_ENTRY fr_int frSceneSetBackgroundImage(fr_scene scene, fr_image image); -extern RPR_API_ENTRY fr_int frSceneGetBackgroundImage(fr_scene scene, fr_image * out_image); -extern RPR_API_ENTRY fr_int frSceneSetCamera(fr_scene scene, fr_camera camera); -extern RPR_API_ENTRY fr_int frSceneGetCamera(fr_scene scene, fr_camera * out_camera); -extern RPR_API_ENTRY fr_int frFrameBufferGetInfo(fr_framebuffer framebuffer, fr_framebuffer_info info, size_t size, void * data, size_t * size_ret); -extern RPR_API_ENTRY fr_int frFrameBufferClear(fr_framebuffer frame_buffer); -extern RPR_API_ENTRY fr_int frFrameBufferSaveToFile(fr_framebuffer frame_buffer, fr_char const * file_path); -extern RPR_API_ENTRY fr_int frContextResolveFrameBuffer(fr_context context, fr_framebuffer src_frame_buffer, fr_framebuffer dst_frame_buffer, fr_bool normalizeOnly = false); -extern RPR_API_ENTRY fr_int frContextCreateMaterialSystem(fr_context in_context, fr_material_system_type type, fr_material_system * out_matsys); -extern RPR_API_ENTRY fr_int frMaterialSystemCreateNode(fr_material_system in_matsys, fr_material_node_type in_type, fr_material_node * out_node); -extern RPR_API_ENTRY fr_int frMaterialNodeSetInputN(fr_material_node in_node, fr_char const * in_input, fr_material_node in_input_node); -extern RPR_API_ENTRY fr_int frMaterialNodeSetInputF(fr_material_node in_node, fr_char const * in_input, fr_float in_value_x, fr_float in_value_y, fr_float in_value_z, fr_float in_value_w); -extern RPR_API_ENTRY fr_int frMaterialNodeSetInputU(fr_material_node in_node, fr_char const * in_input, fr_uint in_value); -extern RPR_API_ENTRY fr_int frMaterialNodeSetInputImageData(fr_material_node in_node, fr_char const * in_input, fr_image image); -extern RPR_API_ENTRY fr_int frMaterialNodeGetInfo(fr_material_node in_node, fr_material_node_info in_info, size_t in_size, void * in_data, size_t * out_size); -extern RPR_API_ENTRY fr_int frMaterialNodeGetInputInfo(fr_material_node in_node, fr_int in_input_idx, fr_material_node_input_info in_info, size_t in_size, void * in_data, size_t * out_size); -extern RPR_API_ENTRY fr_int frObjectDelete(void * obj); -extern RPR_API_ENTRY fr_int frObjectSetName(void * node, fr_char const * name); -extern RPR_API_ENTRY fr_int frContextCreatePostEffect(fr_context context, fr_post_effect_type type, fr_post_effect * out_effect); -extern RPR_API_ENTRY fr_int frContextAttachPostEffect(fr_context context, fr_post_effect effect); -extern RPR_API_ENTRY fr_int frContextDetachPostEffect(fr_context context, fr_post_effect effect); -extern RPR_API_ENTRY fr_int frPostEffectSetParameter1u(fr_post_effect effect, fr_char const * name, fr_uint x); -extern RPR_API_ENTRY fr_int frPostEffectSetParameter1f(fr_post_effect effect, fr_char const * name, fr_float x); -extern RPR_API_ENTRY fr_int frPostEffectSetParameter3f(fr_post_effect effect, fr_char const * name, fr_float x, fr_float y, fr_float z); -extern RPR_API_ENTRY fr_int frPostEffectSetParameter4f(fr_post_effect effect, fr_char const * name, fr_float x, fr_float y, fr_float z, fr_float w); + typedef rpr_char fr_char; + typedef rpr_uchar fr_uchar; + typedef rpr_int fr_int; + typedef rpr_uint fr_uint; + typedef rpr_long fr_long; + typedef rpr_ulong fr_ulong; + typedef rpr_short fr_short; + typedef rpr_ushort fr_ushort; + typedef rpr_float fr_float; + typedef rpr_double fr_double; + typedef rpr_longlong fr_longlong; + typedef rpr_bool fr_bool; + typedef rpr_bitfield fr_bitfield; + typedef rpr_status fr_status; + typedef rpr_context fr_context; + typedef rpr_camera fr_camera; + typedef rpr_shape fr_shape; + typedef rpr_light fr_light; + typedef rpr_scene fr_scene; + typedef rpr_image fr_image; + typedef rpr_buffer fr_buffer; + typedef rpr_hetero_volume fr_hetero_volume; + typedef rpr_framebuffer fr_framebuffer; + typedef rpr_material_system fr_material_system; + typedef rpr_material_node fr_material_node; + typedef rpr_post_effect fr_post_effect; + typedef rpr_context_properties fr_context_properties; + typedef rpr_composite fr_composite; + typedef rpr_lut fr_lut; + typedef rpr_light_type fr_light_type; + typedef rpr_image_option fr_image_option; + typedef rpr_shape_type fr_shape_type; + typedef rpr_context_type fr_context_type; + typedef rpr_creation_flags fr_creation_flags; + typedef rpr_aa_filter fr_aa_filter; + typedef rpr_context_info fr_context_info; + typedef rpr_camera_info fr_camera_info; + typedef rpr_image_info fr_image_info; + typedef rpr_buffer_info fr_buffer_info; + typedef rpr_shape_info fr_shape_info; + typedef rpr_mesh_info fr_mesh_info; + typedef rpr_mesh_polygon_info fr_mesh_polygon_info; + typedef rpr_mesh_polygon_vertex_info fr_mesh_polygon_vertex_info; + typedef rpr_light_info fr_light_info; + typedef rpr_lut_info fr_lut_info; + typedef rpr_scene_info fr_scene_info; + typedef rpr_parameter_info fr_parameter_info; + typedef rpr_framebuffer_info fr_framebuffer_info; + typedef rpr_channel_order fr_channel_order; + typedef rpr_channel_type fr_channel_type; + typedef rpr_parameter_type fr_parameter_type; + typedef rpr_render_mode fr_render_mode; + typedef rpr_component_type fr_component_type; + typedef rpr_buffer_element_type fr_buffer_element_type; + typedef rpr_camera_mode fr_camera_mode; + typedef rpr_tonemapping_operator fr_tonemapping_operator; + typedef rpr_volume_type fr_volume_type; + typedef rpr_material_system_type fr_material_system_type; + typedef rpr_material_node_type fr_material_node_type; + typedef rpr_material_node_input fr_material_node_input; + typedef rpr_material_node_input_type fr_material_node_input_type; + typedef rpr_material_node_info fr_material_node_info; + typedef rpr_material_node_input_info fr_material_node_input_info; + typedef rpr_aov fr_aov; + typedef rpr_post_effect_type fr_post_effect_type; + typedef rpr_post_effect_info fr_post_effect_info; + typedef rpr_composite_info fr_composite_info; + typedef rpr_composite_type fr_composite_type; + typedef rpr_color_space fr_color_space; + typedef rpr_environment_override fr_environment_override; + typedef rpr_subdiv_boundary_interfop_type fr_subdiv_boundary_interfop_type; + typedef rpr_material_node_lookup_value fr_material_node_lookup_value; + typedef rpr_material_node_uvtype_value fr_material_node_uvtype_value; + typedef rpr_image_wrap_type fr_image_wrap_type; + typedef rpr_image_filter_type fr_image_filter_type; + typedef rpr_material_node_arithmetic_operation fr_material_node_arithmetic_operation; + typedef rpr_hetero_volume_parameter fr_hetero_volume_parameter; + typedef rpr_hetero_volume_indices_topology fr_hetero_volume_indices_topology; + typedef rpr_hetero_volume_filter fr_hetero_volume_filter; + typedef _rpr_image_desc _fr_image_desc; + typedef rpr_image_desc fr_image_desc; + typedef _rpr_buffer_desc _fr_buffer_desc; + typedef rpr_buffer_desc fr_buffer_desc; + typedef _rpr_framebuffer_desc _fr_framebuffer_desc; + typedef rpr_framebuffer_desc fr_framebuffer_desc; + typedef _rpr_render_statistics _fr_render_statistics; + typedef rpr_render_statistics fr_render_statistics; + typedef _rpr_image_format _fr_image_format; + typedef rpr_image_format fr_image_format; + typedef _rpr_ies_image_desc _fr_ies_image_desc; + typedef rpr_ies_image_desc fr_ies_image_desc; + typedef rpr_framebuffer_format fr_framebuffer_format; + extern RPR_API_ENTRY fr_int frRegisterPlugin(fr_char const * path); + extern RPR_API_ENTRY fr_int frCreateContext(fr_int api_version, fr_int * pluginIDs, size_t pluginCount, fr_creation_flags creation_flags, fr_context_properties const * props, fr_char const * cache_path, fr_context * out_context); + extern RPR_API_ENTRY fr_int frContextSetActivePlugin(fr_context context, fr_int pluginID); + extern RPR_API_ENTRY fr_int frContextGetInfo(fr_context context, fr_context_info context_info, size_t size, void * data, size_t * size_ret); + extern RPR_API_ENTRY fr_int frContextGetParameterInfo(fr_context context, int param_idx, fr_parameter_info parameter_info, size_t size, void * data, size_t * size_ret); + extern RPR_API_ENTRY fr_int frContextGetAOV(fr_context context, fr_aov aov, fr_framebuffer * out_fb); + extern RPR_API_ENTRY fr_int frContextSetAOV(fr_context context, fr_aov aov, fr_framebuffer frame_buffer); + extern RPR_API_ENTRY fr_int frContextSetAOVindexLookup(fr_context context, fr_int key, fr_float colorR, fr_float colorG, fr_float colorB, fr_float colorA); + extern RPR_API_ENTRY fr_int frContextSetScene(fr_context context, fr_scene scene); + extern RPR_API_ENTRY fr_int frContextGetScene(fr_context arg0, fr_scene * out_scene); + extern RPR_API_ENTRY fr_int frContextSetParameter1u(fr_context context, fr_char const * name, fr_uint x); + extern RPR_API_ENTRY fr_int frContextSetParameter1f(fr_context context, fr_char const * name, fr_float x); + extern RPR_API_ENTRY fr_int frContextSetParameter3f(fr_context context, fr_char const * name, fr_float x, fr_float y, fr_float z); + extern RPR_API_ENTRY fr_int frContextSetParameter4f(fr_context context, fr_char const * name, fr_float x, fr_float y, fr_float z, fr_float w); + extern RPR_API_ENTRY fr_int frContextSetParameterString(fr_context context, fr_char const * name, fr_char const * value); + extern RPR_API_ENTRY fr_int frContextRender(fr_context context); + extern RPR_API_ENTRY fr_int frContextRenderTile(fr_context context, fr_uint xmin, fr_uint xmax, fr_uint ymin, fr_uint ymax); + extern RPR_API_ENTRY fr_int frContextClearMemory(fr_context context); + extern RPR_API_ENTRY fr_int frContextCreateImage(fr_context context, fr_image_format const format, fr_image_desc const * image_desc, void const * data, fr_image * out_image); + extern RPR_API_ENTRY fr_int frContextCreateBuffer(fr_context context, fr_buffer_desc const * buffer_desc, void const * data, fr_buffer * out_buffer); + extern RPR_API_ENTRY fr_int frContextCreateImageFromFile(fr_context context, fr_char const * path, fr_image * out_image); + extern RPR_API_ENTRY fr_int frContextCreateScene(fr_context context, fr_scene * out_scene); + extern RPR_API_ENTRY fr_int frContextCreateInstance(fr_context context, fr_shape shape, fr_shape * out_instance); + extern RPR_API_ENTRY fr_int frContextCreateMesh(fr_context context, fr_float const * vertices, size_t num_vertices, fr_int vertex_stride, fr_float const * normals, size_t num_normals, fr_int normal_stride, fr_float const * texcoords, size_t num_texcoords, fr_int texcoord_stride, fr_int const * vertex_indices, fr_int vidx_stride, fr_int const * normal_indices, fr_int nidx_stride, fr_int const * texcoord_indices, fr_int tidx_stride, fr_int const * num_face_vertices, size_t num_faces, fr_shape * out_mesh); + extern RPR_API_ENTRY fr_int frContextCreateMeshEx(fr_context context, fr_float const * vertices, size_t num_vertices, fr_int vertex_stride, fr_float const * normals, size_t num_normals, fr_int normal_stride, fr_int const * perVertexFlag, size_t num_perVertexFlags, fr_int perVertexFlag_stride, fr_int numberOfTexCoordLayers, fr_float const ** texcoords, size_t const * num_texcoords, fr_int const * texcoord_stride, fr_int const * vertex_indices, fr_int vidx_stride, fr_int const * normal_indices, fr_int nidx_stride, fr_int const ** texcoord_indices, fr_int const * tidx_stride, fr_int const * num_face_vertices, size_t num_faces, fr_shape * out_mesh); + extern RPR_API_ENTRY fr_int frContextCreateMeshEx2(fr_context context, fr_float const * vertices, size_t num_vertices, fr_int vertex_stride, fr_float const * normals, size_t num_normals, fr_int normal_stride, fr_int const * perVertexFlag, size_t num_perVertexFlags, fr_int perVertexFlag_stride, fr_int numberOfTexCoordLayers, fr_float const ** texcoords, size_t const * num_texcoords, fr_int const * texcoord_stride, fr_int const * vertex_indices, fr_int vidx_stride, fr_int const * normal_indices, fr_int nidx_stride, fr_int const ** texcoord_indices, fr_int const * tidx_stride, fr_int const * num_face_vertices, size_t num_faces, fr_mesh_info const * mesh_properties, fr_shape * out_mesh); + extern RPR_API_ENTRY fr_int frContextCreateCamera(fr_context context, fr_camera * out_camera); + extern RPR_API_ENTRY fr_int frContextCreateFrameBuffer(fr_context context, fr_framebuffer_format const format, fr_framebuffer_desc const * fb_desc, fr_framebuffer * out_fb); + extern RPR_API_ENTRY fr_int frCameraGetInfo(fr_camera camera, fr_camera_info camera_info, size_t size, void * data, size_t * size_ret); + extern RPR_API_ENTRY fr_int frCameraSetFocalLength(fr_camera camera, fr_float flength); + extern RPR_API_ENTRY fr_int frCameraSetLinearMotion(fr_camera camera, fr_float x, fr_float y, fr_float z); + extern RPR_API_ENTRY fr_int frCameraSetAngularMotion(fr_camera camera, fr_float x, fr_float y, fr_float z, fr_float w); + extern RPR_API_ENTRY fr_int frCameraSetFocusDistance(fr_camera camera, fr_float fdist); + extern RPR_API_ENTRY fr_int frCameraSetTransform(fr_camera camera, fr_bool transpose, fr_float * transform); + extern RPR_API_ENTRY fr_int frCameraSetSensorSize(fr_camera camera, fr_float width, fr_float height); + extern RPR_API_ENTRY fr_int frCameraLookAt(fr_camera camera, fr_float posx, fr_float posy, fr_float posz, fr_float atx, fr_float aty, fr_float atz, fr_float upx, fr_float upy, fr_float upz); + extern RPR_API_ENTRY fr_int frCameraSetFStop(fr_camera camera, fr_float fstop); + extern RPR_API_ENTRY fr_int frCameraSetApertureBlades(fr_camera camera, fr_uint num_blades); + extern RPR_API_ENTRY fr_int frCameraSetExposure(fr_camera camera, fr_float exposure); + extern RPR_API_ENTRY fr_int frCameraSetMode(fr_camera camera, fr_camera_mode mode); + extern RPR_API_ENTRY fr_int frCameraSetOrthoWidth(fr_camera camera, fr_float width); + extern RPR_API_ENTRY fr_int frCameraSetFocalTilt(fr_camera camera, fr_float tilt); + extern RPR_API_ENTRY fr_int frCameraSetIPD(fr_camera camera, fr_float ipd); + extern RPR_API_ENTRY fr_int frCameraSetLensShift(fr_camera camera, fr_float shiftx, fr_float shifty); + extern RPR_API_ENTRY fr_int frCameraSetTiltCorrection(fr_camera camera, fr_float tiltX, fr_float tiltY); + extern RPR_API_ENTRY fr_int frCameraSetOrthoHeight(fr_camera camera, fr_float height); + extern RPR_API_ENTRY fr_int frCameraSetNearPlane(fr_camera camera, fr_float near); + extern RPR_API_ENTRY fr_int frCameraSetFarPlane(fr_camera camera, fr_float far); + extern RPR_API_ENTRY fr_int frImageGetInfo(fr_image image, fr_image_info image_info, size_t size, void * data, size_t * size_ret); + extern RPR_API_ENTRY fr_int frImageSetWrap(fr_image image, fr_image_wrap_type type); + extern RPR_API_ENTRY fr_int frImageSetFilter(fr_image image, fr_image_filter_type type); + extern RPR_API_ENTRY fr_int frImageSetGamma(fr_image image, fr_float type); + extern RPR_API_ENTRY fr_int frImageSetMipmapEnabled(fr_image image, fr_bool enabled); + extern RPR_API_ENTRY fr_int frShapeSetTransform(fr_shape shape, fr_bool transpose, fr_float const * transform); + extern RPR_API_ENTRY fr_int frShapeSetSubdivisionFactor(fr_shape shape, fr_uint factor); + extern RPR_API_ENTRY fr_int frShapeSetSubdivisionCreaseWeight(fr_shape shape, fr_float factor); + extern RPR_API_ENTRY fr_int frShapeSetSubdivisionBoundaryInterop(fr_shape shape, fr_subdiv_boundary_interfop_type type); + extern RPR_API_ENTRY fr_int frShapeAutoAdaptSubdivisionFactor(fr_shape shape, fr_framebuffer framebuffer, fr_camera camera, fr_int factor); + extern RPR_API_ENTRY fr_int frShapeSetDisplacementScale(fr_shape shape, fr_float minscale, fr_float maxscale); + extern RPR_API_ENTRY fr_int frShapeSetObjectGroupID(fr_shape shape, fr_uint objectGroupID); + extern RPR_API_ENTRY fr_int frShapeSetLayerMask(fr_shape shape, fr_uint layerMask); + extern RPR_API_ENTRY fr_int frShapeSetDisplacementMaterial(fr_shape shape, fr_material_node materialNode); + extern RPR_API_ENTRY fr_int frShapeSetMaterial(fr_shape shape, fr_material_node node); + extern RPR_API_ENTRY fr_int frShapeSetMaterialFaces(fr_shape shape, fr_material_node node, fr_int* face_indices, size_t num_faces); + extern RPR_API_ENTRY fr_int frShapeSetVolumeMaterial(fr_shape shape, fr_material_node node); + extern RPR_API_ENTRY fr_int frShapeSetLinearMotion(fr_shape shape, fr_float x, fr_float y, fr_float z); + extern RPR_API_ENTRY fr_int frShapeSetAngularMotion(fr_shape shape, fr_float x, fr_float y, fr_float z, fr_float w); + extern RPR_API_ENTRY fr_int frShapeSetScaleMotion(fr_shape shape, fr_float x, fr_float y, fr_float z); + extern RPR_API_ENTRY fr_int frShapeSetVisibility(fr_shape shape, fr_bool visible); + extern RPR_API_ENTRY fr_int frShapeSetVisibilityPrimaryOnly(fr_shape shape, fr_bool visible); + extern RPR_API_ENTRY fr_int frShapeSetVisibilityInSpecular(fr_shape shape, fr_bool visible); + extern RPR_API_ENTRY fr_int frShapeSetShadowCatcher(fr_shape shape, fr_bool shadowCatcher); + extern RPR_API_ENTRY fr_int frShapeSetShadow(fr_shape shape, fr_bool casts_shadow); + extern RPR_API_ENTRY fr_int frLightSetTransform(fr_light light, fr_bool transpose, fr_float const * transform); + extern RPR_API_ENTRY fr_int frLightSetGroupId(fr_light light, fr_uint groupId); + extern RPR_API_ENTRY fr_int frShapeGetInfo(fr_shape arg0, fr_shape_info arg1, size_t arg2, void * arg3, size_t * arg4); + extern RPR_API_ENTRY fr_int frMeshGetInfo(fr_shape mesh, fr_mesh_info mesh_info, size_t size, void * data, size_t * size_ret); + extern RPR_API_ENTRY fr_int frHeteroVolumeGetInfo(fr_hetero_volume heteroVol, fr_hetero_volume_parameter heteroVol_info, size_t size, void * data, size_t * size_ret); + extern RPR_API_ENTRY fr_int frBufferGetInfo(fr_buffer buffer, fr_buffer_info buffer_info, size_t size, void * data, size_t * size_ret); + extern RPR_API_ENTRY fr_int frMeshPolygonGetInfo(fr_shape mesh, size_t polygon_index, fr_mesh_polygon_info polygon_info, size_t size, void * data, size_t * size_ret); + extern RPR_API_ENTRY fr_int frInstanceGetBaseShape(fr_shape shape, fr_shape * out_shape); + extern RPR_API_ENTRY fr_int frContextCreatePointLight(fr_context context, fr_light * out_light); + extern RPR_API_ENTRY fr_int frPointLightSetRadiantPower3f(fr_light light, fr_float r, fr_float g, fr_float b); + extern RPR_API_ENTRY fr_int frContextCreateSpotLight(fr_context context, fr_light * light); + extern RPR_API_ENTRY fr_int frSpotLightSetRadiantPower3f(fr_light light, fr_float r, fr_float g, fr_float b); + extern RPR_API_ENTRY fr_int frSpotLightSetConeShape(fr_light light, fr_float iangle, fr_float oangle); + extern RPR_API_ENTRY fr_int frContextCreateDirectionalLight(fr_context context, fr_light * out_light); + extern RPR_API_ENTRY fr_int frDirectionalLightSetRadiantPower3f(fr_light light, fr_float r, fr_float g, fr_float b); + extern RPR_API_ENTRY fr_int frDirectionalLightSetShadowSoftness(fr_light light, fr_float coeff); + extern RPR_API_ENTRY fr_int frContextCreateEnvironmentLight(fr_context context, fr_light * out_light); + extern RPR_API_ENTRY fr_int frEnvironmentLightSetImage(fr_light env_light, fr_image image); + extern RPR_API_ENTRY fr_int frEnvironmentLightSetIntensityScale(fr_light env_light, fr_float intensity_scale); + extern RPR_API_ENTRY fr_int frEnvironmentLightAttachPortal(fr_scene scene, fr_light env_light, fr_shape portal); + extern RPR_API_ENTRY fr_int frEnvironmentLightDetachPortal(fr_scene scene, fr_light env_light, fr_shape portal); + extern RPR_API_ENTRY fr_int frContextCreateSkyLight(fr_context context, fr_light * out_light); + extern RPR_API_ENTRY fr_int frSkyLightSetTurbidity(fr_light skylight, fr_float turbidity); + extern RPR_API_ENTRY fr_int frSkyLightSetAlbedo(fr_light skylight, fr_float albedo); + extern RPR_API_ENTRY fr_int frSkyLightSetScale(fr_light skylight, fr_float scale); + extern RPR_API_ENTRY fr_int frSkyLightSetDirection(fr_light skylight, fr_float x, fr_float y, fr_float z); + extern RPR_API_ENTRY fr_int frSkyLightAttachPortal(fr_scene scene, fr_light skylight, fr_shape portal); + extern RPR_API_ENTRY fr_int frSkyLightDetachPortal(fr_scene scene, fr_light skylight, fr_shape portal); + extern RPR_API_ENTRY fr_int frContextCreateIESLight(fr_context context, fr_light * light); + extern RPR_API_ENTRY fr_int frIESLightSetRadiantPower3f(fr_light light, fr_float r, fr_float g, fr_float b); + extern RPR_API_ENTRY fr_int frIESLightSetImageFromFile(fr_light env_light, fr_char const * imagePath, fr_int nx, fr_int ny); + extern RPR_API_ENTRY fr_int frIESLightSetImageFromIESdata(fr_light env_light, fr_char const * iesData, fr_int nx, fr_int ny); + extern RPR_API_ENTRY fr_int frLightGetInfo(fr_light light, fr_light_info info, size_t size, void * data, size_t * size_ret); + extern RPR_API_ENTRY fr_int frSceneClear(fr_scene scene); + extern RPR_API_ENTRY fr_int frSceneAttachShape(fr_scene scene, fr_shape shape); + extern RPR_API_ENTRY fr_int frSceneDetachShape(fr_scene scene, fr_shape shape); + extern RPR_API_ENTRY fr_int frSceneAttachHeteroVolume(fr_scene scene, fr_hetero_volume heteroVolume); + extern RPR_API_ENTRY fr_int frSceneDetachHeteroVolume(fr_scene scene, fr_hetero_volume heteroVolume); + extern RPR_API_ENTRY fr_int frSceneAttachLight(fr_scene scene, fr_light light); + extern RPR_API_ENTRY fr_int frSceneDetachLight(fr_scene scene, fr_light light); + extern RPR_API_ENTRY fr_int frSceneGetInfo(fr_scene scene, fr_scene_info info, size_t size, void * data, size_t * size_ret); + extern RPR_API_ENTRY fr_int frSceneGetEnvironmentOverride(fr_scene scene, fr_environment_override overrride, fr_light * out_light); + extern RPR_API_ENTRY fr_int frSceneSetEnvironmentOverride(fr_scene scene, fr_environment_override overrride, fr_light light); + extern RPR_API_ENTRY fr_int frSceneSetBackgroundImage(fr_scene scene, fr_image image); + extern RPR_API_ENTRY fr_int frSceneGetBackgroundImage(fr_scene scene, fr_image * out_image); + extern RPR_API_ENTRY fr_int frSceneSetCamera(fr_scene scene, fr_camera camera); + extern RPR_API_ENTRY fr_int frSceneGetCamera(fr_scene scene, fr_camera * out_camera); + extern RPR_API_ENTRY fr_int frFrameBufferGetInfo(fr_framebuffer framebuffer, fr_framebuffer_info info, size_t size, void * data, size_t * size_ret); + extern RPR_API_ENTRY fr_int frFrameBufferClear(fr_framebuffer frame_buffer); + extern RPR_API_ENTRY fr_int frFrameBufferSaveToFile(fr_framebuffer frame_buffer, fr_char const * file_path); + extern RPR_API_ENTRY fr_int frContextResolveFrameBuffer(fr_context context, fr_framebuffer src_frame_buffer, fr_framebuffer dst_frame_buffer, fr_bool normalizeOnly = false); + extern RPR_API_ENTRY fr_int frContextCreateMaterialSystem(fr_context in_context, fr_material_system_type type, fr_material_system * out_matsys); + extern RPR_API_ENTRY fr_int frMaterialSystemGetSize(fr_context in_context, fr_uint * out_size); + extern RPR_API_ENTRY fr_int frMaterialSystemCreateNode(fr_material_system in_matsys, fr_material_node_type in_type, fr_material_node * out_node); + extern RPR_API_ENTRY fr_int frMaterialNodeSetInputN(fr_material_node in_node, fr_char const * in_input, fr_material_node in_input_node); + extern RPR_API_ENTRY fr_int frMaterialNodeSetInputF(fr_material_node in_node, fr_char const * in_input, fr_float in_value_x, fr_float in_value_y, fr_float in_value_z, fr_float in_value_w); + extern RPR_API_ENTRY fr_int frMaterialNodeSetInputU(fr_material_node in_node, fr_char const * in_input, fr_uint in_value); + extern RPR_API_ENTRY fr_int frMaterialNodeSetInputImageData(fr_material_node in_node, fr_char const * in_input, fr_image image); + extern RPR_API_ENTRY fr_int frMaterialNodeSetInputBufferData(fr_material_node in_node, fr_char const * in_input, fr_buffer buffer); + extern RPR_API_ENTRY fr_int frMaterialNodeGetInfo(fr_material_node in_node, fr_material_node_info in_info, size_t in_size, void * in_data, size_t * out_size); + extern RPR_API_ENTRY fr_int frMaterialNodeGetInputInfo(fr_material_node in_node, fr_int in_input_idx, fr_material_node_input_info in_info, size_t in_size, void * in_data, size_t * out_size); + extern RPR_API_ENTRY fr_int frContextCreateComposite(fr_context context, fr_composite_type in_type, fr_composite * out_composite); + extern RPR_API_ENTRY fr_int frContextCreateLUTFromFile(fr_context context, const fr_char * fileLutPath, fr_lut * out_lut); + extern RPR_API_ENTRY fr_int frContextCreateLUTFromData(fr_context context, const fr_char * lutData, fr_lut * out_lut); + extern RPR_API_ENTRY fr_int frCompositeSetInputFb(fr_composite composite, const fr_char * inputName, fr_framebuffer input); + extern RPR_API_ENTRY fr_int frCompositeSetInputC(fr_composite composite, const fr_char * inputName, fr_composite input); + extern RPR_API_ENTRY fr_int frCompositeSetInputLUT(fr_composite composite, const fr_char * inputName, fr_lut input); + extern RPR_API_ENTRY fr_int frCompositeSetInput4f(fr_composite composite, const fr_char * inputName, float x, float y, float z, float w); + extern RPR_API_ENTRY fr_int frCompositeSetInput1u(fr_composite composite, const fr_char * inputName, unsigned int value); + extern RPR_API_ENTRY fr_int frCompositeSetInputOp(fr_composite composite, const fr_char * inputName, fr_material_node_arithmetic_operation op); + extern RPR_API_ENTRY fr_int frCompositeCompute(fr_composite composite, fr_framebuffer fb); + extern RPR_API_ENTRY fr_int frCompositeGetInfo(fr_composite composite, fr_composite_info composite_info, size_t size, void * data, size_t * size_ret); + extern RPR_API_ENTRY fr_int frObjectDelete(void * obj); + extern RPR_API_ENTRY fr_int frObjectSetName(void * node, fr_char const * name); + extern RPR_API_ENTRY fr_int frContextCreatePostEffect(fr_context context, fr_post_effect_type type, fr_post_effect * out_effect); + extern RPR_API_ENTRY fr_int frContextAttachPostEffect(fr_context context, fr_post_effect effect); + extern RPR_API_ENTRY fr_int frContextDetachPostEffect(fr_context context, fr_post_effect effect); + extern RPR_API_ENTRY fr_int frPostEffectSetParameter1u(fr_post_effect effect, fr_char const * name, fr_uint x); + extern RPR_API_ENTRY fr_int frPostEffectSetParameter1f(fr_post_effect effect, fr_char const * name, fr_float x); + extern RPR_API_ENTRY fr_int frPostEffectSetParameter3f(fr_post_effect effect, fr_char const * name, fr_float x, fr_float y, fr_float z); + extern RPR_API_ENTRY fr_int frPostEffectSetParameter4f(fr_post_effect effect, fr_char const * name, fr_float x, fr_float y, fr_float z, fr_float w); + extern RPR_API_ENTRY fr_int frContextGetAttachedPostEffectCount(fr_context context, fr_uint * nb); + extern RPR_API_ENTRY fr_int frContextGetAttachedPostEffect(fr_context context, fr_uint i, fr_post_effect * out_effect); + extern RPR_API_ENTRY fr_int frPostEffectGetInfo(fr_post_effect effect, fr_post_effect_info info, size_t size, void * data, size_t * size_ret); + extern RPR_API_ENTRY fr_int frContextCreateHeteroVolume(fr_context context, fr_hetero_volume * out_heteroVolume, size_t gridSizeX, size_t gridSizeY, size_t gridSizeZ, void const * indicesList, size_t numberOfIndices, fr_hetero_volume_indices_topology indicesListTopology, void const * gridData, size_t gridDataSizeByte, fr_uint gridDataTopology___unused); + extern RPR_API_ENTRY fr_int frShapeSetHeteroVolume(fr_shape shape, fr_hetero_volume heteroVolume); + extern RPR_API_ENTRY fr_int frHeteroVolumeSetTransform(fr_hetero_volume heteroVolume, fr_bool transpose, fr_float const * transform); + extern RPR_API_ENTRY fr_int frHeteroVolumeSetEmission(fr_hetero_volume heteroVolume, fr_float r, fr_float g, fr_float b); + extern RPR_API_ENTRY fr_int frHeteroVolumeSetAlbedo(fr_hetero_volume heteroVolume, fr_float r, fr_float g, fr_float b); + extern RPR_API_ENTRY fr_int frHeteroVolumeSetFilter(fr_hetero_volume heteroVolume, fr_hetero_volume_filter filter); + + /** @brief Connect nodes + * + * Possible error codes: + * RPR_ERROR_OUT_OF_SYSTEM_MEMORY + * RPR_ERROR_OUT_OF_VIDEO_MEMORY + * + */ + //rprMaterialNodeSetInput*_ext + extern RPR_API_ENTRY rpr_int rprMaterialNodeSetInputN_ext(rpr_material_node in_node, rpr_material_node_input in_input, rpr_material_node in_input_node); + extern RPR_API_ENTRY rpr_int rprMaterialNodeSetInputF_ext(rpr_material_node in_node, rpr_material_node_input in_input, rpr_float in_value_x, rpr_float in_value_y, rpr_float in_value_z, rpr_float in_value_w); + extern RPR_API_ENTRY rpr_int rprMaterialNodeSetInputU_ext(rpr_material_node in_node, rpr_material_node_input in_input, rpr_uint in_value); + extern RPR_API_ENTRY rpr_int rprMaterialNodeSetInputImageData_ext(rpr_material_node in_node, rpr_material_node_input in_input, rpr_image image); + extern RPR_API_ENTRY rpr_int rprMaterialNodeSetInputBufferData_ext(rpr_material_node in_node, rpr_material_node_input in_input, rpr_buffer buffer); + #ifdef __cplusplus } diff --git a/Rpr/RadeonProRender_CL.h b/Rpr/RadeonProRender_CL.h new file mode 100644 index 00000000..0bead4e0 --- /dev/null +++ b/Rpr/RadeonProRender_CL.h @@ -0,0 +1,54 @@ +/*****************************************************************************\ +* +* Module Name FireRender_CL.h +* Project FireRender Engine OpenGL Interop API +* +* Description Fire Render Engine OpenCL Interop header +* +* Copyright 2011 - 2013 Advanced Micro Devices, Inc. +* +* All rights reserved. This notice is intended as a precaution against +* inadvertent publication and does not imply publication or any waiver +* of confidentiality. The year included in the foregoing notice is the +* year of creation of the work. +* @author Dmitry Kozlov (dmitry.kozlov@amd.com) +* @author Takahiro Harada (takahiro.harada@amd.com) +* @bug No known bugs. +* +\*****************************************************************************/ +#ifndef __RADEONPRORENDER_CL_H +#define __RADEONPRORENDER_CL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "RadeonProRender.h" + +/* rpr_context_properties */ +#define RPR_CL_CONTEXT 0x3001 +#define RPR_CL_DEVICE 0x3002 +#define RPR_CL_COMMAND_QUEUE 0x3003 + +/* rpr_framebuffer_properties */ +#define RPR_CL_MEM_OBJECT 0x4001 + +typedef void * rpr_cl_context; +typedef void * rpr_cl_device; +typedef void * rpr_cl_command_queue; +typedef void * rpr_cl_mem; +/***************compatibility part***************/ +#define FR_CL_CONTEXT 0x3001 +#define FR_CL_DEVICE 0x3002 +#define FR_CL_COMMAND_QUEUE 0x3003 +#define FR_CL_MEM_OBJECT 0x4001 +typedef rpr_cl_context fr_cl_context; +typedef rpr_cl_device fr_cl_device; +typedef rpr_cl_command_queue fr_cl_command_queue; +typedef rpr_cl_mem fr_cl_mem; + +#ifdef __cplusplus +} +#endif + +#endif /*__RADEONPRORENDER_CL_H */ diff --git a/Rpr/RadeonProRender_GL.h b/Rpr/RadeonProRender_GL.h new file mode 100644 index 00000000..8aab78b7 --- /dev/null +++ b/Rpr/RadeonProRender_GL.h @@ -0,0 +1,65 @@ +/*****************************************************************************\ +* +* Module Name FireRender_GL.h +* Project FireRender Engine OpenGL Interop API +* +* Description Fire Render Engine OpenGL Interop header +* +* Copyright 2011 - 2013 Advanced Micro Devices, Inc. +* +* All rights reserved. This notice is intended as a precaution against +* inadvertent publication and does not imply publication or any waiver +* of confidentiality. The year included in the foregoing notice is the +* year of creation of the work. +* @author Dmitry Kozlov (dmitry.kozlov@amd.com) +* @author Takahiro Harada (takahiro.harada@amd.com) +* @bug No known bugs. +* +\*****************************************************************************/ +#ifndef __RADEONPRORENDER_GL_H +#define __RADEONPRORENDER_GL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "RadeonProRender.h" + +/* Error codes */ +#define RPR_INVALID_GL_SHAREGROUP_REFERENCE_KHR -1000 + +/* rpr_context_properties */ +#define RPR_GL_CONTEXT_KHR 0x2001 +#define RPR_EGL_DISPLAY_KHR 0x2002 +#define RPR_GLX_DISPLAY_KHR 0x2003 +#define RPR_WGL_HDC_KHR 0x2004 +#define RPR_CGL_SHAREGROUP_KHR 0x2005 + +typedef unsigned int rpr_GLuint; +typedef int rpr_GLint; +typedef unsigned int rpr_GLenum; +typedef rpr_uint rpr_gl_object_type; +typedef rpr_uint rpr_gl_texture_info; +typedef rpr_uint rpr_gl_platform_info; + +extern RPR_API_ENTRY rpr_int rprContextCreateFramebufferFromGLTexture2D(rpr_context context, rpr_GLenum target, rpr_GLint miplevel, rpr_GLuint texture, rpr_framebuffer * out_fb); +/***************compatibility part***************/ +#define FR_INVALID_GL_SHAREGROUP_REFERENCE_KHR -1000 +#define FR_GL_CONTEXT_KHR 0x2001 +#define FR_EGL_DISPLAY_KHR 0x2002 +#define FR_GLX_DISPLAY_KHR 0x2003 +#define FR_WGL_HDC_KHR 0x2004 +#define FR_CGL_SHAREGROUP_KHR 0x2005 +typedef rpr_GLuint fr_GLuint; +typedef rpr_GLint fr_GLint; +typedef rpr_GLenum fr_GLenum; +typedef rpr_gl_object_type fr_gl_object_type; +typedef rpr_gl_texture_info fr_gl_texture_info; +typedef rpr_gl_platform_info fr_gl_platform_info; +extern RPR_API_ENTRY fr_int frContextCreateFramebufferFromGLTexture2D(fr_context context, fr_GLenum target, fr_GLint miplevel, fr_GLuint texture, fr_framebuffer * out_fb); + +#ifdef __cplusplus +} +#endif + +#endif /*__RADEONPRORENDER_GL_H */ diff --git a/Rpr/Rpr.lua b/Rpr/Rpr.lua deleted file mode 100644 index 40679661..00000000 --- a/Rpr/Rpr.lua +++ /dev/null @@ -1,86 +0,0 @@ -project "Rpr" - kind "SharedLib" - location "../Rpr" - links {"RadeonRays", "CLW", "Calc"} - files { "../Rpr/**.h", "../Rpr/**.cpp", "../App/**.h", "../App/**.cpp" } - removefiles{"../App/main.cpp","../App/main_benchmark.cpp", "../App/ImGUI/imgui_impl_glfw_gl3.cpp"} - includedirs{ "../RadeonRays/include", "../CLW", "../App", "." } - - if os.is("macosx") then - sysincludedirs {"/usr/local/include"} - libdirs {"/usr/local/lib"} - linkoptions{ "-framework OpenGL", "-framework GLUT" } - buildoptions "-std=c++11 -stdlib=libc++" - links {"OpenImageIO"} - end - - if os.is("windows") then - includedirs { "../3rdparty/glew/include", "../3rdparty/oiio/include" } - linkoptions { '/DEF:"RadeonProRender.def"' } - - links {"RadeonRays",} - links {"glew", "OpenGL32"} - libdirs { "../3rdparty/glew/lib/%{cfg.platform}", - "../3rdparty/freeglut/lib/%{cfg.platform}", - "../3rdparty/embree/lib/%{cfg.platform}", - "../3rdparty/oiio/lib/%{cfg.platform}"} - - configuration {"Debug"} - links {"OpenImageIOD"} - configuration {"Release"} - links {"OpenImageIO"} - configuration {} - end - - if os.is("linux") then - buildoptions "-std=c++11" - links {"OpenImageIO", "pthread",} - if not _OPTIONS["benchmark"] then - links{"glut", "GLEW", "GL",} - end - os.execute("rm -rf obj"); - end - - if _OPTIONS["use_vulkan"] then - local vulkanSDKPath = os.getenv( "VK_SDK_PATH" ); - if vulkanSDKPath == nil then - vulkanSDKPath = os.getenv( "VULKAN_SDK" ); - end - if vulkanSDKPath ~= nil then - configuration {"x32"} - libdirs { vulkanSDKPath .. "/Bin32" } - configuration {"x64"} - libdirs { vulkanSDKPath .. "/Bin" } - configuration {} - end - if os.is("macosx") then - --no Vulkan on macOs need to error out TODO - elseif os.is("linux") then - libdirs { vulkanSDKPath .. "/lib" } - links { "vulkan"} - elseif os.is("windows") then - links {"Anvil"} - links{"vulkan-1"} - end - end - - - configuration {"x32", "Debug"} - targetdir "../Bin/Debug/x86" - configuration {"x64", "Debug"} - targetdir "../Bin/Debug/x64" - configuration {"x32", "Release"} - targetdir "../Bin/Release/x86" - configuration {"x64", "Release"} - targetdir "../Bin/Release/x64" - configuration {} - - if os.is("windows") then - postbuildcommands { - 'copy "..\\3rdparty\\glew\\bin\\%{cfg.platform}\\glew32.dll" "%{cfg.buildtarget.directory}"', - 'copy "..\\3rdparty\\embree\\bin\\%{cfg.platform}\\embree.dll" "%{cfg.buildtarget.directory}"', - 'copy "..\\3rdparty\\embree\\bin\\%{cfg.platform}\\tbb.dll" "%{cfg.buildtarget.directory}"', - 'copy "..\\3rdparty\\oiio\\bin\\%{cfg.platform}\\OpenImageIO.dll" "%{cfg.buildtarget.directory}"', - 'copy "..\\3rdparty\\oiio\\bin\\%{cfg.platform}\\OpenImageIOD.dll" "%{cfg.buildtarget.directory}"' - } - end \ No newline at end of file diff --git a/Baikal/Utils/config_manager.cpp b/Rpr/Utils/config_manager.cpp similarity index 62% rename from Baikal/Utils/config_manager.cpp rename to Rpr/Utils/config_manager.cpp index 3d02ac40..ab0a3055 100644 --- a/Baikal/Utils/config_manager.cpp +++ b/Rpr/Utils/config_manager.cpp @@ -22,8 +22,8 @@ THE SOFTWARE. #include "config_manager.h" #include "CLW.h" -#include "Renderers/PT/ptrenderer.h" -#include "Renderers/BDPT/bdptrenderer.h" +#include "RenderFactory/render_factory.h" +#include #ifndef APP_BENCHMARK @@ -40,7 +40,10 @@ THE SOFTWARE. #include #endif -void ConfigManager::CreateConfigs(Mode mode, bool interop, std::vector& configs, int initial_num_bounces) +void ConfigManager::CreateConfigs( + rpr_creation_flags flags, + std::vector& configs, + int initial_num_bounces) { std::vector platforms; @@ -53,24 +56,51 @@ void ConfigManager::CreateConfigs(Mode mode, bool interop, std::vector& configs.clear(); - bool hasprimary = false; - for (int i = 0; i < platforms.size(); ++i) + static const std::vector kGpuFlags = { - std::vector devices; + RPR_CREATION_FLAGS_ENABLE_GPU0, + RPR_CREATION_FLAGS_ENABLE_GPU1, + RPR_CREATION_FLAGS_ENABLE_GPU2, + RPR_CREATION_FLAGS_ENABLE_GPU3, + RPR_CREATION_FLAGS_ENABLE_GPU4, + RPR_CREATION_FLAGS_ENABLE_GPU5, + RPR_CREATION_FLAGS_ENABLE_GPU6, + RPR_CREATION_FLAGS_ENABLE_GPU7 + }; + + bool use_cpu = (flags & RPR_CREATION_FLAGS_ENABLE_CPU) == RPR_CREATION_FLAGS_ENABLE_CPU; + bool interop = (flags & RPR_CREATION_FLAGS_ENABLE_GL_INTEROP) == RPR_CREATION_FLAGS_ENABLE_GL_INTEROP; + bool hasprimary = false; - for (int d = 0; d < (int)platforms[i].GetDeviceCount(); ++d) + rpr_uint gpu_counter = 0; + + for (std::size_t i = 0; i < platforms.size(); ++i) + { + for (unsigned int d = 0; d < platforms[i].GetDeviceCount(); ++d) { - if ((mode == kUseGpus || mode == kUseSingleGpu) && platforms[i].GetDevice(d).GetType() != CL_DEVICE_TYPE_GPU) - continue; + cl_device_type device_type = platforms[i].GetDevice(d).GetType(); - if ((mode == kUseCpus || mode == kUseSingleCpu) && platforms[i].GetDevice(d).GetType() != CL_DEVICE_TYPE_CPU) + if (device_type == CL_DEVICE_TYPE_GPU) + { + bool comp = (kGpuFlags[gpu_counter] & flags) == kGpuFlags[gpu_counter]; + ++gpu_counter; + if (!comp) + { + continue; + } + } + + if (!use_cpu && (device_type == CL_DEVICE_TYPE_CPU)) + { continue; + } Config cfg; cfg.caninterop = false; -#ifdef WIN32 + if (platforms[i].GetDevice(d).HasGlInterop() && !hasprimary && interop) { +#ifdef WIN32 cl_context_properties props[] = { //OpenCL platform @@ -81,19 +111,7 @@ void ConfigManager::CreateConfigs(Mode mode, bool interop, std::vector& CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC(), 0 }; - - cfg.context = CLWContext::Create(platforms[i].GetDevice(d), props); - devices.push_back(platforms[i].GetDevice(d)); - cfg.devidx = 0; - cfg.type = kPrimary; - cfg.caninterop = true; - hasprimary = true; - } - else #elif __linux__ - - if (platforms[i].GetDevice(d).HasGlInterop() && !hasprimary && interop) - { cl_context_properties props[] = { //OpenCL platform @@ -104,49 +122,34 @@ void ConfigManager::CreateConfigs(Mode mode, bool interop, std::vector& CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay(), 0 }; - +#elif __APPLE__ + CGLContextObj kCGLContext = CGLGetCurrentContext(); + CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext); + // Create CL context properties, add handle & share-group enum ! + cl_context_properties props[] = { + CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, + (cl_context_properties)kCGLShareGroup, 0 + }; +#endif cfg.context = CLWContext::Create(platforms[i].GetDevice(d), props); - devices.push_back(platforms[i].GetDevice(d)); - cfg.devidx = 0; cfg.type = kPrimary; cfg.caninterop = true; hasprimary = true; } else -#elif __APPLE__ - if (platforms[i].GetDevice(d).HasGlInterop() && !hasprimary && interop) - { - CGLContextObj kCGLContext = CGLGetCurrentContext(); - CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext); - // Create CL context properties, add handle & share-group enum ! - cl_context_properties props[] = { - CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, - (cl_context_properties)kCGLShareGroup, 0 - }; - - cfg.context = CLWContext::Create(platforms[i].GetDevice(d), props); - devices.push_back(platforms[i].GetDevice(d)); - cfg.devidx = 0; - cfg.type = kPrimary; - cfg.caninterop = true; - hasprimary = true; - } - else -#endif { cfg.context = CLWContext::Create(platforms[i].GetDevice(d)); - cfg.devidx = 0; cfg.type = kSecondary; } - configs.push_back(cfg); - - if (mode == kUseSingleGpu || mode == kUseSingleCpu) - break; + configs.push_back(std::move(cfg)); } + } - if (configs.size() == 1 && (mode == kUseSingleGpu || mode == kUseSingleCpu)) - break; + if (configs.size() == 0) + { + throw std::runtime_error( + "No devices was selected (probably device index type does not correspond with real device type)."); } if (!hasprimary) @@ -154,14 +157,22 @@ void ConfigManager::CreateConfigs(Mode mode, bool interop, std::vector& configs[0].type = kPrimary; } - for (int i = 0; i < configs.size(); ++i) + for (std::size_t i = 0; i < configs.size(); ++i) { - configs[i].renderer = new Baikal::MyRenderer(configs[i].context, configs[i].devidx, initial_num_bounces); + configs[i].factory = std::make_unique(configs[i].context, "cache"); + configs[i].controller = configs[i].factory->CreateSceneController(); + configs[i].renderer = configs[i].factory->CreateRenderer(Baikal::ClwRenderFactory::RendererType::kUnidirectionalPathTracer); } } #else -void ConfigManager::CreateConfigs(Mode mode, bool interop, std::vector& configs, int initial_num_bounces) +void ConfigManager::CreateConfigs( + Mode mode, + bool interop, + std::vector& configs, + int initial_num_bounces, + int req_platform_index, + int req_device_index) { std::vector platforms; @@ -175,11 +186,8 @@ void ConfigManager::CreateConfigs(Mode mode, bool interop, std::vector& configs.clear(); bool hasprimary = false; - for (int i = 0; i < platforms.size(); ++i) + for (int i = 0; i < (int)platforms.size(); ++i) { - std::vector devices; - int startidx = (int)configs.size(); - for (int d = 0; d < (int)platforms[i].GetDeviceCount(); ++d) { if ((mode == kUseGpus || mode == kUseSingleGpu) && platforms[i].GetDevice(d).GetType() != CL_DEVICE_TYPE_GPU) @@ -191,10 +199,9 @@ void ConfigManager::CreateConfigs(Mode mode, bool interop, std::vector& Config cfg; cfg.caninterop = false; cfg.context = CLWContext::Create(platforms[i].GetDevice(d)); - cfg.devidx = 0; cfg.type = kSecondary; - configs.push_back(cfg); + configs.push_back(std::move(cfg)); if (mode == kUseSingleGpu || mode == kUseSingleCpu) break; @@ -209,9 +216,11 @@ void ConfigManager::CreateConfigs(Mode mode, bool interop, std::vector& configs[0].type = kPrimary; } - for (int i = 0; i < configs.size(); ++i) + for (std::size_t i = 0; i < configs.size(); ++i) { - configs[i].renderer = new Baikal::PtRenderer(configs[i].context, configs[i].devidx, initial_num_bounces); + configs[i].factory = std::make_unique(configs[i].context); + configs[i].controller = configs[i].factory->CreateSceneController(); + configs[i].renderer = configs[i].factory->CreateRenderer(Baikal::ClwRenderFactory::RendererType::kUnidirectionalPathTracer); } } #endif //APP_BENCHMARK diff --git a/Baikal/Utils/config_manager.h b/Rpr/Utils/config_manager.h similarity index 74% rename from Baikal/Utils/config_manager.h rename to Rpr/Utils/config_manager.h index 00995ba1..e043ca38 100644 --- a/Baikal/Utils/config_manager.h +++ b/Rpr/Utils/config_manager.h @@ -23,13 +23,15 @@ THE SOFTWARE. #define CONFIG_MANAGER_H #include "CLW.h" +#include "RenderFactory/clw_render_factory.h" +#include "Renderers/renderer.h" +#include "RadeonProRender.h" #include +#include namespace Baikal { - class PtRenderer; - class BdptRenderer; - using MyRenderer = PtRenderer; + class Renderer; } class ConfigManager @@ -54,14 +56,25 @@ class ConfigManager struct Config { DeviceType type; - int devidx; - Baikal::MyRenderer* renderer; + std::unique_ptr renderer; + std::unique_ptr> controller; + std::unique_ptr> factory; CLWContext context; bool caninterop; + Config() = default; + + Config(Config&& cfg) = default; + + ~Config() + { + } }; - static void CreateConfigs(Mode mode, bool interop, std::vector& renderers, int initial_num_bounces); + static void CreateConfigs( + rpr_creation_flags flags, + std::vector& configs, + int initial_num_bounces); private: diff --git a/Rpr/Wrap.cpp b/Rpr/Wrap.cpp index 79f8412c..6febae61 100644 --- a/Rpr/Wrap.cpp +++ b/Rpr/Wrap.cpp @@ -1,4 +1,6 @@ #include "RadeonProRender.h" +#include "RadeonProRender_CL.h" +#include "RadeonProRender_GL.h" fr_int frRegisterPlugin(fr_char const * path) { @@ -90,6 +92,11 @@ fr_int frContextCreateImage(fr_context context, fr_image_format const format, fr return rprContextCreateImage(context, format, image_desc, data, out_image); } +fr_int frContextCreateBuffer(fr_context context, fr_buffer_desc const * buffer_desc, void const * data, fr_buffer * out_buffer) +{ + return rprContextCreateBuffer(context, buffer_desc, data, out_buffer); +} + fr_int frContextCreateImageFromFile(fr_context context, fr_char const * path, fr_image * out_image) { return rprContextCreateImageFromFile(context, path, out_image); @@ -110,11 +117,16 @@ fr_int frContextCreateMesh(fr_context context, fr_float const * vertices, size_t return rprContextCreateMesh(context, vertices, num_vertices, vertex_stride, normals, num_normals, normal_stride, texcoords, num_texcoords, texcoord_stride, vertex_indices, vidx_stride, normal_indices, nidx_stride, texcoord_indices, tidx_stride, num_face_vertices, num_faces, out_mesh); } -fr_int frContextCreateMeshEx(fr_context context, fr_float const * vertices, size_t num_vertices, fr_int vertex_stride, fr_float const * normals, size_t num_normals, fr_int normal_stride, fr_int const * perVertexFlag, size_t num_perVertexFlags, fr_int perVertexFlag_stride, fr_int numberOfTexCoordLayers, fr_float const ** texcoords, size_t * num_texcoords, fr_int * texcoord_stride, fr_int const * vertex_indices, fr_int vidx_stride, fr_int const * normal_indices, fr_int nidx_stride, fr_int const ** texcoord_indices, fr_int * tidx_stride, fr_int const * num_face_vertices, size_t num_faces, fr_shape * out_mesh) +fr_int frContextCreateMeshEx(fr_context context, fr_float const * vertices, size_t num_vertices, fr_int vertex_stride, fr_float const * normals, size_t num_normals, fr_int normal_stride, fr_int const * perVertexFlag, size_t num_perVertexFlags, fr_int perVertexFlag_stride, fr_int numberOfTexCoordLayers, fr_float const ** texcoords, size_t const * num_texcoords, fr_int const * texcoord_stride, fr_int const * vertex_indices, fr_int vidx_stride, fr_int const * normal_indices, fr_int nidx_stride, fr_int const ** texcoord_indices, fr_int const * tidx_stride, fr_int const * num_face_vertices, size_t num_faces, fr_shape * out_mesh) { return rprContextCreateMeshEx(context, vertices, num_vertices, vertex_stride, normals, num_normals, normal_stride, perVertexFlag, num_perVertexFlags, perVertexFlag_stride, numberOfTexCoordLayers, texcoords, num_texcoords, texcoord_stride, vertex_indices, vidx_stride, normal_indices, nidx_stride, texcoord_indices, tidx_stride, num_face_vertices, num_faces, out_mesh); } +fr_int frContextCreateMeshEx2(fr_context context, fr_float const * vertices, size_t num_vertices, fr_int vertex_stride, fr_float const * normals, size_t num_normals, fr_int normal_stride, fr_int const * perVertexFlag, size_t num_perVertexFlags, fr_int perVertexFlag_stride, fr_int numberOfTexCoordLayers, fr_float const ** texcoords, size_t const * num_texcoords, fr_int const * texcoord_stride, fr_int const * vertex_indices, fr_int vidx_stride, fr_int const * normal_indices, fr_int nidx_stride, fr_int const ** texcoord_indices, fr_int const * tidx_stride, fr_int const * num_face_vertices, size_t num_faces, fr_mesh_info const * mesh_properties, fr_shape * out_mesh) +{ + return rprContextCreateMeshEx2(context, vertices, num_vertices, vertex_stride, normals, num_normals, normal_stride, perVertexFlag, num_perVertexFlags, perVertexFlag_stride, numberOfTexCoordLayers, texcoords, num_texcoords, texcoord_stride, vertex_indices, vidx_stride, normal_indices, nidx_stride, texcoord_indices, tidx_stride, num_face_vertices, num_faces, mesh_properties, out_mesh); +} + fr_int frContextCreateCamera(fr_context context, fr_camera * out_camera) { return rprContextCreateCamera(context, out_camera); @@ -195,11 +207,26 @@ fr_int frCameraSetLensShift(fr_camera camera, fr_float shiftx, fr_float shifty) return rprCameraSetLensShift(camera, shiftx, shifty); } +fr_int frCameraSetTiltCorrection(fr_camera camera, fr_float tiltX, fr_float tiltY) +{ + return rprCameraSetTiltCorrection(camera, tiltX, tiltY); +} + fr_int frCameraSetOrthoHeight(fr_camera camera, fr_float height) { return rprCameraSetOrthoHeight(camera, height); } +fr_int frCameraSetNearPlane(fr_camera camera, fr_float near) +{ + return rprCameraSetNearPlane(camera, near); +} + +fr_int frCameraSetFarPlane(fr_camera camera, fr_float far) +{ + return rprCameraSetFarPlane(camera, far); +} + fr_int frImageGetInfo(fr_image image, fr_image_info image_info, size_t size, void * data, size_t * size_ret) { return rprImageGetInfo(image, image_info, size, data, size_ret); @@ -240,9 +267,9 @@ fr_int frShapeSetObjectGroupID(fr_shape shape, fr_uint objectGroupID) return rprShapeSetObjectGroupID(shape, objectGroupID); } -fr_int frShapeSetDisplacementImage(fr_shape shape, fr_image image) +fr_int frShapeSetDisplacementMaterial(fr_shape shape, fr_material_node materialNode) { - return rprShapeSetDisplacementImage(shape, image); + return rprShapeSetDisplacementMaterial(shape, materialNode); } fr_int frShapeSetMaterial(fr_shape shape, fr_material_node node) @@ -250,9 +277,9 @@ fr_int frShapeSetMaterial(fr_shape shape, fr_material_node node) return rprShapeSetMaterial(shape, node); } -fr_int frShapeSetMaterialOverride(fr_shape shape, fr_material_node node) +fr_int frShapeSetMaterialFaces(fr_shape shape, fr_material_node node, fr_int* face_indices, size_t num_faces) { - return rprShapeSetMaterialOverride(shape, node); + return rprShapeSetMaterialFaces(shape, node, face_indices, num_faces); } fr_int frShapeSetVolumeMaterial(fr_shape shape, fr_material_node node) @@ -270,6 +297,11 @@ fr_int frShapeSetAngularMotion(fr_shape shape, fr_float x, fr_float y, fr_float return rprShapeSetAngularMotion(shape, x, y, z, w); } +fr_int frShapeSetScaleMotion(fr_shape shape, fr_float x, fr_float y, fr_float z) +{ + return rprShapeSetScaleMotion(shape, x, y, z); +} + fr_int frShapeSetVisibility(fr_shape shape, fr_bool visible) { return rprShapeSetVisibility(shape, visible); @@ -375,14 +407,14 @@ fr_int frEnvironmentLightSetIntensityScale(fr_light env_light, fr_float intensit return rprEnvironmentLightSetIntensityScale(env_light, intensity_scale); } -fr_int frEnvironmentLightAttachPortal(fr_light env_light, fr_shape portal) +fr_int frEnvironmentLightAttachPortal(fr_scene scene, fr_light env_light, fr_shape portal) { - return rprEnvironmentLightAttachPortal(env_light, portal); + return rprEnvironmentLightAttachPortal(scene, env_light, portal); } -fr_int frEnvironmentLightDetachPortal(fr_light env_light, fr_shape portal) +fr_int frEnvironmentLightDetachPortal(fr_scene scene, fr_light env_light, fr_shape portal) { - return rprEnvironmentLightDetachPortal(env_light, portal); + return rprEnvironmentLightDetachPortal(scene, env_light, portal); } fr_int frContextCreateSkyLight(fr_context context, fr_light * out_light) @@ -405,14 +437,14 @@ fr_int frSkyLightSetScale(fr_light skylight, fr_float scale) return rprSkyLightSetScale(skylight, scale); } -fr_int frSkyLightAttachPortal(fr_light skylight, fr_shape portal) +fr_int frSkyLightAttachPortal(fr_scene scene, fr_light skylight, fr_shape portal) { - return rprSkyLightAttachPortal(skylight, portal); + return rprSkyLightAttachPortal(scene, skylight, portal); } -fr_int frSkyLightDetachPortal(fr_light skylight, fr_shape portal) +fr_int frSkyLightDetachPortal(fr_scene scene, fr_light skylight, fr_shape portal) { - return rprSkyLightDetachPortal(skylight, portal); + return rprSkyLightDetachPortal(scene, skylight, portal); } fr_int frContextCreateIESLight(fr_context context, fr_light * light) @@ -455,6 +487,16 @@ fr_int frSceneDetachShape(fr_scene scene, fr_shape shape) return rprSceneDetachShape(scene, shape); } +fr_int frSceneAttachHeteroVolume(fr_scene scene, fr_hetero_volume heteroVolume) +{ + return rprSceneAttachHeteroVolume(scene, heteroVolume); +} + +fr_int frSceneDetachHeteroVolume(fr_scene scene, fr_hetero_volume heteroVolume) +{ + return rprSceneDetachHeteroVolume(scene, heteroVolume); +} + fr_int frSceneAttachLight(fr_scene scene, fr_light light) { return rprSceneAttachLight(scene, light); @@ -525,6 +567,11 @@ fr_int frContextCreateMaterialSystem(fr_context in_context, fr_material_system_t return rprContextCreateMaterialSystem(in_context, type, out_matsys); } +fr_int frMaterialSystemGetSize(fr_context in_context, fr_uint * out_size) +{ + return rprMaterialSystemGetSize(in_context, out_size); +} + fr_int frMaterialSystemCreateNode(fr_material_system in_matsys, fr_material_node_type in_type, fr_material_node * out_node) { return rprMaterialSystemCreateNode(in_matsys, in_type, out_node); @@ -550,6 +597,11 @@ fr_int frMaterialNodeSetInputImageData(fr_material_node in_node, fr_char const * return rprMaterialNodeSetInputImageData(in_node, in_input, image); } +fr_int frMaterialNodeSetInputBufferData(fr_material_node in_node, fr_char const * in_input, fr_buffer buffer) +{ + return rprMaterialNodeSetInputBufferData(in_node, in_input, buffer); +} + fr_int frMaterialNodeGetInfo(fr_material_node in_node, fr_material_node_info in_info, size_t in_size, void * in_data, size_t * out_size) { return rprMaterialNodeGetInfo(in_node, in_info, in_size, in_data, out_size); @@ -560,6 +612,46 @@ fr_int frMaterialNodeGetInputInfo(fr_material_node in_node, fr_int in_input_idx, return rprMaterialNodeGetInputInfo(in_node, in_input_idx, in_info, in_size, in_data, out_size); } +fr_int frContextCreateComposite(fr_context context, fr_composite_type in_type, fr_composite * out_composite) +{ + return rprContextCreateComposite(context, in_type, out_composite); +} + +fr_int frCompositeSetInputFb(fr_composite composite, const char * inputName, fr_framebuffer input) +{ + return rprCompositeSetInputFb(composite, inputName, input); +} + +fr_int frCompositeSetInputC(fr_composite composite, const char * inputName, fr_composite input) +{ + return rprCompositeSetInputC(composite, inputName, input); +} + +fr_int frCompositeSetInput4f(fr_composite composite, const char * inputName, float x, float y, float z, float w) +{ + return rprCompositeSetInput4f(composite, inputName, x, y, z, w); +} + +fr_int frCompositeSetInput1u(fr_composite composite, const char * inputName, unsigned int value) +{ + return rprCompositeSetInput1u(composite, inputName, value); +} + +fr_int frCompositeSetInputOp(fr_composite composite, const char * inputName, fr_material_node_arithmetic_operation op) +{ + return rprCompositeSetInputOp(composite, inputName, op); +} + +fr_int frCompositeCompute(fr_composite composite, fr_framebuffer fb) +{ + return rprCompositeCompute(composite, fb); +} + +fr_int frCompositeGetInfo(fr_composite composite, fr_composite_info composite_info, size_t size, void * data, size_t * size_ret) +{ + return rprCompositeGetInfo(composite, composite_info, size, data, size_ret); +} + fr_int frObjectDelete(void * obj) { return rprObjectDelete(obj); @@ -605,9 +697,43 @@ fr_int frPostEffectSetParameter4f(fr_post_effect effect, fr_char const * name, f return rprPostEffectSetParameter4f(effect, name, x, y, z, w); } -//TODO: RadeonProRender_GL.h -//fr_int frContextCreateFramebufferFromGLTexture2D(fr_context context, fr_GLenum target, fr_GLint miplevel, fr_GLuint texture, fr_framebuffer * out_fb) -//{ -// return rprContextCreateFramebufferFromGLTexture2D(context, target, miplevel, texture, out_fb); -//} +fr_int frContextGetAttachedPostEffectCount(fr_context context, fr_uint * nb) +{ + return rprContextGetAttachedPostEffectCount(context, nb); +} + +fr_int frContextGetAttachedPostEffect(fr_context context, fr_uint i, fr_post_effect * out_effect) +{ + return rprContextGetAttachedPostEffect(context, i, out_effect); +} + +fr_int frPostEffectGetInfo(fr_post_effect effect, fr_post_effect_info info, size_t size, void * data, size_t * size_ret) +{ + return rprPostEffectGetInfo(effect, info, size, data, size_ret); +} + +fr_int frContextCreateHeteroVolume(fr_context context, fr_hetero_volume * out_heteroVolume, size_t gridSizeX, size_t gridSizeY, size_t gridSizeZ, void * indicesList, size_t numberOfIndices, fr_hetero_volume_indices_topology indicesListTopology, void * gridData, size_t gridDataSizeByte, fr_uint gridDataTopology___unused) +{ + return rprContextCreateHeteroVolume(context, out_heteroVolume, gridSizeX, gridSizeY, gridSizeZ, indicesList, numberOfIndices, indicesListTopology, gridData, gridDataSizeByte, gridDataTopology___unused); +} + +fr_int frShapeSetHeteroVolume(fr_shape shape, fr_hetero_volume heteroVolume) +{ + return rprShapeSetHeteroVolume(shape, heteroVolume); +} + +fr_int frHeteroVolumeSetTransform(fr_hetero_volume out_heteroVolume, fr_bool transpose, fr_float const * transform) +{ + return rprHeteroVolumeSetTransform(out_heteroVolume, transpose, transform); +} + +fr_int frContextCreateFramebufferFromGLTexture2D(fr_context context, fr_GLenum target, fr_GLint miplevel, fr_GLuint texture, fr_framebuffer * out_fb) +{ + return rprContextCreateFramebufferFromGLTexture2D(context, target, miplevel, texture, out_fb); +} + +fr_int frLightSetGroupId(fr_light light, fr_uint groupId) +{ + return rprLightSetGroupId(light, groupId); +} diff --git a/Rpr/WrapObject/CameraObject.cpp b/Rpr/WrapObject/CameraObject.cpp index abed05df..712b0cf4 100644 --- a/Rpr/WrapObject/CameraObject.cpp +++ b/Rpr/WrapObject/CameraObject.cpp @@ -24,57 +24,143 @@ THE SOFTWARE. #include "SceneGraph/camera.h" #include "radeon_rays.h" +#include + +#include "WrapObject/SceneObject.h" + using namespace Baikal; using namespace RadeonRays; CameraObject::CameraObject() : m_cam(nullptr) { - - //create perspective camera by default - //set cam default properties - RadeonRays::float3 const eye = { 0.f, 0.f, 0.f }; - RadeonRays::float3 const at = { 0.f , 0.f , -1.f }; - RadeonRays::float3 const up = { 0.f , 1.f , 0.f }; - PerspectiveCamera* camera = new PerspectiveCamera(eye, at, up); - - float2 camera_sensor_size = float2(0.036f, 0.024f); // default full frame sensor 36x24 mm - float2 camera_zcap = float2(0.0f, 100000.f); - float camera_focal_length = 0.035f; // 35mm lens - float camera_focus_distance = 1.f; - float camera_aperture = 0.f; - - camera->SetSensorSize(camera_sensor_size); - camera->SetDepthRange(camera_zcap); - camera->SetFocalLength(camera_focal_length); - camera->SetFocusDistance(camera_focus_distance); - camera->SetAperture(camera_aperture); - m_cam = camera; } CameraObject::~CameraObject() { - delete m_cam; - m_cam = nullptr; } void CameraObject::SetTransform(const RadeonRays::matrix& m) { - //default values - RadeonRays::float3 eye(0.f, 0.f, 0.f); - RadeonRays::float3 at(0.f, 0.f, -1.f); - RadeonRays::float3 up(0.f, 1.f, 0.f); - eye = m * eye; - at = m * at; - up = m * up; - m_cam->LookAt(eye, at, up); + //default values + RadeonRays::float4 eye(0.f, 0.f, 0.f, 1.0f); + RadeonRays::float4 at(0.f, 0.f, -1.f, 0.0f); + RadeonRays::float4 up(0.f, 1.f, 0.f, 0.0f); + m_eye = m * eye; + m_at = m * at; + m_up = m * up; + UpdateCameraParams(); } void CameraObject::GetLookAt(RadeonRays::float3& eye, RadeonRays::float3& at, RadeonRays::float3& up) { - eye = m_cam->GetPosition(); - at = m_cam->GetForwardVector() + eye; - up = m_cam->GetUpVector(); -} \ No newline at end of file + eye = m_eye; + at = m_at; + up = m_up; +} + +Baikal::Camera::Ptr CameraObject::GetCamera() +{ + if (m_mode == RPR_CAMERA_MODE_PERSPECTIVE) + { + Baikal::PerspectiveCamera::Ptr camera = PerspectiveCamera::Create(m_eye, m_at, -m_up); + camera->SetSensorSize(m_camera_sensor_size); + camera->SetDepthRange(m_camera_zcap); + camera->SetFocalLength(m_camera_focal_length); + camera->SetFocusDistance(m_camera_focus_distance); + camera->SetAperture(m_camera_aperture); + m_cam = camera; + return m_cam; + } + else if (m_mode == RPR_CAMERA_MODE_ORTHOGRAPHIC) + { + Baikal::OrthographicCamera::Ptr camera = OrthographicCamera::Create(m_eye, m_at, m_up); + camera->SetSensorSize(m_camera_sensor_size); + camera->SetDepthRange(m_camera_zcap); + m_cam = camera; + return m_cam; + } + + assert(!"Usupported camera type"); + return nullptr; +} + +void CameraObject::LookAt(RadeonRays::float3 const& eye, + RadeonRays::float3 const& at, + RadeonRays::float3 const& up) +{ + m_eye = eye; + m_at = at; + m_up = up; + UpdateCameraParams(); +} + +void CameraObject::SetMode(rpr_camera_mode mode) +{ + m_mode = mode; + UpdateCameraParams(); +} + +void CameraObject::UpdateCameraParams() +{ + // Replace camera in all scenes that have it + for (::SceneObject* scene : m_scenes) + { + scene->SetCamera(this); + } +} + +void CameraObject::AddToScene(::SceneObject* scene) +{ + auto it = std::find(m_scenes.begin(), m_scenes.end(), scene); + if (it != m_scenes.end()) return; + + m_scenes.push_back(scene); +} + +void CameraObject::RemoveFromScene(::SceneObject* scene) +{ + m_scenes.remove(scene); +} + +void CameraObject::SetFocalLength(rpr_float flen) +{ + m_camera_focal_length = flen / 1000.f; + UpdateCameraParams(); +} + +void CameraObject::SetFocusDistance(rpr_float fdist) +{ + m_camera_focus_distance = fdist; + UpdateCameraParams(); +} + +void CameraObject::SetSensorSize(RadeonRays::float2 size) +{ + m_camera_sensor_size = size * 0.001f; + UpdateCameraParams(); +} + +void CameraObject::SetOrthoWidth(float width) +{ + m_camera_sensor_size.x = width; + UpdateCameraParams(); +} + +void CameraObject::SetOrthoHeight(float height) +{ + m_camera_sensor_size.y = height; + UpdateCameraParams(); +} + +void CameraObject::SetAperture(rpr_float fstop) +{ + if (fstop > 1000.f) + { + fstop = 0.f; + } + m_camera_aperture = fstop / 1000.f; + UpdateCameraParams(); +} diff --git a/Rpr/WrapObject/CameraObject.h b/Rpr/WrapObject/CameraObject.h index b29b6afc..b0bcddc9 100644 --- a/Rpr/WrapObject/CameraObject.h +++ b/Rpr/WrapObject/CameraObject.h @@ -21,6 +21,9 @@ THE SOFTWARE. ********************************************************************/ #pragma once +#include + +#include "RadeonProRender.h" #include "WrapObject.h" #include "SceneGraph/camera.h" @@ -31,8 +34,10 @@ namespace Baikal { class PerspectiveCamera; } +class SceneObject; + //this class represent rpr_camera -class CameraObject +class RPR_API_ENTRY CameraObject : public WrapObject { public: @@ -41,28 +46,57 @@ class CameraObject //camera data //Note: some values are converted between meters and mm - void SetFocalLength(rpr_float flen) { m_cam->SetFocalLength(flen / 1000.f); } - rpr_float GetFocalLength() { return m_cam->GetFocalLength() * 1000.f; } + void SetFocalLength(rpr_float flen); + rpr_float GetFocalLength() { return m_camera_focal_length * 1000.f; } - void SetFocusDistance(rpr_float fdist) { m_cam->SetFocusDistance(fdist); } - rpr_float GetFocusDistance() { return m_cam->GetFocusDistance(); } + void SetFocusDistance(rpr_float fdist); + rpr_float GetFocusDistance() { return m_camera_focus_distance; } - void SetSensorSize(RadeonRays::float2 size) { m_cam->SetSensorSize(size * 0.001f); } - RadeonRays::float2 GetSensorSize() { return m_cam->GetSensorSize() * 1000.f; } + void SetSensorSize(RadeonRays::float2 size); + RadeonRays::float2 GetSensorSize() { return m_camera_sensor_size * 1000.f; } + + void SetOrthoWidth(float width); + float GetOrthoWidth() { return m_camera_sensor_size.x; } + + void SetOrthoHeight(float height); + float GetOrthoHeight() { return m_camera_sensor_size.y; } void GetLookAt(RadeonRays::float3& eye, RadeonRays::float3& at, RadeonRays::float3& up); + void LookAt(RadeonRays::float3 const& eye, RadeonRays::float3 const& at, - RadeonRays::float3 const& up) { m_cam->LookAt(eye, at, up); }; + RadeonRays::float3 const& up); - void SetAperture(rpr_float fstop) { m_cam->SetAperture(fstop / 1000.f); } - rpr_float GetAperture() { return m_cam->GetAperture() * 1000.f; } + void SetAperture(rpr_float fstop); + rpr_float GetAperture() { return m_camera_aperture * 1000.f; } void SetTransform(const RadeonRays::matrix& m); + void SetMode(rpr_camera_mode mode); + rpr_camera_mode GetMode() const { return m_mode; } + + Baikal::Camera::Ptr GetCamera(); + + void AddToScene(::SceneObject* scene); + void RemoveFromScene(::SceneObject* scene); + + CameraObject(CameraObject&&) = default; + CameraObject& operator= (CameraObject&&) = default; - Baikal::Camera* GetCamera() { return m_cam; } private: - Baikal::PerspectiveCamera* m_cam; -}; \ No newline at end of file + void UpdateCameraParams(); + Baikal::Camera::Ptr m_cam = 0; + rpr_camera_mode m_mode = RPR_CAMERA_MODE_PERSPECTIVE; + + RadeonRays::float3 m_eye = { 0.f, 0.f, 0.f }; + RadeonRays::float3 m_at = { 0.f , 0.f , -1.f }; + RadeonRays::float3 m_up = { 0.f , 1.f , 0.f }; + RadeonRays::float2 m_camera_sensor_size = { 0.036f, 0.024f }; // default full frame sensor 36x24 mm + RadeonRays::float2 m_camera_zcap = { 0.0f, 100000.f }; + float m_camera_focal_length = 0.035f; // 35mm lens + float m_camera_focus_distance = 1.f; + float m_camera_aperture = 0.f; + + std::list<::SceneObject*> m_scenes; +}; diff --git a/Rpr/WrapObject/ContextObject.cpp b/Rpr/WrapObject/ContextObject.cpp index 02f8eef4..e6dfc2a7 100644 --- a/Rpr/WrapObject/ContextObject.cpp +++ b/Rpr/WrapObject/ContextObject.cpp @@ -27,7 +27,7 @@ THE SOFTWARE. #include "WrapObject/CameraObject.h" #include "WrapObject/LightObject.h" #include "WrapObject/FramebufferObject.h" -#include "WrapObject/MaterialObject.h" +#include "WrapObject/Materials/MaterialObject.h" #include "WrapObject/Exception.h" #include "SceneGraph/scene1.h" @@ -35,6 +35,8 @@ THE SOFTWARE. #include "SceneGraph/material.h" #include "SceneGraph/light.h" +#include "RenderFactory/render_factory.h" + namespace { struct ParameterDesc @@ -91,13 +93,18 @@ namespace { RPR_CONTEXT_GPU6_NAME,{ "gpu6name", "Name of the GPU index 6 in context. Constant value.", RPR_PARAMETER_TYPE_STRING } }, { RPR_CONTEXT_GPU7_NAME,{ "gpu7name", "Name of the GPU index 7 in context. Constant value.", RPR_PARAMETER_TYPE_STRING } }, { RPR_CONTEXT_CPU_NAME,{ "cpuname", "Name of the CPU in context. Constant value.", RPR_PARAMETER_TYPE_STRING } }, + { RPR_CONTEXT_RANDOM_SEED,{ "randseed", "Random seed", RPR_PARAMETER_TYPE_UINT } }, }; std::map kOutputTypeMap = { {RPR_AOV_COLOR, Baikal::Renderer::OutputType::kColor}, {RPR_AOV_GEOMETRIC_NORMAL, Baikal::Renderer::OutputType::kWorldGeometricNormal}, {RPR_AOV_SHADING_NORMAL, Baikal::Renderer::OutputType::kWorldShadingNormal}, {RPR_AOV_UV, Baikal::Renderer::OutputType::kUv}, - {RPR_AOV_WORLD_COORDINATE, Baikal::Renderer::OutputType::kWorldPosition}, + {RPR_AOV_WORLD_COORDINATE, Baikal::Renderer::OutputType::kWorldPosition}, + {RPR_AOV_OBJECT_ID, Baikal::Renderer::OutputType::kMeshID}, + {RPR_AOV_OBJECT_GROUP_ID, Baikal::Renderer::OutputType::kGroupID}, + {RPR_AOV_BACKGROUND, Baikal::Renderer::OutputType::kBackground}, + {RPR_AOV_OPACITY, Baikal::Renderer::OutputType::kOpacity}, }; }// anonymous @@ -107,23 +114,14 @@ ContextObject::ContextObject(rpr_creation_flags creation_flags) { rpr_int result = RPR_SUCCESS; - bool interop = (creation_flags & RPR_CREATION_FLAGS_ENABLE_GL_INTEROP); - if (creation_flags & RPR_CREATION_FLAGS_ENABLE_GPU0) + try { - try - { - //TODO: check num_bounces - ConfigManager::CreateConfigs(ConfigManager::kUseSingleGpu, interop, m_cfgs, 5); - } - catch (...) - { - // failed to create context with interop - result = RPR_ERROR_UNSUPPORTED; - } + //TODO: check num_bounces + ConfigManager::CreateConfigs(creation_flags, m_cfgs, 5); } - else + catch (...) { - result = RPR_ERROR_UNIMPLEMENTED; + result = RPR_ERROR_UNSUPPORTED; } if (result != RPR_SUCCESS) @@ -138,12 +136,16 @@ void ContextObject::GetRenderStatistics(void * out_data, size_t * out_size_ret) { //TODO: more statistics rpr_render_statistics* rs = static_cast(out_data); - for (const auto& cfg : m_cfgs) - { - rs->gpumem_usage += cfg.renderer->m_vidmemws; - rs->gpumem_total += cfg.renderer->m_vidmemws; - rs->gpumem_max_allocation += cfg.renderer->m_vidmemws; - } + rs->gpumem_usage = 0; + rs->gpumem_total = 0; + rs->gpumem_max_allocation = 0; + //for (const auto& cfg : m_cfgs) + //{ + // TODO: implement me + //rs->gpumem_usage += cfg.renderer->GetWorkingSetSize(); + //rs->gpumem_total += cfg.renderer->GetWorkingSetSize(); + //rs->gpumem_max_allocation += cfg.renderer->GetWorkingSetSize(); + //} } if (out_size_ret) { @@ -201,32 +203,38 @@ FramebufferObject* ContextObject::GetAOV(rpr_int in_aov) void ContextObject::Render() { - m_current_scene->AddEmissive(); + PrepareScene(); - //render + //render for (auto& c : m_cfgs) { - c.renderer->Render(*m_current_scene->GetScene()); + auto& scene = c.controller->GetCachedScene(m_current_scene->GetScene()); + c.renderer->Render(scene); } - + PostRender(); } void ContextObject::RenderTile(rpr_uint xmin, rpr_uint xmax, rpr_uint ymin, rpr_uint ymax) { - m_current_scene->AddEmissive(); + PrepareScene(); + const RadeonRays::int2 origin = { (int)xmin, (int)ymin }; const RadeonRays::int2 size = { (int)xmax - (int)xmin, (int)ymax - (int)ymin }; //render for (auto& c : m_cfgs) { - c.renderer->RenderTile(*m_current_scene->GetScene(), origin, size); + auto& scene = c.controller->GetCachedScene(m_current_scene->GetScene()); + c.renderer->RenderTile(scene, origin, size); } + PostRender(); } SceneObject* ContextObject::CreateScene() { - return new SceneObject(); + auto scene = new SceneObject; + m_current_scene = m_current_scene ? m_current_scene : scene; + return scene; } MatSysObject* ContextObject::CreateMaterialSystem() @@ -262,15 +270,15 @@ ShapeObject* ContextObject::CreateShapeInstance(ShapeObject* mesh) return mesh->CreateInstance(); } -MaterialObject* ContextObject::CreateTexture(rpr_image_format const in_format, rpr_image_desc const * in_image_desc, void const * in_data) +MaterialObject* ContextObject::CreateImage(rpr_image_format const in_format, rpr_image_desc const * in_image_desc, void const * in_data) { - MaterialObject* result = new MaterialObject(in_format, in_image_desc, in_data); + MaterialObject* result = MaterialObject::CreateImage(in_format, in_image_desc, in_data); return result; } -MaterialObject* ContextObject::CreateTextureFromFile(rpr_char const * in_path) +MaterialObject* ContextObject::CreateImageFromFile(rpr_char const * in_path) { - MaterialObject* result = new MaterialObject(in_path); + MaterialObject* result = MaterialObject::CreateImage(in_path); return result; } @@ -290,15 +298,58 @@ FramebufferObject* ContextObject::CreateFrameBuffer(rpr_framebuffer_format const //TODO:: implement for several devices if (m_cfgs.size() != 1) { - throw Exception(RPR_ERROR_INTERNAL_ERROR, "ContextObject: incalid config count."); + throw Exception(RPR_ERROR_UNIMPLEMENTED, "ContextObject: invalid config count."); + } + auto& c = m_cfgs[0]; + Baikal::Output* out = c.factory->CreateOutput(in_fb_desc->fb_width, in_fb_desc->fb_height).release(); + FramebufferObject* result = new FramebufferObject(out); + return result; +} + +FramebufferObject* ContextObject::CreateFrameBufferFromGLTexture(rpr_GLenum target, rpr_GLint miplevel, rpr_GLuint texture) +{ + //TODO:: implement for several devices + if (m_cfgs.size() != 1) + { + throw Exception(RPR_ERROR_INTERNAL_ERROR, "ContextObject: invalid config count."); } auto& c = m_cfgs[0]; - FramebufferObject* result = new FramebufferObject(); - Baikal::Output* out = c.renderer->CreateOutput(in_fb_desc->fb_width, in_fb_desc->fb_height); + auto copykernel = static_cast(c.renderer.get())->GetCopyKernel(); + FramebufferObject* result = new FramebufferObject(c.context, copykernel, target, miplevel, texture); + std::uint32_t w = static_cast(result->Width()); + std::uint32_t h = static_cast(result->Height()); + Baikal::Output* out = c.factory->CreateOutput(w, h).release(); result->SetOutput(out); return result; } +void ContextObject::SetParameter(const std::string& input, rpr_uint value) +{ + auto it = std::find_if(kContextParameterDescriptions.begin(), kContextParameterDescriptions.end(), + [input](std::pair desc) { return desc.second.name == input; }); + + if (it == kContextParameterDescriptions.end()) + { + throw Exception(RPR_ERROR_INVALID_TAG, "ContextObject: invalid context input parameter."); + } + else if (it->second.type != RPR_PARAMETER_TYPE_UINT) + { + throw Exception(RPR_ERROR_INVALID_PARAMETER_TYPE, "ContextObject: invalid context input type."); + } + + switch (it->first) + { + case RPR_CONTEXT_RANDOM_SEED: + for (auto& c : m_cfgs) + { + c.renderer->SetRandomSeed(value); + } + break; + default: + throw Exception(RPR_ERROR_UNIMPLEMENTED, "ContextObject: requested parameter is not implemented"); + } +} + void ContextObject::SetParameter(const std::string& input, float x, float y, float z, float w) { auto it = std::find_if(kContextParameterDescriptions.begin(), kContextParameterDescriptions.end(), [input](std::pair desc) { return desc.second.name == input; }); @@ -327,4 +378,26 @@ void ContextObject::SetParameter(const std::string& input, const std::string& va { throw Exception(RPR_ERROR_INVALID_PARAMETER_TYPE, "ContextObject: invalid context input type."); } -} \ No newline at end of file +} + +void ContextObject::PrepareScene() +{ + m_current_scene->AddEmissive(); + + //if (m_current_scene->IsDirty()) + { + for (auto& c : m_cfgs) + { + c.controller->CompileScene(m_current_scene->GetScene()); + } + } +} + +void ContextObject::PostRender() +{ + // need to copy data from CL to GL for interop framebuffers + for (auto fb : m_output_framebuffers) + { + fb->UpdateGlTex(); + } +} diff --git a/Rpr/WrapObject/ContextObject.h b/Rpr/WrapObject/ContextObject.h index 1167af95..745c24a8 100644 --- a/Rpr/WrapObject/ContextObject.h +++ b/Rpr/WrapObject/ContextObject.h @@ -24,11 +24,12 @@ THE SOFTWARE. #include "WrapObject/WrapObject.h" #include "WrapObject/LightObject.h" -#include "App/Utils/config_manager.h" -#include "App/Renderers/PT/ptrenderer.h" +#include "Utils/config_manager.h" +#include "Renderers/monte_carlo_renderer.h" #include #include "RadeonProRender.h" +#include "RadeonProRender_GL.h" class TextureObject; class FramebufferObject; @@ -51,6 +52,7 @@ class ContextObject //context info void GetRenderStatistics(void * out_data, size_t * out_size_ret) const; + void SetParameter(const std::string& input, rpr_uint value); void SetParameter(const std::string& input, float x, float y = 0.f, float z = 0.f, float w = 0.f); void SetParameter(const std::string& input, const std::string& value); @@ -74,14 +76,20 @@ class ContextObject rpr_int const * in_texcoord_indices, rpr_int in_tidx_stride, rpr_int const * in_num_face_vertices, size_t in_num_faces); ShapeObject* CreateShapeInstance(ShapeObject* mesh); - MaterialObject* CreateTexture(rpr_image_format const in_format, rpr_image_desc const * in_image_desc, void const * in_data); - MaterialObject* CreateTextureFromFile(rpr_char const * in_path); + MaterialObject* CreateImage(rpr_image_format const in_format, rpr_image_desc const * in_image_desc, void const * in_data); + MaterialObject* CreateImageFromFile(rpr_char const * in_path); CameraObject* CreateCamera(); FramebufferObject* CreateFrameBuffer(rpr_framebuffer_format const in_format, rpr_framebuffer_desc const * in_fb_desc); + FramebufferObject* CreateFrameBufferFromGLTexture(rpr_GLenum target, rpr_GLint miplevel, rpr_GLuint texture); private: + void PrepareScene(); + + //after render update + void PostRender(); + //render configs std::vector m_cfgs; //know framefubbers used as AOV outputs std::set m_output_framebuffers; SceneObject* m_current_scene; -}; \ No newline at end of file +}; diff --git a/Rpr/WrapObject/FramebufferObject.cpp b/Rpr/WrapObject/FramebufferObject.cpp index 674450c0..9f7747bc 100644 --- a/Rpr/WrapObject/FramebufferObject.cpp +++ b/Rpr/WrapObject/FramebufferObject.cpp @@ -20,59 +20,113 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ********************************************************************/ +#include "GL/glew.h" #include "WrapObject/FramebufferObject.h" #include "WrapObject/Exception.h" -#include "App/CLW/clwoutput.h" +#include "Output/clwoutput.h" #include "OpenImageIO/imageio.h" #include "RadeonProRender.h" +#include "RadeonProRender_GL.h" +#include "Renderers/monte_carlo_renderer.h" -FramebufferObject::FramebufferObject() - : m_out(nullptr) +FramebufferObject::FramebufferObject(Baikal::Output* out) + : m_output(out) + , m_width(out->width()) + , m_height(out->height()) { } -FramebufferObject::~FramebufferObject() +FramebufferObject::FramebufferObject(CLWContext context, CLWKernel copy_kernel, rpr_GLenum target, rpr_GLint miplevel, rpr_GLuint texture) + : m_output(nullptr) + , m_width(0) + , m_height(0) + , m_context(context) + , m_copy_cernel(copy_kernel) { - delete m_out; - m_out = nullptr; + if (target != GL_TEXTURE_2D) + { + throw Exception(RPR_ERROR_INTERNAL_ERROR, "Unsupported GL texture target."); + } + + //need to get width and height of GL texture + GLint backup_tex = 0; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &backup_tex); + glBindTexture(target, texture); + glGetTexLevelParameteriv(target, miplevel, GL_TEXTURE_WIDTH, (GLint*)&m_width); + glGetTexLevelParameteriv(target, miplevel, GL_TEXTURE_HEIGHT, (GLint*)&m_height); + + //create interop image + m_cl_interop_image = context.CreateImage2DFromGLTexture(texture); + glBindTexture(target, backup_tex); } -int FramebufferObject::GetWidth() +FramebufferObject::~FramebufferObject() { - return m_out->width(); + delete m_output; + m_output = nullptr; } -int FramebufferObject::GetHeight() +std::size_t FramebufferObject::Width() { - return m_out->height(); + return m_width; +} +std::size_t FramebufferObject::Height() +{ + return m_height; } void FramebufferObject::GetData(void* out_data) { - m_out->GetData(static_cast(out_data)); + m_output->GetData(static_cast(out_data)); } void FramebufferObject::Clear() { - Baikal::ClwOutput* output = dynamic_cast(m_out); + Baikal::ClwOutput* output = dynamic_cast(m_output); output->Clear(RadeonRays::float3(0.f, 0.f, 0.f, 0.f)); } + +void FramebufferObject::UpdateGlTex() +{ + //only if FramebufferObject was created from GL texture + if (m_cl_interop_image) + { + std::vector objects; + objects.push_back(m_cl_interop_image); + m_context.AcquireGLObjects(0, objects); + + int argc = 0; + m_copy_cernel.SetArg(argc++, static_cast(GetOutput())->data()); + m_copy_cernel.SetArg(argc++, static_cast(Width())); + m_copy_cernel.SetArg(argc++, static_cast(Height())); + m_copy_cernel.SetArg(argc++, 2.2f); + m_copy_cernel.SetArg(argc++, m_cl_interop_image); + + std::size_t globalsize = Width() * Height(); + m_context.Launch1D(0, ((globalsize + 63) / 64) * 64, 64, m_copy_cernel); + + m_context.ReleaseGLObjects(0, objects); + m_context.Finish(0); + } +} + + void FramebufferObject::SaveToFile(const char* path) { OIIO_NAMESPACE_USING; - int width = m_out->width(); - int height = m_out->height(); + std::size_t width = Width(); + size_t height = Height(); std::vector tempbuf(width * height); - m_out->GetData(tempbuf.data()); + GetData(tempbuf.data()); std::vector data(tempbuf); //convert pixels - for (auto y = 0; y < height; ++y) + for (std::size_t y = 0; y < height; ++y) { - for (auto x = 0; x < width; ++x) + for (std::size_t x = 0; x < width; ++x) { RadeonRays::float3 val = data[(height - 1 - y) * width + x]; @@ -91,9 +145,9 @@ void FramebufferObject::SaveToFile(const char* path) throw Exception(RPR_ERROR_IO_ERROR, "FramebufferObject: failed to create file."); } - ImageSpec spec(width, height, 3, TypeDesc::FLOAT); + ImageSpec spec(static_cast(width), static_cast(height), 3, TypeDesc::FLOAT); out->open(path, spec); out->write_image(TypeDesc::FLOAT, &tempbuf[0], sizeof(RadeonRays::float3)); out->close(); delete out; -} \ No newline at end of file +} diff --git a/Rpr/WrapObject/FramebufferObject.h b/Rpr/WrapObject/FramebufferObject.h index 4d71187d..897823d5 100644 --- a/Rpr/WrapObject/FramebufferObject.h +++ b/Rpr/WrapObject/FramebufferObject.h @@ -22,31 +22,41 @@ THE SOFTWARE. #pragma once #include "WrapObject.h" -#include "CLW/clwoutput.h" +#include "Output/clwoutput.h" +#include "Renderers/renderer.h" +#include "RadeonProRender_GL.h" //this class represent rpr_context class FramebufferObject : public WrapObject { public: - FramebufferObject(); + FramebufferObject(Baikal::Output* out); + FramebufferObject(CLWContext context, CLWKernel copy_cernel, rpr_GLenum target, rpr_GLint miplevel, rpr_GLuint texture); virtual ~FramebufferObject(); //output void SetOutput(Baikal::Output* out) { - delete m_out; - m_out = out; + delete m_output; + m_output = out; } - int GetWidth(); - int GetHeight(); + std::size_t Width(); + std::size_t Height(); void GetData(void* out_data); void Clear(); void SaveToFile(const char* path); - - Baikal::Output* GetOutput() { return m_out; } + + //if interop this will copy CL output data to GL texture + void UpdateGlTex(); + Baikal::Output* GetOutput() { return m_output; } private: - Baikal::Output* m_out; -}; \ No newline at end of file + Baikal::Output* m_output; + std::size_t m_width; + std::size_t m_height; + CLWImage2D m_cl_interop_image; + CLWContext m_context; + CLWKernel m_copy_cernel; +}; diff --git a/Rpr/WrapObject/LightObject.cpp b/Rpr/WrapObject/LightObject.cpp index bb082f3e..f004aff7 100644 --- a/Rpr/WrapObject/LightObject.cpp +++ b/Rpr/WrapObject/LightObject.cpp @@ -20,10 +20,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ********************************************************************/ #include "WrapObject/LightObject.h" -#include "WrapObject/MaterialObject.h" +#include "WrapObject/Materials/MaterialObject.h" #include "WrapObject/Exception.h" #include "radeon_rays.h" -#include "App/SceneGraph/light.h" +#include "SceneGraph/light.h" #include "RadeonProRender.h" void LightObject::SetTransform(const RadeonRays::matrix& t) @@ -58,17 +58,21 @@ LightObject::LightObject(Type type) switch (type) { case Type::kPointLight: - m_light = new Baikal::PointLight(); + m_light = Baikal::PointLight::Create(); break; case Type::kSpotLight: - m_light = new Baikal::SpotLight(); + m_light = Baikal::SpotLight::Create(); break; case Type::kDirectionalLight: - m_light = new Baikal::DirectionalLight(); + m_light = Baikal::DirectionalLight::Create(); break; case Type::kEnvironmentLight: - m_light = new Baikal::ImageBasedLight(); + { + m_light = Baikal::ImageBasedLight::Create(); + auto ibl = std::dynamic_pointer_cast(m_light); + ibl->SetMirrorX(true); break; + } default: throw Exception(RPR_ERROR_INVALID_PARAMETER, "LightObject: unexpected light type"); } @@ -76,8 +80,26 @@ LightObject::LightObject(Type type) LightObject::~LightObject() { - delete m_light; - m_light = nullptr; +} + +void LightObject::SetPosition(const RadeonRays::float3& position) +{ + m_light->SetPosition(position); +} + +RadeonRays::float3 LightObject::GetPosition() +{ + return m_light->GetPosition(); +} + +void LightObject::SetDirection(const RadeonRays::float3& direction) +{ + m_light->SetDirection(direction); +} + +RadeonRays::float3 LightObject::GetDirection() +{ + return m_light->GetDirection(); } void LightObject::SetRadiantPower(const RadeonRays::float3& p) @@ -93,20 +115,20 @@ RadeonRays::float3 LightObject::GetRadiantPower() void LightObject::SetSpotConeShape(const RadeonRays::float2& cone) { - Baikal::SpotLight* spot = dynamic_cast(m_light); + auto spot = std::dynamic_pointer_cast(m_light); spot->SetConeShape(cone); } RadeonRays::float2 LightObject::GetSpotConeShape() { - Baikal::SpotLight* spot = dynamic_cast(m_light); + auto spot = std::dynamic_pointer_cast(m_light); return spot->GetConeShape(); } void LightObject::SetEnvTexture(MaterialObject* img) { - Baikal::ImageBasedLight* ibl = dynamic_cast(m_light); + auto ibl = std::dynamic_pointer_cast(m_light); ibl->SetTexture(img->GetTexture()); m_env_tex = img; } @@ -119,13 +141,13 @@ MaterialObject* LightObject::GetEnvTexture() void LightObject::SetEnvMultiplier(rpr_float mult) { - Baikal::ImageBasedLight* ibl = dynamic_cast(m_light); + auto ibl = std::dynamic_pointer_cast(m_light); ibl->SetMultiplier(mult); } rpr_float LightObject::GetEnvMultiplier() { - Baikal::ImageBasedLight* ibl = dynamic_cast(m_light); + auto ibl = std::dynamic_pointer_cast(m_light); return ibl->GetMultiplier(); } diff --git a/Rpr/WrapObject/LightObject.h b/Rpr/WrapObject/LightObject.h index 6d8dde55..09b921ff 100644 --- a/Rpr/WrapObject/LightObject.h +++ b/Rpr/WrapObject/LightObject.h @@ -21,20 +21,17 @@ THE SOFTWARE. ********************************************************************/ #pragma once +#include "RadeonProRender.h" #include "WrapObject.h" #include "math/matrix.h" #include "math/float2.h" #include "math/float3.h" #include "RadeonProRender.h" - -namespace Baikal -{ - class Light; -} +#include "SceneGraph/light.h" class MaterialObject; -class LightObject +class RPR_API_ENTRY LightObject : public WrapObject { public: @@ -49,12 +46,18 @@ class LightObject virtual ~LightObject(); Type GetType() const { return m_type; }; - Baikal::Light* GetLight() const { return m_light; }; + Baikal::Light::Ptr GetLight() const { return m_light; }; //light methods void SetTransform(const RadeonRays::matrix& transform); RadeonRays::matrix GetTransform(); - + + void SetPosition(const RadeonRays::float3& position); + RadeonRays::float3 GetPosition(); + + void SetDirection(const RadeonRays::float3& direction); + RadeonRays::float3 GetDirection(); + void SetRadiantPower(const RadeonRays::float3& p); RadeonRays::float3 GetRadiantPower(); @@ -67,9 +70,13 @@ class LightObject MaterialObject* GetEnvTexture(); void SetEnvMultiplier(rpr_float mult); rpr_float GetEnvMultiplier(); + + LightObject(LightObject&&) = default; + LightObject& operator= (LightObject&&) = default; + private: - Baikal::Light* m_light; Type m_type; + Baikal::Light::Ptr m_light; //only for GetEnvTexture() method MaterialObject* m_env_tex; -}; \ No newline at end of file +}; diff --git a/Rpr/WrapObject/MatSysObject.cpp b/Rpr/WrapObject/MatSysObject.cpp index 71b1132d..af40ee89 100644 --- a/Rpr/WrapObject/MatSysObject.cpp +++ b/Rpr/WrapObject/MatSysObject.cpp @@ -21,9 +21,9 @@ THE SOFTWARE. ********************************************************************/ #include "MatSysObject.h" -#include "WrapObject/MaterialObject.h" +#include "WrapObject/Materials/MaterialObject.h" MaterialObject* MatSysObject::CreateMaterial(rpr_material_node_type in_type) { - return new MaterialObject(in_type); + return MaterialObject::CreateMaterial(in_type); } \ No newline at end of file diff --git a/Rpr/WrapObject/MaterialObject.cpp b/Rpr/WrapObject/MaterialObject.cpp deleted file mode 100644 index 95f9490f..00000000 --- a/Rpr/WrapObject/MaterialObject.cpp +++ /dev/null @@ -1,670 +0,0 @@ -/********************************************************************** -Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. - -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 "math/int2.h" -#include "App/SceneGraph/texture.h" -#include "App/SceneGraph/material.h" -#include "App/SceneGraph/IO/image_io.h" -#include "App/SceneGraph/iterator.h" -#include "WrapObject/MaterialObject.h" -#include "WrapObject/Exception.h" - - -using namespace RadeonRays; -using namespace Baikal; - -namespace -{ - //contains pairs of input names - const std::map kInputNamesDictionary = { { "color" , "albedo" }, - { "normal" , "normal" }, - { "roughness" , "roughness" }, - { "roughness_x" , "roughness" }, - { "weight" , "weight" }, - { "ior" , "ior" }, - { "color0", "base_material" }, - { "color1", "top_material" }, - { "data", "data" }, }; - - std::map kMaterialNodeInputStrings = { - { RPR_MATERIAL_INPUT_COLOR, "color" }, - { RPR_MATERIAL_INPUT_COLOR0, "color0" }, - { RPR_MATERIAL_INPUT_COLOR1, "color1" }, - { RPR_MATERIAL_INPUT_NORMAL, "normal" }, - { RPR_MATERIAL_INPUT_UV, "uv" }, - { RPR_MATERIAL_INPUT_DATA, "data" }, - { RPR_MATERIAL_INPUT_ROUGHNESS, "roughness" }, - { RPR_MATERIAL_INPUT_IOR, "ior" }, - { RPR_MATERIAL_INPUT_ROUGHNESS_X, "roughness_x" }, - { RPR_MATERIAL_INPUT_ROUGHNESS_Y, "roughness_y" }, - { RPR_MATERIAL_INPUT_ROTATION, "rotation" }, - { RPR_MATERIAL_INPUT_WEIGHT, "weight" }, - { RPR_MATERIAL_INPUT_OP, "op" }, - { RPR_MATERIAL_INPUT_INVEC, "invec" }, - { RPR_MATERIAL_INPUT_UV_SCALE, "uv_scale" }, - { RPR_MATERIAL_INPUT_VALUE, "value" }, - { RPR_MATERIAL_INPUT_REFLECTANCE, "reflectance" }, - { RPR_MATERIAL_INPUT_SCALE, "bumpscale" }, - { RPR_MATERIAL_INPUT_SCATTERING, "sigmas" }, - { RPR_MATERIAL_INPUT_ABSORBTION, "sigmaa" }, - { RPR_MATERIAL_INPUT_EMISSION, "emission" }, - { RPR_MATERIAL_INPUT_G, "g" }, - { RPR_MATERIAL_INPUT_MULTISCATTER, "multiscatter" }, - - { RPR_MATERIAL_STANDARD_INPUT_DIFFUSE_COLOR, "diffuse.color" }, - { RPR_MATERIAL_STANDARD_INPUT_DIFFUSE_NORMAL, "diffuse.normal" }, - { RPR_MATERIAL_STANDARD_INPUT_GLOSSY_COLOR, "glossy.color" }, - { RPR_MATERIAL_STANDARD_INPUT_GLOSSY_NORMAL, "glossy.normal" }, - { RPR_MATERIAL_STANDARD_INPUT_GLOSSY_ROUGHNESS_X, "glossy.roughness_x" }, - { RPR_MATERIAL_STANDARD_INPUT_GLOSSY_ROUGHNESS_Y, "glossy.roughness_y" }, - { RPR_MATERIAL_STANDARD_INPUT_CLEARCOAT_COLOR, "clearcoat.color" }, - { RPR_MATERIAL_STANDARD_INPUT_CLEARCOAT_NORMAL, "clearcoat.normal" }, - { RPR_MATERIAL_STANDARD_INPUT_REFRACTION_COLOR, "refraction.color" }, - { RPR_MATERIAL_STANDARD_INPUT_REFRACTION_NORMAL, "refraction.normal" }, - { RPR_MATERIAL_STANDARD_INPUT_REFRACTION_ROUGHNESS, "refraction.roughness" }, // REFRACTION doesn't have roughness parameter. - { RPR_MATERIAL_STANDARD_INPUT_REFRACTION_IOR, "refraction.ior" }, - { RPR_MATERIAL_STANDARD_INPUT_TRANSPARENCY_COLOR, "transparency.color" }, - { RPR_MATERIAL_STANDARD_INPUT_DIFFUSE_TO_REFRACTION_WEIGHT, "weights.diffuse2refraction" }, - { RPR_MATERIAL_STANDARD_INPUT_GLOSSY_TO_DIFFUSE_WEIGHT, "weights.glossy2diffuse" }, - { RPR_MATERIAL_STANDARD_INPUT_CLEARCOAT_TO_GLOSSY_WEIGHT, "weights.clearcoat2glossy" }, - { RPR_MATERIAL_STANDARD_INPUT_TRANSPARENCY, "weights.transparency" }, - - }; - - //these materials are unsupported now: - const std::set kUnsupportedMaterials = { RPR_MATERIAL_NODE_ADD, - RPR_MATERIAL_NODE_ARITHMETIC, - RPR_MATERIAL_NODE_BLEND_VALUE, - RPR_MATERIAL_NODE_VOLUME, - RPR_MATERIAL_NODE_INPUT_LOOKUP, }; -} -MaterialObject::MaterialObject(rpr_material_node_type in_type) -{ - m_is_tex = false; - switch (in_type) - { - case RPR_MATERIAL_NODE_DIFFUSE: - case RPR_MATERIAL_NODE_ORENNAYAR: - { - SingleBxdf* mat = new SingleBxdf(SingleBxdf::BxdfType::kLambert); - m_mat = mat; - break; - } - case RPR_MATERIAL_NODE_WARD: - case RPR_MATERIAL_NODE_MICROFACET: - { - SingleBxdf* mat = new SingleBxdf(SingleBxdf::BxdfType::kMicrofacetGGX); - m_mat = mat; - break; - } - case RPR_MATERIAL_NODE_MICROFACET_REFRACTION: - { - SingleBxdf* mat = new SingleBxdf(SingleBxdf::BxdfType::kMicrofacetRefractionGGX); - m_mat = mat; - break; - } - case RPR_MATERIAL_NODE_REFLECTION: - { - SingleBxdf* mat = new SingleBxdf(SingleBxdf::BxdfType::kIdealReflect); - m_mat = mat; - break; - } - case RPR_MATERIAL_NODE_REFRACTION: - { - SingleBxdf* mat = new SingleBxdf(SingleBxdf::BxdfType::kIdealRefract); - m_mat = mat; - break; - } - case RPR_MATERIAL_NODE_STANDARD: - { - SingleBxdf* mat = new SingleBxdf(SingleBxdf::BxdfType::kLambert); - m_mat = mat; - break; - } - case RPR_MATERIAL_NODE_DIFFUSE_REFRACTION: - { - SingleBxdf* mat = new SingleBxdf(SingleBxdf::BxdfType::kTranslucent); - m_mat = mat; - break; - } - case RPR_MATERIAL_NODE_FRESNEL_SCHLICK: - case RPR_MATERIAL_NODE_FRESNEL: - { - SingleBxdf* mat = new SingleBxdf(SingleBxdf::BxdfType::kTranslucent); - m_mat = mat; - break; - } - case RPR_MATERIAL_NODE_EMISSIVE: - { - SingleBxdf* mat = new SingleBxdf(SingleBxdf::BxdfType::kEmissive); - m_mat = mat; - break; - } - case RPR_MATERIAL_NODE_BLEND: - { - MultiBxdf* mat = new MultiBxdf(MultiBxdf::Type::kMix); - mat->SetInputValue("weight", 0.5f); - m_mat = mat; - break; - } - case RPR_MATERIAL_NODE_TRANSPARENT: - case RPR_MATERIAL_NODE_PASSTHROUGH: - { - SingleBxdf* mat = new SingleBxdf(SingleBxdf::BxdfType::kPassthrough); - m_mat = mat; - break; - } - case RPR_MATERIAL_NODE_ADD: - case RPR_MATERIAL_NODE_ARITHMETIC: - case RPR_MATERIAL_NODE_BLEND_VALUE: - case RPR_MATERIAL_NODE_VOLUME: - case RPR_MATERIAL_NODE_INPUT_LOOKUP: - { - //these materials are unsupported - if (kUnsupportedMaterials.find(in_type) == kUnsupportedMaterials.end()) - { - throw Exception(RPR_ERROR_INTERNAL_ERROR, "MaterialObject: need to update list of unsupported materials."); - } - SingleBxdf* mat = new SingleBxdf(SingleBxdf::BxdfType::kLambert); - mat->SetInputValue("albedo", float3(1.f, 0.f, 0.f)); - m_mat = mat; - break; - } - case RPR_MATERIAL_NODE_NORMAL_MAP: - case RPR_MATERIAL_NODE_IMAGE_TEXTURE: - case RPR_MATERIAL_NODE_NOISE2D_TEXTURE: - case RPR_MATERIAL_NODE_DOT_TEXTURE: - case RPR_MATERIAL_NODE_GRADIENT_TEXTURE: - case RPR_MATERIAL_NODE_CHECKER_TEXTURE: - case RPR_MATERIAL_NODE_CONSTANT_TEXTURE: - case RPR_MATERIAL_NODE_BUMP_MAP: - m_tex = new Texture(); - m_is_tex = true; - break; - default: - throw Exception(RPR_ERROR_INVALID_PARAMETER_TYPE, "MaterialObject: unrecognized material type"); - } - - m_type = (Type)in_type; - -} - -MaterialObject::MaterialObject(rpr_image_format const in_format, rpr_image_desc const * in_image_desc, void const * in_data) - : m_is_tex(true) - , m_type(Type::kImage) - , m_tex(nullptr) -{ - //Clean if material was already initialized - Clear(); - - // //TODO: fix only 4 components data supported - //if (in_format.num_components != 4 && in_format.num_components != 3) - //{ - // throw Exception(RPR_ERROR_UNIMPLEMENTED, "TextureObject: only 3 and 4 component texture implemented."); - //} - - //tex size - int2 tex_size(in_image_desc->image_width, in_image_desc->image_height); - - //texture takes ownership of its data array - //so need to copy input data - int pixels_count = tex_size.x * tex_size.y; - - //bytes per pixel - int pixel_bytes = in_format.num_components; - int component_bytes = 1; - Texture::Format data_format = Texture::Format::kRgba8; - switch (in_format.type) - { - case RPR_COMPONENT_TYPE_UINT8: - break; - case RPR_COMPONENT_TYPE_FLOAT16: - component_bytes = 2; - data_format = Texture::Format::kRgba16; - break; - case RPR_COMPONENT_TYPE_FLOAT32: - component_bytes = 4; - data_format = Texture::Format::kRgba32; - break; - default: - throw Exception(RPR_ERROR_INVALID_PARAMETER, "TextureObject: invalid format type."); - } - pixel_bytes *= component_bytes; - int data_size = 4 * component_bytes * pixels_count;//4 component baikal texture - char* data = new char[data_size]; - if (in_format.num_components == 4) - { - //copy data - memcpy(data, in_data, data_size); - } - else - { - //copy to 4component texture - const char* in_data_cast = static_cast(in_data); - for (int i = 0; i < pixels_count; ++i) - { - //copy - for (unsigned int comp_ind = 0; comp_ind < in_format.num_components; ++comp_ind) - { - int index = comp_ind * component_bytes; - memcpy(&data[i * 4 * component_bytes + index], &in_data_cast[i * in_format.num_components * component_bytes + index], component_bytes); - } - //clean other colors - for (unsigned int comp_ind = in_format.num_components; comp_ind < 4; ++comp_ind) - { - memset(&data[i * 4 + comp_ind], 0, component_bytes); - } - } - } - m_tex = new Texture(data, tex_size, data_format); -} - -MaterialObject::MaterialObject(const std::string& in_path) - : m_is_tex(true) - , m_type(Type::kImage) - , m_tex(nullptr) -{ - //Clean if material was already initialized - Clear(); - - //load texture using oiio - ImageIo* oiio = ImageIo::CreateImageIo(); - Texture* texture = nullptr; - try - { - texture = oiio->LoadImage(in_path); - } - catch (...) { - throw Exception(RPR_ERROR_IO_ERROR, "TextureObject: failed to load image."); - } - - m_tex = texture; - delete oiio; -} - -MaterialObject::~MaterialObject() -{ - Clear(); -} - -void MaterialObject::Clear() -{ - if (IsMaterial()) - { - delete m_mat; - m_mat = nullptr; - } - else - { - delete m_tex; - m_tex = nullptr; - } -} - -std::string MaterialObject::TranslatePropName(const std::string& in, Type type) -{ - std::string result; - if (type == Type::kBumpMap) - { - return "bump"; - } - else if (type == Type::kNormalMap) - { - return "normal"; - } - - auto it = kInputNamesDictionary.find(in); - if (it != kInputNamesDictionary.end()) - { - result = it->second; - } - else - { - throw Exception(RPR_ERROR_UNIMPLEMENTED, "MaterialObject: unimplemented input."); - - } - - return result; -} - - -void MaterialObject::SetInputMaterial(const std::string& input_name, MaterialObject* input) -{ - //TODO: fix - if (kUnsupportedMaterials.find(m_type) != kUnsupportedMaterials.end() || - kUnsupportedMaterials.find(input->GetType()) != kUnsupportedMaterials.end()) - { - //this is unsupported material, so don't update anything - return; - } - - //translated input name - std::string name; - - //TODO:fix - //check is input name is registered - auto it_input = std::find_if(kMaterialNodeInputStrings.begin(), kMaterialNodeInputStrings.end(), - [&input_name](const std::pair& input) { return input.second == input_name; }); - if (it_input == kMaterialNodeInputStrings.end()) - { - throw Exception(RPR_ERROR_INVALID_TAG, "MaterialObject: unregistered input name."); - } - try - { - name = TranslatePropName(input_name); - } - catch (Exception& e) - { - //failed to translate valid input name annd ignore it - //TODO: - return; - } - //TODO: fix - //can't set material to color input - if (input_name == "color" && input->IsMaterial()) - { - return; - } - - - //convert input name - if (input->m_type == Type::kImage) - { - if (IsTexture()) - { - if (name != "data") - { - throw Exception(RPR_ERROR_INVALID_TAG, "MaterialObject: inalid input tag"); - } - //copy image data - Baikal::Texture* tex = input->GetTexture(); - const char* data = tex->GetData(); - RadeonRays::int2 size = tex->GetSize(); - auto format = tex->GetFormat(); - char* tex_data = new char[tex->GetSizeInBytes()]; - memcpy(tex_data, data, tex->GetSizeInBytes()); - - m_tex->SetData(tex_data, size, format); - } - } - else - { - if (input->IsTexture()) - { - m_mat->SetInputValue(name, input->GetTexture()); - //handle blend material case - if (m_type == kBlend && name == "weight") - { - MultiBxdf* blend_mat = dynamic_cast(m_mat); - blend_mat->SetType(MultiBxdf::Type::kMix); - } - - - } - else - { - //handle blend material case - if (m_type == kBlend && name == "weight") - { - //expected only fresnel materials - if (input->m_type != Type::kFresnel && input->m_type != Type::kFresnelShlick) - { - throw Exception(RPR_ERROR_INVALID_PARAMETER, "MaterialObject: expected only fresnel materials as weight of blend material."); - } - MultiBxdf* blend_mat = dynamic_cast(m_mat); - blend_mat->SetType(MultiBxdf::Type::kFresnelBlend); - blend_mat->SetInputValue("ior", input->m_mat->GetInputValue("ior").float_value); - } - else - { - m_mat->SetInputValue(name, input->GetMaterial()); - } - } - } - input->AddOutput(this); - SetInput(input, input_name); - Notify(); -} - -void MaterialObject::SetInputValue(const std::string& input_name, const RadeonRays::float4& val) -{ - //TODO: - if (kUnsupportedMaterials.find(m_type) != kUnsupportedMaterials.end()) - { - //this is unsupported material, so don't update anything - return; - } - - std::string name; - - //TODO:fix - //check is input name is registered - auto it_input = std::find_if(kMaterialNodeInputStrings.begin(), kMaterialNodeInputStrings.end(), - [&input_name](const std::pair& input) { return input.second == input_name; }); - if (it_input == kMaterialNodeInputStrings.end()) - { - throw Exception(RPR_ERROR_INVALID_TAG, "MaterialObject: unregistered input name."); - } - try - { - name = TranslatePropName(input_name); - } - catch (Exception& e) - { - //failed to translate valid input name and ignore it - //TODO: - return; - } - - //convert input name - if (m_type == Type::kImage) - { - throw Exception(RPR_ERROR_INVALID_PARAMETER, "MaterialObject: trying SetInputValue for rpr_image object."); - } - - if (IsTexture()) - { - //TODO: handle texture materials nodes - return; - //throw Exception(RPR_ERROR_UNIMPLEMENTED, "MaterialObject: SetInputValue not implemented for Texture materials."); - } - - //translate material name - m_mat->SetInputValue(name, val); - - //if rougness is to small replace microfacet by ideal reflect - if (m_type == Type::kMicrofacet && name == "roughness") - { - if (val.sqnorm() < 1e-6f) - { - SingleBxdf* bxdf_mat = dynamic_cast(m_mat); - bxdf_mat->SetBxdfType(Baikal::SingleBxdf::BxdfType::kIdealReflect); - } - else - { - SingleBxdf* bxdf_mat = dynamic_cast(m_mat); - bxdf_mat->SetBxdfType(Baikal::SingleBxdf::BxdfType::kMicrofacetGGX); - } - } - //handle blend material case - if (m_type == kBlend && name == "weight") - { - MultiBxdf* blend_mat = dynamic_cast(m_mat); - blend_mat->SetType(MultiBxdf::Type::kMix); - } - SetInput(nullptr, input_name); - Notify(); -} - -void MaterialObject::SetInput(MaterialObject* input_mat, const std::string& input_name) -{ - m_inputs[input_name] = input_mat; -} - - -void MaterialObject::AddOutput(MaterialObject* mat) -{ - m_out_mats.insert(mat); -} - -void MaterialObject::RemoveOutput(MaterialObject* mat) -{ - m_out_mats.erase(mat); -} - -void MaterialObject::Notify() -{ - for (auto mat : m_out_mats) - { - mat->Update(this); - } -} - -void MaterialObject::Update(MaterialObject* mat) -{ - auto input_it = std::find_if(m_inputs.begin(), m_inputs.end(), [mat](const std::pair& i) { return i.second == mat; }); - if (input_it == m_inputs.end()) - { - throw Exception(RPR_ERROR_INTERNAL_ERROR, "MaterialObject: failed to find requested input node."); - } - const std::string& input_name = TranslatePropName(input_it->first, mat->GetType()); - if (m_type == kBlend && input_name == "weight") - { - //expected only fresnel materials - if (mat->m_type == Type::kFresnel || mat->m_type == Type::kFresnelShlick) - { - MultiBxdf* blend_mat = dynamic_cast(m_mat); - blend_mat->SetType(MultiBxdf::Type::kFresnelBlend); - blend_mat->SetInputValue("ior", mat->m_mat->GetInputValue("ior").float_value); - } - } -} - -uint64_t MaterialObject::GetInputCount() -{ - return m_inputs.size(); -} - -rpr_uint MaterialObject::GetInputType(int i) -{ - rpr_uint result = RPR_MATERIAL_NODE_INPUT_TYPE_NODE; - //get i input - auto it = m_inputs.begin(); - for (int index = 0; it != m_inputs.end(); ++it, ++index) - if (index == i) - { - break; - } - - //means no MaterialObject connected - if (!it->second) - { - result = RPR_MATERIAL_NODE_INPUT_TYPE_FLOAT4; - } - //connected input represent rpr_image - else if(it->second->IsImg()) - { - result = RPR_MATERIAL_NODE_INPUT_TYPE_IMAGE; - } - - return result; -} - -std::string MaterialObject::GetInputName(int i) -{ - //get i input - auto it = m_inputs.begin(); - for (int index = 0; it != m_inputs.end(); ++it, ++index) - if (index == i) - { - break; - } - - return it->first; -} - - -void MaterialObject::GetInput(int i, void* out, size_t* out_size) -{ - //get i input - auto it = m_inputs.begin(); - for (int index = 0; it != m_inputs.end(); ++it, ++index) - if (index == i) - { - break; - } - - //translated name - std::string trans_name = TranslatePropName(it->first); - //means no MaterialObject connected - if (!it->second) - { - *out_size = sizeof(RadeonRays::float4); - Baikal::Material::InputValue value = m_mat->GetInputValue(trans_name); - if (value.type != Baikal::Material::InputType::kFloat4) - { - throw Exception(RPR_ERROR_INTERNAL_ERROR, "MaterialObject: material input type is unexpected."); - } - - memcpy(out, &value.float_value, *out_size); - } - //images, textures and materials - else - { - *out_size = sizeof(rpr_material_node); - memcpy(out, &it->second, *out_size); - } -} - - -rpr_image_desc MaterialObject::GetTextureDesc() const -{ - RadeonRays::int2 size = m_tex->GetSize(); - rpr_uint depth = (rpr_uint)m_tex->GetSizeInBytes() / size.x / size.y; - return {(rpr_uint)size.x, (rpr_uint)size.y, depth, 0, 0}; -} -char const* MaterialObject::GetTextureData() const -{ - return m_tex->GetData(); -} -rpr_image_format MaterialObject::GetTextureFormat() const -{ - rpr_component_type type; - switch (m_tex->GetFormat()) - { - case Baikal::Texture::Format::kRgba8: - type = RPR_COMPONENT_TYPE_UINT8; - break; - case Baikal::Texture::Format::kRgba16: - type = RPR_COMPONENT_TYPE_FLOAT16; - break; - case Baikal::Texture::Format::kRgba32: - type = RPR_COMPONENT_TYPE_FLOAT32; - break; - default: - throw Exception(RPR_ERROR_INTERNAL_ERROR, "MaterialObject: invalid image format."); - } - //only 4component textures used - return{ 4, type }; -} \ No newline at end of file diff --git a/Rpr/WrapObject/Materials/ArithmeticMaterialObject.cpp b/Rpr/WrapObject/Materials/ArithmeticMaterialObject.cpp new file mode 100644 index 00000000..f130092a --- /dev/null +++ b/Rpr/WrapObject/Materials/ArithmeticMaterialObject.cpp @@ -0,0 +1,396 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "ArithmeticMaterialObject.h" +#include "TextureMaterialObject.h" +#include "WrapObject/Exception.h" +#include "SceneGraph/material.h" +#include "SceneGraph/inputmaps.h" + +using namespace Baikal; +using namespace RadeonRays; + +ArithmeticMaterialObject::ArithmeticMaterialObject(MaterialObject::Type mat_type) + : MaterialObject(mat_type) +{ +} + +Baikal::InputMap::Ptr ArithmeticMaterialObject::GetInputMap() +{ + if (!m_input_map) + { + throw Exception(RPR_ERROR_INTERNAL_ERROR, "InputMap from empty arithmetic node was requested. Set operation first."); + } + return m_input_map; +} + +void ArithmeticMaterialObject::SetInputMaterial(const std::string& input_name, MaterialObject* input) +{ + if (!input->IsArithmetic()) + { + throw Exception(RPR_ERROR_INTERNAL_ERROR, "Only Arithmetic node can be used as input"); + } + if (!m_input_map) + { + throw Exception(RPR_ERROR_INTERNAL_ERROR, "\"op\" input must be set first"); + } + ArithmeticMaterialObject *arithmetic = static_cast(input); + SetInputMap(input_name, arithmetic->GetInputMap()); +} + +void ArithmeticMaterialObject::SetInputTexture(const std::string& input_name, TextureMaterialObject* input) +{ + auto input_map = Baikal::InputMap_Sampler::Create(input->GetTexture()); + SetInputMap(input_name, input_map); +} + + +void ArithmeticMaterialObject::SetInputF(const std::string& input_name, const RadeonRays::float4& val) +{ + auto input_map = Baikal::InputMap_ConstantFloat3::Create(val); + SetInputMap(input_name, input_map); +} + +void ArithmeticMaterialObject::Update(MaterialObject* mat) +{ + +} + +Baikal::Material::Ptr ArithmeticMaterialObject::GetMaterial() +{ + return nullptr; +} + +void ArithmeticMaterialObject::SetInputU(const std::string& input_name, rpr_uint val) +{ + if (input_name == "op") + { + if (m_input_map) + { + throw Exception(RPR_ERROR_INTERNAL_ERROR, "Arithmetic field \"op\" can not be set twice"); + } + + switch (val) + { + case RPR_MATERIAL_NODE_OP_ADD: + m_input_map = Baikal::InputMap_Add::Create( + Baikal::InputMap_ConstantFloat::Create(0.f), + Baikal::InputMap_ConstantFloat::Create(0.f)); + break; + case RPR_MATERIAL_NODE_OP_SUB: + m_input_map = Baikal::InputMap_Sub::Create( + Baikal::InputMap_ConstantFloat::Create(0.f), + Baikal::InputMap_ConstantFloat::Create(0.f)); + break; + case RPR_MATERIAL_NODE_OP_MUL: + m_input_map = Baikal::InputMap_Mul::Create( + Baikal::InputMap_ConstantFloat::Create(0.f), + Baikal::InputMap_ConstantFloat::Create(0.f)); + break; + case RPR_MATERIAL_NODE_OP_DIV: + m_input_map = Baikal::InputMap_Div::Create( + Baikal::InputMap_ConstantFloat::Create(0.f), + Baikal::InputMap_ConstantFloat::Create(0.f)); + break; + case RPR_MATERIAL_NODE_OP_SIN: + m_input_map = Baikal::InputMap_Sin::Create( + Baikal::InputMap_ConstantFloat::Create(0.f)); + break; + case RPR_MATERIAL_NODE_OP_COS: + m_input_map = Baikal::InputMap_Cos::Create( + Baikal::InputMap_ConstantFloat::Create(0.f)); + break; + case RPR_MATERIAL_NODE_OP_TAN: + m_input_map = Baikal::InputMap_Tan::Create( + Baikal::InputMap_ConstantFloat::Create(0.f)); + break; + case RPR_MATERIAL_NODE_OP_SELECT_X: + m_input_map = Baikal::InputMap_Select::Create( + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()), + Baikal::InputMap_Select::Selection::kX); + break; + case RPR_MATERIAL_NODE_OP_SELECT_Y: + m_input_map = Baikal::InputMap_Select::Create( + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()), + Baikal::InputMap_Select::Selection::kY); + break; + case RPR_MATERIAL_NODE_OP_SELECT_Z: + m_input_map = Baikal::InputMap_Select::Create( + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()), + Baikal::InputMap_Select::Selection::kZ); + break; + case RPR_MATERIAL_NODE_OP_SELECT_W: + m_input_map = Baikal::InputMap_Select::Create( + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()), + Baikal::InputMap_Select::Selection::kW); + break; + case RPR_MATERIAL_NODE_OP_COMBINE: + m_input_map = Baikal::InputMap_Shuffle2::Create( + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()), + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()), + {{ 0, 4, 1, 5 }}); // {c0.x, c1.x, c0.y, c1.y} + break; + case RPR_MATERIAL_NODE_OP_DOT3: + m_input_map = Baikal::InputMap_Dot3::Create( + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()), + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()) + ); + break; + case RPR_MATERIAL_NODE_OP_CROSS3: + m_input_map = Baikal::InputMap_Cross3::Create( + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()), + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()) + ); + break; + case RPR_MATERIAL_NODE_OP_LENGTH3: + m_input_map = Baikal::InputMap_Length3::Create( + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3())); + break; + case RPR_MATERIAL_NODE_OP_NORMALIZE3: + m_input_map = Baikal::InputMap_Normalize3::Create( + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3())); + break; + case RPR_MATERIAL_NODE_OP_POW: + m_input_map = Baikal::InputMap_Pow::Create( + Baikal::InputMap_ConstantFloat::Create(0.f), + Baikal::InputMap_ConstantFloat::Create(0.f)); + break; + case RPR_MATERIAL_NODE_OP_ACOS: + m_input_map = Baikal::InputMap_Acos::Create( + Baikal::InputMap_ConstantFloat::Create(0.f)); + break; + case RPR_MATERIAL_NODE_OP_ASIN: + m_input_map = Baikal::InputMap_Asin::Create( + Baikal::InputMap_ConstantFloat::Create(0.f)); + break; + case RPR_MATERIAL_NODE_OP_ATAN: + m_input_map = Baikal::InputMap_Atan::Create( + Baikal::InputMap_ConstantFloat::Create(0.f)); + break; + case RPR_MATERIAL_NODE_OP_AVERAGE_XYZ: + case RPR_MATERIAL_NODE_OP_AVERAGE: + m_input_map = Baikal::InputMap_Lerp::Create( + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()), + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()), + Baikal::InputMap_ConstantFloat::Create(0.5f)); + case RPR_MATERIAL_NODE_OP_MIN: + m_input_map = Baikal::InputMap_Min::Create( + Baikal::InputMap_ConstantFloat::Create(0.f), + Baikal::InputMap_ConstantFloat::Create(0.f)); + break; + case RPR_MATERIAL_NODE_OP_MAX: + m_input_map = Baikal::InputMap_Max::Create( + Baikal::InputMap_ConstantFloat::Create(0.f), + Baikal::InputMap_ConstantFloat::Create(0.f)); + break; + case RPR_MATERIAL_NODE_OP_FLOOR: + m_input_map = Baikal::InputMap_Floor::Create( + Baikal::InputMap_ConstantFloat::Create(0.f)); + break; + case RPR_MATERIAL_NODE_OP_MOD: + m_input_map = Baikal::InputMap_Mod::Create( + Baikal::InputMap_ConstantFloat::Create(0.f), + Baikal::InputMap_ConstantFloat::Create(1.f) + ); + break; + case RPR_MATERIAL_NODE_OP_ABS: + m_input_map = Baikal::InputMap_Abs::Create( + Baikal::InputMap_ConstantFloat::Create(0.f)); + break; + case RPR_MATERIAL_NODE_OP_SHUFFLE_YZWX: + m_input_map = Baikal::InputMap_Shuffle::Create( + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()), + {{1, 2, 3, 0}}); + break; + case RPR_MATERIAL_NODE_OP_SHUFFLE_ZWXY: + m_input_map = Baikal::InputMap_Shuffle::Create( + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()), + {{2, 3, 0, 1}}); + break; + case RPR_MATERIAL_NODE_OP_SHUFFLE_WXYZ: + m_input_map = Baikal::InputMap_Shuffle::Create( + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()), + {{3, 0, 1, 2}}); + break; + case RPR_MATERIAL_NODE_OP_MAT_MUL: + m_input_map = Baikal::InputMap_MatMul::Create( + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()), + RadeonRays::matrix()); + break; + case RPR_MATERIAL_NODE_OP_DOT4: + m_input_map = Baikal::InputMap_Dot4::Create( + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()), + Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3()) + ); + break; + default: + throw Exception(RPR_ERROR_INTERNAL_ERROR, "Unsupported operation"); + } + } +} + +void ArithmeticMaterialObject::SetInputMap(const std::string& input_name, Baikal::InputMap::Ptr input_map) +{ + // get number from string "colorN" + int position = input_name[5] - '0'; + if (position < 0 || position > 3) + { + throw Exception(RPR_ERROR_INTERNAL_ERROR, "Invalid input"); + } + + switch (m_input_map->m_type) + { + // Two inputs + case InputMap::InputMapType::kAdd: + case InputMap::InputMapType::kSub: + case InputMap::InputMapType::kMul: + case InputMap::InputMapType::kDiv: + case InputMap::InputMapType::kMin: + case InputMap::InputMapType::kMax: + case InputMap::InputMapType::kDot3: + case InputMap::InputMapType::kDot4: + case InputMap::InputMapType::kCross3: + case InputMap::InputMapType::kCross4: + case InputMap::InputMapType::kPow: + case InputMap::InputMapType::kMod: + { + //It's safe since all this types differs only in id value + InputMap_Add *i = static_cast(m_input_map.get()); + if (position == 0) + { + i->SetA(input_map); + } + else if (position == 1) + { + i->SetB(input_map); + } + else + { + throw Exception(RPR_ERROR_INTERNAL_ERROR, "Invalid input"); + } + break; + } + //Single input + case InputMap::InputMapType::kSin: + case InputMap::InputMapType::kCos: + case InputMap::InputMapType::kTan: + case InputMap::InputMapType::kAsin: + case InputMap::InputMapType::kAcos: + case InputMap::InputMapType::kAtan: + case InputMap::InputMapType::kLength3: + case InputMap::InputMapType::kNormalize3: + case InputMap::InputMapType::kFloor: + case InputMap::InputMapType::kAbs: + { + //It's safe since all this types differs only in id value + InputMap_Sin *i = static_cast(m_input_map.get()); + if (position == 0) + { + i->SetArg(input_map); + } + else + { + throw Exception(RPR_ERROR_INTERNAL_ERROR, "Invalid input"); + } + break; + } + + // Specials + case InputMap::InputMapType::kLerp: + { + InputMap_Lerp *i = static_cast(m_input_map.get()); + if (position == 0) + { + i->SetA(input_map); + } + else if (position == 1) + { + i->SetB(input_map); + } + else + { + throw Exception(RPR_ERROR_INTERNAL_ERROR, "Invalid input"); + } + + break; + } + case InputMap::InputMapType::kSelect: + { + InputMap_Select *i = static_cast(m_input_map.get()); + if (position == 0) + { + i->SetArg(input_map); + } + else + { + throw Exception(RPR_ERROR_INTERNAL_ERROR, "Invalid input"); + } + + break; + } + case InputMap::InputMapType::kShuffle: + { + InputMap_Shuffle *i = static_cast(m_input_map.get()); + if (position == 0) + { + i->SetArg(input_map); + } + else + { + throw Exception(RPR_ERROR_INTERNAL_ERROR, "Invalid input"); + } + + break; + } + case InputMap::InputMapType::kShuffle2: + { + InputMap_Shuffle2 *i = static_cast(m_input_map.get()); + + if (position == 0) + { + i->SetA(input_map); + } + else if (position == 1) + { + i->SetB(input_map); + } + else + { + throw Exception(RPR_ERROR_INTERNAL_ERROR, "Invalid input"); + } + + break; + } + case InputMap::InputMapType::kMatMul: + { + InputMap_MatMul *i = static_cast(m_input_map.get()); + + if (position == 3) // value is color3 + { + i->SetArg(input_map); + } + + break; + } + default: + throw Exception(RPR_ERROR_INTERNAL_ERROR, "Unsupported input map type"); + } +} diff --git a/Rpr/WrapObject/Materials/ArithmeticMaterialObject.h b/Rpr/WrapObject/Materials/ArithmeticMaterialObject.h new file mode 100644 index 00000000..3e5077d7 --- /dev/null +++ b/Rpr/WrapObject/Materials/ArithmeticMaterialObject.h @@ -0,0 +1,47 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once + +#include "MaterialObject.h" +#include "SceneGraph/inputmap.h" + +//represent RPR arithmetic with "op" RPR_MATERIAL_NODE_OP_MUL +class ArithmeticMaterialObject + : public MaterialObject +{ +public: + ArithmeticMaterialObject(MaterialObject::Type mat_type); + + void SetInputF(const std::string& input_name, const RadeonRays::float4& val) override; + Baikal::Material::Ptr GetMaterial() override; + Baikal::InputMap::Ptr GetInputMap(); + +protected: + void Update(MaterialObject* mat) override; + void SetInputMaterial(const std::string& input_name, MaterialObject* input) override; + void SetInputTexture(const std::string& input_name, TextureMaterialObject* input) override; + void SetInputU(const std::string& input_name, rpr_uint val) override; + void SetInputMap(const std::string& input_name, Baikal::InputMap::Ptr input_map); + +private: + Baikal::InputMap::Ptr m_input_map; +}; diff --git a/Rpr/WrapObject/Materials/ImageMaterialObject.cpp b/Rpr/WrapObject/Materials/ImageMaterialObject.cpp new file mode 100644 index 00000000..92f33bc6 --- /dev/null +++ b/Rpr/WrapObject/Materials/ImageMaterialObject.cpp @@ -0,0 +1,118 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "math/int2.h" +#include "SceneGraph/texture.h" +#include "SceneGraph/material.h" +#include "image_io.h" +#include "SceneGraph/iterator.h" +#include "ImageMaterialObject.h" +#include "WrapObject/Exception.h" + + +using namespace RadeonRays; +using namespace Baikal; + +ImageMaterialObject::ImageMaterialObject(rpr_image_format const in_format, rpr_image_desc const * in_image_desc, void const * in_data) + : MaterialObject(Type::kImage) +{ + //tex size + int2 tex_size(in_image_desc->image_width, in_image_desc->image_height); + + //texture takes ownership of its data array + //so need to copy input data + int pixels_count = tex_size.x * tex_size.y; + + //bytes per pixel + int pixel_bytes = in_format.num_components; + int component_bytes = 1; + Texture::Format data_format = Texture::Format::kRgba8; + switch (in_format.type) + { + case RPR_COMPONENT_TYPE_UINT8: + break; + case RPR_COMPONENT_TYPE_FLOAT16: + component_bytes = 2; + data_format = Texture::Format::kRgba16; + break; + case RPR_COMPONENT_TYPE_FLOAT32: + component_bytes = 4; + data_format = Texture::Format::kRgba32; + break; + default: + throw Exception(RPR_ERROR_INVALID_PARAMETER, "TextureObject: invalid format type."); + } + pixel_bytes *= component_bytes; + int data_size = 4 * component_bytes * pixels_count;//4 component baikal texture + char* data = new char[data_size]; + if (in_format.num_components == 4) + { + //copy data + memcpy(data, in_data, data_size); + } + else + { + //copy to 4component texture + const char* in_data_cast = static_cast(in_data); + for (int i = 0; i < pixels_count; ++i) + { + //copy + for (unsigned int comp_ind = 0; comp_ind < in_format.num_components; ++comp_ind) + { + int index = comp_ind * component_bytes; + memcpy(&data[i * 4 * component_bytes + index], &in_data_cast[i * in_format.num_components * component_bytes + index], component_bytes); + } + //clean other colors + for (unsigned int comp_ind = in_format.num_components; comp_ind < 4; ++comp_ind) + { + int index = comp_ind * component_bytes; + memset(&data[i * 4 * component_bytes + index], 0, component_bytes); + } + } + } + m_tex = Texture::Create(data, tex_size, data_format); +} + +ImageMaterialObject::ImageMaterialObject(const std::string& in_path) + : MaterialObject(Type::kImage) +{ + //load texture using oiio + std::unique_ptr oiio = ImageIo::CreateImageIo(); + Texture::Ptr texture = nullptr; + try + { + texture = oiio->LoadImage(in_path); + } + catch (...) { + throw Exception(RPR_ERROR_IO_ERROR, "TextureObject: failed to load image."); + } + + m_tex = texture; +} + +Baikal::Texture::Ptr ImageMaterialObject::GetTexture() +{ + return m_tex; +} diff --git a/Rpr/WrapObject/Materials/ImageMaterialObject.h b/Rpr/WrapObject/Materials/ImageMaterialObject.h new file mode 100644 index 00000000..75470e36 --- /dev/null +++ b/Rpr/WrapObject/Materials/ImageMaterialObject.h @@ -0,0 +1,37 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once + +#include "MaterialObject.h" + +//represent rpr_image +class ImageMaterialObject + : public MaterialObject +{ +public: + ImageMaterialObject(rpr_image_format const in_format, rpr_image_desc const * in_image_desc, void const * in_data); + ImageMaterialObject(const std::string& in_path); + + virtual Baikal::Texture::Ptr GetTexture() override; +private: + Baikal::Texture::Ptr m_tex; +}; diff --git a/Rpr/WrapObject/Materials/MaterialObject.cpp b/Rpr/WrapObject/Materials/MaterialObject.cpp new file mode 100644 index 00000000..d1c60de4 --- /dev/null +++ b/Rpr/WrapObject/Materials/MaterialObject.cpp @@ -0,0 +1,456 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "math/int2.h" +#include "SceneGraph/texture.h" +#include "SceneGraph/material.h" +#include "image_io.h" +#include "SceneGraph/iterator.h" +#include "WrapObject/Materials/MaterialObject.h" +#include "WrapObject/Exception.h" + +#include "ImageMaterialObject.h" +#include "TextureMaterialObject.h" +#include "UnsupportedMaterialObject.h" +#include "ArithmeticMaterialObject.h" +#include "UberMaterialObject.h" + +using namespace RadeonRays; +using namespace Baikal; + +namespace +{ + //contains pairs of input names + const std::map kInputNamesDictionary = { + { "color" , "albedo" }, + { "normal" , "normal" }, + { "roughness" , "roughness" }, + { "roughness_x" , "roughness" }, + { "weight" , "weight" }, + { "ior" , "ior" }, + { "color0", "color0" }, + { "color1", "color1" }, + { "color2", "color2" }, + { "color3", "color3" }, + { "data", "data" }, + { "sigmas", "sigmas" }, + { "sigmaa", "sigmaa" }, + { "rotation", "rotation" }, + { "anisotropic", "anisotropic" }, + { "g", "g" }, + { "op", "op"}, + { "multiscatter", "multiscatter" }, + { "uberv2.diffuse.color", "uberv2.diffuse.color" }, + { "uberv2.layers", "uberv2.layers" }, + { "uberv2.reflection.color", "uberv2.reflection.color" }, + { "uberv2.reflection.roughness", "uberv2.reflection.roughness" }, + { "uberv2.reflection.anisotropy", "uberv2.reflection.anisotropy" }, + { "uberv2.reflection.anisotropy_rotation", "uberv2.reflection.anisotropy_rotation" }, + { "uberv2.reflection.ior", "uberv2.reflection.ior" }, + { "uberv2.reflection.metalness", "uberv2.reflection.metalness" }, + { "uberv2.refraction.color", "uberv2.refraction.color" }, + { "uberv2.refraction.roughness", "uberv2.refraction.roughness" }, + { "uberv2.refraction.ior", "uberv2.refraction.ior" }, + { "uberv2.refraction.thin", "uberv2.refraction.thin" }, + { "uberv2.coating.color", "uberv2.coating.color" }, + { "uberv2.coating.ior", "uberv2.coating.ior" }, + { "uberv2.coating.metalness", "uberv2.coating.metalness" }, + { "uberv2.emission.color", "uberv2.emission.color" }, + { "uberv2.emission.mode", "uberv2.emission.mode" }, + { "uberv2.transparency", "uberv2.transparency" }, + { "uberv2.normal", "uberv2.normal" }, + { "uberv2.bump", "uberv2.bump" }, + { "uberv2.displacement", "uberv2.displacement" }, + { "uberv2.sss.absorption_color", "uberv2.sss.absorption_color" }, + { "uberv2.sss.scatter_color", "uberv2.sss.scatter_color" }, + { "uberv2.sss.absorption_distance", "uberv2.sss.absorption_distance" }, + { "uberv2.sss.scatter_distance", "uberv2.sss.scatter_distance" }, + { "uberv2.sss.scatter_direction", "uberv2.sss.scatter_direction" }, + { "uberv2.sss.subsurface_color", "uberv2.sss.subsurface_color" }, + { "uberv2.sss.multiscatter", "uberv2.sss.multiscatter" }}; + + std::map kMaterialNodeInputStrings = { + { RPR_MATERIAL_INPUT_COLOR, "color" }, + { RPR_MATERIAL_INPUT_COLOR0, "color0" }, + { RPR_MATERIAL_INPUT_COLOR1, "color1" }, + { RPR_MATERIAL_INPUT_NORMAL, "normal" }, + { RPR_MATERIAL_INPUT_UV, "uv" }, + { RPR_MATERIAL_INPUT_DATA, "data" }, + { RPR_MATERIAL_INPUT_ROUGHNESS, "roughness" }, + { RPR_MATERIAL_INPUT_IOR, "ior" }, + { RPR_MATERIAL_INPUT_ROUGHNESS_X, "roughness_x" }, + { RPR_MATERIAL_INPUT_ROUGHNESS_Y, "roughness_y" }, + { RPR_MATERIAL_INPUT_ROTATION, "rotation" }, + { RPR_MATERIAL_INPUT_WEIGHT, "weight" }, + { RPR_MATERIAL_INPUT_OP, "op" }, + { RPR_MATERIAL_INPUT_INVEC, "invec" }, + { RPR_MATERIAL_INPUT_UV_SCALE, "uv_scale" }, + { RPR_MATERIAL_INPUT_VALUE, "value" }, + { RPR_MATERIAL_INPUT_REFLECTANCE, "reflectance" }, + { RPR_MATERIAL_INPUT_SCALE, "bumpscale" }, + { RPR_MATERIAL_INPUT_SCATTERING, "sigmas" }, + { RPR_MATERIAL_INPUT_ABSORBTION, "sigmaa" }, + { RPR_MATERIAL_INPUT_EMISSION, "emission" }, + { RPR_MATERIAL_INPUT_G, "g" }, + { RPR_MATERIAL_INPUT_MULTISCATTER, "multiscatter" }, + + { RPR_MATERIAL_STANDARD_INPUT_DIFFUSE_COLOR, "diffuse.color" }, + { RPR_MATERIAL_STANDARD_INPUT_DIFFUSE_NORMAL, "diffuse.normal" }, + { RPR_MATERIAL_STANDARD_INPUT_GLOSSY_COLOR, "glossy.color" }, + { RPR_MATERIAL_STANDARD_INPUT_GLOSSY_NORMAL, "glossy.normal" }, + { RPR_MATERIAL_STANDARD_INPUT_GLOSSY_ROUGHNESS_X, "glossy.roughness_x" }, + { RPR_MATERIAL_STANDARD_INPUT_GLOSSY_ROUGHNESS_Y, "glossy.roughness_y" }, + { RPR_MATERIAL_STANDARD_INPUT_CLEARCOAT_COLOR, "clearcoat.color" }, + { RPR_MATERIAL_STANDARD_INPUT_CLEARCOAT_NORMAL, "clearcoat.normal" }, + { RPR_MATERIAL_STANDARD_INPUT_REFRACTION_COLOR, "refraction.color" }, + { RPR_MATERIAL_STANDARD_INPUT_REFRACTION_NORMAL, "refraction.normal" }, + { RPR_MATERIAL_STANDARD_INPUT_REFRACTION_ROUGHNESS, "refraction.roughness" }, // REFRACTION doesn't have roughness parameter. + { RPR_MATERIAL_STANDARD_INPUT_REFRACTION_IOR, "refraction.ior" }, + { RPR_MATERIAL_STANDARD_INPUT_TRANSPARENCY_COLOR, "transparency.color" }, + { RPR_MATERIAL_STANDARD_INPUT_DIFFUSE_TO_REFRACTION_WEIGHT, "weights.diffuse2refraction" }, + { RPR_MATERIAL_STANDARD_INPUT_GLOSSY_TO_DIFFUSE_WEIGHT, "weights.glossy2diffuse" }, + { RPR_MATERIAL_STANDARD_INPUT_CLEARCOAT_TO_GLOSSY_WEIGHT, "weights.clearcoat2glossy" }, + { RPR_MATERIAL_STANDARD_INPUT_TRANSPARENCY, "weights.transparency" }, + + }; + + //these material inputs are ignored + const std::set kUnsupportedInputs = { "anisotropic" }; + + //these materials are unsupported now: + const std::set kUnsupportedMaterials = { RPR_MATERIAL_NODE_ADD, + RPR_MATERIAL_NODE_ARITHMETIC, + RPR_MATERIAL_NODE_BLEND_VALUE, + RPR_MATERIAL_NODE_VOLUME, + RPR_MATERIAL_NODE_INPUT_LOOKUP, + RPR_MATERIAL_NODE_MICROFACET_ANISOTROPIC_REFLECTION, + RPR_MATERIAL_NODE_MICROFACET_ANISOTROPIC_REFRACTION, + RPR_MATERIAL_NODE_TWOSIDED, + RPR_MATERIAL_NODE_UV_PROCEDURAL,}; +} + + +MaterialObject* MaterialObject::CreateImage(rpr_image_format const in_format, rpr_image_desc const * in_image_desc, void const * in_data) +{ + return new ImageMaterialObject(in_format, in_image_desc, in_data); +} + +MaterialObject* MaterialObject::CreateImage(const std::string& in_path) +{ + return new ImageMaterialObject(in_path); +} + +MaterialObject* MaterialObject::CreateMaterial(rpr_material_node_type in_type) +{ + Type type = (Type)in_type; + switch (in_type) + { + // SingleBxdf + case RPR_MATERIAL_NODE_ADD: + case RPR_MATERIAL_NODE_BLEND_VALUE: + case RPR_MATERIAL_NODE_VOLUME: + case RPR_MATERIAL_NODE_INPUT_LOOKUP: + case RPR_MATERIAL_NODE_UV_PROCEDURAL: + + { + return new UnsupportedMaterialObject(type); + } + + + case RPR_MATERIAL_NODE_ARITHMETIC: + { + return new ArithmeticMaterialObject(type); + } + + //Textures + case RPR_MATERIAL_NODE_NORMAL_MAP: + case RPR_MATERIAL_NODE_IMAGE_TEXTURE: + case RPR_MATERIAL_NODE_NOISE2D_TEXTURE: + case RPR_MATERIAL_NODE_DOT_TEXTURE: + case RPR_MATERIAL_NODE_GRADIENT_TEXTURE: + case RPR_MATERIAL_NODE_CHECKER_TEXTURE: + case RPR_MATERIAL_NODE_CONSTANT_TEXTURE: + case RPR_MATERIAL_NODE_BUMP_MAP: + return new TextureMaterialObject(type); + + case RPR_MATERIAL_NODE_UBERV2: + { + return new UberMaterialObject(); + } + default: + throw Exception(RPR_ERROR_INVALID_PARAMETER_TYPE, "MaterialObject: unrecognized material type"); + } + + return nullptr; +} + + +MaterialObject::MaterialObject(Type type) + : m_type(type) +{ +} + +std::string MaterialObject::TranslatePropName(const std::string& in, Type type) +{ + std::string result; + //if (type == Type::kBumpMap) + //{ + // return "bump"; + //} + //else if (type == Type::kNormalMap) + //{ + // return "normal"; + //} + + auto it = kInputNamesDictionary.find(in); + if (it != kInputNamesDictionary.end()) + { + result = it->second; + } + else + { + throw Exception(RPR_ERROR_UNIMPLEMENTED, "MaterialObject: unimplemented input."); + + } + + return result; +} + + +void MaterialObject::SetInputValue(const std::string& input_name, MaterialObject* input) +{ + ImageMaterialObject* img = dynamic_cast(input); + TextureMaterialObject* tex = dynamic_cast(input); + + std::string name = TranslatePropName(input_name, GetType()); + if (img) + { + SetInputImage(name, img); + } + else if (tex) + { + SetInputTexture(name, tex); + } + else + { + SetInputMaterial(name, input); + } + + input->AddOutput(this); + SetInput(input, input_name); + Notify(); +} + +void MaterialObject::SetInputValue(const std::string& input_name, const RadeonRays::float4& val) +{ + std::string name = TranslatePropName(input_name, GetType()); + SetInputF(name, val); + + SetInput(nullptr, input_name); + Notify(); +} + +void MaterialObject::SetInputValue(const std::string& input_name, rpr_uint val) +{ + std::string name = TranslatePropName(input_name, GetType()); + SetInputU(name, val); + + SetInput(nullptr, input_name); + Notify(); +} + +void MaterialObject::SetInput(MaterialObject* input_mat, const std::string& input_name) +{ + //remove link with previous input + MaterialObject* old_input = m_inputs[input_name]; + if (old_input) + { + old_input->RemoveOutput(this); + } + + m_inputs[input_name] = input_mat; +} + + +void MaterialObject::AddOutput(MaterialObject* mat) +{ + m_out_mats.insert(mat); +} + +void MaterialObject::RemoveOutput(MaterialObject* mat) +{ + m_out_mats.erase(mat); +} + +void MaterialObject::Notify() +{ + for (auto mat : m_out_mats) + { + mat->Update(this); + } +} + +void MaterialObject::Update(MaterialObject* mat) +{ + +} + +uint64_t MaterialObject::GetInputCount() +{ + return m_inputs.size(); +} + +rpr_uint MaterialObject::GetInputType(int i) +{ + rpr_uint result = RPR_MATERIAL_NODE_INPUT_TYPE_NODE; + //get i input + auto it = m_inputs.begin(); + for (int index = 0; it != m_inputs.end(); ++it, ++index) + if (index == i) + { + break; + } + + //means no MaterialObject connected + if (!it->second) + { + result = RPR_MATERIAL_NODE_INPUT_TYPE_FLOAT4; + } + //connected input represent rpr_image + else if(it->second->IsImg()) + { + result = RPR_MATERIAL_NODE_INPUT_TYPE_IMAGE; + } + + return result; +} + +std::string MaterialObject::GetInputName(int i) +{ + //get i input + auto it = m_inputs.begin(); + for (int index = 0; it != m_inputs.end(); ++it, ++index) + if (index == i) + { + break; + } + + return it->first; +} + +std::string MaterialObject::GetInputTranslatedName(MaterialObject* mat) +{ + auto input_it = std::find_if(m_inputs.begin(), m_inputs.end(), [mat](const std::pair& i) { return i.second == mat; }); + if (input_it == m_inputs.end()) + { + throw Exception(RPR_ERROR_INTERNAL_ERROR, "MaterialObject: failed to find requested input node."); + } + return TranslatePropName(input_it->first, mat->GetType()); +} + + +void MaterialObject::GetInput(int i, void* out, size_t* out_size) +{ + //get i input + auto it = m_inputs.begin(); + for (int index = 0; it != m_inputs.end(); ++it, ++index) + if (index == i) + { + break; + } + + if (it == m_inputs.end()) return; + //translated name + std::string trans_name = TranslatePropName(it->first); + //means no MaterialObject connected + if (!it->second) + { + Material::Ptr mat = GetMaterial(); + *out_size = sizeof(RadeonRays::float4); + Baikal::Material::InputValue value = mat->GetInputValue(trans_name); + if (value.type != Baikal::Material::InputType::kFloat4) + { + throw Exception(RPR_ERROR_INTERNAL_ERROR, "MaterialObject: material input type is unexpected."); + } + + memcpy(out, &value.float_value, *out_size); + } + //images, textures and materials + else + { + *out_size = sizeof(rpr_material_node); + memcpy(out, &it->second, *out_size); + } +} + +//this call by SetInputMaterial based on input type +void MaterialObject::SetInputMaterial(const std::string& input_name, MaterialObject* input) +{ + throw Exception(RPR_ERROR_INVALID_OBJECT, "Material input not supported for the object."); +} + +void MaterialObject::SetInputTexture(const std::string& input_name, TextureMaterialObject* input) +{ + throw Exception(RPR_ERROR_INVALID_OBJECT, "Texture input not supported for the object."); +} + +void MaterialObject::SetInputImage(const std::string& input_name, ImageMaterialObject* input) +{ + throw Exception(RPR_ERROR_INVALID_OBJECT, "Image input not supported for the object."); +} + +void MaterialObject::SetInputF(const std::string& input_name, const RadeonRays::float4& val) +{ + throw Exception(RPR_ERROR_INVALID_OBJECT, "Float4 input not supported for the object."); +} + +void MaterialObject::SetInputU(const std::string& input_name, rpr_uint val) +{ + throw Exception(RPR_ERROR_INVALID_OBJECT, "rpr_uint input not supported for the object."); +} + +Baikal::Texture::Ptr MaterialObject::GetTexture() +{ + throw Exception(RPR_ERROR_INVALID_OBJECT, "This is not texture object"); +} + +Baikal::Material::Ptr MaterialObject::GetMaterial() +{ + throw Exception(RPR_ERROR_INVALID_OBJECT, "This is not material object"); +} + +rpr_image_desc MaterialObject::GetImageDesc() const +{ + throw Exception(RPR_ERROR_INVALID_IMAGE, "This is not image object"); +} +char const* MaterialObject::GetImageData() const +{ + throw Exception(RPR_ERROR_INVALID_IMAGE, "This is not image object"); + +} +rpr_image_format MaterialObject::GetImageFormat() const +{ + throw Exception(RPR_ERROR_INVALID_IMAGE, "This is not image object"); +} diff --git a/Rpr/WrapObject/MaterialObject.h b/Rpr/WrapObject/Materials/MaterialObject.h similarity index 63% rename from Rpr/WrapObject/MaterialObject.h rename to Rpr/WrapObject/Materials/MaterialObject.h index 4bbf7554..f99517f4 100644 --- a/Rpr/WrapObject/MaterialObject.h +++ b/Rpr/WrapObject/Materials/MaterialObject.h @@ -21,7 +21,7 @@ THE SOFTWARE. ********************************************************************/ #pragma once -#include "WrapObject.h" +#include "WrapObject/WrapObject.h" #include "RadeonProRender.h" #include "math/float3.h" @@ -29,14 +29,14 @@ THE SOFTWARE. #include #include -namespace Baikal -{ - class Texture; - class Material; -} +#include "SceneGraph/texture.h" +#include "SceneGraph/material.h" + +class TextureMaterialObject; +class ImageMaterialObject; //represent rpr_material_node -class MaterialObject +class RPR_API_ENTRY MaterialObject : public WrapObject { public: @@ -69,44 +69,62 @@ class MaterialObject kStandard = RPR_MATERIAL_NODE_STANDARD, kPassthrough = RPR_MATERIAL_NODE_PASSTHROUGH, kOrennayar = RPR_MATERIAL_NODE_ORENNAYAR, + kArithmetic = RPR_MATERIAL_NODE_ARITHMETIC, + kUberV2 = 0x100 }; //initialize methods - //represent rpr_image - //Note: in_data will be copied. Baikal::Texture inside. - MaterialObject(rpr_image_format const in_format, rpr_image_desc const * in_image_desc, void const * in_data); - MaterialObject(const std::string& in_path); + static MaterialObject* CreateImage(rpr_image_format const in_format, rpr_image_desc const * in_image_desc, void const * in_data); + static MaterialObject* CreateImage(const std::string& in_path); + static MaterialObject* CreateMaterial(rpr_material_node_type in_type); - //Baikal::Material or Baikal::Texture inside - MaterialObject(rpr_material_node_type in_type); + virtual ~MaterialObject() = default; - virtual ~MaterialObject(); + bool IsImg() { return m_type == Type::kImage;} + bool IsMap() { return m_type == Type::kBumpMap || + m_type == Type::kNormalMap || + m_type == Type::kDotTexture; } + bool IsArithmetic() const { return m_type == Type::kArithmetic; } - bool IsImg() { return m_type == Type::kImage; } - bool IsTexture() { return m_is_tex; } - bool IsMaterial() { return !m_is_tex; } + bool IsTexture() { return IsImg() || IsMap(); } //inputs - void SetInputMaterial(const std::string& input_name, MaterialObject* input); + void SetInputValue(const std::string& input_name, MaterialObject* input); void SetInputValue(const std::string& input_name, const RadeonRays::float4& val); + void SetInputValue(const std::string& input_name, rpr_uint val); + //Get* Type GetType() { return m_type; } - Baikal::Texture* GetTexture() { return m_tex; } - Baikal::Material* GetMaterial() { return m_mat; } + virtual Baikal::Texture::Ptr GetTexture(); + virtual Baikal::Material::Ptr GetMaterial(); + //rprMaterialGetInfo: uint64_t GetInputCount(); rpr_uint GetInputType(int i); - void GetInput(int i, void* out, size_t* out_size); + virtual void GetInput(int i, void* out, size_t* out_size); + //get input by index. + //Note: RPR related input name std::string GetInputName(int i); + //get input name by material + std::string GetInputTranslatedName(MaterialObject* mat); + //rprImageGetInfo: - rpr_image_desc GetTextureDesc() const; - char const* GetTextureData() const; - rpr_image_format GetTextureFormat() const; + virtual rpr_image_desc GetImageDesc() const; + virtual char const* GetImageData() const; + virtual rpr_image_format GetImageFormat() const; +protected: + MaterialObject(Type type); + //type - is type of input material + std::string TranslatePropName(const std::string& in, Type type = Type::kDiffuse); + //this call by SetInputMaterial based on input type + virtual void SetInputMaterial(const std::string& input_name, MaterialObject* input); + virtual void SetInputTexture(const std::string& input_name, TextureMaterialObject* input); + virtual void SetInputImage(const std::string& input_name, ImageMaterialObject* input); + virtual void SetInputF(const std::string& input_name, const RadeonRays::float4& val); + virtual void SetInputU(const std::string& input_name, rpr_uint val); private: - void Clear(); - bool CheckInputMaterial(); //handle input materials, it need for correct rprMaterialGet* methods. //Note: input_name is RPR input name @@ -116,21 +134,13 @@ class MaterialObject void AddOutput(MaterialObject* mat); void RemoveOutput(MaterialObject* mat); void Notify(); - void Update(MaterialObject* mat); + virtual void Update(MaterialObject* mat); + - //type - is type of input material - std::string TranslatePropName(const std::string& in, Type type = Type::kDiffuse); Type m_type; - bool m_is_tex; - union - { - Baikal::Texture* m_tex; - Baikal::Material* m_mat; - }; //output materials std::set m_out_mats; - //input material + RPR input name. Required for rprMaterialGet* methods. std::map m_inputs; -}; \ No newline at end of file +}; diff --git a/Rpr/WrapObject/Materials/TextureMaterialObject.cpp b/Rpr/WrapObject/Materials/TextureMaterialObject.cpp new file mode 100644 index 00000000..814582f8 --- /dev/null +++ b/Rpr/WrapObject/Materials/TextureMaterialObject.cpp @@ -0,0 +1,110 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "TextureMaterialObject.h" +#include "ImageMaterialObject.h" +#include "WrapObject/Exception.h" + + +using namespace RadeonRays; +using namespace Baikal; + +TextureMaterialObject::TextureMaterialObject(MaterialObject::Type type) + : MaterialObject(type) + , m_tex(Baikal::Texture::Create()) +{ +} + +void TextureMaterialObject::SetInputImage(const std::string& input_name, ImageMaterialObject* input) +{ + if (input_name == "data") + { + CopyData(input); + } + else + { + throw Exception(RPR_ERROR_INVALID_TAG, "MaterialObject: invalid tag for texture."); + } +} +void TextureMaterialObject::SetInputTexture(const std::string& input_name, TextureMaterialObject* input) +{ + if (input_name == "albedo" && IsMap()) + { + CopyData(input); + } + else + { + throw Exception(RPR_ERROR_INVALID_TAG, "MaterialObject: invalid tag for texture."); + } +} + +void TextureMaterialObject::CopyData(MaterialObject* in) +{ + //copy image data + auto tex = in->GetTexture(); + const char* data = tex->GetData(); + auto size = tex->GetSize(); + auto format = tex->GetFormat(); + char* tex_data = new char[tex->GetSizeInBytes()]; + memcpy(tex_data, data, tex->GetSizeInBytes()); + + m_tex->SetData(tex_data, size, format); +} + +rpr_image_desc TextureMaterialObject::GetImageDesc() const +{ + auto size = m_tex->GetSize(); + rpr_uint depth = (rpr_uint)m_tex->GetSizeInBytes() / size.x / size.y; + return{ (rpr_uint)size.x, (rpr_uint)size.y, depth, 0, 0 }; +} +char const* TextureMaterialObject::GetImageData() const +{ + return m_tex->GetData(); +} +rpr_image_format TextureMaterialObject::GetImageFormat() const +{ + rpr_component_type type; + switch (m_tex->GetFormat()) + { + case Baikal::Texture::Format::kRgba8: + type = RPR_COMPONENT_TYPE_UINT8; + break; + case Baikal::Texture::Format::kRgba16: + type = RPR_COMPONENT_TYPE_FLOAT16; + break; + case Baikal::Texture::Format::kRgba32: + type = RPR_COMPONENT_TYPE_FLOAT32; + break; + default: + throw Exception(RPR_ERROR_INTERNAL_ERROR, "MaterialObject: invalid image format."); + } + //only 4component textures used + return{ 4, type }; +} + +Baikal::Texture::Ptr TextureMaterialObject::GetTexture() +{ + return m_tex; +} diff --git a/Rpr/WrapObject/Materials/TextureMaterialObject.h b/Rpr/WrapObject/Materials/TextureMaterialObject.h new file mode 100644 index 00000000..84b6164e --- /dev/null +++ b/Rpr/WrapObject/Materials/TextureMaterialObject.h @@ -0,0 +1,47 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once + +#include "MaterialObject.h" + +//materials represented as Baikal::Texture +class TextureMaterialObject + : public MaterialObject +{ +public: + TextureMaterialObject(Type type); + Baikal::Texture::Ptr GetTexture() override; + + //rprImageGetInfo: + virtual rpr_image_desc GetImageDesc() const override; + virtual char const* GetImageData() const override; + virtual rpr_image_format GetImageFormat() const override; +protected: + + virtual void SetInputTexture(const std::string& input_name, TextureMaterialObject* input) override; + virtual void SetInputImage(const std::string& input_name, ImageMaterialObject* input) override; +private: + + void CopyData(MaterialObject* in); + + Baikal::Texture::Ptr m_tex; +}; diff --git a/Rpr/WrapObject/Materials/UberMaterialObject.cpp b/Rpr/WrapObject/Materials/UberMaterialObject.cpp new file mode 100644 index 00000000..443f7842 --- /dev/null +++ b/Rpr/WrapObject/Materials/UberMaterialObject.cpp @@ -0,0 +1,149 @@ +#include "UberMaterialObject.h" + +#include "TextureMaterialObject.h" +#include "ArithmeticMaterialObject.h" +#include "SceneGraph/uberv2material.h" +#include "SceneGraph/inputmaps.h" +#include "WrapObject/Exception.h" + +using namespace RadeonRays; +using namespace Baikal; + +UberMaterialObject::UberMaterialObject() : + MaterialObject(kUberV2) +{ + m_mat = UberV2Material::Create(); + m_mat->SetLayers(UberV2Material::Layers::kDiffuseLayer); +} + +void UberMaterialObject::SetInputF(const std::string & input_name, const RadeonRays::float4 & val) +{ + // Optimization: if we create a new input, it will take additional time for kernel compilation, + // so we try to find existing input and set a new float value + auto& input = m_mat->GetInput(input_name, Baikal::Material::InputType::kInputMap); + if (input.value.input_map_value->m_type == Baikal::InputMap::InputMapType::kConstantFloat3) + { + auto float_map = std::static_pointer_cast(input.value.input_map_value); + float_map->SetValue(val); + } + else + { + auto input_map = Baikal::InputMap_ConstantFloat3::Create(val); + m_mat->SetInputValue(input_name, input_map); + } +} + +void UberMaterialObject::SetInputU(const std::string& input_name, rpr_uint val) +{ + + // First - check if we set values that are parameters now + if (input_name == "uberv2.layers") + { + m_mat->SetLayers(val); + } + else if (input_name == "uberv2.refraction.ior_mode") + { + m_mat->LinkRefractionIOR(val == RPR_UBER_MATERIAL_REFRACTION_MODE_LINKED); + } + else if (input_name == "uberv2.refraction.thin_surface") + { + m_mat->SetThin(val != 0); + } + else if (input_name == "uberv2.emission.mode") + { + m_mat->SetDoubleSided(val == RPR_UBER_MATERIAL_EMISSION_MODE_DOUBLESIDED); + } + else if (input_name == "uberv2.sss.multiscatter") + { + m_mat->SetMultiscatter(val != 0); + } + else + { + m_mat->SetInputValue(input_name, val); + } +} + +Baikal::Material::Ptr UberMaterialObject::GetMaterial() +{ + return m_mat; +} + +void UberMaterialObject::SetInputMaterial(const std::string & input_name, MaterialObject * input) +{ + if (input->IsArithmetic()) + { + ArithmeticMaterialObject *arithmetic = static_cast(input); + m_mat->SetInputValue(input_name, arithmetic->GetInputMap()); + } + else + { + throw Exception(RPR_ERROR_INTERNAL_ERROR, "Only arithmetic nodes allowed as UberV2 inputs"); + } +} + +void UberMaterialObject::SetInputTexture(const std::string & input_name, TextureMaterialObject * input) +{ + try + { + if (input_name == "uberv2.bump") + { + auto sampler = Baikal::InputMap_SamplerBumpMap::Create(input->GetTexture()); + auto remap = Baikal::InputMap_Remap::Create( + Baikal::InputMap_ConstantFloat3::Create(float3(0.0f, 1.0f, 0.0f)), + Baikal::InputMap_ConstantFloat3::Create(float3(-1.0f, 1.0f, 0.0f)), + sampler); + m_mat->SetInputValue("uberv2.shading_normal", remap); + } + else if (input_name == "uberv2.normal") + { + auto sampler = Baikal::InputMap_Sampler::Create(input->GetTexture()); + auto remap = Baikal::InputMap_Remap::Create( + Baikal::InputMap_ConstantFloat3::Create(float3(0.0f, 1.0f, 0.0f)), + Baikal::InputMap_ConstantFloat3::Create(float3(-1.0f, 1.0f, 0.0f)), + sampler); + m_mat->SetInputValue("uberv2.shading_normal", remap); + } + else + { + auto sampler = Baikal::InputMap_Sampler::Create(input->GetTexture()); + m_mat->SetInputValue(input_name, sampler); + } + } + catch (...) + { + //Ignore + return; + } +} + +void UberMaterialObject::GetInput(int i, void* out, size_t* out_size) +{ + //We have only int values as parameters for now + uint32_t *int_out = static_cast(out); + *out_size = sizeof(uint32_t); + + switch (i) + { + case RPR_UBER_MATERIAL_LAYERS: + *int_out = m_mat->GetLayers(); + break; + case RPR_UBER_MATERIAL_EMISSION_MODE: + *int_out = m_mat->isDoubleSided() ? + RPR_UBER_MATERIAL_EMISSION_MODE_DOUBLESIDED : + RPR_UBER_MATERIAL_EMISSION_MODE_SINGLESIDED; + break; + case RPR_UBER_MATERIAL_REFRACTION_IOR_MODE: + *int_out = m_mat->IsLinkRefractionIOR() ? + RPR_UBER_MATERIAL_REFRACTION_MODE_LINKED : + RPR_UBER_MATERIAL_REFRACTION_MODE_SEPARATE; + break; + case RPR_UBER_MATERIAL_SSS_MULTISCATTER: + *int_out = m_mat->IsMultiscatter() ? 1 : 0; + break; + case RPR_UBER_MATERIAL_REFRACTION_THIN_SURFACE: + *int_out = m_mat->IsThin() ? 1 : 0; + break; + default: + MaterialObject::GetInput(i, out, out_size); + } +} diff --git a/Rpr/WrapObject/Materials/UberMaterialObject.h b/Rpr/WrapObject/Materials/UberMaterialObject.h new file mode 100644 index 00000000..b2fe24e5 --- /dev/null +++ b/Rpr/WrapObject/Materials/UberMaterialObject.h @@ -0,0 +1,47 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once + +#include "MaterialObject.h" +#include "SceneGraph/uberv2material.h" + +class UberMaterialObject : public MaterialObject +{ +public: + UberMaterialObject(); + + void SetInputF(const std::string& input_name, const RadeonRays::float4& val) override; + void SetInputU(const std::string& input_name, rpr_uint val) override; + + Baikal::Material::Ptr GetMaterial() override; + + // Some UberV2 inputs from RPRX API now become parameters in Baikal API so we need to fill em + void GetInput(int i, void* out, size_t* out_size) override; +protected: + void SetInputMaterial(const std::string& input_name, MaterialObject* input) override; + void SetInputTexture(const std::string& input_name, TextureMaterialObject* input) override; + +private: + Baikal::UberV2Material::Ptr m_mat; //ubermaterial material + +}; + diff --git a/Rpr/WrapObject/Materials/UnsupportedMaterialObject.cpp b/Rpr/WrapObject/Materials/UnsupportedMaterialObject.cpp new file mode 100644 index 00000000..5116d5e1 --- /dev/null +++ b/Rpr/WrapObject/Materials/UnsupportedMaterialObject.cpp @@ -0,0 +1,58 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "UnsupportedMaterialObject.h" +#include "WrapObject/Exception.h" + +#include + +using namespace Baikal; +using namespace RadeonRays; + +UnsupportedMaterialObject::UnsupportedMaterialObject(MaterialObject::Type type) + : MaterialObject(type) +{ + +} + +void UnsupportedMaterialObject::SetInputMaterial(const std::string& input_name, MaterialObject* input) +{ + //trying to behave as SingleBxdfMaterialObject and ignore in case of failure + std::cout << "Warning: ignoring unsupported material input name - " << input_name << std::endl; +} + +void UnsupportedMaterialObject::SetInputTexture(const std::string& input_name, TextureMaterialObject* input) +{ + //trying to behave as SingleBxdfMaterialObject and ignore in case of failure + std::cout << "Warning: ignoring unsupported material input name - " << input_name << std::endl; +} + +void UnsupportedMaterialObject::SetInputImage(const std::string& input_name, ImageMaterialObject* input) +{ + //trying to behave as SingleBxdfMaterialObject and ignore in case of failure + std::cout << "Warning: ignoring unsupported material input name - " << input_name << std::endl; +} + +void UnsupportedMaterialObject::SetInputF(const std::string& input_name, const RadeonRays::float4& val) +{ + //trying to behave as SingleBxdfMaterialObject and ignore in case of failure + std::cout << "Warning: ignoring unsupported material input name - " << input_name << std::endl; +} diff --git a/Rpr/WrapObject/Materials/UnsupportedMaterialObject.h b/Rpr/WrapObject/Materials/UnsupportedMaterialObject.h new file mode 100644 index 00000000..9062e845 --- /dev/null +++ b/Rpr/WrapObject/Materials/UnsupportedMaterialObject.h @@ -0,0 +1,39 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. +********************************************************************/ +#pragma once + +#include "MaterialObject.h" + +//default variant of material +class UnsupportedMaterialObject + : public MaterialObject +{ +public: + UnsupportedMaterialObject(MaterialObject::Type mat_type); +protected: + //this call by SetInputMaterial based on input type + void SetInputMaterial(const std::string& input_name, MaterialObject* input) override; + void SetInputTexture(const std::string& input_name, TextureMaterialObject* input) override; + void SetInputImage(const std::string& input_name, ImageMaterialObject* input) override; + void SetInputF(const std::string& input_name, const RadeonRays::float4& val) override; +private: +}; \ No newline at end of file diff --git a/Rpr/WrapObject/SceneObject.cpp b/Rpr/WrapObject/SceneObject.cpp index 308b0bad..d2f0603a 100644 --- a/Rpr/WrapObject/SceneObject.cpp +++ b/Rpr/WrapObject/SceneObject.cpp @@ -24,68 +24,74 @@ THE SOFTWARE. #include "WrapObject/ShapeObject.h" #include "WrapObject/LightObject.h" #include "WrapObject/CameraObject.h" -#include "App/SceneGraph/scene1.h" -#include "App/SceneGraph/light.h" -#include "App/SceneGraph/shape.h" -#include "App/SceneGraph/material.h" -#include "App/SceneGraph/iterator.h" +#include "SceneGraph/scene1.h" +#include "SceneGraph/light.h" +#include "SceneGraph/shape.h" +#include "SceneGraph/material.h" +#include "SceneGraph/iterator.h" #include SceneObject::SceneObject() : m_scene(nullptr) { - m_scene = new Baikal::Scene1(); + m_scene = Baikal::Scene1::Create(); } + SceneObject::~SceneObject() { - delete m_scene; - m_scene = nullptr; +} + +void SceneObject::SetScene(Baikal::Scene1::Ptr scene) +{ + m_scene = std::move(scene); } void SceneObject::Clear() { - m_shapes.clear(); + m_shapes.clear(); m_lights.clear(); //remove lights for (std::unique_ptr it_light(m_scene->CreateLightIterator()); it_light->IsValid();) { - m_scene->DetachLight(it_light->ItemAs()); - it_light.reset(m_scene->CreateLightIterator()); + m_scene->DetachLight(it_light->ItemAs()); + it_light = m_scene->CreateLightIterator(); } //remove shapes for (std::unique_ptr it_shape(m_scene->CreateShapeIterator()); it_shape->IsValid();) { - m_scene->DetachShape(it_shape->ItemAs()); - it_shape.reset(m_scene->CreateShapeIterator()); + m_scene->DetachShape(it_shape->ItemAs()); + it_shape = m_scene->CreateShapeIterator(); } + + if (m_current_camera) m_current_camera->RemoveFromScene(this); } void SceneObject::AttachShape(ShapeObject* shape) { - //check is mesh already in scene - auto it = std::find(m_shapes.begin(), m_shapes.end(), shape); - if (it != m_shapes.end()) - { - return; - } - m_shapes.push_back(shape); + //check is mesh already in scene + auto it = std::find(m_shapes.begin(), m_shapes.end(), shape); + if (it != m_shapes.end()) + { + return; + } + m_shapes.push_back(shape); m_scene->AttachShape(shape->GetShape()); } void SceneObject::DetachShape(ShapeObject* shape) { - //check is mesh in scene - auto it = std::find(m_shapes.begin(), m_shapes.end(), shape); - if (it == m_shapes.end()) - { - return; - } - m_shapes.erase(it); - m_scene->DetachShape(shape->GetShape()); + //check is mesh in scene + auto it = std::find(m_shapes.begin(), m_shapes.end(), shape); + if (it == m_shapes.end()) + { + return; + } + m_shapes.erase(it); + m_scene->DetachShape(shape->GetShape()); } void SceneObject::AttachLight(LightObject* light) @@ -116,13 +122,14 @@ void SceneObject::DetachLight(LightObject* light) void SceneObject::SetCamera(CameraObject* cam) { m_current_camera = cam; - Baikal::Camera* baikal_cam = cam ? cam->GetCamera() : nullptr; + if (m_current_camera) cam->AddToScene(this); + auto baikal_cam = cam ? cam->GetCamera() : nullptr; m_scene->SetCamera(baikal_cam); } void SceneObject::GetShapeList(void* out_list) { - memcpy(out_list, m_shapes.data(), m_shapes.size() * sizeof(ShapeObject*)); + memcpy(out_list, m_shapes.data(), m_shapes.size() * sizeof(ShapeObject*)); } void SceneObject::GetLightList(void* out_list) @@ -130,59 +137,136 @@ void SceneObject::GetLightList(void* out_list) memcpy(out_list, m_lights.data(), m_lights.size() * sizeof(LightObject*)); } +RadeonRays::bbox SceneObject::GetBBox() +{ + return m_scene->GetWorldAABB(); +} + void SceneObject::AddEmissive() { //TODO: check scene isn't changed //recreate amissives if scene is dirty if (!m_scene->GetDirtyFlags()) - { - return; - } + { + return; + } RemoveEmissive(); - //handle emissive materials - for (std::unique_ptr it_shape(m_scene->CreateShapeIterator()); it_shape->IsValid(); it_shape->Next()) - { - const Baikal::Shape* shape = it_shape->ItemAs(); - const Baikal::Mesh* mesh = dynamic_cast(shape); - //instance case - if (!mesh) - { - const Baikal::Instance* inst = dynamic_cast(shape); - assert(inst); - mesh = dynamic_cast(inst->GetBaseShape()); - } - assert(mesh); - - const Baikal::Material* mat = mesh->GetMaterial(); - if (!mat) - { - continue; - } - //fine shapes with emissive material - if (mat->HasEmission()) - { - // Add area light for each polygon of emissive mesh - for (int l = 0; l < mesh->GetNumIndices() / 3; ++l) - { - Baikal::AreaLight* light = new Baikal::AreaLight(mesh, l); - m_scene->AttachLight(light); - m_scene->AttachAutoreleaseObject(light); - m_emmisive_lights.push_back(light); - } - } - } + //handle emissive materials + for (std::unique_ptr it_shape(m_scene->CreateShapeIterator()); it_shape->IsValid(); it_shape->Next()) + { + auto shape = it_shape->ItemAs(); + auto mesh = std::dynamic_pointer_cast(shape); + //instance case + if (!mesh) + { + auto inst = std::dynamic_pointer_cast(shape); + assert(inst); + mesh = std::dynamic_pointer_cast(inst->GetBaseShape()); + } + assert(mesh); + + auto mat = mesh->GetMaterial(); + if (!mat) + { + continue; + } + //fine shapes with emissive material + if (mat->HasEmission()) + { + // Add area light for each polygon of emissive mesh + for (std::size_t l = 0; l < mesh->GetNumIndices() / 3; ++l) + { + auto light = Baikal::AreaLight::Create(mesh, l); + m_scene->AttachLight(light); + m_emmisive_lights.push_back(light); + } + } + } } void SceneObject::RemoveEmissive() { - for (auto light : m_emmisive_lights) - { - m_scene->DetachLight(light); - m_scene->DetachAutoreleaseObject(light); + for (auto light : m_emmisive_lights) + { + m_scene->DetachLight(light); + } + + m_emmisive_lights.clear(); +} - delete light; - } - m_emmisive_lights.clear(); -} \ No newline at end of file +bool SceneObject::IsDirty() +{ + auto dirty = m_scene->GetDirtyFlags(); + return dirty != Baikal::Scene1::kNone; +} + +void SceneObject::SetBackgroundImage(MaterialObject* image) +{ + m_background_image = image; + if (m_background_image && m_background_image->IsTexture()) + m_scene->SetBackgroundImage(m_background_image->GetTexture()); + else + m_scene->SetBackgroundImage(nullptr); +} + +MaterialObject* SceneObject::GetBackgroundImage() const +{ + return m_background_image; +} + +void SceneObject::SetEnvironmentOverride(OverrideType overrride, LightObject* light) +{ + switch (overrride) + { + case OverrideType::kBackground: + m_environment_override.m_background = light; + break; + case OverrideType::kReflection: + m_environment_override.m_reflection = light; + break; + case OverrideType::kRefraction: + m_environment_override.m_refraction = light; + break; + case OverrideType::kTransparency: + m_environment_override.m_transparency = light; + break; + } + + m_scene->SetEnvironmentOverride(m_environment_override.ToScene1EnvironmentOverride()); +} + +LightObject* SceneObject::GetEnvironmentOverride(OverrideType overrride) +{ + switch (overrride) + { + case OverrideType::kBackground: + return m_environment_override.m_background; + case OverrideType::kReflection: + return m_environment_override.m_reflection; + case OverrideType::kRefraction: + return m_environment_override.m_refraction; + case OverrideType::kTransparency: + return m_environment_override.m_transparency; + } + return nullptr; +} + +Baikal::Scene1::EnvironmentOverride SceneObject::EnvironmentOverride::ToScene1EnvironmentOverride() const +{ + Baikal::Scene1::EnvironmentOverride out; + out.m_background = m_background ? + std::static_pointer_cast(m_background->GetLight()) : nullptr; + + out.m_reflection = m_reflection ? + std::static_pointer_cast(m_reflection->GetLight()) : nullptr; + + out.m_refraction = m_refraction ? + std::static_pointer_cast(m_refraction->GetLight()) : nullptr; + + out.m_transparency = m_transparency ? + std::static_pointer_cast(m_transparency->GetLight()) : nullptr; + + return out; +} diff --git a/Rpr/WrapObject/SceneObject.h b/Rpr/WrapObject/SceneObject.h index 9b689e75..aa8a4e04 100644 --- a/Rpr/WrapObject/SceneObject.h +++ b/Rpr/WrapObject/SceneObject.h @@ -21,6 +21,7 @@ THE SOFTWARE. ********************************************************************/ #pragma once +#include "RadeonProRender.h" #include "WrapObject/WrapObject.h" #include "SceneGraph/scene1.h" #include "SceneGraph/shape.h" @@ -31,12 +32,21 @@ THE SOFTWARE. class ShapeObject; class LightObject; class CameraObject; +class MaterialObject; //this class represent rpr_context -class SceneObject +class RPR_API_ENTRY SceneObject : public WrapObject { public: + enum class OverrideType + { + kReflection, + kRefraction, + kTransparency, + kBackground + }; + SceneObject(); virtual ~SceneObject(); @@ -54,20 +64,43 @@ class SceneObject void SetCamera(CameraObject* cam); CameraObject* GetCamera() { return m_current_camera; } - void GetShapeList(void* out_list); - size_t GetShapeCount() { return m_scene->GetNumShapes(); } + void GetShapeList(void* out_list); + size_t GetShapeCount() { return m_scene->GetNumShapes(); } void GetLightList(void* out_list); size_t GetLightCount() { return m_scene->GetNumLights(); } - void AddEmissive(); - void RemoveEmissive(); - Baikal::Scene1* GetScene() { return m_scene; }; + RadeonRays::bbox GetBBox(); + + // Image override + void SetBackgroundImage(MaterialObject* image); + MaterialObject* GetBackgroundImage() const; + + // Environment override + void SetEnvironmentOverride(OverrideType overrride, LightObject* light); + LightObject* GetEnvironmentOverride(OverrideType overrride); + + void AddEmissive(); + void RemoveEmissive(); + bool IsDirty(); + + void SetScene(Baikal::Scene1::Ptr scene); + Baikal::Scene1::Ptr GetScene() { return m_scene; }; + private: - Baikal::Scene1* m_scene; - CameraObject* m_current_camera; - std::vector m_emmisive_lights;//area lights fro emissive shapes + Baikal::Scene1::Ptr m_scene; + CameraObject* m_current_camera = nullptr; + std::vector m_emmisive_lights;//area lights fro emissive shapes std::vector m_shapes; std::vector m_lights; + MaterialObject *m_background_image = nullptr; -}; \ No newline at end of file + struct EnvironmentOverride + { + LightObject* m_reflection = nullptr; + LightObject* m_refraction = nullptr; + LightObject* m_transparency = nullptr; + LightObject* m_background = nullptr; + Baikal::Scene1::EnvironmentOverride ToScene1EnvironmentOverride() const; + } m_environment_override; +}; diff --git a/Rpr/WrapObject/ShapeObject.cpp b/Rpr/WrapObject/ShapeObject.cpp index ab33cd6c..21e5c344 100644 --- a/Rpr/WrapObject/ShapeObject.cpp +++ b/Rpr/WrapObject/ShapeObject.cpp @@ -25,7 +25,7 @@ THE SOFTWARE. #include "WrapObject/ShapeObject.h" #include "WrapObject/Exception.h" -#include "App/SceneGraph/shape.h" +#include "SceneGraph/shape.h" using namespace Baikal; @@ -37,22 +37,22 @@ namespace rpr_int const * in_num_face_vertices, size_t in_num_faces) { std::vector result; - if (!in_data || !in_data_indices) - { - std::cout << "Warning: missing mesh data, fill it with NULL.\n"; - int count = 0; - for (int i = 0; i < in_num_faces; ++i) - { - count +=in_num_face_vertices[i]; - } - result.resize(count * size); - std::fill(result.begin(), result.end(), 0.f); - - return result; - } + if (!in_data || !in_data_indices) + { + std::cout << "Warning: missing mesh data, fill it with NULL.\n"; + int count = 0; + for (std::size_t i = 0; i < in_num_faces; ++i) + { + count += in_num_face_vertices[i]; + } + result.resize(count * size); + std::fill(result.begin(), result.end(), 0.f); + + return result; + } int indent = 0; - for (int i = 0; i < in_num_faces; ++i) + for (std::size_t i = 0; i < in_num_faces; ++i) { int face = in_num_face_vertices[i]; for (int f = indent; f < face + indent; ++f) @@ -70,7 +70,7 @@ namespace } } -ShapeObject::ShapeObject(Baikal::Shape* shape, ShapeObject* base_shape_obj) +ShapeObject::ShapeObject(Baikal::Shape::Ptr shape, ShapeObject* base_shape_obj) : m_shape(shape) , m_current_mat(nullptr) , m_base_obj(base_shape_obj) @@ -79,9 +79,6 @@ ShapeObject::ShapeObject(Baikal::Shape* shape, ShapeObject* base_shape_obj) ShapeObject::~ShapeObject() { - delete m_shape; - m_shape = nullptr; - m_base_obj = nullptr; } ShapeObject* ShapeObject::CreateInstance() @@ -96,8 +93,8 @@ ShapeObject* ShapeObject::CreateInstance() { base_shape = this; } - Instance* instance = new Instance(base_shape->m_shape); - ShapeObject* result = new ShapeObject(instance, base_shape); + auto instance = Instance::Create(base_shape->m_shape); + auto result = new ShapeObject(instance, base_shape); return result; } @@ -149,23 +146,19 @@ ShapeObject* ShapeObject::CreateMesh(rpr_float const * in_vertices, size_t in_nu } //create mesh - Baikal::Mesh* mesh = new Baikal::Mesh(); + auto mesh = Baikal::Mesh::Create(); mesh->SetVertices(verts.data(), verts.size() / 3); mesh->SetNormals(normals.data(), normals.size() / 3); mesh->SetUVs(uvs.data(), uvs.size() / 2); mesh->SetIndices(inds.data(), inds.size()); - return new ShapeObject(mesh, false); + return new ShapeObject(mesh, nullptr); } + void ShapeObject::SetMaterial(MaterialObject* mat) { if (mat) { - if (!mat->IsMaterial()) - { - throw Exception(RPR_ERROR_INVALID_PARAMETER, "ShapeObject: material is a texture."); - } - //handle fresnel materials if (mat->GetType() == MaterialObject::Type::kFresnel || mat->GetType() == MaterialObject::Type::kFresnelShlick) @@ -183,7 +176,7 @@ void ShapeObject::SetMaterial(MaterialObject* mat) uint64_t ShapeObject::GetVertexCount() { - Baikal::Mesh* mesh = dynamic_cast(m_shape); + auto mesh = std::dynamic_pointer_cast(m_shape); if (!mesh) { throw Exception(RPR_ERROR_INTERNAL_ERROR, "ShapeObject: mesh is nullptr."); @@ -193,7 +186,7 @@ uint64_t ShapeObject::GetVertexCount() void ShapeObject::GetVertexData(float* out) const { - Baikal::Mesh* mesh = dynamic_cast(m_shape); + auto mesh = std::dynamic_pointer_cast(m_shape); if (!mesh) { throw Exception(RPR_ERROR_INTERNAL_ERROR, "ShapeObject: mesh is nullptr."); @@ -202,7 +195,7 @@ void ShapeObject::GetVertexData(float* out) const //need to copy data, because RadeonRays::float3 contains 4 float, //but we need only 3 const RadeonRays::float3 * data = mesh->GetVertices(); - for (int i = 0; i < mesh->GetNumVertices(); ++i) + for (std::size_t i = 0; i < mesh->GetNumVertices(); ++i) { out[3 * i] = data[i].x; out[3 * i + 1] = data[i].y; @@ -213,16 +206,17 @@ void ShapeObject::GetVertexData(float* out) const uint64_t ShapeObject::GetNormalCount() { - Baikal::Mesh* mesh = dynamic_cast(m_shape); + auto mesh = std::dynamic_pointer_cast(m_shape); if (!mesh) { throw Exception(RPR_ERROR_INTERNAL_ERROR, "ShapeObject: mesh is nullptr."); } + return mesh->GetNumNormals(); } void ShapeObject::GetNormalData(float* out) const { - Baikal::Mesh* mesh = dynamic_cast(m_shape); + auto mesh = std::dynamic_pointer_cast(m_shape); if (!mesh) { throw Exception(RPR_ERROR_INTERNAL_ERROR, "ShapeObject: mesh is nullptr."); @@ -231,7 +225,7 @@ void ShapeObject::GetNormalData(float* out) const //need to copy data, because RadeonRays::float3 contains 4 float, //but we need only 3 const RadeonRays::float3 * data = mesh->GetNormals(); - for (int i = 0; i < mesh->GetNumNormals(); ++i) + for (std::size_t i = 0; i < mesh->GetNumNormals(); ++i) { out[3 * i] = data[i].x; out[3 * i + 1] = data[i].y; @@ -242,15 +236,18 @@ void ShapeObject::GetNormalData(float* out) const uint64_t ShapeObject::GetUVCount() { - Baikal::Mesh* mesh = dynamic_cast(m_shape); + auto mesh = std::dynamic_pointer_cast(m_shape); if (!mesh) { throw Exception(RPR_ERROR_INTERNAL_ERROR, "ShapeObject: mesh is nullptr."); } return mesh->GetNumUVs(); -}const RadeonRays::float2* ShapeObject::GetUVData() const +} + +const RadeonRays::float2* ShapeObject::GetUVData() const { - Baikal::Mesh* mesh = dynamic_cast(m_shape); + auto mesh = std::dynamic_pointer_cast(m_shape); + if (!mesh) { throw Exception(RPR_ERROR_INTERNAL_ERROR, "ShapeObject: mesh is nullptr."); @@ -260,7 +257,7 @@ uint64_t ShapeObject::GetUVCount() const uint32_t* ShapeObject::GetIndicesData() const { - Baikal::Mesh* mesh = dynamic_cast(m_shape); + auto mesh = std::dynamic_pointer_cast(m_shape); if (!mesh) { throw Exception(RPR_ERROR_INTERNAL_ERROR, "ShapeObject: mesh is nullptr."); @@ -270,7 +267,7 @@ const uint32_t* ShapeObject::GetIndicesData() const uint64_t ShapeObject::GetIndicesCount() const { - Baikal::Mesh* mesh = dynamic_cast(m_shape); + auto mesh = std::dynamic_pointer_cast(m_shape); if (!mesh) { throw Exception(RPR_ERROR_INTERNAL_ERROR, "ShapeObject: mesh is nullptr."); diff --git a/Rpr/WrapObject/ShapeObject.h b/Rpr/WrapObject/ShapeObject.h index 9b5421e4..c2cb958f 100644 --- a/Rpr/WrapObject/ShapeObject.h +++ b/Rpr/WrapObject/ShapeObject.h @@ -22,13 +22,11 @@ THE SOFTWARE. #pragma once #include "RadeonProRender.h" -#include "App/SceneGraph/shape.h" +#include "SceneGraph/shape.h" #include "WrapObject/WrapObject.h" -#include "WrapObject/MaterialObject.h" +#include "WrapObject/Materials/MaterialObject.h" -namespace Baikal { - class Shape; -} +#include "SceneGraph/shape.h" //this class represent rpr_scene class ShapeObject @@ -36,7 +34,7 @@ class ShapeObject { private: - ShapeObject(Baikal::Shape* shape, ShapeObject* base_shape_obj = nullptr); + ShapeObject(Baikal::Shape::Ptr shape, ShapeObject* base_shape_obj = nullptr); virtual ~ShapeObject(); public: @@ -72,9 +70,9 @@ class ShapeObject uint64_t GetIndicesCount() const; ShapeObject* GetBaseShape() { return m_base_obj; } - Baikal::Shape* GetShape() { return m_shape; } + Baikal::Shape::Ptr GetShape() { return m_shape; } private: - Baikal::Shape* m_shape; + Baikal::Shape::Ptr m_shape; MaterialObject* m_current_mat; ShapeObject* m_base_obj; -}; \ No newline at end of file +}; diff --git a/Rpr/WrapObject/WrapObject.h b/Rpr/WrapObject/WrapObject.h index f0b5eaad..cf5b5361 100644 --- a/Rpr/WrapObject/WrapObject.h +++ b/Rpr/WrapObject/WrapObject.h @@ -21,10 +21,12 @@ THE SOFTWARE. ********************************************************************/ #pragma once +#include "RadeonProRender.h" + #include //base wrap class of Baikal scene nodes -class WrapObject +class RPR_API_ENTRY WrapObject { public: WrapObject() = default; @@ -41,9 +43,9 @@ class WrapObject std::string GetName() { return m_name; } void SetName(const std::string& name) { m_name = name; } - //forbidden - WrapObject(const WrapObject&) = delete; - WrapObject& operator= (WrapObject const&) = delete; + WrapObject(WrapObject&&) = default; + WrapObject& operator= (WrapObject&&) = default; + private: std::string m_name; }; diff --git a/RprLoadStore/RprLoadStore.cpp b/RprLoadStore/RprLoadStore.cpp deleted file mode 100644 index 25f8d029..00000000 --- a/RprLoadStore/RprLoadStore.cpp +++ /dev/null @@ -1,505 +0,0 @@ -#include "RprLoadStore.h" - -#include "Rpr/RadeonProRender.h" - -#include -#include - -#include "frs6.h" -#include "frs7.h" -#include "rps8.h" - - -std::map g_extraCustomParam_int; -std::map g_extraCustomParam_float; -std::vector g_listLoadedObjects; - - - -int rprsExportCustomList( - char const * frsFileName, - int materialNode_number, rpr_material_node* materialNode_list, - int camera_number, rpr_camera* camera_list, - int light_number, rpr_light* light_list, - int shape_number, rpr_shape* shape_list, - int image_number, rpr_image* image_list -) -{ - rpr_int status = RPR_SUCCESS; - - std::fstream ofileStore(frsFileName, std::fstream::binary | std::fstream::out | std::fstream::trunc); - if (ofileStore.is_open() && !ofileStore.fail() ) - { - RPS8 frsFile(&ofileStore, true); - - std::vector materialNodeList; - std::vector cameraList; - std::vector lightList; - std::vector shapeList; - std::vector imageList; - - for(int i=0; i imageList; - std::vector shapeList; - std::vector lightList; - std::vector cameraList; - std::vector materialNodeList; - - RPS8 frsFile(&ifileStore, false); - status = frsFile.LoadCustomList( - context, - materialSystem, - imageList, - shapeList, - lightList, - cameraList, - materialNodeList - ); - g_extraCustomParam_int.clear(); - g_extraCustomParam_float.clear(); - g_listLoadedObjects.clear(); - - if ( status == RPR_SUCCESS ) - { - g_extraCustomParam_int = frsFile.GetExtraCustomParam_int(); - g_extraCustomParam_float = frsFile.GetExtraCustomParam_float(); - g_listLoadedObjects = frsFile.GetListObjectDeclared(); - - if ( image_number != NULL ) { *image_number = imageList.size(); } - if ( image_list != NULL ) { for(int i=0; i= 0 && index < nbOfInt ) - { - int i=0; - for(auto it=g_extraCustomParam_int.begin(); it!=g_extraCustomParam_int.end(); it++) - { - if ( i == index ) - { - *value = (*it).second; - return RPR_SUCCESS; - } - i++; - } - } - - return RPR_ERROR_INVALID_PARAMETER; -} - -int rprsGetExtraCustomParamIndex_float(int index, float* value) -{ - int nbOfInt = g_extraCustomParam_int.size(); - int nbOfFloat = g_extraCustomParam_float.size(); - - if ( index >= nbOfInt+0 && index < nbOfInt+nbOfFloat ) - { - int i=nbOfInt; - for(auto it=g_extraCustomParam_float.begin(); it!=g_extraCustomParam_float.end(); it++) - { - if ( i == index ) - { - *value = (*it).second; - return RPR_SUCCESS; - } - i++; - } - } - - return RPR_ERROR_INVALID_PARAMETER; -} - - -int rprsGetNumberOfExtraCustomParam() -{ - return g_extraCustomParam_int.size() + g_extraCustomParam_float.size(); -} - - -int rprsGetExtraCustomParamNameSize(int index, int* nameSizeGet) -{ - int nbOfInt = g_extraCustomParam_int.size(); - int nbOfFloat = g_extraCustomParam_float.size(); - - if ( index >= 0 && index < nbOfInt ) - { - int i=0; - for(auto it=g_extraCustomParam_int.begin(); it!=g_extraCustomParam_int.end(); it++) - { - if ( i == index ) - { - *nameSizeGet = (*it).first.size()+1; - return RPR_SUCCESS; - } - i++; - } - } - else if ( index >= nbOfInt+0 && index < nbOfInt+nbOfFloat ) - { - int i=nbOfInt; - for(auto it=g_extraCustomParam_float.begin(); it!=g_extraCustomParam_float.end(); it++) - { - if ( i == index ) - { - *nameSizeGet = (*it).first.size()+1; - return RPR_SUCCESS; - } - i++; - } - } - - return RPR_ERROR_INVALID_PARAMETER; -} - - -int rprsGetExtraCustomParamType(int index) -{ - - int nbOfInt = g_extraCustomParam_int.size(); - int nbOfFloat = g_extraCustomParam_float.size(); - - if ( index >= 0 && index < nbOfInt ) - { - return RPRLOADSTORE_PARAMETER_TYPE_INT; - } - else if ( index >= nbOfInt+0 && index < nbOfInt+nbOfFloat ) - { - return RPRLOADSTORE_PARAMETER_TYPE_FLOAT; - } - - return RPRLOADSTORE_PARAMETER_TYPE_UNDEF; -} - -int rprsGetExtraCustomParamName(int index, char* nameGet, int nameGetSize) -{ - int nbOfInt = g_extraCustomParam_int.size(); - int nbOfFloat = g_extraCustomParam_float.size(); - - if ( index >= 0 && index < nbOfInt ) - { - int i=0; - for(auto it=g_extraCustomParam_int.begin(); it!=g_extraCustomParam_int.end(); it++) - { - if ( i == index && nameGetSize >= (*it).first.size()+1 ) - { - std::strcpy(nameGet,(*it).first.c_str()); - return RPR_SUCCESS; - } - i++; - } - } - else if ( index >= nbOfInt+0 && index < nbOfInt+nbOfFloat ) - { - int i=nbOfInt; - for(auto it=g_extraCustomParam_float.begin(); it!=g_extraCustomParam_float.end(); it++) - { - if ( i == index && nameGetSize >= (*it).first.size()+1 ) - { - std::strcpy(nameGet,(*it).first.c_str()); - return RPR_SUCCESS; - } - i++; - } - } - - return RPR_ERROR_INVALID_PARAMETER; -} - - - -int rprsListImportedObjects(void** objOut, int sizeLightBytes ,int* numberOfObjectsOut, const char* frName, const char* rprName) -{ - int nbOfObjects = 0; - - for(int iObj=0; iObj= (nbOfObjects+1)*sizeof(rpr_light*) ) - { - objOut[nbOfObjects] = g_listLoadedObjects[iObj].obj; - } - else - { - return RPR_ERROR_INVALID_PARAMETER; - } - } - - nbOfObjects++; - - } - - } - - if ( numberOfObjectsOut ) - { - *numberOfObjectsOut = nbOfObjects; - } - - return RPR_SUCCESS; -} - - -int rprsListImportedCameras(void** Cameras, int sizeCameraBytes ,int* numberOfCameras) -{ - int ret = rprsListImportedObjects(Cameras,sizeCameraBytes,numberOfCameras,"fr_camera","rpr_camera"); - return ret; -} -int rprsListImportedMaterialNodes(void** MaterialNodes, int sizeMaterialNodeBytes ,int* numberOfMaterialNodes) -{ - int ret = rprsListImportedObjects(MaterialNodes,sizeMaterialNodeBytes,numberOfMaterialNodes,"fr_material_node","rpr_material_node"); - return ret; -} -int rprsListImportedLights(void** Lights, int sizeLightBytes ,int* numberOfLights) -{ - int ret = rprsListImportedObjects(Lights,sizeLightBytes,numberOfLights,"fr_light","rpr_light"); - return ret; -} -int rprsListImportedShapes(void** Shapes, int sizeShapeBytes ,int* numberOfShapes) -{ - int ret = rprsListImportedObjects(Shapes,sizeShapeBytes,numberOfShapes,"fr_shape","rpr_shape"); - return ret; -} -int rprsListImportedImages(void** Images, int sizeImageBytes ,int* numberOfImages) -{ - int ret = rprsListImportedObjects(Images,sizeImageBytes,numberOfImages,"fr_image","rpr_image"); - return ret; -} diff --git a/RprLoadStore/RprLoadStore.def b/RprLoadStore/RprLoadStore.def deleted file mode 100644 index f451a786..00000000 --- a/RprLoadStore/RprLoadStore.def +++ /dev/null @@ -1,36 +0,0 @@ -EXPORTS - -rprsExport -rprsImport -rprsGetExtraCustomParam_int -rprsGetExtraCustomParam_float -rprsGetExtraCustomParamIndex_int -rprsGetExtraCustomParamIndex_float -rprsGetNumberOfExtraCustomParam -rprsGetExtraCustomParamNameSize -rprsGetExtraCustomParamName -rprsGetExtraCustomParamType -rprsListImportedCameras -rprsListImportedMaterialNodes -rprsListImportedLights -rprsListImportedShapes -rprsListImportedImages -rprsExportCustomList -rprsImportCustomList -frsExport -frsImport -frsGetExtraCustomParam_int -frsGetExtraCustomParam_float -frsGetExtraCustomParamIndex_int -frsGetExtraCustomParamIndex_float -frsGetNumberOfExtraCustomParam -frsGetExtraCustomParamNameSize -frsGetExtraCustomParamName -frsGetExtraCustomParamType -frsListImportedCameras -frsListImportedMaterialNodes -frsListImportedLights -frsListImportedShapes -frsListImportedImages -frsExportCustomList -frsImportCustomList diff --git a/RprLoadStore/RprLoadStore.h b/RprLoadStore/RprLoadStore.h deleted file mode 100644 index 8d27276a..00000000 --- a/RprLoadStore/RprLoadStore.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef __RPRLOADSTORE_H -#define __RPRLOADSTORE_H - -#define RPR_API_ENTRY - -#ifdef __cplusplus -extern "C" { -#endif - -#define RPRLOADSTORE_PARAMETER_TYPE_UNDEF 0x0 -#define RPRLOADSTORE_PARAMETER_TYPE_INT 0x1 -#define RPRLOADSTORE_PARAMETER_TYPE_FLOAT 0x2 - -extern RPR_API_ENTRY int rprsExport(char const * rprsFileName, void * context, void * scene, int extraCustomParam_int_number, char const * * extraCustomParam_int_names, int const * extraCustomParam_int_values, int extraCustomParam_float_number, char const * * extraCustomParam_float_names, float const * extraCustomParam_float_values); -extern RPR_API_ENTRY int rprsImport(char const * rprsFileName, void * context, void * materialSystem, void * * scene, bool useAlreadyExistingScene); -extern RPR_API_ENTRY int rprsGetExtraCustomParam_int(char const * name, int * value); -extern RPR_API_ENTRY int rprsGetExtraCustomParam_float(char const * name, float * value); -extern RPR_API_ENTRY int rprsGetExtraCustomParamIndex_int(int index, int * value); -extern RPR_API_ENTRY int rprsGetExtraCustomParamIndex_float(int index, float * value); -extern RPR_API_ENTRY int rprsGetNumberOfExtraCustomParam(); -extern RPR_API_ENTRY int rprsGetExtraCustomParamNameSize(int index, int * nameSizeGet); -extern RPR_API_ENTRY int rprsGetExtraCustomParamName(int index, char * nameGet, int nameGetSize); -extern RPR_API_ENTRY int rprsGetExtraCustomParamType(int index); -extern RPR_API_ENTRY int rprsListImportedCameras(void * * Cameras, int sizeCameraBytes, int * numberOfCameras); -extern RPR_API_ENTRY int rprsListImportedMaterialNodes(void * * MaterialNodes, int sizeMaterialNodeBytes, int * numberOfMaterialNodes); -extern RPR_API_ENTRY int rprsListImportedLights(void * * Lights, int sizeLightBytes, int * numberOfLights); -extern RPR_API_ENTRY int rprsListImportedShapes(void * * Shapes, int sizeShapeBytes, int * numberOfShapes); -extern RPR_API_ENTRY int rprsListImportedImages(void * * Images, int sizeImageBytes, int * numberOfImages); -extern RPR_API_ENTRY int rprsExportCustomList(char const * rprsFileName, int materialNode_number, void** materialNode_list, int camera_number, void** camera_list, int light_number, void** light_list, int shape_number, void** shape_list, int image_number, void** image_list); -extern RPR_API_ENTRY int rprsImportCustomList(char const * rprsFileName, void * context, void * materialSystem, int* materialNode_number, void** materialNode_list, int* camera_number, void** camera_list, int* light_number, void** light_list, int* shape_number, void** shape_list, int* image_number, void** image_list); -/***************compatibility part***************/ -#define FRLOADSTORE_PARAMETER_TYPE_UNDEF 0x0 -#define FRLOADSTORE_PARAMETER_TYPE_INT 0x1 -#define FRLOADSTORE_PARAMETER_TYPE_FLOAT 0x2 -extern RPR_API_ENTRY int frsExport(char const * frsFileName, void * context, void * scene, int extraCustomParam_int_number, char const * * extraCustomParam_int_names, int const * extraCustomParam_int_values, int extraCustomParam_float_number, char const * * extraCustomParam_float_names, float const * extraCustomParam_float_values); -extern RPR_API_ENTRY int frsImport(char const * frsFileName, void * context, void * materialSystem, void * * scene, bool useAlreadyExistingScene); -extern RPR_API_ENTRY int frsGetExtraCustomParam_int(char const * name, int * value); -extern RPR_API_ENTRY int frsGetExtraCustomParam_float(char const * name, float * value); -extern RPR_API_ENTRY int frsGetExtraCustomParamIndex_int(int index, int * value); -extern RPR_API_ENTRY int frsGetExtraCustomParamIndex_float(int index, float * value); -extern RPR_API_ENTRY int frsGetNumberOfExtraCustomParam(); -extern RPR_API_ENTRY int frsGetExtraCustomParamNameSize(int index, int * nameSizeGet); -extern RPR_API_ENTRY int frsGetExtraCustomParamName(int index, char * nameGet, int nameGetSize); -extern RPR_API_ENTRY int frsGetExtraCustomParamType(int index); -extern RPR_API_ENTRY int frsListImportedCameras(void * * Cameras, int sizeCameraBytes, int * numberOfCameras); -extern RPR_API_ENTRY int frsListImportedMaterialNodes(void * * MaterialNodes, int sizeMaterialNodeBytes, int * numberOfMaterialNodes); -extern RPR_API_ENTRY int frsListImportedLights(void * * Lights, int sizeLightBytes, int * numberOfLights); -extern RPR_API_ENTRY int frsListImportedShapes(void * * Shapes, int sizeShapeBytes, int * numberOfShapes); -extern RPR_API_ENTRY int frsListImportedImages(void * * Images, int sizeImageBytes, int * numberOfImages); -extern RPR_API_ENTRY int frsExportCustomList(char const * frsFileName, int materialNode_number, void** materialNode_list, int camera_number, void** camera_list, int light_number, void** light_list, int shape_number, void** shape_list, int image_number, void** image_list); -extern RPR_API_ENTRY int frsImportCustomList(char const * frsFileName, void * context, void * materialSystem, int* materialNode_number, void** materialNode_list, int* camera_number, void** camera_list, int* light_number, void** light_list, int* shape_number, void** shape_list, int* image_number, void** image_list); - -#ifdef __cplusplus -} -#endif - -#endif /*__RPRLOADSTORE_H */ diff --git a/RprLoadStore/RprLoadStore.lua b/RprLoadStore/RprLoadStore.lua deleted file mode 100644 index 3d028de5..00000000 --- a/RprLoadStore/RprLoadStore.lua +++ /dev/null @@ -1,32 +0,0 @@ -project "RprLoadStore" - kind "SharedLib" - location "../RprLoadStore" - links {"RadeonRays", "CLW", "Calc", "Rpr",} - files { "../RprLoadStore/**.h", "../RprLoadStore/**.cpp", "../RprLoadStore/**.hpp" , "../RprLoadStore/**.cl" ,"../RprLoadStore/**.def"} - configuration "x32" --- libdirs { os.getenv("AMDAPPSDKROOT").."lib/x86"} - configuration "x64" --- libdirs { os.getenv("AMDAPPSDKROOT").."lib/x86_64"} - configuration {} -- back to all configurations. - if( os.is("windows") ) then - linkoptions { '/DEF:"RprLoadStore.def"' } - end - - if( os.is("linux") ) then - buildoptions { '-std=c++0x' } - end - - if os.is("macosx") then - buildoptions "-std=c++11 -stdlib=libc++" - end - - configuration {"x32", "Debug"} - targetdir "../Bin/Debug/x86" - configuration {"x64", "Debug"} - targetdir "../Bin/Debug/x64" - configuration {"x32", "Release"} - targetdir "../Bin/Release/x86" - configuration {"x64", "Release"} - targetdir "../Bin/Release/x64" - configuration {} - diff --git a/RprLoadStore/Wrap.cpp b/RprLoadStore/Wrap.cpp deleted file mode 100644 index 8366d519..00000000 --- a/RprLoadStore/Wrap.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "RprLoadStore.h" - -int frsExport(char const * rprsFileName, void * context, void * scene, int extraCustomParam_int_number, char const * * extraCustomParam_int_names, int const * extraCustomParam_int_values, int extraCustomParam_float_number, char const * * extraCustomParam_float_names, float const * extraCustomParam_float_values) -{ - return rprsExport(rprsFileName, context, scene, extraCustomParam_int_number, extraCustomParam_int_names, extraCustomParam_int_values, extraCustomParam_float_number, extraCustomParam_float_names, extraCustomParam_float_values); -} - -int frsImport(char const * rprsFileName, void * context, void * materialSystem, void * * scene, bool useAlreadyExistingScene) -{ - return rprsImport(rprsFileName, context, materialSystem, scene, useAlreadyExistingScene); -} - -int frsGetExtraCustomParam_int(char const * name, int * value) -{ - return rprsGetExtraCustomParam_int(name, value); -} - -int frsGetExtraCustomParam_float(char const * name, float * value) -{ - return rprsGetExtraCustomParam_float(name, value); -} - -int frsGetExtraCustomParamIndex_int(int index, int * value) -{ - return rprsGetExtraCustomParamIndex_int(index, value); -} - -int frsGetExtraCustomParamIndex_float(int index, float * value) -{ - return rprsGetExtraCustomParamIndex_float(index, value); -} - -int frsGetNumberOfExtraCustomParam() -{ - return rprsGetNumberOfExtraCustomParam(); -} - -int frsGetExtraCustomParamNameSize(int index, int * nameSizeGet) -{ - return rprsGetExtraCustomParamNameSize(index, nameSizeGet); -} - -int frsGetExtraCustomParamName(int index, char * nameGet, int nameGetSize) -{ - return rprsGetExtraCustomParamName(index, nameGet, nameGetSize); -} - -int frsGetExtraCustomParamType(int index) -{ - return rprsGetExtraCustomParamType(index); -} - -int frsListImportedCameras(void * * Cameras, int sizeCameraBytes, int * numberOfCameras) -{ - return rprsListImportedCameras(Cameras, sizeCameraBytes, numberOfCameras); -} - -int frsListImportedMaterialNodes(void * * MaterialNodes, int sizeMaterialNodeBytes, int * numberOfMaterialNodes) -{ - return rprsListImportedMaterialNodes(MaterialNodes, sizeMaterialNodeBytes, numberOfMaterialNodes); -} - -int frsListImportedLights(void * * Lights, int sizeLightBytes, int * numberOfLights) -{ - return rprsListImportedLights(Lights, sizeLightBytes, numberOfLights); -} - -int frsListImportedShapes(void * * Shapes, int sizeShapeBytes, int * numberOfShapes) -{ - return rprsListImportedShapes(Shapes, sizeShapeBytes, numberOfShapes); -} - -int frsListImportedImages(void * * Images, int sizeImageBytes, int * numberOfImages) -{ - return rprsListImportedImages(Images, sizeImageBytes, numberOfImages); -} - -int frsExportCustomList(char const * rprsFileName, int materialNode_number, void** materialNode_list, int camera_number, void** camera_list, int light_number, void** light_list, int shape_number, void** shape_list, int image_number, void** image_list) -{ - return rprsExportCustomList(rprsFileName, materialNode_number, materialNode_list, camera_number, camera_list, light_number, light_list, shape_number, shape_list, image_number, image_list); -} - -int frsImportCustomList(char const * rprsFileName, void * context, void * materialSystem, int* materialNode_number, void** materialNode_list, int* camera_number, void** camera_list, int* light_number, void** light_list, int* shape_number, void** shape_list, int* image_number, void** image_list) -{ - return rprsImportCustomList(rprsFileName, context, materialSystem, materialNode_number, materialNode_list, camera_number, camera_list, light_number, light_list, shape_number, shape_list, image_number, image_list); -} - diff --git a/RprLoadStore/common.h b/RprLoadStore/common.h deleted file mode 100644 index f3a34baa..00000000 --- a/RprLoadStore/common.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef frLoadStore_common_H_ -#define frLoadStore_common_H_ - -#include - -struct RPS_OBJECT_DECLARED -{ - int32_t id; - - // "fr_shape" or "fr_image" ...etc... - // or - // "rpr_shape" or "rpr_image" ...etc... - std::string type; - - - void* obj; // corresponds to rpr_shape or rpr_image ...etc... -}; - -#endif \ No newline at end of file diff --git a/RprLoadStore/frs6.cpp b/RprLoadStore/frs6.cpp deleted file mode 100644 index e362b137..00000000 --- a/RprLoadStore/frs6.cpp +++ /dev/null @@ -1,2107 +0,0 @@ -#include -#include -#include -#include "frs6.h" - - -#define CHECK_STATUS_RETURNERROR { if (status != RPR_SUCCESS) { ErrorDetected(); return status; } } -#define CHECK_STATUS_RETURNNULL { if (status != RPR_SUCCESS) { ErrorDetected(); return 0; } } - -int32_t const FRS6::m_SHAPE_BEG = 0x0AB000001; -int32_t const FRS6::m_SHAPE_END = 0x0AB000002; -int32_t const FRS6::m_CAMERA_BEG = 0x0AB000003; -int32_t const FRS6::m_CAMERA_END = 0x0AB000004; -int32_t const FRS6::m_LIGHT_BEG = 0x0AB000005; -int32_t const FRS6::m_LIGHT_END = 0x0AB000006; -int32_t const FRS6::m_SHADER_BEG = 0x0AB000007; -int32_t const FRS6::m_SHADER_END = 0x0AB000008; -int32_t const FRS6::m_SCENE_BEG = 0x0AB000009; -int32_t const FRS6::m_SCENE_END = 0x0AB00000A; -int32_t const FRS6::m_CONTEXT_BEG = 0x0AB00000B; -int32_t const FRS6::m_CONTEXT_END = 0x0AB00000C; -int32_t const FRS6::m_EVERYTHING_BEG = 0x0AB00000D; -int32_t const FRS6::m_EVERYTHING_END = 0x0AB00000E; -int32_t const FRS6::m_IMAGE_BEG = 0x0AB00000F; -int32_t const FRS6::m_IMAGE_END = 0x0AB000010; -int32_t const FRS6::m_3DSDATA_BEG = 0x0AB000011; -int32_t const FRS6::m_3DSDATA_END = 0x0AB000012; - -std::vector FRS6::m_shapeList; -std::vector FRS6::m_imageList; - -int32_t FRS6::m_fileVersionOfLoadFile = 0; - -char const FRS6::m_HEADER_CHECKCODE[4] = {'F','R','S','F'}; // "FRSF" = FireRenderSceneFile - -// history of changes : -// version 02 : first -// version 03 : add shadow flag -// version 04 : add LOADER_DATA_FROM_3DS -// version 05 : (07 jan 2016) new material system -// version 06 : (25 feb 2016) add more data inside LOADER_DATA_FROM_3DS + possibility to save if no camera in scene. note that version 6 can import version 5 -int32_t const FRS6::m_FILE_VERSION = 0x00000006; - -rpr_int FRS6::StoreCamera(rpr_camera camera, std::ofstream *myfile) -{ - - myfile->write((const char*)&m_CAMERA_BEG, sizeof(m_CAMERA_BEG)); - - - rpr_int status = RPR_SUCCESS; - - float param_fstop; - status = rprCameraGetInfo(camera, RPR_CAMERA_FSTOP, sizeof(param_fstop), ¶m_fstop, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)¶m_fstop, sizeof(param_fstop)); - - //status = rprCameraGetInfo(camera, RPR_CAMERA_TRANSFORM, sizeof(float)* 16, ¶m, NULL); - //CHECK_STATUS_RETURNERROR; - //myfile->write(param, sizeof(float) * 16); - - unsigned int param_apblade; - status = rprCameraGetInfo(camera, RPR_CAMERA_APERTURE_BLADES, sizeof(unsigned int), ¶m_apblade, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)¶m_apblade, sizeof(unsigned int)); - - float param_camexpo; - status = rprCameraGetInfo(camera, RPR_CAMERA_EXPOSURE, sizeof(param_camexpo), ¶m_camexpo, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)¶m_camexpo, sizeof(param_camexpo)); - - float param_focalLen; - status = rprCameraGetInfo(camera, RPR_CAMERA_FOCAL_LENGTH, sizeof(param_focalLen), ¶m_focalLen, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)¶m_focalLen, sizeof(param_focalLen)); - - float param_sensorsize[2]; - status = rprCameraGetInfo(camera, RPR_CAMERA_SENSOR_SIZE, sizeof(param_sensorsize), ¶m_sensorsize, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)¶m_sensorsize, sizeof(param_sensorsize)); - - rpr_camera_mode param_mode; - status = rprCameraGetInfo(camera, RPR_CAMERA_MODE, sizeof(param_mode), ¶m_mode, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)¶m_mode, sizeof(param_mode)); - - float param_orthowidth; - status = rprCameraGetInfo(camera, RPR_CAMERA_ORTHO_WIDTH, sizeof(param_orthowidth), ¶m_orthowidth, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)¶m_orthowidth, sizeof(param_orthowidth)); - - float param_orthoheight; - status = rprCameraGetInfo(camera, RPR_CAMERA_ORTHO_HEIGHT, sizeof(param_orthoheight), ¶m_orthoheight, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)¶m_orthoheight, sizeof(param_orthoheight)); - - float param_focusdist; - status = rprCameraGetInfo(camera, RPR_CAMERA_FOCUS_DISTANCE, sizeof(param_focusdist), ¶m_focusdist, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)¶m_focusdist, sizeof(param_focusdist)); - - rpr_float param_pos[3]; - status = rprCameraGetInfo(camera, RPR_CAMERA_POSITION, sizeof(param_pos), ¶m_pos, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)param_pos, sizeof(param_pos)); - - rpr_float param_at[3]; - status = rprCameraGetInfo(camera, RPR_CAMERA_LOOKAT, sizeof(param_at), ¶m_at, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)param_at, sizeof(param_at)); - - rpr_float param_up[3]; - status = rprCameraGetInfo(camera, RPR_CAMERA_UP, sizeof(param_up), ¶m_up, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)param_up, sizeof(param_up)); - - myfile->write((const char*)&m_CAMERA_END, sizeof(m_CAMERA_END)); - - - return RPR_SUCCESS; -} - -rpr_camera FRS6::LoadCamera(rpr_context context, std::istream *myfile) -{ - rpr_int status = RPR_SUCCESS; - //uint64_t param_length = 0; - - int32_t checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_CAMERA_BEG) - { - ErrorDetected(); - return 0; - } - - - rpr_camera camera = NULL; - status = rprContextCreateCamera(context, &camera); - CHECK_STATUS_RETURNNULL; - - float param_fstop; - myfile->read((char*)¶m_fstop, sizeof(param_fstop)); - status = rprCameraSetFStop(camera, param_fstop); - CHECK_STATUS_RETURNNULL; - - unsigned int param_apblade; - myfile->read((char*)¶m_apblade, sizeof(param_apblade)); - status = rprCameraSetApertureBlades(camera, param_apblade); - CHECK_STATUS_RETURNNULL; - - float param_camexpo; - myfile->read((char*)¶m_camexpo, sizeof(param_camexpo)); - status = rprCameraSetExposure(camera, param_camexpo); - CHECK_STATUS_RETURNNULL; - - float param_focalLen; - myfile->read((char*)¶m_focalLen, sizeof(param_focalLen)); - status = rprCameraSetFocalLength(camera, param_focalLen); - CHECK_STATUS_RETURNNULL; - - float param_sensorsize[2]; - myfile->read((char*)¶m_sensorsize, sizeof(param_sensorsize)); - status = rprCameraSetSensorSize(camera, (float)param_sensorsize[0], (float)param_sensorsize[1]); - CHECK_STATUS_RETURNNULL; - - rpr_camera_mode param_mode; - myfile->read((char*)¶m_mode, sizeof(param_mode)); - status = rprCameraSetMode(camera, param_mode); - CHECK_STATUS_RETURNNULL; - - float param_orthowidth; - myfile->read((char*)¶m_orthowidth, sizeof(param_orthowidth)); - status = rprCameraSetOrthoWidth(camera, param_orthowidth); - CHECK_STATUS_RETURNNULL; - - float param_focusdist; - myfile->read((char*)¶m_focusdist, sizeof(param_focusdist)); - status = rprCameraSetFocusDistance(camera, param_focusdist); - CHECK_STATUS_RETURNNULL; - - float param_position[3]; - myfile->read((char*)¶m_position, sizeof(param_position)); - float param_lookat[3]; - myfile->read((char*)¶m_lookat, sizeof(param_lookat)); - float param_up[3]; - myfile->read((char*)¶m_up, sizeof(param_up)); - status = rprCameraLookAt(camera, - param_position[0], param_position[1], param_position[2], - param_lookat[0], param_lookat[1], param_lookat[2], - param_up[0], param_up[1], param_up[2]); - CHECK_STATUS_RETURNNULL; - - - checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_CAMERA_END) - { - ErrorDetected(); - return 0; - } - - - return camera; -} - - - -/* -rpr_int FRS6::StoreShader(rpr_material_node shader, std::ofstream *myfile) -{ - - - rpr_int status = RPR_SUCCESS; - //uint64_t param_length = 0; - //char param[4096]; - - myfile->write((const char*)&m_SHADER_BEG, sizeof(m_SHADER_BEG)); - - fr_shader_type shaderType = 0; - status = frShaderGetInfo(shader, FR_SHADER_TYPE, sizeof(shaderType), &shaderType, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&shaderType, sizeof(shaderType)); - - - // name is not implemented - // - //uint64_t shaderName_lenght = 0; - //status = frShaderGetInfo(shader, FR_SHADER_NAME, 0, NULL, &shaderName_lenght); - //CHECK_STATUS_RETURNERROR; - //char* shaderName = new char[shaderName_lenght]; - //status = frShaderGetInfo(shader, FR_SHADER_NAME, shaderName_lenght, shaderName, NULL); - //CHECK_STATUS_RETURNERROR; - //myfile->write((char*)&shaderName_lenght, sizeof(shaderName_lenght)); - //myfile->write((char*)shaderName, shaderName_lenght); - //delete[] shaderName; shaderName = NULL; - // - - uint64_t shaderParameterCount = 0; - status = frShaderGetInfo(shader, FR_SHADER_PARAMETER_COUNT, sizeof(shaderParameterCount), &shaderParameterCount, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&shaderParameterCount, sizeof(shaderParameterCount)); - - - for (int i = 0; i < shaderParameterCount; i++) - { - - uint64_t shaderParameterName_lenght = 0; - status = frShaderGetParameterInfo(shader, i, RPR_PARAMETER_NAME, 0, NULL, &shaderParameterName_lenght); - CHECK_STATUS_RETURNERROR; - char* shaderParameterName = new char[shaderParameterName_lenght]; - status = frShaderGetParameterInfo(shader, i, RPR_PARAMETER_NAME, shaderParameterName_lenght, shaderParameterName, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&shaderParameterName_lenght, sizeof(shaderParameterName_lenght)); - myfile->write((char*)shaderParameterName, shaderParameterName_lenght); - - rpr_parameter_type paramType; - status = frShaderGetParameterInfo(shader, i, RPR_PARAMETER_TYPE, sizeof(paramType), ¶mType, NULL); - myfile->write((char*)¶mType, sizeof(paramType)); - CHECK_STATUS_RETURNERROR; - - - uint64_t shaderParameterValue_lenght = 0; - status = frShaderGetParameterInfo(shader, i, RPR_PARAMETER_VALUE, 0, NULL, &shaderParameterValue_lenght); - CHECK_STATUS_RETURNERROR; - char* shaderParameterValue = new char[shaderParameterValue_lenght]; - status = frShaderGetParameterInfo(shader, i, RPR_PARAMETER_VALUE, shaderParameterValue_lenght, shaderParameterValue, NULL); - CHECK_STATUS_RETURNERROR; - - if (paramType == RPR_PARAMETER_TYPE_IMAGE) - { - if (shaderParameterValue_lenght != sizeof(rpr_image)) - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - rpr_image* img = (rpr_image*)shaderParameterValue; - if (*img != 0) - { - int32_t imageYes = 1; - myfile->write((char*)&imageYes, sizeof(imageYes)); - status = StoreImage(*img, myfile); - CHECK_STATUS_RETURNERROR; - } - else - { - int32_t imageNo = 0; - myfile->write((char*)&imageNo, sizeof(imageNo)); - } - } - else if (RPR_PARAMETER_TYPE_SHADER == paramType) - { - if (shaderParameterValue_lenght != sizeof(rpr_material_node)) - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - else - { - rpr_material_node* shader = (rpr_material_node*)shaderParameterValue; - status = StoreShader(*shader, myfile); - CHECK_STATUS_RETURNERROR; - } - } - else - { - myfile->write((char*)&shaderParameterValue_lenght, sizeof(shaderParameterValue_lenght)); - myfile->write((char*)shaderParameterValue, shaderParameterValue_lenght); - } - - - //don't need description in store file - // - //uint64_t shaderParameterDescription_lenght = 0; - //status = frShaderGetParameterInfo(shader, i, FR_SHADER_PARAMETER_DESCRIPTION, 0, NULL, &shaderParameterDescription_lenght); - //CHECK_STATUS_RETURNERROR; - //char* shaderParameterDescription = new char[shaderParameterDescription_lenght]; - //status = frShaderGetParameterInfo(shader, i, FR_SHADER_PARAMETER_DESCRIPTION, shaderParameterDescription_lenght, shaderParameterDescription, NULL); - //CHECK_STATUS_RETURNERROR; - //myfile->write((char*)&shaderParameterDescription_lenght, sizeof(shaderParameterDescription_lenght)); - //myfile->write((char*)shaderParameterDescription, shaderParameterDescription_lenght); - //delete[] shaderParameterDescription; shaderParameterDescription = NULL; - - - delete[] shaderParameterName; shaderParameterName = NULL; - delete[] shaderParameterValue; shaderParameterValue = NULL; - - } - - myfile->write((const char*)&m_SHADER_END, sizeof(m_SHADER_END)); - - - - - return RPR_SUCCESS; - - // extern RPR_API_ENTRY rpr_int frShaderGetParameterImagePath(rpr_material_node shader, const rpr_char* parameter, const rpr_char* image_path); - -} -*/ - - -/* -rpr_material_node FRS6::LoadShader(rpr_context context, std::istream *myfile) -{ - rpr_int status = RPR_SUCCESS; - - int32_t checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_SHADER_BEG) - { - return 0; - } - - - fr_shader_type shaderType; - myfile->read((char*)&shaderType, sizeof(fr_shader_type)); //SHADER_TYPE - rpr_material_node shader = rprContextCreateShader(context, shaderType, &status); - CHECK_STATUS_RETURNNULL; - - - uint64_t nbParameters; - myfile->read((char*)&nbParameters, sizeof(nbParameters)); //SHADER_PARAMETER_COUNT - for (int i = 0; i < nbParameters; i++) - { - uint64_t paramName_length = 0; - myfile->read((char*)¶mName_length, sizeof(paramName_length)); - char* paramName_data = new char[paramName_length]; - myfile->read((char*)paramName_data, paramName_length); - - rpr_parameter_type paramType; - myfile->read((char*)¶mType, sizeof(paramType)); - - - - if (paramType == RPR_PARAMETER_TYPE_IMAGE) - { - int32_t imageExist = 0; - myfile->read((char*)&imageExist, sizeof(imageExist)); - if (imageExist == 1) - { - rpr_image newImage = LoadImage(context, myfile); - if (newImage == 0) - { - return 0; - } - status = frShaderSetParameterImage(shader, paramName_data, newImage); - CHECK_STATUS_RETURNNULL; - } - } - else if (paramType == RPR_PARAMETER_TYPE_SHADER) - { - rpr_material_node newShader = LoadShader(context, myfile); - if (newShader == 0) - { - return 0; - } - status = frShaderSetParameterShader(shader, paramName_data, newShader); - CHECK_STATUS_RETURNNULL; - } - else - { - uint64_t value_length = 0; - myfile->read((char*)&value_length, sizeof(value_length)); - char* value_data = new char[value_length]; - myfile->read(value_data, value_length); - - - - if (paramType == RPR_PARAMETER_TYPE_FLOAT) - { - float* value_data_float = (float*)value_data; - - if (value_length == sizeof(float) * 1) - { - status = frShaderSetParameter1f(shader, paramName_data, value_data_float[0]); - CHECK_STATUS_RETURNNULL - } - else - { - return 0; - } - } - else if (paramType == RPR_PARAMETER_TYPE_FLOAT2) - { - float* value_data_float = (float*)value_data; - - if (value_length == sizeof(float) * 2) - { - status = frShaderSetParameter2f(shader, paramName_data, value_data_float[0], value_data_float[1]); - CHECK_STATUS_RETURNNULL - } - else - { - return 0; - } - } - else if (paramType == RPR_PARAMETER_TYPE_FLOAT3) - { - float* value_data_float = (float*)value_data; - - if (value_length == sizeof(float) * 3) - { - status = frShaderSetParameter3f(shader, paramName_data, value_data_float[0], value_data_float[1], value_data_float[2]); - CHECK_STATUS_RETURNNULL - } - else - { - return 0; - } - } - else if (paramType == RPR_PARAMETER_TYPE_FLOAT4) - { - float* value_data_float = (float*)value_data; - - if (value_length == sizeof(float) * 4) - { - status = frShaderSetParameter4f(shader, paramName_data, value_data_float[0], value_data_float[1], value_data_float[2], value_data_float[3]); - CHECK_STATUS_RETURNNULL - } - else - { - return 0; - } - - } - else if (paramType == RPR_PARAMETER_TYPE_STRING) - { - status = frShaderSetParameterImagePath(shader, paramName_data, value_data); - CHECK_STATUS_RETURNNULL; - } - else - { - return 0; - } - - - - delete[] paramName_data; paramName_data = NULL; - delete[] value_data; value_data = NULL; - } - - - - } - - - checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_SHADER_END) - { - return 0; - } - - return shader; - - - - - //return 0; -} -*/ - - - - - - -rpr_int FRS6::StoreShape(rpr_shape shape, std::ofstream *myfile) -{ - rpr_int status = RPR_SUCCESS; - - myfile->write((const char*)&m_SHAPE_BEG, sizeof(m_SHAPE_BEG)); - - rpr_shape_type type; - status = rprShapeGetInfo(shape, RPR_SHAPE_TYPE, sizeof(rpr_shape_type), &type, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)&type, sizeof(rpr_shape_type)); - - if ( - type == RPR_SHAPE_TYPE_MESH - ) - { - - m_shapeList.push_back(shape); - - - uint64_t poly_count = 0; - status = rprMeshGetInfo(shape, RPR_MESH_POLYGON_COUNT, sizeof(poly_count), &poly_count, NULL); //number of primitives - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&poly_count, sizeof(uint64_t)); - - uint64_t vertex_count = 0; - status = rprMeshGetInfo(shape, RPR_MESH_VERTEX_COUNT, sizeof(vertex_count), &vertex_count, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&vertex_count, sizeof(uint64_t)); - - uint64_t normal_count = 0; - status = rprMeshGetInfo(shape, RPR_MESH_NORMAL_COUNT, sizeof(normal_count), &normal_count, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&normal_count, sizeof(uint64_t)); - - uint64_t uv_count = 0; - status = rprMeshGetInfo(shape, RPR_MESH_UV_COUNT, sizeof(uv_count), &uv_count, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&uv_count, sizeof(uint64_t)); - - - - if (vertex_count) - { - size_t required_size_size_t = 0; - status = rprMeshGetInfo(shape, RPR_MESH_VERTEX_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - float* data = new float[required_size / sizeof(float)]; - status = rprMeshGetInfo(shape, RPR_MESH_VERTEX_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&required_size, sizeof(required_size)); - myfile->write((const char*)data, required_size); - delete[] data; data = NULL; - } - if (normal_count) - { - size_t required_size_size_t = 0; - status = rprMeshGetInfo(shape, RPR_MESH_NORMAL_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - float* data = new float[required_size / sizeof(float)]; - status = rprMeshGetInfo(shape, RPR_MESH_NORMAL_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&required_size, sizeof(required_size)); - myfile->write((const char*)data, required_size); - delete[] data; data = NULL; - } - if (uv_count) - { - size_t required_size_size_t = 0; - status = rprMeshGetInfo(shape, RPR_MESH_UV_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - float* data = new float[required_size / sizeof(float)]; - status = rprMeshGetInfo(shape, RPR_MESH_UV_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&required_size, sizeof(required_size)); - myfile->write((const char*)data, required_size); - delete[] data; - data = NULL; - - } - if (poly_count) - { - size_t required_size_size_t = 0; - status = rprMeshGetInfo(shape, RPR_MESH_VERTEX_INDEX_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - float* data = new float[required_size / sizeof(float)]; - status = rprMeshGetInfo(shape, RPR_MESH_VERTEX_INDEX_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&required_size, sizeof(required_size)); - myfile->write((const char*)data, required_size); - delete[] data; data = NULL; - - } - if (normal_count) - { - size_t required_size_size_t = 0; - status = rprMeshGetInfo(shape, RPR_MESH_NORMAL_INDEX_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - float* data = new float[required_size / sizeof(float)]; - status = rprMeshGetInfo(shape, RPR_MESH_NORMAL_INDEX_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&required_size, sizeof(required_size)); - myfile->write((const char*)data, required_size); - delete[] data; data = NULL; - - } - if (uv_count) - { - size_t required_size_size_t = 0; - status = rprMeshGetInfo(shape, RPR_MESH_UV_INDEX_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - float* data = new float[required_size / sizeof(float)]; - status = rprMeshGetInfo(shape, RPR_MESH_UV_INDEX_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&required_size, sizeof(required_size)); - myfile->write((const char*)data, required_size); - delete[] data; data = NULL; - - } - if (poly_count) - { - size_t required_size_size_t = 0; - status = rprMeshGetInfo(shape, RPR_MESH_NUM_FACE_VERTICES_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - float* data = new float[required_size / sizeof(float)]; - status = rprMeshGetInfo(shape, RPR_MESH_NUM_FACE_VERTICES_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&required_size, sizeof(required_size)); - myfile->write((const char*)data, required_size); - delete[] data; data = NULL; - - } - - } - else if (type == RPR_SHAPE_TYPE_INSTANCE) - { - //search address of original shape - - rpr_shape shapeOriginal = NULL; - status = rprInstanceGetBaseShape(shape, &shapeOriginal); - CHECK_STATUS_RETURNERROR; - - if (shapeOriginal == 0) - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - - bool found = false; - for (int iShape = 0; iShape < m_shapeList.size(); iShape++) - { - if (m_shapeList[iShape] == shapeOriginal) - { - int32_t indexShapeBase = iShape; - myfile->write((const char*)&indexShapeBase, sizeof(indexShapeBase)); - found = true; - break; - } - } - - if (!found) - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - - } - - - rpr_material_node data_shader = 0; - status = rprShapeGetInfo(shape, RPR_SHAPE_MATERIAL, sizeof(data_shader), &data_shader, NULL); - CHECK_STATUS_RETURNERROR; - if (data_shader) - { - int32_t _true = 1; - myfile->write((const char*)&_true, sizeof(_true)); - } - else - { - int32_t _false = 0; - myfile->write((const char*)&_false, sizeof(_false)); - } - if (data_shader != NULL) - { - rpr_int error = StoreShader(data_shader, myfile); - if (error != RPR_SUCCESS) - { - return error; - } - } - - - float data_transform[16]; - status = rprShapeGetInfo(shape, RPR_SHAPE_TRANSFORM, sizeof(data_transform), data_transform, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)data_transform, sizeof(data_transform)); - - - float data_linMotion[3]; - status = rprShapeGetInfo(shape, RPR_SHAPE_LINEAR_MOTION, sizeof(data_linMotion) , data_linMotion, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)data_linMotion, sizeof(data_linMotion)); - - float data_angMotion[4]; - status = rprShapeGetInfo(shape, RPR_SHAPE_ANGULAR_MOTION, sizeof(data_angMotion) , data_angMotion, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)data_angMotion, sizeof(data_angMotion)); - - rpr_bool data_visFlag; - status = rprShapeGetInfo(shape, RPR_SHAPE_VISIBILITY_FLAG, sizeof(data_visFlag), &data_visFlag, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)&data_visFlag, sizeof(data_visFlag)); - - rpr_bool data_shadoflag; - status = rprShapeGetInfo(shape, RPR_SHAPE_SHADOW_FLAG, sizeof(data_shadoflag), &data_shadoflag, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((const char*)&data_shadoflag, sizeof(data_shadoflag)); - - myfile->write((const char*)&m_SHAPE_END, sizeof(m_SHAPE_END)); - - return RPR_SUCCESS; -} - -rpr_shape FRS6::LoadShape(rpr_context context, rpr_material_system materialSystem, std::istream *myfile ) -{ - rpr_int status = RPR_SUCCESS; - - rpr_shape shape = NULL; - - - int32_t checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_SHAPE_BEG) - { - ErrorDetected(); - return 0; - } - - rpr_shape_type shapeType; - myfile->read((char*)&shapeType, sizeof(shapeType)); - - uint64_t sizePositionBufferByte = 0; - uint64_t sizeNormalBufferByte = 0; - uint64_t sizeUVBufferByte = 0; - - if (shapeType == RPR_SHAPE_TYPE_MESH) - { - uint64_t poly_count = NULL; - uint64_t vertex_count = NULL; - uint64_t normal_count = NULL; - uint64_t uv_count = NULL; - - rpr_float* vertices = NULL; - rpr_float* normals = NULL; - rpr_float* texcoords = NULL; - rpr_int* vertex_indices = NULL; - rpr_int* normal_indices = NULL; - rpr_int* texcoord_indices = NULL; - rpr_int* num_face_vertices = NULL; - - - myfile->read((char*)&poly_count, sizeof(uint64_t)); - myfile->read((char*)&vertex_count, sizeof(uint64_t)); - myfile->read((char*)&normal_count, sizeof(uint64_t)); - myfile->read((char*)&uv_count, sizeof(uint64_t)); - - if (vertex_count) - { - myfile->read((char*)&sizePositionBufferByte, sizeof(uint64_t)); - vertices = new float[sizePositionBufferByte / sizeof(float)]; - myfile->read((char*)vertices, sizePositionBufferByte); - } - if (normal_count) - { - myfile->read((char*)&sizeNormalBufferByte, sizeof(uint64_t)); - normals = new float[sizeNormalBufferByte / sizeof(float)]; - myfile->read((char*)normals, sizeNormalBufferByte); - } - if (uv_count) - { - myfile->read((char*)&sizeUVBufferByte, sizeof(uint64_t)); - texcoords = new float[sizeUVBufferByte / sizeof(float)]; - myfile->read((char*)texcoords, sizeUVBufferByte); - } - if (poly_count) - { - uint64_t required_size; - myfile->read((char*)&required_size, sizeof(uint64_t)); - vertex_indices = new int[required_size / sizeof(int)]; - myfile->read((char*)vertex_indices, required_size); - } - if (normal_count) - { - uint64_t required_size; - myfile->read((char*)&required_size, sizeof(uint64_t)); - normal_indices = new int[required_size / sizeof(int)]; - myfile->read((char*)normal_indices, required_size); - } - if (uv_count) - { - uint64_t required_size; - myfile->read((char*)&required_size, sizeof(uint64_t)); - texcoord_indices = new int[required_size / sizeof(int)]; - myfile->read((char*)texcoord_indices, required_size); - } - if (poly_count) - { - uint64_t required_size; - myfile->read((char*)&required_size, sizeof(uint64_t)); - num_face_vertices = new int[required_size / sizeof(int)]; - myfile->read((char*)num_face_vertices, required_size); - } - - shape = NULL; - status = rprContextCreateMesh(context, - &vertices[0], vertex_count, int(sizePositionBufferByte / vertex_count), - &normals[0], normal_count, int(sizeNormalBufferByte / normal_count), - &texcoords[0], uv_count, int(sizeUVBufferByte / uv_count), - vertex_indices, sizeof(rpr_int), - normal_indices, sizeof(rpr_int), - texcoord_indices, sizeof(rpr_int), - num_face_vertices, poly_count, &shape); - CHECK_STATUS_RETURNNULL; - - m_shapeList.push_back(shape); - - delete[] vertices; vertices = NULL; - delete[] normals; normals = NULL; - delete[] texcoords; texcoords = NULL; - delete[] vertex_indices; vertex_indices = NULL; - delete[] normal_indices; normal_indices = NULL; - delete[] texcoord_indices; texcoord_indices = NULL; - delete[] num_face_vertices; num_face_vertices = NULL; - - } - else if ((rpr_shape_type)shapeType == RPR_SHAPE_TYPE_INSTANCE) - { - int32_t indexShapeOriginal = 0; - myfile->read((char*)&indexShapeOriginal, sizeof(indexShapeOriginal)); - if (indexShapeOriginal >= 0 && indexShapeOriginal < m_shapeList.size()) - { - status = rprContextCreateInstance(context, m_shapeList[indexShapeOriginal], &shape); - CHECK_STATUS_RETURNNULL; - } - else - { - ErrorDetected(); - return 0; - } - - } - - int32_t shaderExist = 0; - myfile->read((char*)&shaderExist, sizeof(shaderExist)); - if (shaderExist != 0) - { - rpr_material_node shader = LoadShader(materialSystem , context, myfile); - if (shader == 0) - { - ErrorDetected(); - return 0; - } - status = rprShapeSetMaterial(shape, shader); - CHECK_STATUS_RETURNNULL - } - - float float16[16]; - myfile->read((char*)float16, sizeof(float16)); - status = rprShapeSetTransform(shape, false, (rpr_float*)float16); - CHECK_STATUS_RETURNNULL - - float linMotion[3]; - myfile->read((char*)linMotion, sizeof(linMotion)); - status = rprShapeSetLinearMotion(shape, linMotion[0], linMotion[1], linMotion[2] ); - CHECK_STATUS_RETURNNULL - - float angMotion[4]; - myfile->read((char*)angMotion, sizeof(angMotion)); - status = rprShapeSetAngularMotion(shape, angMotion[0], angMotion[1], angMotion[2], angMotion[3]); - CHECK_STATUS_RETURNNULL - - rpr_bool visibilityFlag; - myfile->read((char*)&visibilityFlag, sizeof(visibilityFlag)); - status = rprShapeSetVisibility(shape, visibilityFlag); - CHECK_STATUS_RETURNNULL - - rpr_bool shadowFlag; - myfile->read((char*)&shadowFlag, sizeof(shadowFlag)); - status = rprShapeSetShadow(shape, shadowFlag); - CHECK_STATUS_RETURNNULL - - checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_SHAPE_END) - { - ErrorDetected(); - return 0; - } - - return shape; -} - -rpr_int FRS6::StoreLight(rpr_light light, rpr_scene scene, std::ofstream *myfile) -{ - myfile->write((const char*)&m_LIGHT_BEG, sizeof(m_LIGHT_BEG)); - - rpr_int status = RPR_SUCCESS; - //uint64_t param_length = 0; - rpr_light_type type; - - status = rprLightGetInfo(light, RPR_LIGHT_TYPE, sizeof(rpr_light_type), &type, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&type, sizeof(rpr_light_type)); - - - - if (type == RPR_LIGHT_TYPE_POINT) - { - float radian3f[3]; - status = rprLightGetInfo(light, RPR_POINT_LIGHT_RADIANT_POWER, sizeof(radian3f), &radian3f, NULL); - CHECK_STATUS_RETURNERROR; - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&radian3f, sizeof(radian3f)); - } - else if (type == RPR_LIGHT_TYPE_DIRECTIONAL) - { - float radian3f[3]; - status = rprLightGetInfo(light, RPR_DIRECTIONAL_LIGHT_RADIANT_POWER, sizeof(radian3f), &radian3f, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&radian3f, sizeof(radian3f)); - } - else if (type == RPR_LIGHT_TYPE_SPOT) - { - float radian3f[3]; - status = rprLightGetInfo(light, RPR_SPOT_LIGHT_RADIANT_POWER, sizeof(radian3f), &radian3f, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&radian3f, sizeof(radian3f)); - - float coneShape[2]; - status = rprLightGetInfo(light, RPR_SPOT_LIGHT_CONE_SHAPE, sizeof(coneShape), &coneShape, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&coneShape, sizeof(coneShape)); - } - else if (type == RPR_LIGHT_TYPE_ENVIRONMENT) - { - rpr_image image = NULL; - status = rprLightGetInfo(light, RPR_ENVIRONMENT_LIGHT_IMAGE, sizeof(rpr_image), &image, NULL); - CHECK_STATUS_RETURNERROR; - StoreImage((rpr_image)image, myfile); - float intensityScale; - status = rprLightGetInfo(light, RPR_ENVIRONMENT_LIGHT_INTENSITY_SCALE, sizeof(intensityScale), &intensityScale, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&intensityScale, sizeof(intensityScale)); - - - //not used anymore, because rprSceneSetEnvironmentLight replaced by rprSceneAttachLight - int32_t isEnvLight = 0; - myfile->write((const char*)&isEnvLight, sizeof(isEnvLight)); - - } - else - { - return RPR_ERROR_INVALID_PARAMETER; - } - - float lightTransform[16]; - status = rprLightGetInfo(light, RPR_LIGHT_TRANSFORM, sizeof(lightTransform), &lightTransform, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)lightTransform, sizeof(lightTransform)); - - - myfile->write((const char*)&m_LIGHT_END, sizeof(m_LIGHT_END)); - - return RPR_SUCCESS; - -} - -rpr_light FRS6::LoadLight(rpr_context context, rpr_scene scene, std::istream *myfile) -{ - rpr_int status = RPR_SUCCESS; - - rpr_light light = NULL; - - int32_t checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_LIGHT_BEG) - { - ErrorDetected(); - return 0; - } - - - rpr_light_type type = 0; - myfile->read((char*)&type, sizeof(rpr_light_type)); - - - if (type == RPR_LIGHT_TYPE_POINT) - { - light = NULL; - status = rprContextCreatePointLight(context, &light); - CHECK_STATUS_RETURNNULL; - float radian3f[3]; - myfile->read((char*)&radian3f, sizeof(radian3f)); - status = rprPointLightSetRadiantPower3f(light, radian3f[0], radian3f[1], radian3f[2]); - CHECK_STATUS_RETURNNULL; - } - else if (type == RPR_LIGHT_TYPE_DIRECTIONAL) - { - light = NULL; - status = rprContextCreateDirectionalLight(context, &light); - CHECK_STATUS_RETURNNULL; - float radian3f[3]; - myfile->read((char*)&radian3f, sizeof(radian3f)); - status = rprDirectionalLightSetRadiantPower3f(light, radian3f[0], radian3f[1], radian3f[2]); - CHECK_STATUS_RETURNNULL; - } - else if (type == RPR_LIGHT_TYPE_SPOT) - { - light = NULL; - status = rprContextCreateSpotLight(context, &light); - CHECK_STATUS_RETURNNULL; - - float radian3f[3]; - myfile->read((char*)&radian3f, sizeof(radian3f)); - status = rprSpotLightSetRadiantPower3f(light, radian3f[0], radian3f[1], radian3f[2]); - CHECK_STATUS_RETURNNULL; - - float coneShape[2]; - myfile->read((char*)&coneShape, sizeof(coneShape)); - status = rprSpotLightSetConeShape(light, coneShape[0], coneShape[1]); - CHECK_STATUS_RETURNNULL; - } - else if (type == RPR_LIGHT_TYPE_ENVIRONMENT) - { - light = NULL; - status = rprContextCreateEnvironmentLight(context, &light); - CHECK_STATUS_RETURNNULL; - status = rprEnvironmentLightSetImage(light, LoadImage(context, myfile)); - CHECK_STATUS_RETURNNULL; - float intensityScale; - myfile->read((char*)&intensityScale, sizeof(intensityScale)); - status = rprEnvironmentLightSetIntensityScale(light, intensityScale); - CHECK_STATUS_RETURNNULL; - - int32_t isEnvLight = 0; - myfile->read((char*)&isEnvLight, sizeof(isEnvLight)); - if (isEnvLight == 1) - { - // not used anymore because rprSceneSetEnvironmentLight replaced by rprSceneAttachLight - //rprSceneSetEnvironmentLight(scene, light); - } - } - else - { - ErrorDetected(); - return 0; - } - - - - // rpr_light_info - float lightTransform[16]; - myfile->read((char*)&lightTransform, sizeof(lightTransform)); - status = rprLightSetTransform(light, 0, (float*)lightTransform); - CHECK_STATUS_RETURNNULL; - - checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_LIGHT_END) - { - ErrorDetected(); - return 0; - } - - - return light; -} - - -rpr_int FRS6::StoreImage(rpr_image image, std::ofstream *myfile) -{ - - rpr_int status = RPR_SUCCESS; - - myfile->write((const char*)&m_IMAGE_BEG, sizeof(m_IMAGE_BEG)); - - //search if this image is already saved. - auto pos = std::find(m_imageList.begin(), m_imageList.end(), image); - if (pos == m_imageList.end()) - { - //if image not already saved - m_imageList.push_back(image); - int32_t imageIndex = -1; // index = -1 --> means that the image was not already saved prviously - myfile->write((const char*)&imageIndex, sizeof(imageIndex)); - } - else - { - //if image already saved - int32_t imageIndex = (int32_t)(pos - m_imageList.begin()); - myfile->write((const char*)&imageIndex, sizeof(imageIndex)); - myfile->write((const char*)&m_IMAGE_END, sizeof(m_IMAGE_END)); - return RPR_SUCCESS; - } - - - rpr_image_format format; - status = rprImageGetInfo(image, RPR_IMAGE_FORMAT, sizeof(format), &format, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&format, sizeof(rpr_image_format)); - - rpr_image_desc desc; - status = rprImageGetInfo(image, RPR_IMAGE_DESC, sizeof(desc), &desc, NULL); - CHECK_STATUS_RETURNERROR - myfile->write((char*)&desc, sizeof(rpr_image_desc)); - - - size_t size_size_t = 0; - status = rprImageGetInfo(image, RPR_IMAGE_DATA, 0, NULL, &size_size_t); - uint64_t size = size_size_t; - CHECK_STATUS_RETURNERROR - char *idata = new char[size]; - myfile->write((char*)&size, sizeof(uint64_t)); - status = rprImageGetInfo(image, RPR_IMAGE_DATA, size, idata, NULL); - CHECK_STATUS_RETURNERROR - myfile->write(idata, size); - delete[] idata; idata = NULL; - - myfile->write((const char*)&m_IMAGE_END, sizeof(m_IMAGE_END)); - - return status; -} - - -rpr_image FRS6::LoadImage(rpr_context context, std::istream *myfile) -{ - - int32_t checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_IMAGE_BEG) - { - ErrorDetected(); - return 0; - } - - int32_t imageIndex = 0; - myfile->read((char*)&imageIndex, sizeof(imageIndex)); - if (imageIndex == -1) - { - //if the this part of memory is a real image save - - } - else - { - //if this is just an index to an already saved image - - checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_IMAGE_END) - { - ErrorDetected(); - return 0; - } - - return m_imageList[imageIndex]; - } - - - rpr_int status = RPR_SUCCESS; - rpr_image_desc image_desc; - rpr_image_format format; - rpr_image image = NULL; - - myfile->read((char*)&format, sizeof(format)); - myfile->read((char*)&image_desc, sizeof(image_desc)); - - uint64_t size = 0; - myfile->read((char*)&size, sizeof(size)); - char *idata = new char[size]; - myfile->read(idata, size); - - - checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_IMAGE_END) - { - ErrorDetected(); - return 0; - } - - image = NULL; - status = rprContextCreateImage(context, format, &image_desc, idata, &image); - CHECK_STATUS_RETURNNULL; - delete[] idata; idata = NULL; - - m_imageList.push_back(image); - - return image; -} - - -rpr_int FRS6::StoreEverything( - rpr_context context, - rpr_scene scene, - const LOADER_DATA_FROM_3DS* dataFrom3DS, - std::ofstream *myfile - ) -{ - rpr_int status = RPR_SUCCESS; - - // write a wrong check code: the good check code will be written at the end, when we are sure that the generation didn't fail. - char const wrongCheckCode[4] = { '0', '0', '0', '0' }; - myfile->write((const char*)&wrongCheckCode, sizeof(wrongCheckCode)); - - myfile->write((const char*)&m_FILE_VERSION, sizeof(m_FILE_VERSION)); - myfile->write((const char*)&m_EVERYTHING_BEG, sizeof(m_EVERYTHING_BEG)); - status = StoreContext(context, myfile); - if (status != RPR_SUCCESS) { return status; } - status = StoreScene(scene, myfile); - if (status != RPR_SUCCESS) { return status; } - - myfile->write((const char*)&m_3DSDATA_BEG, sizeof(m_3DSDATA_BEG)); - int32_t data3dsStructSize = sizeof(LOADER_DATA_FROM_3DS); - myfile->write((char*)&data3dsStructSize, sizeof(data3dsStructSize)); //since version 6, we enter the size of the struct - if ( dataFrom3DS ) - { - myfile->write((const char*)dataFrom3DS, sizeof(LOADER_DATA_FROM_3DS)); - } - else - { - LOADER_DATA_FROM_3DS emptyData3DS; - memset(&emptyData3DS, 0, sizeof(LOADER_DATA_FROM_3DS)); - emptyData3DS.used = false; // we don't use this data - myfile->write((const char*)&emptyData3DS, sizeof(LOADER_DATA_FROM_3DS)); - } - myfile->write((const char*)&m_3DSDATA_END, sizeof(m_3DSDATA_END)); - - myfile->write((const char*)&m_EVERYTHING_END, sizeof(m_EVERYTHING_END)); - //rewind and write the good check code at the begining of the file. - myfile->seekp(0); - myfile->write((const char*)&m_HEADER_CHECKCODE, sizeof(m_HEADER_CHECKCODE)); - - return RPR_SUCCESS; -} - -rpr_int FRS6::LoadEverything( - rpr_context context, - rpr_material_system materialSystem, - std::istream *myfile, - rpr_scene& scene, - LOADER_DATA_FROM_3DS* dataFrom3DS, - bool useAlreadyExistingScene - ) -{ - - m_fileVersionOfLoadFile = 0; - - rpr_int status = RPR_SUCCESS; - - //check arguments: - if (context == NULL) { return RPR_ERROR_INVALID_PARAMETER; } - if (scene != NULL && !useAlreadyExistingScene ) { return RPR_ERROR_INVALID_PARAMETER; } - if (scene == NULL && useAlreadyExistingScene ) { return RPR_ERROR_INVALID_PARAMETER; } - - char headCheckCode[4] = {0,0,0,0}; - myfile->read(headCheckCode, sizeof(headCheckCode)); - if (headCheckCode[0] != m_HEADER_CHECKCODE[0] || - headCheckCode[1] != m_HEADER_CHECKCODE[1] || - headCheckCode[2] != m_HEADER_CHECKCODE[2] || - headCheckCode[3] != m_HEADER_CHECKCODE[3] ) - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - - myfile->read((char*)&m_fileVersionOfLoadFile, sizeof(m_fileVersionOfLoadFile)); - if (m_fileVersionOfLoadFile < 5 || m_fileVersionOfLoadFile > m_FILE_VERSION) - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - - int32_t checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_EVERYTHING_BEG) - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - - rpr_int succes = LoadContext(context, myfile); - if (succes != RPR_SUCCESS) - { - return succes; - } - - - rpr_scene newScene = LoadScene(context, materialSystem, myfile, useAlreadyExistingScene ? scene : NULL); - if (newScene == 0) - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - - - - checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_3DSDATA_BEG) - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - - - - int32_t data3dsStructSize = 0; - if ( m_fileVersionOfLoadFile >= 6 ) - { - //since version 6, we enter the size of the struct - myfile->read((char*)&data3dsStructSize, sizeof(data3dsStructSize)); - } - else - { - struct LOADER_DATA_FROM_3DS__V4_V5 // old strucure version for V4 and V5 - { - bool used; - float exposure; - bool isNormals; - bool shouldToneMap; - }; - - data3dsStructSize = sizeof(LOADER_DATA_FROM_3DS__V4_V5); - } - - if ( data3dsStructSize > sizeof(LOADER_DATA_FROM_3DS) ) - { - //if the size of the read struct is > than the current size, it's an error - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - - LOADER_DATA_FROM_3DS data3DSFromFile; - memset(&data3DSFromFile,0,sizeof(LOADER_DATA_FROM_3DS)); - char* data3dsStructData = (char*)malloc(data3dsStructSize); - if ( data3dsStructData == NULL ) - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - myfile->read((char*)data3dsStructData, data3dsStructSize); - //memset(dataFrom3DS,0,sizeof(LOADER_DATA_FROM_3DS)); - memcpy(&data3DSFromFile,data3dsStructData,data3dsStructSize); - free(data3dsStructData); data3dsStructData=NULL; - if (dataFrom3DS) - { - memcpy(dataFrom3DS,&data3DSFromFile,data3dsStructSize); - } - - - checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_3DSDATA_END) - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - - - checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_EVERYTHING_END) - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - - if ( !useAlreadyExistingScene ) - { - scene = newScene; - } - - - //overwrite the gamma with the 3dsmax gamma - if ( m_fileVersionOfLoadFile >= 6 && data3DSFromFile.gamma_Enabled ) - { - status = rprContextSetParameter1f(context, "displaygamma", data3DSFromFile.gamma_disp); - CHECK_STATUS_RETURNERROR; - } - - - return RPR_SUCCESS; -} - - -rpr_int FRS6::StoreContext(rpr_context context, std::ofstream *myfile) -{ - - rpr_int status = RPR_SUCCESS; - myfile->write((const char*)&m_CONTEXT_BEG, sizeof(m_CONTEXT_BEG)); - - uint64_t param_count = 0; - status = rprContextGetInfo(context, RPR_CONTEXT_PARAMETER_COUNT, sizeof(uint64_t), ¶m_count, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)¶m_count, sizeof(param_count)); - - - for (int iPass = 0; iPass < 2; iPass++) - { - for (uint64_t i = 0; i < param_count; i++) - { - size_t name_length_size_t = 0; - status = rprContextGetParameterInfo(context, int(i), RPR_PARAMETER_NAME, 0, NULL, &name_length_size_t); - uint64_t name_length = name_length_size_t; - CHECK_STATUS_RETURNERROR; - char* paramName = new char[name_length]; - status = rprContextGetParameterInfo(context, int(i), RPR_PARAMETER_NAME, name_length, paramName, NULL); - CHECK_STATUS_RETURNERROR; - - - //need to store in 2 passes. - //first, we store the parameters that will set several default parameters. - //so we are sure that all custom parameters will be set during the load of context - if ( - (iPass == 0 && (strcmp("imagefilter.type", paramName) == 0 || strcmp("tonemapping.type", paramName) == 0)) - || - (iPass == 1 && strcmp("imagefilter.type", paramName) != 0 && strcmp("tonemapping.type", paramName) != 0) - ) - { - myfile->write((char*)&name_length, sizeof(uint64_t)); - myfile->write(paramName, name_length); - - - rpr_parameter_type type; - status = rprContextGetParameterInfo(context, int(i), RPR_PARAMETER_TYPE, sizeof(type), &type, NULL); - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&type, sizeof(type)); - - - size_t value_length_size_t = 0; - status = rprContextGetParameterInfo(context, int(i), RPR_PARAMETER_VALUE, 0, NULL, &value_length_size_t); - uint64_t value_length = value_length_size_t; - CHECK_STATUS_RETURNERROR; - myfile->write((char*)&value_length, sizeof(value_length)); - - if (value_length > 0) - { - char* paramValue = new char[value_length]; - status = rprContextGetParameterInfo(context, int(i), RPR_PARAMETER_VALUE, value_length, paramValue, NULL); - CHECK_STATUS_RETURNERROR; - - myfile->write(paramValue, value_length); - - delete[] paramValue; paramValue = NULL; - } - } - delete[] paramName; paramName = NULL; - - } - } - - - myfile->write((const char*)&m_CONTEXT_END, sizeof(m_CONTEXT_END)); - - return RPR_SUCCESS; -} - - - -rpr_int FRS6::LoadContext(rpr_context context, std::istream *myfile) -{ - rpr_int status = RPR_SUCCESS; - - - int32_t checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_CONTEXT_BEG) - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - - uint64_t nbParam = 0; - myfile->read((char*)&nbParam, sizeof(uint64_t)); - - - for (int i = 0; i < nbParam; i++) - { - uint64_t name_length = 0; - myfile->read((char*)&name_length, sizeof(name_length)); - char* name_data = new char[name_length]; - myfile->read(name_data, name_length); - - rpr_parameter_type type; - myfile->read((char*)&type, sizeof(rpr_parameter_type)); - - uint64_t data_length = 0; - myfile->read((char*)&data_length, sizeof(data_length)); - - if (data_length > 0) - { - - char* data_data = new char[data_length]; - myfile->read(data_data, data_length); - - if (type == RPR_PARAMETER_TYPE_UINT) - { - rpr_uint* data_uint = (rpr_uint*)data_data; - if (data_length == sizeof(rpr_uint)) - { - status = rprContextSetParameter1u(context, name_data, (rpr_uint)data_uint[0]); - if (status != RPR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - else - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - - } - else if (type == RPR_PARAMETER_TYPE_FLOAT) - { - rpr_float* data_float = (rpr_float*)data_data; - - if (data_length == sizeof(rpr_float)) - { - - status = rprContextSetParameter1f(context, name_data, data_float[0]); - if (status != RPR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - - } - else - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - } - else if (type == RPR_PARAMETER_TYPE_FLOAT3) - { - rpr_float* data_float = (rpr_float*)data_data; - - if (data_length == 3*sizeof(rpr_float)) - { - status = rprContextSetParameter3f(context, name_data, data_float[0], data_float[1], data_float[2]); - if (status != RPR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - else - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - } - else if (type == RPR_PARAMETER_TYPE_FLOAT4) - { - rpr_float* data_float = (rpr_float*)data_data; - - if (data_length == 4*sizeof(rpr_float)) - { - status = rprContextSetParameter4f(context, name_data, data_float[0], data_float[1], data_float[2], data_float[3]); - if (status != RPR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - else - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - } - - - delete[] data_data; data_data = NULL; - - } - - delete[] name_data; name_data = NULL; - - - } - - - checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_CONTEXT_END) - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - - return RPR_SUCCESS; -} - - - -rpr_int FRS6::StoreScene(rpr_scene scene, std::ofstream *myfile) -{ - rpr_int status = RPR_SUCCESS; - - myfile->write((const char*)&m_SCENE_BEG, sizeof(m_SCENE_BEG)); - - - uint64_t nbShape = 0; - status = rprSceneGetInfo(scene, RPR_SCENE_SHAPE_COUNT, sizeof(nbShape), &nbShape, NULL); - CHECK_STATUS_RETURNERROR; - uint64_t nbLight = 0; - status = rprSceneGetInfo(scene, RPR_SCENE_LIGHT_COUNT, sizeof(nbLight), &nbLight, NULL); - CHECK_STATUS_RETURNERROR; - //uint64_t nbTexture = 0; - //status = rprSceneGetInfo(scene, RPR_SCENE_TEXTURE_COUNT, sizeof(nbTexture), &nbTexture, NULL); - //CHECK_STATUS_RETURNERROR; - - - myfile->write((char*)&nbShape, sizeof(nbShape)); - myfile->write((char*)&nbLight, sizeof(nbLight)); - //myfile->write((char*)&nbTexture, sizeof(nbTexture)); - - - rpr_shape* shapes = new rpr_shape[nbShape]; - rpr_light* light = new rpr_light[nbLight]; - //rpr_image* texture = new rpr_image[nbTexture]; - status = rprSceneGetInfo(scene, RPR_SCENE_SHAPE_LIST, nbShape * sizeof(rpr_shape), shapes, NULL); - CHECK_STATUS_RETURNERROR; - status = rprSceneGetInfo(scene, RPR_SCENE_LIGHT_LIST, nbLight * sizeof(rpr_light), light, NULL); - CHECK_STATUS_RETURNERROR; - //status = rprSceneGetInfo(scene, RPR_SCENE_TEXTURE_LIST, nbTexture * sizeof(rpr_image), texture, NULL); - //CHECK_STATUS_RETURNERROR; - -// status = rprSceneGetInfo(scene, RPR_SCENE_TEXTURE_LIST, sizeof(textures), &textures, NULL); - - m_shapeList.clear(); - m_imageList.clear(); - - - //env light - rpr_light envLight = NULL; - //status = rprSceneGetEnvironmentLight(scene, &envLight); - if ( - envLight != NULL - //false - ) - { - int32_t envLightExist = 1; - myfile->write((char*)&envLightExist, sizeof(envLightExist)); - StoreLight(envLight, scene, myfile); - } - else - { - int32_t envLightExist = 0; - myfile->write((char*)&envLightExist, sizeof(envLightExist)); - } - - - - for (uint64_t i = 0; i < nbShape; i++) // first: store non-instanciate shapes - { - rpr_shape_type type; - status = rprShapeGetInfo(shapes[i], RPR_SHAPE_TYPE, sizeof(rpr_shape_type), &type, NULL); - CHECK_STATUS_RETURNERROR; - if (type == RPR_SHAPE_TYPE_MESH) - { - rpr_int err = StoreShape(shapes[i], myfile); - if (err != RPR_SUCCESS) - { - return err; // easier for debug if stop everything - } - } - } - - for (uint64_t i = 0; i < nbShape; i++)// second: store instanciate shapes only - { - rpr_shape_type type; - status = rprShapeGetInfo(shapes[i], RPR_SHAPE_TYPE, sizeof(rpr_shape_type), &type, NULL); - CHECK_STATUS_RETURNERROR; - if (type != RPR_SHAPE_TYPE_MESH) - { - rpr_int err = StoreShape(shapes[i], myfile); - if (err != RPR_SUCCESS) - { - return err; // easier for debug if stop everything - } - } - } - - - for (uint64_t i = 0; i < nbLight; i++) - { - rpr_int err = StoreLight(light[i],scene, myfile); - if (err != RPR_SUCCESS) - { - return err; // easier for debug if stop everything - } - } - - - - rpr_camera camera = NULL; - status = rprSceneGetCamera(scene, &camera); - CHECK_STATUS_RETURNERROR; - - - int32_t sceneCameraExists = 0; - if(camera) - { - sceneCameraExists = 1; - } - myfile->write((char*)&sceneCameraExists, sizeof(sceneCameraExists)); // since version 06, we specify if camera exists of not - - if (camera) - { - status = StoreCamera(camera, myfile); - CHECK_STATUS_RETURNERROR; - } - - - - myfile->write((const char*)&m_SCENE_END, sizeof(m_SCENE_END)); - - return RPR_SUCCESS; - -} - -rpr_scene FRS6::LoadScene(rpr_context context, rpr_material_system materialSystem, std::istream *myfile, rpr_scene sceneExisting) -{ - rpr_int status = RPR_SUCCESS; - - - int32_t checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_SCENE_BEG) - { - ErrorDetected(); - return 0; - } - - - rpr_scene scene = NULL; - if ( sceneExisting == NULL ) - { - scene = NULL; - status = rprContextCreateScene(context, &scene); - } - else - { - scene = sceneExisting; - } - CHECK_STATUS_RETURNNULL; - - - uint64_t nbShape = 0; - myfile->read((char*)&nbShape, sizeof(nbShape)); - uint64_t nbLight = 0; - myfile->read((char*)&nbLight, sizeof(nbLight)); - //uint64_t nbTexture = 0; - //myfile->read((char*)&nbTexture, sizeof(nbTexture)); - - m_shapeList.clear(); - m_imageList.clear(); - - int32_t envLightExist = 0; - myfile->read((char*)&envLightExist, sizeof(envLightExist)); - if (envLightExist == 1) - { - rpr_light newLight = LoadLight(context, scene, myfile); - if (newLight == 0) - { - ErrorDetected(); - return 0; - } - - } - - - - for (int i = 0; i < nbShape; i++) - { - rpr_shape shape = LoadShape(context, materialSystem, myfile); - if (shape == 0) - { - ErrorDetected(); - return 0; // easier for debug if stop everything - } - status = rprSceneAttachShape(scene, shape); - CHECK_STATUS_RETURNNULL; - } - for (int i = 0; i < nbLight; i++) - { - rpr_light light = LoadLight(context,scene, myfile); - if (light == 0) - { - ErrorDetected(); - return 0; // easier for debug if stop everything - } - status = rprSceneAttachLight(scene, light); - CHECK_STATUS_RETURNNULL; - } - - - int32_t cameraExists = 1; - if ( m_fileVersionOfLoadFile >= 6 ) // since version 6, we store if camera exists - { - myfile->read((char*)&cameraExists, sizeof(cameraExists)); - } - - if ( cameraExists == 1) - { - rpr_camera camera = LoadCamera(context, myfile); - if ( camera == NULL ) - { - ErrorDetected(); - return 0; - } - status = rprSceneSetCamera(scene, camera); - CHECK_STATUS_RETURNNULL; - } - - checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_SCENE_END) - { - ErrorDetected(); - return 0; - } - - status = rprContextSetScene(context, scene); - CHECK_STATUS_RETURNNULL; - - return scene; -} - -rpr_int FRS6::StoreShader(rpr_material_node shader, std::ofstream *myfile) -{ - - rpr_int status = RPR_SUCCESS; - - myfile->write((const char*)&m_SHADER_BEG, sizeof(m_SHADER_BEG)); - - rpr_material_node_type nodeType = 0; - status = rprMaterialNodeGetInfo(shader,RPR_MATERIAL_NODE_TYPE, sizeof(nodeType),&nodeType,NULL); - CHECK_STATUS_RETURNNULL; - myfile->write((char*)&nodeType, sizeof(nodeType)); - - uint64_t nbInput = 0; - status = rprMaterialNodeGetInfo(shader,RPR_MATERIAL_NODE_INPUT_COUNT, sizeof(nbInput),&nbInput,NULL); - CHECK_STATUS_RETURNNULL; - myfile->write((char*)&nbInput, sizeof(nbInput)); - - - for (int i = 0; i < nbInput; i++) - { - size_t shaderParameterName_lenght_size_t = 0; - status = rprMaterialNodeGetInputInfo(shader, i, RPR_MATERIAL_NODE_INPUT_NAME, 0, NULL, &shaderParameterName_lenght_size_t); - uint64_t shaderParameterName_lenght = shaderParameterName_lenght_size_t; - CHECK_STATUS_RETURNNULL; - char* shaderParameterName = new char[shaderParameterName_lenght]; - status = rprMaterialNodeGetInputInfo(shader, i, RPR_MATERIAL_NODE_INPUT_NAME, shaderParameterName_lenght, shaderParameterName, NULL); - CHECK_STATUS_RETURNNULL; - myfile->write((char*)&shaderParameterName_lenght, sizeof(shaderParameterName_lenght)); - myfile->write((char*)shaderParameterName, shaderParameterName_lenght); - - rpr_uint nodeInputType = 0; - status = rprMaterialNodeGetInputInfo(shader, i, RPR_MATERIAL_NODE_INPUT_TYPE, sizeof(nodeInputType), &nodeInputType, NULL); - CHECK_STATUS_RETURNNULL; - myfile->write((char*)&nodeInputType, sizeof(nodeInputType)); - - size_t shaderParameterValue_lenght_size_t = 0; - status = rprMaterialNodeGetInputInfo(shader, i, RPR_MATERIAL_NODE_INPUT_VALUE, 0, NULL, &shaderParameterValue_lenght_size_t); - uint64_t shaderParameterValue_lenght = shaderParameterValue_lenght_size_t; - CHECK_STATUS_RETURNNULL; - char* shaderParameterValue = new char[shaderParameterValue_lenght]; - status = rprMaterialNodeGetInputInfo(shader, i, RPR_MATERIAL_NODE_INPUT_VALUE, shaderParameterValue_lenght, shaderParameterValue, NULL); - CHECK_STATUS_RETURNNULL; - - - if ( nodeInputType == RPR_MATERIAL_NODE_INPUT_TYPE_NODE ) - { - if (shaderParameterValue_lenght != sizeof(rpr_material_node)) - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - else - { - rpr_material_node* shader = (rpr_material_node*)shaderParameterValue; - if (*shader != NULL) - { - int32_t shaderExists = 1; - myfile->write((char*)&shaderExists, sizeof(shaderExists)); - status = StoreShader(*shader, myfile); - } - else - { - int32_t shaderExists = 0; - myfile->write((char*)&shaderExists, sizeof(shaderExists)); - } - CHECK_STATUS_RETURNERROR; - } - } - else if (nodeInputType == RPR_MATERIAL_NODE_INPUT_TYPE_IMAGE) - { - if (shaderParameterValue_lenght != sizeof(rpr_image)) - { - ErrorDetected(); - return RPR_ERROR_INTERNAL_ERROR; - } - else - { - rpr_image* image = (rpr_material_node*)shaderParameterValue; - if (*image != NULL) - { - int32_t imageExists = 1; - myfile->write((char*)&imageExists, sizeof(imageExists)); - status = StoreImage(*image, myfile); - } - else - { - int32_t imageExists = 0; - myfile->write((char*)&imageExists, sizeof(imageExists)); - } - CHECK_STATUS_RETURNERROR; - } - } - else - { - myfile->write((char*)&shaderParameterValue_lenght, sizeof(shaderParameterValue_lenght)); - myfile->write((char*)shaderParameterValue, shaderParameterValue_lenght); - } - - delete[] shaderParameterName; shaderParameterName = NULL; - delete[] shaderParameterValue; shaderParameterValue = NULL; - } - - - myfile->write((const char*)&m_SHADER_END, sizeof(m_SHADER_END)); - - return RPR_SUCCESS; -} - - -rpr_material_node FRS6::LoadShader(rpr_material_system materialSystem, rpr_context context, std::istream *myfile) -{ - rpr_int status = RPR_SUCCESS; - - int32_t checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_SHADER_BEG) - { - ErrorDetected(); - return 0; - } - - rpr_material_node_type shaderType; - myfile->read((char*)&shaderType, sizeof(rpr_material_node_type)); - - rpr_material_node shader = NULL; - status = rprMaterialSystemCreateNode(materialSystem, shaderType, &shader); - CHECK_STATUS_RETURNNULL; - - uint64_t nbInput = 0; - myfile->read((char*)&nbInput, sizeof(nbInput)); - - - for (int i = 0; i < nbInput; i++) - { - uint64_t paramName_length = 0; - myfile->read((char*)¶mName_length, sizeof(paramName_length)); - char* paramName_data = new char[paramName_length]; - myfile->read((char*)paramName_data, paramName_length); - - rpr_parameter_type paramType; - myfile->read((char*)¶mType, sizeof(paramType)); - - - - if (paramType == RPR_MATERIAL_NODE_INPUT_TYPE_NODE) - { - int32_t shaderExists; - myfile->read((char*)&shaderExists, sizeof(shaderExists)); - - if (shaderExists == 1) - { - - rpr_material_node newShader = LoadShader(materialSystem, context, myfile); - if (newShader == 0) - { - ErrorDetected(); - return 0; - } - status = rprMaterialNodeSetInputN(shader, paramName_data, newShader); - if (status != RPR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - - } - else - { - status = rprMaterialNodeSetInputN(shader, paramName_data, NULL); - if (status != RPR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - - } - else if (paramType == RPR_MATERIAL_NODE_INPUT_TYPE_IMAGE) - { - int32_t imageExists; - myfile->read((char*)&imageExists, sizeof(imageExists)); - - if (imageExists == 1) - { - - rpr_material_node newImage = LoadImage(context, myfile); - if (newImage == 0) - { - ErrorDetected(); - return 0; - } - status = rprMaterialNodeSetInputImageData(shader, paramName_data, newImage); - if (status != RPR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - - } - else - { - status = rprMaterialNodeSetInputImageData(shader, paramName_data, NULL); - if (status != RPR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - - } - else - { - uint64_t paramValue_length = 0; - myfile->read((char*)¶mValue_length, sizeof(paramValue_length)); - char* paramValue_data = new char[paramValue_length]; - myfile->read((char*)paramValue_data, paramValue_length); - - if ( paramType == RPR_MATERIAL_NODE_INPUT_TYPE_FLOAT4 ) - { - if ( paramValue_length != 4*4 ) // check size is float4 - { - ErrorDetected(); - return 0; - } - float* f4 = (float*)paramValue_data; - status = rprMaterialNodeSetInputF(shader, paramName_data, f4[0],f4[1],f4[2],f4[3]); - if (status != RPR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - else if ( paramType == RPR_MATERIAL_NODE_INPUT_TYPE_UINT ) - { - if ( paramValue_length != 4 ) { ErrorDetected(); return 0; } // check size is UINT - unsigned int* ui1 = (unsigned int*)paramValue_data; - status = rprMaterialNodeSetInputU(shader, paramName_data, ui1[0]); - if (status != RPR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - - } - else - { - ErrorDetected(); - return 0; - } - - delete[] paramValue_data; paramValue_data = NULL; - } - - delete[] paramName_data; paramName_data = NULL; - //delete[] value_data; value_data = NULL; - } - - - checkCode = 0; - myfile->read((char*)&checkCode, sizeof(checkCode)); - if (checkCode != m_SHADER_END) - { - ErrorDetected(); - return 0; - } - - return shader; -} - -void FRS6::ErrorDetected() -{ - - //add breakpoint here for debugging frLoader - int a=0; - -} - -void FRS6::WarningDetected() -{ - - //add breakpoint here for debugging frLoader - int a=0; - -} - - - -int asup_temp() -{ - - - return 0; -} diff --git a/RprLoadStore/frs6.h b/RprLoadStore/frs6.h deleted file mode 100644 index 73a584e1..00000000 --- a/RprLoadStore/frs6.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef frLoadStore_FRS6_H_ -#define frLoadStore_FRS6_H_ - -#include "Rpr/RadeonProRender.h" - -#include -#include -#include -#include - - - -// FRS6 is an old version. I keep it here for legacy purpose. -// the version 6 is not supposed to be used anymore -class FRS6 -{ - -public: - - //when we store a scene from 3DS max, we store additionnal data. - //data is contain in this struct - struct LOADER_DATA_FROM_3DS - { - // added in version 04 : - bool used; // if 'used' is false, all other parameters of this struct are useless - float exposure; - bool isNormals; - bool shouldToneMap; - - // added in version 06 : - int32_t gamma_Enabled; // 0 or 1 - float gamma_disp; - float gamma_fileIn; - float gamma_fileOut; - - }; - - // return RPR_SUCCESS is success - static rpr_int StoreEverything( - rpr_context context, - rpr_scene scene, - const LOADER_DATA_FROM_3DS* dataFrom3DS, // <--- can be NULL if not used - std::ofstream *myfile); - - // - // example : - // rpr_context context = rprCreateContext(...); <-- must not be null, else return fail - // rpr_scene scene = 0; <--- must be NULL. else function returns fail. - // rpr_material_system matsys = NULL; - // rprContextCreateMaterialSystem(context, 0, &matsys); - // LoadEverything( context, matsys, myfile, scene, NULL, false ); - // - // return RPR_SUCCESS is success - static rpr_int LoadEverything( - rpr_context context, - rpr_material_system materialSystem, - std::istream *myfile, - rpr_scene& scene, - LOADER_DATA_FROM_3DS* dataFrom3DS, // <--- can be NULL if not used - bool useAlreadyExistingScene - ); - -private: - - static rpr_int StoreCamera(rpr_camera camera, std::ofstream *myfile);// return RPR_SUCCESS is success - static rpr_camera LoadCamera(rpr_context context, std::istream *myfile);//return NULL if error - static rpr_int StoreShader(rpr_material_node shader, std::ofstream *myfile);// return RPR_SUCCESS is success - static rpr_material_node LoadShader(rpr_material_system materialSystem, rpr_context context, std::istream *myfile);//return NULL if error - static rpr_int StoreShape(rpr_shape shape, std::ofstream *myfile); // return RPR_SUCCESS is success - static rpr_shape LoadShape(rpr_context context, rpr_material_system materialSystem, std::istream *myfile);//return NULL if error - static rpr_int StoreScene(rpr_scene scene, std::ofstream *myfile);// return RPR_SUCCESS is success - static rpr_scene LoadScene(rpr_context context, rpr_material_system materialSystem, std::istream *myfile, rpr_scene sceneExisting);//return NULL if error. If sceneExisting not NULL, the we use this scene. Else we create a new scene. - static rpr_int StoreLight(rpr_light light, rpr_scene scene, std::ofstream *myfile);// return RPR_SUCCESS is success - static rpr_light LoadLight(rpr_context context, rpr_scene scene, std::istream *myfile);//return NULL if error - static rpr_int StoreImage(rpr_image image, std::ofstream *myfile);// return RPR_SUCCESS is success - static rpr_image LoadImage(rpr_context context, std::istream *myfile);//return NULL if error - static rpr_int StoreContext(rpr_context context, std::ofstream *myfile);// return RPR_SUCCESS is success - static rpr_int LoadContext(rpr_context context, std::istream *myfile);// return RPR_SUCCESS is success - - //this is just for debug. advice to call this function each time an error is detected. - //for debugging, we can add a breakpoint in this function - static void ErrorDetected(); - static void WarningDetected(); - - - //just for more safety, the data is encapsulated around keywords. - //so we can check that we are reading correct data - static const int32_t m_SHAPE_BEG; - static const int32_t m_SHAPE_END; - static const int32_t m_CAMERA_BEG; - static const int32_t m_CAMERA_END; - static const int32_t m_LIGHT_BEG; - static const int32_t m_LIGHT_END; - static const int32_t m_SHADER_BEG; - static const int32_t m_SHADER_END; - static const int32_t m_SCENE_BEG; - static const int32_t m_SCENE_END; - static const int32_t m_CONTEXT_BEG; - static const int32_t m_CONTEXT_END; - static const int32_t m_EVERYTHING_BEG; - static const int32_t m_EVERYTHING_END; - static const int32_t m_IMAGE_BEG; - static const int32_t m_IMAGE_END; - static const int32_t m_3DSDATA_BEG; - static const int32_t m_3DSDATA_END; - - //first 4 bytes of the file. - //will never change. - //just tell that it's a FireRender Scene file - static const char m_HEADER_CHECKCODE[4]; - - //should be incremented each time we update the store/load - //version will be write just after the m_HEADER_CHECKCODE - static const int32_t m_FILE_VERSION; - - static std::vector m_shapeList; // list of shape non-instancied - - static std::vector m_imageList; //list to avoid to save several time the same image - - static int32_t m_fileVersionOfLoadFile; - -}; - - - -#endif diff --git a/RprLoadStore/frs7.cpp b/RprLoadStore/frs7.cpp deleted file mode 100644 index 43b75f93..00000000 --- a/RprLoadStore/frs7.cpp +++ /dev/null @@ -1,3046 +0,0 @@ -#include -#include -#include -#include "frs7.h" - -#include - -//with linux, it seems cstddef and string.h are needed for compile -#ifdef __linux__ -#include -#include -#endif - -// history of changes : -// version 02 : first -// version 03 : add shadow flag -// version 04 : add LOADER_DATA_FROM_3DS -// version 05 : (07 jan 2016) new material system -// version 06 : (25 feb 2016) add more data inside LOADER_DATA_FROM_3DS + possibility to save if no camera in scene. note that version 6 can import version 5 -// version 07 : lots of changes. not retrocompatible with previous versions. But really more flexible. the flexibility of this version should make it the very last version of FRS. -int32_t const FRS7::m_FILE_VERSION = 0x00000007; - -char const FRS7::m_HEADER_CHECKCODE[4] = {'F','R','S','F'}; // "FRSF" = FireRenderSceneFile -char const FRS7::m_HEADER_BADCHECKCODE[4] = {'B','A','D','0'}; -char const STR__SHAPE_INSTANCE_REFERENCE_ID[] = "shape_instance_reference_id"; -char const STR__SHAPE_FOR_SKY_LIGHT_PORTAL_ID[] = "shape_for_sky_light_portal_id"; -char const STR__SHAPE_FOR_ENVIRONMENT_LIGHT_PORTAL_ID[] = "shape_for_environment_light_portal_id"; - -#define CHECK_STATUS_RETURNERROR { if (status != FR_SUCCESS) { FRS_MACRO_ERROR(); return status; } } -#define CHECK_STATUS_RETURNNULL { if (status != FR_SUCCESS) { FRS_MACRO_ERROR(); return 0; } } - - -#define FRS_MACRO_ERROR() ErrorDetected (__FUNCTION__,__LINE__,""); - - -FRS7::FRS7(std::fstream* myfile, bool allowWrite) : - m_allowWrite(allowWrite) -{ - m_frsFile = myfile; - m_listObjectDeclared.clear(); - m_level = 0; - - m_idCounter = 1000; // just in order to avoid confusion with other numbers, I start this counter from 1000 - - m_fileVersionOfLoadFile = 0; // only used when read FRS file -} - -FRS7::~FRS7() -{ - -} - -void FRS7::WarningDetected() -{ - //add breakpoint here for debugging frLoader - int a=0; -} -void FRS7::ErrorDetected (const char* function, int32_t line, const char* message) -{ - //add breakpoint here for debugging frLoader - int a=0; - - //if an error is detected, the file is corrupted anyway, so we can write error debug info at the end of the file. - //Note that a bad file file is directly detected at the begining of the file with the string : m_HEADER_BADCHECKCODE - if ( m_allowWrite && m_frsFile->is_open() && !m_frsFile->fail() ) - { - std::ostringstream stringStream; - stringStream << "\r\nERROR -- FUNC=" << std::string(function) << " LINE=" << line << " EXTRA_MESSAGE=" << message << " ENDERROR\r\n"; - std::string errorInfoStr = stringStream.str(); - - m_frsFile->write(errorInfoStr.c_str(), errorInfoStr.length()); - m_frsFile->flush(); - } -} - - - - -fr_int FRS7::StoreEverything( - fr_context context, - fr_scene scene - ) -{ - fr_int status = FR_SUCCESS; - - // write a wrong check code: the good check code will be written at the end, when we are sure that the generation didn't fail. - // so if we have a crash or anything bad during StoreEverything, the FRS will be nicely unvalid. - m_frsFile->write((const char*)&m_HEADER_BADCHECKCODE, sizeof(m_HEADER_BADCHECKCODE)); - m_frsFile->write((const char*)&m_FILE_VERSION, sizeof(m_FILE_VERSION)); - - - status = Store_Context(context); - if (status != FR_SUCCESS) { FRS_MACRO_ERROR(); return status; } - status = Store_Scene(scene); - if (status != FR_SUCCESS) { FRS_MACRO_ERROR(); return status; } - - - //store extra custom params - for (auto it=m_extraCustomParam_int.begin(); it!=m_extraCustomParam_int.end(); ++it) - { - if ( !Store_ObjectParameter((*it).first.c_str(),FRS7::FRSPT_INT32_1,sizeof(float),&((*it).second)) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - } - for (auto it=m_extraCustomParam_float.begin(); it!=m_extraCustomParam_float.end(); ++it) - { - if ( !Store_ObjectParameter((*it).first.c_str(),FRS7::FRSPT_FLOAT1,sizeof(float),&((*it).second)) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - } - - if ( m_level != 0 ) - { - //if level is not 0, this means we have not closed all object delaration - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - - //rewind and write the good check code at the begining of the file. - m_frsFile->seekp(0); - m_frsFile->write((const char*)&m_HEADER_CHECKCODE, sizeof(m_HEADER_CHECKCODE)); - - return status; -} - - -fr_int FRS7::Store_Camera(fr_camera camera) -{ - - fr_int status = FR_SUCCESS; - - if ( !Store_StartObject("sceneCamera","fr_camera",camera) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - float param_fstop; - status = frCameraGetInfo(camera, FR_CAMERA_FSTOP, sizeof(param_fstop), ¶m_fstop, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_CAMERA_FSTOP",FRSPT_FLOAT1,sizeof(param_fstop), ¶m_fstop) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - unsigned int param_apblade; - status = frCameraGetInfo(camera, FR_CAMERA_APERTURE_BLADES, sizeof(unsigned int), ¶m_apblade, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_CAMERA_APERTURE_BLADES",FRSPT_UINT32_1,sizeof(param_apblade), ¶m_apblade) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - float param_camexpo; - status = frCameraGetInfo(camera, FR_CAMERA_EXPOSURE, sizeof(param_camexpo), ¶m_camexpo, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_CAMERA_EXPOSURE",FRSPT_FLOAT1,sizeof(param_camexpo), ¶m_camexpo) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - float param_focalLen; - status = frCameraGetInfo(camera, FR_CAMERA_FOCAL_LENGTH, sizeof(param_focalLen), ¶m_focalLen, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_CAMERA_FOCAL_LENGTH",FRSPT_FLOAT1,sizeof(param_focalLen), ¶m_focalLen) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - float param_sensorsize[2]; - status = frCameraGetInfo(camera, FR_CAMERA_SENSOR_SIZE, sizeof(param_sensorsize), ¶m_sensorsize, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_CAMERA_SENSOR_SIZE",FRSPT_FLOAT2,sizeof(param_sensorsize), ¶m_sensorsize) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - fr_camera_mode param_mode; - status = frCameraGetInfo(camera, FR_CAMERA_MODE, sizeof(param_mode), ¶m_mode, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_CAMERA_MODE",FRSPT_UINT32_1,sizeof(param_mode), ¶m_mode) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - float param_orthowidth; - status = frCameraGetInfo(camera, FR_CAMERA_ORTHO_WIDTH, sizeof(param_orthowidth), ¶m_orthowidth, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_CAMERA_ORTHO_WIDTH",FRSPT_FLOAT1,sizeof(param_orthowidth), ¶m_orthowidth) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - float param_orthoheight; - status = frCameraGetInfo(camera, FR_CAMERA_ORTHO_HEIGHT, sizeof(param_orthoheight), ¶m_orthoheight, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("FR_CAMERA_ORTHO_HEIGHT", FRSPT_FLOAT1, sizeof(param_orthoheight), ¶m_orthoheight)) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - float param_focusdist; - status = frCameraGetInfo(camera, FR_CAMERA_FOCUS_DISTANCE, sizeof(param_focusdist), ¶m_focusdist, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_CAMERA_FOCUS_DISTANCE",FRSPT_FLOAT1,sizeof(param_focusdist), ¶m_focusdist) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - fr_float param_pos[4]; - status = frCameraGetInfo(camera, FR_CAMERA_POSITION, sizeof(param_pos), ¶m_pos, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_CAMERA_POSITION",FRSPT_FLOAT3,3*sizeof(float), param_pos) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - fr_float param_at[4]; - status = frCameraGetInfo(camera, FR_CAMERA_LOOKAT, sizeof(param_at), ¶m_at, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_CAMERA_LOOKAT",FRSPT_FLOAT3,3*sizeof(float), param_at) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - fr_float param_up[4]; - status = frCameraGetInfo(camera, FR_CAMERA_UP, sizeof(param_up), ¶m_up, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_CAMERA_UP",FRSPT_FLOAT3,3*sizeof(float), param_up) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - - //save FR_OBJECT_NAME of object. - size_t frobjectName_size = 0; - status = frCameraGetInfo(camera, FR_OBJECT_NAME, NULL, NULL, &frobjectName_size); - CHECK_STATUS_RETURNERROR; - if ( frobjectName_size <= 0 ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } // because of 0 terminated character, size must be >= 1 - char* frobjectName_data = new char[frobjectName_size]; - status = frCameraGetInfo(camera, FR_OBJECT_NAME, frobjectName_size, frobjectName_data, NULL); - CHECK_STATUS_RETURNERROR; - if ( frobjectName_data[frobjectName_size-1] != '\0' ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } // check that the last character is '\0' - if ( !Store_ObjectParameter("FR_OBJECT_NAME",FRSPT_UNDEF,frobjectName_size, frobjectName_data) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - delete[] frobjectName_data; frobjectName_data = NULL; - - - if ( !Store_EndObject() ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - return FR_SUCCESS; -} - - -fr_int FRS7::Store_MaterialNode(fr_material_node shader, const std::string& name) -{ - - fr_int status = FR_SUCCESS; - - - int indexFound = -1; - //search if this node is already saved. - for (int iObj = 0; iObj < m_listObjectDeclared.size(); iObj++) - { - if (m_listObjectDeclared[iObj].type == "fr_material_node" && m_listObjectDeclared[iObj].obj == shader) - { - indexFound = iObj; - break; - } - } - if ( indexFound != -1 ) - { - //if node already saved, just save reference - if ( !Store_ReferenceToObject(name,"fr_material_node",m_listObjectDeclared[indexFound].id) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - } - else - { - //if node not already saved - - - - if ( !Store_StartObject(name,"fr_material_node",shader) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - fr_material_node_type nodeType = 0; - status = frMaterialNodeGetInfo(shader,FR_MATERIAL_NODE_TYPE, sizeof(nodeType),&nodeType,NULL); - CHECK_STATUS_RETURNNULL; - if ( !Store_ObjectParameter("FR_MATERIAL_NODE_TYPE",FRSPT_UINT32_1,sizeof(nodeType), &nodeType) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - uint64_t nbInput = 0; - status = frMaterialNodeGetInfo(shader,FR_MATERIAL_NODE_INPUT_COUNT, sizeof(nbInput),&nbInput,NULL); - CHECK_STATUS_RETURNNULL; - if ( !Store_ObjectParameter("FR_MATERIAL_NODE_INPUT_COUNT",FRSPT_UINT64_1,sizeof(nbInput), &nbInput) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - - for (int i = 0; i < nbInput; i++) - { - size_t shaderParameterName_lenght_size_t = 0; - status = frMaterialNodeGetInputInfo(shader, i, FR_MATERIAL_NODE_INPUT_NAME_STRING, 0, NULL, &shaderParameterName_lenght_size_t); - uint64_t shaderParameterName_lenght = shaderParameterName_lenght_size_t; - CHECK_STATUS_RETURNNULL; - char* shaderParameterName = new char[shaderParameterName_lenght]; - status = frMaterialNodeGetInputInfo(shader, i, FR_MATERIAL_NODE_INPUT_NAME_STRING, shaderParameterName_lenght, shaderParameterName, NULL); - CHECK_STATUS_RETURNNULL; - //myfile->write((char*)&shaderParameterName_lenght, sizeof(shaderParameterName_lenght)); - //myfile->write((char*)shaderParameterName, shaderParameterName_lenght); - - fr_uint nodeInputType = 0; - status = frMaterialNodeGetInputInfo(shader, i, FR_MATERIAL_NODE_INPUT_TYPE, sizeof(nodeInputType), &nodeInputType, NULL); - CHECK_STATUS_RETURNNULL; - //myfile->write((char*)&nodeInputType, sizeof(nodeInputType)); - - size_t shaderParameterValue_lenght_size_t = 0; - status = frMaterialNodeGetInputInfo(shader, i, FR_MATERIAL_NODE_INPUT_VALUE, 0, NULL, &shaderParameterValue_lenght_size_t); - uint64_t shaderParameterValue_lenght = shaderParameterValue_lenght_size_t; - CHECK_STATUS_RETURNNULL; - char* shaderParameterValue = new char[shaderParameterValue_lenght]; - status = frMaterialNodeGetInputInfo(shader, i, FR_MATERIAL_NODE_INPUT_VALUE, shaderParameterValue_lenght, shaderParameterValue, NULL); - CHECK_STATUS_RETURNNULL; - - - if ( nodeInputType == FR_MATERIAL_NODE_INPUT_TYPE_NODE ) - { - if (shaderParameterValue_lenght != sizeof(fr_material_node)) - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - else - { - - - fr_material_node* shader = (fr_material_node*)shaderParameterValue; - if (*shader != NULL) - { - //int32_t shaderExists = 1; - //myfile->write((char*)&shaderExists, sizeof(shaderExists)); - status = Store_MaterialNode(*shader,shaderParameterName); - } - else - { - //int32_t shaderExists = 0; - //myfile->write((char*)&shaderExists, sizeof(shaderExists)); - } - CHECK_STATUS_RETURNERROR; - - } - } - else if (nodeInputType == FR_MATERIAL_NODE_INPUT_TYPE_IMAGE) - { - if (shaderParameterValue_lenght != sizeof(fr_image)) - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - else - { - fr_image* image = (fr_material_node*)shaderParameterValue; - if (*image != NULL) - { - //int32_t imageExists = 1; - //myfile->write((char*)&imageExists, sizeof(imageExists)); - status = Store_Image(*image,shaderParameterName); - } - else - { - //int32_t imageExists = 0; - //myfile->write((char*)&imageExists, sizeof(imageExists)); - } - CHECK_STATUS_RETURNERROR; - } - } - else if ( nodeInputType == FR_MATERIAL_NODE_INPUT_TYPE_FLOAT4 ) - { - if ( !Store_ObjectParameter(shaderParameterName,FRSPT_FLOAT4,shaderParameterValue_lenght, shaderParameterValue) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - } - else if ( nodeInputType == FR_MATERIAL_NODE_INPUT_TYPE_UINT ) - { - if ( !Store_ObjectParameter(shaderParameterName,FRSPT_UINT32_1,shaderParameterValue_lenght, shaderParameterValue) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - } - else - { - if ( !Store_ObjectParameter(shaderParameterName,FRSPT_UNDEF,shaderParameterValue_lenght, shaderParameterValue) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - } - - delete[] shaderParameterName; shaderParameterName = NULL; - delete[] shaderParameterValue; shaderParameterValue = NULL; - } - - - //save FR_OBJECT_NAME of object. - size_t frobjectName_size = 0; - status = frMaterialNodeGetInfo(shader, FR_OBJECT_NAME, NULL, NULL, &frobjectName_size); - CHECK_STATUS_RETURNERROR; - if ( frobjectName_size <= 0 ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } // because of 0 terminated character, size must be >= 1 - char* frobjectName_data = new char[frobjectName_size]; - status = frMaterialNodeGetInfo(shader, FR_OBJECT_NAME, frobjectName_size, frobjectName_data, NULL); - CHECK_STATUS_RETURNERROR; - if ( frobjectName_data[frobjectName_size-1] != '\0' ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } // check that the last character is '\0' - if ( !Store_ObjectParameter("FR_OBJECT_NAME",FRSPT_UNDEF,frobjectName_size, frobjectName_data) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - delete[] frobjectName_data; frobjectName_data = NULL; - - - if ( !Store_EndObject() ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - } - - return status; -} - -fr_int FRS7::Store_Light(fr_light light, fr_scene scene) -{ - - fr_int status = FR_SUCCESS; - - if ( !Store_StartObject("sceneLight","fr_light",light) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - fr_light_type type = 0; - status = frLightGetInfo(light, FR_LIGHT_TYPE, sizeof(fr_light_type), &type, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_LIGHT_TYPE",FRSPT_UNDEF,sizeof(fr_light_type), &type) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - if (type == FR_LIGHT_TYPE_POINT) - { - float radian4f[4]; - status = frLightGetInfo(light, FR_POINT_LIGHT_RADIANT_POWER, sizeof(radian4f), &radian4f, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_POINT_LIGHT_RADIANT_POWER",FRSPT_FLOAT3,3*sizeof(float), radian4f) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - } - else if (type == FR_LIGHT_TYPE_DIRECTIONAL) - { - float radian4f[4]; - status = frLightGetInfo(light, FR_DIRECTIONAL_LIGHT_RADIANT_POWER, sizeof(radian4f), &radian4f, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_DIRECTIONAL_LIGHT_RADIANT_POWER",FRSPT_FLOAT3,3*sizeof(float), radian4f) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - } - else if (type == FR_LIGHT_TYPE_SPOT) - { - float radian4f[4]; - status = frLightGetInfo(light, FR_SPOT_LIGHT_RADIANT_POWER, sizeof(radian4f), &radian4f, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_SPOT_LIGHT_RADIANT_POWER",FRSPT_FLOAT3,3*sizeof(float), radian4f) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - float coneShape[2]; - status = frLightGetInfo(light, FR_SPOT_LIGHT_CONE_SHAPE, sizeof(coneShape), &coneShape, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_SPOT_LIGHT_CONE_SHAPE",FRSPT_FLOAT2,sizeof(coneShape), coneShape) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - } - else if (type == FR_LIGHT_TYPE_ENVIRONMENT) - { - fr_image image = NULL; - status = frLightGetInfo(light, FR_ENVIRONMENT_LIGHT_IMAGE, sizeof(fr_image), &image, NULL); - CHECK_STATUS_RETURNERROR; - if ( image ) - { - status = Store_Image((fr_image)image,"FR_ENVIRONMENT_LIGHT_IMAGE"); - CHECK_STATUS_RETURNERROR; - } - - float intensityScale; - status = frLightGetInfo(light, FR_ENVIRONMENT_LIGHT_INTENSITY_SCALE, sizeof(intensityScale), &intensityScale, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_ENVIRONMENT_LIGHT_INTENSITY_SCALE",FRSPT_FLOAT1,sizeof(intensityScale), &intensityScale) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - size_t nbOfPortals = 0; - status = frLightGetInfo(light,FR_ENVIRONMENT_LIGHT_PORTAL_COUNT, sizeof(nbOfPortals), &nbOfPortals, NULL ); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_ENVIRONMENT_LIGHT_PORTAL_COUNT",FRSPT_INT64_1,sizeof(nbOfPortals), &nbOfPortals) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - if ( nbOfPortals > 0 ) - { - fr_shape* shapes = new fr_shape[nbOfPortals]; - status = frLightGetInfo(light, FR_ENVIRONMENT_LIGHT_PORTAL_LIST, nbOfPortals * sizeof(fr_shape), shapes, NULL); - CHECK_STATUS_RETURNERROR; - - for (uint64_t i = 0; i < nbOfPortals; i++) - { - fr_int err = Store_Shape(shapes[i],STR__SHAPE_FOR_ENVIRONMENT_LIGHT_PORTAL_ID); - if (err != FR_SUCCESS) - { - FRS_MACRO_ERROR(); - return err; - } - } - - delete[] shapes; shapes=NULL; - } - - } - else if (type == FR_LIGHT_TYPE_SKY) - { - float scale = 0.0f; - status = frLightGetInfo(light, FR_SKY_LIGHT_SCALE, sizeof(scale), &scale, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_SKY_LIGHT_SCALE",FRSPT_FLOAT1,sizeof(scale), &scale) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - float albedo = 0.0f; - status = frLightGetInfo(light, FR_SKY_LIGHT_ALBEDO, sizeof(albedo), &albedo, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_SKY_LIGHT_ALBEDO",FRSPT_FLOAT1,sizeof(albedo), &albedo) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - float turbidity = 0.0f; - status = frLightGetInfo(light, FR_SKY_LIGHT_TURBIDITY, sizeof(turbidity), &turbidity, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_SKY_LIGHT_TURBIDITY",FRSPT_FLOAT1,sizeof(turbidity), &turbidity) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - size_t nbOfPortals = 0; - status = frLightGetInfo(light,FR_SKY_LIGHT_PORTAL_COUNT, sizeof(nbOfPortals), &nbOfPortals, NULL ); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_SKY_LIGHT_PORTAL_COUNT",FRSPT_INT64_1,sizeof(nbOfPortals), &nbOfPortals) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - if ( nbOfPortals > 0 ) - { - fr_shape* shapes = new fr_shape[nbOfPortals]; - status = frLightGetInfo(light, FR_SKY_LIGHT_PORTAL_LIST, nbOfPortals * sizeof(fr_shape), shapes, NULL); - CHECK_STATUS_RETURNERROR; - - for (uint64_t i = 0; i < nbOfPortals; i++) - { - fr_int err = Store_Shape(shapes[i],STR__SHAPE_FOR_SKY_LIGHT_PORTAL_ID); - if (err != FR_SUCCESS) - { - FRS_MACRO_ERROR(); - return err; - } - } - - delete[] shapes; shapes=NULL; - } - - } - else if (type == FR_LIGHT_TYPE_IES) - { - float radian4f[4]; - status = frLightGetInfo(light, FR_IES_LIGHT_RADIANT_POWER, sizeof(radian4f), radian4f, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_IES_LIGHT_RADIANT_POWER",FRSPT_FLOAT3,3*sizeof(float), radian4f) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - fr_ies_image_desc iesdesc; - status = frLightGetInfo(light, FR_IES_LIGHT_IMAGE_DESC, sizeof(iesdesc), &iesdesc, NULL); - CHECK_STATUS_RETURNERROR; - - if ( !Store_ObjectParameter("FR_IES_LIGHT_IMAGE_DESC_W",FRSPT_INT32_1,sizeof(iesdesc.w), &iesdesc.w) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - if ( !Store_ObjectParameter("FR_IES_LIGHT_IMAGE_DESC_H",FRSPT_INT32_1,sizeof(iesdesc.h), &iesdesc.h) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - if ( iesdesc.data ) - { - uint64_t dataSize = strlen(iesdesc.data)+1; // include null-terminated character - if ( !Store_ObjectParameter("FR_IES_LIGHT_IMAGE_DESC_DATA_SIZE",FRSPT_UINT64_1,sizeof(dataSize), &dataSize) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - if ( !Store_ObjectParameter("FR_IES_LIGHT_IMAGE_DESC_DATA",FRSPT_UNDEF,dataSize, iesdesc.data) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - } - else - { - WarningDetected(); - } - - } - else - { - FRS_MACRO_ERROR(); - return FR_ERROR_INVALID_PARAMETER; - } - - float lightTransform[16]; - status = frLightGetInfo(light, FR_LIGHT_TRANSFORM, sizeof(lightTransform), &lightTransform, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_LIGHT_TRANSFORM",FRSPT_FLOAT16,sizeof(lightTransform), lightTransform) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - //save FR_OBJECT_NAME of object. - size_t frobjectName_size = 0; - status = frLightGetInfo(light, FR_OBJECT_NAME, NULL, NULL, &frobjectName_size); - CHECK_STATUS_RETURNERROR; - if ( frobjectName_size <= 0 ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } // because of 0 terminated character, size must be >= 1 - char* frobjectName_data = new char[frobjectName_size]; - status = frLightGetInfo(light, FR_OBJECT_NAME, frobjectName_size, frobjectName_data, NULL); - CHECK_STATUS_RETURNERROR; - if ( frobjectName_data[frobjectName_size-1] != '\0' ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } // check that the last character is '\0' - if ( !Store_ObjectParameter("FR_OBJECT_NAME",FRSPT_UNDEF,frobjectName_size, frobjectName_data) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - delete[] frobjectName_data; frobjectName_data = NULL; - - - if ( !Store_EndObject() ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - return FR_SUCCESS; - -} - -fr_int FRS7::Store_Shape(fr_shape shape, const std::string& name) -{ - fr_int status = FR_SUCCESS; - - int indexFound = -1; - //search if this shape is already saved. - for (int iObj = 0; iObj < m_listObjectDeclared.size(); iObj++) - { - if (m_listObjectDeclared[iObj].type == "fr_shape" && m_listObjectDeclared[iObj].obj == shape) - { - indexFound = iObj; - break; - } - } - if ( indexFound != -1 ) - { - //if shape already saved, just save reference - if ( !Store_ReferenceToObject(name,"fr_shape",m_listObjectDeclared[indexFound].id) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - } - else - { - //if shape not already saved - - if ( !Store_StartObject(name,"fr_shape",shape) ) { return FR_ERROR_INTERNAL_ERROR; } - - fr_shape_type type; - status = frShapeGetInfo(shape, FR_SHAPE_TYPE, sizeof(fr_shape_type), &type, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_SHAPE_TYPE",FRSPT_UNDEF,sizeof(type), &type) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - if ( - type == FR_SHAPE_TYPE_MESH - ) - { - - //m_shapeList.push_back(shape); - - uint64_t poly_count = 0; - status = frMeshGetInfo(shape, FR_MESH_POLYGON_COUNT, sizeof(poly_count), &poly_count, NULL); //number of primitives - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_MESH_POLYGON_COUNT",FRSPT_UINT64_1,sizeof(poly_count), &poly_count) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - uint64_t vertex_count = 0; - status = frMeshGetInfo(shape, FR_MESH_VERTEX_COUNT, sizeof(vertex_count), &vertex_count, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_MESH_VERTEX_COUNT",FRSPT_UINT64_1,sizeof(vertex_count), &vertex_count) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - uint64_t normal_count = 0; - status = frMeshGetInfo(shape, FR_MESH_NORMAL_COUNT, sizeof(normal_count), &normal_count, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_MESH_NORMAL_COUNT",FRSPT_UINT64_1,sizeof(normal_count), &normal_count) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - uint64_t uv_count = 0; - status = frMeshGetInfo(shape, FR_MESH_UV_COUNT, sizeof(uv_count), &uv_count, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_MESH_UV_COUNT",FRSPT_UINT64_1,sizeof(uv_count), &uv_count) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - - if (vertex_count) - { - size_t required_size_size_t = 0; - status = frMeshGetInfo(shape, FR_MESH_VERTEX_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - float* data = new float[required_size / sizeof(float)]; - status = frMeshGetInfo(shape, FR_MESH_VERTEX_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_MESH_VERTEX_ARRAY",FRSPT_UINT64_1,required_size, data) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - delete[] data; data = NULL; - } - if (normal_count) - { - size_t required_size_size_t = 0; - status = frMeshGetInfo(shape, FR_MESH_NORMAL_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - float* data = new float[required_size / sizeof(float)]; - status = frMeshGetInfo(shape, FR_MESH_NORMAL_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_MESH_NORMAL_ARRAY",FRSPT_UINT64_1,required_size, data) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - delete[] data; data = NULL; - } - if (uv_count) - { - size_t required_size_size_t = 0; - status = frMeshGetInfo(shape, FR_MESH_UV_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - float* data = new float[required_size / sizeof(float)]; - status = frMeshGetInfo(shape, FR_MESH_UV_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_MESH_UV_ARRAY",FRSPT_UINT64_1,required_size, data) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - delete[] data; - data = NULL; - - } - if (poly_count) - { - size_t required_size_size_t = 0; - status = frMeshGetInfo(shape, FR_MESH_VERTEX_INDEX_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - int32_t* data = new int32_t[required_size / sizeof(int32_t)]; - status = frMeshGetInfo(shape, FR_MESH_VERTEX_INDEX_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_MESH_VERTEX_INDEX_ARRAY",FRSPT_UNDEF,required_size, data) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - delete[] data; data = NULL; - - } - if (normal_count) - { - size_t required_size_size_t = 0; - status = frMeshGetInfo(shape, FR_MESH_NORMAL_INDEX_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - int32_t* data = new int32_t[required_size / sizeof(int32_t)]; - status = frMeshGetInfo(shape, FR_MESH_NORMAL_INDEX_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_MESH_NORMAL_INDEX_ARRAY",FRSPT_UNDEF,required_size, data) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - delete[] data; data = NULL; - - } - if (uv_count) - { - size_t required_size_size_t = 0; - status = frMeshGetInfo(shape, FR_MESH_UV_INDEX_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - int32_t* data = new int32_t[required_size / sizeof(int32_t)]; - status = frMeshGetInfo(shape, FR_MESH_UV_INDEX_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_MESH_UV_INDEX_ARRAY",FRSPT_UNDEF,required_size, data) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - delete[] data; data = NULL; - - } - if (poly_count) - { - size_t required_size_size_t = 0; - status = frMeshGetInfo(shape, FR_MESH_NUM_FACE_VERTICES_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - int32_t* data = new int32_t[required_size / sizeof(int32_t)]; - status = frMeshGetInfo(shape, FR_MESH_NUM_FACE_VERTICES_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_MESH_NUM_VERTICES_ARRAY",FRSPT_UNDEF,required_size, data) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - delete[] data; data = NULL; - - } - - } - else if (type == FR_SHAPE_TYPE_INSTANCE) - { - //search address of original shape - - fr_shape shapeOriginal = NULL; - status = frInstanceGetBaseShape(shape, &shapeOriginal); - CHECK_STATUS_RETURNERROR; - - if (shapeOriginal == 0) - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - - bool found = false; - for (int iShape = 0; iShape < m_listObjectDeclared.size(); iShape++) - { - if (m_listObjectDeclared[iShape].type == "fr_shape" && m_listObjectDeclared[iShape].obj == shapeOriginal) - { - int32_t IDShapeBase = m_listObjectDeclared[iShape].id; - if ( !Store_ObjectParameter(STR__SHAPE_INSTANCE_REFERENCE_ID,FRSPT_INT32_1,sizeof(IDShapeBase), &IDShapeBase) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - found = true; - break; - } - } - - if (!found) - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - - } - - - fr_material_node data_shader = 0; - status = frShapeGetInfo(shape, FR_SHAPE_MATERIAL, sizeof(data_shader), &data_shader, NULL); - CHECK_STATUS_RETURNERROR; - if (data_shader != NULL) - { - fr_int error = Store_MaterialNode(data_shader,"shaderOfShape"); - if (error != FR_SUCCESS) - { - return error; - } - } - - - float data_transform[16]; - status = frShapeGetInfo(shape, FR_SHAPE_TRANSFORM, sizeof(data_transform), data_transform, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_SHAPE_TRANSFORM",FRSPT_FLOAT16,sizeof(data_transform), data_transform) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - - float data_linMotion[4]; - status = frShapeGetInfo(shape, FR_SHAPE_LINEAR_MOTION, sizeof(data_linMotion) , data_linMotion, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_SHAPE_LINEAR_MOTION",FRSPT_FLOAT3,3*sizeof(float), data_linMotion) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - float data_angMotion[4]; - status = frShapeGetInfo(shape, FR_SHAPE_ANGULAR_MOTION, sizeof(data_angMotion) , data_angMotion, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_SHAPE_ANGULAR_MOTION",FRSPT_FLOAT4,sizeof(data_angMotion), data_angMotion) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - fr_bool data_visFlag; - status = frShapeGetInfo(shape, FR_SHAPE_VISIBILITY_FLAG, sizeof(data_visFlag), &data_visFlag, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_SHAPE_VISIBILITY",FRSPT_INT32_1,sizeof(data_visFlag), &data_visFlag) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - fr_bool data_shadoflag; - status = frShapeGetInfo(shape, FR_SHAPE_SHADOW_FLAG, sizeof(data_shadoflag), &data_shadoflag, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_SHAPE_SHADOW",FRSPT_INT32_1,sizeof(data_shadoflag), &data_shadoflag) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - fr_bool data_shadocatcherflag; - status = frShapeGetInfo(shape, FR_SHAPE_SHADOW_CATCHER_FLAG, sizeof(data_shadocatcherflag), &data_shadocatcherflag, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_SHAPE_SHADOW_CATCHER",FRSPT_INT32_1,sizeof(data_shadocatcherflag), &data_shadocatcherflag) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - - fr_uint data_subdiv; - status = frShapeGetInfo(shape, FR_SHAPE_SUBDIVISION_FACTOR, sizeof(data_subdiv), &data_subdiv, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_SHAPE_SUBDIVISION_FACTOR",FRSPT_UINT32_1,sizeof(data_subdiv), &data_subdiv) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - fr_float data_displacementscale[2]; - status = frShapeGetInfo(shape, FR_SHAPE_DISPLACEMENT_SCALE, sizeof(data_displacementscale), &data_displacementscale, NULL); - CHECK_STATUS_RETURNERROR; - if ( !Store_ObjectParameter("FR_SHAPE_DISPLACEMENT_SCALE",FRSPT_FLOAT2,sizeof(data_displacementscale), &data_displacementscale) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - fr_image displacementimage = NULL; - status = frShapeGetInfo(shape, FR_SHAPE_DISPLACEMENT_IMAGE, sizeof(fr_image), &displacementimage, NULL); - CHECK_STATUS_RETURNERROR; - if ( displacementimage ) - { - status = Store_Image(displacementimage,"FR_SHAPE_DISPLACEMENT_IMAGE"); - CHECK_STATUS_RETURNERROR; - } - - - //save FR_OBJECT_NAME of object. - size_t frobjectName_size = 0; - status = frShapeGetInfo(shape, FR_OBJECT_NAME, NULL, NULL, &frobjectName_size); - CHECK_STATUS_RETURNERROR; - if ( frobjectName_size <= 0 ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } // because of 0 terminated character, size must be >= 1 - char* frobjectName_data = new char[frobjectName_size]; - status = frShapeGetInfo(shape, FR_OBJECT_NAME, frobjectName_size, frobjectName_data, NULL); - CHECK_STATUS_RETURNERROR; - if ( frobjectName_data[frobjectName_size-1] != '\0' ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } // check that the last character is '\0' - if ( !Store_ObjectParameter("FR_OBJECT_NAME",FRSPT_UNDEF,frobjectName_size, frobjectName_data) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - delete[] frobjectName_data; frobjectName_data = NULL; - - - if ( !Store_EndObject() ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - } - return FR_SUCCESS; -} - - -fr_int FRS7::Store_Image(fr_image image, const std::string& name) -{ - - fr_int status = FR_SUCCESS; - - - int indexFound = -1; - //search if this image is already saved. - for (int iObj = 0; iObj < m_listObjectDeclared.size(); iObj++) - { - if (m_listObjectDeclared[iObj].type == "fr_image" && m_listObjectDeclared[iObj].obj == image) - { - indexFound = iObj; - break; - } - } - if ( indexFound != -1 ) - { - //if image already saved, just save reference - if ( !Store_ReferenceToObject(name,"fr_image",m_listObjectDeclared[indexFound].id) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - } - else - { - //if image not already saved - - - if ( !Store_StartObject(name,"fr_image",image) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - - //auto pos = std::find(m_imageList.begin(), m_imageList.end(), image); - //if (pos == m_imageList.end()) - //{ - // //if image not already saved - // m_imageList.push_back(image); - // int32_t imageIndex = -1; // index = -1 --> means that the image was not already saved prviously - // myfile->write((const char*)&imageIndex, sizeof(imageIndex)); - //} - //else - //{ - // //if image already saved - // int32_t imageIndex = (int32_t)(pos - m_imageList.begin()); - // myfile->write((const char*)&imageIndex, sizeof(imageIndex)); - // myfile->write((const char*)&m_IMAGE_END, sizeof(m_IMAGE_END)); - // return FR_SUCCESS; - //} - - - fr_image_format format; - status = frImageGetInfo(image, FR_IMAGE_FORMAT, sizeof(format), &format, NULL); - CHECK_STATUS_RETURNERROR; - //myfile->write((char*)&format, sizeof(fr_image_format)); - if ( !Store_ObjectParameter("FR_IMAGE_FORMAT",FRSPT_UNDEF,sizeof(fr_image_format), &format) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - fr_image_desc desc; - status = frImageGetInfo(image, FR_IMAGE_DESC, sizeof(desc), &desc, NULL); - CHECK_STATUS_RETURNERROR - //myfile->write((char*)&desc, sizeof(fr_image_desc)); - if ( !Store_ObjectParameter("FR_IMAGE_DESC",FRSPT_UNDEF,sizeof(fr_image_desc), &desc) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - size_t size_size_t = 0; - status = frImageGetInfo(image, FR_IMAGE_DATA, 0, NULL, &size_size_t); - uint64_t size = size_size_t; - CHECK_STATUS_RETURNERROR - char *idata = new char[size]; - //myfile->write((char*)&size, sizeof(uint64_t)); - status = frImageGetInfo(image, FR_IMAGE_DATA, size, idata, NULL); - CHECK_STATUS_RETURNERROR - //myfile->write(idata, size); - if ( !Store_ObjectParameter("FR_IMAGE_DATA",FRSPT_UNDEF,size, idata) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - delete[] idata; idata = NULL; - - - //save FR_OBJECT_NAME of object. - size_t frobjectName_size = 0; - status = frImageGetInfo(image, FR_OBJECT_NAME, NULL, NULL, &frobjectName_size); - CHECK_STATUS_RETURNERROR; - if ( frobjectName_size <= 0 ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } // because of 0 terminated character, size must be >= 1 - char* frobjectName_data = new char[frobjectName_size]; - status = frImageGetInfo(image, FR_OBJECT_NAME, frobjectName_size, frobjectName_data, NULL); - CHECK_STATUS_RETURNERROR; - if ( frobjectName_data[frobjectName_size-1] != '\0' ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } // check that the last character is '\0' - if ( !Store_ObjectParameter("FR_OBJECT_NAME",FRSPT_UNDEF,frobjectName_size, frobjectName_data) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - delete[] frobjectName_data; frobjectName_data = NULL; - - - if ( !Store_EndObject() ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - } - return status; -} - - - -fr_int FRS7::Store_Scene(fr_scene scene) -{ - fr_int status = FR_SUCCESS; - - if ( !Store_StartObject("sceneDeclare","fr_scene",scene) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - uint64_t nbShape = 0; - status = frSceneGetInfo(scene, FR_SCENE_SHAPE_COUNT, sizeof(nbShape), &nbShape, NULL); - CHECK_STATUS_RETURNERROR; - uint64_t nbLight = 0; - status = frSceneGetInfo(scene, FR_SCENE_LIGHT_COUNT, sizeof(nbLight), &nbLight, NULL); - CHECK_STATUS_RETURNERROR; - //uint64_t nbTexture = 0; - //status = frSceneGetInfo(scene, FR_SCENE_TEXTURE_COUNT, sizeof(nbTexture), &nbTexture, NULL); - //CHECK_STATUS_RETURNERROR; - - - //myfile->write((char*)&nbShape, sizeof(nbShape)); - //myfile->write((char*)&nbLight, sizeof(nbLight)); - //myfile->write((char*)&nbTexture, sizeof(nbTexture)); - - fr_shape* shapes = NULL; - fr_light* light = NULL; - - if ( nbShape >= 1 ) - { - shapes = new fr_shape[nbShape]; - status = frSceneGetInfo(scene, FR_SCENE_SHAPE_LIST, nbShape * sizeof(fr_shape), shapes, NULL); - CHECK_STATUS_RETURNERROR; - } - - if ( nbLight >= 1 ) - { - light = new fr_light[nbLight]; - status = frSceneGetInfo(scene, FR_SCENE_LIGHT_LIST, nbLight * sizeof(fr_light), light, NULL); - CHECK_STATUS_RETURNERROR; - } - - - for (uint64_t i = 0; i < nbShape; i++) // first: store non-instanciate shapes - { - fr_shape_type type; - status = frShapeGetInfo(shapes[i], FR_SHAPE_TYPE, sizeof(fr_shape_type), &type, NULL); - CHECK_STATUS_RETURNERROR; - if (type == FR_SHAPE_TYPE_MESH) - { - fr_int err = Store_Shape(shapes[i],"nonInstancedSceneShape"); - if (err != FR_SUCCESS) - { - FRS_MACRO_ERROR(); - return err; // easier for debug if stop everything - } - } - } - - for (uint64_t i = 0; i < nbShape; i++)// second: store instanciate shapes only - { - fr_shape_type type; - status = frShapeGetInfo(shapes[i], FR_SHAPE_TYPE, sizeof(fr_shape_type), &type, NULL); - CHECK_STATUS_RETURNERROR; - if (type != FR_SHAPE_TYPE_MESH) - { - fr_int err = Store_Shape(shapes[i],"InstancedSceneShape"); - if (err != FR_SUCCESS) - { - FRS_MACRO_ERROR(); - return err; // easier for debug if stop everything - } - } - } - - for (uint64_t i = 0; i < nbLight; i++) - { - fr_int err = Store_Light(light[i],scene); - if (err != FR_SUCCESS) - { - FRS_MACRO_ERROR(); - return err; // easier for debug if stop everything - } - } - - if ( shapes ) { delete[] shapes; shapes = NULL; } - if ( light ) { delete[] light; light = NULL;} - - fr_camera camera = NULL; - status = frSceneGetCamera(scene, &camera); - CHECK_STATUS_RETURNERROR; - - if (camera) - { - status = Store_Camera(camera); - CHECK_STATUS_RETURNERROR; - } - - //save FR_OBJECT_NAME of object. - size_t frobjectName_size = 0; - status = frSceneGetInfo(scene, FR_OBJECT_NAME, NULL, NULL, &frobjectName_size); - CHECK_STATUS_RETURNERROR; - if ( frobjectName_size <= 0 ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } // because of 0 terminated character, size must be >= 1 - char* frobjectName_data = new char[frobjectName_size]; - status = frSceneGetInfo(scene, FR_OBJECT_NAME, frobjectName_size, frobjectName_data, NULL); - CHECK_STATUS_RETURNERROR; - if ( frobjectName_data[frobjectName_size-1] != '\0' ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } // check that the last character is '\0' - if ( !Store_ObjectParameter("FR_OBJECT_NAME",FRSPT_UNDEF,frobjectName_size, frobjectName_data) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - delete[] frobjectName_data; frobjectName_data = NULL; - - - if ( !Store_EndObject() ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - return FR_SUCCESS; - -} - - -fr_int FRS7::Store_Context(fr_context context) -{ - - fr_int status = FR_SUCCESS; - - if ( !Store_StartObject("contextDeclare","fr_context",context) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - uint64_t param_count = 0; - status = frContextGetInfo(context, FR_CONTEXT_PARAMETER_COUNT, sizeof(uint64_t), ¶m_count, NULL); - CHECK_STATUS_RETURNERROR; - - unsigned int imagefilter_type = -1; - unsigned int tonemapping_type = -1; - - for (int iPass = 0; iPass < 2; iPass++) - { - for (uint64_t i = 0; i < param_count; i++) - { - size_t name_length_size_t = 0; - status = frContextGetParameterInfo(context, int(i), FR_PARAMETER_NAME_STRING, 0, NULL, &name_length_size_t); - uint64_t name_length = name_length_size_t; - CHECK_STATUS_RETURNERROR; - char* paramName = new char[name_length]; - status = frContextGetParameterInfo(context, int(i), FR_PARAMETER_NAME_STRING, name_length, paramName, NULL); - CHECK_STATUS_RETURNERROR; - if ( paramName[name_length-1] != 0 ) // supposed to be null-terminated - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - - fr_context_info paramID = 0; - status = frContextGetParameterInfo(context, int(i), FR_PARAMETER_NAME, sizeof(paramID), ¶mID, NULL); - CHECK_STATUS_RETURNERROR; - - //need to store in 2 passes. - //first, we store the parameters that will set several default parameters. - //so we are sure that all custom parameters will be set during the load of context - if ( - (iPass == 0 && ( paramID == FR_CONTEXT_IMAGE_FILTER_TYPE || paramID == FR_CONTEXT_TONE_MAPPING_TYPE )) - || - (iPass == 1 && paramID != FR_CONTEXT_IMAGE_FILTER_TYPE && paramID != FR_CONTEXT_TONE_MAPPING_TYPE) - ) - { - - //don't store values that don't fitt with filter/tonemap types - bool storeValue = true; - if ( paramID == FR_CONTEXT_IMAGE_FILTER_BOX_RADIUS && imagefilter_type != FR_FILTER_BOX ) { storeValue = false; } - if ( paramID == FR_CONTEXT_IMAGE_FILTER_GAUSSIAN_RADIUS && imagefilter_type != FR_FILTER_GAUSSIAN ) { storeValue = false; } - if ( paramID == FR_CONTEXT_IMAGE_FILTER_TRIANGLE_RADIUS && imagefilter_type != FR_FILTER_TRIANGLE ) { storeValue = false; } - if ( paramID == FR_CONTEXT_IMAGE_FILTER_MITCHELL_RADIUS && imagefilter_type != FR_FILTER_MITCHELL ) { storeValue = false; } - if ( paramID == FR_CONTEXT_IMAGE_FILTER_LANCZOS_RADIUS && imagefilter_type != FR_FILTER_LANCZOS ) { storeValue = false; } - if ( paramID == FR_CONTEXT_IMAGE_FILTER_BLACKMANHARRIS_RADIUS && imagefilter_type != FR_FILTER_BLACKMANHARRIS ) { storeValue = false; } - - if ( paramID == FR_CONTEXT_TONE_MAPPING_LINEAR_SCALE && tonemapping_type != FR_TONEMAPPING_OPERATOR_LINEAR ) { storeValue = false; } - if ( paramID == FR_CONTEXT_TONE_MAPPING_PHOTO_LINEAR_SENSITIVITY && tonemapping_type != FR_TONEMAPPING_OPERATOR_PHOTOLINEAR ) { storeValue = false; } - if ( paramID == FR_CONTEXT_TONE_MAPPING_PHOTO_LINEAR_EXPOSURE && tonemapping_type != FR_TONEMAPPING_OPERATOR_PHOTOLINEAR ) { storeValue = false; } - if ( paramID == FR_CONTEXT_TONE_MAPPING_PHOTO_LINEAR_FSTOP && tonemapping_type != FR_TONEMAPPING_OPERATOR_PHOTOLINEAR ) { storeValue = false; } - if ( paramID == FR_CONTEXT_TONE_MAPPING_REINHARD02_PRE_SCALE && tonemapping_type != FR_TONEMAPPING_OPERATOR_REINHARD02 ) { storeValue = false; } - if ( paramID == FR_CONTEXT_TONE_MAPPING_REINHARD02_POST_SCALE && tonemapping_type != FR_TONEMAPPING_OPERATOR_REINHARD02 ) { storeValue = false; } - if ( paramID == FR_CONTEXT_TONE_MAPPING_REINHARD02_BURN && tonemapping_type != FR_TONEMAPPING_OPERATOR_REINHARD02 ) { storeValue = false; } - - - - if ( storeValue ) - { - fr_parameter_type type; - status = frContextGetParameterInfo(context, int(i), FR_PARAMETER_TYPE, sizeof(type), &type, NULL); - CHECK_STATUS_RETURNERROR; - - size_t value_length_size_t = 0; - status = frContextGetParameterInfo(context, int(i), FR_PARAMETER_VALUE, 0, NULL, &value_length_size_t); - uint64_t value_length = value_length_size_t; - CHECK_STATUS_RETURNERROR; - - char* paramValue = NULL; - if (value_length > 0) - { - paramValue = new char[value_length]; - status = frContextGetParameterInfo(context, int(i), FR_PARAMETER_VALUE, value_length, paramValue, NULL); - CHECK_STATUS_RETURNERROR; - - if ( paramID == FR_CONTEXT_IMAGE_FILTER_TYPE && type == FR_PARAMETER_TYPE_UINT) - { - imagefilter_type = ((unsigned int*)(paramValue))[0]; - } - if ( paramID == FR_CONTEXT_TONE_MAPPING_TYPE && type == FR_PARAMETER_TYPE_UINT) - { - tonemapping_type = ((unsigned int*)(paramValue))[0]; - } - - } - - if ( !Store_ObjectParameter(paramName,FRPARAMETERTYPE_to_FRSPT(type),value_length,paramValue) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - if ( paramValue ) { delete[] paramValue; paramValue = NULL; } - } - } - - delete[] paramName; paramName = NULL; - } - } - - - //save FR_OBJECT_NAME of object. - size_t frobjectName_size = 0; - status = frContextGetInfo(context, FR_OBJECT_NAME, NULL, NULL, &frobjectName_size); - CHECK_STATUS_RETURNERROR; - if ( frobjectName_size <= 0 ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } // because of 0 terminated character, size must be >= 1 - char* frobjectName_data = new char[frobjectName_size]; - status = frContextGetInfo(context, FR_OBJECT_NAME, frobjectName_size, frobjectName_data, NULL); - CHECK_STATUS_RETURNERROR; - if ( frobjectName_data[frobjectName_size-1] != '\0' ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } // check that the last character is '\0' - if ( !Store_ObjectParameter("FR_OBJECT_NAME",FRSPT_UNDEF,frobjectName_size, frobjectName_data) ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - delete[] frobjectName_data; frobjectName_data = NULL; - - - - if ( !Store_EndObject() ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - return FR_SUCCESS; -} - - -bool FRS7::Store_String( const std::string& str) -{ - uint32_t strSize = (uint32_t)str.length(); - m_frsFile->write((const char*)&strSize, sizeof(strSize)); - if ( strSize > 0 ) - { - m_frsFile->write((const char*)str.c_str(), strSize); - } - return true; -} - -bool FRS7::Store_ReferenceToObject(const std::string& objName, const std::string& type, int32_t id) -{ - //just for debug purpose, we check that the referenced ID actually exists - bool found = false; - for(int i=0; iwrite((char*)&typeWrite, sizeof(int32_t)); - if ( !Store_String(objName)) { FRS_MACRO_ERROR(); return false; } - if ( !Store_String(type.c_str())) { FRS_MACRO_ERROR(); return false; } - m_frsFile->write((const char*)&id, sizeof(id)); - - return true; -} - -bool FRS7::Store_StartObject( const std::string& objName,const std::string& type, void* obj) -{ - FRS_ELEMENTS_TYPE typeWrite = FRSRT_OBJECT_BEG; - m_frsFile->write((char*)&typeWrite, sizeof(int32_t)); - if ( !Store_String(objName)) { FRS_MACRO_ERROR(); return false; } - if ( !Store_String(type.c_str())) { FRS_MACRO_ERROR(); return false; } - m_frsFile->write((const char*)&m_idCounter, sizeof(m_idCounter)); - - RPS_OBJECT_DECLARED newObj; - newObj.id = m_idCounter; - newObj.type = type; - newObj.obj = obj; - m_listObjectDeclared.push_back(newObj); - - m_level++; - m_idCounter++; - - return true; -} - -bool FRS7::Store_EndObject() -{ - m_level--; - if ( m_level < 0 ) - { - FRS_MACRO_ERROR(); - return false; - } - - FRS_ELEMENTS_TYPE typeWrite = FRSRT_OBJECT_END; - m_frsFile->write((char*)&typeWrite, sizeof(int32_t)); - Store_String(""); // empty string - return true; -} - -bool FRS7::Store_ObjectParameter( const std::string& parameterName,FRS_PARAMETER_TYPE type,uint64_t dataSize, const void* data) -{ - if ( data == NULL && dataSize > 0 ) - { - FRS_MACRO_ERROR(); - return false; - } - if ( sizeof(FRS_PARAMETER_TYPE) != sizeof(uint32_t) ) - { - FRS_MACRO_ERROR(); - return false; - } - - int32_t sizeOfFRSPT = FRSPT_to_size(type); - if ( sizeOfFRSPT != -1 && sizeOfFRSPT != dataSize ) - { - FRS_MACRO_ERROR(); - return false; - } - - FRS_ELEMENTS_TYPE typeWrite = FRSRT_PARAMETER; - m_frsFile->write((char*)&typeWrite, sizeof(int32_t)); - if ( !Store_String(parameterName)){ FRS_MACRO_ERROR(); return false; } - m_frsFile->write((const char*)&type, sizeof(type)); - m_frsFile->write((const char*)&dataSize, sizeof(dataSize)); - m_frsFile->write((const char*)data, dataSize); - return true; -} - -int32_t FRS7::FRSPT_to_size(FRS_PARAMETER_TYPE in) -{ - if ( in == FRSPT_FLOAT1 ) { return sizeof(float)*1; } - else if ( in == FRSPT_FLOAT2 ) { return sizeof(float)*2; } - else if ( in == FRSPT_FLOAT3 ) { return sizeof(float)*3; } - else if ( in == FRSPT_FLOAT4 ) { return sizeof(float)*4; } - else if ( in == FRSPT_FLOAT16 ) { return sizeof(float)*16; } - - else if ( in == FRSPT_UINT32_1 ) { return sizeof(uint32_t)*1; } - return -1; -} - -fr_parameter_type FRS7::FRSPT_to_FRPARAMETERTYPE(FRS_PARAMETER_TYPE in) -{ - if ( in == FRSPT_FLOAT1 ) { return FR_PARAMETER_TYPE_FLOAT; } - else if ( in == FRSPT_FLOAT2 ) { return FR_PARAMETER_TYPE_FLOAT2; } - else if ( in == FRSPT_FLOAT3 ) { return FR_PARAMETER_TYPE_FLOAT3; } - else if ( in == FRSPT_FLOAT4 ) { return FR_PARAMETER_TYPE_FLOAT4; } - else if ( in == FRSPT_UINT32_1 ) { return FR_PARAMETER_TYPE_UINT; } - FRS_MACRO_ERROR(); - return 0; -} - -FRS7::FRS_PARAMETER_TYPE FRS7::FRPARAMETERTYPE_to_FRSPT(fr_parameter_type in) -{ - if ( in == FR_PARAMETER_TYPE_FLOAT ) { return FRSPT_FLOAT1; } - else if ( in == FR_PARAMETER_TYPE_FLOAT2 ) { return FRSPT_FLOAT2; } - else if ( in == FR_PARAMETER_TYPE_FLOAT3 ) { return FRSPT_FLOAT3; } - else if ( in == FR_PARAMETER_TYPE_FLOAT4 ) { return FRSPT_FLOAT4; } - else if ( in == FR_PARAMETER_TYPE_IMAGE ) { return FRSPT_UNDEF; } - else if ( in == FR_PARAMETER_TYPE_STRING ) { return FRSPT_UNDEF; } - else if ( in == FR_PARAMETER_TYPE_SHADER ) { return FRSPT_UNDEF; } - else if ( in == FR_PARAMETER_TYPE_UINT ) { return FRSPT_UINT32_1; } - return FRSPT_UNDEF; -} - - -fr_int FRS7::LoadEverything( - fr_context context, - fr_material_system materialSystem, - fr_scene& scene, - bool useAlreadyExistingScene - ) -{ - - fr_int status = FR_SUCCESS; - - //check arguments: - if (context == NULL) { FRS_MACRO_ERROR(); return FR_ERROR_INVALID_PARAMETER; } - if (scene != NULL && !useAlreadyExistingScene ) { FRS_MACRO_ERROR(); return FR_ERROR_INVALID_PARAMETER; } - if (scene == NULL && useAlreadyExistingScene ) { FRS_MACRO_ERROR(); return FR_ERROR_INVALID_PARAMETER; } - - char headCheckCode[4] = {0,0,0,0}; - m_frsFile->read(headCheckCode, sizeof(headCheckCode)); - if (headCheckCode[0] != m_HEADER_CHECKCODE[0] || - headCheckCode[1] != m_HEADER_CHECKCODE[1] || - headCheckCode[2] != m_HEADER_CHECKCODE[2] || - headCheckCode[3] != m_HEADER_CHECKCODE[3] ) - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - - m_frsFile->read((char*)&m_fileVersionOfLoadFile, sizeof(m_fileVersionOfLoadFile)); - if (m_fileVersionOfLoadFile != m_FILE_VERSION) - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - - fr_int succes = Read_Context(context); - if (succes != FR_SUCCESS) - { - FRS_MACRO_ERROR(); - return succes; - } - - - fr_scene newScene = Read_Scene(context, materialSystem, useAlreadyExistingScene ? scene : NULL); - if (newScene == 0) - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - - - - //load extra custom param - while(true) - { - std::string elementName; - std::string objBegType; - FRS_ELEMENTS_TYPE nextElem = Read_whatsNext(elementName,objBegType); - if ( nextElem == FRSRT_PARAMETER ) - { - std::string paramName; - FRS_PARAMETER_TYPE paramType = FRSPT_UNDEF; - uint64_t paramDataSize = 0; - if ( Read_Element_Parameter(paramName,paramType,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - if ( paramDataSize > 0 ) - { - //char* data_data = new char[paramDataSize]; - - - if (paramType == FRSPT_INT32_1) - { - fr_int data_int; - if ( Read_Element_ParameterData(&data_int,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - if (paramDataSize == sizeof(fr_int)) - { - m_extraCustomParam_int[paramName] = data_int; - } - else - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - - } - else if (paramType == FRSPT_FLOAT1) - { - fr_float data_float; - if ( Read_Element_ParameterData(&data_float,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - if (paramDataSize == sizeof(fr_float)) - { - m_extraCustomParam_float[paramName] = data_float; - } - else - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - } - else - { - char* data_data = new char[paramDataSize]; - if ( Read_Element_ParameterData(data_data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - WarningDetected(); - - delete[] data_data; data_data = NULL; - } - - //delete[] data_data; data_data = NULL; - } - - } - else if ( nextElem == FRSRT_UNDEF ) // if reached end of file - { - break; - } - else - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - - - } - - - - - if ( !useAlreadyExistingScene ) - { - scene = newScene; - } - - //overwrite the gamma with the 3dsmax gamma - auto dsmax_gammaenabled_found = m_extraCustomParam_int.find("3dsmax.gammaenabled"); - auto dsmax_displaygamma_found = m_extraCustomParam_float.find("3dsmax.displaygamma"); - if ( dsmax_gammaenabled_found != m_extraCustomParam_int.end() && dsmax_displaygamma_found != m_extraCustomParam_float.end() ) - { - if ( m_extraCustomParam_int["3dsmax.gammaenabled"] != 0 ) - { - status = frContextSetParameter1f(context,"displaygamma" , m_extraCustomParam_float["3dsmax.displaygamma"]); - if (status != FR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - } - - if ( m_level != 0 ) - { - //if level is not 0, this means we have not closed all object delaration - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - - - return FR_SUCCESS; -} - - -fr_int FRS7::Read_Context(fr_context context) -{ - fr_int status = FR_SUCCESS; - - - std::string objName; - std::string objType; - int32_t objID = 0; - if ( Read_Element_StartObject(objName, objType, objID) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - if ( objType != "fr_context" ) - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - - - while(true) - { - std::string elementName; - std::string objBegType; - FRS_ELEMENTS_TYPE nextElem = Read_whatsNext(elementName,objBegType); - if ( nextElem == FRSRT_PARAMETER ) - { - std::string paramName; - FRS_PARAMETER_TYPE paramType = FRSPT_UNDEF; - uint64_t paramDataSize = 0; - if ( Read_Element_Parameter(paramName,paramType,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - if ( paramDataSize > 0 ) - { - - - if (paramType == FRSPT_UINT32_1) - { - fr_uint data_uint; - if ( Read_Element_ParameterData(&data_uint,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - if (paramDataSize == sizeof(fr_uint)) - { - status = frContextSetParameter1u(context, paramName.c_str(), (fr_uint)data_uint); - if (status != FR_SUCCESS) - { - if ( paramName != "stacksize" ) // "stacksize" is read only. so it's expected to have an error - { - WarningDetected(); // this is minor error, we wont exit loader for that - } - } - } - else - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - - } - else if (paramType == FRSPT_FLOAT1) - { - fr_float data_float; - if ( Read_Element_ParameterData(&data_float,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - if (paramDataSize == sizeof(fr_float)) - { - - status = frContextSetParameter1f(context, paramName.c_str(), data_float); - if (status != FR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - - } - else - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - } - else if (paramType == FRSPT_FLOAT2) - { - fr_float data_float[2]; - if ( Read_Element_ParameterData(data_float,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - if (paramDataSize == 2*sizeof(fr_float)) - { - status = frContextSetParameter3f(context, paramName.c_str(), data_float[0], data_float[1], 0.0); - if (status != FR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - else - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - } - else if (paramType == FRSPT_FLOAT3) - { - fr_float data_float[3]; - if ( Read_Element_ParameterData(data_float,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - if (paramDataSize == 3*sizeof(fr_float)) - { - status = frContextSetParameter3f(context, paramName.c_str(), data_float[0], data_float[1], data_float[2]); - if (status != FR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - else - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - } - else if (paramType == FRSPT_FLOAT4) - { - fr_float data_float[4]; - if ( Read_Element_ParameterData(data_float,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - if (paramDataSize == 4*sizeof(fr_float)) - { - status = frContextSetParameter4f(context, paramName.c_str(), data_float[0], data_float[1], data_float[2], data_float[3]); - if (status != FR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - else - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - } - else if ( paramType == FRSPT_UNDEF && paramName == "FR_OBJECT_NAME" ) - { - char* data_data = new char[paramDataSize]; - if ( Read_Element_ParameterData(data_data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - status = frObjectSetName(context,data_data); - CHECK_STATUS_RETURNERROR; - delete[] data_data; data_data = NULL; - } - - - // read only parameter. don't set it. - else if ( (paramType == FRSPT_UNDEF && paramName == "gpu0name") - || (paramType == FRSPT_UNDEF && paramName == "gpu1name") - || (paramType == FRSPT_UNDEF && paramName == "gpu2name") - || (paramType == FRSPT_UNDEF && paramName == "gpu3name") - || (paramType == FRSPT_UNDEF && paramName == "gpu4name") - || (paramType == FRSPT_UNDEF && paramName == "gpu5name") - || (paramType == FRSPT_UNDEF && paramName == "gpu6name") - || (paramType == FRSPT_UNDEF && paramName == "gpu7name") - || (paramType == FRSPT_UNDEF && paramName == "cpuname") - ) - { - char* data_data = new char[paramDataSize]; - if ( Read_Element_ParameterData(data_data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - delete[] data_data; data_data = NULL; - } - - - else - { - char* data_data = new char[paramDataSize]; - if ( Read_Element_ParameterData(data_data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - WarningDetected(); - - delete[] data_data; data_data = NULL; - } - - - } - else - { - WarningDetected(); - } - - } - else if ( nextElem == FRSRT_OBJECT_END ) - { - break; - } - else - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - - - } - - - if ( Read_Element_EndObject("fr_context",context,objID) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - - return FR_SUCCESS; -} - -fr_camera FRS7::Read_Camera(fr_context context) -{ - fr_int status = FR_SUCCESS; - - std::string objName; - std::string objType; - int32_t objID = 0; - if ( Read_Element_StartObject(objName, objType, objID) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - if ( objType != "fr_camera" ) - { - FRS_MACRO_ERROR(); - return NULL; - } - - fr_camera camera = NULL; - status = frContextCreateCamera(context,&camera); - CHECK_STATUS_RETURNNULL; - - bool param_pos_declared = false; - fr_float param_pos[3]; - bool param_at_declared = false; - fr_float param_at[3]; - bool param_up_declared = false; - fr_float param_up[3]; - - while(true) - { - - std::string elementName; - std::string objBegType; - FRS_ELEMENTS_TYPE nextElem = Read_whatsNext(elementName,objBegType); - if ( nextElem == FRSRT_PARAMETER ) - { - std::string paramName; - FRS_PARAMETER_TYPE paramType = FRSPT_UNDEF; - uint64_t paramDataSize = 0; - if ( Read_Element_Parameter(paramName,paramType,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - - if ( paramDataSize > 0 ) - { - - if ( paramName == "FR_CAMERA_FSTOP" && paramType == FRSPT_FLOAT1 ) - { - float param_fstop; - if ( Read_Element_ParameterData(¶m_fstop,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frCameraSetFStop(camera, param_fstop); - CHECK_STATUS_RETURNNULL; - } - - else if ( paramName == "FR_CAMERA_APERTURE_BLADES" && paramType == FRSPT_UINT32_1 ) - { - unsigned int param_apblade; - if ( Read_Element_ParameterData(¶m_apblade,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frCameraSetApertureBlades(camera, param_apblade); - CHECK_STATUS_RETURNNULL; - } - else if ( paramName == "FR_CAMERA_EXPOSURE" && paramType == FRSPT_FLOAT1 ) - { - float param_camexpo; - if ( Read_Element_ParameterData(¶m_camexpo,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frCameraSetExposure(camera, param_camexpo); - CHECK_STATUS_RETURNNULL; - } - else if ( paramName == "FR_CAMERA_FOCAL_LENGTH" && paramType == FRSPT_FLOAT1 ) - { - float param_focalLen; - if ( Read_Element_ParameterData(¶m_focalLen,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frCameraSetFocalLength(camera, param_focalLen); - CHECK_STATUS_RETURNNULL; - } - else if ( paramName == "FR_CAMERA_SENSOR_SIZE" && paramType == FRSPT_FLOAT2 ) - { - float param_sensorsize[2]; - if ( Read_Element_ParameterData(param_sensorsize,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frCameraSetSensorSize(camera, param_sensorsize[0], param_sensorsize[1]); - CHECK_STATUS_RETURNNULL; - } - else if ( paramName == "FR_CAMERA_MODE" && paramType == FRSPT_UINT32_1 ) - { - fr_camera_mode param_mode; - if ( Read_Element_ParameterData(¶m_mode,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frCameraSetMode(camera, param_mode); - CHECK_STATUS_RETURNNULL; - } - else if ( paramName == "FR_CAMERA_ORTHO_WIDTH" && paramType == FRSPT_FLOAT1 ) - { - float param_orthowidth; - if ( Read_Element_ParameterData(¶m_orthowidth,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frCameraSetOrthoWidth(camera, param_orthowidth); - CHECK_STATUS_RETURNNULL; - } - else if (paramName == "FR_CAMERA_ORTHO_HEIGHT" && paramType == FRSPT_FLOAT1) - { - float param_orthoheight; - if (Read_Element_ParameterData(¶m_orthoheight, paramDataSize) != FR_SUCCESS) { FRS_MACRO_ERROR(); return NULL; } - status = frCameraSetOrthoHeight(camera, param_orthoheight); - CHECK_STATUS_RETURNNULL; - } - else if ( paramName == "FR_CAMERA_FOCUS_DISTANCE" && paramType == FRSPT_FLOAT1 ) - { - float param_focusdist; - if ( Read_Element_ParameterData(¶m_focusdist,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frCameraSetFocusDistance(camera, param_focusdist); - CHECK_STATUS_RETURNNULL; - } - else if ( paramName == "FR_CAMERA_POSITION" && paramType == FRSPT_FLOAT3 ) - { - param_pos_declared = true; - if ( Read_Element_ParameterData(param_pos,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if ( paramName == "FR_CAMERA_LOOKAT" && paramType == FRSPT_FLOAT3 ) - { - param_at_declared = true; - if ( Read_Element_ParameterData(param_at,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if ( paramName == "FR_CAMERA_UP" && paramType == FRSPT_FLOAT3 ) - { - param_up_declared = true; - if ( Read_Element_ParameterData(param_up,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if ( paramName == "FR_OBJECT_NAME" && paramType == FRSPT_UNDEF ) - { - char* data_data = new char[paramDataSize]; - if ( Read_Element_ParameterData(data_data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frObjectSetName(camera,data_data); - CHECK_STATUS_RETURNNULL; - delete[] data_data; data_data = NULL; - } - else - { - char* data_data = new char[paramDataSize]; - if ( Read_Element_ParameterData(data_data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - WarningDetected(); - delete[] data_data; data_data = NULL; - } - - } - else - { - WarningDetected(); - } - - } - else if ( nextElem == FRSRT_OBJECT_END ) - { - break; - } - else - { - FRS_MACRO_ERROR(); - return NULL; - } - - } - - if ( param_pos_declared && param_at_declared && param_up_declared ) - { - status = frCameraLookAt(camera, - param_pos[0],param_pos[1],param_pos[2], - param_at[0],param_at[1],param_at[2], - param_up[0],param_up[1],param_up[2] - ); - CHECK_STATUS_RETURNNULL; - } - else - { - WarningDetected(); - } - - if ( Read_Element_EndObject("fr_camera",camera,objID) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - - return camera; -} - -fr_light FRS7::Read_Light(fr_context context, fr_scene scene, fr_material_system materialSystem) -{ - fr_int status = FR_SUCCESS; - - - std::string objName; - std::string objType; - int32_t objID = 0; - if ( Read_Element_StartObject(objName, objType, objID) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - if ( objType != "fr_light" ) - { - FRS_MACRO_ERROR(); - return NULL; - } - - fr_light light = NULL; - - fr_light_type lightType = 0; - bool param__FR_IES_LIGHT_IMAGE_DESC_W__defined = false; - int32_t param__FR_IES_LIGHT_IMAGE_DESC_W__data = 0; - bool param__FR_IES_LIGHT_IMAGE_DESC_H__defined = false; - int32_t param__FR_IES_LIGHT_IMAGE_DESC_H__data = 0; - bool param__FR_IES_LIGHT_IMAGE_DESC_DATA__defined = false; - char* param__FR_IES_LIGHT_IMAGE_DESC_DATA__data = NULL; - bool param__FR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__defined = false; - uint64_t param__FR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__data = 0; - int64_t param__EnvlightPortalCount = 0; - int64_t param__SkylightPortalCount = 0; - - while(true) - { - - std::string elementName; - std::string objBegType; - FRS_ELEMENTS_TYPE nextElem = Read_whatsNext(elementName,objBegType); - if ( nextElem == FRSRT_PARAMETER ) - { - std::string paramName; - FRS_PARAMETER_TYPE paramType = FRSPT_UNDEF; - uint64_t paramDataSize = 0; - if ( Read_Element_Parameter(paramName,paramType,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - - if ( paramDataSize > 0 ) - { - - - if (light == NULL && paramType == FRSPT_UNDEF && paramDataSize == sizeof(fr_light_type) && paramName == "FR_LIGHT_TYPE") - { - if ( Read_Element_ParameterData(&lightType,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - - if ( lightType == FR_LIGHT_TYPE_POINT ) - { - status = frContextCreatePointLight(context, &light); - CHECK_STATUS_RETURNNULL; - } - else if ( lightType == FR_LIGHT_TYPE_DIRECTIONAL ) - { - status = frContextCreateDirectionalLight(context, &light); - CHECK_STATUS_RETURNNULL; - } - else if ( lightType == FR_LIGHT_TYPE_SPOT ) - { - status = frContextCreateSpotLight(context, &light); - CHECK_STATUS_RETURNNULL; - } - else if ( lightType == FR_LIGHT_TYPE_ENVIRONMENT ) - { - status = frContextCreateEnvironmentLight(context, &light); - CHECK_STATUS_RETURNNULL; - } - else if ( lightType == FR_LIGHT_TYPE_SKY ) - { - status = frContextCreateSkyLight(context, &light); - CHECK_STATUS_RETURNNULL; - } - else if ( lightType == FR_LIGHT_TYPE_IES ) - { - status = frContextCreateIESLight(context, &light); - CHECK_STATUS_RETURNNULL; - } - else - { - FRS_MACRO_ERROR(); - return NULL; - } - } - else if ( light != NULL && paramName == "FR_POINT_LIGHT_RADIANT_POWER" && paramType == FRSPT_FLOAT3 && paramDataSize == sizeof(float)*3 ) - { - float radian3f[3]; - if ( Read_Element_ParameterData(radian3f,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frPointLightSetRadiantPower3f(light, radian3f[0], radian3f[1], radian3f[2]); - CHECK_STATUS_RETURNNULL; - } - else if ( light != NULL && paramName == "FR_DIRECTIONAL_LIGHT_RADIANT_POWER" && paramType == FRSPT_FLOAT3 && paramDataSize == sizeof(float)*3 ) - { - float radian3f[3]; - if ( Read_Element_ParameterData(radian3f,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frDirectionalLightSetRadiantPower3f(light, radian3f[0], radian3f[1], radian3f[2]); - CHECK_STATUS_RETURNNULL; - } - else if ( light != NULL && paramName == "FR_SPOT_LIGHT_RADIANT_POWER" && paramType == FRSPT_FLOAT3 && paramDataSize == sizeof(float)*3 ) - { - float radian3f[3]; - if ( Read_Element_ParameterData(radian3f,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frSpotLightSetRadiantPower3f(light, radian3f[0], radian3f[1], radian3f[2]); - CHECK_STATUS_RETURNNULL; - } - else if ( light != NULL && paramName == "FR_IES_LIGHT_RADIANT_POWER" && paramType == FRSPT_FLOAT3 && paramDataSize == sizeof(float)*3 ) - { - float radian3f[3]; - if ( Read_Element_ParameterData(radian3f,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frIESLightSetRadiantPower3f(light, radian3f[0], radian3f[1], radian3f[2]); - CHECK_STATUS_RETURNNULL; - } - else if ( light != NULL && paramName == "FR_SPOT_LIGHT_CONE_SHAPE" && paramType == FRSPT_FLOAT2 && paramDataSize == sizeof(float)*2 ) - { - float coneShape2f[2]; - if ( Read_Element_ParameterData(coneShape2f,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frSpotLightSetConeShape(light, coneShape2f[0], coneShape2f[1]); - CHECK_STATUS_RETURNNULL; - } - else if ( light != NULL && paramName == "FR_ENVIRONMENT_LIGHT_INTENSITY_SCALE" && paramType == FRSPT_FLOAT1 && paramDataSize == sizeof(float)*1 ) - { - float intensityScale; - if ( Read_Element_ParameterData(&intensityScale,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frEnvironmentLightSetIntensityScale(light, intensityScale); - CHECK_STATUS_RETURNNULL; - } - else if ( light != NULL && paramName == "lightIsTheEnvironmentLight" && paramType == FRSPT_INT32_1 && paramDataSize == sizeof(int32_t) ) - { - //parameter not used anymore because frSceneSetEnvironmentLight replaced by frSceneAttachLight - - int32_t isEnvLight; - if ( Read_Element_ParameterData(&isEnvLight,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - if ( isEnvLight == 1 ) - { - //status = frSceneSetEnvironmentLight(scene, light); - CHECK_STATUS_RETURNNULL; - } - } - else if ( light != NULL && paramName == "FR_LIGHT_TRANSFORM" && paramType == FRSPT_FLOAT16 && paramDataSize == sizeof(float)*16 ) - { - float lightTransform[16]; - if ( Read_Element_ParameterData(lightTransform,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frLightSetTransform(light, 0, (float*)lightTransform); - CHECK_STATUS_RETURNNULL; - } - - else if ( light != NULL && paramName == "FR_SKY_LIGHT_SCALE" && paramType == FRSPT_FLOAT1 && paramDataSize == sizeof(float)*1 ) - { - float scale; - if ( Read_Element_ParameterData(&scale,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frSkyLightSetScale(light, scale); - CHECK_STATUS_RETURNNULL; - } - else if ( light != NULL && paramName == "FR_SKY_LIGHT_ALBEDO" && paramType == FRSPT_FLOAT1 && paramDataSize == sizeof(float)*1 ) - { - float albedo; - if ( Read_Element_ParameterData(&albedo,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frSkyLightSetAlbedo(light, albedo); - CHECK_STATUS_RETURNNULL; - } - else if ( light != NULL && paramName == "FR_SKY_LIGHT_TURBIDITY" && paramType == FRSPT_FLOAT1 && paramDataSize == sizeof(float)*1 ) - { - float turbidity; - if ( Read_Element_ParameterData(&turbidity,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frSkyLightSetTurbidity(light, turbidity); - CHECK_STATUS_RETURNNULL; - } - - else if ( light != NULL && paramName == "FR_IES_LIGHT_IMAGE_DESC_W" && paramType == FRSPT_INT32_1 && paramDataSize == sizeof(int32_t) ) - { - param__FR_IES_LIGHT_IMAGE_DESC_W__defined = true; - if ( Read_Element_ParameterData(¶m__FR_IES_LIGHT_IMAGE_DESC_W__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if ( light != NULL && paramName == "FR_IES_LIGHT_IMAGE_DESC_H" && paramType == FRSPT_INT32_1 && paramDataSize == sizeof(int32_t) ) - { - param__FR_IES_LIGHT_IMAGE_DESC_H__defined = true; - if ( Read_Element_ParameterData(¶m__FR_IES_LIGHT_IMAGE_DESC_H__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if ( light != NULL && paramName == "FR_IES_LIGHT_IMAGE_DESC_DATA_SIZE" && paramType == FRSPT_UINT64_1 && paramDataSize == sizeof(uint64_t) ) - { - param__FR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__defined = true; - if ( Read_Element_ParameterData(¶m__FR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if ( light != NULL && paramName == "FR_IES_LIGHT_IMAGE_DESC_DATA" && paramType == FRSPT_UNDEF && paramDataSize == param__FR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__data && param__FR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__defined ) - { - param__FR_IES_LIGHT_IMAGE_DESC_DATA__defined = true; - param__FR_IES_LIGHT_IMAGE_DESC_DATA__data = new char[param__FR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__data]; - if ( Read_Element_ParameterData(param__FR_IES_LIGHT_IMAGE_DESC_DATA__data,param__FR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__data) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - - else if ( light != NULL && paramName == "FR_OBJECT_NAME" && paramType == FRSPT_UNDEF ) - { - char* data_data = new char[paramDataSize]; - if ( Read_Element_ParameterData(data_data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frObjectSetName(light,data_data); - CHECK_STATUS_RETURNNULL; - delete[] data_data; data_data = NULL; - } - - else if ( light != NULL && paramName == "FR_ENVIRONMENT_LIGHT_PORTAL_COUNT" && paramType == FRSPT_INT64_1 && paramDataSize == sizeof(int64_t) ) - { - if ( Read_Element_ParameterData(¶m__EnvlightPortalCount,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - - else if ( light != NULL && paramName == "FR_SKY_LIGHT_PORTAL_COUNT" && paramType == FRSPT_INT64_1 && paramDataSize == sizeof(int64_t) ) - { - if ( Read_Element_ParameterData(¶m__SkylightPortalCount,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - - else if ( light == NULL ) - { - // "FR_LIGHT_TYPE" must be declared as the first parameter in the parameters list of the light - FRS_MACRO_ERROR(); - return NULL; - } - else - { - char* data_data = new char[paramDataSize]; - if ( Read_Element_ParameterData(data_data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - - WarningDetected(); - - delete[] data_data; data_data = NULL; - } - - - - - } - else - { - WarningDetected(); - } - - } - else if ( (nextElem == FRSRT_OBJECT_BEG && elementName == "FR_ENVIRONMENT_LIGHT_IMAGE" && objBegType == "fr_image") - || (nextElem == FRSRT_REFERENCE && elementName == "FR_ENVIRONMENT_LIGHT_IMAGE") - ) - { - fr_image img = Read_Image(context); - status = frEnvironmentLightSetImage(light, img); - CHECK_STATUS_RETURNNULL; - } - else if ( (nextElem == FRSRT_OBJECT_BEG && elementName == STR__SHAPE_FOR_SKY_LIGHT_PORTAL_ID && objBegType == "fr_shape") - || (nextElem == FRSRT_REFERENCE && elementName == STR__SHAPE_FOR_SKY_LIGHT_PORTAL_ID) - ) - { - fr_shape shape = Read_Shape(context,materialSystem); - if ( shape == NULL ) { FRS_MACRO_ERROR(); return NULL; } - status = frSkyLightAttachPortal(light, shape); - CHECK_STATUS_RETURNNULL; - } - else if ( (nextElem == FRSRT_OBJECT_BEG && elementName == STR__SHAPE_FOR_ENVIRONMENT_LIGHT_PORTAL_ID && objBegType == "fr_shape") - || (nextElem == FRSRT_REFERENCE && elementName == STR__SHAPE_FOR_ENVIRONMENT_LIGHT_PORTAL_ID) - ) - { - fr_shape shape = Read_Shape(context,materialSystem); - if ( shape == NULL ) { FRS_MACRO_ERROR(); return NULL; } - status = frEnvironmentLightAttachPortal(light, shape); - CHECK_STATUS_RETURNNULL; - } - else if ( nextElem == FRSRT_OBJECT_END ) - { - break; - } - else - { - FRS_MACRO_ERROR(); - return NULL; - } - - } - - if ( Read_Element_EndObject("fr_light",light,objID) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - - - //set parameters for IES - if ( lightType == FR_LIGHT_TYPE_IES - && param__FR_IES_LIGHT_IMAGE_DESC_W__defined - && param__FR_IES_LIGHT_IMAGE_DESC_H__defined - && param__FR_IES_LIGHT_IMAGE_DESC_DATA__defined - && param__FR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__defined ) - { - status = frIESLightSetImageFromIESdata(light, param__FR_IES_LIGHT_IMAGE_DESC_DATA__data, param__FR_IES_LIGHT_IMAGE_DESC_W__data, param__FR_IES_LIGHT_IMAGE_DESC_H__data); - if (status != FR_SUCCESS) { WarningDetected(); } - } - - - - return light; -} - - - -fr_image FRS7::Read_Image(fr_context context) -{ - fr_image image = NULL; - fr_int status = FR_SUCCESS; - - std::string elementName; - std::string objBegType; - FRS_ELEMENTS_TYPE elementType = Read_whatsNext(elementName,objBegType); - if ( objBegType != "fr_image" ) - { - FRS_MACRO_ERROR(); - return NULL; - } - - if ( elementType == FRSRT_REFERENCE ) - { - RPS_OBJECT_DECLARED objReferenced; - if ( Read_Element_Reference(elementName,objBegType,objReferenced) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - image = objReferenced.obj; - } - else if ( elementType == FRSRT_OBJECT_BEG ) - { - int32_t objID = 0; - std::string objType; - Read_Element_StartObject(elementName,objType,objID); - - fr_image_format imgFormat; - memset(&imgFormat,0,sizeof(imgFormat)); - fr_image_desc imgDesc; - memset(&imgDesc,0,sizeof(imgDesc)); - void* imgData = NULL; - char* objectName = NULL; - - while(true) - { - std::string elementName; - std::string objBegType; - FRS_ELEMENTS_TYPE nextElem = Read_whatsNext(elementName,objBegType); - if ( nextElem == FRSRT_PARAMETER ) - { - std::string paramName; - FRS_PARAMETER_TYPE paramType = FRSPT_UNDEF; - uint64_t paramDataSize = 0; - if ( Read_Element_Parameter(paramName,paramType,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - - if ( paramDataSize > 0 ) - { - //char* data_data = new char[paramDataSize]; - - if (paramName == "FR_IMAGE_FORMAT" && paramType == FRSPT_UNDEF && paramDataSize == sizeof(fr_image_format)) - { - //imgFormat = ((fr_image_format*)data_data)[0]; - if ( Read_Element_ParameterData(&imgFormat,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_IMAGE_DESC" && paramType == FRSPT_UNDEF && paramDataSize == sizeof(fr_image_desc)) - { - //imgDesc = ((fr_image_desc*)data_data)[0]; - if ( Read_Element_ParameterData(&imgDesc,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_IMAGE_DATA" && paramType == FRSPT_UNDEF ) - { - imgData = new char[paramDataSize]; - if ( Read_Element_ParameterData(imgData,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_OBJECT_NAME" && paramType == FRSPT_UNDEF ) - { - objectName = new char[paramDataSize]; - if ( Read_Element_ParameterData(objectName,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else - { - FRS_MACRO_ERROR(); return NULL; - } - - //delete[] data_data; data_data = NULL; - } - - } - else if ( nextElem == FRSRT_OBJECT_END ) // if reached end of file - { - break; - } - else - { - FRS_MACRO_ERROR(); - return NULL; - } - } - - if ( imgData == NULL ) - { - FRS_MACRO_ERROR(); - return NULL; - } - status = frContextCreateImage(context, imgFormat, &imgDesc, imgData, &image); - if ( imgData ) { delete[] static_cast(imgData); imgData=NULL; } - CHECK_STATUS_RETURNNULL; - - if ( objectName ) - { - status = frObjectSetName(image,objectName); - CHECK_STATUS_RETURNNULL; - delete[] objectName; objectName=NULL; - } - - Read_Element_EndObject("fr_image",image,objID); - } - else - { - FRS_MACRO_ERROR(); - return NULL; - } - - return image; -} - - -fr_material_node FRS7::Read_MaterialNode(fr_material_system materialSystem, fr_context context) -{ - fr_material_node material = NULL; - fr_int status = FR_SUCCESS; - - std::string elementName; - - std::string objBegType; - FRS_ELEMENTS_TYPE elementType = Read_whatsNext(elementName,objBegType); - if ( objBegType != "fr_material_node" ) - { - FRS_MACRO_ERROR(); - return NULL; - } - - if ( elementType == FRSRT_REFERENCE ) - { - RPS_OBJECT_DECLARED objReferenced; - if ( Read_Element_Reference(elementName,objBegType,objReferenced) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - material = objReferenced.obj; - } - else if ( elementType == FRSRT_OBJECT_BEG ) - { - - - std::string objType; - int32_t materialID = 0; - if ( Read_Element_StartObject(elementName,objType,materialID) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - if ( objType != "fr_material_node" ) - { - FRS_MACRO_ERROR(); - return NULL; - } - - - while(true) - { - - std::string elementName; - std::string objBegType; - FRS_ELEMENTS_TYPE nextElem = Read_whatsNext(elementName,objBegType); - if ( nextElem == FRSRT_PARAMETER ) - { - std::string paramName; - FRS_PARAMETER_TYPE paramType = FRSPT_UNDEF; - uint64_t paramDataSize = 0; - if ( Read_Element_Parameter(paramName,paramType,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - - if ( paramDataSize > 0 ) - { - - - if (paramName == "FR_MATERIAL_NODE_TYPE" && paramType == FRSPT_UINT32_1 && paramDataSize == sizeof(fr_material_node_type) ) - { - fr_material_node_type type = 0; - if ( Read_Element_ParameterData(&type,sizeof(fr_material_node_type)) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frMaterialSystemCreateNode(materialSystem, type, &material); - CHECK_STATUS_RETURNNULL; - } - else if (paramName == "FR_MATERIAL_NODE_INPUT_COUNT" && paramType == FRSPT_UINT64_1 && paramDataSize == sizeof(uint64_t) ) - { - uint64_t nbInput = 0; - if ( Read_Element_ParameterData(&nbInput,sizeof(nbInput)) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else - { - if ( paramType == FRSPT_FLOAT4 ) - { - float paramValue[4]; - if ( Read_Element_ParameterData(paramValue,sizeof(paramValue)) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frMaterialNodeSetInputF(material,paramName.c_str(),paramValue[0],paramValue[1],paramValue[2],paramValue[3]); - if (status != FR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - else if ( paramType == FRSPT_UINT32_1 ) - { - uint32_t paramValue; - if ( Read_Element_ParameterData(¶mValue,sizeof(paramValue)) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frMaterialNodeSetInputU(material,paramName.c_str(),paramValue); - if (status != FR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - else if ( paramType == FRSPT_UNDEF && paramName == "FR_OBJECT_NAME" ) - { - char* data_data = new char[paramDataSize]; - if ( Read_Element_ParameterData(data_data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - status = frObjectSetName(material,data_data); - CHECK_STATUS_RETURNNULL; - delete[] data_data; data_data = NULL; - } - else - { - //unmanaged parameter - char* data_data = new char[paramDataSize]; - if ( Read_Element_ParameterData(data_data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - - WarningDetected(); - - delete[] data_data; data_data = NULL; - } - } - - - } - - } - else if ( (nextElem == FRSRT_OBJECT_BEG && objBegType == "fr_material_node") - || (nextElem == FRSRT_REFERENCE && objBegType == "fr_material_node") - ) - { - - fr_material_node matNode = Read_MaterialNode(materialSystem,context); - if ( matNode == NULL ) - { - FRS_MACRO_ERROR(); - return NULL; - } - status = frMaterialNodeSetInputN(material,elementName.c_str(),matNode); - CHECK_STATUS_RETURNNULL; - - } - else if ( (nextElem == FRSRT_OBJECT_BEG && objBegType == "fr_image") - || (nextElem == FRSRT_REFERENCE && objBegType == "fr_image") - ) - { - - fr_image image = Read_Image(context); - if ( image == NULL ) - { - FRS_MACRO_ERROR(); - return NULL; - } - status = frMaterialNodeSetInputImageData(material,elementName.c_str(),image); - CHECK_STATUS_RETURNNULL; - - } - else if ( nextElem == FRSRT_OBJECT_END ) - { - break; - } - else - { - FRS_MACRO_ERROR(); - return NULL; - } - - } - - - - if ( Read_Element_EndObject("fr_material_node",material,materialID) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - - - - - - } - else - { - FRS_MACRO_ERROR(); - return NULL; - } - - return material; -} - -fr_shape FRS7::Read_Shape(fr_context context, fr_material_system materialSystem ) -{ - fr_int status = FR_SUCCESS; - fr_shape shape = NULL; - - std::string elementName; - std::string objBegType; - FRS_ELEMENTS_TYPE elementType = Read_whatsNext(elementName,objBegType); - if ( objBegType != "fr_shape" ) - { - FRS_MACRO_ERROR(); - return NULL; - } - - if ( elementType == FRSRT_REFERENCE ) - { - RPS_OBJECT_DECLARED objReferenced; - if ( Read_Element_Reference(elementName,objBegType,objReferenced) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - shape = objReferenced.obj; - } - else if ( elementType == FRSRT_OBJECT_BEG ) - { - std::string elementName; - std::string objType; - int32_t objID = 0; - Read_Element_StartObject(elementName,objType,objID); - if ( objType != "fr_shape" ) - { - FRS_MACRO_ERROR(); - return NULL; - } - - - bool param__FR_SHAPE_TYPE__defined = false; - fr_shape_type param__FR_SHAPE_TYPE__data = NULL; - bool param__FR_MESH_POLYGON_COUNT__defined = false; - uint64_t param__FR_MESH_POLYGON_COUNT__data = NULL; - bool param__FR_MESH_VERTEX_COUNT__defined = false; - uint64_t param__FR_MESH_VERTEX_COUNT__data = NULL; - bool param__FR_MESH_NORMAL_COUNT__defined = false; - uint64_t param__FR_MESH_NORMAL_COUNT__data = NULL; - bool param__FR_MESH_UV_COUNT__defined = false; - uint64_t param__FR_MESH_UV_COUNT__data = NULL; - - bool param__FR_MESH_VERTEX_ARRAY__defined = false; - float* param__FR_MESH_VERTEX_ARRAY__data = NULL; - int32_t param__FR_MESH_VERTEX_ARRAY__dataSize = 0; - bool param__FR_MESH_NORMAL_ARRAY__defined = false; - float* param__FR_MESH_NORMAL_ARRAY__data = NULL; - int32_t param__FR_MESH_NORMAL_ARRAY__dataSize = 0; - bool param__FR_MESH_UV_ARRAY__defined = false; - float* param__FR_MESH_UV_ARRAY__data = NULL; - int32_t param__FR_MESH_UV_ARRAY__dataSize = 0; - - bool param__FR_MESH_VERTEX_INDEX_ARRAY__defined = false; - int32_t* param__FR_MESH_VERTEX_INDEX_ARRAY__data = NULL; - bool param__FR_MESH_NORMAL_INDEX_ARRAY__defined = false; - int32_t* param__FR_MESH_NORMAL_INDEX_ARRAY__data = NULL; - bool param__FR_MESH_UV_INDEX_ARRAY__defined = false; - int32_t* param__FR_MESH_UV_INDEX_ARRAY__data = NULL; - bool param__FR_MESH_NUM_VERTICES_ARRAY__defined = false; - int32_t* param__FR_MESH_NUM_VERTICES_ARRAY__data = NULL; - bool param__SHAPE_INSTANCE_REFERENCE_ID__defined = false; - int32_t param__SHAPE_INSTANCE_REFERENCE_ID__data = NULL; - bool param__FR_SHAPE_TRANSFORM__defined = false; - float param__FR_SHAPE_TRANSFORM__data[16]; - bool param__FR_SHAPE_LINEAR_MOTION__defined = false; - float param__FR_SHAPE_LINEAR_MOTION__data[3]; - bool param__FR_SHAPE_ANGULAR_MOTION__defined = false; - float param__FR_SHAPE_ANGULAR_MOTION__data[4]; - bool param__FR_SHAPE_VISIBILITY__defined = false; - fr_bool param__FR_SHAPE_VISIBILITY__data = NULL; - bool param__FR_SHAPE_SHADOW__defined = false; - fr_bool param__FR_SHAPE_SHADOW__data = NULL; - bool param__FR_SHAPE_SHADOWCATCHER__defined = false; - fr_bool param__FR_SHAPE_SHADOWCATCHER__data = NULL; - - bool param__FR_SHAPE_SUBDIVISION_FACTOR__defined = false; - fr_uint param__FR_SHAPE_SUBDIVISION_FACTOR__data = 0; - bool param__FR_SHAPE_DISPLACEMENT_IMAGE__defined = false; - fr_image param__FR_SHAPE_DISPLACEMENT_IMAGE__data = NULL; - bool param__FR_SHAPE_DISPLACEMENT_SCALE__defined = false; - fr_float param__FR_SHAPE_DISPLACEMENT_SCALE__data[2] = {0.0f,0.0f}; - - fr_material_node shapeMaterial = NULL; - - char* objectName = NULL; - - while(true) - { - std::string elementName; - std::string objBegType; - FRS_ELEMENTS_TYPE nextElem = Read_whatsNext(elementName,objBegType); - if ( nextElem == FRSRT_PARAMETER ) - { - std::string paramName; - FRS_PARAMETER_TYPE paramType = FRSPT_UNDEF; - uint64_t paramDataSize = 0; - if ( Read_Element_Parameter(paramName,paramType,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - - if ( paramDataSize > 0 ) - { - - if (paramName == "FR_SHAPE_TYPE" && paramType == FRSPT_UNDEF ) - { - param__FR_SHAPE_TYPE__defined = true; - if ( Read_Element_ParameterData(¶m__FR_SHAPE_TYPE__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_MESH_POLYGON_COUNT" && paramType == FRSPT_UINT64_1 ) - { - param__FR_MESH_POLYGON_COUNT__defined = true; - if ( Read_Element_ParameterData(¶m__FR_MESH_POLYGON_COUNT__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_MESH_VERTEX_COUNT" && paramType == FRSPT_UINT64_1 ) - { - param__FR_MESH_VERTEX_COUNT__defined = true; - if ( Read_Element_ParameterData(¶m__FR_MESH_VERTEX_COUNT__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_MESH_NORMAL_COUNT" && paramType == FRSPT_UINT64_1 ) - { - param__FR_MESH_NORMAL_COUNT__defined = true; - if ( Read_Element_ParameterData(¶m__FR_MESH_NORMAL_COUNT__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_MESH_UV_COUNT" && paramType == FRSPT_UINT64_1 ) - { - param__FR_MESH_UV_COUNT__defined = true; - if ( Read_Element_ParameterData(¶m__FR_MESH_UV_COUNT__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_MESH_VERTEX_ARRAY" && paramType == FRSPT_UINT64_1 ) - { - param__FR_MESH_VERTEX_ARRAY__data = (float*)malloc(paramDataSize); - param__FR_MESH_VERTEX_ARRAY__defined = true; - if ( Read_Element_ParameterData(param__FR_MESH_VERTEX_ARRAY__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - param__FR_MESH_VERTEX_ARRAY__dataSize = paramDataSize; - } - else if (paramName == "FR_MESH_NORMAL_ARRAY" && paramType == FRSPT_UINT64_1 ) - { - param__FR_MESH_NORMAL_ARRAY__data = (float*)malloc(paramDataSize); - param__FR_MESH_NORMAL_ARRAY__defined = true; - if ( Read_Element_ParameterData(param__FR_MESH_NORMAL_ARRAY__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - param__FR_MESH_NORMAL_ARRAY__dataSize = paramDataSize; - } - else if (paramName == "FR_MESH_UV_ARRAY" && paramType == FRSPT_UINT64_1 ) - { - param__FR_MESH_UV_ARRAY__data = (float*)malloc(paramDataSize); - param__FR_MESH_UV_ARRAY__defined = true; - if ( Read_Element_ParameterData(param__FR_MESH_UV_ARRAY__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - param__FR_MESH_UV_ARRAY__dataSize = paramDataSize; - } - else if (paramName == "FR_MESH_VERTEX_INDEX_ARRAY" && paramType == FRSPT_UNDEF ) - { - param__FR_MESH_VERTEX_INDEX_ARRAY__data = (int32_t*)malloc(paramDataSize); - param__FR_MESH_VERTEX_INDEX_ARRAY__defined = true; - if ( Read_Element_ParameterData(param__FR_MESH_VERTEX_INDEX_ARRAY__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_MESH_NORMAL_INDEX_ARRAY" && paramType == FRSPT_UNDEF ) - { - param__FR_MESH_NORMAL_INDEX_ARRAY__data = (int32_t*)malloc(paramDataSize); - param__FR_MESH_NORMAL_INDEX_ARRAY__defined = true; - if ( Read_Element_ParameterData(param__FR_MESH_NORMAL_INDEX_ARRAY__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_MESH_UV_INDEX_ARRAY" && paramType == FRSPT_UNDEF ) - { - param__FR_MESH_UV_INDEX_ARRAY__data = (int32_t*)malloc(paramDataSize); - param__FR_MESH_UV_INDEX_ARRAY__defined = true; - if ( Read_Element_ParameterData(param__FR_MESH_UV_INDEX_ARRAY__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_MESH_NUM_VERTICES_ARRAY" && paramType == FRSPT_UNDEF ) - { - param__FR_MESH_NUM_VERTICES_ARRAY__data = (int32_t*)malloc(paramDataSize); - param__FR_MESH_NUM_VERTICES_ARRAY__defined = true; - if ( Read_Element_ParameterData(param__FR_MESH_NUM_VERTICES_ARRAY__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == STR__SHAPE_INSTANCE_REFERENCE_ID && paramType == FRSPT_INT32_1 ) - { - param__SHAPE_INSTANCE_REFERENCE_ID__defined = true; - if ( Read_Element_ParameterData(¶m__SHAPE_INSTANCE_REFERENCE_ID__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_SHAPE_TRANSFORM" && paramType == FRSPT_FLOAT16 ) - { - param__FR_SHAPE_TRANSFORM__defined = true; - if ( Read_Element_ParameterData(param__FR_SHAPE_TRANSFORM__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_SHAPE_LINEAR_MOTION" && paramType == FRSPT_FLOAT3 ) - { - param__FR_SHAPE_LINEAR_MOTION__defined = true; - if ( Read_Element_ParameterData(param__FR_SHAPE_LINEAR_MOTION__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_SHAPE_ANGULAR_MOTION" && paramType == FRSPT_FLOAT4 ) - { - param__FR_SHAPE_ANGULAR_MOTION__defined = true; - if ( Read_Element_ParameterData(param__FR_SHAPE_ANGULAR_MOTION__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_SHAPE_VISIBILITY" && paramType == FRSPT_INT32_1 ) - { - param__FR_SHAPE_VISIBILITY__defined = true; - if ( Read_Element_ParameterData(¶m__FR_SHAPE_VISIBILITY__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_SHAPE_SHADOW" && paramType == FRSPT_INT32_1 ) - { - param__FR_SHAPE_SHADOW__defined = true; - if ( Read_Element_ParameterData(¶m__FR_SHAPE_SHADOW__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_SHAPE_SHADOW_CATCHER" && paramType == FRSPT_INT32_1 ) - { - param__FR_SHAPE_SHADOWCATCHER__defined = true; - if ( Read_Element_ParameterData(¶m__FR_SHAPE_SHADOWCATCHER__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_SHAPE_DISPLACEMENT_SCALE" && paramType == FRSPT_FLOAT2 ) - { - param__FR_SHAPE_DISPLACEMENT_SCALE__defined = true; - if ( Read_Element_ParameterData(param__FR_SHAPE_DISPLACEMENT_SCALE__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_SHAPE_SUBDIVISION_FACTOR" && paramType == FRSPT_UINT32_1 ) - { - param__FR_SHAPE_SUBDIVISION_FACTOR__defined = true; - if ( Read_Element_ParameterData(¶m__FR_SHAPE_SUBDIVISION_FACTOR__data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "FR_OBJECT_NAME" && paramType == FRSPT_UNDEF ) - { - objectName = new char[paramDataSize]; - if ( Read_Element_ParameterData(objectName,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - } - else - { - char* data_data = new char[paramDataSize]; - if ( Read_Element_ParameterData(data_data,paramDataSize) != FR_SUCCESS ) { FRS_MACRO_ERROR(); return NULL; } - - WarningDetected(); - - delete[] data_data; data_data = NULL; - } - - - } - - } - else if ( (nextElem == FRSRT_OBJECT_BEG && elementName == "FR_SHAPE_DISPLACEMENT_IMAGE" && objBegType == "fr_image") - || (nextElem == FRSRT_REFERENCE && elementName == "FR_SHAPE_DISPLACEMENT_IMAGE") - ) - { - param__FR_SHAPE_DISPLACEMENT_IMAGE__data = Read_Image(context); - param__FR_SHAPE_DISPLACEMENT_IMAGE__defined = true; - } - else if ( (nextElem == FRSRT_OBJECT_BEG && objBegType == "fr_material_node") - || (nextElem == FRSRT_REFERENCE && objBegType == "fr_material_node") - ) - { - shapeMaterial = Read_MaterialNode(materialSystem,context); - if ( shapeMaterial == NULL ) - { - FRS_MACRO_ERROR(); - return NULL; - } - } - else if ( nextElem == FRSRT_OBJECT_END ) - { - break; - } - else - { - FRS_MACRO_ERROR(); - return NULL; - } - } - - - if ( !param__FR_SHAPE_TYPE__defined ) { FRS_MACRO_ERROR(); return NULL; } - if ( param__FR_SHAPE_TYPE__data == FR_SHAPE_TYPE_MESH ) - { - //special case : no UV data - if ( param__FR_MESH_UV_COUNT__defined && param__FR_MESH_UV_COUNT__data == 0 - && !param__FR_MESH_UV_ARRAY__defined - && !param__FR_MESH_UV_INDEX_ARRAY__defined - ) - { - param__FR_MESH_UV_ARRAY__defined = true; - param__FR_MESH_UV_ARRAY__data = nullptr; - param__FR_MESH_UV_ARRAY__dataSize = 0; - param__FR_MESH_UV_INDEX_ARRAY__defined = true; - param__FR_MESH_UV_INDEX_ARRAY__data = nullptr; - } - - - if ( !param__FR_MESH_POLYGON_COUNT__defined - || !param__FR_MESH_VERTEX_COUNT__defined - || !param__FR_MESH_NORMAL_COUNT__defined - || !param__FR_MESH_UV_COUNT__defined - || !param__FR_MESH_VERTEX_ARRAY__defined - || !param__FR_MESH_NORMAL_ARRAY__defined - || !param__FR_MESH_UV_ARRAY__defined - || !param__FR_MESH_VERTEX_INDEX_ARRAY__defined - || !param__FR_MESH_NORMAL_INDEX_ARRAY__defined - || !param__FR_MESH_UV_INDEX_ARRAY__defined - || !param__FR_MESH_NUM_VERTICES_ARRAY__defined - ) - { FRS_MACRO_ERROR(); return NULL; } - - shape = NULL; - status = frContextCreateMesh(context, - param__FR_MESH_VERTEX_ARRAY__data, param__FR_MESH_VERTEX_COUNT__data, int(param__FR_MESH_VERTEX_ARRAY__dataSize / param__FR_MESH_VERTEX_COUNT__data), - param__FR_MESH_NORMAL_ARRAY__data, param__FR_MESH_NORMAL_COUNT__data, int(param__FR_MESH_NORMAL_ARRAY__dataSize / param__FR_MESH_NORMAL_COUNT__data), - param__FR_MESH_UV_ARRAY__data , param__FR_MESH_UV_COUNT__data, param__FR_MESH_UV_ARRAY__dataSize == 0 ? 0 : int(param__FR_MESH_UV_ARRAY__dataSize / param__FR_MESH_UV_COUNT__data), - param__FR_MESH_VERTEX_INDEX_ARRAY__data, sizeof(fr_int), - param__FR_MESH_NORMAL_INDEX_ARRAY__data, sizeof(fr_int), - param__FR_MESH_UV_INDEX_ARRAY__data, sizeof(fr_int), - param__FR_MESH_NUM_VERTICES_ARRAY__data, param__FR_MESH_POLYGON_COUNT__data, &shape); - CHECK_STATUS_RETURNNULL; - } - else if ( param__FR_SHAPE_TYPE__data == FR_SHAPE_TYPE_INSTANCE ) - { - if ( !param__SHAPE_INSTANCE_REFERENCE_ID__defined ) { FRS_MACRO_ERROR(); return NULL; } - - //search the id in the previous loaded - fr_shape shapeReferenced = NULL; - for(int iObj=0; iObjread((char*)&elementType, sizeof(int32_t)); - if ( m_frsFile->eof() ) - { - return FRSRT_UNDEF; - } - - Read_String(name); - - int64_t sizeOfElementHead = sizeof(int32_t) + sizeof(int32_t) + name.length(); - - if ( elementType == FRSRT_OBJECT_BEG || elementType == FRSRT_REFERENCE) - { - Read_String(objBegType); - sizeOfElementHead += sizeof(int32_t) + objBegType.length(); - } - else - { - objBegType = ""; - } - - //rewind to the beginning of element - m_frsFile->seekg(-sizeOfElementHead, m_frsFile->cur); - - if ( - elementType == FRSRT_OBJECT_BEG - || elementType == FRSRT_OBJECT_END - || elementType == FRSRT_PARAMETER - || elementType == FRSRT_REFERENCE - ) - { - return elementType; - } - else - { - FRS_MACRO_ERROR(); - return FRSRT_UNDEF; - } -} - -fr_int FRS7::Read_Element_StartObject(std::string& name, std::string& type, int32_t& id) -{ - FRS_ELEMENTS_TYPE elementType = FRSRT_UNDEF; - m_frsFile->read((char*)&elementType, sizeof(int32_t)); - if ( elementType != FRSRT_OBJECT_BEG ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - Read_String(name); - Read_String(type); - m_frsFile->read((char*)&id, sizeof(int32_t)); - - m_level++; - return FR_SUCCESS; -} - -fr_int FRS7::Read_Element_EndObject(const std::string& type, void* obj, int32_t id) -{ - FRS_ELEMENTS_TYPE elementType = FRSRT_UNDEF; - m_frsFile->read((char*)&elementType, sizeof(int32_t)); - std::string endObjName; //this string is not used - Read_String(endObjName); - if ( elementType != FRSRT_OBJECT_END ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - m_level--; - - RPS_OBJECT_DECLARED newObj; - newObj.id = id; - newObj.type = type; - newObj.obj = obj; - m_listObjectDeclared.push_back(newObj); - - - return FR_SUCCESS; -} - -fr_int FRS7::Read_Element_ParameterData(void* data, uint64_t size) -{ - if ( data == NULL && size != 0 ) - { - FRS_MACRO_ERROR(); - return FR_ERROR_INTERNAL_ERROR; - } - - m_frsFile->read((char*)data, size); - return FR_SUCCESS; -} - -fr_int FRS7::Read_Element_Parameter(std::string& name, FRS_PARAMETER_TYPE& type, uint64_t& dataSize) -{ - FRS_ELEMENTS_TYPE elementType = FRSRT_UNDEF; - m_frsFile->read((char*)&elementType, sizeof(int32_t)); - if ( elementType != FRSRT_PARAMETER ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - Read_String(name); - m_frsFile->read((char*)&type, sizeof(type)); - m_frsFile->read((char*)&dataSize, sizeof(dataSize)); - return FR_SUCCESS; -} - -fr_int FRS7::Read_Element_Reference(std::string& name, std::string& type, RPS_OBJECT_DECLARED& objReferenced) -{ - FRS_ELEMENTS_TYPE elementType = FRSRT_UNDEF; - m_frsFile->read((char*)&elementType, sizeof(int32_t)); - if ( elementType != FRSRT_REFERENCE ) { FRS_MACRO_ERROR(); return FR_ERROR_INTERNAL_ERROR; } - Read_String(name); - Read_String(type); - - int32_t id; - m_frsFile->read((char*)&id, sizeof(int32_t)); - - //search object in list - bool found = false; - for(int iObj=0; iObjread((char*)&strSize, sizeof(strSize)); - - if ( strSize > 0 ) - { - char* strRead = new char[strSize+1]; - m_frsFile->read(strRead, strSize); - strRead[strSize] = '\0'; - str = std::string(strRead); - delete[] strRead; - strRead = NULL; - } - else - { - str = ""; - } - - return FR_SUCCESS; -} diff --git a/RprLoadStore/frs7.h b/RprLoadStore/frs7.h deleted file mode 100644 index cb1e88dc..00000000 --- a/RprLoadStore/frs7.h +++ /dev/null @@ -1,221 +0,0 @@ -#ifndef frLoadStore_FRS7_H_ -#define frLoadStore_FRS7_H_ - -#include "Rpr/RadeonProRender.h" - -#include "common.h" - -#include -#include -#include -#include - - -/* - -Architecture of FRS file : - -we store ELEMENTS. - -there are 4 types of ELEMENTS : -- OBJECT_BEG --> header of an OBJECT. an OBJECT is a set of PARAMETER and REFERENCE -- OBJECT_END --> end of an OBJECT -- PARAMETER --> constains one data (could be an integer, an image, a float4 ...etc...) -- REFERENCE --> reference to an object (for example, this avoid to define several time the same image) - -The head of each ELEMENT is always the same : - < char[] : Element Name String > - - -architecture of each ELEMENTS : - -OBJECT_BEG : - < char[] : object name String > < char[] : object type string > < int32 : ID > - -OBJECT_END : - < char[] : string (usually empty) > - -REFERENCE : - < char[] : reference name String > < char[] : reference type string > < int32 : ID > - -PARAMETER : - < char[] : parameter name String > < int32 : FRS_PARAMETER_TYPE > < int64 : Data size in Byte > < char[] : data > - -*/ - - -class FRS7 -{ - -public: - - FRS7(std::fstream* myfile, bool allowWrite); - ~FRS7(); - - //call that before calling StoreEverything() - void AddExtraCustomParam_int(const std::string& name, int value) { m_extraCustomParam_int[name]=value; } - void AddExtraCustomParam_float(const std::string& name, float value) { m_extraCustomParam_float[name]=value; } - - const std::map& GetExtraCustomParam_int() { return m_extraCustomParam_int; } - const std::map& GetExtraCustomParam_float() { return m_extraCustomParam_float; } - - // return FR_SUCCESS is success - fr_int StoreEverything( - fr_context context, - fr_scene scene - ); - - // return FR_SUCCESS is success - fr_int LoadEverything( - fr_context context, - fr_material_system materialSystem, - fr_scene& scene, - bool useAlreadyExistingScene - ); - - - - const std::vector& GetListObjectDeclared() { return m_listObjectDeclared; } - - -private: - - - //in order to switch between fr_parameter_type and FRS_PARAMETER_TYPE, use FRSPT_to_FRPARAMETERTYPE() or FRPARAMETERTYPE_to_FRSPT() - enum FRS_PARAMETER_TYPE { - - // do NOT modify the numbers because there would be a retro-compatibility issue with FRS already saved - FRSPT_UNDEF = 0, // undef data - - FRSPT_FLOAT1 = 1, - FRSPT_FLOAT2 = 2, - FRSPT_FLOAT3 = 3, - FRSPT_FLOAT4 = 4, - FRSPT_FLOAT16 = 5, - - FRSPT_UINT32_1 = 6, - FRSPT_UINT32_2 = 7, - FRSPT_UINT32_3 = 8, - FRSPT_UINT32_4 = 9, - - FRSPT_INT32_1 = 10, - FRSPT_INT32_2 = 11, - FRSPT_INT32_3 = 12, - FRSPT_INT32_4 = 13, - - FRSPT_UINT64_1 = 14, - FRSPT_UINT64_2 = 15, - FRSPT_UINT64_3 = 16, - FRSPT_UINT64_4 = 17, - - FRSPT_INT64_1 = 18, - FRSPT_INT64_2 = 19, - FRSPT_INT64_3 = 20, - FRSPT_INT64_4 = 21, - - FRSPT_FORCE_DWORD = 0xffffffff - }; - - enum FRS_ELEMENTS_TYPE - { - FRSRT_UNDEF = 0, - - FRSRT_OBJECT_BEG = 0x0CC01, - FRSRT_OBJECT_END = 0x0CC02, - FRSRT_PARAMETER = 0x0CC03, - FRSRT_REFERENCE = 0x0CC04, - - FRSRT_FORCE_DWORD = 0xffffffff - }; - - - //this is just for debug. advice to call this function each time an error is detected. - //for debugging, we can add a breakpoint in this function - void ErrorDetected(const char* function, int32_t line, const char* message); - void WarningDetected(); - - - fr_parameter_type FRSPT_to_FRPARAMETERTYPE(FRS_PARAMETER_TYPE in); - FRS_PARAMETER_TYPE FRPARAMETERTYPE_to_FRSPT(fr_parameter_type in); - int32_t FRSPT_to_size(FRS_PARAMETER_TYPE in); // return -1 if no fixed size for the input argument - - //return false if FAIL - bool Store_String( const std::string& str); - - // type = "fr_shape" or "fr_image" ...etc... - // obj = corresponds to fr_shape or fr_image ...etc... - bool Store_StartObject( const std::string& objName, const std::string& type, void* obj); - - bool Store_EndObject(); - - bool Store_ObjectParameter( const std::string& parameterName,FRS_PARAMETER_TYPE type,uint64_t dataSize, const void* data); - - // [in] type = "fr_shape" or "fr_image" ...etc... - bool Store_ReferenceToObject(const std::string& objName, const std::string& type, int32_t id); - - fr_int Store_Context(fr_context context);// return FR_SUCCESS is success - fr_int Store_Scene(fr_scene scene);// return FR_SUCCESS is success - fr_int Store_Shape(fr_shape shape, const std::string& name); // return FR_SUCCESS is success - fr_int Store_Light(fr_light light, fr_scene scene);// return FR_SUCCESS is success - fr_int Store_Camera(fr_camera camera);// return FR_SUCCESS is success - fr_int Store_MaterialNode(fr_material_node shader, const std::string& name);// return FR_SUCCESS is success - fr_int Store_Image(fr_image image, const std::string& name);// return FR_SUCCESS is success - - - fr_int Read_Context(fr_context context);// return FR_SUCCESS is success - fr_scene Read_Scene(fr_context context, fr_material_system materialSystem, fr_scene sceneExisting);//return NULL if error. If sceneExisting not NULL, the we use this scene. Else we create a new scene. - fr_light Read_Light(fr_context context, fr_scene scene, fr_material_system materialSystem);//return NULL if error - fr_image Read_Image(fr_context context);//return NULL if error - fr_shape Read_Shape(fr_context context, fr_material_system materialSystem);//return NULL if error - fr_material_node Read_MaterialNode(fr_material_system materialSystem, fr_context context);//return NULL if error - fr_camera Read_Camera(fr_context context);//return NULL if error - - // [out] name : name of the next element - // [out] objBegType : only filled if next element is FRSRT_OBJECT_BEG or FRSRT_REFERENCE - // return FRSRT_UNDEF if error or if end of file - FRS_ELEMENTS_TYPE Read_whatsNext(std::string& name, std::string& objBegType); - - fr_int Read_Element_StartObject(std::string& name, std::string& type, int32_t& id); // return FR_SUCCESS if success - - // [in] type = "fr_shape" or "fr_image" ...etc... - // obj = corresponds to fr_shape or fr_image ...etc... - fr_int Read_Element_EndObject(const std::string& type, void* obj, int32_t id); // return FR_SUCCESS if success - - fr_int Read_Element_Parameter(std::string& name, FRS_PARAMETER_TYPE& type, uint64_t& dataSize); // return FR_SUCCESS if success - fr_int Read_Element_ParameterData(void* data, uint64_t size); // return FR_SUCCESS if success - fr_int Read_Element_Reference(std::string& name, std::string& type, RPS_OBJECT_DECLARED& objReferenced); // return FR_SUCCESS if success - fr_int Read_String(std::string& str); // return FR_SUCCESS if success - - //should be incremented each time we update the store/load - //version will be write just after the m_HEADER_CHECKCODE - static const int32_t m_FILE_VERSION; - - //first 4 bytes of the file. - //will never change. - //just tell that it's a FireRender Scene file - static const char m_HEADER_CHECKCODE[4]; - static const char m_HEADER_BADCHECKCODE[4]; // bad checkcode, indicates that FRS file is not correct. - - - int32_t m_level; // increment when enter inside Store_StartObject/Read_Element_ObjBeg. decrement when Store_EndObject/Read_Element_ObjEnd - - std::fstream* m_frsFile; - - int32_t m_idCounter; // increment each time we declare an object - - - - std::vector m_listObjectDeclared; - - int32_t m_fileVersionOfLoadFile; - - std::map m_extraCustomParam_int; - std::map m_extraCustomParam_float; - - const bool m_allowWrite; // = true if allow write the m_frsFile fstream - = false if Read Only - -}; - - - -#endif diff --git a/RprLoadStore/rps8.cpp b/RprLoadStore/rps8.cpp deleted file mode 100644 index 306a9651..00000000 --- a/RprLoadStore/rps8.cpp +++ /dev/null @@ -1,3605 +0,0 @@ -#include -#include -#include -#include "rps8.h" - -#include - -//with linux, it seems cstddef and string.h are needed for compile -#ifdef __linux__ -#include -#include -#endif - -// history of changes : -// version 02 : first -// version 03 : add shadow flag -// version 04 : add LOADER_DATA_FROM_3DS -// version 05 : (07 jan 2016) new material system -// version 06 : (25 feb 2016) add more data inside LOADER_DATA_FROM_3DS + possibility to save if no camera in scene. note that version 6 can import version 5 -// version 07 : lots of changes. not retrocompatible with previous versions. But really more flexible. the flexibility of this version should make it the very last version of RPS. -// version 08 : (05 Oct 2016) new version with the renaming : FR->RPR. extension was FRS, now it's RPS -int32_t const RPS8::m_FILE_VERSION = 0x00000008; - -char const RPS8::m_HEADER_CHECKCODE[4] = { 'R','P','S','F' }; // "¨RPSF" = RadeonProrenderSceneFile -char const RPS8::m_HEADER_BADCHECKCODE[4] = { 'B','A','D','0' }; -char const STR__SHAPE_INSTANCE_REFERENCE_ID[] = "shape_instance_reference_id"; -char const STR__SHAPE_FOR_SKY_LIGHT_PORTAL_ID[] = "shape_for_sky_light_portal_id"; -char const STR__SHAPE_FOR_ENVIRONMENT_LIGHT_PORTAL_ID[] = "shape_for_environment_light_portal_id"; -char const STR__SCENE_LIGHT_ID[] = "scene_light_id"; -char const STR__SCENE_ENV_OVERRIGHT_REFRACTION_ID[] = "___SCENE_ENV_OVERRIGHT_REFRACTION_ID___INTERNAL__"; -char const STR__SCENE_ENV_OVERRIGHT_REFLECTION_ID[] = "___SCENE_ENV_OVERRIGHT_REFLECTION_ID___INTERNAL__"; -char const STR__SCENE_ENV_OVERRIGHT_BACKGROUND_ID[] = "___SCENE_ENV_OVERRIGHT_BACKGROUND_ID___INTERNAL__"; -char const STR__SCENE_ENV_OVERRIGHT_TRANSPARENCY_ID[] = "___SCENE_ENV_OVERRIGHT_TRANSPARENCY_ID___INTERNAL__"; -char const STR__SCENE_BACKGROUND_IMAGE_ID[] = "___SCENE_BACKGROUND_IMAGE_ID___INTERNAL__"; -char const STR__nonInstancedSceneShape_ID[] = "nonInstancedSceneShape"; -char const STR__InstancedSceneShape_ID[] = "InstancedSceneShape"; - - -#define CHECK_STATUS_RETURNERROR { if (status != RPR_SUCCESS) { RPS_MACRO_ERROR(); return status; } } -#define CHECK_STATUS_RETURNNULL { if (status != RPR_SUCCESS) { RPS_MACRO_ERROR(); return 0; } } - - -#define RPS_MACRO_ERROR() ErrorDetected (__FUNCTION__,__LINE__,""); - - -RPS8::RPS8(std::fstream* myfile, bool allowWrite) : - m_allowWrite(allowWrite) -{ - m_rpsFile = myfile; - m_listObjectDeclared.clear(); - m_level = 0; - - m_idCounter = 1000; // just in order to avoid confusion with other numbers, I start this counter from 1000 - - m_fileVersionOfLoadFile = 0; // only used when read RPS file -} - -RPS8::~RPS8() -{ - -} - -void RPS8::WarningDetected() -{ - //add breakpoint here for debugging frLoader - int a = 0; -} -void RPS8::ErrorDetected(const char* function, int32_t line, const char* message) -{ - //add breakpoint here for debugging frLoader - int a = 0; - - //if an error is detected, the file is corrupted anyway, so we can write error debug info at the end of the file. - //Note that a bad file file is directly detected at the begining of the file with the string : m_HEADER_BADCHECKCODE - if (m_allowWrite && m_rpsFile->is_open() && !m_rpsFile->fail()) - { - std::ostringstream stringStream; - stringStream << "\r\nERROR -- FUNC=" << std::string(function) << " LINE=" << line << " EXTRA_MESSAGE=" << message << " ENDERROR\r\n"; - std::string errorInfoStr = stringStream.str(); - - m_rpsFile->write(errorInfoStr.c_str(), errorInfoStr.length()); - m_rpsFile->flush(); - } -} - - - - -rpr_int RPS8::StoreEverything( - rpr_context context, - rpr_scene scene -) -{ - rpr_int status = RPR_SUCCESS; - - // write a wrong check code: the good check code will be written at the end, when we are sure that the generation didn't fail. - // so if we have a crash or anything bad during StoreEverything, the RPS will be nicely unvalid. - m_rpsFile->write((const char*)&m_HEADER_BADCHECKCODE, sizeof(m_HEADER_BADCHECKCODE)); - m_rpsFile->write((const char*)&m_FILE_VERSION, sizeof(m_FILE_VERSION)); - - - status = Store_Context(context); - if (status != RPR_SUCCESS) { RPS_MACRO_ERROR(); return status; } - status = Store_Scene(scene); - if (status != RPR_SUCCESS) { RPS_MACRO_ERROR(); return status; } - - - //store extra custom params - for (auto it = m_extraCustomParam_int.begin(); it != m_extraCustomParam_int.end(); ++it) - { - if (!Store_ObjectParameter((*it).first.c_str(), RPS8::RPSPT_INT32_1, sizeof(float), &((*it).second))) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - } - for (auto it = m_extraCustomParam_float.begin(); it != m_extraCustomParam_float.end(); ++it) - { - if (!Store_ObjectParameter((*it).first.c_str(), RPS8::RPSPT_FLOAT1, sizeof(float), &((*it).second))) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - } - - if (m_level != 0) - { - //if level is not 0, this means we have not closed all object delaration - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - //rewind and write the good check code at the begining of the file. - m_rpsFile->seekp(0); - m_rpsFile->write((const char*)&m_HEADER_CHECKCODE, sizeof(m_HEADER_CHECKCODE)); - - return status; -} - - -rpr_int RPS8::Store_Camera(rpr_camera camera, const std::string& name_) -{ - - rpr_int status = RPR_SUCCESS; - - if (!Store_StartObject(name_, "rpr_camera", camera)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - float param_fstop; - status = rprCameraGetInfo(camera, RPR_CAMERA_FSTOP, sizeof(param_fstop), ¶m_fstop, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_CAMERA_FSTOP", RPSPT_FLOAT1, sizeof(param_fstop), ¶m_fstop)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - unsigned int param_apblade; - status = rprCameraGetInfo(camera, RPR_CAMERA_APERTURE_BLADES, sizeof(unsigned int), ¶m_apblade, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_CAMERA_APERTURE_BLADES", RPSPT_UINT32_1, sizeof(param_apblade), ¶m_apblade)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - float param_camexpo; - status = rprCameraGetInfo(camera, RPR_CAMERA_EXPOSURE, sizeof(param_camexpo), ¶m_camexpo, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_CAMERA_EXPOSURE", RPSPT_FLOAT1, sizeof(param_camexpo), ¶m_camexpo)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - float param_focalLen; - status = rprCameraGetInfo(camera, RPR_CAMERA_FOCAL_LENGTH, sizeof(param_focalLen), ¶m_focalLen, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_CAMERA_FOCAL_LENGTH", RPSPT_FLOAT1, sizeof(param_focalLen), ¶m_focalLen)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - float param_sensorsize[2]; - status = rprCameraGetInfo(camera, RPR_CAMERA_SENSOR_SIZE, sizeof(param_sensorsize), ¶m_sensorsize, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_CAMERA_SENSOR_SIZE", RPSPT_FLOAT2, sizeof(param_sensorsize), ¶m_sensorsize)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - rpr_camera_mode param_mode; - status = rprCameraGetInfo(camera, RPR_CAMERA_MODE, sizeof(param_mode), ¶m_mode, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_CAMERA_MODE", RPSPT_UINT32_1, sizeof(param_mode), ¶m_mode)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - float param_orthowidth; - status = rprCameraGetInfo(camera, RPR_CAMERA_ORTHO_WIDTH, sizeof(param_orthowidth), ¶m_orthowidth, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_CAMERA_ORTHO_WIDTH", RPSPT_FLOAT1, sizeof(param_orthowidth), ¶m_orthowidth)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - float param_tilt; - status = rprCameraGetInfo(camera, RPR_CAMERA_FOCAL_TILT, sizeof(param_tilt), ¶m_tilt, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_CAMERA_FOCAL_TILT", RPSPT_FLOAT1, sizeof(param_tilt), ¶m_tilt)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - float param_ipd; - status = rprCameraGetInfo(camera, RPR_CAMERA_IPD, sizeof(param_ipd), ¶m_ipd, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_CAMERA_IPD", RPSPT_FLOAT1, sizeof(param_ipd), ¶m_ipd)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - rpr_float param_shift[2]; - status = rprCameraGetInfo(camera, RPR_CAMERA_LENS_SHIFT, sizeof(param_shift), param_shift, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_CAMERA_LENS_SHIFT", RPSPT_FLOAT2, sizeof(param_shift), param_shift)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - float param_orthoheight; - status = rprCameraGetInfo(camera, RPR_CAMERA_ORTHO_HEIGHT, sizeof(param_orthoheight), ¶m_orthoheight, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_CAMERA_ORTHO_HEIGHT", RPSPT_FLOAT1, sizeof(param_orthoheight), ¶m_orthoheight)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - float param_focusdist; - status = rprCameraGetInfo(camera, RPR_CAMERA_FOCUS_DISTANCE, sizeof(param_focusdist), ¶m_focusdist, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_CAMERA_FOCUS_DISTANCE", RPSPT_FLOAT1, sizeof(param_focusdist), ¶m_focusdist)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - rpr_float param_pos[4]; - status = rprCameraGetInfo(camera, RPR_CAMERA_POSITION, sizeof(param_pos), ¶m_pos, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_CAMERA_POSITION", RPSPT_FLOAT3, 3 * sizeof(float), param_pos)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - rpr_float param_at[4]; - status = rprCameraGetInfo(camera, RPR_CAMERA_LOOKAT, sizeof(param_at), ¶m_at, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_CAMERA_LOOKAT", RPSPT_FLOAT3, 3 * sizeof(float), param_at)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - rpr_float param_up[4]; - status = rprCameraGetInfo(camera, RPR_CAMERA_UP, sizeof(param_up), ¶m_up, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_CAMERA_UP", RPSPT_FLOAT3, 3 * sizeof(float), param_up)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - - //save RPR_OBJECT_NAME of object. - size_t frobjectName_size = 0; - status = rprCameraGetInfo(camera, RPR_OBJECT_NAME, NULL, NULL, &frobjectName_size); - CHECK_STATUS_RETURNERROR; - if (frobjectName_size <= 0) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } // because of 0 terminated character, size must be >= 1 - char* frobjectName_data = new char[frobjectName_size]; - status = rprCameraGetInfo(camera, RPR_OBJECT_NAME, frobjectName_size, frobjectName_data, NULL); - CHECK_STATUS_RETURNERROR; - if (frobjectName_data[frobjectName_size - 1] != '\0') { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } // check that the last character is '\0' - if (!Store_ObjectParameter("RPR_OBJECT_NAME", RPSPT_UNDEF, frobjectName_size, frobjectName_data)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - delete[] frobjectName_data; frobjectName_data = NULL; - - - if (!Store_EndObject()) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - return RPR_SUCCESS; -} - - -rpr_int RPS8::Store_MaterialNode(rpr_material_node shader, const std::string& name) -{ - - rpr_int status = RPR_SUCCESS; - - - int indexFound = -1; - //search if this node is already saved. - for (int iObj = 0; iObj < m_listObjectDeclared.size(); iObj++) - { - if (m_listObjectDeclared[iObj].type == "rpr_material_node" && m_listObjectDeclared[iObj].obj == shader) - { - indexFound = iObj; - break; - } - } - if (indexFound != -1) - { - //if node already saved, just save reference - if (!Store_ReferenceToObject(name, "rpr_material_node", m_listObjectDeclared[indexFound].id)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - } - else - { - //if node not already saved - - - - if (!Store_StartObject(name, "rpr_material_node", shader)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - rpr_material_node_type nodeType = 0; - status = rprMaterialNodeGetInfo(shader, RPR_MATERIAL_NODE_TYPE, sizeof(nodeType), &nodeType, NULL); - CHECK_STATUS_RETURNNULL; - if (!Store_ObjectParameter("RPR_MATERIAL_NODE_TYPE", RPSPT_UINT32_1, sizeof(nodeType), &nodeType)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - uint64_t nbInput = 0; - status = rprMaterialNodeGetInfo(shader, RPR_MATERIAL_NODE_INPUT_COUNT, sizeof(nbInput), &nbInput, NULL); - CHECK_STATUS_RETURNNULL; - if (!Store_ObjectParameter("RPR_MATERIAL_NODE_INPUT_COUNT", RPSPT_UINT64_1, sizeof(nbInput), &nbInput)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - - for (int i = 0; i < nbInput; i++) - { - size_t shaderParameterName_lenght_size_t = 0; - status = rprMaterialNodeGetInputInfo(shader, i, RPR_MATERIAL_NODE_INPUT_NAME_STRING, 0, NULL, &shaderParameterName_lenght_size_t); - uint64_t shaderParameterName_lenght = shaderParameterName_lenght_size_t; - CHECK_STATUS_RETURNNULL; - char* shaderParameterName = new char[shaderParameterName_lenght]; - status = rprMaterialNodeGetInputInfo(shader, i, RPR_MATERIAL_NODE_INPUT_NAME_STRING, shaderParameterName_lenght, shaderParameterName, NULL); - CHECK_STATUS_RETURNNULL; - //myfile->write((char*)&shaderParameterName_lenght, sizeof(shaderParameterName_lenght)); - //myfile->write((char*)shaderParameterName, shaderParameterName_lenght); - - rpr_uint nodeInputType = 0; - status = rprMaterialNodeGetInputInfo(shader, i, RPR_MATERIAL_NODE_INPUT_TYPE, sizeof(nodeInputType), &nodeInputType, NULL); - CHECK_STATUS_RETURNNULL; - //myfile->write((char*)&nodeInputType, sizeof(nodeInputType)); - - size_t shaderParameterValue_lenght_size_t = 0; - status = rprMaterialNodeGetInputInfo(shader, i, RPR_MATERIAL_NODE_INPUT_VALUE, 0, NULL, &shaderParameterValue_lenght_size_t); - uint64_t shaderParameterValue_lenght = shaderParameterValue_lenght_size_t; - CHECK_STATUS_RETURNNULL; - char* shaderParameterValue = new char[shaderParameterValue_lenght]; - status = rprMaterialNodeGetInputInfo(shader, i, RPR_MATERIAL_NODE_INPUT_VALUE, shaderParameterValue_lenght, shaderParameterValue, NULL); - CHECK_STATUS_RETURNNULL; - - - if (nodeInputType == RPR_MATERIAL_NODE_INPUT_TYPE_NODE) - { - if (shaderParameterValue_lenght != sizeof(rpr_material_node)) - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - else - { - - - rpr_material_node* shader = (rpr_material_node*)shaderParameterValue; - if (*shader != NULL) - { - //int32_t shaderExists = 1; - //myfile->write((char*)&shaderExists, sizeof(shaderExists)); - status = Store_MaterialNode(*shader, shaderParameterName); - } - else - { - //int32_t shaderExists = 0; - //myfile->write((char*)&shaderExists, sizeof(shaderExists)); - } - CHECK_STATUS_RETURNERROR; - - } - } - else if (nodeInputType == RPR_MATERIAL_NODE_INPUT_TYPE_IMAGE) - { - if (shaderParameterValue_lenght != sizeof(rpr_image)) - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - else - { - rpr_image* image = (rpr_material_node*)shaderParameterValue; - if (*image != NULL) - { - //int32_t imageExists = 1; - //myfile->write((char*)&imageExists, sizeof(imageExists)); - status = Store_Image(*image, shaderParameterName); - } - else - { - //int32_t imageExists = 0; - //myfile->write((char*)&imageExists, sizeof(imageExists)); - } - CHECK_STATUS_RETURNERROR; - } - } - else if (nodeInputType == RPR_MATERIAL_NODE_INPUT_TYPE_FLOAT4) - { - if (!Store_ObjectParameter(shaderParameterName, RPSPT_FLOAT4, shaderParameterValue_lenght, shaderParameterValue)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - } - else if (nodeInputType == RPR_MATERIAL_NODE_INPUT_TYPE_UINT) - { - if (!Store_ObjectParameter(shaderParameterName, RPSPT_UINT32_1, shaderParameterValue_lenght, shaderParameterValue)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - } - else - { - if (!Store_ObjectParameter(shaderParameterName, RPSPT_UNDEF, shaderParameterValue_lenght, shaderParameterValue)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - } - - delete[] shaderParameterName; shaderParameterName = NULL; - delete[] shaderParameterValue; shaderParameterValue = NULL; - } - - - //save RPR_OBJECT_NAME of object. - size_t frobjectName_size = 0; - status = rprMaterialNodeGetInfo(shader, RPR_OBJECT_NAME, NULL, NULL, &frobjectName_size); - CHECK_STATUS_RETURNERROR; - if (frobjectName_size <= 0) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } // because of 0 terminated character, size must be >= 1 - char* frobjectName_data = new char[frobjectName_size]; - status = rprMaterialNodeGetInfo(shader, RPR_OBJECT_NAME, frobjectName_size, frobjectName_data, NULL); - CHECK_STATUS_RETURNERROR; - if (frobjectName_data[frobjectName_size - 1] != '\0') { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } // check that the last character is '\0' - if (!Store_ObjectParameter("RPR_OBJECT_NAME", RPSPT_UNDEF, frobjectName_size, frobjectName_data)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - delete[] frobjectName_data; frobjectName_data = NULL; - - - if (!Store_EndObject()) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - } - - return status; -} - -rpr_int RPS8::Store_Light(rpr_light light, const std::string& name) -{ - - rpr_int status = RPR_SUCCESS; - - - int indexFound = -1; - //search if this light is already saved. - for (int iObj = 0; iObj < m_listObjectDeclared.size(); iObj++) - { - if (m_listObjectDeclared[iObj].type == "rpr_light" && m_listObjectDeclared[iObj].obj == light) - { - indexFound = iObj; - break; - } - } - if (indexFound != -1) - { - //if light already saved, just save reference - if (!Store_ReferenceToObject(name, "rpr_light", m_listObjectDeclared[indexFound].id)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - } - else - { - //if light not already saved - - if (!Store_StartObject(name, "rpr_light", light)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - rpr_light_type type = 0; - status = rprLightGetInfo(light, RPR_LIGHT_TYPE, sizeof(rpr_light_type), &type, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_LIGHT_TYPE", RPSPT_UNDEF, sizeof(rpr_light_type), &type)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - if (type == RPR_LIGHT_TYPE_POINT) - { - float radian4f[4]; - status = rprLightGetInfo(light, RPR_POINT_LIGHT_RADIANT_POWER, sizeof(radian4f), &radian4f, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_POINT_LIGHT_RADIANT_POWER", RPSPT_FLOAT3, 3 * sizeof(float), radian4f)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - } - else if (type == RPR_LIGHT_TYPE_DIRECTIONAL) - { - float radian4f[4]; - status = rprLightGetInfo(light, RPR_DIRECTIONAL_LIGHT_RADIANT_POWER, sizeof(radian4f), &radian4f, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_DIRECTIONAL_LIGHT_RADIANT_POWER", RPSPT_FLOAT3, 3 * sizeof(float), radian4f)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - float shadowSoftness; - status = rprLightGetInfo(light, RPR_DIRECTIONAL_LIGHT_SHADOW_SOFTNESS, sizeof(shadowSoftness), &shadowSoftness, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_DIRECTIONAL_LIGHT_SHADOW_SOFTNESS", RPSPT_FLOAT1, 1 * sizeof(float), &shadowSoftness)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - } - else if (type == RPR_LIGHT_TYPE_SPOT) - { - float radian4f[4]; - status = rprLightGetInfo(light, RPR_SPOT_LIGHT_RADIANT_POWER, sizeof(radian4f), &radian4f, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SPOT_LIGHT_RADIANT_POWER", RPSPT_FLOAT3, 3 * sizeof(float), radian4f)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - float coneShape[2]; - status = rprLightGetInfo(light, RPR_SPOT_LIGHT_CONE_SHAPE, sizeof(coneShape), &coneShape, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SPOT_LIGHT_CONE_SHAPE", RPSPT_FLOAT2, sizeof(coneShape), coneShape)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - } - else if (type == RPR_LIGHT_TYPE_ENVIRONMENT) - { - rpr_image image = NULL; - status = rprLightGetInfo(light, RPR_ENVIRONMENT_LIGHT_IMAGE, sizeof(rpr_image), &image, NULL); - CHECK_STATUS_RETURNERROR; - if (image) - { - status = Store_Image((rpr_image)image, "RPR_ENVIRONMENT_LIGHT_IMAGE"); - CHECK_STATUS_RETURNERROR; - } - - float intensityScale; - status = rprLightGetInfo(light, RPR_ENVIRONMENT_LIGHT_INTENSITY_SCALE, sizeof(intensityScale), &intensityScale, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_ENVIRONMENT_LIGHT_INTENSITY_SCALE", RPSPT_FLOAT1, sizeof(intensityScale), &intensityScale)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - size_t nbOfPortals = 0; - status = rprLightGetInfo(light, RPR_ENVIRONMENT_LIGHT_PORTAL_COUNT, sizeof(nbOfPortals), &nbOfPortals, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_ENVIRONMENT_LIGHT_PORTAL_COUNT", RPSPT_INT64_1, sizeof(nbOfPortals), &nbOfPortals)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - if (nbOfPortals > 0) - { - rpr_shape* shapes = new rpr_shape[nbOfPortals]; - status = rprLightGetInfo(light, RPR_ENVIRONMENT_LIGHT_PORTAL_LIST, nbOfPortals * sizeof(rpr_shape), shapes, NULL); - CHECK_STATUS_RETURNERROR; - - for (uint64_t i = 0; i < nbOfPortals; i++) - { - rpr_int err = Store_Shape(shapes[i], STR__SHAPE_FOR_ENVIRONMENT_LIGHT_PORTAL_ID); - if (err != RPR_SUCCESS) - { - RPS_MACRO_ERROR(); - return err; - } - } - - delete[] shapes; shapes = NULL; - } - - } - else if (type == RPR_LIGHT_TYPE_SKY) - { - float scale = 0.0f; - status = rprLightGetInfo(light, RPR_SKY_LIGHT_SCALE, sizeof(scale), &scale, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SKY_LIGHT_SCALE", RPSPT_FLOAT1, sizeof(scale), &scale)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - float albedo = 0.0f; - status = rprLightGetInfo(light, RPR_SKY_LIGHT_ALBEDO, sizeof(albedo), &albedo, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SKY_LIGHT_ALBEDO", RPSPT_FLOAT1, sizeof(albedo), &albedo)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - float turbidity = 0.0f; - status = rprLightGetInfo(light, RPR_SKY_LIGHT_TURBIDITY, sizeof(turbidity), &turbidity, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SKY_LIGHT_TURBIDITY", RPSPT_FLOAT1, sizeof(turbidity), &turbidity)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - size_t nbOfPortals = 0; - status = rprLightGetInfo(light, RPR_SKY_LIGHT_PORTAL_COUNT, sizeof(nbOfPortals), &nbOfPortals, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SKY_LIGHT_PORTAL_COUNT", RPSPT_INT64_1, sizeof(nbOfPortals), &nbOfPortals)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - if (nbOfPortals > 0) - { - rpr_shape* shapes = new rpr_shape[nbOfPortals]; - status = rprLightGetInfo(light, RPR_SKY_LIGHT_PORTAL_LIST, nbOfPortals * sizeof(rpr_shape), shapes, NULL); - CHECK_STATUS_RETURNERROR; - - for (uint64_t i = 0; i < nbOfPortals; i++) - { - rpr_int err = Store_Shape(shapes[i], STR__SHAPE_FOR_SKY_LIGHT_PORTAL_ID); - if (err != RPR_SUCCESS) - { - RPS_MACRO_ERROR(); - return err; - } - } - - delete[] shapes; shapes = NULL; - } - - } - else if (type == RPR_LIGHT_TYPE_IES) - { - float radian4f[4]; - status = rprLightGetInfo(light, RPR_IES_LIGHT_RADIANT_POWER, sizeof(radian4f), radian4f, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_IES_LIGHT_RADIANT_POWER", RPSPT_FLOAT3, 3 * sizeof(float), radian4f)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - rpr_ies_image_desc iesdesc; - status = rprLightGetInfo(light, RPR_IES_LIGHT_IMAGE_DESC, sizeof(iesdesc), &iesdesc, NULL); - CHECK_STATUS_RETURNERROR; - - if (!Store_ObjectParameter("RPR_IES_LIGHT_IMAGE_DESC_W", RPSPT_INT32_1, sizeof(iesdesc.w), &iesdesc.w)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - if (!Store_ObjectParameter("RPR_IES_LIGHT_IMAGE_DESC_H", RPSPT_INT32_1, sizeof(iesdesc.h), &iesdesc.h)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - if (iesdesc.data) - { - uint64_t dataSize = strlen(iesdesc.data) + 1; // include null-terminated character - if (!Store_ObjectParameter("RPR_IES_LIGHT_IMAGE_DESC_DATA_SIZE", RPSPT_UINT64_1, sizeof(dataSize), &dataSize)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - if (!Store_ObjectParameter("RPR_IES_LIGHT_IMAGE_DESC_DATA", RPSPT_UNDEF, dataSize, iesdesc.data)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - } - else - { - WarningDetected(); - } - - } - else - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INVALID_PARAMETER; - } - - float lightTransform[16]; - status = rprLightGetInfo(light, RPR_LIGHT_TRANSFORM, sizeof(lightTransform), &lightTransform, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_LIGHT_TRANSFORM", RPSPT_FLOAT16, sizeof(lightTransform), lightTransform)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - //save RPR_OBJECT_NAME of object. - size_t frobjectName_size = 0; - status = rprLightGetInfo(light, RPR_OBJECT_NAME, NULL, NULL, &frobjectName_size); - CHECK_STATUS_RETURNERROR; - if (frobjectName_size <= 0) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } // because of 0 terminated character, size must be >= 1 - char* frobjectName_data = new char[frobjectName_size]; - status = rprLightGetInfo(light, RPR_OBJECT_NAME, frobjectName_size, frobjectName_data, NULL); - CHECK_STATUS_RETURNERROR; - if (frobjectName_data[frobjectName_size - 1] != '\0') { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } // check that the last character is '\0' - if (!Store_ObjectParameter("RPR_OBJECT_NAME", RPSPT_UNDEF, frobjectName_size, frobjectName_data)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - delete[] frobjectName_data; frobjectName_data = NULL; - - - if (!Store_EndObject()) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - } - - return RPR_SUCCESS; - -} - -rpr_int RPS8::Store_Shape(rpr_shape shape, const std::string& name) -{ - rpr_int status = RPR_SUCCESS; - - int indexFound = -1; - //search if this shape is already saved. - for (int iObj = 0; iObj < m_listObjectDeclared.size(); iObj++) - { - if (m_listObjectDeclared[iObj].type == "rpr_shape" && m_listObjectDeclared[iObj].obj == shape) - { - indexFound = iObj; - break; - } - } - if (indexFound != -1) - { - //if shape already saved, just save reference - if (!Store_ReferenceToObject(name, "rpr_shape", m_listObjectDeclared[indexFound].id)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - } - else - { - //if shape not already saved - - if (!Store_StartObject(name, "rpr_shape", shape)) { return RPR_ERROR_INTERNAL_ERROR; } - - rpr_shape_type type; - status = rprShapeGetInfo(shape, RPR_SHAPE_TYPE, sizeof(rpr_shape_type), &type, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SHAPE_TYPE", RPSPT_UNDEF, sizeof(type), &type)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - if ( - type == RPR_SHAPE_TYPE_MESH - ) - { - - //m_shapeList.push_back(shape); - - uint64_t poly_count = 0; - status = rprMeshGetInfo(shape, RPR_MESH_POLYGON_COUNT, sizeof(poly_count), &poly_count, NULL); //number of primitives - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_MESH_POLYGON_COUNT", RPSPT_UINT64_1, sizeof(poly_count), &poly_count)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - uint64_t vertex_count = 0; - status = rprMeshGetInfo(shape, RPR_MESH_VERTEX_COUNT, sizeof(vertex_count), &vertex_count, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_MESH_VERTEX_COUNT", RPSPT_UINT64_1, sizeof(vertex_count), &vertex_count)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - uint64_t normal_count = 0; - status = rprMeshGetInfo(shape, RPR_MESH_NORMAL_COUNT, sizeof(normal_count), &normal_count, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_MESH_NORMAL_COUNT", RPSPT_UINT64_1, sizeof(normal_count), &normal_count)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - uint64_t uv_count = 0; - status = rprMeshGetInfo(shape, RPR_MESH_UV_COUNT, sizeof(uv_count), &uv_count, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_MESH_UV_COUNT", RPSPT_UINT64_1, sizeof(uv_count), &uv_count)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - uint64_t uv2_count = 0; - status = rprMeshGetInfo(shape, RPR_MESH_UV2_COUNT, sizeof(uv2_count), &uv2_count, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_MESH_UV2_COUNT", RPSPT_UINT64_1, sizeof(uv2_count), &uv2_count)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - if (vertex_count) - { - size_t required_size_size_t = 0; - status = rprMeshGetInfo(shape, RPR_MESH_VERTEX_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - float* data = new float[required_size / sizeof(float)]; - status = rprMeshGetInfo(shape, RPR_MESH_VERTEX_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_MESH_VERTEX_ARRAY", RPSPT_UINT64_1, required_size, data)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - delete[] data; data = NULL; - } - if (normal_count) - { - size_t required_size_size_t = 0; - status = rprMeshGetInfo(shape, RPR_MESH_NORMAL_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - float* data = new float[required_size / sizeof(float)]; - status = rprMeshGetInfo(shape, RPR_MESH_NORMAL_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_MESH_NORMAL_ARRAY", RPSPT_UINT64_1, required_size, data)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - delete[] data; data = NULL; - } - if (uv_count) - { - size_t required_size_size_t = 0; - status = rprMeshGetInfo(shape, RPR_MESH_UV_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - float* data = new float[required_size / sizeof(float)]; - status = rprMeshGetInfo(shape, RPR_MESH_UV_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_MESH_UV_ARRAY", RPSPT_UINT64_1, required_size, data)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - delete[] data; - data = NULL; - - } - if (uv2_count) - { - size_t required_size_size_t = 0; - status = rprMeshGetInfo(shape, RPR_MESH_UV2_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - float* data = new float[required_size / sizeof(float)]; - status = rprMeshGetInfo(shape, RPR_MESH_UV2_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_MESH_UV2_ARRAY", RPSPT_UINT64_1, required_size, data)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - delete[] data; - data = NULL; - - } - if (poly_count) - { - size_t required_size_size_t = 0; - status = rprMeshGetInfo(shape, RPR_MESH_VERTEX_INDEX_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - int32_t* data = new int32_t[required_size / sizeof(int32_t)]; - status = rprMeshGetInfo(shape, RPR_MESH_VERTEX_INDEX_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_MESH_VERTEX_INDEX_ARRAY", RPSPT_UNDEF, required_size, data)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - delete[] data; data = NULL; - - } - if (normal_count) - { - size_t required_size_size_t = 0; - status = rprMeshGetInfo(shape, RPR_MESH_NORMAL_INDEX_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - int32_t* data = new int32_t[required_size / sizeof(int32_t)]; - status = rprMeshGetInfo(shape, RPR_MESH_NORMAL_INDEX_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_MESH_NORMAL_INDEX_ARRAY", RPSPT_UNDEF, required_size, data)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - delete[] data; data = NULL; - - } - if (uv_count) - { - size_t required_size_size_t = 0; - status = rprMeshGetInfo(shape, RPR_MESH_UV_INDEX_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - int32_t* data = new int32_t[required_size / sizeof(int32_t)]; - status = rprMeshGetInfo(shape, RPR_MESH_UV_INDEX_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_MESH_UV_INDEX_ARRAY", RPSPT_UNDEF, required_size, data)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - delete[] data; data = NULL; - - } - if (uv2_count) - { - size_t required_size_size_t = 0; - status = rprMeshGetInfo(shape, RPR_MESH_UV2_INDEX_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - int32_t* data = new int32_t[required_size / sizeof(int32_t)]; - status = rprMeshGetInfo(shape, RPR_MESH_UV2_INDEX_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_MESH_UV2_INDEX_ARRAY", RPSPT_UNDEF, required_size, data)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - delete[] data; data = NULL; - - } - if (poly_count) - { - size_t required_size_size_t = 0; - status = rprMeshGetInfo(shape, RPR_MESH_NUM_FACE_VERTICES_ARRAY, 0, NULL, &required_size_size_t); - uint64_t required_size = required_size_size_t; - CHECK_STATUS_RETURNERROR; - int32_t* data = new int32_t[required_size / sizeof(int32_t)]; - status = rprMeshGetInfo(shape, RPR_MESH_NUM_FACE_VERTICES_ARRAY, required_size, data, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_MESH_NUM_VERTICES_ARRAY", RPSPT_UNDEF, required_size, data)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - delete[] data; data = NULL; - - } - - } - else if (type == RPR_SHAPE_TYPE_INSTANCE) - { - //search address of original shape - - rpr_shape shapeOriginal = NULL; - status = rprInstanceGetBaseShape(shape, &shapeOriginal); - CHECK_STATUS_RETURNERROR; - - if (shapeOriginal == 0) - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - bool found = false; - for (int iShape = 0; iShape < m_listObjectDeclared.size(); iShape++) - { - if (m_listObjectDeclared[iShape].type == "rpr_shape" && m_listObjectDeclared[iShape].obj == shapeOriginal) - { - int32_t IDShapeBase = m_listObjectDeclared[iShape].id; - if (!Store_ObjectParameter(STR__SHAPE_INSTANCE_REFERENCE_ID, RPSPT_INT32_1, sizeof(IDShapeBase), &IDShapeBase)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - found = true; - break; - } - } - - if (!found) - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - } - - - rpr_material_node data_shader = 0; - status = rprShapeGetInfo(shape, RPR_SHAPE_MATERIAL, sizeof(data_shader), &data_shader, NULL); - CHECK_STATUS_RETURNERROR; - if (data_shader != NULL) - { - rpr_int error = Store_MaterialNode(data_shader, "shaderOfShape"); - if (error != RPR_SUCCESS) - { - return error; - } - } - - - float data_transform[16]; - status = rprShapeGetInfo(shape, RPR_SHAPE_TRANSFORM, sizeof(data_transform), data_transform, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SHAPE_TRANSFORM", RPSPT_FLOAT16, sizeof(data_transform), data_transform)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - - float data_linMotion[4]; - status = rprShapeGetInfo(shape, RPR_SHAPE_LINEAR_MOTION, sizeof(data_linMotion), data_linMotion, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SHAPE_LINEAR_MOTION", RPSPT_FLOAT3, 3 * sizeof(float), data_linMotion)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - float data_angMotion[4]; - status = rprShapeGetInfo(shape, RPR_SHAPE_ANGULAR_MOTION, sizeof(data_angMotion), data_angMotion, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SHAPE_ANGULAR_MOTION", RPSPT_FLOAT4, sizeof(data_angMotion), data_angMotion)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - rpr_bool data_visFlag; - status = rprShapeGetInfo(shape, RPR_SHAPE_VISIBILITY_FLAG, sizeof(data_visFlag), &data_visFlag, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SHAPE_VISIBILITY", RPSPT_INT32_1, sizeof(data_visFlag), &data_visFlag)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - rpr_bool data_shadoflag; - status = rprShapeGetInfo(shape, RPR_SHAPE_SHADOW_FLAG, sizeof(data_shadoflag), &data_shadoflag, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SHAPE_SHADOW", RPSPT_INT32_1, sizeof(data_shadoflag), &data_shadoflag)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - rpr_bool data_shadocatcherflag; - status = rprShapeGetInfo(shape, RPR_SHAPE_SHADOW_CATCHER_FLAG, sizeof(data_shadocatcherflag), &data_shadocatcherflag, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SHAPE_SHADOW_CATCHER", RPSPT_INT32_1, sizeof(data_shadocatcherflag), &data_shadocatcherflag)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - - rpr_uint data_subdiv; - status = rprShapeGetInfo(shape, RPR_SHAPE_SUBDIVISION_FACTOR, sizeof(data_subdiv), &data_subdiv, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SHAPE_SUBDIVISION_FACTOR", RPSPT_UINT32_1, sizeof(data_subdiv), &data_subdiv)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - rpr_float data_subdivceaseweight; - status = rprShapeGetInfo(shape, RPR_SHAPE_SUBDIVISION_CREASEWEIGHT, sizeof(data_subdivceaseweight), &data_subdivceaseweight, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SHAPE_SUBDIVISION_CREASEWEIGHT", RPSPT_FLOAT1, sizeof(data_subdivceaseweight), &data_subdivceaseweight)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - rpr_uint data_subdivboundinterop; - status = rprShapeGetInfo(shape, RPR_SHAPE_SUBDIVISION_BOUNDARYINTEROP, sizeof(data_subdivboundinterop), &data_subdivboundinterop, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SHAPE_SUBDIVISION_BOUNDARYINTEROP", RPSPT_UINT32_1, sizeof(data_subdivboundinterop), &data_subdivboundinterop)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - rpr_float data_displacementscale[2]; - status = rprShapeGetInfo(shape, RPR_SHAPE_DISPLACEMENT_SCALE, sizeof(data_displacementscale), &data_displacementscale, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SHAPE_DISPLACEMENT_SCALE", RPSPT_FLOAT2, sizeof(data_displacementscale), &data_displacementscale)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - rpr_uint data_objectGroupId; - status = rprShapeGetInfo(shape, RPR_SHAPE_OBJECT_GROUP_ID, sizeof(data_objectGroupId), &data_objectGroupId, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_SHAPE_OBJECT_GROUP_ID", RPSPT_UINT32_1, sizeof(data_objectGroupId), &data_objectGroupId)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - - rpr_image displacementimage = NULL; - status = rprShapeGetInfo(shape, RPR_SHAPE_DISPLACEMENT_IMAGE, sizeof(rpr_image), &displacementimage, NULL); - CHECK_STATUS_RETURNERROR; - if (displacementimage) - { - status = Store_Image(displacementimage, "RPR_SHAPE_DISPLACEMENT_IMAGE"); - CHECK_STATUS_RETURNERROR; - } - - - //save RPR_OBJECT_NAME of object. - size_t frobjectName_size = 0; - status = rprShapeGetInfo(shape, RPR_OBJECT_NAME, NULL, NULL, &frobjectName_size); - CHECK_STATUS_RETURNERROR; - if (frobjectName_size <= 0) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } // because of 0 terminated character, size must be >= 1 - char* frobjectName_data = new char[frobjectName_size]; - status = rprShapeGetInfo(shape, RPR_OBJECT_NAME, frobjectName_size, frobjectName_data, NULL); - CHECK_STATUS_RETURNERROR; - if (frobjectName_data[frobjectName_size - 1] != '\0') { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } // check that the last character is '\0' - if (!Store_ObjectParameter("RPR_OBJECT_NAME", RPSPT_UNDEF, frobjectName_size, frobjectName_data)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - delete[] frobjectName_data; frobjectName_data = NULL; - - - if (!Store_EndObject()) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - } - return RPR_SUCCESS; -} - - -rpr_int RPS8::Store_Image(rpr_image image, const std::string& name) -{ - - rpr_int status = RPR_SUCCESS; - - - int indexFound = -1; - //search if this image is already saved. - for (int iObj = 0; iObj < m_listObjectDeclared.size(); iObj++) - { - if (m_listObjectDeclared[iObj].type == "rpr_image" && m_listObjectDeclared[iObj].obj == image) - { - indexFound = iObj; - break; - } - } - if (indexFound != -1) - { - //if image already saved, just save reference - if (!Store_ReferenceToObject(name, "rpr_image", m_listObjectDeclared[indexFound].id)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - } - else - { - //if image not already saved - - - if (!Store_StartObject(name, "rpr_image", image)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - - //auto pos = std::find(m_imageList.begin(), m_imageList.end(), image); - //if (pos == m_imageList.end()) - //{ - // //if image not already saved - // m_imageList.push_back(image); - // int32_t imageIndex = -1; // index = -1 --> means that the image was not already saved prviously - // myfile->write((const char*)&imageIndex, sizeof(imageIndex)); - //} - //else - //{ - // //if image already saved - // int32_t imageIndex = (int32_t)(pos - m_imageList.begin()); - // myfile->write((const char*)&imageIndex, sizeof(imageIndex)); - // myfile->write((const char*)&m_IMAGE_END, sizeof(m_IMAGE_END)); - // return RPR_SUCCESS; - //} - - - rpr_image_format format; - status = rprImageGetInfo(image, RPR_IMAGE_FORMAT, sizeof(format), &format, NULL); - CHECK_STATUS_RETURNERROR; - //myfile->write((char*)&format, sizeof(rpr_image_format)); - if (!Store_ObjectParameter("RPR_IMAGE_FORMAT", RPSPT_UNDEF, sizeof(rpr_image_format), &format)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - rpr_image_desc desc; - status = rprImageGetInfo(image, RPR_IMAGE_DESC, sizeof(desc), &desc, NULL); - CHECK_STATUS_RETURNERROR - //myfile->write((char*)&desc, sizeof(rpr_image_desc)); - if (!Store_ObjectParameter("RPR_IMAGE_DESC", RPSPT_UNDEF, sizeof(rpr_image_desc), &desc)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - rpr_uint imgWrap; - status = rprImageGetInfo(image, RPR_IMAGE_WRAP, sizeof(imgWrap), &imgWrap, NULL); - CHECK_STATUS_RETURNERROR; - if (!Store_ObjectParameter("RPR_IMAGE_WRAP", RPSPT_UINT32_1, sizeof(imgWrap), &imgWrap)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - size_t size_size_t = 0; - status = rprImageGetInfo(image, RPR_IMAGE_DATA, 0, NULL, &size_size_t); - uint64_t size = size_size_t; - CHECK_STATUS_RETURNERROR - char *idata = new char[size]; - //myfile->write((char*)&size, sizeof(uint64_t)); - status = rprImageGetInfo(image, RPR_IMAGE_DATA, size, idata, NULL); - CHECK_STATUS_RETURNERROR - //myfile->write(idata, size); - if (!Store_ObjectParameter("RPR_IMAGE_DATA", RPSPT_UNDEF, size, idata)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - delete[] idata; idata = NULL; - - - //save RPR_OBJECT_NAME of object. - size_t frobjectName_size = 0; - status = rprImageGetInfo(image, RPR_OBJECT_NAME, NULL, NULL, &frobjectName_size); - CHECK_STATUS_RETURNERROR; - if (frobjectName_size <= 0) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } // because of 0 terminated character, size must be >= 1 - char* frobjectName_data = new char[frobjectName_size]; - status = rprImageGetInfo(image, RPR_OBJECT_NAME, frobjectName_size, frobjectName_data, NULL); - CHECK_STATUS_RETURNERROR; - if (frobjectName_data[frobjectName_size - 1] != '\0') { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } // check that the last character is '\0' - if (!Store_ObjectParameter("RPR_OBJECT_NAME", RPSPT_UNDEF, frobjectName_size, frobjectName_data)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - delete[] frobjectName_data; frobjectName_data = NULL; - - - if (!Store_EndObject()) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - } - return status; -} - - - -rpr_int RPS8::Store_Scene(rpr_scene scene) -{ - rpr_int status = RPR_SUCCESS; - - if (!Store_StartObject("sceneDeclare", "rpr_scene", scene)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - uint64_t nbShape = 0; - status = rprSceneGetInfo(scene, RPR_SCENE_SHAPE_COUNT, sizeof(nbShape), &nbShape, NULL); - CHECK_STATUS_RETURNERROR; - uint64_t nbLight = 0; - status = rprSceneGetInfo(scene, RPR_SCENE_LIGHT_COUNT, sizeof(nbLight), &nbLight, NULL); - CHECK_STATUS_RETURNERROR; - //uint64_t nbTexture = 0; - //status = rprSceneGetInfo(scene, RPR_SCENE_TEXTURE_COUNT, sizeof(nbTexture), &nbTexture, NULL); - //CHECK_STATUS_RETURNERROR; - - - //myfile->write((char*)&nbShape, sizeof(nbShape)); - //myfile->write((char*)&nbLight, sizeof(nbLight)); - //myfile->write((char*)&nbTexture, sizeof(nbTexture)); - - rpr_shape* shapes = NULL; - rpr_light* light = NULL; - - if (nbShape >= 1) - { - shapes = new rpr_shape[nbShape]; - status = rprSceneGetInfo(scene, RPR_SCENE_SHAPE_LIST, nbShape * sizeof(rpr_shape), shapes, NULL); - CHECK_STATUS_RETURNERROR; - } - - if (nbLight >= 1) - { - light = new rpr_light[nbLight]; - status = rprSceneGetInfo(scene, RPR_SCENE_LIGHT_LIST, nbLight * sizeof(rpr_light), light, NULL); - CHECK_STATUS_RETURNERROR; - } - - - for (uint64_t i = 0; i < nbShape; i++) // first: store non-instanciate shapes - { - rpr_shape_type type; - status = rprShapeGetInfo(shapes[i], RPR_SHAPE_TYPE, sizeof(rpr_shape_type), &type, NULL); - CHECK_STATUS_RETURNERROR; - if (type == RPR_SHAPE_TYPE_MESH) - { - rpr_int err = Store_Shape(shapes[i], STR__nonInstancedSceneShape_ID); - if (err != RPR_SUCCESS) - { - RPS_MACRO_ERROR(); - return err; // easier for debug if stop everything - } - } - } - - for (uint64_t i = 0; i < nbShape; i++)// second: store instanciate shapes only - { - rpr_shape_type type; - status = rprShapeGetInfo(shapes[i], RPR_SHAPE_TYPE, sizeof(rpr_shape_type), &type, NULL); - CHECK_STATUS_RETURNERROR; - if (type != RPR_SHAPE_TYPE_MESH) - { - rpr_int err = Store_Shape(shapes[i], STR__InstancedSceneShape_ID); - if (err != RPR_SUCCESS) - { - RPS_MACRO_ERROR(); - return err; // easier for debug if stop everything - } - } - } - - for (uint64_t i = 0; i < nbLight; i++) - { - rpr_int err = Store_Light(light[i], STR__SCENE_LIGHT_ID); - if (err != RPR_SUCCESS) - { - RPS_MACRO_ERROR(); - return err; // easier for debug if stop everything - } - } - - if (shapes) { delete[] shapes; shapes = NULL; } - if (light) { delete[] light; light = NULL; } - - rpr_camera camera = NULL; - status = rprSceneGetCamera(scene, &camera); - CHECK_STATUS_RETURNERROR; - if (camera) - { - status = Store_Camera(camera, "sceneCamera"); - CHECK_STATUS_RETURNERROR; - } - - - rpr_light light_override_REFRACTION = 0; - status = rprSceneGetEnvironmentOverride(scene, RPR_SCENE_ENVIRONMENT_OVERRIDE_REFRACTION, &light_override_REFRACTION); - CHECK_STATUS_RETURNERROR; - if (light_override_REFRACTION) - { - status = Store_Light(light_override_REFRACTION, STR__SCENE_ENV_OVERRIGHT_REFRACTION_ID); - CHECK_STATUS_RETURNERROR; - } - - rpr_light light_override_REFLECTION = 0; - status = rprSceneGetEnvironmentOverride(scene, RPR_SCENE_ENVIRONMENT_OVERRIDE_REFLECTION, &light_override_REFLECTION); - CHECK_STATUS_RETURNERROR; - if (light_override_REFLECTION) - { - status = Store_Light(light_override_REFLECTION, STR__SCENE_ENV_OVERRIGHT_REFLECTION_ID); - CHECK_STATUS_RETURNERROR; - } - - rpr_light light_override_BACKGROUND = 0; - status = rprSceneGetEnvironmentOverride(scene, RPR_SCENE_ENVIRONMENT_OVERRIDE_BACKGROUND, &light_override_BACKGROUND); - CHECK_STATUS_RETURNERROR; - if (light_override_BACKGROUND) - { - status = Store_Light(light_override_BACKGROUND, STR__SCENE_ENV_OVERRIGHT_BACKGROUND_ID); - CHECK_STATUS_RETURNERROR; - } - - rpr_light light_override_TRANSPARENCY = 0; - status = rprSceneGetEnvironmentOverride(scene, RPR_SCENE_ENVIRONMENT_OVERRIDE_TRANSPARENCY, &light_override_TRANSPARENCY); - CHECK_STATUS_RETURNERROR; - if (light_override_TRANSPARENCY) - { - status = Store_Light(light_override_TRANSPARENCY, STR__SCENE_ENV_OVERRIGHT_TRANSPARENCY_ID); - CHECK_STATUS_RETURNERROR; - } - - rpr_image image_scene_background = 0; - status = rprSceneGetBackgroundImage(scene, &image_scene_background); - CHECK_STATUS_RETURNERROR; - if (image_scene_background) - { - status = Store_Image(image_scene_background, STR__SCENE_BACKGROUND_IMAGE_ID); - CHECK_STATUS_RETURNERROR; - } - - - //save RPR_OBJECT_NAME of object. - size_t frobjectName_size = 0; - status = rprSceneGetInfo(scene, RPR_OBJECT_NAME, NULL, NULL, &frobjectName_size); - CHECK_STATUS_RETURNERROR; - if (frobjectName_size <= 0) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } // because of 0 terminated character, size must be >= 1 - char* frobjectName_data = new char[frobjectName_size]; - status = rprSceneGetInfo(scene, RPR_OBJECT_NAME, frobjectName_size, frobjectName_data, NULL); - CHECK_STATUS_RETURNERROR; - if (frobjectName_data[frobjectName_size - 1] != '\0') { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } // check that the last character is '\0' - if (!Store_ObjectParameter("RPR_OBJECT_NAME", RPSPT_UNDEF, frobjectName_size, frobjectName_data)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - delete[] frobjectName_data; frobjectName_data = NULL; - - - if (!Store_EndObject()) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - return RPR_SUCCESS; - -} - - -rpr_int RPS8::Store_Context(rpr_context context) -{ - - rpr_int status = RPR_SUCCESS; - - if (!Store_StartObject("contextDeclare", "rpr_context", context)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - uint64_t param_count = 0; - status = rprContextGetInfo(context, RPR_CONTEXT_PARAMETER_COUNT, sizeof(uint64_t), ¶m_count, NULL); - CHECK_STATUS_RETURNERROR; - - unsigned int imagefilter_type = -1; - unsigned int tonemapping_type = -1; - - for (int iPass = 0; iPass < 2; iPass++) - { - for (uint64_t i = 0; i < param_count; i++) - { - size_t name_length_size_t = 0; - status = rprContextGetParameterInfo(context, int(i), RPR_PARAMETER_NAME_STRING, 0, NULL, &name_length_size_t); - uint64_t name_length = name_length_size_t; - CHECK_STATUS_RETURNERROR; - char* paramName = new char[name_length]; - status = rprContextGetParameterInfo(context, int(i), RPR_PARAMETER_NAME_STRING, name_length, paramName, NULL); - CHECK_STATUS_RETURNERROR; - if (paramName[name_length - 1] != 0) // supposed to be null-terminated - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - rpr_context_info paramID = 0; - status = rprContextGetParameterInfo(context, int(i), RPR_PARAMETER_NAME, sizeof(paramID), ¶mID, NULL); - CHECK_STATUS_RETURNERROR; - - //need to store in 2 passes. - //first, we store the parameters that will set several default parameters. - //so we are sure that all custom parameters will be set during the load of context - if ( - (iPass == 0 && (paramID == RPR_CONTEXT_IMAGE_FILTER_TYPE || paramID == RPR_CONTEXT_TONE_MAPPING_TYPE)) - || - (iPass == 1 && paramID != RPR_CONTEXT_IMAGE_FILTER_TYPE && paramID != RPR_CONTEXT_TONE_MAPPING_TYPE) - ) - { - - //don't store values that don't fitt with filter/tonemap types - bool storeValue = true; - if (paramID == RPR_CONTEXT_IMAGE_FILTER_BOX_RADIUS && imagefilter_type != RPR_FILTER_BOX) { storeValue = false; } - if (paramID == RPR_CONTEXT_IMAGE_FILTER_GAUSSIAN_RADIUS && imagefilter_type != RPR_FILTER_GAUSSIAN) { storeValue = false; } - if (paramID == RPR_CONTEXT_IMAGE_FILTER_TRIANGLE_RADIUS && imagefilter_type != RPR_FILTER_TRIANGLE) { storeValue = false; } - if (paramID == RPR_CONTEXT_IMAGE_FILTER_MITCHELL_RADIUS && imagefilter_type != RPR_FILTER_MITCHELL) { storeValue = false; } - if (paramID == RPR_CONTEXT_IMAGE_FILTER_LANCZOS_RADIUS && imagefilter_type != RPR_FILTER_LANCZOS) { storeValue = false; } - if (paramID == RPR_CONTEXT_IMAGE_FILTER_BLACKMANHARRIS_RADIUS && imagefilter_type != RPR_FILTER_BLACKMANHARRIS) { storeValue = false; } - - if (paramID == RPR_CONTEXT_TONE_MAPPING_LINEAR_SCALE && tonemapping_type != RPR_TONEMAPPING_OPERATOR_LINEAR) { storeValue = false; } - if (paramID == RPR_CONTEXT_TONE_MAPPING_PHOTO_LINEAR_SENSITIVITY && tonemapping_type != RPR_TONEMAPPING_OPERATOR_PHOTOLINEAR) { storeValue = false; } - if (paramID == RPR_CONTEXT_TONE_MAPPING_PHOTO_LINEAR_EXPOSURE && tonemapping_type != RPR_TONEMAPPING_OPERATOR_PHOTOLINEAR) { storeValue = false; } - if (paramID == RPR_CONTEXT_TONE_MAPPING_PHOTO_LINEAR_FSTOP && tonemapping_type != RPR_TONEMAPPING_OPERATOR_PHOTOLINEAR) { storeValue = false; } - if (paramID == RPR_CONTEXT_TONE_MAPPING_REINHARD02_PRE_SCALE && tonemapping_type != RPR_TONEMAPPING_OPERATOR_REINHARD02) { storeValue = false; } - if (paramID == RPR_CONTEXT_TONE_MAPPING_REINHARD02_POST_SCALE && tonemapping_type != RPR_TONEMAPPING_OPERATOR_REINHARD02) { storeValue = false; } - if (paramID == RPR_CONTEXT_TONE_MAPPING_REINHARD02_BURN && tonemapping_type != RPR_TONEMAPPING_OPERATOR_REINHARD02) { storeValue = false; } - if (paramID == RPR_CONTEXT_TONE_MAPPING_EXPONENTIAL_INTENSITY && tonemapping_type != RPR_TONEMAPPING_OPERATOR_EXPONENTIAL) { storeValue = false; } - - - if (storeValue) - { - rpr_parameter_type type; - status = rprContextGetParameterInfo(context, int(i), RPR_PARAMETER_TYPE, sizeof(type), &type, NULL); - CHECK_STATUS_RETURNERROR; - - size_t value_length_size_t = 0; - status = rprContextGetParameterInfo(context, int(i), RPR_PARAMETER_VALUE, 0, NULL, &value_length_size_t); - uint64_t value_length = value_length_size_t; - CHECK_STATUS_RETURNERROR; - - char* paramValue = NULL; - if (value_length > 0) - { - paramValue = new char[value_length]; - status = rprContextGetParameterInfo(context, int(i), RPR_PARAMETER_VALUE, value_length, paramValue, NULL); - CHECK_STATUS_RETURNERROR; - - if (paramID == RPR_CONTEXT_IMAGE_FILTER_TYPE && type == RPR_PARAMETER_TYPE_UINT) - { - imagefilter_type = ((unsigned int*)(paramValue))[0]; - } - if (paramID == RPR_CONTEXT_TONE_MAPPING_TYPE && type == RPR_PARAMETER_TYPE_UINT) - { - tonemapping_type = ((unsigned int*)(paramValue))[0]; - } - - } - - if (!Store_ObjectParameter(paramName, RPRPARAMETERTYPE_to_RPSPT(type), value_length, paramValue)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - if (paramValue) { delete[] paramValue; paramValue = NULL; } - } - } - - delete[] paramName; paramName = NULL; - } - } - - - //save RPR_OBJECT_NAME of object. - size_t frobjectName_size = 0; - status = rprContextGetInfo(context, RPR_OBJECT_NAME, NULL, NULL, &frobjectName_size); - CHECK_STATUS_RETURNERROR; - if (frobjectName_size <= 0) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } // because of 0 terminated character, size must be >= 1 - char* frobjectName_data = new char[frobjectName_size]; - status = rprContextGetInfo(context, RPR_OBJECT_NAME, frobjectName_size, frobjectName_data, NULL); - CHECK_STATUS_RETURNERROR; - if (frobjectName_data[frobjectName_size - 1] != '\0') { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } // check that the last character is '\0' - if (!Store_ObjectParameter("RPR_OBJECT_NAME", RPSPT_UNDEF, frobjectName_size, frobjectName_data)) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - delete[] frobjectName_data; frobjectName_data = NULL; - - - - if (!Store_EndObject()) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - return RPR_SUCCESS; -} - - -bool RPS8::Store_String(const std::string& str) -{ - uint32_t strSize = (uint32_t)str.length(); - m_rpsFile->write((const char*)&strSize, sizeof(strSize)); - if (strSize > 0) - { - m_rpsFile->write((const char*)str.c_str(), strSize); - } - return true; -} - -bool RPS8::Store_ReferenceToObject(const std::string& objName, const std::string& type, int32_t id) -{ - //just for debug purpose, we check that the referenced ID actually exists - bool found = false; - for (int i = 0; iwrite((char*)&typeWrite, sizeof(int32_t)); - if (!Store_String(objName)) { RPS_MACRO_ERROR(); return false; } - if (!Store_String(type.c_str())) { RPS_MACRO_ERROR(); return false; } - m_rpsFile->write((const char*)&id, sizeof(id)); - - return true; -} - -bool RPS8::Store_StartObject(const std::string& objName, const std::string& type, void* obj) -{ - RPS_ELEMENTS_TYPE typeWrite = RPSRT_OBJECT_BEG; - m_rpsFile->write((char*)&typeWrite, sizeof(int32_t)); - if (!Store_String(objName)) { RPS_MACRO_ERROR(); return false; } - if (!Store_String(type.c_str())) { RPS_MACRO_ERROR(); return false; } - m_rpsFile->write((const char*)&m_idCounter, sizeof(m_idCounter)); - - RPS_OBJECT_DECLARED newObj; - newObj.id = m_idCounter; - newObj.type = type; - newObj.obj = obj; - m_listObjectDeclared.push_back(newObj); - - m_level++; - m_idCounter++; - - return true; -} - -bool RPS8::Store_EndObject() -{ - m_level--; - if (m_level < 0) - { - RPS_MACRO_ERROR(); - return false; - } - - RPS_ELEMENTS_TYPE typeWrite = RPSRT_OBJECT_END; - m_rpsFile->write((char*)&typeWrite, sizeof(int32_t)); - Store_String(""); // empty string - return true; -} - -bool RPS8::Store_ObjectParameter(const std::string& parameterName, RPS_PARAMETER_TYPE type, uint64_t dataSize, const void* data) -{ - if (data == NULL && dataSize > 0) - { - RPS_MACRO_ERROR(); - return false; - } - if (sizeof(RPS_PARAMETER_TYPE) != sizeof(uint32_t)) - { - RPS_MACRO_ERROR(); - return false; - } - - int32_t sizeOfRPSPT = RPSPT_to_size(type); - if (sizeOfRPSPT != -1 && sizeOfRPSPT != dataSize) - { - RPS_MACRO_ERROR(); - return false; - } - - RPS_ELEMENTS_TYPE typeWrite = RPSRT_PARAMETER; - m_rpsFile->write((char*)&typeWrite, sizeof(int32_t)); - if (!Store_String(parameterName)) { RPS_MACRO_ERROR(); return false; } - m_rpsFile->write((const char*)&type, sizeof(type)); - m_rpsFile->write((const char*)&dataSize, sizeof(dataSize)); - m_rpsFile->write((const char*)data, dataSize); - return true; -} - -int32_t RPS8::RPSPT_to_size(RPS_PARAMETER_TYPE in) -{ - if (in == RPSPT_FLOAT1) { return sizeof(float) * 1; } - else if (in == RPSPT_FLOAT2) { return sizeof(float) * 2; } - else if (in == RPSPT_FLOAT3) { return sizeof(float) * 3; } - else if (in == RPSPT_FLOAT4) { return sizeof(float) * 4; } - else if (in == RPSPT_FLOAT16) { return sizeof(float) * 16; } - - else if (in == RPSPT_UINT32_1) { return sizeof(uint32_t) * 1; } - return -1; -} - -rpr_parameter_type RPS8::RPSPT_to_RPRPARAMETERTYPE(RPS_PARAMETER_TYPE in) -{ - if (in == RPSPT_FLOAT1) { return RPR_PARAMETER_TYPE_FLOAT; } - else if (in == RPSPT_FLOAT2) { return RPR_PARAMETER_TYPE_FLOAT2; } - else if (in == RPSPT_FLOAT3) { return RPR_PARAMETER_TYPE_FLOAT3; } - else if (in == RPSPT_FLOAT4) { return RPR_PARAMETER_TYPE_FLOAT4; } - else if (in == RPSPT_UINT32_1) { return RPR_PARAMETER_TYPE_UINT; } - RPS_MACRO_ERROR(); - return 0; -} - -RPS8::RPS_PARAMETER_TYPE RPS8::RPRPARAMETERTYPE_to_RPSPT(rpr_parameter_type in) -{ - if (in == RPR_PARAMETER_TYPE_FLOAT) { return RPSPT_FLOAT1; } - else if (in == RPR_PARAMETER_TYPE_FLOAT2) { return RPSPT_FLOAT2; } - else if (in == RPR_PARAMETER_TYPE_FLOAT3) { return RPSPT_FLOAT3; } - else if (in == RPR_PARAMETER_TYPE_FLOAT4) { return RPSPT_FLOAT4; } - else if (in == RPR_PARAMETER_TYPE_IMAGE) { return RPSPT_UNDEF; } - else if (in == RPR_PARAMETER_TYPE_STRING) { return RPSPT_UNDEF; } - else if (in == RPR_PARAMETER_TYPE_SHADER) { return RPSPT_UNDEF; } - else if (in == RPR_PARAMETER_TYPE_UINT) { return RPSPT_UINT32_1; } - return RPSPT_UNDEF; -} - - - -rpr_int RPS8::LoadCustomList( - rpr_context context, - rpr_material_system materialSystem, - std::vector& imageList, - std::vector& shapeList, - std::vector& lightList, - std::vector& cameraList, - std::vector& materialNodeList -) -{ - char headCheckCode[4] = { 0,0,0,0 }; - m_rpsFile->read(headCheckCode, sizeof(headCheckCode)); - if (headCheckCode[0] != m_HEADER_CHECKCODE[0] || - headCheckCode[1] != m_HEADER_CHECKCODE[1] || - headCheckCode[2] != m_HEADER_CHECKCODE[2] || - headCheckCode[3] != m_HEADER_CHECKCODE[3]) - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - m_rpsFile->read((char*)&m_fileVersionOfLoadFile, sizeof(m_fileVersionOfLoadFile)); - if (m_fileVersionOfLoadFile != m_FILE_VERSION) - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - - while (true) - { - std::string elementName; - std::string objBegType; - RPS_ELEMENTS_TYPE nextElem = Read_whatsNext(elementName, objBegType); - if (nextElem == RPSRT_OBJECT_BEG && objBegType == "rpr_image") - { - rpr_image obj = Read_Image(context); - imageList.push_back(obj); - } - else if (nextElem == RPSRT_OBJECT_BEG && objBegType == "rpr_shape") - { - rpr_shape obj = Read_Shape(context, materialSystem); - shapeList.push_back(obj); - - } - else if (nextElem == RPSRT_OBJECT_BEG && objBegType == "rpr_light") - { - // TODO ! - //rpr_light obj = Read_Light(context ); - //shapeList.push_back(obj); - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - - } - else if (nextElem == RPSRT_OBJECT_BEG) - { - int32_t objID = 0; - std::string objType; - if (Read_Element_StartObject(elementName, objType, objID) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - if (Read_Element_EndObject("", 0, 0) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - } - else if (nextElem == RPSRT_PARAMETER) - { - std::string paramName; - RPS_PARAMETER_TYPE paramType = RPSPT_UNDEF; - uint64_t paramDataSize = 0; - if (Read_Element_Parameter(paramName, paramType, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - } - else if (nextElem == RPSRT_REFERENCE) - { - std::string refName; - std::string refType; - RPS_OBJECT_DECLARED objReferenced; - if (Read_Element_Reference(refName, refType, objReferenced) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - } - else if (nextElem == RPSRT_UNDEF) // if reached end of file - { - break; - } - else - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - - } - - - if (m_level != 0) - { - //if level is not 0, this means we have not closed all object delaration - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - - return RPR_SUCCESS; - -} - - - -rpr_int RPS8::StoreCustomList( - const std::vector& materialNodeList, - const std::vector& cameraList, - const std::vector& lightList, - const std::vector& shapeList, - const std::vector& imageList -) -{ - rpr_int status = RPR_SUCCESS; - - // write a wrong check code: the good check code will be written at the end, when we are sure that the generation didn't fail. - // so if we have a crash or anything bad during StoreEverything, the RPS will be nicely unvalid. - m_rpsFile->write((const char*)&m_HEADER_BADCHECKCODE, sizeof(m_HEADER_BADCHECKCODE)); - m_rpsFile->write((const char*)&m_FILE_VERSION, sizeof(m_FILE_VERSION)); - - - for (int iobj = 0; iobjseekp(0); - m_rpsFile->write((const char*)&m_HEADER_CHECKCODE, sizeof(m_HEADER_CHECKCODE)); - - return status; -} - - - -rpr_int RPS8::LoadEverything( - rpr_context context, - rpr_material_system materialSystem, - rpr_scene& scene, - bool useAlreadyExistingScene -) -{ - - rpr_int status = RPR_SUCCESS; - - //check arguments: - if (context == NULL) { RPS_MACRO_ERROR(); return RPR_ERROR_INVALID_PARAMETER; } - if (scene != NULL && !useAlreadyExistingScene) { RPS_MACRO_ERROR(); return RPR_ERROR_INVALID_PARAMETER; } - if (scene == NULL && useAlreadyExistingScene) { RPS_MACRO_ERROR(); return RPR_ERROR_INVALID_PARAMETER; } - - char headCheckCode[4] = { 0,0,0,0 }; - m_rpsFile->read(headCheckCode, sizeof(headCheckCode)); - if (headCheckCode[0] != m_HEADER_CHECKCODE[0] || - headCheckCode[1] != m_HEADER_CHECKCODE[1] || - headCheckCode[2] != m_HEADER_CHECKCODE[2] || - headCheckCode[3] != m_HEADER_CHECKCODE[3]) - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - m_rpsFile->read((char*)&m_fileVersionOfLoadFile, sizeof(m_fileVersionOfLoadFile)); - if (m_fileVersionOfLoadFile != m_FILE_VERSION) - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - rpr_int succes = Read_Context(context); - if (succes != RPR_SUCCESS) - { - RPS_MACRO_ERROR(); - return succes; - } - - - rpr_scene newScene = Read_Scene(context, materialSystem, useAlreadyExistingScene ? scene : NULL); - if (newScene == 0) - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - - - //load extra custom param - while (true) - { - std::string elementName; - std::string objBegType; - RPS_ELEMENTS_TYPE nextElem = Read_whatsNext(elementName, objBegType); - if (nextElem == RPSRT_PARAMETER) - { - std::string paramName; - RPS_PARAMETER_TYPE paramType = RPSPT_UNDEF; - uint64_t paramDataSize = 0; - if (Read_Element_Parameter(paramName, paramType, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - if (paramDataSize > 0) - { - //char* data_data = new char[paramDataSize]; - - - if (paramType == RPSPT_INT32_1) - { - rpr_int data_int; - if (Read_Element_ParameterData(&data_int, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - if (paramDataSize == sizeof(rpr_int)) - { - m_extraCustomParam_int[paramName] = data_int; - } - else - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - } - else if (paramType == RPSPT_FLOAT1) - { - rpr_float data_float; - if (Read_Element_ParameterData(&data_float, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - if (paramDataSize == sizeof(rpr_float)) - { - m_extraCustomParam_float[paramName] = data_float; - } - else - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - } - else - { - char* data_data = new char[paramDataSize]; - if (Read_Element_ParameterData(data_data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - WarningDetected(); - - delete[] data_data; data_data = NULL; - } - - //delete[] data_data; data_data = NULL; - } - - } - else if (nextElem == RPSRT_UNDEF) // if reached end of file - { - break; - } - else - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - - } - - - - - if (!useAlreadyExistingScene) - { - scene = newScene; - } - - //overwrite the gamma with the 3dsmax gamma - auto dsmax_gammaenabled_found = m_extraCustomParam_int.find("3dsmax.gammaenabled"); - auto dsmax_displaygamma_found = m_extraCustomParam_float.find("3dsmax.displaygamma"); - if (dsmax_gammaenabled_found != m_extraCustomParam_int.end() && dsmax_displaygamma_found != m_extraCustomParam_float.end()) - { - if (m_extraCustomParam_int["3dsmax.gammaenabled"] != 0) - { - status = rprContextSetParameter1f(context, "displaygamma", m_extraCustomParam_float["3dsmax.displaygamma"]); - if (status != RPR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - } - - if (m_level != 0) - { - //if level is not 0, this means we have not closed all object delaration - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - - return RPR_SUCCESS; -} - - -rpr_int RPS8::Read_Context(rpr_context context) -{ - rpr_int status = RPR_SUCCESS; - - - std::string objName; - std::string objType; - int32_t objID = 0; - if (Read_Element_StartObject(objName, objType, objID) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - if (objType != "rpr_context") - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - - while (true) - { - std::string elementName; - std::string objBegType; - RPS_ELEMENTS_TYPE nextElem = Read_whatsNext(elementName, objBegType); - if (nextElem == RPSRT_PARAMETER) - { - std::string paramName; - RPS_PARAMETER_TYPE paramType = RPSPT_UNDEF; - uint64_t paramDataSize = 0; - if (Read_Element_Parameter(paramName, paramType, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - if (paramDataSize > 0) - { - - - if (paramType == RPSPT_UINT32_1) - { - rpr_uint data_uint; - if (Read_Element_ParameterData(&data_uint, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - if (paramDataSize == sizeof(rpr_uint)) - { - status = rprContextSetParameter1u(context, paramName.c_str(), (rpr_uint)data_uint); - if (status != RPR_SUCCESS) - { - if (paramName != "stacksize") // "stacksize" is read only. so it's expected to have an error - { - WarningDetected(); // this is minor error, we wont exit loader for that - } - } - } - else - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - } - else if (paramType == RPSPT_FLOAT1) - { - rpr_float data_float; - if (Read_Element_ParameterData(&data_float, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - if (paramDataSize == sizeof(rpr_float)) - { - - status = rprContextSetParameter1f(context, paramName.c_str(), data_float); - if (status != RPR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - - } - else - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - } - else if (paramType == RPSPT_FLOAT2) - { - rpr_float data_float[2]; - if (Read_Element_ParameterData(data_float, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - if (paramDataSize == 2 * sizeof(rpr_float)) - { - status = rprContextSetParameter3f(context, paramName.c_str(), data_float[0], data_float[1], 0.0); - if (status != RPR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - else - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - } - else if (paramType == RPSPT_FLOAT3) - { - rpr_float data_float[3]; - if (Read_Element_ParameterData(data_float, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - if (paramDataSize == 3 * sizeof(rpr_float)) - { - status = rprContextSetParameter3f(context, paramName.c_str(), data_float[0], data_float[1], data_float[2]); - if (status != RPR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - else - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - } - else if (paramType == RPSPT_FLOAT4) - { - rpr_float data_float[4]; - if (Read_Element_ParameterData(data_float, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - if (paramDataSize == 4 * sizeof(rpr_float)) - { - status = rprContextSetParameter4f(context, paramName.c_str(), data_float[0], data_float[1], data_float[2], data_float[3]); - if (status != RPR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - else - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - } - else if (paramType == RPSPT_UNDEF && paramName == "RPR_OBJECT_NAME") - { - char* data_data = new char[paramDataSize]; - if (Read_Element_ParameterData(data_data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - status = rprObjectSetName(context, data_data); - CHECK_STATUS_RETURNERROR; - delete[] data_data; data_data = NULL; - } - - - // read only parameter. don't set it. - else if ((paramType == RPSPT_UNDEF && paramName == "gpu0name") - || (paramType == RPSPT_UNDEF && paramName == "gpu1name") - || (paramType == RPSPT_UNDEF && paramName == "gpu2name") - || (paramType == RPSPT_UNDEF && paramName == "gpu3name") - || (paramType == RPSPT_UNDEF && paramName == "gpu4name") - || (paramType == RPSPT_UNDEF && paramName == "gpu5name") - || (paramType == RPSPT_UNDEF && paramName == "gpu6name") - || (paramType == RPSPT_UNDEF && paramName == "gpu7name") - || (paramType == RPSPT_UNDEF && paramName == "cpuname") - ) - { - char* data_data = new char[paramDataSize]; - if (Read_Element_ParameterData(data_data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - delete[] data_data; data_data = NULL; - } - - - else - { - char* data_data = new char[paramDataSize]; - if (Read_Element_ParameterData(data_data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - WarningDetected(); - - delete[] data_data; data_data = NULL; - } - - - } - else - { - WarningDetected(); - } - - } - else if (nextElem == RPSRT_OBJECT_END) - { - break; - } - else - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - - } - - - if (Read_Element_EndObject("rpr_context", context, objID) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - - return RPR_SUCCESS; -} - -rpr_camera RPS8::Read_Camera(rpr_context context) -{ - rpr_int status = RPR_SUCCESS; - - std::string objName; - std::string objType; - int32_t objID = 0; - if (Read_Element_StartObject(objName, objType, objID) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - if (objType != "rpr_camera") - { - RPS_MACRO_ERROR(); - return NULL; - } - - rpr_camera camera = NULL; - status = rprContextCreateCamera(context, &camera); - CHECK_STATUS_RETURNNULL; - - bool param_pos_declared = false; - rpr_float param_pos[3]; - bool param_at_declared = false; - rpr_float param_at[3]; - bool param_up_declared = false; - rpr_float param_up[3]; - - while (true) - { - - std::string elementName; - std::string objBegType; - RPS_ELEMENTS_TYPE nextElem = Read_whatsNext(elementName, objBegType); - if (nextElem == RPSRT_PARAMETER) - { - std::string paramName; - RPS_PARAMETER_TYPE paramType = RPSPT_UNDEF; - uint64_t paramDataSize = 0; - if (Read_Element_Parameter(paramName, paramType, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - - if (paramDataSize > 0) - { - - if (paramName == "RPR_CAMERA_FSTOP" && paramType == RPSPT_FLOAT1) - { - float param_fstop; - if (Read_Element_ParameterData(¶m_fstop, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprCameraSetFStop(camera, param_fstop); - CHECK_STATUS_RETURNNULL; - } - - else if (paramName == "RPR_CAMERA_APERTURE_BLADES" && paramType == RPSPT_UINT32_1) - { - unsigned int param_apblade; - if (Read_Element_ParameterData(¶m_apblade, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprCameraSetApertureBlades(camera, param_apblade); - CHECK_STATUS_RETURNNULL; - } - else if (paramName == "RPR_CAMERA_EXPOSURE" && paramType == RPSPT_FLOAT1) - { - float param_camexpo; - if (Read_Element_ParameterData(¶m_camexpo, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprCameraSetExposure(camera, param_camexpo); - CHECK_STATUS_RETURNNULL; - } - else if (paramName == "RPR_CAMERA_FOCAL_LENGTH" && paramType == RPSPT_FLOAT1) - { - float param_focalLen; - if (Read_Element_ParameterData(¶m_focalLen, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprCameraSetFocalLength(camera, param_focalLen); - CHECK_STATUS_RETURNNULL; - } - else if (paramName == "RPR_CAMERA_SENSOR_SIZE" && paramType == RPSPT_FLOAT2) - { - float param_sensorsize[2]; - if (Read_Element_ParameterData(param_sensorsize, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprCameraSetSensorSize(camera, param_sensorsize[0], param_sensorsize[1]); - CHECK_STATUS_RETURNNULL; - } - else if (paramName == "RPR_CAMERA_MODE" && paramType == RPSPT_UINT32_1) - { - rpr_camera_mode param_mode; - if (Read_Element_ParameterData(¶m_mode, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprCameraSetMode(camera, param_mode); - CHECK_STATUS_RETURNNULL; - } - else if (paramName == "RPR_CAMERA_ORTHO_WIDTH" && paramType == RPSPT_FLOAT1) - { - float param_orthowidth; - if (Read_Element_ParameterData(¶m_orthowidth, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprCameraSetOrthoWidth(camera, param_orthowidth); - CHECK_STATUS_RETURNNULL; - } - else if (paramName == "RPR_CAMERA_FOCAL_TILT" && paramType == RPSPT_FLOAT1) - { - float param_tilt; - if (Read_Element_ParameterData(¶m_tilt, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprCameraSetFocalTilt(camera, param_tilt); - CHECK_STATUS_RETURNNULL; - } - else if (paramName == "RPR_CAMERA_IPD" && paramType == RPSPT_FLOAT1) - { - float param_ipd; - if (Read_Element_ParameterData(¶m_ipd, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprCameraSetIPD(camera, param_ipd); - CHECK_STATUS_RETURNNULL; - } - else if (paramName == "RPR_CAMERA_LENS_SHIFT" && paramType == RPSPT_FLOAT2) - { - fr_float param_shift[2]; - if (Read_Element_ParameterData(param_shift, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprCameraSetLensShift(camera, param_shift[0], param_shift[1]); - CHECK_STATUS_RETURNNULL; - } - else if (paramName == "RPR_CAMERA_ORTHO_HEIGHT" && paramType == RPSPT_FLOAT1) - { - float param_orthoheight; - if (Read_Element_ParameterData(¶m_orthoheight, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprCameraSetOrthoHeight(camera, param_orthoheight); - CHECK_STATUS_RETURNNULL; - } - else if (paramName == "RPR_CAMERA_FOCUS_DISTANCE" && paramType == RPSPT_FLOAT1) - { - float param_focusdist; - if (Read_Element_ParameterData(¶m_focusdist, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprCameraSetFocusDistance(camera, param_focusdist); - CHECK_STATUS_RETURNNULL; - } - else if (paramName == "RPR_CAMERA_POSITION" && paramType == RPSPT_FLOAT3) - { - param_pos_declared = true; - if (Read_Element_ParameterData(param_pos, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_CAMERA_LOOKAT" && paramType == RPSPT_FLOAT3) - { - param_at_declared = true; - if (Read_Element_ParameterData(param_at, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_CAMERA_UP" && paramType == RPSPT_FLOAT3) - { - param_up_declared = true; - if (Read_Element_ParameterData(param_up, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_OBJECT_NAME" && paramType == RPSPT_UNDEF) - { - char* data_data = new char[paramDataSize]; - if (Read_Element_ParameterData(data_data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprObjectSetName(camera, data_data); - CHECK_STATUS_RETURNNULL; - delete[] data_data; data_data = NULL; - } - else - { - char* data_data = new char[paramDataSize]; - if (Read_Element_ParameterData(data_data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - WarningDetected(); - delete[] data_data; data_data = NULL; - } - - } - else - { - WarningDetected(); - } - - } - else if (nextElem == RPSRT_OBJECT_END) - { - break; - } - else - { - RPS_MACRO_ERROR(); - return NULL; - } - - } - - if (param_pos_declared && param_at_declared && param_up_declared) - { - status = rprCameraLookAt(camera, - param_pos[0], param_pos[1], param_pos[2], - param_at[0], param_at[1], param_at[2], - param_up[0], param_up[1], param_up[2] - ); - CHECK_STATUS_RETURNNULL; - } - else - { - WarningDetected(); - } - - if (Read_Element_EndObject("rpr_camera", camera, objID) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - - return camera; -} - -rpr_light RPS8::Read_Light(rpr_context context, rpr_scene scene, rpr_material_system materialSystem) -{ - rpr_int status = RPR_SUCCESS; - - rpr_light light = NULL; - - std::string elementName; - std::string objBegType; - RPS_ELEMENTS_TYPE elementType = Read_whatsNext(elementName, objBegType); - if (objBegType != "rpr_light") - { - RPS_MACRO_ERROR(); - return NULL; - } - - if (elementType == RPSRT_REFERENCE) - { - RPS_OBJECT_DECLARED objReferenced; - if (Read_Element_Reference(elementName, objBegType, objReferenced) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - light = objReferenced.obj; - } - else if (elementType == RPSRT_OBJECT_BEG) - { - - std::string objName; - std::string objType; - int32_t objID = 0; - if (Read_Element_StartObject(objName, objType, objID) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - if (objType != "rpr_light") - { - RPS_MACRO_ERROR(); - return NULL; - } - - rpr_light_type lightType = 0; - bool param__RPR_IES_LIGHT_IMAGE_DESC_W__defined = false; - int32_t param__RPR_IES_LIGHT_IMAGE_DESC_W__data = 0; - bool param__RPR_IES_LIGHT_IMAGE_DESC_H__defined = false; - int32_t param__RPR_IES_LIGHT_IMAGE_DESC_H__data = 0; - bool param__RPR_IES_LIGHT_IMAGE_DESC_DATA__defined = false; - char* param__RPR_IES_LIGHT_IMAGE_DESC_DATA__data = NULL; - bool param__RPR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__defined = false; - uint64_t param__RPR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__data = 0; - int64_t param__EnvlightPortalCount = 0; - int64_t param__SkylightPortalCount = 0; - - while (true) - { - - std::string elementName; - std::string objBegType; - RPS_ELEMENTS_TYPE nextElem = Read_whatsNext(elementName, objBegType); - if (nextElem == RPSRT_PARAMETER) - { - std::string paramName; - RPS_PARAMETER_TYPE paramType = RPSPT_UNDEF; - uint64_t paramDataSize = 0; - if (Read_Element_Parameter(paramName, paramType, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - - if (paramDataSize > 0) - { - - - if (light == NULL && paramType == RPSPT_UNDEF && paramDataSize == sizeof(rpr_light_type) && paramName == "RPR_LIGHT_TYPE") - { - if (Read_Element_ParameterData(&lightType, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - - if (lightType == RPR_LIGHT_TYPE_POINT) - { - status = rprContextCreatePointLight(context, &light); - CHECK_STATUS_RETURNNULL; - } - else if (lightType == RPR_LIGHT_TYPE_DIRECTIONAL) - { - status = rprContextCreateDirectionalLight(context, &light); - CHECK_STATUS_RETURNNULL; - } - else if (lightType == RPR_LIGHT_TYPE_SPOT) - { - status = rprContextCreateSpotLight(context, &light); - CHECK_STATUS_RETURNNULL; - } - else if (lightType == RPR_LIGHT_TYPE_ENVIRONMENT) - { - status = rprContextCreateEnvironmentLight(context, &light); - CHECK_STATUS_RETURNNULL; - } - else if (lightType == RPR_LIGHT_TYPE_SKY) - { - status = rprContextCreateSkyLight(context, &light); - CHECK_STATUS_RETURNNULL; - } - else if (lightType == RPR_LIGHT_TYPE_IES) - { - status = rprContextCreateIESLight(context, &light); - CHECK_STATUS_RETURNNULL; - } - else - { - RPS_MACRO_ERROR(); - return NULL; - } - } - else if (light != NULL && paramName == "RPR_POINT_LIGHT_RADIANT_POWER" && paramType == RPSPT_FLOAT3 && paramDataSize == sizeof(float) * 3) - { - float radian3f[3]; - if (Read_Element_ParameterData(radian3f, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprPointLightSetRadiantPower3f(light, radian3f[0], radian3f[1], radian3f[2]); - CHECK_STATUS_RETURNNULL; - } - else if (light != NULL && paramName == "RPR_DIRECTIONAL_LIGHT_RADIANT_POWER" && paramType == RPSPT_FLOAT3 && paramDataSize == sizeof(float) * 3) - { - float radian3f[3]; - if (Read_Element_ParameterData(radian3f, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprDirectionalLightSetRadiantPower3f(light, radian3f[0], radian3f[1], radian3f[2]); - CHECK_STATUS_RETURNNULL; - } - else if (light != NULL && paramName == "RPR_DIRECTIONAL_LIGHT_SHADOW_SOFTNESS" && paramType == RPSPT_FLOAT1 && paramDataSize == sizeof(float) * 1) - { - float shadowsoftness; - if (Read_Element_ParameterData(&shadowsoftness, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprDirectionalLightSetShadowSoftness(light, shadowsoftness); - CHECK_STATUS_RETURNNULL; - } - else if (light != NULL && paramName == "RPR_SPOT_LIGHT_RADIANT_POWER" && paramType == RPSPT_FLOAT3 && paramDataSize == sizeof(float) * 3) - { - float radian3f[3]; - if (Read_Element_ParameterData(radian3f, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprSpotLightSetRadiantPower3f(light, radian3f[0], radian3f[1], radian3f[2]); - CHECK_STATUS_RETURNNULL; - } - else if (light != NULL && paramName == "RPR_IES_LIGHT_RADIANT_POWER" && paramType == RPSPT_FLOAT3 && paramDataSize == sizeof(float) * 3) - { - float radian3f[3]; - if (Read_Element_ParameterData(radian3f, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprIESLightSetRadiantPower3f(light, radian3f[0], radian3f[1], radian3f[2]); - CHECK_STATUS_RETURNNULL; - } - else if (light != NULL && paramName == "RPR_SPOT_LIGHT_CONE_SHAPE" && paramType == RPSPT_FLOAT2 && paramDataSize == sizeof(float) * 2) - { - float coneShape2f[2]; - if (Read_Element_ParameterData(coneShape2f, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprSpotLightSetConeShape(light, coneShape2f[0], coneShape2f[1]); - CHECK_STATUS_RETURNNULL; - } - else if (light != NULL && paramName == "RPR_ENVIRONMENT_LIGHT_INTENSITY_SCALE" && paramType == RPSPT_FLOAT1 && paramDataSize == sizeof(float) * 1) - { - float intensityScale; - if (Read_Element_ParameterData(&intensityScale, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprEnvironmentLightSetIntensityScale(light, intensityScale); - CHECK_STATUS_RETURNNULL; - } - else if (light != NULL && paramName == "lightIsTheEnvironmentLight" && paramType == RPSPT_INT32_1 && paramDataSize == sizeof(int32_t)) - { - //parameter not used anymore because rprSceneSetEnvironmentLight replaced by rprSceneAttachLight - - int32_t isEnvLight; - if (Read_Element_ParameterData(&isEnvLight, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - if (isEnvLight == 1) - { - //status = rprSceneSetEnvironmentLight(scene, light); - CHECK_STATUS_RETURNNULL; - } - } - else if (light != NULL && paramName == "RPR_LIGHT_TRANSFORM" && paramType == RPSPT_FLOAT16 && paramDataSize == sizeof(float) * 16) - { - float lightTransform[16]; - if (Read_Element_ParameterData(lightTransform, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprLightSetTransform(light, 0, (float*)lightTransform); - CHECK_STATUS_RETURNNULL; - } - - else if (light != NULL && paramName == "RPR_SKY_LIGHT_SCALE" && paramType == RPSPT_FLOAT1 && paramDataSize == sizeof(float) * 1) - { - float scale; - if (Read_Element_ParameterData(&scale, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprSkyLightSetScale(light, scale); - CHECK_STATUS_RETURNNULL; - } - else if (light != NULL && paramName == "RPR_SKY_LIGHT_ALBEDO" && paramType == RPSPT_FLOAT1 && paramDataSize == sizeof(float) * 1) - { - float albedo; - if (Read_Element_ParameterData(&albedo, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprSkyLightSetAlbedo(light, albedo); - CHECK_STATUS_RETURNNULL; - } - else if (light != NULL && paramName == "RPR_SKY_LIGHT_TURBIDITY" && paramType == RPSPT_FLOAT1 && paramDataSize == sizeof(float) * 1) - { - float turbidity; - if (Read_Element_ParameterData(&turbidity, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprSkyLightSetTurbidity(light, turbidity); - CHECK_STATUS_RETURNNULL; - } - - else if (light != NULL && paramName == "RPR_IES_LIGHT_IMAGE_DESC_W" && paramType == RPSPT_INT32_1 && paramDataSize == sizeof(int32_t)) - { - param__RPR_IES_LIGHT_IMAGE_DESC_W__defined = true; - if (Read_Element_ParameterData(¶m__RPR_IES_LIGHT_IMAGE_DESC_W__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (light != NULL && paramName == "RPR_IES_LIGHT_IMAGE_DESC_H" && paramType == RPSPT_INT32_1 && paramDataSize == sizeof(int32_t)) - { - param__RPR_IES_LIGHT_IMAGE_DESC_H__defined = true; - if (Read_Element_ParameterData(¶m__RPR_IES_LIGHT_IMAGE_DESC_H__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (light != NULL && paramName == "RPR_IES_LIGHT_IMAGE_DESC_DATA_SIZE" && paramType == RPSPT_UINT64_1 && paramDataSize == sizeof(uint64_t)) - { - param__RPR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__defined = true; - if (Read_Element_ParameterData(¶m__RPR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (light != NULL && paramName == "RPR_IES_LIGHT_IMAGE_DESC_DATA" && paramType == RPSPT_UNDEF && paramDataSize == param__RPR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__data && param__RPR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__defined) - { - param__RPR_IES_LIGHT_IMAGE_DESC_DATA__defined = true; - param__RPR_IES_LIGHT_IMAGE_DESC_DATA__data = new char[param__RPR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__data]; - if (Read_Element_ParameterData(param__RPR_IES_LIGHT_IMAGE_DESC_DATA__data, param__RPR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__data) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - - else if (light != NULL && paramName == "RPR_OBJECT_NAME" && paramType == RPSPT_UNDEF) - { - char* data_data = new char[paramDataSize]; - if (Read_Element_ParameterData(data_data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprObjectSetName(light, data_data); - CHECK_STATUS_RETURNNULL; - delete[] data_data; data_data = NULL; - } - - else if (light != NULL && paramName == "RPR_ENVIRONMENT_LIGHT_PORTAL_COUNT" && paramType == RPSPT_INT64_1 && paramDataSize == sizeof(int64_t)) - { - if (Read_Element_ParameterData(¶m__EnvlightPortalCount, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - - else if (light != NULL && paramName == "RPR_SKY_LIGHT_PORTAL_COUNT" && paramType == RPSPT_INT64_1 && paramDataSize == sizeof(int64_t)) - { - if (Read_Element_ParameterData(¶m__SkylightPortalCount, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - - else if (light == NULL) - { - // "RPR_LIGHT_TYPE" must be declared as the first parameter in the parameters list of the light - RPS_MACRO_ERROR(); - return NULL; - } - else - { - char* data_data = new char[paramDataSize]; - if (Read_Element_ParameterData(data_data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - - WarningDetected(); - - delete[] data_data; data_data = NULL; - } - - - - - } - else - { - WarningDetected(); - } - - } - else if ((nextElem == RPSRT_OBJECT_BEG && elementName == "RPR_ENVIRONMENT_LIGHT_IMAGE" && objBegType == "rpr_image") - || (nextElem == RPSRT_REFERENCE && elementName == "RPR_ENVIRONMENT_LIGHT_IMAGE") - ) - { - rpr_image img = Read_Image(context); - status = rprEnvironmentLightSetImage(light, img); - CHECK_STATUS_RETURNNULL; - } - else if ((nextElem == RPSRT_OBJECT_BEG && elementName == STR__SHAPE_FOR_SKY_LIGHT_PORTAL_ID && objBegType == "rpr_shape") - || (nextElem == RPSRT_REFERENCE && elementName == STR__SHAPE_FOR_SKY_LIGHT_PORTAL_ID) - ) - { - rpr_shape shape = Read_Shape(context, materialSystem); - if (shape == NULL) { RPS_MACRO_ERROR(); return NULL; } - status = rprSkyLightAttachPortal(light, shape); - CHECK_STATUS_RETURNNULL; - } - else if ((nextElem == RPSRT_OBJECT_BEG && elementName == STR__SHAPE_FOR_ENVIRONMENT_LIGHT_PORTAL_ID && objBegType == "rpr_shape") - || (nextElem == RPSRT_REFERENCE && elementName == STR__SHAPE_FOR_ENVIRONMENT_LIGHT_PORTAL_ID) - ) - { - rpr_shape shape = Read_Shape(context, materialSystem); - if (shape == NULL) { RPS_MACRO_ERROR(); return NULL; } - status = rprEnvironmentLightAttachPortal(light, shape); - CHECK_STATUS_RETURNNULL; - } - else if (nextElem == RPSRT_OBJECT_END) - { - break; - } - else - { - RPS_MACRO_ERROR(); - return NULL; - } - - } - - if (Read_Element_EndObject("rpr_light", light, objID) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - - - //set parameters for IES - if (lightType == RPR_LIGHT_TYPE_IES - && param__RPR_IES_LIGHT_IMAGE_DESC_W__defined - && param__RPR_IES_LIGHT_IMAGE_DESC_H__defined - && param__RPR_IES_LIGHT_IMAGE_DESC_DATA__defined - && param__RPR_IES_LIGHT_IMAGE_DESC_DATA_SIZE__defined) - { - status = rprIESLightSetImageFromIESdata(light, param__RPR_IES_LIGHT_IMAGE_DESC_DATA__data, param__RPR_IES_LIGHT_IMAGE_DESC_W__data, param__RPR_IES_LIGHT_IMAGE_DESC_H__data); - if (status != RPR_SUCCESS) { WarningDetected(); } - } - - - - - } - else - { - RPS_MACRO_ERROR(); - return NULL; - } - - return light; -} - - - -rpr_image RPS8::Read_Image(rpr_context context) -{ - rpr_image image = NULL; - rpr_int status = RPR_SUCCESS; - - std::string elementName; - std::string objBegType; - RPS_ELEMENTS_TYPE elementType = Read_whatsNext(elementName, objBegType); - if (objBegType != "rpr_image") - { - RPS_MACRO_ERROR(); - return NULL; - } - - if (elementType == RPSRT_REFERENCE) - { - RPS_OBJECT_DECLARED objReferenced; - if (Read_Element_Reference(elementName, objBegType, objReferenced) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - image = objReferenced.obj; - } - else if (elementType == RPSRT_OBJECT_BEG) - { - int32_t objID = 0; - std::string objType; - Read_Element_StartObject(elementName, objType, objID); - - rpr_image_format imgFormat; - memset(&imgFormat, 0, sizeof(imgFormat)); - rpr_image_desc imgDesc; - memset(&imgDesc, 0, sizeof(imgDesc)); - void* imgData = NULL; - char* objectName = NULL; - - bool param__RPR_IMAGE_WRAP__defined = false; - rpr_uint param__RPR_IMAGE_WRAP__data = 0; - - while (true) - { - std::string elementName; - std::string objBegType; - RPS_ELEMENTS_TYPE nextElem = Read_whatsNext(elementName, objBegType); - if (nextElem == RPSRT_PARAMETER) - { - std::string paramName; - RPS_PARAMETER_TYPE paramType = RPSPT_UNDEF; - uint64_t paramDataSize = 0; - if (Read_Element_Parameter(paramName, paramType, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - - if (paramDataSize > 0) - { - //char* data_data = new char[paramDataSize]; - - if (paramName == "RPR_IMAGE_FORMAT" && paramType == RPSPT_UNDEF && paramDataSize == sizeof(rpr_image_format)) - { - //imgFormat = ((rpr_image_format*)data_data)[0]; - if (Read_Element_ParameterData(&imgFormat, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_IMAGE_DESC" && paramType == RPSPT_UNDEF && paramDataSize == sizeof(rpr_image_desc)) - { - //imgDesc = ((rpr_image_desc*)data_data)[0]; - if (Read_Element_ParameterData(&imgDesc, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_IMAGE_DATA" && paramType == RPSPT_UNDEF) - { - imgData = new char[paramDataSize]; - if (Read_Element_ParameterData(imgData, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_OBJECT_NAME" && paramType == RPSPT_UNDEF) - { - objectName = new char[paramDataSize]; - if (Read_Element_ParameterData(objectName, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_IMAGE_WRAP" && paramType == RPSPT_UINT32_1) - { - param__RPR_IMAGE_WRAP__defined = true; - if (Read_Element_ParameterData(¶m__RPR_IMAGE_WRAP__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else - { - RPS_MACRO_ERROR(); return NULL; - } - - //delete[] data_data; data_data = NULL; - } - - } - else if (nextElem == RPSRT_OBJECT_END) // if reached end of file - { - break; - } - else - { - RPS_MACRO_ERROR(); - return NULL; - } - } - - if (imgData == NULL) - { - RPS_MACRO_ERROR(); - return NULL; - } - status = rprContextCreateImage(context, imgFormat, &imgDesc, imgData, &image); - if (imgData) { delete[] static_cast(imgData); imgData = NULL; } - CHECK_STATUS_RETURNNULL; - - if (objectName) - { - status = rprObjectSetName(image, objectName); - CHECK_STATUS_RETURNNULL; - delete[] objectName; objectName = NULL; - } - - if (param__RPR_IMAGE_WRAP__defined) - { - status = rprImageSetWrap(image, param__RPR_IMAGE_WRAP__data); - CHECK_STATUS_RETURNNULL; - } - - Read_Element_EndObject("rpr_image", image, objID); - } - else - { - RPS_MACRO_ERROR(); - return NULL; - } - - return image; -} - - -rpr_material_node RPS8::Read_MaterialNode(rpr_material_system materialSystem, rpr_context context) -{ - rpr_material_node material = NULL; - rpr_int status = RPR_SUCCESS; - - std::string elementName; - - std::string objBegType; - RPS_ELEMENTS_TYPE elementType = Read_whatsNext(elementName, objBegType); - if (objBegType != "rpr_material_node") - { - RPS_MACRO_ERROR(); - return NULL; - } - - if (elementType == RPSRT_REFERENCE) - { - RPS_OBJECT_DECLARED objReferenced; - if (Read_Element_Reference(elementName, objBegType, objReferenced) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - material = objReferenced.obj; - } - else if (elementType == RPSRT_OBJECT_BEG) - { - - - std::string objType; - int32_t materialID = 0; - if (Read_Element_StartObject(elementName, objType, materialID) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - if (objType != "rpr_material_node") - { - RPS_MACRO_ERROR(); - return NULL; - } - - - while (true) - { - - std::string elementName; - std::string objBegType; - RPS_ELEMENTS_TYPE nextElem = Read_whatsNext(elementName, objBegType); - if (nextElem == RPSRT_PARAMETER) - { - std::string paramName; - RPS_PARAMETER_TYPE paramType = RPSPT_UNDEF; - uint64_t paramDataSize = 0; - if (Read_Element_Parameter(paramName, paramType, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - - if (paramDataSize > 0) - { - - - if (paramName == "RPR_MATERIAL_NODE_TYPE" && paramType == RPSPT_UINT32_1 && paramDataSize == sizeof(rpr_material_node_type)) - { - rpr_material_node_type type = 0; - if (Read_Element_ParameterData(&type, sizeof(rpr_material_node_type)) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprMaterialSystemCreateNode(materialSystem, type, &material); - CHECK_STATUS_RETURNNULL; - } - else if (paramName == "RPR_MATERIAL_NODE_INPUT_COUNT" && paramType == RPSPT_UINT64_1 && paramDataSize == sizeof(uint64_t)) - { - uint64_t nbInput = 0; - if (Read_Element_ParameterData(&nbInput, sizeof(nbInput)) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else - { - if (paramType == RPSPT_FLOAT4) - { - float paramValue[4]; - if (Read_Element_ParameterData(paramValue, sizeof(paramValue)) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprMaterialNodeSetInputF(material, paramName.c_str(), paramValue[0], paramValue[1], paramValue[2], paramValue[3]); - if (status != RPR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - else if (paramType == RPSPT_UINT32_1) - { - uint32_t paramValue; - if (Read_Element_ParameterData(¶mValue, sizeof(paramValue)) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprMaterialNodeSetInputU(material, paramName.c_str(), paramValue); - if (status != RPR_SUCCESS) { WarningDetected(); } // this is minor error, we wont exit loader for that - } - else if (paramType == RPSPT_UNDEF && paramName == "RPR_OBJECT_NAME") - { - char* data_data = new char[paramDataSize]; - if (Read_Element_ParameterData(data_data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - status = rprObjectSetName(material, data_data); - CHECK_STATUS_RETURNNULL; - delete[] data_data; data_data = NULL; - } - else - { - //unmanaged parameter - char* data_data = new char[paramDataSize]; - if (Read_Element_ParameterData(data_data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - - WarningDetected(); - - delete[] data_data; data_data = NULL; - } - } - - - } - - } - else if ((nextElem == RPSRT_OBJECT_BEG && objBegType == "rpr_material_node") - || (nextElem == RPSRT_REFERENCE && objBegType == "rpr_material_node") - ) - { - - rpr_material_node matNode = Read_MaterialNode(materialSystem, context); - if (matNode == NULL) - { - RPS_MACRO_ERROR(); - return NULL; - } - status = rprMaterialNodeSetInputN(material, elementName.c_str(), matNode); - CHECK_STATUS_RETURNNULL; - - } - else if ((nextElem == RPSRT_OBJECT_BEG && objBegType == "rpr_image") - || (nextElem == RPSRT_REFERENCE && objBegType == "rpr_image") - ) - { - - rpr_image image = Read_Image(context); - if (image == NULL) - { - RPS_MACRO_ERROR(); - return NULL; - } - status = rprMaterialNodeSetInputImageData(material, elementName.c_str(), image); - CHECK_STATUS_RETURNNULL; - - } - else if (nextElem == RPSRT_OBJECT_END) - { - break; - } - else - { - RPS_MACRO_ERROR(); - return NULL; - } - - } - - - - if (Read_Element_EndObject("rpr_material_node", material, materialID) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - - - - - - } - else - { - RPS_MACRO_ERROR(); - return NULL; - } - - return material; -} - -rpr_shape RPS8::Read_Shape(rpr_context context, rpr_material_system materialSystem) -{ - rpr_int status = RPR_SUCCESS; - rpr_shape shape = NULL; - - std::string elementName; - std::string objBegType; - RPS_ELEMENTS_TYPE elementType = Read_whatsNext(elementName, objBegType); - if (objBegType != "rpr_shape") - { - RPS_MACRO_ERROR(); - return NULL; - } - - if (elementType == RPSRT_REFERENCE) - { - RPS_OBJECT_DECLARED objReferenced; - if (Read_Element_Reference(elementName, objBegType, objReferenced) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - shape = objReferenced.obj; - } - else if (elementType == RPSRT_OBJECT_BEG) - { - std::string elementName; - std::string objType; - int32_t objID = 0; - Read_Element_StartObject(elementName, objType, objID); - if (objType != "rpr_shape") - { - RPS_MACRO_ERROR(); - return NULL; - } - - - bool param__RPR_SHAPE_TYPE__defined = false; - rpr_shape_type param__RPR_SHAPE_TYPE__data = NULL; - bool param__RPR_MESH_POLYGON_COUNT__defined = false; - uint64_t param__RPR_MESH_POLYGON_COUNT__data = NULL; - bool param__RPR_MESH_VERTEX_COUNT__defined = false; - uint64_t param__RPR_MESH_VERTEX_COUNT__data = NULL; - bool param__RPR_MESH_NORMAL_COUNT__defined = false; - uint64_t param__RPR_MESH_NORMAL_COUNT__data = NULL; - bool param__RPR_MESH_UV_COUNT__defined = false; - uint64_t param__RPR_MESH_UV_COUNT__data = NULL; - bool param__RPR_MESH_UV2_COUNT__defined = false; - uint64_t param__RPR_MESH_UV2_COUNT__data = NULL; - - bool param__RPR_MESH_VERTEX_ARRAY__defined = false; - float* param__RPR_MESH_VERTEX_ARRAY__data = NULL; - int32_t param__RPR_MESH_VERTEX_ARRAY__dataSize = 0; - bool param__RPR_MESH_NORMAL_ARRAY__defined = false; - float* param__RPR_MESH_NORMAL_ARRAY__data = NULL; - int32_t param__RPR_MESH_NORMAL_ARRAY__dataSize = 0; - bool param__RPR_MESH_UV_ARRAY__defined = false; - float* param__RPR_MESH_UV_ARRAY__data = NULL; - int32_t param__RPR_MESH_UV_ARRAY__dataSize = 0; - bool param__RPR_MESH_UV2_ARRAY__defined = false; - float* param__RPR_MESH_UV2_ARRAY__data = NULL; - int32_t param__RPR_MESH_UV2_ARRAY__dataSize = 0; - - bool param__RPR_MESH_VERTEX_INDEX_ARRAY__defined = false; - int32_t* param__RPR_MESH_VERTEX_INDEX_ARRAY__data = NULL; - bool param__RPR_MESH_NORMAL_INDEX_ARRAY__defined = false; - int32_t* param__RPR_MESH_NORMAL_INDEX_ARRAY__data = NULL; - bool param__RPR_MESH_UV_INDEX_ARRAY__defined = false; - int32_t* param__RPR_MESH_UV_INDEX_ARRAY__data = NULL; - bool param__RPR_MESH_UV2_INDEX_ARRAY__defined = false; - int32_t* param__RPR_MESH_UV2_INDEX_ARRAY__data = NULL; - bool param__RPR_MESH_NUM_VERTICES_ARRAY__defined = false; - int32_t* param__RPR_MESH_NUM_VERTICES_ARRAY__data = NULL; - bool param__SHAPE_INSTANCE_REFERENCE_ID__defined = false; - int32_t param__SHAPE_INSTANCE_REFERENCE_ID__data = NULL; - bool param__RPR_SHAPE_TRANSFORM__defined = false; - float param__RPR_SHAPE_TRANSFORM__data[16]; - bool param__RPR_SHAPE_LINEAR_MOTION__defined = false; - float param__RPR_SHAPE_LINEAR_MOTION__data[3]; - bool param__RPR_SHAPE_ANGULAR_MOTION__defined = false; - float param__RPR_SHAPE_ANGULAR_MOTION__data[4]; - bool param__RPR_SHAPE_VISIBILITY__defined = false; - rpr_bool param__RPR_SHAPE_VISIBILITY__data = NULL; - bool param__RPR_SHAPE_SHADOW__defined = false; - rpr_bool param__RPR_SHAPE_SHADOW__data = NULL; - bool param__RPR_SHAPE_SHADOWCATCHER__defined = false; - rpr_bool param__RPR_SHAPE_SHADOWCATCHER__data = NULL; - - bool param__RPR_SHAPE_SUBDIVISION_FACTOR__defined = false; - rpr_uint param__RPR_SHAPE_SUBDIVISION_FACTOR__data = 0; - bool param__RPR_SHAPE_SUBDIVISION_CREASEWEIGHT__defined = false; - rpr_float param__RPR_SHAPE_SUBDIVISION_CREASEWEIGHT__data = 0; - bool param__RPR_SHAPE_SUBDIVISION_BOUNDARYINTEROP__defined = false; - rpr_uint param__RPR_SHAPE_SUBDIVISION_BOUNDARYINTEROP__data = 0; - - bool param__RPR_SHAPE_DISPLACEMENT_IMAGE__defined = false; - rpr_image param__RPR_SHAPE_DISPLACEMENT_IMAGE__data = NULL; - bool param__RPR_SHAPE_DISPLACEMENT_SCALE__defined = false; - rpr_float param__RPR_SHAPE_DISPLACEMENT_SCALE__data[2] = { 0.0f,0.0f }; - bool param__RPR_SHAPE_OBJECT_GROUP_ID__defined = false; - rpr_uint param__RPR_SHAPE_OBJECT_GROUP_ID__data = 0; - - rpr_material_node shapeMaterial = NULL; - - char* objectName = NULL; - - while (true) - { - std::string elementName; - std::string objBegType; - RPS_ELEMENTS_TYPE nextElem = Read_whatsNext(elementName, objBegType); - if (nextElem == RPSRT_PARAMETER) - { - std::string paramName; - RPS_PARAMETER_TYPE paramType = RPSPT_UNDEF; - uint64_t paramDataSize = 0; - if (Read_Element_Parameter(paramName, paramType, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - - if (paramDataSize > 0) - { - - if (paramName == "RPR_SHAPE_TYPE" && paramType == RPSPT_UNDEF) - { - param__RPR_SHAPE_TYPE__defined = true; - if (Read_Element_ParameterData(¶m__RPR_SHAPE_TYPE__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_MESH_POLYGON_COUNT" && paramType == RPSPT_UINT64_1) - { - param__RPR_MESH_POLYGON_COUNT__defined = true; - if (Read_Element_ParameterData(¶m__RPR_MESH_POLYGON_COUNT__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_MESH_VERTEX_COUNT" && paramType == RPSPT_UINT64_1) - { - param__RPR_MESH_VERTEX_COUNT__defined = true; - if (Read_Element_ParameterData(¶m__RPR_MESH_VERTEX_COUNT__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_MESH_NORMAL_COUNT" && paramType == RPSPT_UINT64_1) - { - param__RPR_MESH_NORMAL_COUNT__defined = true; - if (Read_Element_ParameterData(¶m__RPR_MESH_NORMAL_COUNT__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_MESH_UV_COUNT" && paramType == RPSPT_UINT64_1) - { - param__RPR_MESH_UV_COUNT__defined = true; - if (Read_Element_ParameterData(¶m__RPR_MESH_UV_COUNT__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_MESH_UV2_COUNT" && paramType == RPSPT_UINT64_1) - { - param__RPR_MESH_UV2_COUNT__defined = true; - if (Read_Element_ParameterData(¶m__RPR_MESH_UV2_COUNT__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_MESH_VERTEX_ARRAY" && paramType == RPSPT_UINT64_1) - { - param__RPR_MESH_VERTEX_ARRAY__data = (float*)malloc(paramDataSize); - param__RPR_MESH_VERTEX_ARRAY__defined = true; - if (Read_Element_ParameterData(param__RPR_MESH_VERTEX_ARRAY__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - param__RPR_MESH_VERTEX_ARRAY__dataSize = paramDataSize; - } - else if (paramName == "RPR_MESH_NORMAL_ARRAY" && paramType == RPSPT_UINT64_1) - { - param__RPR_MESH_NORMAL_ARRAY__data = (float*)malloc(paramDataSize); - param__RPR_MESH_NORMAL_ARRAY__defined = true; - if (Read_Element_ParameterData(param__RPR_MESH_NORMAL_ARRAY__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - param__RPR_MESH_NORMAL_ARRAY__dataSize = paramDataSize; - } - else if (paramName == "RPR_MESH_UV_ARRAY" && paramType == RPSPT_UINT64_1) - { - param__RPR_MESH_UV_ARRAY__data = (float*)malloc(paramDataSize); - param__RPR_MESH_UV_ARRAY__defined = true; - if (Read_Element_ParameterData(param__RPR_MESH_UV_ARRAY__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - param__RPR_MESH_UV_ARRAY__dataSize = paramDataSize; - } - else if (paramName == "RPR_MESH_UV2_ARRAY" && paramType == RPSPT_UINT64_1) - { - param__RPR_MESH_UV2_ARRAY__data = (float*)malloc(paramDataSize); - param__RPR_MESH_UV2_ARRAY__defined = true; - if (Read_Element_ParameterData(param__RPR_MESH_UV2_ARRAY__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - param__RPR_MESH_UV2_ARRAY__dataSize = paramDataSize; - } - else if (paramName == "RPR_MESH_VERTEX_INDEX_ARRAY" && paramType == RPSPT_UNDEF) - { - param__RPR_MESH_VERTEX_INDEX_ARRAY__data = (int32_t*)malloc(paramDataSize); - param__RPR_MESH_VERTEX_INDEX_ARRAY__defined = true; - if (Read_Element_ParameterData(param__RPR_MESH_VERTEX_INDEX_ARRAY__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_MESH_NORMAL_INDEX_ARRAY" && paramType == RPSPT_UNDEF) - { - param__RPR_MESH_NORMAL_INDEX_ARRAY__data = (int32_t*)malloc(paramDataSize); - param__RPR_MESH_NORMAL_INDEX_ARRAY__defined = true; - if (Read_Element_ParameterData(param__RPR_MESH_NORMAL_INDEX_ARRAY__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_MESH_UV_INDEX_ARRAY" && paramType == RPSPT_UNDEF) - { - param__RPR_MESH_UV_INDEX_ARRAY__data = (int32_t*)malloc(paramDataSize); - param__RPR_MESH_UV_INDEX_ARRAY__defined = true; - if (Read_Element_ParameterData(param__RPR_MESH_UV_INDEX_ARRAY__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_MESH_UV2_INDEX_ARRAY" && paramType == RPSPT_UNDEF) - { - param__RPR_MESH_UV2_INDEX_ARRAY__data = (int32_t*)malloc(paramDataSize); - param__RPR_MESH_UV2_INDEX_ARRAY__defined = true; - if (Read_Element_ParameterData(param__RPR_MESH_UV2_INDEX_ARRAY__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_MESH_NUM_VERTICES_ARRAY" && paramType == RPSPT_UNDEF) - { - param__RPR_MESH_NUM_VERTICES_ARRAY__data = (int32_t*)malloc(paramDataSize); - param__RPR_MESH_NUM_VERTICES_ARRAY__defined = true; - if (Read_Element_ParameterData(param__RPR_MESH_NUM_VERTICES_ARRAY__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == STR__SHAPE_INSTANCE_REFERENCE_ID && paramType == RPSPT_INT32_1) - { - param__SHAPE_INSTANCE_REFERENCE_ID__defined = true; - if (Read_Element_ParameterData(¶m__SHAPE_INSTANCE_REFERENCE_ID__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_SHAPE_TRANSFORM" && paramType == RPSPT_FLOAT16) - { - param__RPR_SHAPE_TRANSFORM__defined = true; - if (Read_Element_ParameterData(param__RPR_SHAPE_TRANSFORM__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_SHAPE_LINEAR_MOTION" && paramType == RPSPT_FLOAT3) - { - param__RPR_SHAPE_LINEAR_MOTION__defined = true; - if (Read_Element_ParameterData(param__RPR_SHAPE_LINEAR_MOTION__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_SHAPE_ANGULAR_MOTION" && paramType == RPSPT_FLOAT4) - { - param__RPR_SHAPE_ANGULAR_MOTION__defined = true; - if (Read_Element_ParameterData(param__RPR_SHAPE_ANGULAR_MOTION__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_SHAPE_VISIBILITY" && paramType == RPSPT_INT32_1) - { - param__RPR_SHAPE_VISIBILITY__defined = true; - if (Read_Element_ParameterData(¶m__RPR_SHAPE_VISIBILITY__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_SHAPE_SHADOW" && paramType == RPSPT_INT32_1) - { - param__RPR_SHAPE_SHADOW__defined = true; - if (Read_Element_ParameterData(¶m__RPR_SHAPE_SHADOW__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_SHAPE_SHADOW_CATCHER" && paramType == RPSPT_INT32_1) - { - param__RPR_SHAPE_SHADOWCATCHER__defined = true; - if (Read_Element_ParameterData(¶m__RPR_SHAPE_SHADOWCATCHER__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_SHAPE_DISPLACEMENT_SCALE" && paramType == RPSPT_FLOAT2) - { - param__RPR_SHAPE_DISPLACEMENT_SCALE__defined = true; - if (Read_Element_ParameterData(param__RPR_SHAPE_DISPLACEMENT_SCALE__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_SHAPE_OBJECT_GROUP_ID" && paramType == RPSPT_UINT32_1) - { - param__RPR_SHAPE_OBJECT_GROUP_ID__defined = true; - if (Read_Element_ParameterData(¶m__RPR_SHAPE_OBJECT_GROUP_ID__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_SHAPE_SUBDIVISION_FACTOR" && paramType == RPSPT_UINT32_1) - { - param__RPR_SHAPE_SUBDIVISION_FACTOR__defined = true; - if (Read_Element_ParameterData(¶m__RPR_SHAPE_SUBDIVISION_FACTOR__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - - else if (paramName == "RPR_SHAPE_SUBDIVISION_CREASEWEIGHT" && paramType == RPSPT_FLOAT1) - { - param__RPR_SHAPE_SUBDIVISION_CREASEWEIGHT__defined = true; - if (Read_Element_ParameterData(¶m__RPR_SHAPE_SUBDIVISION_CREASEWEIGHT__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else if (paramName == "RPR_SHAPE_SUBDIVISION_BOUNDARYINTEROP" && paramType == RPSPT_UINT32_1) - { - param__RPR_SHAPE_SUBDIVISION_BOUNDARYINTEROP__defined = true; - if (Read_Element_ParameterData(¶m__RPR_SHAPE_SUBDIVISION_BOUNDARYINTEROP__data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - - else if (paramName == "RPR_OBJECT_NAME" && paramType == RPSPT_UNDEF) - { - objectName = new char[paramDataSize]; - if (Read_Element_ParameterData(objectName, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - } - else - { - char* data_data = new char[paramDataSize]; - if (Read_Element_ParameterData(data_data, paramDataSize) != RPR_SUCCESS) { RPS_MACRO_ERROR(); return NULL; } - - WarningDetected(); - - delete[] data_data; data_data = NULL; - } - - - } - - } - else if ((nextElem == RPSRT_OBJECT_BEG && elementName == "RPR_SHAPE_DISPLACEMENT_IMAGE" && objBegType == "rpr_image") - || (nextElem == RPSRT_REFERENCE && elementName == "RPR_SHAPE_DISPLACEMENT_IMAGE") - ) - { - param__RPR_SHAPE_DISPLACEMENT_IMAGE__data = Read_Image(context); - param__RPR_SHAPE_DISPLACEMENT_IMAGE__defined = true; - } - else if ((nextElem == RPSRT_OBJECT_BEG && objBegType == "rpr_material_node") - || (nextElem == RPSRT_REFERENCE && objBegType == "rpr_material_node") - ) - { - shapeMaterial = Read_MaterialNode(materialSystem, context); - if (shapeMaterial == NULL) - { - RPS_MACRO_ERROR(); - return NULL; - } - } - else if (nextElem == RPSRT_OBJECT_END) - { - break; - } - else - { - RPS_MACRO_ERROR(); - return NULL; - } - } - - - if (!param__RPR_SHAPE_TYPE__defined) { RPS_MACRO_ERROR(); return NULL; } - if (param__RPR_SHAPE_TYPE__data == RPR_SHAPE_TYPE_MESH) - { - //special case : no UV data - if (param__RPR_MESH_UV_COUNT__defined && param__RPR_MESH_UV_COUNT__data == 0 - && !param__RPR_MESH_UV_ARRAY__defined - && !param__RPR_MESH_UV_INDEX_ARRAY__defined - ) - { - param__RPR_MESH_UV_ARRAY__defined = true; - param__RPR_MESH_UV_ARRAY__data = nullptr; - param__RPR_MESH_UV_ARRAY__dataSize = 0; - param__RPR_MESH_UV_INDEX_ARRAY__defined = true; - param__RPR_MESH_UV_INDEX_ARRAY__data = nullptr; - } - - //special case : no UV2 data - if (param__RPR_MESH_UV2_COUNT__defined && param__RPR_MESH_UV2_COUNT__data == 0 - && !param__RPR_MESH_UV2_ARRAY__defined - && !param__RPR_MESH_UV2_INDEX_ARRAY__defined - ) - { - param__RPR_MESH_UV2_ARRAY__defined = true; - param__RPR_MESH_UV2_ARRAY__data = nullptr; - param__RPR_MESH_UV2_ARRAY__dataSize = 0; - param__RPR_MESH_UV2_INDEX_ARRAY__defined = true; - param__RPR_MESH_UV2_INDEX_ARRAY__data = nullptr; - } - - //special case : for old version, UV2 data doesn't exist - if ( - !param__RPR_MESH_UV2_COUNT__defined - && !param__RPR_MESH_UV2_ARRAY__defined - && !param__RPR_MESH_UV2_INDEX_ARRAY__defined - ) - { - param__RPR_MESH_UV2_ARRAY__defined = true; - param__RPR_MESH_UV2_ARRAY__data = nullptr; - param__RPR_MESH_UV2_ARRAY__dataSize = 0; - param__RPR_MESH_UV2_INDEX_ARRAY__defined = true; - param__RPR_MESH_UV2_INDEX_ARRAY__data = nullptr; - param__RPR_MESH_UV2_COUNT__defined = true; - param__RPR_MESH_UV2_COUNT__data = 0; - } - - - if (!param__RPR_MESH_POLYGON_COUNT__defined - || !param__RPR_MESH_VERTEX_COUNT__defined - || !param__RPR_MESH_NORMAL_COUNT__defined - || !param__RPR_MESH_UV_COUNT__defined - || !param__RPR_MESH_UV2_COUNT__defined - || !param__RPR_MESH_VERTEX_ARRAY__defined - || !param__RPR_MESH_NORMAL_ARRAY__defined - || !param__RPR_MESH_UV_ARRAY__defined - || !param__RPR_MESH_UV2_ARRAY__defined - || !param__RPR_MESH_VERTEX_INDEX_ARRAY__defined - || !param__RPR_MESH_NORMAL_INDEX_ARRAY__defined - || !param__RPR_MESH_UV_INDEX_ARRAY__defined - || !param__RPR_MESH_UV2_INDEX_ARRAY__defined - || !param__RPR_MESH_NUM_VERTICES_ARRAY__defined - ) - { - RPS_MACRO_ERROR(); return NULL; - } - - - const int MAX_UV_CHANNELS = 2; - const rpr_float* texcoords[MAX_UV_CHANNELS] = { nullptr, nullptr }; - size_t num_texcoords[MAX_UV_CHANNELS] = { 0, 0 }; - rpr_int texcoord_stride[MAX_UV_CHANNELS] = { 0, 0 }; - const rpr_int* texcoord_indices_[MAX_UV_CHANNELS] = { nullptr, nullptr }; - rpr_int tidx_stride_[MAX_UV_CHANNELS] = { 0, 0 }; - - - int nbUVchannels = 0; - if (param__RPR_MESH_UV_ARRAY__data != nullptr) - { - texcoords[0] = param__RPR_MESH_UV_ARRAY__data; - num_texcoords[0] = param__RPR_MESH_UV_COUNT__data; - texcoord_stride[0] = param__RPR_MESH_UV_ARRAY__dataSize == 0 ? 0 : int(param__RPR_MESH_UV_ARRAY__dataSize / param__RPR_MESH_UV_COUNT__data); - texcoord_indices_[0] = param__RPR_MESH_UV_INDEX_ARRAY__data; - tidx_stride_[0] = sizeof(rpr_int); - - nbUVchannels++; - if (param__RPR_MESH_UV2_ARRAY__data != nullptr) - { - texcoords[1] = param__RPR_MESH_UV2_ARRAY__data; - num_texcoords[1] = param__RPR_MESH_UV2_COUNT__data; - texcoord_stride[1] = param__RPR_MESH_UV2_ARRAY__dataSize == 0 ? 0 : int(param__RPR_MESH_UV2_ARRAY__dataSize / param__RPR_MESH_UV2_COUNT__data); - texcoord_indices_[1] = param__RPR_MESH_UV2_INDEX_ARRAY__data; - tidx_stride_[1] = sizeof(rpr_int); - - nbUVchannels++; - } - } - - - - shape = NULL; - status = rprContextCreateMeshEx(context, - param__RPR_MESH_VERTEX_ARRAY__data, param__RPR_MESH_VERTEX_COUNT__data, int(param__RPR_MESH_VERTEX_ARRAY__dataSize / param__RPR_MESH_VERTEX_COUNT__data), - param__RPR_MESH_NORMAL_ARRAY__data, param__RPR_MESH_NORMAL_COUNT__data, int(param__RPR_MESH_NORMAL_ARRAY__dataSize / param__RPR_MESH_NORMAL_COUNT__data), - nullptr, 0, 0, - nbUVchannels, - - texcoords, num_texcoords, texcoord_stride, - //param__RPR_MESH_UV_ARRAY__data , param__RPR_MESH_UV_COUNT__data, param__RPR_MESH_UV_ARRAY__dataSize == 0 ? 0 : int(param__RPR_MESH_UV_ARRAY__dataSize / param__RPR_MESH_UV_COUNT__data), - - param__RPR_MESH_VERTEX_INDEX_ARRAY__data, sizeof(rpr_int), - param__RPR_MESH_NORMAL_INDEX_ARRAY__data, sizeof(rpr_int), - - texcoord_indices_, tidx_stride_, - //param__RPR_MESH_UV_INDEX_ARRAY__data, sizeof(rpr_int), - - param__RPR_MESH_NUM_VERTICES_ARRAY__data, param__RPR_MESH_POLYGON_COUNT__data, &shape); - CHECK_STATUS_RETURNNULL; - } - else if (param__RPR_SHAPE_TYPE__data == RPR_SHAPE_TYPE_INSTANCE) - { - if (!param__SHAPE_INSTANCE_REFERENCE_ID__defined) { RPS_MACRO_ERROR(); return NULL; } - - //search the id in the previous loaded - rpr_shape shapeReferenced = NULL; - for (int iObj = 0; iObjread((char*)&elementType, sizeof(int32_t)); - if (m_rpsFile->eof()) - { - return RPSRT_UNDEF; - } - - Read_String(name); - - int64_t sizeOfElementHead = sizeof(int32_t) + sizeof(int32_t) + name.length(); - - if (elementType == RPSRT_OBJECT_BEG || elementType == RPSRT_REFERENCE) - { - Read_String(objBegType); - sizeOfElementHead += sizeof(int32_t) + objBegType.length(); - } - else - { - objBegType = ""; - } - - //rewind to the beginning of element - m_rpsFile->seekg(-sizeOfElementHead, m_rpsFile->cur); - - if ( - elementType == RPSRT_OBJECT_BEG - || elementType == RPSRT_OBJECT_END - || elementType == RPSRT_PARAMETER - || elementType == RPSRT_REFERENCE - ) - { - return elementType; - } - else - { - RPS_MACRO_ERROR(); - return RPSRT_UNDEF; - } -} - -rpr_int RPS8::Read_Element_StartObject(std::string& name, std::string& type, int32_t& id) -{ - RPS_ELEMENTS_TYPE elementType = RPSRT_UNDEF; - m_rpsFile->read((char*)&elementType, sizeof(int32_t)); - if (elementType != RPSRT_OBJECT_BEG) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - Read_String(name); - Read_String(type); - m_rpsFile->read((char*)&id, sizeof(int32_t)); - - m_level++; - return RPR_SUCCESS; -} - -rpr_int RPS8::Read_Element_EndObject(const std::string& type, void* obj, int32_t id) -{ - RPS_ELEMENTS_TYPE elementType = RPSRT_UNDEF; - m_rpsFile->read((char*)&elementType, sizeof(int32_t)); - std::string endObjName; //this string is not used - Read_String(endObjName); - if (elementType != RPSRT_OBJECT_END) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - m_level--; - - RPS_OBJECT_DECLARED newObj; - newObj.id = id; - newObj.type = type; - newObj.obj = obj; - m_listObjectDeclared.push_back(newObj); - - - return RPR_SUCCESS; -} - -rpr_int RPS8::Read_Element_ParameterData(void* data, uint64_t size) -{ - if (data == NULL && size != 0) - { - RPS_MACRO_ERROR(); - return RPR_ERROR_INTERNAL_ERROR; - } - - m_rpsFile->read((char*)data, size); - return RPR_SUCCESS; -} - -rpr_int RPS8::Read_Element_Parameter(std::string& name, RPS_PARAMETER_TYPE& type, uint64_t& dataSize) -{ - RPS_ELEMENTS_TYPE elementType = RPSRT_UNDEF; - m_rpsFile->read((char*)&elementType, sizeof(int32_t)); - if (elementType != RPSRT_PARAMETER) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - Read_String(name); - m_rpsFile->read((char*)&type, sizeof(type)); - m_rpsFile->read((char*)&dataSize, sizeof(dataSize)); - return RPR_SUCCESS; -} - -rpr_int RPS8::Read_Element_Reference(std::string& name, std::string& type, RPS_OBJECT_DECLARED& objReferenced) -{ - RPS_ELEMENTS_TYPE elementType = RPSRT_UNDEF; - m_rpsFile->read((char*)&elementType, sizeof(int32_t)); - if (elementType != RPSRT_REFERENCE) { RPS_MACRO_ERROR(); return RPR_ERROR_INTERNAL_ERROR; } - Read_String(name); - Read_String(type); - - int32_t id; - m_rpsFile->read((char*)&id, sizeof(int32_t)); - - //search object in list - bool found = false; - for (int iObj = 0; iObjread((char*)&strSize, sizeof(strSize)); - - if (strSize > 0) - { - char* strRead = new char[strSize + 1]; - m_rpsFile->read(strRead, strSize); - strRead[strSize] = '\0'; - str = std::string(strRead); - delete[] strRead; - strRead = NULL; - } - else - { - str = ""; - } - - return RPR_SUCCESS; -} diff --git a/RprLoadStore/rps8.h b/RprLoadStore/rps8.h deleted file mode 100644 index 11297a80..00000000 --- a/RprLoadStore/rps8.h +++ /dev/null @@ -1,239 +0,0 @@ -#ifndef frLoadStore_RPS8_H_ -#define frLoadStore_RPS8_H_ - -#include "Rpr/RadeonProRender.h" - -#include "common.h" - -#include -#include -#include -#include - - -/* - -Architecture of RPS file : - -we store ELEMENTS. - -there are 4 types of ELEMENTS : -- OBJECT_BEG --> header of an OBJECT. an OBJECT is a set of PARAMETER and REFERENCE -- OBJECT_END --> end of an OBJECT -- PARAMETER --> constains one data (could be an integer, an image, a float4 ...etc...) -- REFERENCE --> reference to an object (for example, this avoid to define several time the same image) - -The head of each ELEMENT is always the same : - < char[] : Element Name String > - - -architecture of each ELEMENTS : - -OBJECT_BEG : - < char[] : object name String > < char[] : object type string > < int32 : ID > - -OBJECT_END : - < char[] : string (usually empty) > - -REFERENCE : - < char[] : reference name String > < char[] : reference type string > < int32 : ID > - -PARAMETER : - < char[] : parameter name String > < int32 : RPS_PARAMETER_TYPE > < int64 : Data size in Byte > < char[] : data > - -*/ - - -class RPS8 -{ - -public: - - RPS8(std::fstream* myfile, bool allowWrite); - ~RPS8(); - - //call that before calling StoreEverything() - void AddExtraCustomParam_int(const std::string& name, int value) { m_extraCustomParam_int[name]=value; } - void AddExtraCustomParam_float(const std::string& name, float value) { m_extraCustomParam_float[name]=value; } - - const std::map& GetExtraCustomParam_int() { return m_extraCustomParam_int; } - const std::map& GetExtraCustomParam_float() { return m_extraCustomParam_float; } - - // return RPR_SUCCESS is success - rpr_int StoreEverything( - rpr_context context, - rpr_scene scene - ); - - // return RPR_SUCCESS is success - rpr_int LoadEverything( - rpr_context context, - rpr_material_system materialSystem, - rpr_scene& scene, - bool useAlreadyExistingScene - ); - - // return RPR_SUCCESS is success - // store a custom list of RPR objects. - rpr_int StoreCustomList( - const std::vector& materialNode_List, - const std::vector& cameraList, - const std::vector& lightList, - const std::vector& shapeList, - const std::vector& imageList - ); - - rpr_int LoadCustomList( - rpr_context context, - rpr_material_system materialSystem , - std::vector& imageList, - std::vector& shapeList, - std::vector& lightList, - std::vector& cameraList, - std::vector& materialNodeList - ); - - - const std::vector& GetListObjectDeclared() { return m_listObjectDeclared; } - - -private: - - - //in order to switch between rpr_parameter_type and RPS_PARAMETER_TYPE, use RPSPT_to_RPRPARAMETERTYPE() or RPRPARAMETERTYPE_to_RPSPT() - enum RPS_PARAMETER_TYPE { - - // do NOT modify the numbers because there would be a retro-compatibility issue with RPS already saved - RPSPT_UNDEF = 0, // undef data - - RPSPT_FLOAT1 = 1, - RPSPT_FLOAT2 = 2, - RPSPT_FLOAT3 = 3, - RPSPT_FLOAT4 = 4, - RPSPT_FLOAT16 = 5, - - RPSPT_UINT32_1 = 6, - RPSPT_UINT32_2 = 7, - RPSPT_UINT32_3 = 8, - RPSPT_UINT32_4 = 9, - - RPSPT_INT32_1 = 10, - RPSPT_INT32_2 = 11, - RPSPT_INT32_3 = 12, - RPSPT_INT32_4 = 13, - - RPSPT_UINT64_1 = 14, - RPSPT_UINT64_2 = 15, - RPSPT_UINT64_3 = 16, - RPSPT_UINT64_4 = 17, - - RPSPT_INT64_1 = 18, - RPSPT_INT64_2 = 19, - RPSPT_INT64_3 = 20, - RPSPT_INT64_4 = 21, - - RPSPT_FORCE_DWORD = 0xffffffff - }; - - enum RPS_ELEMENTS_TYPE - { - RPSRT_UNDEF = 0, - - RPSRT_OBJECT_BEG = 0x0CC01, - RPSRT_OBJECT_END = 0x0CC02, - RPSRT_PARAMETER = 0x0CC03, - RPSRT_REFERENCE = 0x0CC04, - - RPSRT_FORCE_DWORD = 0xffffffff - }; - - //this is just for debug. advice to call this function each time an error is detected. - //for debugging, we can add a breakpoint in this function - void ErrorDetected(const char* function, int32_t line, const char* message); - void WarningDetected(); - - - rpr_parameter_type RPSPT_to_RPRPARAMETERTYPE(RPS_PARAMETER_TYPE in); - RPS_PARAMETER_TYPE RPRPARAMETERTYPE_to_RPSPT(rpr_parameter_type in); - int32_t RPSPT_to_size(RPS_PARAMETER_TYPE in); // return -1 if no fixed size for the input argument - - //return false if FAIL - bool Store_String( const std::string& str); - - // type = "rpr_shape" or "rpr_image" ...etc... - // obj = corresponds to rpr_shape or rpr_image ...etc... - bool Store_StartObject( const std::string& objName, const std::string& type, void* obj); - - bool Store_EndObject(); - - bool Store_ObjectParameter( const std::string& parameterName,RPS_PARAMETER_TYPE type,uint64_t dataSize, const void* data); - - // [in] type = "rpr_shape" or "rpr_image" ...etc... - bool Store_ReferenceToObject(const std::string& objName, const std::string& type, int32_t id); - - rpr_int Store_Context(rpr_context context);// return RPR_SUCCESS is success - rpr_int Store_Scene(rpr_scene scene);// return RPR_SUCCESS is success - rpr_int Store_Shape(rpr_shape shape, const std::string& name); // return RPR_SUCCESS is success - rpr_int Store_Light(rpr_light light, const std::string& name);// return RPR_SUCCESS is success - rpr_int Store_Camera(rpr_camera camera, const std::string& name_);// return RPR_SUCCESS is success - rpr_int Store_MaterialNode(rpr_material_node shader, const std::string& name);// return RPR_SUCCESS is success - rpr_int Store_Image(rpr_image image, const std::string& name);// return RPR_SUCCESS is success - - - rpr_int Read_Context(rpr_context context);// return RPR_SUCCESS is success - rpr_scene Read_Scene(rpr_context context, rpr_material_system materialSystem, rpr_scene sceneExisting);//return NULL if error. If sceneExisting not NULL, the we use this scene. Else we create a new scene. - rpr_light Read_Light(rpr_context context, rpr_scene scene, rpr_material_system materialSystem);//return NULL if error - rpr_image Read_Image(rpr_context context);//return NULL if error - rpr_shape Read_Shape(rpr_context context, rpr_material_system materialSystem);//return NULL if error - rpr_material_node Read_MaterialNode(rpr_material_system materialSystem, rpr_context context);//return NULL if error - rpr_camera Read_Camera(rpr_context context);//return NULL if error - - // [out] name : name of the next element - // [out] objBegType : only filled if next element is RPSRT_OBJECT_BEG or RPSRT_REFERENCE - // return RPSRT_UNDEF if error or if end of file - RPS_ELEMENTS_TYPE Read_whatsNext(std::string& name, std::string& objBegType); - - rpr_int Read_Element_StartObject(std::string& name, std::string& type, int32_t& id); // return RPR_SUCCESS if success - - // [in] type = "rpr_shape" or "rpr_image" ...etc... - // obj = corresponds to rpr_shape or rpr_image ...etc... - rpr_int Read_Element_EndObject(const std::string& type, void* obj, int32_t id); // return RPR_SUCCESS if success - - rpr_int Read_Element_Parameter(std::string& name, RPS_PARAMETER_TYPE& type, uint64_t& dataSize); // return RPR_SUCCESS if success - rpr_int Read_Element_ParameterData(void* data, uint64_t size); // return RPR_SUCCESS if success - rpr_int Read_Element_Reference(std::string& name, std::string& type, RPS_OBJECT_DECLARED& objReferenced); // return RPR_SUCCESS if success - rpr_int Read_String(std::string& str); // return RPR_SUCCESS if success - - //should be incremented each time we update the store/load - //version will be write just after the m_HEADER_CHECKCODE - static const int32_t m_FILE_VERSION; - - //first 4 bytes of the file. - //will never change. - //just tell that it's a FireRender Scene file - static const char m_HEADER_CHECKCODE[4]; - static const char m_HEADER_BADCHECKCODE[4]; // bad checkcode, indicates that RPS file is not correct. - - - int32_t m_level; // increment when enter inside Store_StartObject/Read_Element_ObjBeg. decrement when Store_EndObject/Read_Element_ObjEnd - - std::fstream* m_rpsFile; - - int32_t m_idCounter; // increment each time we declare an object - - - - std::vector m_listObjectDeclared; - - int32_t m_fileVersionOfLoadFile; - - std::map m_extraCustomParam_int; - std::map m_extraCustomParam_float; - - const bool m_allowWrite; // = true if allow write the m_frsFile fstream - = false if Read Only - -}; - - - -#endif diff --git a/RprSupport/CMakeLists.txt b/RprSupport/CMakeLists.txt new file mode 100644 index 00000000..65f20f4d --- /dev/null +++ b/RprSupport/CMakeLists.txt @@ -0,0 +1,14 @@ +set(SOURCES RprSupport.cpp) + +add_library(RprSupport64 SHARED ${SOURCES}) +target_compile_definitions(RprSupport64 PRIVATE RPR_EXPORT_API) +target_compile_features(RprSupport64 PRIVATE cxx_std_14) +target_include_directories(RprSupport64 PUBLIC ${RprSupport_HEADER}) +target_link_libraries(RprSupport64 PUBLIC RadeonProRender64) + +# Install target +if (WIN32) + install(TARGETS RprSupport64 RUNTIME DESTINATION bin) +else () + install(TARGETS RprSupport64 LIBRARY DESTINATION lib) +endif () diff --git a/RprSupport/RprSupport.cpp b/RprSupport/RprSupport.cpp new file mode 100644 index 00000000..2e8f533d --- /dev/null +++ b/RprSupport/RprSupport.cpp @@ -0,0 +1,253 @@ +/********************************************************************** +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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 "RprSupport.h" +#include "WrapObject/WrapObject.h" +#include "WrapObject/ContextObject.h" +#include "WrapObject/CameraObject.h" +#include "WrapObject/FramebufferObject.h" +#include "WrapObject/LightObject.h" +#include "WrapObject/Materials/MaterialObject.h" +#include "WrapObject/MatSysObject.h" +#include "WrapObject/SceneObject.h" +#include "WrapObject/ShapeObject.h" +#include "WrapObject/Exception.h" + +//defines behavior for unimplemented API part +//#define UNIMLEMENTED_FUNCTION return RPR_SUCCESS; +#define UNIMPLEMENTED_FUNCTION return RPR_ERROR_UNIMPLEMENTED; + +#define UNSUPPORTED_FUNCTION return RPR_SUCCESS; +//#define UNSUPPORTED_FUNCTION return RPR_ERROR_UNSUPPORTED; + +static const std::map kRPRXInputStrings = +{ + { RPRX_UBER_MATERIAL_DIFFUSE_COLOR, "uberv2.diffuse.color"}, + { RPRX_UBER_MATERIAL_DIFFUSE_WEIGHT, "uberv2.diffuse.weight"}, + { RPRX_UBER_MATERIAL_REFLECTION_COLOR, "uberv2.reflection.color"}, + { RPRX_UBER_MATERIAL_REFLECTION_WEIGHT, "uberv2.reflection.weight" }, + { RPRX_UBER_MATERIAL_REFLECTION_ROUGHNESS, "uberv2.reflection.roughness" }, + { RPRX_UBER_MATERIAL_REFLECTION_ANISOTROPY, "uberv2.reflection.anisotropy" }, + { RPRX_UBER_MATERIAL_REFLECTION_ANISOTROPY_ROTATION, "uberv2.reflection.anisotropy_rotation" }, + { RPRX_UBER_MATERIAL_REFLECTION_IOR, "uberv2.reflection.ior" }, + //{ RPRX_UBER_MATERIAL_REFLECTION_METALNESS, "uberv2.reflection.metalness" }, + { RPRX_UBER_MATERIAL_REFRACTION_COLOR, "uberv2.refraction.color" }, + { RPRX_UBER_MATERIAL_REFRACTION_WEIGHT, "uberv2.refraction.weight" }, + { RPRX_UBER_MATERIAL_REFRACTION_ROUGHNESS, "uberv2.refraction.roughness" }, + { RPRX_UBER_MATERIAL_REFRACTION_IOR, "uberv2.refraction.ior" }, + { RPRX_UBER_MATERIAL_REFRACTION_IOR_MODE, "uberv2.refraction.ior_mode" }, + { RPRX_UBER_MATERIAL_REFRACTION_THIN_SURFACE, "uberv2.refraction.thin_surface" }, + { RPRX_UBER_MATERIAL_COATING_COLOR, "uberv2.coating.color" }, + { RPRX_UBER_MATERIAL_COATING_WEIGHT, "uberv2.coating.weight" }, + { RPRX_UBER_MATERIAL_COATING_IOR, "uberv2.coating.ior" }, + { RPRX_UBER_MATERIAL_EMISSION_COLOR, "uberv2.emission.color" }, + { RPRX_UBER_MATERIAL_EMISSION_WEIGHT, "uberv2.emission.weight" }, + { RPRX_UBER_MATERIAL_EMISSION_MODE, "uberv2.emission.mode" }, + { RPRX_UBER_MATERIAL_TRANSPARENCY, "uberv2.transparency" }, + { RPRX_UBER_MATERIAL_NORMAL, "uberv2.normal" }, + { RPRX_UBER_MATERIAL_BUMP, "uberv2.bump" }, + { RPRX_UBER_MATERIAL_DISPLACEMENT, "uberv2.displacement" }, + { RPRX_UBER_MATERIAL_SSS_ABSORPTION_COLOR, "uberv2.sss.absorption_color" }, + { RPRX_UBER_MATERIAL_SSS_SCATTER_COLOR, "uberv2.sss.scatter_color" }, + { RPRX_UBER_MATERIAL_SSS_ABSORPTION_DISTANCE, "uberv2.sss.absorption_distance" }, + { RPRX_UBER_MATERIAL_SSS_SCATTER_DISTANCE, "uberv2.sss.scatter_distance" }, + { RPRX_UBER_MATERIAL_SSS_SCATTER_DIRECTION, "uberv2.sss.scatter_direction" }, + { RPRX_UBER_MATERIAL_SSS_WEIGHT, "uberv2.sss.weight" }, + { RPRX_UBER_MATERIAL_SSS_SUBSURFACE_COLOR, "uberv2.sss.subsurface_color" }, + { RPRX_UBER_MATERIAL_SSS_MULTISCATTER, "uberv2.sss.multiscatter" } +}; + +rpr_int rprxCreateContext(rpr_material_system material_system, rpr_uint flags, rprx_context* out_context) +{ + if (!material_system) + return RPR_ERROR_INVALID_PARAMETER; + + // We only need material system to work with materials, so it's our rprx_context + *out_context = static_cast(material_system); + + return RPR_SUCCESS; +} + +rpr_int rprxCreateMaterial(rprx_context context, rprx_material_type type, rprx_material* out_material) +{ + if (!context || type != RPRX_MATERIAL_UBER) + return RPR_ERROR_INVALID_PARAMETER; + + return rprMaterialSystemCreateNode((rpr_material_system)(context), RPR_MATERIAL_NODE_UBERV2, (rpr_material_node*)out_material); +} + +rpr_int rprxMaterialDelete(rprx_context context, rprx_material material) +{ + if (!context || !material) + return RPR_ERROR_INVALID_PARAMETER; + + return rprObjectDelete((rpr_material_node)material); +} + +rpr_int rprxMaterialSetParameterN(rprx_context context, rprx_material material, rprx_parameter parameter, rpr_material_node node) +{ + if (!material) + return RPR_ERROR_INVALID_PARAMETER; + + auto it = kRPRXInputStrings.find(parameter); + + if (parameter == RPRX_UBER_MATERIAL_BUMP || + parameter == RPRX_UBER_MATERIAL_NORMAL) + { + rpr_uint layers = 0; + + rprMaterialNodeGetInputInfo((rpr_material_node)material, RPR_UBER_MATERIAL_LAYERS, RPR_MATERIAL_NODE_INPUT_VALUE, 4, &layers, 0); + + if (node) + { + layers |= RPR_UBER_MATERIAL_LAYER_SHADING_NORMAL; + } + else + { + layers &= ~RPR_UBER_MATERIAL_LAYER_SHADING_NORMAL; + } + rprMaterialNodeSetInputU_ext((rpr_material_node)material, RPR_UBER_MATERIAL_LAYERS, layers); + } + + return (it != kRPRXInputStrings.end()) ? + rprMaterialNodeSetInputN((rpr_material_node)material, it->second.c_str(), (rpr_material_node)node) : + RPR_ERROR_INVALID_PARAMETER; +} + +rpr_int rprxMaterialSetParameterU(rprx_context context, rprx_material material, rprx_parameter parameter, rpr_uint value) +{ + if (!material) + return RPR_ERROR_INVALID_PARAMETER; + + auto it = kRPRXInputStrings.find(parameter); + + return (it != kRPRXInputStrings.end()) ? + rprMaterialNodeSetInputU((rpr_material_node)material, it->second.c_str(), value) : + RPR_ERROR_INVALID_PARAMETER; +} + +rpr_int rprxMaterialSetParameterF(rprx_context context, rprx_material material, rprx_parameter parameter, rpr_float x, rpr_float y, rpr_float z, rpr_float w) +{ + if (!material) + return RPR_ERROR_INVALID_PARAMETER; + + rpr_uint layers = 0; + rpr_uint status; + + rprMaterialNodeGetInputInfo((rpr_material_node)material, RPR_UBER_MATERIAL_LAYERS, RPR_MATERIAL_NODE_INPUT_VALUE, 4, &layers, 0); + + switch (parameter) + { + case RPRX_UBER_MATERIAL_DIFFUSE_WEIGHT: + if (x > 0.f) layers |= RPR_UBER_MATERIAL_LAYER_DIFFUSE; + else layers &= ~RPR_UBER_MATERIAL_LAYER_DIFFUSE; + return rprMaterialNodeSetInputU_ext((rpr_material_node)material, RPR_UBER_MATERIAL_LAYERS, layers); + + case RPRX_UBER_MATERIAL_COATING_WEIGHT: + if (x > 0.f) layers |= RPR_UBER_MATERIAL_LAYER_COATING; + else layers &= ~RPR_UBER_MATERIAL_LAYER_COATING; + return rprMaterialNodeSetInputU_ext((rpr_material_node)material, RPR_UBER_MATERIAL_LAYERS, layers); + + case RPRX_UBER_MATERIAL_REFLECTION_WEIGHT: + if (x > 0.f) layers |= RPR_UBER_MATERIAL_LAYER_REFLECTION; + else layers &= ~RPR_UBER_MATERIAL_LAYER_REFLECTION; + return rprMaterialNodeSetInputU_ext((rpr_material_node)material, RPR_UBER_MATERIAL_LAYERS, layers); + + case RPRX_UBER_MATERIAL_REFRACTION_WEIGHT: + if (x > 0.f) layers |= RPR_UBER_MATERIAL_LAYER_REFRACTION; + else layers &= ~RPR_UBER_MATERIAL_LAYER_REFRACTION; + return rprMaterialNodeSetInputU_ext((rpr_material_node)material, RPR_UBER_MATERIAL_LAYERS, layers); + + case RPRX_UBER_MATERIAL_TRANSPARENCY: + if (x > 0.f) layers |= RPR_UBER_MATERIAL_LAYER_TRANSPARENCY; + else layers &= ~RPR_UBER_MATERIAL_LAYER_TRANSPARENCY; + status = rprMaterialNodeSetInputU_ext((rpr_material_node)material, RPR_UBER_MATERIAL_LAYERS, layers); + if (status != RPR_SUCCESS) return status; + } + + + auto it = kRPRXInputStrings.find(parameter); + + return (it != kRPRXInputStrings.end()) ? + rprMaterialNodeSetInputF((rpr_material_node)material, it->second.c_str(), x, y, z, w) : + RPR_ERROR_INVALID_PARAMETER; +} + +rpr_int rprxMaterialGetParameterType(rprx_context context, rprx_material material, rprx_parameter parameter, rpr_parameter_type* out_type) +{ + UNIMPLEMENTED_FUNCTION +} + +extern RPR_API_ENTRY rpr_int rprxMaterialGetParameterValue(rprx_context context, rprx_material material, rprx_parameter parameter, void* out_value) +{ + UNIMPLEMENTED_FUNCTION +} + +rpr_int rprxMaterialCommit(rprx_context context, rprx_material material) +{ + UNSUPPORTED_FUNCTION +} + +rpr_int rprxShapeAttachMaterial(rprx_context context, rpr_shape shape, rprx_material material) +{ + return rprShapeSetMaterial(shape, (rpr_material_node)material); +} + +rpr_int rprxShapeDetachMaterial(rprx_context context, rpr_shape shape, rprx_material material) +{ + return rprShapeSetMaterial(shape, nullptr); +} + +rpr_int rprxMaterialAttachMaterial(rprx_context context, rpr_material_node node, rpr_char const* parameter, rprx_material material) +{ + UNIMPLEMENTED_FUNCTION +} + +rpr_int rprxMaterialDetachMaterial(rprx_context context, rpr_material_node node, rpr_char const* parameter, rprx_material material) +{ + UNIMPLEMENTED_FUNCTION +} + +rpr_int rprxDeleteContext(rprx_context context) +{ + UNSUPPORTED_FUNCTION +} + +rpr_int rprxIsMaterialRprx(rprx_context context, rpr_material_node node, rprx_material* out_material, rpr_bool* out_result) +{ + UNIMPLEMENTED_FUNCTION +} + +rpr_int rprxGetLog(rprx_context context, rpr_char* log, size_t* size) +{ + UNIMPLEMENTED_FUNCTION +} + +rpr_int rprxShapeGetMaterial(rprx_context context, rpr_shape shape, rprx_material* material) +{ + UNIMPLEMENTED_FUNCTION +} + + + + + diff --git a/RprSupport/RprSupport.def b/RprSupport/RprSupport.def new file mode 100644 index 00000000..6b3b28e4 --- /dev/null +++ b/RprSupport/RprSupport.def @@ -0,0 +1,19 @@ +EXPORTS + +rprxCreateContext +rprxCreateMaterial +rprxMaterialDelete +rprxMaterialSetParameterN +rprxMaterialSetParameterU +rprxMaterialSetParameterF +rprxMaterialGetParameterType +rprxMaterialGetParameterValue +rprxMaterialCommit +rprxShapeAttachMaterial +rprxShapeDetachMaterial +rprxMaterialAttachMaterial +rprxMaterialDetachMaterial +rprxDeleteContext +rprxIsMaterialRprx +rprxGetLog +rprxShapeGetMaterial diff --git a/RprTest/CMakeLists.txt b/RprTest/CMakeLists.txt new file mode 100644 index 00000000..ad88df59 --- /dev/null +++ b/RprTest/CMakeLists.txt @@ -0,0 +1,48 @@ +set(SOURCES + main.cpp + aov.h + arithmetic.h + basic.h + camera.h + light.h + material.h) + +add_executable(RprTest ${SOURCES}) +target_compile_features(RprTest PRIVATE cxx_std_14) +target_include_directories(RprTest PRIVATE .) +target_link_libraries(RprTest PRIVATE GTest RprSupport64 RadeonProRender64) +set_target_properties(RprTest + PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${Baikal_SOURCE_DIR}/RprTest) + +# TODO: BaikalTest images and RprTest images directories have identical names +if (0) +# Add symbolic links to RprTest/OutputImages and RprTest/ReferenceImages directory +set(RPRTEST_REFERENCEIMAGES_DIR ReferenceImages) +file(TO_NATIVE_PATH ${Baikal_SOURCE_DIR}/RprTest/${RPRTEST_REFERENCEIMAGES_DIR} RPRTEST_REFERENCEIMAGES_SRC) +file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR}/${RPRTEST_REFERENCEIMAGES_DIR} RPRTEST_REFERENCEIMAGES_DST) + +set(RPRTEST_OUTPUTIMAGES_DIR OutputImages) +file(TO_NATIVE_PATH ${Baikal_SOURCE_DIR}/RprTest/${RPRTEST_OUTPUTIMAGES_DIR} RPRTEST_OUTPUTIMAGES_SRC) +file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR}/${RPRTEST_OUTPUTIMAGES_DIR} RPRTEST_OUTPUTIMAGES_DST) + +if (WIN32) + add_custom_target(RprTestImagesDir ALL + COMMAND IF NOT EXIST ${RPRTEST_REFERENCEIMAGES_DST} mklink /D ${RPRTEST_REFERENCEIMAGES_DST} ${RPRTEST_REFERENCEIMAGES_SRC} + COMMAND IF NOT EXIST ${RPRTEST_OUTPUTIMAGES_DST} mklink /D ${RPRTEST_OUTPUTIMAGES_DST} ${RPRTEST_OUTPUTIMAGES_SRC} + ) +else () + add_custom_target(RprTestImagesDir ALL + COMMAND ${CMAKE_COMMAND} -E create_symlink ${RPRTEST_REFERENCEIMAGES_SRC} ${RPRTEST_REFERENCEIMAGES_DST} + COMMAND ${CMAKE_COMMAND} -E create_symlink ${RPRTEST_OUTPUTIMAGES_SRC} ${RPRTEST_OUTPUTIMAGES_DST} + ) +endif () + +add_dependencies(RprTest RprTestImagesDir ResourcesDir) +endif () + +add_dependencies(RprTest ResourcesDir) + +# Install target +install(TARGETS RprTest RUNTIME DESTINATION bin) +install(DIRECTORY DESTINATION bin/${RPRTEST_REFERENCEIMAGES_DIR}) +install(DIRECTORY DESTINATION bin/${RPRTEST_OUTPUTIMAGES_DIR}) diff --git a/RprTest/OutputImages/placeholder.txt b/RprTest/OutputImages/placeholder.txt new file mode 100644 index 00000000..d4d2e2d5 --- /dev/null +++ b/RprTest/OutputImages/placeholder.txt @@ -0,0 +1 @@ +placeholder for output images diff --git a/RprTest/ReferenceImages/placeholder.txt b/RprTest/ReferenceImages/placeholder.txt new file mode 100644 index 00000000..6680b767 --- /dev/null +++ b/RprTest/ReferenceImages/placeholder.txt @@ -0,0 +1 @@ +placeholder for reference images diff --git a/RprTest/RprTest.lua b/RprTest/RprTest.lua deleted file mode 100644 index 2a405a79..00000000 --- a/RprTest/RprTest.lua +++ /dev/null @@ -1,58 +0,0 @@ -project "RprTest" - kind "ConsoleApp" - location "../RprTest" - links {"RadeonRays", "CLW", "Calc", "Rpr", "RprLoadStore"} - files { "../RprTest/**.h", "../RprTest/**.cpp", "../RprTest/**.cl", "../RprTest/**.fsh", "../RprTest/**.vsh" } - - includedirs{ "../Rpr", ".", "../RprLoadStore/" } - - if os.is("macosx") then - sysincludedirs {"/usr/local/include"} - libdirs {"/usr/local/lib"} - buildoptions "-std=c++11 -stdlib=libc++" - links {"OpenImageIO"} - end - - if os.is("windows") then - includedirs { "../3rdparty/oiio/include" } - links {"RadeonRays",} - links {"glew"} - libdirs { "../3rdparty/glew/lib/%{cfg.platform}", - "../3rdparty/freeglut/lib/%{cfg.platform}", - "../3rdparty/embree/lib/%{cfg.platform}", - "../3rdparty/oiio/lib/%{cfg.platform}"} - configuration {"Debug"} - links {"OpenImageIOD"} - configuration {"Release"} - links {"OpenImageIO"} - configuration {} - end - - if os.is("linux") then - buildoptions "-std=c++11" - links {"OpenImageIO", "pthread",} - os.execute("rm -rf obj"); - end - - configuration {"x32", "Debug"} - targetdir "../Bin/Debug/x86" - configuration {"x64", "Debug"} - targetdir "../Bin/Debug/x64" - configuration {"x32", "Release"} - targetdir "../Bin/Release/x86" - configuration {"x64", "Release"} - targetdir "../Bin/Release/x64" - configuration {} - - os.mkdir("Output") - - if os.is("windows") then - postbuildcommands { - 'copy "..\\3rdparty\\glew\\bin\\%{cfg.platform}\\glew32.dll" "%{cfg.buildtarget.directory}"', - 'copy "..\\3rdparty\\freeglut\\bin\\%{cfg.platform}\\freeglut.dll" "%{cfg.buildtarget.directory}"', - 'copy "..\\3rdparty\\embree\\bin\\%{cfg.platform}\\embree.dll" "%{cfg.buildtarget.directory}"', - 'copy "..\\3rdparty\\embree\\bin\\%{cfg.platform}\\tbb.dll" "%{cfg.buildtarget.directory}"', - 'copy "..\\3rdparty\\oiio\\bin\\%{cfg.platform}\\OpenImageIO.dll" "%{cfg.buildtarget.directory}"', - 'copy "..\\3rdparty\\oiio\\bin\\%{cfg.platform}\\OpenImageIOD.dll" "%{cfg.buildtarget.directory}"', - } - end \ No newline at end of file diff --git a/RprTest/aov.h b/RprTest/aov.h new file mode 100644 index 00000000..1db55f31 --- /dev/null +++ b/RprTest/aov.h @@ -0,0 +1,163 @@ +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ + +#pragma once + +#include "basic.h" + +class AovTest : public BasicTest +{ +public: + void CreateFramebuffer() override + { + // Create Framebuffer + rpr_framebuffer_desc desc = { kOutputWidth, kOutputHeight }; + rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; + ASSERT_EQ(rprContextCreateFrameBuffer(m_context, fmt, &desc, &m_framebuffer), RPR_SUCCESS); + } + + void TestAovImplemented(rpr_aov aov) + { + CreateScene(SceneType::kSphereAndPlane); + AddEnvironmentLight("../Resources/Textures/studio015.hdr"); + + ASSERT_EQ(rprContextSetAOV(m_context, aov, m_framebuffer), RPR_SUCCESS); + Render(); + SaveAndCompare(); + } + + void TestAovNotImplemented(rpr_aov aov) const + { + ASSERT_EQ(rprContextSetAOV(m_context, aov, m_framebuffer), RPR_ERROR_UNIMPLEMENTED); + } +}; + +// Test aovs that implemented +TEST_F(AovTest, Aov_Color) +{ + TestAovImplemented(RPR_AOV_COLOR); +} + +TEST_F(AovTest, Aov_WorldCoordinate) +{ + TestAovImplemented(RPR_AOV_WORLD_COORDINATE); +} + +TEST_F(AovTest, Aov_Uv) +{ + TestAovImplemented(RPR_AOV_UV); +} + +TEST_F(AovTest, Aov_GeometricNormal) +{ + TestAovImplemented(RPR_AOV_GEOMETRIC_NORMAL); +} + +TEST_F(AovTest, Aov_ShadingNormal) +{ + TestAovImplemented(RPR_AOV_SHADING_NORMAL); +} + +TEST_F(AovTest, Aov_Opacity) +{ + // Create dummy framebuffer + rpr_framebuffer_desc desc = { kOutputWidth, kOutputHeight }; + rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; + rpr_framebuffer dummy_fb = nullptr; + ASSERT_EQ(rprContextCreateFrameBuffer(m_context, fmt, &desc, &dummy_fb), RPR_SUCCESS); + ASSERT_EQ(rprContextSetAOV(m_context, RPR_AOV_COLOR, dummy_fb), RPR_SUCCESS); + + CreateScene(SceneType::kOpacityPlanes); + AddEnvironmentLight("../Resources/Textures/studio015.hdr"); + + ASSERT_EQ(rprContextSetAOV(m_context, RPR_AOV_OPACITY, m_framebuffer), RPR_SUCCESS); + Render(); + SaveAndCompare(); +} + +TEST_F(AovTest, Aov_ObjectID) +{ + TestAovImplemented(RPR_AOV_OBJECT_ID); +} + +TEST_F(AovTest, Aov_ObjectGroupID) +{ + CreateScene(SceneType::kSphereAndPlane); + AddEnvironmentLight("../Resources/Textures/studio015.hdr"); + + ASSERT_EQ(rprContextSetAOV(m_context, RPR_AOV_OBJECT_GROUP_ID, m_framebuffer), RPR_SUCCESS); + const rpr_shape sphere = GetShape("sphere"); + ASSERT_EQ(rprShapeSetObjectGroupID(sphere, 0), RPR_SUCCESS); + const rpr_shape plane = GetShape("plane"); + ASSERT_EQ(rprShapeSetObjectGroupID(plane, 1), RPR_SUCCESS); + + Render(); + SaveAndCompare("1"); + + // Move sphere to group 1 + ASSERT_EQ(rprShapeSetObjectGroupID(sphere, 1), RPR_SUCCESS); + + Render(); + SaveAndCompare("2"); + +} + +TEST_F(AovTest, Aov_Background) +{ + TestAovImplemented(RPR_AOV_BACKGROUND); +} + +// Make sure that aovs below are not implemented +TEST_F(AovTest, Aov_MaterialIndex) +{ + TestAovNotImplemented(RPR_AOV_MATERIAL_IDX); +} + +TEST_F(AovTest, Aov_Depth) +{ + TestAovNotImplemented(RPR_AOV_DEPTH); +} + +TEST_F(AovTest, Aov_ShadowCatcher) +{ + TestAovNotImplemented(RPR_AOV_SHADOW_CATCHER); +} + +TEST_F(AovTest, Aov_Emission) +{ + TestAovNotImplemented(RPR_AOV_EMISSION); +} + +TEST_F(AovTest, Aov_Velocity) +{ + TestAovNotImplemented(RPR_AOV_VELOCITY); +} + +TEST_F(AovTest, Aov_DirectIllumination) +{ + TestAovNotImplemented(RPR_AOV_DIRECT_ILLUMINATION); +} + +TEST_F(AovTest, Aov_IndirectIllumination) +{ + TestAovNotImplemented(RPR_AOV_INDIRECT_ILLUMINATION); +} diff --git a/RprTest/arithmetic.h b/RprTest/arithmetic.h new file mode 100644 index 00000000..816c32e4 --- /dev/null +++ b/RprTest/arithmetic.h @@ -0,0 +1,271 @@ +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ + +#pragma once + +#include "basic.h" + +class ArithmeticTest : public BasicTest +{ +public: + virtual void SetUp() override + { + BasicTest::SetUp(); + CreateScene(SceneType::kSphereAndPlane); + AddEnvironmentLight("../Resources/Textures/studio015.hdr"); + } + + void TestBinaryOperationConstantMaps(rpr_material_node_type operation, float3 first_arg, float3 second_arg) + { + rpr_material_node arithmetic; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_ARITHMETIC, &arithmetic), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputU(arithmetic, "op", operation), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF(arithmetic, "color0", first_arg.x, first_arg.y, first_arg.z, first_arg.w), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF(arithmetic, "color1", second_arg.x, second_arg.y, second_arg.z, second_arg.w), RPR_SUCCESS); + AddMaterialNode("arithmetic", arithmetic); + + ASSERT_EQ(rprMaterialNodeSetInputN_ext(GetMaterial("sphere_mtl"), RPR_UBER_MATERIAL_DIFFUSE_COLOR, GetMaterial("arithmetic")), RPR_SUCCESS); + + Render(); + SaveAndCompare(); + } + + void TestUnaryOperationTextureMap(rpr_material_node_type operation) + { + rpr_material_node inputTexture; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_IMAGE_TEXTURE, &inputTexture), RPR_SUCCESS); + AddMaterialNode("tex", inputTexture); + ASSERT_EQ(rprMaterialNodeSetInputImageData(inputTexture, "data", FindImage("../Resources/Textures/test_albedo1.jpg")), RPR_SUCCESS); + + rpr_material_node arithmetic; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_ARITHMETIC, &arithmetic), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputU(arithmetic, "op", operation), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputN(arithmetic, "color0", inputTexture), RPR_SUCCESS); + AddMaterialNode("arithmetic", arithmetic); + + ASSERT_EQ(rprMaterialNodeSetInputN_ext(GetMaterial("sphere_mtl"), RPR_UBER_MATERIAL_DIFFUSE_COLOR, GetMaterial("arithmetic")), RPR_SUCCESS); + + Render(); + SaveAndCompare(); + } + + void TestBinaryOperationTextureMaps(rpr_material_node_type operation) + { + rpr_material_node texture_arg1; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_IMAGE_TEXTURE, &texture_arg1), RPR_SUCCESS); + AddMaterialNode("tex1", texture_arg1); + ASSERT_EQ(rprMaterialNodeSetInputImageData(texture_arg1, "data", FindImage("../Resources/Textures/test_albedo1.jpg")), RPR_SUCCESS); + + rpr_material_node texture_arg2; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_IMAGE_TEXTURE, &texture_arg2), RPR_SUCCESS); + AddMaterialNode("tex2", texture_arg2); + ASSERT_EQ(rprMaterialNodeSetInputImageData(texture_arg2, "data", FindImage("../Resources/Textures/test_albedo2.jpg")), RPR_SUCCESS); + + rpr_material_node arithmetic; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_ARITHMETIC, &arithmetic), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputU(arithmetic, "op", operation), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputN(arithmetic, "color0", texture_arg1), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputN(arithmetic, "color1", texture_arg2), RPR_SUCCESS); + AddMaterialNode("arithmetic", arithmetic); + + ASSERT_EQ(rprMaterialNodeSetInputN_ext(GetMaterial("sphere_mtl"), RPR_UBER_MATERIAL_DIFFUSE_COLOR, arithmetic), RPR_SUCCESS); + + Render(); + SaveAndCompare(); + } + +}; + +TEST_F(ArithmeticTest, Arithmetic_AddConst) +{ + TestBinaryOperationConstantMaps(RPR_MATERIAL_NODE_OP_ADD, float3(1.0f, 0.0f, 0.0f), float3(0.0f, 1.0f, 0.0f)); +} + +TEST_F(ArithmeticTest, Arithmetic_SubConst) +{ + TestBinaryOperationConstantMaps(RPR_MATERIAL_NODE_OP_SUB, float3(1.0f, 1.0f, 0.0f), float3(0.0f, 1.0f, 0.0f)); +} + +TEST_F(ArithmeticTest, Arithmetic_MulConst) +{ + TestBinaryOperationConstantMaps(RPR_MATERIAL_NODE_OP_MUL, float3(1.0f, 1.0f, 1.0f), float3(0.0f, 1.0f, 0.0f)); +} + +TEST_F(ArithmeticTest, Arithmetic_DivConst) +{ + TestBinaryOperationConstantMaps(RPR_MATERIAL_NODE_OP_DIV, float3(1.0f, 1.0f, 1.0f), float3(4.0f, 4.0f, 1.0f)); +} + +TEST_F(ArithmeticTest, Arithmetic_AddTextures) +{ + TestBinaryOperationTextureMaps(RPR_MATERIAL_NODE_OP_ADD); +} + +TEST_F(ArithmeticTest, Arithmetic_SubTextures) +{ + TestBinaryOperationTextureMaps(RPR_MATERIAL_NODE_OP_SUB); +} + +TEST_F(ArithmeticTest, Arithmetic_MulTextures) +{ + TestBinaryOperationTextureMaps(RPR_MATERIAL_NODE_OP_MUL); +} + +TEST_F(ArithmeticTest, Arithmetic_DivTextures) +{ + TestBinaryOperationTextureMaps(RPR_MATERIAL_NODE_OP_DIV); +} + +TEST_F(ArithmeticTest, Arithmetic_Sin) +{ + TestUnaryOperationTextureMap(RPR_MATERIAL_NODE_OP_SIN); +} + +TEST_F(ArithmeticTest, Arithmetic_Cos) +{ + TestUnaryOperationTextureMap(RPR_MATERIAL_NODE_OP_COS); +} + +TEST_F(ArithmeticTest, Arithmetic_Tan) +{ + TestUnaryOperationTextureMap(RPR_MATERIAL_NODE_OP_TAN); +} + +TEST_F(ArithmeticTest, Arithmetic_ASin) +{ + TestUnaryOperationTextureMap(RPR_MATERIAL_NODE_OP_ASIN); +} + +TEST_F(ArithmeticTest, Arithmetic_ACos) +{ + TestUnaryOperationTextureMap(RPR_MATERIAL_NODE_OP_ACOS); +} + +TEST_F(ArithmeticTest, Arithmetic_ATan) +{ + TestUnaryOperationTextureMap(RPR_MATERIAL_NODE_OP_ATAN); +} + +TEST_F(ArithmeticTest, Arithmetic_SelectX) +{ + TestUnaryOperationTextureMap(RPR_MATERIAL_NODE_OP_SELECT_X); +} + +TEST_F(ArithmeticTest, Arithmetic_SelectY) +{ + TestUnaryOperationTextureMap(RPR_MATERIAL_NODE_OP_SELECT_Y); +} + +TEST_F(ArithmeticTest, Arithmetic_SelectZ) +{ + TestUnaryOperationTextureMap(RPR_MATERIAL_NODE_OP_SELECT_Z); +} + +TEST_F(ArithmeticTest, Arithmetic_SelectW) +{ + TestUnaryOperationTextureMap(RPR_MATERIAL_NODE_OP_SELECT_W); +} + +TEST_F(ArithmeticTest, Arithmetic_Combine) +{ + TestBinaryOperationTextureMaps(RPR_MATERIAL_NODE_OP_COMBINE); +} + +TEST_F(ArithmeticTest, Arithmetic_Dot3) +{ + TestBinaryOperationTextureMaps(RPR_MATERIAL_NODE_OP_DOT3); +} + +TEST_F(ArithmeticTest, Arithmetic_Dot4) +{ + TestBinaryOperationTextureMaps(RPR_MATERIAL_NODE_OP_DOT4); +} + +TEST_F(ArithmeticTest, Arithmetic_Cross3) +{ + TestBinaryOperationTextureMaps(RPR_MATERIAL_NODE_OP_CROSS3); +} + +TEST_F(ArithmeticTest, Arithmetic_Length3) +{ + TestUnaryOperationTextureMap(RPR_MATERIAL_NODE_OP_LENGTH3); +} + +TEST_F(ArithmeticTest, Arithmetic_Normalize3) +{ + TestUnaryOperationTextureMap(RPR_MATERIAL_NODE_OP_NORMALIZE3); +} + +TEST_F(ArithmeticTest, Arithmetic_Pow) +{ + TestBinaryOperationTextureMaps(RPR_MATERIAL_NODE_OP_POW); +} + +TEST_F(ArithmeticTest, Arithmetic_AverageXYZ) +{ + TestBinaryOperationTextureMaps(RPR_MATERIAL_NODE_OP_AVERAGE_XYZ); +} + +TEST_F(ArithmeticTest, Arithmetic_Average) +{ + TestBinaryOperationTextureMaps(RPR_MATERIAL_NODE_OP_AVERAGE); +} + +TEST_F(ArithmeticTest, Arithmetic_Min) +{ + TestBinaryOperationTextureMaps(RPR_MATERIAL_NODE_OP_MIN); +} + +TEST_F(ArithmeticTest, Arithmetic_Max) +{ + TestBinaryOperationTextureMaps(RPR_MATERIAL_NODE_OP_MAX); +} + +TEST_F(ArithmeticTest, Arithmetic_Floor) +{ + TestUnaryOperationTextureMap(RPR_MATERIAL_NODE_OP_FLOOR); +} + +TEST_F(ArithmeticTest, Arithmetic_Mod) +{ + TestBinaryOperationTextureMaps(RPR_MATERIAL_NODE_OP_MOD); +} + +TEST_F(ArithmeticTest, Arithmetic_Abs) +{ + TestUnaryOperationTextureMap(RPR_MATERIAL_NODE_OP_ABS); +} + +TEST_F(ArithmeticTest, Arithmetic_ShuffleYZWX) +{ + TestUnaryOperationTextureMap(RPR_MATERIAL_NODE_OP_SHUFFLE_YZWX); +} + +TEST_F(ArithmeticTest, Arithmetic_ShuffleZWXY) +{ + TestUnaryOperationTextureMap(RPR_MATERIAL_NODE_OP_SHUFFLE_ZWXY); +} + +TEST_F(ArithmeticTest, Arithmetic_ShuffleWXYZ) +{ + TestUnaryOperationTextureMap(RPR_MATERIAL_NODE_OP_SHUFFLE_WXYZ); +} diff --git a/RprTest/basic.h b/RprTest/basic.h new file mode 100644 index 00000000..0d14f619 --- /dev/null +++ b/RprTest/basic.h @@ -0,0 +1,843 @@ +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ + +#pragma once + +#define _USE_MATH_DEFINES +#include + +#include "math/matrix.h" +#include "math/mathutils.h" + +#include "RadeonProRender.h" +#include "gtest/gtest.h" +#include "OpenImageIO/imageio.h" +#include "SceneGraph/scene_object.h" +#include "Controllers/scene_controller.h" +#include "SceneGraph/clwscene.h" + +#include +#include +#include +#include +#include +#include + +using namespace RadeonRays; + +extern int g_argc; +extern char** g_argv; + +class BasicTest : public ::testing::Test +{ +public: + static std::uint32_t constexpr kRenderIterations = 32; + static std::uint32_t constexpr kOutputWidth = 256; + static std::uint32_t constexpr kOutputHeight = 256; + + enum class SceneType + { + kSphereIbl = 0, + kSphereAndPlane, + kThreeSpheres, + kOpacityPlanes + }; + + virtual void SetUp() + { + char* generate_option = GetCmdOption(g_argv, g_argv + g_argc, "-genref"); + char* tolerance_option = GetCmdOption(g_argv, g_argv + g_argc, "-tolerance"); + char* refpath_option = GetCmdOption(g_argv, g_argv + g_argc, "-ref"); + char* outpath_option = GetCmdOption(g_argv, g_argv + g_argc, "-out"); + + m_generate = generate_option ? true : false; + m_tolerance = tolerance_option ? atoi(tolerance_option) : 20; + m_reference_path = refpath_option ? refpath_option : "ReferenceImages"; + m_output_path = outpath_option ? outpath_option : "OutputImages"; + m_reference_path.append("/"); + m_output_path.append("/"); + + Baikal::SceneObject::ResetId(); + Baikal::SceneController::ResetId(); + + rpr_creation_flags flags = GetCreationFlags(); + ASSERT_EQ(rprCreateContext(RPR_API_VERSION, nullptr, 0, flags, nullptr, nullptr, &m_context), RPR_SUCCESS); + + ASSERT_EQ(rprContextSetParameter1u(m_context, "randseed", 0u), RPR_SUCCESS); + + CreateFramebuffer(); + } + + rpr_creation_flags GetCreationFlags() const + { + char* device_index_option = GetCmdOption(g_argv, g_argv + g_argc, "-device"); + + if (!device_index_option) + { + // Use gpu0 by default + return RPR_CREATION_FLAGS_ENABLE_GPU0; + } + + static const std::vector kGpuFlags = + { + RPR_CREATION_FLAGS_ENABLE_GPU0, + RPR_CREATION_FLAGS_ENABLE_GPU1, + RPR_CREATION_FLAGS_ENABLE_GPU2, + RPR_CREATION_FLAGS_ENABLE_GPU3, + RPR_CREATION_FLAGS_ENABLE_GPU4, + RPR_CREATION_FLAGS_ENABLE_GPU5, + RPR_CREATION_FLAGS_ENABLE_GPU6, + RPR_CREATION_FLAGS_ENABLE_GPU7 + }; + + for (std::size_t i = 0; i < kGpuFlags.size(); ++i) + { + if (std::string(device_index_option + 3) == std::to_string(i)) + { + return kGpuFlags[i]; + } + } + + if (strcmp(device_index_option, "cpu") == 0) + { + return RPR_CREATION_FLAGS_ENABLE_CPU; + } + + // Use gpu0 by default + return RPR_CREATION_FLAGS_ENABLE_GPU0; + } + + virtual void TearDown() + { + // Cleanup + for (const rpr_light light : m_lights) + { + if (light == nullptr) continue; + ASSERT_EQ(rprSceneDetachLight(m_scene, light), RPR_SUCCESS); + ASSERT_EQ(rprObjectDelete(light), RPR_SUCCESS); + } + m_lights.clear(); + + for (auto it = m_shapes.cbegin(); it != m_shapes.cend(); ++it) + { + if (it->second == nullptr) continue; + ASSERT_EQ(rprShapeSetMaterial(it->second, nullptr), RPR_SUCCESS); + ASSERT_EQ(rprSceneDetachShape(m_scene, it->second), RPR_SUCCESS); + ASSERT_EQ(rprObjectDelete(it->second), RPR_SUCCESS); + } + m_shapes.clear(); + + for (auto it = m_material_nodes.cbegin(); it != m_material_nodes.cend(); ++it) + { + if (it->second == nullptr) continue; + ASSERT_EQ(rprObjectDelete(it->second), RPR_SUCCESS); + } + m_material_nodes.clear(); + + for (auto it = m_images.cbegin(); it != m_images.cend(); ++it) + { + if (it->second == nullptr) continue; + ASSERT_EQ(rprObjectDelete(it->second), RPR_SUCCESS); + } + m_images.clear(); + + if (m_camera) + { + ASSERT_NE(m_scene, nullptr); + ASSERT_EQ(rprSceneSetCamera(m_scene, nullptr), RPR_SUCCESS); + ASSERT_EQ(rprObjectDelete(m_camera), RPR_SUCCESS); + m_camera = nullptr; + } + + if (m_scene) + { + ASSERT_EQ(rprObjectDelete(m_scene), RPR_SUCCESS); + m_scene = nullptr; + } + + if (m_framebuffer) + { + ASSERT_EQ(rprObjectDelete(m_framebuffer), RPR_SUCCESS); + m_framebuffer = nullptr; + } + + if (m_context) + { + ASSERT_EQ(rprObjectDelete(m_context), RPR_SUCCESS); + m_context = nullptr; + } + } + + virtual void CreateFramebuffer() + { + rpr_framebuffer_desc desc = { kOutputWidth, kOutputHeight }; + rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; + ASSERT_EQ(rprContextCreateFrameBuffer(m_context, fmt, &desc, &m_framebuffer), RPR_SUCCESS); + // Set color output + ASSERT_EQ(rprContextSetAOV(m_context, RPR_AOV_COLOR, m_framebuffer), RPR_SUCCESS); + } + + void ClearFramebuffer() const + { + ASSERT_EQ(rprFrameBufferClear(m_framebuffer), RPR_SUCCESS); + } + + // + // Lights + // + void AddLight(const rpr_light light) + { + ASSERT_NE(light, nullptr); + ASSERT_EQ(rprSceneAttachLight(m_scene, light), RPR_SUCCESS); + m_lights.push_back(light); + } + + void AddEnvironmentLight(std::string const& path) + { + rpr_light light = nullptr; + ASSERT_EQ(rprContextCreateEnvironmentLight(m_context, &light), RPR_SUCCESS); + const rpr_image image = FindImage(path); + ASSERT_EQ(rprEnvironmentLightSetImage(light, image), RPR_SUCCESS); + AddLight(light); + } + + void RemoveLight(size_t index) + { + ASSERT_TRUE(index >= 0 && index < m_lights.size()); + const rpr_light light = m_lights[index]; + ASSERT_NO_THROW(m_lights.erase(m_lights.begin() + index)); + + ASSERT_EQ(rprSceneDetachLight(m_scene, light), RPR_SUCCESS); + ASSERT_EQ(rprObjectDelete(light), RPR_SUCCESS); + } + + // + // Images + // + void AddImage(std::string const& path, rpr_image* image) + { + ASSERT_EQ(rprContextCreateImageFromFile(m_context, path.c_str(), image), RPR_SUCCESS); + m_images[path] = *image; + } + + rpr_image FindImage(std::string const& path) + { + auto img_it = m_images.find(path); + if (img_it == m_images.end()) + { + rpr_image image = nullptr; + AddImage(path, &image); + return image; + } + else + { + return img_it->second; + } + } + + // + // Materials + // + void AddMaterialNode(std::string const& name, const rpr_material_node material) + { + m_material_nodes[name] = material; + } + + rpr_material_node GetMaterial(std::string const& name) const + { + auto mtl_it = m_material_nodes.find(name); + // Cannot use ASSERT_NE in non-void returning function in GTest + assert(mtl_it != m_material_nodes.end()); + return mtl_it->second; + } + + void AddDiffuseMaterial(std::string const& name, float3 color) + { + rpr_material_node material = nullptr; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_UBERV2, &material), RPR_SUCCESS); + + ASSERT_EQ(rprMaterialNodeSetInputU_ext(material, RPR_UBER_MATERIAL_LAYERS, RPR_UBER_MATERIAL_LAYER_DIFFUSE), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_DIFFUSE_COLOR, color.x, color.y, color.z, 0.0f), RPR_SUCCESS); + + AddMaterialNode(name, material); + } + + void AddSpecularMaterial(std::string const& name, float3 color, float roughness) + { + rpr_material_node material = nullptr; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_UBERV2, &material), RPR_SUCCESS); + + ASSERT_EQ(rprMaterialNodeSetInputU_ext(material, RPR_UBER_MATERIAL_LAYERS, RPR_UBER_MATERIAL_LAYER_REFLECTION), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_REFLECTION_COLOR, color.x, color.y, color.z, 0.0f), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_REFLECTION_IOR, 2.0f, 2.0f, 2.0f, 2.0f), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_REFLECTION_ROUGHNESS, roughness, roughness, roughness, 0.0f), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_REFLECTION_METALNESS, 0.0f, 0.0f, 0.0f, 0.0f), RPR_SUCCESS); + + AddMaterialNode(name, material); + } + + void AddRefractionMaterial(std::string const& name, float3 color, float roughness) + { + rpr_material_node material = nullptr; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_UBERV2, &material), RPR_SUCCESS); + + ASSERT_EQ(rprMaterialNodeSetInputU_ext(material, RPR_UBER_MATERIAL_LAYERS, RPR_UBER_MATERIAL_LAYER_REFRACTION), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_REFRACTION_COLOR, color.x, color.y, color.z, 0.0f), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_REFRACTION_IOR, 2.0f, 2.0f, 2.0f, 2.0f), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_REFRACTION_ROUGHNESS, roughness, roughness, roughness, 0.0f), RPR_SUCCESS); + + AddMaterialNode(name, material); + } + + void AddTransparentMaterial(std::string const& name, float3 transparency) + { + rpr_material_node material = nullptr; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_UBERV2, &material), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputU_ext(material, RPR_UBER_MATERIAL_LAYERS, RPR_UBER_MATERIAL_LAYER_DIFFUSE | RPR_UBER_MATERIAL_LAYER_TRANSPARENCY), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_DIFFUSE_COLOR, 1.0f, 0.0f, 0.0f, 0.0f), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_TRANSPARENCY, transparency.x, transparency.y, transparency.z, 0.0f), RPR_SUCCESS); + + AddMaterialNode(name, material); + } + + void AddEmissiveMaterial(std::string const& name, float3 color) + { + rpr_material_node material = nullptr; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_UBERV2, &material), RPR_SUCCESS); + + ASSERT_EQ(rprMaterialNodeSetInputU_ext(material, RPR_UBER_MATERIAL_LAYERS, RPR_UBER_MATERIAL_LAYER_EMISSION), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_EMISSION_COLOR, color.x, color.y, color.z, 0.0f), RPR_SUCCESS); + + AddMaterialNode(name, material); + } + + void AddCoatMaterial(std::string const& name, float3 diffuse_color, float3 coat_color) + { + rpr_material_node material = nullptr; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_UBERV2, &material), RPR_SUCCESS); + + ASSERT_EQ(rprMaterialNodeSetInputU_ext(material, RPR_UBER_MATERIAL_LAYERS, RPR_UBER_MATERIAL_LAYER_DIFFUSE | RPR_UBER_MATERIAL_LAYER_COATING), RPR_SUCCESS); + + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_DIFFUSE_COLOR, diffuse_color.x, diffuse_color.y, diffuse_color.z, 0.0f), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_COATING_COLOR, coat_color.x, coat_color.y, coat_color.z, 0.0f), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_COATING_IOR, 2.0f, 2.0f, 2.0f, 2.0f), RPR_SUCCESS); + + AddMaterialNode(name, material); + } + + void AddMetalMaterial(std::string const& name, float3 diffuse_color, float3 reflection_color) + { + rpr_material_node material = nullptr; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_UBERV2, &material), RPR_SUCCESS); + + ASSERT_EQ(rprMaterialNodeSetInputU_ext(material, RPR_UBER_MATERIAL_LAYERS, RPR_UBER_MATERIAL_LAYER_DIFFUSE | RPR_UBER_MATERIAL_LAYER_REFLECTION), RPR_SUCCESS); + + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_DIFFUSE_COLOR, diffuse_color.x, diffuse_color.y, diffuse_color.z, 0.0f), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_REFLECTION_COLOR, reflection_color.x, reflection_color.y, reflection_color.z, 0.0f), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_REFLECTION_METALNESS, 1.0f, 1.0f, 1.0f, 1.0f), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_REFLECTION_ROUGHNESS, 0.0f, 0.0f, 0.0f, 0.0f), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(material, RPR_UBER_MATERIAL_REFLECTION_IOR, 2.0f, 0.0f, 0.0f, 0.0f), RPR_SUCCESS); + } + + void ApplyMaterialToObject(std::string const& shape_name, std::string const& mtl_name) const + { + auto shapes_it = m_shapes.find(shape_name); + ASSERT_NE(shapes_it, m_shapes.end()); + const rpr_shape shape = shapes_it->second; + + auto mtl_it = m_material_nodes.find(mtl_name); + ASSERT_NE(mtl_it, m_material_nodes.end()); + const rpr_material_node material = mtl_it->second; + + ASSERT_EQ(rprShapeSetMaterial(shape, material), RPR_SUCCESS); + } + + // + // Shapes + // + void AddShape(std::string const& name, const rpr_shape shape) + { + ASSERT_EQ(rprSceneAttachShape(m_scene, shape), RPR_SUCCESS); + m_shapes[name] = shape; + } + + rpr_shape GetShape(std::string const& name) const + { + auto shape_it = m_shapes.find(name); + // Cannot use ASSERT_NE in non-void returning function in GTest + assert(shape_it != m_shapes.end()); + return shape_it->second; + } + + void AddSphere(std::string const& name, std::uint32_t lat, std::uint32_t lon, float r, RadeonRays::float3 const& c) + { + size_t num_verts = (lat - 2) * lon + 2; + size_t num_tris = (lat - 2) * (lon - 1) * 2; + + std::vector vertices(num_verts); + std::vector normals(num_verts); + std::vector uvs(num_verts); + std::vector indices(num_tris * 3); + + auto t = 0U; + for (auto j = 1U; j < lat - 1; j++) + { + for (auto i = 0U; i < lon; i++) + { + float theta = float(j) / (lat - 1) * (float)M_PI; + float phi = float(i) / (lon - 1) * (float)M_PI * 2; + vertices[t].x = r * sinf(theta) * cosf(phi) + c.x; + vertices[t].y = r * cosf(theta) + c.y; + vertices[t].z = r * -sinf(theta) * sinf(phi) + c.z; + normals[t].x = sinf(theta) * cosf(phi); + normals[t].y = cosf(theta); + normals[t].z = -sinf(theta) * sinf(phi); + uvs[t].x = phi / (2 * (float)M_PI); + uvs[t].y = theta / ((float)M_PI); + ++t; + } + } + + vertices[t].x = c.x; vertices[t].y = c.y + r; vertices[t].z = c.z; + normals[t].x = 0; normals[t].y = 1; normals[t].z = 0; + uvs[t].x = 0; uvs[t].y = 0; + ++t; + vertices[t].x = c.x; vertices[t].y = c.y - r; vertices[t].z = c.z; + normals[t].x = 0; normals[t].y = -1; normals[t].z = 0; + uvs[t].x = 1; uvs[t].y = 1; + ++t; + + t = 0U; + for (auto j = 0U; j < lat - 3; j++) + { + for (auto i = 0U; i < lon - 1; i++) + { + indices[t++] = j * lon + i; + indices[t++] = (j + 1) * lon + i + 1; + indices[t++] = j * lon + i + 1; + indices[t++] = j * lon + i; + indices[t++] = (j + 1) * lon + i; + indices[t++] = (j + 1) * lon + i + 1; + } + } + + for (auto i = 0U; i < lon - 1; i++) + { + indices[t++] = (lat - 2) * lon; + indices[t++] = i; + indices[t++] = i + 1; + indices[t++] = (lat - 2) * lon + 1; + indices[t++] = (lat - 3) * lon + i + 1; + indices[t++] = (lat - 3) * lon + i; + } + + std::vector faces(indices.size() / 3, 3); + + rpr_shape sphere = nullptr; + ASSERT_EQ(rprContextCreateMesh(m_context, + (rpr_float const*)vertices.data(), vertices.size(), sizeof(RadeonRays::float3), + (rpr_float const*)normals.data(), normals.size(), sizeof(RadeonRays::float3), + (rpr_float const*)uvs.data(), uvs.size(), sizeof(RadeonRays::float2), + (rpr_int const*)indices.data(), sizeof(rpr_int), + (rpr_int const*)indices.data(), sizeof(rpr_int), + (rpr_int const*)indices.data(), sizeof(rpr_int), + faces.data(), faces.size(), &sphere), RPR_SUCCESS); + + AddShape(name, sphere); + + } + + void AddPlane(std::string const& name, float3 center, float2 size, float3 normal) + { + struct Vertex + { + float3 position; + float3 normal; + float2 uv; + }; + + float3 n = normalize(normal); + float3 axis = fabs(n.x) > 0.001f ? float3(0.0f, 1.0f, 0.0f) : float3(1.0f, 0.0f, 0.0f); + float3 t = normalize(cross(axis, n)); + float3 s = cross(n, t); + + Vertex vertices[4] = + { + { { -s * size.x - t * size.y + center }, n, { 0.0f, 0.0f } }, + { { s * size.x - t * size.y + center }, n, { 1.0f, 0.0f } }, + { { s * size.x + t * size.y + center }, n, { 1.0f, 1.0f } }, + { { -s * size.x + t * size.y + center }, n, { 0.0f, 1.0f } } + }; + + rpr_int indices[] = + { + 3, 1, 0, + 2, 1, 3 + }; + + rpr_int num_face_vertices[] = + { + 3, 3 + }; + + rpr_shape quad = nullptr; + + ASSERT_EQ(rprContextCreateMesh(m_context, + (rpr_float const*)&vertices[0], 4, sizeof(Vertex), + (rpr_float const*)((char*)&vertices[0] + sizeof(float3)), 4, sizeof(Vertex), + (rpr_float const*)((char*)&vertices[0] + sizeof(float3) * 2), 4, sizeof(Vertex), + (rpr_int const*)indices, sizeof(rpr_int), + (rpr_int const*)indices, sizeof(rpr_int), + (rpr_int const*)indices, sizeof(rpr_int), + num_face_vertices, 2, &quad), RPR_SUCCESS); + + AddShape(name, quad); + + } + + void CreateCamera() + { + // Make sure we've created the context and the scene + ASSERT_NE(m_context, nullptr); + ASSERT_NE(m_scene, nullptr); + + // Create camera + ASSERT_EQ(rprContextCreateCamera(m_context, &m_camera), RPR_SUCCESS); + + ASSERT_EQ(rprCameraSetMode(m_camera, RPR_CAMERA_MODE_PERSPECTIVE), RPR_SUCCESS); + // Set default sensor size 36x36 mm because we're rendering to square viewport + ASSERT_EQ(rprCameraSetSensorSize(m_camera, 36.0f, 36.0f), RPR_SUCCESS); + + ASSERT_EQ(rprSceneSetCamera(m_scene, m_camera), RPR_SUCCESS); + } + + void CreateScene(SceneType type) + { + // Create scene and material system + ASSERT_EQ(rprContextCreateMaterialSystem(m_context, 0, &m_matsys), RPR_SUCCESS); + ASSERT_EQ(rprContextCreateScene(m_context, &m_scene), RPR_SUCCESS); + ASSERT_EQ(rprContextSetScene(m_context, m_scene), RPR_SUCCESS); + + // Create camera + CreateCamera(); + + // Add objects, materials and lights + switch (type) + { + case SceneType::kSphereIbl: + ASSERT_EQ(rprCameraLookAt(m_camera, 0.0f, 0.0f, -10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f), RPR_SUCCESS); + AddSphere("sphere", 64, 32, 2.0f, float3(0.0f, 0.0f, 0.0f)); + AddDiffuseMaterial("sphere_mtl", float3(0.8f, 0.8f, 0.8f)); + ApplyMaterialToObject("sphere", "sphere_mtl"); + AddEnvironmentLight("../Resources/Textures/studio015.hdr"); + break; + case SceneType::kSphereAndPlane: + ASSERT_EQ(rprCameraLookAt(m_camera, 0.0f, 2.0f, -10.0f, 0.0f, 2.0f, 0.0f, 0.0f, 1.0f, 0.0f), RPR_SUCCESS); + AddSphere("sphere", 64, 32, 2.0f, float3(0.0f, 0.0f, 0.0f)); + AddDiffuseMaterial("sphere_mtl", float3(0.8f, 0.8f, 0.8f)); + ApplyMaterialToObject("sphere", "sphere_mtl"); + AddPlane("plane", float3(0.0f, -2.0f, 0.0f), float2(8.0f, 8.0f), float3(0.0f, 1.0f, 0.0f)); + AddDiffuseMaterial("plane_mtl", float3(0.8f, 0.8f, 0.8f)); + ApplyMaterialToObject("plane", "plane_mtl"); + break; + case SceneType::kThreeSpheres: + ASSERT_EQ(rprCameraLookAt(m_camera, 0.0f, 2.0f, -10.0f, 0.0f, 2.0f, 0.0f, 0.0f, 1.0f, 0.0f), RPR_SUCCESS); + + AddPlane("plane", float3(0.0f, -2.0f, 0.0f), float2(8.0f, 8.0f), float3(0.0f, 1.0f, 0.0f)); + AddDiffuseMaterial("plane_mtl", float3(0.8f, 0.8f, 0.8f)); + ApplyMaterialToObject("plane", "plane_mtl"); + + AddSphere("sphere_specular", 64, 32, 2.f, float3(4.0f, 0.0f, 0.0f)); + AddSpecularMaterial("specular_mtl", float3(1.0f, 1.0f, 1.0f), 0.001f); + ApplyMaterialToObject("sphere_specular", "specular_mtl"); + + AddSphere("sphere_refract", 64, 32, 2.f, float3(0.0f, 0.0f, 0.0f)); + AddRefractionMaterial("refractive_mtl", float3(1.0f, 1.0f, 1.0f), 0.001f); + ApplyMaterialToObject("sphere_refract", "refractive_mtl"); + + AddSphere("sphere_transparent", 64, 32, 2.f, float3(-4.0f, 0.0f, 0.0f)); + AddTransparentMaterial("transparent_mtl", float3(0.8f, 0.8f, 0.8f)); + ApplyMaterialToObject("sphere_transparent", "transparent_mtl"); + break; + case SceneType::kOpacityPlanes: + ASSERT_EQ(rprCameraLookAt(m_camera, 0.0f, 2.0f, -10.0f, 0.0f, 2.0f, 0.0f, 0.0f, 1.0f, 0.0f), RPR_SUCCESS); + + AddDiffuseMaterial("floor_mtl", float3(0.8f, 0.8f, 0.8f)); + AddPlane("floor", float3(0.0f, -2.0f, 0.0f), float2(8.0f, 8.0f), float3(0.0f, 1.0f, 0.0f)); + ApplyMaterialToObject("floor", "floor_mtl"); + + AddTransparentMaterial("transparent_mtl", 0.9f); + for (std::size_t i = 0; i < 8; ++i) + { + AddPlane("plane" + std::to_string(i), float3(0.0f, 0.0f, i * 0.5f), float2(4.0f - i * 0.5f, 4.0f - i * 0.5f), float3(0.0f, 0.0f, -1.0f)); + ApplyMaterialToObject("plane" + std::to_string(i), "transparent_mtl"); + } + break; + } + } + + void Render(std::uint32_t num_iterations = kRenderIterations) const + { + ClearFramebuffer(); + for (std::uint32_t i = 0; i < num_iterations; ++i) + { + ASSERT_EQ(rprContextRender(m_context), RPR_SUCCESS); + } + } + + void LoadImage(std::string const& file_name, std::vector& data) const + { + OIIO_NAMESPACE_USING + + ImageInput* input = ImageInput::open(file_name); + + ImageSpec const& spec = input->spec(); + + auto size = spec.width * spec.height * spec.depth * 4; + + data.resize(size); + + // Read data to storage + input->read_image(TypeDesc::UINT8, &data[0], sizeof(char) * 4); + + // Close handle + input->close(); + + delete input; + } + + bool CompareToReference(std::string const& file_name) const + { + if (m_generate) + return true; + + std::string path_to_output = m_output_path; + path_to_output.append(file_name); + std::string path_to_reference = m_reference_path; + path_to_reference.append(file_name); + + std::vector output_data; + std::vector reference_data; + + LoadImage(path_to_output, output_data); + LoadImage(path_to_reference, reference_data); + + auto num_values = output_data.size(); + auto difference = 0u; + for (auto i = 0u; i < num_values; ++i) + { + if (output_data[i] != reference_data[i]) + { + ++difference; + } + } + + return difference <= m_tolerance; + } + + void SaveOutput(std::string const& file_name) const + { + std::string path = m_generate ? m_reference_path : m_output_path; + path.append(file_name); + + ASSERT_EQ(rprFrameBufferSaveToFile(m_framebuffer, path.c_str()), RPR_SUCCESS); + } + + std::string TestName() const + { + return ::testing::UnitTest::GetInstance()->current_test_info()->name(); + } + + // Save to file and compare to reference + void SaveAndCompare() const + { + std::ostringstream oss; + oss << TestName() << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + + // Use formatting in filename + void SaveAndCompare(char const* const format, ...) const + { + char buffer[128]; + va_list args; + va_start(args, format); + vsnprintf(buffer, 128, format, args); + va_end(args); + std::ostringstream oss; + oss << TestName() << "_" << buffer << ".png"; + SaveOutput(oss.str()); + ASSERT_TRUE(CompareToReference(oss.str())); + } + + static char* GetCmdOption(char** begin, char** end, const std::string& option) + { + char** itr = std::find(begin, end, option); + if (itr != end && ++itr != end) + { + return *itr; + } + return 0; + } + +protected: + rpr_context m_context = nullptr; + rpr_material_system m_matsys = nullptr; + rpr_scene m_scene = nullptr; + rpr_camera m_camera = nullptr; + rpr_framebuffer m_framebuffer = nullptr; + + std::map m_shapes; + std::map m_material_nodes; + std::map m_images; + std::vector m_lights; + + std::string m_reference_path; + std::string m_output_path; + + bool m_generate; + std::uint32_t m_tolerance; + +}; + +// Memstat test +TEST_F(BasicTest, Basic_MemoryStatistics) +{ + rpr_render_statistics rs; + rs.gpumem_usage = 0; + rs.gpumem_total = 0; + rs.gpumem_max_allocation = 0; + + //create context and check there is no used resources + ASSERT_EQ(rprContextGetInfo(m_context, RPR_CONTEXT_RENDER_STATISTICS, sizeof(rpr_render_statistics), &rs, NULL), RPR_SUCCESS); + + ASSERT_EQ(rs.gpumem_usage, 0); + ASSERT_EQ(rs.gpumem_total, 0); + ASSERT_EQ(rs.gpumem_max_allocation, 0); + +} + +// Tiled render test +TEST_F(BasicTest, Basic_TiledRender) +{ + CreateScene(SceneType::kSphereAndPlane); + AddEnvironmentLight("../Resources/Textures/studio015.hdr"); + + ClearFramebuffer(); + for (std::size_t i = 0; i < kRenderIterations; ++i) + { + ASSERT_EQ(rprContextRenderTile(m_context, 0, 128, 0, 128), RPR_SUCCESS); + } + + SaveAndCompare(); + +} +// Add instancing test +// Instancing doesn't work on osx +#ifndef __APPLE__ +TEST_F(BasicTest, Basic_Instancing) +{ + CreateScene(SceneType::kSphereAndPlane); + AddEnvironmentLight("../Resources/Textures/studio015.hdr"); + + const rpr_shape sphere = GetShape("sphere"); + const rpr_material_node sphere_mtl = GetMaterial("sphere_mtl"); + rpr_shape instance = nullptr; + for (int i = 0; i < 16; ++i) + { + ASSERT_EQ(rprContextCreateInstance(m_context, sphere, &instance), RPR_SUCCESS); + + float x = i / 4 - 1.5f; + float y = i % 4 + 1.0f; + float z = 2.0f; + float s = rand_float() * 0.5f + 0.1f; + matrix m = translation(float3(x, y, z) * 2.0f) * scale(float3(s, s, s)); + ASSERT_EQ(rprShapeSetTransform(instance, true, &m.m00), RPR_SUCCESS); + AddShape("instance" + std::to_string(i), instance); + ASSERT_EQ(rprShapeSetMaterial(instance, sphere_mtl), RPR_SUCCESS); + } + + Render(); + SaveAndCompare(); + +} +#endif +//test RPR_MATERIAL_NODE_INPUT_LOOKUP and rprContextCreateMeshEx unsupported +TEST_F(BasicTest, Basic_MultiUV) +{ + rpr_material_node uv_node = nullptr; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_INPUT_LOOKUP, &uv_node), RPR_ERROR_INVALID_PARAMETER); + + struct VertexMT + { + rpr_float pos[3]; + rpr_float norm[3]; + rpr_float tex0[2]; + rpr_float tex1[2]; + }; + + VertexMT vertices[] = + { + {{-2.0f, 2.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f}}, + {{ 2.0f, 2.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}}, + {{ 2.0f, -2.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}}, + {{-2.0f, -2.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}} + }; + + rpr_int indices[] = + { + 3, 2, 1, 0 + }; + + rpr_int num_face_vertices[] = + { + 4 + }; + + unsigned int num_vertices = sizeof(vertices) / sizeof(vertices[0]); + unsigned int num_faces = sizeof(num_face_vertices) / sizeof(num_face_vertices[0]); + + rpr_float const* texcoords[] = { (rpr_float const*)((char*)&vertices[0] + sizeof(rpr_float) * 6), (rpr_float const*)((char*)&vertices[0] + sizeof(rpr_float) * 8) }; + size_t num_texcoords[] = { num_vertices, num_vertices }; + rpr_int texcoord_stride[] = { sizeof(VertexMT), sizeof(VertexMT) }; + rpr_int const* texcoord_indices[] = { indices, indices }; + rpr_int tidx_stride[] = { sizeof(rpr_int), sizeof(rpr_int) }; + + rpr_shape mesh = nullptr; + ASSERT_EQ(rprContextCreateMeshEx(m_context, + // Vertices + (rpr_float const*)&vertices[0], num_vertices, sizeof(VertexMT), + // Normals + (rpr_float const*)((char*)&vertices[0] + sizeof(rpr_float) * 3), num_faces, sizeof(VertexMT), + // Vertex flags + nullptr, 0, 0, + // Texcoords + 2, texcoords, num_texcoords, texcoord_stride, + // Vertex indices + indices, sizeof(rpr_int), + // Normal indices + indices, sizeof(rpr_int), + // Texcoord indices + texcoord_indices, tidx_stride, + num_face_vertices, num_faces, &mesh), RPR_ERROR_UNIMPLEMENTED); +} diff --git a/RprTest/cache/placeholder.txt b/RprTest/cache/placeholder.txt new file mode 100644 index 00000000..455f0d98 --- /dev/null +++ b/RprTest/cache/placeholder.txt @@ -0,0 +1 @@ +placeholder for kernel cache \ No newline at end of file diff --git a/RprTest/camera.h b/RprTest/camera.h new file mode 100644 index 00000000..a2448055 --- /dev/null +++ b/RprTest/camera.h @@ -0,0 +1,103 @@ +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ + +#pragma once + +#include "basic.h" + +class CameraTest : public BasicTest +{ +public: + virtual void SetUp() override + { + BasicTest::SetUp(); + CreateScene(SceneType::kSphereIbl); + } + +}; + +TEST_F(CameraTest, Camera_FocalLength) +{ + std::vector values = { 0.014f, 0.035f, 0.05f, 0.085f, 0.135f }; + + for (auto v : values) + { + ASSERT_EQ(rprCameraSetFocalLength(m_camera, v * 1000.0f), RPR_SUCCESS); + Render(); + SaveAndCompare("%.3f", v); + } +} + +TEST_F(CameraTest, Camera_SensorSize) +{ + std::vector> values = + { + { 0.0167f, 0.0251f }, // APS-C + { 0.024f, 0.036f }, // Full frame + { 0.036f, 0.036f } // Mid frame + }; + + for (auto v : values) + { + ASSERT_EQ(rprCameraSetSensorSize(m_camera, v.first * 1000.0f, v.second * 1000.0f), RPR_SUCCESS); + Render(); + SaveAndCompare("%.3f_%.3f", v.first, v.second); + } +} + +TEST_F(CameraTest, Camera_Aperture) +{ + std::vector values = { 0.1f, 0.01f, 0.05f, 0.025f }; + + ASSERT_EQ(rprCameraSetFocusDistance(m_camera, 6.0f), RPR_SUCCESS); + + for (auto v : values) + { + ASSERT_EQ(rprCameraSetFStop(m_camera, v * 1000.0f), RPR_SUCCESS); + Render(); + SaveAndCompare("%.3f", v); + } +} + +TEST_F(CameraTest, Camera_FocusDistance) +{ + std::vector values = { 1.f, 3.f, 6.f, 9.f }; + + ASSERT_EQ(rprCameraSetFStop(m_camera, 0.15f * 1000.0f), RPR_SUCCESS); + + for (auto v : values) + { + ASSERT_EQ(rprCameraSetFocusDistance(m_camera, v), RPR_SUCCESS); + Render(); + SaveAndCompare("%.3f", v); + } +} + +TEST_F(CameraTest, Camera_Ortho) +{ + ASSERT_EQ(rprCameraSetMode(m_camera, RPR_CAMERA_MODE_ORTHOGRAPHIC), RPR_SUCCESS); + ASSERT_EQ(rprCameraSetOrthoWidth(m_camera, 5.0f), RPR_SUCCESS); + ASSERT_EQ(rprCameraSetOrthoHeight(m_camera, 5.0f), RPR_SUCCESS); + + Render(); + SaveAndCompare(); +} diff --git a/RprTest/light.h b/RprTest/light.h new file mode 100644 index 00000000..5238b907 --- /dev/null +++ b/RprTest/light.h @@ -0,0 +1,378 @@ +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ + +#pragma once + +#include "basic.h" + +class LightTest : public BasicTest +{ +public: + virtual void SetUp() override + { + BasicTest::SetUp(); + CreateScene(SceneType::kSphereAndPlane); + } + + void AddPointLight(float3 pos, float3 color) + { + rpr_light light = nullptr; + ASSERT_EQ(rprContextCreatePointLight(m_context, &light), RPR_SUCCESS); + matrix lightm = translation(pos); + ASSERT_EQ(rprLightSetTransform(light, true, &lightm.m00), RPR_SUCCESS); + ASSERT_EQ(rprPointLightSetRadiantPower3f(light, color.x, color.y, color.z), RPR_SUCCESS); + AddLight(light); + + } + + void AddDirectionalLight(float yaw, float pitch, float3 color) + { + rpr_light light = nullptr; + ASSERT_EQ(rprContextCreateDirectionalLight(m_context, &light), RPR_SUCCESS); + matrix lightm = rotation_x(pitch) * rotation_y(yaw); + ASSERT_EQ(rprLightSetTransform(light, false, &lightm.m00), RPR_SUCCESS); + ASSERT_EQ(rprDirectionalLightSetRadiantPower3f(light, color.x, color.y, color.z), RPR_SUCCESS); + AddLight(light); + } + + void AddSpotLight(float3 pos, float yaw, float pitch, float3 color, float iangle, float oangle) + { + rpr_light light = nullptr; + ASSERT_EQ(rprContextCreateSpotLight(m_context, &light), RPR_SUCCESS); + matrix lightm = translation(pos) * rotation_x(pitch) * rotation_y(yaw); + ASSERT_EQ(rprLightSetTransform(light, true, &lightm.m00), RPR_SUCCESS); + ASSERT_EQ(rprSpotLightSetRadiantPower3f(light, color.x, color.y, color.z), RPR_SUCCESS); + ASSERT_EQ(rprSpotLightSetConeShape(light, iangle, oangle), RPR_SUCCESS); + AddLight(light); + } + + void AddAreaLight() + { + AddEmissiveMaterial("emission", float3(5.0f, 0.0f, 0.0f)); + AddPlane("plane1", float3(0.0f, 6.0f, 0.0f), float2(2.0f, 2.0f), float3(0, -1.0f, 0.0f)); + ApplyMaterialToObject("plane1", "emission"); + } + +}; + +TEST_F(LightTest, Light_PointLight) +{ + std::vector positions + { + float3( 3.0f, 6.0f, 0.0f), + float3(-2.0f, 6.0f, -1.0f), + float3( 0.0f, 6.0f, -3.0f) + }; + + std::vector colors + { + float3(3.0f, 0.1f, 0.1f), + float3(0.1f, 3.0f, 0.1f), + float3(0.1f, 0.1f, 3.0f) + }; + + for (size_t i = 0; i < 3; ++i) + { + AddPointLight(positions[i], colors[i] * 10.0f); + } + + Render(); + SaveAndCompare("1"); + + RemoveLight(0); + Render(); + SaveAndCompare("2"); + +} + +TEST_F(LightTest, Light_PointLightMany) +{ + const size_t num_lights = 16; + const float step = (float)(2.f * M_PI / num_lights); + + for (size_t i = 0; i < num_lights; ++i) + { + float x = 5.0f * std::cos(i * step); + float y = 5.0f; + float z = 5.0f * std::sin(i * step); + float f = (float)i / num_lights; + float3 color = f * float3(1.f, 0.f, 0.f) + (1.f - f) * float3(0.f, 1.f, 0.f); + + AddPointLight(float3(x, y, z), color * 10.0f); + } + + Render(); + SaveAndCompare(); +} + +TEST_F(LightTest, Light_DirectionalLight) +{ + std::vector> directions + { + { 0.0f, (float)M_PI / 3.0f }, + { (float)M_PI / 3.0f * 2.0f, (float)M_PI / 4.0f }, + { (float)M_PI / 3.0f * 4.0f, (float)M_PI / 6.0f } + }; + + std::vector colors + { + float3(3.0f, 0.1f, 0.1f), + float3(0.1f, 3.0f, 0.1f), + float3(0.1f, 0.1f, 3.0f) + }; + + for (size_t i = 0; i < 3; ++i) + { + AddDirectionalLight(directions[i].first, directions[i].second, colors[i]); + } + + Render(); + SaveAndCompare("1"); + + RemoveLight(0); + Render(); + SaveAndCompare("2"); + +} + +TEST_F(LightTest, Light_SpotLight) +{ + std::vector positions + { + float3( 0.0f, 6.0f, 6.0f), + float3( 5.2f, 6.0f, -3.0f), + float3(-5.2f, 6.0f, -3.0f) + }; + + // Yaw, pitch + std::vector> directions + { + { 0.0f, 0.0f }, + { (float)M_PI * 2.0f / 3.0f, (float)M_PI / 4.0f }, + { (float)M_PI * 4.0f / 3.0f, (float)M_PI / 4.0f } + }; + + std::vector colors + { + float3(3.0f, 0.1f, 0.1f), + float3(0.1f, 3.0f, 0.1f), + float3(0.1f, 0.1f, 3.0f) + }; + + // Cosines of inner and outer falloff angles + std::vector> cone_shapes + { + { std::cos((float)M_PI / 4), std::cos((float)M_PI / 3) }, + { std::cos((float)M_PI / 6), std::cos((float)M_PI / 4) }, + { std::cos((float)M_PI / 12), std::cos((float)M_PI / 6) } + }; + + for (int i = 0; i < 3; ++i) + { + AddSpotLight(positions[i], directions[i].first, directions[i].second, colors[i] * 100.0f, cone_shapes[i].first, cone_shapes[i].second); + } + + Render(); + SaveAndCompare("1"); + + RemoveLight(0); + Render(); + SaveAndCompare("2"); + +} + + +TEST_F(LightTest, Light_AreaLight) +{ + AddAreaLight(); + Render(); + SaveAndCompare(); +} + +TEST_F(LightTest, Light_PointAndAreaLight) +{ + std::vector positions + { + float3(3.0f, 6.0f, 0.0f), + float3(-2.0f, 6.0f, -1.0f), + float3(0.0f, 6.0f, -3.0f) + }; + + std::vector colors + { + float3(3.0f, 0.1f, 0.1f), + float3(0.1f, 3.0f, 0.1f), + float3(0.1f, 0.1f, 3.0f) + }; + + for (size_t i = 0; i < 3; ++i) + { + AddPointLight(positions[i], colors[i] * 10.0f); + } + + AddAreaLight(); + + Render(); + SaveAndCompare(); +} + +TEST_F(LightTest, Light_DirectionalAndAreaLight) +{ + std::vector> directions + { + { 0.0f, (float)M_PI / 3.0f }, + { (float)M_PI / 3.0f * 2.0f, (float)M_PI / 4.0f }, + { (float)M_PI / 3.0f * 4.0f, (float)M_PI / 6.0f } + }; + + std::vector colors + { + float3(3.0f, 0.1f, 0.1f), + float3(0.1f, 3.0f, 0.1f), + float3(0.1f, 0.1f, 3.0f) + }; + + for (size_t i = 0; i < 3; ++i) + { + AddDirectionalLight(directions[i].first, directions[i].second, colors[i]); + } + + AddAreaLight(); + + Render(); + SaveAndCompare(); +} + +TEST_F(LightTest, Light_SpotAndAreaLight) +{ + std::vector positions + { + float3(0.0f, 6.0f, 6.0f), + float3(5.2f, 6.0f, -3.0f), + float3(-5.2f, 6.0f, -3.0f) + }; + + // Yaw, pitch + std::vector> directions + { + { 0.0f, 0.0f }, + { (float)M_PI * 2.0f / 3.0f, (float)M_PI / 4.0f }, + { (float)M_PI * 4.0f / 3.0f, (float)M_PI / 4.0f } + }; + + std::vector colors + { + float3(3.0f, 0.1f, 0.1f), + float3(0.1f, 3.0f, 0.1f), + float3(0.1f, 0.1f, 3.0f) + }; + + // Cosines of inner and outer falloff angles + std::vector> cone_shapes + { + { std::cos((float)M_PI / 4), std::cos((float)M_PI / 3) }, + { std::cos((float)M_PI / 6), std::cos((float)M_PI / 4) }, + { std::cos((float)M_PI / 12), std::cos((float)M_PI / 6) } + }; + + for (int i = 0; i < 3; ++i) + { + AddSpotLight(positions[i], directions[i].first, directions[i].second, colors[i] * 100.0f, cone_shapes[i].first, cone_shapes[i].second); + } + + AddAreaLight(); + + Render(); + SaveAndCompare(); +} + +TEST_F(LightTest, Light_EmissiveSphere) +{ + AddEmissiveMaterial("sphere_emissive_mtl", float3(4.0f, 2.0f, 1.0f)); + ApplyMaterialToObject("sphere", "sphere_emissive_mtl"); + Render(); + SaveAndCompare(); +} + +TEST_F(LightTest, Light_ImageBasedLight) +{ + AddEnvironmentLight("../Resources/Textures/studio015.hdr"); + Render(); + SaveAndCompare("1"); + RemoveLight(0); + + AddEnvironmentLight("../Resources/Textures/test_albedo1.jpg"); + Render(); + SaveAndCompare("2"); + +} + +TEST_F(LightTest, Light_ImageBasedLightAndLightChanging) +{ + // Ibl, point, spot + AddEnvironmentLight("../Resources/Textures/studio015.hdr"); + AddPointLight(float3(3.0f, 6.0f, 0.0f), float3(10.0f, 100.0f, 10.0f)); + AddSpotLight(float3(-5.2f, 6.0f, -3.0f), (float)M_PI * 4.0f / 3.0f, (float)M_PI / 4.0f, float3(100.0f, 10.0f, 10.0f), std::cos((float)M_PI / 6), std::cos((float)M_PI / 3)); + + Render(); + SaveAndCompare("1"); + RemoveLight(1); + RemoveLight(1); + + // Ibl, directional + AddDirectionalLight((float)M_PI / 3.0f * 2.0f, (float)M_PI / 4.0f, float3(3.0f, 0.1f, 0.1f)); + Render(); + SaveAndCompare("2"); + RemoveLight(1); + + // Ibl, area + AddAreaLight(); + Render(); + SaveAndCompare("3"); + +} + +// Overrides don't work in Rpr for now... +//class LightTestOverrideReflections : public LightTest +//{ +//public: +// virtual void SetUp() override +// { +// BasicTest::SetUp(); +// CreateScene(SceneType::kThreeSpheres); +// } +//}; +// +//TEST_F(LightTestOverrideReflections, Light_OverrideReflection) +//{ +// AddEnvironmentLight("../Resources/Textures/test_albedo1.jpg"); +// ASSERT_EQ(rprSceneSetEnvironmentOverride(m_scene, RPR_SCENE_ENVIRONMENT_OVERRIDE_REFLECTION, m_lights[0]), RPR_SUCCESS); +// +// AddEnvironmentLight("../Resources/Textures/test_albedo3.jpg"); +// ASSERT_EQ(rprSceneSetEnvironmentOverride(m_scene, RPR_SCENE_ENVIRONMENT_OVERRIDE_REFRACTION, m_lights[1]), RPR_SUCCESS); +// +// ASSERT_EQ(rprSceneSetBackgroundImage(m_scene, FindImage("../Resources/Textures/test_normal.jpg")), RPR_SUCCESS); +// +// Render(); +// SaveAndCompare(); +// +//} diff --git a/RprTest/main.cpp b/RprTest/main.cpp index f7d0c049..7ae5a314 100644 --- a/RprTest/main.cpp +++ b/RprTest/main.cpp @@ -1,3105 +1,40 @@ -#include "../Rpr/RadeonProRender.h" -#include "../RadeonRays/include/math/matrix.h" -#include "../RadeonRays/include/math/mathutils.h" -#include "../RprLoadStore/RprLoadStore.h" - -#include -#include -#include -#define _USE_MATH_DEFINES -#include -#include - -using namespace RadeonRays; - -namespace -{ - //control how many frames to render in tests for resulting image - int kRenderIterations = 256; - //default structure for Vertex data - struct Vertex - { - rpr_float pos[3]; - rpr_float norm[3]; - rpr_float tex[2]; - }; - - //multi texture Vertex - struct VertexMT - { - rpr_float pos[3]; - rpr_float norm[3]; - rpr_float tex0[2]; - rpr_float tex1[2]; - }; - rpr_shape CreateSphere(rpr_context context, std::uint32_t lat, std::uint32_t lon, float r, RadeonRays::float3 const& c) - { - auto num_verts = (lat - 2) * lon + 2; - auto num_tris = (lat - 2) * (lon - 1) * 2; - - std::vector vertices(num_verts); - std::vector normals(num_verts); - std::vector uvs(num_verts); - std::vector indices(num_tris * 3); - - - auto t = 0U; - for (auto j = 1U; j < lat - 1; j++) - for (auto i = 0U; i < lon; i++) - { - float theta = float(j) / (lat - 1) * (float)M_PI; - float phi = float(i) / (lon - 1) * (float)M_PI * 2; - vertices[t].x = r * sinf(theta) * cosf(phi) + c.x; - vertices[t].y = r * cosf(theta) + c.y; - vertices[t].z = r * -sinf(theta) * sinf(phi) + c.z; - normals[t].x = sinf(theta) * cosf(phi); - normals[t].y = cosf(theta); - normals[t].z = -sinf(theta) * sinf(phi); - uvs[t].x = phi / (2 * (float)M_PI); - uvs[t].y = theta / ((float)M_PI); - ++t; - } - - vertices[t].x = c.x; vertices[t].y = c.y + r; vertices[t].z = c.z; - normals[t].x = 0; normals[t].y = 1; normals[t].z = 0; - uvs[t].x = 0; uvs[t].y = 0; - ++t; - vertices[t].x = c.x; vertices[t].y = c.y - r; vertices[t].z = c.z; - normals[t].x = 0; normals[t].y = -1; normals[t].z = 0; - uvs[t].x = 1; uvs[t].y = 1; - ++t; - - t = 0U; - for (auto j = 0U; j < lat - 3; j++) - for (auto i = 0U; i < lon - 1; i++) - { - indices[t++] = j * lon + i; - indices[t++] = (j + 1) * lon + i + 1; - indices[t++] = j * lon + i + 1; - indices[t++] = j * lon + i; - indices[t++] = (j + 1) * lon + i; - indices[t++] = (j + 1) * lon + i + 1; - } - - for (auto i = 0U; i < lon - 1; i++) - { - indices[t++] = (lat - 2) * lon; - indices[t++] = i; - indices[t++] = i + 1; - indices[t++] = (lat - 2) * lon + 1; - indices[t++] = (lat - 3) * lon + i + 1; - indices[t++] = (lat - 3) * lon + i; - } - - std::vector faces(indices.size() / 3, 3); - rpr_int status = RPR_SUCCESS; - rpr_shape mesh = NULL; status = rprContextCreateMesh(context, - (rpr_float const*)vertices.data(), vertices.size(), sizeof(float3), - (rpr_float const*)normals.data(), normals.size(), sizeof(float3), - (rpr_float const*)uvs.data(), uvs.size(), sizeof(float2), - (rpr_int const*)indices.data(), sizeof(rpr_int), - (rpr_int const*)indices.data(), sizeof(rpr_int), - (rpr_int const*)indices.data(), sizeof(rpr_int), - faces.data(), faces.size(), &mesh); - assert(status == RPR_SUCCESS); - - return mesh; - } -} - -#define FR_MACRO_CLEAN_SHAPE_RELEASE(mesh1__, scene1__)\ - status = rprShapeSetMaterial(mesh1__, NULL);\ - assert(status == RPR_SUCCESS);\ - status = rprSceneDetachShape(scene1__, mesh1__);\ - assert(status == RPR_SUCCESS);\ - status = rprObjectDelete(mesh1__); mesh1__ = NULL;\ - assert(status == RPR_SUCCESS); - -#define FR_MACRO_SAFE_FRDELETE(a) { status = rprObjectDelete(a); a = NULL; assert(status == RPR_SUCCESS); } - - -void MeshCreationTest() -{ - struct Vertex - { - rpr_float pos[3]; - rpr_float norm[3]; - rpr_float tex[2]; - }; - - Vertex quad[] = - { - { -1.0f, 1.0f, -1.0f, 0.f, 1.f, 0.f, 0.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f, 0.f, 1.f, 0.f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 1.0f , 0.f, 1.f, 0.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, 1.0f , 0.f, 1.f, 0.f, 0.0f, 1.0f } - }; - - rpr_int indices[] = - { - 3,1,0, - 2,1,3 - }; - - rpr_int num_face_vertices[] = - { - 3, 3 - }; - - rpr_int status = RPR_SUCCESS; - rpr_context context = nullptr; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - assert(status == RPR_SUCCESS); - - rpr_shape quad_mesh = NULL; status = rprContextCreateMesh(context, - (rpr_float const*)&quad[0], 24, sizeof(Vertex), - (rpr_float const*)((char*)&quad[0] + sizeof(rpr_float) * 3), 24, sizeof(Vertex), - (rpr_float const*)((char*)&quad[0] + sizeof(rpr_float) * 6), 24, sizeof(Vertex), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - num_face_vertices, 2, &quad_mesh); - assert(status == RPR_SUCCESS); - - status = rprObjectDelete(quad_mesh); quad_mesh = NULL; - assert(status == RPR_SUCCESS); -} - -void SimpleRenderTest() -{ - rpr_int status = RPR_SUCCESS; - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - assert(status == RPR_SUCCESS); - rpr_material_system matsys = NULL; - status = rprContextCreateMaterialSystem(context, 0, &matsys); - assert(status == RPR_SUCCESS); - - rpr_scene scene = NULL; status = rprContextCreateScene(context, &scene); - assert(status == RPR_SUCCESS); - - Vertex cube[] = - { - { -1.0f, 1.0f, -1.0f, 0.f, 1.f, 0.f, 0.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f, 0.f, 1.f, 0.f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 1.0f , 0.f, 1.f, 0.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, 1.0f , 0.f, 1.f, 0.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, -1.0f , 0.f, -1.f, 0.f, 0.0f, 0.0f }, - { 1.0f, -1.0f, -1.0f , 0.f, -1.f, 0.f, 1.0f, 0.0f }, - { 1.0f, -1.0f, 1.0f , 0.f, -1.f, 0.f, 1.0f, 1.0f }, - { -1.0f, -1.0f, 1.0f , 0.f, -1.f, 0.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, 1.0f , -1.f, 0.f, 0.f, 0.0f, 0.0f }, - { -1.0f, -1.0f, -1.0f , -1.f, 0.f, 0.f, 1.0f, 0.0f }, - { -1.0f, 1.0f, -1.0f , -1.f, 0.f, 0.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, 1.0f , -1.f, 0.f, 0.f, 0.0f, 1.0f }, - - { 1.0f, -1.0f, 1.0f , 1.f, 0.f, 0.f, 0.0f, 0.0f }, - { 1.0f, -1.0f, -1.0f , 1.f, 0.f, 0.f, 1.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f , 1.f, 0.f, 0.f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f , 1.f, 0.f, 0.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, -1.0f , 0.f, 0.f, -1.f ,0.0f, 0.0f }, - { 1.0f, -1.0f, -1.0f , 0.f, 0.f, -1.f ,1.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f , 0.f, 0.f, -1.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, -1.0f , 0.f, 0.f, -1.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, 1.0f , 0.f, 0.f, 1.f,0.0f, 0.0f }, - { 1.0f, -1.0f, 1.0f , 0.f, 0.f, 1.f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 1.0f , 0.f, 0.f, 1.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, 1.0f , 0.f, 0.f, 1.f,0.0f, 1.0f }, - }; - - Vertex plane[] = - { - { -5.f, 0.f, -5.f, 0.f, 1.f, 0.f, 0.f, 0.f }, - { -5.f, 0.f, 5.f, 0.f, 1.f, 0.f, 0.f, 1.f }, - { 5.f, 0.f, 5.f, 0.f, 1.f, 0.f, 1.f, 1.f }, - { 5.f, 0.f, -5.f, 0.f, 1.f, 0.f, 1.f, 0.f }, - }; - - rpr_int indices[] = - { - 3,1,0, - 2,1,3, - - 6,4,5, - 7,4,6, - - 11,9,8, - 10,9,11, - - 14,12,13, - 15,12,14, - - 19,17,16, - 18,17,19, - - 22,20,21, - 23,20,22 - }; - - - rpr_int num_face_vertices[] = - { - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 - }; - - //material - rpr_material_node diffuse = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_DIFFUSE, &diffuse); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(diffuse, "color", 0.7f, 0.7f, 0.0f, 0.0f); - assert(status == RPR_SUCCESS); - - //sphere - rpr_shape mesh = CreateSphere(context, 64, 32, 2.f, float3()); - assert(status == RPR_SUCCESS); - status = rprSceneAttachShape(scene, mesh); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(mesh, diffuse); - assert(status == RPR_SUCCESS); - matrix m = translation(float3(0, 1, 0)); - status = rprShapeSetTransform(mesh, false, &m.m00); - assert(status == RPR_SUCCESS); - - //plane mesh - rpr_shape plane_mesh = NULL; status = rprContextCreateMesh(context, - (rpr_float const*)&plane[0], 4, sizeof(Vertex), - (rpr_float const*)((char*)&plane[0] + sizeof(rpr_float) * 3), 4, sizeof(Vertex), - (rpr_float const*)((char*)&plane[0] + sizeof(rpr_float) * 6), 4, sizeof(Vertex), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - num_face_vertices, 2, &plane_mesh); - status = rprSceneAttachShape(scene, plane_mesh); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(plane_mesh, diffuse); - assert(status == RPR_SUCCESS); - - //camera - rpr_camera camera = NULL; status = rprContextCreateCamera(context, &camera); - assert(status == RPR_SUCCESS); - status = rprCameraLookAt(camera, 0, 3, 10, 0, 0, 0, 0, 1, 0); - assert(status == RPR_SUCCESS); - status = rprCameraSetFocalLength(camera, 23.f); - assert(status == RPR_SUCCESS); - status = rprCameraSetFStop(camera, 5.4f); - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, camera); - assert(status == RPR_SUCCESS); - - status = rprContextSetScene(context, scene); - assert(status == RPR_SUCCESS); - - //light - rpr_light light = NULL; status = rprContextCreateSpotLight(context, &light); - assert(status == RPR_SUCCESS); - matrix lightm = translation(float3(0, 16, 0)) * rotation_x(M_PI_2); - status = rprLightSetTransform(light, true, &lightm.m00); - assert(status == RPR_SUCCESS); - status = rprSpotLightSetConeShape(light, M_PI_4, M_PI * 2.f / 3.f); - assert(status == RPR_SUCCESS); - status = rprSpotLightSetRadiantPower3f(light, 350, 350, 350); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, light); - assert(status == RPR_SUCCESS); - - //setup out - rpr_framebuffer_desc desc; - desc.fb_width = 800; - desc.fb_height = 600; - - rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; - rpr_framebuffer frame_buffer = NULL; status = rprContextCreateFrameBuffer(context, fmt, &desc, &frame_buffer); - assert(status == RPR_SUCCESS); - status = rprContextSetAOV(context, RPR_AOV_COLOR, frame_buffer); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); assert(status == RPR_SUCCESS); - - //render - for (int i = 0; i < kRenderIterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - - status = rprFrameBufferSaveToFile(frame_buffer, "Output/SimpleRenderTest_f1.jpg"); - assert(status == RPR_SUCCESS); - - //change light - status = rprSpotLightSetConeShape(light, M_PI_4 * 0.5f, M_PI_4 * 0.5f); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); assert(status == RPR_SUCCESS); - assert(status == RPR_SUCCESS); - - for (int i = 0; i < kRenderIterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - status = rprFrameBufferSaveToFile(frame_buffer, "Output/SimpleRenderTest_f2.jpg"); - assert(status == RPR_SUCCESS); - rpr_render_statistics rs; - status = rprContextGetInfo(context, RPR_CONTEXT_RENDER_STATISTICS, sizeof(rpr_render_statistics), &rs, NULL); - assert(status == RPR_SUCCESS); - - //cleanup - status = rprSceneDetachLight(scene, light); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(light); light = NULL; - assert(status == RPR_SUCCESS); - rprObjectDelete(diffuse); - status = rprSceneSetCamera(scene, NULL); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(scene); scene = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(camera); camera = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(frame_buffer); frame_buffer = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(matsys); matsys = NULL; - assert(status == RPR_SUCCESS); -} - -void ComplexRenderTest() -{ - rpr_int status = RPR_SUCCESS; - - //context, scene and mat. system - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - assert(status == RPR_SUCCESS); - rpr_material_system matsys = NULL; - status = rprContextCreateMaterialSystem(context, 0, &matsys); - assert(status == RPR_SUCCESS); - rpr_scene scene = NULL; status = rprContextCreateScene(context, &scene); - assert(status == RPR_SUCCESS); - - struct Vertex - { - rpr_float pos[3]; - rpr_float norm[3]; - rpr_float tex[2]; - }; - - Vertex cube[] = - { - { -1.0f, 1.0f, -1.0f, 0.f, 1.f, 0.f, 0.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f, 0.f, 1.f, 0.f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 1.0f , 0.f, 1.f, 0.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, 1.0f , 0.f, 1.f, 0.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, -1.0f , 0.f, -1.f, 0.f, 0.0f, 0.0f }, - { 1.0f, -1.0f, -1.0f , 0.f, -1.f, 0.f, 1.0f, 0.0f }, - { 1.0f, -1.0f, 1.0f , 0.f, -1.f, 0.f, 1.0f, 1.0f }, - { -1.0f, -1.0f, 1.0f , 0.f, -1.f, 0.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, 1.0f , -1.f, 0.f, 0.f, 0.0f, 0.0f }, - { -1.0f, -1.0f, -1.0f , -1.f, 0.f, 0.f, 1.0f, 0.0f }, - { -1.0f, 1.0f, -1.0f , -1.f, 0.f, 0.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, 1.0f , -1.f, 0.f, 0.f, 0.0f, 1.0f }, - - { 1.0f, -1.0f, 1.0f , 1.f, 0.f, 0.f, 0.0f, 0.0f }, - { 1.0f, -1.0f, -1.0f , 1.f, 0.f, 0.f, 1.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f , 1.f, 0.f, 0.f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f , 1.f, 0.f, 0.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, -1.0f , 0.f, 0.f, -1.f ,0.0f, 0.0f }, - { 1.0f, -1.0f, -1.0f , 0.f, 0.f, -1.f ,1.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f , 0.f, 0.f, -1.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, -1.0f , 0.f, 0.f, -1.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, 1.0f , 0.f, 0.f, 1.f,0.0f, 0.0f }, - { 1.0f, -1.0f, 1.0f , 0.f, 0.f, 1.f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 1.0f , 0.f, 0.f, 1.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, 1.0f , 0.f, 0.f, 1.f,0.0f, 1.0f }, - }; - - Vertex plane[] = - { - { -15.f, 0.f, -15.f, 0.f, 1.f, 0.f, 0.f, 0.f }, - { -15.f, 0.f, 15.f, 0.f, 1.f, 0.f, 0.f, 1.f }, - { 15.f, 0.f, 15.f, 0.f, 1.f, 0.f, 1.f, 1.f }, - { 15.f, 0.f, -15.f, 0.f, 1.f, 0.f, 1.f, 0.f }, - }; - - rpr_int indices[] = - { - 3,1,0, - 2,1,3, - - 6,4,5, - 7,4,6, - - 11,9,8, - 10,9,11, - - 14,12,13, - 15,12,14, - - 19,17,16, - 18,17,19, - - 22,20,21, - 23,20,22 - }; - - rpr_int num_face_vertices[] = - { - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 - }; - - rpr_shape mesh = NULL; status = rprContextCreateMesh(context, - (rpr_float const*)&cube[0], 24, sizeof(Vertex), - (rpr_float const*)((char*)&cube[0] + sizeof(rpr_float) * 3), 24, sizeof(Vertex), - (rpr_float const*)((char*)&cube[0] + sizeof(rpr_float) * 6), 24, sizeof(Vertex), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - num_face_vertices, 12, &mesh); - - assert(status == RPR_SUCCESS); - - rpr_shape plane_mesh = NULL; status = rprContextCreateMesh(context, - (rpr_float const*)&plane[0], 4, sizeof(Vertex), - (rpr_float const*)((char*)&plane[0] + sizeof(rpr_float) * 3), 4, sizeof(Vertex), - (rpr_float const*)((char*)&plane[0] + sizeof(rpr_float) * 6), 4, sizeof(Vertex), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - num_face_vertices, 2, &plane_mesh); - - rpr_shape mesh1 = NULL; status = rprContextCreateInstance(context, mesh, &mesh1); - assert(status == RPR_SUCCESS); - - //translate cubes - matrix m = translation(float3(-2, 1, 0)); - status = rprShapeSetTransform(mesh1, true, &m.m00); - assert(status == RPR_SUCCESS); - matrix m1 = translation(float3(2, 1, 0)) * rotation_y(0.5); - status = rprShapeSetTransform(mesh, true, &m1.m00); - assert(status == RPR_SUCCESS); - - //attach shapes - status = rprSceneAttachShape(scene, mesh); - assert(status == RPR_SUCCESS); - status = rprSceneAttachShape(scene, mesh1); - assert(status == RPR_SUCCESS); - status = rprSceneAttachShape(scene, plane_mesh); - assert(status == RPR_SUCCESS); - - //camera - rpr_camera camera = NULL; status = rprContextCreateCamera(context, &camera); - assert(status == RPR_SUCCESS); - status = rprCameraLookAt(camera, 0, 3, 10, 0, 0, 0, 0, 1, 0); - assert(status == RPR_SUCCESS); - status = rprCameraSetSensorSize(camera, 22.5f, 15.f); - assert(status == RPR_SUCCESS); - status = rprCameraSetFocalLength(camera, 35.f); - assert(status == RPR_SUCCESS); - status = rprCameraSetFStop(camera, 6.4f); - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, camera); - assert(status == RPR_SUCCESS); - - status = rprContextSetScene(context, scene); - assert(status == RPR_SUCCESS); - - //materials - rpr_material_node diffuse = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_DIFFUSE, &diffuse); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(diffuse, "color", 0.9f, 0.9f, 0.f, 1.0f); - assert(status == RPR_SUCCESS); - rpr_image img = NULL; status = rprContextCreateImageFromFile(context, "../Resources/Textures/test_diffuse.jpg", &img); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputImageData(diffuse, "color", img); - assert(status == RPR_SUCCESS); - rpr_material_node materialNodeTexture = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_IMAGE_TEXTURE, &materialNodeTexture); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputImageData(materialNodeTexture, "data", img); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputN(diffuse, "color", materialNodeTexture); - assert(status == RPR_SUCCESS); - - status = rprShapeSetMaterial(mesh, diffuse); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(mesh1, diffuse); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(plane_mesh, diffuse); - assert(status == RPR_SUCCESS); - - //light - rpr_light light = NULL; status = rprContextCreatePointLight(context, &light); - assert(status == RPR_SUCCESS); - matrix lightm = translation(float3(0, 6, 0)) * rotation_z(3.14f); - status = rprLightSetTransform(light, true, &lightm.m00); - assert(status == RPR_SUCCESS); - status = rprPointLightSetRadiantPower3f(light, 100, 100, 100); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, light); - assert(status == RPR_SUCCESS); - - //result buffer - rpr_framebuffer_desc desc; - desc.fb_width = 800; - desc.fb_height = 600; - rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; - rpr_framebuffer frame_buffer = NULL; status = rprContextCreateFrameBuffer(context, fmt, &desc, &frame_buffer); - assert(status == RPR_SUCCESS); - status = rprContextSetAOV(context, RPR_AOV_COLOR, frame_buffer); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - - //render - for (int i = 0; i < kRenderIterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - status = rprFrameBufferSaveToFile(frame_buffer, "Output/ComplexRender.jpg"); - assert(status == RPR_SUCCESS); - - //cleanup - FR_MACRO_CLEAN_SHAPE_RELEASE(mesh, scene); - FR_MACRO_CLEAN_SHAPE_RELEASE(mesh1, scene); - FR_MACRO_CLEAN_SHAPE_RELEASE(plane_mesh, scene); - FR_MACRO_SAFE_FRDELETE(img); - FR_MACRO_SAFE_FRDELETE(materialNodeTexture); - status = rprSceneDetachLight(scene, light); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(light); light = NULL; - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, NULL); - assert(status == RPR_SUCCESS); - rprObjectDelete(diffuse); - status = rprObjectDelete(scene); scene = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(camera); camera = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(frame_buffer); frame_buffer = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(matsys); matsys = NULL; - assert(status == RPR_SUCCESS); -} - -void EnvLightClearTest() -{ - rpr_int status = RPR_SUCCESS; - - //create context, scene and mat system - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - assert(status == RPR_SUCCESS); - rpr_material_system matsys = NULL; - status = rprContextCreateMaterialSystem(context, 0, &matsys); - assert(status == RPR_SUCCESS); - rpr_scene scene = NULL; status = rprContextCreateScene(context, &scene); - assert(status == RPR_SUCCESS); - status = rprContextSetScene(context, scene); - assert(status == RPR_SUCCESS); - - struct Vertex - { - rpr_float pos[3]; - rpr_float norm[3]; - rpr_float tex[2]; - }; - - Vertex cube[] = - { - { -1.0f, 1.0f, -1.0f, 0.f, 1.f, 0.f, 0.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f, 0.f, 1.f, 0.f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 1.0f , 0.f, 1.f, 0.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, 1.0f , 0.f, 1.f, 0.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, -1.0f , 0.f, -1.f, 0.f, 0.0f, 0.0f }, - { 1.0f, -1.0f, -1.0f , 0.f, -1.f, 0.f, 1.0f, 0.0f }, - { 1.0f, -1.0f, 1.0f , 0.f, -1.f, 0.f, 1.0f, 1.0f }, - { -1.0f, -1.0f, 1.0f , 0.f, -1.f, 0.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, 1.0f , -1.f, 0.f, 0.f, 0.0f, 0.0f }, - { -1.0f, -1.0f, -1.0f , -1.f, 0.f, 0.f, 1.0f, 0.0f }, - { -1.0f, 1.0f, -1.0f , -1.f, 0.f, 0.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, 1.0f , -1.f, 0.f, 0.f, 0.0f, 1.0f }, - - { 1.0f, -1.0f, 1.0f , 1.f, 0.f, 0.f, 0.0f, 0.0f }, - { 1.0f, -1.0f, -1.0f , 1.f, 0.f, 0.f, 1.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f , 1.f, 0.f, 0.f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f , 1.f, 0.f, 0.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, -1.0f , 0.f, 0.f, -1.f ,0.0f, 0.0f }, - { 1.0f, -1.0f, -1.0f , 0.f, 0.f, -1.f ,1.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f , 0.f, 0.f, -1.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, -1.0f , 0.f, 0.f, -1.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, 1.0f , 0.f, 0.f, 1.f,0.0f, 0.0f }, - { 1.0f, -1.0f, 1.0f , 0.f, 0.f, 1.f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 1.0f , 0.f, 0.f, 1.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, 1.0f , 0.f, 0.f, 1.f,0.0f, 1.0f }, - }; - - Vertex plane[] = - { - { -500.f, 0.f, -500.f, 0.f, 1.f, 0.f, 0.f, 0.f }, - { -500.f, 0.f, 500.f, 0.f, 1.f, 0.f, 0.f, 1.f }, - { 500.f, 0.f, 500.f, 0.f, 1.f, 0.f, 1.f, 1.f }, - { 500.f, 0.f, -500.f, 0.f, 1.f, 0.f, 1.f, 0.f }, - }; - - rpr_int indices[] = - { - 3,1,0, - 2,1,3, - - 6,4,5, - 7,4,6, - - 11,9,8, - 10,9,11, - - 14,12,13, - 15,12,14, - - 19,17,16, - 18,17,19, - - 22,20,21, - 23,20,22 - }; - - - rpr_int num_face_vertices[] = - { - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 - }; - - //materials - rpr_material_node diffuse = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_DIFFUSE, &diffuse); - assert(status == RPR_SUCCESS); - rpr_material_node specularSphere = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_REFLECTION, &specularSphere); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(diffuse, "color", 0.7f, 0.7f, 0.7f, 1.0f); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(specularSphere, "color", 1.0f, 1.0f, 1.0f, 1.0f); - assert(status == RPR_SUCCESS); - - //sphere mesh - rpr_shape mesh = CreateSphere(context, 64, 32, 2.f, float3()); - assert(status == RPR_SUCCESS); - status = rprSceneAttachShape(scene, mesh); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(mesh, diffuse); - assert(status == RPR_SUCCESS); - matrix m = translation(float3(0, 1, 0)) * scale(float3(0.2, 0.2, 0.2)); - status = rprShapeSetTransform(mesh, false, &m.m00); - assert(status == RPR_SUCCESS); - - //plane mesh - rpr_shape plane_mesh = NULL; status = rprContextCreateMesh(context, - (rpr_float const*)&plane[0], 4, sizeof(Vertex), - (rpr_float const*)((char*)&plane[0] + sizeof(rpr_float) * 3), 4, sizeof(Vertex), - (rpr_float const*)((char*)&plane[0] + sizeof(rpr_float) * 6), 4, sizeof(Vertex), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - num_face_vertices, 2, &plane_mesh); - status = rprSceneAttachShape(scene, plane_mesh); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(plane_mesh, diffuse); - assert(status == RPR_SUCCESS); - - //camera - rpr_camera camera = NULL; status = rprContextCreateCamera(context, &camera); - assert(status == RPR_SUCCESS); - status = rprCameraLookAt(camera, 0, 1, 10, 0, 0, 0, 0, 1, 0); - assert(status == RPR_SUCCESS); - status = rprCameraSetFocalLength(camera, 23.f); - assert(status == RPR_SUCCESS); - status = rprCameraSetFStop(camera, 5.4f); - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, camera); - assert(status == RPR_SUCCESS); - - //environment light - rpr_light light = NULL; status = rprContextCreateEnvironmentLight(context, &light); - assert(status == RPR_SUCCESS); - rpr_image imageInput = NULL; status = rprContextCreateImageFromFile(context, "../Resources/Textures/studio015.hdr", &imageInput); - assert(status == RPR_SUCCESS); - status = rprEnvironmentLightSetImage(light, imageInput); - assert(status == RPR_SUCCESS); - status = rprEnvironmentLightSetIntensityScale(light, 5.f); - assert(status == RPR_SUCCESS); - matrix lightm = rotation_y(M_PI); - status = rprLightSetTransform(light, false, &lightm.m00); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, light); - assert(status == RPR_SUCCESS); - - //output - rpr_framebuffer_desc desc; - desc.fb_width = 800; - desc.fb_height = 600; - rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; - rpr_framebuffer frame_buffer = NULL; status = rprContextCreateFrameBuffer(context, fmt, &desc, &frame_buffer); - assert(status == RPR_SUCCESS); - status = rprContextSetAOV(context, RPR_AOV_COLOR, frame_buffer); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - - //render - for (int i = 0; i < kRenderIterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - - rprFrameBufferSaveToFile(frame_buffer, "Output/EnvLightClear_Stage1.png"); - - //check clear frame buffer - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - rprFrameBufferSaveToFile(frame_buffer, "Output/EnvLightClear_Stage2.png"); - - //clear scene and reattach resources - status = rprSceneClear(scene); - assert(status == RPR_SUCCESS); - status = rprSceneAttachShape(scene, plane_mesh); - assert(status == RPR_SUCCESS); - lightm = rotation_y(-M_PI_2); - status = rprLightSetTransform(light, true, &lightm.m00); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, light); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - - //render - for (int i = 0; i < kRenderIterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - - rprFrameBufferSaveToFile(frame_buffer, "Output/EnvLightClear_Stage3.png"); - - //cleanup - status = rprObjectDelete(imageInput); imageInput = NULL; - assert(status == RPR_SUCCESS); - FR_MACRO_CLEAN_SHAPE_RELEASE(mesh, scene); - FR_MACRO_CLEAN_SHAPE_RELEASE(plane_mesh, scene); - status = rprSceneDetachLight(scene, light); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(light); light = NULL; - assert(status == RPR_SUCCESS); - rprObjectDelete(diffuse); - rprObjectDelete(specularSphere); - status = rprSceneSetCamera(scene, NULL); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(scene); scene = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(camera); camera = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(frame_buffer); frame_buffer = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(matsys); matsys = NULL; - assert(status == RPR_SUCCESS); -} - -void MemoryStatistics() -{ - rpr_render_statistics rs; - rs.gpumem_usage = 0; - rs.gpumem_total = 0; - rs.gpumem_max_allocation = 0; - - //create context and check there is no used resources - rpr_int status = RPR_SUCCESS; - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - assert(status == RPR_SUCCESS); - status = rprContextGetInfo(context, RPR_CONTEXT_RENDER_STATISTICS, sizeof(rpr_render_statistics), &rs, NULL); - assert(status == RPR_SUCCESS); - - assert(rs.gpumem_usage == 0); - assert(rs.gpumem_total == 0); - assert(rs.gpumem_max_allocation == 0); -} - -void DefaultMaterialTest() -{ - rpr_int status = RPR_SUCCESS; - //create context and scene - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - assert(status == RPR_SUCCESS); - rpr_scene scene = NULL; status = rprContextCreateScene(context, &scene); - assert(status == RPR_SUCCESS); - - struct Vertex - { - rpr_float pos[3]; - rpr_float norm[3]; - rpr_float tex[2]; - }; - - Vertex quad[] = - { - { -5.0f, -1.0f, -5.0f, 0.f, 1.f, 0.f, 0.f, 0.f }, - { 5.0f, -1.0f, -5.0f, 0.f, 1.f, 0.f, 1.f, 0.f }, - { 5.0f, -1.0f, 5.0f, 0.f, 1.f, 0.f, 1.f, 1.f }, - { -5.0f, -1.0f, 5.0f, 0.f, 1.f, 0.f, 0.f, 1.f }, - }; - - - rpr_int indices[] = - { - 3,1,0, - 2,1,3, - }; - - rpr_int num_face_vertices[] = - { - 3, 3 - }; - - //plane mesh - rpr_shape mesh = NULL; status = rprContextCreateMesh(context, - (rpr_float const*)&quad[0], 4, sizeof(Vertex), - (rpr_float const*)((char*)&quad[0] + sizeof(rpr_float) * 3), 4, sizeof(Vertex), - (rpr_float const*)((char*)&quad[0] + sizeof(rpr_float) * 6), 4, sizeof(Vertex), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - num_face_vertices, 2, &mesh); - assert(status == RPR_SUCCESS); - matrix r = rotation_x(M_PI_2); - status = rprShapeSetTransform(mesh, false, &r.m00); - assert(status == RPR_SUCCESS); - status = rprSceneAttachShape(scene, mesh); - assert(status == RPR_SUCCESS); - - //camera - rpr_camera camera = NULL; status = rprContextCreateCamera(context, &camera); - assert(status == RPR_SUCCESS); - status = rprCameraLookAt(camera, 0, 0, 10, 0, 0, 0, 0, 1, 0); - assert(status == RPR_SUCCESS); - status = rprCameraSetFocalLength(camera, 20.f); - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, camera); - assert(status == RPR_SUCCESS); - status = rprContextSetScene(context, scene); - assert(status == RPR_SUCCESS); - - //light - rpr_light light = NULL; status = rprContextCreatePointLight(context, &light); - assert(status == RPR_SUCCESS); - matrix lightm = translation(float3(0, 0, 6)); - status = rprLightSetTransform(light, true, &lightm.m00); - assert(status == RPR_SUCCESS); - status = rprPointLightSetRadiantPower3f(light, 200, 200, 200); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, light); - assert(status == RPR_SUCCESS); - - //setup output - rpr_framebuffer_desc desc; - desc.fb_width = 800; - desc.fb_height = 600; - rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; - rpr_framebuffer frame_buffer = NULL; status = rprContextCreateFrameBuffer(context, fmt, &desc, &frame_buffer); - assert(status == RPR_SUCCESS); - status = rprContextSetAOV(context, RPR_AOV_COLOR, frame_buffer); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - - //render - for (int i = 0; i < kRenderIterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - - rprFrameBufferSaveToFile(frame_buffer, "Output/DefaultMaterialTest.png"); - - //cleanup - status = rprSceneDetachLight(scene, light); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(light); light = NULL; - assert(status == RPR_SUCCESS); - FR_MACRO_CLEAN_SHAPE_RELEASE(mesh, scene); - status = rprSceneSetCamera(scene, NULL); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(scene); scene = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(camera); camera = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(frame_buffer); frame_buffer = NULL; - assert(status == RPR_SUCCESS); -} - -void NullShaderTest() -{ - rpr_int status = RPR_SUCCESS; - - //create context, material system and scene - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - rpr_material_system matsys = NULL; - status = rprContextCreateMaterialSystem(context, 0, &matsys); - assert(status == RPR_SUCCESS); - rpr_scene scene = NULL; status = rprContextCreateScene(context, &scene); - assert(status == RPR_SUCCESS); - status = rprContextSetScene(context, scene); - assert(status == RPR_SUCCESS); - - struct Vertex - { - rpr_float pos[3]; - rpr_float norm[3]; - rpr_float tex[2]; - }; - - Vertex quad[] = - { - { -5.0f, -1.0f, -5.0f, 0.f, 1.f, 0.f, 0.f, 0.f }, - { 5.0f, -1.0f, -5.0f, 0.f, 1.f, 0.f, 1.f, 0.f }, - { 5.0f, -1.0f, 5.0f, 0.f, 1.f, 0.f, 1.f, 1.f }, - { -5.0f, -1.0f, 5.0f, 0.f, 1.f, 0.f, 0.f, 1.f }, - }; - - - rpr_int indices[] = - { - 3,1,0, - 2,1,3, - }; - - rpr_int num_face_vertices[] = - { - 3, 3 - }; - - //plane mesh - rpr_shape mesh = NULL; status = rprContextCreateMesh(context, - (rpr_float const*)&quad[0], 4, sizeof(Vertex), - (rpr_float const*)((char*)&quad[0] + sizeof(rpr_float) * 3), 4, sizeof(Vertex), - (rpr_float const*)((char*)&quad[0] + sizeof(rpr_float) * 6), 4, sizeof(Vertex), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - num_face_vertices, 2, &mesh); - assert(status == RPR_SUCCESS); - matrix r = rotation_x(M_PI_2); - status = rprShapeSetTransform(mesh, false, &r.m00); - assert(status == RPR_SUCCESS); - status = rprSceneAttachShape(scene, mesh); - assert(status == RPR_SUCCESS); - - //camera - rpr_camera camera = NULL; status = rprContextCreateCamera(context, &camera); - assert(status == RPR_SUCCESS); - status = rprCameraLookAt(camera, 0, 0, 10, 0, 0, 0, 0, 1, 0); - assert(status == RPR_SUCCESS); - status = rprCameraSetFocalLength(camera, 20.f); - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, camera); - assert(status == RPR_SUCCESS); - - //materials - rpr_material_node diffuse = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_DIFFUSE, &diffuse); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(diffuse, "color", 1, 0, 0, 1); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(mesh, diffuse); - assert(status == RPR_SUCCESS); - - //light - rpr_light light = NULL; status = rprContextCreatePointLight(context, &light); - assert(status == RPR_SUCCESS); - matrix lightm = translation(float3(0, 0, 6)); - status = rprLightSetTransform(light, true, &lightm.m00); - assert(status == RPR_SUCCESS); - status = rprPointLightSetRadiantPower3f(light, 200, 200, 200); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, light); - assert(status == RPR_SUCCESS); - - //setup output - rpr_framebuffer_desc desc; - desc.fb_width = 800; - desc.fb_height = 600; - rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; - rpr_framebuffer frame_buffer = NULL; status = rprContextCreateFrameBuffer(context, fmt, &desc, &frame_buffer); - assert(status == RPR_SUCCESS); - status = rprContextSetAOV(context, RPR_AOV_COLOR, frame_buffer); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - - //render - int render_iterations = 100; - for (int i = 0; i < render_iterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - - rprFrameBufferSaveToFile(frame_buffer, "Output/NullShader_Stage1.png"); - - //try with NULL material - status = rprShapeSetMaterial(mesh, NULL); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - for (int i = 0; i < render_iterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - - rprFrameBufferSaveToFile(frame_buffer, "Output/NullShader_Stage2.png"); - - - //cleanup - status = rprSceneDetachLight(scene, light); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(light); light = NULL; - assert(status == RPR_SUCCESS); - FR_MACRO_CLEAN_SHAPE_RELEASE(mesh, scene); - rprObjectDelete(diffuse); - status = rprSceneSetCamera(scene, NULL); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(scene); scene = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(camera); camera = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(frame_buffer); frame_buffer = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(matsys); matsys = NULL; - assert(status == RPR_SUCCESS); -} - -void TiledRender() -{ - rpr_int status = RPR_SUCCESS; - - //prepare - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - assert(status == RPR_SUCCESS); - rpr_material_system matsys = NULL; - status = rprContextCreateMaterialSystem(context, 0, &matsys); - assert(status == RPR_SUCCESS); - rpr_scene scene = NULL; status = rprContextCreateScene(context, &scene); - assert(status == RPR_SUCCESS); - status = rprContextSetScene(context, scene); - assert(status == RPR_SUCCESS); - - struct Vertex - { - rpr_float pos[3]; - rpr_float norm[3]; - rpr_float tex[2]; - }; - - Vertex cube[] = - { - { -1.0f, 1.0f, -1.0f, 0.f, 1.f, 0.f, 0.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f, 0.f, 1.f, 0.f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 1.0f , 0.f, 1.f, 0.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, 1.0f , 0.f, 1.f, 0.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, -1.0f , 0.f, -1.f, 0.f, 0.0f, 0.0f }, - { 1.0f, -1.0f, -1.0f , 0.f, -1.f, 0.f, 1.0f, 0.0f }, - { 1.0f, -1.0f, 1.0f , 0.f, -1.f, 0.f, 1.0f, 1.0f }, - { -1.0f, -1.0f, 1.0f , 0.f, -1.f, 0.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, 1.0f , -1.f, 0.f, 0.f, 0.0f, 0.0f }, - { -1.0f, -1.0f, -1.0f , -1.f, 0.f, 0.f, 1.0f, 0.0f }, - { -1.0f, 1.0f, -1.0f , -1.f, 0.f, 0.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, 1.0f , -1.f, 0.f, 0.f, 0.0f, 1.0f }, - - { 1.0f, -1.0f, 1.0f , 1.f, 0.f, 0.f, 0.0f, 0.0f }, - { 1.0f, -1.0f, -1.0f , 1.f, 0.f, 0.f, 1.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f , 1.f, 0.f, 0.f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f , 1.f, 0.f, 0.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, -1.0f , 0.f, 0.f, -1.f ,0.0f, 0.0f }, - { 1.0f, -1.0f, -1.0f , 0.f, 0.f, -1.f ,1.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f , 0.f, 0.f, -1.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, -1.0f , 0.f, 0.f, -1.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, 1.0f , 0.f, 0.f, 1.f,0.0f, 0.0f }, - { 1.0f, -1.0f, 1.0f , 0.f, 0.f, 1.f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 1.0f , 0.f, 0.f, 1.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, 1.0f , 0.f, 0.f, 1.f,0.0f, 1.0f }, - }; - - Vertex plane[] = - { - { -500.f, 0.f, -500.f, 0.f, 1.f, 0.f, 0.f, 0.f }, - { -500.f, 0.f, 500.f, 0.f, 1.f, 0.f, 0.f, 1.f }, - { 500.f, 0.f, 500.f, 0.f, 1.f, 0.f, 1.f, 1.f }, - { 500.f, 0.f, -500.f, 0.f, 1.f, 0.f, 1.f, 0.f }, - }; - - rpr_int indices[] = - { - 3,1,0, - 2,1,3, - - 6,4,5, - 7,4,6, - - 11,9,8, - 10,9,11, - - 14,12,13, - 15,12,14, - - 19,17,16, - 18,17,19, - - 22,20,21, - 23,20,22 - }; - - rpr_int num_face_vertices[] = - { - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 - }; - - //meshes - rpr_shape mesh = NULL; status = rprContextCreateMesh(context, - (rpr_float const*)&cube[0], 24, sizeof(Vertex), - (rpr_float const*)((char*)&cube[0] + sizeof(rpr_float) * 3), 24, sizeof(Vertex), - (rpr_float const*)((char*)&cube[0] + sizeof(rpr_float) * 6), 24, sizeof(Vertex), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - num_face_vertices, 12, &mesh); - assert(status == RPR_SUCCESS); - status = rprSceneAttachShape(scene, mesh); - assert(status == RPR_SUCCESS); - matrix m = rotation_x(M_PI_4) * rotation_y(M_PI); - status = rprShapeSetTransform(mesh, false, &m.m00); - assert(status == RPR_SUCCESS); - - rpr_shape plane_mesh = NULL; status = rprContextCreateMesh(context, - (rpr_float const*)&plane[0], 4, sizeof(Vertex), - (rpr_float const*)((char*)&plane[0] + sizeof(rpr_float) * 3), 4, sizeof(Vertex), - (rpr_float const*)((char*)&plane[0] + sizeof(rpr_float) * 6), 4, sizeof(Vertex), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - num_face_vertices, 2, &plane_mesh); - assert(status == RPR_SUCCESS); - status = rprSceneAttachShape(scene, plane_mesh); - assert(status == RPR_SUCCESS); - - //camera - rpr_camera camera = NULL; status = rprContextCreateCamera(context, &camera); - assert(status == RPR_SUCCESS); - status = rprCameraLookAt(camera, 0, 3, 10, 0, 0, 0, 0, 1, 0); - assert(status == RPR_SUCCESS); - status = rprCameraSetFocalLength(camera, 50.f); - assert(status == RPR_SUCCESS); - status = rprCameraSetFStop(camera, 5.4f); - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, camera); - assert(status == RPR_SUCCESS); - - //material - rpr_material_node diffuse = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_DIFFUSE, &diffuse); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(diffuse, "color", 0.7f, 0.7f, 0.0f, 0.0f); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(mesh, diffuse); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(plane_mesh, diffuse); - assert(status == RPR_SUCCESS); - - //light - rpr_light light = NULL; status = rprContextCreatePointLight(context, &light); - assert(status == RPR_SUCCESS); - matrix lightm = translation(float3(0, 6, 0)); - status = rprLightSetTransform(light, true, &lightm.m00); - assert(status == RPR_SUCCESS); - status = rprPointLightSetRadiantPower3f(light, 60, 60, 60); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, light); - assert(status == RPR_SUCCESS); - - //output - rpr_framebuffer_desc desc; - desc.fb_width = 800; - desc.fb_height = 600; - rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; - rpr_framebuffer frame_buffer = NULL; status = rprContextCreateFrameBuffer(context, fmt, &desc, &frame_buffer); - assert(status == RPR_SUCCESS); - status = rprContextSetAOV(context, RPR_AOV_COLOR, frame_buffer); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); assert(status == RPR_SUCCESS); - assert(status == RPR_SUCCESS); - - //render - for (int i = 0; i < kRenderIterations; ++i) - { - status = rprContextRenderTile(context, 10, desc.fb_width/2, 10, desc.fb_height/2); - //status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - - rprFrameBufferSaveToFile(frame_buffer, "Output/Tiled_Render.png"); - - //clear - FR_MACRO_CLEAN_SHAPE_RELEASE(plane_mesh, scene); - status = rprSceneDetachLight(scene, light); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(light); light = NULL; - assert(status == RPR_SUCCESS); - FR_MACRO_CLEAN_SHAPE_RELEASE(mesh, scene); - rprObjectDelete(diffuse); - status = rprSceneSetCamera(scene, NULL); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(scene); scene = NULL; - assert(status == RPR_SUCCESS); - - status = rprObjectDelete(camera); camera = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(frame_buffer); frame_buffer = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(matsys); matsys = NULL; - assert(status == RPR_SUCCESS); -} - -void AOVTest() -{ - rpr_int status = RPR_SUCCESS; - - //context, scene and mat. system - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - assert(status == RPR_SUCCESS); - rpr_material_system matsys = NULL; - status = rprContextCreateMaterialSystem(context, 0, &matsys); - assert(status == RPR_SUCCESS); - rpr_scene scene = NULL; status = rprContextCreateScene(context, &scene); - assert(status == RPR_SUCCESS); - - struct Vertex - { - rpr_float pos[3]; - rpr_float norm[3]; - rpr_float tex[2]; - }; - - Vertex cube[] = - { - { -1.0f, 1.0f, -1.0f, 0.f, 1.f, 0.f, 0.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f, 0.f, 1.f, 0.f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 1.0f , 0.f, 1.f, 0.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, 1.0f , 0.f, 1.f, 0.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, -1.0f , 0.f, -1.f, 0.f, 0.0f, 0.0f }, - { 1.0f, -1.0f, -1.0f , 0.f, -1.f, 0.f, 1.0f, 0.0f }, - { 1.0f, -1.0f, 1.0f , 0.f, -1.f, 0.f, 1.0f, 1.0f }, - { -1.0f, -1.0f, 1.0f , 0.f, -1.f, 0.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, 1.0f , -1.f, 0.f, 0.f, 0.0f, 0.0f }, - { -1.0f, -1.0f, -1.0f , -1.f, 0.f, 0.f, 1.0f, 0.0f }, - { -1.0f, 1.0f, -1.0f , -1.f, 0.f, 0.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, 1.0f , -1.f, 0.f, 0.f, 0.0f, 1.0f }, - - { 1.0f, -1.0f, 1.0f , 1.f, 0.f, 0.f, 0.0f, 0.0f }, - { 1.0f, -1.0f, -1.0f , 1.f, 0.f, 0.f, 1.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f , 1.f, 0.f, 0.f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f , 1.f, 0.f, 0.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, -1.0f , 0.f, 0.f, -1.f ,0.0f, 0.0f }, - { 1.0f, -1.0f, -1.0f , 0.f, 0.f, -1.f ,1.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f , 0.f, 0.f, -1.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, -1.0f , 0.f, 0.f, -1.f, 0.0f, 1.0f }, - - { -1.0f, -1.0f, 1.0f , 0.f, 0.f, 1.f,0.0f, 0.0f }, - { 1.0f, -1.0f, 1.0f , 0.f, 0.f, 1.f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 1.0f , 0.f, 0.f, 1.f, 1.0f, 1.0f }, - { -1.0f, 1.0f, 1.0f , 0.f, 0.f, 1.f,0.0f, 1.0f }, - }; - - Vertex plane[] = - { - { -15.f, 0.f, -15.f, 0.f, 1.f, 0.f, 0.f, 0.f }, - { -15.f, 0.f, 15.f, 0.f, 1.f, 0.f, 0.f, 1.f }, - { 15.f, 0.f, 15.f, 0.f, 1.f, 0.f, 1.f, 1.f }, - { 15.f, 0.f, -15.f, 0.f, 1.f, 0.f, 1.f, 0.f }, - }; - - rpr_int indices[] = - { - 3,1,0, - 2,1,3, - - 6,4,5, - 7,4,6, - - 11,9,8, - 10,9,11, - - 14,12,13, - 15,12,14, - - 19,17,16, - 18,17,19, - - 22,20,21, - 23,20,22 - }; - - rpr_int num_face_vertices[] = - { - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 - }; - - rpr_shape mesh = NULL; status = rprContextCreateMesh(context, - (rpr_float const*)&cube[0], 24, sizeof(Vertex), - (rpr_float const*)((char*)&cube[0] + sizeof(rpr_float) * 3), 24, sizeof(Vertex), - (rpr_float const*)((char*)&cube[0] + sizeof(rpr_float) * 6), 24, sizeof(Vertex), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - num_face_vertices, 12, &mesh); - - assert(status == RPR_SUCCESS); - - rpr_shape plane_mesh = NULL; status = rprContextCreateMesh(context, - (rpr_float const*)&plane[0], 4, sizeof(Vertex), - (rpr_float const*)((char*)&plane[0] + sizeof(rpr_float) * 3), 4, sizeof(Vertex), - (rpr_float const*)((char*)&plane[0] + sizeof(rpr_float) * 6), 4, sizeof(Vertex), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - num_face_vertices, 2, &plane_mesh); - - rpr_shape mesh1 = NULL; status = rprContextCreateInstance(context, mesh, &mesh1); - assert(status == RPR_SUCCESS); - - //translate cubes - matrix m = translation(float3(-2, 1, 0)); - status = rprShapeSetTransform(mesh1, true, &m.m00); - assert(status == RPR_SUCCESS); - matrix m1 = translation(float3(2, 1, 0)) * rotation_y(0.5); - status = rprShapeSetTransform(mesh, true, &m1.m00); - assert(status == RPR_SUCCESS); - - //attach shapes - status = rprSceneAttachShape(scene, mesh); - assert(status == RPR_SUCCESS); - status = rprSceneAttachShape(scene, mesh1); - assert(status == RPR_SUCCESS); - status = rprSceneAttachShape(scene, plane_mesh); - assert(status == RPR_SUCCESS); - - //camera - rpr_camera camera = NULL; status = rprContextCreateCamera(context, &camera); - assert(status == RPR_SUCCESS); - status = rprCameraLookAt(camera, 0, 3, 10, 0, 0, 0, 0, 1, 0); - assert(status == RPR_SUCCESS); - status = rprCameraSetSensorSize(camera, 22.5f, 15.f); - assert(status == RPR_SUCCESS); - status = rprCameraSetFocalLength(camera, 35.f); - assert(status == RPR_SUCCESS); - status = rprCameraSetFStop(camera, 6.4f); - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, camera); - assert(status == RPR_SUCCESS); - - status = rprContextSetScene(context, scene); - assert(status == RPR_SUCCESS); - - //materials - rpr_material_node diffuse = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_DIFFUSE, &diffuse); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(diffuse, "color", 0.9f, 0.9f, 0.f, 1.0f); - assert(status == RPR_SUCCESS); - rpr_image img = NULL; status = rprContextCreateImageFromFile(context, "../Resources/Textures/test_diffuse.jpg", &img); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputImageData(diffuse, "color", img); - assert(status == RPR_SUCCESS); - rpr_material_node materialNodeTexture = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_IMAGE_TEXTURE, &materialNodeTexture); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputImageData(materialNodeTexture, "data", img); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputN(diffuse, "color", materialNodeTexture); - assert(status == RPR_SUCCESS); - - status = rprShapeSetMaterial(mesh, diffuse); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(mesh1, diffuse); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(plane_mesh, diffuse); - assert(status == RPR_SUCCESS); - - //light - rpr_light light = NULL; status = rprContextCreatePointLight(context, &light); - assert(status == RPR_SUCCESS); - matrix lightm = translation(float3(0, 6, 0)) * rotation_z(3.14f); - status = rprLightSetTransform(light, true, &lightm.m00); - assert(status == RPR_SUCCESS); - status = rprPointLightSetRadiantPower3f(light, 100, 100, 100); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, light); - assert(status == RPR_SUCCESS); - - //result buffer - rpr_framebuffer_desc desc; - desc.fb_width = 800; - desc.fb_height = 600; - rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; - - const std::map kAovs = { {RPR_AOV_COLOR, "RPR_AOV_COLOR"}, - { RPR_AOV_OPACITY, "RPR_AOV_OPACITY" }, - { RPR_AOV_WORLD_COORDINATE, "RPR_AOV_WORLD_COORDINATE"}, - { RPR_AOV_UV, "RPR_AOV_UV"}, - { RPR_AOV_MATERIAL_IDX, "RPR_AOV_MATERIAL_IDX"}, - { RPR_AOV_GEOMETRIC_NORMAL, "RPR_AOV_GEOMETRIC_NORMAL"}, - { RPR_AOV_SHADING_NORMAL, "RPR_AOV_SHADING_NORMAL"}, - { RPR_AOV_DEPTH, "RPR_AOV_DEPTH"}, - { RPR_AOV_OBJECT_ID, "RPR_AOV_OBJECT_ID"}, - { RPR_AOV_OBJECT_GROUP_ID, "RPR_AOV_OBJECT_GROUP_ID"},}; - for (auto aov : kAovs) - { - rpr_framebuffer buf = NULL; status = rprContextCreateFrameBuffer(context, fmt, &desc, &buf); - assert(status == RPR_SUCCESS); - status = rprContextSetAOV(context, aov.first, buf); - //some AOVs not supported now - if (status == FR_ERROR_UNIMPLEMENTED) - { - std::cout << "AOVTest():Warning " << aov.second << " is unsupported" << std::endl; - status = rprObjectDelete(buf); buf = NULL; - continue; - } - status = rprFrameBufferClear(buf); - assert(status == RPR_SUCCESS); - } - - //render - for (int i = 0; i < kRenderIterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - - for (auto aov : kAovs) - { - rpr_framebuffer buf = NULL; - status = rprContextGetAOV(context, aov.first, &buf); - //some AOVs not supported now - if (status == FR_ERROR_UNIMPLEMENTED) - { - continue; - } - const std::string name = "Output/AOVTest_" + aov.second + ".jpg"; - status = rprFrameBufferSaveToFile(buf, name.c_str()); - assert(status == RPR_SUCCESS); - } - - - //cleanup - FR_MACRO_CLEAN_SHAPE_RELEASE(mesh, scene); - FR_MACRO_CLEAN_SHAPE_RELEASE(mesh1, scene); - FR_MACRO_CLEAN_SHAPE_RELEASE(plane_mesh, scene); - FR_MACRO_SAFE_FRDELETE(img); - FR_MACRO_SAFE_FRDELETE(materialNodeTexture); - status = rprSceneDetachLight(scene, light); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(light); light = NULL; - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, NULL); - assert(status == RPR_SUCCESS); - rprObjectDelete(diffuse); - status = rprObjectDelete(scene); scene = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(camera); camera = NULL; - assert(status == RPR_SUCCESS); - - for (auto aov : kAovs) - { - rpr_framebuffer buf = NULL; - status = rprContextGetAOV(context, aov.first, &buf); - //some AOVs not supported now - if (status == FR_ERROR_UNIMPLEMENTED) - { - continue; - } - status = rprObjectDelete(buf); buf = NULL; - assert(status == RPR_SUCCESS); - } - - status = rprObjectDelete(matsys); matsys = NULL; - assert(status == RPR_SUCCESS); -} -void test_feature_cameraDOF() -{ - rpr_int status = RPR_SUCCESS; - //create context, material system and scene - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - rpr_material_system matsys = NULL; - rpr_scene scene = NULL; status = rprContextCreateScene(context, &scene); - assert(status == RPR_SUCCESS); - status = rprContextSetScene(context, scene); - assert(status == RPR_SUCCESS); - - float c = 0.5f; - float d = -7.0f; - float o = -7.0f; - float x = 0.6f; - - Vertex meshVertices[] = - { - { -1.0f*x, (0.0f + 0.5f)*c, 0.0f + o, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f },//0 - { 1.0f*x, (0.0f + 0.5f)*c, 0.0f + o, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f },//1 - { 1.0f*x, (-0.5f + 0.5f)*c, 0.0f + o , 0.0f, 0.0f, 1.0f, 1.0f, 1.0f },//2 - { -1.0f*x, (-0.5f + 0.5f)*c, 0.0f + o , 0.0f, 0.0f, 1.0f, 0.0f, 1.0f },//3 - - { -1.0f*x, (0.0f + 0.8f)*c, 1.0f*d + o, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f },//4 - { 1.0f*x, (0.0f + 0.8f)*c, 1.0f*d + o, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f },//5 - { 1.0f*x, (-0.5f + 0.8f)*c, 1.0f*d + o , 0.0f, 0.0f, 1.0f, 1.0f, 1.0f },//6 - { -1.0f*x, (-0.5f + 0.8f)*c, 1.0f*d + o , 0.0f, 0.0f, 1.0f, 0.0f, 1.0f },//7 - - // in the DOF unit test, we will focus on those 4 vertices : - { -1.0f*x, (0.0f + 1.5f)*c, 2.0f*d + o, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f },//8 - { 1.0f*x, (0.0f + 1.5f)*c, 2.0f*d + o, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f },//9 - { 1.0f*x, (-0.5f + 1.5f)*c, 2.0f*d + o , 0.0f, 0.0f, 1.0f, 1.0f, 1.0f },//10 - { -1.0f*x, (-0.5f + 1.5f)*c, 2.0f*d + o , 0.0f, 0.0f, 1.0f, 0.0f, 1.0f },//11 - - { -1.0f*x, (0.0f + 2.5f)*c, 3.0f*d + o, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f },//12 - { 1.0f*x, (0.0f + 2.5f)*c, 3.0f*d + o, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f },//13 - { 1.0f*x, (-0.5f + 2.5f)*c, 3.0f*d + o , 0.0f, 0.0f, 1.0f, 1.0f, 1.0f },//14 - { -1.0f*x, (-0.5f + 2.5f)*c, 3.0f*d + o , 0.0f, 0.0f, 1.0f, 0.0f, 1.0f },//15 - - { -1.0f*x, (0.0f + 4.0f)*c, 4.0f*d + o, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f },//16 - { 1.0f*x, (0.0f + 4.0f)*c, 4.0f*d + o, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f },//17 - { 1.0f*x, (-0.5f + 4.0f)*c, 4.0f*d + o , 0.0f, 0.0f, 1.0f, 1.0f, 1.0f },//18 - { -1.0f*x, (-0.5f + 4.0f)*c, 4.0f*d + o , 0.0f, 0.0f, 1.0f, 0.0f, 1.0f },//19 - }; - - - rpr_int indices[] = - { - 2,1,0, - 3,2,0, - - 4 + 2,4 + 1,4 + 0, - 4 + 3,4 + 2,4 + 0, - - 8 + 2,8 + 1,8 + 0, - 8 + 3,8 + 2,8 + 0, - - 12 + 2,12 + 1,12 + 0, - 12 + 3,12 + 2,12 + 0, - - 16 + 2,16 + 1,16 + 0, - 16 + 3,16 + 2,16 + 0, - - }; - - rpr_int num_face_vertices[] = - { - 3, 3, - 3, 3, - 3, 3, - 3, 3, - 3, 3, - }; - - //mesh - rpr_shape mesh = 0; status = rprContextCreateMesh(context, - (rpr_float const*)&meshVertices[0], sizeof(meshVertices) / sizeof(meshVertices[0]), sizeof(Vertex), - (rpr_float const*)((char*)&meshVertices[0] + sizeof(rpr_float) * 3), sizeof(meshVertices) / sizeof(meshVertices[0]), sizeof(Vertex), - (rpr_float const*)((char*)&meshVertices[0] + sizeof(rpr_float) * 6), sizeof(meshVertices) / sizeof(meshVertices[0]), sizeof(Vertex), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - num_face_vertices, sizeof(num_face_vertices) / sizeof(num_face_vertices[0]), &mesh); - assert(status == RPR_SUCCESS); - status = rprSceneAttachShape(scene, mesh); - assert(status == RPR_SUCCESS); - - - //set camera - rpr_camera camera = NULL; status = rprContextCreateCamera(context, &camera); - assert(status == RPR_SUCCESS); - status = rprCameraLookAt(camera, 0.0f, +0.6f, 4.0f, 0.0f, +0.6f, 0.0f, 0.0f, 1.0f, 0.0f); - assert(status == RPR_SUCCESS); - status = rprCameraSetFocalLength(camera, 200.0f); - assert(status == RPR_SUCCESS); - status = rprCameraSetFStop(camera, 1.0f); - assert(status == RPR_SUCCESS); - status = rprCameraSetFocusDistance(camera, 25.0f); - assert(status == RPR_SUCCESS); - status = rprCameraSetMode(camera, RPR_CAMERA_MODE_PERSPECTIVE); - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, camera); - assert(status == RPR_SUCCESS); - - //output - rpr_framebuffer_desc desc; - desc.fb_width = 800; - desc.fb_height = 600; - rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; - rpr_framebuffer frame_buffer = NULL; status = rprContextCreateFrameBuffer(context, fmt, &desc, &frame_buffer); - assert(status == RPR_SUCCESS); - status = rprContextSetAOV(context, RPR_AOV_COLOR, frame_buffer); - assert(status == RPR_SUCCESS); - status = rprContextSetParameter1u(context, "rendermode", RPR_RENDER_MODE_GLOBAL_ILLUMINATION); - assert(status == RPR_SUCCESS); - - //light - rpr_light light = NULL; status = rprContextCreatePointLight(context, &light); - assert(status == RPR_SUCCESS); - matrix lightm = translation(float3(0.0f, +0.6f, 4.0f)); - status = rprLightSetTransform(light, true, &lightm.m00); - assert(status == RPR_SUCCESS); - status = rprPointLightSetRadiantPower3f(light, 1000, 1000, 1000); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, light); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - - //render - for (rpr_uint i = 0; i< kRenderIterations; i++) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - rprFrameBufferSaveToFile(frame_buffer, "Output/feature_cameraDOF.png"); - - //cleanup - status = rprSceneDetachLight(scene, light); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(light); light = NULL; - assert(status == RPR_SUCCESS); - FR_MACRO_CLEAN_SHAPE_RELEASE(mesh, scene); - status = rprSceneSetCamera(scene, NULL); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(scene); scene = NULL; - assert(status == RPR_SUCCESS); - - status = rprObjectDelete(camera); camera = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(frame_buffer); frame_buffer = NULL; - assert(status == RPR_SUCCESS); - -} - -void test_feature_ContextImageFromData() -{ - rpr_int status = RPR_SUCCESS; - - //create context and scene - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - rpr_material_system matsys = NULL; - status = rprContextCreateMaterialSystem(context, 0, &matsys); - assert(status == RPR_SUCCESS); - rpr_scene scene = NULL; - status = rprContextCreateScene(context, &scene); - assert(status == RPR_SUCCESS); - status = rprContextSetScene(context, scene); - assert(status == RPR_SUCCESS); - - //texture - rpr_image_format imageFormat; - memset(&imageFormat, 0, sizeof(imageFormat)); - imageFormat.num_components = 4; - imageFormat.type = RPR_COMPONENT_TYPE_FLOAT32; - rpr_image_desc imageDesc; - memset(&imageDesc, 0, sizeof(imageDesc)); - imageDesc.image_depth = 1; - imageDesc.image_width = 32; - imageDesc.image_height = 32; - imageDesc.image_row_pitch = imageDesc.image_width * sizeof(float) * 4; - imageDesc.image_slice_pitch = imageDesc.image_width * imageDesc.image_height * sizeof(float) * 4; - std::vector dataImage(imageDesc.image_width * imageDesc.image_height * 4); - - //first : fill texture with red - for (rpr_uint y = 0; y().swap(dataImage); - - //mesh - Vertex meshVertices[] = { { -2.0f, 2.0f, 0.0f, 0.0f, 0.0f, +1.0f, 0.0f, 0.0f }, - { 2.0f, 2.0f, 0.0f, 0.0f, 0.0f, +1.0f, 1.0f, 0.0f }, - { 2.0f, -2.0f, 0.0f, 0.0f, 0.0f, +1.0f, 1.0f, 1.0f }, - { -2.0f, -2.0f, 0.0f, 0.0f, 0.0f, +1.0f, 0.0f, 1.0f }, }; - rpr_int indices[] = { 3, 2, 1, 0, }; - rpr_int num_face_vertices[] = { 4, }; - - rpr_shape mesh = 0; - status = rprContextCreateMesh(context, - (rpr_float const*)&meshVertices[0], 4, sizeof(Vertex), - (rpr_float const*)((char*)&meshVertices[0] + sizeof(rpr_float) * 3), 4, sizeof(Vertex), - (rpr_float const*)((char*)&meshVertices[0] + sizeof(rpr_float) * 6), 4, sizeof(Vertex), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - num_face_vertices, 1, &mesh); - assert(status == RPR_SUCCESS); - status = rprSceneAttachShape(scene, mesh); - assert(status == RPR_SUCCESS); - - //materials - rpr_material_node textureNormalMap = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_IMAGE_TEXTURE, &textureNormalMap); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputImageData(textureNormalMap, "data", imageBuilt); - assert(status == RPR_SUCCESS); - rpr_material_node diffuseSphere = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_DIFFUSE, &diffuseSphere); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputN(diffuseSphere, "color", textureNormalMap); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(mesh, diffuseSphere); - assert(status == RPR_SUCCESS); - - //camera - rpr_camera camera = NULL; status = rprContextCreateCamera(context, &camera); - assert(status == RPR_SUCCESS); - status = rprCameraLookAt(camera, 0, 0, 7, 0, 0, 0, 0, 1, 0); - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, camera); - assert(status == RPR_SUCCESS); - - //light - rpr_light light = NULL; status = rprContextCreatePointLight(context, &light); - assert(status == RPR_SUCCESS); - matrix lightm = translation(float3(0, 0, 4)) * rotation_z(3.14f); - status = rprLightSetTransform(light, true, &lightm.m00); - assert(status == RPR_SUCCESS); - status = rprPointLightSetRadiantPower3f(light, 40, 40, 40); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, light); - assert(status == RPR_SUCCESS); - - //output - rpr_framebuffer_desc desc; - desc.fb_width = 800; - desc.fb_height = 600; - rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; - rpr_framebuffer frame_buffer = NULL; status = rprContextCreateFrameBuffer(context, fmt, &desc, &frame_buffer); - assert(status == RPR_SUCCESS); - status = rprContextSetAOV(context, RPR_AOV_COLOR, frame_buffer); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - - //render - for (rpr_uint i = 0; i < kRenderIterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - rprFrameBufferSaveToFile(frame_buffer, "Output/feature_ContextImageFromData.png"); - - //cleanup - FR_MACRO_SAFE_FRDELETE(textureNormalMap); - status = rprObjectDelete(imageBuilt); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(frame_buffer); frame_buffer = NULL; - assert(status == RPR_SUCCESS); - status = rprSceneDetachLight(scene, light); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(light); light = NULL; - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, NULL); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(camera); camera = NULL; - assert(status == RPR_SUCCESS); - FR_MACRO_CLEAN_SHAPE_RELEASE(mesh, scene); - status = rprObjectDelete(diffuseSphere); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(scene); scene = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(matsys); matsys = NULL; - assert(status == RPR_SUCCESS); -} - -//test RPR_MATERIAL_NODE_INPUT_LOOKUP and rprContextCreateMeshEx unsupported -void test_feature_multiUV() -{ - rpr_int status = RPR_SUCCESS; - - //create context and scene - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - assert(status == RPR_SUCCESS); - rpr_material_system matsys = NULL; - status = rprContextCreateMaterialSystem(context, 0, &matsys); - assert(status == RPR_SUCCESS); - rpr_scene scene = NULL; status = rprContextCreateScene(context, &scene); - assert(status == RPR_SUCCESS); - status = rprContextSetScene(context, scene); - assert(status == RPR_SUCCESS); - - - rpr_material_node uv_node = NULL; - status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_INPUT_LOOKUP, &uv_node); - assert(status == RPR_ERROR_UNSUPPORTED); - - VertexMT meshVertices[] = - { - { -2.0f, 2.0f, 0.0f, 0.0f, 0.0f, +1.0f, 0.0f, 0.0f , 1.0f, 1.0f }, - { 2.0f, 2.0f, 0.0f, 0.0f, 0.0f, +1.0f, 1.0f, 0.0f , 0.0f, 1.0f }, - { 2.0f, -2.0f, 0.0f , 0.0f, 0.0f, +1.0f, 1.0f, 1.0f , 0.0f, 0.0f }, - { -2.0f, -2.0f, 0.0f , 0.0f, 0.0f, +1.0f, 0.0f, 1.0f , 1.0f, 0.0f }, - }; - rpr_int indices[] = - { - 3,2,1,0, - }; - rpr_int num_face_vertices[] = - { - 4, - }; - - //TODO: codestyle - unsigned int meshVertices_nbOfElement = sizeof(meshVertices) / sizeof(meshVertices[0]); - unsigned int num_face_vertices_nbOfElement = sizeof(num_face_vertices) / sizeof(num_face_vertices[0]); - rpr_shape mesh = 0; - - const rpr_float* texcoords[] = { (rpr_float const*)((char*)&meshVertices[0] + sizeof(rpr_float) * 6), (rpr_float const*)((char*)&meshVertices[0] + sizeof(rpr_float) * 8) }; - size_t num_texcoords[] = { meshVertices_nbOfElement, meshVertices_nbOfElement }; - rpr_int texcoord_stride[] = { sizeof(VertexMT) , sizeof(VertexMT) }; - const rpr_int* texcoord_indices_[] = { indices, indices }; - rpr_int tidx_stride_[] = { sizeof(rpr_int) ,sizeof(rpr_int) }; - - status = rprContextCreateMeshEx(context, - (rpr_float const*)&meshVertices[0], meshVertices_nbOfElement, sizeof(VertexMT), - (rpr_float const*)((char*)&meshVertices[0] + sizeof(rpr_float) * 3), meshVertices_nbOfElement, sizeof(VertexMT), - nullptr, 0, 0, - 2, - texcoords, num_texcoords, texcoord_stride, - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - - texcoord_indices_, tidx_stride_, - - num_face_vertices, num_face_vertices_nbOfElement, &mesh); - assert(status == RPR_ERROR_UNSUPPORTED); - - //cleanup - status = rprSceneSetCamera(scene, NULL); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(scene); scene = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(matsys); matsys = NULL; - assert(status == RPR_SUCCESS); -} - -void test_apiMecha_Light() -{ - rpr_int status = RPR_SUCCESS; - //create context and scene - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - assert(status == RPR_SUCCESS); - rpr_scene scene = NULL; status = rprContextCreateScene(context, &scene); - assert(status == RPR_SUCCESS); - - for (rpr_int iter = 0; iter<3; iter++)//add/destroy several times - { - - rpr_light lightDir = NULL; status = rprContextCreateDirectionalLight(context, &lightDir); - assert(status == RPR_SUCCESS); - rpr_light lightEnv = NULL; status = rprContextCreateEnvironmentLight(context, &lightEnv); - assert(status == RPR_SUCCESS); - rpr_light lightPoint = NULL; status = rprContextCreatePointLight(context, &lightPoint); - assert(status == RPR_SUCCESS); - rpr_light lightSpot = NULL; status = rprContextCreateSpotLight(context, &lightSpot); - assert(status == RPR_SUCCESS); - - matrix transform = translation(float3(-0.7f, 0.5f, 1.5f)); - - status = rprLightSetTransform(lightDir, true, &transform.m00); - assert(status == RPR_SUCCESS); - status = rprLightSetTransform(lightEnv, true, &transform.m00); - assert(status == RPR_SUCCESS); - status = rprLightSetTransform(lightPoint, true, &transform.m00); - assert(status == RPR_SUCCESS); - status = rprLightSetTransform(lightSpot, true, &transform.m00); - assert(status == RPR_SUCCESS); - - size_t querrySize = 0; - char* querryData = (char*)malloc(1); - - for (rpr_int i = 0; i<4; i++) - { - rpr_light pLightTest = NULL; - rpr_light_type LightTypeShouldBe = 0; - if (i == 0) { pLightTest = lightDir; LightTypeShouldBe = RPR_LIGHT_TYPE_DIRECTIONAL; } - else if (i == 1) { pLightTest = lightEnv; LightTypeShouldBe = RPR_LIGHT_TYPE_ENVIRONMENT; } - else if (i == 2) { pLightTest = lightPoint; LightTypeShouldBe = RPR_LIGHT_TYPE_POINT; } - else if (i == 3) { pLightTest = lightSpot; LightTypeShouldBe = RPR_LIGHT_TYPE_SPOT; } - else { assert(false); } - - status = rprLightGetInfo(pLightTest, RPR_LIGHT_TRANSFORM, 0, NULL, &querrySize); - assert(status == RPR_SUCCESS); - querryData = (char*)realloc(querryData, querrySize); - status = rprLightGetInfo(pLightTest, RPR_LIGHT_TRANSFORM, querrySize, querryData, NULL); - assert(status == RPR_SUCCESS); - if (querrySize != sizeof(matrix)) { assert(false); } - if (memcmp(querryData, &transform.m00, querrySize) != 0) { assert(false); } - - status = rprLightGetInfo(pLightTest, RPR_LIGHT_TYPE, 0, NULL, &querrySize); - assert(status == RPR_SUCCESS); - querryData = (char*)realloc(querryData, querrySize); - status = rprLightGetInfo(pLightTest, RPR_LIGHT_TYPE, querrySize, querryData, NULL); - assert(status == RPR_SUCCESS); - if (querrySize != sizeof(rpr_light_type)) { assert(false); } - if (memcmp(querryData, &LightTypeShouldBe, querrySize) != 0) { assert(false); } - } - - free(querryData); querryData = NULL; - - //attach - status = rprSceneAttachLight(scene, lightDir); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, lightEnv); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, lightPoint); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, lightSpot); - assert(status == RPR_SUCCESS); - - //detach - status = rprSceneDetachLight(scene, lightDir); - assert(status == RPR_SUCCESS); - status = rprSceneDetachLight(scene, lightEnv); - assert(status == RPR_SUCCESS); - status = rprSceneDetachLight(scene, lightPoint); - assert(status == RPR_SUCCESS); - status = rprSceneDetachLight(scene, lightSpot); - assert(status == RPR_SUCCESS); - - //cleanup - status = rprObjectDelete(lightDir); lightDir = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(lightEnv); lightEnv = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(lightPoint); lightPoint = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(lightSpot); lightSpot = NULL; - assert(status == RPR_SUCCESS); - } - - status = rprObjectDelete(scene); scene = NULL; - assert(status == RPR_SUCCESS); -} - -void test_feature_LightDirectional() -{ - rpr_int status = RPR_SUCCESS; - - //create context and scene - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - assert(status == RPR_SUCCESS); - rpr_material_system matsys = NULL; - status = rprContextCreateMaterialSystem(context, 0, &matsys); - assert(status == RPR_SUCCESS); - rpr_scene scene = NULL; status = rprContextCreateScene(context, &scene); - assert(status == RPR_SUCCESS); - status = rprContextSetScene(context, scene); - assert(status == RPR_SUCCESS); - - //vertex data - float c = 0.5f; - float d = -7.0f; - float o = -7.0f; - float x = 0.6f; - - Vertex meshVertices[] = - { - { -2.0f, 2.0f, 0.0f, 0.0f, 0.0f, +1.0f, 0.0f, 0.0f }, - { 2.0f, 2.0f, 0.0f, 0.0f, 0.0f, +1.0f, 1.0f, 0.0f }, - { 2.0f, -2.0f, 0.0f , 0.0f, 0.0f, +1.0f, 1.0f, 1.0f }, - { -2.0f, -2.0f, 0.0f , 0.0f, 0.0f, +1.0f, 0.0f, 1.0f }, - }; - rpr_int indices[] = - { - 3,2,1,0, - }; - rpr_int num_face_vertices[] = - { - 4, - }; - - //mesh - rpr_shape mesh = 0; status = rprContextCreateMesh(context, - (rpr_float const*)&meshVertices[0], sizeof(meshVertices) / sizeof(meshVertices[0]), sizeof(Vertex), - (rpr_float const*)((char*)&meshVertices[0] + sizeof(rpr_float) * 3), sizeof(meshVertices) / sizeof(meshVertices[0]), sizeof(Vertex), - (rpr_float const*)((char*)&meshVertices[0] + sizeof(rpr_float) * 6), sizeof(meshVertices) / sizeof(meshVertices[0]), sizeof(Vertex), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - num_face_vertices, sizeof(num_face_vertices) / sizeof(num_face_vertices[0]), &mesh); - status = rprSceneAttachShape(scene, mesh); - assert(status == RPR_SUCCESS); - //camera - rpr_camera camera = NULL; status = rprContextCreateCamera(context, &camera); - assert(status == RPR_SUCCESS); - status = rprCameraLookAt(camera, 0, 0, 7, 0, 0, 0, 0, 1, 0); - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, camera); - assert(status == RPR_SUCCESS); - - - rpr_framebuffer_desc desc; - desc.fb_width = 800; - desc.fb_height = 600; - - //shader - rpr_material_node shader_lambert = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_DIFFUSE, &shader_lambert); - status = rprMaterialNodeSetInputF(shader_lambert, "color", 0.0f, 0.5f, 1.0f, 1.0f); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(mesh, shader_lambert); - assert(status == RPR_SUCCESS); - - - //light - rpr_light light = NULL; status = rprContextCreateDirectionalLight(context, &light); - assert(status == RPR_SUCCESS); - matrix lightm = translation(float3(1.0f, 0.0f, 1.0f)) * rotation_y(0.5f*3.14f / 2.0f); - status = rprLightSetTransform(light, true, &lightm.m00); - assert(status == RPR_SUCCESS); - status = rprDirectionalLightSetRadiantPower3f(light, 1.0f, 1.0f, 1.0f); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, light); - assert(status == RPR_SUCCESS); - - - rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; - rpr_framebuffer frame_buffer = NULL; status = rprContextCreateFrameBuffer(context, fmt, &desc, &frame_buffer); - assert(status == RPR_SUCCESS); - - status = rprContextSetAOV(context, RPR_AOV_COLOR, frame_buffer); - assert(status == RPR_SUCCESS); - - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - - //render - for (rpr_uint i = 0; i instances; - std::vector materials; - - for (auto x = -20; x <= 20; x+= 2) - for (auto y = -20; y <= 20; y += 2) - { - if (x == 0 && y == 0) continue; - rpr_shape instance = nullptr; - status = rprContextCreateInstance(context, mesh, &instance); - assert(status == RPR_SUCCESS); - - float s = 0.75f + rand_float(); - matrix m = translation(float3(x, y, rand_float() * 10.f - 5.f)) * scale(float3(s, s, s)); - status = rprShapeSetTransform(instance, true, &m.m00); - assert(status == RPR_SUCCESS); - - status = rprSceneAttachShape(scene, instance); - assert(status == RPR_SUCCESS); - - if (rand_float() < 0.1) - { - rpr_material_node mat = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_DIFFUSE, &mat); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(mat, "color", rand_float(), rand_float(), rand_float(), 1.f); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(instance, mat); - assert(status == RPR_SUCCESS); - materials.push_back(mat); - } - else if (rand_float() < 0.5) - { - rpr_material_node spec = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_MICROFACET, &spec); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(spec, "color", rand_float(), rand_float(), rand_float(), 1.f); - status = rprMaterialNodeSetInputF(spec, "roughness", 0.5f * rand_float(), 0.5f * rand_float(), 0.5f * rand_float(), 1.f); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(instance, spec); - assert(status == RPR_SUCCESS); - materials.push_back(spec); - } - else - { - rpr_material_node mat = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_DIFFUSE, &mat); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(mat, "color", rand_float(), rand_float(), rand_float(), 1.f); - assert(status == RPR_SUCCESS); - materials.push_back(mat); - rpr_material_node spec = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_MICROFACET, &spec); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(spec, "color", rand_float(), rand_float(), rand_float(), 1.f); - status = rprMaterialNodeSetInputF(spec, "roughness", 0.1f * rand_float(), 0.1f * rand_float(), 0.1f * rand_float(), 1.f); - assert(status == RPR_SUCCESS); - materials.push_back(spec); - rpr_material_node layered = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_BLEND, &layered); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputN(layered, "color0", mat); - status = rprMaterialNodeSetInputN(layered, "color1", spec); - assert(status == RPR_SUCCESS); - rpr_material_node fresnel = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_FRESNEL, &fresnel); - assert(status == RPR_SUCCESS); - - auto ior = 1.f + rand_float() * 2.f; - status = rprMaterialNodeSetInputF(fresnel, "ior", ior, ior, ior, ior); - assert(status == RPR_SUCCESS); - materials.push_back(fresnel); - status = rprMaterialNodeSetInputN(layered, "weight", fresnel); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(instance, layered); - assert(status == RPR_SUCCESS); - materials.push_back(layered); - } - - instances.push_back(instance); - } - - rpr_light light = NULL; status = rprContextCreateEnvironmentLight(context, &light); - assert(status == RPR_SUCCESS); - rpr_image imageInput = NULL; status = rprContextCreateImageFromFile(context, "../Resources/Textures/studio015.hdr", &imageInput); - assert(status == RPR_SUCCESS); - status = rprEnvironmentLightSetImage(light, imageInput); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, light); - assert(status == RPR_SUCCESS); - - //camera - rpr_camera camera = NULL; status = rprContextCreateCamera(context, &camera); - assert(status == RPR_SUCCESS); - status = rprCameraLookAt(camera, 0, 0, 20, 0, 0, 0, 0, 1, 0); - assert(status == RPR_SUCCESS); - status = rprCameraSetFocalLength(camera, 23.f); - assert(status == RPR_SUCCESS); - //status = rprCameraSetFStop(camera, 5.4f); - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, camera); - assert(status == RPR_SUCCESS); - - status = rprContextSetScene(context, scene); - assert(status == RPR_SUCCESS); - - //light - - //setup out - rpr_framebuffer_desc desc; - desc.fb_width = 800; - desc.fb_height = 600; - - rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; - rpr_framebuffer frame_buffer = NULL; status = rprContextCreateFrameBuffer(context, fmt, &desc, &frame_buffer); - assert(status == RPR_SUCCESS); - status = rprContextSetAOV(context, RPR_AOV_COLOR, frame_buffer); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); assert(status == RPR_SUCCESS); - - //change light - status = rprFrameBufferClear(frame_buffer); assert(status == RPR_SUCCESS); - assert(status == RPR_SUCCESS); - - for (int i = 0; i < kRenderIterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - - status = rprFrameBufferSaveToFile(frame_buffer, "Output/ManySpheresTest.jpg"); - assert(status == RPR_SUCCESS); - rpr_render_statistics rs; - status = rprContextGetInfo(context, RPR_CONTEXT_RENDER_STATISTICS, sizeof(rpr_render_statistics), &rs, NULL); - assert(status == RPR_SUCCESS); - - - //cleanup - for (auto& i : instances) - { - status = rprObjectDelete(i); - assert(status == RPR_SUCCESS); - } - - for (auto& i : materials) - { - status = rprObjectDelete(i); - assert(status == RPR_SUCCESS); - } - - status = rprSceneDetachLight(scene, light); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(light); light = NULL; - assert(status == RPR_SUCCESS); - rprObjectDelete(diffuse); - status = rprSceneSetCamera(scene, NULL); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(scene); scene = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(camera); camera = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(frame_buffer); frame_buffer = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(matsys); matsys = NULL; - assert(status == RPR_SUCCESS); -} - -void BumpmapTest() -{ - rpr_int status = RPR_SUCCESS; - //context and scene - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - assert(status == RPR_SUCCESS); - rpr_material_system matsys = NULL; - status = rprContextCreateMaterialSystem(context, 0, &matsys); - assert(status == RPR_SUCCESS); - rpr_scene scene = NULL; status = rprContextCreateScene(context, &scene); - assert(status == RPR_SUCCESS); - status = rprContextSetScene(context, scene); - assert(status == RPR_SUCCESS); - - struct vertex - { - rpr_float pos[3]; - rpr_float norm[3]; - rpr_float tex[2]; - }; - - vertex quad[] = - { - { -5.0f, -1.0f, -5.0f, 0.f, 1.f, 0.f, 0.f, 0.f }, - { 5.0f, -1.0f, -5.0f, 0.f, 1.f, 0.f, 1.f, 0.f }, - { 5.0f, -1.0f, 5.0f, 0.f, 1.f, 0.f, 1.f, 1.f }, - { -5.0f, -1.0f, 5.0f, 0.f, 1.f, 0.f, 0.f, 1.f }, - }; - - - rpr_int indices[] = - { - 3,1,0, - 2,1,3, - }; - - rpr_int num_face_vertices[] = - { - 3, 3 - }; - - rpr_shape mesh = NULL; status = rprContextCreateMesh(context, - (rpr_float const*)&quad[0], 4, sizeof(vertex), - (rpr_float const*)((char*)&quad[0] + sizeof(rpr_float) * 3), 4, sizeof(vertex), - (rpr_float const*)((char*)&quad[0] + sizeof(rpr_float) * 6), 4, sizeof(vertex), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - num_face_vertices, 2, &mesh); - assert(status == RPR_SUCCESS); - status = rprSceneAttachShape(scene, mesh); - assert(status == RPR_SUCCESS); - - //materials - rpr_image img = NULL; status = rprContextCreateImageFromFile(context, "../Resources/Textures/test_diffuse.jpg", &img); - assert(status == RPR_SUCCESS); - rpr_material_node materialNodeTextureA = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_IMAGE_TEXTURE, &materialNodeTextureA); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputImageData(materialNodeTextureA, "data", img); - assert(status == RPR_SUCCESS); - - rpr_image imgBump = NULL; status = rprContextCreateImageFromFile(context, "../Resources/Textures/test_normal.jpg", &imgBump); - assert(status == RPR_SUCCESS); - rpr_material_node materialNodeTextureB = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_NORMAL_MAP, &materialNodeTextureB); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputImageData(materialNodeTextureB, "data", imgBump); - assert(status == RPR_SUCCESS); - - //camera - rpr_camera camera = NULL; status = rprContextCreateCamera(context, &camera); - assert(status == RPR_SUCCESS); - status = rprCameraLookAt(camera, 0, 3, 10, 0, 0, 0, 0, 1, 0); - assert(status == RPR_SUCCESS); - status = rprCameraSetFocalLength(camera, 50.f); - assert(status == RPR_SUCCESS); - status = rprCameraSetFStop(camera, 5.4f); - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, camera); - assert(status == RPR_SUCCESS); - - //material - rpr_material_node diffuse = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_DIFFUSE, &diffuse); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(diffuse, "color", 1, 1, 1, 1); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputN(diffuse, "color", materialNodeTextureA); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputN(diffuse, "normal", materialNodeTextureB); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(mesh, diffuse); - assert(status == RPR_SUCCESS); - - //light - rpr_light light = NULL; status = rprContextCreatePointLight(context, &light); - assert(status == RPR_SUCCESS); - matrix lightm = translation(float3(0, 6, 0)); - status = rprLightSetTransform(light, true, &lightm.m00); - assert(status == RPR_SUCCESS); - status = rprPointLightSetRadiantPower3f(light, 200, 200, 200); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, light); - assert(status == RPR_SUCCESS); - - //output - rpr_framebuffer_desc desc; - desc.fb_width = 800; - desc.fb_height = 600; - rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; - rpr_framebuffer frame_buffer = NULL; status = rprContextCreateFrameBuffer(context, fmt, &desc, &frame_buffer); - assert(status == RPR_SUCCESS); - status = rprContextSetAOV(context, RPR_AOV_COLOR, frame_buffer); - assert(status == RPR_SUCCESS); - - //unsupported: - //status = rprContextSetParameter1u(context, "rendermode", RPR_RENDER_MODE_NORMAL); - //assert(status == RPR_SUCCESS); - //status = rprContextSetParameter1u(context, "xflip", 0); - //assert(status == RPR_SUCCESS); - //status = rprContextSetParameter1u(context, "yflip", 1); - //assert(status == RPR_SUCCESS); - - //render - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - for (int i = 0; i < 100; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - rprFrameBufferSaveToFile(frame_buffer, "Output/BumpMap_Stage1.png"); - - //cleanup - FR_MACRO_SAFE_FRDELETE(materialNodeTextureA); - FR_MACRO_SAFE_FRDELETE(materialNodeTextureB); - FR_MACRO_SAFE_FRDELETE(img); - FR_MACRO_SAFE_FRDELETE(imgBump); - status = rprSceneDetachLight(scene, light); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(light); light = NULL; - assert(status == RPR_SUCCESS); - FR_MACRO_CLEAN_SHAPE_RELEASE(mesh, scene); - rprObjectDelete(diffuse); - status = rprSceneSetCamera(scene, NULL); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(scene); scene = NULL; - assert(status == RPR_SUCCESS); - - status = rprObjectDelete(camera); camera = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(frame_buffer); frame_buffer = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(matsys); matsys = NULL; - assert(status == RPR_SUCCESS); -} - -void test_feature_shaderBumpmap() -{ - rpr_int status = RPR_SUCCESS; - //create scene and context - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - assert(status == RPR_SUCCESS); - rpr_material_system matsys = NULL; - status = rprContextCreateMaterialSystem(context, 0, &matsys); - assert(status == RPR_SUCCESS); - rpr_scene scene = NULL; status = rprContextCreateScene(context, &scene); - assert(status == RPR_SUCCESS); - status = rprContextSetScene(context, scene); - assert(status == RPR_SUCCESS); - - //materials - rpr_material_node shaderMicrofacet = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_MICROFACET, &shaderMicrofacet); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(shaderMicrofacet, "color", 0.3f, 0.7f, 0.9f, 1.0f); - assert(status == RPR_SUCCESS); - - rpr_image imageInputA = NULL; status = rprContextCreateImageFromFile(context, "../Resources/Textures/test_bump.jpg", &imageInputA); - assert(status == RPR_SUCCESS); - rpr_material_node textureNormalMap = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_BUMP_MAP, &textureNormalMap); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputImageData(textureNormalMap, "data", imageInputA); - assert(status == RPR_SUCCESS); - - status = rprMaterialNodeSetInputN(shaderMicrofacet, "normal", textureNormalMap); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(shaderMicrofacet, "ior", 1.3f, 0.0f, 0.0f, 0.0f); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(shaderMicrofacet, "roughness", 0.5f, 0.0f, 0.0f, 0.0f); - assert(status == RPR_SUCCESS); - - Vertex meshVertices[] = - { - { -2.0f, 2.0f, 0.0f, 0.0f, 0.0f, +1.0f, 0.0f, 0.0f }, - { 2.0f, 2.0f, 0.0f, 0.0f, 0.0f, +1.0f, 1.0f, 0.0f }, - { 2.0f, -2.0f, 0.0f , 0.0f, 0.0f, +1.0f, 1.0f, 1.0f }, - { -2.0f, -2.0f, 0.0f , 0.0f, 0.0f, +1.0f, 0.0f, 1.0f }, - }; - rpr_int indices[] = - { - 3,2,1,0, - }; - rpr_int num_face_vertices[] = - { - 4, - }; - - //mesh - rpr_shape mesh = 0; status = rprContextCreateMesh(context, - (rpr_float const*)&meshVertices[0], sizeof(meshVertices) / sizeof(meshVertices[0]), sizeof(Vertex), - (rpr_float const*)((char*)&meshVertices[0] + sizeof(rpr_float) * 3), sizeof(meshVertices) / sizeof(meshVertices[0]), sizeof(Vertex), - (rpr_float const*)((char*)&meshVertices[0] + sizeof(rpr_float) * 6), sizeof(meshVertices) / sizeof(meshVertices[0]), sizeof(Vertex), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - num_face_vertices, sizeof(num_face_vertices) / sizeof(num_face_vertices[0]), &mesh); - - status = rprShapeSetMaterial(mesh, shaderMicrofacet); - assert(status == RPR_SUCCESS); - status = rprSceneAttachShape(scene, mesh); - assert(status == RPR_SUCCESS); - - //camera - rpr_camera camera = NULL; status = rprContextCreateCamera(context, &camera); - assert(status == RPR_SUCCESS); - status = rprCameraLookAt(camera, 0, 0, 7, 0, 0, 0, 0, 1, 0); - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, camera); - assert(status == RPR_SUCCESS); - - //light - rpr_light light = NULL; status = rprContextCreatePointLight(context, &light); - assert(status == RPR_SUCCESS); - matrix lightm = translation(float3(0, 0, 4)) * rotation_z(3.14f); - status = rprLightSetTransform(light, true, &lightm.m00); - assert(status == RPR_SUCCESS); - status = rprPointLightSetRadiantPower3f(light, 40, 40, 40); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, light); - assert(status == RPR_SUCCESS); - - //output - rpr_framebuffer_desc desc; - desc.fb_width = 800; - desc.fb_height = 600; - rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; - rpr_framebuffer frame_buffer = NULL; status = rprContextCreateFrameBuffer(context, fmt, &desc, &frame_buffer); - assert(status == RPR_SUCCESS); - status = rprContextSetAOV(context, RPR_AOV_COLOR, frame_buffer); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - - //render - for (rpr_uint i = 0; i < kRenderIterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - rprFrameBufferSaveToFile(frame_buffer, "Output/feature_shaderBumpmap_0.png"); - - //dynamic : change parameters - status = rprMaterialNodeSetInputF(shaderMicrofacet, "color", 0.9f, 0.7f, 0.3f, 1.0f); - assert(status == RPR_SUCCESS); - - rpr_image imageInputB = NULL; status = rprContextCreateImageFromFile(context, "../Resources/Textures/test_bump.jpg", &imageInputB); - assert(status == RPR_SUCCESS); - rpr_material_node textureNormalMap2 = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_BUMP_MAP, &textureNormalMap2); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputImageData(textureNormalMap2, "data", imageInputB); - assert(status == RPR_SUCCESS); - - status = rprMaterialNodeSetInputN(shaderMicrofacet, "normal", textureNormalMap2); - assert(status == RPR_SUCCESS); - - status = rprMaterialNodeSetInputF(shaderMicrofacet, "ior", 1.3f, 0.0f, 0.0f, 0.0f); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - for (rpr_uint i = 0; i < kRenderIterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - rprFrameBufferSaveToFile(frame_buffer, "Output/feature_shaderBumpmap_1.png"); - - - //dynamic : change parameters - //unsupported: - //status = rprMaterialNodeSetInputF(textureNormalMap2, "bumpscale", 2.0f, 1.0f, 1.0f, 1.0f); - //assert(status == RPR_SUCCESS); - - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - for (rpr_uint i = 0; i < kRenderIterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - rprFrameBufferSaveToFile(frame_buffer, "Output/feature_shaderBumpmap_2.png"); - - - status = rprObjectDelete(imageInputA); imageInputA = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(imageInputB); imageInputB = NULL; - assert(status == RPR_SUCCESS); - FR_MACRO_SAFE_FRDELETE(textureNormalMap); - FR_MACRO_SAFE_FRDELETE(textureNormalMap2); - FR_MACRO_CLEAN_SHAPE_RELEASE(mesh, scene); - status = rprSceneDetachLight(scene, light); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(light); light = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(shaderMicrofacet); - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, NULL); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(scene); scene = NULL; - assert(status == RPR_SUCCESS); - - status = rprObjectDelete(camera); camera = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(frame_buffer); frame_buffer = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(matsys); matsys = NULL; - assert(status == RPR_SUCCESS); -} - -void test_feature_shaderTypeLayered() -{ - rpr_int status = RPR_SUCCESS; - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - assert(status == RPR_SUCCESS); - rpr_material_system matsys = NULL; - status = rprContextCreateMaterialSystem(context, 0, &matsys); - assert(status == RPR_SUCCESS); - rpr_scene scene = NULL; status = rprContextCreateScene(context, &scene); - assert(status == RPR_SUCCESS); - status = rprContextSetScene(context, scene); - assert(status == RPR_SUCCESS); - - //materials - rpr_material_node diffuseSphere = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_DIFFUSE, &diffuseSphere); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(diffuseSphere, "color", 0.0f, 0.0f, 1.0f, 1.0f); - assert(status == RPR_SUCCESS); - rpr_material_node specularSphere = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_MICROFACET, &specularSphere); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(specularSphere, "color", 0.1f, 0.9f, 0.2f, 1.0f); - assert(status == RPR_SUCCESS); - rpr_image imageInputA = NULL; status = rprContextCreateImageFromFile(context, "../Resources/Textures/test_normal.jpg", &imageInputA); - assert(status == RPR_SUCCESS); - rpr_material_node textureNormalMap = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_NORMAL_MAP, &textureNormalMap); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputImageData(textureNormalMap, "data", imageInputA); - assert(status == RPR_SUCCESS); - - status = rprMaterialNodeSetInputN(specularSphere, "normal", textureNormalMap); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(specularSphere, "ior", 1.3f, 0.0f, 0.0f, 0.0f); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(specularSphere, "roughness", 0.5f, 0.0f, 0.0f, 0.0f); - assert(status == RPR_SUCCESS); - - rpr_material_node layered = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_BLEND, &layered); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputN(layered, "color1", specularSphere); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputN(layered, "color0", diffuseSphere); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(layered, "weight", 0.4f, 0.0f, 0.0f, 0.0f); - assert(status == RPR_SUCCESS); - - Vertex meshVertices[] = - { - { -2.0f, 2.0f, 0.0f, 0.0f, 0.0f, +1.0f, 0.0f, 0.0f }, - { 2.0f, 2.0f, 0.0f, 0.0f, 0.0f, +1.0f, 1.0f, 0.0f }, - { 2.0f, -2.0f, 0.0f , 0.0f, 0.0f, +1.0f, 1.0f, 1.0f }, - { -2.0f, -2.0f, 0.0f , 0.0f, 0.0f, +1.0f, 0.0f, 1.0f }, - }; - rpr_int indices[] = - { - 3,2,1,0, - }; - rpr_int num_face_vertices[] = - { - 4, - }; - - //mesh - rpr_shape mesh = 0; status = rprContextCreateMesh(context, - (rpr_float const*)&meshVertices[0], sizeof(meshVertices) / sizeof(meshVertices[0]), sizeof(Vertex), - (rpr_float const*)((char*)&meshVertices[0] + sizeof(rpr_float) * 3), sizeof(meshVertices) / sizeof(meshVertices[0]), sizeof(Vertex), - (rpr_float const*)((char*)&meshVertices[0] + sizeof(rpr_float) * 6), sizeof(meshVertices) / sizeof(meshVertices[0]), sizeof(Vertex), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - (rpr_int const*)indices, sizeof(rpr_int), - num_face_vertices, sizeof(num_face_vertices) / sizeof(num_face_vertices[0]), &mesh); - - status = rprShapeSetMaterial(mesh, layered); - assert(status == RPR_SUCCESS); - status = rprSceneAttachShape(scene, mesh); - assert(status == RPR_SUCCESS); - - //camera - rpr_camera camera = NULL; status = rprContextCreateCamera(context, &camera); - assert(status == RPR_SUCCESS); - status = rprCameraLookAt(camera, 0, 0, 7, 0, 0, 0, 0, 1, 0); - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, camera); - assert(status == RPR_SUCCESS); - - //light - rpr_light light = NULL; status = rprContextCreatePointLight(context, &light); - assert(status == RPR_SUCCESS); - matrix lightm = translation(float3(0, 0, 4)) * rotation_z(3.14f); - status = rprLightSetTransform(light, true, &lightm.m00); - assert(status == RPR_SUCCESS); - status = rprPointLightSetRadiantPower3f(light, 40, 40, 40); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, light); - assert(status == RPR_SUCCESS); - - //output - rpr_framebuffer_desc desc; - desc.fb_width = 800; - desc.fb_height = 600; - rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; - rpr_framebuffer frame_buffer = NULL; status = rprContextCreateFrameBuffer(context, fmt, &desc, &frame_buffer); - assert(status == RPR_SUCCESS); - status = rprContextSetAOV(context, RPR_AOV_COLOR, frame_buffer); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - - //render - for (rpr_uint i = 0; i < kRenderIterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - - rprFrameBufferSaveToFile(frame_buffer, "Output/feature_shaderTypeLayered.png"); - - - //dynamic : change parameters : - rpr_image imageInputB = NULL; status = rprContextCreateImageFromFile(context, "../Resources/Textures/test_normal.jpg", &imageInputB); - assert(status == RPR_SUCCESS); - rpr_material_node textureNormalMap2 = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_NORMAL_MAP, &textureNormalMap2); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputImageData(textureNormalMap2, "data", imageInputB); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputN(specularSphere, "normal", textureNormalMap2); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(specularSphere, "roughness", 0.2f, 0.0f, 0.0f, 0.0f); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(layered, "weight", 0.6f, 0.0f, 0.0f, 0.0f); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - for (rpr_uint i = 0; i < kRenderIterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - rprFrameBufferSaveToFile(frame_buffer, "Output/feature_shaderTypeLayered_dynamic.png"); - - //cleanup - FR_MACRO_SAFE_FRDELETE(textureNormalMap); - FR_MACRO_SAFE_FRDELETE(textureNormalMap2); - status = rprObjectDelete(imageInputA); imageInputA = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(imageInputB); imageInputB = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(frame_buffer); frame_buffer = NULL; - assert(status == RPR_SUCCESS); - status = rprSceneDetachLight(scene, light); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(light); light = NULL; - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, NULL); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(camera); camera = NULL; - assert(status == RPR_SUCCESS); - FR_MACRO_CLEAN_SHAPE_RELEASE(mesh, scene); - status = rprObjectDelete(layered); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(specularSphere); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(diffuseSphere); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(scene); scene = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(matsys); matsys = NULL; - assert(status == RPR_SUCCESS); -} - - -void LoadFrs(const std::string& file) -{ - rpr_int status = RPR_SUCCESS; - - //create context and scene - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - rpr_scene scene = NULL; - rpr_material_system matsys = NULL; - status = rprContextCreateMaterialSystem(context, 0, &matsys); - assert(status == RPR_SUCCESS); - - //load frs file - status = rprsImport(file.c_str(), context, matsys, &scene, false); - assert(status == RPR_SUCCESS); - - ////add env light - //rpr_light light = nullptr; - //status = rprContextCreateEnvironmentLight(context, &light); - //assert(status == RPR_SUCCESS); - //rpr_image image_input = NULL; status = rprContextCreateImageFromFile(context, "../Resources/Textures/Studio015.hdr", &image_input); - //assert(status == RPR_SUCCESS); - //status = rprEnvironmentLightSetImage(light, image_input); - //assert(status == RPR_SUCCESS); - //status = rprEnvironmentLightSetIntensityScale(light, 1.f); - //assert(status == RPR_SUCCESS); - //status = rprSceneAttachLight(scene, light); - //assert(status == RPR_SUCCESS); - - - size_t shapeCount = 0; - status = rprSceneGetInfo(scene, RPR_SCENE_SHAPE_COUNT, sizeof(shapeCount), &shapeCount, NULL); - assert(status == RPR_SUCCESS); - - std::vector shapes(shapeCount); - status = rprSceneGetInfo(scene, RPR_SCENE_SHAPE_LIST, shapeCount * sizeof(rpr_shape), shapes.data(), NULL); - assert(status == RPR_SUCCESS); - - //rpr_material_node grey = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_DIFFUSE, &grey); - //assert(status == RPR_SUCCESS); - //status = rprMaterialNodeSetInputF(grey, "color", 0.5f, 0.5f, 0.5f, 1.0f); - //assert(status == RPR_SUCCESS); - //// Iterate over shapes and replace materials. - //for (size_t i = 0; i < shapeCount; i++) - //{ - // // Retrieve the shape's material node. - // rpr_material_node mat = 0; - // status = rprShapeSetMaterial(shapes[i], grey); - // assert(status == RPR_SUCCESS); - //} - - rpr_camera cam; - status = rprSceneGetInfo(scene, RPR_SCENE_CAMERA, sizeof(rpr_camera), &cam, NULL); - assert(status == RPR_SUCCESS); - status = rprCameraSetFStop(cam, 0.f); - assert(status == RPR_SUCCESS); - - - //output - rpr_framebuffer_desc desc; - desc.fb_width = 800; - desc.fb_height = 600; - rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; - rpr_framebuffer frame_buffer = NULL; status = rprContextCreateFrameBuffer(context, fmt, &desc, &frame_buffer); - assert(status == RPR_SUCCESS); - status = rprContextSetAOV(context, RPR_AOV_COLOR, frame_buffer); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - - //render - for (rpr_uint i = 0; i < kRenderIterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - - rprFrameBufferSaveToFile(frame_buffer, "Output/LoadFrs.png"); - - //cleanup - status = rprObjectDelete(frame_buffer); frame_buffer = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(scene); scene = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(matsys); matsys = NULL; - assert(status == RPR_SUCCESS); - +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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 "basic.h" +#include "aov.h" +#include "camera.h" +#include "light.h" +#include "material.h" +#include "arithmetic.h" + +int g_argc; +char** g_argv; + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + g_argc = argc; + g_argv = argv; + return RUN_ALL_TESTS(); } -void UpdateMaterial() -{ - //check material properties updated properly - //on blend material - rpr_int status = RPR_SUCCESS; - rpr_context context; - status = rprCreateContext(RPR_API_VERSION, nullptr, 0, RPR_CREATION_FLAGS_ENABLE_GPU0, NULL, NULL, &context); - assert(status == RPR_SUCCESS); - rpr_material_system matsys = NULL; - status = rprContextCreateMaterialSystem(context, 0, &matsys); - assert(status == RPR_SUCCESS); - - rpr_scene scene = NULL; status = rprContextCreateScene(context, &scene); - assert(status == RPR_SUCCESS); - - //material - rpr_material_node red = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_DIFFUSE, &red); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(red, "color", 1.f, 0.f, 0.f, 1.f); - assert(status == RPR_SUCCESS); - rpr_material_node green = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_DIFFUSE, &green); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputF(green, "color", 0.f, 1.f, 0.f, 1.f); - assert(status == RPR_SUCCESS); - rpr_material_node layered = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_BLEND, &layered); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputN(layered, "color0", red); - status = rprMaterialNodeSetInputN(layered, "color1", green); - assert(status == RPR_SUCCESS); - rpr_material_node fresnel = NULL; status = rprMaterialSystemCreateNode(matsys, RPR_MATERIAL_NODE_FRESNEL, &fresnel); - assert(status == RPR_SUCCESS); - auto ior = 0.f; - status = rprMaterialNodeSetInputF(fresnel, "ior", ior, ior, ior, ior); - assert(status == RPR_SUCCESS); - status = rprMaterialNodeSetInputN(layered, "weight", fresnel); - assert(status == RPR_SUCCESS); - - //sphere - rpr_shape mesh = CreateSphere(context, 64, 32, 1.f, float3()); - assert(status == RPR_SUCCESS); - status = rprSceneAttachShape(scene, mesh); - assert(status == RPR_SUCCESS); - status = rprShapeSetMaterial(mesh, layered); - assert(status == RPR_SUCCESS); - - //light - rpr_light light = NULL; status = rprContextCreateEnvironmentLight(context, &light); - assert(status == RPR_SUCCESS); - rpr_image imageInput = NULL; status = rprContextCreateImageFromFile(context, "../Resources/Textures/studio015.hdr", &imageInput); - assert(status == RPR_SUCCESS); - status = rprEnvironmentLightSetImage(light, imageInput); - assert(status == RPR_SUCCESS); - status = rprSceneAttachLight(scene, light); - assert(status == RPR_SUCCESS); - - //camera - rpr_camera camera = NULL; status = rprContextCreateCamera(context, &camera); - assert(status == RPR_SUCCESS); - status = rprCameraLookAt(camera, 0, 0, 3, 0, 0, 0, 0, 1, 0); - assert(status == RPR_SUCCESS); - status = rprCameraSetFocalLength(camera, 23.f); - assert(status == RPR_SUCCESS); - status = rprCameraSetFStop(camera, 5.4f); - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, camera); - assert(status == RPR_SUCCESS); - - status = rprContextSetScene(context, scene); - assert(status == RPR_SUCCESS); - - //light - - //setup out - rpr_framebuffer_desc desc; - desc.fb_width = 800; - desc.fb_height = 600; - - rpr_framebuffer_format fmt = { 4, RPR_COMPONENT_TYPE_FLOAT32 }; - rpr_framebuffer frame_buffer = NULL; status = rprContextCreateFrameBuffer(context, fmt, &desc, &frame_buffer); - assert(status == RPR_SUCCESS); - status = rprContextSetAOV(context, RPR_AOV_COLOR, frame_buffer); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - - //render - for (int i = 0; i < kRenderIterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - status = rprFrameBufferSaveToFile(frame_buffer, "Output/UpdateMaterial_1.jpg"); - - //update ior - ior = 1.f; - status = rprMaterialNodeSetInputF(fresnel, "ior", ior, ior, ior, ior); - assert(status == RPR_SUCCESS); - status = rprFrameBufferClear(frame_buffer); - assert(status == RPR_SUCCESS); - for (int i = 0; i < kRenderIterations; ++i) - { - status = rprContextRender(context); - assert(status == RPR_SUCCESS); - } - status = rprFrameBufferSaveToFile(frame_buffer, "Output/UpdateMaterial_2.jpg"); - - assert(status == RPR_SUCCESS); - rpr_render_statistics rs; - status = rprContextGetInfo(context, RPR_CONTEXT_RENDER_STATISTICS, sizeof(rpr_render_statistics), &rs, NULL); - assert(status == RPR_SUCCESS); - - - - //cleanup - status = rprSceneDetachLight(scene, light); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(light); light = NULL; - assert(status == RPR_SUCCESS); - status = rprSceneSetCamera(scene, NULL); - assert(status == RPR_SUCCESS); - status = rprObjectDelete(scene); scene = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(camera); camera = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(frame_buffer); frame_buffer = NULL; - assert(status == RPR_SUCCESS); - status = rprObjectDelete(matsys); matsys = NULL; - assert(status == RPR_SUCCESS); -} -int main(int argc, char* argv[]) -{ - MeshCreationTest(); - SimpleRenderTest(); - ComplexRenderTest(); - EnvLightClearTest(); - MemoryStatistics(); - DefaultMaterialTest(); - NullShaderTest(); - TiledRender(); - AOVTest(); - test_feature_cameraDOF(); - test_feature_ContextImageFromData(); -// test_feature_multiUV(); -// test_apiMecha_Light(); - test_feature_LightDirectional(); - InstancingTest(); - BumpmapTest(); - test_feature_shaderBumpmap(); - test_feature_shaderTypeLayered(); - UpdateMaterial(); - //LoadFrs("../Resources/frs/bath_new.frs"); - - return 0; -} \ No newline at end of file diff --git a/RprTest/material.h b/RprTest/material.h new file mode 100644 index 00000000..95188bfb --- /dev/null +++ b/RprTest/material.h @@ -0,0 +1,377 @@ +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ + +#pragma once + +#include "basic.h" + +class MaterialTest : public BasicTest +{ +public: + const std::vector colors = + { + float3(0.9f, 0.2f, 0.1f), + float3(0.1f, 0.9f, 0.1f), + float3(0.3f, 0.2f, 0.8f) + }; + + const std::string resource_dir = "../Resources/Textures/"; + const std::string ext = ".jpg"; + const std::vector texture_names = + { + "test_albedo1", + "test_albedo2", + "test_albedo3" + }; + + const std::vector iors = + { + 1.1f, 1.6f, 2.2f, 5.f + }; + + const std::vector roughnesses = + { + 0.0001f, 0.01f, 0.1f, 0.4f + }; + + virtual void SetUp() override + { + BasicTest::SetUp(); + CreateScene(SceneType::kSphereAndPlane); + AddEnvironmentLight("../Resources/Textures/studio015.hdr"); + } + +}; + +TEST_F(MaterialTest, Material_Diffuse) +{ + const rpr_material_node sphere_mtl = GetMaterial("sphere_mtl"); + + for (auto const& c : colors) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_DIFFUSE_COLOR, c.x, c.y, c.z, 0.0f), RPR_SUCCESS); + + Render(); + SaveAndCompare("%f_%f_%f", c.x, c.y, c.z); + } + + rpr_material_node inputTexture; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_IMAGE_TEXTURE, &inputTexture), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputN_ext(sphere_mtl, RPR_UBER_MATERIAL_DIFFUSE_COLOR, inputTexture), RPR_SUCCESS); + AddMaterialNode("tex", inputTexture); + + for (auto const& tex_name : texture_names) + { + ASSERT_EQ(rprMaterialNodeSetInputImageData(inputTexture, "data", FindImage(resource_dir + tex_name + ext)), RPR_SUCCESS); + + Render(); + SaveAndCompare("%s", tex_name.c_str()); + } + +} + +// Create image from data, not from file +TEST_F(MaterialTest, Material_ImageFromMemory) +{ + rpr_image_format imageFormat; + memset(&imageFormat, 0, sizeof(imageFormat)); + imageFormat.num_components = 4; + imageFormat.type = RPR_COMPONENT_TYPE_FLOAT32; + rpr_image_desc imageDesc; + memset(&imageDesc, 0, sizeof(imageDesc)); + imageDesc.image_depth = 1; + imageDesc.image_width = 32; + imageDesc.image_height = 32; + imageDesc.image_row_pitch = imageDesc.image_width * sizeof(float) * 4; + imageDesc.image_slice_pitch = imageDesc.image_width * imageDesc.image_height * sizeof(float) * 4; + std::vector dataImage(imageDesc.image_width * imageDesc.image_height * 4); + + for (rpr_uint y = 0; y < imageDesc.image_height; y++) + { + for (rpr_uint x = 0; x < imageDesc.image_width; x++) + { + dataImage[x * 4 + y * imageDesc.image_width * 4 + 0] = (std::sin(x * 2.0f) + std::cos(y * 2.0f)) * 0.25f + 0.5f; // R + dataImage[x * 4 + y * imageDesc.image_width * 4 + 1] = (std::cos(x * 2.0f) + std::sin(y * 2.0f)) * 0.25f + 0.5f; // G + dataImage[x * 4 + y * imageDesc.image_width * 4 + 2] = 0.0f; // B + dataImage[x * 4 + y * imageDesc.image_width * 4 + 3] = 1.0f; // A + } + } + + rpr_image image = nullptr; + ASSERT_EQ(rprContextCreateImage(m_context, imageFormat, &imageDesc, dataImage.data(), &image), RPR_SUCCESS); + m_images["procedural"] = image; + + const rpr_material_node sphere_mtl = GetMaterial("sphere_mtl"); + rpr_material_node inputTexture; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_IMAGE_TEXTURE, &inputTexture), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputN_ext(sphere_mtl, RPR_UBER_MATERIAL_DIFFUSE_COLOR, inputTexture), RPR_SUCCESS); + AddMaterialNode("tex", inputTexture); + ASSERT_EQ(rprMaterialNodeSetInputImageData(inputTexture, "data", image), RPR_SUCCESS); + + Render(); + SaveAndCompare(); +} + +TEST_F(MaterialTest, Material_Reflect) +{ + const rpr_material_node sphere_mtl = GetMaterial("sphere_mtl"); + ASSERT_EQ(rprMaterialNodeSetInputU_ext(sphere_mtl, RPR_UBER_MATERIAL_LAYERS, RPR_UBER_MATERIAL_LAYER_DIFFUSE | RPR_UBER_MATERIAL_LAYER_REFLECTION), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFLECTION_ROUGHNESS, 0.0f, 0.0f, 0.0f, 0.0f), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFLECTION_METALNESS, 0.0f, 0.0f, 0.0f, 0.0f), RPR_SUCCESS); + + for (auto const& c : colors) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_DIFFUSE_COLOR, c.x, c.y, c.z, 0.0f), RPR_SUCCESS); + + for (auto& ior : iors) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFLECTION_IOR, ior, ior, ior, ior), RPR_SUCCESS); + + Render(); + SaveAndCompare("%f_%f_%f_%f", c.x, c.y, c.z, ior); + } + } + + rpr_material_node inputTexture; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_IMAGE_TEXTURE, &inputTexture), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputN_ext(sphere_mtl, RPR_UBER_MATERIAL_DIFFUSE_COLOR, inputTexture), RPR_SUCCESS); + AddMaterialNode("tex", inputTexture); + + for (auto const& tex_name : texture_names) + { + ASSERT_EQ(rprMaterialNodeSetInputImageData(inputTexture, "data", FindImage(resource_dir + tex_name + ext)), RPR_SUCCESS); + + for (auto const& ior : iors) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFLECTION_IOR, ior, ior, ior, ior), RPR_SUCCESS); + + Render(); + SaveAndCompare("%s_%f", tex_name.c_str(), ior); + } + } + +} + +TEST_F(MaterialTest, Material_MicrofacetGGX) +{ + const rpr_material_node sphere_mtl = GetMaterial("sphere_mtl"); + ASSERT_EQ(rprMaterialNodeSetInputU_ext(sphere_mtl, RPR_UBER_MATERIAL_LAYERS, RPR_UBER_MATERIAL_LAYER_DIFFUSE | RPR_UBER_MATERIAL_LAYER_REFLECTION), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFLECTION_METALNESS, 0.0f, 0.0f, 0.0f, 0.0f), RPR_SUCCESS); + + for (auto const& r : roughnesses) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFLECTION_ROUGHNESS, r, r, r, r), RPR_SUCCESS); + for (auto const& c : colors) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_DIFFUSE_COLOR, c.x, c.y, c.z, 0.0f), RPR_SUCCESS); + for (auto const& ior : iors) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFLECTION_IOR, ior, ior, ior, ior), RPR_SUCCESS); + + Render(); + SaveAndCompare("%f_%f_%f_%f_%f", r, c.x, c.y, c.z, ior); + } + } + } + + rpr_material_node inputTexture; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_IMAGE_TEXTURE, &inputTexture), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputN_ext(sphere_mtl, RPR_UBER_MATERIAL_DIFFUSE_COLOR, inputTexture), RPR_SUCCESS); + AddMaterialNode("tex", inputTexture); + + for (auto const& tex_name : texture_names) + { + ASSERT_EQ(rprMaterialNodeSetInputImageData(inputTexture, "data", FindImage(resource_dir + tex_name + ext)), RPR_SUCCESS); + for (auto const& r : roughnesses) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFLECTION_ROUGHNESS, r, r, r, r), RPR_SUCCESS); + for (auto const& ior : iors) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFLECTION_IOR, ior, ior, ior, ior), RPR_SUCCESS); + + Render(); + SaveAndCompare("%s_%f_%f", tex_name.c_str(), r, ior); + } + } + } +} + +TEST_F(MaterialTest, Material_Refract) +{ + const rpr_material_node sphere_mtl = GetMaterial("sphere_mtl"); + ASSERT_EQ(rprMaterialNodeSetInputU_ext(sphere_mtl, RPR_UBER_MATERIAL_LAYERS, RPR_UBER_MATERIAL_LAYER_REFRACTION), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFRACTION_ROUGHNESS, 0.0f, 0.0f, 0.0f, 0.0f), RPR_SUCCESS); + + for (auto const& c : colors) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFRACTION_COLOR, c.x, c.y, c.z, 0.0f), RPR_SUCCESS); + + for (auto& ior : iors) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFRACTION_IOR, ior, ior, ior, ior), RPR_SUCCESS); + + Render(); + SaveAndCompare("%f_%f_%f_%f", c.x, c.y, c.z, ior); + } + } + + rpr_material_node inputTexture; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_IMAGE_TEXTURE, &inputTexture), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputN_ext(sphere_mtl, RPR_UBER_MATERIAL_REFRACTION_COLOR, inputTexture), RPR_SUCCESS); + AddMaterialNode("tex", inputTexture); + + for (auto const& tex_name : texture_names) + { + ASSERT_EQ(rprMaterialNodeSetInputImageData(inputTexture, "data", FindImage(resource_dir + tex_name + ext)), RPR_SUCCESS); + + for (auto const& ior : iors) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFRACTION_IOR, ior, ior, ior, ior), RPR_SUCCESS); + + Render(); + SaveAndCompare("%s_%f", tex_name.c_str(), ior); + } + } + +} + +TEST_F(MaterialTest, Material_MicrofacetRefractGGX) +{ + const rpr_material_node sphere_mtl = GetMaterial("sphere_mtl"); + ASSERT_EQ(rprMaterialNodeSetInputU_ext(sphere_mtl, RPR_UBER_MATERIAL_LAYERS, RPR_UBER_MATERIAL_LAYER_REFRACTION), RPR_SUCCESS); + + for (auto const& r : roughnesses) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFRACTION_ROUGHNESS, r, r, r, r), RPR_SUCCESS); + for (auto const& c : colors) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFRACTION_COLOR, c.x, c.y, c.z, 0.0f), RPR_SUCCESS); + for (auto const& ior : iors) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFRACTION_IOR, ior, ior, ior, ior), RPR_SUCCESS); + + Render(); + SaveAndCompare("%f_%f_%f_%f_%f", r, c.x, c.y, c.z, ior); + } + } + } + + rpr_material_node inputTexture; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_IMAGE_TEXTURE, &inputTexture), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputN_ext(sphere_mtl, RPR_UBER_MATERIAL_REFRACTION_COLOR, inputTexture), RPR_SUCCESS); + AddMaterialNode("tex", inputTexture); + + for (auto const& tex_name : texture_names) + { + ASSERT_EQ(rprMaterialNodeSetInputImageData(inputTexture, "data", FindImage(resource_dir + tex_name + ext)), RPR_SUCCESS); + for (auto const& r : roughnesses) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFRACTION_ROUGHNESS, r, r, r, r), RPR_SUCCESS); + for (auto const& ior : iors) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFRACTION_IOR, ior, ior, ior, ior), RPR_SUCCESS); + + Render(); + SaveAndCompare("%s_%f_%f", tex_name.c_str(), r, ior); + } + } + } + +} + +TEST_F(MaterialTest, Material_ReflectionMicrofacetAndRefraction) +{ + const rpr_material_node sphere_mtl = GetMaterial("sphere_mtl"); + ASSERT_EQ(rprMaterialNodeSetInputU_ext(sphere_mtl, RPR_UBER_MATERIAL_LAYERS, RPR_UBER_MATERIAL_LAYER_REFLECTION | RPR_UBER_MATERIAL_LAYER_REFRACTION), RPR_SUCCESS); + + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFLECTION_COLOR, 1.0f, 1.0f, 1.0f, 0.0f), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFRACTION_COLOR, 1.0f, 1.0f, 1.0f, 0.0f), RPR_SUCCESS); + + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFRACTION_ROUGHNESS, 0.0f, 0.0f, 0.0f, 0.0f), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFLECTION_ROUGHNESS, 0.002f, 0.002f, 0.002f, 0.002f), RPR_SUCCESS); + + for (auto& ior : iors) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFLECTION_IOR, ior, ior, ior, ior), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_REFRACTION_IOR, ior, ior, ior, ior), RPR_SUCCESS); + + Render(); + SaveAndCompare("%f", ior); + } +} + +TEST_F(MaterialTest, Material_Coating) +{ + const rpr_material_node sphere_mtl = GetMaterial("sphere_mtl"); + ASSERT_EQ(rprMaterialNodeSetInputU_ext(sphere_mtl, RPR_UBER_MATERIAL_LAYERS, RPR_UBER_MATERIAL_LAYER_DIFFUSE | RPR_UBER_MATERIAL_LAYER_COATING), RPR_SUCCESS); + + for (auto const& c : colors) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_COATING_COLOR, c.x, c.y, c.z, 0.0f), RPR_SUCCESS); + + for (auto& ior : iors) + { + ASSERT_EQ(rprMaterialNodeSetInputF_ext(sphere_mtl, RPR_UBER_MATERIAL_COATING_IOR, ior, ior, ior, ior), RPR_SUCCESS); + + Render(); + SaveAndCompare("%f_%f_%f_%f", c.x, c.y, c.z, ior); + } + } + +} + + +TEST_F(BasicTest, Material_VolumeScattering) +{ + // UNSUPPORTED_FUNCTION + ASSERT_EQ(rprShapeSetVolumeMaterial(nullptr, nullptr), RPR_SUCCESS); +} + +TEST_F(MaterialTest, Material_NormalMapping) +{ + const rpr_material_node sphere_mtl = GetMaterial("sphere_mtl"); + ASSERT_EQ(rprMaterialNodeSetInputU_ext(sphere_mtl, RPR_UBER_MATERIAL_LAYERS, RPR_UBER_MATERIAL_LAYER_DIFFUSE | RPR_UBER_MATERIAL_LAYER_SHADING_NORMAL), RPR_SUCCESS); + rpr_material_node inputTexture; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_IMAGE_TEXTURE, &inputTexture), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputImageData(inputTexture, "data", FindImage("../Resources/Textures/test_normal.jpg")), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputN_ext(sphere_mtl, RPR_UBER_MATERIAL_NORMAL, inputTexture), RPR_SUCCESS); + AddMaterialNode("tex", inputTexture); + + Render(256); + SaveAndCompare(); + +} + +TEST_F(MaterialTest, Material_BumpMapping) +{ + const rpr_material_node sphere_mtl = GetMaterial("sphere_mtl"); + ASSERT_EQ(rprMaterialNodeSetInputU_ext(sphere_mtl, RPR_UBER_MATERIAL_LAYERS, RPR_UBER_MATERIAL_LAYER_DIFFUSE | RPR_UBER_MATERIAL_LAYER_SHADING_NORMAL), RPR_SUCCESS); + rpr_material_node inputTexture; + ASSERT_EQ(rprMaterialSystemCreateNode(m_matsys, RPR_MATERIAL_NODE_IMAGE_TEXTURE, &inputTexture), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputImageData(inputTexture, "data", FindImage("../Resources/Textures/test_bump.jpg")), RPR_SUCCESS); + ASSERT_EQ(rprMaterialNodeSetInputN_ext(sphere_mtl, RPR_UBER_MATERIAL_BUMP, inputTexture), RPR_SUCCESS); + AddMaterialNode("tex", inputTexture); + + Render(256); + SaveAndCompare(); + +} diff --git a/RprTest/tiny_obj_loader.cpp b/RprTest/tiny_obj_loader.cpp deleted file mode 100644 index a61ff2c4..00000000 --- a/RprTest/tiny_obj_loader.cpp +++ /dev/null @@ -1,725 +0,0 @@ -// -// Copyright 2012-2013, Syoyo Fujita. -// -// Licensed under 2-clause BSD liecense. -// - -// -// version 0.9.7: Support multi-materials(per-face material ID) per object/group. -// version 0.9.6: Support Ni(index of refraction) mtl parameter. -// Parse transmittance material parameter correctly. -// version 0.9.5: Parse multiple group name. -// Add support of specifying the base path to load material file. -// version 0.9.4: Initial suupport of group tag(g) -// version 0.9.3: Fix parsing triple 'x/y/z' -// version 0.9.2: Add more .mtl load support -// version 0.9.1: Add initial .mtl load support -// version 0.9.0: Initial -// - - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "tiny_obj_loader.h" - -namespace tinyobj { - -struct vertex_index { - int v_idx, vt_idx, vn_idx; - vertex_index() {}; - vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {}; - vertex_index(int vidx, int vtidx, int vnidx) : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {}; - -}; -// for std::map -static inline bool operator<(const vertex_index& a, const vertex_index& b) -{ - if (a.v_idx != b.v_idx) return (a.v_idx < b.v_idx); - if (a.vn_idx != b.vn_idx) return (a.vn_idx < b.vn_idx); - if (a.vt_idx != b.vt_idx) return (a.vt_idx < b.vt_idx); - - return false; -} - -struct obj_shape { - std::vector v; - std::vector vn; - std::vector vt; -}; - -static inline bool isSpace(const char c) { - return (c == ' ') || (c == '\t'); -} - -static inline bool isNewLine(const char c) { - return (c == '\r') || (c == '\n') || (c == '\0'); -} - -// Make index zero-base, and also support relative index. -static inline int fixIndex(int idx, int n) -{ - int i; - - if (idx > 0) { - i = idx - 1; - } else if (idx == 0) { - i = 0; - } else { // negative value = relative - i = n + idx; - } - return i; -} - -static inline std::string parseString(const char*& token) -{ - std::string s; - int b = (int)strspn(token, " \t"); - int e = (int)strcspn(token, " \t\r"); - s = std::string(&token[b], &token[e]); - - token += (e - b); - return s; -} - -static inline int parseInt(const char*& token) -{ - token += strspn(token, " \t"); - int i = atoi(token); - token += strcspn(token, " \t\r"); - return i; -} - -static inline float parseFloat(const char*& token) -{ - token += strspn(token, " \t"); - float f = (float)atof(token); - token += strcspn(token, " \t\r"); - return f; -} - -static inline void parseFloat2( - float& x, float& y, - const char*& token) -{ - x = parseFloat(token); - y = parseFloat(token); -} - -static inline void parseFloat3( - float& x, float& y, float& z, - const char*& token) -{ - x = parseFloat(token); - y = parseFloat(token); - z = parseFloat(token); -} - - -// Parse triples: i, i/j/k, i//k, i/j -static vertex_index parseTriple( - const char* &token, - int vsize, - int vnsize, - int vtsize) -{ - vertex_index vi(-1); - - vi.v_idx = fixIndex(atoi(token), vsize); - token += strcspn(token, "/ \t\r"); - if (token[0] != '/') { - return vi; - } - token++; - - // i//k - if (token[0] == '/') { - token++; - vi.vn_idx = fixIndex(atoi(token), vnsize); - token += strcspn(token, "/ \t\r"); - return vi; - } - - // i/j/k or i/j - vi.vt_idx = fixIndex(atoi(token), vtsize); - token += strcspn(token, "/ \t\r"); - if (token[0] != '/') { - return vi; - } - - // i/j/k - token++; // skip '/' - vi.vn_idx = fixIndex(atoi(token), vnsize); - token += strcspn(token, "/ \t\r"); - return vi; -} - -static unsigned int -updateVertex( - std::map& vertexCache, - std::vector& positions, - std::vector& normals, - std::vector& texcoords, - const std::vector& in_positions, - const std::vector& in_normals, - const std::vector& in_texcoords, - const vertex_index& i) -{ - const std::map::iterator it = vertexCache.find(i); - - if (it != vertexCache.end()) { - // found cache - return it->second; - } - - assert(in_positions.size() > (unsigned int) (3*i.v_idx+2)); - - positions.push_back(in_positions[3*i.v_idx+0]); - positions.push_back(in_positions[3*i.v_idx+1]); - positions.push_back(in_positions[3*i.v_idx+2]); - - if (i.vn_idx >= 0) { - normals.push_back(in_normals[3*i.vn_idx+0]); - normals.push_back(in_normals[3*i.vn_idx+1]); - normals.push_back(in_normals[3*i.vn_idx+2]); - } - - if (i.vt_idx >= 0) { - texcoords.push_back(in_texcoords[2*i.vt_idx+0]); - texcoords.push_back(in_texcoords[2*i.vt_idx+1]); - } - - unsigned int idx = (unsigned)positions.size() / 3 - 1; - vertexCache[i] = idx; - - return idx; -} - -void InitMaterial(material_t& material) { - material.name = ""; - material.ambient_texname = ""; - material.diffuse_texname = ""; - material.specular_texname = ""; - material.normal_texname = ""; - for (int i = 0; i < 3; i ++) { - material.ambient[i] = 0.f; - material.diffuse[i] = 0.f; - material.specular[i] = 0.f; - material.transmittance[i] = 0.f; - material.emission[i] = 0.f; - } - material.illum = 0; - material.dissolve = 1.f; - material.shininess = 1.f; - material.ior = 1.f; - material.unknown_parameter.clear(); -} - -static bool -exportFaceGroupToShape( - shape_t& shape, - std::map vertexCache, - const std::vector &in_positions, - const std::vector &in_normals, - const std::vector &in_texcoords, - const std::vector >& faceGroup, - const int material_id, - const std::string &name, - bool clearCache) -{ - if (faceGroup.empty()) { - return false; - } - - size_t offset; - - offset = shape.mesh.indices.size(); - - // Flatten vertices and indices - for (size_t i = 0; i < faceGroup.size(); i++) { - const std::vector& face = faceGroup[i]; - - vertex_index i0 = face[0]; - vertex_index i1(-1); - vertex_index i2 = face[1]; - - size_t npolys = face.size(); - - // Polygon -> triangle fan conversion - for (size_t k = 2; k < npolys; k++) { - i1 = i2; - i2 = face[k]; - - unsigned int v0 = updateVertex(vertexCache, shape.mesh.positions, shape.mesh.normals, shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i0); - unsigned int v1 = updateVertex(vertexCache, shape.mesh.positions, shape.mesh.normals, shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i1); - unsigned int v2 = updateVertex(vertexCache, shape.mesh.positions, shape.mesh.normals, shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i2); - - shape.mesh.indices.push_back(v0); - shape.mesh.indices.push_back(v1); - shape.mesh.indices.push_back(v2); - - shape.mesh.material_ids.push_back(material_id); - } - - } - - shape.name = name; - - if (clearCache) - vertexCache.clear(); - - return true; - -} - -std::string LoadMtl ( - std::map& material_map, - std::vector& materials, - std::istream& inStream) -{ - material_map.clear(); - std::stringstream err; - - material_t material; - - int maxchars = 8192; // Alloc enough size. - std::vector buf(maxchars); // Alloc enough size. - while (inStream.peek() != -1) { - inStream.getline(&buf[0], maxchars); - - std::string linebuf(&buf[0]); - - // Trim newline '\r\n' or '\n' - if (linebuf.size() > 0) { - if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1); - } - if (linebuf.size() > 0) { - if (linebuf[linebuf.size()-1] == '\r') linebuf.erase(linebuf.size()-1); - } - - // Skip if empty line. - if (linebuf.empty()) { - continue; - } - - // Skip leading space. - const char* token = linebuf.c_str(); - token += strspn(token, " \t"); - - assert(token); - if (token[0] == '\0') continue; // empty line - - if (token[0] == '#') continue; // comment line - - // new mtl - if ((0 == strncmp(token, "newmtl", 6)) && isSpace((token[6]))) { - // flush previous material. - if (!material.name.empty()) - { - material_map.insert(std::pair(material.name, (int)materials.size())); - materials.push_back(material); - } - - // initial temporary material - InitMaterial(material); - - // set new mtl name - char namebuf[4096]; - token += 7; - sscanf(token, "%s", namebuf); - material.name = namebuf; - continue; - } - - // ambient - if (token[0] == 'K' && token[1] == 'a' && isSpace((token[2]))) { - token += 2; - float r, g, b; - parseFloat3(r, g, b, token); - material.ambient[0] = r; - material.ambient[1] = g; - material.ambient[2] = b; - continue; - } - - // diffuse - if (token[0] == 'K' && token[1] == 'd' && isSpace((token[2]))) { - token += 2; - float r, g, b; - parseFloat3(r, g, b, token); - material.diffuse[0] = r; - material.diffuse[1] = g; - material.diffuse[2] = b; - continue; - } - - // specular - if (token[0] == 'K' && token[1] == 's' && isSpace((token[2]))) { - token += 2; - float r, g, b; - parseFloat3(r, g, b, token); - material.specular[0] = r; - material.specular[1] = g; - material.specular[2] = b; - continue; - } - - // transmittance - if (token[0] == 'K' && token[1] == 't' && isSpace((token[2]))) { - token += 2; - float r, g, b; - parseFloat3(r, g, b, token); - material.transmittance[0] = r; - material.transmittance[1] = g; - material.transmittance[2] = b; - continue; - } - - // ior(index of refraction) - if (token[0] == 'N' && token[1] == 'i' && isSpace((token[2]))) { - token += 2; - material.ior = parseFloat(token); - continue; - } - - // emission - if(token[0] == 'K' && token[1] == 'e' && isSpace(token[2])) { - token += 2; - float r, g, b; - parseFloat3(r, g, b, token); - material.emission[0] = r; - material.emission[1] = g; - material.emission[2] = b; - continue; - } - - // shininess - if(token[0] == 'N' && token[1] == 's' && isSpace(token[2])) { - token += 2; - material.shininess = parseFloat(token); - continue; - } - - // illum model - if (0 == strncmp(token, "illum", 5) && isSpace(token[5])) { - token += 6; - material.illum = parseInt(token); - continue; - } - - // dissolve - if ((token[0] == 'd' && isSpace(token[1]))) { - token += 1; - material.dissolve = parseFloat(token); - continue; - } - if (token[0] == 'T' && token[1] == 'r' && isSpace(token[2])) { - token += 2; - material.dissolve = parseFloat(token); - continue; - } - - // ambient texture - if ((0 == strncmp(token, "map_Ka", 6)) && isSpace(token[6])) { - token += 7; - material.ambient_texname = token; - continue; - } - - // diffuse texture - if ((0 == strncmp(token, "map_Kd", 6)) && isSpace(token[6])) { - token += 7; - material.diffuse_texname = token; - continue; - } - - // specular texture - if ((0 == strncmp(token, "map_Ks", 6)) && isSpace(token[6])) { - token += 7; - material.specular_texname = token; - continue; - } - - // normal texture - if ((0 == strncmp(token, "map_Ns", 6)) && isSpace(token[6])) { - token += 7; - material.normal_texname = token; - continue; - } - - // unknown parameter - const char* _space = strchr(token, ' '); - if(!_space) { - _space = strchr(token, '\t'); - } - if(_space) { - int len = (int)(_space - token); - std::string key(token, len); - std::string value = _space + 1; - material.unknown_parameter.insert(std::pair(key, value)); - } - } - // flush last material. - material_map.insert(std::pair(material.name, (int)materials.size())); - materials.push_back(material); - - return err.str(); -} - -std::string MaterialFileReader::operator() ( - const std::string& matId, - std::vector& materials, - std::map& matMap) -{ - std::string filepath; - - if (!m_mtlBasePath.empty()) { - filepath = std::string(m_mtlBasePath) + "/" + matId; - } else { - filepath = matId; - } - - std::ifstream matIStream(filepath.c_str()); - return LoadMtl(matMap, materials, matIStream); -} - -std::string -LoadObj( - std::vector& shapes, - std::vector& materials, // [output] - const char* filename, - const char* mtl_basepath) -{ - - shapes.clear(); - - std::stringstream err; - - std::ifstream ifs(filename); - if (!ifs) { - err << "Cannot open file [" << filename << "]" << std::endl; - return err.str(); - } - - std::string basePath; - if (mtl_basepath) { - basePath = mtl_basepath; - } - MaterialFileReader matFileReader( basePath ); - - return LoadObj(shapes, materials, ifs, matFileReader); -} - -std::string LoadObj( - std::vector& shapes, - std::vector& materials, // [output] - std::istream& inStream, - MaterialReader& readMatFn) -{ - std::stringstream err; - - std::vector v; - std::vector vn; - std::vector vt; - std::vector > faceGroup; - std::string name; - - // material - std::map material_map; - std::map vertexCache; - int material = -1; - - shape_t shape; - - int maxchars = 8192; // Alloc enough size. - std::vector buf(maxchars); // Alloc enough size. - while (inStream.peek() != -1) { - inStream.getline(&buf[0], maxchars); - - std::string linebuf(&buf[0]); - - // Trim newline '\r\n' or '\n' - if (linebuf.size() > 0) { - if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1); - } - if (linebuf.size() > 0) { - if (linebuf[linebuf.size()-1] == '\r') linebuf.erase(linebuf.size()-1); - } - - // Skip if empty line. - if (linebuf.empty()) { - continue; - } - - // Skip leading space. - const char* token = linebuf.c_str(); - token += strspn(token, " \t"); - - assert(token); - if (token[0] == '\0') continue; // empty line - - if (token[0] == '#') continue; // comment line - - // vertex - if (token[0] == 'v' && isSpace((token[1]))) { - token += 2; - float x, y, z; - parseFloat3(x, y, z, token); - v.push_back(x); - v.push_back(y); - v.push_back(z); - continue; - } - - // normal - if (token[0] == 'v' && token[1] == 'n' && isSpace((token[2]))) { - token += 3; - float x, y, z; - parseFloat3(x, y, z, token); - vn.push_back(x); - vn.push_back(y); - vn.push_back(z); - continue; - } - - // texcoord - if (token[0] == 'v' && token[1] == 't' && isSpace((token[2]))) { - token += 3; - float x, y; - parseFloat2(x, y, token); - vt.push_back(x); - vt.push_back(y); - continue; - } - - // face - if (token[0] == 'f' && isSpace((token[1]))) { - token += 2; - token += strspn(token, " \t"); - - std::vector face; - while (!isNewLine(token[0])) { - vertex_index vi = parseTriple(token, (int)v.size() / 3, (int)vn.size() / 3, (int)vt.size() / 2); - face.push_back(vi); - int n = (int)strspn(token, " \t\r"); - token += n; - } - - faceGroup.push_back(face); - - continue; - } - - // use mtl - if ((0 == strncmp(token, "usemtl", 6)) && isSpace((token[6]))) { - - char namebuf[4096]; - token += 7; - sscanf(token, "%s", namebuf); - - exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, false); - faceGroup.clear(); - - if (material_map.find(namebuf) != material_map.end()) { - material = material_map[namebuf]; - } else { - // { error!! material not found } - material = -1; - } - - continue; - - } - - // load mtl - if ((0 == strncmp(token, "mtllib", 6)) && isSpace((token[6]))) { - char namebuf[4096]; - token += 7; - sscanf(token, "%s", namebuf); - - std::string err_mtl = readMatFn(namebuf, materials, material_map); - if (!err_mtl.empty()) { - faceGroup.clear(); // for safety - return err_mtl; - } - - continue; - } - - // group name - if (token[0] == 'g' && isSpace((token[1]))) { - - // flush previous face group. - bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true); - if (ret) { - shapes.push_back(shape); - } - - shape = shape_t(); - - //material = -1; - faceGroup.clear(); - - std::vector names; - while (!isNewLine(token[0])) { - std::string str = parseString(token); - names.push_back(str); - token += strspn(token, " \t\r"); // skip tag - } - - assert(names.size() > 0); - - // names[0] must be 'g', so skipt 0th element. - if (names.size() > 1) { - name = names[1]; - } else { - name = ""; - } - - continue; - } - - // object name - if (token[0] == 'o' && isSpace((token[1]))) { - - // flush previous face group. - bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true); - if (ret) { - shapes.push_back(shape); - } - - //material = -1; - faceGroup.clear(); - shape = shape_t(); - - // @todo { multiple object name? } - char namebuf[4096]; - token += 2; - sscanf(token, "%s", namebuf); - name = std::string(namebuf); - - - continue; - } - - // Ignore unknown command. - } - - bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true); - if (ret) { - shapes.push_back(shape); - } - faceGroup.clear(); // for safety - - return err.str(); -} - - -} diff --git a/RprTest/tiny_obj_loader.h b/RprTest/tiny_obj_loader.h deleted file mode 100644 index 7cc6fa6a..00000000 --- a/RprTest/tiny_obj_loader.h +++ /dev/null @@ -1,107 +0,0 @@ -// -// Copyright 2012-2013, Syoyo Fujita. -// -// Licensed under 2-clause BSD liecense. -// -#ifndef _TINY_OBJ_LOADER_H -#define _TINY_OBJ_LOADER_H - -#include -#include -#include - -namespace tinyobj { - -typedef struct -{ - std::string name; - - float ambient[3]; - float diffuse[3]; - float specular[3]; - float transmittance[3]; - float emission[3]; - float shininess; - float ior; // index of refraction - float dissolve; // 1 == opaque; 0 == fully transparent - // illumination model (see http://www.fileformat.info/format/material/) - int illum; - - std::string ambient_texname; - std::string diffuse_texname; - std::string specular_texname; - std::string normal_texname; - std::map unknown_parameter; -} material_t; - -typedef struct -{ - std::vector positions; - std::vector normals; - std::vector texcoords; - std::vector indices; - std::vector material_ids; // per-mesh material ID -} mesh_t; - -typedef struct -{ - std::string name; - mesh_t mesh; -} shape_t; - -class MaterialReader -{ -public: - MaterialReader(){} - virtual ~MaterialReader(){} - - virtual std::string operator() ( - const std::string& matId, - std::vector& materials, - std::map& matMap) = 0; -}; - -class MaterialFileReader: - public MaterialReader -{ - public: - MaterialFileReader(const std::string& mtl_basepath): m_mtlBasePath(mtl_basepath) {} - virtual ~MaterialFileReader() {} - virtual std::string operator() ( - const std::string& matId, - std::vector& materials, - std::map& matMap); - - private: - std::string m_mtlBasePath; -}; - -/// Loads .obj from a file. -/// 'shapes' will be filled with parsed shape data -/// The function returns error string. -/// Returns empty string when loading .obj success. -/// 'mtl_basepath' is optional, and used for base path for .mtl file. -std::string LoadObj( - std::vector& shapes, // [output] - std::vector& materials, // [output] - const char* filename, - const char* mtl_basepath = NULL); - -/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve -/// std::istream for materials. -/// Returns empty string when loading .obj success. -std::string LoadObj( - std::vector& shapes, // [output] - std::vector& materials, // [output] - std::istream& inStream, - MaterialReader& readMatFn); - -/// Loads materials into std::map -/// Returns an empty string if successful -std::string LoadMtl ( - std::map& material_map, - std::vector& materials, - std::istream& inStream); -} - -#endif // _TINY_OBJ_LOADER_H diff --git a/Tools/Jenkins/build_test.jenkinsfile b/Tools/Jenkins/build_test.jenkinsfile new file mode 100644 index 00000000..e6bd6c76 --- /dev/null +++ b/Tools/Jenkins/build_test.jenkinsfile @@ -0,0 +1 @@ +rpr_baikal_cmake_pipeline() diff --git a/Baikal/SceneGraph/IO/image_io.cpp b/Tools/MaterialConverter/BaikalOld/SceneGraph/IO/image_io.cpp similarity index 73% rename from Baikal/SceneGraph/IO/image_io.cpp rename to Tools/MaterialConverter/BaikalOld/SceneGraph/IO/image_io.cpp index 6eaea4c5..c15683cb 100644 --- a/Baikal/SceneGraph/IO/image_io.cpp +++ b/Tools/MaterialConverter/BaikalOld/SceneGraph/IO/image_io.cpp @@ -3,19 +3,19 @@ #include "OpenImageIO/imageio.h" -namespace Baikal +namespace BaikalOld { class Oiio : public ImageIo { public: - Texture* LoadImage(std::string const& filename) const override; - void SaveImage(std::string const& filename, Texture const* texture) const override; + Texture::Ptr LoadImage(std::string const& filename) const override; + void SaveImage(std::string const& filename, Texture::Ptr texture) const override; }; - + static Texture::Format GetTextureForemat(OIIO_NAMESPACE::ImageSpec const& spec) { OIIO_NAMESPACE_USING - + if (spec.format.basetype == TypeDesc::UINT8) return Texture::Format::kRgba8; else if (spec.format.basetype == TypeDesc::HALF) @@ -23,11 +23,11 @@ namespace Baikal else return Texture::Format::kRgba32; } - + static OIIO_NAMESPACE::TypeDesc GetTextureForemat(Texture::Format fmt) { OIIO_NAMESPACE_USING - + if (fmt == Texture::Format::kRgba8) return TypeDesc::UINT8; else if (fmt == Texture::Format::kRgba16) @@ -35,98 +35,91 @@ namespace Baikal else return TypeDesc::FLOAT; } - - Texture* Oiio::LoadImage(const std::string &filename) const + + Texture::Ptr Oiio::LoadImage(const std::string &filename) const { OIIO_NAMESPACE_USING - - ImageInput* input = ImageInput::open(filename); - + + std::unique_ptr input{ImageInput::open(filename)}; + if (!input) { throw std::runtime_error("Can't load " + filename + " image"); } - + ImageSpec const& spec = input->spec(); - + auto fmt = GetTextureForemat(spec); char* texturedata = nullptr; if (fmt == Texture::Format::kRgba8) { auto size = spec.width * spec.height * spec.depth * 4; - + texturedata = new char[size]; - + // Read data to storage input->read_image(TypeDesc::UINT8, texturedata, sizeof(char) * 4); - + // Close handle input->close(); } else if (fmt == Texture::Format::kRgba16) { auto size = spec.width * spec.height * spec.depth * sizeof(float) * 2; - + // Resize storage texturedata = new char[size]; - + // Read data to storage input->read_image(TypeDesc::HALF, texturedata, sizeof(float) * 2); - + // Close handle input->close(); } else { auto size = spec.width * spec.height * spec.depth * sizeof(RadeonRays::float3); - + // Resize storage texturedata = new char[size]; - + // Read data to storage input->read_image(TypeDesc::FLOAT, texturedata, sizeof(RadeonRays::float3)); - + // Close handle input->close(); } - // Return new texture - auto tex = new Texture(texturedata, RadeonRays::int2(spec.width, spec.height), fmt); - - // Cleanup - delete input; - // - return tex; + return Texture::Create(texturedata, RadeonRays::int2(spec.width, spec.height), fmt);; } - - void Oiio::SaveImage(std::string const& filename, Texture const* texture) const + + void Oiio::SaveImage(std::string const& filename, Texture::Ptr texture) const { OIIO_NAMESPACE_USING; - - ImageOutput* out = ImageOutput::create(filename); - + + std::unique_ptr out{ImageOutput::create(filename)}; + if (!out) { throw std::runtime_error("Can't create image file on disk"); } - + auto dim = texture->GetSize(); auto fmt = GetTextureForemat(texture->GetFormat()); - + ImageSpec spec(dim.x, dim.y, 4, fmt); - + out->open(filename, spec); - + out->write_image(fmt, texture->GetData()); out->close(); - } - - ImageIo* ImageIo::CreateImageIo() + + std::unique_ptr ImageIo::CreateImageIo() { - return new Oiio(); + return std::make_unique(); } } diff --git a/Baikal/SceneGraph/IO/image_io.h b/Tools/MaterialConverter/BaikalOld/SceneGraph/IO/image_io.h similarity index 89% rename from Baikal/SceneGraph/IO/image_io.h rename to Tools/MaterialConverter/BaikalOld/SceneGraph/IO/image_io.h index ba72be91..10cd1fac 100644 --- a/Baikal/SceneGraph/IO/image_io.h +++ b/Tools/MaterialConverter/BaikalOld/SceneGraph/IO/image_io.h @@ -29,8 +29,11 @@ #pragma once #include +#include -namespace Baikal +#include "BaikalOld/SceneGraph/texture.h" + +namespace BaikalOld { class Texture; @@ -43,7 +46,7 @@ namespace Baikal { public: // Create default image IO - static ImageIo* CreateImageIo(); + static std::unique_ptr CreateImageIo(); // Constructor ImageIo() = default; @@ -51,8 +54,8 @@ namespace Baikal virtual ~ImageIo() = default; // Load texture from file - virtual Texture* LoadImage(std::string const& filename) const = 0; - virtual void SaveImage(std::string const& filename, Texture const* texture) const = 0; + virtual Texture::Ptr LoadImage(std::string const& filename) const = 0; + virtual void SaveImage(std::string const& filename, Texture::Ptr texture) const = 0; // Disallow copying ImageIo(ImageIo const&) = delete; diff --git a/Baikal/SceneGraph/IO/material_io.cpp b/Tools/MaterialConverter/BaikalOld/SceneGraph/IO/material_io.cpp similarity index 58% rename from Baikal/SceneGraph/IO/material_io.cpp rename to Tools/MaterialConverter/BaikalOld/SceneGraph/IO/material_io.cpp index 3bd2ce7f..ad62374b 100644 --- a/Baikal/SceneGraph/IO/material_io.cpp +++ b/Tools/MaterialConverter/BaikalOld/SceneGraph/IO/material_io.cpp @@ -1,21 +1,19 @@ #include "material_io.h" -#include "SceneGraph/scene1.h" -#include "SceneGraph/iterator.h" -#include "SceneGraph/shape.h" -#include "SceneGraph/material.h" - -#include "SceneGraph/IO/image_io.h" -#include "SceneGraph/Collector/collector.h" +#include "BaikalOld/SceneGraph/iterator.h" +#include "BaikalOld/SceneGraph/material.h" +#include "BaikalOld/SceneGraph/IO/image_io.h" #include "XML/tinyxml2.h" +#include #include #include #include +#include -namespace Baikal +namespace BaikalOld { using namespace tinyxml2; @@ -27,27 +25,27 @@ namespace Baikal void SaveMaterials(std::string const& filename, Iterator& iterator) override; // Load materials from disk - Iterator* LoadMaterials(std::string const& filename) override; + std::unique_ptr LoadMaterials(std::string const& file_name) override; private: // Write single material - void WriteMaterial(ImageIo& io, XMLPrinter& printer, Material const* material); + void WriteMaterial(ImageIo& io, XMLPrinter& printer, Material::Ptr material); // Write single material input void WriteInput(ImageIo& io, XMLPrinter& printer, std::string const& name, Material::InputValue value); // Load single material - Material* LoadMaterial(ImageIo& io, XMLElement& element); + Material::Ptr LoadMaterial(ImageIo& io, XMLElement& element); // Load single input - void LoadInput(ImageIo& io, Material* material, XMLElement& element); + void LoadInput(ImageIo& io, Material::Ptr material, XMLElement& element); // Texture to name map - std::map m_tex2name; + std::map m_tex2name; - std::map m_name2tex; - std::map m_id2mat; + std::map m_name2tex; + std::map m_id2mat; struct ResolveRequest { - Material* material; + Material::Ptr material; std::string input; std::uint64_t id; @@ -61,9 +59,9 @@ namespace Baikal std::string m_base_path; }; - MaterialIo* MaterialIo::CreateMaterialIoXML() + std::unique_ptr MaterialIo::CreateMaterialIoXML() { - return new MaterialIoXML(); + return std::make_unique(); } static std::string Float4ToString(RadeonRays::float3 const& v) @@ -77,27 +75,27 @@ namespace Baikal { switch (type) { - case Baikal::SingleBxdf::BxdfType::kZero: + case BaikalOld::SingleBxdf::BxdfType::kZero: return "zero"; - case Baikal::SingleBxdf::BxdfType::kLambert: + case BaikalOld::SingleBxdf::BxdfType::kLambert: return "lambert"; - case Baikal::SingleBxdf::BxdfType::kIdealReflect: + case BaikalOld::SingleBxdf::BxdfType::kIdealReflect: return "ideal_reflect"; - case Baikal::SingleBxdf::BxdfType::kIdealRefract: + case BaikalOld::SingleBxdf::BxdfType::kIdealRefract: return "ideal_refract";; - case Baikal::SingleBxdf::BxdfType::kMicrofacetBeckmann: + case BaikalOld::SingleBxdf::BxdfType::kMicrofacetBeckmann: return "microfacet_beckmann"; - case Baikal::SingleBxdf::BxdfType::kMicrofacetGGX: + case BaikalOld::SingleBxdf::BxdfType::kMicrofacetGGX: return "microfacet_ggx"; - case Baikal::SingleBxdf::BxdfType::kEmissive: + case BaikalOld::SingleBxdf::BxdfType::kEmissive: return "emissive"; - case Baikal::SingleBxdf::BxdfType::kPassthrough: + case BaikalOld::SingleBxdf::BxdfType::kPassthrough: return "passthrough"; - case Baikal::SingleBxdf::BxdfType::kTranslucent: + case BaikalOld::SingleBxdf::BxdfType::kTranslucent: return "translucent"; - case Baikal::SingleBxdf::BxdfType::kMicrofacetRefractionGGX: + case BaikalOld::SingleBxdf::BxdfType::kMicrofacetRefractionGGX: return "microfacet_refraction_ggx"; - case Baikal::SingleBxdf::BxdfType::kMicrofacetRefractionBeckmann: + case BaikalOld::SingleBxdf::BxdfType::kMicrofacetRefractionBeckmann: return "microfacet_refraction_beckmann"; default: return "lambert"; @@ -108,17 +106,17 @@ namespace Baikal { static std::map bxdf_map = { - { "zero" , Baikal::SingleBxdf::BxdfType::kZero }, - { "lambert" , Baikal::SingleBxdf::BxdfType::kLambert }, - { "ideal_reflect" , Baikal::SingleBxdf::BxdfType::kIdealReflect }, - { "ideal_refract" , Baikal::SingleBxdf::BxdfType::kIdealRefract }, - { "microfacet_beckmann" , Baikal::SingleBxdf::BxdfType::kMicrofacetBeckmann }, - { "microfacet_ggx" , Baikal::SingleBxdf::BxdfType::kMicrofacetGGX }, - { "emissive" , Baikal::SingleBxdf::BxdfType::kEmissive }, - { "passthrough" , Baikal::SingleBxdf::BxdfType::kPassthrough }, - { "translucent" , Baikal::SingleBxdf::BxdfType::kTranslucent }, - { "microfacet_refraction_ggx" , Baikal::SingleBxdf::BxdfType::kMicrofacetRefractionGGX }, - { "microfacet_refraction_beckmann" , Baikal::SingleBxdf::BxdfType::kMicrofacetRefractionBeckmann }, + { "zero" , BaikalOld::SingleBxdf::BxdfType::kZero }, + { "lambert" , BaikalOld::SingleBxdf::BxdfType::kLambert }, + { "ideal_reflect" , BaikalOld::SingleBxdf::BxdfType::kIdealReflect }, + { "ideal_refract" , BaikalOld::SingleBxdf::BxdfType::kIdealRefract }, + { "microfacet_beckmann" , BaikalOld::SingleBxdf::BxdfType::kMicrofacetBeckmann }, + { "microfacet_ggx" , BaikalOld::SingleBxdf::BxdfType::kMicrofacetGGX }, + { "emissive" , BaikalOld::SingleBxdf::BxdfType::kEmissive }, + { "passthrough" , BaikalOld::SingleBxdf::BxdfType::kPassthrough }, + { "translucent" , BaikalOld::SingleBxdf::BxdfType::kTranslucent }, + { "microfacet_refraction_ggx" , BaikalOld::SingleBxdf::BxdfType::kMicrofacetRefractionGGX }, + { "microfacet_refraction_beckmann" , BaikalOld::SingleBxdf::BxdfType::kMicrofacetRefractionBeckmann }, }; auto iter = bxdf_map.find(bxdf); @@ -128,7 +126,7 @@ namespace Baikal return iter->second; } - return Baikal::SingleBxdf::BxdfType::kLambert; + return BaikalOld::SingleBxdf::BxdfType::kLambert; } void MaterialIoXML::WriteInput(ImageIo& io, XMLPrinter& printer, std::string const& name, Material::InputValue value) @@ -155,7 +153,7 @@ namespace Baikal else { std::ostringstream oss; - oss << (std::uint64_t)value.tex_value << ".jpg"; + oss << (std::uint64_t)value.tex_value.get() << ".jpg"; io.SaveImage(m_base_path + oss.str(), value.tex_value); @@ -168,23 +166,23 @@ namespace Baikal { printer.PushAttribute("type", "material"); - printer.PushAttribute("value", (int)(reinterpret_cast(value.mat_value))); + printer.PushAttribute("value", (int)(reinterpret_cast(value.mat_value.get()))); } printer.CloseElement(); } - void MaterialIoXML::WriteMaterial(ImageIo& io, XMLPrinter& printer, Material const* material) + void MaterialIoXML::WriteMaterial(ImageIo& io, XMLPrinter& printer, Material::Ptr material) { printer.OpenElement("Material"); printer.PushAttribute("name", material->GetName().c_str()); - printer.PushAttribute("id", (int)(reinterpret_cast(material))); + printer.PushAttribute("id", (int)(reinterpret_cast(material.get()))); printer.PushAttribute("thin", material->IsThin()); - SingleBxdf const* bxdf = dynamic_cast(material); + auto bxdf = std::dynamic_pointer_cast(material); if (bxdf) { @@ -233,7 +231,7 @@ namespace Baikal } else { - MultiBxdf const* blend = dynamic_cast(material); + auto blend = std::dynamic_pointer_cast(material); printer.PushAttribute("type", "blend"); @@ -280,11 +278,11 @@ namespace Baikal m_tex2name.clear(); - std::unique_ptr image_io(ImageIo::CreateImageIo()); + auto image_io = ImageIo::CreateImageIo(); for (mat_iter.Reset();mat_iter.IsValid(); mat_iter.Next()) { - auto material = mat_iter.ItemAs(); + auto material = mat_iter.ItemAs(); if (material) { @@ -297,7 +295,7 @@ namespace Baikal doc.SaveFile(filename.c_str()); } - void MaterialIoXML::LoadInput(ImageIo& io, Material* material, XMLElement& element) + void MaterialIoXML::LoadInput(ImageIo& io, Material::Ptr material, XMLElement& element) { std::string type(element.Attribute("type")); std::string name(element.Attribute("name")); @@ -316,7 +314,6 @@ namespace Baikal else if (type == "texture") { std::string filename(element.Attribute("value")); - auto iter = m_name2tex.find(filename); if (iter != m_name2tex.cend()) @@ -326,6 +323,7 @@ namespace Baikal else { auto texture = io.LoadImage(m_base_path + filename); + texture->SetName(filename); material->SetInputValue(name, texture); m_name2tex[name] = texture; } @@ -351,7 +349,7 @@ namespace Baikal } } - Material* MaterialIoXML::LoadMaterial(ImageIo& io, XMLElement& element) + Material::Ptr MaterialIoXML::LoadMaterial(ImageIo& io, XMLElement& element) { std::string name(element.Attribute("name")); std::string type(element.Attribute("type")); @@ -360,11 +358,11 @@ namespace Baikal std::string thin(attribute_thin ? attribute_thin : ""); auto id = static_cast(std::atoi(element.Attribute("id"))); - Material* material = nullptr; + Material::Ptr material = nullptr; if (type == "simple") { - auto bxdf = new SingleBxdf(SingleBxdf::BxdfType::kLambert); + auto bxdf = SingleBxdf::Create(SingleBxdf::BxdfType::kLambert); auto bxdf_type = StringToBxdf(element.Attribute("bxdf")); @@ -374,7 +372,7 @@ namespace Baikal } else if (type == "blend") { - auto blend = new MultiBxdf(MultiBxdf::Type::kFresnelBlend); + auto blend = MultiBxdf::Create(MultiBxdf::Type::kFresnelBlend); auto blend_type = static_cast(std::atoi(element.Attribute("blend_type"))); @@ -401,28 +399,28 @@ namespace Baikal return material; } - Iterator* MaterialIoXML::LoadMaterials(std::string const& filename) + std::unique_ptr MaterialIoXML::LoadMaterials(std::string const& file_name) { m_id2mat.clear(); m_name2tex.clear(); m_resolve_requests.clear(); - auto slash = filename.find_last_of('/'); - if (slash == std::string::npos) slash = filename.find_last_of('\\'); + auto slash = file_name.find_last_of('/'); + if (slash == std::string::npos) slash = file_name.find_last_of('\\'); if (slash != std::string::npos) - m_base_path.assign(filename.cbegin(), filename.cbegin() + slash + 1); + m_base_path.assign(file_name.cbegin(), file_name.cbegin() + slash + 1); else m_base_path.clear(); XMLDocument doc; - doc.LoadFile(filename.c_str()); + doc.LoadFile(file_name.c_str()); - std::unique_ptr image_io(ImageIo::CreateImageIo()); + auto image_io = ImageIo::CreateImageIo(); - std::set materials; + std::set materials; for (auto element = doc.FirstChildElement(); element; element = element->NextSiblingElement()) { - Material* material = LoadMaterial(*image_io, *element); + auto material = LoadMaterial(*image_io, *element); materials.insert(material); } @@ -432,99 +430,7 @@ namespace Baikal i.material->SetInputValue(i.input, m_id2mat[i.id]); } - return new ContainerIterator>(std::move(materials)); - } - - void MaterialIo::SaveMaterialsFromScene(std::string const& filename, Scene1 const& scene) - { - std::unique_ptr shape_iter(scene.CreateShapeIterator()); - - Collector mat_collector; - // Collect materials from shapes first - mat_collector.Collect(shape_iter.get(), - // This function adds all materials to resulting map - // recursively via Material dependency API - [](void const* item) -> std::set - { - // Resulting material set - std::set mats; - // Material stack - std::stack material_stack; - - // Get material from current shape - auto shape = reinterpret_cast(item); - auto material = shape->GetMaterial(); - - if (material) - { - // Push to stack as an initializer - material_stack.push(material); - } - - // Drain the stack - while (!material_stack.empty()) - { - // Get current material - Material const* m = material_stack.top(); - material_stack.pop(); - - // Emplace into the set - mats.emplace(m); - - // Create dependency iterator - std::unique_ptr mat_iter(m->CreateMaterialIterator()); - - // Push all dependencies into the stack - for (; mat_iter->IsValid(); mat_iter->Next()) - { - material_stack.push(mat_iter->ItemAs()); - } - } - - // Return resulting set - return mats; - }); - - std::unique_ptr mat_iter(mat_collector.CreateIterator()); - - SaveMaterials(filename, *mat_iter); - } - - void MaterialIo::ReplaceSceneMaterials(Scene1& scene, Iterator& iterator, MaterialMap const& mapping) - { - std::map name2mat; - - for (iterator.Reset(); iterator.IsValid(); iterator.Next()) - { - auto material = iterator.ItemAs(); - auto name = material->GetName(); - name2mat[name] = material; - } - - std::unique_ptr shape_iter(scene.CreateShapeIterator()); - - for (; shape_iter->IsValid(); shape_iter->Next()) - { - // TODO: remove this hack - auto shape = const_cast(shape_iter->ItemAs()); - auto material = shape->GetMaterial(); - - if (!material) - continue; - - auto name = material->GetName(); - auto citer = mapping.find(name); - - if (citer != mapping.cend()) - { - auto mat_iter = name2mat.find(citer->second); - - if (mat_iter != name2mat.cend()) - { - shape->SetMaterial(mat_iter->second); - } - } - } + return std::make_unique>>(std::move(materials)); } MaterialIo::MaterialMap MaterialIo::LoadMaterialMapping(std::string const& filename) @@ -544,31 +450,4 @@ namespace Baikal return map; } - void MaterialIo::SaveIdentityMapping(std::string const& filename, Scene1 const& scene) - { - XMLDocument doc; - XMLPrinter printer; - - std::unique_ptr shape_iter(scene.CreateShapeIterator()); - std::set serialized_mats; - - for (; shape_iter->IsValid(); shape_iter->Next()) - { - auto material = shape_iter->ItemAs()->GetMaterial(); - - if (material && serialized_mats.find(material) == serialized_mats.cend()) - { - auto name = material->GetName(); - printer.OpenElement("Mapping"); - printer.PushAttribute("from", name.c_str()); - printer.PushAttribute("to", name.c_str()); - printer.CloseElement(); - serialized_mats.emplace(material); - } - } - - doc.Parse(printer.CStr()); - - doc.SaveFile(filename.c_str()); - } } diff --git a/Baikal/SceneGraph/IO/material_io.h b/Tools/MaterialConverter/BaikalOld/SceneGraph/IO/material_io.h similarity index 90% rename from Baikal/SceneGraph/IO/material_io.h rename to Tools/MaterialConverter/BaikalOld/SceneGraph/IO/material_io.h index ad45653c..6cc0b81b 100644 --- a/Baikal/SceneGraph/IO/material_io.h +++ b/Tools/MaterialConverter/BaikalOld/SceneGraph/IO/material_io.h @@ -30,8 +30,9 @@ #include #include +#include -namespace Baikal +namespace BaikalOld { class Scene1; class Iterator; @@ -45,7 +46,7 @@ namespace Baikal { public: // Create XML based material IO - static MaterialIo* CreateMaterialIoXML(); + static std::unique_ptr CreateMaterialIoXML(); using MaterialMap = std::map; @@ -55,10 +56,10 @@ namespace Baikal virtual ~MaterialIo() = 0; // Save materials from scene into a file - virtual void SaveMaterials(std::string const& filename, Iterator& iterator) = 0; + virtual void SaveMaterials(std::string const& file_name, Iterator& iterator) = 0; // Load materials from disk - virtual Iterator* LoadMaterials(std::string const& filename) = 0; + virtual std::unique_ptr LoadMaterials(std::string const& file_name) = 0; // Helper method: save all materials in the scene void SaveMaterialsFromScene(std::string const& filename, Scene1 const& scene); diff --git a/Tools/MaterialConverter/BaikalOld/SceneGraph/iterator.h b/Tools/MaterialConverter/BaikalOld/SceneGraph/iterator.h new file mode 100644 index 00000000..4107ce5b --- /dev/null +++ b/Tools/MaterialConverter/BaikalOld/SceneGraph/iterator.h @@ -0,0 +1,177 @@ +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ +#pragma once + +/** + \file iterator.h + \author Dmitry Kozlov + \version 1.0 + \brief Contains declaration of BaikalOld object iterators. + */ +#include "scene_object.h" + +namespace BaikalOld +{ + /** + \brief Iterator base interface. + + \details Iterators are used to go over different BaikalOld scene graph objects, such as meshes or lights. + */ + class Iterator + { + public: + // Constructor + Iterator() = default; + // Destructor + virtual ~Iterator() = default; + + // Valid means it still has items to iterate over: you can call Next() + virtual bool IsValid() const = 0; + + // Goes to next object, iterator should be valid before this call + virtual void Next() = 0; + + // Retrieve underlying object + virtual SceneObject::Ptr Item() const = 0; + + // Sets the iterator into its initial state (beginning of the sequence) + virtual void Reset() = 0; + + // Retrieve with uncoditional cast: caller is responsible of all the implications, no type check here + template typename T::Ptr ItemAs() const { return std::static_pointer_cast(Item()); } + + // Disable copies and moves + Iterator(Iterator const&) = delete; + Iterator& operator = (Iterator const&) = delete; + }; + + + /** + \brief Represents empty sequence. + + \details Objects return empty iterator when there is nothing to iterate over. + */ + class EmptyIterator : public Iterator + { + public: + // Constructor + EmptyIterator() = default; + // Destructor + ~EmptyIterator() = default; + // EmptyIterator is never valid + bool IsValid() const override { return false; } + // Nothing to go to + void Next() override {} + // Dereferencing always returns nullptr + SceneObject::Ptr Item() const override { return nullptr; } + // Nothing to reset + void Reset() override {} + }; + + /** + \brief Represents wrapper on iterable entities supporting comparison and ++. + + \details Objects return this type of iterator if they are iteration over arrays or stl containers. + */ + template class IteratorImpl : public Iterator + { + public: + // Initialize with an existing iterators + IteratorImpl(UnderlyingIterator begin, UnderlyingIterator end) + : m_begin(begin) + , m_end(end) + , m_cur(begin) + { + } + + // Check if we reached end + bool IsValid() const override + { + return m_cur != m_end; + } + + // Advance by 1 + void Next() override + { + ++m_cur; + } + + // Get underlying item + SceneObject::Ptr Item() const override + { + return *m_cur; + } + + // Set to starting iterator + void Reset() override + { + m_cur = m_begin; + } + + private: + UnderlyingIterator m_begin; + UnderlyingIterator m_end; + UnderlyingIterator m_cur; + }; + + template class ContainerIterator : public Iterator + { + public: + ContainerIterator(T&& container) : + m_container(std::move(container)) + { + m_begin = m_container.cbegin(); + m_end = m_container.cend(); + Reset(); + } + + // Check if we reached end + bool IsValid() const override + { + return m_cur != m_end; + } + + // Advance by 1 + void Next() override + { + ++m_cur; + } + + // Get underlying item + SceneObject::Ptr Item() const override + { + return *m_cur; + } + + // Set to starting iterator + void Reset() override + { + m_cur = m_begin; + } + + private: + T m_container; + typename T::const_iterator m_begin; + typename T::const_iterator m_end; + typename T::const_iterator m_cur; + }; +} diff --git a/Tools/MaterialConverter/BaikalOld/SceneGraph/material.cpp b/Tools/MaterialConverter/BaikalOld/SceneGraph/material.cpp new file mode 100644 index 00000000..241891a9 --- /dev/null +++ b/Tools/MaterialConverter/BaikalOld/SceneGraph/material.cpp @@ -0,0 +1,311 @@ +#include "material.h" +#include "iterator.h" + +#include +#include + +namespace BaikalOld +{ + Material::Material() + : m_thin(false) + { + } + + void Material::RegisterInput(std::string const& name, + std::string const& desc, + std::set&& supported_types) + { + Input input {{name, desc, std::move(supported_types)}, InputValue()}; + + assert(input.info.supported_types.size() > 0); + + input.value.type = *input.info.supported_types.begin(); + + switch (input.value.type) + { + case InputType::kFloat4: + input.value.float_value = RadeonRays::float4(); + break; + case InputType::kTexture: + input.value.tex_value = nullptr; + break; + case InputType::kMaterial: + input.value.mat_value = nullptr; + break; + default: + break; + } + + m_inputs.emplace(std::make_pair(name, input)); + } + + void Material::ClearInputs() + { + m_inputs.clear(); + } + + + // Iterator of dependent materials (plugged as inputs) + std::unique_ptr Material::CreateMaterialIterator() const + { + std::set materials; + + std::for_each(m_inputs.cbegin(), m_inputs.cend(), + [&materials](std::pair const& map_entry) + { + if (map_entry.second.value.type == InputType::kMaterial && + map_entry.second.value.mat_value != nullptr) + { + materials.insert(map_entry.second.value.mat_value); + } + } + ); + + return std::make_unique>>(std::move(materials)); + } + + // Iterator of textures (plugged as inputs) + std::unique_ptr Material::CreateTextureIterator() const + { + std::set textures; + + std::for_each(m_inputs.cbegin(), m_inputs.cend(), + [&textures](std::pair const& map_entry) + { + if (map_entry.second.value.type == InputType::kTexture && + map_entry.second.value.tex_value != nullptr) + { + textures.insert(map_entry.second.value.tex_value); + } + } + ); + + return std::make_unique>>(std::move(textures)); + } + + // Set input value + // If specific data type is not supported throws std::runtime_error + + Material::Input& Material::GetInput(const std::string& name, InputType type) + { + auto input_iter = m_inputs.find(name); + if (input_iter == m_inputs.cend()) + { + throw std::runtime_error("No such input"); + } + + auto& input = input_iter->second; + if (input.info.supported_types.find(type) == input.info.supported_types.cend()) + { + throw std::runtime_error("Input type not supported"); + } + + return input; + } + + void Material::SetInputValue(std::string const& name, uint32_t value) + { + auto& input = GetInput(name, InputType::kUint); + input.value.type = InputType::kUint; + input.value.uint_value = value; + SetDirty(true); + } + + void Material::SetInputValue(std::string const& name, RadeonRays::float4 const& value) + { + auto& input = GetInput(name, InputType::kFloat4); + input.value.type = InputType::kFloat4; + input.value.float_value = value; + SetDirty(true); + } + + void Material::SetInputValue(std::string const& name, Texture::Ptr texture) + { + auto& input = GetInput(name, InputType::kTexture); + input.value.type = InputType::kTexture; + input.value.tex_value = texture; + SetDirty(true); + } + + void Material::SetInputValue(std::string const& name, Material::Ptr material) + { + auto& input = GetInput(name, InputType::kMaterial); + input.value.type = InputType::kMaterial; + input.value.mat_value = material; + SetDirty(true); + } + + Material::InputValue Material::GetInputValue(std::string const& name) const + { + auto input_iter = m_inputs.find(name); + + if (input_iter != m_inputs.cend()) + { + auto& input = input_iter->second; + + return input.value; + } + else + { + throw std::runtime_error("No such input"); + } + } + + bool Material::IsThin() const + { + return m_thin; + } + + void Material::SetThin(bool thin) + { + m_thin = thin; + SetDirty(true); + } + + SingleBxdf::SingleBxdf(BxdfType type) + : m_type(type) + { + RegisterInput("albedo", "Diffuse color", {InputType::kFloat4, InputType::kTexture}); + RegisterInput("normal", "Normal map", {InputType::kTexture}); + RegisterInput("bump", "Bump map", { InputType::kTexture }); + RegisterInput("ior", "Index of refraction", {InputType::kFloat4}); + RegisterInput("fresnel", "Fresnel flag", {InputType::kFloat4}); + RegisterInput("roughness", "Roughness", {InputType::kFloat4, InputType::kTexture}); + + SetInputValue("albedo", RadeonRays::float4(0.7f, 0.7f, 0.7f, 1.f)); + SetInputValue("normal", static_cast(nullptr)); + SetInputValue("bump", static_cast(nullptr)); + } + + SingleBxdf::BxdfType SingleBxdf::GetBxdfType() const + { + return m_type; + } + + void SingleBxdf::SetBxdfType(BxdfType type) + { + m_type = type; + SetDirty(true); + } + + bool SingleBxdf::HasEmission() const + { + return m_type == BxdfType::kEmissive; + } + + MultiBxdf::MultiBxdf(Type type) + : m_type(type) + { + RegisterInput("base_material", "Base material", {InputType::kMaterial}); + RegisterInput("top_material", "Top material", {InputType::kMaterial}); + RegisterInput("ior", "Index of refraction", {InputType::kFloat4}); + RegisterInput("weight", "Blend weight", {InputType::kFloat4, InputType::kTexture}); + } + + MultiBxdf::Type MultiBxdf::GetType() const + { + return m_type; + } + + void MultiBxdf::SetType(Type type) + { + m_type = type; + SetDirty(true); + } + + bool MultiBxdf::HasEmission() const + { + auto base = GetInputValue("base_material"); + auto top = GetInputValue("base_material"); + + if (base.mat_value && base.mat_value->HasEmission()) + return true; + if (top.mat_value && top.mat_value->HasEmission()) + return true; + + return false; + } + + DisneyBxdf::DisneyBxdf() + { + RegisterInput("albedo", "Base color", {InputType::kFloat4, InputType::kTexture}); + RegisterInput("metallic", "Metallicity", {InputType::kFloat4, InputType::kTexture}); + RegisterInput("subsurface", "Subsurface look of diffuse base", {InputType::kFloat4}); + RegisterInput("specular", "Specular exponent", {InputType::kFloat4, InputType::kTexture}); + RegisterInput("specular_tint", "Specular color to base", {InputType::kFloat4, InputType::kTexture}); + RegisterInput("anisotropy", "Anisotropy of specular layer", {InputType::kFloat4, InputType::kTexture}); + RegisterInput("sheen", "Sheen for cloth", {InputType::kFloat4, InputType::kTexture}); + RegisterInput("sheen_tint", "Sheen to base color", {InputType::kFloat4, InputType::kTexture}); + RegisterInput("clearcoat", "Clearcoat layer", {InputType::kFloat4, InputType::kTexture}); + RegisterInput("clearcoat_gloss", "Clearcoat roughness", {InputType::kFloat4, InputType::kTexture}); + RegisterInput("roughness", "Roughness of specular & diffuse layers", {InputType::kFloat4, InputType::kTexture}); + RegisterInput("normal", "Normal map", {InputType::kTexture}); + RegisterInput("bump", "Bump map", { InputType::kTexture }); + + SetInputValue("albedo", RadeonRays::float4(0.7f, 0.7f, 0.7f, 1.f)); + SetInputValue("metallic", RadeonRays::float4(0.25f, 0.25f, 0.25f, 0.25f)); + SetInputValue("specular", RadeonRays::float4(0.25f, 0.25f, 0.25f, 0.25f)); + SetInputValue("normal", Texture::Ptr{nullptr}); + SetInputValue("bump", Texture::Ptr{nullptr}); + } + + // Check if material has emissive components + bool DisneyBxdf::HasEmission() const + { + return false; + } + + // VolumeMaterial implementation + VolumeMaterial::VolumeMaterial() + { + RegisterInput("absorption", "Absorption of volume material", { InputType::kFloat4 }); + RegisterInput("scattering", "Scattering of light inside of volume material", { InputType::kFloat4 }); + RegisterInput("emission", "Emission of light inside of volume material", { InputType::kFloat4 }); + RegisterInput("phase function", "Phase function", { InputType::kUint }); + + SetInputValue("absorption", RadeonRays::float4(.0f, .0f, .0f, .0f)); + SetInputValue("scattering", RadeonRays::float4(.0f, .0f, .0f, .0f)); + SetInputValue("emission", RadeonRays::float4(.0f, .0f, .0f, .0f)); + SetInputValue("phase function", 0); + } + + // Check if material has emissive components + bool VolumeMaterial::HasEmission() const + { + return (GetInputValue("emission").float_value.sqnorm() != 0); + } + + namespace { + struct SingleBxdfConcrete: public SingleBxdf { + SingleBxdfConcrete(BxdfType type) : + SingleBxdf(type) {} + }; + + struct MultiBxdfConcrete: public MultiBxdf { + MultiBxdfConcrete(Type type) : + BaikalOld::MultiBxdf(type) {} + }; + + struct DisneyBxdfConcrete: public DisneyBxdf { + }; + + struct VolumeMaterialConcrete : public VolumeMaterial { + }; + } + + SingleBxdf::Ptr SingleBxdf::Create(BxdfType type) { + return std::make_shared(type); + } + + MultiBxdf::Ptr MultiBxdf::Create(Type type) { + return std::make_shared(type); + } + + DisneyBxdf::Ptr DisneyBxdf::Create() { + return std::make_shared(); + } + + VolumeMaterial::Ptr VolumeMaterial::Create() { + return std::make_shared(); + } +} diff --git a/Tools/MaterialConverter/BaikalOld/SceneGraph/material.h b/Tools/MaterialConverter/BaikalOld/SceneGraph/material.h new file mode 100644 index 00000000..602e671c --- /dev/null +++ b/Tools/MaterialConverter/BaikalOld/SceneGraph/material.h @@ -0,0 +1,257 @@ +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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 material.h + \author Dmitry Kozlov + \version 1.0 + \brief Contains a class representing material + */ +#pragma once + +#include +#include +#include +#include +#include +#include "math/float3.h" + +#include "scene_object.h" +#include "texture.h" + +namespace BaikalOld +{ + class Iterator; + class Texture; + + /** + \brief High level material interface + + \details Base class for all CPU side material supported by the renderer. + */ + class Material : public SceneObject + { + public: + using Ptr = std::shared_ptr; + + // Material input type + enum class InputType + { + kUint = 0, + kFloat4, + kTexture, + kMaterial + }; + + // Input description + struct InputInfo + { + // Short name + std::string name; + // Desctiption + std::string desc; + // Set of supported types + std::set supported_types; + }; + + // Input value description + struct InputValue { + // Current type + InputType type; + + // Possible values (use based on type) + uint32_t uint_value; + RadeonRays::float4 float_value; + Texture::Ptr tex_value; + Material::Ptr mat_value; + + InputValue() + : type(InputType::kMaterial) + , float_value() + , tex_value(nullptr) + , mat_value(nullptr) + { + } + }; + + // Full input state + struct Input + { + InputInfo info; + InputValue value; + }; + + // Destructor + virtual ~Material() = 0; + + // Iterator of dependent materials (plugged as inputs) + virtual std::unique_ptr CreateMaterialIterator() const; + // Iterator of textures (plugged as inputs) + virtual std::unique_ptr CreateTextureIterator() const; + // Check if material has emissive components + virtual bool HasEmission() const; + + // Set input value + // If specific data type is not supported throws std::runtime_error + void SetInputValue(std::string const& name, uint32_t value); + void SetInputValue(std::string const& name, + RadeonRays::float4 const& value); + void SetInputValue(std::string const& name, Texture::Ptr texture); + void SetInputValue(std::string const& name, Material::Ptr material); + + InputValue GetInputValue(std::string const& name) const; + + // Check if material is thin (normal is always pointing in ray incidence + // direction) + bool IsThin() const; + // Set thin flag + void SetThin(bool thin); + + Material(Material const&) = delete; + Material& operator = (Material const&) = delete; + + protected: + Input& GetInput(const std::string& name, InputType type); + + Material(); + + // Register specific input + void RegisterInput(std::string const& name, std::string const& desc, + std::set&& supported_types); + + // Wipe out all the inputs + void ClearInputs(); + + private: + class InputIterator; + + using InputMap = std::unordered_map; + // Input map + InputMap m_inputs; + // Thin material + bool m_thin; + }; + + inline Material::~Material() + { + } + + inline bool Material::HasEmission() const + { + return false; + } + + class SingleBxdf : public Material + { + public: + enum class BxdfType + { + kZero, + kLambert, + kIdealReflect, + kIdealRefract, + kMicrofacetBeckmann, + kMicrofacetGGX, + kEmissive, + kPassthrough, + kTranslucent, + kMicrofacetRefractionGGX, + kMicrofacetRefractionBeckmann + }; + + using Ptr = std::shared_ptr; + static Ptr Create(BxdfType type); + + BxdfType GetBxdfType() const; + void SetBxdfType(BxdfType type); + + // Check if material has emissive components + bool HasEmission() const override; + + protected: + SingleBxdf(BxdfType type); + + private: + BxdfType m_type; + }; + + class MultiBxdf : public Material + { + public: + enum class Type + { + kLayered, + kFresnelBlend, + kMix + }; + + using Ptr = std::shared_ptr; + static Ptr Create(Type type); + + Type GetType() const; + void SetType(Type type); + + // Check if material has emissive components + bool HasEmission() const override; + + protected: + MultiBxdf(Type type); + + private: + Type m_type; + }; + + class DisneyBxdf : public Material + { + public: + using Ptr = std::shared_ptr; + static Ptr Create(); + + // Check if material has emissive components + bool HasEmission() const override; + + protected: + DisneyBxdf(); + }; + + class VolumeMaterial : public Material + { + public: + enum class PhaseFunction + { + kUniform = 0, + kRayleigh, + kMieMurky, + kMieHazy + }; + + using Ptr = std::shared_ptr; + static Ptr Create(); + + // Check if material has emissive components + bool HasEmission() const override; + + protected: + VolumeMaterial(); + }; + +} diff --git a/Tools/MaterialConverter/BaikalOld/SceneGraph/scene_object.h b/Tools/MaterialConverter/BaikalOld/SceneGraph/scene_object.h new file mode 100644 index 00000000..ac227f43 --- /dev/null +++ b/Tools/MaterialConverter/BaikalOld/SceneGraph/scene_object.h @@ -0,0 +1,94 @@ +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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 scene_object.h + \author Dmitry Kozlov + \version 1.0 + \brief Contains base interface for scene graph objects + */ +#pragma once + +#include +#include + +namespace BaikalOld +{ + class SceneObject + { + public: + using Ptr = std::shared_ptr; + + // Destructor + virtual ~SceneObject() = 0; + + // Check if the object has been changed since last reset + virtual bool IsDirty() const; + // Set dirty flag + virtual void SetDirty(bool dirty) const; + + // Set & get name + void SetName(std::string const& name); + std::string GetName() const; + + SceneObject(SceneObject const&) = delete; + SceneObject& operator = (SceneObject const&) = delete; + + protected: + // Constructor + SceneObject(); + + private: + mutable bool m_dirty; + + std::string m_name; + }; + + inline SceneObject::SceneObject() + : m_dirty(false) + { + } + + inline SceneObject::~SceneObject() + { + } + + inline bool SceneObject::IsDirty() const + { + return m_dirty; + } + + inline void SceneObject::SetDirty(bool dirty) const + { + m_dirty = dirty; + } + + inline std::string SceneObject::GetName() const + { + return m_name; + } + + inline void SceneObject::SetName(std::string const& name) + { + m_name = name; + } +} diff --git a/Tools/MaterialConverter/BaikalOld/SceneGraph/texture.cpp b/Tools/MaterialConverter/BaikalOld/SceneGraph/texture.cpp new file mode 100644 index 00000000..bfc0492e --- /dev/null +++ b/Tools/MaterialConverter/BaikalOld/SceneGraph/texture.cpp @@ -0,0 +1,90 @@ +#include "texture.h" + +#include "Utils/half.h" + +namespace BaikalOld +{ + RadeonRays::float3 Texture::ComputeAverageValue() const + { + auto avg = RadeonRays::float3(); + + switch (m_format) { + case Format::kRgba8: + { + auto data = reinterpret_cast(m_data.get()); + auto num_elements = m_size.x * m_size.y; + + + for (auto i = 0; i < num_elements; ++i) + { + float r = data[4 * i] / 255.f; + float g = data[4 * i + 1] / 255.f; + float b = data[4 * i + 2] / 255.f; + avg += RadeonRays::float3(r, g, b); + } + + avg *= (1.f / num_elements); + break; + } + case Format::kRgba16: + { + auto data = reinterpret_cast(m_data.get()); + auto num_elements = m_size.x * m_size.y; + + for (auto i = 0; i < num_elements; ++i) + { + auto r = data[4 * i]; + auto g = data[4 * i + 1]; + auto b = data[4 * i + 2]; + + half hr, hg, hb; + hr.setBits(r); + hg.setBits(g); + hb.setBits(b); + + avg += RadeonRays::float3(hr, hg, hb); + } + + avg *= (1.f / num_elements); + break; + } + case Format::kRgba32: + { + auto data = reinterpret_cast(m_data.get()); + auto num_elements = m_size.x * m_size.y; + + for (auto i = 0; i < num_elements; ++i) + { + auto r = data[4 * i]; + auto g = data[4 * i + 1]; + auto b = data[4 * i + 2]; + + avg += RadeonRays::float3(r, g, b); + } + + avg *= (1.f / num_elements); + break; + } + default: + break; + } + + return avg; + } + + namespace { + struct TextureConcrete: public Texture { + TextureConcrete() = default; + TextureConcrete(char* data, RadeonRays::int2 size, Format format) : + Texture(data, size, format){} + }; + } + + Texture::Ptr Texture::Create() { + return std::make_shared(); + } + + Texture::Ptr Texture::Create(char* data, RadeonRays::int2 size, Format format) { + return std::make_shared(data, size, format); + } +} diff --git a/Tools/MaterialConverter/BaikalOld/SceneGraph/texture.h b/Tools/MaterialConverter/BaikalOld/SceneGraph/texture.h new file mode 100644 index 00000000..d25c8570 --- /dev/null +++ b/Tools/MaterialConverter/BaikalOld/SceneGraph/texture.h @@ -0,0 +1,164 @@ +/********************************************************************** + Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + + 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 texture.h + \author Dmitry Kozlov + \version 1.0 + \brief Contains declaration of a texture class. + */ +#pragma once + +#include "math/float3.h" +#include "math/float2.h" +#include "math/int2.h" +#include +#include +#include + +#include "scene_object.h" + +namespace BaikalOld +{ + class Material; + + /** + \brief Texture class. + + Texture is used to host CPU memory for image data. + */ + class Texture : public SceneObject + { + public: + enum class Format + { + kRgba8, + kRgba16, + kRgba32 + }; + + using Ptr = std::shared_ptr; + static Ptr Create(char* data, RadeonRays::int2 size, Format format); + static Ptr Create(); + + // Destructor (the data is destroyed as well) + virtual ~Texture() = default; + + // Set data + void SetData(char* data, RadeonRays::int2 size, Format format); + + // Get texture dimensions + RadeonRays::int2 GetSize() const; + // Get texture raw data + char const* GetData() const; + // Get texture format + Format GetFormat() const; + // Get data size in bytes + std::size_t GetSizeInBytes() const; + + // Average normalized value + RadeonRays::float3 ComputeAverageValue() const; + + // Disallow copying + Texture(Texture const&) = delete; + Texture& operator = (Texture const&) = delete; + + protected: + // Constructor + Texture(); + // Note, that texture takes ownership of its data array + Texture(char* data, RadeonRays::int2 size, Format format); + + private: + // Image data + std::unique_ptr m_data; + // Image dimensions + RadeonRays::int2 m_size; + // Format + Format m_format; + }; + + inline Texture::Texture() + : m_data(new char[16]) + , m_size(2,2) + , m_format(Format::kRgba8) + { + // Create checkerboard by default + m_data[0] = m_data[1] = m_data[2] = m_data[3] = (char)0xFF; + m_data[4] = m_data[5] = m_data[6] = m_data[7] = (char)0x00; + m_data[8] = m_data[9] = m_data[10] = m_data[11] = (char)0xFF; + m_data[12] = m_data[13] = m_data[14] = m_data[15] = (char)0x00; + } + + inline Texture::Texture(char* data, RadeonRays::int2 size, Format format) + : m_data(data) + , m_size(size) + , m_format(format) + { + } + + inline void Texture::SetData(char* data, RadeonRays::int2 size, Format format) + { + m_data.reset(data); + m_size = size; + m_format = format; + SetDirty(true); + } + + inline RadeonRays::int2 Texture::GetSize() const + { + return m_size; + } + + inline char const* Texture::GetData() const + { + return m_data.get(); + } + + inline Texture::Format Texture::GetFormat() const + { + return m_format; + } + + inline std::size_t Texture::GetSizeInBytes() const + { + std::uint32_t component_size = 1; + + switch (m_format) { + case Format::kRgba8: + component_size = 1; + break; + case Format::kRgba16: + component_size = 2; + break; + case Format::kRgba32: + component_size = 4; + break; + default: + break; + } + + return 4 * component_size * m_size.x * m_size.y; + } + + +} diff --git a/Tools/MaterialConverter/CMakeLists.txt b/Tools/MaterialConverter/CMakeLists.txt new file mode 100644 index 00000000..794338b0 --- /dev/null +++ b/Tools/MaterialConverter/CMakeLists.txt @@ -0,0 +1,26 @@ +SET(BAIKAL_OLD_SOURCES + BaikalOld/SceneGraph/iterator.h + BaikalOld/SceneGraph/material.cpp + BaikalOld/SceneGraph/material.h + BaikalOld/SceneGraph/scene_object.h + BaikalOld/SceneGraph/texture.cpp + BaikalOld/SceneGraph/texture.h) + +SET(BAIKAL_OLD_IO_SOURCES + BaikalOld/SceneGraph/IO/image_io.cpp + BaikalOld/SceneGraph/IO/image_io.h + BaikalOld/SceneGraph/IO/material_io.cpp + BaikalOld/SceneGraph/IO/material_io.h) + +source_group("BaikalOld\\SceneGraph" FILES ${BAIKAL_OLD_SOURCES}) +source_group("BaikalOld\\SceneGraph\\IO" FILES ${BAIKAL_OLD_IO_SOURCES}) + +SET(SOURCES + material_converter.cpp + material_converter.h + main.cpp) + +add_executable(MaterialConverter ${SOURCES} ${BAIKAL_OLD_SOURCES} ${BAIKAL_OLD_IO_SOURCES}) +target_compile_features(MaterialConverter PRIVATE cxx_std_14) +target_include_directories(MaterialConverter PRIVATE .) +target_link_libraries(MaterialConverter PUBLIC Baikal BaikalIO) diff --git a/Tools/MaterialConverter/README.md b/Tools/MaterialConverter/README.md new file mode 100644 index 00000000..ef4c160c --- /dev/null +++ b/Tools/MaterialConverter/README.md @@ -0,0 +1,6 @@ +## Material Converter +This tool is intended to convert Baikal scene materials setup specified in `materials.xml` from the "old" version to the UberV2. +### Usage +Run `MaterialConverter -p ` where `` is the folder that contains `mapping.xml` and `materials.xml` of the old Baikal version. +### Result +Material Converter will create `/materials_new.xml` which is compatible with UberV2. diff --git a/Tools/MaterialConverter/main.cpp b/Tools/MaterialConverter/main.cpp new file mode 100644 index 00000000..71f73c23 --- /dev/null +++ b/Tools/MaterialConverter/main.cpp @@ -0,0 +1,130 @@ +/********************************************************************** + Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + + 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 "BaikalOld/SceneGraph/IO/material_io.h" +#include "BaikalOld/SceneGraph/iterator.h" +#include "BaikalOld/SceneGraph/material.h" + +#include "material_io.h" +#include "SceneGraph/iterator.h" +#include "SceneGraph/uberv2material.h" + +#include "material_converter.h" +#include "XML/tinyxml2.h" +#include + +#include +#include +#include +#include +#include + +namespace +{ + char const* kHelpMessage = + "MaterialConverter -p "; +} + +static char* GetCmdOption(char** begin, char** end, const std::string& option) +{ + char** itr = std::find(begin, end, option); + if (itr != end && ++itr != end) + { + return *itr; + } + return 0; +} + +void Process(int argc, char** argv) +{ + char* scene_path = GetCmdOption(argv, argv + argc, "-p"); + + if (!scene_path) + { + std::cout << kHelpMessage << std::endl; + return; + } + + std::string scene_path_str = std::string(scene_path); + + std::ifstream in_materials(scene_path_str + "materials.xml"); + if (!in_materials) + { + throw std::runtime_error("Failed to open materials.xml file!"); + } + + std::ifstream in_mapping(scene_path_str + "mapping.xml"); + if (!in_mapping) + { + throw std::runtime_error("Failed to open mapping.xml file!"); + } + + in_materials.close(); + in_mapping.close(); + + std::cout << "Loading materials.xml" << std::endl; + + auto material_io = BaikalOld::MaterialIo::CreateMaterialIoXML(); + auto mats = material_io->LoadMaterials(scene_path_str + "materials.xml"); + + std::map all_materials; + for (mats->Reset(); mats->IsValid(); mats->Next()) + { + auto mtl = mats->ItemAs(); + all_materials[mtl->GetName()] = mtl; + } + + tinyxml2::XMLDocument doc; + doc.LoadFile((scene_path_str + "mapping.xml").c_str()); + + std::set old_materials; + for (auto element = doc.FirstChildElement(); element; element = element->NextSiblingElement()) + { + old_materials.emplace(all_materials[element->Attribute("to")]); + } + + std::cout << "Converting materials" << std::endl; + std::set new_materials = MaterialConverter::TranslateMaterials(old_materials); + + auto material_io_new = Baikal::MaterialIo::CreateMaterialIoXML(); + auto material_new_iterator = std::make_unique>(std::move(new_materials)); + + std::cout << "Saving to new materials xml file" << std::endl; + material_io_new->SaveMaterials(scene_path_str + "materials_new.xml", *material_new_iterator); + + std::cout << "Done." << std::endl; +} + +int main(int argc, char** argv) +{ + try + { + Process(argc, argv); + } + catch (std::exception& ex) + { + std::cerr << "Caught exception: " << ex.what() << std::endl; + return -1; + } + + return 0; +} diff --git a/Tools/MaterialConverter/material_converter.cpp b/Tools/MaterialConverter/material_converter.cpp new file mode 100644 index 00000000..263e85ce --- /dev/null +++ b/Tools/MaterialConverter/material_converter.cpp @@ -0,0 +1,693 @@ +/********************************************************************** + Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + + 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 "material_converter.h" + +#include "Utils/log.h" + +#include "BaikalOld/SceneGraph/iterator.h" + +#include "SceneGraph/iterator.h" +#include "SceneGraph/inputmaps.h" + +#include +#include +#include + +Baikal::Texture::Format MaterialConverter::TranslateFormat(BaikalOld::Texture::Format old_format) +{ + switch (old_format) + { + case BaikalOld::Texture::Format::kRgba8: + return Baikal::Texture::Format::kRgba8; + case BaikalOld::Texture::Format::kRgba16: + return Baikal::Texture::Format::kRgba16; + case BaikalOld::Texture::Format::kRgba32: + return Baikal::Texture::Format::kRgba32; + } + + return Baikal::Texture::Format::kRgba8; +} + +namespace +{ + static const Baikal::InputMap_ConstantFloat::Ptr kGammaPower = Baikal::InputMap_ConstantFloat::Create(2.2f); + static const Baikal::InputMap_ConstantFloat3::Ptr kBlackColor = Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3(0.0f, 0.0f, 0.0f)); + // Mark for passthrough bxdfs + static const Baikal::InputMap_ConstantFloat3::Ptr kPassthroughTransparency = Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3(0.0f, 0.0f, 0.0f)); + // Used by shading normal layer + static const Baikal::InputMap_ConstantFloat3::Ptr kNormalSrcRange = Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3(0.0f, 1.0f, 0.0f)); + static const Baikal::InputMap_ConstantFloat3::Ptr kNormalDstRange = Baikal::InputMap_ConstantFloat3::Create(RadeonRays::float3(-1.0f, 1.0f, 0.0f)); +} + +Baikal::InputMap::Ptr MaterialConverter::TranslateInput(BaikalOld::Material::Ptr old_mtl, std::string const& input_name) +{ + Baikal::InputMap::Ptr input_map = nullptr; + auto old_input_value = old_mtl->GetInputValue(input_name); + + Baikal::LogInfo("Translating input \"", input_name.c_str(), "\" of material \"", old_mtl->GetName(), "\"\n"); + + switch (old_input_value.type) + { + case BaikalOld::Material::InputType::kUint: + throw std::runtime_error("Cannot translate uint to input map!"); + break; + + case BaikalOld::Material::InputType::kMaterial: + throw std::runtime_error("Cannot translate material to input map!"); + break; + + case BaikalOld::Material::InputType::kFloat4: + Baikal::LogInfo("Float4 value: (", old_input_value.float_value.x, ", ", old_input_value.float_value.y, ", ", old_input_value.float_value.z, ")\n"); + input_map = Baikal::InputMap_ConstantFloat3::Create(old_input_value.float_value); + break; + + case BaikalOld::Material::InputType::kTexture: + { + Baikal::LogInfo("Texture value: \"", old_input_value.tex_value->GetName(), "\"\n"); + + char* data = new char[old_input_value.tex_value->GetSizeInBytes()]; + memcpy(data, old_input_value.tex_value->GetData(), old_input_value.tex_value->GetSizeInBytes()); + + RadeonRays::int2 old_size = old_input_value.tex_value->GetSize(); + + auto new_texture = Baikal::Texture::Create(data, + RadeonRays::int3(old_size.x, old_size.y, 1), + TranslateFormat(old_input_value.tex_value->GetFormat())); + + new_texture->SetName(old_input_value.tex_value->GetName()); + + input_map = Baikal::InputMap_Sampler::Create(new_texture); + + if (input_name == "albedo") + { + // Convert texture from gamma to linear space + input_map = Baikal::InputMap_Pow::Create(input_map, kGammaPower); + } + } + break; + + default: + throw std::runtime_error("Translation of unsupported input"); + } + + return input_map; +} + +Baikal::UberV2Material::Ptr MaterialConverter::TranslateSingleBxdfMaterial(BaikalOld::SingleBxdf::Ptr old_mtl) +{ + Baikal::LogInfo("Translating SingleBxdf material: \"", old_mtl->GetName(), "\"\n"); + + auto uber_mtl = Baikal::UberV2Material::Create(); + uber_mtl->SetName(old_mtl->GetName()); + + switch (old_mtl->GetBxdfType()) + { + case BaikalOld::SingleBxdf::BxdfType::kZero: + Baikal::LogInfo("BxdfType: Zero\n"); + uber_mtl->SetLayers(Baikal::UberV2Material::kDiffuseLayer); + // Black diffuse + uber_mtl->SetInputValue("uberv2.diffuse.color", kBlackColor); + break; + + case BaikalOld::SingleBxdf::BxdfType::kLambert: + Baikal::LogInfo("BxdfType: Lambert\n"); + uber_mtl->SetLayers(Baikal::UberV2Material::kDiffuseLayer); + uber_mtl->SetInputValue("uberv2.diffuse.color", TranslateInput(old_mtl, "albedo")); + if (old_mtl->GetInputValue("normal").tex_value != nullptr) + { + Baikal::LogInfo("Found normal\n"); + uber_mtl->SetLayers(Baikal::UberV2Material::kDiffuseLayer | Baikal::UberV2Material::kShadingNormalLayer); + uber_mtl->SetInputValue("uberv2.shading_normal", Baikal::InputMap_Remap::Create( + kNormalSrcRange, kNormalDstRange, TranslateInput(old_mtl, "normal"))); + } + break; + + case BaikalOld::SingleBxdf::BxdfType::kIdealReflect: + Baikal::LogInfo("BxdfType: Ideal reflection\n"); + uber_mtl->SetLayers(Baikal::UberV2Material::kReflectionLayer); + uber_mtl->SetInputValue("uberv2.reflection.color", TranslateInput(old_mtl, "albedo")); + uber_mtl->SetInputValue("uberv2.reflection.roughness", kBlackColor); + uber_mtl->SetInputValue("uberv2.reflection.ior", TranslateInput(old_mtl, "ior")); + break; + + case BaikalOld::SingleBxdf::BxdfType::kMicrofacetBeckmann: + case BaikalOld::SingleBxdf::BxdfType::kMicrofacetGGX: + Baikal::LogInfo("BxdfType: Microfacet reflection\n"); + uber_mtl->SetLayers(Baikal::UberV2Material::kReflectionLayer); + uber_mtl->SetInputValue("uberv2.reflection.color", TranslateInput(old_mtl, "albedo")); + uber_mtl->SetInputValue("uberv2.reflection.roughness", TranslateInput(old_mtl, "roughness")); + uber_mtl->SetInputValue("uberv2.reflection.ior", TranslateInput(old_mtl, "ior")); + break; + + case BaikalOld::SingleBxdf::BxdfType::kEmissive: + Baikal::LogInfo("BxdfType: Emission\n"); + uber_mtl->SetLayers(Baikal::UberV2Material::kEmissionLayer); + uber_mtl->SetInputValue("uberv2.emission.color", TranslateInput(old_mtl, "albedo")); + break; + case BaikalOld::SingleBxdf::BxdfType::kPassthrough: + Baikal::LogInfo("BxdfType: Passthrough\n"); + uber_mtl->SetLayers(Baikal::UberV2Material::kTransparencyLayer); + uber_mtl->SetInputValue("uberv2.transparency", kPassthroughTransparency); + break; + + case BaikalOld::SingleBxdf::BxdfType::kTranslucent: + Baikal::LogInfo("BxdfType: Translucensy\n"); + throw std::runtime_error("TranslateSingleBxdfMaterial: Translucent materials isn't supported in UberV2"); + break; + + case BaikalOld::SingleBxdf::BxdfType::kIdealRefract: + Baikal::LogInfo("BxdfType: Ideal refraction\n"); + uber_mtl->SetLayers(Baikal::UberV2Material::kRefractionLayer); + uber_mtl->SetInputValue("uberv2.refraction.color", TranslateInput(old_mtl, "albedo")); + uber_mtl->SetInputValue("uberv2.refraction.roughness", kBlackColor); + uber_mtl->SetInputValue("uberv2.refraction.ior", TranslateInput(old_mtl, "ior")); + break; + + case BaikalOld::SingleBxdf::BxdfType::kMicrofacetRefractionGGX: + case BaikalOld::SingleBxdf::BxdfType::kMicrofacetRefractionBeckmann: + Baikal::LogInfo("BxdfType: Microfacet refraction\n"); + uber_mtl->SetLayers(Baikal::UberV2Material::kRefractionLayer); + uber_mtl->SetInputValue("uberv2.refraction.color", TranslateInput(old_mtl, "albedo")); + uber_mtl->SetInputValue("uberv2.refraction.roughness", TranslateInput(old_mtl, "roughness")); + uber_mtl->SetInputValue("uberv2.refraction.ior", TranslateInput(old_mtl, "ior")); + break; + + default: + throw std::runtime_error("TranslateSingleBxdfMaterial: You shouldn't get here"); + + } + + return uber_mtl; +} + +bool HasLayer(std::uint32_t all_layers, std::uint32_t layer) +{ + return (all_layers & layer) == layer; +} + +Baikal::UberV2Material::Ptr MaterialConverter::MergeFresnelBlendMaterials(Baikal::UberV2Material::Ptr base, Baikal::UberV2Material::Ptr top, BaikalOld::Material::Ptr mtl) +{ + Baikal::LogInfo("Merge materials \"", base->GetName(), "\" and \"", top->GetName(), "\" into one\n"); + + auto result = Baikal::UberV2Material::Create(); + result->SetName(mtl->GetName()); + + std::uint32_t base_layers = base->GetLayers(); + std::uint32_t top_layers = top->GetLayers(); + std::uint32_t result_layers = 0; + + Baikal::InputMap::Ptr blend_factor = TranslateInput(mtl, "ior"); + + // Emission + { + bool base_has_emission = HasLayer(base_layers, Baikal::UberV2Material::kEmissionLayer); + bool top_has_emission = HasLayer(top_layers, Baikal::UberV2Material::kEmissionLayer); + + if (base_has_emission && top_has_emission) + { + Baikal::LogInfo("Base and top materials both have emission: merging as result = base + top\n"); + result_layers |= Baikal::UberV2Material::kEmissionLayer; + auto base_emission = base->GetInputValue("uberv2.emission.color").input_map_value; + auto top_emission = top->GetInputValue("uberv2.emission.color").input_map_value; + auto emission_result = Baikal::InputMap_Add::Create(base_emission, top_emission); + result->SetInputValue("uberv2.emission.color", emission_result); + } + else if (base_has_emission || top_has_emission) + { + result_layers |= Baikal::UberV2Material::kEmissionLayer; + + Baikal::InputMap::Ptr input_color = nullptr; + + if (base_has_emission) + { + Baikal::LogInfo("Base material: emission\n"); + input_color = base->GetInputValue("uberv2.emission.color").input_map_value; + } + + if (top_has_emission) + { + Baikal::LogInfo("Top material: emission\n"); + input_color = top->GetInputValue("uberv2.emission.color").input_map_value; + } + + result->SetInputValue("uberv2.emission.color", input_color); + } + } + + // Transparency + { + bool base_has_transparency = HasLayer(base_layers, Baikal::UberV2Material::kTransparencyLayer); + bool top_has_transparency = HasLayer(top_layers, Baikal::UberV2Material::kTransparencyLayer); + + if (base_has_transparency && top_has_transparency) + { + Baikal::LogInfo("Base and top materials both have transparency: merging as result = base * top\n"); + result_layers |= Baikal::UberV2Material::kTransparencyLayer; + auto base_transparency = base->GetInputValue("uberv2.transparency").input_map_value; + auto top_transparency = top->GetInputValue("uberv2.transparency").input_map_value; + auto transparency_result = Baikal::InputMap_Mul::Create(base_transparency, top_transparency); + result->SetInputValue("uberv2.transparency", transparency_result); + } + else if (base_has_transparency || top_has_transparency) + { + result_layers |= Baikal::UberV2Material::kTransparencyLayer; + + Baikal::InputMap::Ptr input_transparency = nullptr; + + if (base_has_transparency) + { + Baikal::LogInfo("Base material: transparency\n"); + input_transparency = base->GetInputValue("uberv2.transparency").input_map_value; + } + + if (top_has_transparency) + { + Baikal::LogInfo("Top material: transparency\n"); + input_transparency = top->GetInputValue("uberv2.transparency").input_map_value; + } + + if (input_transparency == kPassthroughTransparency) + { + Baikal::LogInfo("Set blend factor as transparency \n"); + input_transparency = blend_factor; + } + + result->SetInputValue("uberv2.transparency", input_transparency); + } + } + + // Coating + { + bool base_has_coating = HasLayer(base_layers, Baikal::UberV2Material::kCoatingLayer); + bool top_has_coating = HasLayer(top_layers, Baikal::UberV2Material::kCoatingLayer); + + if (base_has_coating && top_has_coating) + { + throw std::runtime_error("Base and top materials both have coating layer: merging is not supported"); + } + else if (base_has_coating || top_has_coating) + { + result_layers |= Baikal::UberV2Material::kCoatingLayer; + + Baikal::InputMap::Ptr input_color = nullptr; + Baikal::InputMap::Ptr input_ior = nullptr; + + if (base_has_coating) + { + Baikal::LogInfo("Base material: coating\n"); + input_color = base->GetInputValue("uberv2.coating.color").input_map_value; + input_ior = base->GetInputValue("uberv2.coating.ior").input_map_value; + } + + if (top_has_coating) + { + Baikal::LogInfo("Top material: coating\n"); + input_color = top->GetInputValue("uberv2.coating.color").input_map_value; + input_ior = top->GetInputValue("uberv2.coating.ior").input_map_value; + } + + result->SetInputValue("uberv2.coating.color", input_color); + result->SetInputValue("uberv2.coating.ior", input_ior); + } + } + + // Reflection + { + bool base_has_reflection = HasLayer(base_layers, Baikal::UberV2Material::kReflectionLayer); + bool top_has_reflection = HasLayer(top_layers, Baikal::UberV2Material::kReflectionLayer); + + if (base_has_reflection && top_has_reflection) + { + Baikal::LogInfo("Base and top materials both have reflection: merging as base - reflection, top - coating\n"); + // Base is reflection + result_layers |= Baikal::UberV2Material::kReflectionLayer; + + Baikal::InputMap::Ptr base_color = base->GetInputValue("uberv2.reflection.color").input_map_value; + Baikal::InputMap::Ptr base_roughness = base->GetInputValue("uberv2.reflection.roughness").input_map_value; + Baikal::InputMap::Ptr base_ior = base->GetInputValue("uberv2.reflection.ior").input_map_value; + + result->SetInputValue("uberv2.reflection.color", base_color); + result->SetInputValue("uberv2.reflection.roughness", base_roughness); + result->SetInputValue("uberv2.reflection.ior", base_ior); + + // Top is coating + result_layers |= Baikal::UberV2Material::kCoatingLayer; + + Baikal::InputMap::Ptr coating_color = top->GetInputValue("uberv2.reflection.color").input_map_value; + + result->SetInputValue("uberv2.coating.color", coating_color); + result->SetInputValue("uberv2.coating.ior", blend_factor); + } + else if (base_has_reflection || top_has_reflection) + { + result_layers |= Baikal::UberV2Material::kReflectionLayer; + + Baikal::InputMap::Ptr input_color = nullptr; + Baikal::InputMap::Ptr input_roughness = nullptr; + + if (base_has_reflection) + { + Baikal::LogInfo("Base material: reflection\n"); + input_color = base->GetInputValue("uberv2.reflection.color").input_map_value; + input_roughness = base->GetInputValue("uberv2.reflection.roughness").input_map_value; + } + + if (top_has_reflection) + { + Baikal::LogInfo("Top material: reflection\n"); + input_color = top->GetInputValue("uberv2.reflection.color").input_map_value; + input_roughness = top->GetInputValue("uberv2.reflection.roughness").input_map_value; + } + + result->SetInputValue("uberv2.reflection.color", input_color); + result->SetInputValue("uberv2.reflection.roughness", input_roughness); + result->SetInputValue("uberv2.reflection.ior", blend_factor); + } + } + + // Diffuse + { + bool base_has_diffuse = HasLayer(base_layers, Baikal::UberV2Material::kDiffuseLayer); + bool top_has_diffuse = HasLayer(top_layers, Baikal::UberV2Material::kDiffuseLayer); + + if (base_has_diffuse && top_has_diffuse) + { + Baikal::LogInfo("Base and top materials both have diffuse layer: merging as result = lerp(base, top, factor)\n"); + result_layers |= Baikal::UberV2Material::kDiffuseLayer; + Baikal::InputMap::Ptr base_diffuse = base->GetInputValue("uberv2.diffuse.color").input_map_value; + Baikal::InputMap::Ptr top_diffuse = top->GetInputValue("uberv2.diffuse.color").input_map_value; + result->SetInputValue("uberv2.diffuse.color", Baikal::InputMap_Lerp::Create(base_diffuse, top_diffuse, blend_factor)); + } + else if (base_has_diffuse || top_has_diffuse) + { + result_layers |= Baikal::UberV2Material::kDiffuseLayer; + + Baikal::InputMap::Ptr input_color = nullptr; + + if (base_has_diffuse) + { + Baikal::LogInfo("Base material: diffuse\n"); + input_color = base->GetInputValue("uberv2.diffuse.color").input_map_value; + } + + if (top_has_diffuse) + { + Baikal::LogInfo("Top material: diffuse\n"); + input_color = top->GetInputValue("uberv2.diffuse.color").input_map_value; + } + + result->SetInputValue("uberv2.diffuse.color", input_color); + } + } + + // Refraction + { + bool base_has_refraction = HasLayer(base_layers, Baikal::UberV2Material::kRefractionLayer); + bool top_has_refraction = HasLayer(top_layers, Baikal::UberV2Material::kRefractionLayer); + + if (base_has_refraction && top_has_refraction) + { + throw std::runtime_error("Base and top materials both have refraction layer: refraction merging is not supported"); + } + else if (base_has_refraction || top_has_refraction) + { + result_layers |= Baikal::UberV2Material::kRefractionLayer; + + Baikal::InputMap::Ptr input_color = nullptr; + Baikal::InputMap::Ptr input_roughness = nullptr; + + if (base_has_refraction) + { + Baikal::LogInfo("Base material: refraction\n"); + input_color = base->GetInputValue("uberv2.refraction.color").input_map_value; + input_roughness = base->GetInputValue("uberv2.refraction.roughness").input_map_value; + } + + if (top_has_refraction) + { + Baikal::LogInfo("Top material: refraction\n"); + input_color = top->GetInputValue("uberv2.refraction.color").input_map_value; + input_roughness = top->GetInputValue("uberv2.refraction.roughness").input_map_value; + } + + result->SetInputValue("uberv2.refraction.color", input_color); + result->SetInputValue("uberv2.refraction.roughness", input_roughness); + result->SetInputValue("uberv2.refraction.ior", blend_factor); + } + } + + // Shading normal + { + bool base_has_shading_normal = HasLayer(base_layers, Baikal::UberV2Material::kShadingNormalLayer); + bool top_has_shading_normal = HasLayer(top_layers, Baikal::UberV2Material::kShadingNormalLayer); + + if (base_has_shading_normal && top_has_shading_normal) + { + throw std::runtime_error("Base and top materials both have shading normal layer: refraction merging is not supported"); + } + else if (base_has_shading_normal || top_has_shading_normal) + { + result_layers |= Baikal::UberV2Material::kShadingNormalLayer; + Baikal::InputMap::Ptr input_normal = nullptr; + + if (base_has_shading_normal) + { + Baikal::LogInfo("Base material: shading normal\n"); + input_normal = base->GetInputValue("uberv2.shading_normal").input_map_value; + } + + if (top_has_shading_normal) + { + Baikal::LogInfo("Top material: shading normal\n"); + input_normal = top->GetInputValue("uberv2.shading_normal").input_map_value; + } + + result->SetInputValue("uberv2.shading_normal", input_normal); + } + } + + // Don't forget to set layers + result->SetLayers(result_layers); + return result; +} + +Baikal::UberV2Material::Ptr MaterialConverter::TranslateFresnelBlend(BaikalOld::MultiBxdf::Ptr mtl) +{ + auto base = mtl->GetInputValue("base_material").mat_value; + auto top = mtl->GetInputValue("top_material").mat_value; + + Baikal::LogInfo("Translating fresnel blend of \"", base->GetName(), "\" and \"", top->GetName(), "\"\n"); + + // Translate this materials and get two uber materials + // Then 'Merge' them to get single uber material + auto base_new = TranslateMaterial(base); + auto top_new = TranslateMaterial(top); + + return MergeFresnelBlendMaterials(base_new, top_new, mtl); +} + +Baikal::UberV2Material::Ptr MaterialConverter::MergeMixMaterials(Baikal::UberV2Material::Ptr base, Baikal::UberV2Material::Ptr top, BaikalOld::Material::Ptr mtl) +{ + Baikal::LogInfo("Merge mix materials \"", base->GetName(), "\" and \"", top->GetName(), "\" into one\n"); + + auto result = Baikal::UberV2Material::Create(); + result->SetName(mtl->GetName()); + + std::uint32_t base_layers = base->GetLayers(); + std::uint32_t top_layers = top->GetLayers(); + std::uint32_t result_layers = 0; + + Baikal::InputMap::Ptr blend_factor = TranslateInput(mtl, "weight"); + + static const std::vector>> kLayersInputs = + { + { + Baikal::UberV2Material::kEmissionLayer, + { "uberv2.emission.color" } + }, + { + Baikal::UberV2Material::kTransparencyLayer, + { "uberv2.transparency" } + }, + { + Baikal::UberV2Material::kCoatingLayer, + { "uberv2.coating.color", "uberv2.coating.ior" } + }, + { + Baikal::UberV2Material::kReflectionLayer, + { "uberv2.reflection.color", "uberv2.reflection.roughness", "uberv2.reflection.anisotropy", + "uberv2.reflection.anisotropy_rotation", "uberv2.reflection.ior", "uberv2.reflection.metalness" } + }, + { + Baikal::UberV2Material::kDiffuseLayer, + { "uberv2.diffuse.color" } + }, + { + Baikal::UberV2Material::kRefractionLayer, + { "uberv2.refraction.color", "uberv2.refraction.roughness", "uberv2.refraction.ior" } + }, + { + Baikal::UberV2Material::kShadingNormalLayer, + { "uberv2.shading_normal" } + }, + }; + + // Iterate through layers + for (auto const& item: kLayersInputs) + { + bool base_has_layer = HasLayer(base_layers, item.first); + bool top_has_layer = HasLayer(top_layers, item.first); + if (base_has_layer && top_has_layer) + { + result_layers |= item.first; + // Lerp inputs + for (auto const& input_name: item.second) + { + Baikal::LogInfo("Base and top materials both have ", input_name, ": merging as result = lerp(base, top, factor)\n"); + + auto base_input = base->GetInputValue(input_name).input_map_value; + auto top_input = top->GetInputValue(input_name).input_map_value; + + result->SetInputValue(input_name, Baikal::InputMap_Lerp::Create(base_input, top_input, blend_factor)); + } + } + else if (base_has_layer || top_has_layer) + { + result_layers |= item.first; + for (auto const& input_name: item.second) + { + Baikal::InputMap::Ptr input = nullptr; + + if (base_has_layer) + { + Baikal::LogInfo("Base material: ", input_name, "\n"); + input = base->GetInputValue(input_name).input_map_value; + } + + if (top_has_layer) + { + Baikal::LogInfo("Top material: ", input_name, "\n"); + input = top->GetInputValue(input_name).input_map_value; + } + + if (item.first == Baikal::UberV2Material::kTransparencyLayer && input == kPassthroughTransparency) + { + Baikal::LogInfo("Set blend factor as transparency \n"); + input = blend_factor; + } + + result->SetInputValue(input_name, input); + } + } + } + + // Don't forget to set layers + result->SetLayers(result_layers); + + return result; +} + +Baikal::UberV2Material::Ptr MaterialConverter::TranslateMix(BaikalOld::MultiBxdf::Ptr mtl) +{ + auto base = mtl->GetInputValue("base_material").mat_value; + auto top = mtl->GetInputValue("top_material").mat_value; + + Baikal::LogInfo("Translating mix of \"", base->GetName(), "\" and \"", top->GetName(), "\"\n"); + + // Translate this materials and get two uber materials + // Then 'Merge' them to get single uber material + auto base_new = TranslateMaterial(base); + auto top_new = TranslateMaterial(top); + + return MergeMixMaterials(base_new, top_new, mtl); +} + +Baikal::UberV2Material::Ptr MaterialConverter::TranslateMultiBxdfMaterial(BaikalOld::MultiBxdf::Ptr mtl) +{ + Baikal::LogInfo("Translating MultiBxdf material \"", mtl->GetName(), "\"\n"); + switch (mtl->GetType()) + { + case BaikalOld::MultiBxdf::Type::kLayered: + throw std::runtime_error("kLayered translation is not supported"); + case BaikalOld::MultiBxdf::Type::kFresnelBlend: + return TranslateFresnelBlend(mtl); + case BaikalOld::MultiBxdf::Type::kMix: + return TranslateMix(mtl); + } + + return nullptr; +} + +Baikal::UberV2Material::Ptr MaterialConverter::TranslateMaterial(BaikalOld::Material::Ptr mtl) +{ + if (auto single_bxdf = std::dynamic_pointer_cast(mtl)) + { + return TranslateSingleBxdfMaterial(single_bxdf); + } + else if (auto multi_bxdf = std::dynamic_pointer_cast(mtl)) + { + return TranslateMultiBxdfMaterial(multi_bxdf); + } + else if (auto disney_bxdf = std::dynamic_pointer_cast(mtl)) + { + throw std::runtime_error("Translation of disney bxdf materials is not supported"); + } + else if (auto volume_mtl = std::dynamic_pointer_cast(mtl)) + { + throw std::runtime_error("Translation of volume materials is not supported"); + } + + throw std::runtime_error("TranslateMaterial: unsupported material type"); +} + +std::set MaterialConverter::TranslateMaterials(std::set const& old_materials) +{ + std::set result; + unsigned int i = 0; + for (auto old_mtl: old_materials) + { + if (!old_mtl) + { + std::cout << "Empty material" << std::endl; + continue; + } + + Baikal::LogInfo("******************************************************\n"); + Baikal::LogInfo(++i, ". Processing scene material: \"", old_mtl->GetName(), "\"\n"); + Baikal::LogInfo("******************************************************\n"); + + try + { + auto new_mtl = TranslateMaterial(old_mtl); + new_mtl->SetName(old_mtl->GetName()); + result.insert(new_mtl); + } + catch (std::exception const& ex) + { + Baikal::LogInfo(">>> Caught exception: ", ex.what()); + throw; + } + } + + return result; +} diff --git a/Tools/MaterialConverter/material_converter.h b/Tools/MaterialConverter/material_converter.h new file mode 100644 index 00000000..60bfe8eb --- /dev/null +++ b/Tools/MaterialConverter/material_converter.h @@ -0,0 +1,47 @@ +/********************************************************************** + Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + + 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. + ********************************************************************/ + +#pragma once + +#include "BaikalOld/SceneGraph/material.h" + +#include "SceneGraph/uberv2material.h" + +#include + +class MaterialConverter +{ +public: + static std::set TranslateMaterials(std::set const& old_materials); + +private: + static Baikal::Texture::Format TranslateFormat(BaikalOld::Texture::Format old_format); + static Baikal::InputMap::Ptr TranslateInput(BaikalOld::Material::Ptr old_mtl, std::string const& input_name); + static Baikal::UberV2Material::Ptr TranslateSingleBxdfMaterial(BaikalOld::SingleBxdf::Ptr old_mtl); + static Baikal::UberV2Material::Ptr MergeFresnelBlendMaterials(Baikal::UberV2Material::Ptr base, Baikal::UberV2Material::Ptr top, BaikalOld::Material::Ptr mtl); + static Baikal::UberV2Material::Ptr MergeMixMaterials(Baikal::UberV2Material::Ptr base, Baikal::UberV2Material::Ptr top, BaikalOld::Material::Ptr mtl); + static Baikal::UberV2Material::Ptr TranslateFresnelBlend(BaikalOld::MultiBxdf::Ptr mtl); + static Baikal::UberV2Material::Ptr TranslateMix(BaikalOld::MultiBxdf::Ptr mtl); + static Baikal::UberV2Material::Ptr TranslateMultiBxdfMaterial(BaikalOld::MultiBxdf::Ptr mtl); + static Baikal::UberV2Material::Ptr TranslateMaterial(BaikalOld::Material::Ptr mtl); + +}; diff --git a/Tools/deploy/App.lua b/Tools/deploy/App.lua deleted file mode 100644 index a1fb93f7..00000000 --- a/Tools/deploy/App.lua +++ /dev/null @@ -1,52 +0,0 @@ -project "App" - kind "ConsoleApp" - location "../App" - links {"CLW"} - files { "../App/**.h", "../App/**.cpp", "../App/**.cl", "../App/**.fsh", "../App/**.vsh" } - includedirs{ "../FireRays/include", "../CLW" } - - configuration {"x64"} - links { "FireRays64" } - libdirs { "../FireRays/lib/x64"} - configuration {} - - if os.is("macosx") then - includedirs {"../3rdParty/oiio16/include"} - libdirs {"../3rdParty/oiio16/lib/x64"} - linkoptions{ "-framework OpenGL", "-framework GLUT" } - buildoptions "-std=c++11 -stdlib=libc++" - links {"OpenImageIO"} - end - - if os.is("windows") then - includedirs { "../3rdParty/glew/include", "../3rdParty/freeglut/include", "../3rdParty/oiio/include" } - links {"freeglut", "glew"} - - configuration {"x64"} - libdirs { "../3rdParty/glew/lib/x64", "../3rdParty/freeglut/lib/x64", "../3rdParty/embree/lib/x64", "../3rdParty/oiio/lib/x64"} - configuration {} - - configuration {"Debug"} - links {"OpenImageIOD"} - configuration {"Release"} - links {"OpenImageIO"} - end - - if os.is("linux") then - buildoptions "-std=c++11" - links {"OpenImageIO", "glut", "GLEW", "GL", "pthread"} - os.execute("rm -rf obj"); - end - - if _OPTIONS["embed_kernels"] then - configuration {} - defines {"FR_EMBED_KERNELS"} - os.execute("python ../scripts/stringify.py ./CL/ > ./CL/cache/kernels.h") - print ">> App: CL kernels embedded" - end - - configuration {"x64", "Debug"} - targetdir "../Bin/Debug/x64" - configuration {"x64", "Release"} - targetdir "../Bin/Release/x64" - configuration {} diff --git a/Tools/deploy/CLW.lua b/Tools/deploy/CLW.lua deleted file mode 100644 index eb581de4..00000000 --- a/Tools/deploy/CLW.lua +++ /dev/null @@ -1,26 +0,0 @@ -project "CLW" - kind "StaticLib" - location "../CLW" - includedirs { "." } - files { "../CLW/**.h", "../CLW/**.cpp", "../CLW/**.cl" } - - if os.is("macosx") then - buildoptions "-std=c++11 -stdlib=libc++" - else if os.is("linux") then - buildoptions "-std=c++11 -fPIC" - os.execute("rm -rf obj"); - end - end - - if _OPTIONS["embed_kernels"] then - configuration {} - defines {"FR_EMBED_KERNELS"} - os.execute("python ../scripts/stringify.py ./CL/ > ./CL/cache/kernels.h") - print ">> CLW: CL kernels embedded" - end - - configuration {"x64", "Debug"} - targetdir "../Bin/Debug/x64" - configuration {"x64", "Release"} - targetdir "../Bin/Release/x64" - configuration {} diff --git a/Tools/deploy/OpenCLSearch.lua b/Tools/deploy/OpenCLSearch.lua deleted file mode 100644 index 72e47896..00000000 --- a/Tools/deploy/OpenCLSearch.lua +++ /dev/null @@ -1,113 +0,0 @@ - if os.is("windows") then - local amdopenclpath = os.getenv("AMDAPPSDKROOT") - if( amdopenclpath ) then - amdopenclpath = string.gsub(amdopenclpath, "\\", "/"); - local clIncludePath = string.format("%s/include",amdopenclpath); - local clLibPath = string.format("%s/lib/x86",amdopenclpath); - local clLibPath64 = string.format("%s/lib/x86_64",amdopenclpath); - print("OpenCL_Path(AMD)", amdopenclpath) - if (amdopenclpath) then - includedirs {clIncludePath} - -- libdirs {clLibPath} - configuration "x64" - libdirs {clLibPath64} - configuration "x32" - libdirs {clLibPath} - configuration {} - links {"OpenCL"} - end - end - - local nvidiaopenclpath = os.getenv("CUDA_PATH") - if( nvidiaopenclpath ) then - defines { "OPENCL_10" } - nvidiaopenclpath = string.gsub(nvidiaopenclpath, "\\", "/"); - local clIncludePath = string.format("%s/include",nvidiaopenclpath); - local clLibPath = string.format("%s/lib/Win32",nvidiaopenclpath); - local clLibPath64 = string.format("%s/lib/x64",nvidiaopenclpath); - print("OpenCL_Path(Nvidia)", nvidiaopenclpath) - if (nvidiaopenclpath) then - includedirs {clIncludePath} - -- libdirs {clLibPath} - configuration "x64" - libdirs {clLibPath64} - configuration "x32" - libdirs {clLibPath} - configuration {} - links {"OpenCL"} - end - end - - local intelopenclpath = os.getenv("INTELOCLSDKROOT") - if( intelopenclpath ) then - defines { "INTEL_BUG_WORKROUND" } - intelopenclpath = string.gsub(intelopenclpath, "\\", "/"); - local clIncludePath = string.format("%s/include",intelopenclpath); - local clLibPath = string.format("%s/lib/x86",intelopenclpath); - local clLibPath64 = string.format("%s/lib/x64",intelopenclpath); - print("OpenCL_Path(Intel)", intelopenclpath) - if (intelopenclpath) then - includedirs {clIncludePath} - -- libdirs {clLibPath} - configuration "x64" - libdirs {clLibPath64} - configuration "x32" - libdirs {clLibPath} - configuration {} - links {"OpenCL"} - end - end - end - - if os.is("macosx") then - linkoptions{ "-framework OpenCL" } - end - - if os.is("linux") then - local amdopenclpath = os.getenv("AMDAPPSDKROOT") - local nvidiaopenclpath = os.getenv("CUDA_PATH") - if( amdopenclpath ) then - amdopenclpath = string.gsub(amdopenclpath, "\\", "/"); - local clIncludePath = string.format("%s/include",amdopenclpath); - local clLibPath = string.format("%s/lib/x86",amdopenclpath); - local clLibPath64 = string.format("%s/lib/x86_64",amdopenclpath); - print("OpenCL_Path(AMD)", amdopenclpath) - if (amdopenclpath) then - includedirs {clIncludePath} - -- libdirs {clLibPath} - configuration "x64" - libdirs {clLibPath64} - configuration "x32" - libdirs {clLibPath} - configuration {} - links {"OpenCL"} - end - elseif( nvidiaopenclpath ) then - defines { "OPENCL_10" } - nvidiaopenclpath = string.gsub(nvidiaopenclpath, "\\", "/"); - local clIncludePath = string.format("%s/include",nvidiaopenclpath); - local clLibPath = string.format("%s/lib/Win32",nvidiaopenclpath); - local clLibPath64 = string.format("%s/lib/x64",nvidiaopenclpath); - print("OpenCL_Path(Nvidia)", nvidiaopenclpath) - if (nvidiaopenclpath) then - includedirs {clIncludePath} - -- libdirs {clLibPath} - configuration "x64" - libdirs {clLibPath64} - configuration "x32" - libdirs {clLibPath} - configuration {} - links {"OpenCL"} - end - else - configuration "x64" - libdirs {"/usr/lib/x86_64-linux-gnu"} - configuration "x32" - libdirs {"/usr/lib/i386-linux-gnu"} - configuration {} - links {"OpenCL", "pthread"} - end - end - - - diff --git a/Tools/deploy/premake4.lua b/Tools/deploy/premake4.lua deleted file mode 100644 index c90db99e..00000000 --- a/Tools/deploy/premake4.lua +++ /dev/null @@ -1,81 +0,0 @@ -function fileExists(name) - local f=io.open(name,"r") - if f~=nil then io.close(f) return true else return false end -end - -newoption { - trigger = "embed_kernels", - description = "Embed CL kernels into binary module" -} - - -solution "FireRays" - configurations { "Debug", "Release" } - language "C++" - flags { "NoMinimalRebuild", "EnableSSE", "EnableSSE2" } - -- find and add path to Opencl headers - dofile ("./OpenCLSearch.lua" ) - -- define common includes - includedirs { ".","./3rdParty/include" } - - -- perform OS specific initializations - local targetName; - if os.is("macosx") then - targetName = "osx" - platforms {"x64"} - else - platforms {"x64"} - end - - if os.is("windows") then - targetName = "win" - defines{ "WIN32" } - buildoptions { "/MP" } --multiprocessor build - defines {"_CRT_SECURE_NO_WARNINGS"} - end - - --make configuration specific definitions - configuration "Debug" - defines { "_DEBUG" } - flags { "Symbols" } - configuration "Release" - defines { "NDEBUG" } - flags { "Optimize" } - - configuration {"x64", "Debug"} - targetsuffix "64D" - configuration {"x64", "Release"} - targetsuffix "64" - - configuration {} -- back to all configurations - - if fileExists("./CLW/CLW.lua") then - dofile("./CLW/CLW.lua") - end - - if fileExists("./App/App.lua") then - dofile("./App/App.lua") - end - - if os.is("windows") then - os.execute("mkdir Bin & cd Bin & mkdir Release & cd Release & mkdir x64 & cd .. & mkdir Debug & cd Debug & mkdir x64 & cd ../..") - - os.execute("cp ./3rdParty/freeglut/bin/x64/freeglut.dll ./Bin/Release/x64/") - os.execute("cp ./3rdParty/freeglut/bin/x64/freeglut.dll ./Bin/Debug/x64/") - - os.execute("cp ./3rdParty/glew/bin/x64/glew32.dll ./Bin/Release/x64/") - os.execute("cp ./3rdParty/glew/bin/x64/glew32.dll ./Bin/Debug/x64/") - - os.execute("cp ./3rdParty/oiio/bin/x64/OpenImageIO.dll ./Bin/Release/x64/") - os.execute("cp ./3rdParty/oiio/bin/x64/OpenImageIOD.dll ./Bin/Debug/x64/") - - os.execute("cp ./FireRays/bin/x64/FireRays64.dll ./Bin/Release/x64/") - os.execute("cp ./FireRays/bin/x64/FireRays64.dll ./Bin/Debug/x64/") - end - - - if os.is("macosx") then - os.execute("mkdir Bin ; cd Bin ; mkdir Release ; cd Release ; mkdir x64 ; cd .. ; mkdir Debug ; cd Debug ; mkdir x64 ; cd ../..") - os.execute("cp ./FireRays/lib/x64/libFireRays64.dylib ./Bin/Release/x64/") - os.execute("cp ./FireRays/lib/x64/libFireRays64.dylib ./Bin/Debug/x64/") - end diff --git a/Tools/premake/linux64/premake5 b/Tools/premake/linux64/premake5 deleted file mode 100644 index 099acd4a..00000000 Binary files a/Tools/premake/linux64/premake5 and /dev/null differ diff --git a/Tools/premake/osx/premake4 b/Tools/premake/osx/premake4 deleted file mode 100644 index 60428883..00000000 Binary files a/Tools/premake/osx/premake4 and /dev/null differ diff --git a/Tools/premake/osx/premake5 b/Tools/premake/osx/premake5 deleted file mode 100755 index 04d2d82e..00000000 Binary files a/Tools/premake/osx/premake5 and /dev/null differ diff --git a/Tools/premake/win/premake5.exe b/Tools/premake/win/premake5.exe deleted file mode 100644 index 6ce0e391..00000000 Binary files a/Tools/premake/win/premake5.exe and /dev/null differ diff --git a/Tools/scripts/baikal_stringify.py b/Tools/scripts/baikal_stringify.py new file mode 100644 index 00000000..bda0d791 --- /dev/null +++ b/Tools/scripts/baikal_stringify.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +import sys +import os +import re + +def make_header_list_recursive(file, files_to_headers_map): + header_list = [] + file_includes = [incs for f, incs in files_to_headers_map if f == file] + for i in file_includes[0]: + header_list += make_header_list_recursive(i, files_to_headers_map) + header_list += [i] + # remove duplicates and save order + return sorted(set(header_list), key=lambda x: header_list.index(x)) + +# generate variable name based on file and its type +def filevarname(file, typest): + return 'g_'+ file.replace(dir, '').replace(ext, '').replace('/', '_') + '_' + typest + +def print_file(filename, dir): + fh = open(dir + filename) + # include only new files + header_list = [] + for line in fh.readlines(): + a = line.strip('\r\n') + match = re.search('#include\s*<(.*/.+)>', a) + if match: + header_name = match.group(1) + if header_name not in header_list: + header_list.append(header_name) + print('"' + a.replace('\\','\\\\').replace('"', '\\"') + ' \\n"\\') + return header_list + +def stringify(filename, dir, typest): + print('static const char ' + filevarname(filename, typest) +'[] = \\') + header_list = print_file(filename, dir) + print(';\n') + return header_list + +argvs = sys.argv + +if len(argvs) == 4: + dir = argvs[1] + ext = argvs[2] + typest = argvs[3] +else: + sys.error('Wrong argument count!') + +files = [] +for root, directories, filenames in os.walk(dir): + for filename in filenames: + name = os.path.join(os.path.relpath(root, dir), filename) + name = name.replace('\\', '/') + name = name.replace('./', '') + files.append(name) + + +print('/* This is an auto-generated file. Do not edit manually! */\n') +print('#pragma once\n') +print('#include \n') + +# this will contain tuple(filename, include files) +files_to_headers_map = [] +for file in files: + if file.find(ext) == -1: + continue + header_list = stringify(file, dir, typest) + files_to_headers_map.append((dir + file, header_list)) + +for file, headers in files_to_headers_map: + if not headers: + continue + print('static const std::unordered_map ' + filevarname(file, typest) + '_headers =\n{') + for i in make_header_list_recursive(file, files_to_headers_map): + print(' {"' + i + '", ' + filevarname(i, typest) + '},') + print('};\n') diff --git a/cmake/FindFBX_SDK.cmake b/cmake/FindFBX_SDK.cmake new file mode 100644 index 00000000..547416b6 --- /dev/null +++ b/cmake/FindFBX_SDK.cmake @@ -0,0 +1,34 @@ +set(FBX_SDK_DIR "C:/Program Files/Autodesk/FBX/FBX SDK/2017.0.1") + +if (WIN32) + set(FBX_SDK_LIB_NAME libfbxsdk-md) +else () + set(FBX_SDK_LIB_NAME fbxsdk) +endif (WIN32) + +find_library(FBX_SDK_LIBRARY_RELEASE NAMES ${FBX_SDK_LIB_NAME} PATHS "${FBX_SDK_DIR}/lib/vs2015/x64/release") +find_library(FBX_SDK_LIBRARY_DEBUG NAMES ${FBX_SDK_LIB_NAME} PATHS "${FBX_SDK_DIR}/lib/vs2015/x64/debug") +find_path(FBX_SDK_INCLUDE_DIR NAMES fbxsdk.h PATHS "${FBX_SDK_DIR}/include") + +include(SelectLibraryConfigurations) +select_library_configurations(FBX_SDK) + +find_package_handle_standard_args(FBX_SDK DEFAULT_MSG FBX_SDK_LIBRARY FBX_SDK_INCLUDE_DIR) + +add_library(fbxsdk::fbxsdk UNKNOWN IMPORTED) + +set_target_properties(fbxsdk::fbxsdk PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FBX_SDK_INCLUDE_DIR}") + +if (OIIO_LIBRARY_RELEASE) + set_property(TARGET fbxsdk::fbxsdk APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) + set_target_properties(fbxsdk::fbxsdk PROPERTIES IMPORTED_LOCATION_RELEASE "${FBX_SDK_LIBRARY_RELEASE}") +endif (OIIO_LIBRARY_RELEASE) + +if (OIIO_LIBRARY_DEBUG) + set_property(TARGET fbxsdk::fbxsdk APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(fbxsdk::fbxsdk PROPERTIES IMPORTED_LOCATION_DEBUG "${FBX_SDK_LIBRARY_DEBUG}") +endif (OIIO_LIBRARY_DEBUG) + +if(NOT OIIO_LIBRARY_RELEASE AND NOT OIIO_LIBRARY_DEBUG) + set_property(TARGET fbxsdk::fbxsdk APPEND PROPERTY IMPORTED_LOCATION "${FBX_SDK_LIBRARY}") +endif(NOT OIIO_LIBRARY_RELEASE AND NOT OIIO_LIBRARY_DEBUG) diff --git a/cmake/FindGLEW.cmake b/cmake/FindGLEW.cmake new file mode 100644 index 00000000..7ab4b4ef --- /dev/null +++ b/cmake/FindGLEW.cmake @@ -0,0 +1,69 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# FindGLEW +# -------- +# +# Find the OpenGL Extension Wrangler Library (GLEW) +# +# IMPORTED Targets +# ^^^^^^^^^^^^^^^^ +# +# This module defines the :prop_tgt:`IMPORTED` target ``GLEW::GLEW``, +# if GLEW has been found. +# +# Result Variables +# ^^^^^^^^^^^^^^^^ +# +# This module defines the following variables: +# +# :: +# +# GLEW_INCLUDE_DIRS - include directories for GLEW +# GLEW_LIBRARIES - libraries to link against GLEW +# GLEW_FOUND - true if GLEW has been found and can be used + +set(GLEW_DIR "${Baikal_SOURCE_DIR}/3rdparty/glew") + +find_path(GLEW_INCLUDE_DIR GL/glew.h PATHS "${GLEW_DIR}/include") + +if(NOT GLEW_LIBRARY) + find_library(GLEW_LIBRARY_RELEASE NAMES GLEW glew32 glew glew32s PATH_SUFFIXES lib64 PATHS "${GLEW_DIR}/lib/x64") + find_library(GLEW_LIBRARY_DEBUG NAMES GLEWd glew32d glewd PATH_SUFFIXES lib64 PATHS "${GLEW_DIR}/lib/x64") + + include(SelectLibraryConfigurations) + select_library_configurations(GLEW) +endif () + +find_package_handle_standard_args(GLEW REQUIRED_VARS GLEW_INCLUDE_DIR GLEW_LIBRARY) + +if(GLEW_FOUND) + set(GLEW_INCLUDE_DIRS "${GLEW_INCLUDE_DIR}") + + if(NOT GLEW_LIBRARIES) + set(GLEW_LIBRARIES "${GLEW_LIBRARY}") + endif() + + if (NOT TARGET GLEW::GLEW) + add_library(GLEW::GLEW UNKNOWN IMPORTED) + set_target_properties(GLEW::GLEW PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${GLEW_INCLUDE_DIRS}") + + if(GLEW_LIBRARY_RELEASE) + set_property(TARGET GLEW::GLEW APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) + set_target_properties(GLEW::GLEW PROPERTIES IMPORTED_LOCATION_RELEASE "${GLEW_LIBRARY_RELEASE}") + endif() + + if(GLEW_LIBRARY_DEBUG) + set_property(TARGET GLEW::GLEW APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(GLEW::GLEW PROPERTIES IMPORTED_LOCATION_DEBUG "${GLEW_LIBRARY_DEBUG}") + endif() + + if(NOT GLEW_LIBRARY_RELEASE AND NOT GLEW_LIBRARY_DEBUG) + set_property(TARGET GLEW::GLEW APPEND PROPERTY IMPORTED_LOCATION "${GLEW_LIBRARY}") + endif() + endif() +endif() + +mark_as_advanced(GLEW_INCLUDE_DIR) diff --git a/cmake/FindGLFW3.cmake b/cmake/FindGLFW3.cmake new file mode 100644 index 00000000..356c877b --- /dev/null +++ b/cmake/FindGLFW3.cmake @@ -0,0 +1,10 @@ +set(GLFW3_DIR "${Baikal_SOURCE_DIR}/3rdparty/glfw") + +find_library(GLFW3_LIB NAMES glfw glfw3 PATHS "${GLFW3_DIR}/lib/x64") +find_path(GLFW3_INCLUDE_DIR NAMES GLFW/glfw3.h PATHS "${GLFW3_DIR}/include") + +find_package_handle_standard_args(GLFW3 DEFAULT_MSG GLFW3_LIB GLFW3_INCLUDE_DIR) + +add_library(glfw3::glfw3 UNKNOWN IMPORTED) +set_target_properties(glfw3::glfw3 PROPERTIES IMPORTED_LOCATION "${GLFW3_LIB}") +set_target_properties(glfw3::glfw3 PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${GLFW3_INCLUDE_DIR}") diff --git a/cmake/FindOIIO.cmake b/cmake/FindOIIO.cmake new file mode 100644 index 00000000..41281b21 --- /dev/null +++ b/cmake/FindOIIO.cmake @@ -0,0 +1,30 @@ +set(OIIO_DIR "${Baikal_SOURCE_DIR}/3rdparty/oiio") + + +find_library(OIIO_LIBRARY_RELEASE NAMES OpenImageIO PATH_SUFFIXES lib64 PATHS "${OIIO_DIR}/lib/x64") +find_library(OIIO_LIBRARY_DEBUG NAMES OpenImageIOD PATH_SUFFIXES lib64 PATHS "${OIIO_DIR}/lib/x64") +find_path(OIIO_INCLUDE_DIR NAMES OpenImageIO/oiioversion.h PATHS "${OIIO_DIR}/include") + +include(SelectLibraryConfigurations) +select_library_configurations(OIIO) + +find_package_handle_standard_args(OIIO DEFAULT_MSG OIIO_LIBRARY OIIO_INCLUDE_DIR) + +add_library(OpenImageIO::OpenImageIO UNKNOWN IMPORTED) + +set_target_properties(OpenImageIO::OpenImageIO PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${OIIO_INCLUDE_DIR}") + +if (OIIO_LIBRARY_RELEASE) + set_property(TARGET OpenImageIO::OpenImageIO APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) + set_target_properties(OpenImageIO::OpenImageIO PROPERTIES IMPORTED_LOCATION_RELEASE "${OIIO_LIBRARY_RELEASE}") +endif (OIIO_LIBRARY_RELEASE) + +if (OIIO_LIBRARY_DEBUG) + set_property(TARGET OpenImageIO::OpenImageIO APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(OpenImageIO::OpenImageIO PROPERTIES IMPORTED_LOCATION_DEBUG "${OIIO_LIBRARY_DEBUG}") +endif (OIIO_LIBRARY_DEBUG) + +if(NOT OIIO_LIBRARY_RELEASE AND NOT OIIO_LIBRARY_DEBUG) + set_property(TARGET OpenImageIO::OpenImageIO APPEND PROPERTY IMPORTED_LOCATION "${OIIO_LIBRARY}") +endif(NOT OIIO_LIBRARY_RELEASE AND NOT OIIO_LIBRARY_DEBUG) + diff --git a/premake5.lua b/premake5.lua deleted file mode 100644 index 2d0aa039..00000000 --- a/premake5.lua +++ /dev/null @@ -1,98 +0,0 @@ -function fileExists(name) - local f=io.open(name,"r") - if f~=nil then io.close(f) return true else return false end -end - -newoption { - trigger = "denoiser", - description = "Use denoising on output" -} - -newoption { - trigger = "benchmark", - description = "Benchmark with command line interface instead of App." -} - -newoption { - trigger = "rpr", - description = "Enable RadeonProRender API lib" -} - -solution "Baikal" -platforms {"x64"} -configurations { "Debug", "Release" } -language "C++" -flags { "NoMinimalRebuild", "EnableSSE", "EnableSSE2" } - --- define common includes -includedirs { ".","./3rdParty/include" } - - -dofile ("./OpenCLSearch.lua" ) -defines {"USE_OPENCL"} - --- perform OS specific initializations -local targetName; -if os.is("macosx") then - targetName = "osx" -end - -if os.is("windows") then - targetName = "win" - defines{ "WIN32" } - buildoptions { "/MP" } --multiprocessor build - defines {"_CRT_SECURE_NO_WARNINGS"} -elseif os.is("linux") then - buildoptions {"-fvisibility=hidden"} -end - ---make configuration specific definitions -configuration "Debug" - defines { "_DEBUG" } - flags { "Symbols" } -configuration "Release" - defines { "NDEBUG" } - flags { "Optimize" } - -configuration {"x64", "Debug"} - targetsuffix "64D" -configuration {"x64", "Release"} - targetsuffix "64" - -configuration {} -- back to all configurations - -if _OPTIONS["rpr"] then - if fileExists("./Rpr/Rpr.lua") then - dofile("./Rpr/Rpr.lua") - end - if fileExists("./RprTest/RprTest.lua") then - dofile("./RprTest/RprTest.lua") - end - if fileExists("./RprLoadStore/RprLoadStore.lua") then - dofile("./RprLoadStore/RprLoadStore.lua") - end -end - -if fileExists("./Baikal/Baikal.lua") then - dofile("./Baikal/Baikal.lua") -end - -if fileExists("./Gtest/gtest.lua") then - dofile("./Gtest/gtest.lua") -end - -if fileExists("./UnitTest/UnitTest.lua") then - dofile("./UnitTest/UnitTest.lua") -end - -if fileExists("./RadeonRaysPremakeAdapter/RadeonRays.lua") then - dofile("./RadeonRaysPremakeAdapter/RadeonRays.lua") -end - -if fileExists("./RadeonRaysPremakeAdapter/CLW.lua") then - dofile("./RadeonRaysPremakeAdapter/CLW.lua") -end - -if fileExists("./RadeonRaysPremakeAdapter/Calc.lua") then - dofile("./RadeonRaysPremakeAdapter/Calc.lua") -end \ No newline at end of file