diff --git a/License-Cabin.txt b/License-Cabin.txt new file mode 100644 index 000000000..ce98ff4b5 --- /dev/null +++ b/License-Cabin.txt @@ -0,0 +1,95 @@ +Copyright (c) 2011, Pablo Impallari (www.impallari.com|impallari@gmail.com), +Copyright (c) 2011, Igino Marini. (www.ikern.com|mail@iginomarini.com), +with Reserved Font Name Cabin. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/build/scripts/actions/unicode.lua b/build/scripts/actions/unicode.lua index 4db23db8a..8105cb3a0 100644 --- a/build/scripts/actions/unicode.lua +++ b/build/scripts/actions/unicode.lua @@ -191,7 +191,7 @@ end newaction { - trigger = "unicode", + trigger = "parseunicode", description = "Parse the Unicode Character Data and put the useful informations into a header", execute = parseUnicodeData } diff --git a/build/scripts/module/utility.lua b/build/scripts/module/utility.lua index ba88c4c3b..e6c25021e 100644 --- a/build/scripts/module/utility.lua +++ b/build/scripts/module/utility.lua @@ -10,6 +10,8 @@ files "../src/Nazara/Utility/**.cpp" } +links "freetype-s" + if (os.is("windows")) then excludes { "../src/Nazara/Utility/Posix/*.hpp", "../src/Nazara/Utility/Posix/*.cpp" } links "gdi32" diff --git a/examples/FirstScene/main.cpp b/examples/FirstScene/main.cpp index 65f948375..9ed702a69 100644 --- a/examples/FirstScene/main.cpp +++ b/examples/FirstScene/main.cpp @@ -84,7 +84,7 @@ int main() // Ensuite, nous allons rajouter un modèle à notre scène. // Les modèles représentent, globalement, tout ce qui est visible en trois dimensions. // Nous choisirons ici un vaisseau spatial (Quoi de mieux pour une scène spatiale ?) - NzModel spaceship; + NzModel* spaceship = scene.CreateNode(); // Création depuis la scène // Une structure permettant de paramétrer le chargement des modèles NzModelParameters params; @@ -95,9 +95,13 @@ int main() // Ce paramètre sert à indiquer la mise à l'échelle désirée lors du chargement du modèle. params.mesh.scale.Set(0.01f); // Un centième de la taille originelle + // Les UVs de ce fichier sont retournées (repère OpenGL, origine coin bas-gauche) par rapport à ce que le moteur attend + // Nous devons dire au moteur de les retourner lors du chargement + params.mesh.flipUVs = true; + // On charge ensuite le modèle depuis son fichier // Le moteur va charger le fichier et essayer de retrouver les fichiers associés (comme les matériaux, textures, ...) - if (!spaceship.LoadFromFile("resources/Spaceship/spaceship.obj", params)) + if (!spaceship->LoadFromFile("resources/Spaceship/spaceship.obj", params)) { std::cout << "Failed to load spaceship" << std::endl; std::getchar(); @@ -107,7 +111,7 @@ int main() // Nous voulons afficher quelques statistiques relatives au modèle, comme le nombre de sommets et de triangles // Pour cela, nous devons accéder au mesh (maillage 3D) - NzMesh* mesh = spaceship.GetMesh(); + NzMesh* mesh = spaceship->GetMesh(); std::cout << mesh->GetVertexCount() << " sommets" << std::endl; std::cout << mesh->GetTriangleCount() << " triangles" << std::endl; @@ -115,7 +119,7 @@ int main() // En revanche, le format OBJ ne précise pas l'utilisation d'une normal map, nous devons donc la charger manuellement // Pour commencer on récupère le matériau du mesh, celui-ci en possède plusieurs mais celui qui nous intéresse, // celui de la coque, est le second (Cela est bien entendu lié au modèle en lui-même) - NzMaterial* material = spaceship.GetMaterial(1); + NzMaterial* material = spaceship->GetMaterial(1); // On lui indique ensuite le chemin vers la normal map if (!material->SetNormalMap("resources/Spaceship/Texture/normal.png")) @@ -125,10 +129,6 @@ int main() std::cout << "Failed to load normal map" << std::endl; } - // Il nous reste à attacher le modèle à la scène, ce qui se fait simplement via cet appel - spaceship.SetParent(scene); - // Et voilà, à partir de maintenant le modèle fait partie de la hiérarchie de la scène, et sera donc rendu avec cette dernière - // Nous avons besoin également d'une caméra, pour des raisons évidentes, celle-ci sera à l'écart du modèle // regardant dans sa direction. @@ -160,18 +160,15 @@ int main() // -PointLight: Lumière située à un endroit précis, envoyant de la lumière finie dans toutes les directions // -SpotLight: Lumière située à un endroit précis, envoyant de la lumière vers un endroit donné, avec un angle de diffusion - // Nous choisissons une lumière directionnelle représentant la nébuleuse de notre skybox - NzLight nebulaLight(nzLightType_Directional); + // Nous créons une lumière directionnelle pour représenter la nébuleuse de notre skybox + NzLight* nebulaLight = scene.CreateNode(nzLightType_Directional); // Il nous faut ensuite configurer la lumière // Pour commencer, sa couleur, la nébuleuse étant d'une couleur jaune, j'ai choisi ces valeurs - nebulaLight.SetColor(NzColor(255, 182, 90)); + nebulaLight->SetColor(NzColor(255, 182, 90)); // Nous appliquons ensuite une rotation de sorte que la lumière dans la même direction que la nébuleuse - nebulaLight.SetRotation(NzEulerAnglesf(0.f, 102.f, 0.f)); - - // Et nous ajoutons la lumière à la scène - nebulaLight.SetParent(scene); + nebulaLight->SetRotation(NzEulerAnglesf(0.f, 102.f, 0.f)); // Nous allons maintenant créer la fenêtre, dans laquelle nous ferons nos rendus // Celle-ci demande des paramètres plus complexes diff --git a/include/Nazara/Audio/Algorithm.hpp b/include/Nazara/Audio/Algorithm.hpp index 2042536b3..696d64682 100644 --- a/include/Nazara/Audio/Algorithm.hpp +++ b/include/Nazara/Audio/Algorithm.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Audio/Algorithm.inl b/include/Nazara/Audio/Algorithm.inl index 9d8e4aa13..c673d9601 100644 --- a/include/Nazara/Audio/Algorithm.inl +++ b/include/Nazara/Audio/Algorithm.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Audio/Audio.hpp b/include/Nazara/Audio/Audio.hpp index 876b182a8..2c82bc424 100644 --- a/include/Nazara/Audio/Audio.hpp +++ b/include/Nazara/Audio/Audio.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Audio/Config.hpp b/include/Nazara/Audio/Config.hpp index 0adc2c04f..a30e67e3c 100644 --- a/include/Nazara/Audio/Config.hpp +++ b/include/Nazara/Audio/Config.hpp @@ -1,7 +1,7 @@ /* Nazara Engine - Audio module - Copyright (C) 2014 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) + Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/include/Nazara/Audio/ConfigCheck.hpp b/include/Nazara/Audio/ConfigCheck.hpp index e102d56ab..7c32933bd 100644 --- a/include/Nazara/Audio/ConfigCheck.hpp +++ b/include/Nazara/Audio/ConfigCheck.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Audio/Debug.hpp b/include/Nazara/Audio/Debug.hpp index ae84c7a0c..4e6124741 100644 --- a/include/Nazara/Audio/Debug.hpp +++ b/include/Nazara/Audio/Debug.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Audio/DebugOff.hpp b/include/Nazara/Audio/DebugOff.hpp index c91fba4e5..254d7701d 100644 --- a/include/Nazara/Audio/DebugOff.hpp +++ b/include/Nazara/Audio/DebugOff.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Audio/Enums.hpp b/include/Nazara/Audio/Enums.hpp index bbdac5941..a9d8dd41d 100644 --- a/include/Nazara/Audio/Enums.hpp +++ b/include/Nazara/Audio/Enums.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Audio/Music.hpp b/include/Nazara/Audio/Music.hpp index abc7e0a62..2ea35535a 100644 --- a/include/Nazara/Audio/Music.hpp +++ b/include/Nazara/Audio/Music.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -22,13 +22,12 @@ struct NzMusicParams class NzMusic; class NzSoundStream; -class NzThread; using NzMusicLoader = NzResourceLoader; struct NzMusicImpl; -class NAZARA_API NzMusic : public NzResource, public NzSoundEmitter +class NAZARA_API NzMusic : public NzResource, public NzSoundEmitter, NzNonCopyable { friend NzMusicLoader; diff --git a/include/Nazara/Audio/OpenAL.hpp b/include/Nazara/Audio/OpenAL.hpp index 2ab4a0518..d806e890e 100644 --- a/include/Nazara/Audio/OpenAL.hpp +++ b/include/Nazara/Audio/OpenAL.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Audio/Sound.hpp b/include/Nazara/Audio/Sound.hpp index 88f0f3aaf..c05e215aa 100644 --- a/include/Nazara/Audio/Sound.hpp +++ b/include/Nazara/Audio/Sound.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Audio/SoundBuffer.hpp b/include/Nazara/Audio/SoundBuffer.hpp index 726eb3b29..d2f09e904 100644 --- a/include/Nazara/Audio/SoundBuffer.hpp +++ b/include/Nazara/Audio/SoundBuffer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -26,7 +27,9 @@ struct NzSoundBufferParams class NzSound; class NzSoundBuffer; +using NzSoundBufferConstListener = NzObjectListenerWrapper; using NzSoundBufferConstRef = NzObjectRef; +using NzSoundBufferListener = NzObjectListenerWrapper; using NzSoundBufferLoader = NzResourceLoader; using NzSoundBufferRef = NzObjectRef; diff --git a/include/Nazara/Audio/SoundEmitter.hpp b/include/Nazara/Audio/SoundEmitter.hpp index e105d22fb..41b488395 100644 --- a/include/Nazara/Audio/SoundEmitter.hpp +++ b/include/Nazara/Audio/SoundEmitter.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Audio/SoundStream.hpp b/include/Nazara/Audio/SoundStream.hpp index 382702d59..c3bb47eb7 100644 --- a/include/Nazara/Audio/SoundStream.hpp +++ b/include/Nazara/Audio/SoundStream.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core.hpp b/include/Nazara/Core.hpp index 3f7f5b424..e4d1f7078 100644 --- a/include/Nazara/Core.hpp +++ b/include/Nazara/Core.hpp @@ -1,4 +1,4 @@ -// This file was automatically generated on 11 Jul 2014 at 10:21:52 +// This file was automatically generated on 17 Jan 2015 at 00:38:08 /* Nazara Engine - Core module @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +55,7 @@ #include #include #include +#include #include #include #include diff --git a/include/Nazara/Core/AbstractHash.hpp b/include/Nazara/Core/AbstractHash.hpp index 7bad4f20f..11ea82906 100644 --- a/include/Nazara/Core/AbstractHash.hpp +++ b/include/Nazara/Core/AbstractHash.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/ByteArray.hpp b/include/Nazara/Core/ByteArray.hpp index edf19b178..aba0d0158 100644 --- a/include/Nazara/Core/ByteArray.hpp +++ b/include/Nazara/Core/ByteArray.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/CallOnExit.hpp b/include/Nazara/Core/CallOnExit.hpp index 3f8fc1f2f..9c6da1ae6 100644 --- a/include/Nazara/Core/CallOnExit.hpp +++ b/include/Nazara/Core/CallOnExit.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -19,6 +19,7 @@ class NzCallOnExit : NzNonCopyable NzCallOnExit(Func func = nullptr); ~NzCallOnExit(); + void CallAndReset(Func func = nullptr); void Reset(Func func = nullptr); private: diff --git a/include/Nazara/Core/CallOnExit.inl b/include/Nazara/Core/CallOnExit.inl index 00960f3ac..c24b737a5 100644 --- a/include/Nazara/Core/CallOnExit.inl +++ b/include/Nazara/Core/CallOnExit.inl @@ -1,7 +1,8 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp +#include #include inline NzCallOnExit::NzCallOnExit(Func func) : @@ -15,6 +16,14 @@ inline NzCallOnExit::~NzCallOnExit() m_func(); } +inline void NzCallOnExit::CallAndReset(Func func) +{ + if (m_func) + m_func(); + + Reset(func); +} + inline void NzCallOnExit::Reset(Func func) { m_func = func; diff --git a/include/Nazara/Core/Clock.hpp b/include/Nazara/Core/Clock.hpp index b510137b7..7f4ffc156 100644 --- a/include/Nazara/Core/Clock.hpp +++ b/include/Nazara/Core/Clock.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -19,6 +19,7 @@ class NAZARA_API NzClock { public: NzClock(nzUInt64 startingValue = 0, bool paused = false); + NzClock(const NzClock& clock) = default; float GetSeconds() const; nzUInt64 GetMicroseconds() const; @@ -30,6 +31,8 @@ class NAZARA_API NzClock void Restart(); void Unpause(); + NzClock& operator=(const NzClock& clock) = default; + private: NazaraMutexAttrib(m_mutex, mutable) diff --git a/include/Nazara/Core/Color.hpp b/include/Nazara/Core/Color.hpp index 8e174056c..611fa8e59 100644 --- a/include/Nazara/Core/Color.hpp +++ b/include/Nazara/Core/Color.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Color.inl b/include/Nazara/Core/Color.inl index 3357f5c20..00b29321e 100644 --- a/include/Nazara/Core/Color.inl +++ b/include/Nazara/Core/Color.inl @@ -1,8 +1,9 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include #include @@ -235,7 +236,7 @@ inline void NzColor::ToCMYK(const NzColor& color, float* cyan, float* magenta, f float c, m, y; ToCMY(color, &c, &m, &y); - float k = std::min(std::min(std::min(1.f, c), m), y); + float k = std::min({1.f, c, m, y}); if (NzNumberEquals(k, 1.f)) { @@ -260,8 +261,8 @@ inline void NzColor::ToHSL(const NzColor& color, nzUInt8* hue, nzUInt8* saturati float g = color.g / 255.f; float b = color.b / 255.f; - float min = std::min(std::min(r, g), b); // Min. value of RGB - float max = std::max(std::max(r, g), b); // Max. value of RGB + float min = std::min({r, g, b}); // Min. value of RGB + float max = std::max({r, g, b}); // Max. value of RGB float deltaMax = max - min; //Delta RGB value diff --git a/include/Nazara/Core/ConditionVariable.hpp b/include/Nazara/Core/ConditionVariable.hpp index d8290d7fa..5e1787cb7 100644 --- a/include/Nazara/Core/ConditionVariable.hpp +++ b/include/Nazara/Core/ConditionVariable.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Config.hpp b/include/Nazara/Core/Config.hpp index 94f2c0ca9..3cdc38629 100644 --- a/include/Nazara/Core/Config.hpp +++ b/include/Nazara/Core/Config.hpp @@ -1,7 +1,7 @@ /* Nazara Engine - Core module - Copyright (C) 2014 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) + Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/include/Nazara/Core/ConfigCheck.hpp b/include/Nazara/Core/ConfigCheck.hpp index a5d0b3772..503152153 100644 --- a/include/Nazara/Core/ConfigCheck.hpp +++ b/include/Nazara/Core/ConfigCheck.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Core.hpp b/include/Nazara/Core/Core.hpp index 021432a8a..5443e8f2b 100644 --- a/include/Nazara/Core/Core.hpp +++ b/include/Nazara/Core/Core.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Debug.hpp b/include/Nazara/Core/Debug.hpp index 7febcddd3..6301f574a 100644 --- a/include/Nazara/Core/Debug.hpp +++ b/include/Nazara/Core/Debug.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Debug/NewRedefinition.hpp b/include/Nazara/Core/Debug/NewRedefinition.hpp index d0fea86c2..b315d7ade 100644 --- a/include/Nazara/Core/Debug/NewRedefinition.hpp +++ b/include/Nazara/Core/Debug/NewRedefinition.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/DebugOff.hpp b/include/Nazara/Core/DebugOff.hpp index fd70b6f0b..e042eff24 100644 --- a/include/Nazara/Core/DebugOff.hpp +++ b/include/Nazara/Core/DebugOff.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Directory.hpp b/include/Nazara/Core/Directory.hpp index 1a7ae5905..b5afb15f0 100644 --- a/include/Nazara/Core/Directory.hpp +++ b/include/Nazara/Core/Directory.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -8,6 +8,7 @@ #define NAZARA_DIRECTORY_HPP #include +#include #include #if defined(NAZARA_PLATFORM_WINDOWS) @@ -27,7 +28,7 @@ class NzDirectoryImpl; -class NAZARA_API NzDirectory +class NAZARA_API NzDirectory : NzNonCopyable { public: NzDirectory(); diff --git a/include/Nazara/Core/DynLib.hpp b/include/Nazara/Core/DynLib.hpp index 12b89249f..733b7c962 100644 --- a/include/Nazara/Core/DynLib.hpp +++ b/include/Nazara/Core/DynLib.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Endianness.hpp b/include/Nazara/Core/Endianness.hpp index fb58c63d5..76b9e34ad 100644 --- a/include/Nazara/Core/Endianness.hpp +++ b/include/Nazara/Core/Endianness.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Endianness.inl b/include/Nazara/Core/Endianness.inl index b9e6d8f17..ab696dba3 100644 --- a/include/Nazara/Core/Endianness.inl +++ b/include/Nazara/Core/Endianness.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Enums.hpp b/include/Nazara/Core/Enums.hpp index 82e384138..81ccae4e0 100644 --- a/include/Nazara/Core/Enums.hpp +++ b/include/Nazara/Core/Enums.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Error.hpp b/include/Nazara/Core/Error.hpp index 51de269e1..dde4a5100 100644 --- a/include/Nazara/Core/Error.hpp +++ b/include/Nazara/Core/Error.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/ErrorFlags.hpp b/include/Nazara/Core/ErrorFlags.hpp index e763293c7..714996b4f 100644 --- a/include/Nazara/Core/ErrorFlags.hpp +++ b/include/Nazara/Core/ErrorFlags.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/File.hpp b/include/Nazara/Core/File.hpp index 8eff60c73..10abc76e3 100644 --- a/include/Nazara/Core/File.hpp +++ b/include/Nazara/Core/File.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Format.hpp b/include/Nazara/Core/Format.hpp index caa69d879..d03f05eae 100644 --- a/include/Nazara/Core/Format.hpp +++ b/include/Nazara/Core/Format.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Functor.hpp b/include/Nazara/Core/Functor.hpp index 0adbebcf4..4ecbeed25 100644 --- a/include/Nazara/Core/Functor.hpp +++ b/include/Nazara/Core/Functor.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Functor.inl b/include/Nazara/Core/Functor.inl index dfcaac9c4..265ef5605 100644 --- a/include/Nazara/Core/Functor.inl +++ b/include/Nazara/Core/Functor.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/GuillotineBinPack.hpp b/include/Nazara/Core/GuillotineBinPack.hpp new file mode 100644 index 000000000..c1562ba3a --- /dev/null +++ b/include/Nazara/Core/GuillotineBinPack.hpp @@ -0,0 +1,85 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +// Implémentation originale de Jukka Jylänki (Merci de sa contribution au domaine public) +// http://clb.demon.fi/projects/even-more-rectangle-bin-packing + +#pragma once + +#ifndef NAZARA_GUILLOTINEBINPACK_HPP +#define NAZARA_GUILLOTINEBINPACK_HPP + +#include +#include +#include +#include + +class NAZARA_API NzGuillotineBinPack +{ + public: + enum FreeRectChoiceHeuristic + { + RectBestAreaFit, + RectBestLongSideFit, + RectBestShortSideFit, + RectWorstAreaFit, + RectWorstLongSideFit, + RectWorstShortSideFit + }; + + enum GuillotineSplitHeuristic + { + SplitLongerAxis, + SplitLongerLeftoverAxis, + SplitMaximizeArea, + SplitMinimizeArea, + SplitShorterAxis, + SplitShorterLeftoverAxis + }; + + NzGuillotineBinPack(); + NzGuillotineBinPack(unsigned int width, unsigned int height); + NzGuillotineBinPack(const NzVector2ui& size); + NzGuillotineBinPack(const NzGuillotineBinPack&) = default; + NzGuillotineBinPack(NzGuillotineBinPack&&) = default; + ~NzGuillotineBinPack() = default; + + void Clear(); + + void Expand(unsigned int newWidth, unsigned newHeight); + void Expand(const NzVector2ui& newSize); + + void FreeRectangle(const NzRectui& rect); + + unsigned int GetHeight() const; + float GetOccupancy() const; + NzVector2ui GetSize() const; + unsigned int GetWidth() const; + + bool Insert(NzRectui* rects, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod); + bool Insert(NzRectui* rects, bool* flipped, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod); + bool Insert(NzRectui* rects, bool* flipped, bool* inserted, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod); + + bool MergeFreeRectangles(); + + void Reset(); + void Reset(unsigned int width, unsigned int height); + void Reset(const NzVector2ui& size); + + NzGuillotineBinPack& operator=(const NzGuillotineBinPack&) = default; + NzGuillotineBinPack& operator=(NzGuillotineBinPack&&) = default; + + private: + void SplitFreeRectAlongAxis(const NzRectui& freeRect, const NzRectui& placedRect, bool splitHorizontal); + void SplitFreeRectByHeuristic(const NzRectui& freeRect, const NzRectui& placedRect, GuillotineSplitHeuristic method); + + static int ScoreByHeuristic(int width, int height, const NzRectui& freeRect, FreeRectChoiceHeuristic rectChoice); + + std::vector m_freeRectangles; + unsigned int m_height; + unsigned int m_usedArea; + unsigned int m_width; +}; + +#endif // NAZARA_GUILLOTINEBINPACK_HPP diff --git a/include/Nazara/Core/HardwareInfo.hpp b/include/Nazara/Core/HardwareInfo.hpp index bafd8f687..575b3ebc9 100644 --- a/include/Nazara/Core/HardwareInfo.hpp +++ b/include/Nazara/Core/HardwareInfo.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Hash.hpp b/include/Nazara/Core/Hash.hpp index c092b78fb..2f3f45b7b 100644 --- a/include/Nazara/Core/Hash.hpp +++ b/include/Nazara/Core/Hash.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Hash/CRC32.hpp b/include/Nazara/Core/Hash/CRC32.hpp index 00b7276f0..067717e43 100644 --- a/include/Nazara/Core/Hash/CRC32.hpp +++ b/include/Nazara/Core/Hash/CRC32.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Hash/Fletcher16.hpp b/include/Nazara/Core/Hash/Fletcher16.hpp index afdaa17db..cd756477c 100644 --- a/include/Nazara/Core/Hash/Fletcher16.hpp +++ b/include/Nazara/Core/Hash/Fletcher16.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Hash/MD5.hpp b/include/Nazara/Core/Hash/MD5.hpp index 00d64d17e..a2559c4c3 100644 --- a/include/Nazara/Core/Hash/MD5.hpp +++ b/include/Nazara/Core/Hash/MD5.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Hash/SHA1.hpp b/include/Nazara/Core/Hash/SHA1.hpp index d49a2ec0e..896a5ea45 100644 --- a/include/Nazara/Core/Hash/SHA1.hpp +++ b/include/Nazara/Core/Hash/SHA1.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Hash/SHA224.hpp b/include/Nazara/Core/Hash/SHA224.hpp index 467b679b7..d65d28328 100644 --- a/include/Nazara/Core/Hash/SHA224.hpp +++ b/include/Nazara/Core/Hash/SHA224.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Hash/SHA256.hpp b/include/Nazara/Core/Hash/SHA256.hpp index 0bea3ccdb..aa27760ff 100644 --- a/include/Nazara/Core/Hash/SHA256.hpp +++ b/include/Nazara/Core/Hash/SHA256.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Hash/SHA384.hpp b/include/Nazara/Core/Hash/SHA384.hpp index 912828365..a07885760 100644 --- a/include/Nazara/Core/Hash/SHA384.hpp +++ b/include/Nazara/Core/Hash/SHA384.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Hash/SHA512.hpp b/include/Nazara/Core/Hash/SHA512.hpp index ffdaff72e..22dd2e968 100644 --- a/include/Nazara/Core/Hash/SHA512.hpp +++ b/include/Nazara/Core/Hash/SHA512.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Hash/Whirlpool.hpp b/include/Nazara/Core/Hash/Whirlpool.hpp index ec6651f49..b4970712e 100644 --- a/include/Nazara/Core/Hash/Whirlpool.hpp +++ b/include/Nazara/Core/Hash/Whirlpool.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/HashDigest.hpp b/include/Nazara/Core/HashDigest.hpp index da4afb227..ef0acd151 100644 --- a/include/Nazara/Core/HashDigest.hpp +++ b/include/Nazara/Core/HashDigest.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -11,7 +11,7 @@ #include #include -#include +#include class NAZARA_API NzHashDigest { diff --git a/include/Nazara/Core/Hashable.hpp b/include/Nazara/Core/Hashable.hpp index b6bdf9d6b..483262622 100644 --- a/include/Nazara/Core/Hashable.hpp +++ b/include/Nazara/Core/Hashable.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Initializer.hpp b/include/Nazara/Core/Initializer.hpp index 4645cbac7..3737593df 100644 --- a/include/Nazara/Core/Initializer.hpp +++ b/include/Nazara/Core/Initializer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Initializer.inl b/include/Nazara/Core/Initializer.inl index fe92b3a2f..732a12418 100644 --- a/include/Nazara/Core/Initializer.inl +++ b/include/Nazara/Core/Initializer.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/InputStream.hpp b/include/Nazara/Core/InputStream.hpp index ae6ce3ee7..4db9be523 100644 --- a/include/Nazara/Core/InputStream.hpp +++ b/include/Nazara/Core/InputStream.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/LockGuard.hpp b/include/Nazara/Core/LockGuard.hpp index b73a30d84..394f13e2a 100644 --- a/include/Nazara/Core/LockGuard.hpp +++ b/include/Nazara/Core/LockGuard.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Log.hpp b/include/Nazara/Core/Log.hpp index 0348d2c10..458dc1b3d 100644 --- a/include/Nazara/Core/Log.hpp +++ b/include/Nazara/Core/Log.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/MemoryHelper.hpp b/include/Nazara/Core/MemoryHelper.hpp new file mode 100644 index 000000000..1dafec898 --- /dev/null +++ b/include/Nazara/Core/MemoryHelper.hpp @@ -0,0 +1,20 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_MEMORYHELPER_HPP +#define NAZARA_MEMORYHELPER_HPP + +#include + +void NzOperatorDelete(void* ptr); +void* NzOperatorNew(std::size_t size); + +template +T* NzPlacementNew(void* ptr, Args... args); + +#include + +#endif // NAZARA_MEMORYHELPER_HPP diff --git a/include/Nazara/Core/MemoryHelper.inl b/include/Nazara/Core/MemoryHelper.inl new file mode 100644 index 000000000..14a297fff --- /dev/null +++ b/include/Nazara/Core/MemoryHelper.inl @@ -0,0 +1,45 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +// Je ne suis pas fier des cinq lignes qui suivent mais difficile de faire autrement pour le moment... +#ifdef NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION + #define NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION_DEFINED +#else + #define NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION +#endif + +#include +#include +#include + +inline void NzOperatorDelete(void* ptr) +{ + #if NAZARA_CORE_MANAGE_MEMORY + NzMemoryManager::Free(ptr); + #else + operator delete(ptr); + #endif +} + +inline void* NzOperatorNew(std::size_t size) +{ + #if NAZARA_CORE_MANAGE_MEMORY + return NzMemoryManager::Allocate(size); + #else + return operator new(size); + #endif +} + +template +T* NzPlacementNew(void* ptr, Args... args) +{ + return new (ptr) T(std::forward(args)...); +} + +#include + +// Si c'est nous qui avons défini la constante, alors il nous faut l'enlever (Pour éviter que le moteur entier n'en souffre) +#ifndef NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION_DEFINED + #undef NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION +#endif diff --git a/include/Nazara/Core/MemoryManager.hpp b/include/Nazara/Core/MemoryManager.hpp index 437e5c53b..a9481468d 100644 --- a/include/Nazara/Core/MemoryManager.hpp +++ b/include/Nazara/Core/MemoryManager.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/MemoryPool.hpp b/include/Nazara/Core/MemoryPool.hpp index 64efc4ccd..c53df3786 100644 --- a/include/Nazara/Core/MemoryPool.hpp +++ b/include/Nazara/Core/MemoryPool.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/MemoryPool.inl b/include/Nazara/Core/MemoryPool.inl index 5521e790d..0ad5c3398 100644 --- a/include/Nazara/Core/MemoryPool.inl +++ b/include/Nazara/Core/MemoryPool.inl @@ -1,15 +1,8 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp -// Je ne suis pas fier des cinq lignes qui suivent mais difficile de faire autrement pour le moment... -#ifdef NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION - #define NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION_DEFINED -#else - #define NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION -#endif - -#include +#include #include template @@ -58,7 +51,7 @@ void* NzMemoryPool::Allocate(unsigned int size) } } - return operator new(size); + return NzOperatorNew(size); } template @@ -93,7 +86,7 @@ void NzMemoryPool::Free(void* ptr) if (m_next) m_next->Free(ptr); else - operator delete(ptr); + NzOperatorDelete(ptr); } } } @@ -111,8 +104,3 @@ unsigned int NzMemoryPool::GetSize() const } #include - -// Si c'est nous qui avons défini la constante, alors il nous faut l'enlever (Pour éviter que le moteur entier n'en souffre) -#ifndef NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION_DEFINED - #undef NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION -#endif diff --git a/include/Nazara/Core/MemoryStream.hpp b/include/Nazara/Core/MemoryStream.hpp index 91e3d3390..0370d8465 100644 --- a/include/Nazara/Core/MemoryStream.hpp +++ b/include/Nazara/Core/MemoryStream.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Mutex.hpp b/include/Nazara/Core/Mutex.hpp index dc7adaf87..b34341836 100644 --- a/include/Nazara/Core/Mutex.hpp +++ b/include/Nazara/Core/Mutex.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/NonCopyable.hpp b/include/Nazara/Core/NonCopyable.hpp index aff4d3ce7..b6bc2ab2f 100644 --- a/include/Nazara/Core/NonCopyable.hpp +++ b/include/Nazara/Core/NonCopyable.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/ObjectListener.hpp b/include/Nazara/Core/ObjectListener.hpp index 60e132245..f534f24c5 100644 --- a/include/Nazara/Core/ObjectListener.hpp +++ b/include/Nazara/Core/ObjectListener.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/ObjectListenerWrapper.hpp b/include/Nazara/Core/ObjectListenerWrapper.hpp new file mode 100644 index 000000000..e44476a16 --- /dev/null +++ b/include/Nazara/Core/ObjectListenerWrapper.hpp @@ -0,0 +1,45 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_OBJECTLISTENERWRAPPER_HPP +#define NAZARA_OBJECTLISTENERWRAPPER_HPP + +#include +#include +#include +#include + +template +class NzObjectListenerWrapper +{ + static_assert(std::is_base_of::value, "ObjListenerWrapper should only be used with RefCounted-derived type"); + + public: + NzObjectListenerWrapper(NzObjectListener* listener, int index = 0, T* object = nullptr); + NzObjectListenerWrapper(const NzObjectListenerWrapper& listener); + NzObjectListenerWrapper(NzObjectListenerWrapper&& listener); + ~NzObjectListenerWrapper(); + + bool IsValid() const; + void Reset(T* object = nullptr); + + operator bool() const; + operator T*() const; + T* operator->() const; + + NzObjectListenerWrapper& operator=(T* object); + NzObjectListenerWrapper& operator=(const NzObjectListenerWrapper& listener); + NzObjectListenerWrapper& operator=(NzObjectListenerWrapper&& listener); + + private: + T* m_object; + NzObjectListener* m_listener; + int m_index; +}; + +#include + +#endif // NAZARA_OBJECTLISTENERWRAPPER_HPP diff --git a/include/Nazara/Core/ObjectListenerWrapper.inl b/include/Nazara/Core/ObjectListenerWrapper.inl new file mode 100644 index 000000000..aa72db910 --- /dev/null +++ b/include/Nazara/Core/ObjectListenerWrapper.inl @@ -0,0 +1,108 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include + +template +NzObjectListenerWrapper::NzObjectListenerWrapper(NzObjectListener* listener, int index, T* object) : +m_object(nullptr), +m_listener(listener), +m_index(index) +{ + Reset(object); +} + +template +NzObjectListenerWrapper::NzObjectListenerWrapper(const NzObjectListenerWrapper& listener) : +m_object(nullptr), +m_listener(listener.m_listener), +m_index(listener.m_index) +{ + Reset(listener.m_object); +} + +template +NzObjectListenerWrapper::NzObjectListenerWrapper(NzObjectListenerWrapper&& listener) : +m_object(listener.m_object), +m_listener(listener.m_listener), +m_index(listener.m_index) +{ + listener.m_object = nullptr; +} + +template +NzObjectListenerWrapper::~NzObjectListenerWrapper() +{ + Reset(nullptr); +} + +template +bool NzObjectListenerWrapper::IsValid() const +{ + return m_object != nullptr; +} + +template +void NzObjectListenerWrapper::Reset(T* object) +{ + if (object) + object->AddObjectListener(m_listener, m_index); + + if (m_object) + m_object->RemoveObjectListener(m_listener); + + m_object = object; +} + +template +NzObjectListenerWrapper::operator bool() const +{ + return IsValid(); +} + +template +NzObjectListenerWrapper::operator T*() const +{ + return m_object; +} + +template +T* NzObjectListenerWrapper::operator->() const +{ + return m_object; +} + +template +NzObjectListenerWrapper& NzObjectListenerWrapper::operator=(T* object) +{ + Reset(object); + + return *this; +} + +template +NzObjectListenerWrapper& NzObjectListenerWrapper::operator=(const NzObjectListenerWrapper& listener) +{ + m_index = listener.m_index; + m_listener = listener.m_listener; + Reset(listener.m_object); + + return *this; +} + +template +NzObjectListenerWrapper& NzObjectListenerWrapper::operator=(NzObjectListenerWrapper&& listener) +{ + Reset(); + + m_index = listener.m_index; + m_listener = listener.m_listener; + m_object = listener.m_object; + + listener.m_object = nullptr; + + return *this; +} + +#include diff --git a/include/Nazara/Core/ObjectRef.hpp b/include/Nazara/Core/ObjectRef.hpp index 1d7b2b93e..246cdb8e3 100644 --- a/include/Nazara/Core/ObjectRef.hpp +++ b/include/Nazara/Core/ObjectRef.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -18,26 +18,26 @@ class NzObjectRef public: NzObjectRef(); - NzObjectRef(T* resource); + NzObjectRef(T* object); NzObjectRef(const NzObjectRef& ref); NzObjectRef(NzObjectRef&& ref) noexcept; ~NzObjectRef(); bool IsValid() const; T* Release(); - bool Reset(T* resource = nullptr); + bool Reset(T* object = nullptr); NzObjectRef& Swap(NzObjectRef& ref); operator bool() const; operator T*() const; T* operator->() const; - NzObjectRef& operator=(T* resource); + NzObjectRef& operator=(T* object); NzObjectRef& operator=(const NzObjectRef& ref); NzObjectRef& operator=(NzObjectRef&& ref) noexcept; private: - T* m_resource; + T* m_object; }; #include diff --git a/include/Nazara/Core/ObjectRef.inl b/include/Nazara/Core/ObjectRef.inl index b598061f5..e78a4a1e4 100644 --- a/include/Nazara/Core/ObjectRef.inl +++ b/include/Nazara/Core/ObjectRef.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -7,70 +7,70 @@ template NzObjectRef::NzObjectRef() : -m_resource(nullptr) +m_object(nullptr) { } template -NzObjectRef::NzObjectRef(T* resource) : -m_resource(resource) +NzObjectRef::NzObjectRef(T* object) : +m_object(object) { - if (m_resource) - m_resource->AddReference(); + if (m_object) + m_object->AddReference(); } template NzObjectRef::NzObjectRef(const NzObjectRef& ref) : -m_resource(ref.m_resource) +m_object(ref.m_object) { - if (m_resource) - m_resource->AddReference(); + if (m_object) + m_object->AddReference(); } template NzObjectRef::NzObjectRef(NzObjectRef&& ref) noexcept : -m_resource(ref.m_resource) +m_object(ref.m_object) { - ref.m_resource = nullptr; // On vole la référence + ref.m_object = nullptr; // On vole la référence } template NzObjectRef::~NzObjectRef() { - if (m_resource) - m_resource->RemoveReference(); + if (m_object) + m_object->RemoveReference(); } template bool NzObjectRef::IsValid() const { - return m_resource != nullptr; + return m_object != nullptr; } template T* NzObjectRef::Release() { - T* resource = m_resource; - m_resource = nullptr; + T* object = m_object; + m_object = nullptr; - return resource; + return object; } template -bool NzObjectRef::Reset(T* resource) +bool NzObjectRef::Reset(T* object) { bool destroyed = false; - if (m_resource != resource) + if (m_object != object) { - if (m_resource) + if (m_object) { - destroyed = m_resource->RemoveReference(); - m_resource = nullptr; + destroyed = m_object->RemoveReference(); + m_object = nullptr; } - m_resource = resource; - if (m_resource) - m_resource->AddReference(); + m_object = object; + if (m_object) + m_object->AddReference(); } return destroyed; @@ -79,7 +79,7 @@ bool NzObjectRef::Reset(T* resource) template NzObjectRef& NzObjectRef::Swap(NzObjectRef& ref) { - std::swap(m_resource, ref.m_resource); + std::swap(m_object, ref.m_object); return *this; } @@ -93,19 +93,19 @@ NzObjectRef::operator bool() const template NzObjectRef::operator T*() const { - return m_resource; + return m_object; } template T* NzObjectRef::operator->() const { - return m_resource; + return m_object; } template -NzObjectRef& NzObjectRef::operator=(T* resource) +NzObjectRef& NzObjectRef::operator=(T* object) { - Reset(resource); + Reset(object); return *this; } @@ -113,7 +113,7 @@ NzObjectRef& NzObjectRef::operator=(T* resource) template NzObjectRef& NzObjectRef::operator=(const NzObjectRef& ref) { - Reset(ref.m_resource); + Reset(ref.m_object); return *this; } @@ -123,7 +123,7 @@ NzObjectRef& NzObjectRef::operator=(NzObjectRef&& ref) noexcept { Reset(); - std::swap(m_resource, ref.m_resource); + std::swap(m_object, ref.m_object); return *this; } diff --git a/include/Nazara/Core/OffsetOf.hpp b/include/Nazara/Core/OffsetOf.hpp index 0393f7fc7..4f13abacf 100644 --- a/include/Nazara/Core/OffsetOf.hpp +++ b/include/Nazara/Core/OffsetOf.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -16,7 +16,7 @@ template M NzImplGetMemberType(M T::*); template constexpr std::size_t NzImplOffsetOf() { - return reinterpret_cast(&(((T*)0)->*M)); + return reinterpret_cast(&((static_cast(0))->*M)); } #define NzOffsetOf(type, member) NzImplOffsetOf() diff --git a/include/Nazara/Core/ParameterList.hpp b/include/Nazara/Core/ParameterList.hpp index f43979d9e..e8c3fb51c 100644 --- a/include/Nazara/Core/ParameterList.hpp +++ b/include/Nazara/Core/ParameterList.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/PluginManager.hpp b/include/Nazara/Core/PluginManager.hpp index 3f1ab6178..e4a1851b4 100644 --- a/include/Nazara/Core/PluginManager.hpp +++ b/include/Nazara/Core/PluginManager.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Primitive.hpp b/include/Nazara/Core/Primitive.hpp index f54a6a8c6..655a8fdab 100644 --- a/include/Nazara/Core/Primitive.hpp +++ b/include/Nazara/Core/Primitive.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Primitive.inl b/include/Nazara/Core/Primitive.inl index 6de686238..b27031f56 100644 --- a/include/Nazara/Core/Primitive.inl +++ b/include/Nazara/Core/Primitive.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/PrimitiveList.hpp b/include/Nazara/Core/PrimitiveList.hpp index 9894040dd..8a8b096aa 100644 --- a/include/Nazara/Core/PrimitiveList.hpp +++ b/include/Nazara/Core/PrimitiveList.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/RefCounted.hpp b/include/Nazara/Core/RefCounted.hpp index 9a24397fc..e60e73364 100644 --- a/include/Nazara/Core/RefCounted.hpp +++ b/include/Nazara/Core/RefCounted.hpp @@ -23,6 +23,8 @@ class NAZARA_API NzRefCounted { public: NzRefCounted(bool persistent = true); + NzRefCounted(const NzRefCounted&) = delete; + NzRefCounted(NzRefCounted&&) = delete; virtual ~NzRefCounted(); void AddObjectListener(NzObjectListener* listener, int index = 0) const; @@ -37,6 +39,9 @@ class NAZARA_API NzRefCounted bool SetPersistent(bool persistent = true, bool checkReferenceCount = false); + NzRefCounted& operator=(const NzRefCounted&) = delete; + NzRefCounted& operator=(NzRefCounted&&) = delete; + protected: void NotifyCreated(); void NotifyDestroy(); diff --git a/include/Nazara/Core/Resource.hpp b/include/Nazara/Core/Resource.hpp index 875465856..5c79cd249 100644 --- a/include/Nazara/Core/Resource.hpp +++ b/include/Nazara/Core/Resource.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -14,12 +14,17 @@ class NAZARA_API NzResource { public: NzResource() = default; + NzResource(const NzResource&) = default; + NzResource(NzResource&&) = default; virtual ~NzResource(); - NzString GetFilePath() const; + const NzString& GetFilePath() const; void SetFilePath(const NzString& filePath); + NzResource& operator=(const NzResource&) = default; + NzResource& operator=(NzResource&&) = default; + private: NzString m_filePath; }; diff --git a/include/Nazara/Core/ResourceLoader.hpp b/include/Nazara/Core/ResourceLoader.hpp index 512b3bc1e..090b65c6d 100644 --- a/include/Nazara/Core/ResourceLoader.hpp +++ b/include/Nazara/Core/ResourceLoader.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -22,6 +22,7 @@ class NzResourceLoader public: using ExtensionGetter = bool (*)(const NzString& extension); using FileLoader = bool (*)(Type* resource, const NzString& filePath, const Parameters& parameters); + using MemoryLoader = bool (*)(Type* resource, const void* data, std::size_t size, const Parameters& parameters); using StreamChecker = nzTernary (*)(NzInputStream& stream, const Parameters& parameters); using StreamLoader = bool (*)(Type* resource, NzInputStream& stream, const Parameters& parameters); @@ -31,10 +32,10 @@ class NzResourceLoader static bool LoadFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters = Parameters()); static bool LoadFromStream(Type* resource, NzInputStream& stream, const Parameters& parameters = Parameters()); - static void RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr); - static void UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr); + static void RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr, MemoryLoader memoryLoader = nullptr); + static void UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr, MemoryLoader memoryLoader = nullptr); - using Loader = std::tuple; + using Loader = std::tuple; using LoaderList = std::list; }; diff --git a/include/Nazara/Core/ResourceLoader.inl b/include/Nazara/Core/ResourceLoader.inl index 2d1cf2466..6622be2f4 100644 --- a/include/Nazara/Core/ResourceLoader.inl +++ b/include/Nazara/Core/ResourceLoader.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -123,9 +123,77 @@ bool NzResourceLoader::LoadFromFile(Type* resource, const NzSt template bool NzResourceLoader::LoadFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters) { + #if NAZARA_CORE_SAFE + if (!parameters.IsValid()) + { + NazaraError("Invalid parameters"); + return false; + } + + if (size == 0) + { + NazaraError("No data to load"); + return false; + } + #endif + NzMemoryStream stream(data, size); - return LoadFromStream(resource, stream, parameters); + bool found = false; + for (Loader& loader : Type::s_loaders) + { + StreamChecker checkFunc = std::get<1>(loader); + StreamLoader streamLoader = std::get<2>(loader); + MemoryLoader memoryLoader = std::get<4>(loader); + + nzTernary recognized = nzTernary_Unknown; + if (memoryLoader) + { + if (checkFunc) + { + stream.SetCursorPos(0); + + recognized = checkFunc(stream, parameters); + if (recognized == nzTernary_False) + continue; + else + found = true; + } + else + { + recognized = nzTernary_Unknown; + found = true; + } + + if (memoryLoader(resource, data, size, parameters)) + return true; + } + else + { + stream.SetCursorPos(0); + + recognized = checkFunc(stream, parameters); + if (recognized == nzTernary_False) + continue; + else if (recognized == nzTernary_True) + found = true; + + stream.SetCursorPos(0); + + if (streamLoader(resource, stream, parameters)) + return true; + } + + if (recognized == nzTernary_True) + NazaraWarning("Loader failed"); + } + + if (found) + NazaraError("Failed to load file: all loaders failed"); + else + NazaraError("Failed to load file: no loader found"); + + return false; } template @@ -181,7 +249,7 @@ bool NzResourceLoader::LoadFromStream(Type* resource, NzInputS } template -void NzResourceLoader::RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader) +void NzResourceLoader::RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader, MemoryLoader memoryLoader) { #if NAZARA_CORE_SAFE if (streamLoader) @@ -192,20 +260,20 @@ void NzResourceLoader::RegisterLoader(ExtensionGetter extensio return; } } - else if (!fileLoader) + else if (!fileLoader && !memoryLoader) { - NazaraError("Neither FileLoader nor StreamLoader were present"); + NazaraError("Neither FileLoader nor MemoryLoader nor StreamLoader were present"); return; } #endif - Type::s_loaders.push_front(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader)); + Type::s_loaders.push_front(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader, memoryLoader)); } template -void NzResourceLoader::UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader) +void NzResourceLoader::UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader, MemoryLoader memoryLoader) { - Type::s_loaders.remove(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader)); + Type::s_loaders.remove(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader, memoryLoader)); } #include diff --git a/include/Nazara/Core/Semaphore.hpp b/include/Nazara/Core/Semaphore.hpp index f09c4a3cb..2dd6f5ef5 100644 --- a/include/Nazara/Core/Semaphore.hpp +++ b/include/Nazara/Core/Semaphore.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/SparsePtr.hpp b/include/Nazara/Core/SparsePtr.hpp index eec23149c..317d3f8b8 100644 --- a/include/Nazara/Core/SparsePtr.hpp +++ b/include/Nazara/Core/SparsePtr.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -10,30 +10,49 @@ ///FIXME: Est-ce que SparsePtr est vraiment le meilleur nom pour cette classe ? #include +#include +#include template class NzSparsePtr { public: + using BytePtr = typename std::conditional::value, const nzUInt8*, nzUInt8*>::type; + using VoidPtr = typename std::conditional::value, const void*, void*>::type; + NzSparsePtr(); - NzSparsePtr(void* ptr, unsigned int stride); + NzSparsePtr(T* ptr); + NzSparsePtr(VoidPtr ptr, int stride); + template NzSparsePtr(const NzSparsePtr& ptr); NzSparsePtr(const NzSparsePtr& ptr) = default; ~NzSparsePtr() = default; - void* Get() const; - unsigned int GetStride() const; - void Set(void* ptr); - void SetStride(unsigned int stride); + VoidPtr GetPtr() const; + int GetStride() const; + void Reset(); + void Reset(T* ptr); + void Reset(VoidPtr ptr, int stride); + void Reset(const NzSparsePtr& ptr); + template void Reset(const NzSparsePtr& ptr); + + void SetPtr(VoidPtr ptr); + void SetStride(int stride); + + operator bool() const; + operator T*() const; T& operator*() const; T& operator->() const; - T& operator[](unsigned int index) const; + T& operator[](int index) const; + NzSparsePtr operator+(int count) const; NzSparsePtr operator+(unsigned int count) const; + NzSparsePtr operator-(int count) const; NzSparsePtr operator-(unsigned int count) const; + std::ptrdiff_t operator-(const NzSparsePtr& ptr) const; - NzSparsePtr& operator+=(unsigned int count); - NzSparsePtr& operator-=(unsigned int count); + NzSparsePtr& operator+=(int count); + NzSparsePtr& operator-=(int count); NzSparsePtr& operator++(); NzSparsePtr operator++(int); @@ -51,8 +70,8 @@ class NzSparsePtr NzSparsePtr& operator=(const NzSparsePtr& ptr) = default; private: - nzUInt8* m_ptr; - unsigned int m_stride; + BytePtr m_ptr; + int m_stride; }; #include diff --git a/include/Nazara/Core/SparsePtr.inl b/include/Nazara/Core/SparsePtr.inl index f769e577e..fbe48f727 100644 --- a/include/Nazara/Core/SparsePtr.inl +++ b/include/Nazara/Core/SparsePtr.inl @@ -1,47 +1,108 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp #include template -NzSparsePtr::NzSparsePtr() : -m_ptr(nullptr), -m_stride(0) +NzSparsePtr::NzSparsePtr() { + Reset(); } template -NzSparsePtr::NzSparsePtr(void* ptr, unsigned int stride) +NzSparsePtr::NzSparsePtr(T* ptr) { - Set(ptr); - SetStride(stride); + Reset(ptr); } template -void* NzSparsePtr::Get() const +NzSparsePtr::NzSparsePtr(VoidPtr ptr, int stride) +{ + Reset(ptr, stride); +} + +template +template +NzSparsePtr::NzSparsePtr(const NzSparsePtr& ptr) +{ + Reset(ptr); +} + +template +typename NzSparsePtr::VoidPtr NzSparsePtr::GetPtr() const { return m_ptr; } template -unsigned int NzSparsePtr::GetStride() const +int NzSparsePtr::GetStride() const { return m_stride; } template -void NzSparsePtr::Set(void* ptr) +void NzSparsePtr::Reset() { - m_ptr = reinterpret_cast(ptr); + SetPtr(nullptr); + SetStride(0); } template -void NzSparsePtr::SetStride(unsigned int stride) +void NzSparsePtr::Reset(T* ptr) +{ + SetPtr(ptr); + SetStride(sizeof(T)); +} + +template +void NzSparsePtr::Reset(VoidPtr ptr, int stride) +{ + SetPtr(ptr); + SetStride(stride); +} + +template +void NzSparsePtr::Reset(const NzSparsePtr& ptr) +{ + SetPtr(ptr.GetPtr()); + SetStride(ptr.GetStride()); +} + +template +template +void NzSparsePtr::Reset(const NzSparsePtr& ptr) +{ + static_assert(std::is_convertible::value, "Source type pointer cannot be implicitely converted to target type pointer"); + + SetPtr(static_cast(ptr.GetPtr())); + SetStride(ptr.GetStride()); +} + +template +void NzSparsePtr::SetPtr(VoidPtr ptr) +{ + m_ptr = reinterpret_cast(ptr); +} + +template +void NzSparsePtr::SetStride(int stride) { m_stride = stride; } +template +NzSparsePtr::operator bool() const +{ + return m_ptr != nullptr; +} + +template +NzSparsePtr::operator T*() const +{ + return reinterpret_cast(m_ptr); +} + template T& NzSparsePtr::operator*() const { @@ -55,17 +116,29 @@ T& NzSparsePtr::operator->() const } template -T& NzSparsePtr::operator[](unsigned int index) const +T& NzSparsePtr::operator[](int index) const { return *reinterpret_cast(m_ptr + index*m_stride); } +template +NzSparsePtr NzSparsePtr::operator+(int count) const +{ + return NzSparsePtr(m_ptr + count*m_stride, m_stride); +} + template NzSparsePtr NzSparsePtr::operator+(unsigned int count) const { return NzSparsePtr(m_ptr + count*m_stride, m_stride); } +template +NzSparsePtr NzSparsePtr::operator-(int count) const +{ + return NzSparsePtr(m_ptr - count*m_stride, m_stride); +} + template NzSparsePtr NzSparsePtr::operator-(unsigned int count) const { @@ -73,16 +146,24 @@ NzSparsePtr NzSparsePtr::operator-(unsigned int count) const } template -NzSparsePtr& NzSparsePtr::operator+=(unsigned int count) +std::ptrdiff_t NzSparsePtr::operator-(const NzSparsePtr& ptr) const +{ + return (m_ptr - ptr.m_ptr)/m_stride; +} + +template +NzSparsePtr& NzSparsePtr::operator+=(int count) { m_ptr += count*m_stride; + return *this; } template -NzSparsePtr& NzSparsePtr::operator-=(unsigned int count) +NzSparsePtr& NzSparsePtr::operator-=(int count) { m_ptr -= count*m_stride; + return *this; } @@ -90,6 +171,7 @@ template NzSparsePtr& NzSparsePtr::operator++() { m_ptr += m_stride; + return *this; } diff --git a/include/Nazara/Core/Stream.hpp b/include/Nazara/Core/Stream.hpp index 91ed88fa6..fa4aafe12 100644 --- a/include/Nazara/Core/Stream.hpp +++ b/include/Nazara/Core/Stream.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/String.hpp b/include/Nazara/Core/String.hpp index 73253fa95..b9be14585 100644 --- a/include/Nazara/Core/String.hpp +++ b/include/Nazara/Core/String.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/String.inl b/include/Nazara/Core/String.inl index ac922d99b..1224afa32 100644 --- a/include/Nazara/Core/String.inl +++ b/include/Nazara/Core/String.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/StringStream.hpp b/include/Nazara/Core/StringStream.hpp index 7807c9806..c3899f16b 100644 --- a/include/Nazara/Core/StringStream.hpp +++ b/include/Nazara/Core/StringStream.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/TaskScheduler.hpp b/include/Nazara/Core/TaskScheduler.hpp index 65fddbc79..1d34403e4 100644 --- a/include/Nazara/Core/TaskScheduler.hpp +++ b/include/Nazara/Core/TaskScheduler.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/TaskScheduler.inl b/include/Nazara/Core/TaskScheduler.inl index bbe33c9cf..ffef85de3 100644 --- a/include/Nazara/Core/TaskScheduler.inl +++ b/include/Nazara/Core/TaskScheduler.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Thread.hpp b/include/Nazara/Core/Thread.hpp index 088300118..bbf82c31b 100644 --- a/include/Nazara/Core/Thread.hpp +++ b/include/Nazara/Core/Thread.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Thread.inl b/include/Nazara/Core/Thread.inl index dc9aa46af..b057d770e 100644 --- a/include/Nazara/Core/Thread.inl +++ b/include/Nazara/Core/Thread.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/ThreadSafety.hpp b/include/Nazara/Core/ThreadSafety.hpp index 9a0d8e274..7eb5bbf0b 100644 --- a/include/Nazara/Core/ThreadSafety.hpp +++ b/include/Nazara/Core/ThreadSafety.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/ThreadSafetyOff.hpp b/include/Nazara/Core/ThreadSafetyOff.hpp index a77e0acaa..e6a1ce208 100644 --- a/include/Nazara/Core/ThreadSafetyOff.hpp +++ b/include/Nazara/Core/ThreadSafetyOff.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Tuple.hpp b/include/Nazara/Core/Tuple.hpp index 13a5a69e7..1626e5177 100644 --- a/include/Nazara/Core/Tuple.hpp +++ b/include/Nazara/Core/Tuple.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Tuple.inl b/include/Nazara/Core/Tuple.inl index db7e80b45..46c6b5753 100644 --- a/include/Nazara/Core/Tuple.inl +++ b/include/Nazara/Core/Tuple.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Unicode.hpp b/include/Nazara/Core/Unicode.hpp index 2a0d1f48f..bc086ee46 100644 --- a/include/Nazara/Core/Unicode.hpp +++ b/include/Nazara/Core/Unicode.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Core/Updatable.hpp b/include/Nazara/Core/Updatable.hpp index f0aa8256a..540754caa 100644 --- a/include/Nazara/Core/Updatable.hpp +++ b/include/Nazara/Core/Updatable.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core Module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,9 +9,12 @@ #include -class NzUpdatable +class NAZARA_API NzUpdatable { public: + NzUpdatable() = default; + virtual ~NzUpdatable(); + virtual void Update() = 0; }; diff --git a/include/Nazara/Graphics.hpp b/include/Nazara/Graphics.hpp index 689572165..202f07a8c 100644 --- a/include/Nazara/Graphics.hpp +++ b/include/Nazara/Graphics.hpp @@ -1,4 +1,4 @@ -// This file was automatically generated on 11 Jul 2014 at 10:21:52 +// This file was automatically generated on 17 Jan 2015 at 00:38:08 /* Nazara Engine - Graphics module @@ -52,19 +52,20 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include #include -#include +#include #include #include #include +#include #include #include diff --git a/include/Nazara/Graphics/AbstractBackground.hpp b/include/Nazara/Graphics/AbstractBackground.hpp index 00ded21f3..42471d504 100644 --- a/include/Nazara/Graphics/AbstractBackground.hpp +++ b/include/Nazara/Graphics/AbstractBackground.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/AbstractRenderQueue.hpp b/include/Nazara/Graphics/AbstractRenderQueue.hpp index c3a9de2e4..367d6ec78 100644 --- a/include/Nazara/Graphics/AbstractRenderQueue.hpp +++ b/include/Nazara/Graphics/AbstractRenderQueue.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -8,15 +8,19 @@ #define NAZARA_ABSTRACTRENDERQUEUE_HPP #include +#include #include +#include #include #include #include +#include class NzDrawable; class NzLight; class NzMaterial; class NzSprite; +class NzTexture; struct NzMeshData; class NAZARA_API NzAbstractRenderQueue : NzNonCopyable @@ -25,10 +29,21 @@ class NAZARA_API NzAbstractRenderQueue : NzNonCopyable NzAbstractRenderQueue() = default; virtual ~NzAbstractRenderQueue(); + // Je ne suis vraiment pas fan du nombre de surcharges pour AddBillboards, + // mais je n'ai pas d'autre solution tout aussi performante pour le moment... + virtual void AddBillboard(const NzMaterial* material, const NzVector3f& position, const NzVector2f& size, const NzVector2f& sinCos = NzVector2f(0.f, 1.f), const NzColor& color = NzColor::White) = 0; + virtual void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr = nullptr, NzSparsePtr colorPtr = nullptr) = 0; + virtual void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr, NzSparsePtr alphaPtr) = 0; + virtual void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr colorPtr = nullptr) = 0; + virtual void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr alphaPtr) = 0; + virtual void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr = nullptr, NzSparsePtr colorPtr = nullptr) = 0; + virtual void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr, NzSparsePtr alphaPtr) = 0; + virtual void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr colorPtr = nullptr) = 0; + virtual void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr alphaPtr) = 0; virtual void AddDrawable(const NzDrawable* drawable) = 0; virtual void AddLight(const NzLight* light) = 0; virtual void AddMesh(const NzMaterial* material, const NzMeshData& meshData, const NzBoxf& meshAABB, const NzMatrix4f& transformMatrix) = 0; - virtual void AddSprite(const NzSprite* sprite) = 0; + virtual void AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const NzTexture* overlay = nullptr) = 0; virtual void Clear(bool fully) = 0; }; diff --git a/include/Nazara/Graphics/AbstractRenderTechnique.hpp b/include/Nazara/Graphics/AbstractRenderTechnique.hpp index 66947bada..3cc22e30c 100644 --- a/include/Nazara/Graphics/AbstractRenderTechnique.hpp +++ b/include/Nazara/Graphics/AbstractRenderTechnique.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/AbstractViewer.hpp b/include/Nazara/Graphics/AbstractViewer.hpp index 7e0306689..50ea34e24 100644 --- a/include/Nazara/Graphics/AbstractViewer.hpp +++ b/include/Nazara/Graphics/AbstractViewer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -28,6 +28,9 @@ class NAZARA_API NzAbstractViewer virtual NzVector3f GetEyePosition() const = 0; virtual NzVector3f GetForward() const = 0; virtual const NzFrustumf& GetFrustum() const = 0; + virtual NzVector3f GetGlobalForward() const = 0; + virtual NzVector3f GetGlobalRight() const = 0; + virtual NzVector3f GetGlobalUp() const = 0; virtual const NzMatrix4f& GetProjectionMatrix() const = 0; virtual const NzRenderTarget* GetTarget() const = 0; virtual const NzMatrix4f& GetViewMatrix() const = 0; diff --git a/include/Nazara/Graphics/Camera.hpp b/include/Nazara/Graphics/Camera.hpp index 534f48df7..8e3622484 100644 --- a/include/Nazara/Graphics/Camera.hpp +++ b/include/Nazara/Graphics/Camera.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,12 +9,12 @@ #include #include -#include #include #include #include #include #include +#include class NAZARA_API NzCamera : public NzAbstractViewer, public NzNode, NzRenderTarget::Listener { @@ -32,6 +32,9 @@ class NAZARA_API NzCamera : public NzAbstractViewer, public NzNode, NzRenderTarg NzVector3f GetForward() const; float GetFOV() const; const NzFrustumf& GetFrustum() const; + NzVector3f GetGlobalForward() const; + NzVector3f GetGlobalRight() const; + NzVector3f GetGlobalUp() const; const NzMatrix4f& GetProjectionMatrix() const; const NzRenderTarget* GetTarget() const; const NzRectf& GetTargetRegion() const; diff --git a/include/Nazara/Graphics/ColorBackground.hpp b/include/Nazara/Graphics/ColorBackground.hpp index c0fe76371..d2418289a 100644 --- a/include/Nazara/Graphics/ColorBackground.hpp +++ b/include/Nazara/Graphics/ColorBackground.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/Config.hpp b/include/Nazara/Graphics/Config.hpp index b09bace5e..1a51c5803 100644 --- a/include/Nazara/Graphics/Config.hpp +++ b/include/Nazara/Graphics/Config.hpp @@ -1,7 +1,7 @@ /* Nazara Engine - Graphics module - Copyright (C) 2014 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) + Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/include/Nazara/Graphics/ConfigCheck.hpp b/include/Nazara/Graphics/ConfigCheck.hpp index 8b46edaaf..98fee1840 100644 --- a/include/Nazara/Graphics/ConfigCheck.hpp +++ b/include/Nazara/Graphics/ConfigCheck.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/Debug.hpp b/include/Nazara/Graphics/Debug.hpp index 7902d36b1..1d048c131 100644 --- a/include/Nazara/Graphics/Debug.hpp +++ b/include/Nazara/Graphics/Debug.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/DebugOff.hpp b/include/Nazara/Graphics/DebugOff.hpp index f5e3b3e1c..38a452aab 100644 --- a/include/Nazara/Graphics/DebugOff.hpp +++ b/include/Nazara/Graphics/DebugOff.hpp @@ -1,9 +1,9 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp // On suppose que Debug.hpp a déjà été inclus, tout comme Config.hpp -#if NAZARA_GRAPHICS_HPP +#if NAZARA_GRAPHICS_MANAGE_MEMORY #undef delete #undef new #endif diff --git a/include/Nazara/Graphics/DeferredBloomPass.hpp b/include/Nazara/Graphics/DeferredBloomPass.hpp index e273ad530..ae6b2ff65 100644 --- a/include/Nazara/Graphics/DeferredBloomPass.hpp +++ b/include/Nazara/Graphics/DeferredBloomPass.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/DeferredDOFPass.hpp b/include/Nazara/Graphics/DeferredDOFPass.hpp index 81f3dae32..d5c7bd298 100644 --- a/include/Nazara/Graphics/DeferredDOFPass.hpp +++ b/include/Nazara/Graphics/DeferredDOFPass.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/DeferredFXAAPass.hpp b/include/Nazara/Graphics/DeferredFXAAPass.hpp index a12f7774e..662d89d5b 100644 --- a/include/Nazara/Graphics/DeferredFXAAPass.hpp +++ b/include/Nazara/Graphics/DeferredFXAAPass.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/DeferredFinalPass.hpp b/include/Nazara/Graphics/DeferredFinalPass.hpp index 84512b6ce..fb0990feb 100644 --- a/include/Nazara/Graphics/DeferredFinalPass.hpp +++ b/include/Nazara/Graphics/DeferredFinalPass.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/DeferredFogPass.hpp b/include/Nazara/Graphics/DeferredFogPass.hpp index b17e346b0..fd4e831e2 100644 --- a/include/Nazara/Graphics/DeferredFogPass.hpp +++ b/include/Nazara/Graphics/DeferredFogPass.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -25,6 +25,7 @@ class NAZARA_API NzDeferredFogPass : public NzDeferredRenderPass NzRenderStates m_states; NzShaderRef m_shader; NzTextureSampler m_pointSampler; + int m_shaderEyePositionLocation; }; #endif // NAZARA_DEFERREDFOGPASS_HPP diff --git a/include/Nazara/Graphics/DeferredForwardPass.hpp b/include/Nazara/Graphics/DeferredForwardPass.hpp index 94f99eaba..b0c561c93 100644 --- a/include/Nazara/Graphics/DeferredForwardPass.hpp +++ b/include/Nazara/Graphics/DeferredForwardPass.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/DeferredGeometryPass.hpp b/include/Nazara/Graphics/DeferredGeometryPass.hpp index 8bdc2703c..11c238d53 100644 --- a/include/Nazara/Graphics/DeferredGeometryPass.hpp +++ b/include/Nazara/Graphics/DeferredGeometryPass.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -22,6 +22,18 @@ class NAZARA_API NzDeferredGeometryPass : public NzDeferredRenderPass bool Resize(const NzVector2ui& dimensions); protected: + struct ShaderUniforms; + + const ShaderUniforms* GetShaderUniforms(const NzShader* shader) const; + + struct ShaderUniforms + { + int eyePosition; + int sceneAmbient; + int textureOverlay; + }; + + mutable std::unordered_map m_shaderUniforms; NzRenderStates m_clearStates; NzShaderRef m_clearShader; }; diff --git a/include/Nazara/Graphics/DeferredPhongLightingPass.hpp b/include/Nazara/Graphics/DeferredPhongLightingPass.hpp index 38c92be48..94f53ec2a 100644 --- a/include/Nazara/Graphics/DeferredPhongLightingPass.hpp +++ b/include/Nazara/Graphics/DeferredPhongLightingPass.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -39,7 +39,11 @@ class NAZARA_API NzDeferredPhongLightingPass : public NzDeferredRenderPass NzStaticMesh* m_coneMesh; NzStaticMesh* m_sphereMesh; bool m_lightMeshesDrawing; + int m_directionalLightShaderEyePositionLocation; + int m_directionalLightShaderSceneAmbientLocation; int m_pointSpotLightShaderDiscardLocation; + int m_pointSpotLightShaderEyePositionLocation; + int m_pointSpotLightShaderSceneAmbientLocation; }; #endif // NAZARA_DEFERREDPHONGLIGHTINGPASS_HPP diff --git a/include/Nazara/Graphics/DeferredRenderPass.hpp b/include/Nazara/Graphics/DeferredRenderPass.hpp index 62f1cd339..a4dd5eaa5 100644 --- a/include/Nazara/Graphics/DeferredRenderPass.hpp +++ b/include/Nazara/Graphics/DeferredRenderPass.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/DeferredRenderQueue.hpp b/include/Nazara/Graphics/DeferredRenderQueue.hpp index b5ee2b395..6b59462fc 100644 --- a/include/Nazara/Graphics/DeferredRenderQueue.hpp +++ b/include/Nazara/Graphics/DeferredRenderQueue.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -11,52 +11,81 @@ #include #include #include +#include #include #include +#include #include +#include #include #include class NzForwardRenderQueue; -class NzMaterial; -class NzSkeletalMesh; -class NzStaticMesh; class NAZARA_API NzDeferredRenderQueue : public NzAbstractRenderQueue, NzObjectListener { public: NzDeferredRenderQueue(NzForwardRenderQueue* forwardQueue); - ~NzDeferredRenderQueue(); + ~NzDeferredRenderQueue() = default; + void AddBillboard(const NzMaterial* material, const NzVector3f& position, const NzVector2f& size, const NzVector2f& sinCos = NzVector2f(0.f, 1.f), const NzColor& color = NzColor::White) override; + void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr = nullptr, NzSparsePtr colorPtr = nullptr) override; + void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr, NzSparsePtr alphaPtr) override; + void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr colorPtr = nullptr) override; + void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr alphaPtr) override; + void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr = nullptr, NzSparsePtr colorPtr = nullptr) override; + void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr, NzSparsePtr alphaPtr) override; + void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr colorPtr = nullptr) override; + void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr alphaPtr) override; void AddDrawable(const NzDrawable* drawable) override; void AddLight(const NzLight* light) override; void AddMesh(const NzMaterial* material, const NzMeshData& meshData, const NzBoxf& meshAABB, const NzMatrix4f& transformMatrix) override; - void AddSprite(const NzSprite* sprite) override; + void AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const NzTexture* overlay = nullptr) override; void Clear(bool fully); - struct BatchedModelMaterialComparator - { - bool operator()(const NzMaterial* mat1, const NzMaterial* mat2); - }; - - struct BatchedSpriteMaterialComparator - { - bool operator()(const NzMaterial* mat1, const NzMaterial* mat2); - }; - struct MeshDataComparator { bool operator()(const NzMeshData& data1, const NzMeshData& data2); }; - typedef std::map, MeshDataComparator> MeshInstanceContainer; - typedef std::map, BatchedModelMaterialComparator> ModelBatches; - typedef std::map> BatchedSpriteContainer; + struct MeshInstanceEntry + { + MeshInstanceEntry(NzObjectListener* listener, int indexBufferValue, int vertexBufferValue) : + indexBufferListener(listener, indexBufferValue), + vertexBufferListener(listener, vertexBufferValue) + { + } + + std::vector instances; + NzIndexBufferConstListener indexBufferListener; + NzVertexBufferConstListener vertexBufferListener; + }; + + typedef std::map MeshInstanceContainer; + + struct BatchedModelMaterialComparator + { + bool operator()(const NzMaterial* mat1, const NzMaterial* mat2); + }; + + struct BatchedModelEntry + { + BatchedModelEntry(NzObjectListener* listener, int materialValue) : + materialListener(listener, materialValue) + { + } + + NzMaterialConstListener materialListener; + MeshInstanceContainer meshMap; + bool enabled = false; + bool instancingEnabled = false; + }; + + typedef std::map ModelBatches; typedef std::vector LightContainer; ModelBatches opaqueModels; - BatchedSpriteContainer sprites; LightContainer directionalLights; LightContainer pointLights; LightContainer spotLights; diff --git a/include/Nazara/Graphics/DeferredRenderTechnique.hpp b/include/Nazara/Graphics/DeferredRenderTechnique.hpp index 90f81fc46..1a5f2669c 100644 --- a/include/Nazara/Graphics/DeferredRenderTechnique.hpp +++ b/include/Nazara/Graphics/DeferredRenderTechnique.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/Drawable.hpp b/include/Nazara/Graphics/Drawable.hpp index 97841eebb..7ccfc936b 100644 --- a/include/Nazara/Graphics/Drawable.hpp +++ b/include/Nazara/Graphics/Drawable.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -13,7 +13,7 @@ class NAZARA_API NzDrawable { public: NzDrawable() = default; - ~NzDrawable(); + virtual ~NzDrawable(); virtual void Draw() const = 0; }; diff --git a/include/Nazara/Graphics/Enums.hpp b/include/Nazara/Graphics/Enums.hpp index 59a8104c4..1e301ecb9 100644 --- a/include/Nazara/Graphics/Enums.hpp +++ b/include/Nazara/Graphics/Enums.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -43,6 +43,41 @@ enum nzMaterialUniform nzMaterialUniform_Max = nzMaterialUniform_SpecularMap }; +enum nzParticleComponent +{ + nzParticleComponent_Unused = -1, + + nzParticleComponent_Color, + nzParticleComponent_Life, + nzParticleComponent_Mass, + nzParticleComponent_Normal, + nzParticleComponent_Position, + nzParticleComponent_Radius, + nzParticleComponent_Rotation, + nzParticleComponent_Size, + nzParticleComponent_Velocity, + nzParticleComponent_Userdata0, + nzParticleComponent_Userdata1, + nzParticleComponent_Userdata2, + nzParticleComponent_Userdata3, + nzParticleComponent_Userdata4, + nzParticleComponent_Userdata5, + nzParticleComponent_Userdata6, + nzParticleComponent_Userdata7, + nzParticleComponent_Userdata8, + + nzParticleComponent_Max = nzParticleComponent_Userdata8 +}; + +enum nzParticleLayout +{ + nzParticleLayout_Billboard, + nzParticleLayout_Model, + nzParticleLayout_Sprite, + + nzParticleLayout_Max = nzParticleLayout_Sprite +}; + enum nzRenderPassType { nzRenderPassType_AA, @@ -71,10 +106,12 @@ enum nzRenderTechniqueType enum nzSceneNodeType { - nzSceneNodeType_Light, // NzLight - nzSceneNodeType_Model, // NzModel - nzSceneNodeType_Root, // NzSceneRoot - nzSceneNodeType_Sprite, // NzSprite + nzSceneNodeType_Light, // NzLight + nzSceneNodeType_Model, // NzModel + nzSceneNodeType_ParticleEmitter, // NzParticleEmitter + nzSceneNodeType_Root, // NzSceneRoot + nzSceneNodeType_Sprite, // NzSprite + nzSceneNodeType_TextSprite, // NzTextSprite nzSceneNodeType_User, nzSceneNodeType_Max = nzSceneNodeType_User @@ -85,10 +122,13 @@ enum nzShaderFlags { nzShaderFlags_None = 0, - nzShaderFlags_Deferred = 0x1, - nzShaderFlags_Instancing = 0x2, + nzShaderFlags_Billboard = 0x01, + nzShaderFlags_Deferred = 0x02, + nzShaderFlags_Instancing = 0x04, + nzShaderFlags_TextureOverlay = 0x08, + nzShaderFlags_VertexColor = 0x10, - nzShaderFlags_Max = nzShaderFlags_Instancing*2-1 + nzShaderFlags_Max = nzShaderFlags_VertexColor*2-1 }; #endif // NAZARA_ENUMS_GRAPHICS_HPP diff --git a/include/Nazara/Graphics/ForwardRenderQueue.hpp b/include/Nazara/Graphics/ForwardRenderQueue.hpp index b57ca839c..9ac81b692 100644 --- a/include/Nazara/Graphics/ForwardRenderQueue.hpp +++ b/include/Nazara/Graphics/ForwardRenderQueue.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -11,16 +11,16 @@ #include #include #include +#include #include #include +#include #include +#include #include #include class NzAbstractViewer; -class NzMaterial; -class NzSkeletalMesh; -class NzStaticMesh; class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzObjectListener { @@ -28,12 +28,21 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzObjectLi public: NzForwardRenderQueue() = default; - ~NzForwardRenderQueue(); + ~NzForwardRenderQueue() = default; + void AddBillboard(const NzMaterial* material, const NzVector3f& position, const NzVector2f& size, const NzVector2f& sinCos = NzVector2f(0.f, 1.f), const NzColor& color = NzColor::White) override; + void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr = nullptr, NzSparsePtr colorPtr = nullptr) override; + void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr, NzSparsePtr alphaPtr) override; + void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr colorPtr = nullptr) override; + void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr alphaPtr) override; + void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr = nullptr, NzSparsePtr colorPtr = nullptr) override; + void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr, NzSparsePtr alphaPtr) override; + void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr colorPtr = nullptr) override; + void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr alphaPtr) override; void AddDrawable(const NzDrawable* drawable) override; void AddLight(const NzLight* light) override; void AddMesh(const NzMaterial* material, const NzMeshData& meshData, const NzBoxf& meshAABB, const NzMatrix4f& transformMatrix) override; - void AddSprite(const NzSprite* sprite) override; + void AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const NzTexture* overlay = nullptr) override; void Clear(bool fully); @@ -43,37 +52,128 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzObjectLi bool OnObjectDestroy(const NzRefCounted* object, int index) override; void OnObjectReleased(const NzRefCounted* object, int index) override; - struct TransparentModelData + /// Billboards + struct BillboardData { - NzMatrix4f transformMatrix; - NzMeshData meshData; - NzSpheref boundingSphere; - const NzMaterial* material; + NzColor color; + NzVector3f center; + NzVector2f size; + NzVector2f sinCos; }; - struct BatchedModelMaterialComparator + struct BatchedBillboardComparator { bool operator()(const NzMaterial* mat1, const NzMaterial* mat2); }; + struct BatchedBillboardEntry + { + BatchedBillboardEntry(NzObjectListener* listener, int materialValue) : + materialListener(listener, materialValue) + { + } + + NzMaterialConstListener materialListener; + std::vector billboards; + }; + + typedef std::map BatchedBillboardContainer; + + /// Sprites + struct SpriteChain_XYZ_Color_UV + { + const NzVertexStruct_XYZ_Color_UV* vertices; + unsigned int spriteCount; + }; + + struct BatchedSpriteEntry + { + BatchedSpriteEntry(NzObjectListener* listener, int textureValue) : + textureListener(listener, textureValue) + { + } + + std::vector spriteChains; + NzTextureConstListener textureListener; + }; + struct BatchedSpriteMaterialComparator { bool operator()(const NzMaterial* mat1, const NzMaterial* mat2); }; + typedef std::map BasicSpriteOverlayContainer; + + struct BatchedBasicSpriteEntry + { + BatchedBasicSpriteEntry(NzObjectListener* listener, int materialValue) : + materialListener(listener, materialValue) + { + } + + NzMaterialConstListener materialListener; + BasicSpriteOverlayContainer overlayMap; + bool enabled = false; + }; + + typedef std::map BasicSpriteBatches; + + /// Meshes struct MeshDataComparator { bool operator()(const NzMeshData& data1, const NzMeshData& data2); }; - typedef std::map>, MeshDataComparator> MeshInstanceContainer; - typedef std::map, BatchedModelMaterialComparator> ModelBatches; - typedef std::map> BatchedSpriteContainer; + struct MeshInstanceEntry + { + MeshInstanceEntry(NzObjectListener* listener, int indexBufferValue, int vertexBufferValue) : + indexBufferListener(listener, indexBufferValue), + vertexBufferListener(listener, vertexBufferValue) + { + } + + std::vector instances; + NzIndexBufferConstListener indexBufferListener; + NzSpheref squaredBoundingSphere; + NzVertexBufferConstListener vertexBufferListener; + }; + + typedef std::map MeshInstanceContainer; + + struct BatchedModelMaterialComparator + { + bool operator()(const NzMaterial* mat1, const NzMaterial* mat2); + }; + + struct BatchedModelEntry + { + BatchedModelEntry(NzObjectListener* listener, int materialValue) : + materialListener(listener, materialValue) + { + } + + NzMaterialConstListener materialListener; + MeshInstanceContainer meshMap; + bool enabled = false; + bool instancingEnabled = false; + }; + + typedef std::map ModelBatches; + + struct TransparentModelData + { + NzMatrix4f transformMatrix; + NzMeshData meshData; + NzSpheref squaredBoundingSphere; + const NzMaterial* material; + }; + typedef std::vector LightContainer; typedef std::vector TransparentModelContainer; + BatchedBillboardContainer billboards; + BasicSpriteBatches basicSprites; ModelBatches opaqueModels; - BatchedSpriteContainer sprites; TransparentModelContainer transparentModels; std::vector transparentModelData; std::vector otherDrawables; diff --git a/include/Nazara/Graphics/ForwardRenderTechnique.hpp b/include/Nazara/Graphics/ForwardRenderTechnique.hpp index a7e0fefc0..179fcd863 100644 --- a/include/Nazara/Graphics/ForwardRenderTechnique.hpp +++ b/include/Nazara/Graphics/ForwardRenderTechnique.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -19,7 +19,7 @@ class NAZARA_API NzForwardRenderTechnique : public NzAbstractRenderTechnique { public: NzForwardRenderTechnique(); - ~NzForwardRenderTechnique(); + ~NzForwardRenderTechnique() = default; void Clear(const NzScene* scene) const; bool Draw(const NzScene* scene) const; @@ -30,30 +30,46 @@ class NAZARA_API NzForwardRenderTechnique : public NzAbstractRenderTechnique void SetMaxLightPassPerObject(unsigned int passCount); + static bool Initialize(); + static void Uninitialize(); + private: - struct LightUniforms; + struct ShaderUniforms; + void DrawBasicSprites(const NzScene* scene) const; + void DrawBillboards(const NzScene* scene) const; void DrawOpaqueModels(const NzScene* scene) const; - void DrawSprites(const NzScene* scene) const; void DrawTransparentModels(const NzScene* scene) const; - const LightUniforms* GetLightUniforms(const NzShader* shader) const; + const ShaderUniforms* GetShaderUniforms(const NzShader* shader) const; - struct LightUniforms + struct ShaderUniforms { - NzLightUniforms uniforms; - bool exists; - int offset; // "Distance" entre Lights[0].type et Lights[1].type + NzLightUniforms lightUniforms; + bool hasLightUniforms; + /// Moins coûteux en mémoire que de stocker un NzLightUniforms par index de lumière, /// à voir si ça fonctionne chez tout le monde + int lightOffset; // "Distance" entre Lights[0].type et Lights[1].type + + // Autre uniformes + int eyePosition; + int sceneAmbient; + int textureOverlay; }; - mutable std::unordered_map m_lightUniforms; + mutable std::unordered_map m_shaderUniforms; + NzBuffer m_vertexBuffer; mutable NzForwardRenderQueue m_renderQueue; - NzIndexBufferRef m_indexBuffer; mutable NzLightManager m_directionalLights; mutable NzLightManager m_lights; + NzVertexBuffer m_billboardPointBuffer; NzVertexBuffer m_spriteBuffer; unsigned int m_maxLightPassPerObject; + + static NzIndexBuffer s_quadIndexBuffer; + static NzVertexBuffer s_quadVertexBuffer; + static NzVertexDeclaration s_billboardInstanceDeclaration; + static NzVertexDeclaration s_billboardVertexDeclaration; }; #endif // NAZARA_FORWARDRENDERTECHNIQUE_HPP diff --git a/include/Nazara/Graphics/Graphics.hpp b/include/Nazara/Graphics/Graphics.hpp index 169ed9dcd..adba47320 100644 --- a/include/Nazara/Graphics/Graphics.hpp +++ b/include/Nazara/Graphics/Graphics.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/GuillotineTextureAtlas.hpp b/include/Nazara/Graphics/GuillotineTextureAtlas.hpp new file mode 100644 index 000000000..fa82c8056 --- /dev/null +++ b/include/Nazara/Graphics/GuillotineTextureAtlas.hpp @@ -0,0 +1,25 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_GUILLOTINETEXTUREATLAS_HPP +#define NAZARA_GUILLOTINETEXTUREATLAS_HPP + +#include +#include + +class NAZARA_API NzGuillotineTextureAtlas : public NzGuillotineImageAtlas +{ + public: + NzGuillotineTextureAtlas() = default; + ~NzGuillotineTextureAtlas() = default; + + nzUInt32 GetStorage() const; + + private: + NzAbstractImage* ResizeImage(NzAbstractImage* oldImage, const NzVector2ui& size) const override; +}; + +#endif // NAZARA_GUILLOTINETEXTUREATLAS_HPP diff --git a/include/Nazara/Graphics/Light.hpp b/include/Nazara/Graphics/Light.hpp index 4a53eed94..5f24f7e67 100644 --- a/include/Nazara/Graphics/Light.hpp +++ b/include/Nazara/Graphics/Light.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -18,17 +18,19 @@ struct NzLightUniforms; class NAZARA_API NzLight : public NzSceneNode { public: - NzLight(nzLightType type); + NzLight(nzLightType type = nzLightType_Point); NzLight(const NzLight& light); ~NzLight() = default; void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; + NzLight* Clone() const; + NzLight* Create() const; + void Enable(const NzShader* shader, const NzLightUniforms& uniforms, int offset = 0) const; float GetAmbientFactor() const; float GetAttenuation() const; - const NzBoundingVolumef& GetBoundingVolume() const; NzColor GetColor() const; float GetDiffuseFactor() const; float GetInnerAngle() const; @@ -54,15 +56,13 @@ class NAZARA_API NzLight : public NzSceneNode private: bool FrustumCull(const NzFrustumf& frustum) const override; - void InvalidateNode() override; + void MakeBoundingVolume() const override; void Register() override; void Unregister() override; void UpdateBoundingVolume() const; nzLightType m_type; - mutable NzBoundingVolumef m_boundingVolume; NzColor m_color; - mutable bool m_boundingVolumeUpdated; float m_ambientFactor; float m_attenuation; float m_diffuseFactor; diff --git a/include/Nazara/Graphics/LightManager.hpp b/include/Nazara/Graphics/LightManager.hpp index 2796084dc..939421cae 100644 --- a/include/Nazara/Graphics/LightManager.hpp +++ b/include/Nazara/Graphics/LightManager.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/Material.hpp b/include/Nazara/Graphics/Material.hpp index 15311fd54..b692e704e 100644 --- a/include/Nazara/Graphics/Material.hpp +++ b/include/Nazara/Graphics/Material.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -35,7 +36,9 @@ struct NAZARA_API NzMaterialParams class NzMaterial; +using NzMaterialConstListener = NzObjectListenerWrapper; using NzMaterialConstRef = NzObjectRef; +using NzMaterialListener = NzObjectListenerWrapper; using NzMaterialLoader = NzResourceLoader; using NzMaterialRef = NzObjectRef; @@ -47,13 +50,13 @@ class NAZARA_API NzMaterial : public NzRefCounted, public NzResource public: NzMaterial(); NzMaterial(const NzMaterial& material); - NzMaterial(NzMaterial&& material); ~NzMaterial(); const NzShader* Apply(nzUInt32 shaderFlags = 0, nzUInt8 textureUnit = 0, nzUInt8* lastUsedUnit = nullptr) const; void Enable(nzRendererParameter renderParameter, bool enable); void EnableAlphaTest(bool alphaTest); + void EnableDepthSorting(bool depthSorting); void EnableLighting(bool lighting); void EnableTransform(bool transform); @@ -89,6 +92,7 @@ class NAZARA_API NzMaterial : public NzRefCounted, public NzResource bool HasSpecularMap() const; bool IsAlphaTestEnabled() const; + bool IsDepthSortingEnabled() const; bool IsEnabled(nzRendererParameter renderParameter) const; bool IsLightingEnabled() const; bool IsTransformEnabled() const; @@ -128,7 +132,6 @@ class NAZARA_API NzMaterial : public NzRefCounted, public NzResource void SetSrcBlend(nzBlendFunc func); NzMaterial& operator=(const NzMaterial& material); - NzMaterial& operator=(NzMaterial&& material); static NzMaterial* GetDefault(); @@ -136,11 +139,12 @@ class NAZARA_API NzMaterial : public NzRefCounted, public NzResource struct ShaderInstance { const NzShader* shader; - NzUberShaderInstance* uberInstance; + NzUberShaderInstance* uberInstance = nullptr; int uniforms[nzMaterialUniform_Max+1]; }; void Copy(const NzMaterial& material); + void Move(NzMaterial&& material); void GenerateShader(nzUInt32 flags) const; void InvalidateShaders(); @@ -162,6 +166,7 @@ class NAZARA_API NzMaterial : public NzRefCounted, public NzResource NzUberShaderConstRef m_uberShader; mutable ShaderInstance m_shaders[nzShaderFlags_Max+1]; bool m_alphaTestEnabled; + bool m_depthSortingEnabled; bool m_lightingEnabled; bool m_transformEnabled; float m_alphaThreshold; diff --git a/include/Nazara/Graphics/Model.hpp b/include/Nazara/Graphics/Model.hpp index 5c390d8c5..e93b65679 100644 --- a/include/Nazara/Graphics/Model.hpp +++ b/include/Nazara/Graphics/Model.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -37,16 +37,17 @@ class NAZARA_API NzModel : public NzResource, public NzSceneNode public: NzModel(); NzModel(const NzModel& model); - NzModel(NzModel&& model); virtual ~NzModel(); void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; void AdvanceAnimation(float elapsedTime); + NzModel* Clone() const; + NzModel* Create() const; + void EnableAnimation(bool animation); NzAnimation* GetAnimation() const; - const NzBoundingVolumef& GetBoundingVolume() const; NzMaterial* GetMaterial(const NzString& subMeshName) const; NzMaterial* GetMaterial(unsigned int matIndex) const; NzMaterial* GetMaterial(unsigned int skinIndex, const NzString& subMeshName) const; @@ -84,16 +85,12 @@ class NAZARA_API NzModel : public NzResource, public NzSceneNode void SetSkinCount(unsigned int skinCount); NzModel& operator=(const NzModel& node); - NzModel& operator=(NzModel&& node); protected: - void InvalidateNode() override; - virtual void UpdateBoundingVolume() const; + void MakeBoundingVolume() const override; std::vector m_materials; - mutable NzBoundingVolumef m_boundingVolume; NzMeshRef m_mesh; - mutable bool m_boundingVolumeUpdated; unsigned int m_matCount; unsigned int m_skin; unsigned int m_skinCount; diff --git a/include/Nazara/Graphics/ParticleController.hpp b/include/Nazara/Graphics/ParticleController.hpp new file mode 100644 index 000000000..528e5fabd --- /dev/null +++ b/include/Nazara/Graphics/ParticleController.hpp @@ -0,0 +1,34 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_PARTICLECONTROLLER_HPP +#define NAZARA_PARTICLECONTROLLER_HPP + +#include +#include +#include +#include + +class NzParticleController; +class NzParticleMapper; +class NzParticleSystem; + +using NzParticleControllerConstListener = NzObjectListenerWrapper; +using NzParticleControllerConstRef = NzObjectRef; +using NzParticleControllerListener = NzObjectListenerWrapper; +using NzParticleControllerRef = NzObjectRef; + +class NAZARA_API NzParticleController : public NzRefCounted +{ + public: + NzParticleController() = default; + NzParticleController(const NzParticleController& controller); + virtual ~NzParticleController(); + + virtual void Apply(NzParticleSystem& system, NzParticleMapper& mapper, unsigned int startId, unsigned int endId, float elapsedTime) = 0; +}; + +#endif // NAZARA_PARTICLECONTROLLER_HPP diff --git a/include/Nazara/Graphics/ParticleDeclaration.hpp b/include/Nazara/Graphics/ParticleDeclaration.hpp new file mode 100644 index 000000000..4f423b4f8 --- /dev/null +++ b/include/Nazara/Graphics/ParticleDeclaration.hpp @@ -0,0 +1,70 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_PARTICLEDECLARATION_HPP +#define NAZARA_PARTICLEDECLARATION_HPP + +#include +#include +#include +#include +#include +#include + +class NzParticleDeclaration; + +using NzParticleDeclarationConstListener = NzObjectListenerWrapper; +using NzParticleDeclarationConstRef = NzObjectRef; +using NzParticleDeclarationListener = NzObjectListenerWrapper; +using NzParticleDeclarationRef = NzObjectRef; + +class NAZARA_API NzParticleDeclaration : public NzRefCounted +{ + friend class NzGraphics; + + public: + NzParticleDeclaration(); + NzParticleDeclaration(const NzParticleDeclaration& declaration); + ~NzParticleDeclaration(); + + void DisableComponent(nzParticleComponent component); + void EnableComponent(nzParticleComponent component, nzComponentType type, unsigned int offset); + + void GetComponent(nzParticleComponent component, bool* enabled, nzComponentType* type, unsigned int* offset) const; + unsigned int GetStride() const; + + void SetStride(unsigned int stride); + + NzParticleDeclaration& operator=(const NzParticleDeclaration& declaration); + + static NzParticleDeclaration* Get(nzParticleLayout layout); + static bool IsTypeSupported(nzComponentType type); + + private: + static bool Initialize(); + static void Uninitialize(); + + struct Component + { + nzComponentType type; + bool enabled = false; + unsigned int offset; + + /* + ** -Lynix: + ** Il serait aussi possible de préciser le stride de façon indépendante, ce que je ne permets pas + ** pour décomplexifier l'interface en enlevant quelque chose que je juge inutile. + ** Si vous pensez que ça peut être utile, n'hésitez pas à me le faire savoir ! + */ + }; + + Component m_components[nzParticleComponent_Max+1]; + unsigned int m_stride; + + static NzParticleDeclaration s_declarations[nzParticleLayout_Max+1]; +}; + +#endif // NAZARA_PARTICLEDECLARATION_HPP diff --git a/include/Nazara/Graphics/ParticleEmitter.hpp b/include/Nazara/Graphics/ParticleEmitter.hpp new file mode 100644 index 000000000..b8bb32deb --- /dev/null +++ b/include/Nazara/Graphics/ParticleEmitter.hpp @@ -0,0 +1,48 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_PARTICLEEMITTER_HPP +#define NAZARA_PARTICLEEMITTER_HPP + +#include +#include + +class NzParticleMapper; +class NzParticleSystem; + +class NAZARA_API NzParticleEmitter : public NzNode +{ + public: + NzParticleEmitter(); + NzParticleEmitter(const NzParticleEmitter& emitter) = default; + NzParticleEmitter(NzParticleEmitter&& emitter) = default; + virtual ~NzParticleEmitter(); + + virtual void Emit(NzParticleSystem& system, float elapsedTime) const; + + void EnableLagCompensation(bool enable); + + unsigned int GetEmissionCount() const; + float GetEmissionRate() const; + + bool IsLagCompensationEnabled() const; + + void SetEmissionCount(unsigned int count); + void SetEmissionRate(float rate); + + NzParticleEmitter& operator=(const NzParticleEmitter& emitter) = default; + NzParticleEmitter& operator=(NzParticleEmitter&& emitter) = default; + + private: + virtual void SetupParticles(NzParticleMapper& mapper, unsigned int count) const = 0; + + bool m_lagCompensationEnabled; + mutable float m_emissionAccumulator; + float m_emissionRate; + unsigned int m_emissionCount; +}; + +#endif // NAZARA_PARTICLEEMITTER_HPP diff --git a/include/Nazara/Graphics/ParticleGenerator.hpp b/include/Nazara/Graphics/ParticleGenerator.hpp new file mode 100644 index 000000000..006420184 --- /dev/null +++ b/include/Nazara/Graphics/ParticleGenerator.hpp @@ -0,0 +1,34 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_PARTICLEGENERATOR_HPP +#define NAZARA_PARTICLEGENERATOR_HPP + +#include +#include +#include +#include + +class NzParticleGenerator; +class NzParticleMapper; +class NzParticleSystem; + +using NzParticleGeneratorConstListener = NzObjectListenerWrapper; +using NzParticleGeneratorConstRef = NzObjectRef; +using NzParticleGeneratorListener = NzObjectListenerWrapper; +using NzParticleGeneratorRef = NzObjectRef; + +class NAZARA_API NzParticleGenerator : public NzRefCounted +{ + public: + NzParticleGenerator() = default; + NzParticleGenerator(const NzParticleGenerator& generator); + virtual ~NzParticleGenerator(); + + virtual void Generate(NzParticleSystem& system, NzParticleMapper& mapper, unsigned int startId, unsigned int endId) = 0; +}; + +#endif // NAZARA_PARTICLEGENERATOR_HPP diff --git a/include/Nazara/Graphics/ParticleMapper.hpp b/include/Nazara/Graphics/ParticleMapper.hpp new file mode 100644 index 000000000..9fb4e7102 --- /dev/null +++ b/include/Nazara/Graphics/ParticleMapper.hpp @@ -0,0 +1,31 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_PARTICLEMAPPER_HPP +#define NAZARA_PARTICLEMAPPER_HPP + +#include +#include +#include +#include + +class NAZARA_API NzParticleMapper +{ + public: + NzParticleMapper(void* buffer, const NzParticleDeclaration* declaration); + ~NzParticleMapper(); + + template NzSparsePtr GetComponentPtr(nzParticleComponent component); + template NzSparsePtr GetComponentPtr(nzParticleComponent component) const; + + private: + const NzParticleDeclaration* m_declaration; + nzUInt8* m_ptr; +}; + +#include + +#endif // NAZARA_PARTICLEMAPPER_HPP diff --git a/include/Nazara/Graphics/ParticleMapper.inl b/include/Nazara/Graphics/ParticleMapper.inl new file mode 100644 index 000000000..07f974ad8 --- /dev/null +++ b/include/Nazara/Graphics/ParticleMapper.inl @@ -0,0 +1,50 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +template +NzSparsePtr NzParticleMapper::GetComponentPtr(nzParticleComponent component) +{ + // Ensuite le composant qui nous intéresse + bool enabled; + nzComponentType type; + unsigned int offset; + m_declaration->GetComponent(component, &enabled, &type, &offset); + + if (enabled) + { + ///TODO: Vérifier le rapport entre le type de l'attribut et le type template ? + return NzSparsePtr(m_ptr + offset, m_declaration->GetStride()); + } + else + { + NazaraError("Attribute 0x" + NzString::Number(component, 16) + " is not enabled"); + return NzSparsePtr(); + } +} + +template +NzSparsePtr NzParticleMapper::GetComponentPtr(nzParticleComponent component) const +{ + // Ensuite le composant qui nous intéresse + bool enabled; + nzComponentType type; + unsigned int offset; + m_declaration->GetComponent(component, &enabled, &type, &offset); + + if (enabled) + { + ///TODO: Vérifier le rapport entre le type de l'attribut et le type template ? + return NzSparsePtr(m_ptr + offset, m_declaration->GetStride()); + } + else + { + NazaraError("Attribute 0x" + NzString::Number(component, 16) + " is not enabled"); + return NzSparsePtr(); + } +} + +#include diff --git a/include/Nazara/Graphics/ParticleRenderer.hpp b/include/Nazara/Graphics/ParticleRenderer.hpp new file mode 100644 index 000000000..d93df0d8b --- /dev/null +++ b/include/Nazara/Graphics/ParticleRenderer.hpp @@ -0,0 +1,35 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_PARTICLERENDERER_HPP +#define NAZARA_PARTICLERENDERER_HPP + +#include +#include +#include +#include + +class NzAbstractRenderQueue; +class NzParticleMapper; +class NzParticleRenderer; +class NzParticleSystem; + +using NzParticleRendererConstListener = NzObjectListenerWrapper; +using NzParticleRendererConstRef = NzObjectRef; +using NzParticleRendererListener = NzObjectListenerWrapper; +using NzParticleRendererRef = NzObjectRef; + +class NAZARA_API NzParticleRenderer : public NzRefCounted +{ + public: + NzParticleRenderer() = default; + NzParticleRenderer(const NzParticleRenderer& renderer); + virtual ~NzParticleRenderer(); + + virtual void Render(const NzParticleSystem& system, const NzParticleMapper& mapper, unsigned int startId, unsigned int endId, NzAbstractRenderQueue* renderQueue) = 0; +}; + +#endif // NAZARA_PARTICLERENDERER_HPP diff --git a/include/Nazara/Graphics/ParticleStruct.hpp b/include/Nazara/Graphics/ParticleStruct.hpp new file mode 100644 index 000000000..7c478b812 --- /dev/null +++ b/include/Nazara/Graphics/ParticleStruct.hpp @@ -0,0 +1,42 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_PARTICLESTRUCT_HPP +#define NAZARA_PARTICLESTRUCT_HPP + +#include +#include +#include +#include + +struct NzParticleStruct_Billboard +{ + NzColor color; + NzVector3f normal; + NzVector3f position; + NzVector3f velocity; + nzUInt32 life; + float rotation; +}; + +struct NzParticleStruct_Model +{ + NzVector3f position; + NzVector3f velocity; + nzUInt32 life; + NzQuaternionf rotation; +}; + +struct NzParticleStruct_Sprite +{ + NzColor color; + NzVector2f position; + NzVector2f velocity; + nzUInt32 life; + float rotation; +}; + +#endif // NAZARA_PARTICLESTRUCT_HPP diff --git a/include/Nazara/Graphics/ParticleSystem.hpp b/include/Nazara/Graphics/ParticleSystem.hpp new file mode 100644 index 000000000..8484f4628 --- /dev/null +++ b/include/Nazara/Graphics/ParticleSystem.hpp @@ -0,0 +1,91 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_PARTICLESYSTEM_HPP +#define NAZARA_PARTICLESYSTEM_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class NAZARA_API NzParticleSystem : public NzSceneNode, NzUpdatable +{ + public: + NzParticleSystem(unsigned int maxParticleCount, nzParticleLayout layout); + NzParticleSystem(unsigned int maxParticleCount, const NzParticleDeclaration* declaration); + NzParticleSystem(const NzParticleSystem& emitter); + ~NzParticleSystem(); + + void AddController(NzParticleController* controller); + void AddEmitter(NzParticleEmitter* emitter); + void AddGenerator(NzParticleGenerator* generator); + void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const; + + void ApplyControllers(NzParticleMapper& mapper, unsigned int particleCount, float elapsedTime, float& stepAccumulator); + + void* CreateParticle(); + void* CreateParticles(unsigned int count); + + void EnableFixedStep(bool fixedStep); + + void* GenerateParticle(); + void* GenerateParticles(unsigned int count); + + const NzParticleDeclaration* GetDeclaration() const; + float GetFixedStepSize() const; + unsigned int GetMaxParticleCount() const; + unsigned int GetParticleCount() const; + unsigned int GetParticleSize() const; + nzSceneNodeType GetSceneNodeType() const override; + + bool IsDrawable() const; + bool IsFixedStepEnabled() const; + + void KillParticle(unsigned int index); + void KillParticles(); + + void RemoveController(NzParticleController* controller); + void RemoveEmitter(NzParticleEmitter* emitter); + void RemoveGenerator(NzParticleGenerator* generator); + + void SetFixedStepSize(float stepSize); + void SetRenderer(NzParticleRenderer* renderer); + + NzParticleSystem& operator=(const NzParticleSystem& emitter); + + private: + void MakeBoundingVolume() const override; + void Register() override; + void ResizeBuffer(); + void Unregister() override; + void Update() override; + + std::set> m_dyingParticles; + mutable std::vector m_buffer; + std::vector m_controllers; + std::vector m_emitters; + std::vector m_generators; + NzParticleDeclarationConstRef m_declaration; + NzParticleRendererRef m_renderer; + bool m_fixedStepEnabled; + bool m_processing; + float m_stepAccumulator; + float m_stepSize; + unsigned int m_maxParticleCount; + unsigned int m_particleCount; + unsigned int m_particleSize; +}; + +#endif // NAZARA_PARTICLESYSTEM_HPP diff --git a/include/Nazara/Graphics/RenderTechniques.hpp b/include/Nazara/Graphics/RenderTechniques.hpp index 63f9ad3ac..0821e3f51 100644 --- a/include/Nazara/Graphics/RenderTechniques.hpp +++ b/include/Nazara/Graphics/RenderTechniques.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/Scene.hpp b/include/Nazara/Graphics/Scene.hpp index d286c4c19..04febb346 100644 --- a/include/Nazara/Graphics/Scene.hpp +++ b/include/Nazara/Graphics/Scene.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -8,42 +8,61 @@ #define NAZARA_SCENE_HPP #include +#include #include +#include #include #include #include +#include #include +#include +#include +#include class NzAbstractRenderQueue; class NzAbstractViewer; -class NzCamera; -class NzLight; -class NzModel; class NzNode; -class NzRenderQueue; class NzSceneNode; -struct NzSceneImpl; class NAZARA_API NzScene { - friend NzCamera; + friend NzSceneNode; public: NzScene(); - ~NzScene(); + ~NzScene() = default; void AddToVisibilityList(NzUpdatable* object); + template T* CreateNode(Args&&... args); + template T* CreateNode(const NzString& name, Args&&... args); + template T* CreateNode(const NzString& name, const NzString& templateNodeName); + + void Clear(); + void Cull(); void Draw(); void EnableBackground(bool enable); + NzSceneNode* FindNode(const NzString& name); + const NzSceneNode* FindNode(const NzString& name) const; + template T* FindNodeAs(const NzString& name); + template const T* FindNodeAs(const NzString& name) const; + NzColor GetAmbientColor() const; NzAbstractBackground* GetBackground() const; + NzVector3f GetBackward() const; + NzVector3f GetDown() const; + NzVector3f GetForward() const; + NzVector3f GetLeft() const; NzAbstractRenderTechnique* GetRenderTechnique() const; - NzSceneNode& GetRoot() const; + NzVector3f GetRight() const; + NzSceneNode& GetRoot(); + const NzSceneNode& GetRoot() const; NzAbstractViewer* GetViewer() const; + NzVector3f GetUp() const; float GetUpdateTime() const; unsigned int GetUpdatePerSecond() const; @@ -51,6 +70,11 @@ class NAZARA_API NzScene void RegisterForUpdate(NzUpdatable* object); + void RemoveNode(NzSceneNode* node); + void RemoveNode(const NzString& name); + + void RenderFrame(); + void SetAmbientColor(const NzColor& color); void SetBackground(NzAbstractBackground* background); void SetRenderTechnique(NzAbstractRenderTechnique* renderTechnique); @@ -66,9 +90,28 @@ class NAZARA_API NzScene operator const NzSceneNode&() const; private: + bool ChangeNodeName(NzSceneNode* node, const NzString& newName); + bool RegisterSceneNode(const NzString& name, NzSceneNode* node); void RecursiveFrustumCull(NzAbstractRenderQueue* renderQueue, const NzFrustumf& frustum, NzNode* node); - NzSceneImpl* m_impl; + mutable std::unique_ptr m_background; + mutable std::unique_ptr m_renderTechnique; + std::unordered_map m_nodeMap; + std::vector> m_nodes; + std::vector m_updateList; + std::vector m_visibleUpdateList; + NzClock m_updateClock; + NzColor m_ambientColor; + NzSceneRoot m_root; + NzAbstractViewer* m_viewer; + bool m_backgroundEnabled; + bool m_update; + float m_frameTime; + float m_updateTime; + mutable int m_renderTechniqueRanking; + unsigned int m_updatePerSecond; }; +#include + #endif // NAZARA_SCENE_HPP diff --git a/include/Nazara/Graphics/Scene.inl b/include/Nazara/Graphics/Scene.inl new file mode 100644 index 000000000..2231d1364 --- /dev/null +++ b/include/Nazara/Graphics/Scene.inl @@ -0,0 +1,139 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +///TODO: Déplacer vers SceneNode et exposer + +// Pour être sûr que ce code soit à jour +static_assert(nzSceneNodeType_Max == 6, "Please update the code below"); + +class NzLight; +class NzModel; +class NzParticleEmitter; +class NzSceneRoot; +class NzSprite; +class NzTextSprite; + +template +constexpr nzSceneNodeType NzImplGetType() +{ + return nzSceneNodeType_User; +} + +template<> +inline constexpr nzSceneNodeType NzImplGetType() +{ + return nzSceneNodeType_Light; +} + +template<> +inline constexpr nzSceneNodeType NzImplGetType() +{ + return nzSceneNodeType_Model; +} + +template<> +inline constexpr nzSceneNodeType NzImplGetType() +{ + return nzSceneNodeType_ParticleEmitter; +} + +template<> +inline constexpr nzSceneNodeType NzImplGetType() +{ + return nzSceneNodeType_Root; +} + +template<> +inline constexpr nzSceneNodeType NzImplGetType() +{ + return nzSceneNodeType_Sprite; +} + +template<> +inline constexpr nzSceneNodeType NzImplGetType() +{ + return nzSceneNodeType_TextSprite; +} + + +template +T* NzScene::CreateNode(Args&&... args) +{ + std::unique_ptr node(new T(std::forward(args)...)); + if (!RegisterSceneNode(NzString(), node.get())) + return nullptr; + + return node.release(); +} + +template +T* NzScene::CreateNode(const NzString& name, Args&&... args) +{ + std::unique_ptr node(new T(std::forward(args)...)); + if (!RegisterSceneNode(name, node.get())) + return nullptr; + + return node.release(); +} + +template +T* NzScene::CreateNode(const NzString& name, const NzString& templateNodeName) +{ + auto it = m_nodeMap.find(templateNodeName); + if (it == m_nodeMap.end()) + { + NazaraError("Node \"" + templateNodeName + "\" is not registred"); + return nullptr; + } + + NzSceneNode* sceneNode = it->second; + if (sceneNode->GetSceneNodeType() != NzImplGetType()) + { + NazaraError("Scene node type of T (" + NzString::Number(NzImplGetType()) + ") doesn't match template scene node type (" + NzString::Number(sceneNode->GetSceneNodeType()) + ")"); + return nullptr; + } + + std::unique_ptr node(static_cast(sceneNode)->Copy()); + if (!RegisterSceneNode(name, node.get())) + return nullptr; + + return node.release(); +} + +template +T* NzScene::FindNodeAs(const NzString& name) +{ + NzSceneNode* sceneNode = FindNode(name); + if (!sceneNode) + return nullptr; + + if (sceneNode->GetSceneNodeType() != NzImplGetType()) + { + NazaraError("Scene node type of T (" + NzString::Number(NzImplGetType()) + ") doesn't match \"" + name + "\" scene node type (" + NzString::Number(sceneNode->GetSceneNodeType()) + ")"); + return nullptr; + } + + return static_cast(sceneNode); +} + +template +const T* NzScene::FindNodeAs(const NzString& name) const +{ + const NzSceneNode* sceneNode = FindNode(name); + if (!sceneNode) + return nullptr; + + if (sceneNode->GetSceneNodeType() != NzImplGetType()) + { + NazaraError("Scene node type of T (" + NzString::Number(NzImplGetType()) + ") doesn't match \"" + name + "\" scene node type (" + NzString::Number(sceneNode->GetSceneNodeType()) + ")"); + return nullptr; + } + + return static_cast(sceneNode); +} + +#include diff --git a/include/Nazara/Graphics/SceneLayer.hpp b/include/Nazara/Graphics/SceneLayer.hpp deleted file mode 100644 index 20fe359a2..000000000 --- a/include/Nazara/Graphics/SceneLayer.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (C) 2014 Jérôme Leclercq -// This file is part of the "Nazara Engine - Graphics module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_SCENELAYER_HPP -#define NAZARA_SCENELAYER_HPP - -#include - -class NzAbstractRenderTechnique; -class NzAbstractViewer; - -class NAZARA_API NzSceneLayer -{ - public: - NzSceneLayer(); - ~NzSceneLayer(); - - void Draw(); - - nzUInt32 GetBufferClearFlags() const; - NzAbstractRenderQueue* GetRenderQueue() const; - NzAbstractRenderTechnique* GetRenderTechnique() const; - NzScene* GetScene() const; - NzAbstractViewer* GetViewer() const; - - void SetBufferClearFlags(nzUInt32 flags); - void SetRenderTechnique(NzAbstractRenderTechnique* renderTechnique); - void SetViewer(NzAbstractViewer* viewer); -}; - -#endif // NAZARA_SCENELAYER_HPP diff --git a/include/Nazara/Graphics/SceneNode.hpp b/include/Nazara/Graphics/SceneNode.hpp index 09aa1fab3..dea994277 100644 --- a/include/Nazara/Graphics/SceneNode.hpp +++ b/include/Nazara/Graphics/SceneNode.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,52 +9,78 @@ #include #include -#include #include #include #include +class NzAbstractRenderQueue; +class NzScene; + class NAZARA_API NzSceneNode : public NzNode { - friend class NzScene; + friend NzScene; public: NzSceneNode(); NzSceneNode(const NzSceneNode& sceneNode); + NzSceneNode(NzSceneNode& sceneNode) = delete; virtual ~NzSceneNode(); virtual void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const = 0; + // Idiôme "virtual constructor" + virtual NzSceneNode* Clone() const = 0; + virtual NzSceneNode* Create() const = 0; + void EnableDrawing(bool drawingEnabled); - virtual const NzBoundingVolumef& GetBoundingVolume() const = 0; + NzVector3f GetBackward() const; + virtual const NzBoundingVolumef& GetBoundingVolume() const; + NzVector3f GetDown() const; + NzVector3f GetForward() const; + NzVector3f GetLeft() const; + const NzString& GetName() const; nzNodeType GetNodeType() const final; + NzVector3f GetRight() const; NzScene* GetScene() const; virtual nzSceneNodeType GetSceneNodeType() const = 0; + NzVector3f GetUp() const; + + void InvalidateAABB(); virtual bool IsDrawable() const = 0; bool IsDrawingEnabled() const; bool IsVisible() const; + bool SetName(const NzString& name); + NzSceneNode& operator=(const NzSceneNode& sceneNode); - NzSceneNode& operator=(NzSceneNode&& sceneNode); + NzSceneNode& operator=(NzSceneNode&& sceneNode) = delete; protected: virtual bool FrustumCull(const NzFrustumf& frustum) const; + virtual void InvalidateNode() override; + virtual void MakeBoundingVolume() const = 0; virtual void OnParenting(const NzNode* parent) override; virtual void OnVisibilityChange(bool visibility); void RecursiveSetScene(NzScene* scene, NzNode* node); virtual void Register(); + void SetNameInternal(const NzString& name); void SetScene(NzScene* scene); virtual void Unregister(); virtual void Update(); + virtual void UpdateBoundingVolume() const; + mutable NzBoundingVolumef m_boundingVolume; NzScene* m_scene; + mutable bool m_boundingVolumeUpdated; bool m_drawingEnabled; bool m_visible; private: void UpdateVisibility(const NzFrustumf& frustum); + + NzString m_name; }; #endif // NAZARA_SCENENODE_HPP diff --git a/include/Nazara/Graphics/SceneRoot.hpp b/include/Nazara/Graphics/SceneRoot.hpp index 7b81fd5ac..60ae329be 100644 --- a/include/Nazara/Graphics/SceneRoot.hpp +++ b/include/Nazara/Graphics/SceneRoot.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -10,14 +10,15 @@ #include #include +class NzScene; + class NAZARA_API NzSceneRoot : public NzSceneNode { - friend struct NzSceneImpl; + friend NzScene; public: void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; - const NzBoundingVolumef& GetBoundingVolume() const override; nzSceneNodeType GetSceneNodeType() const override; bool IsDrawable() const; @@ -26,6 +27,10 @@ class NAZARA_API NzSceneRoot : public NzSceneNode NzSceneRoot(NzScene* scene); virtual ~NzSceneRoot(); + NzSceneRoot* Clone() const; + NzSceneRoot* Create() const; + + void MakeBoundingVolume() const override; void Register(); void Unregister(); }; diff --git a/include/Nazara/Graphics/ScreenNode.hpp b/include/Nazara/Graphics/ScreenNode.hpp deleted file mode 100644 index 214362b1b..000000000 --- a/include/Nazara/Graphics/ScreenNode.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2014 Jérôme Leclercq -// This file is part of the "Nazara Engine - Graphics module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_SCENENODE_HPP -#define NAZARA_SCENENODE_HPP - -#include -#include -#include -#include -#include -#include - -class NAZARA_API NzSceneNode : public NzNode -{ - friend class NzScene; - - public: - NzSceneNode(); - NzSceneNode(const NzSceneNode& node); - virtual ~NzSceneNode(); - - virtual void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const = 0; - - virtual const NzBoundingVolumef& GetBoundingVolume() const = 0; - nzNodeType GetNodeType() const final; - NzScene* GetScene() const; - virtual nzSceneNodeType GetSceneNodeType() const = 0; - - bool IsVisible() const; - - protected: - virtual void OnParenting(const NzNode* parent) override; - virtual void OnVisibilityChange(bool visibility); - void RecursiveSetScene(NzScene* scene, NzNode* node); - virtual void Register(); - void SetScene(NzScene* scene); - virtual void Unregister(); - virtual void Update(); - virtual bool VisibilityTest(const NzCamera* camera) = 0; - - NzScene* m_scene; - bool m_visible; - - private: - void UpdateVisibility(const NzCamera& camera); -}; - -#endif // NAZARA_SCENENODE_HPP diff --git a/include/Nazara/Graphics/SkeletalModel.hpp b/include/Nazara/Graphics/SkeletalModel.hpp new file mode 100644 index 000000000..e29fc4d79 --- /dev/null +++ b/include/Nazara/Graphics/SkeletalModel.hpp @@ -0,0 +1,90 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_SKELETALMODEL_HPP +#define NAZARA_SKELETALMODEL_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +struct NAZARA_API NzSkeletalModelParameters : public NzModelParameters +{ + bool loadAnimation = true; + NzAnimationParams animation; + + bool IsValid() const; +}; + +class NzSkeletalModel; + +using NzSkeletalModelLoader = NzResourceLoader; + +class NAZARA_API NzSkeletalModel : public NzModel, NzUpdatable +{ + friend NzSkeletalModelLoader; + + public: + NzSkeletalModel(); + NzSkeletalModel(const NzSkeletalModel& model); + NzSkeletalModel(NzSkeletalModel&& model); + ~NzSkeletalModel(); + + void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; + void AdvanceAnimation(float elapsedTime); + + NzSkeletalModel* Clone() const; + NzSkeletalModel* Create() const; + + void EnableAnimation(bool animation); + + NzAnimation* GetAnimation() const; + NzSkeleton* GetSkeleton(); + const NzSkeleton* GetSkeleton() const; + + bool HasAnimation() const; + + bool IsAnimated() const; + bool IsAnimationEnabled() const; + bool IsDrawable() const; + + bool LoadFromFile(const NzString& filePath, const NzSkeletalModelParameters& params = NzSkeletalModelParameters()); + bool LoadFromMemory(const void* data, std::size_t size, const NzSkeletalModelParameters& params = NzSkeletalModelParameters()); + bool LoadFromStream(NzInputStream& stream, const NzSkeletalModelParameters& params = NzSkeletalModelParameters()); + + void Reset(); + + bool SetAnimation(NzAnimation* animation); + void SetMesh(NzMesh* mesh) override; + bool SetSequence(const NzString& sequenceName); + void SetSequence(unsigned int sequenceIndex); + + NzSkeletalModel& operator=(const NzSkeletalModel& node); + NzSkeletalModel& operator=(NzSkeletalModel&& node); + + private: + void MakeBoundingVolume() const override; + void Register() override; + void Unregister() override; + void Update() override; + + NzAnimationRef m_animation; + NzSkeleton m_skeleton; + const NzSequence* m_currentSequence; + bool m_animationEnabled; + float m_interpolation; + unsigned int m_currentFrame; + unsigned int m_nextFrame; + + static NzSkeletalModelLoader::LoaderList s_loaders; +}; + +#endif // NAZARA_SKELETALMODEL_HPP diff --git a/include/Nazara/Graphics/SkinningManager.hpp b/include/Nazara/Graphics/SkinningManager.hpp index 5b015c066..550fddc9a 100644 --- a/include/Nazara/Graphics/SkinningManager.hpp +++ b/include/Nazara/Graphics/SkinningManager.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/SkyboxBackground.hpp b/include/Nazara/Graphics/SkyboxBackground.hpp index 6815dbc3a..97bc164c9 100644 --- a/include/Nazara/Graphics/SkyboxBackground.hpp +++ b/include/Nazara/Graphics/SkyboxBackground.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/Sprite.hpp b/include/Nazara/Graphics/Sprite.hpp index 54ebb71a1..ec8945c54 100644 --- a/include/Nazara/Graphics/Sprite.hpp +++ b/include/Nazara/Graphics/Sprite.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -10,6 +10,7 @@ #include #include #include +#include class NAZARA_API NzSprite : public NzSceneNode { @@ -17,12 +18,14 @@ class NAZARA_API NzSprite : public NzSceneNode NzSprite(); NzSprite(NzTexture* texture); NzSprite(const NzSprite& sprite); - NzSprite(NzSprite&& sprite); - ~NzSprite(); + ~NzSprite() = default; void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; - const NzBoundingVolumef& GetBoundingVolume() const override; + NzSprite* Clone() const; + NzSprite* Create() const; + + const NzColor& GetColor() const; NzMaterial* GetMaterial() const; nzSceneNodeType GetSceneNodeType() const override; const NzVector2f& GetSize() const; @@ -30,23 +33,30 @@ class NAZARA_API NzSprite : public NzSceneNode bool IsDrawable() const; + void SetColor(const NzColor& color); + void SetDefaultMaterial(); void SetMaterial(NzMaterial* material, bool resizeSprite = true); void SetSize(const NzVector2f& size); + void SetSize(float sizeX, float sizeY); void SetTexture(NzTexture* texture, bool resizeSprite = true); void SetTextureCoords(const NzRectf& coords); void SetTextureRect(const NzRectui& rect); + NzSprite& operator=(const NzSprite& sprite); + private: void InvalidateNode() override; + void MakeBoundingVolume() const override; void Register() override; void Unregister() override; - void UpdateBoundingVolume() const; + void UpdateVertices() const; - mutable NzBoundingVolumef m_boundingVolume; + NzColor m_color; NzMaterialRef m_material; NzRectf m_textureCoords; NzVector2f m_size; - mutable bool m_boundingVolumeUpdated; + mutable NzVertexStruct_XYZ_Color_UV m_vertices[4]; + mutable bool m_verticesUpdated; }; #endif // NAZARA_SPRITE_HPP diff --git a/include/Nazara/Graphics/TextSprite.hpp b/include/Nazara/Graphics/TextSprite.hpp new file mode 100644 index 000000000..a0730d669 --- /dev/null +++ b/include/Nazara/Graphics/TextSprite.hpp @@ -0,0 +1,75 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_TEXTSPRITE_HPP +#define NAZARA_TEXTSPRITE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +class NAZARA_API NzTextSprite : public NzSceneNode, NzAbstractAtlas::Listener +{ + public: + NzTextSprite(); + NzTextSprite(const NzTextSprite& sprite); + ~NzTextSprite(); + + void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; + + void Clear(); + + NzTextSprite* Clone() const; + NzTextSprite* Create() const; + + const NzColor& GetColor() const; + NzMaterial* GetMaterial() const; + nzSceneNodeType GetSceneNodeType() const override; + + void InvalidateVertices(); + bool IsDrawable() const; + + void SetColor(const NzColor& color); + void SetDefaultMaterial(); + void SetMaterial(NzMaterial* material); + + void Update(const NzAbstractTextDrawer& drawer); + + NzTextSprite& operator=(const NzTextSprite& text); + + private: + void ClearAtlases(); + void InvalidateNode() override; + void MakeBoundingVolume() const override; + bool OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) override; + bool OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata) override; + void OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata) override; + void Register() override; + void Unregister() override; + void UpdateVertices() const; + + struct RenderIndices + { + unsigned int first; + unsigned int count; + }; + + std::set m_atlases; + mutable std::unordered_map m_renderInfos; + mutable std::vector m_localVertices; + mutable std::vector m_vertices; + NzColor m_color; + NzMaterialRef m_material; + NzRectui m_localBounds; + mutable bool m_verticesUpdated; +}; + +#endif // NAZARA_TEXTSPRITE_HPP diff --git a/include/Nazara/Graphics/TextureBackground.hpp b/include/Nazara/Graphics/TextureBackground.hpp index 707d70c14..e20ac25a2 100644 --- a/include/Nazara/Graphics/TextureBackground.hpp +++ b/include/Nazara/Graphics/TextureBackground.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Graphics/View.hpp b/include/Nazara/Graphics/View.hpp index 899c34de6..41cab8fe8 100644 --- a/include/Nazara/Graphics/View.hpp +++ b/include/Nazara/Graphics/View.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,17 +9,18 @@ #include #include -#include #include #include #include #include #include +#include class NAZARA_API NzView : public NzAbstractViewer, public NzNode, NzRenderTarget::Listener { public: NzView(); + NzView(const NzVector2f& size); ~NzView(); void EnsureFrustumUpdate() const; @@ -31,7 +32,11 @@ class NAZARA_API NzView : public NzAbstractViewer, public NzNode, NzRenderTarget NzVector3f GetEyePosition() const; NzVector3f GetForward() const; const NzFrustumf& GetFrustum() const; + NzVector3f GetGlobalForward() const; + NzVector3f GetGlobalRight() const; + NzVector3f GetGlobalUp() const; const NzMatrix4f& GetProjectionMatrix() const; + const NzVector2f& GetSize() const; const NzRenderTarget* GetTarget() const; const NzRectf& GetTargetRegion() const; const NzMatrix4f& GetViewMatrix() const; @@ -39,6 +44,8 @@ class NAZARA_API NzView : public NzAbstractViewer, public NzNode, NzRenderTarget float GetZFar() const; float GetZNear() const; + void SetSize(const NzVector2f& size); + void SetSize(float width, float height); void SetTarget(const NzRenderTarget* renderTarget); void SetTarget(const NzRenderTarget& renderTarget); void SetTargetRegion(const NzRectf& region); @@ -63,6 +70,7 @@ class NAZARA_API NzView : public NzAbstractViewer, public NzNode, NzRenderTarget mutable NzMatrix4f m_viewMatrix; NzRectf m_targetRegion; mutable NzRecti m_viewport; + NzVector2f m_size; const NzRenderTarget* m_target; mutable bool m_frustumUpdated; mutable bool m_projectionMatrixUpdated; diff --git a/include/Nazara/Lua/Config.hpp b/include/Nazara/Lua/Config.hpp index 7a4440231..9e7563345 100644 --- a/include/Nazara/Lua/Config.hpp +++ b/include/Nazara/Lua/Config.hpp @@ -1,7 +1,7 @@ /* Nazara Engine - Lua scripting module - Copyright (C) 2014 Jérôme Leclercq (lynix680@gmail.com) + Copyright (C) 2015 Jérôme Leclercq (lynix680@gmail.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/include/Nazara/Lua/ConfigCheck.hpp b/include/Nazara/Lua/ConfigCheck.hpp index 21d39454d..246fe1d52 100644 --- a/include/Nazara/Lua/ConfigCheck.hpp +++ b/include/Nazara/Lua/ConfigCheck.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Lua module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Lua/Debug.hpp b/include/Nazara/Lua/Debug.hpp index 4d6e67953..8cfefe4fc 100644 --- a/include/Nazara/Lua/Debug.hpp +++ b/include/Nazara/Lua/Debug.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Lua scripting module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Lua/DebugOff.hpp b/include/Nazara/Lua/DebugOff.hpp index 6d9271835..3609f245d 100644 --- a/include/Nazara/Lua/DebugOff.hpp +++ b/include/Nazara/Lua/DebugOff.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Lua scripting module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Lua/Enums.hpp b/include/Nazara/Lua/Enums.hpp index 251887ade..8e54ed526 100644 --- a/include/Nazara/Lua/Enums.hpp +++ b/include/Nazara/Lua/Enums.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Lua scripting module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Lua/Lua.hpp b/include/Nazara/Lua/Lua.hpp index 95c42b1c3..3defd0c5f 100644 --- a/include/Nazara/Lua/Lua.hpp +++ b/include/Nazara/Lua/Lua.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Lua scripting module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Lua/LuaClass.hpp b/include/Nazara/Lua/LuaClass.hpp index bb75569fe..85cad0162 100644 --- a/include/Nazara/Lua/LuaClass.hpp +++ b/include/Nazara/Lua/LuaClass.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Lua scripting module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Lua/LuaClass.inl b/include/Nazara/Lua/LuaClass.inl index ac79d2468..3f5e68c25 100644 --- a/include/Nazara/Lua/LuaClass.inl +++ b/include/Nazara/Lua/LuaClass.inl @@ -1,9 +1,9 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Lua scripting module" // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include +#include #include template @@ -31,7 +31,7 @@ void NzLuaClass::Register(NzLuaInstance& lua) // Ainsi c'est Lua qui va s'occuper de la destruction pour nous :-) // De même, l'utilisation d'un shared_ptr permet de garder la structure en vie même si l'instance est libérée avant le LuaClass void* info = lua.PushUserdata(sizeof(std::shared_ptr)); - new (info) std::shared_ptr(m_info); + NzPlacementNew>(info, m_info); // On créé la table qui contiendra une méthode (Le finalizer) pour libérer le ClassInfo lua.PushTable(0, 1); diff --git a/include/Nazara/Lua/LuaInstance.hpp b/include/Nazara/Lua/LuaInstance.hpp index a7d530c6a..f18c2dde8 100644 --- a/include/Nazara/Lua/LuaInstance.hpp +++ b/include/Nazara/Lua/LuaInstance.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Lua scripting module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Math.hpp b/include/Nazara/Math.hpp index e70158c4a..b80211a25 100644 --- a/include/Nazara/Math.hpp +++ b/include/Nazara/Math.hpp @@ -30,7 +30,7 @@ #ifndef NAZARA_GLOBAL_MATH_HPP #define NAZARA_GLOBAL_MATH_HPP -#include +#include #include #include #include diff --git a/include/Nazara/Math/Basic.hpp b/include/Nazara/Math/Algorithm.hpp similarity index 81% rename from include/Nazara/Math/Basic.hpp rename to include/Nazara/Math/Algorithm.hpp index c100da41c..a842c1df8 100644 --- a/include/Nazara/Math/Basic.hpp +++ b/include/Nazara/Math/Algorithm.hpp @@ -1,11 +1,11 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp #pragma once -#ifndef NAZARA_BASIC_HPP -#define NAZARA_BASIC_HPP +#ifndef NAZARA_ALGORITHM_MATH_HPP +#define NAZARA_ALGORITHM_MATH_HPP #include #include @@ -22,10 +22,9 @@ template T NzApproach(T value, T objective, T increment); template constexpr T NzClamp(T value, T min, T max); -template constexpr T NzDegrees(T degrees); +template constexpr T NzFromDegrees(T degrees); +template constexpr T NzFromRadians(T radians); template constexpr T NzDegreeToRadian(T degrees); -template T NzMultiplyAdd(T x, T y, T z); -unsigned int NzIntegralPow(unsigned int base, unsigned int exponent); unsigned int NzGetNearestPowerOfTwo(unsigned int number); unsigned int NzGetNumberLength(signed char number); unsigned int NzGetNumberLength(unsigned char number); @@ -36,14 +35,17 @@ unsigned int NzGetNumberLength(unsigned long long number); unsigned int NzGetNumberLength(float number, nzUInt8 precision = NAZARA_CORE_DECIMAL_DIGITS); unsigned int NzGetNumberLength(double number, nzUInt8 precision = NAZARA_CORE_DECIMAL_DIGITS); unsigned int NzGetNumberLength(long double number, nzUInt8 precision = NAZARA_CORE_DECIMAL_DIGITS); +unsigned int NzIntegralPow(unsigned int base, unsigned int exponent); template T NzLerp(T from, T to, T2 interpolation); +template T NzMultiplyAdd(T x, T y, T z); template T NzNormalizeAngle(T angle); template bool NzNumberEquals(T a, T b, T maxDifference = std::numeric_limits::epsilon()); NzString NzNumberToString(long long number, nzUInt8 radix = 10); -template T NzRadians(T radians); template T NzRadianToDegree(T radians); long long NzStringToNumber(NzString str, nzUInt8 radix = 10, bool* ok = nullptr); +template constexpr T NzToDegrees(T angle); +template constexpr T NzToRadians(T angle); -#include +#include -#endif // NAZARA_BASIC_HPP +#endif // NAZARA_ALGORITHM_MATH_HPP diff --git a/include/Nazara/Math/Basic.inl b/include/Nazara/Math/Algorithm.inl similarity index 90% rename from include/Nazara/Math/Basic.inl rename to include/Nazara/Math/Algorithm.inl index a90c291d8..dc95dbba8 100644 --- a/include/Nazara/Math/Basic.inl +++ b/include/Nazara/Math/Algorithm.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -31,7 +31,13 @@ constexpr T NzClamp(T value, T min, T max) } template -constexpr T NzDegrees(T degrees) +constexpr T NzDegreeToRadian(T degrees) +{ + return degrees * F(M_PI/180.0); +} + +template +constexpr T NzFromDegrees(T degrees) { #if NAZARA_MATH_ANGLE_RADIAN return NzDegreeToRadian(degrees); @@ -41,49 +47,13 @@ constexpr T NzDegrees(T degrees) } template -constexpr T NzDegreeToRadian(T degrees) +constexpr T NzFromRadians(T radians) { - return degrees * F(M_PI/180.0); -} - -template -T NzMultiplyAdd(T x, T y, T z) -{ - return x*y + z; -} - -#ifdef FP_FAST_FMAF -template<> -inline float NzMultiplyAdd(float x, float y, float z) -{ - return std::fmaf(x, y, z); -} -#endif - -#ifdef FP_FAST_FMA -template<> -inline double NzMultiplyAdd(double x, double y, double z) -{ - return std::fma(x, y, z); -} -#endif - -#ifdef FP_FAST_FMAL -template<> -inline long double NzMultiplyAdd(long double x, long double y, long double z) -{ - return std::fmal(x, y, z); -} -#endif - -inline unsigned int NzIntegralPow(unsigned int base, unsigned int exponent) -{ - ///TODO: Marquer comme constexpr en C++14 - unsigned int r = 1; - for (unsigned int i = 0; i < exponent; ++i) - r *= base; - - return r; + #if NAZARA_MATH_ANGLE_RADIAN + return radians; + #else + return NzRadianToDegree(radians); + #endif } inline unsigned int NzGetNearestPowerOfTwo(unsigned int number) @@ -91,7 +61,7 @@ inline unsigned int NzGetNearestPowerOfTwo(unsigned int number) ///TODO: Marquer comme constexpr en C++14 unsigned int x = 1; // Tant que x est plus petit que n, on décale ses bits vers la gauche, ce qui revient à multiplier par deux - while(x <= number) + while (x < number) x <<= 1; return x; @@ -165,22 +135,32 @@ inline unsigned int NzGetNumberLength(unsigned long long number) inline unsigned int NzGetNumberLength(float number, nzUInt8 precision) { - // L'imprécision des flottants nécessite un cast (log10(9.99999) = 1) + // L'imprécision des flottants nécessite un cast (log10(9.99999) = 0.99999) return NzGetNumberLength(static_cast(number)) + precision + 1; // Plus un pour le point } inline unsigned int NzGetNumberLength(double number, nzUInt8 precision) { - // L'imprécision des flottants nécessite un cast (log10(9.99999) = 1) + // L'imprécision des flottants nécessite un cast (log10(9.99999) = 0.99999) return NzGetNumberLength(static_cast(number)) + precision + 1; // Plus un pour le point } inline unsigned int NzGetNumberLength(long double number, nzUInt8 precision) { - // L'imprécision des flottants nécessite un cast (log10(9.99999) = 1) + // L'imprécision des flottants nécessite un cast (log10(9.99999) = 0.99999) return NzGetNumberLength(static_cast(number)) + precision + 1; // Plus un pour le point } +inline unsigned int NzIntegralPow(unsigned int base, unsigned int exponent) +{ + ///TODO: Marquer comme constexpr en C++14 + unsigned int r = 1; + for (unsigned int i = 0; i < exponent; ++i) + r *= base; + + return r; +} + template T NzLerp(T from, T to, T2 interpolation) { @@ -192,6 +172,36 @@ T NzLerp(T from, T to, T2 interpolation) return from + interpolation*(to - from); } +template +T NzMultiplyAdd(T x, T y, T z) +{ + return x*y + z; +} + +#ifdef FP_FAST_FMAF +template<> +inline float NzMultiplyAdd(float x, float y, float z) +{ + return std::fmaf(x, y, z); +} +#endif + +#ifdef FP_FAST_FMA +template<> +inline double NzMultiplyAdd(double x, double y, double z) +{ + return std::fma(x, y, z); +} +#endif + +#ifdef FP_FAST_FMAL +template<> +inline long double NzMultiplyAdd(long double x, long double y, long double z) +{ + return std::fmal(x, y, z); +} +#endif + template T NzNormalizeAngle(T angle) { @@ -200,29 +210,20 @@ T NzNormalizeAngle(T angle) #else const T limit = F(180.0); #endif + const T twoLimit = limit*F(2.0); - ///TODO: Trouver une solution sans duplication - if (angle > F(0.0)) - { - angle += limit; - angle -= static_cast(angle / (F(2.0)*limit)) * (F(2.0)*limit); - angle -= limit; - } - else - { - angle -= limit; - angle -= static_cast(angle / (F(2.0)*limit)) * (F(2.0)*limit); - angle += limit; - } + angle = std::fmod(angle + limit, twoLimit); + if (angle < F(0.0)) + angle += twoLimit; - return angle; + return angle - limit; } template bool NzNumberEquals(T a, T b, T maxDifference) { T diff = a - b; - if (diff < 0) + if (diff < F(0.0)) diff = -diff; return diff <= maxDifference; @@ -268,16 +269,6 @@ inline NzString NzNumberToString(long long number, nzUInt8 radix) return str.Reversed(); } -template -T NzRadians(T radians) -{ - #if NAZARA_MATH_ANGLE_RADIAN - return radians; - #else - return NzRadianToDegree(radians); - #endif -} - template T NzRadianToDegree(T radians) { @@ -298,12 +289,13 @@ inline long long NzStringToNumber(NzString str, nzUInt8 radix, bool* ok) } #endif + static const char* symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + str.Simplify(); if (radix > 10) - str.ToUpper(); + str = str.ToUpper(); bool negative = str.StartsWith('-'); - static const char* symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char* digit = &str[(negative) ? 1 : 0]; unsigned long long total = 0; @@ -332,6 +324,26 @@ inline long long NzStringToNumber(NzString str, nzUInt8 radix, bool* ok) return (negative) ? -static_cast(total) : total; } +template +constexpr T NzToDegrees(T angle) +{ + #if NAZARA_MATH_ANGLE_RADIAN + return NzRadianToDegree(angle); + #else + return angle; + #endif +} + +template +constexpr T NzToRadians(T angle) +{ + #if NAZARA_MATH_ANGLE_RADIAN + return angle; + #else + return NzDegreeToRadian(angle); + #endif +} + #undef F2 #undef F diff --git a/include/Nazara/Math/BoundingVolume.hpp b/include/Nazara/Math/BoundingVolume.hpp index 999bfdd6a..1d0521d72 100644 --- a/include/Nazara/Math/BoundingVolume.hpp +++ b/include/Nazara/Math/BoundingVolume.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Math/BoundingVolume.inl b/include/Nazara/Math/BoundingVolume.inl index ed84258a1..ad8fc9415 100644 --- a/include/Nazara/Math/BoundingVolume.inl +++ b/include/Nazara/Math/BoundingVolume.inl @@ -1,10 +1,10 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include -#include +#include #include #include #include @@ -175,6 +175,7 @@ template void NzBoundingVolume::Update(const NzMatrix4& transformMatrix) { obb.Update(transformMatrix); + aabb.Set(obb(0), obb(1)); for (unsigned int i = 2; i < 8; ++i) aabb.ExtendTo(obb(i)); diff --git a/include/Nazara/Math/Box.hpp b/include/Nazara/Math/Box.hpp index 0409caffc..6b5e5d565 100644 --- a/include/Nazara/Math/Box.hpp +++ b/include/Nazara/Math/Box.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -38,7 +38,7 @@ class NzBox NzBox& ExtendTo(const NzVector3& point); NzSphere GetBoundingSphere() const; - NzVector3 GetCorner(nzCorner corner) const; + NzVector3 GetCorner(nzBoxCorner corner) const; NzVector3 GetCenter() const; NzVector3 GetLengths() const; NzVector3 GetMaximum() const; diff --git a/include/Nazara/Math/Box.inl b/include/Nazara/Math/Box.inl index e8f9b8fed..b7873d064 100644 --- a/include/Nazara/Math/Box.inl +++ b/include/Nazara/Math/Box.inl @@ -1,9 +1,9 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include +#include #include #include #include @@ -117,32 +117,32 @@ NzBox& NzBox::ExtendTo(const NzVector3& point) } template -NzVector3 NzBox::GetCorner(nzCorner corner) const +NzVector3 NzBox::GetCorner(nzBoxCorner corner) const { switch (corner) { - case nzCorner_FarLeftBottom: + case nzBoxCorner_FarLeftBottom: return NzVector3(x, y, z); - case nzCorner_FarLeftTop: + case nzBoxCorner_FarLeftTop: return NzVector3(x, y + height, z); - case nzCorner_FarRightBottom: + case nzBoxCorner_FarRightBottom: return NzVector3(x + width, y, z); - case nzCorner_FarRightTop: + case nzBoxCorner_FarRightTop: return NzVector3(x + width, y + height, z); - case nzCorner_NearLeftBottom: + case nzBoxCorner_NearLeftBottom: return NzVector3(x, y, z + depth); - case nzCorner_NearLeftTop: + case nzBoxCorner_NearLeftTop: return NzVector3(x, y + height, z + depth); - case nzCorner_NearRightBottom: + case nzBoxCorner_NearRightBottom: return NzVector3(x + width, y, z + depth); - case nzCorner_NearRightTop: + case nzBoxCorner_NearRightTop: return NzVector3(x + width, y + height, z + depth); } @@ -247,27 +247,30 @@ bool NzBox::Intersect(const NzBox& box, NzBox* intersection) const { T left = std::max(x, box.x); T right = std::min(x + width, box.x + box.width); + if (left >= right) + return false; + T top = std::max(y, box.y); T bottom = std::min(y + height, box.y + box.height); + if (top >= bottom) + return false; + T up = std::max(z, box.z); T down = std::min(z + depth, box.z + box.depth); - - if (left < right && top < bottom && up < down) - { - if (intersection) - { - intersection->x = left; - intersection->y = top; - intersection->z = up; - intersection->width = right - left; - intersection->height = bottom - top; - intersection->depth = down - up; - } - - return true; - } - else + if (up >= down) return false; + + if (intersection) + { + intersection->x = left; + intersection->y = top; + intersection->z = up; + intersection->width = right - left; + intersection->height = bottom - top; + intersection->depth = down - up; + } + + return true; } template diff --git a/include/Nazara/Math/Config.hpp b/include/Nazara/Math/Config.hpp index dd5f70041..f265fdd52 100644 --- a/include/Nazara/Math/Config.hpp +++ b/include/Nazara/Math/Config.hpp @@ -1,7 +1,7 @@ /* Nazara Engine - Mathematics module - Copyright (C) 2014 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) + Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) Rémi "overdrivr" Bèges (remi.beges@laposte.net) Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/include/Nazara/Math/Enums.hpp b/include/Nazara/Math/Enums.hpp index efa249643..496615b9e 100644 --- a/include/Nazara/Math/Enums.hpp +++ b/include/Nazara/Math/Enums.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -7,18 +7,18 @@ #ifndef NAZARA_ENUMS_MATH_HPP #define NAZARA_ENUMS_MATH_HPP -enum nzCorner +enum nzBoxCorner { - nzCorner_FarLeftBottom, - nzCorner_FarLeftTop, - nzCorner_FarRightBottom, - nzCorner_FarRightTop, - nzCorner_NearLeftBottom, - nzCorner_NearLeftTop, - nzCorner_NearRightBottom, - nzCorner_NearRightTop, + nzBoxCorner_FarLeftBottom, + nzBoxCorner_FarLeftTop, + nzBoxCorner_FarRightBottom, + nzBoxCorner_FarRightTop, + nzBoxCorner_NearLeftBottom, + nzBoxCorner_NearLeftTop, + nzBoxCorner_NearRightBottom, + nzBoxCorner_NearRightTop, - nzCorner_Max = nzCorner_NearRightTop + nzBoxCorner_Max = nzBoxCorner_NearRightTop }; enum nzExtend @@ -51,4 +51,14 @@ enum nzIntersectionSide nzIntersectionSide_Max = nzIntersectionSide_Outside }; +enum nzRectCorner +{ + nzRectCorner_LeftBottom, + nzRectCorner_LeftTop, + nzRectCorner_RightBottom, + nzRectCorner_RightTop, + + nzRectCorner_Max = nzRectCorner_RightTop +}; + #endif // NAZARA_ENUMS_MATH_HPP diff --git a/include/Nazara/Math/EulerAngles.hpp b/include/Nazara/Math/EulerAngles.hpp index 6b6cabc2d..41030d7be 100644 --- a/include/Nazara/Math/EulerAngles.hpp +++ b/include/Nazara/Math/EulerAngles.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -43,8 +43,8 @@ template class NzEulerAngles /*NzEulerAngles operator*(const NzEulerAngles& angles) const; NzEulerAngles operator/(const NzEulerAngles& angles) const;*/ - NzEulerAngles operator+=(const NzEulerAngles& angles); - NzEulerAngles operator-=(const NzEulerAngles& angles); + NzEulerAngles& operator+=(const NzEulerAngles& angles); + NzEulerAngles& operator-=(const NzEulerAngles& angles); /*NzEulerAngles operator*=(const NzEulerAngles& angles); NzEulerAngles operator/=(const NzEulerAngles& angles);*/ diff --git a/include/Nazara/Math/EulerAngles.inl b/include/Nazara/Math/EulerAngles.inl index a085d99cf..8e29a40d9 100644 --- a/include/Nazara/Math/EulerAngles.inl +++ b/include/Nazara/Math/EulerAngles.inl @@ -1,9 +1,9 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include +#include #include #include #include @@ -123,7 +123,7 @@ NzEulerAngles NzEulerAngles::operator-(const NzEulerAngles& angles) const } template -NzEulerAngles NzEulerAngles::operator+=(const NzEulerAngles& angles) +NzEulerAngles& NzEulerAngles::operator+=(const NzEulerAngles& angles) { pitch += angles.pitch; yaw += angles.yaw; @@ -133,7 +133,7 @@ NzEulerAngles NzEulerAngles::operator+=(const NzEulerAngles& angles) } template -NzEulerAngles NzEulerAngles::operator-=(const NzEulerAngles& angles) +NzEulerAngles& NzEulerAngles::operator-=(const NzEulerAngles& angles) { pitch -= angles.pitch; yaw -= angles.yaw; diff --git a/include/Nazara/Math/Frustum.hpp b/include/Nazara/Math/Frustum.hpp index e5de19b50..e28949f46 100644 --- a/include/Nazara/Math/Frustum.hpp +++ b/include/Nazara/Math/Frustum.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -37,7 +37,7 @@ class NzFrustum NzFrustum& Extract(const NzMatrix4& clipMatrix); NzFrustum& Extract(const NzMatrix4& view, const NzMatrix4& projection); - const NzVector3& GetCorner(nzCorner corner) const; + const NzVector3& GetCorner(nzBoxCorner corner) const; const NzPlane& GetPlane(nzFrustumPlane plane) const; nzIntersectionSide Intersect(const NzBoundingVolume& volume) const; @@ -52,7 +52,7 @@ class NzFrustum NzString ToString() const; private: - NzVector3 m_corners[nzCorner_Max+1]; + NzVector3 m_corners[nzBoxCorner_Max+1]; NzPlane m_planes[nzFrustumPlane_Max+1]; }; diff --git a/include/Nazara/Math/Frustum.inl b/include/Nazara/Math/Frustum.inl index 8541a34f1..fbdbdbdcc 100644 --- a/include/Nazara/Math/Frustum.inl +++ b/include/Nazara/Math/Frustum.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -7,7 +7,7 @@ // http://www.lighthouse3d.com/tutorials/view-frustum-culling/ #include -#include +#include #include #include @@ -44,23 +44,23 @@ NzFrustum& NzFrustum::Build(T angle, T ratio, T zNear, T zFar, const NzVec NzVector3 fc = eye + f * zFar; // Calcul du frustum - m_corners[nzCorner_FarLeftBottom] = fc - u*farH - s*farW; - m_corners[nzCorner_FarLeftTop] = fc + u*farH - s*farW; - m_corners[nzCorner_FarRightTop] = fc + u*farH + s*farW; - m_corners[nzCorner_FarRightBottom] = fc - u*farH + s*farW; + m_corners[nzBoxCorner_FarLeftBottom] = fc - u*farH - s*farW; + m_corners[nzBoxCorner_FarLeftTop] = fc + u*farH - s*farW; + m_corners[nzBoxCorner_FarRightTop] = fc + u*farH + s*farW; + m_corners[nzBoxCorner_FarRightBottom] = fc - u*farH + s*farW; - m_corners[nzCorner_NearLeftBottom] = nc - u*nearH - s*nearW; - m_corners[nzCorner_NearLeftTop] = nc + u*nearH - s*nearW; - m_corners[nzCorner_NearRightTop] = nc + u*nearH + s*nearW; - m_corners[nzCorner_NearRightBottom] = nc - u*nearH + s*nearW; + m_corners[nzBoxCorner_NearLeftBottom] = nc - u*nearH - s*nearW; + m_corners[nzBoxCorner_NearLeftTop] = nc + u*nearH - s*nearW; + m_corners[nzBoxCorner_NearRightTop] = nc + u*nearH + s*nearW; + m_corners[nzBoxCorner_NearRightBottom] = nc - u*nearH + s*nearW; // Construction des plans du frustum - m_planes[nzFrustumPlane_Bottom].Set(m_corners[nzCorner_NearLeftBottom], m_corners[nzCorner_NearRightBottom], m_corners[nzCorner_FarRightBottom]); - m_planes[nzFrustumPlane_Far].Set(m_corners[nzCorner_FarRightTop], m_corners[nzCorner_FarLeftTop], m_corners[nzCorner_FarLeftBottom]); - m_planes[nzFrustumPlane_Left].Set(m_corners[nzCorner_NearLeftTop], m_corners[nzCorner_NearLeftBottom], m_corners[nzCorner_FarLeftBottom]); - m_planes[nzFrustumPlane_Near].Set(m_corners[nzCorner_NearLeftTop], m_corners[nzCorner_NearRightTop], m_corners[nzCorner_NearRightBottom]); - m_planes[nzFrustumPlane_Right].Set(m_corners[nzCorner_NearRightBottom], m_corners[nzCorner_NearRightTop], m_corners[nzCorner_FarRightBottom]); - m_planes[nzFrustumPlane_Top].Set(m_corners[nzCorner_NearRightTop], m_corners[nzCorner_NearLeftTop], m_corners[nzCorner_FarLeftTop]); + m_planes[nzFrustumPlane_Bottom].Set(m_corners[nzBoxCorner_NearLeftBottom], m_corners[nzBoxCorner_NearRightBottom], m_corners[nzBoxCorner_FarRightBottom]); + m_planes[nzFrustumPlane_Far].Set(m_corners[nzBoxCorner_FarRightTop], m_corners[nzBoxCorner_FarLeftTop], m_corners[nzBoxCorner_FarLeftBottom]); + m_planes[nzFrustumPlane_Left].Set(m_corners[nzBoxCorner_NearLeftTop], m_corners[nzBoxCorner_NearLeftBottom], m_corners[nzBoxCorner_FarLeftBottom]); + m_planes[nzFrustumPlane_Near].Set(m_corners[nzBoxCorner_NearLeftTop], m_corners[nzBoxCorner_NearRightTop], m_corners[nzBoxCorner_NearRightBottom]); + m_planes[nzFrustumPlane_Right].Set(m_corners[nzBoxCorner_NearRightBottom], m_corners[nzBoxCorner_NearRightTop], m_corners[nzBoxCorner_FarRightBottom]); + m_planes[nzFrustumPlane_Top].Set(m_corners[nzBoxCorner_NearRightTop], m_corners[nzBoxCorner_NearLeftTop], m_corners[nzBoxCorner_FarLeftTop]); return *this; } @@ -272,56 +272,56 @@ NzFrustum& NzFrustum::Extract(const NzMatrix4& clipMatrix) corner = invClipMatrix.Transform(corner); corner.Normalize(); - m_corners[nzCorner_FarLeftBottom] = NzVector3(corner.x, corner.y, corner.z); + m_corners[nzBoxCorner_FarLeftBottom] = NzVector3(corner.x, corner.y, corner.z); // FarLeftTop corner.Set(F(-1.0), F(1.0), F(1.0)); corner = invClipMatrix.Transform(corner); corner.Normalize(); - m_corners[nzCorner_FarLeftTop] = NzVector3(corner.x, corner.y, corner.z); + m_corners[nzBoxCorner_FarLeftTop] = NzVector3(corner.x, corner.y, corner.z); // FarRightBottom corner.Set(F(1.0), F(-1.0), F(1.0)); corner = invClipMatrix.Transform(corner); corner.Normalize(); - m_corners[nzCorner_FarRightBottom] = NzVector3(corner.x, corner.y, corner.z); + m_corners[nzBoxCorner_FarRightBottom] = NzVector3(corner.x, corner.y, corner.z); // FarRightTop corner.Set(F(1.0), F(1.0), F(1.0)); corner = invClipMatrix.Transform(corner); corner.Normalize(); - m_corners[nzCorner_FarRightTop] = NzVector3(corner.x, corner.y, corner.z); + m_corners[nzBoxCorner_FarRightTop] = NzVector3(corner.x, corner.y, corner.z); // NearLeftBottom corner.Set(F(-1.0), F(-1.0), F(0.0)); corner = invClipMatrix.Transform(corner); corner.Normalize(); - m_corners[nzCorner_NearLeftBottom] = NzVector3(corner.x, corner.y, corner.z); + m_corners[nzBoxCorner_NearLeftBottom] = NzVector3(corner.x, corner.y, corner.z); // NearLeftTop corner.Set(F(-1.0), F(1.0), F(0.0)); corner = invClipMatrix.Transform(corner); corner.Normalize(); - m_corners[nzCorner_NearLeftTop] = NzVector3(corner.x, corner.y, corner.z); + m_corners[nzBoxCorner_NearLeftTop] = NzVector3(corner.x, corner.y, corner.z); // NearRightBottom corner.Set(F(1.0), F(-1.0), F(0.0)); corner = invClipMatrix.Transform(corner); corner.Normalize(); - m_corners[nzCorner_NearRightBottom] = NzVector3(corner.x, corner.y, corner.z); + m_corners[nzBoxCorner_NearRightBottom] = NzVector3(corner.x, corner.y, corner.z); // NearRightTop corner.Set(F(1.0), F(1.0), F(0.0)); corner = invClipMatrix.Transform(corner); corner.Normalize(); - m_corners[nzCorner_NearRightTop] = NzVector3(corner.x, corner.y, corner.z); + m_corners[nzBoxCorner_NearRightTop] = NzVector3(corner.x, corner.y, corner.z); } else NazaraWarning("Clip matrix is not invertible, failed to compute frustum corners"); @@ -339,10 +339,10 @@ NzFrustum& NzFrustum::Extract(const NzMatrix4& view, const NzMatrix4 } template -const NzVector3& NzFrustum::GetCorner(nzCorner corner) const +const NzVector3& NzFrustum::GetCorner(nzBoxCorner corner) const { #ifdef NAZARA_DEBUG - if (corner > nzCorner_Max) + if (corner > nzBoxCorner_Max) { NazaraError("Corner not handled (0x" + NzString::Number(corner, 16) + ')'); @@ -481,7 +481,7 @@ template template NzFrustum& NzFrustum::Set(const NzFrustum& frustum) { - for (unsigned int i = 0; i <= nzCorner_Max; ++i) + for (unsigned int i = 0; i <= nzBoxCorner_Max; ++i) m_corners[i].Set(frustum.m_corners[i]); for (unsigned int i = 0; i <= nzFrustumPlane_Max; ++i) diff --git a/include/Nazara/Math/Matrix4.hpp b/include/Nazara/Math/Matrix4.hpp index 2def3428d..ac142f4f1 100644 --- a/include/Nazara/Math/Matrix4.hpp +++ b/include/Nazara/Math/Matrix4.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -7,6 +7,8 @@ #ifndef NAZARA_MATRIX4_HPP #define NAZARA_MATRIX4_HPP +///FIXME: Matrices column-major, difficile de bosser avec (Tout passer en row-major et transposer dans les shaders ?) + #include #include @@ -38,12 +40,14 @@ class NzMatrix4 NzMatrix4& Concatenate(const NzMatrix4& matrix); NzMatrix4& ConcatenateAffine(const NzMatrix4& matrix); + NzVector4 GetColumn(unsigned int column) const; T GetDeterminant() const; T GetDeterminantAffine() const; bool GetInverse(NzMatrix4* dest) const; bool GetInverseAffine(NzMatrix4* dest) const; NzQuaternion GetRotation() const; //NzMatrix3 GetRotationMatrix() const; + NzVector4 GetRow(unsigned int row) const; NzVector3 GetScale() const; NzVector3 GetTranslation() const; void GetTransposed(NzMatrix4* dest) const; diff --git a/include/Nazara/Math/Matrix4.inl b/include/Nazara/Math/Matrix4.inl index 989302bd1..d689879d0 100644 --- a/include/Nazara/Math/Matrix4.inl +++ b/include/Nazara/Math/Matrix4.inl @@ -1,10 +1,10 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include -#include +#include #include #include #include @@ -144,6 +144,25 @@ NzMatrix4& NzMatrix4::ConcatenateAffine(const NzMatrix4& matrix) F(1.0)); } +template +NzVector4 NzMatrix4::GetColumn(unsigned int column) const +{ + ///FIXME: Est-ce une bonne idée de gérer la matrice de cette façon ? + + #if NAZARA_MATH_SAFE + if (column > 3) + { + NzStringStream ss; + ss << "Row out of range: (" << column << ") > 3"; + + throw std::out_of_range(ss.ToString()); + } + #endif + + T* ptr = (&m11) + column*4; + return NzVector4(ptr); +} + template T NzMatrix4::GetDeterminant() const { @@ -444,6 +463,25 @@ NzQuaternion NzMatrix4::GetRotation() const return quat; } +template +NzVector4 NzMatrix4::GetRow(unsigned int row) const +{ + ///FIXME: Est-ce une bonne idée de gérer la matrice de cette façon ? + + #if NAZARA_MATH_SAFE + if (row > 3) + { + NzStringStream ss; + ss << "Column out of range: (" << row << ") > 3"; + + throw std::out_of_range(ss.ToString()); + } + #endif + + T* ptr = &m11; + return NzVector4(ptr[row], ptr[row+4], ptr[row+8], ptr[row+12]); +} + template NzVector3 NzMatrix4::GetScale() const { @@ -524,9 +562,9 @@ template bool NzMatrix4::IsIdentity() const { return (NzNumberEquals(m11, F(1.0)) && NzNumberEquals(m12, F(0.0)) && NzNumberEquals(m13, F(0.0)) && NzNumberEquals(m14, F(0.0)) && - NzNumberEquals(m11, F(0.0)) && NzNumberEquals(m12, F(1.0)) && NzNumberEquals(m13, F(0.0)) && NzNumberEquals(m14, F(0.0)) && - NzNumberEquals(m11, F(0.0)) && NzNumberEquals(m12, F(0.0)) && NzNumberEquals(m13, F(1.0)) && NzNumberEquals(m14, F(0.0)) && - NzNumberEquals(m11, F(0.0)) && NzNumberEquals(m12, F(0.0)) && NzNumberEquals(m13, F(0.0)) && NzNumberEquals(m14, F(1.0))); + NzNumberEquals(m21, F(0.0)) && NzNumberEquals(m22, F(1.0)) && NzNumberEquals(m23, F(0.0)) && NzNumberEquals(m24, F(0.0)) && + NzNumberEquals(m31, F(0.0)) && NzNumberEquals(m32, F(0.0)) && NzNumberEquals(m33, F(1.0)) && NzNumberEquals(m34, F(0.0)) && + NzNumberEquals(m41, F(0.0)) && NzNumberEquals(m42, F(0.0)) && NzNumberEquals(m43, F(0.0)) && NzNumberEquals(m44, F(1.0))); } template @@ -640,8 +678,6 @@ NzMatrix4& NzMatrix4::MakeTransform(const NzVector3& translation, const m34 = F(0.0); m44 = F(1.0); - // Pas besoin de mettre à jour l'identité (Déjà fait par Set*) - return *this; } @@ -818,7 +854,6 @@ NzVector4 NzMatrix4::Transform(const NzVector4& vector) const template NzMatrix4& NzMatrix4::Transpose() { - // N'affecte pas l'identité (La transposée d'une matrice identité est la matrice identité elle-même) std::swap(m12, m21); std::swap(m13, m31); std::swap(m14, m41); diff --git a/include/Nazara/Math/OrientedBox.hpp b/include/Nazara/Math/OrientedBox.hpp index 9f5b711b6..1631099aa 100644 --- a/include/Nazara/Math/OrientedBox.hpp +++ b/include/Nazara/Math/OrientedBox.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -24,7 +24,7 @@ class NzOrientedBox NzOrientedBox(const NzOrientedBox& orientedBox) = default; ~NzOrientedBox() = default; - const NzVector3& GetCorner(nzCorner corner) const; + const NzVector3& GetCorner(nzBoxCorner corner) const; bool IsValid() const; @@ -59,7 +59,7 @@ class NzOrientedBox NzBox localBox; private: - NzVector3 m_corners[nzCorner_Max+1]; // Ne peuvent pas être modifiés directement + NzVector3 m_corners[nzBoxCorner_Max+1]; // Ne peuvent pas être modifiés directement }; template diff --git a/include/Nazara/Math/OrientedBox.inl b/include/Nazara/Math/OrientedBox.inl index 33a131c72..c83aee440 100644 --- a/include/Nazara/Math/OrientedBox.inl +++ b/include/Nazara/Math/OrientedBox.inl @@ -1,9 +1,9 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include +#include #include #include @@ -37,10 +37,10 @@ NzOrientedBox::NzOrientedBox(const NzOrientedBox& orientedBox) } template -const NzVector3& NzOrientedBox::GetCorner(nzCorner corner) const +const NzVector3& NzOrientedBox::GetCorner(nzBoxCorner corner) const { #ifdef NAZARA_DEBUG - if (corner > nzCorner_Max) + if (corner > nzBoxCorner_Max) { NazaraError("Corner not handled (0x" + NzString::Number(corner, 16) + ')'); @@ -102,7 +102,7 @@ template template NzOrientedBox& NzOrientedBox::Set(const NzOrientedBox& orientedBox) { - for (unsigned int i = 0; i <= nzCorner_Max; ++i) + for (unsigned int i = 0; i <= nzBoxCorner_Max; ++i) m_corners[i].Set(orientedBox.m_corners[i]); localBox = orientedBox.localBox; @@ -115,21 +115,21 @@ NzString NzOrientedBox::ToString() const { NzStringStream ss; - return ss << "OrientedBox(FLB: " << m_corners[nzCorner_FarLeftBottom].ToString() << "\n" - << " FLT: " << m_corners[nzCorner_FarLeftTop].ToString() << "\n" - << " FRB: " << m_corners[nzCorner_FarRightBottom].ToString() << "\n" - << " FRT: " << m_corners[nzCorner_FarRightTop].ToString() << "\n" - << " NLB: " << m_corners[nzCorner_NearLeftBottom].ToString() << "\n" - << " NLT: " << m_corners[nzCorner_NearLeftTop].ToString() << "\n" - << " NRB: " << m_corners[nzCorner_NearRightBottom].ToString() << "\n" - << " NRT: " << m_corners[nzCorner_NearRightTop].ToString() << ")\n"; + return ss << "OrientedBox(FLB: " << m_corners[nzBoxCorner_FarLeftBottom].ToString() << "\n" + << " FLT: " << m_corners[nzBoxCorner_FarLeftTop].ToString() << "\n" + << " FRB: " << m_corners[nzBoxCorner_FarRightBottom].ToString() << "\n" + << " FRT: " << m_corners[nzBoxCorner_FarRightTop].ToString() << "\n" + << " NLB: " << m_corners[nzBoxCorner_NearLeftBottom].ToString() << "\n" + << " NLT: " << m_corners[nzBoxCorner_NearLeftTop].ToString() << "\n" + << " NRB: " << m_corners[nzBoxCorner_NearRightBottom].ToString() << "\n" + << " NRT: " << m_corners[nzBoxCorner_NearRightTop].ToString() << ")\n"; } template void NzOrientedBox::Update(const NzMatrix4& transformMatrix) { - for (unsigned int i = 0; i <= nzCorner_Max; ++i) - m_corners[i] = transformMatrix.Transform(localBox.GetCorner(static_cast(i))); + for (unsigned int i = 0; i <= nzBoxCorner_Max; ++i) + m_corners[i] = transformMatrix.Transform(localBox.GetCorner(static_cast(i))); } template @@ -148,7 +148,7 @@ template NzVector3& NzOrientedBox::operator()(unsigned int i) { #if NAZARA_MATH_SAFE - if (i > nzCorner_Max) + if (i > nzBoxCorner_Max) { NzStringStream ss; ss << "Index out of range: (" << i << " >= 3)"; @@ -165,7 +165,7 @@ template NzVector3 NzOrientedBox::operator()(unsigned int i) const { #if NAZARA_MATH_SAFE - if (i > nzCorner_Max) + if (i > nzBoxCorner_Max) { NzStringStream ss; ss << "Index out of range: (" << i << " >= 3)"; diff --git a/include/Nazara/Math/Plane.hpp b/include/Nazara/Math/Plane.hpp index b816ae195..f2c428bde 100644 --- a/include/Nazara/Math/Plane.hpp +++ b/include/Nazara/Math/Plane.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Math/Plane.inl b/include/Nazara/Math/Plane.inl index 4e7c81029..10ece793d 100644 --- a/include/Nazara/Math/Plane.inl +++ b/include/Nazara/Math/Plane.inl @@ -1,9 +1,9 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include +#include #include #include diff --git a/include/Nazara/Math/Quaternion.hpp b/include/Nazara/Math/Quaternion.hpp index 4521ea909..03b27c02a 100644 --- a/include/Nazara/Math/Quaternion.hpp +++ b/include/Nazara/Math/Quaternion.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges - Jérôme Leclercq +// Copyright (C) 2015 Rémi Bèges - Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -76,6 +76,7 @@ template class NzQuaternion static NzQuaternion Identity(); static NzQuaternion Lerp(const NzQuaternion& from, const NzQuaternion& to, T interpolation); + static NzQuaternion Normalize(const NzQuaternion& quat, T* length = nullptr); static NzQuaternion RotationBetween(const NzVector3& from, const NzVector3& to); static NzQuaternion Slerp(const NzQuaternion& from, const NzQuaternion& to, T interpolation); static NzQuaternion Zero(); diff --git a/include/Nazara/Math/Quaternion.inl b/include/Nazara/Math/Quaternion.inl index 3e27982f6..9d498b5c6 100644 --- a/include/Nazara/Math/Quaternion.inl +++ b/include/Nazara/Math/Quaternion.inl @@ -1,9 +1,9 @@ -// Copyright (C) 2014 Rémi Bèges - Jérôme Leclercq +// Copyright (C) 2015 Rémi Bèges - Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include +#include #include #include #include @@ -265,14 +265,14 @@ NzEulerAngles NzQuaternion::ToEulerAngles() const T test = x*y + z*w; if (test > F(0.499)) // singularity at north pole - return NzEulerAngles(NzDegrees(F(90.0)), NzRadians(F(2.0) * std::atan2(x, w)), F(0.0)); + return NzEulerAngles(NzFromDegrees(F(90.0)), NzFromRadians(F(2.0) * std::atan2(x, w)), F(0.0)); if (test < F(-0.499)) - return NzEulerAngles(NzDegrees(F(-90.0)), NzRadians(F(-2.0) * std::atan2(x, w)), F(0.0)); + return NzEulerAngles(NzFromDegrees(F(-90.0)), NzFromRadians(F(-2.0) * std::atan2(x, w)), F(0.0)); - return NzEulerAngles(NzRadians(std::atan2(F(2.0)*x*w - F(2.0)*y*z, F(1.0) - F(2.0)*x* - F(2.0)*z*z)), - NzRadians(std::atan2(F(2.0)*y*w - F(2.0)*x*z, F(1.0) - F(2.0)*y*y - F(2.0)*z*z)), - NzRadians(std::asin(F(2.0)*test))); + return NzEulerAngles(NzFromRadians(std::atan2(F(2.0)*x*w - F(2.0)*y*z, F(1.0) - F(2.0)*x* - F(2.0)*z*z)), + NzFromRadians(std::atan2(F(2.0)*y*w - F(2.0)*x*z, F(1.0) - F(2.0)*y*y - F(2.0)*z*z)), + NzFromRadians(std::asin(F(2.0)*test))); } template @@ -408,6 +408,12 @@ NzQuaternion NzQuaternion::Lerp(const NzQuaternion& from, const NzQuaterni return interpolated; } +template +NzQuaternion NzQuaternion::Normalize(const NzQuaternion& quat, T* length) +{ + return quat.GetNormal(length); +} + template NzQuaternion NzQuaternion::RotationBetween(const NzVector3& from, const NzVector3& to) { diff --git a/include/Nazara/Math/Ray.hpp b/include/Nazara/Math/Ray.hpp index d47663e88..e1cc40829 100644 --- a/include/Nazara/Math/Ray.hpp +++ b/include/Nazara/Math/Ray.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Gawaboumga (https://github.com/Gawaboumga) - Jérôme Leclercq +// Copyright (C) 2015 Gawaboumga (https://github.com/Gawaboumga) - Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Math/Ray.inl b/include/Nazara/Math/Ray.inl index ec4802bca..6ee22ad4e 100644 --- a/include/Nazara/Math/Ray.inl +++ b/include/Nazara/Math/Ray.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Gawaboumga (https://github.com/Gawaboumga) - Jérôme Leclercq +// Copyright (C) 2015 Gawaboumga (https://github.com/Gawaboumga) - Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -204,9 +204,9 @@ bool NzRay::Intersect(const NzBox& box, const NzMatrix4& transform, T* template bool NzRay::Intersect(const NzOrientedBox& orientedBox, T* closestHit, T* farthestHit) const { - NzVector3 width = (orientedBox.GetCorner(nzCorner_NearLeftBottom) - orientedBox.GetCorner(nzCorner_FarLeftBottom)).Normalize(); - NzVector3 height = (orientedBox.GetCorner(nzCorner_FarLeftTop) - orientedBox.GetCorner(nzCorner_FarLeftBottom)).Normalize(); - NzVector3 depth = (orientedBox.GetCorner(nzCorner_FarRightBottom) - orientedBox.GetCorner(nzCorner_FarLeftBottom)).Normalize(); + NzVector3 width = (orientedBox.GetCorner(nzBoxCorner_NearLeftBottom) - orientedBox.GetCorner(nzBoxCorner_FarLeftBottom)).Normalize(); + NzVector3 height = (orientedBox.GetCorner(nzBoxCorner_FarLeftTop) - orientedBox.GetCorner(nzBoxCorner_FarLeftBottom)).Normalize(); + NzVector3 depth = (orientedBox.GetCorner(nzBoxCorner_FarRightBottom) - orientedBox.GetCorner(nzBoxCorner_FarLeftBottom)).Normalize(); // Construction de la matrice de transformation de l'OBB NzMatrix4 matrix(width.x, height.x, depth.x, F(0.0), @@ -225,7 +225,7 @@ bool NzRay::Intersect(const NzPlane& plane, T* hit) const if (NzNumberEquals(divisor, F(0.0))) return false; // perpendicular - T lambda = -(plane.normal.DotProduct(origin) - plane.distance) / divisor; // The plane is ax+by+cz=d + T lambda = -(plane.normal.DotProduct(origin) + plane.distance) / divisor; // The plane is ax+by+cz=d if (lambda < F(0.0)) return false; // Le plan est derrière le rayon diff --git a/include/Nazara/Math/Rect.hpp b/include/Nazara/Math/Rect.hpp index a91c7b0e9..cb93b2167 100644 --- a/include/Nazara/Math/Rect.hpp +++ b/include/Nazara/Math/Rect.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -8,6 +8,7 @@ #define NAZARA_RECT_HPP #include +#include #include template @@ -33,6 +34,7 @@ class NzRect NzRect& ExtendTo(const NzRect& rect); NzVector2 GetCenter() const; + NzVector2 GetCorner(nzRectCorner corner) const; NzVector2 GetLengths() const; NzVector2 GetMaximum() const; NzVector2 GetMinimum() const; diff --git a/include/Nazara/Math/Rect.inl b/include/Nazara/Math/Rect.inl index ab35b30c5..9782ac69e 100644 --- a/include/Nazara/Math/Rect.inl +++ b/include/Nazara/Math/Rect.inl @@ -1,9 +1,9 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include +#include #include #include #include @@ -109,6 +109,28 @@ NzVector2 NzRect::GetCenter() const return GetPosition() + GetLengths() / F(2.0); } +template +NzVector2 NzRect::GetCorner(nzRectCorner corner) const +{ + switch (corner) + { + case nzRectCorner_LeftBottom: + return NzVector2(x, y + height); + + case nzRectCorner_LeftTop: + return NzVector2(x, y); + + case nzRectCorner_RightBottom: + return NzVector2(x + width, y + height); + + case nzRectCorner_RightTop: + return NzVector2(x + width, y); + } + + NazaraError("Corner not handled (0x" + NzString::Number(corner, 16) + ')'); + return NzVector2(); +} + template NzVector2 NzRect::GetLengths() const { @@ -166,24 +188,24 @@ template bool NzRect::Intersect(const NzRect& rect, NzRect* intersection) const { T left = std::max(x, rect.x); - T right = std::min(x+width, rect.x+rect.width); - T top = std::max(y, rect.y); - T bottom = std::min(y+height, rect.y+rect.height); - - if (left < right && top < bottom) - { - if (intersection) - { - intersection->x = left; - intersection->y = top; - intersection->width = right-left; - intersection->height = bottom-top; - } - - return true; - } - else + T right = std::min(x + width, rect.x + rect.width); + if (left >= right) return false; + + T top = std::max(y, rect.y); + T bottom = std::min(y + height, rect.y + rect.height); + if (top >= bottom) + return false; + + if (intersection) + { + intersection->x = left; + intersection->y = top; + intersection->width = right - left; + intersection->height = bottom - top; + } + + return true; } template diff --git a/include/Nazara/Math/Sphere.hpp b/include/Nazara/Math/Sphere.hpp index 64378a949..f452ddf4e 100644 --- a/include/Nazara/Math/Sphere.hpp +++ b/include/Nazara/Math/Sphere.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Math/Sphere.inl b/include/Nazara/Math/Sphere.inl index b9a97eb43..f8ece724c 100644 --- a/include/Nazara/Math/Sphere.inl +++ b/include/Nazara/Math/Sphere.inl @@ -1,9 +1,9 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include +#include #include #include #include diff --git a/include/Nazara/Math/Vector2.hpp b/include/Nazara/Math/Vector2.hpp index 357babaa5..c42700de5 100644 --- a/include/Nazara/Math/Vector2.hpp +++ b/include/Nazara/Math/Vector2.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,6 +9,9 @@ #include +template class NzVector3; +template class NzVector4; + template class NzVector2 { @@ -19,6 +22,8 @@ class NzVector2 NzVector2(const T vec[2]); template explicit NzVector2(const NzVector2& vec); NzVector2(const NzVector2& vec) = default; + explicit NzVector2(const NzVector3& vec); + explicit NzVector2(const NzVector4& vec); ~NzVector2() = default; T AbsDotProduct(const NzVector2& vec) const; @@ -48,6 +53,8 @@ class NzVector2 NzVector2& Set(T scale); NzVector2& Set(const T vec[2]); NzVector2& Set(const NzVector2& vec); + NzVector2& Set(const NzVector3& vec); + NzVector2& Set(const NzVector4& vec); template NzVector2& Set(const NzVector2& vec); T SquaredDistance(const NzVector2& vec) const; diff --git a/include/Nazara/Math/Vector2.inl b/include/Nazara/Math/Vector2.inl index b457f0ad0..05a7ae792 100644 --- a/include/Nazara/Math/Vector2.inl +++ b/include/Nazara/Math/Vector2.inl @@ -1,9 +1,9 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include +#include #include #include #include @@ -36,28 +36,28 @@ NzVector2::NzVector2(const NzVector2& vec) Set(vec); } +template +NzVector2::NzVector2(const NzVector3& vec) +{ + Set(vec); +} + +template +NzVector2::NzVector2(const NzVector4& vec) +{ + Set(vec); +} + template T NzVector2::AbsDotProduct(const NzVector2& vec) const { - return std::fabs(x * vec.x) + std::fabs(y * vec.y); -} - -template<> -inline int NzVector2::AbsDotProduct(const NzVector2& vec) const -{ - return std::labs(x * vec.x) + std::labs(y * vec.y); -} - -template<> -inline unsigned int NzVector2::AbsDotProduct(const NzVector2& vec) const -{ - return std::labs(x * vec.x) + std::labs(y * vec.y); + return std::abs(x * vec.x) + std::abs(y * vec.y); } template T NzVector2::AngleBetween(const NzVector2& vec) const { - return NzRadians(std::atan2(vec.y, vec.x) - std::atan2(y, x)); + return NzFromRadians(std::atan2(vec.y, vec.x) - std::atan2(y, x)); } template @@ -150,11 +150,13 @@ NzVector2& NzVector2::Minimize(const NzVector2& vec) template NzVector2& NzVector2::Normalize(T* length) { - T norm = std::sqrt(GetSquaredLength()); - T invNorm = F(1.0) / norm; - - x *= invNorm; - y *= invNorm; + T norm = GetLength(); + if (norm > F(0.0)) + { + T invNorm = F(1.0) / norm; + x *= invNorm; + y *= invNorm; + } if (length) *length = norm; @@ -206,6 +208,24 @@ NzVector2& NzVector2::Set(const NzVector2& vec) return *this; } +template +NzVector2& NzVector2::Set(const NzVector3& vec) +{ + x = vec.x; + y = vec.y; + + return *this; +} + +template +NzVector2& NzVector2::Set(const NzVector4& vec) +{ + x = vec.x; + y = vec.y; + + return *this; +} + template T NzVector2::SquaredDistance(const NzVector2& vec) const { diff --git a/include/Nazara/Math/Vector3.hpp b/include/Nazara/Math/Vector3.hpp index 875662270..14cd41b0a 100644 --- a/include/Nazara/Math/Vector3.hpp +++ b/include/Nazara/Math/Vector3.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges - Jérôme Leclercq +// Copyright (C) 2015 Rémi Bèges - Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -8,18 +8,23 @@ #define NAZARA_VECTOR3_HPP #include -#include -template class NzVector3 +template class NzVector2; +template class NzVector4; + +template +class NzVector3 { public: NzVector3() = default; NzVector3(T X, T Y, T Z); + NzVector3(T X, const NzVector2& vec); explicit NzVector3(T scale); NzVector3(const T vec[3]); NzVector3(const NzVector2& vec, T Z = 0.0); template explicit NzVector3(const NzVector3& vec); NzVector3(const NzVector3& vec) = default; + explicit NzVector3(const NzVector4& vec); ~NzVector3() = default; T AbsDotProduct(const NzVector3& vec) const; @@ -56,11 +61,13 @@ template class NzVector3 NzVector3& Normalize(T* length = nullptr); NzVector3& Set(T X, T Y, T Z); + NzVector3& Set(T X, const NzVector2& vec); NzVector3& Set(T scale); NzVector3& Set(const T vec[3]); NzVector3& Set(const NzVector2& vec, T Z = 0.0); NzVector3& Set(const NzVector3& vec); template NzVector3& Set(const NzVector3& vec); + NzVector3& Set(const NzVector4& vec); T SquaredDistance(const NzVector3& vec) const; diff --git a/include/Nazara/Math/Vector3.inl b/include/Nazara/Math/Vector3.inl index 2ca0c5051..a2f0ed35c 100644 --- a/include/Nazara/Math/Vector3.inl +++ b/include/Nazara/Math/Vector3.inl @@ -1,9 +1,9 @@ -// Copyright (C) 2014 Rémi Bèges - Jérôme Leclercq +// Copyright (C) 2015 Rémi Bèges - Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include +#include #include #include #include @@ -17,6 +17,12 @@ NzVector3::NzVector3(T X, T Y, T Z) Set(X, Y, Z); } +template +NzVector3::NzVector3(T X, const NzVector2& vec) +{ + Set(X, vec); +} + template NzVector3::NzVector3(T scale) { @@ -42,22 +48,16 @@ NzVector3::NzVector3(const NzVector3& vec) Set(vec); } +template +NzVector3::NzVector3(const NzVector4& vec) +{ + Set(vec); +} + template T NzVector3::AbsDotProduct(const NzVector3& vec) const { - return std::fabs(x * vec.x) + std::fabs(y * vec.y) + std::fabs(z * vec.z); -} - -template<> -inline int NzVector3::AbsDotProduct(const NzVector3& vec) const -{ - return std::labs(x * vec.x) + std::labs(y * vec.y) + std::labs(z * vec.z); -} - -template<> -inline unsigned int NzVector3::AbsDotProduct(const NzVector3& vec) const -{ - return std::labs(x * vec.x) + std::labs(y * vec.y) + std::labs(z * vec.z); + return std::abs(x * vec.x) + std::abs(y * vec.y) + std::abs(z * vec.z); } template @@ -77,7 +77,7 @@ T NzVector3::AngleBetween(const NzVector3& vec) const #endif T alpha = DotProduct(vec)/divisor; - return NzRadians(std::acos(NzClamp(alpha, F(-1.0), F(1.0)))); + return NzFromRadians(std::acos(NzClamp(alpha, F(-1.0), F(1.0)))); } template @@ -231,11 +231,13 @@ template NzVector3& NzVector3::Normalize(T* length) { T norm = GetLength(); - T invNorm = F(1.0) / norm; - - x *= invNorm; - y *= invNorm; - z *= invNorm; + if (norm > F(0.0)) + { + T invNorm = F(1.0) / norm; + x *= invNorm; + y *= invNorm; + z *= invNorm; + } if (length) *length = norm; @@ -253,6 +255,16 @@ NzVector3& NzVector3::Set(T X, T Y, T Z) return *this; } +template +NzVector3& NzVector3::Set(T X, const NzVector2& vec) +{ + x = X; + y = vec.x; + z = vec.y; + + return *this; +} + template NzVector3& NzVector3::Set(T scale) { @@ -300,6 +312,16 @@ NzVector3& NzVector3::Set(const NzVector3& vec) return *this; } +template +NzVector3& NzVector3::Set(const NzVector4& vec) +{ + x = vec.x; + y = vec.y; + z = vec.z; + + return *this; +} + template T NzVector3::SquaredDistance(const NzVector3& vec) const { diff --git a/include/Nazara/Math/Vector4.hpp b/include/Nazara/Math/Vector4.hpp index 5b71081d8..d4620a64a 100644 --- a/include/Nazara/Math/Vector4.hpp +++ b/include/Nazara/Math/Vector4.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges - Jérôme Leclercq +// Copyright (C) 2015 Rémi Bèges - Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -8,16 +8,23 @@ #define NAZARA_VECTOR4_HPP #include -#include -template class NzVector4 +template class NzVector2; +template class NzVector3; + +template +class NzVector4 { public: NzVector4() = default; NzVector4(T X, T Y, T Z, T W = 1.0); + NzVector4(T X, T Y, const NzVector2& vec); + NzVector4(T X, const NzVector2& vec, T W); + NzVector4(T X, const NzVector3& vec); explicit NzVector4(T scale); NzVector4(const T vec[4]); - NzVector4(const NzVector3& vec, T W = 1.0); + NzVector4(const NzVector2& vec, T Z = 0.0, T W = 1.0); + NzVector4(const NzVector3& vec, T W = 0.0); template explicit NzVector4(const NzVector4& vec); NzVector4(const NzVector4& vec) = default; ~NzVector4() = default; @@ -39,8 +46,12 @@ template class NzVector4 NzVector4& Normalize(T* length = nullptr); NzVector4& Set(T X, T Y, T Z, T W = 1.0); + NzVector4& Set(T X, T Y, const NzVector2& vec); + NzVector4& Set(T X, const NzVector2& vec, T W); + NzVector4& Set(T X, const NzVector3& vec); NzVector4& Set(T scale); NzVector4& Set(const T vec[4]); + NzVector4& Set(const NzVector2& vec, T Z = 0.0, T W = 1.0); NzVector4& Set(const NzVector3& vec, T W = 1.0); NzVector4& Set(const NzVector4& vec); template NzVector4& Set(const NzVector4& vec); diff --git a/include/Nazara/Math/Vector4.inl b/include/Nazara/Math/Vector4.inl index 77229fd5c..fdef535a7 100644 --- a/include/Nazara/Math/Vector4.inl +++ b/include/Nazara/Math/Vector4.inl @@ -1,9 +1,9 @@ -// Copyright (C) 2014 Rémi Bèges - Jérôme Leclercq +// Copyright (C) 2015 Rémi Bèges - Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include +#include #include #include #include @@ -18,6 +18,24 @@ NzVector4::NzVector4(T X, T Y, T Z, T W) Set(X, Y, Z, W); } +template +NzVector4::NzVector4(T X, T Y, const NzVector2& vec) +{ + Set(X, Y, vec); +} + +template +NzVector4::NzVector4(T X, const NzVector2& vec, T W) +{ + Set(X, vec, W); +} + +template +NzVector4::NzVector4(T X, const NzVector3& vec) +{ + Set(X, vec); +} + template NzVector4::NzVector4(T scale) { @@ -30,6 +48,12 @@ NzVector4::NzVector4(const T vec[4]) Set(vec); } +template +NzVector4::NzVector4(const NzVector2& vec, T Z, T W) +{ + Set(vec, Z, W); +} + template NzVector4::NzVector4(const NzVector3& vec, T W) { @@ -46,19 +70,7 @@ NzVector4::NzVector4(const NzVector4& vec) template T NzVector4::AbsDotProduct(const NzVector4& vec) const { - return std::fabs(x * vec.x) + std::fabs(y * vec.y) + std::fabs(z * vec.z) + std::fabs(w * vec.w); -} - -template<> -inline int NzVector4::AbsDotProduct(const NzVector4& vec) const -{ - return std::labs(x * vec.x) + std::labs(y * vec.y) + std::labs(z * vec.z) + std::labs(w * vec.w); -} - -template<> -inline unsigned int NzVector4::AbsDotProduct(const NzVector4& vec) const -{ - return std::labs(x * vec.x) + std::labs(y * vec.y) + std::labs(z * vec.z) + std::labs(w * vec.w); + return std::abs(x * vec.x) + std::abs(y * vec.y) + std::abs(z * vec.z) + std::abs(w * vec.w); } template @@ -155,10 +167,43 @@ NzVector4& NzVector4::Normalize(T* length) template NzVector4& NzVector4::Set(T X, T Y, T Z, T W) { - w = W; x = X; y = Y; z = Z; + w = W; + + return *this; +} + +template +NzVector4& NzVector4::Set(T X, T Y, const NzVector2& vec) +{ + x = X; + y = Y; + z = vec.x; + w = vec.y; + + return *this; +} + +template +NzVector4& NzVector4::Set(T X, const NzVector2& vec, T W) +{ + x = X; + y = vec.x; + z = vec.y; + w = W; + + return *this; +} + +template +NzVector4& NzVector4::Set(T X, const NzVector3& vec) +{ + x = X; + y = vec.x; + z = vec.y; + w = vec.z; return *this; } @@ -166,10 +211,10 @@ NzVector4& NzVector4::Set(T X, T Y, T Z, T W) template NzVector4& NzVector4::Set(T scale) { - w = scale; x = scale; y = scale; z = scale; + w = scale; return *this; } @@ -182,6 +227,17 @@ NzVector4& NzVector4::Set(const T vec[4]) return *this; } +template +NzVector4& NzVector4::Set(const NzVector2& vec, T Z, T W) +{ + x = vec.x; + y = vec.y; + z = Z; + w = W; + + return *this; +} + template NzVector4& NzVector4::Set(const NzVector3& vec, T W) { @@ -205,10 +261,10 @@ template template NzVector4& NzVector4::Set(const NzVector4& vec) { - w = F(vec.w); x = F(vec.x); y = F(vec.y); z = F(vec.z); + w = F(vec.w); return *this; } diff --git a/include/Nazara/Noise/Abstract2DNoise.hpp b/include/Nazara/Noise/Abstract2DNoise.hpp index 6ee7c551a..b472c36b3 100644 --- a/include/Nazara/Noise/Abstract2DNoise.hpp +++ b/include/Nazara/Noise/Abstract2DNoise.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/Abstract3DNoise.hpp b/include/Nazara/Noise/Abstract3DNoise.hpp index 9ca263e8b..f40ec770e 100644 --- a/include/Nazara/Noise/Abstract3DNoise.hpp +++ b/include/Nazara/Noise/Abstract3DNoise.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/Abstract4DNoise.hpp b/include/Nazara/Noise/Abstract4DNoise.hpp index 66192420b..a9ba2a8b7 100644 --- a/include/Nazara/Noise/Abstract4DNoise.hpp +++ b/include/Nazara/Noise/Abstract4DNoise.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/ComplexNoiseBase.hpp b/include/Nazara/Noise/ComplexNoiseBase.hpp index 649655a16..528ab5582 100644 --- a/include/Nazara/Noise/ComplexNoiseBase.hpp +++ b/include/Nazara/Noise/ComplexNoiseBase.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/Config.hpp b/include/Nazara/Noise/Config.hpp index c9a033f1b..29b7c647a 100644 --- a/include/Nazara/Noise/Config.hpp +++ b/include/Nazara/Noise/Config.hpp @@ -1,7 +1,7 @@ /* Nazara Engine - Noise module - Copyright (C) 2014 Rémi "Overdrivr" Bèges (remi.beges@laposte.net) + Copyright (C) 2015 Rémi "Overdrivr" Bèges (remi.beges@laposte.net) 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 diff --git a/include/Nazara/Noise/ConfigCheck.hpp b/include/Nazara/Noise/ConfigCheck.hpp index 3cad1d19a..04bbcdeeb 100644 --- a/include/Nazara/Noise/ConfigCheck.hpp +++ b/include/Nazara/Noise/ConfigCheck.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/Debug.hpp b/include/Nazara/Noise/Debug.hpp index c47777ba1..377ae7b1c 100644 --- a/include/Nazara/Noise/Debug.hpp +++ b/include/Nazara/Noise/Debug.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/DebugOff.hpp b/include/Nazara/Noise/DebugOff.hpp index 9993f1d15..75903b6cc 100644 --- a/include/Nazara/Noise/DebugOff.hpp +++ b/include/Nazara/Noise/DebugOff.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/FBM2D.hpp b/include/Nazara/Noise/FBM2D.hpp index 6e17b9f50..4ffade2c8 100644 --- a/include/Nazara/Noise/FBM2D.hpp +++ b/include/Nazara/Noise/FBM2D.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/FBM3D.hpp b/include/Nazara/Noise/FBM3D.hpp index e856cb3cb..985c0c777 100644 --- a/include/Nazara/Noise/FBM3D.hpp +++ b/include/Nazara/Noise/FBM3D.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/FBM4D.hpp b/include/Nazara/Noise/FBM4D.hpp index 9367167ef..e79f83c4a 100644 --- a/include/Nazara/Noise/FBM4D.hpp +++ b/include/Nazara/Noise/FBM4D.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/HybridMultiFractal3D.hpp b/include/Nazara/Noise/HybridMultiFractal3D.hpp index 4578b0951..615a3b9a1 100644 --- a/include/Nazara/Noise/HybridMultiFractal3D.hpp +++ b/include/Nazara/Noise/HybridMultiFractal3D.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/HybridMultiFractal4D.hpp b/include/Nazara/Noise/HybridMultiFractal4D.hpp index f52ab9ee4..8d27df096 100644 --- a/include/Nazara/Noise/HybridMultiFractal4D.hpp +++ b/include/Nazara/Noise/HybridMultiFractal4D.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/HybridMultifractal2D.hpp b/include/Nazara/Noise/HybridMultifractal2D.hpp index 831a9429d..9ed2d0b2a 100644 --- a/include/Nazara/Noise/HybridMultifractal2D.hpp +++ b/include/Nazara/Noise/HybridMultifractal2D.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/MappedNoiseBase.hpp b/include/Nazara/Noise/MappedNoiseBase.hpp index 9c61acfb6..62a1f9fc5 100644 --- a/include/Nazara/Noise/MappedNoiseBase.hpp +++ b/include/Nazara/Noise/MappedNoiseBase.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/Noise.hpp b/include/Nazara/Noise/Noise.hpp index 0a2f53dec..ea7cc91a3 100644 --- a/include/Nazara/Noise/Noise.hpp +++ b/include/Nazara/Noise/Noise.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/NoiseBase.hpp b/include/Nazara/Noise/NoiseBase.hpp index a108d20dd..76c2c4315 100644 --- a/include/Nazara/Noise/NoiseBase.hpp +++ b/include/Nazara/Noise/NoiseBase.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/Perlin2D.hpp b/include/Nazara/Noise/Perlin2D.hpp index fb9022e82..e719a3870 100644 --- a/include/Nazara/Noise/Perlin2D.hpp +++ b/include/Nazara/Noise/Perlin2D.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/Perlin3D.hpp b/include/Nazara/Noise/Perlin3D.hpp index c1b4e97db..e487a49fc 100644 --- a/include/Nazara/Noise/Perlin3D.hpp +++ b/include/Nazara/Noise/Perlin3D.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/Perlin4D.hpp b/include/Nazara/Noise/Perlin4D.hpp index 66a436149..90ec5a92e 100644 --- a/include/Nazara/Noise/Perlin4D.hpp +++ b/include/Nazara/Noise/Perlin4D.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/Simplex2D.hpp b/include/Nazara/Noise/Simplex2D.hpp index 33e77fd4d..8b44a5a11 100644 --- a/include/Nazara/Noise/Simplex2D.hpp +++ b/include/Nazara/Noise/Simplex2D.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/Simplex3D.hpp b/include/Nazara/Noise/Simplex3D.hpp index 9d9042f1f..b2257c063 100644 --- a/include/Nazara/Noise/Simplex3D.hpp +++ b/include/Nazara/Noise/Simplex3D.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Noise/Simplex4D.hpp b/include/Nazara/Noise/Simplex4D.hpp index a9b87fa87..3415e16cb 100644 --- a/include/Nazara/Noise/Simplex4D.hpp +++ b/include/Nazara/Noise/Simplex4D.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Physics/Config.hpp b/include/Nazara/Physics/Config.hpp index 3f10a9aad..06d30e383 100644 --- a/include/Nazara/Physics/Config.hpp +++ b/include/Nazara/Physics/Config.hpp @@ -1,7 +1,7 @@ /* Nazara Engine - Physics module - Copyright (C) 2014 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) + Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/include/Nazara/Physics/ConfigCheck.hpp b/include/Nazara/Physics/ConfigCheck.hpp index 037b6d0ec..3ec7c9599 100644 --- a/include/Nazara/Physics/ConfigCheck.hpp +++ b/include/Nazara/Physics/ConfigCheck.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Physics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Physics/Debug.hpp b/include/Nazara/Physics/Debug.hpp index f5ac12a54..c97bc63f7 100644 --- a/include/Nazara/Physics/Debug.hpp +++ b/include/Nazara/Physics/Debug.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Physics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Physics/DebugOff.hpp b/include/Nazara/Physics/DebugOff.hpp index b22910c3b..6e6dd97a4 100644 --- a/include/Nazara/Physics/DebugOff.hpp +++ b/include/Nazara/Physics/DebugOff.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Physics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Physics/Enums.hpp b/include/Nazara/Physics/Enums.hpp index 090ccde97..defbdae19 100644 --- a/include/Nazara/Physics/Enums.hpp +++ b/include/Nazara/Physics/Enums.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Physics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Physics/Geom.hpp b/include/Nazara/Physics/Geom.hpp index 85522ba55..5c851ee30 100644 --- a/include/Nazara/Physics/Geom.hpp +++ b/include/Nazara/Physics/Geom.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Physics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Physics/PhysObject.hpp b/include/Nazara/Physics/PhysObject.hpp index c395f176e..10e0bece9 100644 --- a/include/Nazara/Physics/PhysObject.hpp +++ b/include/Nazara/Physics/PhysObject.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Physics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Physics/PhysWorld.hpp b/include/Nazara/Physics/PhysWorld.hpp index 80071da32..7069ff412 100644 --- a/include/Nazara/Physics/PhysWorld.hpp +++ b/include/Nazara/Physics/PhysWorld.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Physics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Physics/Physics.hpp b/include/Nazara/Physics/Physics.hpp index 7a0e73aec..c4da3db7f 100644 --- a/include/Nazara/Physics/Physics.hpp +++ b/include/Nazara/Physics/Physics.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Physics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Prerequesites.hpp b/include/Nazara/Prerequesites.hpp index 04fa0b48b..ac58d90ea 100644 --- a/include/Nazara/Prerequesites.hpp +++ b/include/Nazara/Prerequesites.hpp @@ -1,7 +1,7 @@ /* Nazara Engine - Copyright (C) 2014 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) + Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/include/Nazara/Renderer/Config.hpp b/include/Nazara/Renderer/Config.hpp index 0e5b08fc7..eb9bf3d7f 100644 --- a/include/Nazara/Renderer/Config.hpp +++ b/include/Nazara/Renderer/Config.hpp @@ -1,7 +1,7 @@ /* Nazara Engine - Renderer module - Copyright (C) 2014 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) + Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/include/Nazara/Renderer/ConfigCheck.hpp b/include/Nazara/Renderer/ConfigCheck.hpp index 9e362d5ed..3860a809b 100644 --- a/include/Nazara/Renderer/ConfigCheck.hpp +++ b/include/Nazara/Renderer/ConfigCheck.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Renderer/Context.hpp b/include/Nazara/Renderer/Context.hpp index 29c4a3714..94ebad183 100644 --- a/include/Nazara/Renderer/Context.hpp +++ b/include/Nazara/Renderer/Context.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -8,6 +8,7 @@ #define NAZARA_CONTEXT_HPP #include +#include #include #include #include @@ -16,7 +17,9 @@ class NzContext; +using NzContextConstListener = NzObjectListenerWrapper; using NzContextConstRef = NzObjectRef; +using NzContextListener = NzObjectListenerWrapper; using NzContextRef = NzObjectRef; class NzContextImpl; diff --git a/include/Nazara/Renderer/ContextParameters.hpp b/include/Nazara/Renderer/ContextParameters.hpp index c7c80de9b..5e344778c 100644 --- a/include/Nazara/Renderer/ContextParameters.hpp +++ b/include/Nazara/Renderer/ContextParameters.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Renderer/Debug.hpp b/include/Nazara/Renderer/Debug.hpp index 2d30c585b..ef0e73147 100644 --- a/include/Nazara/Renderer/Debug.hpp +++ b/include/Nazara/Renderer/Debug.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Renderer/DebugDrawer.hpp b/include/Nazara/Renderer/DebugDrawer.hpp index fc632765a..cb1ae2953 100644 --- a/include/Nazara/Renderer/DebugDrawer.hpp +++ b/include/Nazara/Renderer/DebugDrawer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -27,6 +27,7 @@ class NAZARA_API NzDebugDrawer static void Draw(const NzFrustumf& frustum); static void Draw(const NzOrientedBoxf& orientedBox); static void Draw(const NzSkeleton* skeleton); + static void Draw(const NzVector3f& position, float size = 0.1f); static void DrawBinormals(const NzStaticMesh* subMesh); static void DrawCone(const NzVector3f& origin, const NzQuaternionf& rotation, float angle, float length); static void DrawLine(const NzVector3f& p1, const NzVector3f& p2); diff --git a/include/Nazara/Renderer/DebugOff.hpp b/include/Nazara/Renderer/DebugOff.hpp index 031da1959..b20650b99 100644 --- a/include/Nazara/Renderer/DebugOff.hpp +++ b/include/Nazara/Renderer/DebugOff.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Renderer/Enums.hpp b/include/Nazara/Renderer/Enums.hpp index 229800e9b..d20b6dd87 100644 --- a/include/Nazara/Renderer/Enums.hpp +++ b/include/Nazara/Renderer/Enums.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -35,11 +35,11 @@ enum nzBlendFunc enum nzFaceFilling { - nzFaceFilling_Point, - nzFaceFilling_Line, nzFaceFilling_Fill, + nzFaceFilling_Line, + nzFaceFilling_Point, - nzFaceFilling_Max = nzFaceFilling_Fill + nzFaceFilling_Max = nzFaceFilling_Point }; enum nzFaceSide @@ -185,19 +185,8 @@ enum nzSamplerWrap nzSamplerWrap_Max = nzSamplerWrap_Repeat }; -enum nzShaderTarget -{ - nzShaderTarget_FullscreenQuad, - nzShaderTarget_Model, - nzShaderTarget_None, - nzShaderTarget_Sprite, - - nzShaderTarget_Max = nzShaderTarget_Sprite -}; - enum nzShaderUniform { - nzShaderUniform_EyePosition, nzShaderUniform_InvProjMatrix, nzShaderUniform_InvTargetSize, nzShaderUniform_InvViewMatrix, @@ -206,7 +195,6 @@ enum nzShaderUniform nzShaderUniform_InvWorldViewMatrix, nzShaderUniform_InvWorldViewProjMatrix, nzShaderUniform_ProjMatrix, - nzShaderUniform_SceneAmbient, nzShaderUniform_TargetSize, nzShaderUniform_ViewMatrix, nzShaderUniform_ViewProjMatrix, diff --git a/include/Nazara/Renderer/GpuQuery.hpp b/include/Nazara/Renderer/GpuQuery.hpp index 76dc4d46f..bd792b979 100644 --- a/include/Nazara/Renderer/GpuQuery.hpp +++ b/include/Nazara/Renderer/GpuQuery.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Renderer/OpenGL.hpp b/include/Nazara/Renderer/OpenGL.hpp index df6c199d7..08079582a 100644 --- a/include/Nazara/Renderer/OpenGL.hpp +++ b/include/Nazara/Renderer/OpenGL.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -69,6 +69,7 @@ class NAZARA_API NzOpenGL GLenum dataFormat; GLenum dataType; GLint internalFormat; + GLint swizzle[4]; }; NzOpenGL() = delete; diff --git a/include/Nazara/Renderer/RenderBuffer.hpp b/include/Nazara/Renderer/RenderBuffer.hpp index 207f33f59..48947f927 100644 --- a/include/Nazara/Renderer/RenderBuffer.hpp +++ b/include/Nazara/Renderer/RenderBuffer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,13 +9,16 @@ #include #include +#include #include #include #include class NzRenderBuffer; +using NzRenderBufferConstListener = NzObjectListenerWrapper; using NzRenderBufferConstRef = NzObjectRef; +using NzRenderBufferListener = NzObjectListenerWrapper; using NzRenderBufferRef = NzObjectRef; class NAZARA_API NzRenderBuffer : public NzRefCounted, NzNonCopyable diff --git a/include/Nazara/Renderer/RenderStates.hpp b/include/Nazara/Renderer/RenderStates.hpp index 3ae14d6d6..15d796afb 100644 --- a/include/Nazara/Renderer/RenderStates.hpp +++ b/include/Nazara/Renderer/RenderStates.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Renderer/RenderStates.inl b/include/Nazara/Renderer/RenderStates.inl index 26f60c8cd..8a7f188da 100644 --- a/include/Nazara/Renderer/RenderStates.inl +++ b/include/Nazara/Renderer/RenderStates.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Renderer/RenderTarget.hpp b/include/Nazara/Renderer/RenderTarget.hpp index c62d1c5b6..b9f5643ad 100644 --- a/include/Nazara/Renderer/RenderTarget.hpp +++ b/include/Nazara/Renderer/RenderTarget.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -44,7 +44,7 @@ class NAZARA_API NzRenderTarget { public: Listener() = default; - ~Listener(); + virtual ~Listener(); virtual bool OnRenderTargetParametersChange(const NzRenderTarget* renderTarget, void* userdata); virtual void OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata); @@ -61,7 +61,7 @@ class NAZARA_API NzRenderTarget private: mutable std::unordered_map m_listeners; - bool m_listenersLocked; + bool m_listenersLocked; }; #endif // NAZARA_RENDERTARGET_HPP diff --git a/include/Nazara/Renderer/RenderTargetParameters.hpp b/include/Nazara/Renderer/RenderTargetParameters.hpp index 57e7071ad..cd8a4ab0a 100644 --- a/include/Nazara/Renderer/RenderTargetParameters.hpp +++ b/include/Nazara/Renderer/RenderTargetParameters.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Renderer/RenderTexture.hpp b/include/Nazara/Renderer/RenderTexture.hpp index 10bdfc84e..c86c79e06 100644 --- a/include/Nazara/Renderer/RenderTexture.hpp +++ b/include/Nazara/Renderer/RenderTexture.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Renderer/RenderWindow.hpp b/include/Nazara/Renderer/RenderWindow.hpp index 141b2590e..41c2e6412 100644 --- a/include/Nazara/Renderer/RenderWindow.hpp +++ b/include/Nazara/Renderer/RenderWindow.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index aff9101fa..50f8b0717 100644 --- a/include/Nazara/Renderer/Renderer.hpp +++ b/include/Nazara/Renderer/Renderer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -31,6 +31,9 @@ class NAZARA_API NzRenderer friend NzTexture; public: + using DrawCall = void (*)(nzPrimitiveMode, unsigned int, unsigned int); + using DrawCallInstanced = void (*)(unsigned int, nzPrimitiveMode, unsigned int, unsigned int); + NzRenderer() = delete; ~NzRenderer() = delete; @@ -57,6 +60,7 @@ class NAZARA_API NzRenderer static nzUInt8 GetMaxAnisotropyLevel(); static unsigned int GetMaxColorAttachments(); static unsigned int GetMaxRenderTargets(); + static unsigned int GetMaxTextureSize(); static unsigned int GetMaxTextureUnits(); static unsigned int GetMaxVertexAttribs(); static float GetPointSize(); diff --git a/include/Nazara/Renderer/Shader.hpp b/include/Nazara/Renderer/Shader.hpp index 76e37af08..ecdc0b3e6 100644 --- a/include/Nazara/Renderer/Shader.hpp +++ b/include/Nazara/Renderer/Shader.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -23,7 +24,9 @@ class NzShader; class NzShaderStage; +using NzShaderConstListener = NzObjectListenerWrapper; using NzShaderConstRef = NzObjectRef; +using NzShaderListener = NzObjectListenerWrapper; using NzShaderRef = NzObjectRef; class NAZARA_API NzShader : public NzRefCounted, NzNonCopyable @@ -32,7 +35,6 @@ class NAZARA_API NzShader : public NzRefCounted, NzNonCopyable public: NzShader(); - NzShader(NzShader&& shader); ~NzShader(); void AttachStage(nzShaderStage stage, const NzShaderStage& shaderStage); @@ -94,8 +96,6 @@ class NAZARA_API NzShader : public NzRefCounted, NzNonCopyable // Fonctions OpenGL unsigned int GetOpenGLID() const; - NzShader& operator=(NzShader&& shader); - static bool IsStageSupported(nzShaderStage stage); private: diff --git a/include/Nazara/Renderer/ShaderLibrary.hpp b/include/Nazara/Renderer/ShaderLibrary.hpp index bc1d6b1ce..859be77af 100644 --- a/include/Nazara/Renderer/ShaderLibrary.hpp +++ b/include/Nazara/Renderer/ShaderLibrary.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Renderer/ShaderStage.hpp b/include/Nazara/Renderer/ShaderStage.hpp index c5ecac17a..adb1f7f2c 100644 --- a/include/Nazara/Renderer/ShaderStage.hpp +++ b/include/Nazara/Renderer/ShaderStage.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Renderer/Texture.hpp b/include/Nazara/Renderer/Texture.hpp index 30eddb909..29a4d6762 100644 --- a/include/Nazara/Renderer/Texture.hpp +++ b/include/Nazara/Renderer/Texture.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,28 +9,31 @@ #include #include +#include #include #include #include #include +#include #include #include -#include class NzTexture; +using NzTextureConstListener = NzObjectListenerWrapper; using NzTextureConstRef = NzObjectRef; +using NzTextureListener = NzObjectListenerWrapper; using NzTextureRef = NzObjectRef; struct NzTextureImpl; -class NAZARA_API NzTexture : public NzRefCounted, public NzResource, NzNonCopyable +class NAZARA_API NzTexture : public NzAbstractImage, public NzRefCounted, public NzResource, NzNonCopyable { friend class NzRenderer; - friend class NzRenderTexture; public: NzTexture() = default; + NzTexture(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth = 1, nzUInt8 levelCount = 1); explicit NzTexture(const NzImage& image); ~NzTexture(); @@ -43,18 +46,20 @@ class NAZARA_API NzTexture : public NzRefCounted, public NzResource, NzNonCopyab void EnsureMipmapsUpdate() const; - nzUInt8 GetBytesPerPixel() const; - unsigned int GetDepth() const; + unsigned int GetDepth(nzUInt8 level = 0) const; nzPixelFormat GetFormat() const; - unsigned int GetHeight() const; - NzVector2ui GetSize() const; + unsigned int GetHeight(nzUInt8 level = 0) const; + nzUInt8 GetLevelCount() const; + nzUInt8 GetMaxLevel() const; + unsigned int GetMemoryUsage() const; + unsigned int GetMemoryUsage(nzUInt8 level) const; + NzVector3ui GetSize(nzUInt8 level = 0) const; nzImageType GetType() const; - unsigned int GetWidth() const; + unsigned int GetWidth(nzUInt8 level = 0) const; bool HasMipmaps() const; - bool IsCompressed() const; - bool IsCubemap() const; + void InvalidateMipmaps(); bool IsValid() const; // Load @@ -63,6 +68,12 @@ class NAZARA_API NzTexture : public NzRefCounted, public NzResource, NzNonCopyab bool LoadFromMemory(const void* data, std::size_t size, const NzImageParams& params = NzImageParams(), bool generateMipmaps = true); bool LoadFromStream(NzInputStream& stream, const NzImageParams& params = NzImageParams(), bool generateMipmaps = true); + // LoadArray + bool LoadArrayFromFile(const NzString& filePath, const NzImageParams& imageParams = NzImageParams(), bool generateMipmaps = true, const NzVector2ui& atlasSize = NzVector2ui(2, 2)); + bool LoadArrayFromImage(const NzImage& image, bool generateMipmaps = true, const NzVector2ui& atlasSize = NzVector2ui(2, 2)); + bool LoadArrayFromMemory(const void* data, std::size_t size, const NzImageParams& imageParams = NzImageParams(), bool generateMipmaps = true, const NzVector2ui& atlasSize = NzVector2ui(2, 2)); + bool LoadArrayFromStream(NzInputStream& stream, const NzImageParams& imageParams = NzImageParams(), bool generateMipmaps = true, const NzVector2ui& atlasSize = NzVector2ui(2, 2)); + // LoadCubemap bool LoadCubemapFromFile(const NzString& filePath, const NzImageParams& imageParams = NzImageParams(), bool generateMipmaps = true, const NzCubemapParams& cubemapParams = NzCubemapParams()); bool LoadCubemapFromImage(const NzImage& image, bool generateMipmaps = true, const NzCubemapParams& params = NzCubemapParams()); @@ -82,10 +93,6 @@ class NAZARA_API NzTexture : public NzRefCounted, public NzResource, NzNonCopyab bool Update(const nzUInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0); bool Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0); bool Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0); - bool UpdateFace(nzCubemapFace face, const NzImage& image, nzUInt8 level = 0); - bool UpdateFace(nzCubemapFace face, const NzImage& image, const NzRectui& rect, nzUInt8 level = 0); - bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0); - bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRectui& rect, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0); // Fonctions OpenGL unsigned int GetOpenGLID() const; @@ -96,7 +103,7 @@ class NAZARA_API NzTexture : public NzRefCounted, public NzResource, NzNonCopyab static bool IsTypeSupported(nzImageType type); private: - void InvalidateMipmaps(); + bool CreateTexture(bool proxy); NzTextureImpl* m_impl = nullptr; }; diff --git a/include/Nazara/Renderer/TextureSampler.hpp b/include/Nazara/Renderer/TextureSampler.hpp index 61dd5a17d..6eefb8793 100644 --- a/include/Nazara/Renderer/TextureSampler.hpp +++ b/include/Nazara/Renderer/TextureSampler.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Renderer/UberShader.hpp b/include/Nazara/Renderer/UberShader.hpp index 355ccf968..28a49ab0c 100644 --- a/include/Nazara/Renderer/UberShader.hpp +++ b/include/Nazara/Renderer/UberShader.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -16,7 +17,9 @@ class NzUberShader; +using NzUberShaderConstListener = NzObjectListenerWrapper; using NzUberShaderConstRef = NzObjectRef; +using NzUberShaderListener = NzObjectListenerWrapper; using NzUberShaderRef = NzObjectRef; class NAZARA_API NzUberShader : public NzRefCounted diff --git a/include/Nazara/Renderer/UberShaderInstance.hpp b/include/Nazara/Renderer/UberShaderInstance.hpp index 1720a5f79..c42020d19 100644 --- a/include/Nazara/Renderer/UberShaderInstance.hpp +++ b/include/Nazara/Renderer/UberShaderInstance.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Renderer/UberShaderInstancePreprocessor.hpp b/include/Nazara/Renderer/UberShaderInstancePreprocessor.hpp index 4f1b09f08..2bbeb8d49 100644 --- a/include/Nazara/Renderer/UberShaderInstancePreprocessor.hpp +++ b/include/Nazara/Renderer/UberShaderInstancePreprocessor.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Renderer/UberShaderLibrary.hpp b/include/Nazara/Renderer/UberShaderLibrary.hpp index 8561d809d..8a52da284 100644 --- a/include/Nazara/Renderer/UberShaderLibrary.hpp +++ b/include/Nazara/Renderer/UberShaderLibrary.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Renderer/UberShaderPreprocessor.hpp b/include/Nazara/Renderer/UberShaderPreprocessor.hpp index 3818c2154..83ae69b3d 100644 --- a/include/Nazara/Renderer/UberShaderPreprocessor.hpp +++ b/include/Nazara/Renderer/UberShaderPreprocessor.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -23,8 +23,8 @@ class NAZARA_API NzUberShaderPreprocessor : public NzUberShader NzUberShaderInstance* Get(const NzParameterList& parameters) const; - void SetShader(nzShaderStage stage, const NzString& source, const NzString& flags); - bool SetShaderFromFile(nzShaderStage stage, const NzString& filePath, const NzString& flags); + void SetShader(nzShaderStage stage, const NzString& source, const NzString& shaderFlags, const NzString& requiredFlags = NzString()); + bool SetShaderFromFile(nzShaderStage stage, const NzString& filePath, const NzString& shaderFlags, const NzString& requiredFlags = NzString()); static bool IsSupported(); @@ -33,6 +33,7 @@ class NAZARA_API NzUberShaderPreprocessor : public NzUberShader { mutable std::unordered_map cache; std::unordered_map flags; + nzUInt32 requiredFlags; NzString source; bool present = false; }; diff --git a/include/Nazara/Utility.hpp b/include/Nazara/Utility.hpp index 78642c29b..6f7ecb312 100644 --- a/include/Nazara/Utility.hpp +++ b/include/Nazara/Utility.hpp @@ -1,4 +1,4 @@ -// This file was automatically generated on 11 Jul 2014 at 10:21:52 +// This file was automatically generated on 17 Jan 2015 at 00:38:08 /* Nazara Engine - Utility module @@ -29,7 +29,10 @@ #ifndef NAZARA_GLOBAL_UTILITY_HPP #define NAZARA_GLOBAL_UTILITY_HPP +#include #include +#include +#include #include #include #include @@ -39,6 +42,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -52,6 +59,7 @@ #include #include #include +#include #include #include #include diff --git a/include/Nazara/Utility/AbstractAtlas.hpp b/include/Nazara/Utility/AbstractAtlas.hpp new file mode 100644 index 000000000..eb0a240ae --- /dev/null +++ b/include/Nazara/Utility/AbstractAtlas.hpp @@ -0,0 +1,58 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_ABSTRACTATLAS_HPP +#define NAZARA_ABSTRACTATLAS_HPP + +#include +#include +#include +#include +#include + +class NzAbstractImage; +class NzImage; + +class NAZARA_API NzAbstractAtlas +{ + public: + class Listener; + + NzAbstractAtlas(); + virtual ~NzAbstractAtlas(); + + void AddListener(Listener* font, void* userdata = nullptr) const; + + virtual void Clear() = 0; + virtual void Free(NzSparsePtr rects, NzSparsePtr layers, unsigned int count) = 0; + virtual NzAbstractImage* GetLayer(unsigned int layerIndex) const = 0; + virtual unsigned int GetLayerCount() const = 0; + virtual nzUInt32 GetStorage() const = 0; + virtual bool Insert(const NzImage& image, NzRectui* rect, bool* flipped, unsigned int* layerIndex) = 0; + + void RemoveListener(Listener* font) const; + + class NAZARA_API Listener + { + public: + Listener() = default; + virtual ~Listener(); + + virtual bool OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata); + virtual bool OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata); + virtual void OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata); + }; + + protected: + void NotifyCleared(); + void NotifyLayerChange(NzAbstractImage* oldLayer, NzAbstractImage* newLayer); + + private: + mutable std::unordered_map m_listeners; + bool m_listenersLocked; +}; + +#endif // NAZARA_ABSTRACTATLAS_HPP diff --git a/include/Nazara/Utility/AbstractBuffer.hpp b/include/Nazara/Utility/AbstractBuffer.hpp index e8c7a47db..bb05c2cca 100644 --- a/include/Nazara/Utility/AbstractBuffer.hpp +++ b/include/Nazara/Utility/AbstractBuffer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/AbstractImage.hpp b/include/Nazara/Utility/AbstractImage.hpp new file mode 100644 index 000000000..8697ea813 --- /dev/null +++ b/include/Nazara/Utility/AbstractImage.hpp @@ -0,0 +1,42 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_ABSTRACTIMAGE_HPP +#define NAZARA_ABSTRACTIMAGE_HPP + +#include +#include +#include +#include +#include + +class NAZARA_API NzAbstractImage +{ + public: + NzAbstractImage() = default; + virtual ~NzAbstractImage(); + + nzUInt8 GetBytesPerPixel() const; + virtual unsigned int GetDepth(nzUInt8 level = 0) const = 0; + virtual nzPixelFormat GetFormat() const = 0; + virtual unsigned int GetHeight(nzUInt8 level = 0) const = 0; + virtual nzUInt8 GetLevelCount() const = 0; + virtual nzUInt8 GetMaxLevel() const = 0; + virtual unsigned int GetMemoryUsage() const = 0; + virtual unsigned int GetMemoryUsage(nzUInt8 level) const = 0; + virtual NzVector3ui GetSize(nzUInt8 level = 0) const = 0; + virtual nzImageType GetType() const = 0; + virtual unsigned int GetWidth(nzUInt8 level = 0) const = 0; + + bool IsCompressed() const; + bool IsCubemap() const; + + virtual bool Update(const nzUInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0) = 0; + virtual bool Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0) = 0; + virtual bool Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0) = 0; +}; + +#endif // NAZARA_IMAGE_HPP diff --git a/include/Nazara/Utility/AbstractTextDrawer.hpp b/include/Nazara/Utility/AbstractTextDrawer.hpp new file mode 100644 index 000000000..76df09a00 --- /dev/null +++ b/include/Nazara/Utility/AbstractTextDrawer.hpp @@ -0,0 +1,42 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_ABSTRACTTEXTDRAWER_HPP +#define NAZARA_ABSTRACTTEXTDRAWER_HPP + +#include +#include +#include +#include + +class NzAbstractImage; +class NzFont; + +class NAZARA_API NzAbstractTextDrawer +{ + public: + struct Glyph; + + NzAbstractTextDrawer() = default; + virtual ~NzAbstractTextDrawer(); + + virtual const NzRectui& GetBounds() const = 0; + virtual NzFont* GetFont(unsigned int index) const = 0; + virtual unsigned int GetFontCount() const = 0; + virtual const Glyph& GetGlyph(unsigned int index) const = 0; + virtual unsigned int GetGlyphCount() const = 0; + + struct Glyph + { + NzColor color; + NzRectui atlasRect; + NzVector2f corners[4]; + NzAbstractImage* atlas; + bool flipped; + }; +}; + +#endif // NAZARA_ABSTRACTTEXTDRAWER_HPP diff --git a/include/Nazara/Utility/Algorithm.hpp b/include/Nazara/Utility/Algorithm.hpp index 59812fca4..72306ce90 100644 --- a/include/Nazara/Utility/Algorithm.hpp +++ b/include/Nazara/Utility/Algorithm.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -32,6 +32,7 @@ NAZARA_API void NzComputePlaneIndexVertexCount(const NzVector2ui& subdivision, u NAZARA_API void NzComputeUvSphereIndexVertexCount(unsigned int sliceCount, unsigned int stackCount, unsigned int* indexCount, unsigned int* vertexCount); template NzBoxf NzComputeVerticesAABB(const T* vertices, unsigned int vertexCount); +///TODO: Remplacer le pointeur vertices par une structure composée de plusieurs SparsePtr NAZARA_API void NzGenerateBox(const NzVector3f& lengths, const NzVector3ui& subdivision, const NzMatrix4f& matrix, const NzRectf& textureCoords, NzMeshVertex* vertices, NzIndexIterator indices, NzBoxf* aabb = nullptr, unsigned int indexOffset = 0); NAZARA_API void NzGenerateCone(float length, float radius, unsigned int subdivision, const NzMatrix4f& matrix, const NzRectf& textureCoords, NzMeshVertex* vertices, NzIndexIterator indices, NzBoxf* aabb = nullptr, unsigned int indexOffset = 0); NAZARA_API void NzGenerateCubicSphere(float size, unsigned int subdivision, const NzMatrix4f& matrix, const NzRectf& textureCoords, NzMeshVertex* vertices, NzIndexIterator indices, NzBoxf* aabb = nullptr, unsigned int indexOffset = 0); diff --git a/include/Nazara/Utility/Algorithm.inl b/include/Nazara/Utility/Algorithm.inl index 0fb69cf93..93664c35e 100644 --- a/include/Nazara/Utility/Algorithm.inl +++ b/include/Nazara/Utility/Algorithm.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/Animation.hpp b/include/Nazara/Utility/Animation.hpp index c76438303..1deae6222 100644 --- a/include/Nazara/Utility/Animation.hpp +++ b/include/Nazara/Utility/Animation.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -8,6 +8,7 @@ #define NAZARA_ANIMATION_HPP #include +#include #include #include #include @@ -15,11 +16,12 @@ #include #include #include +#include struct NAZARA_API NzAnimationParams { // La frame de fin à charger - unsigned int endFrame = static_cast(-1); + unsigned int endFrame = std::numeric_limits::max(); // La frame de début à charger unsigned int startFrame = 0; @@ -29,7 +31,9 @@ struct NAZARA_API NzAnimationParams class NzAnimation; class NzSkeleton; +using NzAnimationConstListener = NzObjectListenerWrapper; using NzAnimationConstRef = NzObjectRef; +using NzAnimationListener = NzObjectListenerWrapper; using NzAnimationLoader = NzResourceLoader; using NzAnimationRef = NzObjectRef; diff --git a/include/Nazara/Utility/Buffer.hpp b/include/Nazara/Utility/Buffer.hpp index 3f5b1ef06..9642c2b91 100644 --- a/include/Nazara/Utility/Buffer.hpp +++ b/include/Nazara/Utility/Buffer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,13 +9,16 @@ #include #include +#include #include #include #include class NzBuffer; +using NzBufferConstListener = NzObjectListenerWrapper; using NzBufferConstRef = NzObjectRef; +using NzBufferListener = NzObjectListenerWrapper; using NzBufferRef = NzObjectRef; class NzAbstractBuffer; @@ -25,22 +28,22 @@ class NAZARA_API NzBuffer : public NzRefCounted, NzNonCopyable friend class NzUtility; public: - using BufferFunction = NzAbstractBuffer* (*)(NzBuffer* parent, nzBufferType type); + using BufferFactory = NzAbstractBuffer* (*)(NzBuffer* parent, nzBufferType type); NzBuffer(nzBufferType type); - NzBuffer(nzBufferType type, unsigned int size, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); + NzBuffer(nzBufferType type, unsigned int size, nzUInt32 storage = nzDataStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); ~NzBuffer(); bool CopyContent(const NzBuffer& buffer); - bool Create(unsigned int size, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); + bool Create(unsigned int size, nzUInt32 storage = nzDataStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); void Destroy(); bool Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard = false); NzAbstractBuffer* GetImpl() const; unsigned int GetSize() const; - nzBufferStorage GetStorage() const; + nzUInt32 GetStorage() const; nzBufferType GetType() const; nzBufferUsage GetUsage() const; @@ -50,24 +53,24 @@ class NAZARA_API NzBuffer : public NzRefCounted, NzNonCopyable void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0); void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0) const; - bool SetStorage(nzBufferStorage storage); + bool SetStorage(nzUInt32 storage); void Unmap() const; - static bool IsSupported(nzBufferStorage storage); - static void SetBufferFunction(nzBufferStorage storage, BufferFunction func); + static bool IsStorageSupported(nzUInt32 storage); + static void SetBufferFactory(nzUInt32 storage, BufferFactory func); private: static bool Initialize(); static void Uninitialize(); - nzBufferStorage m_storage; nzBufferType m_type; nzBufferUsage m_usage; + nzUInt32 m_storage; NzAbstractBuffer* m_impl; unsigned int m_size; - static BufferFunction s_bufferFunctions[nzBufferStorage_Max+1]; + static BufferFactory s_bufferFactories[nzDataStorage_Max+1]; }; #endif // NAZARA_BUFFER_HPP diff --git a/include/Nazara/Utility/BufferMapper.hpp b/include/Nazara/Utility/BufferMapper.hpp index 546f2cdb0..814d78f8b 100644 --- a/include/Nazara/Utility/BufferMapper.hpp +++ b/include/Nazara/Utility/BufferMapper.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/BufferMapper.inl b/include/Nazara/Utility/BufferMapper.inl index 758a60ca8..1f6499c85 100644 --- a/include/Nazara/Utility/BufferMapper.inl +++ b/include/Nazara/Utility/BufferMapper.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/Config.hpp b/include/Nazara/Utility/Config.hpp index a05568d2f..6eae437b9 100644 --- a/include/Nazara/Utility/Config.hpp +++ b/include/Nazara/Utility/Config.hpp @@ -1,7 +1,7 @@ /* Nazara Engine - Utility module - Copyright (C) 2014 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) + Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/include/Nazara/Utility/ConfigCheck.hpp b/include/Nazara/Utility/ConfigCheck.hpp index 85379eba1..b4c976edc 100644 --- a/include/Nazara/Utility/ConfigCheck.hpp +++ b/include/Nazara/Utility/ConfigCheck.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/CubemapParams.hpp b/include/Nazara/Utility/CubemapParams.hpp index 760782acf..a9e82e299 100644 --- a/include/Nazara/Utility/CubemapParams.hpp +++ b/include/Nazara/Utility/CubemapParams.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/Cursor.hpp b/include/Nazara/Utility/Cursor.hpp index a3a3015e4..884bd04ab 100644 --- a/include/Nazara/Utility/Cursor.hpp +++ b/include/Nazara/Utility/Cursor.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/Debug.hpp b/include/Nazara/Utility/Debug.hpp index d5ae45202..85319685a 100644 --- a/include/Nazara/Utility/Debug.hpp +++ b/include/Nazara/Utility/Debug.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/DebugOff.hpp b/include/Nazara/Utility/DebugOff.hpp index 177f4e29a..5cb9a0750 100644 --- a/include/Nazara/Utility/DebugOff.hpp +++ b/include/Nazara/Utility/DebugOff.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index 52bc9cba6..49d66c2af 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -25,15 +25,6 @@ enum nzBufferAccess nzBufferAccess_Max = nzBufferAccess_WriteOnly }; -enum nzBufferStorage -{ - //nzBufferStorage_Both, ///TODO - nzBufferStorage_Hardware, - nzBufferStorage_Software, - - nzBufferStorage_Max = nzBufferStorage_Software -}; - enum nzBufferType { nzBufferType_Index, @@ -84,6 +75,16 @@ enum nzCubemapFace nzCubemapFace_Max = nzCubemapFace_NegativeZ }; +enum nzDataStorageFlags +{ + nzDataStorage_Hardware = 0x1, + nzDataStorage_Software = 0x2, + + nzDataStorage_Both = nzDataStorage_Hardware | nzDataStorage_Software, + + nzDataStorage_Max = nzDataStorage_Software*2-1 +}; + enum nzEventType { nzEventType_GainedFocus, @@ -130,6 +131,7 @@ enum nzPixelFormat { nzPixelFormat_Undefined = -1, + nzPixelFormat_A8, // 1*uint8 nzPixelFormat_BGR8, // 3*uint8 nzPixelFormat_BGRA8, // 4*uint8 nzPixelFormat_DXT1, @@ -217,16 +219,39 @@ enum nzPrimitiveMode nzPrimitiveMode_Max = nzPrimitiveMode_TriangleFan }; +enum nzTextAlign +{ + nzTextAlign_Left, + nzTextAlign_Middle, + nzTextAlign_Right, + + nzTextAlign_Max = nzTextAlign_Right +}; + +enum nzTextStyleFlags +{ + nzTextStyle_Regular = 0x0, + + nzTextStyle_Bold = 0x1, + nzTextStyle_Italic = 0x2, + nzTextStyle_StrikeThrough = 0x4, + nzTextStyle_Underlined = 0x8, + + nzTextStyle_Max = nzTextStyle_Underlined*2-1 +}; + enum nzVertexComponent { nzVertexComponent_Unused = -1, + // Nous nous limitons à 16 composants de sommets car c'est le minimum supporté par le GPU nzVertexComponent_InstanceData0, nzVertexComponent_InstanceData1, nzVertexComponent_InstanceData2, nzVertexComponent_InstanceData3, nzVertexComponent_InstanceData4, nzVertexComponent_InstanceData5, + nzVertexComponent_Color, nzVertexComponent_Normal, nzVertexComponent_Position, nzVertexComponent_Tangent, @@ -236,22 +261,24 @@ enum nzVertexComponent nzVertexComponent_Userdata2, nzVertexComponent_Userdata3, nzVertexComponent_Userdata4, - nzVertexComponent_Userdata5, nzVertexComponent_FirstInstanceData = nzVertexComponent_InstanceData0, - nzVertexComponent_FirstVertexData = nzVertexComponent_Normal, + nzVertexComponent_FirstVertexData = nzVertexComponent_Color, nzVertexComponent_LastInstanceData = nzVertexComponent_InstanceData5, - nzVertexComponent_LastVertexData = nzVertexComponent_Userdata5, + nzVertexComponent_LastVertexData = nzVertexComponent_Userdata4, - nzVertexComponent_Max = nzVertexComponent_Userdata5 + nzVertexComponent_Max = nzVertexComponent_Userdata4 }; enum nzVertexLayout { // Déclarations destinées au rendu nzVertexLayout_XY, + nzVertexLayout_XY_Color, nzVertexLayout_XY_UV, nzVertexLayout_XYZ, + nzVertexLayout_XYZ_Color, + nzVertexLayout_XYZ_Color_UV, nzVertexLayout_XYZ_Normal, nzVertexLayout_XYZ_Normal_UV, nzVertexLayout_XYZ_Normal_UV_Tangent, diff --git a/include/Nazara/Utility/Event.hpp b/include/Nazara/Utility/Event.hpp index 50062e7b5..0403bd51e 100644 --- a/include/Nazara/Utility/Event.hpp +++ b/include/Nazara/Utility/Event.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,6 +9,7 @@ #ifndef NAZARA_EVENT_HPP #define NAZARA_EVENT_HPP +#include #include #include diff --git a/include/Nazara/Utility/Font.hpp b/include/Nazara/Utility/Font.hpp new file mode 100644 index 000000000..f812bc047 --- /dev/null +++ b/include/Nazara/Utility/Font.hpp @@ -0,0 +1,147 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_FONT_HPP +#define NAZARA_FONT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct NAZARA_API NzFontParams +{ + bool IsValid() const; +}; + +class NzFont; +class NzFontData; + +struct NzFontGlyph; + +using NzFontConstListener = NzObjectListenerWrapper; +using NzFontConstRef = NzObjectRef; +using NzFontListener = NzObjectListenerWrapper; +using NzFontLoader = NzResourceLoader; +using NzFontRef = NzObjectRef; + +class NAZARA_API NzFont : public NzRefCounted, public NzResource, NzAbstractAtlas::Listener, NzNonCopyable +{ + friend NzFontLoader; + + public: + struct Glyph; + struct SizeInfo; + + NzFont(); + ~NzFont(); + + void ClearGlyphCache(); + void ClearKerningCache(); + void ClearSizeInfoCache(); + + bool Create(NzFontData* data); + void Destroy(); + + bool ExtractGlyph(unsigned int characterSize, char32_t character, nzUInt32 style, NzFontGlyph* glyph) const; + + const std::shared_ptr& GetAtlas() const; + unsigned int GetCachedGlyphCount(unsigned int characterSize, nzUInt32 style) const; + unsigned int GetCachedGlyphCount() const; + NzString GetFamilyName() const; + int GetKerning(unsigned int characterSize, char32_t first, char32_t second) const; + const Glyph& GetGlyph(unsigned int characterSize, nzUInt32 style, char32_t character) const; + unsigned int GetGlyphBorder() const; + unsigned int GetMinimumStepSize() const; + const SizeInfo& GetSizeInfo(unsigned int characterSize) const; + NzString GetStyleName() const; + + bool IsValid() const; + + bool Precache(unsigned int characterSize, nzUInt32 style, char32_t character) const; + bool Precache(unsigned int characterSize, nzUInt32 style, const NzString& characterSet) const; + + // Open + bool OpenFromFile(const NzString& filePath, const NzFontParams& params = NzFontParams()); + bool OpenFromMemory(const void* data, std::size_t size, const NzFontParams& params = NzFontParams()); + bool OpenFromStream(NzInputStream& stream, const NzFontParams& params = NzFontParams()); + + void SetAtlas(const std::shared_ptr& atlas); + void SetGlyphBorder(unsigned int borderSize); + void SetMinimumStepSize(unsigned int minimumStepSize); + + static std::shared_ptr GetDefaultAtlas(); + static NzFont* GetDefault(); + static unsigned int GetDefaultGlyphBorder(); + static unsigned int GetDefaultMinimumStepSize(); + + static bool Initialize(); + + static void SetDefaultAtlas(const std::shared_ptr& atlas); + static void SetDefaultGlyphBorder(unsigned int borderSize); + static void SetDefaultMinimumStepSize(unsigned int minimumStepSize); + + static void Uninitialize(); + + enum ModicationCode + { + ModificationCode_AtlasChanged, + ModificationCode_AtlasLayerChanged, + ModificationCode_GlyphCacheCleared, + ModificationCode_KerningCacheCleared, + ModificationCode_SizeInfoCacheCleared + }; + + struct Glyph + { + NzRecti aabb; + NzRectui atlasRect; + bool requireFauxBold; + bool requireFauxItalic; + bool flipped; + bool valid; + int advance; + unsigned int layerIndex; + }; + + struct SizeInfo + { + int spaceAdvance; + unsigned int lineHeight; + float underlinePosition; + float underlineThickness; + }; + + private: + using GlyphMap = std::unordered_map; + + nzUInt64 ComputeKey(unsigned int characterSize, nzUInt32 style) const; + bool OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) override; + bool OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata) override; + void OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata) override; + const Glyph& PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, nzUInt32 style, char32_t character) const; + + std::shared_ptr m_atlas; + std::unique_ptr m_data; + mutable std::unordered_map> m_kerningCache; + mutable std::unordered_map m_glyphes; + mutable std::unordered_map m_sizeInfoCache; + unsigned int m_glyphBorder; + unsigned int m_minimumStepSize; + + static std::shared_ptr s_defaultAtlas; + static NzFont* s_defaultFont; + static NzFontLoader::LoaderList s_loaders; + static unsigned int s_defaultGlyphBorder; + static unsigned int s_defaultMinimumStepSize; +}; + +#endif // NAZARA_FONT_HPP diff --git a/include/Nazara/Utility/FontData.hpp b/include/Nazara/Utility/FontData.hpp new file mode 100644 index 000000000..11f0e6c9e --- /dev/null +++ b/include/Nazara/Utility/FontData.hpp @@ -0,0 +1,38 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_FONTDATA_HPP +#define NAZARA_FONTDATA_HPP + +#include +#include + +struct NzFontGlyph; + +class NAZARA_API NzFontData +{ + public: + NzFontData() = default; + virtual ~NzFontData(); + + virtual bool ExtractGlyph(unsigned int characterSize, char32_t character, nzUInt32 style, NzFontGlyph* dst) = 0; + + virtual NzString GetFamilyName() const = 0; + virtual NzString GetStyleName() const = 0; + + virtual bool HasKerning() const = 0; + + virtual bool IsScalable() const = 0; + + virtual int QueryKerning(unsigned int characterSize, char32_t first, char32_t second) const = 0; + virtual unsigned int QueryLineHeight(unsigned int characterSize) const = 0; + virtual float QueryUnderlinePosition(unsigned int characterSize) const = 0; + virtual float QueryUnderlineThickness(unsigned int characterSize) const = 0; + + virtual bool SupportsStyle(nzUInt32 style) const = 0; +}; + +#endif // NAZARA_FONTDATA_HPP diff --git a/include/Nazara/Utility/FontGlyph.hpp b/include/Nazara/Utility/FontGlyph.hpp new file mode 100644 index 000000000..516052be4 --- /dev/null +++ b/include/Nazara/Utility/FontGlyph.hpp @@ -0,0 +1,19 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_FONTGLYPH_HPP +#define NAZARA_FONTGLYPH_HPP + +#include + +struct NzFontGlyph +{ + NzImage image; + NzRecti aabb; + int advance; +}; + +#endif // NAZARA_FONTGLYPH_HPP diff --git a/include/Nazara/Utility/GuillotineImageAtlas.hpp b/include/Nazara/Utility/GuillotineImageAtlas.hpp new file mode 100644 index 000000000..bf65129f6 --- /dev/null +++ b/include/Nazara/Utility/GuillotineImageAtlas.hpp @@ -0,0 +1,67 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_GUILLOTINEIMAGEATLAS_HPP +#define NAZARA_GUILLOTINEIMAGEATLAS_HPP + +#include +#include +#include +#include +#include +#include +#include + +class NAZARA_API NzGuillotineImageAtlas : public NzAbstractAtlas +{ + public: + NzGuillotineImageAtlas(); + virtual ~NzGuillotineImageAtlas(); + + void Clear(); + void Free(NzSparsePtr rects, NzSparsePtr layers, unsigned int count); + + NzGuillotineBinPack::FreeRectChoiceHeuristic GetRectChoiceHeuristic() const; + NzGuillotineBinPack::GuillotineSplitHeuristic GetRectSplitHeuristic() const; + NzAbstractImage* GetLayer(unsigned int layerIndex) const; + unsigned int GetLayerCount() const; + nzUInt32 GetStorage() const; + + bool Insert(const NzImage& image, NzRectui* rect, bool* flipped, unsigned int* layerIndex); + + void SetRectChoiceHeuristic(NzGuillotineBinPack::FreeRectChoiceHeuristic heuristic); + void SetRectSplitHeuristic(NzGuillotineBinPack::GuillotineSplitHeuristic heuristic); + + protected: + struct Layer; + + virtual NzAbstractImage* ResizeImage(NzAbstractImage* oldImage, const NzVector2ui& size) const; + bool ResizeLayer(Layer& layer, const NzVector2ui& size); + + struct QueuedGlyph + { + NzImage image; + NzRectui rect; + bool flipped; + }; + + struct Layer + { + std::vector queuedGlyphs; + std::unique_ptr image; + NzGuillotineBinPack binPack; + unsigned int freedRectangles = 0; + }; + + private: + void ProcessGlyphQueue(Layer& layer) const; + + mutable std::vector m_layers; + NzGuillotineBinPack::FreeRectChoiceHeuristic m_rectChoiceHeuristic; + NzGuillotineBinPack::GuillotineSplitHeuristic m_rectSplitHeuristic; +}; + +#endif // NAZARA_GUILLOTINEIMAGEATLAS_HPP diff --git a/include/Nazara/Utility/Icon.hpp b/include/Nazara/Utility/Icon.hpp index 67dbc0791..369cc7639 100644 --- a/include/Nazara/Utility/Icon.hpp +++ b/include/Nazara/Utility/Icon.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/Image.hpp b/include/Nazara/Utility/Image.hpp index beff250a3..210ad340b 100644 --- a/include/Nazara/Utility/Image.hpp +++ b/include/Nazara/Utility/Image.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -10,16 +10,13 @@ #include #include #include +#include #include #include #include #include -#include -#include -#include +#include #include -#include -#include #include ///TODO: Filtres @@ -37,11 +34,13 @@ struct NAZARA_API NzImageParams class NzImage; +using NzImageConstListener = NzObjectListenerWrapper; using NzImageConstRef = NzObjectRef; +using NzImageListener = NzObjectListenerWrapper; using NzImageLoader = NzResourceLoader; using NzImageRef = NzObjectRef; -class NAZARA_API NzImage : public NzRefCounted, public NzResource +class NAZARA_API NzImage : public NzAbstractImage, public NzRefCounted, public NzResource { friend NzImageLoader; @@ -51,7 +50,6 @@ class NAZARA_API NzImage : public NzRefCounted, public NzResource NzImage(); NzImage(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth = 1, nzUInt8 levelCount = 1); NzImage(const NzImage& image); - NzImage(NzImage&& image) noexcept; NzImage(SharedImage* sharedImage); ~NzImage(); @@ -69,22 +67,20 @@ class NAZARA_API NzImage : public NzRefCounted, public NzResource bool FlipHorizontally(); bool FlipVertically(); - nzUInt8 GetBytesPerPixel() const; const nzUInt8* GetConstPixels(unsigned int x = 0, unsigned int y = 0, unsigned int z = 0, nzUInt8 level = 0) const; unsigned int GetDepth(nzUInt8 level = 0) const; nzPixelFormat GetFormat() const; unsigned int GetHeight(nzUInt8 level = 0) const; nzUInt8 GetLevelCount() const; nzUInt8 GetMaxLevel() const; + unsigned int GetMemoryUsage() const; + unsigned int GetMemoryUsage(nzUInt8 level) const; NzColor GetPixelColor(unsigned int x, unsigned int y = 0, unsigned int z = 0) const; nzUInt8* GetPixels(unsigned int x = 0, unsigned int y = 0, unsigned int z = 0, nzUInt8 level = 0); - unsigned int GetSize() const; - unsigned int GetSize(nzUInt8 level) const; + NzVector3ui GetSize(nzUInt8 level = 0) const; nzImageType GetType() const; unsigned int GetWidth(nzUInt8 level = 0) const; - bool IsCompressed() const; - bool IsCubemap() const; bool IsValid() const; // Load @@ -92,6 +88,12 @@ class NAZARA_API NzImage : public NzRefCounted, public NzResource bool LoadFromMemory(const void* data, std::size_t size, const NzImageParams& params = NzImageParams()); bool LoadFromStream(NzInputStream& stream, const NzImageParams& params = NzImageParams()); + // LoadArray + bool LoadArrayFromFile(const NzString& filePath, const NzImageParams& imageParams = NzImageParams(), const NzVector2ui& atlasSize = NzVector2ui(2, 2)); + bool LoadArrayFromImage(const NzImage& image, const NzVector2ui& atlasSize = NzVector2ui(2, 2)); + bool LoadArrayFromMemory(const void* data, std::size_t size, const NzImageParams& imageParams = NzImageParams(), const NzVector2ui& atlasSize = NzVector2ui(2, 2)); + bool LoadArrayFromStream(NzInputStream& stream, const NzImageParams& imageParams = NzImageParams(), const NzVector2ui& atlasSize = NzVector2ui(2, 2)); + // LoadCubemap bool LoadCubemapFromFile(const NzString& filePath, const NzImageParams& imageParams = NzImageParams(), const NzCubemapParams& cubemapParams = NzCubemapParams()); bool LoadCubemapFromImage(const NzImage& image, const NzCubemapParams& params = NzCubemapParams()); @@ -101,15 +103,15 @@ class NAZARA_API NzImage : public NzRefCounted, public NzResource void SetLevelCount(nzUInt8 levelCount); bool SetPixelColor(const NzColor& color, unsigned int x, unsigned int y = 0, unsigned int z = 0); - void Update(const nzUInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0); - void Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0); - void Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0); + bool Update(const nzUInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0); + bool Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0); + bool Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0); NzImage& operator=(const NzImage& image); - NzImage& operator=(NzImage&& image) noexcept; static void Copy(nzUInt8* destination, const nzUInt8* source, nzUInt8 bpp, unsigned int width, unsigned int height, unsigned int depth = 1, unsigned int dstWidth = 0, unsigned int dstHeight = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0); static nzUInt8 GetMaxLevel(unsigned int width, unsigned int height, unsigned int depth = 1); + static nzUInt8 GetMaxLevel(nzImageType type, unsigned int width, unsigned int height, unsigned int depth = 1); struct SharedImage { diff --git a/include/Nazara/Utility/IndexBuffer.hpp b/include/Nazara/Utility/IndexBuffer.hpp index 67b8a9f3e..52eb5730f 100644 --- a/include/Nazara/Utility/IndexBuffer.hpp +++ b/include/Nazara/Utility/IndexBuffer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -8,23 +8,25 @@ #define NAZARA_INDEXBUFFER_HPP #include +#include #include -#include #include class NzIndexBuffer; +using NzIndexBufferConstListener = NzObjectListenerWrapper; using NzIndexBufferConstRef = NzObjectRef; +using NzIndexBufferListener = NzObjectListenerWrapper; using NzIndexBufferRef = NzObjectRef; class NAZARA_API NzIndexBuffer : public NzRefCounted { public: NzIndexBuffer() = default; + NzIndexBuffer(bool largeIndices, NzBuffer* buffer); NzIndexBuffer(bool largeIndices, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset); - NzIndexBuffer(bool largeIndices, unsigned int length, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); + NzIndexBuffer(bool largeIndices, unsigned int length, nzUInt32 storage = nzDataStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); NzIndexBuffer(const NzIndexBuffer& indexBuffer); - NzIndexBuffer(NzIndexBuffer&& indexBuffer) noexcept; ~NzIndexBuffer(); unsigned int ComputeCacheMissCount() const; @@ -51,17 +53,16 @@ class NAZARA_API NzIndexBuffer : public NzRefCounted void Optimize(); void Reset(); + void Reset(bool largeIndices, NzBuffer* buffer); void Reset(bool largeIndices, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset); - void Reset(bool largeIndices, unsigned int length, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); + void Reset(bool largeIndices, unsigned int length, nzUInt32 storage = nzDataStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); void Reset(const NzIndexBuffer& indexBuffer); - void Reset(NzIndexBuffer&& indexBuffer) noexcept; - bool SetStorage(nzBufferStorage storage); + bool SetStorage(nzUInt32 storage); void Unmap() const; NzIndexBuffer& operator=(const NzIndexBuffer& indexBuffer); - NzIndexBuffer& operator=(NzIndexBuffer&& indexBuffer) noexcept; private: NzBufferRef m_buffer; diff --git a/include/Nazara/Utility/IndexIterator.hpp b/include/Nazara/Utility/IndexIterator.hpp index d989f90fb..b0eaa8cb8 100644 --- a/include/Nazara/Utility/IndexIterator.hpp +++ b/include/Nazara/Utility/IndexIterator.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/IndexIterator.inl b/include/Nazara/Utility/IndexIterator.inl index d7def8d59..38ac4e6f5 100644 --- a/include/Nazara/Utility/IndexIterator.inl +++ b/include/Nazara/Utility/IndexIterator.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/IndexMapper.hpp b/include/Nazara/Utility/IndexMapper.hpp index 4e53fb609..e06d1826f 100644 --- a/include/Nazara/Utility/IndexMapper.hpp +++ b/include/Nazara/Utility/IndexMapper.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/Joint.hpp b/include/Nazara/Utility/Joint.hpp index 64f48f034..1aec0d5dd 100644 --- a/include/Nazara/Utility/Joint.hpp +++ b/include/Nazara/Utility/Joint.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/Joystick.hpp b/include/Nazara/Utility/Joystick.hpp new file mode 100644 index 000000000..8260a9302 --- /dev/null +++ b/include/Nazara/Utility/Joystick.hpp @@ -0,0 +1,24 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_JOYSTICK_HPP +#define NAZARA_JOYSTICK_HPP + +#include +#include + +class NAZARA_API NzJoystick +{ + public: + NzJoystick() = delete; + ~NzJoystick() = delete; + + static unsigned int GetMaxJoystickCount(); + + static void Update(); +}; + +#endif // NAZARA_JOYSTICK_HPP diff --git a/include/Nazara/Utility/Keyboard.hpp b/include/Nazara/Utility/Keyboard.hpp index f9f5e5702..475ec7e91 100644 --- a/include/Nazara/Utility/Keyboard.hpp +++ b/include/Nazara/Utility/Keyboard.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/Mesh.hpp b/include/Nazara/Utility/Mesh.hpp index 9a3480741..900dc013e 100644 --- a/include/Nazara/Utility/Mesh.hpp +++ b/include/Nazara/Utility/Mesh.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include #include @@ -25,18 +25,21 @@ struct NAZARA_API NzMeshParams { NzMeshParams(); // Vérifie que le storage par défaut est supporté (software autrement) - // Si ceci sera le stockage utilisé par les buffers - nzBufferStorage storage = nzBufferStorage_Hardware; - // La mise à l'échelle éventuelle que subira le mesh NzVector3f scale = NzVector3f::Unit(); + // Si ceci sera le stockage utilisé par les buffers + nzUInt32 storage = nzDataStorage_Hardware; + // Charger une version animée du mesh si possible ? bool animated = true; // Faut-il centrer le mesh autour de l'origine ? bool center = false; + // Faut-il retourner les UV ? + bool flipUVs = false; + // Faut-il optimiser les index buffers ? (Rendu plus rapide, mais le chargement dure plus longtemps) bool optimizeIndexBuffers = true; @@ -50,13 +53,15 @@ class NzPrimitiveList; typedef NzVertexStruct_XYZ_Normal_UV_Tangent NzMeshVertex; typedef NzVertexStruct_XYZ_Normal_UV_Tangent_Skinning NzSkeletalMeshVertex; +using NzMeshConstListener = NzObjectListenerWrapper; using NzMeshConstRef = NzObjectRef; +using NzMeshListener = NzObjectListenerWrapper; using NzMeshLoader = NzResourceLoader; using NzMeshRef = NzObjectRef; struct NzMeshImpl; -class NAZARA_API NzMesh : public NzRefCounted, public NzResource, NzObjectListener +class NAZARA_API NzMesh : public NzRefCounted, public NzResource { friend NzMeshLoader; @@ -119,8 +124,6 @@ class NAZARA_API NzMesh : public NzRefCounted, public NzResource, NzObjectListen void Transform(const NzMatrix4f& matrix); private: - void OnObjectReleased(const NzRefCounted* object, int index) override; - NzMeshImpl* m_impl = nullptr; static NzMeshLoader::LoaderList s_loaders; diff --git a/include/Nazara/Utility/MeshData.hpp b/include/Nazara/Utility/MeshData.hpp index f2bac177b..ff12d3681 100644 --- a/include/Nazara/Utility/MeshData.hpp +++ b/include/Nazara/Utility/MeshData.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/Mouse.hpp b/include/Nazara/Utility/Mouse.hpp index 843504ae9..8dad35bbd 100644 --- a/include/Nazara/Utility/Mouse.hpp +++ b/include/Nazara/Utility/Mouse.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/Node.hpp b/include/Nazara/Utility/Node.hpp index 290f3a933..7f9662d33 100644 --- a/include/Nazara/Utility/Node.hpp +++ b/include/Nazara/Utility/Node.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -24,39 +24,38 @@ class NAZARA_API NzNode void EnsureDerivedUpdate() const; void EnsureTransformMatrixUpdate() const; - NzVector3f GetBackward() const; + virtual NzVector3f GetBackward() const; const std::vector& GetChilds() const; - NzVector3f GetDown() const; - NzVector3f GetForward() const; + virtual NzVector3f GetDown() const; + virtual NzVector3f GetForward() const; bool GetInheritPosition() const; bool GetInheritRotation() const; bool GetInheritScale() const; NzVector3f GetInitialPosition() const; NzQuaternionf GetInitialRotation() const; NzVector3f GetInitialScale() const; - NzVector3f GetLeft() const; - const NzString& GetName() const; + virtual NzVector3f GetLeft() const; virtual nzNodeType GetNodeType() const; const NzNode* GetParent() const; NzVector3f GetPosition(nzCoordSys coordSys = nzCoordSys_Global) const; - NzVector3f GetRight() const; + virtual NzVector3f GetRight() const; NzQuaternionf GetRotation(nzCoordSys coordSys = nzCoordSys_Global) const; NzVector3f GetScale(nzCoordSys coordSys = nzCoordSys_Global) const; const NzMatrix4f& GetTransformMatrix() const; - NzVector3f GetUp() const; + virtual NzVector3f GetUp() const; bool HasChilds() const; NzNode& Interpolate(const NzNode& nodeA, const NzNode& nodeB, float interpolation, nzCoordSys coordSys = nzCoordSys_Global); NzNode& Move(const NzVector3f& movement, nzCoordSys coordSys = nzCoordSys_Local); - NzNode& Move(float movementX, float movementY, float movementZ, nzCoordSys coordSys = nzCoordSys_Local); + NzNode& Move(float movementX, float movementY, float movementZ = 0.f, nzCoordSys coordSys = nzCoordSys_Local); NzNode& Rotate(const NzQuaternionf& rotation, nzCoordSys coordSys = nzCoordSys_Local); NzNode& Scale(const NzVector3f& scale); NzNode& Scale(float scale); - NzNode& Scale(float scaleX, float scaleY, float scaleZ); + NzNode& Scale(float scaleX, float scaleY, float scaleZ = 1.f); void SetInheritRotation(bool inheritRotation); void SetInheritScale(bool inheritScale); @@ -64,18 +63,17 @@ class NAZARA_API NzNode void SetInitialRotation(const NzQuaternionf& quat); void SetInitialScale(const NzVector3f& scale); void SetInitialScale(float scale); - void SetInitialScale(float scaleX, float scaleY, float scaleZ); + void SetInitialScale(float scaleX, float scaleY, float scaleZ = 1.f); void SetInitialPosition(const NzVector3f& translation); - void SetInitialPosition(float translationX, float translationXY, float translationZ); - void SetName(const NzString& name); + void SetInitialPosition(float translationX, float translationXY, float translationZ = 0.f); void SetParent(const NzNode* node = nullptr, bool keepDerived = false); void SetParent(const NzNode& node, bool keepDerived = false); void SetPosition(const NzVector3f& translation, nzCoordSys coordSys = nzCoordSys_Local); - void SetPosition(float translationX, float translationXY, float translationZ, nzCoordSys coordSys = nzCoordSys_Local); + void SetPosition(float translationX, float translationY, float translationZ = 0.f, nzCoordSys coordSys = nzCoordSys_Local); void SetRotation(const NzQuaternionf& quat, nzCoordSys coordSys = nzCoordSys_Local); void SetScale(const NzVector3f& scale, nzCoordSys coordSys = nzCoordSys_Local); void SetScale(float scale, nzCoordSys coordSys = nzCoordSys_Local); - void SetScale(float scaleX, float scaleY, float scaleZ, nzCoordSys coordSys = nzCoordSys_Local); + void SetScale(float scaleX, float scaleY, float scaleZ = 1.f, nzCoordSys coordSys = nzCoordSys_Local); void SetTransformMatrix(const NzMatrix4f& matrix); // Local -> global @@ -95,7 +93,7 @@ class NAZARA_API NzNode virtual void InvalidateNode(); virtual void OnParenting(const NzNode* parent); void RemoveChild(NzNode* node) const; - void UpdateDerived() const; + virtual void UpdateDerived() const; virtual void UpdateTransformMatrix() const; mutable std::vector m_childs; @@ -103,7 +101,6 @@ class NAZARA_API NzNode mutable NzQuaternionf m_derivedRotation; NzQuaternionf m_initialRotation; NzQuaternionf m_rotation; - NzString m_name; mutable NzVector3f m_derivedPosition; mutable NzVector3f m_derivedScale; NzVector3f m_initialPosition; diff --git a/include/Nazara/Utility/PixelFormat.hpp b/include/Nazara/Utility/PixelFormat.hpp index 9f864e9ad..3e1aa254f 100644 --- a/include/Nazara/Utility/PixelFormat.hpp +++ b/include/Nazara/Utility/PixelFormat.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -13,6 +13,10 @@ #include #include +///TODO: Permettre la conversion automatique entre les formats via des renseignements de bits et de type pour chaque format. +/// Ce serait plus lent que la conversion spécialisée (qui ne disparaîtra donc pas) mais ça permettrait au moteur de faire la conversion +/// entre n'importe quels formats non-compressés. + class NzPixelFormat { friend class NzUtility; diff --git a/include/Nazara/Utility/PixelFormat.inl b/include/Nazara/Utility/PixelFormat.inl index c92f8b8c0..e399e408f 100644 --- a/include/Nazara/Utility/PixelFormat.inl +++ b/include/Nazara/Utility/PixelFormat.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -168,6 +168,9 @@ inline nzUInt8 NzPixelFormat::GetBitsPerPixel(nzPixelFormat format) { switch (format) { + case nzPixelFormat_A8: + return 8; + case nzPixelFormat_BGR8: return 24; @@ -287,20 +290,14 @@ inline nzUInt8 NzPixelFormat::GetBitsPerPixel(nzPixelFormat format) inline nzUInt8 NzPixelFormat::GetBytesPerPixel(nzPixelFormat format) { - nzUInt8 bytesPerPixel = GetBitsPerPixel(format)/8; - - #if NAZARA_UTILITY_SAFE - if (bytesPerPixel == 0) - NazaraWarning("This format is either invalid or using less than one byte per pixel"); - #endif - - return bytesPerPixel; + return GetBitsPerPixel(format)/8; } inline nzPixelFormatType NzPixelFormat::GetType(nzPixelFormat format) { switch (format) { + case nzPixelFormat_A8: case nzPixelFormat_BGR8: case nzPixelFormat_BGRA8: case nzPixelFormat_DXT1: @@ -372,6 +369,7 @@ inline bool NzPixelFormat::HasAlpha(nzPixelFormat format) { switch (format) { + case nzPixelFormat_A8: case nzPixelFormat_BGRA8: case nzPixelFormat_DXT3: case nzPixelFormat_DXT5: @@ -444,6 +442,7 @@ inline bool NzPixelFormat::IsCompressed(nzPixelFormat format) case nzPixelFormat_DXT5: return true; + case nzPixelFormat_A8: case nzPixelFormat_BGR8: case nzPixelFormat_BGRA8: case nzPixelFormat_L8: @@ -529,6 +528,9 @@ inline NzString NzPixelFormat::ToString(nzPixelFormat format) { switch (format) { + case nzPixelFormat_A8: + return "A8"; + case nzPixelFormat_BGR8: return "BGR8"; diff --git a/include/Nazara/Utility/Sequence.hpp b/include/Nazara/Utility/Sequence.hpp index 79bd08dcb..2497b7d0a 100644 --- a/include/Nazara/Utility/Sequence.hpp +++ b/include/Nazara/Utility/Sequence.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/SimpleTextDrawer.hpp b/include/Nazara/Utility/SimpleTextDrawer.hpp new file mode 100644 index 000000000..5793fdce2 --- /dev/null +++ b/include/Nazara/Utility/SimpleTextDrawer.hpp @@ -0,0 +1,60 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_SIMPLETEXTDRAWER_HPP +#define NAZARA_SIMPLETEXTDRAWER_HPP + +#include +#include +#include +#include +#include +#include +#include + +class NAZARA_API NzSimpleTextDrawer : public NzAbstractTextDrawer, NzObjectListener +{ + public: + NzSimpleTextDrawer(); + virtual ~NzSimpleTextDrawer() = default; + + const NzRectui& GetBounds() const; + unsigned int GetCharacterSize() const; + const NzColor& GetColor() const; + NzFont* GetFont() const; + nzUInt32 GetStyle() const; + + void SetCharacterSize(unsigned int characterSize); + void SetColor(const NzColor& color); + void SetFont(NzFont* font); + void SetStyle(nzUInt32 style); + void SetText(const NzString& str); + + static NzSimpleTextDrawer Draw(const NzString& str, unsigned int characterSize, nzUInt32 style = nzTextStyle_Regular, const NzColor& color = NzColor::White); + static NzSimpleTextDrawer Draw(NzFont* font, const NzString& str, unsigned int characterSize, nzUInt32 style = nzTextStyle_Regular, const NzColor& color = NzColor::White); + + private: + NzFont* GetFont(unsigned int index) const override; + unsigned int GetFontCount() const override; + const Glyph& GetGlyph(unsigned int index) const override; + unsigned int GetGlyphCount() const override; + + bool OnObjectModified(const NzRefCounted* object, int index, unsigned int code) override; + void OnObjectReleased(const NzRefCounted* object, int index) override; + void UpdateGlyphs() const; + + mutable std::vector m_glyphs; + NzColor m_color; + NzFontRef m_font; + NzFontListener m_fontListener; // Doit se situer après le FontRef (pour être libéré avant) + mutable NzRectui m_bounds; + NzString m_text; + nzUInt32 m_style; + mutable bool m_glyphUpdated; + unsigned int m_characterSize; +}; + +#endif // NAZARA_SIMPLETEXTDRAWER_HPP diff --git a/include/Nazara/Utility/SkeletalMesh.hpp b/include/Nazara/Utility/SkeletalMesh.hpp index 01ab224bb..51dc5e0c3 100644 --- a/include/Nazara/Utility/SkeletalMesh.hpp +++ b/include/Nazara/Utility/SkeletalMesh.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -8,12 +8,15 @@ #define NAZARA_SKELETALMESH_HPP #include -#include +#include +#include #include class NzSkeletalMesh; +using NzSkeletalMeshConstListener = NzObjectListenerWrapper; using NzSkeletalMeshConstRef = NzObjectRef; +using NzSkeletalMeshListener = NzObjectListenerWrapper; using NzSkeletalMeshRef = NzObjectRef; class NAZARA_API NzSkeletalMesh final : public NzSubMesh diff --git a/include/Nazara/Utility/Skeleton.hpp b/include/Nazara/Utility/Skeleton.hpp index bbe780a01..465dcf9c8 100644 --- a/include/Nazara/Utility/Skeleton.hpp +++ b/include/Nazara/Utility/Skeleton.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -8,11 +8,20 @@ #define NAZARA_SKELETON_HPP #include +#include +#include #include #include #include #include +class NzSkeleton; + +using NzSkeletonConstListener = NzObjectListenerWrapper; +using NzSkeletonConstRef = NzObjectRef; +using NzSkeletonListener = NzObjectListenerWrapper; +using NzSkeletonRef = NzObjectRef; + struct NzSkeletonImpl; class NAZARA_API NzSkeleton : public NzRefCounted diff --git a/include/Nazara/Utility/StaticMesh.hpp b/include/Nazara/Utility/StaticMesh.hpp index 45d4f6ef4..d94986df2 100644 --- a/include/Nazara/Utility/StaticMesh.hpp +++ b/include/Nazara/Utility/StaticMesh.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -8,11 +8,15 @@ #define NAZARA_STATICMESH_HPP #include +#include +#include #include class NzStaticMesh; +using NzStaticMeshConstListener = NzObjectListenerWrapper; using NzStaticMeshConstRef = NzObjectRef; +using NzStaticMeshListener = NzObjectListenerWrapper; using NzStaticMeshRef = NzObjectRef; class NAZARA_API NzStaticMesh final : public NzSubMesh diff --git a/include/Nazara/Utility/SubMesh.hpp b/include/Nazara/Utility/SubMesh.hpp index db9b0c07c..c14391e00 100644 --- a/include/Nazara/Utility/SubMesh.hpp +++ b/include/Nazara/Utility/SubMesh.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -8,6 +8,7 @@ #define NAZARA_SUBMESH_HPP #include +#include #include #include #include @@ -19,7 +20,9 @@ class NzMesh; class NzSubMesh; +using NzSubMeshConstListener = NzObjectListenerWrapper; using NzSubMeshConstRef = NzObjectRef; +using NzSubMeshListener = NzObjectListenerWrapper; using NzSubMeshRef = NzObjectRef; class NAZARA_API NzSubMesh : public NzRefCounted diff --git a/include/Nazara/Utility/TriangleIterator.hpp b/include/Nazara/Utility/TriangleIterator.hpp index 48c68e86b..59288fa1d 100644 --- a/include/Nazara/Utility/TriangleIterator.hpp +++ b/include/Nazara/Utility/TriangleIterator.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/Utility.hpp b/include/Nazara/Utility/Utility.hpp index 94749ec4b..fa40d5135 100644 --- a/include/Nazara/Utility/Utility.hpp +++ b/include/Nazara/Utility/Utility.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/VertexBuffer.hpp b/include/Nazara/Utility/VertexBuffer.hpp index 593d6edf2..5e15d6125 100644 --- a/include/Nazara/Utility/VertexBuffer.hpp +++ b/include/Nazara/Utility/VertexBuffer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -8,6 +8,7 @@ #define NAZARA_VERTEXBUFFER_HPP #include +#include #include #include #include @@ -15,17 +16,19 @@ class NzVertexBuffer; +using NzVertexBufferConstListener = NzObjectListenerWrapper; using NzVertexBufferConstRef = NzObjectRef; +using NzVertexBufferListener = NzObjectListenerWrapper; using NzVertexBufferRef = NzObjectRef; class NAZARA_API NzVertexBuffer : public NzRefCounted { public: NzVertexBuffer() = default; + NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer); NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset); - NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); + NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzUInt32 storage = nzDataStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); NzVertexBuffer(const NzVertexBuffer& vertexBuffer); - NzVertexBuffer(NzVertexBuffer&& vertexBuffer) noexcept; ~NzVertexBuffer(); bool Fill(const void* data, unsigned int startVertex, unsigned int length, bool forceDiscard = false); @@ -47,18 +50,17 @@ class NAZARA_API NzVertexBuffer : public NzRefCounted void* MapRaw(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0) const; void Reset(); + void Reset(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer); void Reset(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset); - void Reset(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); + void Reset(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzUInt32 storage = nzDataStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); void Reset(const NzVertexBuffer& vertexBuffer); - void Reset(NzVertexBuffer&& vertexBuffer) noexcept; - bool SetStorage(nzBufferStorage storage); + bool SetStorage(nzUInt32 storage); void SetVertexDeclaration(const NzVertexDeclaration* vertexDeclaration); void Unmap() const; NzVertexBuffer& operator=(const NzVertexBuffer& vertexBuffer); - NzVertexBuffer& operator=(NzVertexBuffer&& vertexBuffer) noexcept; private: NzBufferRef m_buffer; diff --git a/include/Nazara/Utility/VertexDeclaration.hpp b/include/Nazara/Utility/VertexDeclaration.hpp index 55f37c389..c8c086f56 100644 --- a/include/Nazara/Utility/VertexDeclaration.hpp +++ b/include/Nazara/Utility/VertexDeclaration.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -8,13 +8,16 @@ #define NAZARA_VERTEXDECLARATION_HPP #include +#include #include #include #include class NzVertexDeclaration; +using NzVertexDeclarationConstListener = NzObjectListenerWrapper; using NzVertexDeclarationConstRef = NzObjectRef; +using NzVertexDeclarationListener = NzObjectListenerWrapper; using NzVertexDeclarationRef = NzObjectRef; class NAZARA_API NzVertexDeclaration : public NzRefCounted @@ -45,9 +48,9 @@ class NAZARA_API NzVertexDeclaration : public NzRefCounted struct Component { - nzComponentType type; - bool enabled = false; - unsigned int offset; + nzComponentType type; // Le type de donnée + bool enabled = false; // Ce composant est-il activé ?/ + unsigned int offset; // La position, en octets, de la première donnée /* ** -Lynix: diff --git a/include/Nazara/Utility/VertexMapper.hpp b/include/Nazara/Utility/VertexMapper.hpp index 446d1450d..8bfdd4ca0 100644 --- a/include/Nazara/Utility/VertexMapper.hpp +++ b/include/Nazara/Utility/VertexMapper.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,18 +9,16 @@ #include #include -#include -#include #include #include -#include -#include +#include class NzSubMesh; class NAZARA_API NzVertexMapper { public: + NzVertexMapper(NzVertexBuffer* vertexBuffer, unsigned int vertexCount); NzVertexMapper(NzSubMesh* subMesh); ~NzVertexMapper(); @@ -31,7 +29,6 @@ class NAZARA_API NzVertexMapper private: NzBufferMapper m_mapper; - NzVertexDeclarationConstRef m_declaration; unsigned int m_vertexCount; }; diff --git a/include/Nazara/Utility/VertexMapper.inl b/include/Nazara/Utility/VertexMapper.inl index 19bfa18c6..34270b084 100644 --- a/include/Nazara/Utility/VertexMapper.inl +++ b/include/Nazara/Utility/VertexMapper.inl @@ -1,21 +1,26 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include template NzSparsePtr NzVertexMapper::GetComponentPtr(nzVertexComponent component) { + // On récupère la déclaration depuis le buffer + const NzVertexDeclaration* declaration = m_mapper.GetBuffer()->GetVertexDeclaration(); + + // Ensuite le composant qui nous intéresse bool enabled; nzComponentType type; unsigned int offset; - m_declaration->GetComponent(component, &enabled, &type, &offset); + declaration->GetComponent(component, &enabled, &type, &offset); if (enabled) { ///TODO: Vérifier le rapport entre le type de l'attribut et le type template ? - return NzSparsePtr(static_cast(m_mapper.GetPointer()) + offset, m_declaration->GetStride()); + return NzSparsePtr(static_cast(m_mapper.GetPointer()) + offset, declaration->GetStride()); } else { diff --git a/include/Nazara/Utility/VertexStruct.hpp b/include/Nazara/Utility/VertexStruct.hpp index 62c01c439..2f4130398 100644 --- a/include/Nazara/Utility/VertexStruct.hpp +++ b/include/Nazara/Utility/VertexStruct.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -7,6 +7,7 @@ #ifndef NAZARA_VERTEXSTRUCT_HPP #define NAZARA_VERTEXSTRUCT_HPP +#include #include #include @@ -17,7 +18,12 @@ struct NzVertexStruct_XY NzVector2f position; }; -struct NzVertexStruct_XY_UV : public NzVertexStruct_XY +struct NzVertexStruct_XY_Color : NzVertexStruct_XY +{ + NzColor color; +}; + +struct NzVertexStruct_XY_UV : NzVertexStruct_XY { NzVector2f uv; }; @@ -29,29 +35,39 @@ struct NzVertexStruct_XYZ NzVector3f position; }; -struct NzVertexStruct_XYZ_Normal : public NzVertexStruct_XYZ +struct NzVertexStruct_XYZ_Color : NzVertexStruct_XYZ { - NzVector3f normal; + NzColor color; }; -struct NzVertexStruct_XYZ_Normal_UV : public NzVertexStruct_XYZ_Normal +struct NzVertexStruct_XYZ_Color_UV : NzVertexStruct_XYZ_Color { NzVector2f uv; }; -struct NzVertexStruct_XYZ_Normal_UV_Tangent : public NzVertexStruct_XYZ_Normal_UV +struct NzVertexStruct_XYZ_Normal : NzVertexStruct_XYZ +{ + NzVector3f normal; +}; + +struct NzVertexStruct_XYZ_Normal_UV : NzVertexStruct_XYZ_Normal +{ + NzVector2f uv; +}; + +struct NzVertexStruct_XYZ_Normal_UV_Tangent : NzVertexStruct_XYZ_Normal_UV { NzVector3f tangent; }; -struct NzVertexStruct_XYZ_UV : public NzVertexStruct_XYZ +struct NzVertexStruct_XYZ_UV : NzVertexStruct_XYZ { NzVector2f uv; }; /************************* Structures 3D (+ Skinning) ************************/ -struct NzVertexStruct_XYZ_Normal_UV_Tangent_Skinning : public NzVertexStruct_XYZ_Normal_UV_Tangent +struct NzVertexStruct_XYZ_Normal_UV_Tangent_Skinning : NzVertexStruct_XYZ_Normal_UV_Tangent { nzInt32 weightCount; diff --git a/include/Nazara/Utility/VideoMode.hpp b/include/Nazara/Utility/VideoMode.hpp index 5a2b476df..57b0c7d63 100644 --- a/include/Nazara/Utility/VideoMode.hpp +++ b/include/Nazara/Utility/VideoMode.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/Window.hpp b/include/Nazara/Utility/Window.hpp index 9e4b75d38..1850c07a4 100644 --- a/include/Nazara/Utility/Window.hpp +++ b/include/Nazara/Utility/Window.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Utility/WindowHandle.hpp b/include/Nazara/Utility/WindowHandle.hpp index 9b26b8fbc..bebbc1107 100644 --- a/include/Nazara/Utility/WindowHandle.hpp +++ b/include/Nazara/Utility/WindowHandle.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Audio/Audio.cpp b/src/Nazara/Audio/Audio.cpp index 656dccdcd..3ef54bf46 100644 --- a/src/Nazara/Audio/Audio.cpp +++ b/src/Nazara/Audio/Audio.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Audio/Loaders/sndfile.hpp b/src/Nazara/Audio/Loaders/sndfile.hpp index ad5ffb562..5ab600bce 100644 --- a/src/Nazara/Audio/Loaders/sndfile.hpp +++ b/src/Nazara/Audio/Loaders/sndfile.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Audio/Loaders/sndfile/Loader.cpp b/src/Nazara/Audio/Loaders/sndfile/Loader.cpp index 62a1268ab..d1b8be31f 100644 --- a/src/Nazara/Audio/Loaders/sndfile/Loader.cpp +++ b/src/Nazara/Audio/Loaders/sndfile/Loader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -61,7 +61,7 @@ namespace sf_count_t Tell(void* user_data) { - NzInputStream* stream = reinterpret_cast(user_data); + NzInputStream* stream = static_cast(user_data); return stream->GetCursorPos(); } @@ -106,13 +106,21 @@ namespace bool Open(const NzString& filePath, bool forceMono) { - if (!m_file.Open(filePath, NzFile::ReadOnly)) + std::unique_ptr file(new NzFile); + if (!file->Open(filePath, NzFile::ReadOnly)) { NazaraError("Failed to open stream from file: " + NzError::GetLastError()); return false; } + m_ownedStream = std::move(file); - return Open(m_file, forceMono); + return Open(*m_ownedStream, forceMono); + } + + bool Open(const void* data, std::size_t size, bool forceMono) + { + m_ownedStream.reset(new NzMemoryStream(data, size)); + return Open(*m_ownedStream, forceMono); } bool Open(NzInputStream& stream, bool forceMono) @@ -185,8 +193,8 @@ namespace private: std::vector m_mixBuffer; + std::unique_ptr m_ownedStream; nzAudioFormat m_format; - NzFile m_file; SNDFILE* m_handle; bool m_mixToMono; unsigned int m_duration; @@ -243,6 +251,28 @@ namespace return true; } + bool LoadMusicMemory(NzMusic* music, const void* data, std::size_t size, const NzMusicParams& parameters) + { + NazaraUnused(parameters); + + std::unique_ptr musicStream(new sndfileStream); + if (!musicStream->Open(data, size, parameters.forceMono)) + { + NazaraError("Failed to open music stream"); + return false; + } + + if (!music->Create(musicStream.get())) + { + NazaraError("Failed to create music"); + return false; + } + + musicStream.release(); + + return true; + } + bool LoadMusicStream(NzMusic* music, NzInputStream& stream, const NzMusicParams& parameters) { NazaraUnused(parameters); @@ -342,12 +372,12 @@ namespace void NzLoaders_sndfile_Register() { - NzMusicLoader::RegisterLoader(IsSupported, CheckMusic, LoadMusicStream, LoadMusicFile); + NzMusicLoader::RegisterLoader(IsSupported, CheckMusic, LoadMusicStream, LoadMusicFile, LoadMusicMemory); NzSoundBufferLoader::RegisterLoader(IsSupported, CheckSoundBuffer, LoadSoundBuffer); } void NzLoaders_sndfile_Unregister() { - NzMusicLoader::UnregisterLoader(IsSupported, CheckMusic, LoadMusicStream, LoadMusicFile); + NzMusicLoader::UnregisterLoader(IsSupported, CheckMusic, LoadMusicStream, LoadMusicFile, LoadMusicMemory); NzSoundBufferLoader::UnregisterLoader(IsSupported, CheckSoundBuffer, LoadSoundBuffer); } diff --git a/src/Nazara/Audio/Music.cpp b/src/Nazara/Audio/Music.cpp index 16dfc64ec..50bff83be 100644 --- a/src/Nazara/Audio/Music.cpp +++ b/src/Nazara/Audio/Music.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -18,8 +19,8 @@ bool NzMusicParams::IsValid() const struct NzMusicImpl { ALenum audioFormat; + std::unique_ptr stream; std::vector chunkSamples; - NzSoundStream* stream; NzThread thread; bool loop = false; bool paused = false; @@ -50,7 +51,7 @@ bool NzMusic::Create(NzSoundStream* soundStream) m_impl->sampleRate = soundStream->GetSampleRate(); m_impl->audioFormat = NzOpenAL::AudioFormat[format]; m_impl->chunkSamples.resize(format * m_impl->sampleRate); // Une seconde de samples - m_impl->stream = soundStream; + m_impl->stream.reset(soundStream); return true; } @@ -61,7 +62,6 @@ void NzMusic::Destroy() { Stop(); - delete m_impl->stream; delete m_impl; m_impl = nullptr; } @@ -116,6 +116,7 @@ nzUInt32 NzMusic::GetPlayingOffset() const } #endif + ///TODO return 0; } @@ -131,6 +132,7 @@ nzSoundStatus NzMusic::GetStatus() const nzSoundStatus status = GetInternalStatus(); + // Pour compenser les éventuels retards (ou le laps de temps entre Play() et la mise en route du thread) if (m_impl->streaming && status == nzSoundStatus_Stopped) status = nzSoundStatus_Playing; @@ -180,14 +182,17 @@ void NzMusic::Play() } #endif + // Nous sommes déjà en train de jouer if (m_impl->streaming) { + // Peut-être sommes-nous en pause if (GetStatus() != nzSoundStatus_Playing) alSourcePlay(m_source); return; } + // Lancement du thread de streaming m_impl->stream->Seek(0); m_impl->streaming = true; m_impl->thread = NzThread(&NzMusic::MusicThread, this); @@ -195,6 +200,19 @@ void NzMusic::Play() return; } +void NzMusic::SetPlayingOffset(nzUInt32 offset) +{ + #if NAZARA_AUDIO_SAFE + if (!m_impl) + { + NazaraError("Music not created"); + return; + } + #endif + + ///TODO +} + void NzMusic::Stop() { #if NAZARA_AUDIO_SAFE @@ -217,39 +235,44 @@ bool NzMusic::FillAndQueueBuffer(unsigned int buffer) unsigned int sampleCount = m_impl->chunkSamples.size(); unsigned int sampleRead = 0; + // Lecture depuis le stream pour remplir le buffer for (;;) { sampleRead += m_impl->stream->Read(&m_impl->chunkSamples[sampleRead], sampleCount - sampleRead); - if (sampleRead < sampleCount && m_impl->loop) - m_impl->stream->Seek(0); - else - break; + if (sampleRead < sampleCount && !m_impl->loop) + break; // Fin du stream (On ne boucle pas) + + m_impl->stream->Seek(0); // On boucle au début du stream et on remplit à nouveau } + // Mise à jour du buffer (envoi à OpenAL) et placement dans la file d'attente if (sampleRead > 0) { alBufferData(buffer, m_impl->audioFormat, &m_impl->chunkSamples[0], sampleRead*sizeof(nzInt16), m_impl->sampleRate); alSourceQueueBuffers(m_source, 1, &buffer); } - return sampleRead != sampleCount; // Fin du fichier (N'arrive pas en cas de loop) + return sampleRead != sampleCount; // Fin du stream (N'arrive pas en cas de loop) } void NzMusic::MusicThread() { + // Allocation des buffers de streaming ALuint buffers[NAZARA_AUDIO_STREAMED_BUFFER_COUNT]; alGenBuffers(NAZARA_AUDIO_STREAMED_BUFFER_COUNT, buffers); for (unsigned int i = 0; i < NAZARA_AUDIO_STREAMED_BUFFER_COUNT; ++i) { - if (FillAndQueueBuffer(buffers[i])) // Fin du fichier ? - break; // Nous avons atteint la fin du fichier, inutile de rajouter des buffers + if (FillAndQueueBuffer(buffers[i])) + break; // Nous avons atteint la fin du stream, inutile de rajouter des buffers } alSourcePlay(m_source); + // Boucle de lecture (remplissage de nouveaux buffers au fur et à mesure) while (m_impl->streaming) { + // La lecture s'est arrêtée, nous avons atteint la fin du stream nzSoundStatus status = GetInternalStatus(); if (status == nzSoundStatus_Stopped) { @@ -257,6 +280,7 @@ void NzMusic::MusicThread() break; } + // On traite les buffers lus ALint processedCount = 0; alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &processedCount); @@ -268,11 +292,14 @@ void NzMusic::MusicThread() break; } + // On retourne dormir un peu NzThread::Sleep(50); } + // Arrêt de la lecture du son (dans le cas où ça ne serait pas déjà fait) alSourceStop(m_source); + // On supprime les buffers du stream ALint queuedBufferCount; alGetSourcei(m_source, AL_BUFFERS_QUEUED, &queuedBufferCount); diff --git a/src/Nazara/Audio/OpenAL.cpp b/src/Nazara/Audio/OpenAL.cpp index 2e15a4ba7..f156ec729 100644 --- a/src/Nazara/Audio/OpenAL.cpp +++ b/src/Nazara/Audio/OpenAL.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Audio/Sound.cpp b/src/Nazara/Audio/Sound.cpp index 69a24c054..da0e9a959 100644 --- a/src/Nazara/Audio/Sound.cpp +++ b/src/Nazara/Audio/Sound.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Audio/SoundBuffer.cpp b/src/Nazara/Audio/SoundBuffer.cpp index 7cd831313..6cbfcc6ba 100644 --- a/src/Nazara/Audio/SoundBuffer.cpp +++ b/src/Nazara/Audio/SoundBuffer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -23,7 +24,7 @@ struct NzSoundBufferImpl ALuint buffer; nzAudioFormat format; nzUInt32 duration; - nzInt16* samples; + std::unique_ptr samples; unsigned int sampleCount; unsigned int sampleRate; }; @@ -104,7 +105,7 @@ bool NzSoundBuffer::Create(nzAudioFormat format, unsigned int sampleCount, unsig m_impl->format = format; m_impl->sampleCount = sampleCount; m_impl->sampleRate = sampleRate; - m_impl->samples = new nzInt16[sampleCount]; + m_impl->samples.reset(new nzInt16[sampleCount]); std::memcpy(&m_impl->samples[0], samples, sampleCount*sizeof(nzInt16)); NotifyCreated(); @@ -117,7 +118,6 @@ void NzSoundBuffer::Destroy() { NotifyDestroy(); - delete[] m_impl->samples; delete m_impl; m_impl = nullptr; } @@ -159,7 +159,7 @@ const nzInt16* NzSoundBuffer::GetSamples() const } #endif - return m_impl->samples; + return m_impl->samples.get(); } unsigned int NzSoundBuffer::GetSampleCount() const diff --git a/src/Nazara/Audio/SoundEmitter.cpp b/src/Nazara/Audio/SoundEmitter.cpp index 54d326954..47b39a741 100644 --- a/src/Nazara/Audio/SoundEmitter.cpp +++ b/src/Nazara/Audio/SoundEmitter.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Audio/SoundStream.cpp b/src/Nazara/Audio/SoundStream.cpp index b10bd90a0..a81ea7e41 100644 --- a/src/Nazara/Audio/SoundStream.cpp +++ b/src/Nazara/Audio/SoundStream.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/AbstractHash.cpp b/src/Nazara/Core/AbstractHash.cpp index 838a62859..b388da5e2 100644 --- a/src/Nazara/Core/AbstractHash.cpp +++ b/src/Nazara/Core/AbstractHash.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/ByteArray.cpp b/src/Nazara/Core/ByteArray.cpp index 94903dd4d..16a7ed1b2 100644 --- a/src/Nazara/Core/ByteArray.cpp +++ b/src/Nazara/Core/ByteArray.cpp @@ -1,10 +1,10 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include -#include +#include #include #include #include @@ -404,11 +404,14 @@ nzUInt8 NzByteArray::operator[](unsigned int pos) const NzByteArray& NzByteArray::operator=(const NzByteArray& array) { - ReleaseArray(); + if (this != &array) + { + ReleaseArray(); - m_sharedArray = array.m_sharedArray; - if (m_sharedArray != &emptyArray) - m_sharedArray->refCount++; + m_sharedArray = array.m_sharedArray; + if (m_sharedArray != &emptyArray) + m_sharedArray->refCount++; + } return *this; } diff --git a/src/Nazara/Core/Clock.cpp b/src/Nazara/Core/Clock.cpp index f1cf8ceb0..8ad7a32a1 100644 --- a/src/Nazara/Core/Clock.cpp +++ b/src/Nazara/Core/Clock.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Color.cpp b/src/Nazara/Core/Color.cpp index 815fad032..a6e596021 100644 --- a/src/Nazara/Core/Color.cpp +++ b/src/Nazara/Core/Color.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/ConditionVariable.cpp b/src/Nazara/Core/ConditionVariable.cpp index f45393a95..ac8dcd50a 100644 --- a/src/Nazara/Core/ConditionVariable.cpp +++ b/src/Nazara/Core/ConditionVariable.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Core.cpp b/src/Nazara/Core/Core.cpp index 0fd722719..7e32de55d 100644 --- a/src/Nazara/Core/Core.cpp +++ b/src/Nazara/Core/Core.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Debug/NewRedefinition.cpp b/src/Nazara/Core/Debug/NewRedefinition.cpp index b4c06b816..36a9f2d91 100644 --- a/src/Nazara/Core/Debug/NewRedefinition.cpp +++ b/src/Nazara/Core/Debug/NewRedefinition.cpp @@ -1,16 +1,16 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #if NAZARA_CORE_MANAGE_MEMORY -#define NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION - -#include #include #include // Nécessaire ? +#define NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION +#include + void* operator new(std::size_t size, const char* file, unsigned int line) { return NzMemoryManager::Allocate(size, false, file, line); diff --git a/src/Nazara/Core/Directory.cpp b/src/Nazara/Core/Directory.cpp index 32ce320ef..e500eda06 100644 --- a/src/Nazara/Core/Directory.cpp +++ b/src/Nazara/Core/Directory.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/DynLib.cpp b/src/Nazara/Core/DynLib.cpp index b819f1ef7..13182213a 100644 --- a/src/Nazara/Core/DynLib.cpp +++ b/src/Nazara/Core/DynLib.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Error.cpp b/src/Nazara/Core/Error.cpp index e73a3e87a..42a297076 100644 --- a/src/Nazara/Core/Error.cpp +++ b/src/Nazara/Core/Error.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/ErrorFlags.cpp b/src/Nazara/Core/ErrorFlags.cpp index a6805f87e..15a298087 100644 --- a/src/Nazara/Core/ErrorFlags.cpp +++ b/src/Nazara/Core/ErrorFlags.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/File.cpp b/src/Nazara/Core/File.cpp index aa803a9fa..6c38f30f7 100644 --- a/src/Nazara/Core/File.cpp +++ b/src/Nazara/Core/File.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -733,7 +733,7 @@ bool NzFile::FillHash(NzAbstractHash* hash) const unsigned int size; while (remainingSize > 0) { - size = (remainingSize >= NAZARA_CORE_FILE_BUFFERSIZE) ? NAZARA_CORE_FILE_BUFFERSIZE : static_cast(remainingSize); + size = std::min(remainingSize, static_cast(NAZARA_CORE_FILE_BUFFERSIZE)); if (file.Read(&buffer[0], sizeof(char), size) != sizeof(char)*size) { NazaraError("Unable to read file"); diff --git a/src/Nazara/Core/GuillotineBinPack.cpp b/src/Nazara/Core/GuillotineBinPack.cpp new file mode 100644 index 000000000..3127c4203 --- /dev/null +++ b/src/Nazara/Core/GuillotineBinPack.cpp @@ -0,0 +1,446 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +// Implémentation originale de Jukka Jylänki (Merci de sa contribution au domaine public) +// http://clb.demon.fi/projects/even-more-rectangle-bin-packing +// Je n'ai vraiment fait qu'adapter le code au moteur (Avec quelques améliorations), je n'ai aucun mérite sur le code ci-dessous + +#include +#include +#include +#include +#include +#include + +namespace +{ + int ScoreBestAreaFit(int width, int height, const NzRectui& freeRectSize) + { + return freeRectSize.width * freeRectSize.height - width * height; + } + + int ScoreBestLongSideFit(int width, int height, const NzRectui& freeRectSize) + { + int leftoverHoriz = std::abs(freeRectSize.width - width); + int leftoverVert = std::abs(freeRectSize.height - height); + int leftover = std::max(leftoverHoriz, leftoverVert); + + return leftover; + } + + int ScoreBestShortSideFit(int width, int height, const NzRectui& freeRectSize) + { + int leftoverHoriz = std::abs(freeRectSize.width - width); + int leftoverVert = std::abs(freeRectSize.height - height); + int leftover = std::min(leftoverHoriz, leftoverVert); + + return leftover; + } + + int ScoreWorstAreaFit(int width, int height, const NzRectui& freeRectSize) + { + return -ScoreBestAreaFit(width, height, freeRectSize); + } + + int ScoreWorstLongSideFit(int width, int height, const NzRectui& freeRectSize) + { + return -ScoreBestLongSideFit(width, height, freeRectSize); + } + + int ScoreWorstShortSideFit(int width, int height, const NzRectui& freeRectSize) + { + return -ScoreBestShortSideFit(width, height, freeRectSize); + } +} + +NzGuillotineBinPack::NzGuillotineBinPack() +{ + Reset(); +} + +NzGuillotineBinPack::NzGuillotineBinPack(unsigned int width, unsigned int height) +{ + Reset(width, height); +} + +NzGuillotineBinPack::NzGuillotineBinPack(const NzVector2ui& size) +{ + Reset(size); +} + +void NzGuillotineBinPack::Clear() +{ + m_freeRectangles.clear(); + m_freeRectangles.push_back(NzRectui(0, 0, m_width, m_height)); + + m_usedArea = 0; +} + +void NzGuillotineBinPack::Expand(unsigned int newWidth, unsigned newHeight) +{ + unsigned int oldWidth = m_width; + unsigned int oldHeight = m_height; + + m_width = std::max(newWidth, m_width); + m_height = std::max(newHeight, m_height); + + if (m_width > oldWidth) + m_freeRectangles.push_back(NzRectui(oldWidth, 0, m_width - oldWidth, oldHeight)); + + if (m_height > oldHeight) + m_freeRectangles.push_back(NzRectui(0, oldHeight, m_width, m_height - oldHeight)); + + // On va ensuite fusionner les rectangles tant que possible + while (MergeFreeRectangles()); +} + +void NzGuillotineBinPack::Expand(const NzVector2ui& newSize) +{ + Expand(newSize.x, newSize.y); +} + +void NzGuillotineBinPack::FreeRectangle(const NzRectui& rect) +{ + ///DOC: Cette méthode ne devrait recevoir que des rectangles calculés par la méthode Insert et peut provoquer de la fragmentation + m_freeRectangles.push_back(rect); + + m_usedArea -= rect.width * rect.height; +} + +unsigned int NzGuillotineBinPack::GetHeight() const +{ + return m_height; +} + +float NzGuillotineBinPack::GetOccupancy() const +{ + return static_cast(m_usedArea)/(m_width*m_height); +} + +NzVector2ui NzGuillotineBinPack::GetSize() const +{ + return NzVector2ui(m_width, m_height); +} + +unsigned int NzGuillotineBinPack::GetWidth() const +{ + return m_width; +} + +bool NzGuillotineBinPack::Insert(NzRectui* rects, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod) +{ + return Insert(rects, nullptr, nullptr, count, merge, rectChoice, splitMethod); +} + +bool NzGuillotineBinPack::Insert(NzRectui* rects, bool* flipped, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod) +{ + return Insert(rects, flipped, nullptr, count, merge, rectChoice, splitMethod); +} + +bool NzGuillotineBinPack::Insert(NzRectui* rects, bool* flipped, bool* inserted, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod) +{ + std::vector remainingRects(count); // La position du rectangle + for (unsigned int i = 0; i < count; ++i) + remainingRects[i] = &rects[i]; + + // Pack rectangles one at a time until we have cleared the rects array of all rectangles. + while (!remainingRects.empty()) + { + // Stores the penalty score of the best rectangle placement - bigger=worse, smaller=better. + bool bestFlipped; + int bestFreeRect; + int bestRect; + int bestScore = std::numeric_limits::max(); + + for (std::size_t i = 0; i < m_freeRectangles.size(); ++i) + { + NzRectui& freeRect = m_freeRectangles[i]; + + for (std::size_t j = 0; j < remainingRects.size(); ++j) + { + NzRectui& rect = *remainingRects[j]; + + // If this rectangle is a perfect match, we pick it instantly. + if (rect.width == freeRect.width && rect.height == freeRect.height) + { + bestFreeRect = i; + bestRect = j; + bestFlipped = false; + bestScore = std::numeric_limits::min(); + i = m_freeRectangles.size(); // Force a jump out of the outer loop as well - we got an instant fit. + break; + } + // If flipping this rectangle is a perfect match, pick that then. + else if (rect.height == freeRect.width && rect.width == freeRect.height) + { + bestFreeRect = i; + bestRect = j; + bestFlipped = true; + bestScore = std::numeric_limits::min(); + i = m_freeRectangles.size(); // Force a jump out of the outer loop as well - we got an instant fit. + break; + } + // Try if we can fit the rectangle upright. + else if (rect.width <= freeRect.width && rect.height <= freeRect.height) + { + int score = ScoreByHeuristic(rect.width, rect.height, freeRect, rectChoice); + if (score < bestScore) + { + bestFreeRect = i; + bestRect = j; + bestFlipped = false; + bestScore = score; + } + } + // If not, then perhaps flipping sideways will make it fit? + else if (rect.height <= freeRect.width && rect.width <= freeRect.height) + { + int score = ScoreByHeuristic(rect.height, rect.width, freeRect, rectChoice); + if (score < bestScore) + { + bestFreeRect = i; + bestRect = j; + bestFlipped = true; + bestScore = score; + } + } + } + } + + // If we didn't manage to find any rectangle to pack, abort. + if (bestScore == std::numeric_limits::max()) + { + // Si nous le pouvons, on marque les rectangles n'ayant pas pu être insérés + if (inserted) + { + for (NzRectui* rect : remainingRects) + { + unsigned int position = rect - rects; + inserted[position] = false; + } + } + + return false; + } + + // Otherwise, we're good to go and do the actual packing. + unsigned int position = remainingRects[bestRect] - rects; + NzRectui& rect = *remainingRects[bestRect]; + rect.x = m_freeRectangles[bestFreeRect].x; + rect.y = m_freeRectangles[bestFreeRect].y; + + if (bestFlipped) + std::swap(rect.width, rect.height); + + if (flipped) + flipped[position] = bestFlipped; + + if (inserted) + inserted[position] = true; + + // Remove the free space we lost in the bin. + SplitFreeRectByHeuristic(m_freeRectangles[bestFreeRect], rect, splitMethod); + m_freeRectangles.erase(m_freeRectangles.begin() + bestFreeRect); + + // Remove the rectangle we just packed from the input list. + remainingRects.erase(remainingRects.begin() + bestRect); + + // Perform a Rectangle Merge step if desired. + if (merge) + MergeFreeRectangles(); + + m_usedArea += rect.width * rect.height; + } + + return true; +} + +bool NzGuillotineBinPack::MergeFreeRectangles() +{ + ///DOC: Renvoie true s'il y a eu fusion (et donc si une fusion est encore possible) + std::size_t oriSize = m_freeRectangles.size(); + + // Do a Theta(n^2) loop to see if any pair of free rectangles could me merged into one. + // Note that we miss any opportunities to merge three rectangles into one. (should call this function again to detect that) + for (std::size_t i = 0; i < m_freeRectangles.size(); ++i) + { + NzRectui& firstRect = m_freeRectangles[i]; + + for (std::size_t j = i+1; j < m_freeRectangles.size(); ++j) + { + NzRectui& secondRect = m_freeRectangles[j]; + + if (firstRect.width == secondRect.width && firstRect.x == secondRect.x) + { + if (firstRect.y == secondRect.y + secondRect.height) + { + firstRect.y -= secondRect.height; + firstRect.height += secondRect.height; + m_freeRectangles.erase(m_freeRectangles.begin() + j); + --j; + } + else if (firstRect.y + firstRect.height == secondRect.y) + { + firstRect.height += secondRect.height; + m_freeRectangles.erase(m_freeRectangles.begin() + j); + --j; + } + } + else if (firstRect.height == secondRect.height && firstRect.y == secondRect.y) + { + if (firstRect.x == secondRect.x + secondRect.width) + { + firstRect.x -= secondRect.width; + firstRect.width += secondRect.width; + m_freeRectangles.erase(m_freeRectangles.begin() + j); + --j; + } + else if (firstRect.x + firstRect.width == secondRect.x) + { + firstRect.width += secondRect.width; + m_freeRectangles.erase(m_freeRectangles.begin() + j); + --j; + } + } + } + } + + return m_freeRectangles.size() < oriSize; +} + +void NzGuillotineBinPack::Reset() +{ + m_height = 0; + m_width = 0; + + Clear(); +} + +void NzGuillotineBinPack::Reset(unsigned int width, unsigned int height) +{ + m_height = height; + m_width = width; + + Clear(); +} + +void NzGuillotineBinPack::Reset(const NzVector2ui& size) +{ + Reset(size.x, size.y); +} + +void NzGuillotineBinPack::SplitFreeRectAlongAxis(const NzRectui& freeRect, const NzRectui& placedRect, bool splitHorizontal) +{ + // Form the two new rectangles. + NzRectui bottom; + bottom.x = freeRect.x; + bottom.y = freeRect.y + placedRect.height; + bottom.height = freeRect.height - placedRect.height; + + NzRectui right; + right.x = freeRect.x + placedRect.width; + right.y = freeRect.y; + right.width = freeRect.width - placedRect.width; + + if (splitHorizontal) + { + bottom.width = freeRect.width; + right.height = placedRect.height; + } + else // Split vertically + { + bottom.width = placedRect.width; + right.height = freeRect.height; + } + + // Add the new rectangles into the free rectangle pool if they weren't degenerate. + if (bottom.width > 0 && bottom.height > 0) + m_freeRectangles.push_back(bottom); + + if (right.width > 0 && right.height > 0) + m_freeRectangles.push_back(right); +} + +void NzGuillotineBinPack::SplitFreeRectByHeuristic(const NzRectui& freeRect, const NzRectui& placedRect, GuillotineSplitHeuristic method) +{ + // Compute the lengths of the leftover area. + const int w = freeRect.width - placedRect.width; + const int h = freeRect.height - placedRect.height; + + // Placing placedRect into freeRect results in an L-shaped free area, which must be split into + // two disjoint rectangles. This can be achieved with by splitting the L-shape using a single line. + // We have two choices: horizontal or vertical. + + // Use the given heuristic to decide which choice to make. + + bool splitHorizontal; + switch (method) + { + case SplitLongerAxis: + // Split along the longer total axis. + splitHorizontal = (freeRect.width > freeRect.height); + break; + + case SplitLongerLeftoverAxis: + // Split along the longer leftover axis. + splitHorizontal = (w > h); + break; + + case SplitMaximizeArea: + // Maximize the smaller area == minimize the larger area. + // Tries to make the rectangles more even-sized. + splitHorizontal = (placedRect.width * h <= w * placedRect.height); + break; + + case SplitMinimizeArea: + // Maximize the larger area == minimize the smaller area. + // Tries to make the single bigger rectangle. + splitHorizontal = (placedRect.width * h > w * placedRect.height); + break; + + case SplitShorterAxis: + // Split along the shorter total axis. + splitHorizontal = (freeRect.width <= freeRect.height); + break; + + case SplitShorterLeftoverAxis: + // Split along the shorter leftover axis. + splitHorizontal = (w <= h); + break; + + default: + NazaraError("Split heuristic out of enum (0x" + NzString::Number(method, 16) + ')'); + splitHorizontal = true; + } + + // Perform the actual split. + SplitFreeRectAlongAxis(freeRect, placedRect, splitHorizontal); +} + +int NzGuillotineBinPack::ScoreByHeuristic(int width, int height, const NzRectui& freeRect, FreeRectChoiceHeuristic rectChoice) +{ + switch (rectChoice) + { + case RectBestAreaFit: + return ScoreBestAreaFit(width, height, freeRect); + + case RectBestLongSideFit: + return ScoreBestLongSideFit(width, height, freeRect); + + case RectBestShortSideFit: + return ScoreBestShortSideFit(width, height, freeRect); + + case RectWorstAreaFit: + return ScoreWorstAreaFit(width, height, freeRect); + + case RectWorstLongSideFit: + return ScoreWorstLongSideFit(width, height, freeRect); + + case RectWorstShortSideFit: + return ScoreWorstShortSideFit(width, height, freeRect); + } + + NazaraError("Rect choice heuristic out of enum (0x" + NzString::Number(rectChoice, 16) + ')'); + return std::numeric_limits::max(); +} diff --git a/src/Nazara/Core/HardwareInfo.cpp b/src/Nazara/Core/HardwareInfo.cpp index 09299e052..6bc12835a 100644 --- a/src/Nazara/Core/HardwareInfo.cpp +++ b/src/Nazara/Core/HardwareInfo.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Hash.cpp b/src/Nazara/Core/Hash.cpp index 3a1707710..4a7654d77 100644 --- a/src/Nazara/Core/Hash.cpp +++ b/src/Nazara/Core/Hash.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Hash/CRC32.cpp b/src/Nazara/Core/Hash/CRC32.cpp index c2c1377e0..6021cf455 100644 --- a/src/Nazara/Core/Hash/CRC32.cpp +++ b/src/Nazara/Core/Hash/CRC32.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Hash/Fletcher16.cpp b/src/Nazara/Core/Hash/Fletcher16.cpp index 609896211..3a608a6b1 100644 --- a/src/Nazara/Core/Hash/Fletcher16.cpp +++ b/src/Nazara/Core/Hash/Fletcher16.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Hash/MD5.cpp b/src/Nazara/Core/Hash/MD5.cpp index a2c8a2483..5ac1ff61e 100644 --- a/src/Nazara/Core/Hash/MD5.cpp +++ b/src/Nazara/Core/Hash/MD5.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Hash/SHA/Internal.cpp b/src/Nazara/Core/Hash/SHA/Internal.cpp index 9ea5069cb..922a8767d 100644 --- a/src/Nazara/Core/Hash/SHA/Internal.cpp +++ b/src/Nazara/Core/Hash/SHA/Internal.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -770,14 +770,6 @@ void SHA224_Init(SHA_CTX* context) SHA256_Internal_Init(context, sha224_initial_hash_value); } -namespace -{ - void SHA224_Internal_Transform(SHA_CTX* context, const nzUInt32* data) - { - SHA256_Internal_Transform(context, data); - } -} - void SHA224_Update(SHA_CTX* context, const nzUInt8 *data, std::size_t len) { SHA256_Update(context, data, len); diff --git a/src/Nazara/Core/Hash/SHA/Internal.hpp b/src/Nazara/Core/Hash/SHA/Internal.hpp index 1e8e7eae1..78748bdff 100644 --- a/src/Nazara/Core/Hash/SHA/Internal.hpp +++ b/src/Nazara/Core/Hash/SHA/Internal.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Hash/SHA1.cpp b/src/Nazara/Core/Hash/SHA1.cpp index 20e81ea1a..b35c3fb4b 100644 --- a/src/Nazara/Core/Hash/SHA1.cpp +++ b/src/Nazara/Core/Hash/SHA1.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Hash/SHA224.cpp b/src/Nazara/Core/Hash/SHA224.cpp index 1c6f70d0e..fd0a3f12b 100644 --- a/src/Nazara/Core/Hash/SHA224.cpp +++ b/src/Nazara/Core/Hash/SHA224.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Hash/SHA256.cpp b/src/Nazara/Core/Hash/SHA256.cpp index 572f1c6eb..056f06343 100644 --- a/src/Nazara/Core/Hash/SHA256.cpp +++ b/src/Nazara/Core/Hash/SHA256.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Hash/SHA384.cpp b/src/Nazara/Core/Hash/SHA384.cpp index 8c3d1f3dc..816b26dd9 100644 --- a/src/Nazara/Core/Hash/SHA384.cpp +++ b/src/Nazara/Core/Hash/SHA384.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Hash/SHA512.cpp b/src/Nazara/Core/Hash/SHA512.cpp index 91071acf3..513797448 100644 --- a/src/Nazara/Core/Hash/SHA512.cpp +++ b/src/Nazara/Core/Hash/SHA512.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Hash/Whirlpool.cpp b/src/Nazara/Core/Hash/Whirlpool.cpp index 6921f05c7..886943f41 100644 --- a/src/Nazara/Core/Hash/Whirlpool.cpp +++ b/src/Nazara/Core/Hash/Whirlpool.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/HashDigest.cpp b/src/Nazara/Core/HashDigest.cpp index 27aa22db3..aeba77415 100644 --- a/src/Nazara/Core/HashDigest.cpp +++ b/src/Nazara/Core/HashDigest.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Hashable.cpp b/src/Nazara/Core/Hashable.cpp index 881341088..6b3f1e074 100644 --- a/src/Nazara/Core/Hashable.cpp +++ b/src/Nazara/Core/Hashable.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/InputStream.cpp b/src/Nazara/Core/InputStream.cpp index 2e5f4f14c..cd231bebf 100644 --- a/src/Nazara/Core/InputStream.cpp +++ b/src/Nazara/Core/InputStream.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/LockGuard.cpp b/src/Nazara/Core/LockGuard.cpp index 9e25a8d3c..4ffaa3aed 100644 --- a/src/Nazara/Core/LockGuard.cpp +++ b/src/Nazara/Core/LockGuard.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Log.cpp b/src/Nazara/Core/Log.cpp index 946548479..51622d100 100644 --- a/src/Nazara/Core/Log.cpp +++ b/src/Nazara/Core/Log.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include diff --git a/src/Nazara/Core/MemoryManager.cpp b/src/Nazara/Core/MemoryManager.cpp index ff38dadc1..a91133234 100644 --- a/src/Nazara/Core/MemoryManager.cpp +++ b/src/Nazara/Core/MemoryManager.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/MemoryStream.cpp b/src/Nazara/Core/MemoryStream.cpp index 1c1bcd6cb..f8b391c6e 100644 --- a/src/Nazara/Core/MemoryStream.cpp +++ b/src/Nazara/Core/MemoryStream.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Mutex.cpp b/src/Nazara/Core/Mutex.cpp index 923309566..ca2929a3a 100644 --- a/src/Nazara/Core/Mutex.cpp +++ b/src/Nazara/Core/Mutex.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/ParameterList.cpp b/src/Nazara/Core/ParameterList.cpp index ba0e7322e..5b6e74b93 100644 --- a/src/Nazara/Core/ParameterList.cpp +++ b/src/Nazara/Core/ParameterList.cpp @@ -1,12 +1,10 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp -// Notre utilisation du placement new n'est pas (encore ?) compatible avec les définitions du MLT -#define NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION - #include #include +#include #include #include #include @@ -309,7 +307,7 @@ void NzParameterList::SetParameter(const NzString& name, const NzString& value) parameter.type = nzParameterType_String; - new (¶meter.value.stringVal) NzString(value); + NzPlacementNew(¶meter.value.stringVal, value); } void NzParameterList::SetParameter(const NzString& name, const char* value) @@ -322,7 +320,7 @@ void NzParameterList::SetParameter(const NzString& name, const char* value) parameter.type = nzParameterType_String; - new (¶meter.value.stringVal) NzString(value); + NzPlacementNew(¶meter.value.stringVal, value); } void NzParameterList::SetParameter(const NzString& name, void* value) @@ -405,7 +403,7 @@ NzParameterList& NzParameterList::operator=(const NzParameterList& list) case nzParameterType_String: parameter.type = nzParameterType_String; - new (¶meter.value.stringVal) NzString(it->second.value.stringVal); + NzPlacementNew(¶meter.value.stringVal, it->second.value.stringVal); break; case nzParameterType_Userdata: diff --git a/src/Nazara/Core/PluginManager.cpp b/src/Nazara/Core/PluginManager.cpp index 5ee08fe91..77346ec29 100644 --- a/src/Nazara/Core/PluginManager.cpp +++ b/src/Nazara/Core/PluginManager.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Posix/DynLibImpl.hpp b/src/Nazara/Core/Posix/DynLibImpl.hpp index 96f8a08f3..d4c022dba 100644 --- a/src/Nazara/Core/Posix/DynLibImpl.hpp +++ b/src/Nazara/Core/Posix/DynLibImpl.hpp @@ -19,7 +19,7 @@ class NzDynLibImpl : NzNonCopyable NzDynLibImpl(NzDynLib* m_parent); ~NzDynLibImpl() = default; - NzDynLibFunc GetSymbol(const NzString& symbol, NzString& errorMessage) const; + NzDynLibFunc GetSymbol(const NzString& symbol, NzString* errorMessage) const; bool Load(const NzString& libraryPath, NzString* errorMessage); void Unload(); diff --git a/src/Nazara/Core/PrimitiveList.cpp b/src/Nazara/Core/PrimitiveList.cpp index 6e4961cbe..2636ed415 100644 --- a/src/Nazara/Core/PrimitiveList.cpp +++ b/src/Nazara/Core/PrimitiveList.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/RefCounted.cpp b/src/Nazara/Core/RefCounted.cpp index 449e379dc..6ca923a44 100644 --- a/src/Nazara/Core/RefCounted.cpp +++ b/src/Nazara/Core/RefCounted.cpp @@ -71,7 +71,11 @@ void NzRefCounted::RemoveObjectListener(NzObjectListener* listener) const { ObjectListenerMap::iterator it = m_objectListeners.find(listener); if (it != m_objectListeners.end()) - RemoveObjectListenerIterator(it); + { + unsigned int& referenceCount = it->second.second; + if (--referenceCount == 0) + m_objectListeners.erase(it); + } } } @@ -119,7 +123,7 @@ void NzRefCounted::NotifyCreated() while (it != m_objectListeners.end()) { if (!it->first->OnObjectCreated(this, it->second.first)) - RemoveObjectListenerIterator(it++); + m_objectListeners.erase(it++); else ++it; } @@ -137,7 +141,7 @@ void NzRefCounted::NotifyDestroy() while (it != m_objectListeners.end()) { if (!it->first->OnObjectDestroy(this, it->second.first)) - RemoveObjectListenerIterator(it++); + m_objectListeners.erase(it++); else ++it; } @@ -155,19 +159,10 @@ void NzRefCounted::NotifyModified(unsigned int code) while (it != m_objectListeners.end()) { if (!it->first->OnObjectModified(this, it->second.first, code)) - RemoveObjectListenerIterator(it++); + m_objectListeners.erase(it++); else ++it; } m_objectListenersLocked = false; } - -void NzRefCounted::RemoveObjectListenerIterator(ObjectListenerMap::iterator iterator) const -{ - unsigned int& referenceCount = iterator->second.second; - if (referenceCount == 1) - m_objectListeners.erase(iterator); - else - referenceCount--; -} diff --git a/src/Nazara/Core/Resource.cpp b/src/Nazara/Core/Resource.cpp index 3c8bf27fd..789dc91a4 100644 --- a/src/Nazara/Core/Resource.cpp +++ b/src/Nazara/Core/Resource.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -7,7 +7,7 @@ NzResource::~NzResource() = default; -NzString NzResource::GetFilePath() const +const NzString& NzResource::GetFilePath() const { return m_filePath; } diff --git a/src/Nazara/Core/Semaphore.cpp b/src/Nazara/Core/Semaphore.cpp index a36efa875..6cdb83f6d 100644 --- a/src/Nazara/Core/Semaphore.cpp +++ b/src/Nazara/Core/Semaphore.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Stream.cpp b/src/Nazara/Core/Stream.cpp index be7227935..77948a382 100644 --- a/src/Nazara/Core/Stream.cpp +++ b/src/Nazara/Core/Stream.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/String.cpp b/src/Nazara/Core/String.cpp index 54e5b3eb7..e2b0ed97e 100644 --- a/src/Nazara/Core/String.cpp +++ b/src/Nazara/Core/String.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include @@ -2785,35 +2785,19 @@ NzString& NzString::Set(const char* string, unsigned int length) NzString& NzString::Set(const std::string& string) { - if (string.size() > 0) - { - if (m_sharedString->capacity >= string.size()) - EnsureOwnership(true); - else - { - ReleaseString(); - - m_sharedString = new SharedString; - m_sharedString->capacity = string.size(); - m_sharedString->string = new char[string.size()+1]; - } - - m_sharedString->size = string.size(); - std::memcpy(m_sharedString->string, string.c_str(), string.size()+1); - } - else - ReleaseString(); - - return *this; + return Set(string.data(), string.size()); } NzString& NzString::Set(const NzString& string) { - ReleaseString(); + if (this != &string) + { + ReleaseString(); - m_sharedString = string.m_sharedString; - if (m_sharedString != &emptyString) - m_sharedString->refCount++; + m_sharedString = string.m_sharedString; + if (m_sharedString != &emptyString) + m_sharedString->refCount++; + } return *this; } diff --git a/src/Nazara/Core/StringStream.cpp b/src/Nazara/Core/StringStream.cpp index a15196cac..9eb4494ff 100644 --- a/src/Nazara/Core/StringStream.cpp +++ b/src/Nazara/Core/StringStream.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/TaskScheduler.cpp b/src/Nazara/Core/TaskScheduler.cpp index bf916392e..4e328045e 100644 --- a/src/Nazara/Core/TaskScheduler.cpp +++ b/src/Nazara/Core/TaskScheduler.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Thread.cpp b/src/Nazara/Core/Thread.cpp index 2d603dce9..47d7d102d 100644 --- a/src/Nazara/Core/Thread.cpp +++ b/src/Nazara/Core/Thread.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Unicode.cpp b/src/Nazara/Core/Unicode.cpp index ac72ecc9b..25b54c20c 100644 --- a/src/Nazara/Core/Unicode.cpp +++ b/src/Nazara/Core/Unicode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -18,34 +18,348 @@ struct Character #include -#else // Implémentation bidon +#else // Implémentation supportant la table ASCII NzUnicode::Category NzUnicode::GetCategory(char32_t character) { - NazaraUnused(character); + switch (character) + { + case '\x00': + case '\x01': + case '\x02': + case '\x03': + case '\x04': + case '\x05': + case '\x06': + case '\x07': + case '\x08': + case '\x09': + case '\x0A': + case '\x0B': + case '\x0C': + case '\x0D': + case '\x0E': + case '\x0F': + case '\x10': + case '\x11': + case '\x12': + case '\x13': + case '\x14': + case '\x15': + case '\x16': + case '\x17': + case '\x18': + case '\x19': + case '\x1A': + case '\x1B': + case '\x1C': + case '\x1D': + case '\x1E': + case '\x1F': + case '\x7F': + return Category_Other_Control; + + case ' ': + return Category_Separator_Space; + + case '!': + case '"': + case '#': + case '$': + case '%': + case '&': + case '\'': + case '*': + case ',': + case '.': + case '/': + case ':': + case ';': + case '?': + case '@': + case '\\': + return Category_Punctuation_Other; + + case '(': + case '[': + case '{': + return Category_Punctuation_Open; + + case ')': + case '}': + case ']': + return Category_Punctuation_Close; + + case '+': + case '<': + case '=': + case '>': + case '|': + case '~': + return Category_Symbol_Math; + + case '-': + return Category_Punctuation_Dash; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return Category_Number_DecimalDigit; + + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + return Category_Number_DecimalDigit; + + case '_': + return Category_Punctuation_Connector; + + case '^': + case '`': + return Category_Symbol_Modifier; + + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + return Category_Number_DecimalDigit; + + default: + break; + } return Category_NoCategory; } NzUnicode::Direction NzUnicode::GetDirection(char32_t character) { - NazaraUnused(character); + switch (character) + { + case '\x00': + case '\x01': + case '\x02': + case '\x03': + case '\x04': + case '\x05': + case '\x06': + case '\x07': + case '\x08': + case '\x0E': + case '\x0F': + case '\x10': + case '\x11': + case '\x12': + case '\x13': + case '\x14': + case '\x15': + case '\x16': + case '\x17': + case '\x18': + case '\x19': + case '\x1A': + case '\x1B': + case '\x7F': + return Direction_Boundary_Neutral; + + case '\x09': + case '\x0B': + case '\x1F': + return Direction_Segment_Separator; + + case '\x0A': + case '\x0D': + case '\x1C': + case '\x1D': + case '\x1E': + return Direction_Paragraph_Separator; + + case '\x0C': + case ' ': + return Direction_White_Space; + + case '!': + case '"': + case '&': + case '\'': + case '(': + case ')': + case '*': + case ';': + case '<': + case '=': + case '>': + case '?': + case '@': + case '[': + case '\\': + case ']': + case '^': + case '_': + case '`': + case '{': + case '|': + case '}': + case '~': + return Direction_Other_Neutral; + + case '#': + case '$': + case '%': + return Direction_European_Terminator; + + case '+': + case '-': + return Direction_European_Separator; + + case ',': + case '.': + case '/': + case ':': + return Direction_Common_Separator; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return Direction_European_Number; + + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + return Direction_Left_To_Right; + + default: + break; + } return Direction_Boundary_Neutral; } char32_t NzUnicode::GetLowercase(char32_t character) { - return character; + if (character >= 'A' && character <= 'Z') + return character + ('a' - 'A'); + else + return character; } char32_t NzUnicode::GetTitlecase(char32_t character) { - return character; + return GetUppercase(character); } char32_t NzUnicode::GetUppercase(char32_t character) { - return character; + if (character >= 'a' && character <= 'z') + return character + ('A' - 'a'); + else + return character; } #endif diff --git a/src/Nazara/Core/Updatable.cpp b/src/Nazara/Core/Updatable.cpp new file mode 100644 index 000000000..79495dcbc --- /dev/null +++ b/src/Nazara/Core/Updatable.cpp @@ -0,0 +1,8 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +NzUpdatable::~NzUpdatable() = default; diff --git a/src/Nazara/Core/Win32/ClockImpl.cpp b/src/Nazara/Core/Win32/ClockImpl.cpp index dbc3c1602..334b977db 100644 --- a/src/Nazara/Core/Win32/ClockImpl.cpp +++ b/src/Nazara/Core/Win32/ClockImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/ClockImpl.hpp b/src/Nazara/Core/Win32/ClockImpl.hpp index a5a329c2e..c73eb5dcf 100644 --- a/src/Nazara/Core/Win32/ClockImpl.hpp +++ b/src/Nazara/Core/Win32/ClockImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/ConditionVariableImpl.cpp b/src/Nazara/Core/Win32/ConditionVariableImpl.cpp index 2df0558c6..0e1d30539 100644 --- a/src/Nazara/Core/Win32/ConditionVariableImpl.cpp +++ b/src/Nazara/Core/Win32/ConditionVariableImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/ConditionVariableImpl.hpp b/src/Nazara/Core/Win32/ConditionVariableImpl.hpp index e9041927b..171c9cd2a 100644 --- a/src/Nazara/Core/Win32/ConditionVariableImpl.hpp +++ b/src/Nazara/Core/Win32/ConditionVariableImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/DirectoryImpl.cpp b/src/Nazara/Core/Win32/DirectoryImpl.cpp index d5fd6eb93..f48a0c7f4 100644 --- a/src/Nazara/Core/Win32/DirectoryImpl.cpp +++ b/src/Nazara/Core/Win32/DirectoryImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/DirectoryImpl.hpp b/src/Nazara/Core/Win32/DirectoryImpl.hpp index 040e3afee..cb2df657d 100644 --- a/src/Nazara/Core/Win32/DirectoryImpl.hpp +++ b/src/Nazara/Core/Win32/DirectoryImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/DynLibImpl.cpp b/src/Nazara/Core/Win32/DynLibImpl.cpp index 37ac5a0e9..b10ae8a38 100644 --- a/src/Nazara/Core/Win32/DynLibImpl.cpp +++ b/src/Nazara/Core/Win32/DynLibImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/DynLibImpl.hpp b/src/Nazara/Core/Win32/DynLibImpl.hpp index fedc93103..662524370 100644 --- a/src/Nazara/Core/Win32/DynLibImpl.hpp +++ b/src/Nazara/Core/Win32/DynLibImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/FileImpl.cpp b/src/Nazara/Core/Win32/FileImpl.cpp index 3f88b71ad..455c99e18 100644 --- a/src/Nazara/Core/Win32/FileImpl.cpp +++ b/src/Nazara/Core/Win32/FileImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/FileImpl.hpp b/src/Nazara/Core/Win32/FileImpl.hpp index 6802214e7..15420b8db 100644 --- a/src/Nazara/Core/Win32/FileImpl.hpp +++ b/src/Nazara/Core/Win32/FileImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/HardwareInfoImpl.cpp b/src/Nazara/Core/Win32/HardwareInfoImpl.cpp index 0f5aa77a6..4fb664aca 100644 --- a/src/Nazara/Core/Win32/HardwareInfoImpl.cpp +++ b/src/Nazara/Core/Win32/HardwareInfoImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/HardwareInfoImpl.hpp b/src/Nazara/Core/Win32/HardwareInfoImpl.hpp index 238b1ea66..cd8f4264a 100644 --- a/src/Nazara/Core/Win32/HardwareInfoImpl.hpp +++ b/src/Nazara/Core/Win32/HardwareInfoImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/MutexImpl.cpp b/src/Nazara/Core/Win32/MutexImpl.cpp index 504c9be48..81c712077 100644 --- a/src/Nazara/Core/Win32/MutexImpl.cpp +++ b/src/Nazara/Core/Win32/MutexImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/MutexImpl.hpp b/src/Nazara/Core/Win32/MutexImpl.hpp index 148fe7dfb..a45b49b0d 100644 --- a/src/Nazara/Core/Win32/MutexImpl.hpp +++ b/src/Nazara/Core/Win32/MutexImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/SemaphoreImpl.cpp b/src/Nazara/Core/Win32/SemaphoreImpl.cpp index 2561f4846..eddba3927 100644 --- a/src/Nazara/Core/Win32/SemaphoreImpl.cpp +++ b/src/Nazara/Core/Win32/SemaphoreImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/SemaphoreImpl.hpp b/src/Nazara/Core/Win32/SemaphoreImpl.hpp index 62cb250d3..e89c93908 100644 --- a/src/Nazara/Core/Win32/SemaphoreImpl.hpp +++ b/src/Nazara/Core/Win32/SemaphoreImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/TaskSchedulerImpl.cpp b/src/Nazara/Core/Win32/TaskSchedulerImpl.cpp index 09c3c1abd..bb230f086 100644 --- a/src/Nazara/Core/Win32/TaskSchedulerImpl.cpp +++ b/src/Nazara/Core/Win32/TaskSchedulerImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/TaskSchedulerImpl.hpp b/src/Nazara/Core/Win32/TaskSchedulerImpl.hpp index df1630414..0eb0fd6e1 100644 --- a/src/Nazara/Core/Win32/TaskSchedulerImpl.hpp +++ b/src/Nazara/Core/Win32/TaskSchedulerImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/ThreadImpl.cpp b/src/Nazara/Core/Win32/ThreadImpl.cpp index c5b88701c..e654e9158 100644 --- a/src/Nazara/Core/Win32/ThreadImpl.cpp +++ b/src/Nazara/Core/Win32/ThreadImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/ThreadImpl.hpp b/src/Nazara/Core/Win32/ThreadImpl.hpp index 17044b465..564f66db9 100644 --- a/src/Nazara/Core/Win32/ThreadImpl.hpp +++ b/src/Nazara/Core/Win32/ThreadImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/Time.cpp b/src/Nazara/Core/Win32/Time.cpp index 91d1b2713..c4802a2f2 100644 --- a/src/Nazara/Core/Win32/Time.cpp +++ b/src/Nazara/Core/Win32/Time.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Core/Win32/Time.hpp b/src/Nazara/Core/Win32/Time.hpp index 6a6096b02..e28fe7654 100644 --- a/src/Nazara/Core/Win32/Time.hpp +++ b/src/Nazara/Core/Win32/Time.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/AbstractBackground.cpp b/src/Nazara/Graphics/AbstractBackground.cpp index 718e68ca1..5792b448f 100644 --- a/src/Nazara/Graphics/AbstractBackground.cpp +++ b/src/Nazara/Graphics/AbstractBackground.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/AbstractRenderQueue.cpp b/src/Nazara/Graphics/AbstractRenderQueue.cpp index dde6a4305..4ceea80f5 100644 --- a/src/Nazara/Graphics/AbstractRenderQueue.cpp +++ b/src/Nazara/Graphics/AbstractRenderQueue.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/AbstractRenderTechnique.cpp b/src/Nazara/Graphics/AbstractRenderTechnique.cpp index bd5f7d39c..c338091b8 100644 --- a/src/Nazara/Graphics/AbstractRenderTechnique.cpp +++ b/src/Nazara/Graphics/AbstractRenderTechnique.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/AbstractViewer.cpp b/src/Nazara/Graphics/AbstractViewer.cpp index 43fbb2072..58feebfa7 100644 --- a/src/Nazara/Graphics/AbstractViewer.cpp +++ b/src/Nazara/Graphics/AbstractViewer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/Camera.cpp b/src/Nazara/Graphics/Camera.cpp index a0eb272a6..ba7539481 100644 --- a/src/Nazara/Graphics/Camera.cpp +++ b/src/Nazara/Graphics/Camera.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -80,6 +80,21 @@ const NzFrustumf& NzCamera::GetFrustum() const return m_frustum; } +NzVector3f NzCamera::GetGlobalForward() const +{ + return NzVector3f::Forward(); +} + +NzVector3f NzCamera::GetGlobalRight() const +{ + return NzVector3f::Right(); +} + +NzVector3f NzCamera::GetGlobalUp() const +{ + return NzVector3f::Up(); +} + const NzMatrix4f& NzCamera::GetProjectionMatrix() const { if (!m_projectionMatrixUpdated) diff --git a/src/Nazara/Graphics/ColorBackground.cpp b/src/Nazara/Graphics/ColorBackground.cpp index 71193fe82..5428873fb 100644 --- a/src/Nazara/Graphics/ColorBackground.cpp +++ b/src/Nazara/Graphics/ColorBackground.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/DeferredBloomPass.cpp b/src/Nazara/Graphics/DeferredBloomPass.cpp index 9b66184dd..29e875d3c 100644 --- a/src/Nazara/Graphics/DeferredBloomPass.cpp +++ b/src/Nazara/Graphics/DeferredBloomPass.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -10,9 +10,9 @@ NzDeferredBloomPass::NzDeferredBloomPass() : m_uniformUpdated(false), -m_brightLuminance(0.8), -m_brightMiddleGrey(0.5), -m_brightThreshold(0.8), +m_brightLuminance(0.8f), +m_brightMiddleGrey(0.5f), +m_brightThreshold(0.8f), m_blurPassCount(5) { m_bilinearSampler.SetAnisotropyLevel(1); diff --git a/src/Nazara/Graphics/DeferredDOFPass.cpp b/src/Nazara/Graphics/DeferredDOFPass.cpp index d526640cf..541181411 100644 --- a/src/Nazara/Graphics/DeferredDOFPass.cpp +++ b/src/Nazara/Graphics/DeferredDOFPass.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/DeferredFXAAPass.cpp b/src/Nazara/Graphics/DeferredFXAAPass.cpp index defd181ef..929a23453 100644 --- a/src/Nazara/Graphics/DeferredFXAAPass.cpp +++ b/src/Nazara/Graphics/DeferredFXAAPass.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/DeferredFinalPass.cpp b/src/Nazara/Graphics/DeferredFinalPass.cpp index 71794c090..a44bbd6d9 100644 --- a/src/Nazara/Graphics/DeferredFinalPass.cpp +++ b/src/Nazara/Graphics/DeferredFinalPass.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/DeferredFogPass.cpp b/src/Nazara/Graphics/DeferredFogPass.cpp index 1f2e23af4..01f20f95b 100644 --- a/src/Nazara/Graphics/DeferredFogPass.cpp +++ b/src/Nazara/Graphics/DeferredFogPass.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -125,6 +125,7 @@ NzDeferredFogPass::NzDeferredFogPass() m_pointSampler.SetWrapMode(nzSamplerWrap_Clamp); m_shader = BuildFogShader(); + m_shaderEyePositionLocation = m_shader->GetUniformLocation("EyePosition"); m_states.parameters[nzRendererParameter_DepthBuffer] = false; } @@ -138,7 +139,7 @@ bool NzDeferredFogPass::Process(const NzScene* scene, unsigned int firstWorkText NzRenderer::SetViewport(NzRecti(0, 0, m_dimensions.x, m_dimensions.y)); NzRenderer::SetShader(m_shader); - m_shader->SendVector(m_shader->GetUniformLocation(nzShaderUniform_EyePosition), scene->GetViewer()->GetEyePosition()); + m_shader->SendVector(m_shaderEyePositionLocation, scene->GetViewer()->GetEyePosition()); NzRenderer::SetRenderStates(m_states); NzRenderer::SetTexture(0, m_workTextures[secondWorkTexture]); diff --git a/src/Nazara/Graphics/DeferredForwardPass.cpp b/src/Nazara/Graphics/DeferredForwardPass.cpp index 368377e08..b6c16971b 100644 --- a/src/Nazara/Graphics/DeferredForwardPass.cpp +++ b/src/Nazara/Graphics/DeferredForwardPass.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/DeferredGeometryPass.cpp b/src/Nazara/Graphics/DeferredGeometryPass.cpp index e1a008493..0b2616cc4 100644 --- a/src/Nazara/Graphics/DeferredGeometryPass.cpp +++ b/src/Nazara/Graphics/DeferredGeometryPass.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -51,23 +51,21 @@ bool NzDeferredGeometryPass::Process(const NzScene* scene, unsigned int firstWor NzRenderer::SetMatrix(nzMatrixType_View, viewer->GetViewMatrix()); const NzShader* lastShader = nullptr; + const ShaderUniforms* shaderUniforms = nullptr; for (auto& matIt : m_renderQueue->opaqueModels) { - bool& used = std::get<0>(matIt.second); - if (used) + auto& matEntry = matIt.second; + + if (matEntry.enabled) { - bool& renderQueueInstancing = std::get<1>(matIt.second); - NzDeferredRenderQueue::MeshInstanceContainer& meshInstances = std::get<2>(matIt.second); + NzDeferredRenderQueue::MeshInstanceContainer& meshInstances = matEntry.meshMap; if (!meshInstances.empty()) { const NzMaterial* material = matIt.first; - // Nous utilisons de l'instancing que lorsqu'aucune lumière (autre que directionnelle) n'est active - // Ceci car l'instancing n'est pas compatible avec la recherche des lumières les plus proches - // (Le deferred shading n'a pas ce problème) - bool useInstancing = instancingEnabled && renderQueueInstancing; + bool useInstancing = instancingEnabled && matEntry.instancingEnabled; // On commence par récupérer le programme du matériau nzUInt32 flags = nzShaderFlags_Deferred; @@ -79,10 +77,13 @@ bool NzDeferredGeometryPass::Process(const NzScene* scene, unsigned int firstWor // Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas if (shader != lastShader) { + // Index des uniformes dans le shader + shaderUniforms = GetShaderUniforms(shader); + // Couleur ambiante de la scène - shader->SendColor(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor()); + shader->SendColor(shaderUniforms->sceneAmbient, scene->GetAmbientColor()); // Position de la caméra - shader->SendVector(shader->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition()); + shader->SendVector(shaderUniforms->eyePosition, viewer->GetEyePosition()); lastShader = shader; } @@ -91,28 +92,29 @@ bool NzDeferredGeometryPass::Process(const NzScene* scene, unsigned int firstWor for (auto& meshIt : meshInstances) { const NzMeshData& meshData = meshIt.first; - std::vector& instances = meshIt.second; + auto& meshEntry = meshIt.second; + std::vector& instances = meshEntry.instances; if (!instances.empty()) { const NzIndexBuffer* indexBuffer = meshData.indexBuffer; const NzVertexBuffer* vertexBuffer = meshData.vertexBuffer; // Gestion du draw call avant la boucle de rendu - std::function DrawFunc; - std::function InstancedDrawFunc; + NzRenderer::DrawCall drawFunc; + NzRenderer::DrawCallInstanced instancedDrawFunc; unsigned int indexCount; if (indexBuffer) { - DrawFunc = NzRenderer::DrawIndexedPrimitives; - InstancedDrawFunc = NzRenderer::DrawIndexedPrimitivesInstanced; + drawFunc = NzRenderer::DrawIndexedPrimitives; + instancedDrawFunc = NzRenderer::DrawIndexedPrimitivesInstanced; indexCount = indexBuffer->GetIndexCount(); } else { - DrawFunc = NzRenderer::DrawPrimitives; - InstancedDrawFunc = NzRenderer::DrawPrimitivesInstanced; + drawFunc = NzRenderer::DrawPrimitives; + instancedDrawFunc = NzRenderer::DrawPrimitivesInstanced; indexCount = vertexBuffer->GetVertexCount(); } @@ -140,18 +142,18 @@ bool NzDeferredGeometryPass::Process(const NzScene* scene, unsigned int firstWor instanceMatrices += renderedInstanceCount; // Et on affiche - InstancedDrawFunc(renderedInstanceCount, meshData.primitiveMode, 0, indexCount); + instancedDrawFunc(renderedInstanceCount, meshData.primitiveMode, 0, indexCount); } } else { - // Sans instancing, on doit effectuer un drawcall pour chaque instance + // Sans instancing, on doit effectuer un draw call pour chaque instance // Cela reste néanmoins plus rapide que l'instancing en dessous d'un certain nombre d'instances // À cause du temps de modification du buffer d'instancing for (const NzMatrix4f& matrix : instances) { NzRenderer::SetMatrix(nzMatrixType_World, matrix); - DrawFunc(meshData.primitiveMode, 0, indexCount); + drawFunc(meshData.primitiveMode, 0, indexCount); } } @@ -161,8 +163,8 @@ bool NzDeferredGeometryPass::Process(const NzScene* scene, unsigned int firstWor } // Et on remet à zéro les données - renderQueueInstancing = false; - used = false; + matEntry.enabled = false; + matEntry.instancingEnabled = false; } } @@ -228,7 +230,23 @@ bool NzDeferredGeometryPass::Resize(const NzVector2ui& dimensions) } catch (const std::exception& e) { - NazaraError("Failed to create G-Buffer RTT"); + NazaraError("Failed to create G-Buffer RTT: " + NzString(e.what())); return false; } } + +const NzDeferredGeometryPass::ShaderUniforms* NzDeferredGeometryPass::GetShaderUniforms(const NzShader* shader) const +{ + auto it = m_shaderUniforms.find(shader); + if (it == m_shaderUniforms.end()) + { + ShaderUniforms uniforms; + uniforms.eyePosition = shader->GetUniformLocation("EyePosition"); + uniforms.sceneAmbient = shader->GetUniformLocation("SceneAmbient"); + uniforms.textureOverlay = shader->GetUniformLocation("TextureOverlay"); + + it = m_shaderUniforms.emplace(shader, uniforms).first; + } + + return &it->second; +} diff --git a/src/Nazara/Graphics/DeferredPhongLightingPass.cpp b/src/Nazara/Graphics/DeferredPhongLightingPass.cpp index 7068114cc..6208edbd5 100644 --- a/src/Nazara/Graphics/DeferredPhongLightingPass.cpp +++ b/src/Nazara/Graphics/DeferredPhongLightingPass.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -17,6 +17,8 @@ NzDeferredPhongLightingPass::NzDeferredPhongLightingPass() : m_lightMeshesDrawing(false) { m_directionalLightShader = NzShaderLibrary::Get("DeferredDirectionnalLight"); + m_directionalLightShaderEyePositionLocation = m_directionalLightShader->GetUniformLocation("EyePosition"); + m_directionalLightShaderSceneAmbientLocation = m_directionalLightShader->GetUniformLocation("SceneAmbient"); m_directionalLightUniforms.ubo = false; m_directionalLightUniforms.locations.type = -1; // Type déjà connu @@ -28,6 +30,8 @@ m_lightMeshesDrawing(false) m_pointSpotLightShader = NzShaderLibrary::Get("DeferredPointSpotLight"); m_pointSpotLightShaderDiscardLocation = m_pointSpotLightShader->GetUniformLocation("Discard"); + m_pointSpotLightShaderEyePositionLocation = m_pointSpotLightShader->GetUniformLocation("EyePosition"); + m_pointSpotLightShaderSceneAmbientLocation = m_pointSpotLightShader->GetUniformLocation("SceneAmbient"); m_pointSpotLightUniforms.ubo = false; m_pointSpotLightUniforms.locations.type = m_pointSpotLightShader->GetUniformLocation("LightType"); @@ -96,8 +100,8 @@ bool NzDeferredPhongLightingPass::Process(const NzScene* scene, unsigned int fir { NzRenderer::SetRenderStates(lightStates); NzRenderer::SetShader(m_directionalLightShader); - m_directionalLightShader->SendColor(m_directionalLightShader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor()); - m_directionalLightShader->SendVector(m_directionalLightShader->GetUniformLocation(nzShaderUniform_EyePosition), scene->GetViewer()->GetEyePosition()); + m_directionalLightShader->SendColor(m_directionalLightShaderSceneAmbientLocation, scene->GetAmbientColor()); + m_directionalLightShader->SendVector(m_directionalLightShaderEyePositionLocation, scene->GetViewer()->GetEyePosition()); for (const NzLight* light : m_renderQueue->directionalLights) { @@ -126,8 +130,8 @@ bool NzDeferredPhongLightingPass::Process(const NzScene* scene, unsigned int fir NzRenderer::SetRenderStates(lightStates); NzRenderer::SetShader(m_pointSpotLightShader); - m_pointSpotLightShader->SendColor(m_pointSpotLightShader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor()); - m_pointSpotLightShader->SendVector(m_pointSpotLightShader->GetUniformLocation(nzShaderUniform_EyePosition), scene->GetViewer()->GetEyePosition()); + m_pointSpotLightShader->SendColor(m_pointSpotLightShaderEyePositionLocation, scene->GetAmbientColor()); + m_pointSpotLightShader->SendVector(m_pointSpotLightShaderSceneAmbientLocation, scene->GetViewer()->GetEyePosition()); NzMatrix4f lightMatrix; lightMatrix.MakeIdentity(); diff --git a/src/Nazara/Graphics/DeferredRenderPass.cpp b/src/Nazara/Graphics/DeferredRenderPass.cpp index 2d9a33226..b71b3dd73 100644 --- a/src/Nazara/Graphics/DeferredRenderPass.cpp +++ b/src/Nazara/Graphics/DeferredRenderPass.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/DeferredRenderQueue.cpp b/src/Nazara/Graphics/DeferredRenderQueue.cpp index b57ac1959..071178ad8 100644 --- a/src/Nazara/Graphics/DeferredRenderQueue.cpp +++ b/src/Nazara/Graphics/DeferredRenderQueue.cpp @@ -1,16 +1,15 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include +#include #include #include -#include -#include -#include #include +///TODO: Rendre les billboards via Deferred Shading si possible + namespace { enum ObjectType @@ -26,9 +25,49 @@ m_forwardQueue(forwardQueue) { } -NzDeferredRenderQueue::~NzDeferredRenderQueue() +void NzDeferredRenderQueue::AddBillboard(const NzMaterial* material, const NzVector3f& position, const NzVector2f& size, const NzVector2f& sinCos, const NzColor& color) { - Clear(true); + m_forwardQueue->AddBillboard(material, position, size, sinCos, color); +} + +void NzDeferredRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr, NzSparsePtr colorPtr) +{ + m_forwardQueue->AddBillboards(material, count, positionPtr, sizePtr, sinCosPtr, colorPtr); +} + +void NzDeferredRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr, NzSparsePtr alphaPtr) +{ + m_forwardQueue->AddBillboards(material, count, positionPtr, sizePtr, sinCosPtr, alphaPtr); +} + +void NzDeferredRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr colorPtr) +{ + m_forwardQueue->AddBillboards(material, count, positionPtr, sizePtr, anglePtr, colorPtr); +} + +void NzDeferredRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr alphaPtr) +{ + m_forwardQueue->AddBillboards(material, count, positionPtr, sizePtr, anglePtr, alphaPtr); +} + +void NzDeferredRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr, NzSparsePtr colorPtr) +{ + m_forwardQueue->AddBillboards(material, count, positionPtr, sizePtr, sinCosPtr, colorPtr); +} + +void NzDeferredRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr, NzSparsePtr alphaPtr) +{ + m_forwardQueue->AddBillboards(material, count, positionPtr, sizePtr, sinCosPtr, alphaPtr); +} + +void NzDeferredRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr colorPtr) +{ + m_forwardQueue->AddBillboards(material, count, positionPtr, sizePtr, anglePtr, colorPtr); +} + +void NzDeferredRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr alphaPtr) +{ + m_forwardQueue->AddBillboards(material, count, positionPtr, sizePtr, anglePtr, alphaPtr); } void NzDeferredRenderQueue::AddDrawable(const NzDrawable* drawable) @@ -46,6 +85,7 @@ void NzDeferredRenderQueue::AddLight(const NzLight* light) } #endif + // On trie la lumière (elles sont traitées différement selon leur type) switch (light->GetLightType()) { case nzLightType_Directional: @@ -61,71 +101,55 @@ void NzDeferredRenderQueue::AddLight(const NzLight* light) break; } + // On envoie également la lumière au forward-shading + ///TODO: Possibilité pour une lumière de se réserver au Deferred Shading m_forwardQueue->AddLight(light); } void NzDeferredRenderQueue::AddMesh(const NzMaterial* material, const NzMeshData& meshData, const NzBoxf& meshAABB, const NzMatrix4f& transformMatrix) { if (material->IsEnabled(nzRendererParameter_Blend)) + // Un matériau transparent ? J'aime pas, va voir dans la forward queue si j'y suis m_forwardQueue->AddMesh(material, meshData, meshAABB, transformMatrix); else { - ModelBatches::iterator it = opaqueModels.find(material); + auto it = opaqueModels.find(material); if (it == opaqueModels.end()) { - it = opaqueModels.insert(std::make_pair(material, ModelBatches::mapped_type())).first; - material->AddObjectListener(this, ObjectType_Material); + BatchedModelEntry entry(this, ObjectType_Material); + entry.materialListener = material; + + it = opaqueModels.insert(std::make_pair(material, std::move(entry))).first; } - bool& used = std::get<0>(it->second); - bool& enableInstancing = std::get<1>(it->second); - MeshInstanceContainer& meshMap = std::get<2>(it->second); + BatchedModelEntry& entry = it->second; + entry.enabled = true; - used = true; + auto& meshMap = entry.meshMap; - MeshInstanceContainer::iterator it2 = meshMap.find(meshData); + auto it2 = meshMap.find(meshData); if (it2 == meshMap.end()) { - it2 = meshMap.insert(std::make_pair(meshData, MeshInstanceContainer::mapped_type())).first; + MeshInstanceEntry instanceEntry(this, ObjectType_IndexBuffer, ObjectType_VertexBuffer); + instanceEntry.indexBufferListener = meshData.indexBuffer; + instanceEntry.vertexBufferListener = meshData.vertexBuffer; - if (meshData.indexBuffer) - meshData.indexBuffer->AddObjectListener(this, ObjectType_IndexBuffer); - - meshData.vertexBuffer->AddObjectListener(this, ObjectType_VertexBuffer); + it2 = meshMap.insert(std::make_pair(meshData, std::move(instanceEntry))).first; } - std::vector& instances = it2->second; + // On ajoute la matrice à la liste des instances de cet objet + std::vector& instances = it2->second.instances; instances.push_back(transformMatrix); // Avons-nous suffisamment d'instances pour que le coût d'utilisation de l'instancing soit payé ? if (instances.size() >= NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT) - enableInstancing = true; // Apparemment oui, activons l'instancing avec ce matériau + entry.instancingEnabled = true; // Apparemment oui, activons l'instancing avec ce matériau } } -void NzDeferredRenderQueue::AddSprite(const NzSprite* sprite) +void NzDeferredRenderQueue::AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const NzTexture* overlay) { - #if NAZARA_GRAPHICS_SAFE - if (!sprite) - { - NazaraError("Invalid sprite"); - return; - } - - if (!sprite->IsDrawable()) - { - NazaraError("Sprite is not drawable"); - return; - } - #endif - - /*NzMaterial* material = sprite->GetMaterial(); - if (!material->IsLightingEnabled() || material->IsEnabled(nzRendererParameter_Blend)) - m_forwardQueue->AddSprite(sprite); - else - sprites[material].push_back(sprite);*/ - - m_forwardQueue->AddSprite(sprite); + m_forwardQueue->AddSprites(material, vertices, spriteCount, overlay); } void NzDeferredRenderQueue::Clear(bool fully) @@ -135,27 +159,7 @@ void NzDeferredRenderQueue::Clear(bool fully) spotLights.clear(); if (fully) - { - for (auto& matIt : opaqueModels) - { - const NzMaterial* material = matIt.first; - material->RemoveObjectListener(this); - - MeshInstanceContainer& instances = std::get<2>(matIt.second); - for (auto& instanceIt : instances) - { - const NzMeshData& renderData = instanceIt.first; - - if (renderData.indexBuffer) - renderData.indexBuffer->RemoveObjectListener(this); - - renderData.vertexBuffer->RemoveObjectListener(this); - } - } - opaqueModels.clear(); - sprites.clear(); - } m_forwardQueue->Clear(fully); } @@ -168,7 +172,7 @@ bool NzDeferredRenderQueue::OnObjectDestroy(const NzRefCounted* object, int inde { for (auto& modelPair : opaqueModels) { - MeshInstanceContainer& meshes = std::get<2>(modelPair.second); + MeshInstanceContainer& meshes = modelPair.second.meshMap; for (auto it = meshes.begin(); it != meshes.end();) { const NzMeshData& renderData = it->first; @@ -182,14 +186,18 @@ bool NzDeferredRenderQueue::OnObjectDestroy(const NzRefCounted* object, int inde } case ObjectType_Material: - opaqueModels.erase(static_cast(object)); + { + const NzMaterial* material = static_cast(object); + + opaqueModels.erase(material); break; + } case ObjectType_VertexBuffer: { for (auto& modelPair : opaqueModels) { - MeshInstanceContainer& meshes = std::get<2>(modelPair.second); + MeshInstanceContainer& meshes = modelPair.second.meshMap; for (auto it = meshes.begin(); it != meshes.end();) { const NzMeshData& renderData = it->first; @@ -217,7 +225,7 @@ void NzDeferredRenderQueue::OnObjectReleased(const NzRefCounted* object, int ind { for (auto& modelPair : opaqueModels) { - MeshInstanceContainer& meshes = std::get<2>(modelPair.second); + MeshInstanceContainer& meshes = modelPair.second.meshMap; for (auto it = meshes.begin(); it != meshes.end();) { const NzMeshData& renderData = it->first; @@ -247,7 +255,7 @@ void NzDeferredRenderQueue::OnObjectReleased(const NzRefCounted* object, int ind { for (auto& modelPair : opaqueModels) { - MeshInstanceContainer& meshes = std::get<2>(modelPair.second); + MeshInstanceContainer& meshes = modelPair.second.meshMap; for (auto it = meshes.begin(); it != meshes.end();) { const NzMeshData& renderData = it->first; @@ -282,26 +290,6 @@ bool NzDeferredRenderQueue::BatchedModelMaterialComparator::operator()(const NzM return mat1 < mat2; } -bool NzDeferredRenderQueue::BatchedSpriteMaterialComparator::operator()(const NzMaterial* mat1, const NzMaterial* mat2) -{ - const NzUberShader* uberShader1 = mat1->GetShader(); - const NzUberShader* uberShader2 = mat2->GetShader(); - if (uberShader1 != uberShader2) - return uberShader1 < uberShader2; - - const NzShader* shader1 = mat1->GetShaderInstance(nzShaderFlags_Deferred)->GetShader(); - const NzShader* shader2 = mat2->GetShaderInstance(nzShaderFlags_Deferred)->GetShader(); - if (shader1 != shader2) - return shader1 < shader2; - - const NzTexture* diffuseMap1 = mat1->GetDiffuseMap(); - const NzTexture* diffuseMap2 = mat2->GetDiffuseMap(); - if (diffuseMap1 != diffuseMap2) - return diffuseMap1 < diffuseMap2; - - return mat1 < mat2; -} - bool NzDeferredRenderQueue::MeshDataComparator::operator()(const NzMeshData& data1, const NzMeshData& data2) { const NzBuffer* buffer1; diff --git a/src/Nazara/Graphics/DeferredRenderTechnique.cpp b/src/Nazara/Graphics/DeferredRenderTechnique.cpp index 042af5c81..2b9a30aa6 100644 --- a/src/Nazara/Graphics/DeferredRenderTechnique.cpp +++ b/src/Nazara/Graphics/DeferredRenderTechnique.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,34 @@ namespace { + const nzUInt8 r_fragmentSource_BloomBright[] = { + #include + }; + + const nzUInt8 r_fragmentSource_BloomFinal[] = { + #include + }; + + const nzUInt8 r_fragmentSource_DirectionalLight[] = { + #include + }; + + const nzUInt8 r_fragmentSource_FXAA[] = { + #include + }; + + const nzUInt8 r_fragmentSource_GBufferClear[] = { + #include + }; + + const nzUInt8 r_fragmentSource_GaussianBlur[] = { + #include + }; + + const nzUInt8 r_fragmentSource_PointSpotLight[] = { + #include + }; + unsigned int RenderPassPriority[] = { 6, // nzRenderPassType_AA @@ -412,34 +441,6 @@ bool NzDeferredRenderTechnique::Resize(const NzVector2ui& dimensions) const bool NzDeferredRenderTechnique::Initialize() { - const nzUInt8 fragmentSource_BloomBright[] = { - #include - }; - - const nzUInt8 fragmentSource_BloomFinal[] = { - #include - }; - - const nzUInt8 fragmentSource_DirectionalLight[] = { - #include - }; - - const nzUInt8 fragmentSource_FXAA[] = { - #include - }; - - const nzUInt8 fragmentSource_GBufferClear[] = { - #include - }; - - const nzUInt8 fragmentSource_GaussianBlur[] = { - #include - }; - - const nzUInt8 fragmentSource_PointSpotLight[] = { - #include - }; - const char vertexSource_Basic[] = "#version 140\n" @@ -497,7 +498,7 @@ bool NzDeferredRenderTechnique::Initialize() NzShader* shader; // Shaders critiques (Nécessaires pour le Deferred Shading minimal) - shader = RegisterDeferredShader("DeferredGBufferClear", fragmentSource_GBufferClear, sizeof(fragmentSource_GBufferClear), ppVertexStage, &error); + shader = RegisterDeferredShader("DeferredGBufferClear", r_fragmentSource_GBufferClear, sizeof(r_fragmentSource_GBufferClear), ppVertexStage, &error); if (!shader) { NazaraError("Failed to register critical shader: " + error); @@ -505,7 +506,7 @@ bool NzDeferredRenderTechnique::Initialize() } - shader = RegisterDeferredShader("DeferredDirectionnalLight", fragmentSource_DirectionalLight, sizeof(fragmentSource_DirectionalLight), ppVertexStage, &error); + shader = RegisterDeferredShader("DeferredDirectionnalLight", r_fragmentSource_DirectionalLight, sizeof(r_fragmentSource_DirectionalLight), ppVertexStage, &error); if (!shader) { NazaraError("Failed to register critical shader: " + error); @@ -517,7 +518,7 @@ bool NzDeferredRenderTechnique::Initialize() shader->SendInteger(shader->GetUniformLocation("GBuffer2"), 2); - shader = RegisterDeferredShader("DeferredPointSpotLight", fragmentSource_PointSpotLight, sizeof(fragmentSource_PointSpotLight), basicVertexStage, &error); + shader = RegisterDeferredShader("DeferredPointSpotLight", r_fragmentSource_PointSpotLight, sizeof(r_fragmentSource_PointSpotLight), basicVertexStage, &error); if (!shader) { NazaraError("Failed to register critical shader: " + error); @@ -530,7 +531,7 @@ bool NzDeferredRenderTechnique::Initialize() // Shaders optionnels (S'ils ne sont pas présents, le rendu minimal sera quand même assuré) - shader = RegisterDeferredShader("DeferredBloomBright", fragmentSource_BloomBright, sizeof(fragmentSource_BloomBright), ppVertexStage, &error); + shader = RegisterDeferredShader("DeferredBloomBright", r_fragmentSource_BloomBright, sizeof(r_fragmentSource_BloomBright), ppVertexStage, &error); if (shader) shader->SendInteger(shader->GetUniformLocation("ColorTexture"), 0); else @@ -539,7 +540,7 @@ bool NzDeferredRenderTechnique::Initialize() } - shader = RegisterDeferredShader("DeferredBloomFinal", fragmentSource_BloomFinal, sizeof(fragmentSource_BloomFinal), ppVertexStage, &error); + shader = RegisterDeferredShader("DeferredBloomFinal", r_fragmentSource_BloomFinal, sizeof(r_fragmentSource_BloomFinal), ppVertexStage, &error); if (shader) { shader->SendInteger(shader->GetUniformLocation("ColorTexture"), 0); @@ -551,7 +552,7 @@ bool NzDeferredRenderTechnique::Initialize() } - shader = RegisterDeferredShader("DeferredFXAA", fragmentSource_FXAA, sizeof(fragmentSource_FXAA), ppVertexStage, &error); + shader = RegisterDeferredShader("DeferredFXAA", r_fragmentSource_FXAA, sizeof(r_fragmentSource_FXAA), ppVertexStage, &error); if (shader) shader->SendInteger(shader->GetUniformLocation("ColorTexture"), 0); else @@ -560,7 +561,7 @@ bool NzDeferredRenderTechnique::Initialize() } - shader = RegisterDeferredShader("DeferredGaussianBlur", fragmentSource_GaussianBlur, sizeof(fragmentSource_GaussianBlur), ppVertexStage, &error); + shader = RegisterDeferredShader("DeferredGaussianBlur", r_fragmentSource_GaussianBlur, sizeof(r_fragmentSource_GaussianBlur), ppVertexStage, &error); if (shader) shader->SendInteger(shader->GetUniformLocation("ColorTexture"), 0); else diff --git a/src/Nazara/Graphics/Drawable.cpp b/src/Nazara/Graphics/Drawable.cpp index 7c474bb69..d6ec401a1 100644 --- a/src/Nazara/Graphics/Drawable.cpp +++ b/src/Nazara/Graphics/Drawable.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/ForwardRenderQueue.cpp b/src/Nazara/Graphics/ForwardRenderQueue.cpp index 19bc866bf..59d61a3df 100644 --- a/src/Nazara/Graphics/ForwardRenderQueue.cpp +++ b/src/Nazara/Graphics/ForwardRenderQueue.cpp @@ -1,30 +1,360 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include -#include -#include -#include -#include -#include #include +///TODO: Remplacer les sinus/cosinus par une lookup table (va booster les perfs d'un bon x10) + namespace { - enum ResourceType + enum ObjectType { - ResourceType_IndexBuffer, - ResourceType_Material, - ResourceType_VertexBuffer + ObjectType_IndexBuffer, + ObjectType_Material, + ObjectType_Texture, + ObjectType_VertexBuffer }; } -NzForwardRenderQueue::~NzForwardRenderQueue() +void NzForwardRenderQueue::AddBillboard(const NzMaterial* material, const NzVector3f& position, const NzVector2f& size, const NzVector2f& sinCos, const NzColor& color) { - Clear(true); + auto it = billboards.find(material); + if (it == billboards.end()) + { + BatchedBillboardEntry entry(this, ObjectType_Material); + entry.materialListener = material; + + it = billboards.insert(std::make_pair(material, std::move(entry))).first; + } + + BatchedBillboardEntry& entry = it->second; + + auto& billboardVector = entry.billboards; + billboardVector.push_back(BillboardData{color, position, size, sinCos}); +} + +void NzForwardRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr, NzSparsePtr colorPtr) +{ + ///DOC: sinCosPtr et colorPtr peuvent être nuls, ils seont remplacés respectivement par Vector2f(0.f, 1.f) et Color::White + NzVector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1 + + if (!sinCosPtr) + sinCosPtr.Reset(&defaultSinCos, 0); // L'astuce ici est de mettre le stride sur zéro, rendant le pointeur immobile + + if (!colorPtr) + colorPtr.Reset(&NzColor::White, 0); // Pareil + + auto it = billboards.find(material); + if (it == billboards.end()) + { + BatchedBillboardEntry entry(this, ObjectType_Material); + entry.materialListener = material; + + it = billboards.insert(std::make_pair(material, std::move(entry))).first; + } + + BatchedBillboardEntry& entry = it->second; + + auto& billboardVector = entry.billboards; + unsigned int prevSize = billboardVector.size(); + billboardVector.resize(prevSize + count); + + BillboardData* billboardData = &billboardVector[prevSize]; + for (unsigned int i = 0; i < count; ++i) + { + billboardData->center = *positionPtr++; + billboardData->color = *colorPtr++; + billboardData->sinCos = *sinCosPtr++; + billboardData->size = *sizePtr++; + billboardData++; + } +} + +void NzForwardRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr, NzSparsePtr alphaPtr) +{ + ///DOC: sinCosPtr et alphaPtr peuvent être nuls, ils seont remplacés respectivement par Vector2f(0.f, 1.f) et Color::White + NzVector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1 + + if (!sinCosPtr) + sinCosPtr.Reset(&defaultSinCos, 0); // L'astuce ici est de mettre le stride sur zéro, rendant le pointeur immobile + + float defaultAlpha = 1.f; + + if (!alphaPtr) + alphaPtr.Reset(&defaultAlpha, 0); // Pareil + + auto it = billboards.find(material); + if (it == billboards.end()) + { + BatchedBillboardEntry entry(this, ObjectType_Material); + entry.materialListener = material; + + it = billboards.insert(std::make_pair(material, std::move(entry))).first; + } + + BatchedBillboardEntry& entry = it->second; + + auto& billboardVector = entry.billboards; + unsigned int prevSize = billboardVector.size(); + billboardVector.resize(prevSize + count); + + BillboardData* billboardData = &billboardVector[prevSize]; + for (unsigned int i = 0; i < count; ++i) + { + billboardData->center = *positionPtr++; + billboardData->color = NzColor(255, 255, 255, static_cast(255.f * (*alphaPtr++))); + billboardData->sinCos = *sinCosPtr++; + billboardData->size = *sizePtr++; + billboardData++; + } +} + +void NzForwardRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr colorPtr) +{ + ///DOC: sinCosPtr et colorPtr peuvent être nuls, ils seont remplacés respectivement par Vector2f(0.f, 1.f) et Color::White + float defaultRotation = 0.f; + + if (!anglePtr) + anglePtr.Reset(&defaultRotation, 0); // L'astuce ici est de mettre le stride sur zéro, rendant le pointeur immobile + + if (!colorPtr) + colorPtr.Reset(&NzColor::White, 0); // Pareil + + auto it = billboards.find(material); + if (it == billboards.end()) + { + BatchedBillboardEntry entry(this, ObjectType_Material); + entry.materialListener = material; + + it = billboards.insert(std::make_pair(material, std::move(entry))).first; + } + + BatchedBillboardEntry& entry = it->second; + + auto& billboardVector = entry.billboards; + unsigned int prevSize = billboardVector.size(); + billboardVector.resize(prevSize + count); + + BillboardData* billboardData = &billboardVector[prevSize]; + for (unsigned int i = 0; i < count; ++i) + { + float sin = std::sin(NzToRadians(*anglePtr)); + float cos = std::cos(NzToRadians(*anglePtr)); + anglePtr++; + + billboardData->center = *positionPtr++; + billboardData->color = *colorPtr++; + billboardData->sinCos.Set(sin, cos); + billboardData->size = *sizePtr++; + billboardData++; + } +} + +void NzForwardRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr alphaPtr) +{ + ///DOC: sinCosPtr et alphaPtr peuvent être nuls, ils seont remplacés respectivement par Vector2f(0.f, 1.f) et Color::White + float defaultRotation = 0.f; + + if (!anglePtr) + anglePtr.Reset(&defaultRotation, 0); // L'astuce ici est de mettre le stride sur zéro, rendant le pointeur immobile + + float defaultAlpha = 1.f; + + if (!alphaPtr) + alphaPtr.Reset(&defaultAlpha, 0); // Pareil + + auto it = billboards.find(material); + if (it == billboards.end()) + { + BatchedBillboardEntry entry(this, ObjectType_Material); + entry.materialListener = material; + + it = billboards.insert(std::make_pair(material, std::move(entry))).first; + } + + BatchedBillboardEntry& entry = it->second; + + auto& billboardVector = entry.billboards; + unsigned int prevSize = billboardVector.size(); + billboardVector.resize(prevSize + count); + + BillboardData* billboardData = &billboardVector[prevSize]; + for (unsigned int i = 0; i < count; ++i) + { + float sin = std::sin(NzToRadians(*anglePtr)); + float cos = std::cos(NzToRadians(*anglePtr)); + anglePtr++; + + billboardData->center = *positionPtr++; + billboardData->color = NzColor(255, 255, 255, static_cast(255.f * (*alphaPtr++))); + billboardData->sinCos.Set(sin, cos); + billboardData->size = *sizePtr++; + billboardData++; + } +} + +void NzForwardRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr, NzSparsePtr colorPtr) +{ + ///DOC: sinCosPtr et colorPtr peuvent être nuls, ils seont remplacés respectivement par Vector2f(0.f, 1.f) et Color::White + NzVector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1 + + if (!sinCosPtr) + sinCosPtr.Reset(&defaultSinCos, 0); // L'astuce ici est de mettre le stride sur zéro, rendant le pointeur immobile + + if (!colorPtr) + colorPtr.Reset(&NzColor::White, 0); // Pareil + + auto it = billboards.find(material); + if (it == billboards.end()) + { + BatchedBillboardEntry entry(this, ObjectType_Material); + entry.materialListener = material; + + it = billboards.insert(std::make_pair(material, std::move(entry))).first; + } + + BatchedBillboardEntry& entry = it->second; + + auto& billboardVector = entry.billboards; + unsigned int prevSize = billboardVector.size(); + billboardVector.resize(prevSize + count); + + BillboardData* billboardData = &billboardVector[prevSize]; + for (unsigned int i = 0; i < count; ++i) + { + billboardData->center = *positionPtr++; + billboardData->color = *colorPtr++; + billboardData->sinCos = *sinCosPtr++; + billboardData->size.Set(*sizePtr++); + billboardData++; + } +} + +void NzForwardRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr sinCosPtr, NzSparsePtr alphaPtr) +{ + ///DOC: sinCosPtr et alphaPtr peuvent être nuls, ils seont remplacés respectivement par Vector2f(0.f, 1.f) et Color::White + NzVector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1 + + if (!sinCosPtr) + sinCosPtr.Reset(&defaultSinCos, 0); // L'astuce ici est de mettre le stride sur zéro, rendant le pointeur immobile + + float defaultAlpha = 1.f; + + if (!alphaPtr) + alphaPtr.Reset(&defaultAlpha, 0); // Pareil + + auto it = billboards.find(material); + if (it == billboards.end()) + { + BatchedBillboardEntry entry(this, ObjectType_Material); + entry.materialListener = material; + + it = billboards.insert(std::make_pair(material, std::move(entry))).first; + } + + BatchedBillboardEntry& entry = it->second; + + auto& billboardVector = entry.billboards; + unsigned int prevSize = billboardVector.size(); + billboardVector.resize(prevSize + count); + + BillboardData* billboardData = &billboardVector[prevSize]; + for (unsigned int i = 0; i < count; ++i) + { + billboardData->center = *positionPtr++; + billboardData->color = NzColor(255, 255, 255, static_cast(255.f * (*alphaPtr++))); + billboardData->sinCos = *sinCosPtr++; + billboardData->size.Set(*sizePtr++); + billboardData++; + } +} + +void NzForwardRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr colorPtr) +{ + ///DOC: sinCosPtr et colorPtr peuvent être nuls, ils seont remplacés respectivement par Vector2f(0.f, 1.f) et Color::White + float defaultRotation = 0.f; + + if (!anglePtr) + anglePtr.Reset(&defaultRotation, 0); // L'astuce ici est de mettre le stride sur zéro, rendant le pointeur immobile + + if (!colorPtr) + colorPtr.Reset(&NzColor::White, 0); // Pareil + + auto it = billboards.find(material); + if (it == billboards.end()) + { + BatchedBillboardEntry entry(this, ObjectType_Material); + entry.materialListener = material; + + it = billboards.insert(std::make_pair(material, std::move(entry))).first; + } + + BatchedBillboardEntry& entry = it->second; + + auto& billboardVector = entry.billboards; + unsigned int prevSize = billboardVector.size(); + billboardVector.resize(prevSize + count); + + BillboardData* billboardData = &billboardVector[prevSize]; + for (unsigned int i = 0; i < count; ++i) + { + float sin = std::sin(NzToRadians(*anglePtr)); + float cos = std::cos(NzToRadians(*anglePtr)); + anglePtr++; + + billboardData->center = *positionPtr++; + billboardData->color = *colorPtr++; + billboardData->sinCos.Set(sin, cos); + billboardData->size.Set(*sizePtr++); + billboardData++; + } +} + +void NzForwardRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr positionPtr, NzSparsePtr sizePtr, NzSparsePtr anglePtr, NzSparsePtr alphaPtr) +{ + ///DOC: sinCosPtr et alphaPtr peuvent être nuls, ils seont remplacés respectivement par Vector2f(0.f, 1.f) et Color::White + float defaultRotation = 0.f; + + if (!anglePtr) + anglePtr.Reset(&defaultRotation, 0); // L'astuce ici est de mettre le stride sur zéro, rendant le pointeur immobile + + float defaultAlpha = 1.f; + + if (!alphaPtr) + alphaPtr.Reset(&defaultAlpha, 0); // Pareil + + auto it = billboards.find(material); + if (it == billboards.end()) + { + BatchedBillboardEntry entry(this, ObjectType_Material); + entry.materialListener = material; + + it = billboards.insert(std::make_pair(material, std::move(entry))).first; + } + + BatchedBillboardEntry& entry = it->second; + + auto& billboardVector = entry.billboards; + unsigned int prevSize = billboardVector.size(); + billboardVector.resize(prevSize + count); + + BillboardData* billboardData = &billboardVector[prevSize]; + for (unsigned int i = 0; i < count; ++i) + { + float sin = std::sin(NzToRadians(*anglePtr)); + float cos = std::cos(NzToRadians(*anglePtr)); + anglePtr++; + + billboardData->center = *positionPtr++; + billboardData->color = NzColor(255, 255, 255, static_cast(255.f * (*alphaPtr++))); + billboardData->sinCos.Set(sin, cos); + billboardData->size.Set(*sizePtr++); + billboardData++; + } } void NzForwardRenderQueue::AddDrawable(const NzDrawable* drawable) @@ -72,72 +402,81 @@ void NzForwardRenderQueue::AddMesh(const NzMaterial* material, const NzMeshData& { if (material->IsEnabled(nzRendererParameter_Blend)) { + // Le matériau est transparent, nous devons rendre ce mesh d'une autre façon (après le rendu des objets opaques et en les triant) unsigned int index = transparentModelData.size(); transparentModelData.resize(index+1); TransparentModelData& data = transparentModelData.back(); - data.boundingSphere = NzSpheref(transformMatrix.GetTranslation() + meshAABB.GetCenter(), meshAABB.GetSquaredRadius()); data.material = material; data.meshData = meshData; + data.squaredBoundingSphere = NzSpheref(transformMatrix.GetTranslation() + meshAABB.GetCenter(), meshAABB.GetSquaredRadius()); data.transformMatrix = transformMatrix; transparentModels.push_back(index); } else { - ModelBatches::iterator it = opaqueModels.find(material); + auto it = opaqueModels.find(material); if (it == opaqueModels.end()) { - it = opaqueModels.insert(std::make_pair(material, ModelBatches::mapped_type())).first; - material->AddObjectListener(this, ResourceType_Material); + BatchedModelEntry entry(this, ObjectType_Material); + entry.materialListener = material; + + it = opaqueModels.insert(std::make_pair(material, std::move(entry))).first; } - bool& used = std::get<0>(it->second); - bool& enableInstancing = std::get<1>(it->second); - MeshInstanceContainer& meshMap = std::get<2>(it->second); + BatchedModelEntry& entry = it->second; + entry.enabled = true; - used = true; + auto& meshMap = entry.meshMap; - MeshInstanceContainer::iterator it2 = meshMap.find(meshData); + auto it2 = meshMap.find(meshData); if (it2 == meshMap.end()) { - it2 = meshMap.insert(std::make_pair(meshData, MeshInstanceContainer::mapped_type())).first; + MeshInstanceEntry instanceEntry(this, ObjectType_IndexBuffer, ObjectType_VertexBuffer); + instanceEntry.indexBufferListener = meshData.indexBuffer; + instanceEntry.squaredBoundingSphere = meshAABB.GetSquaredBoundingSphere(); + instanceEntry.vertexBufferListener = meshData.vertexBuffer; - NzSpheref& squaredBoundingSphere = it2->second.first; - squaredBoundingSphere.Set(meshAABB.GetSquaredBoundingSphere()); - - if (meshData.indexBuffer) - meshData.indexBuffer->AddObjectListener(this, ResourceType_IndexBuffer); - - meshData.vertexBuffer->AddObjectListener(this, ResourceType_VertexBuffer); + it2 = meshMap.insert(std::make_pair(meshData, std::move(instanceEntry))).first; } - std::vector& instances = it2->second.second; + std::vector& instances = it2->second.instances; instances.push_back(transformMatrix); // Avons-nous suffisamment d'instances pour que le coût d'utilisation de l'instancing soit payé ? if (instances.size() >= NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT) - enableInstancing = true; // Apparemment oui, activons l'instancing avec ce matériau + entry.instancingEnabled = true; // Apparemment oui, activons l'instancing avec ce matériau } } -void NzForwardRenderQueue::AddSprite(const NzSprite* sprite) +void NzForwardRenderQueue::AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const NzTexture* overlay) { - #if NAZARA_GRAPHICS_SAFE - if (!sprite) + auto matIt = basicSprites.find(material); + if (matIt == basicSprites.end()) { - NazaraError("Invalid sprite"); - return; + BatchedBasicSpriteEntry entry(this, ObjectType_Material); + entry.materialListener = material; + + matIt = basicSprites.insert(std::make_pair(material, std::move(entry))).first; } - if (!sprite->IsDrawable()) - { - NazaraError("Sprite is not drawable"); - return; - } - #endif + BatchedBasicSpriteEntry& entry = matIt->second; + entry.enabled = true; - sprites[sprite->GetMaterial()].push_back(sprite); + auto& overlayMap = entry.overlayMap; + + auto overlayIt = overlayMap.find(overlay); + if (overlayIt == overlayMap.end()) + { + BatchedSpriteEntry overlayEntry(this, ObjectType_Texture); + overlayEntry.textureListener = overlay; + + overlayIt = overlayMap.insert(std::make_pair(overlay, std::move(overlayEntry))).first; + } + + auto& spriteVector = overlayIt->second.spriteChains; + spriteVector.push_back(SpriteChain_XYZ_Color_UV({vertices, spriteCount})); } void NzForwardRenderQueue::Clear(bool fully) @@ -150,53 +489,55 @@ void NzForwardRenderQueue::Clear(bool fully) if (fully) { - for (auto& matIt : opaqueModels) - { - const NzMaterial* material = matIt.first; - material->RemoveObjectListener(this); - - MeshInstanceContainer& instances = std::get<2>(matIt.second); - for (auto& instanceIt : instances) - { - const NzMeshData& renderData = instanceIt.first; - - if (renderData.indexBuffer) - renderData.indexBuffer->RemoveObjectListener(this); - - renderData.vertexBuffer->RemoveObjectListener(this); - } - } + basicSprites.clear(); + billboards.clear(); opaqueModels.clear(); - sprites.clear(); } } void NzForwardRenderQueue::Sort(const NzAbstractViewer* viewer) { NzPlanef nearPlane = viewer->GetFrustum().GetPlane(nzFrustumPlane_Near); + NzVector3f viewerPos = viewer->GetEyePosition(); NzVector3f viewerNormal = viewer->GetForward(); std::sort(transparentModels.begin(), transparentModels.end(), [this, &nearPlane, &viewerNormal](unsigned int index1, unsigned int index2) { - const NzSpheref& sphere1 = transparentModelData[index1].boundingSphere; - const NzSpheref& sphere2 = transparentModelData[index2].boundingSphere; + const NzSpheref& sphere1 = transparentModelData[index1].squaredBoundingSphere; + const NzSpheref& sphere2 = transparentModelData[index2].squaredBoundingSphere; NzVector3f position1 = sphere1.GetNegativeVertex(viewerNormal); NzVector3f position2 = sphere2.GetNegativeVertex(viewerNormal); return nearPlane.Distance(position1) > nearPlane.Distance(position2); }); + + for (auto& pair : billboards) + { + const NzMaterial* mat = pair.first; + + if (mat->IsDepthSortingEnabled()) + { + BatchedBillboardEntry& entry = pair.second; + auto& billboardVector = entry.billboards; + + std::sort(billboardVector.begin(), billboardVector.end(), [&viewerPos](const BillboardData& data1, const BillboardData& data2) + { + return viewerPos.SquaredDistance(data1.center) > viewerPos.SquaredDistance(data2.center); + }); + } + } } bool NzForwardRenderQueue::OnObjectDestroy(const NzRefCounted* object, int index) { switch (index) { - case ResourceType_IndexBuffer: + case ObjectType_IndexBuffer: { for (auto& modelPair : opaqueModels) { - MeshInstanceContainer& meshes = std::get<2>(modelPair.second); + MeshInstanceContainer& meshes = modelPair.second.meshMap; for (auto it = meshes.begin(); it != meshes.end();) { const NzMeshData& renderData = it->first; @@ -209,15 +550,21 @@ bool NzForwardRenderQueue::OnObjectDestroy(const NzRefCounted* object, int index break; } - case ResourceType_Material: - opaqueModels.erase(static_cast(object)); - break; + case ObjectType_Material: + { + const NzMaterial* material = static_cast(object); - case ResourceType_VertexBuffer: + basicSprites.erase(material); + billboards.erase(material); + opaqueModels.erase(material); + break; + } + + case ObjectType_VertexBuffer: { for (auto& modelPair : opaqueModels) { - MeshInstanceContainer& meshes = std::get<2>(modelPair.second); + MeshInstanceContainer& meshes = modelPair.second.meshMap; for (auto it = meshes.begin(); it != meshes.end();) { const NzMeshData& renderData = it->first; @@ -241,11 +588,11 @@ void NzForwardRenderQueue::OnObjectReleased(const NzRefCounted* object, int inde switch (index) { - case ResourceType_IndexBuffer: + case ObjectType_IndexBuffer: { for (auto& modelPair : opaqueModels) { - MeshInstanceContainer& meshes = std::get<2>(modelPair.second); + MeshInstanceContainer& meshes = modelPair.second.meshMap; for (auto it = meshes.begin(); it != meshes.end();) { const NzMeshData& renderData = it->first; @@ -258,8 +605,26 @@ void NzForwardRenderQueue::OnObjectReleased(const NzRefCounted* object, int inde break; } - case ResourceType_Material: + case ObjectType_Material: { + for (auto it = basicSprites.begin(); it != basicSprites.end(); ++it) + { + if (it->first == object) + { + basicSprites.erase(it); + break; + } + } + + for (auto it = billboards.begin(); it != billboards.end(); ++it) + { + if (it->first == object) + { + billboards.erase(it); + break; + } + } + for (auto it = opaqueModels.begin(); it != opaqueModels.end(); ++it) { if (it->first == object) @@ -268,14 +633,33 @@ void NzForwardRenderQueue::OnObjectReleased(const NzRefCounted* object, int inde break; } } + break; } - case ResourceType_VertexBuffer: + case ObjectType_Texture: + { + for (auto matIt = basicSprites.begin(); matIt != basicSprites.end(); ++matIt) + { + auto& overlayMap = matIt->second.overlayMap; + for (auto overlayIt = overlayMap.begin(); overlayIt != overlayMap.end(); ++overlayIt) + { + if (overlayIt->first == object) + { + overlayMap.erase(overlayIt); + break; + } + } + } + + break; + } + + case ObjectType_VertexBuffer: { for (auto& modelPair : opaqueModels) { - MeshInstanceContainer& meshes = std::get<2>(modelPair.second); + MeshInstanceContainer& meshes = modelPair.second.meshMap; for (auto it = meshes.begin(); it != meshes.end();) { const NzMeshData& renderData = it->first; @@ -290,6 +674,26 @@ void NzForwardRenderQueue::OnObjectReleased(const NzRefCounted* object, int inde } } +bool NzForwardRenderQueue::BatchedBillboardComparator::operator()(const NzMaterial* mat1, const NzMaterial* mat2) +{ + const NzUberShader* uberShader1 = mat1->GetShader(); + const NzUberShader* uberShader2 = mat2->GetShader(); + if (uberShader1 != uberShader2) + return uberShader1 < uberShader2; + + const NzShader* shader1 = mat1->GetShaderInstance(nzShaderFlags_Billboard | nzShaderFlags_VertexColor)->GetShader(); + const NzShader* shader2 = mat2->GetShaderInstance(nzShaderFlags_Billboard | nzShaderFlags_VertexColor)->GetShader(); + if (shader1 != shader2) + return shader1 < shader2; + + const NzTexture* diffuseMap1 = mat1->GetDiffuseMap(); + const NzTexture* diffuseMap2 = mat2->GetDiffuseMap(); + if (diffuseMap1 != diffuseMap2) + return diffuseMap1 < diffuseMap2; + + return mat1 < mat2; +} + bool NzForwardRenderQueue::BatchedModelMaterialComparator::operator()(const NzMaterial* mat1, const NzMaterial* mat2) { const NzUberShader* uberShader1 = mat1->GetShader(); @@ -299,7 +703,6 @@ bool NzForwardRenderQueue::BatchedModelMaterialComparator::operator()(const NzMa const NzShader* shader1 = mat1->GetShaderInstance()->GetShader(); const NzShader* shader2 = mat2->GetShaderInstance()->GetShader(); - if (shader1 != shader2) return shader1 < shader2; @@ -320,7 +723,6 @@ bool NzForwardRenderQueue::BatchedSpriteMaterialComparator::operator()(const NzM const NzShader* shader1 = mat1->GetShaderInstance()->GetShader(); const NzShader* shader2 = mat2->GetShaderInstance()->GetShader(); - if (shader1 != shader2) return shader1 < shader2; diff --git a/src/Nazara/Graphics/ForwardRenderTechnique.cpp b/src/Nazara/Graphics/ForwardRenderTechnique.cpp index 68726c809..5605812ec 100644 --- a/src/Nazara/Graphics/ForwardRenderTechnique.cpp +++ b/src/Nazara/Graphics/ForwardRenderTechnique.cpp @@ -1,13 +1,16 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -22,46 +25,29 @@ namespace { - static NzIndexBuffer* s_indexBuffer = nullptr; - unsigned int s_maxSprites = 8192; - - NzIndexBuffer* BuildIndexBuffer() + struct BillboardPoint { - std::unique_ptr indexBuffer(new NzIndexBuffer(false, s_maxSprites*6, nzBufferStorage_Hardware, nzBufferUsage_Static)); - indexBuffer->SetPersistent(false); + NzColor color; + NzVector3f position; + NzVector2f size; + NzVector2f sinCos; // doit suivre size + NzVector2f uv; + }; - NzBufferMapper mapper(indexBuffer.get(), nzBufferAccess_WriteOnly); - nzUInt16* indices = static_cast(mapper.GetPointer()); - - for (unsigned int i = 0; i < s_maxSprites; ++i) - { - *indices++ = i*4 + 0; - *indices++ = i*4 + 2; - *indices++ = i*4 + 1; - - *indices++ = i*4 + 2; - *indices++ = i*4 + 3; - *indices++ = i*4 + 1; - } - - return indexBuffer.release(); - } + unsigned int s_maxQuads = std::numeric_limits::max()/6; + unsigned int s_vertexBufferSize = 4*1024*1024; // 4 MiB } NzForwardRenderTechnique::NzForwardRenderTechnique() : -m_spriteBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_UV), s_maxSprites*4, nzBufferStorage_Hardware, nzBufferUsage_Dynamic), +m_vertexBuffer(nzBufferType_Vertex), m_maxLightPassPerObject(3) { - if (!s_indexBuffer) - s_indexBuffer = BuildIndexBuffer(); + NzErrorFlags flags(nzErrorFlag_ThrowException, true); - m_indexBuffer = s_indexBuffer; -} + m_vertexBuffer.Create(s_vertexBufferSize, nzDataStorage_Hardware, nzBufferUsage_Dynamic); -NzForwardRenderTechnique::~NzForwardRenderTechnique() -{ - if (m_indexBuffer.Reset()) - s_indexBuffer = nullptr; + m_billboardPointBuffer.Reset(&s_billboardVertexDeclaration, &m_vertexBuffer); + m_spriteBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Color_UV), &m_vertexBuffer); } void NzForwardRenderTechnique::Clear(const NzScene* scene) const @@ -87,59 +73,17 @@ bool NzForwardRenderTechnique::Draw(const NzScene* scene) const if (!m_renderQueue.transparentModels.empty()) DrawTransparentModels(scene); - if (!m_renderQueue.sprites.empty()) - DrawSprites(scene); + if (!m_renderQueue.basicSprites.empty()) + DrawBasicSprites(scene); + + if (!m_renderQueue.billboards.empty()) + DrawBillboards(scene); // Les autres drawables (Exemple: Terrain) for (const NzDrawable* drawable : m_renderQueue.otherDrawables) drawable->Draw(); return true; - - // Les billboards - /*if (!m_renderQueue.billboards.empty()) - { - //NzRenderer::SetIndexBuffer(m_billboardIndexBuffer); - NzRenderer::SetMatrix(nzMatrixType_World, NzMatrix4f::Identity()); - NzRenderer::SetShader(m_billboardShader); - NzRenderer::SetVertexBuffer(m_billboardVertexBuffer); - - m_billboardShader->SendVector(s_cameraForwardLocation, camera->GetForward()); - m_billboardShader->SendVector(s_cameraUpLocation, camera->GetUp()); - m_billboardShader->SendVector(s_worldUpLocation, NzVector3f::Up()); - - // Couleur ambiante de la scène - m_billboardShader->SendColor(m_billboardShader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor()); - // Position de la caméra - m_billboardShader->SendVector(m_billboardShader->GetUniformLocation(nzShaderUniform_CameraPosition), camera->GetPosition()); - - lightCount = 0; - - // On envoie les lumières directionnelles s'il y a (Les mêmes pour tous) - m_renderQueue.lights[0]->Apply(m_billboardShader, 0); - - for (auto& matIt : m_renderQueue.billboards) - { - const NzMaterial* material = matIt.first; - auto& billboards = matIt.second; - - material->Apply(m_billboardShader); - - unsigned int billboardCount = billboards.size(); - const NzForwardRenderQueue::BillboardData* data = &billboards[0]; - while (billboardCount > 0) - { - unsigned int renderedBillboardCount = std::min(billboardCount, maxBillboards); - billboardCount -= renderedBillboardCount; - - m_billboardVertexBuffer->FillVertices(data, 0, renderedBillboardCount, true); - data += renderedBillboardCount; - - NzRenderer::DrawPrimitives(nzPrimitiveMode_PointList, 0, renderedBillboardCount); - } - billboards.clear(); - } - }*/ } unsigned int NzForwardRenderTechnique::GetMaxLightPassPerObject() const @@ -162,19 +106,329 @@ void NzForwardRenderTechnique::SetMaxLightPassPerObject(unsigned int passCount) m_maxLightPassPerObject = passCount; } +void NzForwardRenderTechnique::DrawBasicSprites(const NzScene* scene) const +{ + NzAbstractViewer* viewer = scene->GetViewer(); + const NzShader* lastShader = nullptr; + const ShaderUniforms* shaderUniforms = nullptr; + + NzRenderer::SetIndexBuffer(&s_quadIndexBuffer); + NzRenderer::SetMatrix(nzMatrixType_World, NzMatrix4f::Identity()); + NzRenderer::SetVertexBuffer(&m_spriteBuffer); + + for (auto& matIt : m_renderQueue.basicSprites) + { + const NzMaterial* material = matIt.first; + auto& matEntry = matIt.second; + + if (matEntry.enabled) + { + auto& overlayMap = matEntry.overlayMap; + for (auto& overlayIt : overlayMap) + { + const NzTexture* overlay = overlayIt.first; + auto& spriteChainVector = overlayIt.second.spriteChains; + + unsigned int spriteChainCount = spriteChainVector.size(); + if (spriteChainCount > 0) + { + // On commence par appliquer du matériau (et récupérer le shader ainsi activé) + nzUInt32 flags = nzShaderFlags_VertexColor; + if (overlay) + flags |= nzShaderFlags_TextureOverlay; + + nzUInt8 overlayUnit; + const NzShader* shader = material->Apply(flags, 0, &overlayUnit); + + if (overlay) + { + overlayUnit++; + NzRenderer::SetTexture(overlayUnit, overlay); + NzRenderer::SetTextureSampler(overlayUnit, material->GetDiffuseSampler()); + } + + // Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas + if (shader != lastShader) + { + // Index des uniformes dans le shader + shaderUniforms = GetShaderUniforms(shader); + + // Couleur ambiante de la scène + shader->SendColor(shaderUniforms->sceneAmbient, scene->GetAmbientColor()); + // Overlay + shader->SendInteger(shaderUniforms->textureOverlay, overlayUnit); + // Position de la caméra + shader->SendVector(shaderUniforms->eyePosition, viewer->GetEyePosition()); + + lastShader = shader; + } + + unsigned int spriteChain = 0; // Quelle chaîne de sprite traitons-nous + unsigned int spriteChainOffset = 0; // À quel offset dans la dernière chaîne nous sommes-nous arrêtés + + do + { + // On ouvre le buffer en écriture + NzBufferMapper vertexMapper(m_spriteBuffer, nzBufferAccess_DiscardAndWrite); + NzVertexStruct_XYZ_Color_UV* vertices = reinterpret_cast(vertexMapper.GetPointer()); + + unsigned int spriteCount = 0; + unsigned int maxSpriteCount = std::min(s_maxQuads, m_spriteBuffer.GetVertexCount()/4); + + do + { + NzForwardRenderQueue::SpriteChain_XYZ_Color_UV& currentChain = spriteChainVector[spriteChain]; + unsigned int count = std::min(maxSpriteCount - spriteCount, currentChain.spriteCount - spriteChainOffset); + + std::memcpy(vertices, currentChain.vertices + spriteChainOffset*4, 4*count*sizeof(NzVertexStruct_XYZ_Color_UV)); + vertices += count*4; + + spriteCount += count; + spriteChainOffset += count; + + // Avons-nous traité la chaîne entière ? + if (spriteChainOffset == currentChain.spriteCount) + { + spriteChain++; + spriteChainOffset = 0; + } + } + while (spriteCount < maxSpriteCount && spriteChain < spriteChainCount); + + vertexMapper.Unmap(); + + NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, spriteCount*6); + } + while (spriteChain < spriteChainCount); + + spriteChainVector.clear(); + } + } + + // On remet à zéro + matEntry.enabled = false; + } + } +} + +bool NzForwardRenderTechnique::Initialize() +{ + try + { + NzErrorFlags flags(nzErrorFlag_ThrowException, true); + + s_quadIndexBuffer.Reset(false, s_maxQuads*6, nzDataStorage_Hardware, nzBufferUsage_Static); + + NzBufferMapper mapper(s_quadIndexBuffer, nzBufferAccess_WriteOnly); + nzUInt16* indices = static_cast(mapper.GetPointer()); + + for (unsigned int i = 0; i < s_maxQuads; ++i) + { + *indices++ = i*4 + 0; + *indices++ = i*4 + 2; + *indices++ = i*4 + 1; + + *indices++ = i*4 + 2; + *indices++ = i*4 + 3; + *indices++ = i*4 + 1; + } + + mapper.Unmap(); // Inutile de garder le buffer ouvert plus longtemps + + // Quad buffer (utilisé pour l'instancing de billboard et de sprites) + //Note: Les UV sont calculés dans le shader + s_quadVertexBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XY), 4, nzDataStorage_Hardware, nzBufferUsage_Static); + + float vertices[2*4] = { + -0.5f, -0.5f, + 0.5f, -0.5f, + -0.5f, 0.5f, + 0.5f, 0.5f, + }; + + s_quadVertexBuffer.FillRaw(vertices, 0, sizeof(vertices)); + + // Déclaration lors du rendu des billboards par sommet + s_billboardVertexDeclaration.EnableComponent(nzVertexComponent_Color, nzComponentType_Color, NzOffsetOf(BillboardPoint, color)); + s_billboardVertexDeclaration.EnableComponent(nzVertexComponent_Position, nzComponentType_Float3, NzOffsetOf(BillboardPoint, position)); + s_billboardVertexDeclaration.EnableComponent(nzVertexComponent_TexCoord, nzComponentType_Float2, NzOffsetOf(BillboardPoint, uv)); + s_billboardVertexDeclaration.EnableComponent(nzVertexComponent_Userdata0, nzComponentType_Float4, NzOffsetOf(BillboardPoint, size)); // Englobe sincos + + // Declaration utilisée lors du rendu des billboards par instancing + // L'avantage ici est la copie directe (std::memcpy) des données de la RenderQueue vers le buffer GPU + s_billboardInstanceDeclaration.EnableComponent(nzVertexComponent_InstanceData0, nzComponentType_Float3, NzOffsetOf(NzForwardRenderQueue::BillboardData, center)); + s_billboardInstanceDeclaration.EnableComponent(nzVertexComponent_InstanceData1, nzComponentType_Float4, NzOffsetOf(NzForwardRenderQueue::BillboardData, size)); // Englobe sincos + s_billboardInstanceDeclaration.EnableComponent(nzVertexComponent_InstanceData2, nzComponentType_Color, NzOffsetOf(NzForwardRenderQueue::BillboardData, color)); + } + catch (const std::exception& e) + { + NazaraError("Failed to initialise: " + NzString(e.what())); + return false; + } + + return true; +} + +void NzForwardRenderTechnique::Uninitialize() +{ + s_quadIndexBuffer.Reset(); + s_quadVertexBuffer.Reset(); +} + +void NzForwardRenderTechnique::DrawBillboards(const NzScene* scene) const +{ + NzAbstractViewer* viewer = scene->GetViewer(); + const NzShader* lastShader = nullptr; + const ShaderUniforms* shaderUniforms = nullptr; + + if (NzRenderer::HasCapability(nzRendererCap_Instancing)) + { + NzVertexBuffer* instanceBuffer = NzRenderer::GetInstanceBuffer(); + instanceBuffer->SetVertexDeclaration(&s_billboardInstanceDeclaration); + + NzRenderer::SetVertexBuffer(&s_quadVertexBuffer); + + for (auto& matIt : m_renderQueue.billboards) + { + const NzMaterial* material = matIt.first; + auto& entry = matIt.second; + auto& billboardVector = entry.billboards; + + unsigned int billboardCount = billboardVector.size(); + if (billboardCount > 0) + { + // On commence par appliquer du matériau (et récupérer le shader ainsi activé) + const NzShader* shader = material->Apply(nzShaderFlags_Billboard | nzShaderFlags_Instancing | nzShaderFlags_VertexColor); + + // Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas + if (shader != lastShader) + { + // Index des uniformes dans le shader + shaderUniforms = GetShaderUniforms(shader); + + // Couleur ambiante de la scène + shader->SendColor(shaderUniforms->sceneAmbient, scene->GetAmbientColor()); + // Position de la caméra + shader->SendVector(shaderUniforms->eyePosition, viewer->GetEyePosition()); + + lastShader = shader; + } + + const NzForwardRenderQueue::BillboardData* data = &billboardVector[0]; + unsigned int maxBillboardPerDraw = instanceBuffer->GetVertexCount(); + do + { + unsigned int renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw); + billboardCount -= renderedBillboardCount; + + instanceBuffer->Fill(data, 0, renderedBillboardCount, true); + data += renderedBillboardCount; + + NzRenderer::DrawPrimitivesInstanced(renderedBillboardCount, nzPrimitiveMode_TriangleStrip, 0, 4); + } + while (billboardCount > 0); + + billboardVector.clear(); + } + } + } + else + { + NzRenderer::SetIndexBuffer(&s_quadIndexBuffer); + NzRenderer::SetVertexBuffer(&m_billboardPointBuffer); + + for (auto& matIt : m_renderQueue.billboards) + { + const NzMaterial* material = matIt.first; + auto& entry = matIt.second; + auto& billboardVector = entry.billboards; + + unsigned int billboardCount = billboardVector.size(); + if (billboardCount > 0) + { + // On commence par appliquer du matériau (et récupérer le shader ainsi activé) + const NzShader* shader = material->Apply(nzShaderFlags_Billboard | nzShaderFlags_VertexColor); + + // Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas + if (shader != lastShader) + { + // Couleur ambiante de la scène + shader->SendColor(shaderUniforms->sceneAmbient, scene->GetAmbientColor()); + // Position de la caméra + shader->SendVector(shaderUniforms->eyePosition, viewer->GetEyePosition()); + + lastShader = shader; + } + + const NzForwardRenderQueue::BillboardData* data = &billboardVector[0]; + unsigned int maxBillboardPerDraw = std::min(s_maxQuads, m_billboardPointBuffer.GetVertexCount()/4); + + do + { + unsigned int renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw); + billboardCount -= renderedBillboardCount; + + NzBufferMapper vertexMapper(m_billboardPointBuffer, nzBufferAccess_DiscardAndWrite, 0, renderedBillboardCount*4); + BillboardPoint* vertices = reinterpret_cast(vertexMapper.GetPointer()); + + for (unsigned int i = 0; i < renderedBillboardCount; ++i) + { + const NzForwardRenderQueue::BillboardData& billboard = *data++; + + vertices->color = billboard.color; + vertices->position = billboard.center; + vertices->sinCos = billboard.sinCos; + vertices->size = billboard.size; + vertices->uv.Set(0.f, 1.f); + vertices++; + + vertices->color = billboard.color; + vertices->position = billboard.center; + vertices->sinCos = billboard.sinCos; + vertices->size = billboard.size; + vertices->uv.Set(1.f, 1.f); + vertices++; + + vertices->color = billboard.color; + vertices->position = billboard.center; + vertices->sinCos = billboard.sinCos; + vertices->size = billboard.size; + vertices->uv.Set(0.f, 0.f); + vertices++; + + vertices->color = billboard.color; + vertices->position = billboard.center; + vertices->sinCos = billboard.sinCos; + vertices->size = billboard.size; + vertices->uv.Set(1.f, 0.f); + vertices++; + } + + vertexMapper.Unmap(); + + NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, renderedBillboardCount*6); + } + while (billboardCount > 0); + + billboardVector.clear(); + } + } + } +} + void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const { NzAbstractViewer* viewer = scene->GetViewer(); - const LightUniforms* lightUniforms = nullptr; const NzShader* lastShader = nullptr; + const ShaderUniforms* shaderUniforms = nullptr; for (auto& matIt : m_renderQueue.opaqueModels) { - bool& used = std::get<0>(matIt.second); - if (used) + auto& matEntry = matIt.second; + + if (matEntry.enabled) { - bool& renderQueueInstancing = std::get<1>(matIt.second); - NzForwardRenderQueue::MeshInstanceContainer& meshInstances = std::get<2>(matIt.second); + NzForwardRenderQueue::MeshInstanceContainer& meshInstances = matEntry.meshMap; if (!meshInstances.empty()) { @@ -183,7 +437,7 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const // Nous utilisons de l'instancing que lorsqu'aucune lumière (autre que directionnelle) n'est active // Ceci car l'instancing n'est pas compatible avec la recherche des lumières les plus proches // (Le deferred shading n'a pas ce problème) - bool instancing = m_instancingEnabled && (!material->IsLightingEnabled() || m_lights.IsEmpty()) && renderQueueInstancing; + bool instancing = m_instancingEnabled && (!material->IsLightingEnabled() || m_lights.IsEmpty()) && matEntry.instancingEnabled; // On commence par appliquer du matériau (et récupérer le shader ainsi activé) const NzShader* shader = material->Apply((instancing) ? nzShaderFlags_Instancing : 0); @@ -191,23 +445,25 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const // Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas if (shader != lastShader) { - // Couleur ambiante de la scène - shader->SendColor(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor()); - // Position de la caméra - shader->SendVector(shader->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition()); + // Index des uniformes dans le shader + shaderUniforms = GetShaderUniforms(shader); - // Index des uniformes d'éclairage dans le shader - lightUniforms = GetLightUniforms(shader); + // Couleur ambiante de la scène + shader->SendColor(shaderUniforms->sceneAmbient, scene->GetAmbientColor()); + // Position de la caméra + shader->SendVector(shaderUniforms->eyePosition, viewer->GetEyePosition()); lastShader = shader; } // Meshes - for (auto& subMeshIt : meshInstances) + for (auto& meshIt : meshInstances) { - const NzMeshData& meshData = subMeshIt.first; - const NzSpheref& boundingSphere = subMeshIt.second.first; - std::vector& instances = subMeshIt.second.second; + const NzMeshData& meshData = meshIt.first; + auto& meshEntry = meshIt.second; + + const NzSpheref& squaredBoundingSphere = meshEntry.squaredBoundingSphere; + std::vector& instances = meshEntry.instances; if (!instances.empty()) { @@ -215,20 +471,20 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const const NzVertexBuffer* vertexBuffer = meshData.vertexBuffer; // Gestion du draw call avant la boucle de rendu - std::function DrawFunc; - std::function InstancedDrawFunc; + NzRenderer::DrawCall drawFunc; + NzRenderer::DrawCallInstanced instancedDrawFunc; unsigned int indexCount; if (indexBuffer) { - DrawFunc = NzRenderer::DrawIndexedPrimitives; - InstancedDrawFunc = NzRenderer::DrawIndexedPrimitivesInstanced; + drawFunc = NzRenderer::DrawIndexedPrimitives; + instancedDrawFunc = NzRenderer::DrawIndexedPrimitivesInstanced; indexCount = indexBuffer->GetIndexCount(); } else { - DrawFunc = NzRenderer::DrawPrimitives; - InstancedDrawFunc = NzRenderer::DrawPrimitivesInstanced; + drawFunc = NzRenderer::DrawPrimitives; + instancedDrawFunc = NzRenderer::DrawPrimitivesInstanced; indexCount = vertexBuffer->GetVertexCount(); } @@ -250,7 +506,7 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const unsigned int passCount = (lightCount == 0) ? 1 : (lightCount-1)/NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS + 1; for (unsigned int pass = 0; pass < passCount; ++pass) { - if (lightUniforms->exists) + if (shaderUniforms->hasLightUniforms) { unsigned int renderedLightCount = std::min(lightCount, NazaraSuffixMacro(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, U)); lightCount -= renderedLightCount; @@ -267,15 +523,15 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const } for (unsigned int i = 0; i < renderedLightCount; ++i) - m_directionalLights.GetLight(lightIndex++)->Enable(shader, lightUniforms->uniforms, lightUniforms->offset*i); + m_directionalLights.GetLight(lightIndex++)->Enable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i); for (unsigned int i = renderedLightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i) - NzLight::Disable(shader, lightUniforms->uniforms, lightUniforms->offset*i); + NzLight::Disable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i); } const NzMatrix4f* instanceMatrices = &instances[0]; unsigned int instanceCount = instances.size(); - unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); // On calcule le nombre d'instances que l'on pourra afficher cette fois-ci (Selon la taille du buffer d'instancing) + unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); // Le nombre maximum d'instances en une fois while (instanceCount > 0) { @@ -288,7 +544,7 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const instanceMatrices += renderedInstanceCount; // Et on affiche - InstancedDrawFunc(renderedInstanceCount, meshData.primitiveMode, 0, indexCount); + instancedDrawFunc(renderedInstanceCount, meshData.primitiveMode, 0, indexCount); } } @@ -298,12 +554,12 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const } else { - if (lightUniforms->exists) + if (shaderUniforms->hasLightUniforms) { for (const NzMatrix4f& matrix : instances) { unsigned int directionalLightCount = m_directionalLights.GetLightCount(); - unsigned int otherLightCount = m_lights.ComputeClosestLights(matrix.GetTranslation() + boundingSphere.GetPosition(), boundingSphere.radius, m_maxLightPassPerObject*NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS - directionalLightCount); + unsigned int otherLightCount = m_lights.ComputeClosestLights(matrix.GetTranslation() + squaredBoundingSphere.GetPosition(), squaredBoundingSphere.radius, m_maxLightPassPerObject*NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS - directionalLightCount); unsigned int lightCount = directionalLightCount + otherLightCount; NzRenderer::SetMatrix(nzMatrixType_World, matrix); @@ -332,17 +588,17 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const for (unsigned int i = 0; i < renderedLightCount; ++i) { if (directionalLightIndex >= directionalLightCount) - m_lights.GetResult(otherLightIndex++)->Enable(shader, lightUniforms->uniforms, lightUniforms->offset*i); + m_lights.GetResult(otherLightIndex++)->Enable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i); else - m_directionalLights.GetLight(directionalLightIndex++)->Enable(shader, lightUniforms->uniforms, lightUniforms->offset*i); + m_directionalLights.GetLight(directionalLightIndex++)->Enable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i); } // On désactive l'éventuel surplus for (unsigned int i = renderedLightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i) - NzLight::Disable(shader, lightUniforms->uniforms, lightUniforms->offset*i); + NzLight::Disable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i); // Et on passe à l'affichage - DrawFunc(meshData.primitiveMode, 0, indexCount); + drawFunc(meshData.primitiveMode, 0, indexCount); } NzRenderer::Enable(nzRendererParameter_Blend, false); @@ -351,13 +607,13 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const } else { - // Sans instancing, on doit effectuer un drawcall pour chaque instance + // Sans instancing, on doit effectuer un draw call pour chaque instance // Cela reste néanmoins plus rapide que l'instancing en dessous d'un certain nombre d'instances // À cause du temps de modification du buffer d'instancing for (const NzMatrix4f& matrix : instances) { NzRenderer::SetMatrix(nzMatrixType_World, matrix); - DrawFunc(meshData.primitiveMode, 0, indexCount); + drawFunc(meshData.primitiveMode, 0, indexCount); } } } @@ -367,84 +623,8 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const } // Et on remet à zéro les données - renderQueueInstancing = false; - used = false; - } - } -} - -void NzForwardRenderTechnique::DrawSprites(const NzScene* scene) const -{ - NzAbstractViewer* viewer = scene->GetViewer(); - const NzShader* lastShader = nullptr; - - NzRenderer::SetIndexBuffer(m_indexBuffer); - NzRenderer::SetMatrix(nzMatrixType_World, NzMatrix4f::Identity()); - NzRenderer::SetVertexBuffer(&m_spriteBuffer); - - for (auto& matIt : m_renderQueue.sprites) - { - const NzMaterial* material = matIt.first; - auto& spriteVector = matIt.second; - - unsigned int spriteCount = spriteVector.size(); - if (spriteCount > 0) - { - // On commence par appliquer du matériau (et récupérer le shader ainsi activé) - const NzShader* shader = material->Apply(); - - // Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas - if (shader != lastShader) - { - // Couleur ambiante de la scène - shader->SendColor(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor()); - // Position de la caméra - shader->SendVector(shader->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition()); - - lastShader = shader; - } - - const NzSprite** spritePtr = &spriteVector[0]; - do - { - unsigned int renderedSpriteCount = std::min(spriteCount, 64U); - spriteCount -= renderedSpriteCount; - - NzBufferMapper vertexMapper(m_spriteBuffer, nzBufferAccess_DiscardAndWrite, 0, renderedSpriteCount*4); - NzVertexStruct_XYZ_UV* vertices = reinterpret_cast(vertexMapper.GetPointer()); - - for (unsigned int i = 0; i < renderedSpriteCount; ++i) - { - const NzSprite* sprite = *spritePtr++; - const NzRectf& textureCoords = sprite->GetTextureCoords(); - const NzVector2f& halfSize = sprite->GetSize()*0.5f; - NzVector3f center = sprite->GetPosition(); - NzQuaternionf rotation = sprite->GetRotation(); - - vertices->position = center + rotation * NzVector3f(-halfSize.x, -halfSize.y, 0.f); - vertices->uv.Set(textureCoords.x, textureCoords.y + textureCoords.height); - vertices++; - - vertices->position = center + rotation * NzVector3f(halfSize.x, -halfSize.y, 0.f); - vertices->uv.Set(textureCoords.width, textureCoords.y + textureCoords.height); - vertices++; - - vertices->position = center + rotation * NzVector3f(-halfSize.x, halfSize.y, 0.f); - vertices->uv.Set(textureCoords.x, textureCoords.y); - vertices++; - - vertices->position = center + rotation * NzVector3f(halfSize.x, halfSize.y, 0.f); - vertices->uv.Set(textureCoords.width, textureCoords.y); - vertices++; - } - - vertexMapper.Unmap(); - - NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, renderedSpriteCount*6); - } - while (spriteCount > 0); - - spriteVector.clear(); + matEntry.enabled = false; + matEntry.instancingEnabled = false; } } } @@ -452,8 +632,8 @@ void NzForwardRenderTechnique::DrawSprites(const NzScene* scene) const void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene) const { NzAbstractViewer* viewer = scene->GetViewer(); - const LightUniforms* lightUniforms = nullptr; const NzShader* lastShader = nullptr; + const ShaderUniforms* shaderUniforms = nullptr; unsigned int lightCount = 0; for (unsigned int index : m_renderQueue.transparentModels) @@ -469,18 +649,18 @@ void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene) const // Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas if (shader != lastShader) { - // Couleur ambiante de la scène - shader->SendColor(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor()); - // Position de la caméra - shader->SendVector(shader->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition()); + // Index des uniformes dans le shader + shaderUniforms = GetShaderUniforms(shader); - // Index des uniformes d'éclairage dans le shader - lightUniforms = GetLightUniforms(shader); + // Couleur ambiante de la scène + shader->SendColor(shaderUniforms->sceneAmbient, scene->GetAmbientColor()); + // Position de la caméra + shader->SendVector(shaderUniforms->eyePosition, viewer->GetEyePosition()); // On envoie les lumières directionnelles s'il y a (Les mêmes pour tous) lightCount = std::min(m_directionalLights.GetLightCount(), NazaraSuffixMacro(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, U)); for (unsigned int i = 0; i < lightCount; ++i) - m_directionalLights.GetLight(i)->Enable(shader, lightUniforms->uniforms, lightUniforms->offset*i); + m_directionalLights.GetLight(i)->Enable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i); lastShader = shader; } @@ -493,17 +673,17 @@ void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene) const const NzVertexBuffer* vertexBuffer = meshData.vertexBuffer; // Gestion du draw call avant la boucle de rendu - std::function DrawFunc; + NzRenderer::DrawCall drawFunc; unsigned int indexCount; if (indexBuffer) { - DrawFunc = NzRenderer::DrawIndexedPrimitives; + drawFunc = NzRenderer::DrawIndexedPrimitives; indexCount = indexBuffer->GetIndexCount(); } else { - DrawFunc = NzRenderer::DrawPrimitives; + drawFunc = NzRenderer::DrawPrimitives; indexCount = vertexBuffer->GetVertexCount(); } @@ -513,47 +693,58 @@ void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene) const // Calcul des lumières les plus proches if (lightCount < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS && !m_lights.IsEmpty()) { - unsigned int count = std::min(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS - lightCount, m_lights.ComputeClosestLights(matrix.GetTranslation() + modelData.boundingSphere.GetPosition(), modelData.boundingSphere.radius, NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS)); + NzVector3f position = matrix.GetTranslation() + modelData.squaredBoundingSphere.GetPosition(); + float radius = modelData.squaredBoundingSphere.radius; + unsigned int closestLightCount = m_lights.ComputeClosestLights(position, radius, NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS); + + unsigned int count = std::min(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS - lightCount, closestLightCount); for (unsigned int i = 0; i < count; ++i) - m_lights.GetResult(i)->Enable(shader, lightUniforms->uniforms, lightUniforms->offset*(lightCount++)); + m_lights.GetResult(i)->Enable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*(lightCount++)); } for (unsigned int i = lightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i) - NzLight::Disable(shader, lightUniforms->uniforms, lightUniforms->offset*i); + NzLight::Disable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i); NzRenderer::SetMatrix(nzMatrixType_World, matrix); - DrawFunc(meshData.primitiveMode, 0, indexCount); + drawFunc(meshData.primitiveMode, 0, indexCount); } } -const NzForwardRenderTechnique::LightUniforms* NzForwardRenderTechnique::GetLightUniforms(const NzShader* shader) const +const NzForwardRenderTechnique::ShaderUniforms* NzForwardRenderTechnique::GetShaderUniforms(const NzShader* shader) const { - auto it = m_lightUniforms.find(shader); - if (it != m_lightUniforms.end()) - return &(it->second); - else + auto it = m_shaderUniforms.find(shader); + if (it == m_shaderUniforms.end()) { + ShaderUniforms uniforms; + uniforms.eyePosition = shader->GetUniformLocation("EyePosition"); + uniforms.sceneAmbient = shader->GetUniformLocation("SceneAmbient"); + uniforms.textureOverlay = shader->GetUniformLocation("TextureOverlay"); + int type0Location = shader->GetUniformLocation("Lights[0].type"); int type1Location = shader->GetUniformLocation("Lights[1].type"); - LightUniforms lightUniforms; - if (type0Location > 0 && type1Location > 0) { - lightUniforms.exists = true; - lightUniforms.offset = type1Location - type0Location; - lightUniforms.uniforms.ubo = false; - lightUniforms.uniforms.locations.type = type0Location; - lightUniforms.uniforms.locations.color = shader->GetUniformLocation("Lights[0].color"); - lightUniforms.uniforms.locations.factors = shader->GetUniformLocation("Lights[0].factors"); - lightUniforms.uniforms.locations.parameters1 = shader->GetUniformLocation("Lights[0].parameters1"); - lightUniforms.uniforms.locations.parameters2 = shader->GetUniformLocation("Lights[0].parameters2"); - lightUniforms.uniforms.locations.parameters3 = shader->GetUniformLocation("Lights[0].parameters3"); + uniforms.hasLightUniforms = true; + uniforms.lightOffset = type1Location - type0Location; + uniforms.lightUniforms.ubo = false; + uniforms.lightUniforms.locations.type = type0Location; + uniforms.lightUniforms.locations.color = shader->GetUniformLocation("Lights[0].color"); + uniforms.lightUniforms.locations.factors = shader->GetUniformLocation("Lights[0].factors"); + uniforms.lightUniforms.locations.parameters1 = shader->GetUniformLocation("Lights[0].parameters1"); + uniforms.lightUniforms.locations.parameters2 = shader->GetUniformLocation("Lights[0].parameters2"); + uniforms.lightUniforms.locations.parameters3 = shader->GetUniformLocation("Lights[0].parameters3"); } else - lightUniforms.exists = false; + uniforms.hasLightUniforms = false; - auto pair = m_lightUniforms.emplace(shader, lightUniforms); - return &(pair.first->second); + it = m_shaderUniforms.emplace(shader, uniforms).first; } + + return &it->second; } + +NzIndexBuffer NzForwardRenderTechnique::s_quadIndexBuffer; +NzVertexBuffer NzForwardRenderTechnique::s_quadVertexBuffer; +NzVertexDeclaration NzForwardRenderTechnique::s_billboardInstanceDeclaration; +NzVertexDeclaration NzForwardRenderTechnique::s_billboardVertexDeclaration; diff --git a/src/Nazara/Graphics/Graphics.cpp b/src/Nazara/Graphics/Graphics.cpp index db8e9c619..93c7766a3 100644 --- a/src/Nazara/Graphics/Graphics.cpp +++ b/src/Nazara/Graphics/Graphics.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,13 +9,16 @@ #include #include #include +#include #include +#include #include #include #include #include #include #include +#include #include bool NzGraphics::Initialize() @@ -44,6 +47,12 @@ bool NzGraphics::Initialize() return false; } + if (!NzParticleDeclaration::Initialize()) + { + NazaraError("Failed to initialize particle declarations"); + return false; + } + if (!NzSkinningManager::Initialize()) { NazaraError("Failed to initialize skinning manager"); @@ -58,14 +67,26 @@ bool NzGraphics::Initialize() NzLoaders_Texture_Register(); // RenderTechniques + if (!NzForwardRenderTechnique::Initialize()) + { + NazaraError("Failed to initialize Forward Rendering"); + return false; + } + NzRenderTechniques::Register(NzRenderTechniques::ToString(nzRenderTechniqueType_BasicForward), 0, []() -> NzAbstractRenderTechnique* { return new NzForwardRenderTechnique; }); if (NzDeferredRenderTechnique::IsSupported()) { - NzDeferredRenderTechnique::Initialize(); - NzRenderTechniques::Register(NzRenderTechniques::ToString(nzRenderTechniqueType_DeferredShading), 20, []() -> NzAbstractRenderTechnique* { return new NzDeferredRenderTechnique; }); + if (NzDeferredRenderTechnique::Initialize()) + NzRenderTechniques::Register(NzRenderTechniques::ToString(nzRenderTechniqueType_DeferredShading), 20, []() -> NzAbstractRenderTechnique* { return new NzDeferredRenderTechnique; }); + else + { + NazaraWarning("Failed to initialize Deferred Rendering"); + } } + NzFont::SetDefaultAtlas(std::make_shared()); + onExit.Reset(); NazaraNotice("Initialized: Graphics module"); @@ -91,13 +112,40 @@ void NzGraphics::Uninitialize() // Libération du module s_moduleReferenceCounter = 0; + // Libération de l'atlas s'il vient de nous + std::shared_ptr defaultAtlas = NzFont::GetDefaultAtlas(); + if (defaultAtlas && defaultAtlas->GetStorage() & nzDataStorage_Hardware) + { + NzFont::SetDefaultAtlas(nullptr); + + // La police par défaut peut faire vivre un atlas hardware après la libération du module (ce qui va être problématique) + // du coup, si la police par défaut utilise un atlas hardware, on lui enlève. + // Je n'aime pas cette solution mais je n'en ai pas de meilleure sous la main pour l'instant + if (!defaultAtlas.unique()) + { + // Encore au moins une police utilise l'atlas + NzFont* defaultFont = NzFont::GetDefault(); + defaultFont->SetAtlas(nullptr); + + if (!defaultAtlas.unique()) + { + // Toujours pas seuls propriétaires ? Ah ben zut. + NazaraWarning("Default font atlas uses hardware storage and is still used"); + } + } + } + + defaultAtlas.reset(); + // Loaders NzLoaders_Mesh_Unregister(); NzLoaders_OBJ_Unregister(); NzLoaders_Texture_Unregister(); NzDeferredRenderTechnique::Uninitialize(); + NzForwardRenderTechnique::Uninitialize(); NzMaterial::Uninitialize(); + NzParticleDeclaration::Uninitialize(); NzSkinningManager::Uninitialize(); NazaraNotice("Uninitialized: Graphics module"); diff --git a/src/Nazara/Graphics/GuillotineTextureAtlas.cpp b/src/Nazara/Graphics/GuillotineTextureAtlas.cpp new file mode 100644 index 000000000..baa477498 --- /dev/null +++ b/src/Nazara/Graphics/GuillotineTextureAtlas.cpp @@ -0,0 +1,48 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +nzUInt32 NzGuillotineTextureAtlas::GetStorage() const +{ + return nzDataStorage_Hardware; +} + +NzAbstractImage* NzGuillotineTextureAtlas::ResizeImage(NzAbstractImage* oldImage, const NzVector2ui& size) const +{ + std::unique_ptr newTexture(new NzTexture); + if (newTexture->Create(nzImageType_2D, nzPixelFormat_A8, size.x, size.y, 1, 0xFF)) + { + if (oldImage) + { + NzTexture* oldTexture = static_cast(oldImage); + + // Copie des anciennes données + ///TODO: Copie de texture à texture + NzImage image; + if (!oldTexture->Download(&image)) + { + NazaraError("Failed to download old texture"); + return nullptr; + } + + if (!newTexture->Update(image, NzRectui(0, 0, image.GetWidth(), image.GetHeight()))) + { + NazaraError("Failed to update texture"); + return nullptr; + } + } + + return newTexture.release(); + } + else + { + // Si on arrive ici c'est que la taille demandée est trop grande pour la carte graphique + // ou que nous manquons de mémoire + return nullptr; + } +} diff --git a/src/Nazara/Graphics/Light.cpp b/src/Nazara/Graphics/Light.cpp index d3ce97152..414c6cffa 100644 --- a/src/Nazara/Graphics/Light.cpp +++ b/src/Nazara/Graphics/Light.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -14,11 +14,11 @@ #include ///TODO: Utilisation des UBOs +///TODO: Scale ? NzLight::NzLight(nzLightType type) : m_type(type), m_color(NzColor::White), -m_boundingVolumeUpdated(false), m_ambientFactor((type == nzLightType_Directional) ? 0.2f : 0.f), m_attenuation(0.9f), m_diffuseFactor(1.f), @@ -31,9 +31,7 @@ m_radius(5.f) NzLight::NzLight(const NzLight& light) : NzSceneNode(light), m_type(light.m_type), -m_boundingVolume(light.m_boundingVolume), m_color(light.m_color), -m_boundingVolumeUpdated(light.m_boundingVolumeUpdated), m_ambientFactor(light.m_ambientFactor), m_attenuation(light.m_attenuation), m_diffuseFactor(light.m_diffuseFactor), @@ -41,7 +39,7 @@ m_innerAngle(light.m_innerAngle), m_outerAngle(light.m_outerAngle), m_radius(light.m_radius) { - SetParent(light); + SetParent(light.GetParent()); } void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const @@ -49,6 +47,16 @@ void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const renderQueue->AddLight(this); } +NzLight* NzLight::Clone() const +{ + return new NzLight(*this); +} + +NzLight* NzLight::Create() const +{ + return new NzLight; +} + void NzLight::Enable(const NzShader* shader, const NzLightUniforms& uniforms, int offset) const { /* @@ -112,14 +120,6 @@ float NzLight::GetAttenuation() const return m_attenuation; } -const NzBoundingVolumef& NzLight::GetBoundingVolume() const -{ - if (!m_boundingVolumeUpdated) - UpdateBoundingVolume(); - - return m_boundingVolume; -} - NzColor NzLight::GetColor() const { return m_color; @@ -251,11 +251,45 @@ bool NzLight::FrustumCull(const NzFrustumf& frustum) const return false; } -void NzLight::InvalidateNode() +void NzLight::MakeBoundingVolume() const { - NzSceneNode::InvalidateNode(); + switch (m_type) + { + case nzLightType_Directional: + m_boundingVolume.MakeInfinite(); + break; - m_boundingVolumeUpdated = false; + case nzLightType_Point: + { + NzVector3f radius(m_radius); + m_boundingVolume.Set(-radius, radius); + break; + } + + case nzLightType_Spot: + { + // On forme une boite sur l'origine + NzBoxf box(NzVector3f::Zero()); + + // On calcule le reste des points + NzVector3f base(NzVector3f::Forward()*m_radius); + + // Il nous faut maintenant le rayon du cercle projeté à cette distance + // Tangente = Opposé/Adjaçent <=> Opposé = Adjaçent*Tangente + float radius = m_radius*std::tan(NzDegreeToRadian(m_outerAngle)); + NzVector3f lExtend = NzVector3f::Left()*radius; + NzVector3f uExtend = NzVector3f::Up()*radius; + + // Et on ajoute ensuite les quatres extrémités de la pyramide + box.ExtendTo(base + lExtend + uExtend); + box.ExtendTo(base + lExtend - uExtend); + box.ExtendTo(base - lExtend + uExtend); + box.ExtendTo(base - lExtend - uExtend); + + m_boundingVolume.Set(box); + break; + } + } } void NzLight::Register() @@ -269,46 +303,7 @@ void NzLight::Unregister() void NzLight::UpdateBoundingVolume() const { if (m_boundingVolume.IsNull()) - { - switch (m_type) - { - case nzLightType_Directional: - m_boundingVolume.MakeInfinite(); - m_boundingVolumeUpdated = true; - return; // Rien d'autre à faire - - case nzLightType_Point: - { - NzVector3f radius(m_radius); - m_boundingVolume.Set(-radius, radius); - break; - } - - case nzLightType_Spot: - { - // On forme une boite sur l'origine - NzBoxf box(NzVector3f::Zero()); - - // On calcule le reste des points - NzVector3f base(NzVector3f::Forward()*m_radius); - - // Il nous faut maintenant le rayon du cercle projeté à cette distance - // Tangente = Opposé/Adjaçent <=> Opposé = Adjaçent*Tangente - float radius = m_radius*std::tan(NzDegreeToRadian(m_outerAngle)); - NzVector3f lExtend = NzVector3f::Left()*radius; - NzVector3f uExtend = NzVector3f::Up()*radius; - - // Et on ajoute ensuite les quatres extrémités de la pyramide - box.ExtendTo(base + lExtend + uExtend); - box.ExtendTo(base + lExtend - uExtend); - box.ExtendTo(base - lExtend + uExtend); - box.ExtendTo(base - lExtend - uExtend); - - m_boundingVolume.Set(box); - break; - } - } - } + MakeBoundingVolume(); switch (m_type) { diff --git a/src/Nazara/Graphics/LightManager.cpp b/src/Nazara/Graphics/LightManager.cpp index 107a170bc..d0f8b3bb6 100644 --- a/src/Nazara/Graphics/LightManager.cpp +++ b/src/Nazara/Graphics/LightManager.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -37,10 +37,10 @@ unsigned int NzLightManager::ComputeClosestLights(const NzVector3f& position, fl light.score = std::numeric_limits::max(); // Nous jouons au Golf } - for (unsigned int i = 0; i < m_lights.size(); ++i) + for (auto it = m_lights.begin(); it != m_lights.end(); ++it) { - const NzLight** lights = m_lights[i].first; - unsigned int lightCount = m_lights[i].second; + const NzLight** lights = it->first; + unsigned int lightCount = it->second; for (unsigned int j = 0; j < lightCount; ++j) { diff --git a/src/Nazara/Graphics/Loaders/Mesh.hpp b/src/Nazara/Graphics/Loaders/Mesh.hpp index c730f2a92..44c5d98e1 100644 --- a/src/Nazara/Graphics/Loaders/Mesh.hpp +++ b/src/Nazara/Graphics/Loaders/Mesh.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/Loaders/Mesh/Loader.cpp b/src/Nazara/Graphics/Loaders/Mesh/Loader.cpp index d64597248..ad973f77e 100644 --- a/src/Nazara/Graphics/Loaders/Mesh/Loader.cpp +++ b/src/Nazara/Graphics/Loaders/Mesh/Loader.cpp @@ -1,10 +1,11 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include +#include #include #include #include @@ -32,11 +33,71 @@ namespace } if (mesh->IsAnimable()) + { + NazaraError("Can't load animated mesh into static model"); + return false; + } + + // Nous ne pouvons plus avoir recours au smart pointeur à partir d'ici si nous voulons être exception-safe + NzMesh* meshPtr = mesh.get(); + + model->Reset(); + model->SetMesh(meshPtr); + mesh.release(); + + if (parameters.loadMaterials) + { + unsigned int matCount = model->GetMaterialCount(); + + for (unsigned int i = 0; i < matCount; ++i) + { + NzString mat = meshPtr->GetMaterial(i); + if (!mat.IsEmpty()) + { + std::unique_ptr material(new NzMaterial); + material->SetPersistent(false); + + if (material->LoadFromFile(mat, parameters.material)) + { + model->SetMaterial(i, material.get()); + material.release(); + } + else + NazaraWarning("Failed to load material #" + NzString::Number(i)); + } + } + } + + return true; + } + + nzTernary CheckAnimated(NzInputStream& stream, const NzSkeletalModelParameters& parameters) + { + NazaraUnused(stream); + NazaraUnused(parameters); + + return nzTernary_Unknown; + } + + bool LoadAnimated(NzSkeletalModel* model, NzInputStream& stream, const NzSkeletalModelParameters& parameters) + { + NazaraUnused(parameters); + + std::unique_ptr mesh(new NzMesh); + mesh->SetPersistent(false); + if (!mesh->LoadFromStream(stream, parameters.mesh)) + { + NazaraError("Failed to load model mesh"); + return false; + } + + if (!mesh->IsAnimable()) { NazaraError("Can't load static mesh into animated model"); return false; } + // Nous ne pouvons plus avoir recours au smart pointeur à partir d'ici si nous voulons être exception-safe NzMesh* meshPtr = mesh.get(); @@ -74,9 +135,11 @@ namespace void NzLoaders_Mesh_Register() { NzModelLoader::RegisterLoader(NzMeshLoader::IsExtensionSupported, CheckStatic, LoadStatic); + NzSkeletalModelLoader::RegisterLoader(NzMeshLoader::IsExtensionSupported, CheckAnimated, LoadAnimated); } void NzLoaders_Mesh_Unregister() { NzModelLoader::UnregisterLoader(NzMeshLoader::IsExtensionSupported, CheckStatic, LoadStatic); + NzSkeletalModelLoader::UnregisterLoader(NzMeshLoader::IsExtensionSupported, CheckAnimated, LoadAnimated); } diff --git a/src/Nazara/Graphics/Loaders/OBJ.hpp b/src/Nazara/Graphics/Loaders/OBJ.hpp index 4748fc7bd..71f20f8e3 100644 --- a/src/Nazara/Graphics/Loaders/OBJ.hpp +++ b/src/Nazara/Graphics/Loaders/OBJ.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp b/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp index 3d939f7ea..d848ef052 100644 --- a/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp +++ b/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -61,6 +61,8 @@ namespace for (unsigned int i = 0; i < meshCount; ++i) { unsigned int faceCount = meshes[i].faces.size(); + if (faceCount == 0) + continue; std::vector indices; indices.reserve(faceCount*3); // Pire cas si les faces sont des triangles @@ -97,6 +99,7 @@ namespace } } + // Création des buffers std::unique_ptr indexBuffer(new NzIndexBuffer(vertexCount > std::numeric_limits::max(), indices.size(), parameters.mesh.storage, nzBufferUsage_Static)); indexBuffer->SetPersistent(false); @@ -108,7 +111,7 @@ namespace for (unsigned int j = 0; j < indices.size(); ++j) indexMapper.Set(j, indices[j]); - indexMapper.Unmap(); + indexMapper.Unmap(); // Pour laisser les autres tâches affecter l'index buffer // Remplissage des vertices bool hasNormals = true; @@ -139,7 +142,7 @@ namespace if (index >= 0) { const NzVector3f& uvw = texCoords[index]; - vertex.uv.Set(uvw.x, uvw.y); + vertex.uv.Set(uvw.x, (parameters.mesh.flipUVs) ? 1.f - uvw.y : uvw.y); // Inversion des UVs si demandé } else hasTexCoords = false; @@ -167,9 +170,7 @@ namespace subMesh->SetMaterialIndex(meshes[i].material); subMesh->SetPrimitiveMode(nzPrimitiveMode_TriangleList); - if (parameters.mesh.center) - subMesh->Center(); - + // Ce que nous pouvons générer dépend des données à disposition (par exemple les tangentes nécessitent des coordonnées de texture) if (hasNormals && hasTexCoords) subMesh->GenerateTangents(); else if (hasTexCoords) @@ -181,6 +182,18 @@ namespace subMesh.release(); } + if (parameters.mesh.center) + { + unsigned int subMeshCount = mesh->GetSubMeshCount(); + for (unsigned int i = 0; i < subMeshCount; ++i) + { + NzStaticMesh* subMesh = static_cast(mesh->GetSubMesh(i)); + subMesh->Center(); + } + + mesh->InvalidateAABB(); + } + mesh->SetMaterialCount(parser.GetMaterialCount()); model->SetMesh(mesh.get()); diff --git a/src/Nazara/Graphics/Loaders/OBJ/MTLParser.cpp b/src/Nazara/Graphics/Loaders/OBJ/MTLParser.cpp index fedbf0ed3..2614fa511 100644 --- a/src/Nazara/Graphics/Loaders/OBJ/MTLParser.cpp +++ b/src/Nazara/Graphics/Loaders/OBJ/MTLParser.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/Loaders/OBJ/MTLParser.hpp b/src/Nazara/Graphics/Loaders/OBJ/MTLParser.hpp index 6103d75d9..5bfbef6d0 100644 --- a/src/Nazara/Graphics/Loaders/OBJ/MTLParser.hpp +++ b/src/Nazara/Graphics/Loaders/OBJ/MTLParser.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/Loaders/OBJ/OBJParser.cpp b/src/Nazara/Graphics/Loaders/OBJ/OBJParser.cpp index 933deeca6..6bb87be56 100644 --- a/src/Nazara/Graphics/Loaders/OBJ/OBJParser.cpp +++ b/src/Nazara/Graphics/Loaders/OBJ/OBJParser.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -27,7 +27,7 @@ NzOBJParser::~NzOBJParser() const NzString* NzOBJParser::GetMaterials() const { - return &m_materials[0]; + return m_materials.data(); } unsigned int NzOBJParser::GetMaterialCount() const @@ -37,7 +37,7 @@ unsigned int NzOBJParser::GetMaterialCount() const const NzOBJParser::Mesh* NzOBJParser::GetMeshes() const { - return &m_meshes[0]; + return m_meshes.data(); } unsigned int NzOBJParser::GetMeshCount() const @@ -52,7 +52,7 @@ const NzString& NzOBJParser::GetMtlLib() const const NzVector3f* NzOBJParser::GetNormals() const { - return &m_normals[0]; + return m_normals.data(); } unsigned int NzOBJParser::GetNormalCount() const @@ -62,7 +62,7 @@ unsigned int NzOBJParser::GetNormalCount() const const NzVector4f* NzOBJParser::GetPositions() const { - return &m_positions[0]; + return m_positions.data(); } unsigned int NzOBJParser::GetPositionCount() const @@ -72,7 +72,7 @@ unsigned int NzOBJParser::GetPositionCount() const const NzVector3f* NzOBJParser::GetTexCoords() const { - return &m_texCoords[0]; + return m_texCoords.data(); } unsigned int NzOBJParser::GetTexCoordCount() const @@ -93,13 +93,15 @@ bool NzOBJParser::Parse() m_positions.clear(); m_texCoords.clear(); - // Beaucoup de meshs font plus de 100 sommets, on prépare le terrain + // Beaucoup de meshs font plus de 100 sommets, préparons le terrain m_normals.reserve(100); m_positions.reserve(100); m_texCoords.reserve(100); + // On va regrouper les meshs par nom et par matériau std::unordered_map>> meshes; + // On prépare le mesh par défaut std::vector* currentMesh = &meshes[meshName][matName]; while (Advance(false)) @@ -265,8 +267,8 @@ bool NzOBJParser::Parse() break; } + #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING case 's': - #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING if (m_currentLine.GetSize() <= 2 || m_currentLine[1] == ' ') { NzString param = m_currentLine.SubString(2); @@ -275,8 +277,8 @@ bool NzOBJParser::Parse() } else UnrecognizedLine(); - #endif break; + #endif case 'u': #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING diff --git a/src/Nazara/Graphics/Loaders/OBJ/OBJParser.hpp b/src/Nazara/Graphics/Loaders/OBJ/OBJParser.hpp index baf7215e2..512eda666 100644 --- a/src/Nazara/Graphics/Loaders/OBJ/OBJParser.hpp +++ b/src/Nazara/Graphics/Loaders/OBJ/OBJParser.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/Loaders/Texture.hpp b/src/Nazara/Graphics/Loaders/Texture.hpp index b2d459400..4b746b35a 100644 --- a/src/Nazara/Graphics/Loaders/Texture.hpp +++ b/src/Nazara/Graphics/Loaders/Texture.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/Loaders/Texture/Loader.cpp b/src/Nazara/Graphics/Loaders/Texture/Loader.cpp index 84a38997f..8412e2ca5 100644 --- a/src/Nazara/Graphics/Loaders/Texture/Loader.cpp +++ b/src/Nazara/Graphics/Loaders/Texture/Loader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/Material.cpp b/src/Nazara/Graphics/Material.cpp index 007f25984..42a4653e7 100644 --- a/src/Nazara/Graphics/Material.cpp +++ b/src/Nazara/Graphics/Material.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -15,6 +15,25 @@ #include #include +namespace +{ + const nzUInt8 r_coreFragmentShader[] = { + #include + }; + + const nzUInt8 r_coreVertexShader[] = { + #include + }; + + const nzUInt8 r_compatibilityFragmentShader[] = { + #include + }; + + const nzUInt8 r_compatibilityVertexShader[] = { + #include + }; +} + bool NzMaterialParams::IsValid() const { if (!NzUberShaderLibrary::Has(shaderName)) @@ -30,25 +49,11 @@ NzMaterial::NzMaterial() NzMaterial::NzMaterial(const NzMaterial& material) : NzRefCounted(), -NzResource() +NzResource(material) { Copy(material); } -NzMaterial::NzMaterial(NzMaterial&& material) -{ - Copy(material); - - // Nous "volons" la référence du matériau - material.m_alphaMap.Reset(); - material.m_diffuseMap.Reset(); - material.m_emissiveMap.Reset(); - material.m_heightMap.Reset(); - material.m_normalMap.Reset(); - material.m_specularMap.Reset(); - material.m_uberShader.Reset(); -} - NzMaterial::~NzMaterial() { NotifyDestroy(); @@ -153,6 +158,11 @@ void NzMaterial::EnableAlphaTest(bool alphaTest) InvalidateShaders(); } +void NzMaterial::EnableDepthSorting(bool depthSorting) +{ + m_depthSortingEnabled = depthSorting; +} + void NzMaterial::EnableLighting(bool lighting) { m_lightingEnabled = lighting; @@ -249,10 +259,11 @@ const NzUberShader* NzMaterial::GetShader() const const NzUberShaderInstance* NzMaterial::GetShaderInstance(nzUInt32 flags) const { - if (!m_shaders[flags].uberInstance) + const ShaderInstance& instance = m_shaders[flags]; + if (!instance.uberInstance) GenerateShader(flags); - return m_shaders[flags].uberInstance; + return instance.uberInstance; } float NzMaterial::GetShininess() const @@ -320,6 +331,11 @@ bool NzMaterial::IsAlphaTestEnabled() const return m_alphaTestEnabled; } +bool NzMaterial::IsDepthSortingEnabled() const +{ + return m_depthSortingEnabled; +} + bool NzMaterial::IsEnabled(nzRendererParameter parameter) const { #ifdef NAZARA_DEBUG @@ -376,6 +392,7 @@ void NzMaterial::Reset() m_alphaThreshold = 0.2f; m_alphaTestEnabled = false; m_ambientColor = NzColor(128, 128, 128); + m_depthSortingEnabled = false; m_diffuseColor = NzColor::White; m_diffuseSampler = NzTextureSampler(); m_lightingEnabled = true; @@ -618,27 +635,13 @@ void NzMaterial::SetSrcBlend(nzBlendFunc func) NzMaterial& NzMaterial::operator=(const NzMaterial& material) { + NzResource::operator=(material); + Copy(material); return *this; } -NzMaterial& NzMaterial::operator=(NzMaterial&& material) -{ - Copy(material); - - // Comme ça nous volons la référence du matériau - material.m_alphaMap.Reset(); - material.m_diffuseMap.Reset(); - material.m_emissiveMap.Reset(); - material.m_heightMap.Reset(); - material.m_normalMap.Reset(); - material.m_specularMap.Reset(); - material.m_uberShader.Reset(); - - return *this; -} - NzMaterial* NzMaterial::GetDefault() { return s_defaultMaterial; @@ -646,33 +649,33 @@ NzMaterial* NzMaterial::GetDefault() void NzMaterial::Copy(const NzMaterial& material) { - // On relache les références proprement - m_alphaMap.Reset(); - m_diffuseMap.Reset(); - m_emissiveMap.Reset(); - m_heightMap.Reset(); - m_normalMap.Reset(); - m_specularMap.Reset(); - m_uberShader.Reset(); + // Copie des états de base + m_alphaTestEnabled = material.m_alphaTestEnabled; + m_alphaThreshold = material.m_alphaThreshold; + m_ambientColor = material.m_ambientColor; + m_depthSortingEnabled = material.m_depthSortingEnabled; + m_diffuseColor = material.m_diffuseColor; + m_diffuseSampler = material.m_diffuseSampler; + m_lightingEnabled = material.m_lightingEnabled; + m_shininess = material.m_shininess; + m_specularColor = material.m_specularColor; + m_specularSampler = material.m_specularSampler; + m_states = material.m_states; + m_transformEnabled = material.m_transformEnabled; - std::memcpy(this, &material, sizeof(NzMaterial)); // Autorisé dans notre cas, et bien plus rapide - - // Ensuite une petite astuce pour récupérer correctement les références - m_alphaMap.Release(); - m_diffuseMap.Release(); - m_emissiveMap.Release(); - m_heightMap.Release(); - m_normalMap.Release(); - m_specularMap.Release(); - m_uberShader.Release(); - - m_alphaMap = material.m_alphaMap; - m_diffuseMap = material.m_diffuseMap; + // Copie des références de texture + m_alphaMap = material.m_alphaMap; + m_diffuseMap = material.m_diffuseMap; m_emissiveMap = material.m_emissiveMap; - m_heightMap = material.m_heightMap; - m_normalMap = material.m_normalMap; + m_heightMap = material.m_heightMap; + m_normalMap = material.m_normalMap; m_specularMap = material.m_specularMap; + + // Copie de la référence vers l'Über-Shader m_uberShader = material.m_uberShader; + + // On copie les instances de shader par la même occasion + std::memcpy(&m_shaders[0], &material.m_shaders[0], (nzShaderFlags_Max+1)*sizeof(ShaderInstance)); } void NzMaterial::GenerateShader(nzUInt32 flags) const @@ -688,11 +691,15 @@ void NzMaterial::GenerateShader(nzUInt32 flags) const list.SetParameter("PARALLAX_MAPPING", m_heightMap.IsValid()); list.SetParameter("SPECULAR_MAPPING", m_specularMap.IsValid()); list.SetParameter("TEXTURE_MAPPING", m_alphaMap.IsValid() || m_diffuseMap.IsValid() || m_emissiveMap.IsValid() || - m_normalMap.IsValid() || m_heightMap.IsValid() || m_specularMap.IsValid()); + m_normalMap.IsValid() || m_heightMap.IsValid() || m_specularMap.IsValid() || + flags & nzShaderFlags_TextureOverlay); list.SetParameter("TRANSFORM", m_transformEnabled); - list.SetParameter("FLAG_DEFERRED", static_cast(flags & nzShaderFlags_Deferred)); - list.SetParameter("FLAG_INSTANCING", static_cast(flags & nzShaderFlags_Instancing)); + list.SetParameter("FLAG_BILLBOARD", static_cast(flags & nzShaderFlags_Billboard)); + list.SetParameter("FLAG_DEFERRED", static_cast((flags & nzShaderFlags_Deferred) != 0)); + list.SetParameter("FLAG_INSTANCING", static_cast((flags & nzShaderFlags_Instancing) != 0)); + list.SetParameter("FLAG_TEXTUREOVERLAY", static_cast((flags & nzShaderFlags_TextureOverlay) != 0)); + list.SetParameter("FLAG_VERTEXCOLOR", static_cast((flags & nzShaderFlags_VertexColor) != 0)); ShaderInstance& instance = m_shaders[flags]; instance.uberInstance = m_uberShader->Get(list); @@ -734,33 +741,17 @@ bool NzMaterial::Initialize() NzString vertexShader; if (glsl140) { - const nzUInt8 coreFragmentShader[] = { - #include - }; - - const nzUInt8 coreVertexShader[] = { - #include - }; - - fragmentShader.Set(reinterpret_cast(coreFragmentShader), sizeof(coreFragmentShader)); - vertexShader.Set(reinterpret_cast(coreVertexShader), sizeof(coreVertexShader)); + fragmentShader.Set(reinterpret_cast(r_coreFragmentShader), sizeof(r_coreFragmentShader)); + vertexShader.Set(reinterpret_cast(r_coreVertexShader), sizeof(r_coreVertexShader)); } else { - const nzUInt8 compatibilityFragmentShader[] = { - #include - }; - - const nzUInt8 compatibilityVertexShader[] = { - #include - }; - - fragmentShader.Set(reinterpret_cast(compatibilityFragmentShader), sizeof(compatibilityFragmentShader)); - vertexShader.Set(reinterpret_cast(compatibilityVertexShader), sizeof(compatibilityVertexShader)); + fragmentShader.Set(reinterpret_cast(r_compatibilityFragmentShader), sizeof(r_compatibilityFragmentShader)); + vertexShader.Set(reinterpret_cast(r_compatibilityVertexShader), sizeof(r_compatibilityVertexShader)); } - uberShader->SetShader(nzShaderStage_Fragment, fragmentShader, "ALPHA_MAPPING ALPHA_TEST AUTO_TEXCOORDS DIFFUSE_MAPPING"); - uberShader->SetShader(nzShaderStage_Vertex, vertexShader, "FLAG_INSTANCING TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH"); + uberShader->SetShader(nzShaderStage_Fragment, fragmentShader, "FLAG_TEXTUREOVERLAY ALPHA_MAPPING ALPHA_TEST AUTO_TEXCOORDS DIFFUSE_MAPPING"); + uberShader->SetShader(nzShaderStage_Vertex, vertexShader, "FLAG_BILLBOARD FLAG_INSTANCING FLAG_VERTEXCOLOR TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH"); NzUberShaderLibrary::Register("Basic", uberShader.get()); uberShader.release(); @@ -800,8 +791,8 @@ bool NzMaterial::Initialize() vertexShader.Set(reinterpret_cast(compatibilityVertexShader), sizeof(compatibilityVertexShader)); } - uberShader->SetShader(nzShaderStage_Fragment, fragmentShader, "FLAG_DEFERRED ALPHA_MAPPING ALPHA_TEST DIFFUSE_MAPPING EMISSIVE_MAPPING LIGHTING NORMAL_MAPPING PARALLAX_MAPPING SPECULAR_MAPPING"); - uberShader->SetShader(nzShaderStage_Vertex, vertexShader, "FLAG_DEFERRED FLAG_INSTANCING COMPUTE_TBNMATRIX LIGHTING PARALLAX_MAPPING TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH"); + uberShader->SetShader(nzShaderStage_Fragment, fragmentShader, "FLAG_DEFERRED FLAG_TEXTUREOVERLAY ALPHA_MAPPING ALPHA_TEST AUTO_TEXCOORDS DIFFUSE_MAPPING EMISSIVE_MAPPING LIGHTING NORMAL_MAPPING PARALLAX_MAPPING SPECULAR_MAPPING"); + uberShader->SetShader(nzShaderStage_Vertex, vertexShader, "FLAG_BILLBOARD FLAG_DEFERRED FLAG_INSTANCING FLAG_VERTEXCOLOR COMPUTE_TBNMATRIX LIGHTING PARALLAX_MAPPING TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH"); NzUberShaderLibrary::Register("PhongLighting", uberShader.get()); uberShader.release(); diff --git a/src/Nazara/Graphics/Model.cpp b/src/Nazara/Graphics/Model.cpp index 8f9b85122..4339db399 100644 --- a/src/Nazara/Graphics/Model.cpp +++ b/src/Nazara/Graphics/Model.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -25,7 +25,6 @@ bool NzModelParameters::IsValid() const } NzModel::NzModel() : -m_boundingVolumeUpdated(true), m_matCount(0), m_skin(0), m_skinCount(1) @@ -33,22 +32,15 @@ m_skinCount(1) } NzModel::NzModel(const NzModel& model) : +NzResource(model), NzSceneNode(model), m_materials(model.m_materials), -m_boundingVolume(model.m_boundingVolume), -m_boundingVolumeUpdated(model.m_boundingVolumeUpdated), +m_mesh(model.m_mesh), m_matCount(model.m_matCount), m_skin(model.m_skin), m_skinCount(model.m_skinCount) { - if (model.m_mesh) - { - // Nous n'avons des matériaux que si nous avons un mesh - m_mesh = model.m_mesh; - m_materials = model.m_materials; - } - - SetParent(model); + SetParent(model.GetParent()); } NzModel::~NzModel() @@ -75,22 +67,14 @@ void NzModel::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const } } -const NzBoundingVolumef& NzModel::GetBoundingVolume() const +NzModel* NzModel::Clone() const { - #if NAZARA_GRAPHICS_SAFE - if (!m_mesh) - { - NazaraError("Model has no mesh"); + return new NzModel(*this); +} - static NzBoundingVolumef dummy(nzExtend_Null); - return dummy; - } - #endif - - if (!m_boundingVolumeUpdated) - UpdateBoundingVolume(); - - return m_boundingVolume; +NzModel* NzModel::Create() const +{ + return new NzModel; } NzMaterial* NzModel::GetMaterial(const NzString& subMeshName) const @@ -396,7 +380,7 @@ void NzModel::SetSkinCount(unsigned int skinCount) #if NAZARA_GRAPHICS_SAFE if (skinCount == 0) { - NazaraError("Skin count must be over 0"); + NazaraError("Skin count must be over zero"); return; } #endif @@ -407,6 +391,7 @@ void NzModel::SetSkinCount(unsigned int skinCount) NzModel& NzModel::operator=(const NzModel& node) { + NzResource::operator=(node); NzSceneNode::operator=(node); m_boundingVolume = node.m_boundingVolume; @@ -420,41 +405,12 @@ NzModel& NzModel::operator=(const NzModel& node) return *this; } -NzModel& NzModel::operator=(NzModel&& node) +void NzModel::MakeBoundingVolume() const { - NzSceneNode::operator=(node); - - // Ressources - m_mesh = std::move(node.m_mesh); - m_materials = std::move(node.m_materials); - - // Paramètres - m_boundingVolume = node.m_boundingVolume; - m_boundingVolumeUpdated = node.m_boundingVolumeUpdated; - m_matCount = node.m_matCount; - m_skin = node.m_skin; - m_skinCount = node.m_skinCount; - - return *this; -} - -void NzModel::InvalidateNode() -{ - NzSceneNode::InvalidateNode(); - - m_boundingVolumeUpdated = false; -} - -void NzModel::UpdateBoundingVolume() const -{ - if (m_boundingVolume.IsNull()) + if (m_mesh) m_boundingVolume.Set(m_mesh->GetAABB()); - - if (!m_transformMatrixUpdated) - UpdateTransformMatrix(); - - m_boundingVolume.Update(m_transformMatrix); - m_boundingVolumeUpdated = true; + else + m_boundingVolume.MakeNull(); } NzModelLoader::LoaderList NzModel::s_loaders; diff --git a/src/Nazara/Graphics/ParticleController.cpp b/src/Nazara/Graphics/ParticleController.cpp new file mode 100644 index 000000000..6dadf695d --- /dev/null +++ b/src/Nazara/Graphics/ParticleController.cpp @@ -0,0 +1,14 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +NzParticleController::NzParticleController(const NzParticleController& controller) : +NzRefCounted() +{ + NazaraUnused(controller); +} + +NzParticleController::~NzParticleController() = default; diff --git a/src/Nazara/Graphics/ParticleDeclaration.cpp b/src/Nazara/Graphics/ParticleDeclaration.cpp new file mode 100644 index 000000000..586ac3489 --- /dev/null +++ b/src/Nazara/Graphics/ParticleDeclaration.cpp @@ -0,0 +1,231 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +NzParticleDeclaration::NzParticleDeclaration() : +m_stride(0) +{ +} + +NzParticleDeclaration::NzParticleDeclaration(const NzParticleDeclaration& declaration) : +NzRefCounted(), +m_stride(declaration.m_stride) +{ + std::memcpy(m_components, declaration.m_components, sizeof(Component)*(nzParticleComponent_Max+1)); +} + +NzParticleDeclaration::~NzParticleDeclaration() +{ + NotifyDestroy(); +} + +void NzParticleDeclaration::DisableComponent(nzParticleComponent component) +{ + #ifdef NAZARA_DEBUG + if (component > nzParticleComponent_Max) + { + NazaraError("Vertex component out of enum"); + return; + } + #endif + + #if NAZARA_GRAPHICS_SAFE + if (component == nzParticleComponent_Unused) + { + NazaraError("Cannot disable \"unused\" component"); + return; + } + #endif + + Component& vertexComponent = m_components[component]; + if (vertexComponent.enabled) + { + vertexComponent.enabled = false; + m_stride -= NzUtility::ComponentStride[vertexComponent.type]; + } +} + +void NzParticleDeclaration::EnableComponent(nzParticleComponent component, nzComponentType type, unsigned int offset) +{ + #ifdef NAZARA_DEBUG + if (component > nzParticleComponent_Max) + { + NazaraError("Vertex component out of enum"); + return; + } + #endif + + #if NAZARA_GRAPHICS_SAFE + if (!IsTypeSupported(type)) + { + NazaraError("Component type 0x" + NzString::Number(type, 16) + " is not supported by particle declarations"); + return; + } + #endif + + if (component != nzParticleComponent_Unused) + { + Component& particleComponent = m_components[component]; + if (particleComponent.enabled) + m_stride -= NzUtility::ComponentStride[particleComponent.type]; + else + particleComponent.enabled = true; + + particleComponent.offset = offset; + particleComponent.type = type; + } + + m_stride += NzUtility::ComponentStride[type]; +} + +void NzParticleDeclaration::GetComponent(nzParticleComponent component, bool* enabled, nzComponentType* type, unsigned int* offset) const +{ + #ifdef NAZARA_DEBUG + if (component > nzParticleComponent_Max) + { + NazaraError("Particle component out of enum"); + return; + } + #endif + + #if NAZARA_GRAPHICS_SAFE + if (component == nzParticleComponent_Unused) + { + NazaraError("Cannot get \"unused\" component"); + return; + } + #endif + + const Component& particleComponent = m_components[component]; + + if (enabled) + *enabled = particleComponent.enabled; + + if (type) + *type = particleComponent.type; + + if (offset) + *offset = particleComponent.offset; +} + +unsigned int NzParticleDeclaration::GetStride() const +{ + return m_stride; +} + +void NzParticleDeclaration::SetStride(unsigned int stride) +{ + m_stride = stride; +} + +NzParticleDeclaration& NzParticleDeclaration::operator=(const NzParticleDeclaration& declaration) +{ + std::memcpy(m_components, declaration.m_components, sizeof(Component)*(nzParticleComponent_Max+1)); + m_stride = declaration.m_stride; + + return *this; +} + +NzParticleDeclaration* NzParticleDeclaration::Get(nzParticleLayout layout) +{ + #ifdef NAZARA_DEBUG + if (layout > nzParticleLayout_Max) + { + NazaraError("Particle layout out of enum"); + return nullptr; + } + #endif + + return &s_declarations[layout]; +} + +bool NzParticleDeclaration::IsTypeSupported(nzComponentType type) +{ + switch (type) + { + case nzComponentType_Color: + case nzComponentType_Double1: + case nzComponentType_Double2: + case nzComponentType_Double3: + case nzComponentType_Double4: + case nzComponentType_Float1: + case nzComponentType_Float2: + case nzComponentType_Float3: + case nzComponentType_Float4: + case nzComponentType_Int1: + case nzComponentType_Int2: + case nzComponentType_Int3: + case nzComponentType_Int4: + case nzComponentType_Quaternion: + return true; + } + + NazaraError("Component type not handled (0x" + NzString::Number(type, 16) + ')'); + return false; +} + +bool NzParticleDeclaration::Initialize() +{ + try + { + NzErrorFlags flags(nzErrorFlag_Silent | nzErrorFlag_ThrowException); + + // Layout : Type + NzParticleDeclaration* declaration; + + // nzParticleLayout_Billboard : NzParticleStruct_Billboard + declaration = &s_declarations[nzParticleLayout_Billboard]; + declaration->EnableComponent(nzParticleComponent_Color, nzComponentType_Color, NzOffsetOf(NzParticleStruct_Billboard, color)); + declaration->EnableComponent(nzParticleComponent_Life, nzComponentType_Int1, NzOffsetOf(NzParticleStruct_Billboard, life)); + declaration->EnableComponent(nzParticleComponent_Normal, nzComponentType_Float3, NzOffsetOf(NzParticleStruct_Billboard, normal)); + declaration->EnableComponent(nzParticleComponent_Position, nzComponentType_Float3, NzOffsetOf(NzParticleStruct_Billboard, position)); + declaration->EnableComponent(nzParticleComponent_Rotation, nzComponentType_Float1, NzOffsetOf(NzParticleStruct_Billboard, rotation)); + declaration->EnableComponent(nzParticleComponent_Velocity, nzComponentType_Float3, NzOffsetOf(NzParticleStruct_Billboard, velocity)); + + NazaraAssert(declaration->GetStride() == sizeof(NzParticleStruct_Billboard), "Invalid stride for declaration nzParticleLayout_Billboard"); + + // nzParticleLayout_Model : NzParticleStruct_Model + declaration = &s_declarations[nzParticleLayout_Model]; + declaration->EnableComponent(nzParticleComponent_Life, nzComponentType_Int1, NzOffsetOf(NzParticleStruct_Model, life)); + declaration->EnableComponent(nzParticleComponent_Position, nzComponentType_Float3, NzOffsetOf(NzParticleStruct_Model, position)); + declaration->EnableComponent(nzParticleComponent_Rotation, nzComponentType_Quaternion, NzOffsetOf(NzParticleStruct_Model, rotation)); + declaration->EnableComponent(nzParticleComponent_Velocity, nzComponentType_Float3, NzOffsetOf(NzParticleStruct_Model, velocity)); + + NazaraAssert(declaration->GetStride() == sizeof(NzParticleStruct_Model), "Invalid stride for declaration nzParticleLayout_Model"); + + // nzParticleLayout_Sprite : NzParticleStruct_Sprite + declaration = &s_declarations[nzParticleLayout_Sprite]; + declaration->EnableComponent(nzParticleComponent_Color, nzComponentType_Color, NzOffsetOf(NzParticleStruct_Sprite, color)); + declaration->EnableComponent(nzParticleComponent_Life, nzComponentType_Int1, NzOffsetOf(NzParticleStruct_Sprite, life)); + declaration->EnableComponent(nzParticleComponent_Position, nzComponentType_Float2, NzOffsetOf(NzParticleStruct_Sprite, position)); + declaration->EnableComponent(nzParticleComponent_Rotation, nzComponentType_Float1, NzOffsetOf(NzParticleStruct_Sprite, rotation)); + declaration->EnableComponent(nzParticleComponent_Velocity, nzComponentType_Float2, NzOffsetOf(NzParticleStruct_Sprite, velocity)); + + NazaraAssert(declaration->GetStride() == sizeof(NzParticleStruct_Sprite), "Invalid stride for declaration nzParticleLayout_Sprite"); + } + catch (const std::exception& e) + { + NazaraError("Failed to initialize particle declarations: " + NzString(e.what())); + return false; + } + + return true; +} + +void NzParticleDeclaration::Uninitialize() +{ + // Rien à faire +} + +NzParticleDeclaration NzParticleDeclaration::s_declarations[nzParticleLayout_Max+1]; diff --git a/src/Nazara/Graphics/ParticleEmitter.cpp b/src/Nazara/Graphics/ParticleEmitter.cpp new file mode 100644 index 000000000..c38233630 --- /dev/null +++ b/src/Nazara/Graphics/ParticleEmitter.cpp @@ -0,0 +1,92 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +NzParticleEmitter::NzParticleEmitter() : +m_lagCompensationEnabled(false), +m_emissionAccumulator(0.f), +m_emissionRate(0.f), +m_emissionCount(1) +{ +} + +NzParticleEmitter::~NzParticleEmitter() = default; + +void NzParticleEmitter::Emit(NzParticleSystem& system, float elapsedTime) const +{ + if (m_emissionRate > 0.f) + { + // On accumule la partie réelle (pour éviter qu'un taux d'update élevé empêche des particules de se former) + m_emissionAccumulator += elapsedTime*m_emissionRate; + + float emissionCount = std::floor(m_emissionAccumulator); // Le nombre d'émissions de cette mise à jour + m_emissionAccumulator -= emissionCount; // On enlève la partie entière + + if (emissionCount >= 1.f) + { + // On calcule le nombre maximum de particules pouvant être émises cette fois-ci + unsigned int emissionCountInt = static_cast(emissionCount); + unsigned int maxParticleCount = emissionCountInt*m_emissionCount; + + // On récupère le nombre de particules qu'il est possible de créer selon l'espace libre + unsigned int particleCount = std::min(maxParticleCount, system.GetMaxParticleCount() - system.GetParticleCount()); + if (particleCount == 0) + return; + + // Et on émet nos particules + void* particles = system.GenerateParticles(particleCount); + NzParticleMapper mapper(particles, system.GetDeclaration()); + + SetupParticles(mapper, particleCount); + + if (m_lagCompensationEnabled) + { + // On va maintenant appliquer les contrôleurs + float accumulator = 0.f; + float invEmissionRate = 1.f/m_emissionRate; + for (unsigned int i = 1; i <= emissionCountInt; ++i) + system.ApplyControllers(mapper, std::min(m_emissionCount*i, particleCount), 20*invEmissionRate, accumulator); + } + } + } +} + +void NzParticleEmitter::EnableLagCompensation(bool enable) +{ + m_lagCompensationEnabled = enable; +} + +unsigned int NzParticleEmitter::GetEmissionCount() const +{ + return m_emissionCount; +} + +float NzParticleEmitter::GetEmissionRate() const +{ + return m_emissionRate; +} + +bool NzParticleEmitter::IsLagCompensationEnabled() const +{ + return m_lagCompensationEnabled; +} + +void NzParticleEmitter::SetEmissionCount(unsigned int count) +{ + m_emissionCount = count; +} + +void NzParticleEmitter::SetEmissionRate(float rate) +{ + m_emissionRate = rate; +} diff --git a/src/Nazara/Graphics/ParticleGenerator.cpp b/src/Nazara/Graphics/ParticleGenerator.cpp new file mode 100644 index 000000000..9ce5327b5 --- /dev/null +++ b/src/Nazara/Graphics/ParticleGenerator.cpp @@ -0,0 +1,14 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +NzParticleGenerator::NzParticleGenerator(const NzParticleGenerator& generator) : +NzRefCounted() +{ + NazaraUnused(generator); +} + +NzParticleGenerator::~NzParticleGenerator() = default; diff --git a/src/Nazara/Graphics/ParticleMapper.cpp b/src/Nazara/Graphics/ParticleMapper.cpp new file mode 100644 index 000000000..03e1a1082 --- /dev/null +++ b/src/Nazara/Graphics/ParticleMapper.cpp @@ -0,0 +1,15 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +NzParticleMapper::NzParticleMapper(void* buffer, const NzParticleDeclaration* declaration) : +m_declaration(declaration), +m_ptr(static_cast(buffer)) +{ +} + +NzParticleMapper::~NzParticleMapper() = default; diff --git a/src/Nazara/Graphics/ParticleRenderer.cpp b/src/Nazara/Graphics/ParticleRenderer.cpp new file mode 100644 index 000000000..5a743086e --- /dev/null +++ b/src/Nazara/Graphics/ParticleRenderer.cpp @@ -0,0 +1,14 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +NzParticleRenderer::NzParticleRenderer(const NzParticleRenderer& renderer) : +NzRefCounted() +{ + NazaraUnused(renderer); +} + +NzParticleRenderer::~NzParticleRenderer() = default; diff --git a/src/Nazara/Graphics/ParticleSystem.cpp b/src/Nazara/Graphics/ParticleSystem.cpp new file mode 100644 index 000000000..3a7351b2c --- /dev/null +++ b/src/Nazara/Graphics/ParticleSystem.cpp @@ -0,0 +1,346 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +NzParticleSystem::NzParticleSystem(unsigned int maxParticleCount, nzParticleLayout layout) : +NzParticleSystem(maxParticleCount, NzParticleDeclaration::Get(layout)) +{ +} + +NzParticleSystem::NzParticleSystem(unsigned int maxParticleCount, const NzParticleDeclaration* declaration) : +m_declaration(declaration), +m_fixedStepEnabled(false), +m_processing(false), +m_stepAccumulator(0.f), +m_stepSize(1.f/60.f), +m_maxParticleCount(maxParticleCount), +m_particleCount(0) +{ + // En cas d'erreur, un constructeur ne peut que lancer une exception + NzErrorFlags flags(nzErrorFlag_ThrowException, true); + + m_particleSize = m_declaration->GetStride(); // La taille de chaque particule + + ResizeBuffer(); +} + +NzParticleSystem::NzParticleSystem(const NzParticleSystem& system) : +NzSceneNode(system), +m_controllers(system.m_controllers), +m_generators(system.m_generators), +m_declaration(system.m_declaration), +m_renderer(system.m_renderer), +m_fixedStepEnabled(system.m_fixedStepEnabled), +m_processing(false), +m_stepAccumulator(0.f), +m_stepSize(system.m_stepSize), +m_maxParticleCount(system.m_maxParticleCount), +m_particleCount(system.m_particleCount), +m_particleSize(system.m_particleSize) +{ + NzErrorFlags flags(nzErrorFlag_ThrowException, true); + + ResizeBuffer(); + + // On ne copie que les particules vivantes + std::memcpy(m_buffer.data(), system.m_buffer.data(), system.m_particleCount*m_particleSize); +} + +NzParticleSystem::~NzParticleSystem() = default; + +void NzParticleSystem::AddController(NzParticleController* controller) +{ + m_controllers.emplace_back(controller); +} + +void NzParticleSystem::AddEmitter(NzParticleEmitter* emitter) +{ + m_emitters.emplace_back(emitter); +} + +void NzParticleSystem::AddGenerator(NzParticleGenerator* generator) +{ + m_generators.emplace_back(generator); +} + +void NzParticleSystem::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const +{ + ///FIXME: Vérifier le renderer + if (m_particleCount > 0) + { + NzParticleMapper mapper(m_buffer.data(), m_declaration); + m_renderer->Render(*this, mapper, 0, m_particleCount-1, renderQueue); + } +} + +void* NzParticleSystem::CreateParticle() +{ + return CreateParticles(1); +} + +void* NzParticleSystem::CreateParticles(unsigned int count) +{ + if (count == 0) + return nullptr; + + if (m_particleCount+count > m_maxParticleCount) + return nullptr; + + unsigned int particlesIndex = m_particleCount; + m_particleCount += count; + + return &m_buffer[particlesIndex*m_particleSize]; +} + +void NzParticleSystem::EnableFixedStep(bool fixedStep) +{ + // On teste pour empêcher que cette méthode ne remette systématiquement le step accumulator à zéro + if (m_fixedStepEnabled != fixedStep) + { + m_fixedStepEnabled = fixedStep; + m_stepAccumulator = 0.f; + } +} + +void* NzParticleSystem::GenerateParticle() +{ + return GenerateParticles(1); +} + +void* NzParticleSystem::GenerateParticles(unsigned int count) +{ + void* ptr = CreateParticles(count); + if (!ptr) + return nullptr; + + NzParticleMapper mapper(ptr, m_declaration); + for (NzParticleGenerator* generator : m_generators) + generator->Generate(*this, mapper, 0, count-1); + + return ptr; +} + +const NzParticleDeclaration* NzParticleSystem::GetDeclaration() const +{ + return m_declaration; +} + +float NzParticleSystem::GetFixedStepSize() const +{ + return m_stepSize; +} + +unsigned int NzParticleSystem::GetMaxParticleCount() const +{ + return m_maxParticleCount; +} + +unsigned int NzParticleSystem::GetParticleCount() const +{ + return m_particleCount; +} + +unsigned int NzParticleSystem::GetParticleSize() const +{ + return m_particleSize; +} + +nzSceneNodeType NzParticleSystem::GetSceneNodeType() const +{ + return nzSceneNodeType_ParticleEmitter; +} + +bool NzParticleSystem::IsDrawable() const +{ + return true; +} + +bool NzParticleSystem::IsFixedStepEnabled() const +{ + return m_fixedStepEnabled; +} + +void NzParticleSystem::KillParticle(unsigned int index) +{ + ///FIXME: Vérifier index + + if (m_processing) + { + // Le buffer est en train d'être modifié, nous ne pouvons pas réduire sa taille, on place alors la particule dans une liste d'attente + m_dyingParticles.insert(index); + return; + } + + // On déplace la dernière particule vivante à la place de celle-ci + if (--m_particleCount > 0) + std::memcpy(&m_buffer[index*m_particleSize], &m_buffer[m_particleCount*m_particleSize], m_particleSize); +} + +void NzParticleSystem::KillParticles() +{ + m_particleCount = 0; +} + +void NzParticleSystem::RemoveController(NzParticleController* controller) +{ + auto it = std::find(m_controllers.begin(), m_controllers.end(), controller); + if (it != m_controllers.end()) + m_controllers.erase(it); +} + +void NzParticleSystem::RemoveEmitter(NzParticleEmitter* emitter) +{ + auto it = std::find(m_emitters.begin(), m_emitters.end(), emitter); + if (it != m_emitters.end()) + m_emitters.erase(it); +} + +void NzParticleSystem::RemoveGenerator(NzParticleGenerator* generator) +{ + auto it = std::find(m_generators.begin(), m_generators.end(), generator); + if (it != m_generators.end()) + m_generators.erase(it); +} + +void NzParticleSystem::SetFixedStepSize(float stepSize) +{ + m_stepSize = stepSize; +} + +void NzParticleSystem::SetRenderer(NzParticleRenderer* renderer) +{ + m_renderer = renderer; +} + +NzParticleSystem& NzParticleSystem::operator=(const NzParticleSystem& system) +{ + NzErrorFlags flags(nzErrorFlag_ThrowException, true); + + NzSceneNode::operator=(system); + + m_controllers = system.m_controllers; + m_declaration = system.m_declaration; + m_fixedStepEnabled = system.m_fixedStepEnabled; + m_generators = system.m_generators; + m_maxParticleCount = system.m_maxParticleCount; + m_particleCount = system.m_particleCount; + m_particleSize = system.m_particleSize; + m_renderer = system.m_renderer; + m_stepSize = system.m_stepSize; + + // La copie ne peut pas (ou plutôt ne devrait pas) avoir lieu pendant une mise à jour, inutile de copier + m_dyingParticles.clear(); + m_processing = false; + m_stepAccumulator = 0.f; + + m_buffer.clear(); // Pour éviter une recopie lors du resize() qui ne servira pas à grand chose + ResizeBuffer(); + + // On ne copie que les particules vivantes + std::memcpy(m_buffer.data(), system.m_buffer.data(), system.m_particleCount*m_particleSize); + + return *this; +} + +void NzParticleSystem::ApplyControllers(NzParticleMapper& mapper, unsigned int particleCount, float elapsedTime, float& stepAccumulator) +{ + m_processing = true; + + // Pour éviter un verrouillage en cas d'exception + NzCallOnExit onExit([this]() + { + m_processing = false; + }); + + if (m_fixedStepEnabled) + { + stepAccumulator += elapsedTime; + while (stepAccumulator >= m_stepSize) + { + for (NzParticleController* controller : m_controllers) + controller->Apply(*this, mapper, 0, particleCount-1, m_stepSize); + + stepAccumulator -= m_stepSize; + } + } + else + { + for (NzParticleController* controller : m_controllers) + controller->Apply(*this, mapper, 0, particleCount-1, elapsedTime); + } + + onExit.CallAndReset(); + + // On tue maintenant les particules mortes durant la mise à jour + if (m_dyingParticles.size() < m_particleCount) + { + // On tue les particules depuis la dernière vers la première (en terme de place), le std::set étant trié via std::greater + // La raison est simple, étant donné que la mort d'une particule signifie le déplacement de la dernière particule du buffer, + // sans cette solution certaines particules pourraient échapper à la mort + for (unsigned int index : m_dyingParticles) + KillParticle(index); + } + else + KillParticles(); // Toutes les particules sont mortes, ceci est beaucoup plus rapide + + m_dyingParticles.clear(); +} + +void NzParticleSystem::MakeBoundingVolume() const +{ + ///TODO: Calculer l'AABB (prendre la taille des particules en compte s'il y a) + m_boundingVolume.MakeInfinite(); +} + +void NzParticleSystem::Register() +{ + m_scene->RegisterForUpdate(this); +} + +void NzParticleSystem::ResizeBuffer() +{ + // Histoire de décrire un peu mieux l'erreur en cas d'échec + try + { + m_buffer.resize(m_maxParticleCount*m_particleSize); + } + catch (const std::exception& e) + { + NzStringStream stream; + stream << "Failed to allocate particle buffer (" << e.what() << ") for " << m_maxParticleCount << " particles of size " << m_particleSize; + + NazaraError(stream.ToString()); + } +} + +void NzParticleSystem::Unregister() +{ + m_scene->UnregisterForUpdate(this); +} + +void NzParticleSystem::Update() +{ + float elapsedTime = m_scene->GetUpdateTime(); + + // Émission + for (NzParticleEmitter* emitter : m_emitters) + emitter->Emit(*this, elapsedTime); + + // Mise à jour + if (m_particleCount > 0) + { + ///TODO: Mettre à jour en utilisant des threads + NzParticleMapper mapper(m_buffer.data(), m_declaration); + ApplyControllers(mapper, m_particleCount, elapsedTime, m_stepAccumulator); + } +} diff --git a/src/Nazara/Graphics/RenderTechniques.cpp b/src/Nazara/Graphics/RenderTechniques.cpp index 6f7635f3c..820700451 100644 --- a/src/Nazara/Graphics/RenderTechniques.cpp +++ b/src/Nazara/Graphics/RenderTechniques.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/Resources/Shaders/Basic/compatibility.frag b/src/Nazara/Graphics/Resources/Shaders/Basic/compatibility.frag index ab1d445ca..bc3955b48 100644 --- a/src/Nazara/Graphics/Resources/Shaders/Basic/compatibility.frag +++ b/src/Nazara/Graphics/Resources/Shaders/Basic/compatibility.frag @@ -1,22 +1,31 @@ /********************Entrant********************/ varying vec2 vTexCoord; +varying vec4 vColor; /********************Uniformes********************/ uniform sampler2D MaterialAlphaMap; uniform float MaterialAlphaThreshold; uniform vec4 MaterialDiffuse; uniform sampler2D MaterialDiffuseMap; +uniform vec2 InvTargetSize; /********************Fonctions********************/ void main() { - vec4 fragmentColor = MaterialDiffuse; + vec4 fragmentColor = MaterialDiffuse; * vColor; + +#if AUTO_TEXCOORDS + vec2 texCoord = gl_FragCoord.xy * InvTargetSize; +#else + vec2 texCoord = vTexCoord; +#endif + #if DIFFUSE_MAPPING - fragmentColor *= texture2D(MaterialDiffuseMap, vTexCoord); + fragmentColor *= texture2D(MaterialDiffuseMap, texCoord); #endif #if ALPHA_MAPPING - fragmentColor.a *= texture2D(MaterialAlphaMap, vTexCoord).r; + fragmentColor.a *= texture2D(MaterialAlphaMap, texCoord).r; #endif #if ALPHA_TEST diff --git a/src/Nazara/Graphics/Resources/Shaders/Basic/compatibility.frag.h b/src/Nazara/Graphics/Resources/Shaders/Basic/compatibility.frag.h index 0ffb28cff..b1ae605a4 100644 --- a/src/Nazara/Graphics/Resources/Shaders/Basic/compatibility.frag.h +++ b/src/Nazara/Graphics/Resources/Shaders/Basic/compatibility.frag.h @@ -1 +1 @@ -47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,97,114,121,105,110,103,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,118,101,99,52,32,102,114,97,103,109,101,110,116,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,35,105,102,32,68,73,70,70,85,83,69,95,77,65,80,80,73,78,71,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,32,42,61,32,116,101,120,116,117,114,101,50,68,40,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,44,32,118,84,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,77,65,80,80,73,78,71,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,32,42,61,32,116,101,120,116,117,114,101,50,68,40,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,44,32,118,84,101,120,67,111,111,114,100,41,46,114,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,84,69,83,84,13,10,9,105,102,32,40,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,32,60,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,41,13,10,9,9,100,105,115,99,97,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,9,103,108,95,70,114,97,103,67,111,108,111,114,32,61,32,102,114,97,103,109,101,110,116,67,111,108,111,114,59,13,10,125, \ No newline at end of file +47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,97,114,121,105,110,103,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,118,97,114,121,105,110,103,32,118,101,99,52,32,118,67,111,108,111,114,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,59,13,10,117,110,105,102,111,114,109,32,118,101,99,50,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,118,101,99,52,32,102,114,97,103,109,101,110,116,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,32,42,32,118,67,111,108,111,114,59,13,10,13,10,35,105,102,32,65,85,84,79,95,84,69,88,67,79,79,82,68,83,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,103,108,95,70,114,97,103,67,111,111,114,100,46,120,121,32,42,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,35,101,108,115,101,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,118,84,101,120,67,111,111,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,68,73,70,70,85,83,69,95,77,65,80,80,73,78,71,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,32,42,61,32,116,101,120,116,117,114,101,50,68,40,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,44,32,116,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,77,65,80,80,73,78,71,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,32,42,61,32,116,101,120,116,117,114,101,50,68,40,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,84,69,83,84,13,10,9,105,102,32,40,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,32,60,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,41,13,10,9,9,100,105,115,99,97,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,9,103,108,95,70,114,97,103,67,111,108,111,114,32,61,32,102,114,97,103,109,101,110,116,67,111,108,111,114,59,13,10,125, \ No newline at end of file diff --git a/src/Nazara/Graphics/Resources/Shaders/Basic/compatibility.vert b/src/Nazara/Graphics/Resources/Shaders/Basic/compatibility.vert index 111db31db..47c2260d7 100644 --- a/src/Nazara/Graphics/Resources/Shaders/Basic/compatibility.vert +++ b/src/Nazara/Graphics/Resources/Shaders/Basic/compatibility.vert @@ -1,10 +1,19 @@ /********************Entrant********************/ +#if FLAG_BILLBOARD +varying vec3 InstanceData0; // center +varying vec4 InstanceData1; // size | sin cos +varying vec4 InstanceData2; // color +#else varying mat4 InstanceData0; +#endif + +varying vec4 VertexColor; varying vec3 VertexPosition; varying vec2 VertexTexCoord; /********************Sortant********************/ varying vec2 vTexCoord; +varying vec4 vColor; /********************Uniformes********************/ uniform float VertexDepth; @@ -14,29 +23,77 @@ uniform mat4 WorldViewProjMatrix; /********************Fonctions********************/ void main() { -#if FLAG_INSTANCING - #if TRANSFORM - gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0); +#if FLAG_VERTEXCOLOR + vec4 color = VertexColor; +#else + vec4 color = vec4(1.0); +#endif + vec2 texCoords; + +#if FLAG_BILLBOARD + #if FLAG_INSTANCING + vec3 billboardCenter = InstanceData0; + vec2 billboardSize = InstanceData1.xy; + vec2 billboardSinCos = InstanceData1.zw; + vec4 billboardColor = InstanceData2; + + vec2 rotatedPosition; + rotatedPosition.x = VertexPosition.x*billboardSinCos.y - VertexPosition.y*billboardSinCos.x; + rotatedPosition.y = VertexPosition.y*billboardSinCos.y + VertexPosition.x*billboardSinCos.x; + rotatedPosition *= billboardSize; + + vec3 cameraRight = vec3(ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]); + vec3 cameraUp = vec3(ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]); + vec3 vertexPos = billboardCenter + cameraRight*rotatedPosition.x + cameraUp*rotatedPosition.y; + + gl_Position = ViewProjMatrix * vec4(vertexPos, 1.0); + color = billboardColor; + texCoords = VertexPosition.xy + vec2(0.5, 0.5); #else - #if UNIFORM_VERTEX_DEPTH - gl_Position = InstanceData0 * vec4(VertexPosition.xy, VertexDepth, 1.0); - #else - gl_Position = InstanceData0 * vec4(VertexPosition, 1.0); - #endif + vec2 billboardCorner = VertexTexCoord - vec2(0.5, 0.5); + vec2 billboardSize = VertexUserdata0.xy; + vec2 billboardSinCos = VertexUserdata0.zw; + + vec2 rotatedPosition; + rotatedPosition.x = billboardCorner.x*billboardSinCos.y - billboardCorner.y*billboardSinCos.x; + rotatedPosition.y = billboardCorner.y*billboardSinCos.y + billboardCorner.x*billboardSinCos.x; + rotatedPosition *= billboardSize; + + vec3 cameraRight = vec3(ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]); + vec3 cameraUp = vec3(ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]); + vec3 vertexPos = VertexPosition + cameraRight*rotatedPosition.x + cameraUp*rotatedPosition.y; + + gl_Position = ViewProjMatrix * vec4(vertexPos, 1.0); + texCoords = VertexTexCoord; #endif #else - #if TRANSFORM - gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0); - #else - #if UNIFORM_VERTEX_DEPTH - gl_Position = vec4(VertexPosition.xy, VertexDepth, 1.0); + #if FLAG_INSTANCING + #if TRANSFORM + gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0); #else - gl_Position = vec4(VertexPosition, 1.0); + #if UNIFORM_VERTEX_DEPTH + gl_Position = InstanceData0 * vec4(VertexPosition.xy, VertexDepth, 1.0); + #else + gl_Position = InstanceData0 * vec4(VertexPosition, 1.0); + #endif + #endif + #else + #if TRANSFORM + gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0); + #else + #if UNIFORM_VERTEX_DEPTH + gl_Position = vec4(VertexPosition.xy, VertexDepth, 1.0); + #else + gl_Position = vec4(VertexPosition, 1.0); + #endif #endif #endif + + texCoords = VertexTexCoord; #endif + vColor = color; #if TEXTURE_MAPPING - vTexCoord = vec2(VertexTexCoord); + vTexCoord = vec2(texCoords); #endif } diff --git a/src/Nazara/Graphics/Resources/Shaders/Basic/compatibility.vert.h b/src/Nazara/Graphics/Resources/Shaders/Basic/compatibility.vert.h index 5182574de..556f0c733 100644 --- a/src/Nazara/Graphics/Resources/Shaders/Basic/compatibility.vert.h +++ b/src/Nazara/Graphics/Resources/Shaders/Basic/compatibility.vert.h @@ -1 +1 @@ -47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,97,114,121,105,110,103,32,109,97,116,52,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,59,13,10,118,97,114,121,105,110,103,32,118,101,99,50,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,83,111,114,116,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,97,114,121,105,110,103,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,86,101,114,116,101,120,68,101,112,116,104,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,35,101,108,115,101,13,10,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,110,100,105,102,13,10,35,101,108,115,101,13,10,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,35,101,108,115,101,13,10,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,110,100,105,102,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,84,69,88,84,85,82,69,95,77,65,80,80,73,78,71,13,10,9,118,84,101,120,67,111,111,114,100,32,61,32,118,101,99,50,40,86,101,114,116,101,120,84,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,125,13,10, \ No newline at end of file +47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,35,105,102,32,70,76,65,71,95,66,73,76,76,66,79,65,82,68,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,32,47,47,32,99,101,110,116,101,114,13,10,118,97,114,121,105,110,103,32,118,101,99,52,32,73,110,115,116,97,110,99,101,68,97,116,97,49,59,32,47,47,32,115,105,122,101,32,124,32,115,105,110,32,99,111,115,13,10,118,97,114,121,105,110,103,32,118,101,99,52,32,73,110,115,116,97,110,99,101,68,97,116,97,50,59,32,47,47,32,99,111,108,111,114,13,10,35,101,108,115,101,13,10,118,97,114,121,105,110,103,32,109,97,116,52,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,13,10,35,101,110,100,105,102,13,10,13,10,118,97,114,121,105,110,103,32,118,101,99,52,32,86,101,114,116,101,120,67,111,108,111,114,59,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,59,13,10,118,97,114,121,105,110,103,32,118,101,99,50,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,83,111,114,116,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,97,114,121,105,110,103,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,118,97,114,121,105,110,103,32,118,101,99,52,32,118,67,111,108,111,114,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,86,101,114,116,101,120,68,101,112,116,104,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,35,105,102,32,70,76,65,71,95,86,69,82,84,69,88,67,79,76,79,82,13,10,9,118,101,99,52,32,99,111,108,111,114,32,61,32,86,101,114,116,101,120,67,111,108,111,114,59,13,10,35,101,108,115,101,13,10,9,118,101,99,52,32,99,111,108,111,114,32,61,32,118,101,99,52,40,49,46,48,41,59,13,10,35,101,110,100,105,102,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,115,59,13,10,13,10,35,105,102,32,70,76,65,71,95,66,73,76,76,66,79,65,82,68,13,10,9,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,118,101,99,51,32,98,105,108,108,98,111,97,114,100,67,101,110,116,101,114,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,83,105,122,101,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,49,46,120,121,59,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,49,46,122,119,59,13,10,9,118,101,99,52,32,98,105,108,108,98,111,97,114,100,67,111,108,111,114,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,50,59,13,10,13,10,9,118,101,99,50,32,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,120,32,61,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,121,32,45,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,121,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,120,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,121,32,61,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,121,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,121,32,43,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,120,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,32,42,61,32,98,105,108,108,98,111,97,114,100,83,105,122,101,59,13,10,13,10,9,118,101,99,51,32,99,97,109,101,114,97,82,105,103,104,116,32,61,32,118,101,99,51,40,86,105,101,119,77,97,116,114,105,120,91,48,93,91,48,93,44,32,86,105,101,119,77,97,116,114,105,120,91,49,93,91,48,93,44,32,86,105,101,119,77,97,116,114,105,120,91,50,93,91,48,93,41,59,13,10,9,118,101,99,51,32,99,97,109,101,114,97,85,112,32,61,32,118,101,99,51,40,86,105,101,119,77,97,116,114,105,120,91,48,93,91,49,93,44,32,86,105,101,119,77,97,116,114,105,120,91,49,93,91,49,93,44,32,86,105,101,119,77,97,116,114,105,120,91,50,93,91,49,93,41,59,13,10,9,118,101,99,51,32,118,101,114,116,101,120,80,111,115,32,61,32,98,105,108,108,98,111,97,114,100,67,101,110,116,101,114,32,43,32,99,97,109,101,114,97,82,105,103,104,116,42,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,120,32,43,32,99,97,109,101,114,97,85,112,42,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,121,59,13,10,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,118,101,114,116,101,120,80,111,115,44,32,49,46,48,41,59,13,10,9,99,111,108,111,114,32,61,32,98,105,108,108,98,111,97,114,100,67,111,108,111,114,59,13,10,9,116,101,120,67,111,111,114,100,115,32,61,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,32,43,32,118,101,99,50,40,48,46,53,44,32,48,46,53,41,59,13,10,9,35,101,108,115,101,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,32,61,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,32,45,32,118,101,99,50,40,48,46,53,44,32,48,46,53,41,59,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,83,105,122,101,32,61,32,86,101,114,116,101,120,85,115,101,114,100,97,116,97,48,46,120,121,59,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,32,61,32,86,101,114,116,101,120,85,115,101,114,100,97,116,97,48,46,122,119,59,13,10,9,13,10,9,118,101,99,50,32,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,120,32,61,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,46,120,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,121,32,45,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,46,121,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,120,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,121,32,61,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,46,121,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,121,32,43,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,46,120,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,120,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,32,42,61,32,98,105,108,108,98,111,97,114,100,83,105,122,101,59,13,10,13,10,9,118,101,99,51,32,99,97,109,101,114,97,82,105,103,104,116,32,61,32,118,101,99,51,40,86,105,101,119,77,97,116,114,105,120,91,48,93,91,48,93,44,32,86,105,101,119,77,97,116,114,105,120,91,49,93,91,48,93,44,32,86,105,101,119,77,97,116,114,105,120,91,50,93,91,48,93,41,59,13,10,9,118,101,99,51,32,99,97,109,101,114,97,85,112,32,61,32,118,101,99,51,40,86,105,101,119,77,97,116,114,105,120,91,48,93,91,49,93,44,32,86,105,101,119,77,97,116,114,105,120,91,49,93,91,49,93,44,32,86,105,101,119,77,97,116,114,105,120,91,50,93,91,49,93,41,59,13,10,9,118,101,99,51,32,118,101,114,116,101,120,80,111,115,32,61,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,32,43,32,99,97,109,101,114,97,82,105,103,104,116,42,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,120,32,43,32,99,97,109,101,114,97,85,112,42,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,121,59,13,10,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,118,101,114,116,101,120,80,111,115,44,32,49,46,48,41,59,13,10,9,116,101,120,67,111,111,114,100,115,32,61,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,9,35,101,110,100,105,102,13,10,35,101,108,115,101,13,10,9,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,9,35,101,108,115,101,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,9,35,101,110,100,105,102,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,108,115,101,13,10,9,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,9,35,101,108,115,101,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,9,35,101,110,100,105,102,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,110,100,105,102,13,10,13,10,9,116,101,120,67,111,111,114,100,115,32,61,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,9,118,67,111,108,111,114,32,61,32,99,111,108,111,114,59,13,10,35,105,102,32,84,69,88,84,85,82,69,95,77,65,80,80,73,78,71,13,10,9,118,84,101,120,67,111,111,114,100,32,61,32,118,101,99,50,40,116,101,120,67,111,111,114,100,115,41,59,13,10,35,101,110,100,105,102,13,10,125,13,10, \ No newline at end of file diff --git a/src/Nazara/Graphics/Resources/Shaders/Basic/core.frag b/src/Nazara/Graphics/Resources/Shaders/Basic/core.frag index a789242b9..53844cbc6 100644 --- a/src/Nazara/Graphics/Resources/Shaders/Basic/core.frag +++ b/src/Nazara/Graphics/Resources/Shaders/Basic/core.frag @@ -3,22 +3,24 @@ layout(early_fragment_tests) in; #endif /********************Entrant********************/ +in vec4 vColor; in vec2 vTexCoord; /********************Sortant********************/ out vec4 RenderTarget0; /********************Uniformes********************/ +uniform vec2 InvTargetSize; uniform sampler2D MaterialAlphaMap; uniform float MaterialAlphaThreshold; uniform vec4 MaterialDiffuse; uniform sampler2D MaterialDiffuseMap; -uniform vec2 InvTargetSize; +uniform sampler2D TextureOverlay; /********************Fonctions********************/ void main() { - vec4 fragmentColor = MaterialDiffuse; + vec4 fragmentColor = MaterialDiffuse * vColor; #if AUTO_TEXCOORDS vec2 texCoord = gl_FragCoord.xy * InvTargetSize; @@ -34,6 +36,10 @@ void main() fragmentColor.a *= texture(MaterialAlphaMap, texCoord).r; #endif +#if FLAG_TEXTUREOVERLAY + fragmentColor *= texture(TextureOverlay, texCoord); +#endif + #if ALPHA_TEST if (fragmentColor.a < MaterialAlphaThreshold) discard; diff --git a/src/Nazara/Graphics/Resources/Shaders/Basic/core.frag.h b/src/Nazara/Graphics/Resources/Shaders/Basic/core.frag.h index 97c8ee9b1..c6eff909e 100644 --- a/src/Nazara/Graphics/Resources/Shaders/Basic/core.frag.h +++ b/src/Nazara/Graphics/Resources/Shaders/Basic/core.frag.h @@ -1 +1 @@ -35,105,102,32,69,65,82,76,89,95,70,82,65,71,77,69,78,84,95,84,69,83,84,83,32,38,38,32,33,65,76,80,72,65,95,84,69,83,84,13,10,108,97,121,111,117,116,40,101,97,114,108,121,95,102,114,97,103,109,101,110,116,95,116,101,115,116,115,41,32,105,110,59,13,10,35,101,110,100,105,102,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,105,110,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,83,111,114,116,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,111,117,116,32,118,101,99,52,32,82,101,110,100,101,114,84,97,114,103,101,116,48,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,59,13,10,117,110,105,102,111,114,109,32,118,101,99,50,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,118,101,99,52,32,102,114,97,103,109,101,110,116,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,13,10,35,105,102,32,65,85,84,79,95,84,69,88,67,79,79,82,68,83,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,103,108,95,70,114,97,103,67,111,111,114,100,46,120,121,32,42,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,35,101,108,115,101,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,118,84,101,120,67,111,111,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,68,73,70,70,85,83,69,95,77,65,80,80,73,78,71,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,44,32,116,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,77,65,80,80,73,78,71,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,84,69,83,84,13,10,9,105,102,32,40,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,32,60,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,41,13,10,9,9,100,105,115,99,97,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,102,114,97,103,109,101,110,116,67,111,108,111,114,59,13,10,125, \ No newline at end of file +35,105,102,32,69,65,82,76,89,95,70,82,65,71,77,69,78,84,95,84,69,83,84,83,32,38,38,32,33,65,76,80,72,65,95,84,69,83,84,13,10,108,97,121,111,117,116,40,101,97,114,108,121,95,102,114,97,103,109,101,110,116,95,116,101,115,116,115,41,32,105,110,59,13,10,35,101,110,100,105,102,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,105,110,32,118,101,99,52,32,118,67,111,108,111,114,59,13,10,105,110,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,83,111,114,116,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,111,117,116,32,118,101,99,52,32,82,101,110,100,101,114,84,97,114,103,101,116,48,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,118,101,99,50,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,84,101,120,116,117,114,101,79,118,101,114,108,97,121,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,118,101,99,52,32,102,114,97,103,109,101,110,116,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,32,42,32,118,67,111,108,111,114,59,13,10,13,10,35,105,102,32,65,85,84,79,95,84,69,88,67,79,79,82,68,83,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,103,108,95,70,114,97,103,67,111,111,114,100,46,120,121,32,42,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,35,101,108,115,101,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,118,84,101,120,67,111,111,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,68,73,70,70,85,83,69,95,77,65,80,80,73,78,71,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,44,32,116,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,77,65,80,80,73,78,71,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,70,76,65,71,95,84,69,88,84,85,82,69,79,86,69,82,76,65,89,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,32,42,61,32,116,101,120,116,117,114,101,40,84,101,120,116,117,114,101,79,118,101,114,108,97,121,44,32,116,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,84,69,83,84,13,10,9,105,102,32,40,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,32,60,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,41,13,10,9,9,100,105,115,99,97,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,102,114,97,103,109,101,110,116,67,111,108,111,114,59,13,10,125, \ No newline at end of file diff --git a/src/Nazara/Graphics/Resources/Shaders/Basic/core.vert b/src/Nazara/Graphics/Resources/Shaders/Basic/core.vert index 0516e8090..1a0590b2a 100644 --- a/src/Nazara/Graphics/Resources/Shaders/Basic/core.vert +++ b/src/Nazara/Graphics/Resources/Shaders/Basic/core.vert @@ -1,42 +1,102 @@ /********************Entrant********************/ +#if FLAG_BILLBOARD +in vec3 InstanceData0; // center +in vec4 InstanceData1; // size | sin cos +in vec4 InstanceData2; // color +#else in mat4 InstanceData0; +#endif + +in vec4 VertexColor; in vec3 VertexPosition; in vec2 VertexTexCoord; +in vec4 VertexUserdata0; /********************Sortant********************/ +out vec4 vColor; out vec2 vTexCoord; /********************Uniformes********************/ uniform float VertexDepth; +uniform mat4 ViewMatrix; uniform mat4 ViewProjMatrix; uniform mat4 WorldViewProjMatrix; /********************Fonctions********************/ void main() { -#if FLAG_INSTANCING - #if TRANSFORM - gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0); - #else - #if UNIFORM_VERTEX_DEPTH - gl_Position = InstanceData0 * vec4(VertexPosition.xy, VertexDepth, 1.0); - #else - gl_Position = InstanceData0 * vec4(VertexPosition, 1.0); - #endif - #endif +#if FLAG_VERTEXCOLOR + vec4 color = VertexColor; #else - #if TRANSFORM - gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0); - #else - #if UNIFORM_VERTEX_DEPTH - gl_Position = vec4(VertexPosition.xy, VertexDepth, 1.0); - #else - gl_Position = vec4(VertexPosition, 1.0); - #endif - #endif + vec4 color = vec4(1.0); #endif + vec2 texCoords; + +#if FLAG_BILLBOARD + #if FLAG_INSTANCING + vec3 billboardCenter = InstanceData0; + vec2 billboardSize = InstanceData1.xy; + vec2 billboardSinCos = InstanceData1.zw; + vec4 billboardColor = InstanceData2; + + vec2 rotatedPosition; + rotatedPosition.x = VertexPosition.x*billboardSinCos.y - VertexPosition.y*billboardSinCos.x; + rotatedPosition.y = VertexPosition.y*billboardSinCos.y + VertexPosition.x*billboardSinCos.x; + rotatedPosition *= billboardSize; + + vec3 cameraRight = vec3(ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]); + vec3 cameraUp = vec3(ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]); + vec3 vertexPos = billboardCenter + cameraRight*rotatedPosition.x + cameraUp*rotatedPosition.y; + + gl_Position = ViewProjMatrix * vec4(vertexPos, 1.0); + color = billboardColor; + texCoords = VertexPosition.xy + 0.5; + #else + vec2 billboardCorner = VertexTexCoord - 0.5; + vec2 billboardSize = VertexUserdata0.xy; + vec2 billboardSinCos = VertexUserdata0.zw; + + vec2 rotatedPosition; + rotatedPosition.x = billboardCorner.x*billboardSinCos.y - billboardCorner.y*billboardSinCos.x; + rotatedPosition.y = billboardCorner.y*billboardSinCos.y + billboardCorner.x*billboardSinCos.x; + rotatedPosition *= billboardSize; + + vec3 cameraRight = vec3(ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]); + vec3 cameraUp = vec3(ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]); + vec3 vertexPos = VertexPosition + cameraRight*rotatedPosition.x + cameraUp*rotatedPosition.y; + + gl_Position = ViewProjMatrix * vec4(vertexPos, 1.0); + texCoords = VertexTexCoord; + #endif +#else + #if FLAG_INSTANCING + #if TRANSFORM + gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0); + #else + #if UNIFORM_VERTEX_DEPTH + gl_Position = InstanceData0 * vec4(VertexPosition.xy, VertexDepth, 1.0); + #else + gl_Position = InstanceData0 * vec4(VertexPosition, 1.0); + #endif + #endif + #else + #if TRANSFORM + gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0); + #else + #if UNIFORM_VERTEX_DEPTH + gl_Position = vec4(VertexPosition.xy, VertexDepth, 1.0); + #else + gl_Position = vec4(VertexPosition, 1.0); + #endif + #endif + #endif + + texCoords = VertexTexCoord; +#endif + + vColor = color; #if TEXTURE_MAPPING - vTexCoord = vec2(VertexTexCoord); + vTexCoord = vec2(texCoords); #endif } diff --git a/src/Nazara/Graphics/Resources/Shaders/Basic/core.vert.h b/src/Nazara/Graphics/Resources/Shaders/Basic/core.vert.h index 681ed8a5a..fff3d503a 100644 --- a/src/Nazara/Graphics/Resources/Shaders/Basic/core.vert.h +++ b/src/Nazara/Graphics/Resources/Shaders/Basic/core.vert.h @@ -1 +1 @@ -47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,105,110,32,109,97,116,52,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,13,10,105,110,32,118,101,99,51,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,59,13,10,105,110,32,118,101,99,50,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,83,111,114,116,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,111,117,116,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,86,101,114,116,101,120,68,101,112,116,104,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,35,101,108,115,101,13,10,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,110,100,105,102,13,10,35,101,108,115,101,13,10,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,35,101,108,115,101,13,10,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,110,100,105,102,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,84,69,88,84,85,82,69,95,77,65,80,80,73,78,71,13,10,9,118,84,101,120,67,111,111,114,100,32,61,32,118,101,99,50,40,86,101,114,116,101,120,84,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,125,13,10, \ No newline at end of file +47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,35,105,102,32,70,76,65,71,95,66,73,76,76,66,79,65,82,68,13,10,105,110,32,118,101,99,51,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,32,47,47,32,99,101,110,116,101,114,13,10,105,110,32,118,101,99,52,32,73,110,115,116,97,110,99,101,68,97,116,97,49,59,32,47,47,32,115,105,122,101,32,124,32,115,105,110,32,99,111,115,13,10,105,110,32,118,101,99,52,32,73,110,115,116,97,110,99,101,68,97,116,97,50,59,32,47,47,32,99,111,108,111,114,13,10,35,101,108,115,101,13,10,105,110,32,109,97,116,52,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,13,10,35,101,110,100,105,102,13,10,13,10,105,110,32,118,101,99,52,32,86,101,114,116,101,120,67,111,108,111,114,59,13,10,105,110,32,118,101,99,51,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,59,13,10,105,110,32,118,101,99,50,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,105,110,32,118,101,99,52,32,86,101,114,116,101,120,85,115,101,114,100,97,116,97,48,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,83,111,114,116,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,111,117,116,32,118,101,99,52,32,118,67,111,108,111,114,59,13,10,111,117,116,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,86,101,114,116,101,120,68,101,112,116,104,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,86,105,101,119,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,35,105,102,32,70,76,65,71,95,86,69,82,84,69,88,67,79,76,79,82,13,10,9,118,101,99,52,32,99,111,108,111,114,32,61,32,86,101,114,116,101,120,67,111,108,111,114,59,13,10,35,101,108,115,101,13,10,9,118,101,99,52,32,99,111,108,111,114,32,61,32,118,101,99,52,40,49,46,48,41,59,13,10,35,101,110,100,105,102,13,10,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,115,59,13,10,13,10,35,105,102,32,70,76,65,71,95,66,73,76,76,66,79,65,82,68,13,10,9,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,118,101,99,51,32,98,105,108,108,98,111,97,114,100,67,101,110,116,101,114,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,83,105,122,101,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,49,46,120,121,59,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,49,46,122,119,59,13,10,9,118,101,99,52,32,98,105,108,108,98,111,97,114,100,67,111,108,111,114,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,50,59,13,10,13,10,9,118,101,99,50,32,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,120,32,61,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,121,32,45,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,121,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,120,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,121,32,61,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,121,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,121,32,43,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,120,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,32,42,61,32,98,105,108,108,98,111,97,114,100,83,105,122,101,59,13,10,13,10,9,118,101,99,51,32,99,97,109,101,114,97,82,105,103,104,116,32,61,32,118,101,99,51,40,86,105,101,119,77,97,116,114,105,120,91,48,93,91,48,93,44,32,86,105,101,119,77,97,116,114,105,120,91,49,93,91,48,93,44,32,86,105,101,119,77,97,116,114,105,120,91,50,93,91,48,93,41,59,13,10,9,118,101,99,51,32,99,97,109,101,114,97,85,112,32,61,32,118,101,99,51,40,86,105,101,119,77,97,116,114,105,120,91,48,93,91,49,93,44,32,86,105,101,119,77,97,116,114,105,120,91,49,93,91,49,93,44,32,86,105,101,119,77,97,116,114,105,120,91,50,93,91,49,93,41,59,13,10,9,118,101,99,51,32,118,101,114,116,101,120,80,111,115,32,61,32,98,105,108,108,98,111,97,114,100,67,101,110,116,101,114,32,43,32,99,97,109,101,114,97,82,105,103,104,116,42,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,120,32,43,32,99,97,109,101,114,97,85,112,42,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,121,59,13,10,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,118,101,114,116,101,120,80,111,115,44,32,49,46,48,41,59,13,10,9,99,111,108,111,114,32,61,32,98,105,108,108,98,111,97,114,100,67,111,108,111,114,59,13,10,9,116,101,120,67,111,111,114,100,115,32,61,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,32,43,32,48,46,53,59,13,10,9,35,101,108,115,101,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,32,61,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,32,45,32,48,46,53,59,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,83,105,122,101,32,61,32,86,101,114,116,101,120,85,115,101,114,100,97,116,97,48,46,120,121,59,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,32,61,32,86,101,114,116,101,120,85,115,101,114,100,97,116,97,48,46,122,119,59,13,10,9,13,10,9,118,101,99,50,32,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,120,32,61,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,46,120,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,121,32,45,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,46,121,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,120,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,121,32,61,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,46,121,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,121,32,43,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,46,120,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,120,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,32,42,61,32,98,105,108,108,98,111,97,114,100,83,105,122,101,59,13,10,13,10,9,118,101,99,51,32,99,97,109,101,114,97,82,105,103,104,116,32,61,32,118,101,99,51,40,86,105,101,119,77,97,116,114,105,120,91,48,93,91,48,93,44,32,86,105,101,119,77,97,116,114,105,120,91,49,93,91,48,93,44,32,86,105,101,119,77,97,116,114,105,120,91,50,93,91,48,93,41,59,13,10,9,118,101,99,51,32,99,97,109,101,114,97,85,112,32,61,32,118,101,99,51,40,86,105,101,119,77,97,116,114,105,120,91,48,93,91,49,93,44,32,86,105,101,119,77,97,116,114,105,120,91,49,93,91,49,93,44,32,86,105,101,119,77,97,116,114,105,120,91,50,93,91,49,93,41,59,13,10,9,118,101,99,51,32,118,101,114,116,101,120,80,111,115,32,61,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,32,43,32,99,97,109,101,114,97,82,105,103,104,116,42,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,120,32,43,32,99,97,109,101,114,97,85,112,42,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,121,59,13,10,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,118,101,114,116,101,120,80,111,115,44,32,49,46,48,41,59,13,10,9,116,101,120,67,111,111,114,100,115,32,61,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,9,35,101,110,100,105,102,13,10,35,101,108,115,101,13,10,9,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,9,35,101,108,115,101,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,9,35,101,110,100,105,102,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,108,115,101,13,10,9,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,9,35,101,108,115,101,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,9,35,101,110,100,105,102,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,110,100,105,102,13,10,13,10,9,116,101,120,67,111,111,114,100,115,32,61,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,9,118,67,111,108,111,114,32,61,32,99,111,108,111,114,59,13,10,35,105,102,32,84,69,88,84,85,82,69,95,77,65,80,80,73,78,71,13,10,9,118,84,101,120,67,111,111,114,100,32,61,32,118,101,99,50,40,116,101,120,67,111,111,114,100,115,41,59,13,10,35,101,110,100,105,102,13,10,125,13,10, \ No newline at end of file diff --git a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/compatibility.frag b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/compatibility.frag index d122528d4..f78f73ed6 100644 --- a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/compatibility.frag +++ b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/compatibility.frag @@ -1,5 +1,5 @@ #if FLAG_DEFERRED - #error Deferred Shading needs core profile + #error Deferred Shading is not supported by compatibility shaders #endif #define LIGHT_DIRECTIONAL 0 @@ -11,6 +11,7 @@ varying mat3 vLightToWorld; varying vec3 vNormal; varying vec2 vTexCoord; varying vec3 vWorldPos; +varying vec4 vColor; /********************Uniformes********************/ struct Light @@ -24,9 +25,10 @@ struct Light vec2 parameters3; }; -uniform vec3 EyePosition; +// Lumières uniform Light Lights[3]; +// Matériau uniform sampler2D MaterialAlphaMap; uniform float MaterialAlphaThreshold; uniform vec4 MaterialAmbient; @@ -38,18 +40,27 @@ uniform float MaterialShininess; uniform vec4 MaterialSpecular; uniform sampler2D MaterialSpecularMap; +// Autres +uniform vec3 EyePosition; uniform vec4 SceneAmbient; /********************Fonctions********************/ void main() { - vec4 diffuseColor = MaterialDiffuse; + vec4 diffuseColor = MaterialDiffuse * vColor; + +#if AUTO_TEXCOORDS + vec2 texCoord = gl_FragCoord.xy * InvTargetSize; +#else + vec2 texCoord = vTexCoord; +#endif + #if DIFFUSE_MAPPING - diffuseColor *= texture(MaterialDiffuseMap, vTexCoord); + diffuseColor *= texture(MaterialDiffuseMap, texCoord); #endif #if ALPHA_MAPPING - diffuseColor.a *= texture(MaterialAlphaMap, vTexCoord).r; + diffuseColor.a *= texture(MaterialAlphaMap, texCoord).r; #endif #if ALPHA_TEST @@ -63,7 +74,7 @@ void main() vec3 lightSpecular = vec3(0.0); #if NORMAL_MAPPING - vec3 normal = normalize(vLightToWorld * (2.0 * vec3(texture(MaterialNormalMap, vTexCoord)) - 1.0)); + vec3 normal = normalize(vLightToWorld * (2.0 * vec3(texture(MaterialNormalMap, texCoord)) - 1.0)); #else vec3 normal = normalize(vNormal); #endif @@ -206,7 +217,7 @@ void main() lightSpecular *= MaterialSpecular.rgb; #if SPECULAR_MAPPING - lightSpecular *= texture(MaterialSpecularMap, vTexCoord).rgb; // Utiliser l'alpha de MaterialSpecular n'aurait aucun sens + lightSpecular *= texture(MaterialSpecularMap, texCoord).rgb; // Utiliser l'alpha de MaterialSpecular n'aurait aucun sens #endif vec3 lightColor = (lightAmbient + lightDiffuse + lightSpecular); @@ -215,7 +226,7 @@ void main() #if EMISSIVE_MAPPING float lightIntensity = dot(lightColor, vec3(0.3, 0.59, 0.11)); - vec3 emissionColor = MaterialDiffuse.rgb * texture(MaterialEmissiveMap, vTexCoord).rgb; + vec3 emissionColor = MaterialDiffuse.rgb * texture(MaterialEmissiveMap, texCoord).rgb; RenderTarget0 = vec4(mix(fragmentColor.rgb, emissionColor, clamp(1.0 - 3.0*lightIntensity, 0.0, 1.0)), fragmentColor.a); #else RenderTarget0 = fragmentColor; diff --git a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/compatibility.frag.h b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/compatibility.frag.h index 97855b8e5..3358d4e82 100644 --- a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/compatibility.frag.h +++ b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/compatibility.frag.h @@ -1 +1 @@ -35,105,102,32,70,76,65,71,95,68,69,70,69,82,82,69,68,13,10,9,35,101,114,114,111,114,32,68,101,102,101,114,114,101,100,32,83,104,97,100,105,110,103,32,110,101,101,100,115,32,99,111,114,101,32,112,114,111,102,105,108,101,13,10,35,101,110,100,105,102,13,10,13,10,35,100,101,102,105,110,101,32,76,73,71,72,84,95,68,73,82,69,67,84,73,79,78,65,76,32,48,13,10,35,100,101,102,105,110,101,32,76,73,71,72,84,95,80,79,73,78,84,32,49,13,10,35,100,101,102,105,110,101,32,76,73,71,72,84,95,83,80,79,84,32,50,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,97,114,121,105,110,103,32,109,97,116,51,32,118,76,105,103,104,116,84,111,87,111,114,108,100,59,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,118,78,111,114,109,97,108,59,13,10,118,97,114,121,105,110,103,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,118,87,111,114,108,100,80,111,115,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,115,116,114,117,99,116,32,76,105,103,104,116,13,10,123,13,10,9,105,110,116,32,116,121,112,101,59,13,10,9,118,101,99,52,32,99,111,108,111,114,59,13,10,9,118,101,99,50,32,102,97,99,116,111,114,115,59,13,10,13,10,9,118,101,99,52,32,112,97,114,97,109,101,116,101,114,115,49,59,13,10,9,118,101,99,52,32,112,97,114,97,109,101,116,101,114,115,50,59,13,10,9,118,101,99,50,32,112,97,114,97,109,101,116,101,114,115,51,59,13,10,125,59,13,10,13,10,117,110,105,102,111,114,109,32,118,101,99,51,32,69,121,101,80,111,115,105,116,105,111,110,59,13,10,117,110,105,102,111,114,109,32,76,105,103,104,116,32,76,105,103,104,116,115,91,51,93,59,13,10,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,69,109,105,115,115,105,118,101,77,97,112,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,78,111,114,109,97,108,77,97,112,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,77,97,112,59,13,10,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,83,99,101,110,101,65,109,98,105,101,110,116,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,118,101,99,52,32,100,105,102,102,117,115,101,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,35,105,102,32,68,73,70,70,85,83,69,95,77,65,80,80,73,78,71,13,10,9,100,105,102,102,117,115,101,67,111,108,111,114,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,44,32,118,84,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,77,65,80,80,73,78,71,13,10,9,100,105,102,102,117,115,101,67,111,108,111,114,46,97,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,44,32,118,84,101,120,67,111,111,114,100,41,46,114,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,84,69,83,84,13,10,9,105,102,32,40,100,105,102,102,117,115,101,67,111,108,111,114,46,97,32,60,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,41,13,10,9,9,100,105,115,99,97,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,76,73,71,72,84,73,78,71,13,10,9,118,101,99,51,32,108,105,103,104,116,65,109,98,105,101,110,116,32,61,32,118,101,99,51,40,48,46,48,41,59,13,10,9,118,101,99,51,32,108,105,103,104,116,68,105,102,102,117,115,101,32,61,32,118,101,99,51,40,48,46,48,41,59,13,10,9,118,101,99,51,32,108,105,103,104,116,83,112,101,99,117,108,97,114,32,61,32,118,101,99,51,40,48,46,48,41,59,13,10,13,10,9,35,105,102,32,78,79,82,77,65,76,95,77,65,80,80,73,78,71,13,10,9,118,101,99,51,32,110,111,114,109,97,108,32,61,32,110,111,114,109,97,108,105,122,101,40,118,76,105,103,104,116,84,111,87,111,114,108,100,32,42,32,40,50,46,48,32,42,32,118,101,99,51,40,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,78,111,114,109,97,108,77,97,112,44,32,118,84,101,120,67,111,111,114,100,41,41,32,45,32,49,46,48,41,41,59,13,10,9,35,101,108,115,101,13,10,9,118,101,99,51,32,110,111,114,109,97,108,32,61,32,110,111,114,109,97,108,105,122,101,40,118,78,111,114,109,97,108,41,59,13,10,9,35,101,110,100,105,102,13,10,13,10,9,105,102,32,40,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,32,62,32,48,46,48,41,13,10,9,123,13,10,9,9,118,101,99,51,32,101,121,101,86,101,99,32,61,32,110,111,114,109,97,108,105,122,101,40,69,121,101,80,111,115,105,116,105,111,110,32,45,32,118,87,111,114,108,100,80,111,115,41,59,13,10,13,10,9,9,102,111,114,32,40,105,110,116,32,105,32,61,32,48,59,32,105,32,60,32,51,59,32,43,43,105,41,13,10,9,9,123,13,10,9,9,9,105,102,32,40,76,105,103,104,116,115,91,105,93,46,116,121,112,101,32,61,61,32,76,73,71,72,84,95,68,73,82,69,67,84,73,79,78,65,76,41,13,10,9,9,9,123,13,10,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,45,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,59,13,10,13,10,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,13,10,9,9,9,9,47,47,32,83,112,101,99,117,108,97,114,13,10,9,9,9,9,118,101,99,51,32,114,101,102,108,101,99,116,105,111,110,32,61,32,114,101,102,108,101,99,116,40,45,108,105,103,104,116,68,105,114,44,32,110,111,114,109,97,108,41,59,13,10,9,9,9,9,102,108,111,97,116,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,109,97,120,40,100,111,116,40,114,101,102,108,101,99,116,105,111,110,44,32,101,121,101,86,101,99,41,44,32,48,46,48,41,59,13,10,9,9,9,9,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,112,111,119,40,115,112,101,99,117,108,97,114,70,97,99,116,111,114,44,32,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,41,59,13,10,13,10,9,9,9,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,43,61,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,59,13,10,9,9,9,125,13,10,9,9,9,101,108,115,101,32,105,102,32,40,76,105,103,104,116,115,91,105,93,46,116,121,112,101,32,61,61,32,76,73,71,72,84,95,80,79,73,78,84,41,13,10,9,9,9,123,13,10,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,118,87,111,114,108,100,80,111,115,59,13,10,9,9,9,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,32,47,47,32,78,111,114,109,97,108,105,115,97,116,105,111,110,13,10,9,9,9,9,13,10,9,9,9,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,9,9,9,9,13,10,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,13,10,9,9,9,9,47,47,32,83,112,101,99,117,108,97,114,13,10,9,9,9,9,118,101,99,51,32,114,101,102,108,101,99,116,105,111,110,32,61,32,114,101,102,108,101,99,116,40,45,108,105,103,104,116,68,105,114,44,32,110,111,114,109,97,108,41,59,13,10,9,9,9,9,102,108,111,97,116,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,109,97,120,40,100,111,116,40,114,101,102,108,101,99,116,105,111,110,44,32,101,121,101,86,101,99,41,44,32,48,46,48,41,59,13,10,9,9,9,9,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,112,111,119,40,115,112,101,99,117,108,97,114,70,97,99,116,111,114,44,32,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,41,59,13,10,13,10,9,9,9,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,43,61,32,97,116,116,32,42,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,59,13,10,9,9,9,125,13,10,9,9,9,101,108,115,101,32,105,102,32,40,76,105,103,104,116,115,91,105,93,46,116,121,112,101,32,61,61,32,76,73,71,72,84,95,83,80,79,84,41,13,10,9,9,9,123,13,10,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,118,87,111,114,108,100,80,111,115,59,13,10,9,9,9,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,32,47,47,32,78,111,114,109,97,108,105,115,97,116,105,111,110,13,10,9,9,9,9,13,10,9,9,9,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,47,47,32,77,111,100,105,102,105,99,97,116,105,111,110,32,100,101,32,108,39,97,116,116,195,169,110,117,97,116,105,111,110,32,112,111,117,114,32,103,195,169,114,101,114,32,108,101,32,115,112,111,116,13,10,9,9,9,9,102,108,111,97,116,32,99,117,114,65,110,103,108,101,32,61,32,100,111,116,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,120,121,122,44,32,45,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,102,108,111,97,116,32,111,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,51,46,121,59,13,10,9,9,9,9,102,108,111,97,116,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,51,46,120,32,45,32,111,117,116,101,114,65,110,103,108,101,59,13,10,9,9,9,9,97,116,116,32,42,61,32,109,97,120,40,40,99,117,114,65,110,103,108,101,32,45,32,111,117,116,101,114,65,110,103,108,101,41,32,47,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,13,10,9,9,9,9,47,47,32,83,112,101,99,117,108,97,114,13,10,9,9,9,9,118,101,99,51,32,114,101,102,108,101,99,116,105,111,110,32,61,32,114,101,102,108,101,99,116,40,45,108,105,103,104,116,68,105,114,44,32,110,111,114,109,97,108,41,59,13,10,9,9,9,9,102,108,111,97,116,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,109,97,120,40,100,111,116,40,114,101,102,108,101,99,116,105,111,110,44,32,101,121,101,86,101,99,41,44,32,48,46,48,41,59,13,10,9,9,9,9,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,112,111,119,40,115,112,101,99,117,108,97,114,70,97,99,116,111,114,44,32,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,41,59,13,10,13,10,9,9,9,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,43,61,32,97,116,116,32,42,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,59,13,10,9,9,9,125,13,10,9,9,125,13,10,9,125,13,10,9,101,108,115,101,13,10,9,123,13,10,9,9,102,111,114,32,40,105,110,116,32,105,32,61,32,48,59,32,105,32,60,32,51,59,32,43,43,105,41,13,10,9,9,123,13,10,9,9,9,105,102,32,40,76,105,103,104,116,115,91,105,93,46,116,121,112,101,32,61,61,32,76,73,71,72,84,95,68,73,82,69,67,84,73,79,78,65,76,41,13,10,9,9,9,123,13,10,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,45,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,59,13,10,13,10,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,9,9,9,125,13,10,9,9,9,101,108,115,101,32,105,102,32,40,76,105,103,104,116,115,91,105,93,46,116,121,112,101,32,61,61,32,76,73,71,72,84,95,80,79,73,78,84,41,13,10,9,9,9,123,13,10,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,118,87,111,114,108,100,80,111,115,59,13,10,9,9,9,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,32,47,47,32,78,111,114,109,97,108,105,115,97,116,105,111,110,13,10,9,9,9,9,13,10,9,9,9,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,9,9,9,9,13,10,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,9,9,9,125,13,10,9,9,9,101,108,115,101,32,105,102,32,40,76,105,103,104,116,115,91,105,93,46,116,121,112,101,32,61,61,32,76,73,71,72,84,95,83,80,79,84,41,13,10,9,9,9,123,13,10,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,118,87,111,114,108,100,80,111,115,59,13,10,9,9,9,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,32,47,47,32,78,111,114,109,97,108,105,115,97,116,105,111,110,13,10,9,9,9,9,13,10,9,9,9,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,47,47,32,77,111,100,105,102,105,99,97,116,105,111,110,32,100,101,32,108,39,97,116,116,195,169,110,117,97,116,105,111,110,32,112,111,117,114,32,103,195,169,114,101,114,32,108,101,32,115,112,111,116,13,10,9,9,9,9,102,108,111,97,116,32,99,117,114,65,110,103,108,101,32,61,32,100,111,116,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,120,121,122,44,32,45,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,102,108,111,97,116,32,111,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,51,46,121,59,13,10,9,9,9,9,102,108,111,97,116,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,51,46,120,32,45,32,111,117,116,101,114,65,110,103,108,101,59,13,10,9,9,9,9,97,116,116,32,42,61,32,109,97,120,40,40,99,117,114,65,110,103,108,101,32,45,32,111,117,116,101,114,65,110,103,108,101,41,32,47,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,9,9,9,125,13,10,9,9,125,13,10,9,125,13,10,13,10,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,42,61,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,46,114,103,98,59,13,10,9,35,105,102,32,83,80,69,67,85,76,65,82,95,77,65,80,80,73,78,71,13,10,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,77,97,112,44,32,118,84,101,120,67,111,111,114,100,41,46,114,103,98,59,32,47,47,32,85,116,105,108,105,115,101,114,32,108,39,97,108,112,104,97,32,100,101,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,32,110,39,97,117,114,97,105,116,32,97,117,99,117,110,32,115,101,110,115,13,10,9,35,101,110,100,105,102,13,10,9,9,13,10,9,118,101,99,51,32,108,105,103,104,116,67,111,108,111,114,32,61,32,40,108,105,103,104,116,65,109,98,105,101,110,116,32,43,32,108,105,103,104,116,68,105,102,102,117,115,101,32,43,32,108,105,103,104,116,83,112,101,99,117,108,97,114,41,59,13,10,9,118,101,99,52,32,102,114,97,103,109,101,110,116,67,111,108,111,114,32,61,32,118,101,99,52,40,108,105,103,104,116,67,111,108,111,114,44,32,49,46,48,41,32,42,32,100,105,102,102,117,115,101,67,111,108,111,114,59,13,10,13,10,9,35,105,102,32,69,77,73,83,83,73,86,69,95,77,65,80,80,73,78,71,13,10,9,102,108,111,97,116,32,108,105,103,104,116,73,110,116,101,110,115,105,116,121,32,61,32,100,111,116,40,108,105,103,104,116,67,111,108,111,114,44,32,118,101,99,51,40,48,46,51,44,32,48,46,53,57,44,32,48,46,49,49,41,41,59,13,10,13,10,9,118,101,99,51,32,101,109,105,115,115,105,111,110,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,46,114,103,98,32,42,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,69,109,105,115,115,105,118,101,77,97,112,44,32,118,84,101,120,67,111,111,114,100,41,46,114,103,98,59,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,118,101,99,52,40,109,105,120,40,102,114,97,103,109,101,110,116,67,111,108,111,114,46,114,103,98,44,32,101,109,105,115,115,105,111,110,67,111,108,111,114,44,32,99,108,97,109,112,40,49,46,48,32,45,32,51,46,48,42,108,105,103,104,116,73,110,116,101,110,115,105,116,121,44,32,48,46,48,44,32,49,46,48,41,41,44,32,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,41,59,13,10,9,35,101,108,115,101,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,102,114,97,103,109,101,110,116,67,111,108,111,114,59,13,10,9,35,101,110,100,105,102,32,47,47,32,69,77,73,83,83,73,86,69,95,77,65,80,80,73,78,71,13,10,35,101,108,115,101,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,100,105,102,102,117,115,101,67,111,108,111,114,59,13,10,35,101,110,100,105,102,32,47,47,32,76,73,71,72,84,73,78,71,13,10,125,13,10, \ No newline at end of file +35,105,102,32,70,76,65,71,95,68,69,70,69,82,82,69,68,13,10,9,35,101,114,114,111,114,32,68,101,102,101,114,114,101,100,32,83,104,97,100,105,110,103,32,105,115,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,98,121,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,115,104,97,100,101,114,115,13,10,35,101,110,100,105,102,13,10,13,10,35,100,101,102,105,110,101,32,76,73,71,72,84,95,68,73,82,69,67,84,73,79,78,65,76,32,48,13,10,35,100,101,102,105,110,101,32,76,73,71,72,84,95,80,79,73,78,84,32,49,13,10,35,100,101,102,105,110,101,32,76,73,71,72,84,95,83,80,79,84,32,50,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,97,114,121,105,110,103,32,109,97,116,51,32,118,76,105,103,104,116,84,111,87,111,114,108,100,59,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,118,78,111,114,109,97,108,59,13,10,118,97,114,121,105,110,103,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,118,87,111,114,108,100,80,111,115,59,13,10,118,97,114,121,105,110,103,32,118,101,99,52,32,118,67,111,108,111,114,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,115,116,114,117,99,116,32,76,105,103,104,116,13,10,123,13,10,9,105,110,116,32,116,121,112,101,59,13,10,9,118,101,99,52,32,99,111,108,111,114,59,13,10,9,118,101,99,50,32,102,97,99,116,111,114,115,59,13,10,13,10,9,118,101,99,52,32,112,97,114,97,109,101,116,101,114,115,49,59,13,10,9,118,101,99,52,32,112,97,114,97,109,101,116,101,114,115,50,59,13,10,9,118,101,99,50,32,112,97,114,97,109,101,116,101,114,115,51,59,13,10,125,59,13,10,13,10,47,47,32,76,117,109,105,195,168,114,101,115,13,10,117,110,105,102,111,114,109,32,76,105,103,104,116,32,76,105,103,104,116,115,91,51,93,59,13,10,13,10,47,47,32,77,97,116,195,169,114,105,97,117,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,69,109,105,115,115,105,118,101,77,97,112,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,78,111,114,109,97,108,77,97,112,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,77,97,112,59,13,10,13,10,47,47,32,65,117,116,114,101,115,13,10,117,110,105,102,111,114,109,32,118,101,99,51,32,69,121,101,80,111,115,105,116,105,111,110,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,83,99,101,110,101,65,109,98,105,101,110,116,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,118,101,99,52,32,100,105,102,102,117,115,101,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,32,42,32,118,67,111,108,111,114,59,13,10,13,10,35,105,102,32,65,85,84,79,95,84,69,88,67,79,79,82,68,83,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,103,108,95,70,114,97,103,67,111,111,114,100,46,120,121,32,42,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,35,101,108,115,101,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,118,84,101,120,67,111,111,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,68,73,70,70,85,83,69,95,77,65,80,80,73,78,71,13,10,9,100,105,102,102,117,115,101,67,111,108,111,114,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,44,32,116,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,77,65,80,80,73,78,71,13,10,9,100,105,102,102,117,115,101,67,111,108,111,114,46,97,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,84,69,83,84,13,10,9,105,102,32,40,100,105,102,102,117,115,101,67,111,108,111,114,46,97,32,60,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,41,13,10,9,9,100,105,115,99,97,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,76,73,71,72,84,73,78,71,13,10,9,118,101,99,51,32,108,105,103,104,116,65,109,98,105,101,110,116,32,61,32,118,101,99,51,40,48,46,48,41,59,13,10,9,118,101,99,51,32,108,105,103,104,116,68,105,102,102,117,115,101,32,61,32,118,101,99,51,40,48,46,48,41,59,13,10,9,118,101,99,51,32,108,105,103,104,116,83,112,101,99,117,108,97,114,32,61,32,118,101,99,51,40,48,46,48,41,59,13,10,13,10,9,35,105,102,32,78,79,82,77,65,76,95,77,65,80,80,73,78,71,13,10,9,118,101,99,51,32,110,111,114,109,97,108,32,61,32,110,111,114,109,97,108,105,122,101,40,118,76,105,103,104,116,84,111,87,111,114,108,100,32,42,32,40,50,46,48,32,42,32,118,101,99,51,40,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,78,111,114,109,97,108,77,97,112,44,32,116,101,120,67,111,111,114,100,41,41,32,45,32,49,46,48,41,41,59,13,10,9,35,101,108,115,101,13,10,9,118,101,99,51,32,110,111,114,109,97,108,32,61,32,110,111,114,109,97,108,105,122,101,40,118,78,111,114,109,97,108,41,59,13,10,9,35,101,110,100,105,102,13,10,13,10,9,105,102,32,40,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,32,62,32,48,46,48,41,13,10,9,123,13,10,9,9,118,101,99,51,32,101,121,101,86,101,99,32,61,32,110,111,114,109,97,108,105,122,101,40,69,121,101,80,111,115,105,116,105,111,110,32,45,32,118,87,111,114,108,100,80,111,115,41,59,13,10,13,10,9,9,102,111,114,32,40,105,110,116,32,105,32,61,32,48,59,32,105,32,60,32,51,59,32,43,43,105,41,13,10,9,9,123,13,10,9,9,9,105,102,32,40,76,105,103,104,116,115,91,105,93,46,116,121,112,101,32,61,61,32,76,73,71,72,84,95,68,73,82,69,67,84,73,79,78,65,76,41,13,10,9,9,9,123,13,10,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,45,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,59,13,10,13,10,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,13,10,9,9,9,9,47,47,32,83,112,101,99,117,108,97,114,13,10,9,9,9,9,118,101,99,51,32,114,101,102,108,101,99,116,105,111,110,32,61,32,114,101,102,108,101,99,116,40,45,108,105,103,104,116,68,105,114,44,32,110,111,114,109,97,108,41,59,13,10,9,9,9,9,102,108,111,97,116,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,109,97,120,40,100,111,116,40,114,101,102,108,101,99,116,105,111,110,44,32,101,121,101,86,101,99,41,44,32,48,46,48,41,59,13,10,9,9,9,9,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,112,111,119,40,115,112,101,99,117,108,97,114,70,97,99,116,111,114,44,32,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,41,59,13,10,13,10,9,9,9,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,43,61,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,59,13,10,9,9,9,125,13,10,9,9,9,101,108,115,101,32,105,102,32,40,76,105,103,104,116,115,91,105,93,46,116,121,112,101,32,61,61,32,76,73,71,72,84,95,80,79,73,78,84,41,13,10,9,9,9,123,13,10,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,118,87,111,114,108,100,80,111,115,59,13,10,9,9,9,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,32,47,47,32,78,111,114,109,97,108,105,115,97,116,105,111,110,13,10,9,9,9,9,13,10,9,9,9,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,9,9,9,9,13,10,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,13,10,9,9,9,9,47,47,32,83,112,101,99,117,108,97,114,13,10,9,9,9,9,118,101,99,51,32,114,101,102,108,101,99,116,105,111,110,32,61,32,114,101,102,108,101,99,116,40,45,108,105,103,104,116,68,105,114,44,32,110,111,114,109,97,108,41,59,13,10,9,9,9,9,102,108,111,97,116,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,109,97,120,40,100,111,116,40,114,101,102,108,101,99,116,105,111,110,44,32,101,121,101,86,101,99,41,44,32,48,46,48,41,59,13,10,9,9,9,9,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,112,111,119,40,115,112,101,99,117,108,97,114,70,97,99,116,111,114,44,32,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,41,59,13,10,13,10,9,9,9,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,43,61,32,97,116,116,32,42,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,59,13,10,9,9,9,125,13,10,9,9,9,101,108,115,101,32,105,102,32,40,76,105,103,104,116,115,91,105,93,46,116,121,112,101,32,61,61,32,76,73,71,72,84,95,83,80,79,84,41,13,10,9,9,9,123,13,10,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,118,87,111,114,108,100,80,111,115,59,13,10,9,9,9,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,32,47,47,32,78,111,114,109,97,108,105,115,97,116,105,111,110,13,10,9,9,9,9,13,10,9,9,9,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,47,47,32,77,111,100,105,102,105,99,97,116,105,111,110,32,100,101,32,108,39,97,116,116,195,169,110,117,97,116,105,111,110,32,112,111,117,114,32,103,195,169,114,101,114,32,108,101,32,115,112,111,116,13,10,9,9,9,9,102,108,111,97,116,32,99,117,114,65,110,103,108,101,32,61,32,100,111,116,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,120,121,122,44,32,45,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,102,108,111,97,116,32,111,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,51,46,121,59,13,10,9,9,9,9,102,108,111,97,116,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,51,46,120,32,45,32,111,117,116,101,114,65,110,103,108,101,59,13,10,9,9,9,9,97,116,116,32,42,61,32,109,97,120,40,40,99,117,114,65,110,103,108,101,32,45,32,111,117,116,101,114,65,110,103,108,101,41,32,47,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,13,10,9,9,9,9,47,47,32,83,112,101,99,117,108,97,114,13,10,9,9,9,9,118,101,99,51,32,114,101,102,108,101,99,116,105,111,110,32,61,32,114,101,102,108,101,99,116,40,45,108,105,103,104,116,68,105,114,44,32,110,111,114,109,97,108,41,59,13,10,9,9,9,9,102,108,111,97,116,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,109,97,120,40,100,111,116,40,114,101,102,108,101,99,116,105,111,110,44,32,101,121,101,86,101,99,41,44,32,48,46,48,41,59,13,10,9,9,9,9,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,112,111,119,40,115,112,101,99,117,108,97,114,70,97,99,116,111,114,44,32,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,41,59,13,10,13,10,9,9,9,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,43,61,32,97,116,116,32,42,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,59,13,10,9,9,9,125,13,10,9,9,125,13,10,9,125,13,10,9,101,108,115,101,13,10,9,123,13,10,9,9,102,111,114,32,40,105,110,116,32,105,32,61,32,48,59,32,105,32,60,32,51,59,32,43,43,105,41,13,10,9,9,123,13,10,9,9,9,105,102,32,40,76,105,103,104,116,115,91,105,93,46,116,121,112,101,32,61,61,32,76,73,71,72,84,95,68,73,82,69,67,84,73,79,78,65,76,41,13,10,9,9,9,123,13,10,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,45,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,59,13,10,13,10,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,9,9,9,125,13,10,9,9,9,101,108,115,101,32,105,102,32,40,76,105,103,104,116,115,91,105,93,46,116,121,112,101,32,61,61,32,76,73,71,72,84,95,80,79,73,78,84,41,13,10,9,9,9,123,13,10,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,118,87,111,114,108,100,80,111,115,59,13,10,9,9,9,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,32,47,47,32,78,111,114,109,97,108,105,115,97,116,105,111,110,13,10,9,9,9,9,13,10,9,9,9,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,9,9,9,9,13,10,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,9,9,9,125,13,10,9,9,9,101,108,115,101,32,105,102,32,40,76,105,103,104,116,115,91,105,93,46,116,121,112,101,32,61,61,32,76,73,71,72,84,95,83,80,79,84,41,13,10,9,9,9,123,13,10,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,118,87,111,114,108,100,80,111,115,59,13,10,9,9,9,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,32,47,47,32,78,111,114,109,97,108,105,115,97,116,105,111,110,13,10,9,9,9,9,13,10,9,9,9,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,47,47,32,77,111,100,105,102,105,99,97,116,105,111,110,32,100,101,32,108,39,97,116,116,195,169,110,117,97,116,105,111,110,32,112,111,117,114,32,103,195,169,114,101,114,32,108,101,32,115,112,111,116,13,10,9,9,9,9,102,108,111,97,116,32,99,117,114,65,110,103,108,101,32,61,32,100,111,116,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,120,121,122,44,32,45,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,102,108,111,97,116,32,111,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,51,46,121,59,13,10,9,9,9,9,102,108,111,97,116,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,51,46,120,32,45,32,111,117,116,101,114,65,110,103,108,101,59,13,10,9,9,9,9,97,116,116,32,42,61,32,109,97,120,40,40,99,117,114,65,110,103,108,101,32,45,32,111,117,116,101,114,65,110,103,108,101,41,32,47,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,9,9,9,125,13,10,9,9,125,13,10,9,125,13,10,13,10,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,42,61,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,46,114,103,98,59,13,10,9,35,105,102,32,83,80,69,67,85,76,65,82,95,77,65,80,80,73,78,71,13,10,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,103,98,59,32,47,47,32,85,116,105,108,105,115,101,114,32,108,39,97,108,112,104,97,32,100,101,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,32,110,39,97,117,114,97,105,116,32,97,117,99,117,110,32,115,101,110,115,13,10,9,35,101,110,100,105,102,13,10,9,9,13,10,9,118,101,99,51,32,108,105,103,104,116,67,111,108,111,114,32,61,32,40,108,105,103,104,116,65,109,98,105,101,110,116,32,43,32,108,105,103,104,116,68,105,102,102,117,115,101,32,43,32,108,105,103,104,116,83,112,101,99,117,108,97,114,41,59,13,10,9,118,101,99,52,32,102,114,97,103,109,101,110,116,67,111,108,111,114,32,61,32,118,101,99,52,40,108,105,103,104,116,67,111,108,111,114,44,32,49,46,48,41,32,42,32,100,105,102,102,117,115,101,67,111,108,111,114,59,13,10,13,10,9,35,105,102,32,69,77,73,83,83,73,86,69,95,77,65,80,80,73,78,71,13,10,9,102,108,111,97,116,32,108,105,103,104,116,73,110,116,101,110,115,105,116,121,32,61,32,100,111,116,40,108,105,103,104,116,67,111,108,111,114,44,32,118,101,99,51,40,48,46,51,44,32,48,46,53,57,44,32,48,46,49,49,41,41,59,13,10,13,10,9,118,101,99,51,32,101,109,105,115,115,105,111,110,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,46,114,103,98,32,42,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,69,109,105,115,115,105,118,101,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,103,98,59,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,118,101,99,52,40,109,105,120,40,102,114,97,103,109,101,110,116,67,111,108,111,114,46,114,103,98,44,32,101,109,105,115,115,105,111,110,67,111,108,111,114,44,32,99,108,97,109,112,40,49,46,48,32,45,32,51,46,48,42,108,105,103,104,116,73,110,116,101,110,115,105,116,121,44,32,48,46,48,44,32,49,46,48,41,41,44,32,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,41,59,13,10,9,35,101,108,115,101,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,102,114,97,103,109,101,110,116,67,111,108,111,114,59,13,10,9,35,101,110,100,105,102,32,47,47,32,69,77,73,83,83,73,86,69,95,77,65,80,80,73,78,71,13,10,35,101,108,115,101,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,100,105,102,102,117,115,101,67,111,108,111,114,59,13,10,35,101,110,100,105,102,32,47,47,32,76,73,71,72,84,73,78,71,13,10,125,13,10, \ No newline at end of file diff --git a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/compatibility.vert b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/compatibility.vert index 37fafc556..e42e972f7 100644 --- a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/compatibility.vert +++ b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/compatibility.vert @@ -1,5 +1,12 @@ /********************Entrant********************/ +#if FLAG_BILLBOARD +varying vec3 InstanceData0; // center +varying vec4 InstanceData1; // size | sin cos +varying vec4 InstanceData2; // color +#else varying mat4 InstanceData0; +#endif + varying vec3 VertexPosition; varying vec3 VertexNormal; varying vec3 VertexTangent; @@ -10,6 +17,7 @@ varying mat3 vLightToWorld; varying vec3 vNormal; varying vec2 vTexCoord; varying vec3 vWorldPos; +varying vec4 vColor; /********************Uniformes********************/ uniform float VertexDepth; @@ -20,28 +28,76 @@ uniform mat4 WorldViewProjMatrix; /********************Fonctions********************/ void main() { -#if FLAG_INSTANCING - #if TRANSFORM - gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0); +#if FLAG_VERTEXCOLOR + vec4 color = VertexColor; +#else + vec4 color = vec4(1.0); +#endif + vec2 texCoords; + +#if FLAG_BILLBOARD + #if FLAG_INSTANCING + vec3 billboardCenter = InstanceData0; + vec2 billboardSize = InstanceData1.xy; + vec2 billboardSinCos = InstanceData1.zw; + vec4 billboardColor = InstanceData2; + + vec2 rotatedPosition; + rotatedPosition.x = VertexPosition.x*billboardSinCos.y - VertexPosition.y*billboardSinCos.x; + rotatedPosition.y = VertexPosition.y*billboardSinCos.y + VertexPosition.x*billboardSinCos.x; + rotatedPosition *= billboardSize; + + vec3 cameraRight = vec3(ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]); + vec3 cameraUp = vec3(ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]); + vec3 vertexPos = billboardCenter + cameraRight*rotatedPosition.x + cameraUp*rotatedPosition.y; + + gl_Position = ViewProjMatrix * vec4(vertexPos, 1.0); + color = billboardColor; + texCoords = VertexPosition.xy + vec2(0.5, 0.5); #else - #if UNIFORM_VERTEX_DEPTH - gl_Position = InstanceData0 * vec4(VertexPosition.xy, VertexDepth, 1.0); - #else - gl_Position = InstanceData0 * vec4(VertexPosition, 1.0); - #endif + vec2 billboardCorner = VertexTexCoord - vec2(0.5, 0.5); + vec2 billboardSize = VertexUserdata0.xy; + vec2 billboardSinCos = VertexUserdata0.zw; + + vec2 rotatedPosition; + rotatedPosition.x = billboardCorner.x*billboardSinCos.y - billboardCorner.y*billboardSinCos.x; + rotatedPosition.y = billboardCorner.y*billboardSinCos.y + billboardCorner.x*billboardSinCos.x; + rotatedPosition *= billboardSize; + + vec3 cameraRight = vec3(ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]); + vec3 cameraUp = vec3(ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]); + vec3 vertexPos = VertexPosition + cameraRight*rotatedPosition.x + cameraUp*rotatedPosition.y; + + gl_Position = ViewProjMatrix * vec4(vertexPos, 1.0); + texCoords = VertexTexCoord; #endif #else - #if TRANSFORM - gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0); - #else - #if UNIFORM_VERTEX_DEPTH - gl_Position = vec4(VertexPosition.xy, VertexDepth, 1.0); + #if FLAG_INSTANCING + #if TRANSFORM + gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0); #else - gl_Position = vec4(VertexPosition, 1.0); + #if UNIFORM_VERTEX_DEPTH + gl_Position = InstanceData0 * vec4(VertexPosition.xy, VertexDepth, 1.0); + #else + gl_Position = InstanceData0 * vec4(VertexPosition, 1.0); + #endif + #endif + #else + #if TRANSFORM + gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0); + #else + #if UNIFORM_VERTEX_DEPTH + gl_Position = vec4(VertexPosition.xy, VertexDepth, 1.0); + #else + gl_Position = vec4(VertexPosition, 1.0); + #endif #endif #endif + + texCoords = VertexTexCoord; #endif + vColor = color; #if LIGHTING #if FLAG_INSTANCING @@ -61,11 +117,7 @@ void main() #endif #if TEXTURE_MAPPING -/* #if FLAG_FLIP_UVS - vTexCoord = vec2(VertexTexCoord.x, 1.0 - VertexTexCoord.y); - #else*/ - vTexCoord = VertexTexCoord; - #endif + vTexCoord = vec2(texCoords); #endif #if LIGHTING && PARALLAX_MAPPING diff --git a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/compatibility.vert.h b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/compatibility.vert.h index 8437da5c7..29df285c8 100644 --- a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/compatibility.vert.h +++ b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/compatibility.vert.h @@ -1 +1 @@ -47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,97,114,121,105,110,103,32,109,97,116,52,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,59,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,86,101,114,116,101,120,78,111,114,109,97,108,59,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,86,101,114,116,101,120,84,97,110,103,101,110,116,59,13,10,118,97,114,121,105,110,103,32,118,101,99,50,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,83,111,114,116,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,97,114,121,105,110,103,32,109,97,116,51,32,118,76,105,103,104,116,84,111,87,111,114,108,100,59,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,118,78,111,114,109,97,108,59,13,10,118,97,114,121,105,110,103,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,118,87,111,114,108,100,80,111,115,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,86,101,114,116,101,120,68,101,112,116,104,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,87,111,114,108,100,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,35,101,108,115,101,13,10,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,110,100,105,102,13,10,35,101,108,115,101,13,10,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,35,101,108,115,101,13,10,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,110,100,105,102,13,10,35,101,110,100,105,102,13,10,13,10,13,10,35,105,102,32,76,73,71,72,84,73,78,71,13,10,9,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,109,97,116,51,32,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,61,32,109,97,116,51,40,73,110,115,116,97,110,99,101,68,97,116,97,48,91,48,93,46,120,121,122,44,32,73,110,115,116,97,110,99,101,68,97,116,97,48,91,49,93,46,120,121,122,44,32,73,110,115,116,97,110,99,101,68,97,116,97,48,91,50,93,46,120,121,122,41,59,13,10,9,35,101,108,115,101,13,10,9,109,97,116,51,32,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,61,32,109,97,116,51,40,87,111,114,108,100,77,97,116,114,105,120,91,48,93,46,120,121,122,44,32,87,111,114,108,100,77,97,116,114,105,120,91,49,93,46,120,121,122,44,32,87,111,114,108,100,77,97,116,114,105,120,91,50,93,46,120,121,122,41,59,13,10,9,35,101,110,100,105,102,13,10,9,13,10,9,35,105,102,32,78,79,82,77,65,76,95,77,65,80,80,73,78,71,13,10,9,118,101,99,51,32,98,105,110,111,114,109,97,108,32,61,32,99,114,111,115,115,40,86,101,114,116,101,120,78,111,114,109,97,108,44,32,86,101,114,116,101,120,84,97,110,103,101,110,116,41,59,13,10,9,118,76,105,103,104,116,84,111,87,111,114,108,100,91,48,93,32,61,32,110,111,114,109,97,108,105,122,101,40,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,42,32,86,101,114,116,101,120,84,97,110,103,101,110,116,41,59,13,10,9,118,76,105,103,104,116,84,111,87,111,114,108,100,91,49,93,32,61,32,110,111,114,109,97,108,105,122,101,40,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,42,32,98,105,110,111,114,109,97,108,41,59,13,10,9,118,76,105,103,104,116,84,111,87,111,114,108,100,91,50,93,32,61,32,110,111,114,109,97,108,105,122,101,40,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,42,32,86,101,114,116,101,120,78,111,114,109,97,108,41,59,13,10,9,35,101,108,115,101,13,10,9,118,78,111,114,109,97,108,32,61,32,110,111,114,109,97,108,105,122,101,40,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,42,32,86,101,114,116,101,120,78,111,114,109,97,108,41,59,13,10,9,35,101,110,100,105,102,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,84,69,88,84,85,82,69,95,77,65,80,80,73,78,71,13,10,47,42,9,35,105,102,32,70,76,65,71,95,70,76,73,80,95,85,86,83,13,10,9,118,84,101,120,67,111,111,114,100,32,61,32,118,101,99,50,40,86,101,114,116,101,120,84,101,120,67,111,111,114,100,46,120,44,32,49,46,48,32,45,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,46,121,41,59,13,10,9,35,101,108,115,101,42,47,13,10,9,118,84,101,120,67,111,111,114,100,32,61,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,9,35,101,110,100,105,102,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,76,73,71,72,84,73,78,71,32,38,38,32,80,65,82,65,76,76,65,88,95,77,65,80,80,73,78,71,13,10,9,118,86,105,101,119,68,105,114,32,61,32,69,121,101,80,111,115,105,116,105,111,110,32,45,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,59,32,13,10,9,118,86,105,101,119,68,105,114,32,42,61,32,118,76,105,103,104,116,84,111,87,111,114,108,100,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,76,73,71,72,84,73,78,71,32,38,38,32,33,70,76,65,71,95,68,69,70,69,82,82,69,68,13,10,9,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,118,87,111,114,108,100,80,111,115,32,61,32,118,101,99,51,40,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,41,59,13,10,9,35,101,108,115,101,13,10,9,118,87,111,114,108,100,80,111,115,32,61,32,118,101,99,51,40,87,111,114,108,100,77,97,116,114,105,120,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,41,59,13,10,9,35,101,110,100,105,102,13,10,35,101,110,100,105,102,13,10,125,13,10, \ No newline at end of file +47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,35,105,102,32,70,76,65,71,95,66,73,76,76,66,79,65,82,68,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,32,47,47,32,99,101,110,116,101,114,13,10,118,97,114,121,105,110,103,32,118,101,99,52,32,73,110,115,116,97,110,99,101,68,97,116,97,49,59,32,47,47,32,115,105,122,101,32,124,32,115,105,110,32,99,111,115,13,10,118,97,114,121,105,110,103,32,118,101,99,52,32,73,110,115,116,97,110,99,101,68,97,116,97,50,59,32,47,47,32,99,111,108,111,114,13,10,35,101,108,115,101,13,10,118,97,114,121,105,110,103,32,109,97,116,52,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,13,10,35,101,110,100,105,102,13,10,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,59,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,86,101,114,116,101,120,78,111,114,109,97,108,59,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,86,101,114,116,101,120,84,97,110,103,101,110,116,59,13,10,118,97,114,121,105,110,103,32,118,101,99,50,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,83,111,114,116,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,97,114,121,105,110,103,32,109,97,116,51,32,118,76,105,103,104,116,84,111,87,111,114,108,100,59,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,118,78,111,114,109,97,108,59,13,10,118,97,114,121,105,110,103,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,118,97,114,121,105,110,103,32,118,101,99,51,32,118,87,111,114,108,100,80,111,115,59,13,10,118,97,114,121,105,110,103,32,118,101,99,52,32,118,67,111,108,111,114,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,86,101,114,116,101,120,68,101,112,116,104,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,87,111,114,108,100,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,35,105,102,32,70,76,65,71,95,86,69,82,84,69,88,67,79,76,79,82,13,10,9,118,101,99,52,32,99,111,108,111,114,32,61,32,86,101,114,116,101,120,67,111,108,111,114,59,13,10,35,101,108,115,101,13,10,9,118,101,99,52,32,99,111,108,111,114,32,61,32,118,101,99,52,40,49,46,48,41,59,13,10,35,101,110,100,105,102,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,115,59,13,10,13,10,35,105,102,32,70,76,65,71,95,66,73,76,76,66,79,65,82,68,13,10,9,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,118,101,99,51,32,98,105,108,108,98,111,97,114,100,67,101,110,116,101,114,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,83,105,122,101,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,49,46,120,121,59,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,49,46,122,119,59,13,10,9,118,101,99,52,32,98,105,108,108,98,111,97,114,100,67,111,108,111,114,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,50,59,13,10,13,10,9,118,101,99,50,32,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,120,32,61,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,121,32,45,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,121,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,120,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,121,32,61,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,121,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,121,32,43,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,120,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,32,42,61,32,98,105,108,108,98,111,97,114,100,83,105,122,101,59,13,10,13,10,9,118,101,99,51,32,99,97,109,101,114,97,82,105,103,104,116,32,61,32,118,101,99,51,40,86,105,101,119,77,97,116,114,105,120,91,48,93,91,48,93,44,32,86,105,101,119,77,97,116,114,105,120,91,49,93,91,48,93,44,32,86,105,101,119,77,97,116,114,105,120,91,50,93,91,48,93,41,59,13,10,9,118,101,99,51,32,99,97,109,101,114,97,85,112,32,61,32,118,101,99,51,40,86,105,101,119,77,97,116,114,105,120,91,48,93,91,49,93,44,32,86,105,101,119,77,97,116,114,105,120,91,49,93,91,49,93,44,32,86,105,101,119,77,97,116,114,105,120,91,50,93,91,49,93,41,59,13,10,9,118,101,99,51,32,118,101,114,116,101,120,80,111,115,32,61,32,98,105,108,108,98,111,97,114,100,67,101,110,116,101,114,32,43,32,99,97,109,101,114,97,82,105,103,104,116,42,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,120,32,43,32,99,97,109,101,114,97,85,112,42,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,121,59,13,10,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,118,101,114,116,101,120,80,111,115,44,32,49,46,48,41,59,13,10,9,99,111,108,111,114,32,61,32,98,105,108,108,98,111,97,114,100,67,111,108,111,114,59,13,10,9,116,101,120,67,111,111,114,100,115,32,61,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,32,43,32,118,101,99,50,40,48,46,53,44,32,48,46,53,41,59,13,10,9,35,101,108,115,101,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,32,61,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,32,45,32,118,101,99,50,40,48,46,53,44,32,48,46,53,41,59,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,83,105,122,101,32,61,32,86,101,114,116,101,120,85,115,101,114,100,97,116,97,48,46,120,121,59,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,32,61,32,86,101,114,116,101,120,85,115,101,114,100,97,116,97,48,46,122,119,59,13,10,9,13,10,9,118,101,99,50,32,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,120,32,61,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,46,120,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,121,32,45,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,46,121,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,120,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,121,32,61,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,46,121,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,121,32,43,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,46,120,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,120,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,32,42,61,32,98,105,108,108,98,111,97,114,100,83,105,122,101,59,13,10,13,10,9,118,101,99,51,32,99,97,109,101,114,97,82,105,103,104,116,32,61,32,118,101,99,51,40,86,105,101,119,77,97,116,114,105,120,91,48,93,91,48,93,44,32,86,105,101,119,77,97,116,114,105,120,91,49,93,91,48,93,44,32,86,105,101,119,77,97,116,114,105,120,91,50,93,91,48,93,41,59,13,10,9,118,101,99,51,32,99,97,109,101,114,97,85,112,32,61,32,118,101,99,51,40,86,105,101,119,77,97,116,114,105,120,91,48,93,91,49,93,44,32,86,105,101,119,77,97,116,114,105,120,91,49,93,91,49,93,44,32,86,105,101,119,77,97,116,114,105,120,91,50,93,91,49,93,41,59,13,10,9,118,101,99,51,32,118,101,114,116,101,120,80,111,115,32,61,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,32,43,32,99,97,109,101,114,97,82,105,103,104,116,42,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,120,32,43,32,99,97,109,101,114,97,85,112,42,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,121,59,13,10,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,118,101,114,116,101,120,80,111,115,44,32,49,46,48,41,59,13,10,9,116,101,120,67,111,111,114,100,115,32,61,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,9,35,101,110,100,105,102,13,10,35,101,108,115,101,13,10,9,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,9,35,101,108,115,101,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,9,35,101,110,100,105,102,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,108,115,101,13,10,9,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,9,35,101,108,115,101,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,9,35,101,110,100,105,102,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,110,100,105,102,13,10,9,13,10,9,116,101,120,67,111,111,114,100,115,32,61,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,9,118,67,111,108,111,114,32,61,32,99,111,108,111,114,59,13,10,13,10,35,105,102,32,76,73,71,72,84,73,78,71,13,10,9,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,109,97,116,51,32,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,61,32,109,97,116,51,40,73,110,115,116,97,110,99,101,68,97,116,97,48,91,48,93,46,120,121,122,44,32,73,110,115,116,97,110,99,101,68,97,116,97,48,91,49,93,46,120,121,122,44,32,73,110,115,116,97,110,99,101,68,97,116,97,48,91,50,93,46,120,121,122,41,59,13,10,9,35,101,108,115,101,13,10,9,109,97,116,51,32,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,61,32,109,97,116,51,40,87,111,114,108,100,77,97,116,114,105,120,91,48,93,46,120,121,122,44,32,87,111,114,108,100,77,97,116,114,105,120,91,49,93,46,120,121,122,44,32,87,111,114,108,100,77,97,116,114,105,120,91,50,93,46,120,121,122,41,59,13,10,9,35,101,110,100,105,102,13,10,9,13,10,9,35,105,102,32,78,79,82,77,65,76,95,77,65,80,80,73,78,71,13,10,9,118,101,99,51,32,98,105,110,111,114,109,97,108,32,61,32,99,114,111,115,115,40,86,101,114,116,101,120,78,111,114,109,97,108,44,32,86,101,114,116,101,120,84,97,110,103,101,110,116,41,59,13,10,9,118,76,105,103,104,116,84,111,87,111,114,108,100,91,48,93,32,61,32,110,111,114,109,97,108,105,122,101,40,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,42,32,86,101,114,116,101,120,84,97,110,103,101,110,116,41,59,13,10,9,118,76,105,103,104,116,84,111,87,111,114,108,100,91,49,93,32,61,32,110,111,114,109,97,108,105,122,101,40,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,42,32,98,105,110,111,114,109,97,108,41,59,13,10,9,118,76,105,103,104,116,84,111,87,111,114,108,100,91,50,93,32,61,32,110,111,114,109,97,108,105,122,101,40,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,42,32,86,101,114,116,101,120,78,111,114,109,97,108,41,59,13,10,9,35,101,108,115,101,13,10,9,118,78,111,114,109,97,108,32,61,32,110,111,114,109,97,108,105,122,101,40,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,42,32,86,101,114,116,101,120,78,111,114,109,97,108,41,59,13,10,9,35,101,110,100,105,102,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,84,69,88,84,85,82,69,95,77,65,80,80,73,78,71,13,10,9,118,84,101,120,67,111,111,114,100,32,61,32,118,101,99,50,40,116,101,120,67,111,111,114,100,115,41,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,76,73,71,72,84,73,78,71,32,38,38,32,80,65,82,65,76,76,65,88,95,77,65,80,80,73,78,71,13,10,9,118,86,105,101,119,68,105,114,32,61,32,69,121,101,80,111,115,105,116,105,111,110,32,45,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,59,32,13,10,9,118,86,105,101,119,68,105,114,32,42,61,32,118,76,105,103,104,116,84,111,87,111,114,108,100,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,76,73,71,72,84,73,78,71,32,38,38,32,33,70,76,65,71,95,68,69,70,69,82,82,69,68,13,10,9,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,118,87,111,114,108,100,80,111,115,32,61,32,118,101,99,51,40,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,41,59,13,10,9,35,101,108,115,101,13,10,9,118,87,111,114,108,100,80,111,115,32,61,32,118,101,99,51,40,87,111,114,108,100,77,97,116,114,105,120,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,41,59,13,10,9,35,101,110,100,105,102,13,10,35,101,110,100,105,102,13,10,125,13,10, \ No newline at end of file diff --git a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag index 055b5472e..80ad84697 100644 --- a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag +++ b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag @@ -7,6 +7,7 @@ layout(early_fragment_tests) in; #define LIGHT_SPOT 2 /********************Entrant********************/ +in vec4 vColor; in mat3 vLightToWorld; in vec3 vNormal; in vec2 vTexCoord; @@ -30,9 +31,10 @@ struct Light vec2 parameters3; }; -uniform vec3 EyePosition; +// Lumières uniform Light Lights[3]; +// Matériau uniform sampler2D MaterialAlphaMap; uniform float MaterialAlphaThreshold; uniform vec4 MaterialAmbient; @@ -45,10 +47,15 @@ uniform float MaterialShininess; uniform vec4 MaterialSpecular; uniform sampler2D MaterialSpecularMap; +// Autres uniform float ParallaxBias = -0.03; uniform float ParallaxScale = 0.02; +uniform vec2 InvTargetSize; +uniform vec3 EyePosition; uniform vec4 SceneAmbient; +uniform sampler2D TextureOverlay; + /********************Fonctions********************/ vec3 FloatToColor(float f) { @@ -76,8 +83,14 @@ vec4 EncodeNormal(in vec3 normal) void main() { - vec4 diffuseColor = MaterialDiffuse; + vec4 diffuseColor = MaterialDiffuse * vColor; + +#if AUTO_TEXCOORDS + vec2 texCoord = gl_FragCoord.xy * InvTargetSize; +#else vec2 texCoord = vTexCoord; +#endif + #if LIGHTING && PARALLAX_MAPPING float height = texture(MaterialHeightMap, texCoord).r; float v = height*ParallaxScale + ParallaxBias; @@ -90,9 +103,14 @@ void main() diffuseColor *= texture(MaterialDiffuseMap, texCoord); #endif +#if FLAG_TEXTUREOVERLAY + diffuseColor *= texture(TextureOverlay, texCoord); +#endif + #if FLAG_DEFERRED #if ALPHA_TEST - #if ALPHA_MAPPING // Inutile de faire de l'alpha-mapping sans alpha-test en Deferred (l'alpha n'est pas sauvegardé) + // Inutile de faire de l'alpha-mapping sans alpha-test en Deferred (l'alpha n'est pas sauvegardé dans le G-Buffer) + #if ALPHA_MAPPING diffuseColor.a *= texture(MaterialAlphaMap, texCoord).r; #endif diff --git a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag.h b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag.h index 54e4bb415..29895eefa 100644 --- a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag.h +++ b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag.h @@ -1 +1 @@ -35,105,102,32,69,65,82,76,89,95,70,82,65,71,77,69,78,84,95,84,69,83,84,83,32,38,38,32,33,65,76,80,72,65,95,84,69,83,84,13,10,108,97,121,111,117,116,40,101,97,114,108,121,95,102,114,97,103,109,101,110,116,95,116,101,115,116,115,41,32,105,110,59,13,10,35,101,110,100,105,102,13,10,13,10,35,100,101,102,105,110,101,32,76,73,71,72,84,95,68,73,82,69,67,84,73,79,78,65,76,32,48,13,10,35,100,101,102,105,110,101,32,76,73,71,72,84,95,80,79,73,78,84,32,49,13,10,35,100,101,102,105,110,101,32,76,73,71,72,84,95,83,80,79,84,32,50,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,105,110,32,109,97,116,51,32,118,76,105,103,104,116,84,111,87,111,114,108,100,59,13,10,105,110,32,118,101,99,51,32,118,78,111,114,109,97,108,59,13,10,105,110,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,105,110,32,118,101,99,51,32,118,86,105,101,119,68,105,114,59,13,10,105,110,32,118,101,99,51,32,118,87,111,114,108,100,80,111,115,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,83,111,114,116,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,111,117,116,32,118,101,99,52,32,82,101,110,100,101,114,84,97,114,103,101,116,48,59,13,10,111,117,116,32,118,101,99,52,32,82,101,110,100,101,114,84,97,114,103,101,116,49,59,13,10,111,117,116,32,118,101,99,52,32,82,101,110,100,101,114,84,97,114,103,101,116,50,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,115,116,114,117,99,116,32,76,105,103,104,116,13,10,123,13,10,9,105,110,116,32,116,121,112,101,59,13,10,9,118,101,99,52,32,99,111,108,111,114,59,13,10,9,118,101,99,50,32,102,97,99,116,111,114,115,59,13,10,13,10,9,118,101,99,52,32,112,97,114,97,109,101,116,101,114,115,49,59,13,10,9,118,101,99,52,32,112,97,114,97,109,101,116,101,114,115,50,59,13,10,9,118,101,99,50,32,112,97,114,97,109,101,116,101,114,115,51,59,13,10,125,59,13,10,13,10,117,110,105,102,111,114,109,32,118,101,99,51,32,69,121,101,80,111,115,105,116,105,111,110,59,13,10,117,110,105,102,111,114,109,32,76,105,103,104,116,32,76,105,103,104,116,115,91,51,93,59,13,10,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,69,109,105,115,115,105,118,101,77,97,112,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,72,101,105,103,104,116,77,97,112,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,78,111,114,109,97,108,77,97,112,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,77,97,112,59,13,10,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,80,97,114,97,108,108,97,120,66,105,97,115,32,61,32,45,48,46,48,51,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,80,97,114,97,108,108,97,120,83,99,97,108,101,32,61,32,48,46,48,50,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,83,99,101,110,101,65,109,98,105,101,110,116,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,101,99,51,32,70,108,111,97,116,84,111,67,111,108,111,114,40,102,108,111,97,116,32,102,41,13,10,123,13,10,9,118,101,99,51,32,99,111,108,111,114,59,13,10,13,10,9,102,32,42,61,32,50,53,54,46,48,59,13,10,9,99,111,108,111,114,46,120,32,61,32,102,108,111,111,114,40,102,41,59,13,10,13,10,9,102,32,61,32,40,102,32,45,32,99,111,108,111,114,46,120,41,32,42,32,50,53,54,46,48,59,13,10,9,99,111,108,111,114,46,121,32,61,32,102,108,111,111,114,40,102,41,59,13,10,13,10,9,99,111,108,111,114,46,122,32,61,32,102,32,45,32,99,111,108,111,114,46,121,59,13,10,9,99,111,108,111,114,46,120,121,32,42,61,32,48,46,48,48,51,57,48,54,50,53,59,32,47,47,32,42,61,32,49,46,48,47,50,53,54,13,10,13,10,9,114,101,116,117,114,110,32,99,111,108,111,114,59,13,10,125,13,10,13,10,35,100,101,102,105,110,101,32,107,80,73,32,51,46,49,52,49,53,57,50,54,53,51,54,13,10,13,10,118,101,99,52,32,69,110,99,111,100,101,78,111,114,109,97,108,40,105,110,32,118,101,99,51,32,110,111,114,109,97,108,41,13,10,123,13,10,9,47,47,114,101,116,117,114,110,32,118,101,99,52,40,110,111,114,109,97,108,42,48,46,53,32,43,32,48,46,53,44,32,48,46,48,41,59,13,10,9,114,101,116,117,114,110,32,118,101,99,52,40,118,101,99,50,40,97,116,97,110,40,110,111,114,109,97,108,46,121,44,32,110,111,114,109,97,108,46,120,41,47,107,80,73,44,32,110,111,114,109,97,108,46,122,41,44,32,48,46,48,44,32,48,46,48,41,59,13,10,125,13,10,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,118,101,99,52,32,100,105,102,102,117,115,101,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,118,84,101,120,67,111,111,114,100,59,13,10,35,105,102,32,76,73,71,72,84,73,78,71,32,38,38,32,80,65,82,65,76,76,65,88,95,77,65,80,80,73,78,71,13,10,9,102,108,111,97,116,32,104,101,105,103,104,116,32,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,72,101,105,103,104,116,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,59,13,10,9,102,108,111,97,116,32,118,32,61,32,104,101,105,103,104,116,42,80,97,114,97,108,108,97,120,83,99,97,108,101,32,43,32,80,97,114,97,108,108,97,120,66,105,97,115,59,13,10,13,10,9,118,101,99,51,32,118,105,101,119,68,105,114,32,61,32,110,111,114,109,97,108,105,122,101,40,118,86,105,101,119,68,105,114,41,59,13,10,9,116,101,120,67,111,111,114,100,32,43,61,32,118,32,42,32,118,105,101,119,68,105,114,46,120,121,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,68,73,70,70,85,83,69,95,77,65,80,80,73,78,71,13,10,9,100,105,102,102,117,115,101,67,111,108,111,114,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,44,32,116,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,70,76,65,71,95,68,69,70,69,82,82,69,68,13,10,9,35,105,102,32,65,76,80,72,65,95,84,69,83,84,13,10,9,9,35,105,102,32,65,76,80,72,65,95,77,65,80,80,73,78,71,32,47,47,32,73,110,117,116,105,108,101,32,100,101,32,102,97,105,114,101,32,100,101,32,108,39,97,108,112,104,97,45,109,97,112,112,105,110,103,32,115,97,110,115,32,97,108,112,104,97,45,116,101,115,116,32,101,110,32,68,101,102,101,114,114,101,100,32,40,108,39,97,108,112,104,97,32,110,39,101,115,116,32,112,97,115,32,115,97,117,118,101,103,97,114,100,195,169,41,13,10,9,100,105,102,102,117,115,101,67,111,108,111,114,46,97,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,59,13,10,9,9,35,101,110,100,105,102,13,10,9,9,13,10,9,105,102,32,40,100,105,102,102,117,115,101,67,111,108,111,114,46,97,32,60,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,41,13,10,9,9,100,105,115,99,97,114,100,59,13,10,9,35,101,110,100,105,102,32,47,47,32,65,76,80,72,65,95,84,69,83,84,13,10,13,10,9,35,105,102,32,76,73,71,72,84,73,78,71,13,10,9,9,35,105,102,32,78,79,82,77,65,76,95,77,65,80,80,73,78,71,13,10,9,118,101,99,51,32,110,111,114,109,97,108,32,61,32,110,111,114,109,97,108,105,122,101,40,118,76,105,103,104,116,84,111,87,111,114,108,100,32,42,32,40,50,46,48,32,42,32,118,101,99,51,40,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,78,111,114,109,97,108,77,97,112,44,32,116,101,120,67,111,111,114,100,41,41,32,45,32,49,46,48,41,41,59,13,10,9,9,35,101,108,115,101,13,10,9,118,101,99,51,32,110,111,114,109,97,108,32,61,32,110,111,114,109,97,108,105,122,101,40,118,78,111,114,109,97,108,41,59,13,10,9,9,35,101,110,100,105,102,32,47,47,32,78,79,82,77,65,76,95,77,65,80,80,73,78,71,13,10,13,10,9,118,101,99,51,32,115,112,101,99,117,108,97,114,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,46,114,103,98,59,13,10,9,9,35,105,102,32,83,80,69,67,85,76,65,82,95,77,65,80,80,73,78,71,13,10,9,115,112,101,99,117,108,97,114,67,111,108,111,114,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,103,98,59,13,10,9,9,35,101,110,100,105,102,13,10,13,10,9,47,42,13,10,9,84,101,120,116,117,114,101,48,58,32,68,105,102,102,117,115,101,32,67,111,108,111,114,32,43,32,83,112,101,99,117,108,97,114,13,10,9,84,101,120,116,117,114,101,49,58,32,78,111,114,109,97,108,32,43,32,83,112,101,99,117,108,97,114,13,10,9,84,101,120,116,117,114,101,50,58,32,69,110,99,111,100,101,100,32,100,101,112,116,104,32,43,32,83,104,105,110,105,110,101,115,115,13,10,9,42,47,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,118,101,99,52,40,100,105,102,102,117,115,101,67,111,108,111,114,46,114,103,98,44,32,100,111,116,40,115,112,101,99,117,108,97,114,67,111,108,111,114,44,32,118,101,99,51,40,48,46,51,44,32,48,46,53,57,44,32,48,46,49,49,41,41,41,59,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,49,32,61,32,118,101,99,52,40,69,110,99,111,100,101,78,111,114,109,97,108,40,110,111,114,109,97,108,41,41,59,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,50,32,61,32,118,101,99,52,40,70,108,111,97,116,84,111,67,111,108,111,114,40,103,108,95,70,114,97,103,67,111,111,114,100,46,122,41,44,32,40,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,32,61,61,32,48,46,48,41,32,63,32,48,46,48,32,58,32,109,97,120,40,108,111,103,50,40,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,41,44,32,48,46,49,41,47,49,48,46,53,41,59,32,47,47,32,104,116,116,112,58,47,47,119,119,119,46,103,117,101,114,114,105,108,108,97,45,103,97,109,101,115,46,99,111,109,47,112,117,98,108,105,99,97,116,105,111,110,115,47,100,114,95,107,122,50,95,114,115,120,95,100,101,118,48,55,46,112,100,102,13,10,9,35,101,108,115,101,32,47,47,32,76,73,71,72,84,73,78,71,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,118,101,99,52,40,100,105,102,102,117,115,101,67,111,108,111,114,46,114,103,98,44,32,48,46,48,41,59,13,10,9,35,101,110,100,105,102,13,10,35,101,108,115,101,32,47,47,32,70,76,65,71,95,68,69,70,69,82,82,69,68,13,10,9,35,105,102,32,65,76,80,72,65,95,77,65,80,80,73,78,71,13,10,9,100,105,102,102,117,115,101,67,111,108,111,114,46,97,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,59,13,10,9,35,101,110,100,105,102,13,10,13,10,9,35,105,102,32,65,76,80,72,65,95,84,69,83,84,13,10,9,105,102,32,40,100,105,102,102,117,115,101,67,111,108,111,114,46,97,32,60,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,41,13,10,9,9,100,105,115,99,97,114,100,59,13,10,9,35,101,110,100,105,102,13,10,13,10,9,35,105,102,32,76,73,71,72,84,73,78,71,13,10,9,118,101,99,51,32,108,105,103,104,116,65,109,98,105,101,110,116,32,61,32,118,101,99,51,40,48,46,48,41,59,13,10,9,118,101,99,51,32,108,105,103,104,116,68,105,102,102,117,115,101,32,61,32,118,101,99,51,40,48,46,48,41,59,13,10,9,118,101,99,51,32,108,105,103,104,116,83,112,101,99,117,108,97,114,32,61,32,118,101,99,51,40,48,46,48,41,59,13,10,13,10,9,9,35,105,102,32,78,79,82,77,65,76,95,77,65,80,80,73,78,71,13,10,9,118,101,99,51,32,110,111,114,109,97,108,32,61,32,110,111,114,109,97,108,105,122,101,40,118,76,105,103,104,116,84,111,87,111,114,108,100,32,42,32,40,50,46,48,32,42,32,118,101,99,51,40,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,78,111,114,109,97,108,77,97,112,44,32,116,101,120,67,111,111,114,100,41,41,32,45,32,49,46,48,41,41,59,13,10,9,9,35,101,108,115,101,13,10,9,118,101,99,51,32,110,111,114,109,97,108,32,61,32,110,111,114,109,97,108,105,122,101,40,118,78,111,114,109,97,108,41,59,13,10,9,9,35,101,110,100,105,102,13,10,13,10,9,105,102,32,40,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,32,62,32,48,46,48,41,13,10,9,123,13,10,9,9,118,101,99,51,32,101,121,101,86,101,99,32,61,32,110,111,114,109,97,108,105,122,101,40,69,121,101,80,111,115,105,116,105,111,110,32,45,32,118,87,111,114,108,100,80,111,115,41,59,13,10,13,10,9,9,102,111,114,32,40,105,110,116,32,105,32,61,32,48,59,32,105,32,60,32,51,59,32,43,43,105,41,13,10,9,9,123,13,10,9,9,9,115,119,105,116,99,104,32,40,76,105,103,104,116,115,91,105,93,46,116,121,112,101,41,13,10,9,9,9,123,13,10,9,9,9,9,99,97,115,101,32,76,73,71,72,84,95,68,73,82,69,67,84,73,79,78,65,76,58,13,10,9,9,9,9,123,13,10,9,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,45,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,59,13,10,13,10,9,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,13,10,9,9,9,9,9,47,47,32,83,112,101,99,117,108,97,114,13,10,9,9,9,9,9,118,101,99,51,32,114,101,102,108,101,99,116,105,111,110,32,61,32,114,101,102,108,101,99,116,40,45,108,105,103,104,116,68,105,114,44,32,110,111,114,109,97,108,41,59,13,10,9,9,9,9,9,102,108,111,97,116,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,109,97,120,40,100,111,116,40,114,101,102,108,101,99,116,105,111,110,44,32,101,121,101,86,101,99,41,44,32,48,46,48,41,59,13,10,9,9,9,9,9,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,112,111,119,40,115,112,101,99,117,108,97,114,70,97,99,116,111,114,44,32,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,41,59,13,10,13,10,9,9,9,9,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,43,61,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,59,13,10,9,9,9,9,9,98,114,101,97,107,59,13,10,9,9,9,9,125,13,10,13,10,9,9,9,9,99,97,115,101,32,76,73,71,72,84,95,80,79,73,78,84,58,13,10,9,9,9,9,123,13,10,9,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,118,87,111,114,108,100,80,111,115,59,13,10,9,9,9,9,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,32,47,47,32,78,111,114,109,97,108,105,115,97,116,105,111,110,13,10,9,9,9,9,9,13,10,9,9,9,9,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,9,9,9,9,9,13,10,9,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,13,10,9,9,9,9,9,47,47,32,83,112,101,99,117,108,97,114,13,10,9,9,9,9,9,118,101,99,51,32,114,101,102,108,101,99,116,105,111,110,32,61,32,114,101,102,108,101,99,116,40,45,108,105,103,104,116,68,105,114,44,32,110,111,114,109,97,108,41,59,13,10,9,9,9,9,9,102,108,111,97,116,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,109,97,120,40,100,111,116,40,114,101,102,108,101,99,116,105,111,110,44,32,101,121,101,86,101,99,41,44,32,48,46,48,41,59,13,10,9,9,9,9,9,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,112,111,119,40,115,112,101,99,117,108,97,114,70,97,99,116,111,114,44,32,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,41,59,13,10,13,10,9,9,9,9,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,43,61,32,97,116,116,32,42,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,59,13,10,9,9,9,9,9,98,114,101,97,107,59,13,10,9,9,9,9,125,13,10,13,10,9,9,9,9,99,97,115,101,32,76,73,71,72,84,95,83,80,79,84,58,13,10,9,9,9,9,123,13,10,9,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,118,87,111,114,108,100,80,111,115,59,13,10,9,9,9,9,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,32,47,47,32,78,111,114,109,97,108,105,115,97,116,105,111,110,13,10,9,9,9,9,9,13,10,9,9,9,9,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,9,47,47,32,77,111,100,105,102,105,99,97,116,105,111,110,32,100,101,32,108,39,97,116,116,195,169,110,117,97,116,105,111,110,32,112,111,117,114,32,103,195,169,114,101,114,32,108,101,32,115,112,111,116,13,10,9,9,9,9,9,102,108,111,97,116,32,99,117,114,65,110,103,108,101,32,61,32,100,111,116,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,120,121,122,44,32,45,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,9,102,108,111,97,116,32,111,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,51,46,121,59,13,10,9,9,9,9,9,102,108,111,97,116,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,51,46,120,32,45,32,111,117,116,101,114,65,110,103,108,101,59,13,10,9,9,9,9,9,97,116,116,32,42,61,32,109,97,120,40,40,99,117,114,65,110,103,108,101,32,45,32,111,117,116,101,114,65,110,103,108,101,41,32,47,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,13,10,9,9,9,9,9,47,47,32,83,112,101,99,117,108,97,114,13,10,9,9,9,9,9,118,101,99,51,32,114,101,102,108,101,99,116,105,111,110,32,61,32,114,101,102,108,101,99,116,40,45,108,105,103,104,116,68,105,114,44,32,110,111,114,109,97,108,41,59,13,10,9,9,9,9,9,102,108,111,97,116,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,109,97,120,40,100,111,116,40,114,101,102,108,101,99,116,105,111,110,44,32,101,121,101,86,101,99,41,44,32,48,46,48,41,59,13,10,9,9,9,9,9,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,112,111,119,40,115,112,101,99,117,108,97,114,70,97,99,116,111,114,44,32,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,41,59,13,10,13,10,9,9,9,9,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,43,61,32,97,116,116,32,42,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,59,13,10,9,9,9,9,9,98,114,101,97,107,59,13,10,9,9,9,9,125,13,10,9,9,9,9,13,10,9,9,9,9,100,101,102,97,117,108,116,58,13,10,9,9,9,9,9,98,114,101,97,107,59,13,10,9,9,9,125,13,10,9,9,125,13,10,9,125,13,10,9,101,108,115,101,13,10,9,123,13,10,9,9,102,111,114,32,40,105,110,116,32,105,32,61,32,48,59,32,105,32,60,32,51,59,32,43,43,105,41,13,10,9,9,123,13,10,9,9,9,115,119,105,116,99,104,32,40,76,105,103,104,116,115,91,105,93,46,116,121,112,101,41,13,10,9,9,9,123,13,10,9,9,9,9,99,97,115,101,32,76,73,71,72,84,95,68,73,82,69,67,84,73,79,78,65,76,58,13,10,9,9,9,9,123,13,10,9,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,110,111,114,109,97,108,105,122,101,40,45,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,41,59,13,10,13,10,9,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,9,9,9,9,9,98,114,101,97,107,59,13,10,9,9,9,9,125,13,10,13,10,9,9,9,9,99,97,115,101,32,76,73,71,72,84,95,80,79,73,78,84,58,13,10,9,9,9,9,123,13,10,9,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,118,87,111,114,108,100,80,111,115,59,13,10,9,9,9,9,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,32,47,47,32,78,111,114,109,97,108,105,115,97,116,105,111,110,13,10,9,9,9,9,9,13,10,9,9,9,9,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,9,9,9,9,9,13,10,9,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,9,9,9,9,9,98,114,101,97,107,59,13,10,9,9,9,9,125,13,10,13,10,9,9,9,9,99,97,115,101,32,76,73,71,72,84,95,83,80,79,84,58,13,10,9,9,9,9,123,13,10,9,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,118,87,111,114,108,100,80,111,115,59,13,10,9,9,9,9,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,32,47,47,32,78,111,114,109,97,108,105,115,97,116,105,111,110,13,10,9,9,9,9,9,13,10,9,9,9,9,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,9,47,47,32,77,111,100,105,102,105,99,97,116,105,111,110,32,100,101,32,108,39,97,116,116,195,169,110,117,97,116,105,111,110,32,112,111,117,114,32,103,195,169,114,101,114,32,108,101,32,115,112,111,116,13,10,9,9,9,9,9,102,108,111,97,116,32,99,117,114,65,110,103,108,101,32,61,32,100,111,116,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,120,121,122,44,32,45,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,9,102,108,111,97,116,32,111,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,51,46,121,59,13,10,9,9,9,9,9,102,108,111,97,116,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,51,46,120,32,45,32,111,117,116,101,114,65,110,103,108,101,59,13,10,9,9,9,9,9,97,116,116,32,42,61,32,109,97,120,40,40,99,117,114,65,110,103,108,101,32,45,32,111,117,116,101,114,65,110,103,108,101,41,32,47,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,9,9,9,9,125,13,10,9,9,9,9,13,10,9,9,9,9,100,101,102,97,117,108,116,58,13,10,9,9,9,9,9,98,114,101,97,107,59,13,10,9,9,9,125,13,10,9,9,125,13,10,9,125,13,10,13,10,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,42,61,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,46,114,103,98,59,13,10,9,9,35,105,102,32,83,80,69,67,85,76,65,82,95,77,65,80,80,73,78,71,13,10,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,103,98,59,32,47,47,32,85,116,105,108,105,115,101,114,32,108,39,97,108,112,104,97,32,100,101,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,32,110,39,97,117,114,97,105,116,32,97,117,99,117,110,32,115,101,110,115,13,10,9,9,35,101,110,100,105,102,13,10,9,9,13,10,9,118,101,99,51,32,108,105,103,104,116,67,111,108,111,114,32,61,32,40,108,105,103,104,116,65,109,98,105,101,110,116,32,43,32,108,105,103,104,116,68,105,102,102,117,115,101,32,43,32,108,105,103,104,116,83,112,101,99,117,108,97,114,41,59,13,10,9,118,101,99,52,32,102,114,97,103,109,101,110,116,67,111,108,111,114,32,61,32,118,101,99,52,40,108,105,103,104,116,67,111,108,111,114,44,32,49,46,48,41,32,42,32,100,105,102,102,117,115,101,67,111,108,111,114,59,13,10,13,10,9,9,35,105,102,32,69,77,73,83,83,73,86,69,95,77,65,80,80,73,78,71,13,10,9,102,108,111,97,116,32,108,105,103,104,116,73,110,116,101,110,115,105,116,121,32,61,32,100,111,116,40,108,105,103,104,116,67,111,108,111,114,44,32,118,101,99,51,40,48,46,51,44,32,48,46,53,57,44,32,48,46,49,49,41,41,59,13,10,13,10,9,118,101,99,51,32,101,109,105,115,115,105,111,110,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,46,114,103,98,32,42,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,69,109,105,115,115,105,118,101,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,103,98,59,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,118,101,99,52,40,109,105,120,40,102,114,97,103,109,101,110,116,67,111,108,111,114,46,114,103,98,44,32,101,109,105,115,115,105,111,110,67,111,108,111,114,44,32,99,108,97,109,112,40,49,46,48,32,45,32,51,46,48,42,108,105,103,104,116,73,110,116,101,110,115,105,116,121,44,32,48,46,48,44,32,49,46,48,41,41,44,32,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,41,59,13,10,9,9,35,101,108,115,101,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,102,114,97,103,109,101,110,116,67,111,108,111,114,59,13,10,9,9,35,101,110,100,105,102,32,47,47,32,69,77,73,83,83,73,86,69,95,77,65,80,80,73,78,71,13,10,9,35,101,108,115,101,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,100,105,102,102,117,115,101,67,111,108,111,114,59,13,10,9,35,101,110,100,105,102,32,47,47,32,76,73,71,72,84,73,78,71,13,10,35,101,110,100,105,102,32,47,47,32,70,76,65,71,95,68,69,70,69,82,82,69,68,13,10,125,13,10, \ No newline at end of file +35,105,102,32,69,65,82,76,89,95,70,82,65,71,77,69,78,84,95,84,69,83,84,83,32,38,38,32,33,65,76,80,72,65,95,84,69,83,84,13,10,108,97,121,111,117,116,40,101,97,114,108,121,95,102,114,97,103,109,101,110,116,95,116,101,115,116,115,41,32,105,110,59,13,10,35,101,110,100,105,102,13,10,13,10,35,100,101,102,105,110,101,32,76,73,71,72,84,95,68,73,82,69,67,84,73,79,78,65,76,32,48,13,10,35,100,101,102,105,110,101,32,76,73,71,72,84,95,80,79,73,78,84,32,49,13,10,35,100,101,102,105,110,101,32,76,73,71,72,84,95,83,80,79,84,32,50,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,105,110,32,118,101,99,52,32,118,67,111,108,111,114,59,13,10,105,110,32,109,97,116,51,32,118,76,105,103,104,116,84,111,87,111,114,108,100,59,13,10,105,110,32,118,101,99,51,32,118,78,111,114,109,97,108,59,13,10,105,110,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,105,110,32,118,101,99,51,32,118,86,105,101,119,68,105,114,59,13,10,105,110,32,118,101,99,51,32,118,87,111,114,108,100,80,111,115,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,83,111,114,116,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,111,117,116,32,118,101,99,52,32,82,101,110,100,101,114,84,97,114,103,101,116,48,59,13,10,111,117,116,32,118,101,99,52,32,82,101,110,100,101,114,84,97,114,103,101,116,49,59,13,10,111,117,116,32,118,101,99,52,32,82,101,110,100,101,114,84,97,114,103,101,116,50,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,115,116,114,117,99,116,32,76,105,103,104,116,13,10,123,13,10,9,105,110,116,32,116,121,112,101,59,13,10,9,118,101,99,52,32,99,111,108,111,114,59,13,10,9,118,101,99,50,32,102,97,99,116,111,114,115,59,13,10,13,10,9,118,101,99,52,32,112,97,114,97,109,101,116,101,114,115,49,59,13,10,9,118,101,99,52,32,112,97,114,97,109,101,116,101,114,115,50,59,13,10,9,118,101,99,50,32,112,97,114,97,109,101,116,101,114,115,51,59,13,10,125,59,13,10,13,10,47,47,32,76,117,109,105,195,168,114,101,115,13,10,117,110,105,102,111,114,109,32,76,105,103,104,116,32,76,105,103,104,116,115,91,51,93,59,13,10,13,10,47,47,32,77,97,116,195,169,114,105,97,117,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,69,109,105,115,115,105,118,101,77,97,112,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,72,101,105,103,104,116,77,97,112,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,78,111,114,109,97,108,77,97,112,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,77,97,112,59,13,10,13,10,47,47,32,65,117,116,114,101,115,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,80,97,114,97,108,108,97,120,66,105,97,115,32,61,32,45,48,46,48,51,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,80,97,114,97,108,108,97,120,83,99,97,108,101,32,61,32,48,46,48,50,59,13,10,117,110,105,102,111,114,109,32,118,101,99,50,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,117,110,105,102,111,114,109,32,118,101,99,51,32,69,121,101,80,111,115,105,116,105,111,110,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,83,99,101,110,101,65,109,98,105,101,110,116,59,13,10,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,84,101,120,116,117,114,101,79,118,101,114,108,97,121,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,101,99,51,32,70,108,111,97,116,84,111,67,111,108,111,114,40,102,108,111,97,116,32,102,41,13,10,123,13,10,9,118,101,99,51,32,99,111,108,111,114,59,13,10,13,10,9,102,32,42,61,32,50,53,54,46,48,59,13,10,9,99,111,108,111,114,46,120,32,61,32,102,108,111,111,114,40,102,41,59,13,10,13,10,9,102,32,61,32,40,102,32,45,32,99,111,108,111,114,46,120,41,32,42,32,50,53,54,46,48,59,13,10,9,99,111,108,111,114,46,121,32,61,32,102,108,111,111,114,40,102,41,59,13,10,13,10,9,99,111,108,111,114,46,122,32,61,32,102,32,45,32,99,111,108,111,114,46,121,59,13,10,9,99,111,108,111,114,46,120,121,32,42,61,32,48,46,48,48,51,57,48,54,50,53,59,32,47,47,32,42,61,32,49,46,48,47,50,53,54,13,10,13,10,9,114,101,116,117,114,110,32,99,111,108,111,114,59,13,10,125,13,10,13,10,35,100,101,102,105,110,101,32,107,80,73,32,51,46,49,52,49,53,57,50,54,53,51,54,13,10,13,10,118,101,99,52,32,69,110,99,111,100,101,78,111,114,109,97,108,40,105,110,32,118,101,99,51,32,110,111,114,109,97,108,41,13,10,123,13,10,9,47,47,114,101,116,117,114,110,32,118,101,99,52,40,110,111,114,109,97,108,42,48,46,53,32,43,32,48,46,53,44,32,48,46,48,41,59,13,10,9,114,101,116,117,114,110,32,118,101,99,52,40,118,101,99,50,40,97,116,97,110,40,110,111,114,109,97,108,46,121,44,32,110,111,114,109,97,108,46,120,41,47,107,80,73,44,32,110,111,114,109,97,108,46,122,41,44,32,48,46,48,44,32,48,46,48,41,59,13,10,125,13,10,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,118,101,99,52,32,100,105,102,102,117,115,101,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,32,42,32,118,67,111,108,111,114,59,13,10,13,10,35,105,102,32,65,85,84,79,95,84,69,88,67,79,79,82,68,83,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,103,108,95,70,114,97,103,67,111,111,114,100,46,120,121,32,42,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,35,101,108,115,101,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,118,84,101,120,67,111,111,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,76,73,71,72,84,73,78,71,32,38,38,32,80,65,82,65,76,76,65,88,95,77,65,80,80,73,78,71,13,10,9,102,108,111,97,116,32,104,101,105,103,104,116,32,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,72,101,105,103,104,116,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,59,13,10,9,102,108,111,97,116,32,118,32,61,32,104,101,105,103,104,116,42,80,97,114,97,108,108,97,120,83,99,97,108,101,32,43,32,80,97,114,97,108,108,97,120,66,105,97,115,59,13,10,13,10,9,118,101,99,51,32,118,105,101,119,68,105,114,32,61,32,110,111,114,109,97,108,105,122,101,40,118,86,105,101,119,68,105,114,41,59,13,10,9,116,101,120,67,111,111,114,100,32,43,61,32,118,32,42,32,118,105,101,119,68,105,114,46,120,121,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,68,73,70,70,85,83,69,95,77,65,80,80,73,78,71,13,10,9,100,105,102,102,117,115,101,67,111,108,111,114,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,44,32,116,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,70,76,65,71,95,84,69,88,84,85,82,69,79,86,69,82,76,65,89,13,10,9,100,105,102,102,117,115,101,67,111,108,111,114,32,42,61,32,116,101,120,116,117,114,101,40,84,101,120,116,117,114,101,79,118,101,114,108,97,121,44,32,116,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,70,76,65,71,95,68,69,70,69,82,82,69,68,13,10,9,35,105,102,32,65,76,80,72,65,95,84,69,83,84,13,10,9,9,47,47,32,73,110,117,116,105,108,101,32,100,101,32,102,97,105,114,101,32,100,101,32,108,39,97,108,112,104,97,45,109,97,112,112,105,110,103,32,115,97,110,115,32,97,108,112,104,97,45,116,101,115,116,32,101,110,32,68,101,102,101,114,114,101,100,32,40,108,39,97,108,112,104,97,32,110,39,101,115,116,32,112,97,115,32,115,97,117,118,101,103,97,114,100,195,169,32,100,97,110,115,32,108,101,32,71,45,66,117,102,102,101,114,41,13,10,9,9,35,105,102,32,65,76,80,72,65,95,77,65,80,80,73,78,71,13,10,9,100,105,102,102,117,115,101,67,111,108,111,114,46,97,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,59,13,10,9,9,35,101,110,100,105,102,13,10,9,9,13,10,9,105,102,32,40,100,105,102,102,117,115,101,67,111,108,111,114,46,97,32,60,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,41,13,10,9,9,100,105,115,99,97,114,100,59,13,10,9,35,101,110,100,105,102,32,47,47,32,65,76,80,72,65,95,84,69,83,84,13,10,13,10,9,35,105,102,32,76,73,71,72,84,73,78,71,13,10,9,9,35,105,102,32,78,79,82,77,65,76,95,77,65,80,80,73,78,71,13,10,9,118,101,99,51,32,110,111,114,109,97,108,32,61,32,110,111,114,109,97,108,105,122,101,40,118,76,105,103,104,116,84,111,87,111,114,108,100,32,42,32,40,50,46,48,32,42,32,118,101,99,51,40,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,78,111,114,109,97,108,77,97,112,44,32,116,101,120,67,111,111,114,100,41,41,32,45,32,49,46,48,41,41,59,13,10,9,9,35,101,108,115,101,13,10,9,118,101,99,51,32,110,111,114,109,97,108,32,61,32,110,111,114,109,97,108,105,122,101,40,118,78,111,114,109,97,108,41,59,13,10,9,9,35,101,110,100,105,102,32,47,47,32,78,79,82,77,65,76,95,77,65,80,80,73,78,71,13,10,13,10,9,118,101,99,51,32,115,112,101,99,117,108,97,114,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,46,114,103,98,59,13,10,9,9,35,105,102,32,83,80,69,67,85,76,65,82,95,77,65,80,80,73,78,71,13,10,9,115,112,101,99,117,108,97,114,67,111,108,111,114,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,103,98,59,13,10,9,9,35,101,110,100,105,102,13,10,13,10,9,47,42,13,10,9,84,101,120,116,117,114,101,48,58,32,68,105,102,102,117,115,101,32,67,111,108,111,114,32,43,32,83,112,101,99,117,108,97,114,13,10,9,84,101,120,116,117,114,101,49,58,32,78,111,114,109,97,108,32,43,32,83,112,101,99,117,108,97,114,13,10,9,84,101,120,116,117,114,101,50,58,32,69,110,99,111,100,101,100,32,100,101,112,116,104,32,43,32,83,104,105,110,105,110,101,115,115,13,10,9,42,47,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,118,101,99,52,40,100,105,102,102,117,115,101,67,111,108,111,114,46,114,103,98,44,32,100,111,116,40,115,112,101,99,117,108,97,114,67,111,108,111,114,44,32,118,101,99,51,40,48,46,51,44,32,48,46,53,57,44,32,48,46,49,49,41,41,41,59,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,49,32,61,32,118,101,99,52,40,69,110,99,111,100,101,78,111,114,109,97,108,40,110,111,114,109,97,108,41,41,59,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,50,32,61,32,118,101,99,52,40,70,108,111,97,116,84,111,67,111,108,111,114,40,103,108,95,70,114,97,103,67,111,111,114,100,46,122,41,44,32,40,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,32,61,61,32,48,46,48,41,32,63,32,48,46,48,32,58,32,109,97,120,40,108,111,103,50,40,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,41,44,32,48,46,49,41,47,49,48,46,53,41,59,32,47,47,32,104,116,116,112,58,47,47,119,119,119,46,103,117,101,114,114,105,108,108,97,45,103,97,109,101,115,46,99,111,109,47,112,117,98,108,105,99,97,116,105,111,110,115,47,100,114,95,107,122,50,95,114,115,120,95,100,101,118,48,55,46,112,100,102,13,10,9,35,101,108,115,101,32,47,47,32,76,73,71,72,84,73,78,71,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,118,101,99,52,40,100,105,102,102,117,115,101,67,111,108,111,114,46,114,103,98,44,32,48,46,48,41,59,13,10,9,35,101,110,100,105,102,13,10,35,101,108,115,101,32,47,47,32,70,76,65,71,95,68,69,70,69,82,82,69,68,13,10,9,35,105,102,32,65,76,80,72,65,95,77,65,80,80,73,78,71,13,10,9,100,105,102,102,117,115,101,67,111,108,111,114,46,97,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,59,13,10,9,35,101,110,100,105,102,13,10,13,10,9,35,105,102,32,65,76,80,72,65,95,84,69,83,84,13,10,9,105,102,32,40,100,105,102,102,117,115,101,67,111,108,111,114,46,97,32,60,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,41,13,10,9,9,100,105,115,99,97,114,100,59,13,10,9,35,101,110,100,105,102,13,10,13,10,9,35,105,102,32,76,73,71,72,84,73,78,71,13,10,9,118,101,99,51,32,108,105,103,104,116,65,109,98,105,101,110,116,32,61,32,118,101,99,51,40,48,46,48,41,59,13,10,9,118,101,99,51,32,108,105,103,104,116,68,105,102,102,117,115,101,32,61,32,118,101,99,51,40,48,46,48,41,59,13,10,9,118,101,99,51,32,108,105,103,104,116,83,112,101,99,117,108,97,114,32,61,32,118,101,99,51,40,48,46,48,41,59,13,10,13,10,9,9,35,105,102,32,78,79,82,77,65,76,95,77,65,80,80,73,78,71,13,10,9,118,101,99,51,32,110,111,114,109,97,108,32,61,32,110,111,114,109,97,108,105,122,101,40,118,76,105,103,104,116,84,111,87,111,114,108,100,32,42,32,40,50,46,48,32,42,32,118,101,99,51,40,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,78,111,114,109,97,108,77,97,112,44,32,116,101,120,67,111,111,114,100,41,41,32,45,32,49,46,48,41,41,59,13,10,9,9,35,101,108,115,101,13,10,9,118,101,99,51,32,110,111,114,109,97,108,32,61,32,110,111,114,109,97,108,105,122,101,40,118,78,111,114,109,97,108,41,59,13,10,9,9,35,101,110,100,105,102,13,10,13,10,9,105,102,32,40,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,32,62,32,48,46,48,41,13,10,9,123,13,10,9,9,118,101,99,51,32,101,121,101,86,101,99,32,61,32,110,111,114,109,97,108,105,122,101,40,69,121,101,80,111,115,105,116,105,111,110,32,45,32,118,87,111,114,108,100,80,111,115,41,59,13,10,13,10,9,9,102,111,114,32,40,105,110,116,32,105,32,61,32,48,59,32,105,32,60,32,51,59,32,43,43,105,41,13,10,9,9,123,13,10,9,9,9,115,119,105,116,99,104,32,40,76,105,103,104,116,115,91,105,93,46,116,121,112,101,41,13,10,9,9,9,123,13,10,9,9,9,9,99,97,115,101,32,76,73,71,72,84,95,68,73,82,69,67,84,73,79,78,65,76,58,13,10,9,9,9,9,123,13,10,9,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,45,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,59,13,10,13,10,9,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,13,10,9,9,9,9,9,47,47,32,83,112,101,99,117,108,97,114,13,10,9,9,9,9,9,118,101,99,51,32,114,101,102,108,101,99,116,105,111,110,32,61,32,114,101,102,108,101,99,116,40,45,108,105,103,104,116,68,105,114,44,32,110,111,114,109,97,108,41,59,13,10,9,9,9,9,9,102,108,111,97,116,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,109,97,120,40,100,111,116,40,114,101,102,108,101,99,116,105,111,110,44,32,101,121,101,86,101,99,41,44,32,48,46,48,41,59,13,10,9,9,9,9,9,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,112,111,119,40,115,112,101,99,117,108,97,114,70,97,99,116,111,114,44,32,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,41,59,13,10,13,10,9,9,9,9,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,43,61,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,59,13,10,9,9,9,9,9,98,114,101,97,107,59,13,10,9,9,9,9,125,13,10,13,10,9,9,9,9,99,97,115,101,32,76,73,71,72,84,95,80,79,73,78,84,58,13,10,9,9,9,9,123,13,10,9,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,118,87,111,114,108,100,80,111,115,59,13,10,9,9,9,9,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,32,47,47,32,78,111,114,109,97,108,105,115,97,116,105,111,110,13,10,9,9,9,9,9,13,10,9,9,9,9,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,9,9,9,9,9,13,10,9,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,13,10,9,9,9,9,9,47,47,32,83,112,101,99,117,108,97,114,13,10,9,9,9,9,9,118,101,99,51,32,114,101,102,108,101,99,116,105,111,110,32,61,32,114,101,102,108,101,99,116,40,45,108,105,103,104,116,68,105,114,44,32,110,111,114,109,97,108,41,59,13,10,9,9,9,9,9,102,108,111,97,116,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,109,97,120,40,100,111,116,40,114,101,102,108,101,99,116,105,111,110,44,32,101,121,101,86,101,99,41,44,32,48,46,48,41,59,13,10,9,9,9,9,9,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,112,111,119,40,115,112,101,99,117,108,97,114,70,97,99,116,111,114,44,32,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,41,59,13,10,13,10,9,9,9,9,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,43,61,32,97,116,116,32,42,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,59,13,10,9,9,9,9,9,98,114,101,97,107,59,13,10,9,9,9,9,125,13,10,13,10,9,9,9,9,99,97,115,101,32,76,73,71,72,84,95,83,80,79,84,58,13,10,9,9,9,9,123,13,10,9,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,118,87,111,114,108,100,80,111,115,59,13,10,9,9,9,9,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,32,47,47,32,78,111,114,109,97,108,105,115,97,116,105,111,110,13,10,9,9,9,9,9,13,10,9,9,9,9,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,9,47,47,32,77,111,100,105,102,105,99,97,116,105,111,110,32,100,101,32,108,39,97,116,116,195,169,110,117,97,116,105,111,110,32,112,111,117,114,32,103,195,169,114,101,114,32,108,101,32,115,112,111,116,13,10,9,9,9,9,9,102,108,111,97,116,32,99,117,114,65,110,103,108,101,32,61,32,100,111,116,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,120,121,122,44,32,45,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,9,102,108,111,97,116,32,111,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,51,46,121,59,13,10,9,9,9,9,9,102,108,111,97,116,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,51,46,120,32,45,32,111,117,116,101,114,65,110,103,108,101,59,13,10,9,9,9,9,9,97,116,116,32,42,61,32,109,97,120,40,40,99,117,114,65,110,103,108,101,32,45,32,111,117,116,101,114,65,110,103,108,101,41,32,47,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,13,10,9,9,9,9,9,47,47,32,83,112,101,99,117,108,97,114,13,10,9,9,9,9,9,118,101,99,51,32,114,101,102,108,101,99,116,105,111,110,32,61,32,114,101,102,108,101,99,116,40,45,108,105,103,104,116,68,105,114,44,32,110,111,114,109,97,108,41,59,13,10,9,9,9,9,9,102,108,111,97,116,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,109,97,120,40,100,111,116,40,114,101,102,108,101,99,116,105,111,110,44,32,101,121,101,86,101,99,41,44,32,48,46,48,41,59,13,10,9,9,9,9,9,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,112,111,119,40,115,112,101,99,117,108,97,114,70,97,99,116,111,114,44,32,77,97,116,101,114,105,97,108,83,104,105,110,105,110,101,115,115,41,59,13,10,13,10,9,9,9,9,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,43,61,32,97,116,116,32,42,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,59,13,10,9,9,9,9,9,98,114,101,97,107,59,13,10,9,9,9,9,125,13,10,9,9,9,9,13,10,9,9,9,9,100,101,102,97,117,108,116,58,13,10,9,9,9,9,9,98,114,101,97,107,59,13,10,9,9,9,125,13,10,9,9,125,13,10,9,125,13,10,9,101,108,115,101,13,10,9,123,13,10,9,9,102,111,114,32,40,105,110,116,32,105,32,61,32,48,59,32,105,32,60,32,51,59,32,43,43,105,41,13,10,9,9,123,13,10,9,9,9,115,119,105,116,99,104,32,40,76,105,103,104,116,115,91,105,93,46,116,121,112,101,41,13,10,9,9,9,123,13,10,9,9,9,9,99,97,115,101,32,76,73,71,72,84,95,68,73,82,69,67,84,73,79,78,65,76,58,13,10,9,9,9,9,123,13,10,9,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,110,111,114,109,97,108,105,122,101,40,45,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,41,59,13,10,13,10,9,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,9,9,9,9,9,98,114,101,97,107,59,13,10,9,9,9,9,125,13,10,13,10,9,9,9,9,99,97,115,101,32,76,73,71,72,84,95,80,79,73,78,84,58,13,10,9,9,9,9,123,13,10,9,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,118,87,111,114,108,100,80,111,115,59,13,10,9,9,9,9,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,32,47,47,32,78,111,114,109,97,108,105,115,97,116,105,111,110,13,10,9,9,9,9,9,13,10,9,9,9,9,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,9,9,9,9,9,13,10,9,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,9,9,9,9,9,98,114,101,97,107,59,13,10,9,9,9,9,125,13,10,13,10,9,9,9,9,99,97,115,101,32,76,73,71,72,84,95,83,80,79,84,58,13,10,9,9,9,9,123,13,10,9,9,9,9,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,118,87,111,114,108,100,80,111,115,59,13,10,9,9,9,9,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,32,47,47,32,78,111,114,109,97,108,105,115,97,116,105,111,110,13,10,9,9,9,9,9,13,10,9,9,9,9,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,47,47,32,65,109,98,105,101,110,116,13,10,9,9,9,9,9,108,105,103,104,116,65,109,98,105,101,110,116,32,43,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,77,97,116,101,114,105,97,108,65,109,98,105,101,110,116,46,114,103,98,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,9,9,9,9,47,47,32,77,111,100,105,102,105,99,97,116,105,111,110,32,100,101,32,108,39,97,116,116,195,169,110,117,97,116,105,111,110,32,112,111,117,114,32,103,195,169,114,101,114,32,108,101,32,115,112,111,116,13,10,9,9,9,9,9,102,108,111,97,116,32,99,117,114,65,110,103,108,101,32,61,32,100,111,116,40,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,50,46,120,121,122,44,32,45,108,105,103,104,116,68,105,114,41,59,13,10,9,9,9,9,9,102,108,111,97,116,32,111,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,51,46,121,59,13,10,9,9,9,9,9,102,108,111,97,116,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,105,93,46,112,97,114,97,109,101,116,101,114,115,51,46,120,32,45,32,111,117,116,101,114,65,110,103,108,101,59,13,10,9,9,9,9,9,97,116,116,32,42,61,32,109,97,120,40,40,99,117,114,65,110,103,108,101,32,45,32,111,117,116,101,114,65,110,103,108,101,41,32,47,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,47,47,32,68,105,102,102,117,115,101,13,10,9,9,9,9,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,9,9,9,9,108,105,103,104,116,68,105,102,102,117,115,101,32,43,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,105,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,105,93,46,102,97,99,116,111,114,115,46,121,59,13,10,9,9,9,9,125,13,10,9,9,9,9,13,10,9,9,9,9,100,101,102,97,117,108,116,58,13,10,9,9,9,9,9,98,114,101,97,107,59,13,10,9,9,9,125,13,10,9,9,125,13,10,9,125,13,10,13,10,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,42,61,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,46,114,103,98,59,13,10,9,9,35,105,102,32,83,80,69,67,85,76,65,82,95,77,65,80,80,73,78,71,13,10,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,103,98,59,32,47,47,32,85,116,105,108,105,115,101,114,32,108,39,97,108,112,104,97,32,100,101,32,77,97,116,101,114,105,97,108,83,112,101,99,117,108,97,114,32,110,39,97,117,114,97,105,116,32,97,117,99,117,110,32,115,101,110,115,13,10,9,9,35,101,110,100,105,102,13,10,9,9,13,10,9,118,101,99,51,32,108,105,103,104,116,67,111,108,111,114,32,61,32,40,108,105,103,104,116,65,109,98,105,101,110,116,32,43,32,108,105,103,104,116,68,105,102,102,117,115,101,32,43,32,108,105,103,104,116,83,112,101,99,117,108,97,114,41,59,13,10,9,118,101,99,52,32,102,114,97,103,109,101,110,116,67,111,108,111,114,32,61,32,118,101,99,52,40,108,105,103,104,116,67,111,108,111,114,44,32,49,46,48,41,32,42,32,100,105,102,102,117,115,101,67,111,108,111,114,59,13,10,13,10,9,9,35,105,102,32,69,77,73,83,83,73,86,69,95,77,65,80,80,73,78,71,13,10,9,102,108,111,97,116,32,108,105,103,104,116,73,110,116,101,110,115,105,116,121,32,61,32,100,111,116,40,108,105,103,104,116,67,111,108,111,114,44,32,118,101,99,51,40,48,46,51,44,32,48,46,53,57,44,32,48,46,49,49,41,41,59,13,10,13,10,9,118,101,99,51,32,101,109,105,115,115,105,111,110,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,46,114,103,98,32,42,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,69,109,105,115,115,105,118,101,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,103,98,59,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,118,101,99,52,40,109,105,120,40,102,114,97,103,109,101,110,116,67,111,108,111,114,46,114,103,98,44,32,101,109,105,115,115,105,111,110,67,111,108,111,114,44,32,99,108,97,109,112,40,49,46,48,32,45,32,51,46,48,42,108,105,103,104,116,73,110,116,101,110,115,105,116,121,44,32,48,46,48,44,32,49,46,48,41,41,44,32,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,41,59,13,10,9,9,35,101,108,115,101,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,102,114,97,103,109,101,110,116,67,111,108,111,114,59,13,10,9,9,35,101,110,100,105,102,32,47,47,32,69,77,73,83,83,73,86,69,95,77,65,80,80,73,78,71,13,10,9,35,101,108,115,101,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,100,105,102,102,117,115,101,67,111,108,111,114,59,13,10,9,35,101,110,100,105,102,32,47,47,32,76,73,71,72,84,73,78,71,13,10,35,101,110,100,105,102,32,47,47,32,70,76,65,71,95,68,69,70,69,82,82,69,68,13,10,125,13,10, \ No newline at end of file diff --git a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert index ca9c5c3eb..5c1d95fef 100644 --- a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert +++ b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert @@ -1,11 +1,20 @@ /********************Entrant********************/ +#if FLAG_BILLBOARD +in vec3 InstanceData0; // center +in vec4 InstanceData1; // size | sin cos +in vec4 InstanceData2; // color +#else in mat4 InstanceData0; +#endif + +in vec4 VertexColor; in vec3 VertexPosition; in vec3 VertexNormal; in vec3 VertexTangent; in vec2 VertexTexCoord; /********************Sortant********************/ +out vec4 vColor; out mat3 vLightToWorld; out vec3 vNormal; out vec2 vTexCoord; @@ -22,29 +31,79 @@ uniform mat4 WorldViewProjMatrix; /********************Fonctions********************/ void main() { -#if FLAG_INSTANCING - #if TRANSFORM - gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0); - #else - #if UNIFORM_VERTEX_DEPTH - gl_Position = InstanceData0 * vec4(VertexPosition.xy, VertexDepth, 1.0); - #else - gl_Position = InstanceData0 * vec4(VertexPosition, 1.0); - #endif - #endif +#if FLAG_VERTEXCOLOR + vec4 color = VertexColor; #else - #if TRANSFORM - gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0); - #else - #if UNIFORM_VERTEX_DEPTH - gl_Position = vec4(VertexPosition.xy, VertexDepth, 1.0); - #else - gl_Position = vec4(VertexPosition, 1.0); - #endif - #endif + vec4 color = vec4(1.0); #endif -//#if LIGHTING + vec2 texCoords; + +#if FLAG_BILLBOARD + #if FLAG_INSTANCING + vec3 billboardCenter = InstanceData0; + vec2 billboardSize = InstanceData1.xy; + vec2 billboardSinCos = InstanceData1.zw; + vec4 billboardColor = InstanceData2; + + vec2 rotatedPosition; + rotatedPosition.x = VertexPosition.x*billboardSinCos.y - VertexPosition.y*billboardSinCos.x; + rotatedPosition.y = VertexPosition.y*billboardSinCos.y + VertexPosition.x*billboardSinCos.x; + rotatedPosition *= billboardSize; + + vec3 cameraRight = vec3(ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]); + vec3 cameraUp = vec3(ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]); + vec3 vertexPos = billboardCenter + cameraRight*rotatedPosition.x + cameraUp*rotatedPosition.y; + + gl_Position = ViewProjMatrix * vec4(vertexPos, 1.0); + color = billboardColor; + texCoords = VertexPosition.xy + 0.5; + #else + vec2 billboardCorner = VertexTexCoord - 0.5; + vec2 billboardSize = VertexUserdata0.xy; + vec2 billboardSinCos = VertexUserdata0.zw; + + vec2 rotatedPosition; + rotatedPosition.x = billboardCorner.x*billboardSinCos.y - billboardCorner.y*billboardSinCos.x; + rotatedPosition.y = billboardCorner.y*billboardSinCos.y + billboardCorner.x*billboardSinCos.x; + rotatedPosition *= billboardSize; + + vec3 cameraRight = vec3(ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]); + vec3 cameraUp = vec3(ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]); + vec3 vertexPos = VertexPosition + cameraRight*rotatedPosition.x + cameraUp*rotatedPosition.y; + + gl_Position = ViewProjMatrix * vec4(vertexPos, 1.0); + texCoords = VertexTexCoord; + #endif +#else + #if FLAG_INSTANCING + #if TRANSFORM + gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0); + #else + #if UNIFORM_VERTEX_DEPTH + gl_Position = InstanceData0 * vec4(VertexPosition.xy, VertexDepth, 1.0); + #else + gl_Position = InstanceData0 * vec4(VertexPosition, 1.0); + #endif + #endif + #else + #if TRANSFORM + gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0); + #else + #if UNIFORM_VERTEX_DEPTH + gl_Position = vec4(VertexPosition.xy, VertexDepth, 1.0); + #else + gl_Position = vec4(VertexPosition, 1.0); + #endif + #endif + #endif + + texCoords = VertexTexCoord; +#endif + + vColor = color; + +#if LIGHTING #if FLAG_INSTANCING mat3 rotationMatrix = mat3(InstanceData0); #else @@ -59,14 +118,10 @@ void main() #else vNormal = normalize(rotationMatrix * VertexNormal); #endif -//#endif +#endif #if TEXTURE_MAPPING -/* #if FLAG_FLIP_UVS - vTexCoord = vec2(VertexTexCoord.x, 1.0 - VertexTexCoord.y); - #else*/ vTexCoord = VertexTexCoord; -// #endif #endif #if LIGHTING && PARALLAX_MAPPING diff --git a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert.h b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert.h index dddde34f9..3c23c60a3 100644 --- a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert.h +++ b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert.h @@ -1 +1 @@ -47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,105,110,32,109,97,116,52,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,13,10,105,110,32,118,101,99,51,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,59,13,10,105,110,32,118,101,99,51,32,86,101,114,116,101,120,78,111,114,109,97,108,59,13,10,105,110,32,118,101,99,51,32,86,101,114,116,101,120,84,97,110,103,101,110,116,59,13,10,105,110,32,118,101,99,50,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,83,111,114,116,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,111,117,116,32,109,97,116,51,32,118,76,105,103,104,116,84,111,87,111,114,108,100,59,13,10,111,117,116,32,118,101,99,51,32,118,78,111,114,109,97,108,59,13,10,111,117,116,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,111,117,116,32,118,101,99,51,32,118,86,105,101,119,68,105,114,59,13,10,111,117,116,32,118,101,99,51,32,118,87,111,114,108,100,80,111,115,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,118,101,99,51,32,69,121,101,80,111,115,105,116,105,111,110,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,86,101,114,116,101,120,68,101,112,116,104,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,87,111,114,108,100,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,35,101,108,115,101,13,10,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,110,100,105,102,13,10,35,101,108,115,101,13,10,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,35,101,108,115,101,13,10,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,110,100,105,102,13,10,35,101,110,100,105,102,13,10,13,10,47,47,35,105,102,32,76,73,71,72,84,73,78,71,13,10,9,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,109,97,116,51,32,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,61,32,109,97,116,51,40,73,110,115,116,97,110,99,101,68,97,116,97,48,41,59,13,10,9,35,101,108,115,101,13,10,9,109,97,116,51,32,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,61,32,109,97,116,51,40,87,111,114,108,100,77,97,116,114,105,120,41,59,13,10,9,35,101,110,100,105,102,13,10,9,13,10,9,35,105,102,32,67,79,77,80,85,84,69,95,84,66,78,77,65,84,82,73,88,13,10,9,118,101,99,51,32,98,105,110,111,114,109,97,108,32,61,32,99,114,111,115,115,40,86,101,114,116,101,120,78,111,114,109,97,108,44,32,86,101,114,116,101,120,84,97,110,103,101,110,116,41,59,13,10,9,118,76,105,103,104,116,84,111,87,111,114,108,100,91,48,93,32,61,32,110,111,114,109,97,108,105,122,101,40,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,42,32,86,101,114,116,101,120,84,97,110,103,101,110,116,41,59,13,10,9,118,76,105,103,104,116,84,111,87,111,114,108,100,91,49,93,32,61,32,110,111,114,109,97,108,105,122,101,40,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,42,32,98,105,110,111,114,109,97,108,41,59,13,10,9,118,76,105,103,104,116,84,111,87,111,114,108,100,91,50,93,32,61,32,110,111,114,109,97,108,105,122,101,40,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,42,32,86,101,114,116,101,120,78,111,114,109,97,108,41,59,13,10,9,35,101,108,115,101,13,10,9,118,78,111,114,109,97,108,32,61,32,110,111,114,109,97,108,105,122,101,40,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,42,32,86,101,114,116,101,120,78,111,114,109,97,108,41,59,13,10,9,35,101,110,100,105,102,13,10,47,47,35,101,110,100,105,102,13,10,13,10,35,105,102,32,84,69,88,84,85,82,69,95,77,65,80,80,73,78,71,13,10,47,42,9,35,105,102,32,70,76,65,71,95,70,76,73,80,95,85,86,83,13,10,9,118,84,101,120,67,111,111,114,100,32,61,32,118,101,99,50,40,86,101,114,116,101,120,84,101,120,67,111,111,114,100,46,120,44,32,49,46,48,32,45,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,46,121,41,59,13,10,9,35,101,108,115,101,42,47,13,10,9,118,84,101,120,67,111,111,114,100,32,61,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,47,47,9,35,101,110,100,105,102,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,76,73,71,72,84,73,78,71,32,38,38,32,80,65,82,65,76,76,65,88,95,77,65,80,80,73,78,71,13,10,9,118,86,105,101,119,68,105,114,32,61,32,69,121,101,80,111,115,105,116,105,111,110,32,45,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,59,32,13,10,9,118,86,105,101,119,68,105,114,32,42,61,32,118,76,105,103,104,116,84,111,87,111,114,108,100,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,76,73,71,72,84,73,78,71,32,38,38,32,33,70,76,65,71,95,68,69,70,69,82,82,69,68,13,10,9,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,118,87,111,114,108,100,80,111,115,32,61,32,118,101,99,51,40,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,41,59,13,10,9,35,101,108,115,101,13,10,9,118,87,111,114,108,100,80,111,115,32,61,32,118,101,99,51,40,87,111,114,108,100,77,97,116,114,105,120,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,41,59,13,10,9,35,101,110,100,105,102,13,10,35,101,110,100,105,102,13,10,125,13,10, \ No newline at end of file +47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,35,105,102,32,70,76,65,71,95,66,73,76,76,66,79,65,82,68,13,10,105,110,32,118,101,99,51,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,32,47,47,32,99,101,110,116,101,114,13,10,105,110,32,118,101,99,52,32,73,110,115,116,97,110,99,101,68,97,116,97,49,59,32,47,47,32,115,105,122,101,32,124,32,115,105,110,32,99,111,115,13,10,105,110,32,118,101,99,52,32,73,110,115,116,97,110,99,101,68,97,116,97,50,59,32,47,47,32,99,111,108,111,114,13,10,35,101,108,115,101,13,10,105,110,32,109,97,116,52,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,13,10,35,101,110,100,105,102,13,10,13,10,105,110,32,118,101,99,52,32,86,101,114,116,101,120,67,111,108,111,114,59,13,10,105,110,32,118,101,99,51,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,59,13,10,105,110,32,118,101,99,51,32,86,101,114,116,101,120,78,111,114,109,97,108,59,13,10,105,110,32,118,101,99,51,32,86,101,114,116,101,120,84,97,110,103,101,110,116,59,13,10,105,110,32,118,101,99,50,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,83,111,114,116,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,111,117,116,32,118,101,99,52,32,118,67,111,108,111,114,59,13,10,111,117,116,32,109,97,116,51,32,118,76,105,103,104,116,84,111,87,111,114,108,100,59,13,10,111,117,116,32,118,101,99,51,32,118,78,111,114,109,97,108,59,13,10,111,117,116,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,111,117,116,32,118,101,99,51,32,118,86,105,101,119,68,105,114,59,13,10,111,117,116,32,118,101,99,51,32,118,87,111,114,108,100,80,111,115,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,118,101,99,51,32,69,121,101,80,111,115,105,116,105,111,110,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,86,101,114,116,101,120,68,101,112,116,104,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,87,111,114,108,100,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,35,105,102,32,70,76,65,71,95,86,69,82,84,69,88,67,79,76,79,82,13,10,9,118,101,99,52,32,99,111,108,111,114,32,61,32,86,101,114,116,101,120,67,111,108,111,114,59,13,10,35,101,108,115,101,13,10,9,118,101,99,52,32,99,111,108,111,114,32,61,32,118,101,99,52,40,49,46,48,41,59,13,10,35,101,110,100,105,102,13,10,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,115,59,13,10,13,10,35,105,102,32,70,76,65,71,95,66,73,76,76,66,79,65,82,68,13,10,9,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,118,101,99,51,32,98,105,108,108,98,111,97,114,100,67,101,110,116,101,114,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,83,105,122,101,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,49,46,120,121,59,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,49,46,122,119,59,13,10,9,118,101,99,52,32,98,105,108,108,98,111,97,114,100,67,111,108,111,114,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,50,59,13,10,13,10,9,118,101,99,50,32,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,120,32,61,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,121,32,45,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,121,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,120,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,121,32,61,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,121,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,121,32,43,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,120,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,32,42,61,32,98,105,108,108,98,111,97,114,100,83,105,122,101,59,13,10,13,10,9,118,101,99,51,32,99,97,109,101,114,97,82,105,103,104,116,32,61,32,118,101,99,51,40,86,105,101,119,77,97,116,114,105,120,91,48,93,91,48,93,44,32,86,105,101,119,77,97,116,114,105,120,91,49,93,91,48,93,44,32,86,105,101,119,77,97,116,114,105,120,91,50,93,91,48,93,41,59,13,10,9,118,101,99,51,32,99,97,109,101,114,97,85,112,32,61,32,118,101,99,51,40,86,105,101,119,77,97,116,114,105,120,91,48,93,91,49,93,44,32,86,105,101,119,77,97,116,114,105,120,91,49,93,91,49,93,44,32,86,105,101,119,77,97,116,114,105,120,91,50,93,91,49,93,41,59,13,10,9,118,101,99,51,32,118,101,114,116,101,120,80,111,115,32,61,32,98,105,108,108,98,111,97,114,100,67,101,110,116,101,114,32,43,32,99,97,109,101,114,97,82,105,103,104,116,42,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,120,32,43,32,99,97,109,101,114,97,85,112,42,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,121,59,13,10,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,118,101,114,116,101,120,80,111,115,44,32,49,46,48,41,59,13,10,9,99,111,108,111,114,32,61,32,98,105,108,108,98,111,97,114,100,67,111,108,111,114,59,13,10,9,116,101,120,67,111,111,114,100,115,32,61,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,32,43,32,48,46,53,59,13,10,9,35,101,108,115,101,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,32,61,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,32,45,32,48,46,53,59,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,83,105,122,101,32,61,32,86,101,114,116,101,120,85,115,101,114,100,97,116,97,48,46,120,121,59,13,10,9,118,101,99,50,32,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,32,61,32,86,101,114,116,101,120,85,115,101,114,100,97,116,97,48,46,122,119,59,13,10,9,13,10,9,118,101,99,50,32,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,120,32,61,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,46,120,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,121,32,45,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,46,121,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,120,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,121,32,61,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,46,121,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,121,32,43,32,98,105,108,108,98,111,97,114,100,67,111,114,110,101,114,46,120,42,98,105,108,108,98,111,97,114,100,83,105,110,67,111,115,46,120,59,13,10,9,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,32,42,61,32,98,105,108,108,98,111,97,114,100,83,105,122,101,59,13,10,13,10,9,118,101,99,51,32,99,97,109,101,114,97,82,105,103,104,116,32,61,32,118,101,99,51,40,86,105,101,119,77,97,116,114,105,120,91,48,93,91,48,93,44,32,86,105,101,119,77,97,116,114,105,120,91,49,93,91,48,93,44,32,86,105,101,119,77,97,116,114,105,120,91,50,93,91,48,93,41,59,13,10,9,118,101,99,51,32,99,97,109,101,114,97,85,112,32,61,32,118,101,99,51,40,86,105,101,119,77,97,116,114,105,120,91,48,93,91,49,93,44,32,86,105,101,119,77,97,116,114,105,120,91,49,93,91,49,93,44,32,86,105,101,119,77,97,116,114,105,120,91,50,93,91,49,93,41,59,13,10,9,118,101,99,51,32,118,101,114,116,101,120,80,111,115,32,61,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,32,43,32,99,97,109,101,114,97,82,105,103,104,116,42,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,120,32,43,32,99,97,109,101,114,97,85,112,42,114,111,116,97,116,101,100,80,111,115,105,116,105,111,110,46,121,59,13,10,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,118,101,114,116,101,120,80,111,115,44,32,49,46,48,41,59,13,10,9,116,101,120,67,111,111,114,100,115,32,61,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,9,35,101,110,100,105,102,13,10,35,101,108,115,101,13,10,9,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,9,35,101,108,115,101,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,9,35,101,110,100,105,102,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,108,115,101,13,10,9,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,9,35,101,108,115,101,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,9,35,101,110,100,105,102,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,110,100,105,102,13,10,13,10,9,116,101,120,67,111,111,114,100,115,32,61,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,9,118,67,111,108,111,114,32,61,32,99,111,108,111,114,59,13,10,13,10,35,105,102,32,76,73,71,72,84,73,78,71,13,10,9,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,109,97,116,51,32,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,61,32,109,97,116,51,40,73,110,115,116,97,110,99,101,68,97,116,97,48,41,59,13,10,9,35,101,108,115,101,13,10,9,109,97,116,51,32,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,61,32,109,97,116,51,40,87,111,114,108,100,77,97,116,114,105,120,41,59,13,10,9,35,101,110,100,105,102,13,10,9,13,10,9,35,105,102,32,67,79,77,80,85,84,69,95,84,66,78,77,65,84,82,73,88,13,10,9,118,101,99,51,32,98,105,110,111,114,109,97,108,32,61,32,99,114,111,115,115,40,86,101,114,116,101,120,78,111,114,109,97,108,44,32,86,101,114,116,101,120,84,97,110,103,101,110,116,41,59,13,10,9,118,76,105,103,104,116,84,111,87,111,114,108,100,91,48,93,32,61,32,110,111,114,109,97,108,105,122,101,40,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,42,32,86,101,114,116,101,120,84,97,110,103,101,110,116,41,59,13,10,9,118,76,105,103,104,116,84,111,87,111,114,108,100,91,49,93,32,61,32,110,111,114,109,97,108,105,122,101,40,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,42,32,98,105,110,111,114,109,97,108,41,59,13,10,9,118,76,105,103,104,116,84,111,87,111,114,108,100,91,50,93,32,61,32,110,111,114,109,97,108,105,122,101,40,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,42,32,86,101,114,116,101,120,78,111,114,109,97,108,41,59,13,10,9,35,101,108,115,101,13,10,9,118,78,111,114,109,97,108,32,61,32,110,111,114,109,97,108,105,122,101,40,114,111,116,97,116,105,111,110,77,97,116,114,105,120,32,42,32,86,101,114,116,101,120,78,111,114,109,97,108,41,59,13,10,9,35,101,110,100,105,102,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,84,69,88,84,85,82,69,95,77,65,80,80,73,78,71,13,10,9,118,84,101,120,67,111,111,114,100,32,61,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,76,73,71,72,84,73,78,71,32,38,38,32,80,65,82,65,76,76,65,88,95,77,65,80,80,73,78,71,13,10,9,118,86,105,101,119,68,105,114,32,61,32,69,121,101,80,111,115,105,116,105,111,110,32,45,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,59,32,13,10,9,118,86,105,101,119,68,105,114,32,42,61,32,118,76,105,103,104,116,84,111,87,111,114,108,100,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,76,73,71,72,84,73,78,71,32,38,38,32,33,70,76,65,71,95,68,69,70,69,82,82,69,68,13,10,9,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,118,87,111,114,108,100,80,111,115,32,61,32,118,101,99,51,40,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,41,59,13,10,9,35,101,108,115,101,13,10,9,118,87,111,114,108,100,80,111,115,32,61,32,118,101,99,51,40,87,111,114,108,100,77,97,116,114,105,120,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,41,59,13,10,9,35,101,110,100,105,102,13,10,35,101,110,100,105,102,13,10,125,13,10, \ No newline at end of file diff --git a/src/Nazara/Graphics/Scene.cpp b/src/Nazara/Graphics/Scene.cpp index 2c9f286a8..289ff1b1e 100644 --- a/src/Nazara/Graphics/Scene.cpp +++ b/src/Nazara/Graphics/Scene.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,57 +9,36 @@ #include #include #include -#include #include #include #include -#include -#include -#include #include -struct NzSceneImpl +NzScene::NzScene() : +m_ambientColor(25, 25, 25), +m_root(this), +m_viewer(nullptr), +m_backgroundEnabled(true), +m_update(false), +m_updatePerSecond(60) { - NzSceneImpl(NzScene* scene) : - root(scene) - { - } - - std::unique_ptr background; - std::unique_ptr renderTechnique; - std::vector updateList; - std::vector visibleUpdateList; - NzClock updateClock; - NzColor ambientColor = NzColor(25,25,25); - NzSceneRoot root; - NzAbstractViewer* viewer = nullptr; - bool backgroundEnabled = true; - bool update = false; - float frameTime; - float updateTime; - int renderTechniqueRanking; - unsigned int updatePerSecond = 60; -}; - -NzScene::NzScene() -{ - m_impl = new NzSceneImpl(this); -} - -NzScene::~NzScene() -{ - delete m_impl; } void NzScene::AddToVisibilityList(NzUpdatable* object) { - m_impl->visibleUpdateList.push_back(object); + m_visibleUpdateList.push_back(object); +} + +void NzScene::Clear() +{ + m_nodeMap.clear(); + m_nodes.clear(); } void NzScene::Cull() { #if NAZARA_GRAPHICS_SAFE - if (!m_impl->viewer) + if (!m_viewer) { NazaraError("No viewer"); return; @@ -69,42 +48,40 @@ void NzScene::Cull() NzAbstractRenderQueue* renderQueue = GetRenderTechnique()->GetRenderQueue(); renderQueue->Clear(false); - m_impl->visibleUpdateList.clear(); + m_visibleUpdateList.clear(); // Frustum culling - RecursiveFrustumCull(renderQueue, m_impl->viewer->GetFrustum(), &m_impl->root); + RecursiveFrustumCull(renderQueue, m_viewer->GetFrustum(), &m_root); ///TODO: Occlusion culling - - ///TODO: Light culling } void NzScene::Draw() { #if NAZARA_GRAPHICS_SAFE - if (!m_impl->viewer) + if (!m_viewer) { NazaraError("No viewer"); return; } #endif - m_impl->viewer->ApplyView(); + m_viewer->ApplyView(); try { - NzErrorFlags errFlags(nzErrorFlag_ThrowException); - m_impl->renderTechnique->Clear(this); - m_impl->renderTechnique->Draw(this); + NzErrorFlags errFlags(nzErrorFlag_ThrowException, true); + m_renderTechnique->Clear(this); + m_renderTechnique->Draw(this); } catch (const std::exception& e) { - NzString oldName = m_impl->renderTechnique->GetName(); + NzString oldName = m_renderTechnique->GetName(); - if (m_impl->renderTechniqueRanking > 0) + if (m_renderTechniqueRanking > 0) { - m_impl->renderTechnique.reset(NzRenderTechniques::GetByRanking(m_impl->renderTechniqueRanking-1, &m_impl->renderTechniqueRanking)); - NazaraError("Render technique \"" + oldName + "\" failed, fallback to \"" + m_impl->renderTechnique->GetName() + '"'); + m_renderTechnique.reset(NzRenderTechniques::GetByRanking(m_renderTechniqueRanking-1, &m_renderTechniqueRanking)); + NazaraError("Render technique \"" + oldName + "\" failed, falling back to \"" + m_renderTechnique->GetName() + '"'); } else { @@ -118,53 +95,154 @@ void NzScene::Draw() void NzScene::EnableBackground(bool enable) { - m_impl->backgroundEnabled = enable; + m_backgroundEnabled = enable; +} + +NzSceneNode* NzScene::FindNode(const NzString& name) +{ + auto it = m_nodeMap.find(name); + if (it == m_nodeMap.end()) + return nullptr; + + return it->second; +} + +const NzSceneNode* NzScene::FindNode(const NzString& name) const +{ + auto it = m_nodeMap.find(name); + if (it == m_nodeMap.end()) + return nullptr; + + return it->second; } NzColor NzScene::GetAmbientColor() const { - return m_impl->ambientColor; + return m_ambientColor; } NzAbstractBackground* NzScene::GetBackground() const { - if (!m_impl->background) - m_impl->background.reset(new NzColorBackground); + if (!m_background) + m_background.reset(new NzColorBackground); - return m_impl->background.get(); + return m_background.get(); +} + +NzVector3f NzScene::GetBackward() const +{ + #if NAZARA_GRAPHICS_SAFE + if (!m_viewer) + { + NazaraError("No viewer"); + return NzVector3f::Backward(); + } + #endif + + return -m_viewer->GetGlobalForward(); +} + +NzVector3f NzScene::GetDown() const +{ + #if NAZARA_GRAPHICS_SAFE + if (!m_viewer) + { + NazaraError("No viewer"); + return NzVector3f::Down(); + } + #endif + + return -m_viewer->GetGlobalUp(); +} + +NzVector3f NzScene::GetForward() const +{ + #if NAZARA_GRAPHICS_SAFE + if (!m_viewer) + { + NazaraError("No viewer"); + return NzVector3f::Forward(); + } + #endif + + return m_viewer->GetGlobalForward(); +} + +NzVector3f NzScene::GetLeft() const +{ + #if NAZARA_GRAPHICS_SAFE + if (!m_viewer) + { + NazaraError("No viewer"); + return NzVector3f::Left(); + } + #endif + + return -m_viewer->GetGlobalRight(); } NzAbstractRenderTechnique* NzScene::GetRenderTechnique() const { - if (!m_impl->renderTechnique) - m_impl->renderTechnique.reset(NzRenderTechniques::GetByRanking(-1, &m_impl->renderTechniqueRanking)); + if (!m_renderTechnique) + m_renderTechnique.reset(NzRenderTechniques::GetByRanking(-1, &m_renderTechniqueRanking)); - return m_impl->renderTechnique.get(); + return m_renderTechnique.get(); } -NzSceneNode& NzScene::GetRoot() const +NzVector3f NzScene::GetRight() const { - return m_impl->root; + #if NAZARA_GRAPHICS_SAFE + if (!m_viewer) + { + NazaraError("No viewer"); + return NzVector3f::Right(); + } + #endif + + return m_viewer->GetGlobalRight(); +} + +NzSceneNode& NzScene::GetRoot() +{ + return m_root; +} + +const NzSceneNode& NzScene::GetRoot() const +{ + return m_root; } NzAbstractViewer* NzScene::GetViewer() const { - return m_impl->viewer; + return m_viewer; +} + +NzVector3f NzScene::GetUp() const +{ + #if NAZARA_GRAPHICS_SAFE + if (!m_viewer) + { + NazaraError("No viewer"); + return NzVector3f::Up(); + } + #endif + + return m_viewer->GetGlobalUp(); } float NzScene::GetUpdateTime() const { - return m_impl->updateTime; + return m_updateTime; } unsigned int NzScene::GetUpdatePerSecond() const { - return m_impl->updatePerSecond; + return m_updatePerSecond; } bool NzScene::IsBackgroundEnabled() const { - return m_impl->backgroundEnabled; + return m_backgroundEnabled; } void NzScene::RegisterForUpdate(NzUpdatable* object) @@ -177,27 +255,77 @@ void NzScene::RegisterForUpdate(NzUpdatable* object) } #endif - m_impl->updateList.push_back(object); + m_updateList.push_back(object); +} + +void NzScene::RemoveNode(NzSceneNode* node) +{ + if (!node) + return; + + // C'est moche mais je n'ai pas d'autre choix que d'utiliser un std::unique_ptr pour utiliser std::find + std::unique_ptr ptr(node); + auto it = std::find(m_nodes.begin(), m_nodes.end(), ptr); + ptr.release(); + + if (it == m_nodes.end()) + { + NazaraError("This scene node doesn't belong to this scene"); + return; + } + + NzString nodeName = node->GetName(); + if (!nodeName.IsEmpty()) + m_nodeMap.erase(nodeName); + + m_nodes.erase(it); +} + +void NzScene::RemoveNode(const NzString& name) +{ + RemoveNode(FindNode(name)); +} + +void NzScene::RenderFrame() +{ + try + { + NzErrorFlags errFlags(nzErrorFlag_ThrowException, true); + Update(); + Cull(); + UpdateVisible(); + Draw(); + } + catch (const std::exception& e) + { + NazaraError("Failed to render frame: " + NzString(e.what())); + } } void NzScene::SetAmbientColor(const NzColor& color) { - m_impl->ambientColor = color; + m_ambientColor = color; } void NzScene::SetBackground(NzAbstractBackground* background) { - m_impl->background.reset(background); + m_background.reset(background); } void NzScene::SetRenderTechnique(NzAbstractRenderTechnique* renderTechnique) { - m_impl->renderTechnique.reset(renderTechnique); + m_renderTechnique.reset(renderTechnique); } void NzScene::SetViewer(NzAbstractViewer* viewer) { - m_impl->viewer = viewer; + if (m_viewer != viewer) + { + m_viewer = viewer; + + // Invalidation de tous les nodes de la scène (utile pour la régénération des sommets dépendant du viewer) + m_root.InvalidateNode(); + } } void NzScene::SetViewer(NzAbstractViewer& viewer) @@ -207,7 +335,7 @@ void NzScene::SetViewer(NzAbstractViewer& viewer) void NzScene::SetUpdatePerSecond(unsigned int updatePerSecond) { - m_impl->updatePerSecond = updatePerSecond; + m_updatePerSecond = updatePerSecond; } void NzScene::UnregisterForUpdate(NzUpdatable* object) @@ -220,20 +348,20 @@ void NzScene::UnregisterForUpdate(NzUpdatable* object) } #endif - auto it = std::find(m_impl->updateList.begin(), m_impl->updateList.end(), object); - if (it != m_impl->updateList.end()) - m_impl->updateList.erase(it); + auto it = std::find(m_updateList.begin(), m_updateList.end(), object); + if (it != m_updateList.end()) + m_updateList.erase(it); } void NzScene::Update() { - m_impl->update = (m_impl->updatePerSecond == 0 || m_impl->updateClock.GetMilliseconds() > 1000/m_impl->updatePerSecond); - if (m_impl->update) + m_update = (m_updatePerSecond == 0 || m_updateClock.GetMilliseconds() > 1000/m_updatePerSecond); + if (m_update) { - m_impl->updateTime = m_impl->updateClock.GetSeconds(); - m_impl->updateClock.Restart(); + m_updateTime = m_updateClock.GetSeconds(); + m_updateClock.Restart(); - for (NzUpdatable* updatable : m_impl->updateList) + for (NzUpdatable* updatable : m_updateList) ///TODO: Multihreading updatable->Update(); } @@ -243,16 +371,68 @@ void NzScene::UpdateVisible() { NzSkinningManager::Skin(); - if (m_impl->update) + if (m_update) { - for (NzUpdatable* node : m_impl->visibleUpdateList) + for (NzUpdatable* node : m_visibleUpdateList) node->Update(); } } NzScene::operator const NzSceneNode&() const { - return m_impl->root; + return m_root; +} + +bool NzScene::ChangeNodeName(NzSceneNode* node, const NzString& newName) +{ + #ifdef NAZARA_DEBUG + std::unique_ptr ptr(node); + auto it = std::find(m_nodes.begin(), m_nodes.end(), ptr); + ptr.release(); + + if (it == m_nodes.end()) + { + NazaraInternalError("Node isn't part of the scene"); + return false; + } + #endif + + if (!newName.IsEmpty()) + { + auto pair = m_nodeMap.insert(std::make_pair(newName, node)); + if (!pair.second) + { + NazaraError("Name \"" + newName + "\" is already in use"); + return false; + } + } + + NzString oldName = node->GetName(); + if (!oldName.IsEmpty()) + m_nodeMap.erase(oldName); + + node->SetNameInternal(newName); + return true; +} + +bool NzScene::RegisterSceneNode(const NzString& name, NzSceneNode* node) +{ + if (!name.IsEmpty()) + { + if (m_nodeMap.find(name) != m_nodeMap.end()) + { + NazaraError("Node " + name + " is already registred"); + return false; + } + + m_nodeMap[name] = node; + } + + node->SetNameInternal(name); + node->SetParent(m_root, true); + + m_nodes.emplace_back(node); + return true; } void NzScene::RecursiveFrustumCull(NzAbstractRenderQueue* renderQueue, const NzFrustumf& frustum, NzNode* node) diff --git a/src/Nazara/Graphics/SceneNode.cpp b/src/Nazara/Graphics/SceneNode.cpp index fbd88b866..1c7062e30 100644 --- a/src/Nazara/Graphics/SceneNode.cpp +++ b/src/Nazara/Graphics/SceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -11,6 +11,7 @@ NzSceneNode::NzSceneNode() : m_scene(nullptr), +m_boundingVolumeUpdated(false), m_drawingEnabled(true), m_visible(false) { @@ -19,6 +20,7 @@ m_visible(false) NzSceneNode::NzSceneNode(const NzSceneNode& sceneNode) : NzNode(sceneNode), m_scene(nullptr), +m_boundingVolumeUpdated(false), m_drawingEnabled(sceneNode.m_drawingEnabled), m_visible(false) { @@ -31,16 +33,107 @@ void NzSceneNode::EnableDrawing(bool drawingEnabled) m_drawingEnabled = drawingEnabled; } +NzVector3f NzSceneNode::GetBackward() const +{ + if (m_scene) + { + if (!m_derivedUpdated) + UpdateDerived(); + + return m_derivedRotation * m_scene->GetBackward(); + } + else + return NzNode::GetBackward(); +} + +const NzBoundingVolumef& NzSceneNode::GetBoundingVolume() const +{ + if (!m_boundingVolumeUpdated) + UpdateBoundingVolume(); + + return m_boundingVolume; +} + +NzVector3f NzSceneNode::GetDown() const +{ + if (m_scene) + { + if (!m_derivedUpdated) + UpdateDerived(); + + return m_derivedRotation * m_scene->GetDown(); + } + else + return NzNode::GetDown(); +} + +NzVector3f NzSceneNode::GetForward() const +{ + if (m_scene) + { + if (!m_derivedUpdated) + UpdateDerived(); + + return m_derivedRotation * m_scene->GetForward(); + } + else + return NzNode::GetForward(); +} + +NzVector3f NzSceneNode::GetLeft() const +{ + if (m_scene) + { + if (!m_derivedUpdated) + UpdateDerived(); + + return m_derivedRotation * m_scene->GetLeft(); + } + else + return NzNode::GetLeft(); +} + +const NzString& NzSceneNode::GetName() const +{ + return m_name; +} + nzNodeType NzSceneNode::GetNodeType() const { return nzNodeType_Scene; } +NzVector3f NzSceneNode::GetRight() const +{ + if (m_scene) + { + if (!m_derivedUpdated) + UpdateDerived(); + + return m_derivedRotation * m_scene->GetRight(); + } + else + return NzNode::GetRight(); +} + NzScene* NzSceneNode::GetScene() const { return m_scene; } +NzVector3f NzSceneNode::GetUp() const +{ + if (m_scene) + { + if (!m_derivedUpdated) + UpdateDerived(); + + return m_derivedRotation * m_scene->GetUp(); + } + else + return NzNode::GetUp(); +} + bool NzSceneNode::IsDrawingEnabled() const { return m_drawingEnabled; @@ -51,6 +144,19 @@ bool NzSceneNode::IsVisible() const return m_visible; } +bool NzSceneNode::SetName(const NzString& name) +{ + if (m_scene) + // On demande à la scène de changer notre nom + return m_scene->ChangeNodeName(this, name); + else + { + // Pas de scène ? Changeons notre nom nous-même + SetNameInternal(name); + return true; + } +} + NzSceneNode& NzSceneNode::operator=(const NzSceneNode& sceneNode) { NzNode::operator=(sceneNode); @@ -62,26 +168,23 @@ NzSceneNode& NzSceneNode::operator=(const NzSceneNode& sceneNode) return *this; } -NzSceneNode& NzSceneNode::operator=(NzSceneNode&& sceneNode) -{ - NzNode::operator=(sceneNode); - - // La scène est affectée via le parenting du node - m_drawingEnabled = sceneNode.m_drawingEnabled; - m_visible = sceneNode.m_visible; - - return *this; -} - bool NzSceneNode::FrustumCull(const NzFrustumf& frustum) const { return frustum.Contains(GetBoundingVolume()); } +void NzSceneNode::InvalidateNode() +{ + NzNode::InvalidateNode(); + + m_boundingVolumeUpdated = false; +} + void NzSceneNode::OnParenting(const NzNode* parent) { if (parent) { + ///FIXME: Remonter jusqu'au premier parent de type SceneNode plutôt que de s'arrêter au premier venu if (parent->GetNodeType() == nzNodeType_Scene) SetScene(static_cast(parent)->m_scene); } @@ -116,6 +219,11 @@ void NzSceneNode::Register() { } +void NzSceneNode::SetNameInternal(const NzString& name) +{ + m_name = name; +} + void NzSceneNode::SetScene(NzScene* scene) { if (m_scene != scene) @@ -139,6 +247,18 @@ void NzSceneNode::Update() { } +void NzSceneNode::UpdateBoundingVolume() const +{ + if (m_boundingVolume.IsNull()) + MakeBoundingVolume(); + + if (!m_transformMatrixUpdated) + UpdateTransformMatrix(); + + m_boundingVolume.Update(m_transformMatrix); + m_boundingVolumeUpdated = true; +} + void NzSceneNode::UpdateVisibility(const NzFrustumf& frustum) { bool wasVisible = m_visible; diff --git a/src/Nazara/Graphics/SceneRoot.cpp b/src/Nazara/Graphics/SceneRoot.cpp index 46e446eaa..7cd3b7741 100644 --- a/src/Nazara/Graphics/SceneRoot.cpp +++ b/src/Nazara/Graphics/SceneRoot.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -20,12 +20,6 @@ void NzSceneRoot::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const NazaraInternalError("SceneNode::AddToRenderQueue() called on SceneRoot"); } -const NzBoundingVolumef& NzSceneRoot::GetBoundingVolume() const -{ - static NzBoundingVolumef infinite(nzExtend_Infinite); - return infinite; -} - nzSceneNodeType NzSceneRoot::GetSceneNodeType() const { return nzSceneNodeType_Root; @@ -36,6 +30,23 @@ bool NzSceneRoot::IsDrawable() const return true; } +NzSceneRoot* NzSceneRoot::Clone() const +{ + NazaraInternalError("SceneNode::Clone() called on SceneRoot"); + return nullptr; +} + +NzSceneRoot* NzSceneRoot::Create() const +{ + NazaraInternalError("SceneNode::Create() called on SceneRoot"); + return nullptr; +} + +void NzSceneRoot::MakeBoundingVolume() const +{ + m_boundingVolume.MakeInfinite(); +} + void NzSceneRoot::Register() { NazaraInternalError("SceneNode::Register() called on SceneRoot"); diff --git a/src/Nazara/Graphics/SkeletalModel.cpp b/src/Nazara/Graphics/SkeletalModel.cpp new file mode 100644 index 000000000..94af428b6 --- /dev/null +++ b/src/Nazara/Graphics/SkeletalModel.cpp @@ -0,0 +1,352 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +bool NzSkeletalModelParameters::IsValid() const +{ + if (!NzModelParameters::IsValid()) + return false; + + if (loadAnimation && !animation.IsValid()) + return false; + + return true; +} + +NzSkeletalModel::NzSkeletalModel() : +m_currentSequence(nullptr), +m_animationEnabled(true) +{ +} + +NzSkeletalModel::NzSkeletalModel(const NzSkeletalModel& model) : +NzModel(model), +m_skeleton(model.m_skeleton), +m_currentSequence(model.m_currentSequence), +m_animationEnabled(model.m_animationEnabled), +m_interpolation(model.m_interpolation), +m_currentFrame(model.m_currentFrame), +m_nextFrame(model.m_nextFrame) +{ +} + +NzSkeletalModel::~NzSkeletalModel() +{ + m_scene->UnregisterForUpdate(this); +} + +void NzSkeletalModel::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const +{ + const NzMatrix4f& transformMatrix = GetTransformMatrix(); + + unsigned int submeshCount = m_mesh->GetSubMeshCount(); + for (unsigned int i = 0; i < submeshCount; ++i) + { + const NzSkeletalMesh* mesh = static_cast(m_mesh->GetSubMesh(i)); + const NzMaterial* material = m_materials[mesh->GetMaterialIndex()]; + + NzMeshData meshData; + meshData.indexBuffer = mesh->GetIndexBuffer(); + meshData.primitiveMode = mesh->GetPrimitiveMode(); + meshData.vertexBuffer = NzSkinningManager::GetBuffer(mesh, &m_skeleton); + + renderQueue->AddMesh(material, meshData, m_skeleton.GetAABB(), transformMatrix); + } +} + +void NzSkeletalModel::AdvanceAnimation(float elapsedTime) +{ + #if NAZARA_GRAPHICS_SAFE + if (!m_animation) + { + NazaraError("Model has no animation"); + return; + } + #endif + + m_interpolation += m_currentSequence->frameRate * elapsedTime; + while (m_interpolation > 1.f) + { + m_interpolation -= 1.f; + + unsigned lastFrame = m_currentSequence->firstFrame + m_currentSequence->frameCount - 1; + if (m_nextFrame+1 > lastFrame) + { + if (m_animation->IsLoopPointInterpolationEnabled()) + { + m_currentFrame = m_nextFrame; + m_nextFrame = m_currentSequence->firstFrame; + } + else + { + m_currentFrame = m_currentSequence->firstFrame; + m_nextFrame = m_currentFrame+1; + } + } + else + { + m_currentFrame = m_nextFrame; + m_nextFrame++; + } + } + + m_animation->AnimateSkeleton(&m_skeleton, m_currentFrame, m_nextFrame, m_interpolation); + + InvalidateBoundingVolume(); +} + +NzSkeletalModel* NzSkeletalModel::Clone() const +{ + return new NzSkeletalModel(*this); +} + +NzSkeletalModel* NzSkeletalModel::Create() const +{ + return new NzSkeletalModel; +} + +void NzSkeletalModel::EnableAnimation(bool animation) +{ + m_animationEnabled = animation; +} + +NzAnimation* NzSkeletalModel::GetAnimation() const +{ + return m_animation; +} + +NzSkeleton* NzSkeletalModel::GetSkeleton() +{ + InvalidateBoundingVolume(); + + return &m_skeleton; +} + +const NzSkeleton* NzSkeletalModel::GetSkeleton() const +{ + return &m_skeleton; +} + +bool NzSkeletalModel::HasAnimation() const +{ + return m_animation != nullptr; +} + +bool NzSkeletalModel::IsAnimated() const +{ + return true; +} + +bool NzSkeletalModel::IsAnimationEnabled() const +{ + return m_animationEnabled; +} + +bool NzSkeletalModel::IsDrawable() const +{ + return m_mesh != nullptr && m_mesh->GetSubMeshCount() >= 1; +} + +bool NzSkeletalModel::LoadFromFile(const NzString& filePath, const NzSkeletalModelParameters& params) +{ + return NzSkeletalModelLoader::LoadFromFile(this, filePath, params); +} + +bool NzSkeletalModel::LoadFromMemory(const void* data, std::size_t size, const NzSkeletalModelParameters& params) +{ + return NzSkeletalModelLoader::LoadFromMemory(this, data, size, params); +} + +bool NzSkeletalModel::LoadFromStream(NzInputStream& stream, const NzSkeletalModelParameters& params) +{ + return NzSkeletalModelLoader::LoadFromStream(this, stream, params); +} + +void NzSkeletalModel::Reset() +{ + NzModel::Reset(); + + m_skeleton.Destroy(); +} + +bool NzSkeletalModel::SetAnimation(NzAnimation* animation) +{ + #if NAZARA_GRAPHICS_SAFE + if (!m_mesh) + { + NazaraError("Model has no mesh"); + return false; + } + + if (animation) + { + if (!animation->IsValid()) + { + NazaraError("Invalid animation"); + return false; + } + + if (animation->GetType() != m_mesh->GetAnimationType()) + { + NazaraError("Animation type must match mesh animation type"); + return false; + } + + if (animation->GetJointCount() != m_mesh->GetJointCount()) + { + NazaraError("Animation joint count must match mesh joint count"); + return false; + } + } + #endif + + m_animation = animation; + if (m_animation) + { + m_currentFrame = 0; + m_interpolation = 0.f; + + SetSequence(0); + } + + return true; +} + +void NzSkeletalModel::SetMesh(NzMesh* mesh) +{ + #if NAZARA_GRAPHICS_SAFE + if (mesh && mesh->GetAnimationType() != nzAnimationType_Skeletal) + { + NazaraError("Mesh animation type must be skeletal"); + return; + } + #endif + + NzModel::SetMesh(mesh); + + if (m_mesh) + { + if (m_animation && m_animation->GetJointCount() != m_mesh->GetJointCount()) + { + NazaraWarning("Animation joint count is not matching new mesh joint count, disabling animation..."); + SetAnimation(nullptr); + } + + m_skeleton = *m_mesh->GetSkeleton(); // Copie du squelette template + } +} + +bool NzSkeletalModel::SetSequence(const NzString& sequenceName) +{ + ///TODO: Rendre cette erreur "safe" avec le nouveau système de gestions d'erreur (No-log) + #if NAZARA_GRAPHICS_SAFE + if (!m_animation) + { + NazaraError("Model has no animation"); + return false; + } + #endif + + const NzSequence* currentSequence = m_animation->GetSequence(sequenceName); + if (!currentSequence) + { + NazaraError("Sequence not found"); + return false; + } + + m_currentSequence = currentSequence; + m_nextFrame = m_currentSequence->firstFrame; + + return true; +} + +void NzSkeletalModel::SetSequence(unsigned int sequenceIndex) +{ + #if NAZARA_GRAPHICS_SAFE + if (!m_animation) + { + NazaraError("Model has no animation"); + return; + } + #endif + + const NzSequence* currentSequence = m_animation->GetSequence(sequenceIndex); + #if NAZARA_GRAPHICS_SAFE + if (!currentSequence) + { + NazaraError("Sequence not found"); + return; + } + #endif + + m_currentSequence = currentSequence; + m_nextFrame = m_currentSequence->firstFrame; +} + +NzSkeletalModel& NzSkeletalModel::operator=(const NzSkeletalModel& node) +{ + NzSkeletalModel::operator=(node); + + m_animation = node.m_animation; + m_animationEnabled = node.m_animationEnabled; + m_currentFrame = node.m_currentFrame; + m_currentSequence = node.m_currentSequence; + m_interpolation = node.m_interpolation; + m_nextFrame = node.m_nextFrame; + m_skeleton = node.m_skeleton; + + return *this; +} + +NzSkeletalModel& NzSkeletalModel::operator=(NzSkeletalModel&& node) +{ + NzModel::operator=(node); + + // Ressources + m_animation = std::move(node.m_animation); + m_skeleton = std::move(node.m_skeleton); + + // Paramètres + m_animationEnabled = node.m_animationEnabled; + m_currentFrame = node.m_currentFrame; + m_currentSequence = node.m_currentSequence; + m_interpolation = node.m_interpolation; + m_nextFrame = node.m_nextFrame; + + return *this; +} + +void NzSkeletalModel::MakeBoundingVolume() const +{ + m_boundingVolume.Set(m_skeleton.GetAABB()); +} + +void NzSkeletalModel::Register() +{ + m_scene->RegisterForUpdate(this); +} + +void NzSkeletalModel::Unregister() +{ + m_scene->UnregisterForUpdate(this); +} + +void NzSkeletalModel::Update() +{ + if (m_animationEnabled && m_animation) + AdvanceAnimation(m_scene->GetUpdateTime()); +} + +NzSkeletalModelLoader::LoaderList NzSkeletalModel::s_loaders; diff --git a/src/Nazara/Graphics/SkinningManager.cpp b/src/Nazara/Graphics/SkinningManager.cpp index 4eb73f9d8..5aed6f248 100644 --- a/src/Nazara/Graphics/SkinningManager.cpp +++ b/src/Nazara/Graphics/SkinningManager.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -35,8 +35,8 @@ namespace NzVertexBuffer* buffer; }; - using MeshMap = std::unordered_map; - using SkeletonMap = std::unordered_map; + using MeshMap = std::unordered_map>; + using SkeletonMap = std::unordered_map>; SkeletonMap s_cache; std::vector s_skinningQueue; @@ -51,7 +51,7 @@ namespace { for (auto& pair : s_cache) { - MeshMap& meshMap = pair.second; + MeshMap& meshMap = pair.second.second; meshMap.erase(static_cast(object)); } break; @@ -75,17 +75,20 @@ namespace { for (auto& pair : s_cache) { - MeshMap& meshMap = pair.second; + MeshMap& meshMap = pair.second.second; for (auto& pair2 : meshMap) - pair2.second.updated = false; + pair2.second.second.updated = false; } break; } case ObjectType_Skeleton: { - for (auto& pair : s_cache.at(static_cast(object))) - pair.second.updated = false; + const NzSkeleton* skeleton = static_cast(object); + for (auto& pair : s_cache.at(skeleton).second) + pair.second.second.updated = false; + + break; break; } } @@ -161,25 +164,20 @@ NzVertexBuffer* NzSkinningManager::GetBuffer(const NzSkeletalMesh* mesh, const N SkeletonMap::iterator it = s_cache.find(skeleton); if (it == s_cache.end()) - { - it = s_cache.insert(std::make_pair(skeleton, SkeletonMap::mapped_type())).first; - skeleton->AddObjectListener(&listener, ObjectType_Skeleton); - } + it = s_cache.insert(std::make_pair(skeleton, std::make_pair(NzSkeletonConstListener(&listener, ObjectType_Skeleton, skeleton), MeshMap{}))).first; NzVertexBuffer* buffer; - MeshMap& meshMap = it->second; + MeshMap& meshMap = it->second.second; MeshMap::iterator it2 = meshMap.find(mesh); if (it2 == meshMap.end()) { std::unique_ptr vertexBuffer(new NzVertexBuffer); vertexBuffer->SetPersistent(false); - vertexBuffer->Reset(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Normal_UV_Tangent), mesh->GetVertexCount(), nzBufferStorage_Hardware, nzBufferUsage_Dynamic); + vertexBuffer->Reset(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Normal_UV_Tangent), mesh->GetVertexCount(), nzDataStorage_Hardware, nzBufferUsage_Dynamic); BufferData data({vertexBuffer.get(), true}); - meshMap.insert(std::make_pair(mesh, data)); - - mesh->AddObjectListener(&listener, ObjectType_SkeletalMesh); + meshMap.insert(std::make_pair(mesh, std::make_pair(NzSkeletalMeshConstListener(&listener, ObjectType_SkeletalMesh, mesh), data))); s_skinningQueue.push_back(SkinningData{mesh, skeleton, vertexBuffer.get()}); @@ -187,7 +185,7 @@ NzVertexBuffer* NzSkinningManager::GetBuffer(const NzSkeletalMesh* mesh, const N } else { - BufferData& data = it2->second; + BufferData& data = it2->second.second; if (!data.updated) { s_skinningQueue.push_back(SkinningData{mesh, skeleton, data.buffer}); @@ -221,13 +219,6 @@ bool NzSkinningManager::Initialize() void NzSkinningManager::Uninitialize() { - for (auto& pair : s_cache) - { - pair.first->RemoveObjectListener(&listener); - MeshMap& meshMap = pair.second; - for (auto& pair2 : meshMap) - pair2.first->RemoveObjectListener(&listener); - } s_cache.clear(); s_skinningQueue.clear(); } diff --git a/src/Nazara/Graphics/SkyboxBackground.cpp b/src/Nazara/Graphics/SkyboxBackground.cpp index d4347d25f..ba806d76b 100644 --- a/src/Nazara/Graphics/SkyboxBackground.cpp +++ b/src/Nazara/Graphics/SkyboxBackground.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -21,7 +21,7 @@ namespace { NzIndexBuffer* BuildIndexBuffer() { - std::unique_ptr indexBuffer(new NzIndexBuffer(false, 36, nzBufferStorage_Hardware, nzBufferUsage_Static)); + std::unique_ptr indexBuffer(new NzIndexBuffer(false, 36, nzDataStorage_Hardware, nzBufferUsage_Static)); indexBuffer->SetPersistent(false); nzUInt16 indices[6*6] = @@ -87,7 +87,7 @@ namespace "void main()\n" "{\n" " gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);\n" - " vTexCoord = vec3(VertexPosition.x, -VertexPosition.y, -VertexPosition.z);\n" + " vTexCoord = vec3(VertexPosition.x, VertexPosition.y, -VertexPosition.z);\n" "}\n"; const char* vertexSource140 = @@ -102,7 +102,7 @@ namespace "void main()\n" "{\n" " gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);\n" - " vTexCoord = vec3(VertexPosition.x, -VertexPosition.y, -VertexPosition.z);\n" + " vTexCoord = vec3(VertexPosition.x, VertexPosition.y, -VertexPosition.z);\n" "}\n"; ///TODO: Remplacer ça par des ShaderNode @@ -155,7 +155,7 @@ namespace NzVertexBuffer* BuildVertexBuffer() { - std::unique_ptr vertexBuffer(new NzVertexBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ), 8, nzBufferStorage_Hardware, nzBufferUsage_Static)); + std::unique_ptr vertexBuffer(new NzVertexBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ), 8, nzDataStorage_Hardware, nzBufferUsage_Static)); vertexBuffer->SetPersistent(false); float vertices[8*(sizeof(float)*3)] = diff --git a/src/Nazara/Graphics/Sprite.cpp b/src/Nazara/Graphics/Sprite.cpp index 7d14a1a8e..f5f28d00a 100644 --- a/src/Nazara/Graphics/Sprite.cpp +++ b/src/Nazara/Graphics/Sprite.cpp @@ -1,75 +1,66 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include +#include +#include +#include #include #include NzSprite::NzSprite() : -m_boundingVolume(NzBoundingVolumef::Null()), +m_color(NzColor::White), m_textureCoords(0.f, 0.f, 1.f, 1.f), m_size(64.f, 64.f), -m_boundingVolumeUpdated(true) +m_verticesUpdated(false) { + SetDefaultMaterial(); } NzSprite::NzSprite(NzTexture* texture) : -m_boundingVolume(NzBoundingVolumef::Null()), -m_textureCoords(0.f, 0.f, 1.f, 1.f) +m_color(NzColor::White), +m_textureCoords(0.f, 0.f, 1.f, 1.f), +m_size(64.f, 64.f), +m_verticesUpdated(false) { - if (texture) - { - m_material = new NzMaterial; - m_material->SetPersistent(false); - m_material->SetDiffuseMap(texture); - - if (texture->IsValid()) - m_size.Set(texture->GetWidth(), texture->GetHeight()); - else - m_size.Set(64.f, 64.f); - - m_boundingVolumeUpdated = false; - } - else - { - m_size.Set(64.f, 64.f); - m_boundingVolumeUpdated = true; - } + SetTexture(texture, true); } NzSprite::NzSprite(const NzSprite& sprite) : NzSceneNode(sprite), -m_boundingVolume(sprite.m_boundingVolume), +m_color(sprite.m_color), m_material(sprite.m_material), m_textureCoords(sprite.m_textureCoords), m_size(sprite.m_size), -m_boundingVolumeUpdated(sprite.m_boundingVolumeUpdated) +m_vertices(sprite.m_vertices), +m_verticesUpdated(sprite.m_verticesUpdated) { - SetParent(sprite); + SetParent(sprite.GetParent()); } -NzSprite::NzSprite(NzSprite&& sprite) : -NzSceneNode(sprite), -m_boundingVolume(sprite.m_boundingVolume), -m_material(std::move(sprite.m_material)), -m_textureCoords(sprite.m_textureCoords), -m_size(sprite.m_size), -m_boundingVolumeUpdated(sprite.m_boundingVolumeUpdated) -{ -} - -NzSprite::~NzSprite() = default; - void NzSprite::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const { - renderQueue->AddSprite(this); + if (!m_verticesUpdated) + UpdateVertices(); + + renderQueue->AddSprites(m_material, m_vertices, 1); } -const NzBoundingVolumef& NzSprite::GetBoundingVolume() const +NzSprite* NzSprite::Clone() const { - static NzBoundingVolumef infinity(NzBoundingVolumef::Infinite()); - return infinity; + return new NzSprite(*this); +} + +NzSprite* NzSprite::Create() const +{ + return new NzSprite; +} + +const NzColor& NzSprite::GetColor() const +{ + return m_color; } NzMaterial* NzSprite::GetMaterial() const @@ -97,38 +88,69 @@ bool NzSprite::IsDrawable() const return m_material != nullptr; } +void NzSprite::SetColor(const NzColor& color) +{ + m_color = color; + m_verticesUpdated = false; +} + +void NzSprite::SetDefaultMaterial() +{ + std::unique_ptr material(new NzMaterial); + material->Enable(nzRendererParameter_FaceCulling, false); + material->EnableLighting(false); + + SetMaterial(material.get()); + + material->SetPersistent(false); + material.release(); +} + void NzSprite::SetMaterial(NzMaterial* material, bool resizeSprite) { m_material = material; - - NzTexture* diffuseMap = m_material->GetDiffuseMap(); - if (resizeSprite && diffuseMap && diffuseMap->IsValid()) - SetSize(NzVector2f(diffuseMap->GetSize())); + if (m_material && resizeSprite) + { + NzTexture* diffuseMap = m_material->GetDiffuseMap(); + if (diffuseMap && diffuseMap->IsValid()) + SetSize(NzVector2f(NzVector2ui(diffuseMap->GetSize()))); + } } void NzSprite::SetSize(const NzVector2f& size) { m_size = size; + + // On invalide la bounding box m_boundingVolume.MakeNull(); m_boundingVolumeUpdated = false; + m_verticesUpdated = false; +} + +void NzSprite::SetSize(float sizeX, float sizeY) +{ + SetSize(NzVector2f(sizeX, sizeY)); } void NzSprite::SetTexture(NzTexture* texture, bool resizeSprite) { - std::unique_ptr material(new NzMaterial); - material->SetPersistent(false); + if (!m_material) + SetDefaultMaterial(); + else if (m_material->GetReferenceCount() > 1) + { + m_material = new NzMaterial(*m_material); + m_material->SetPersistent(false); + } - material->Enable(nzRendererParameter_FaceCulling, false); - material->EnableLighting(false); - material->SetDiffuseMap(texture); - - SetMaterial(material.get(), resizeSprite); - material.release(); + m_material->SetDiffuseMap(texture); + if (resizeSprite && texture && texture->IsValid()) + SetSize(NzVector2f(NzVector2ui(texture->GetSize()))); } void NzSprite::SetTextureCoords(const NzRectf& coords) { m_textureCoords = coords; + m_verticesUpdated = false; } void NzSprite::SetTextureRect(const NzRectui& rect) @@ -155,29 +177,69 @@ void NzSprite::SetTextureRect(const NzRectui& rect) SetTextureCoords(NzRectf(invWidth*rect.x, invHeight*rect.y, invWidth*rect.width, invHeight*rect.height)); } +NzSprite& NzSprite::operator=(const NzSprite& sprite) +{ + NzSceneNode::operator=(sprite); + + m_color = sprite.m_color; + m_material = sprite.m_material; + m_textureCoords = sprite.m_textureCoords; + m_size = sprite.m_size; + + // On ne copie pas les sommets finaux car il est très probable que nos paramètres soient modifiés et qu'ils doivent être régénérés de toute façon + m_verticesUpdated = false; + + return *this; +} + void NzSprite::InvalidateNode() { NzSceneNode::InvalidateNode(); - m_boundingVolumeUpdated = false; + m_verticesUpdated = false; } void NzSprite::Register() { + // Le changement de scène peut affecter les sommets + m_verticesUpdated = false; } void NzSprite::Unregister() { } -void NzSprite::UpdateBoundingVolume() const +void NzSprite::MakeBoundingVolume() const { - if (m_boundingVolume.IsNull()) - m_boundingVolume.Set(-m_size.x*0.5f, -m_size.y*0.5f, 0.f, m_size.x, m_size.y, 0.f); + NzVector3f down = (m_scene) ? m_scene->GetDown() : NzVector3f::Down(); + NzVector3f right = (m_scene) ? m_scene->GetRight() : NzVector3f::Right(); + m_boundingVolume.Set(NzVector3f(0.f), m_size.x*right + m_size.y*down); +} + +void NzSprite::UpdateVertices() const +{ if (!m_transformMatrixUpdated) UpdateTransformMatrix(); - m_boundingVolume.Update(m_transformMatrix); - m_boundingVolumeUpdated = true; + NzVector3f down = (m_scene) ? m_scene->GetDown() : NzVector3f::Down(); + NzVector3f right = (m_scene) ? m_scene->GetRight() : NzVector3f::Right(); + + m_vertices[0].color = m_color; + m_vertices[0].position = m_transformMatrix.Transform(NzVector3f(0.f)); + m_vertices[0].uv.Set(m_textureCoords.GetCorner(nzRectCorner_LeftTop)); + + m_vertices[1].color = m_color; + m_vertices[1].position = m_transformMatrix.Transform(m_size.x*right); + m_vertices[1].uv.Set(m_textureCoords.GetCorner(nzRectCorner_RightTop)); + + m_vertices[2].color = m_color; + m_vertices[2].position = m_transformMatrix.Transform(m_size.y*down); + m_vertices[2].uv.Set(m_textureCoords.GetCorner(nzRectCorner_LeftBottom)); + + m_vertices[3].color = m_color; + m_vertices[3].position = m_transformMatrix.Transform(m_size.x*right + m_size.y*down); + m_vertices[3].uv.Set(m_textureCoords.GetCorner(nzRectCorner_RightBottom)); + + m_verticesUpdated = true; } diff --git a/src/Nazara/Graphics/TextSprite.cpp b/src/Nazara/Graphics/TextSprite.cpp new file mode 100644 index 000000000..099709dd8 --- /dev/null +++ b/src/Nazara/Graphics/TextSprite.cpp @@ -0,0 +1,418 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +NzTextSprite::NzTextSprite() : +m_color(NzColor::White), +m_verticesUpdated(false) +{ + SetDefaultMaterial(); +} + +NzTextSprite::NzTextSprite(const NzTextSprite& sprite) : +NzSceneNode(sprite), +m_atlases(sprite.m_atlases), +m_renderInfos(sprite.m_renderInfos), +m_localVertices(sprite.m_localVertices), +m_vertices(sprite.m_vertices), +m_color(sprite.m_color), +m_material(sprite.m_material), +m_localBounds(sprite.m_localBounds), +m_verticesUpdated(sprite.m_verticesUpdated) +{ + SetParent(sprite.GetParent()); + + for (const NzAbstractAtlas* atlas : m_atlases) + atlas->AddListener(this); +} + +NzTextSprite::~NzTextSprite() +{ + ClearAtlases(); +} + +void NzTextSprite::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const +{ + if (!m_verticesUpdated) + UpdateVertices(); + + for (auto& pair : m_renderInfos) + { + NzTexture* overlay = pair.first; + RenderIndices& indices = pair.second; + + if (indices.count > 0) + renderQueue->AddSprites(m_material, &m_vertices[indices.first*4], indices.count, overlay); + } +} + +void NzTextSprite::Clear() +{ + ClearAtlases(); + m_boundingVolume.MakeNull(); + m_localVertices.clear(); + m_renderInfos.clear(); + m_vertices.clear(); +} + +NzTextSprite* NzTextSprite::Clone() const +{ + return new NzTextSprite(*this); +} + +NzTextSprite* NzTextSprite::Create() const +{ + return new NzTextSprite; +} + +const NzColor& NzTextSprite::GetColor() const +{ + return m_color; +} + +NzMaterial* NzTextSprite::GetMaterial() const +{ + return m_material; +} + +nzSceneNodeType NzTextSprite::GetSceneNodeType() const +{ + return nzSceneNodeType_TextSprite; +} + +void NzTextSprite::InvalidateVertices() +{ + m_verticesUpdated = false; +} + +bool NzTextSprite::IsDrawable() const +{ + return m_material != nullptr; +} + +void NzTextSprite::SetColor(const NzColor& color) +{ + m_color = color; + m_verticesUpdated = false; +} + +void NzTextSprite::SetDefaultMaterial() +{ + std::unique_ptr material(new NzMaterial); + material->Enable(nzRendererParameter_Blend, true); + material->Enable(nzRendererParameter_DepthWrite, false); + material->Enable(nzRendererParameter_FaceCulling, false); + material->EnableLighting(false); + material->SetDstBlend(nzBlendFunc_InvSrcAlpha); + material->SetSrcBlend(nzBlendFunc_SrcAlpha); + + SetMaterial(material.get()); + + material->SetPersistent(false); + material.release(); +} + +void NzTextSprite::SetMaterial(NzMaterial* material) +{ + m_material = material; +} + +void NzTextSprite::Update(const NzAbstractTextDrawer& drawer) +{ + ClearAtlases(); + + NzCallOnExit clearOnFail([this]() + { + Clear(); + }); + + unsigned int fontCount = drawer.GetFontCount(); + for (unsigned int i = 0; i < fontCount; ++i) + { + NzFont* font = drawer.GetFont(i); + const NzAbstractAtlas* atlas = font->GetAtlas().get(); + + #if NAZARA_GRAPHICS_SAFE + if ((atlas->GetStorage() & nzDataStorage_Hardware) == 0) + { + // Cet atlas ne nous donnera pas de texture, nous ne pouvons pas l'utiliser + NazaraError("Font " + NzString::Pointer(font) + " uses a non-hardware atlas which cannot be used by text sprites"); + return; + } + #endif + + if (m_atlases.insert(atlas).second) + atlas->AddListener(this); + } + + unsigned int glyphCount = drawer.GetGlyphCount(); + m_localVertices.resize(glyphCount * 4); + m_vertices.resize(glyphCount * 4); + + NzTexture* lastTexture = nullptr; + unsigned int* count = nullptr; + for (unsigned int i = 0; i < glyphCount; ++i) + { + const NzAbstractTextDrawer::Glyph& glyph = drawer.GetGlyph(i); + + NzTexture* texture = static_cast(glyph.atlas); + if (lastTexture != texture) + { + auto pair = m_renderInfos.insert(std::make_pair(texture, RenderIndices{0U, 0U})); + + count = &pair.first->second.count; + lastTexture = texture; + } + + (*count)++; + } + + // Attribution des indices + unsigned int index = 0; + for (auto& pair : m_renderInfos) + { + RenderIndices& indices = pair.second; + + indices.first = index; + + index += indices.count; + indices.count = 0; // On réinitialise count à zéro (on va s'en servir pour compteur dans la boucle suivante) + } + + NzSparsePtr texCoordPtr(&m_vertices[0].uv, sizeof(NzVertexStruct_XYZ_Color_UV)); + + lastTexture = nullptr; + RenderIndices* indices = nullptr; + for (unsigned int i = 0; i < glyphCount; ++i) + { + const NzAbstractTextDrawer::Glyph& glyph = drawer.GetGlyph(i); + + NzTexture* texture = static_cast(glyph.atlas); + if (lastTexture != texture) + { + indices = &m_renderInfos[texture]; // On a changé de texture, on ajuste le pointeur + lastTexture = texture; + } + + // Affectation des positions et couleurs (locaux) + for (unsigned int j = 0; j < 4; ++j) + { + m_localVertices[i*4 + j].color = glyph.color; + m_localVertices[i*4 + j].position.Set(glyph.corners[j]); + } + + // Calcul des coordonnées de texture (globaux) + + // On commence par transformer les coordonnées entières en flottantes: + NzVector2ui size(texture->GetSize()); + float invWidth = 1.f/size.x; + float invHeight = 1.f/size.y; + + NzRectf uvRect(glyph.atlasRect); + uvRect.x *= invWidth; + uvRect.y *= invHeight; + uvRect.width *= invWidth; + uvRect.height *= invHeight; + + // Extraction des quatre coins et attribution + NzSparsePtr texCoord = texCoordPtr + indices->first*4 + indices->count*4; + if (!glyph.flipped) + { + // Le glyphe n'est pas retourné, l'ordre des UV suit celui des sommets + *texCoord++ = uvRect.GetCorner(nzRectCorner_LeftTop); + *texCoord++ = uvRect.GetCorner(nzRectCorner_RightTop); + *texCoord++ = uvRect.GetCorner(nzRectCorner_LeftBottom); + *texCoord++ = uvRect.GetCorner(nzRectCorner_RightBottom); + } + else + { + // Le glyphe a subit une rotation de 90° (sens antihoraire), on adapte les UV en conséquence + *texCoord++ = uvRect.GetCorner(nzRectCorner_LeftBottom); + *texCoord++ = uvRect.GetCorner(nzRectCorner_LeftTop); + *texCoord++ = uvRect.GetCorner(nzRectCorner_RightBottom); + *texCoord++ = uvRect.GetCorner(nzRectCorner_RightTop); + } + + // Et on passe au prochain + indices->count++; + } + + m_localBounds = drawer.GetBounds(); + m_boundingVolume.MakeNull(); + m_boundingVolumeUpdated = false; + m_verticesUpdated = false; + + clearOnFail.Reset(); +} + +NzTextSprite& NzTextSprite::operator=(const NzTextSprite& text) +{ + NzSceneNode::operator=(text); + + m_atlases = text.m_atlases; + m_color = text.m_color; + m_material = text.m_material; + m_renderInfos = text.m_renderInfos; + m_localBounds = text.m_localBounds; + m_localVertices = text.m_localVertices; + + // On ne copie pas les sommets finaux car il est très probable que nos paramètres soient modifiés et qu'ils doivent être régénérés de toute façon + m_verticesUpdated = false; + + return *this; +} + +void NzTextSprite::ClearAtlases() +{ + for (const NzAbstractAtlas* atlas : m_atlases) + atlas->RemoveListener(this); + + m_atlases.clear(); +} + +void NzTextSprite::InvalidateNode() +{ + NzSceneNode::InvalidateNode(); + + m_verticesUpdated = false; +} + +void NzTextSprite::MakeBoundingVolume() const +{ + NzVector3f down = (m_scene) ? m_scene->GetDown() : NzVector3f::Down(); + NzVector3f right = (m_scene) ? m_scene->GetRight() : NzVector3f::Right(); + + NzRectf bounds(m_localBounds); + NzVector2f max = bounds.GetMaximum(); + NzVector2f min = bounds.GetMinimum(); + + m_boundingVolume.Set(min.x*right + min.y*down, max.x*right + max.y*down); +} + +bool NzTextSprite::OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) +{ + NazaraUnused(userdata); + + #ifdef NAZARA_DEBUG + if (m_atlases.find(atlas) == m_atlases.end()) + { + NazaraInternalError("Not listening to " + NzString::Pointer(atlas)); + return false; + } + #endif + + NazaraWarning("TextSprite " + NzString::Pointer(this) + " has been cleared because atlas " + NzString::Pointer(atlas) + " that was under use has been cleared"); + Clear(); + + return false; +} + +bool NzTextSprite::OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata) +{ + NazaraUnused(atlas); + NazaraUnused(userdata); + + #ifdef NAZARA_DEBUG + if (m_atlases.find(atlas) == m_atlases.end()) + { + NazaraInternalError("Not listening to " + NzString::Pointer(atlas)); + return false; + } + #endif + + NzTexture* oldTexture = static_cast(oldLayer); + NzTexture* newTexture = static_cast(newLayer); + + auto it = m_renderInfos.find(oldTexture); + if (it != m_renderInfos.end()) + { + // Nous utilisons bien cette texture, nous devons mettre à jour les coordonnées de texture + RenderIndices indices = std::move(it->second); + + NzVector2ui oldSize(oldTexture->GetSize()); + NzVector2ui newSize(newTexture->GetSize()); + NzVector2f scale = NzVector2f(oldSize)/NzVector2f(newSize); + + NzSparsePtr texCoordPtr(&m_vertices[indices.first].uv, sizeof(NzVertexStruct_XYZ_Color_UV)); + for (unsigned int i = 0; i < indices.count; ++i) + { + for (unsigned int j = 0; j < 4; ++j) + texCoordPtr[i*4 + j] *= scale; + } + + // Nous enlevons l'ancienne texture et rajoutons la nouvelle à sa place (pour les mêmes indices) + m_renderInfos.erase(it); + m_renderInfos.insert(std::make_pair(newTexture, std::move(indices))); + } + + return true; +} + +void NzTextSprite::OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata) +{ + NazaraUnused(userdata); + + #ifdef NAZARA_DEBUG + if (m_atlases.find(atlas) == m_atlases.end()) + { + NazaraInternalError("Not listening to " + NzString::Pointer(atlas)); + return; + } + #endif + + NazaraWarning("TextSprite " + NzString::Pointer(this) + " has been cleared because atlas " + NzString::Pointer(atlas) + " that was under use has been released"); + Clear(); +} + +void NzTextSprite::Register() +{ + // Le changement de scène peut affecter les sommets + m_verticesUpdated = false; +} + +void NzTextSprite::Unregister() +{ +} + +void NzTextSprite::UpdateVertices() const +{ + if (!m_transformMatrixUpdated) + UpdateTransformMatrix(); + + NzVector3f down = (m_scene) ? m_scene->GetDown() : NzVector3f::Down(); + NzVector3f right = (m_scene) ? m_scene->GetRight() : NzVector3f::Right(); + + NzSparsePtr colorPtr(&m_vertices[0].color, sizeof(NzVertexStruct_XYZ_Color_UV)); + NzSparsePtr posPtr(&m_vertices[0].position, sizeof(NzVertexStruct_XYZ_Color_UV)); + + for (auto& pair : m_renderInfos) + { + RenderIndices& indices = pair.second; + + NzSparsePtr color = colorPtr + indices.first*4; + NzSparsePtr pos = posPtr + indices.first*4; + NzVertexStruct_XY_Color* localVertex = &m_localVertices[indices.first*4]; + for (unsigned int i = 0; i < indices.count; ++i) + { + for (unsigned int j = 0; j < 4; ++j) + { + *pos++ = m_transformMatrix.Transform(localVertex->position.x*right + localVertex->position.y*down); + *color++ = m_color * localVertex->color; + + localVertex++; + } + } + } + + m_verticesUpdated = true; +} diff --git a/src/Nazara/Graphics/TextureBackground.cpp b/src/Nazara/Graphics/TextureBackground.cpp index a9d4a1bbc..38f501590 100644 --- a/src/Nazara/Graphics/TextureBackground.cpp +++ b/src/Nazara/Graphics/TextureBackground.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Graphics/View.cpp b/src/Nazara/Graphics/View.cpp index 3caa0b48f..0316b9e53 100644 --- a/src/Nazara/Graphics/View.cpp +++ b/src/Nazara/Graphics/View.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -10,6 +10,7 @@ NzView::NzView() : m_targetRegion(0.f, 0.f, 1.f, 1.f), +m_size(0.f), m_target(nullptr), m_frustumUpdated(false), m_projectionMatrixUpdated(false), @@ -20,6 +21,12 @@ m_zNear(-1.f) { } +NzView::NzView(const NzVector2f& size) : +NzView() // On délègue +{ + SetSize(size); +} + NzView::~NzView() { if (m_target) @@ -73,6 +80,21 @@ const NzFrustumf& NzView::GetFrustum() const return m_frustum; } +NzVector3f NzView::GetGlobalForward() const +{ + return NzVector3f::UnitZ(); +} + +NzVector3f NzView::GetGlobalRight() const +{ + return NzVector3f::UnitX(); +} + +NzVector3f NzView::GetGlobalUp() const +{ + return -NzVector3f::UnitY(); +} + const NzMatrix4f& NzView::GetProjectionMatrix() const { if (!m_projectionMatrixUpdated) @@ -125,6 +147,17 @@ float NzView::GetZNear() const return m_zNear; } +void NzView::SetSize(const NzVector2f& size) +{ + SetSize(size.x, size.y); +} + +void NzView::SetSize(float width, float height) +{ + m_size.Set(width, height); + m_projectionMatrixUpdated = false; +} + void NzView::SetTarget(const NzRenderTarget* renderTarget) { if (m_target) @@ -256,10 +289,16 @@ void NzView::UpdateFrustum() const void NzView::UpdateProjectionMatrix() const { - if (!m_viewportUpdated) - UpdateViewport(); + if (m_size.x <= 0.f || m_size.y <= 0.f) // Si la taille est nulle, on prendra la taille du viewport + { + if (!m_viewportUpdated) + UpdateViewport(); + + m_projectionMatrix.MakeOrtho(0.f, m_viewport.width, 0.f, m_viewport.height, m_zNear, m_zFar); + } + else + m_projectionMatrix.MakeOrtho(0.f, m_size.x, 0.f, m_size.y, m_zNear, m_zFar); - m_projectionMatrix.MakeOrtho(m_viewport.x, m_viewport.x + m_viewport.width, m_viewport.y, m_viewport.y + m_viewport.height, m_zNear, m_zFar); m_projectionMatrixUpdated = true; } diff --git a/src/Nazara/Lua/Lua.cpp b/src/Nazara/Lua/Lua.cpp index 236ae84a8..5ea40b97d 100644 --- a/src/Nazara/Lua/Lua.cpp +++ b/src/Nazara/Lua/Lua.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Lua scripting module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Lua/LuaInstance.cpp b/src/Nazara/Lua/LuaInstance.cpp index 2db6aeb80..396fd4a35 100644 --- a/src/Nazara/Lua/LuaInstance.cpp +++ b/src/Nazara/Lua/LuaInstance.cpp @@ -1,9 +1,7 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Lua scripting module" // For conditions of distribution and use, see copyright notice in Config.hpp -#define NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION - #include #include #include @@ -11,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -558,7 +557,7 @@ bool NzLuaInstance::IsOfType(int index, nzLuaType type) const return lua_isuserdata(m_state, index) == 1; } - NazaraError("Lua type unhandled (0x" + NzString::Number(type, 16) + ')'); + NazaraError("Lua type not handled (0x" + NzString::Number(type, 16) + ')'); return false; } @@ -621,7 +620,7 @@ void NzLuaInstance::PushCFunction(NzLuaCFunction func, int upvalueCount) void NzLuaInstance::PushFunction(NzLuaFunction func) { NzLuaFunction* luaFunc = reinterpret_cast(lua_newuserdata(m_state, sizeof(NzLuaFunction))); - new (luaFunc) NzLuaFunction(std::move(func)); + NzPlacementNew(luaFunc, std::move(func)); lua_pushcclosure(m_state, ProxyFunc, 1); } diff --git a/src/Nazara/Noise/Abstract2DNoise.cpp b/src/Nazara/Noise/Abstract2DNoise.cpp index c8cef53f0..2f2ae4f76 100644 --- a/src/Nazara/Noise/Abstract2DNoise.cpp +++ b/src/Nazara/Noise/Abstract2DNoise.cpp @@ -1,9 +1,8 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include #include #include #include diff --git a/src/Nazara/Noise/Abstract3DNoise.cpp b/src/Nazara/Noise/Abstract3DNoise.cpp index 9a386160c..654df62d6 100644 --- a/src/Nazara/Noise/Abstract3DNoise.cpp +++ b/src/Nazara/Noise/Abstract3DNoise.cpp @@ -1,9 +1,8 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include #include #include #include diff --git a/src/Nazara/Noise/Abstract4DNoise.cpp b/src/Nazara/Noise/Abstract4DNoise.cpp index 5e9afe9ff..781e3b57e 100644 --- a/src/Nazara/Noise/Abstract4DNoise.cpp +++ b/src/Nazara/Noise/Abstract4DNoise.cpp @@ -1,9 +1,8 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include #include #include #include diff --git a/src/Nazara/Noise/ComplexNoiseBase.cpp b/src/Nazara/Noise/ComplexNoiseBase.cpp index d94a7e350..7529efdb5 100644 --- a/src/Nazara/Noise/ComplexNoiseBase.cpp +++ b/src/Nazara/Noise/ComplexNoiseBase.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Noise/FBM2D.cpp b/src/Nazara/Noise/FBM2D.cpp index 9d91e1a93..8d43e3a07 100644 --- a/src/Nazara/Noise/FBM2D.cpp +++ b/src/Nazara/Noise/FBM2D.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Noise/FBM3D.cpp b/src/Nazara/Noise/FBM3D.cpp index ea78d3155..6ac7afc07 100644 --- a/src/Nazara/Noise/FBM3D.cpp +++ b/src/Nazara/Noise/FBM3D.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Noise/FBM4D.cpp b/src/Nazara/Noise/FBM4D.cpp index a0fb382ae..c5a256a40 100644 --- a/src/Nazara/Noise/FBM4D.cpp +++ b/src/Nazara/Noise/FBM4D.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Noise/HybridMultiFractal3D.cpp b/src/Nazara/Noise/HybridMultiFractal3D.cpp index 20c169386..77df9e3d4 100644 --- a/src/Nazara/Noise/HybridMultiFractal3D.cpp +++ b/src/Nazara/Noise/HybridMultiFractal3D.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Noise/HybridMultiFractal4D.cpp b/src/Nazara/Noise/HybridMultiFractal4D.cpp index aa81c4730..7909d3c1e 100644 --- a/src/Nazara/Noise/HybridMultiFractal4D.cpp +++ b/src/Nazara/Noise/HybridMultiFractal4D.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Noise/HybridMultifractal2D.cpp b/src/Nazara/Noise/HybridMultifractal2D.cpp index 0bbc07c6f..6721fd981 100644 --- a/src/Nazara/Noise/HybridMultifractal2D.cpp +++ b/src/Nazara/Noise/HybridMultifractal2D.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Noise/MappedNoiseBase.cpp b/src/Nazara/Noise/MappedNoiseBase.cpp index 2200fdb8f..27b8ece40 100644 --- a/src/Nazara/Noise/MappedNoiseBase.cpp +++ b/src/Nazara/Noise/MappedNoiseBase.cpp @@ -1,10 +1,10 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include #include +#include #include #include #include diff --git a/src/Nazara/Noise/Noise.cpp b/src/Nazara/Noise/Noise.cpp index cf53c644d..86fc17a6a 100644 --- a/src/Nazara/Noise/Noise.cpp +++ b/src/Nazara/Noise/Noise.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Noise/NoiseBase.cpp b/src/Nazara/Noise/NoiseBase.cpp index 1927ba7fa..d394b7f9c 100644 --- a/src/Nazara/Noise/NoiseBase.cpp +++ b/src/Nazara/Noise/NoiseBase.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Noise/Perlin2D.cpp b/src/Nazara/Noise/Perlin2D.cpp index 18eca6411..4622016d0 100644 --- a/src/Nazara/Noise/Perlin2D.cpp +++ b/src/Nazara/Noise/Perlin2D.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Noise/Perlin3D.cpp b/src/Nazara/Noise/Perlin3D.cpp index 253d90873..87d79622b 100644 --- a/src/Nazara/Noise/Perlin3D.cpp +++ b/src/Nazara/Noise/Perlin3D.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Noise/Perlin4D.cpp b/src/Nazara/Noise/Perlin4D.cpp index 388cbaef5..1c49c40f8 100644 --- a/src/Nazara/Noise/Perlin4D.cpp +++ b/src/Nazara/Noise/Perlin4D.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Noise/Simplex2D.cpp b/src/Nazara/Noise/Simplex2D.cpp index b4b62521d..78f9ceb43 100644 --- a/src/Nazara/Noise/Simplex2D.cpp +++ b/src/Nazara/Noise/Simplex2D.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Noise/Simplex3D.cpp b/src/Nazara/Noise/Simplex3D.cpp index 09b4c8c40..9a6138cff 100644 --- a/src/Nazara/Noise/Simplex3D.cpp +++ b/src/Nazara/Noise/Simplex3D.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Noise/Simplex4D.cpp b/src/Nazara/Noise/Simplex4D.cpp index 05629bc68..9cc2b28a1 100644 --- a/src/Nazara/Noise/Simplex4D.cpp +++ b/src/Nazara/Noise/Simplex4D.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Rémi Bèges +// Copyright (C) 2015 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Physics/Geom.cpp b/src/Nazara/Physics/Geom.cpp index a7e348f07..8bb344ba4 100644 --- a/src/Nazara/Physics/Geom.cpp +++ b/src/Nazara/Physics/Geom.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Physics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Physics/PhysObject.cpp b/src/Nazara/Physics/PhysObject.cpp index 36b8f12c8..bde930811 100644 --- a/src/Nazara/Physics/PhysObject.cpp +++ b/src/Nazara/Physics/PhysObject.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Physics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Physics/PhysWorld.cpp b/src/Nazara/Physics/PhysWorld.cpp index 786151e6e..63ef5c886 100644 --- a/src/Nazara/Physics/PhysWorld.cpp +++ b/src/Nazara/Physics/PhysWorld.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Physics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Physics/Physics.cpp b/src/Nazara/Physics/Physics.cpp index fb4e4f9a1..c54023b2c 100644 --- a/src/Nazara/Physics/Physics.cpp +++ b/src/Nazara/Physics/Physics.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Physics module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Renderer/Context.cpp b/src/Nazara/Renderer/Context.cpp index 031e9b780..3a897d7aa 100644 --- a/src/Nazara/Renderer/Context.cpp +++ b/src/Nazara/Renderer/Context.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -38,7 +38,7 @@ namespace switch (source) { case GL_DEBUG_SOURCE_API: - ss << "OpenGL"; + ss << "OpenGL API"; break; case GL_DEBUG_SOURCE_WINDOW_SYSTEM: diff --git a/src/Nazara/Renderer/ContextParameters.cpp b/src/Nazara/Renderer/ContextParameters.cpp index 06051819e..a7dec4546 100644 --- a/src/Nazara/Renderer/ContextParameters.cpp +++ b/src/Nazara/Renderer/ContextParameters.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Renderer/DebugDrawer.cpp b/src/Nazara/Renderer/DebugDrawer.cpp index 1a2e96ee7..f6822e9b9 100644 --- a/src/Nazara/Renderer/DebugDrawer.cpp +++ b/src/Nazara/Renderer/DebugDrawer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -159,64 +159,64 @@ void NzDebugDrawer::Draw(const NzFrustumf& frustum) NzBufferMapper mapper(s_vertexBuffer, nzBufferAccess_DiscardAndWrite, 0, 24); NzVertexStruct_XYZ* vertex = reinterpret_cast(mapper.GetPointer()); - vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftBottom)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftBottom)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_NearRightBottom)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightBottom)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftBottom)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftBottom)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftTop)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftTop)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftBottom)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftBottom)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftBottom)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftBottom)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_FarRightTop)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightTop)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftTop)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftTop)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_FarRightTop)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightTop)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_FarRightBottom)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightBottom)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_FarRightTop)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightTop)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_NearRightTop)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightTop)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftBottom)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftBottom)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_FarRightBottom)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightBottom)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftBottom)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftBottom)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftTop)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftTop)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftTop)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftTop)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_NearRightTop)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightTop)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftTop)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftTop)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftTop)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftTop)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_NearRightBottom)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightBottom)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_NearRightTop)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightTop)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_NearRightBottom)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightBottom)); vertex++; - vertex->position.Set(frustum.GetCorner(nzCorner_FarRightBottom)); + vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightBottom)); vertex++; mapper.Unmap(); @@ -241,64 +241,64 @@ void NzDebugDrawer::Draw(const NzOrientedBoxf& orientedBox) NzBufferMapper mapper(s_vertexBuffer, nzBufferAccess_DiscardAndWrite, 0, 24); NzVertexStruct_XYZ* vertex = reinterpret_cast(mapper.GetPointer()); - vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftBottom)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftBottom)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightBottom)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightBottom)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftBottom)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftBottom)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftTop)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftTop)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftBottom)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftBottom)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftBottom)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftBottom)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightTop)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightTop)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftTop)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftTop)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightTop)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightTop)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightBottom)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightBottom)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightTop)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightTop)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightTop)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightTop)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftBottom)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftBottom)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightBottom)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightBottom)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftBottom)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftBottom)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftTop)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftTop)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftTop)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftTop)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightTop)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightTop)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftTop)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftTop)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftTop)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftTop)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightBottom)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightBottom)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightTop)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightTop)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightBottom)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightBottom)); vertex++; - vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightBottom)); + vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightBottom)); vertex++; mapper.Unmap(); @@ -363,6 +363,11 @@ void NzDebugDrawer::Draw(const NzSkeleton* skeleton) } } +void NzDebugDrawer::Draw(const NzVector3f& position, float size) +{ + Draw(NzBoxf(position.x - size*0.5f, position.y - size*0.5f, position.z - size*0.5f, size, size, size)); +} + void NzDebugDrawer::DrawBinormals(const NzStaticMesh* subMesh) { if (!Initialize()) @@ -661,8 +666,8 @@ bool NzDebugDrawer::Initialize() // s_vertexBuffer try { - NzErrorFlags flags(nzErrorFlag_ThrowException); - s_vertexBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XYZ), 65365, nzBufferStorage_Hardware, nzBufferUsage_Dynamic); + NzErrorFlags flags(nzErrorFlag_ThrowException, true); + s_vertexBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XYZ), 65365, nzDataStorage_Hardware, nzBufferUsage_Dynamic); } catch (const std::exception& e) { diff --git a/src/Nazara/Renderer/GpuQuery.cpp b/src/Nazara/Renderer/GpuQuery.cpp index f015c1a32..37b03ebe7 100644 --- a/src/Nazara/Renderer/GpuQuery.cpp +++ b/src/Nazara/Renderer/GpuQuery.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Renderer/HardwareBuffer.cpp b/src/Nazara/Renderer/HardwareBuffer.cpp index f4f3b8c95..891ef6289 100644 --- a/src/Nazara/Renderer/HardwareBuffer.cpp +++ b/src/Nazara/Renderer/HardwareBuffer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Renderer/HardwareBuffer.hpp b/src/Nazara/Renderer/HardwareBuffer.hpp index 7c53970d7..5a7c9c107 100644 --- a/src/Nazara/Renderer/HardwareBuffer.hpp +++ b/src/Nazara/Renderer/HardwareBuffer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Renderer/OpenGL.cpp b/src/Nazara/Renderer/OpenGL.cpp index 3d57503a6..01f60a39f 100644 --- a/src/Nazara/Renderer/OpenGL.cpp +++ b/src/Nazara/Renderer/OpenGL.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -1072,7 +1072,7 @@ bool NzOpenGL::Initialize() } // DrawInstanced - if (s_openglVersion >= 330) + if (s_openglVersion >= 310) { try { @@ -1463,8 +1463,42 @@ void NzOpenGL::SetViewport(const NzRecti& viewport) bool NzOpenGL::TranslateFormat(nzPixelFormat pixelFormat, Format* format, FormatType type) { + // Par défaut + format->swizzle[0] = GL_RED; + format->swizzle[1] = GL_GREEN; + format->swizzle[2] = GL_BLUE; + format->swizzle[3] = GL_ALPHA; + switch (pixelFormat) { + case nzPixelFormat_A8: + if (type == FormatType_Texture) // Format supporté uniquement par les textures + { + if (GetVersion() >= 300) + { + format->dataFormat = GL_RED; + format->dataType = GL_UNSIGNED_BYTE; + format->internalFormat = GL_R8; + + // Simulation du format + format->swizzle[0] = GL_ONE; + format->swizzle[1] = GL_ONE; + format->swizzle[2] = GL_ONE; + format->swizzle[3] = GL_RED; + } + else + { + // Le bon vieux format GL_ALPHA + format->dataFormat = GL_ALPHA; + format->dataType = GL_UNSIGNED_BYTE; + format->internalFormat = GL_ALPHA; + } + + return true; + } + else + return false; + case nzPixelFormat_BGR8: format->dataFormat = GL_BGR; format->dataType = GL_UNSIGNED_BYTE; @@ -1496,8 +1530,58 @@ bool NzOpenGL::TranslateFormat(nzPixelFormat pixelFormat, Format* format, Format return true; case nzPixelFormat_L8: + if (type == FormatType_Texture) // Format supporté uniquement par les textures + { + if (GetVersion() >= 300) + { + format->dataFormat = GL_RED; + format->dataType = GL_UNSIGNED_BYTE; + format->internalFormat = GL_R8; + + // Simulation du format + format->swizzle[0] = GL_RED; + format->swizzle[1] = GL_RED; + format->swizzle[2] = GL_RED; + format->swizzle[3] = GL_ONE; + } + else + { + format->dataFormat = 0x1909; // GL_LUMINANCE + format->dataType = GL_UNSIGNED_BYTE; + format->internalFormat = 0x1909; // GL_LUMINANCE + } + + return true; + } + else + return false; + case nzPixelFormat_LA8: - return false; + if (type == FormatType_Texture) // Format supporté uniquement par les textures + { + if (GetVersion() >= 300) + { + format->dataFormat = GL_RG; + format->dataType = GL_UNSIGNED_BYTE; + format->internalFormat = GL_RG8; + + // Simulation du format + format->swizzle[0] = GL_RED; + format->swizzle[1] = GL_RED; + format->swizzle[2] = GL_RED; + format->swizzle[3] = GL_GREEN; + } + else + { + format->dataFormat = 0x190A; // GL_LUMINANCE_ALPHA + format->dataType = GL_UNSIGNED_BYTE; + format->internalFormat = 0x190A; // GL_LUMINANCE_ALPHA; + } + + return true; + } + else + return false; case nzPixelFormat_R8: format->dataFormat = GL_RED; @@ -1941,8 +2025,8 @@ GLenum NzOpenGL::CubemapFace[] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, // nzCubemapFace_PositiveX GL_TEXTURE_CUBE_MAP_NEGATIVE_X, // nzCubemapFace_NegativeX - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, // nzCubemapFace_PositiveY (Inversion pour les standards OpenGL) - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, // nzCubemapFace_NegativeY (Inversion pour les standards OpenGL) + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, // nzCubemapFace_PositiveY + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, // nzCubemapFace_NegativeY GL_TEXTURE_CUBE_MAP_POSITIVE_Z, // nzCubemapFace_PositiveZ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z // nzCubemapFace_NegativeZ }; @@ -1951,9 +2035,9 @@ static_assert(nzCubemapFace_Max+1 == 6, "Cubemap face array is incomplete"); GLenum NzOpenGL::FaceFilling[] = { - GL_POINT, // nzFaceFilling_Point + GL_FILL, // nzFaceFilling_Fill GL_LINE, // nzFaceFilling_Line - GL_FILL // nzFaceFilling_Fill + GL_POINT // nzFaceFilling_Point }; static_assert(nzFaceFilling_Max+1 == 3, "Face filling array is incomplete"); @@ -2104,16 +2188,16 @@ nzUInt8 NzOpenGL::VertexComponentIndex[] = 13, // nzVertexComponent_InstanceData3 14, // nzVertexComponent_InstanceData4 15, // nzVertexComponent_InstanceData5 + 4, // nzVertexComponent_Color 2, // nzVertexComponent_Normal 0, // nzVertexComponent_Position 3, // nzVertexComponent_Tangent 1, // nzVertexComponent_TexCoord - 4, // nzVertexComponent_Userdata0 - 5, // nzVertexComponent_Userdata1 - 6, // nzVertexComponent_Userdata2 - 7, // nzVertexComponent_Userdata3 - 8, // nzVertexComponent_Userdata4 - 9 // nzVertexComponent_Userdata5 + 5, // nzVertexComponent_Userdata0 + 6, // nzVertexComponent_Userdata1 + 7, // nzVertexComponent_Userdata2 + 8, // nzVertexComponent_Userdata3 + 9 // nzVertexComponent_Userdata4 }; static_assert(nzVertexComponent_Max+1 == 16, "Attribute index array is incomplete"); diff --git a/src/Nazara/Renderer/RenderBuffer.cpp b/src/Nazara/Renderer/RenderBuffer.cpp index 407a75a7d..c569742d5 100644 --- a/src/Nazara/Renderer/RenderBuffer.cpp +++ b/src/Nazara/Renderer/RenderBuffer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Renderer/RenderTarget.cpp b/src/Nazara/Renderer/RenderTarget.cpp index 2a72e88c1..47bd8db6d 100644 --- a/src/Nazara/Renderer/RenderTarget.cpp +++ b/src/Nazara/Renderer/RenderTarget.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Renderer/RenderTexture.cpp b/src/Nazara/Renderer/RenderTexture.cpp index 1a0c0119d..2cb238fcf 100644 --- a/src/Nazara/Renderer/RenderTexture.cpp +++ b/src/Nazara/Renderer/RenderTexture.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -18,8 +19,17 @@ namespace { struct Attachment { + Attachment(NzObjectListener* listener, int bufferIndex = 0, int textureIndex = 0) : + bufferListener(listener, bufferIndex), + textureListener(listener, textureIndex) + { + } + NzRenderBufferRef buffer; NzTextureRef texture; + // Les listeners doivent se trouver après les références (pour être libérés avant elles) + NzRenderBufferListener bufferListener; + NzTextureListener textureListener; nzAttachmentPoint attachmentPoint; bool isBuffer; @@ -50,11 +60,16 @@ namespace struct NzRenderTextureImpl { + NzRenderTextureImpl(NzObjectListener* listener, int contextIndex = 0) : + context(listener, contextIndex) + { + } + GLuint fbo; std::vector attachments; std::vector colorTargets; mutable std::vector drawBuffers; - const NzContext* context; + NzContextConstListener context; bool checked = false; bool complete = false; bool userDefinedTargets = false; @@ -138,20 +153,23 @@ bool NzRenderTexture::AttachBuffer(nzAttachmentPoint attachmentPoint, nzUInt8 in Unlock(); - unsigned int attachIndex = attachmentIndex[attachmentPoint]+index; - if (m_impl->attachments.size() <= attachIndex) - m_impl->attachments.resize(attachIndex+1); + unsigned int attachIndex = attachmentIndex[attachmentPoint] + index; + // On créé les attachements si ça n'a pas déjà été fait + for (unsigned int i = m_impl->attachments.size(); i <= attachIndex; ++i) + { + Attachment attachment(this, attachIndex, attachIndex); + m_impl->attachments.emplace_back(std::move(attachment)); + } Attachment& attachment = m_impl->attachments[attachIndex]; attachment.attachmentPoint = attachmentPoint; attachment.buffer = buffer; + attachment.bufferListener = buffer; attachment.isBuffer = true; attachment.isUsed = true; attachment.height = buffer->GetHeight(); attachment.width = buffer->GetWidth(); - buffer->AddObjectListener(this, attachIndex); - m_impl->checked = false; if (attachmentPoint == nzAttachmentPoint_Color && !m_impl->userDefinedTargets) @@ -282,9 +300,14 @@ bool NzRenderTexture::AttachTexture(nzAttachmentPoint attachmentPoint, nzUInt8 i Unlock(); - unsigned int attachIndex = attachmentIndex[attachmentPoint]+index; - if (m_impl->attachments.size() <= attachIndex) - m_impl->attachments.resize(attachIndex+1); + unsigned int attachIndex = attachmentIndex[attachmentPoint] + index; + + // On créé les attachements si ça n'a pas déjà été fait + for (unsigned int i = m_impl->attachments.size(); i <= attachIndex; ++i) + { + Attachment attachment(this, attachIndex, attachIndex); + m_impl->attachments.emplace_back(std::move(attachment)); + } Attachment& attachment = m_impl->attachments[attachIndex]; attachment.attachmentPoint = attachmentPoint; @@ -292,10 +315,9 @@ bool NzRenderTexture::AttachTexture(nzAttachmentPoint attachmentPoint, nzUInt8 i attachment.isUsed = true; attachment.height = texture->GetHeight(); attachment.texture = texture; + attachment.textureListener = texture; attachment.width = texture->GetWidth(); - texture->AddObjectListener(this, attachIndex); - m_impl->checked = false; if (attachmentPoint == nzAttachmentPoint_Color && !m_impl->userDefinedTargets) @@ -326,7 +348,7 @@ bool NzRenderTexture::Create(bool lock) } #endif - std::unique_ptr impl(new NzRenderTextureImpl); + std::unique_ptr impl(new NzRenderTextureImpl(this)); impl->fbo = 0; glGenFramebuffers(1, &impl->fbo); @@ -339,7 +361,6 @@ bool NzRenderTexture::Create(bool lock) m_impl = impl.release(); m_impl->context = NzContext::GetCurrent(); - m_impl->context->AddObjectListener(this); if (lock) { @@ -371,19 +392,6 @@ void NzRenderTexture::Destroy() if (IsActive()) NzRenderer::SetTarget(nullptr); - m_impl->context->RemoveObjectListener(this); - - for (const Attachment& attachment : m_impl->attachments) - { - if (attachment.isUsed) - { - if (attachment.isBuffer) - attachment.buffer->RemoveObjectListener(this); - else - attachment.texture->RemoveObjectListener(this); - } - } - // Le FBO devant être supprimé dans son contexte d'origine, nous déléguons sa suppression à la classe OpenGL // Celle-ci va libérer le FBO dès que possible (la prochaine fois que son contexte d'origine sera actif) NzOpenGL::DeleteFrameBuffer(m_impl->context, m_impl->fbo); @@ -409,7 +417,7 @@ void NzRenderTexture::Detach(nzAttachmentPoint attachmentPoint, nzUInt8 index) } #endif - unsigned int attachIndex = attachmentIndex[attachmentPoint]+index; + unsigned int attachIndex = attachmentIndex[attachmentPoint] + index; if (attachIndex >= m_impl->attachments.size()) return; @@ -429,7 +437,7 @@ void NzRenderTexture::Detach(nzAttachmentPoint attachmentPoint, nzUInt8 index) { glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, GL_RENDERBUFFER, 0); - attachement.buffer->RemoveObjectListener(this); + attachement.bufferListener = nullptr; attachement.buffer = nullptr; } else @@ -439,7 +447,7 @@ void NzRenderTexture::Detach(nzAttachmentPoint attachmentPoint, nzUInt8 index) else glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, 0, 0, 0); - attachement.texture->RemoveObjectListener(this); + attachement.textureListener = nullptr; attachement.texture = nullptr; } diff --git a/src/Nazara/Renderer/RenderWindow.cpp b/src/Nazara/Renderer/RenderWindow.cpp index 367399c09..3da301254 100644 --- a/src/Nazara/Renderer/RenderWindow.cpp +++ b/src/Nazara/Renderer/RenderWindow.cpp @@ -1,9 +1,10 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include +#include #include #include #include @@ -12,30 +13,18 @@ #include #include +///TODO: Améliorer les méthode CopyTo* + NzRenderWindow::NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters) { + NzErrorFlags flags(nzErrorFlag_ThrowException, true); Create(mode, title, style, parameters); - - #ifdef NAZARA_DEBUG - if (!m_impl) - { - NazaraError("Failed to create render window"); - throw std::runtime_error("Constructor failed"); - } - #endif } NzRenderWindow::NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters) { + NzErrorFlags flags(nzErrorFlag_ThrowException, true); Create(handle, parameters); - - #ifdef NAZARA_DEBUG - if (!m_impl) - { - NazaraError("Failed to create render window"); - throw std::runtime_error("Constructor failed"); - } - #endif } NzRenderWindow::~NzRenderWindow() @@ -331,4 +320,3 @@ void NzRenderWindow::OnWindowResized() { NotifySizeChange(); } - diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index 9c0c76375..343de29cc 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -35,6 +35,22 @@ namespace { + const nzUInt8 r_coreFragmentShader[] = { + #include + }; + + const nzUInt8 r_coreVertexShader[] = { + #include + }; + + const nzUInt8 r_compatibilityFragmentShader[] = { + #include + }; + + const nzUInt8 r_compatibilityVertexShader[] = { + #include + }; + enum ObjectType { ObjectType_Context, @@ -67,10 +83,38 @@ namespace bool samplerUpdated = false; }; - using VAO_Key = std::tuple; - using VAO_Map = std::map; + struct VAO_Entry + { + VAO_Entry(NzObjectListener* listener, int indexBufferIndex, int vertexBufferIndex, int vertexDeclarationIndex, int instancingDeclarationIndex) : + indexBufferListener(listener, indexBufferIndex), + vertexBufferListener(listener, vertexBufferIndex), + instancingDeclarationListener(listener, instancingDeclarationIndex), + vertexDeclarationListener(listener, vertexDeclarationIndex) + { + } - using Context_Map = std::unordered_map; + GLuint vao; + NzIndexBufferConstListener indexBufferListener; + NzVertexBufferConstListener vertexBufferListener; + NzVertexDeclarationConstListener instancingDeclarationListener; + NzVertexDeclarationConstListener vertexDeclarationListener; + }; + + using VAO_Key = std::tuple; + using VAO_Map = std::map; + + struct Context_Entry + { + Context_Entry(NzObjectListener* listener, int index) : + contextListener(listener, index) + { + } + + NzContextConstListener contextListener; + VAO_Map vaoMap; + }; + + using Context_Map = std::unordered_map; Context_Map s_vaos; std::vector s_dirtyTextureUnits; @@ -93,6 +137,7 @@ namespace bool s_useVertexArrayObjects; unsigned int s_maxColorAttachments; unsigned int s_maxRenderTarget; + unsigned int s_maxTextureSize; unsigned int s_maxTextureUnit; unsigned int s_maxVertexAttribs; @@ -116,7 +161,7 @@ namespace for (auto& pair : s_vaos) { const NzContext* context = pair.first; - VAO_Map& vaos = pair.second; + VAO_Map& vaos = pair.second.vaoMap; auto it = vaos.begin(); while (it != vaos.end()) @@ -131,7 +176,7 @@ namespace // son contexte d'origine est actif, sinon il faudra le mettre en file d'attente // Ceci est géré par la méthode OpenGL::DeleteVertexArray - NzOpenGL::DeleteVertexArray(context, it->second); + NzOpenGL::DeleteVertexArray(context, it->second.vao); vaos.erase(it++); } else @@ -147,7 +192,7 @@ namespace for (auto& pair : s_vaos) { const NzContext* context = pair.first; - VAO_Map& vaos = pair.second; + VAO_Map& vaos = pair.second.vaoMap; auto it = vaos.begin(); while (it != vaos.end()) @@ -162,7 +207,7 @@ namespace // son contexte d'origine est actif, sinon il faudra le mettre en file d'attente // Ceci est géré par la méthode OpenGL::DeleteVertexArray - NzOpenGL::DeleteVertexArray(context, it->second); + NzOpenGL::DeleteVertexArray(context, it->second.vao); vaos.erase(it++); } else @@ -178,7 +223,7 @@ namespace for (auto& pair : s_vaos) { const NzContext* context = pair.first; - VAO_Map& vaos = pair.second; + VAO_Map& vaos = pair.second.vaoMap; auto it = vaos.begin(); while (it != vaos.end()) @@ -194,7 +239,7 @@ namespace // son contexte d'origine est actif, sinon il faudra le mettre en file d'attente // Ceci est géré par la méthode OpenGL::DeleteVertexArray - NzOpenGL::DeleteVertexArray(context, it->second); + NzOpenGL::DeleteVertexArray(context, it->second.vao); vaos.erase(it++); } else @@ -376,7 +421,7 @@ void NzRenderer::DrawIndexedPrimitivesInstanced(unsigned int instanceCount, nzPr if (instanceCount == 0) { - NazaraError("Instance count must be over 0"); + NazaraError("Instance count must be over zero"); return; } @@ -471,7 +516,7 @@ void NzRenderer::DrawPrimitivesInstanced(unsigned int instanceCount, nzPrimitive if (instanceCount == 0) { - NazaraError("Instance count must be over 0"); + NazaraError("Instance count must be over zero"); return; } @@ -613,6 +658,11 @@ unsigned int NzRenderer::GetMaxRenderTargets() return s_maxRenderTarget; } +unsigned int NzRenderer::GetMaxTextureSize() +{ + return s_maxTextureSize; +} + unsigned int NzRenderer::GetMaxTextureUnits() { return s_maxTextureUnit; @@ -693,7 +743,10 @@ bool NzRenderer::Initialize() return false; } - NzBuffer::SetBufferFunction(nzBufferStorage_Hardware, [](NzBuffer* parent, nzBufferType type) -> NzAbstractBuffer* { return new NzHardwareBuffer(parent, type); } ); + NzBuffer::SetBufferFactory(nzDataStorage_Hardware, [](NzBuffer* parent, nzBufferType type) -> NzAbstractBuffer* + { + return new NzHardwareBuffer(parent, type); + }); for (unsigned int i = 0; i <= nzMatrixType_Max; ++i) { @@ -704,19 +757,19 @@ bool NzRenderer::Initialize() } // Récupération des capacités d'OpenGL - s_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter); - s_capabilities[nzRendererCap_ConditionalRendering] = NzOpenGL::IsSupported(nzOpenGLExtension_ConditionalRender); - s_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(nzOpenGLExtension_FP64); - s_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5 - s_capabilities[nzRendererCap_Instancing] = NzOpenGL::IsSupported(nzOpenGLExtension_DrawInstanced) && NzOpenGL::IsSupported(nzOpenGLExtension_InstancedArray); + s_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter); + s_capabilities[nzRendererCap_ConditionalRendering] = NzOpenGL::IsSupported(nzOpenGLExtension_ConditionalRender); + s_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(nzOpenGLExtension_FP64); + s_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5 + s_capabilities[nzRendererCap_Instancing] = NzOpenGL::IsSupported(nzOpenGLExtension_DrawInstanced) && NzOpenGL::IsSupported(nzOpenGLExtension_InstancedArray); s_capabilities[nzRendererCap_MultipleRenderTargets] = (glBindFragDataLocation != nullptr); // Natif depuis OpenGL 2.0 mais inutile sans glBindFragDataLocation - s_capabilities[nzRendererCap_OcclusionQuery] = true; // Natif depuis OpenGL 1.5 - s_capabilities[nzRendererCap_PixelBufferObject] = NzOpenGL::IsSupported(nzOpenGLExtension_PixelBufferObject); - s_capabilities[nzRendererCap_RenderTexture] = NzOpenGL::IsSupported(nzOpenGLExtension_FrameBufferObject); - s_capabilities[nzRendererCap_Texture3D] = true; // Natif depuis OpenGL 1.2 - s_capabilities[nzRendererCap_TextureCubemap] = true; // Natif depuis OpenGL 1.3 - s_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3 - s_capabilities[nzRendererCap_TextureNPOT] = true; // Natif depuis OpenGL 2.0 + s_capabilities[nzRendererCap_OcclusionQuery] = true; // Natif depuis OpenGL 1.5 + s_capabilities[nzRendererCap_PixelBufferObject] = NzOpenGL::IsSupported(nzOpenGLExtension_PixelBufferObject); + s_capabilities[nzRendererCap_RenderTexture] = NzOpenGL::IsSupported(nzOpenGLExtension_FrameBufferObject); + s_capabilities[nzRendererCap_Texture3D] = true; // Natif depuis OpenGL 1.2 + s_capabilities[nzRendererCap_TextureCubemap] = true; // Natif depuis OpenGL 1.3 + s_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3 + s_capabilities[nzRendererCap_TextureNPOT] = true; // Natif depuis OpenGL 2.0 NzContext::EnsureContext(); @@ -760,6 +813,10 @@ bool NzRenderer::Initialize() else s_maxTextureUnit = 1; + GLint maxTextureSize; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); + s_maxTextureSize = maxTextureSize; + GLint maxVertexAttribs; glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs); s_maxVertexAttribs = static_cast(maxVertexAttribs); @@ -776,7 +833,7 @@ bool NzRenderer::Initialize() s_updateFlags = Update_Matrices | Update_Shader | Update_VAO; s_vertexBuffer = nullptr; - s_fullscreenQuadBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XY), 4, nzBufferStorage_Hardware, nzBufferUsage_Static); + s_fullscreenQuadBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XY), 4, nzDataStorage_Hardware, nzBufferUsage_Static); float vertices[4*2] = { @@ -797,7 +854,7 @@ bool NzRenderer::Initialize() try { NzErrorFlags errFlags(nzErrorFlag_ThrowException, true); - s_instanceBuffer.Reset(nullptr, NAZARA_RENDERER_INSTANCE_BUFFER_SIZE, nzBufferStorage_Hardware, nzBufferUsage_Dynamic); + s_instanceBuffer.Reset(nullptr, NAZARA_RENDERER_INSTANCE_BUFFER_SIZE, nzDataStorage_Hardware, nzBufferUsage_Dynamic); } catch (const std::exception& e) { @@ -836,39 +893,23 @@ bool NzRenderer::Initialize() return false; } - const nzUInt8 coreFragmentShader[] = { - #include - }; - - const nzUInt8 coreVertexShader[] = { - #include - }; - - const nzUInt8 compatibilityFragmentShader[] = { - #include - }; - - const nzUInt8 compatibilityVertexShader[] = { - #include - }; - const char* fragmentShader; const char* vertexShader; unsigned int fragmentShaderLength; unsigned int vertexShaderLength; if (NzOpenGL::GetGLSLVersion() >= 140) { - fragmentShader = reinterpret_cast(coreFragmentShader); - fragmentShaderLength = sizeof(coreFragmentShader); - vertexShader = reinterpret_cast(coreVertexShader); - vertexShaderLength = sizeof(coreVertexShader); + fragmentShader = reinterpret_cast(r_coreFragmentShader); + fragmentShaderLength = sizeof(r_coreFragmentShader); + vertexShader = reinterpret_cast(r_coreVertexShader); + vertexShaderLength = sizeof(r_coreVertexShader); } else { - fragmentShader = reinterpret_cast(compatibilityFragmentShader); - fragmentShaderLength = sizeof(compatibilityFragmentShader); - vertexShader = reinterpret_cast(compatibilityVertexShader); - vertexShaderLength = sizeof(compatibilityVertexShader); + fragmentShader = reinterpret_cast(r_compatibilityFragmentShader); + fragmentShaderLength = sizeof(r_compatibilityFragmentShader); + vertexShader = reinterpret_cast(r_compatibilityVertexShader); + vertexShaderLength = sizeof(r_compatibilityVertexShader); } if (!shader->AttachStageFromSource(nzShaderStage_Fragment, fragmentShader, fragmentShaderLength)) @@ -925,7 +966,7 @@ bool NzRenderer::IsComponentTypeSupported(nzComponentType type) return false; } - NazaraError("Attribute type out of enum (0x" + NzString::Number(type, 16) + ')'); + NazaraError("Attribute type not handled (0x" + NzString::Number(type, 16) + ')'); return false; } @@ -1521,28 +1562,14 @@ void NzRenderer::Uninitialize() for (auto& pair : s_vaos) { const NzContext* context = pair.first; + const Context_Entry& contextEntry = pair.second; - for (auto& pair2 : pair.second) + for (auto& pair2 : contextEntry.vaoMap) { - const VAO_Key& key = pair2.first; - const NzIndexBuffer* indexBuffer = std::get<0>(key); - const NzVertexBuffer* vertexBuffer = std::get<1>(key); - const NzVertexDeclaration* vertexDeclaration = std::get<2>(key); - const NzVertexDeclaration* instancingDeclaration = std::get<3>(key); - - if (indexBuffer) - indexBuffer->RemoveObjectListener(&s_listener); - - vertexBuffer->RemoveObjectListener(&s_listener); - vertexDeclaration->RemoveObjectListener(&s_listener); - - if (instancingDeclaration) - instancingDeclaration->RemoveObjectListener(&s_listener); - - NzOpenGL::DeleteVertexArray(context, pair2.second); + const VAO_Entry& entry = pair2.second; + NzOpenGL::DeleteVertexArray(context, entry.vao); } } - s_vaos.clear(); NzOpenGL::Uninitialize(); @@ -1707,16 +1734,16 @@ bool NzRenderer::EnsureStateUpdate() // Note: Les VAOs ne sont pas partagés entre les contextes, nous avons donc un tableau de VAOs par contexte const NzContext* context = NzContext::GetCurrent(); - VAO_Map* vaos; auto it = s_vaos.find(context); if (it == s_vaos.end()) { - context->AddObjectListener(&s_listener, ObjectType_Context); - auto pair = s_vaos.insert(std::make_pair(context, Context_Map::mapped_type())); - vaos = &pair.first->second; + Context_Entry entry(&s_listener, ObjectType_Context); + entry.contextListener = context; + + it = s_vaos.insert(std::make_pair(context, std::move(entry))).first; } - else - vaos = &it->second; + + VAO_Map& vaoMap = it->second.vaoMap; // Notre clé est composée de ce qui définit un VAO const NzVertexDeclaration* vertexDeclaration = s_vertexBuffer->GetVertexDeclaration(); @@ -1724,23 +1751,22 @@ bool NzRenderer::EnsureStateUpdate() VAO_Key key(s_indexBuffer, s_vertexBuffer, vertexDeclaration, instancingDeclaration); // On recherche un VAO existant avec notre configuration - vaoIt = vaos->find(key); - if (vaoIt == vaos->end()) + vaoIt = vaoMap.find(key); + if (vaoIt == vaoMap.end()) { // On créé notre VAO glGenVertexArrays(1, &s_currentVAO); glBindVertexArray(s_currentVAO); // On l'ajoute à notre liste - vaoIt = vaos->insert(std::make_pair(key, s_currentVAO)).first; - if (s_indexBuffer) - s_indexBuffer->AddObjectListener(&s_listener, ObjectType_IndexBuffer); + VAO_Entry entry(&s_listener, ObjectType_IndexBuffer, ObjectType_VertexBuffer, ObjectType_VertexDeclaration, ObjectType_VertexDeclaration); + entry.indexBufferListener = std::get<0>(key); + entry.instancingDeclarationListener = std::get<3>(key); + entry.vertexBufferListener = std::get<1>(key); + entry.vertexDeclarationListener = std::get<2>(key); + entry.vao = s_currentVAO; - s_vertexBuffer->AddObjectListener(&s_listener, ObjectType_VertexBuffer); - vertexDeclaration->AddObjectListener(&s_listener, ObjectType_VertexDeclaration); - - if (instancingDeclaration) - instancingDeclaration->AddObjectListener(&s_listener, ObjectType_VertexDeclaration); + vaoIt = vaoMap.insert(std::make_pair(key, std::move(entry))).first; // Et on indique qu'on veut le programmer update = true; @@ -1748,7 +1774,7 @@ bool NzRenderer::EnsureStateUpdate() else { // Notre VAO existe déjà, il est donc inutile de le reprogrammer - s_currentVAO = vaoIt->second; + s_currentVAO = vaoIt->second.vao; update = false; } @@ -1787,15 +1813,15 @@ bool NzRenderer::EnsureStateUpdate() unsigned int offset; vertexDeclaration->GetComponent(static_cast(j), &enabled, &type, &offset); - if (!IsComponentTypeSupported(type)) - { - NazaraError("Invalid vertex declaration " + NzString::Pointer(vertexDeclaration) + ": Vertex component 0x" + NzString::Number(j, 16) + " (type: 0x" + NzString::Number(type, 16) + ") is not supported"); - updateFailed = true; - break; - } - if (enabled) { + if (!IsComponentTypeSupported(type)) + { + NazaraError("Invalid vertex declaration " + NzString::Pointer(vertexDeclaration) + ": Vertex component 0x" + NzString::Number(j, 16) + " (type: 0x" + NzString::Number(type, 16) + ") is not supported"); + updateFailed = true; + break; + } + glEnableVertexAttribArray(NzOpenGL::VertexComponentIndex[j]); switch (type) @@ -1857,7 +1883,7 @@ bool NzRenderer::EnsureStateUpdate() default: { - NazaraInternalError("Unsupported component type"); + NazaraInternalError("Unsupported component type (0x" + NzString::Number(type, 16) + ')'); break; } } @@ -1899,8 +1925,8 @@ bool NzRenderer::EnsureStateUpdate() if (updateFailed) { // La création de notre VAO a échoué, libérons-le et marquons-le comme problématique - glDeleteVertexArrays(1, &vaoIt->second); - vaoIt->second = 0; + glDeleteVertexArrays(1, &vaoIt->second.vao); + vaoIt->second.vao = 0; s_currentVAO = 0; } else @@ -1964,7 +1990,8 @@ void NzRenderer::OnTextureReleased(const NzTexture* texture) { if (unit.texture == texture) unit.texture = nullptr; - // Inutile de changer le flag pour une texture désactivée + + // Inutile de changer le flag pour une texture désactivée } } diff --git a/src/Nazara/Renderer/Shader.cpp b/src/Nazara/Renderer/Shader.cpp index 699e36442..21fd03a55 100644 --- a/src/Nazara/Renderer/Shader.cpp +++ b/src/Nazara/Renderer/Shader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -16,17 +16,6 @@ m_program(0) { } -NzShader::NzShader(NzShader&& shader) : -m_linked(shader.m_linked), -m_program(shader.m_program) -{ - for (unsigned int i = 0; i <= nzShaderStage_Max; ++i) - m_attachedShaders[i] = std::move(shader.m_attachedShaders[i]); - - shader.m_linked = false; - shader.m_program = 0; -} - NzShader::~NzShader() { Destroy(); @@ -155,6 +144,7 @@ bool NzShader::Create() glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_InstanceData3], "InstanceData3"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_InstanceData4], "InstanceData4"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_InstanceData5], "InstanceData5"); + glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Color], "VertexColor"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Normal], "VertexNormal"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Position], "VertexPosition"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Tangent], "VertexTangent"); @@ -164,7 +154,6 @@ bool NzShader::Create() glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Userdata2], "VertexUserdata2"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Userdata3], "VertexUserdata3"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Userdata4], "VertexUserdata4"); - glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Userdata5], "VertexUserdata5"); if (NzRenderer::HasCapability(nzRendererCap_MultipleRenderTargets)) { @@ -254,10 +243,10 @@ NzString NzShader::GetSourceCode(nzShaderStage stage) const unsigned int totalLength = 0; for (unsigned int shader : m_attachedShaders[stage]) { - GLint length; - glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &length); + GLint length; + glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &length); - totalLength += length - 1; + totalLength += length - 1; } totalLength += (m_attachedShaders[stage].size()-1)*(sizeof(sep)/sizeof(char)); @@ -757,22 +746,6 @@ unsigned int NzShader::GetOpenGLID() const return m_program; } -NzShader& NzShader::operator=(NzShader&& shader) -{ - Destroy(); - - for (unsigned int i = 0; i <= nzShaderStage_Max; ++i) - m_attachedShaders[i] = std::move(shader.m_attachedShaders[i]); - - m_linked = shader.m_linked; - m_program = shader.m_program; - - shader.m_linked = false; - shader.m_program = 0; - - return *this; -} - bool NzShader::IsStageSupported(nzShaderStage stage) { return NzShaderStage::IsSupported(stage); @@ -789,7 +762,6 @@ bool NzShader::PostLinkage() // Pour éviter de se tromper entre le nom et la constante #define CacheUniform(name) m_uniformLocations[nzShaderUniform_##name] = glGetUniformLocation(m_program, #name) - CacheUniform(EyePosition); CacheUniform(InvProjMatrix); CacheUniform(InvTargetSize); CacheUniform(InvViewMatrix); @@ -798,7 +770,6 @@ bool NzShader::PostLinkage() CacheUniform(InvWorldViewMatrix); CacheUniform(InvWorldViewProjMatrix); CacheUniform(ProjMatrix); - CacheUniform(SceneAmbient); CacheUniform(TargetSize); CacheUniform(ViewMatrix); CacheUniform(ViewProjMatrix); diff --git a/src/Nazara/Renderer/ShaderLibrary.cpp b/src/Nazara/Renderer/ShaderLibrary.cpp index 316a6019b..a474ae6d4 100644 --- a/src/Nazara/Renderer/ShaderLibrary.cpp +++ b/src/Nazara/Renderer/ShaderLibrary.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Renderer/ShaderStage.cpp b/src/Nazara/Renderer/ShaderStage.cpp index b3a3c421a..c45757192 100644 --- a/src/Nazara/Renderer/ShaderStage.cpp +++ b/src/Nazara/Renderer/ShaderStage.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index c534f5cdd..f9ae3e810 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -1,12 +1,15 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include +#include #include #include #include +#include #include #include #include @@ -26,112 +29,10 @@ struct NzTextureImpl namespace { - bool CreateTexture(NzTextureImpl* impl, bool proxy) + inline unsigned int GetLevelSize(unsigned int size, nzUInt8 level) { - NzOpenGL::Format openGLFormat; - if (!NzOpenGL::TranslateFormat(impl->format, &openGLFormat, NzOpenGL::FormatType_Texture)) - { - NazaraError("Format " + NzPixelFormat::ToString(impl->format) + " not supported by OpenGL"); - return false; - } - - GLenum target = (proxy) ? NzOpenGL::TextureTargetProxy[impl->type] : NzOpenGL::TextureTarget[impl->type]; - switch (impl->type) - { - case nzImageType_1D: - { - if (glTexStorage1D && !proxy) // Les drivers AMD semblent ne pas aimer glTexStorage avec un format proxy - glTexStorage1D(target, impl->levelCount, openGLFormat.internalFormat, impl->width); - else - { - unsigned int w = impl->width; - for (nzUInt8 level = 0; level < impl->levelCount; ++level) - { - glTexImage1D(target, level, openGLFormat.internalFormat, w, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr); - if (w > 1U) - w >>= 1; - } - } - break; - } - - case nzImageType_1D_Array: - case nzImageType_2D: - { - if (glTexStorage2D && !proxy) - glTexStorage2D(target, impl->levelCount, openGLFormat.internalFormat, impl->width, impl->height); - else - { - unsigned int w = impl->width; - unsigned int h = impl->height; - for (nzUInt8 level = 0; level < impl->levelCount; ++level) - { - glTexImage2D(target, level, openGLFormat.internalFormat, w, h, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr); - if (w > 1U) - w >>= 1; - - if (h > 1U) - h >>= 1; - } - } - break; - } - - case nzImageType_2D_Array: - case nzImageType_3D: - { - if (glTexStorage3D && !proxy) - glTexStorage3D(target, impl->levelCount, openGLFormat.internalFormat, impl->width, impl->height, impl->depth); - else - { - unsigned int w = impl->width; - unsigned int h = impl->height; - unsigned int d = impl->depth; - for (nzUInt8 level = 0; level < impl->levelCount; ++level) - { - glTexImage3D(target, level, openGLFormat.internalFormat, w, h, d, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr); - if (w > 1U) - w >>= 1; - - if (h > 1U) - h >>= 1; - - if (d > 1U) - d >>= 1; - } - } - break; - } - - case nzImageType_Cubemap: - { - if (glTexStorage2D && !proxy) - glTexStorage2D(target, impl->levelCount, openGLFormat.internalFormat, impl->width, impl->height); - else - { - unsigned int size = impl->width; // Les cubemaps ont une longueur et largeur identique - for (nzUInt8 level = 0; level < impl->levelCount; ++level) - { - for (GLenum face : NzOpenGL::CubemapFace) - glTexImage2D(face, level, openGLFormat.internalFormat, size, size, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr); - - if (size > 1U) - size >>= 1; - } - } - break; - } - } - - if (proxy) - { - GLint internalFormat = 0; - glGetTexLevelParameteriv(target, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalFormat); - if (internalFormat == 0) - return false; - } - - return true; + // Contrairement à la classe Image, un appel à GetLevelSize(0, level) n'est pas possible + return std::max(size >> level, 1U); } inline void SetUnpackAlignement(nzUInt8 bpp) @@ -147,17 +48,16 @@ namespace } } +NzTexture::NzTexture(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount) +{ + NzErrorFlags flags(nzErrorFlag_ThrowException); + Create(type, format, width, height, depth, levelCount); +} + NzTexture::NzTexture(const NzImage& image) { + NzErrorFlags flags(nzErrorFlag_ThrowException); LoadFromImage(image); - - #ifdef NAZARA_DEBUG - if (!m_impl) - { - NazaraError("Failed to create texture"); - throw std::runtime_error("Constructor failed"); - } - #endif } NzTexture::~NzTexture() @@ -218,7 +118,7 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt if (depth > 1) { - NazaraError("1D textures must be 1 depth"); + NazaraError("1D textures must be 1 deep"); return false; } break; @@ -227,7 +127,7 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt case nzImageType_2D: if (depth > 1) { - NazaraError("2D textures must be 1 depth"); + NazaraError("2D textures must be 1 deep"); return false; } break; @@ -239,7 +139,7 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt case nzImageType_Cubemap: if (depth > 1) { - NazaraError("Cubemaps must be 1 depth"); + NazaraError("Cubemaps must be 1 deep"); return false; } @@ -262,40 +162,44 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt levelCount = 1; } - std::unique_ptr impl(new NzTextureImpl); - glGenTextures(1, &impl->id); + m_impl = new NzTextureImpl; + m_impl->depth = GetValidSize(depth); + m_impl->format = format; + m_impl->height = GetValidSize(height); + m_impl->levelCount = levelCount; + m_impl->type = type; + m_impl->width = GetValidSize(width); - impl->depth = GetValidSize(depth); - impl->format = format; - impl->height = GetValidSize(height); - impl->levelCount = levelCount; - impl->type = type; - impl->width = GetValidSize(width); + glGenTextures(1, &m_impl->id); + NzOpenGL::BindTexture(m_impl->type, m_impl->id); - NzOpenGL::BindTexture(impl->type, impl->id); - - // Vérification du support par la carte graphique - if (!CreateTexture(impl.get(), true)) + // En cas d'erreur (sortie prématurée), on détruit la texture + NzCallOnExit onExit([this]() { - NzOpenGL::DeleteTexture(m_impl->id); + Destroy(); + }); + // On précise le nombre de mipmaps avant la spécification de la texture + // https://www.opengl.org/wiki/Hardware_specifics:_NVidia + SetMipmapRange(0, m_impl->levelCount-1); + if (m_impl->levelCount > 1U) + EnableMipmapping(true); + + // Vérification du support par la carte graphique (texture proxy) + if (!CreateTexture(true)) + { NazaraError("Texture's parameters not supported by driver"); return false; } // Création de la texture - if (!CreateTexture(impl.get(), false)) + if (!CreateTexture(false)) { - NzOpenGL::DeleteTexture(m_impl->id); - NazaraError("Failed to create texture"); return false; } - m_impl = impl.release(); - - if (m_impl->levelCount > 1U) - EnableMipmapping(true); + onExit.Reset(); NotifyCreated(); return true; @@ -344,29 +248,10 @@ bool NzTexture::Download(NzImage* image) const return false; } - unsigned int width = m_impl->width; - unsigned int height = m_impl->height; - unsigned int depth = m_impl->depth; - // Téléchargement... NzOpenGL::BindTexture(m_impl->type, m_impl->id); for (nzUInt8 level = 0; level < m_impl->levelCount; ++level) - { - glGetTexImage(NzOpenGL::TextureTarget[m_impl->type], level, format.dataFormat, format.dataType, image->GetPixels(level)); - - if (width > 1) - width >>= 1; - - if (height > 1) - height >>= 1; - - if (depth > 1) - depth >>= 1; - } - - // Inversion de la texture pour le repère d'OpenGL - if (!image->FlipVertically()) - NazaraWarning("Failed to flip image"); + glGetTexImage(NzOpenGL::TextureTarget[m_impl->type], level, format.dataFormat, format.dataType, image->GetPixels(0, 0, 0, level)); return true; } @@ -388,7 +273,11 @@ bool NzTexture::EnableMipmapping(bool enable) } if (m_impl->levelCount == 1) // Transformation d'une texture sans mipmaps vers une texture avec mipmaps + { + ///FIXME: Est-ce que cette opération est seulement possible ? m_impl->levelCount = NzImage::GetMaxLevel(m_impl->width, m_impl->height, m_impl->depth); + SetMipmapRange(0, m_impl->levelCount-1); + } if (!m_impl->mipmapping && enable) m_impl->mipmapsUpdated = false; @@ -408,7 +297,7 @@ void NzTexture::EnsureMipmapsUpdate() const } } -nzUInt8 NzTexture::GetBytesPerPixel() const +unsigned int NzTexture::GetDepth(nzUInt8 level) const { #if NAZARA_RENDERER_SAFE if (!m_impl) @@ -418,20 +307,7 @@ nzUInt8 NzTexture::GetBytesPerPixel() const } #endif - return NzPixelFormat::GetBytesPerPixel(m_impl->format); -} - -unsigned int NzTexture::GetDepth() const -{ - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return 0; - } - #endif - - return m_impl->depth; + return GetLevelSize(m_impl->depth, level); } nzPixelFormat NzTexture::GetFormat() const @@ -447,7 +323,7 @@ nzPixelFormat NzTexture::GetFormat() const return m_impl->format; } -unsigned int NzTexture::GetHeight() const +unsigned int NzTexture::GetHeight(nzUInt8 level) const { #if NAZARA_RENDERER_SAFE if (!m_impl) @@ -457,10 +333,10 @@ unsigned int NzTexture::GetHeight() const } #endif - return m_impl->height; + return GetLevelSize(m_impl->height, level); } -NzVector2ui NzTexture::GetSize() const +nzUInt8 NzTexture::GetLevelCount() const { #if NAZARA_RENDERER_SAFE if (!m_impl) @@ -470,7 +346,90 @@ NzVector2ui NzTexture::GetSize() const } #endif - return NzVector2ui(m_impl->width, m_impl->height); + return m_impl->levelCount; +} + +nzUInt8 NzTexture::GetMaxLevel() const +{ + #if NAZARA_RENDERER_SAFE + if (!m_impl) + { + NazaraError("Texture must be valid"); + return 0; + } + #endif + + return NzImage::GetMaxLevel(m_impl->type, m_impl->width, m_impl->height, m_impl->depth); +} + +unsigned int NzTexture::GetMemoryUsage() const +{ + #if NAZARA_RENDERER_SAFE + if (!m_impl) + { + NazaraError("Texture must be valid"); + return 0; + } + #endif + + unsigned int width = m_impl->width; + unsigned int height = m_impl->height; + unsigned int depth = m_impl->depth; + + unsigned int size = 0; + for (unsigned int i = 0; i < m_impl->levelCount; ++i) + { + size += width * height * depth; + + if (width > 1) + width >>= 1; + + if (height > 1) + height >>= 1; + + if (depth > 1) + depth >>= 1; + } + + if (m_impl->type == nzImageType_Cubemap) + size *= 6; + + return size * NzPixelFormat::GetBytesPerPixel(m_impl->format); +} + +unsigned int NzTexture::GetMemoryUsage(nzUInt8 level) const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Texture must be valid"); + return 0; + } + + if (level >= m_impl->levelCount) + { + NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_impl->levelCount) + ')'); + return 0; + } + #endif + + return (GetLevelSize(m_impl->width, level)) * + (GetLevelSize(m_impl->height, level)) * + ((m_impl->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_impl->depth, level)) * + NzPixelFormat::GetBytesPerPixel(m_impl->format); +} + +NzVector3ui NzTexture::GetSize(nzUInt8 level) const +{ + #if NAZARA_RENDERER_SAFE + if (!m_impl) + { + NazaraError("Texture must be valid"); + return NzVector3ui(0, 0, 0); + } + #endif + + return NzVector3ui(GetLevelSize(m_impl->width, level), GetLevelSize(m_impl->height, level), GetLevelSize(m_impl->depth, level)); } nzImageType NzTexture::GetType() const @@ -486,7 +445,7 @@ nzImageType NzTexture::GetType() const return m_impl->type; } -unsigned int NzTexture::GetWidth() const +unsigned int NzTexture::GetWidth(nzUInt8 level) const { #if NAZARA_RENDERER_SAFE if (!m_impl) @@ -496,7 +455,7 @@ unsigned int NzTexture::GetWidth() const } #endif - return m_impl->width; + return GetLevelSize(m_impl->width, level); } bool NzTexture::HasMipmaps() const @@ -512,30 +471,17 @@ bool NzTexture::HasMipmaps() const return m_impl->levelCount > 1; } -bool NzTexture::IsCompressed() const +void NzTexture::InvalidateMipmaps() { #if NAZARA_RENDERER_SAFE if (!m_impl) { - NazaraError("Texture must be valid"); - return false; + NazaraInternalError("Texture must be valid"); + return; } #endif - return NzPixelFormat::IsCompressed(m_impl->format); -} - -bool NzTexture::IsCubemap() const -{ - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return false; - } - #endif - - return m_impl->type == nzImageType_Cubemap; + m_impl->mipmapsUpdated = false; } bool NzTexture::IsValid() const @@ -571,6 +517,7 @@ bool NzTexture::LoadFromImage(const NzImage& image, bool generateMipmaps) nzPixelFormat format = newImage.GetFormat(); if (!IsFormatSupported(format)) { + ///TODO: Sélectionner le format le plus adapté selon les composantes présentes dans le premier format nzPixelFormat newFormat = (NzPixelFormat::HasAlpha(format)) ? nzPixelFormat_BGRA8 : nzPixelFormat_BGR8; NazaraWarning("Format " + NzPixelFormat::ToString(format) + " not supported, trying to convert it to " + NzPixelFormat::ToString(newFormat) + "..."); @@ -602,17 +549,20 @@ bool NzTexture::LoadFromImage(const NzImage& image, bool generateMipmaps) return false; } + NzCallOnExit destroyOnExit([this]() + { + Destroy(); + }); + if (type == nzImageType_Cubemap) { for (nzUInt8 level = 0; level < levelCount; ++level) { for (unsigned int i = 0; i <= nzCubemapFace_Max; ++i) { - if (!UpdateFace(static_cast(i), newImage.GetConstPixels(0, 0, i, level), level)) + if (!Update(newImage.GetConstPixels(0, 0, i, level), NzRectui(0, 0, newImage.GetWidth(level), newImage.GetHeight(level)), i, level)) { NazaraError("Failed to update texture"); - Destroy(); - return false; } } @@ -625,13 +575,13 @@ bool NzTexture::LoadFromImage(const NzImage& image, bool generateMipmaps) if (!Update(newImage.GetConstPixels(0, 0, 0, level), level)) { NazaraError("Failed to update texture"); - Destroy(); - return false; } } } + destroyOnExit.Reset(); + return true; } @@ -659,124 +609,100 @@ bool NzTexture::LoadFromStream(NzInputStream& stream, const NzImageParams& param return LoadFromImage(image, generateMipmaps); } -bool NzTexture::LoadCubemapFromFile(const NzString& filePath, const NzImageParams& imageParams, bool generateMipmaps, const NzCubemapParams& cubemapParams) +bool NzTexture::LoadArrayFromFile(const NzString& filePath, const NzImageParams& imageParams, bool generateMipmaps, const NzVector2ui& atlasSize) { - NzImage image; - if (!image.LoadFromFile(filePath, imageParams)) + NzImage cubemap; + if (!cubemap.LoadArrayFromFile(filePath, imageParams, atlasSize)) { - NazaraError("Failed to load image"); + NazaraError("Failed to load cubemap"); return false; } - return LoadCubemapFromImage(image, generateMipmaps, cubemapParams); + return LoadFromImage(cubemap, generateMipmaps); +} + +bool NzTexture::LoadArrayFromImage(const NzImage& image, bool generateMipmaps, const NzVector2ui& atlasSize) +{ + NzImage cubemap; + if (!cubemap.LoadArrayFromImage(image, atlasSize)) + { + NazaraError("Failed to load cubemap"); + return false; + } + + return LoadFromImage(cubemap, generateMipmaps); +} + +bool NzTexture::LoadArrayFromMemory(const void* data, std::size_t size, const NzImageParams& imageParams, bool generateMipmaps, const NzVector2ui& atlasSize) +{ + NzImage cubemap; + if (!cubemap.LoadArrayFromMemory(data, size, imageParams, atlasSize)) + { + NazaraError("Failed to load cubemap"); + return false; + } + + return LoadFromImage(cubemap, generateMipmaps); +} + +bool NzTexture::LoadArrayFromStream(NzInputStream& stream, const NzImageParams& imageParams, bool generateMipmaps, const NzVector2ui& atlasSize) +{ + NzImage cubemap; + if (!cubemap.LoadArrayFromStream(stream, imageParams, atlasSize)) + { + NazaraError("Failed to load cubemap"); + return false; + } + + return LoadFromImage(cubemap, generateMipmaps); +} + +bool NzTexture::LoadCubemapFromFile(const NzString& filePath, const NzImageParams& imageParams, bool generateMipmaps, const NzCubemapParams& cubemapParams) +{ + NzImage cubemap; + if (!cubemap.LoadCubemapFromFile(filePath, imageParams, cubemapParams)) + { + NazaraError("Failed to load cubemap"); + return false; + } + + return LoadFromImage(cubemap, generateMipmaps); } bool NzTexture::LoadCubemapFromImage(const NzImage& image, bool generateMipmaps, const NzCubemapParams& params) { - // Implémentation presque identique à celle de Image::LoadCubemapFromImage - #if NAZARA_UTILITY_SAFE - if (!image.IsValid()) + NzImage cubemap; + if (!cubemap.LoadCubemapFromImage(image, params)) { - NazaraError("Image must be valid"); - return false; - } - #endif - - unsigned int width = image.GetWidth(); - unsigned int height = image.GetHeight(); - unsigned int faceSize = (params.faceSize == 0) ? std::max(width, height)/4 : params.faceSize; - - // Sans cette vérification, celles des rectangles pourrait réussir via un overflow - if (width < faceSize || height < faceSize) - { - NazaraError("Image is too small for this face size"); + NazaraError("Failed to load cubemap"); return false; } - // Calcul et vérification des surfaces - unsigned limitX = width - faceSize; - unsigned limitY = height - faceSize; - - NzVector2ui backPos = params.backPosition * faceSize; - if (backPos.x > limitX || backPos.y > limitY) - { - NazaraError("Back rectangle is out of image"); - return false; - } - - NzVector2ui downPos = params.downPosition * faceSize; - if (downPos.x > limitX || downPos.y > limitY) - { - NazaraError("Down rectangle is out of image"); - return false; - } - - NzVector2ui forwardPos = params.forwardPosition * faceSize; - if (forwardPos.x > limitX || forwardPos.y > limitY) - { - NazaraError("Forward rectangle is out of image"); - return false; - } - - NzVector2ui leftPos = params.leftPosition * faceSize; - if (leftPos.x > limitX || leftPos.y > limitY) - { - NazaraError("Left rectangle is out of image"); - return false; - } - - NzVector2ui rightPos = params.rightPosition * faceSize; - if (rightPos.x > limitX || rightPos.y > limitY) - { - NazaraError("Right rectangle is out of image"); - return false; - } - - NzVector2ui upPos = params.upPosition * faceSize; - if (upPos.x > limitX || upPos.y > limitY) - { - NazaraError("Up rectangle is out of image"); - return false; - } - - if (!Create(nzImageType_Cubemap, image.GetFormat(), faceSize, faceSize, 1, (generateMipmaps) ? 0xFF : 1)) - { - NazaraError("Failed to create texture"); - return false; - } - - UpdateFace(nzCubemapFace_NegativeX, image.GetConstPixels(leftPos.x, leftPos.y), width, height); - UpdateFace(nzCubemapFace_NegativeY, image.GetConstPixels(downPos.x, downPos.y), width, height); - UpdateFace(nzCubemapFace_NegativeZ, image.GetConstPixels(backPos.x, backPos.y), width, height); - UpdateFace(nzCubemapFace_PositiveX, image.GetConstPixels(rightPos.x, rightPos.y), width, height); - UpdateFace(nzCubemapFace_PositiveY, image.GetConstPixels(upPos.x, upPos.y), width, height); - UpdateFace(nzCubemapFace_PositiveZ, image.GetConstPixels(forwardPos.x, forwardPos.y), width, height); - - return true; + return LoadFromImage(cubemap, generateMipmaps); } bool NzTexture::LoadCubemapFromMemory(const void* data, std::size_t size, const NzImageParams& imageParams, bool generateMipmaps, const NzCubemapParams& cubemapParams) { - NzImage image; - if (!image.LoadFromMemory(data, size, imageParams)) + NzImage cubemap; + if (!cubemap.LoadCubemapFromMemory(data, size, imageParams, cubemapParams)) { - NazaraError("Failed to load image"); + NazaraError("Failed to load cubemap"); return false; } - return LoadCubemapFromImage(image, generateMipmaps, cubemapParams); + return LoadFromImage(cubemap, generateMipmaps); } bool NzTexture::LoadCubemapFromStream(NzInputStream& stream, const NzImageParams& imageParams, bool generateMipmaps, const NzCubemapParams& cubemapParams) { - NzImage image; - if (!image.LoadFromStream(stream, imageParams)) + NzImage cubemap; + if (!cubemap.LoadCubemapFromStream(stream, imageParams, cubemapParams)) { - NazaraError("Failed to load image"); + NazaraError("Failed to load cubemap"); return false; } - return LoadCubemapFromImage(image, generateMipmaps, cubemapParams); + return LoadFromImage(cubemap, generateMipmaps); } bool NzTexture::LoadFaceFromFile(nzCubemapFace face, const NzString& filePath, const NzImageParams& params) @@ -809,14 +735,13 @@ bool NzTexture::LoadFaceFromFile(nzCubemapFace face, const NzString& filePath, c } unsigned int faceSize = m_impl->width; - if (image.GetWidth() != faceSize || image.GetHeight() != faceSize) { NazaraError("Image size must match texture face size"); return false; } - return UpdateFace(face, image); + return Update(image, NzRectui(0, 0, faceSize, faceSize), face); } bool NzTexture::LoadFaceFromMemory(nzCubemapFace face, const void* data, std::size_t size, const NzImageParams& params) @@ -849,14 +774,13 @@ bool NzTexture::LoadFaceFromMemory(nzCubemapFace face, const void* data, std::si } unsigned int faceSize = m_impl->width; - if (image.GetWidth() != faceSize || image.GetHeight() != faceSize) { NazaraError("Image size must match texture face size"); return false; } - return UpdateFace(face, image); + return Update(image, NzRectui(0, 0, faceSize, faceSize), face); } bool NzTexture::LoadFaceFromStream(nzCubemapFace face, NzInputStream& stream, const NzImageParams& params) @@ -896,7 +820,7 @@ bool NzTexture::LoadFaceFromStream(nzCubemapFace face, NzInputStream& stream, co return false; } - return UpdateFace(face, image); + return Update(image, NzRectui(0, 0, faceSize, faceSize), face); } bool NzTexture::SetMipmapRange(nzUInt8 minLevel, nzUInt8 maxLevel) @@ -1016,7 +940,7 @@ bool NzTexture::Update(const nzUInt8* pixels, unsigned int srcWidth, unsigned in } #endif - return Update(pixels, NzBoxui(std::max(m_impl->width >> level, 1U), std::max(m_impl->height >> level, 1U), std::max(m_impl->depth >> level, 1U)), srcWidth, srcHeight, level); + return Update(pixels, NzBoxui(GetLevelSize(m_impl->width, level), GetLevelSize(m_impl->height, level), GetLevelSize(m_impl->depth, level)), srcWidth, srcHeight, level); } bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level) @@ -1028,12 +952,6 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int s return false; } - if (m_impl->type == nzImageType_Cubemap) - { - NazaraError("Update is not designed for cubemaps, use UpdateFace instead"); - return false; - } - if (!pixels) { NazaraError("Invalid pixel source"); @@ -1047,12 +965,13 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int s } #endif - unsigned int height = std::max(m_impl->height >> level, 1U); + unsigned int height = GetLevelSize(m_impl->height, level); #if NAZARA_RENDERER_SAFE - if (box.x+box.width > std::max(m_impl->width >> level, 1U) || - box.y+box.height > height || - box.z+box.depth > std::max(m_impl->depth >> level, 1U)) + unsigned int width = GetLevelSize(m_impl->width, level); + unsigned int depth = (m_impl->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_impl->depth, level); + if (box.x+box.width > width || box.y+box.height > height || box.z+box.depth > depth || + (m_impl->type == nzImageType_Cubemap && box.depth > 1)) // Nous n'autorisons pas de modifier plus d'une face du cubemap à la fois { NazaraError("Cube dimensions are out of bounds"); return false; @@ -1072,37 +991,29 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int s return false; } - nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_impl->format); - - unsigned int size = box.width*box.height*box.depth*bpp; - std::unique_ptr flipped(new nzUInt8[size]); - NzImage::Copy(flipped.get(), pixels, bpp, box.width, box.height, box.depth, 0, 0, srcWidth, srcHeight); - - // Inversion de la texture pour le repère d'OpenGL - if (!NzPixelFormat::Flip(nzPixelFlipping_Horizontally, m_impl->format, box.width, box.height, box.depth, flipped.get(), flipped.get())) - NazaraWarning("Failed to flip image"); - - SetUnpackAlignement(bpp); + SetUnpackAlignement(NzPixelFormat::GetBytesPerPixel(m_impl->format)); + glPixelStorei(GL_UNPACK_ROW_LENGTH, srcWidth); + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, srcHeight); NzOpenGL::BindTexture(m_impl->type, m_impl->id); switch (m_impl->type) { case nzImageType_1D: - glTexSubImage1D(GL_TEXTURE_1D, level, box.x, box.width, format.dataFormat, format.dataType, flipped.get()); + glTexSubImage1D(GL_TEXTURE_1D, level, box.x, box.width, format.dataFormat, format.dataType, pixels); break; case nzImageType_1D_Array: case nzImageType_2D: - glTexSubImage2D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, height-box.height-box.y, box.width, box.height, format.dataFormat, format.dataType, flipped.get()); + glTexSubImage2D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, box.y, box.width, box.height, format.dataFormat, format.dataType, pixels); break; case nzImageType_2D_Array: case nzImageType_3D: - glTexSubImage3D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, height-box.height-box.y, box.z, box.width, box.height, box.depth, format.dataFormat, format.dataType, flipped.get()); + glTexSubImage3D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, box.y, box.z, box.width, box.height, box.depth, format.dataFormat, format.dataType, pixels); break; case nzImageType_Cubemap: - NazaraError("Update used on a cubemap texture, please enable safe mode"); + glTexSubImage2D(NzOpenGL::CubemapFace[box.z], level, box.x, box.y, box.width, box.height, format.dataFormat, format.dataType, pixels); break; } @@ -1114,126 +1025,6 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int return Update(pixels, NzBoxui(rect.x, rect.y, z, rect.width, rect.height, 1), srcWidth, srcHeight, level); } -bool NzTexture::UpdateFace(nzCubemapFace face, const NzImage& image, nzUInt8 level) -{ - #if NAZARA_RENDERER_SAFE - if (!image.IsValid()) - { - NazaraError("Image must be valid"); - return false; - } - - if (image.GetFormat() != m_impl->format) - { - NazaraError("Image format does not match texture format"); - return false; - } - #endif - - return UpdateFace(face, image.GetConstPixels(0, 0, 0, level), NzRectui(0, 0, image.GetWidth(level), image.GetHeight(level)), 0, 0, level); -} - -bool NzTexture::UpdateFace(nzCubemapFace face, const NzImage& image, const NzRectui& rect, nzUInt8 level) -{ - #if NAZARA_RENDERER_SAFE - if (!image.IsValid()) - { - NazaraError("Image must be valid"); - return false; - } - - if (image.GetFormat() != m_impl->format) - { - NazaraError("Image format does not match texture format"); - return false; - } - #endif - - return UpdateFace(face, image.GetConstPixels(0, 0, 0, level), rect, image.GetWidth(level), image.GetHeight(level), level); -} - -bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level) -{ - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return false; - } - #endif - - return UpdateFace(face, pixels, NzRectui(0, 0, m_impl->width, m_impl->height), srcWidth, srcHeight, level); -} - -bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRectui& rect, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level) -{ - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return false; - } - - if (m_impl->type != nzImageType_Cubemap) - { - NazaraError("UpdateFace is designed for cubemaps, use Update instead"); - return false; - } - - if (!pixels) - { - NazaraError("Invalid pixel source"); - return false; - } - - if (!rect.IsValid()) - { - NazaraError("Invalid rectangle"); - return false; - } - #endif - - unsigned int height = std::max(m_impl->height >> level, 1U); - - #if NAZARA_RENDERER_SAFE - if (rect.x+rect.width > std::max(m_impl->width >> level, 1U) || rect.y+rect.height > height) - { - NazaraError("Rectangle dimensions are out of bounds"); - return false; - } - - if (level >= m_impl->levelCount) - { - NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_impl->levelCount) + ')'); - return false; - } - #endif - - NzOpenGL::Format format; - if (!NzOpenGL::TranslateFormat(m_impl->format, &format, NzOpenGL::FormatType_Texture)) - { - NazaraError("Failed to get OpenGL format"); - return false; - } - - nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_impl->format); - - // Inversion de la texture pour le repère d'OpenGL - unsigned int size = rect.width*rect.height*bpp; - std::unique_ptr flipped(new nzUInt8[size]); - NzImage::Copy(flipped.get(), pixels, bpp, rect.width, rect.height, 1, 0, 0, srcWidth, srcHeight); - - if (!NzPixelFormat::Flip(nzPixelFlipping_Horizontally, m_impl->format, rect.width, rect.height, 1, flipped.get(), flipped.get())) - NazaraWarning("Failed to flip image"); - - SetUnpackAlignement(bpp); - - NzOpenGL::BindTexture(m_impl->type, m_impl->id); - glTexSubImage2D(NzOpenGL::CubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, flipped.get()); - - return true; -} - unsigned int NzTexture::GetOpenGLID() const { #if NAZARA_RENDERER_SAFE @@ -1266,8 +1057,11 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format) switch (format) { // Formats de base + case nzPixelFormat_A8: case nzPixelFormat_BGR8: case nzPixelFormat_BGRA8: + case nzPixelFormat_L8: + case nzPixelFormat_LA8: case nzPixelFormat_RGB8: case nzPixelFormat_RGBA8: return true; @@ -1326,12 +1120,7 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format) case nzPixelFormat_Stencil16: return false; - // Dépréciés depuis OpenGL 3 - ///FIXME: Il doit bien exister des remplaçants (GL_RED ?) - case nzPixelFormat_L8: - case nzPixelFormat_LA8: - return false; - + // Formats compressés case nzPixelFormat_DXT1: case nzPixelFormat_DXT3: case nzPixelFormat_DXT5: @@ -1342,7 +1131,6 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format) } NazaraError("Invalid pixel format"); - return false; } @@ -1370,15 +1158,119 @@ bool NzTexture::IsTypeSupported(nzImageType type) return false; } -void NzTexture::InvalidateMipmaps() +bool NzTexture::CreateTexture(bool proxy) { - #if NAZARA_RENDERER_SAFE - if (!m_impl) + NzOpenGL::Format openGLFormat; + if (!NzOpenGL::TranslateFormat(m_impl->format, &openGLFormat, NzOpenGL::FormatType_Texture)) { - NazaraInternalError("Texture must be valid"); - return; + NazaraError("Format " + NzPixelFormat::ToString(m_impl->format) + " not supported by OpenGL"); + return false; } - #endif - m_impl->mipmapsUpdated = false; + GLenum target = (proxy) ? NzOpenGL::TextureTargetProxy[m_impl->type] : NzOpenGL::TextureTarget[m_impl->type]; + switch (m_impl->type) + { + case nzImageType_1D: + { + if (glTexStorage1D && !proxy) // Les drivers AMD semblent ne pas aimer glTexStorage avec un format proxy + glTexStorage1D(target, m_impl->levelCount, openGLFormat.internalFormat, m_impl->width); + else + { + unsigned int w = m_impl->width; + for (nzUInt8 level = 0; level < m_impl->levelCount; ++level) + { + glTexImage1D(target, level, openGLFormat.internalFormat, w, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr); + if (w > 1U) + w >>= 1; + } + } + break; + } + + case nzImageType_1D_Array: + case nzImageType_2D: + { + if (glTexStorage2D && !proxy) + glTexStorage2D(target, m_impl->levelCount, openGLFormat.internalFormat, m_impl->width, m_impl->height); + else + { + unsigned int w = m_impl->width; + unsigned int h = m_impl->height; + for (nzUInt8 level = 0; level < m_impl->levelCount; ++level) + { + glTexImage2D(target, level, openGLFormat.internalFormat, w, h, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr); + if (w > 1U) + w >>= 1; + + if (h > 1U) + h >>= 1; + } + } + break; + } + + case nzImageType_2D_Array: + case nzImageType_3D: + { + if (glTexStorage3D && !proxy) + glTexStorage3D(target, m_impl->levelCount, openGLFormat.internalFormat, m_impl->width, m_impl->height, m_impl->depth); + else + { + unsigned int w = m_impl->width; + unsigned int h = m_impl->height; + unsigned int d = m_impl->depth; + for (nzUInt8 level = 0; level < m_impl->levelCount; ++level) + { + glTexImage3D(target, level, openGLFormat.internalFormat, w, h, d, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr); + if (w > 1U) + w >>= 1; + + if (h > 1U) + h >>= 1; + + if (d > 1U) + d >>= 1; + } + } + break; + } + + case nzImageType_Cubemap: + { + if (glTexStorage2D && !proxy) + glTexStorage2D(target, m_impl->levelCount, openGLFormat.internalFormat, m_impl->width, m_impl->height); + else + { + unsigned int size = m_impl->width; // Les cubemaps ont une longueur et largeur identique + for (nzUInt8 level = 0; level < m_impl->levelCount; ++level) + { + for (GLenum face : NzOpenGL::CubemapFace) + glTexImage2D(face, level, openGLFormat.internalFormat, size, size, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr); + + if (size > 1U) + size >>= 1; + } + } + break; + } + } + + if (proxy) + { + GLint internalFormat = 0; + glGetTexLevelParameteriv(target, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalFormat); + if (internalFormat == 0) + return false; + } + + // Application du swizzle + if (!proxy && NzOpenGL::GetVersion() >= 300) + { + glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, openGLFormat.swizzle[0]); + glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, openGLFormat.swizzle[1]); + glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, openGLFormat.swizzle[2]); + glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, openGLFormat.swizzle[3]); + } + + return true; } diff --git a/src/Nazara/Renderer/TextureSampler.cpp b/src/Nazara/Renderer/TextureSampler.cpp index e304a5d49..3c36c61ff 100644 --- a/src/Nazara/Renderer/TextureSampler.cpp +++ b/src/Nazara/Renderer/TextureSampler.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Renderer/UberShader.cpp b/src/Nazara/Renderer/UberShader.cpp index 9ebc25e9c..6503a0450 100644 --- a/src/Nazara/Renderer/UberShader.cpp +++ b/src/Nazara/Renderer/UberShader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Renderer/UberShaderInstance.cpp b/src/Nazara/Renderer/UberShaderInstance.cpp index 9ad4d5043..367c96bf3 100644 --- a/src/Nazara/Renderer/UberShaderInstance.cpp +++ b/src/Nazara/Renderer/UberShaderInstance.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Renderer/UberShaderInstancePreprocessor.cpp b/src/Nazara/Renderer/UberShaderInstancePreprocessor.cpp index c349c41fe..422d936b4 100644 --- a/src/Nazara/Renderer/UberShaderInstancePreprocessor.cpp +++ b/src/Nazara/Renderer/UberShaderInstancePreprocessor.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Renderer/UberShaderLibrary.cpp b/src/Nazara/Renderer/UberShaderLibrary.cpp index 9afc9b516..cb5ca9ba8 100644 --- a/src/Nazara/Renderer/UberShaderLibrary.cpp +++ b/src/Nazara/Renderer/UberShaderLibrary.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Renderer/UberShaderPreprocessor.cpp b/src/Nazara/Renderer/UberShaderPreprocessor.cpp index cffd8bc6b..7bac973d1 100644 --- a/src/Nazara/Renderer/UberShaderPreprocessor.cpp +++ b/src/Nazara/Renderer/UberShaderPreprocessor.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -32,7 +32,8 @@ NzUberShaderInstance* NzUberShaderPreprocessor::Get(const NzParameterList& param { try { - NzErrorFlags errFlags(nzErrorFlag_Silent | nzErrorFlag_ThrowException); + // Une exception sera lancée à la moindre erreur et celle-ci ne sera pas enregistrée dans le log (car traitée dans le bloc catch) + NzErrorFlags errFlags(nzErrorFlag_Silent | nzErrorFlag_ThrowException, true); std::unique_ptr shader(new NzShader); shader->SetPersistent(false); @@ -42,7 +43,8 @@ NzUberShaderInstance* NzUberShaderPreprocessor::Get(const NzParameterList& param { const Shader& shaderStage = m_shaders[i]; - if (shaderStage.present) + // Le shader stage est-il activé dans cette version du shader ? + if (shaderStage.present && (flags & shaderStage.requiredFlags) == shaderStage.requiredFlags) { nzUInt32 stageFlags = 0; for (auto it = shaderStage.flags.begin(); it != shaderStage.flags.end(); ++it) @@ -73,49 +75,46 @@ NzUberShaderInstance* NzUberShaderPreprocessor::Get(const NzParameterList& param for (auto it = shaderStage.flags.begin(); it != shaderStage.flags.end(); ++it) code << "#define " << it->first << ' ' << ((stageFlags & it->second) ? '1' : '0') << '\n'; - code << "\n#line 1\n"; + code << "\n#line 1\n"; // Pour que les éventuelles erreurs du shader se réfèrent à la bonne ligne code << shaderStage.source; stage.SetSource(code); stage.Compile(); - shader->AttachStage(static_cast(i), stage); - - shaderStage.cache.emplace(flags, std::move(stage)); + stageIt = shaderStage.cache.emplace(flags, std::move(stage)).first; } - else - shader->AttachStage(static_cast(i), stageIt->second); + + shader->AttachStage(static_cast(i), stageIt->second); } } shader->Link(); - auto pair = m_cache.emplace(flags, shader.get()); + // On construit l'instant + shaderIt = m_cache.emplace(flags, shader.get()).first; shader.release(); - - return &(pair.first)->second; // On retourne l'objet construit } catch (const std::exception& e) { NzErrorFlags errFlags(nzErrorFlag_ThrowExceptionDisabled); - NazaraError("Failed to build uber shader instance: " + NzError::GetLastError()); + NazaraError("Failed to build UberShader instance: " + NzError::GetLastError()); throw; } - } - else - return &shaderIt->second; + + return &shaderIt->second; } -void NzUberShaderPreprocessor::SetShader(nzShaderStage stage, const NzString& source, const NzString& flagString) +void NzUberShaderPreprocessor::SetShader(nzShaderStage stage, const NzString& source, const NzString& shaderFlags, const NzString& requiredFlags) { Shader& shader = m_shaders[stage]; shader.present = true; shader.source = source; + // On extrait les flags de la chaîne std::vector flags; - flagString.Split(flags, ' '); + shaderFlags.Split(flags, ' '); for (NzString& flag : flags) { @@ -127,9 +126,31 @@ void NzUberShaderPreprocessor::SetShader(nzShaderStage stage, const NzString& so if (it2 == shader.flags.end()) shader.flags[flag] = 1U << shader.flags.size(); } + + // On construit les flags requis pour l'activation du shader + shader.requiredFlags = 0; + + flags.clear(); + requiredFlags.Split(flags, ' '); + + for (NzString& flag : flags) + { + nzUInt32 flagVal; + + auto it = m_flags.find(flag); + if (it == m_flags.end()) + { + flagVal = 1U << m_flags.size(); + m_flags[flag] = flagVal; + } + else + flagVal = it->second; + + shader.requiredFlags |= flagVal; + } } -bool NzUberShaderPreprocessor::SetShaderFromFile(nzShaderStage stage, const NzString& filePath, const NzString& flags) +bool NzUberShaderPreprocessor::SetShaderFromFile(nzShaderStage stage, const NzString& filePath, const NzString& shaderFlags, const NzString& requiredFlags) { NzFile file(filePath); if (!file.Open(NzFile::ReadOnly | NzFile::Text)) @@ -150,7 +171,7 @@ bool NzUberShaderPreprocessor::SetShaderFromFile(nzShaderStage stage, const NzSt file.Close(); - SetShader(stage, source, flags); + SetShader(stage, source, shaderFlags, requiredFlags); return true; } diff --git a/src/Nazara/Renderer/Win32/ContextImpl.cpp b/src/Nazara/Renderer/Win32/ContextImpl.cpp index 1ae61bd3e..5fbe85539 100644 --- a/src/Nazara/Renderer/Win32/ContextImpl.cpp +++ b/src/Nazara/Renderer/Win32/ContextImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -160,15 +160,15 @@ bool NzContextImpl::Create(NzContextParameters& parameters) { *attrib++ = WGL_CONTEXT_PROFILE_MASK_ARB; *attrib++ = (parameters.compatibilityProfile) ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : WGL_CONTEXT_CORE_PROFILE_BIT_ARB; + + // Les contextes forward-compatible ne sont plus utilisés pour cette raison : + // http://www.opengl.org/discussion_boards/showthread.php/175052-Forward-compatible-vs-Core-profile } if (parameters.debugMode) { *attrib++ = WGL_CONTEXT_FLAGS_ARB; *attrib++ = WGL_CONTEXT_DEBUG_BIT_ARB; - - // Les contextes forward-compatible ne sont plus utilisés pour cette raison : - // http://www.opengl.org/discussion_boards/showthread.php/175052-Forward-compatible-vs-Core-profile } *attrib++ = 0; diff --git a/src/Nazara/Renderer/Win32/ContextImpl.hpp b/src/Nazara/Renderer/Win32/ContextImpl.hpp index cd17c9df2..07d88d44a 100644 --- a/src/Nazara/Renderer/Win32/ContextImpl.hpp +++ b/src/Nazara/Renderer/Win32/ContextImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/AbstractAtlas.cpp b/src/Nazara/Utility/AbstractAtlas.cpp new file mode 100644 index 000000000..dac73acf7 --- /dev/null +++ b/src/Nazara/Utility/AbstractAtlas.cpp @@ -0,0 +1,89 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +NzAbstractAtlas::NzAbstractAtlas() : +m_listenersLocked(false) +{ +} + +NzAbstractAtlas::~NzAbstractAtlas() +{ + m_listenersLocked = true; + for (auto& pair : m_listeners) + pair.first->OnAtlasReleased(this, pair.second); +} + +void NzAbstractAtlas::AddListener(Listener* listener, void* userdata) const +{ + if (!m_listenersLocked) + m_listeners.insert(std::make_pair(listener, userdata)); +} + +void NzAbstractAtlas::RemoveListener(Listener* listener) const +{ + if (!m_listenersLocked) + m_listeners.erase(listener); +} + +void NzAbstractAtlas::NotifyCleared() +{ + m_listenersLocked = true; + + auto it = m_listeners.begin(); + while (it != m_listeners.end()) + { + if (!it->first->OnAtlasCleared(this, it->second)) + m_listeners.erase(it++); + else + ++it; + } + + m_listenersLocked = false; +} + +void NzAbstractAtlas::NotifyLayerChange(NzAbstractImage* oldLayer, NzAbstractImage* newLayer) +{ + m_listenersLocked = true; + + auto it = m_listeners.begin(); + while (it != m_listeners.end()) + { + if (!it->first->OnAtlasLayerChange(this, oldLayer, newLayer, it->second)) + m_listeners.erase(it++); + else + ++it; + } + + m_listenersLocked = false; +} + + +NzAbstractAtlas::Listener::~Listener() = default; + +bool NzAbstractAtlas::Listener::OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) +{ + NazaraUnused(atlas); + NazaraUnused(userdata); + + return true; +} + +bool NzAbstractAtlas::Listener::OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata) +{ + NazaraUnused(atlas); + NazaraUnused(oldLayer); + NazaraUnused(newLayer); + NazaraUnused(userdata); + + return true; +} + +void NzAbstractAtlas::Listener::OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata) +{ + NazaraUnused(atlas); + NazaraUnused(userdata); +} diff --git a/src/Nazara/Utility/AbstractBuffer.cpp b/src/Nazara/Utility/AbstractBuffer.cpp index 84661c25a..76b82b07d 100644 --- a/src/Nazara/Utility/AbstractBuffer.cpp +++ b/src/Nazara/Utility/AbstractBuffer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/AbstractImage.cpp b/src/Nazara/Utility/AbstractImage.cpp new file mode 100644 index 000000000..9e5ea28a0 --- /dev/null +++ b/src/Nazara/Utility/AbstractImage.cpp @@ -0,0 +1,24 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +NzAbstractImage::~NzAbstractImage() = default; + +nzUInt8 NzAbstractImage::GetBytesPerPixel() const +{ + return NzPixelFormat::GetBytesPerPixel(GetFormat()); +} + +bool NzAbstractImage::IsCompressed() const +{ + return NzPixelFormat::IsCompressed(GetFormat()); +} + +bool NzAbstractImage::IsCubemap() const +{ + return GetType() == nzImageType_Cubemap; +} diff --git a/src/Nazara/Utility/AbstractTextDrawer.cpp b/src/Nazara/Utility/AbstractTextDrawer.cpp new file mode 100644 index 000000000..289836751 --- /dev/null +++ b/src/Nazara/Utility/AbstractTextDrawer.cpp @@ -0,0 +1,9 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +NzAbstractTextDrawer::~NzAbstractTextDrawer() = default; + diff --git a/src/Nazara/Utility/Algorithm.cpp b/src/Nazara/Utility/Algorithm.cpp index 7d7e6c939..777181331 100644 --- a/src/Nazara/Utility/Algorithm.cpp +++ b/src/Nazara/Utility/Algorithm.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -26,7 +26,7 @@ */ #include -#include +#include #include #include #include @@ -189,11 +189,9 @@ namespace void MoveTriangleToEnd(int tri) { auto it = std::find(tri_indices.begin(), tri_indices.end(), tri); - int t_ind = (it != tri_indices.end()) ? std::distance(tri_indices.begin(), it) : -1; + NazaraAssert(it != tri_indices.end(), "Triangle not found"); - NazaraAssert(t_ind >= 0, "Triangle not found"); - - tri_indices.erase(tri_indices.begin() + t_ind, tri_indices.begin() + t_ind + 1); + tri_indices.erase(it); tri_indices.push_back(tri); } }; @@ -546,15 +544,14 @@ namespace TriangleCacheData* t = &m_triangles[tri]; // calculate vertex scores - float sum = 0.0f; + float sum = 0.f; for (unsigned int i = 0; i < 3; ++i) { VertexCacheData *v = &m_vertices[t->verts[i]]; float sc = v->current_score; if (!v->calculated) - { sc = CalculateVertexScore(t->verts[i]); - } + v->current_score = sc; v->calculated = true; sum += sc; diff --git a/src/Nazara/Utility/Animation.cpp b/src/Nazara/Utility/Animation.cpp index e3fb1704e..6b0d1b06e 100644 --- a/src/Nazara/Utility/Animation.cpp +++ b/src/Nazara/Utility/Animation.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -48,7 +48,7 @@ bool NzAnimation::AddSequence(const NzSequence& sequence) if (sequence.frameCount == 0) { - NazaraError("Sequence frame count must be over 0"); + NazaraError("Sequence frame count must be over zero"); return false; } #endif diff --git a/src/Nazara/Utility/Buffer.cpp b/src/Nazara/Utility/Buffer.cpp index 6bf62d6d0..dae34312e 100644 --- a/src/Nazara/Utility/Buffer.cpp +++ b/src/Nazara/Utility/Buffer.cpp @@ -1,9 +1,11 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include +#include #include #include #include @@ -15,7 +17,7 @@ namespace { - NzAbstractBuffer* SoftwareBufferFunction(NzBuffer* parent, nzBufferType type) + NzAbstractBuffer* SoftwareBufferFactory(NzBuffer* parent, nzBufferType type) { return new NzSoftwareBuffer(parent, type); } @@ -28,19 +30,12 @@ m_size(0) { } -NzBuffer::NzBuffer(nzBufferType type, unsigned int size, nzBufferStorage storage, nzBufferUsage usage) : +NzBuffer::NzBuffer(nzBufferType type, unsigned int size, nzUInt32 storage, nzBufferUsage usage) : m_type(type), m_impl(nullptr) { + NzErrorFlags flags(nzErrorFlag_ThrowException, true); Create(size, storage, usage); - - #ifdef NAZARA_DEBUG - if (!m_impl) - { - NazaraError("Failed to create buffer"); - throw std::runtime_error("Constructor failed"); - } - #endif } NzBuffer::~NzBuffer() @@ -65,22 +60,21 @@ bool NzBuffer::CopyContent(const NzBuffer& buffer) #endif NzBufferMapper mapper(buffer, nzBufferAccess_ReadOnly); - return Fill(mapper.GetPointer(), 0, buffer.GetSize()); } -bool NzBuffer::Create(unsigned int size, nzBufferStorage storage, nzBufferUsage usage) +bool NzBuffer::Create(unsigned int size, nzUInt32 storage, nzBufferUsage usage) { Destroy(); // Notre buffer est-il supporté ? - if (!s_bufferFunctions[storage]) + if (!IsStorageSupported(storage)) { NazaraError("Buffer storage not supported"); return false; } - std::unique_ptr impl(s_bufferFunctions[storage](this, m_type)); + std::unique_ptr impl(s_bufferFactories[storage](this, m_type)); if (!impl->Create(size, usage)) { NazaraError("Failed to create buffer"); @@ -137,7 +131,7 @@ unsigned int NzBuffer::GetSize() const return m_size; } -nzBufferStorage NzBuffer::GetStorage() const +nzUInt32 NzBuffer::GetStorage() const { return m_storage; } @@ -154,7 +148,7 @@ nzBufferUsage NzBuffer::GetUsage() const bool NzBuffer::IsHardware() const { - return m_storage == nzBufferStorage_Hardware; + return m_storage & nzDataStorage_Hardware; } bool NzBuffer::IsValid() const @@ -206,7 +200,7 @@ void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int siz return m_impl->Map(access, offset, (size == 0) ? m_size-offset : size); } -bool NzBuffer::SetStorage(nzBufferStorage storage) +bool NzBuffer::SetStorage(nzUInt32 storage) { #if NAZARA_UTILITY_SAFE if (!m_impl) @@ -219,13 +213,11 @@ bool NzBuffer::SetStorage(nzBufferStorage storage) if (m_storage == storage) return true; - #if NAZARA_UTILITY_SAFE - if (!IsSupported(storage)) + if (!IsStorageSupported(storage)) { NazaraError("Storage not supported"); return false; } - #endif void* ptr = m_impl->Map(nzBufferAccess_ReadOnly, 0, m_size); if (!ptr) @@ -234,31 +226,36 @@ bool NzBuffer::SetStorage(nzBufferStorage storage) return false; } - NzAbstractBuffer* impl = s_bufferFunctions[storage](this, m_type); + NzCallOnExit unmapMyImpl([this]() + { + m_impl->Unmap(); + }); + + std::unique_ptr impl(s_bufferFactories[storage](this, m_type)); if (!impl->Create(m_size, m_usage)) { NazaraError("Failed to create buffer"); - delete impl; - m_impl->Unmap(); - return false; } + NzCallOnExit destroyImpl([&impl]() + { + impl->Destroy(); + }); + if (!impl->Fill(ptr, 0, m_size)) { NazaraError("Failed to fill buffer"); - impl->Destroy(); - delete impl; - m_impl->Unmap(); - return false; } - m_impl->Unmap(); + destroyImpl.Reset(); + + unmapMyImpl.CallAndReset(); m_impl->Destroy(); delete m_impl; - m_impl = impl; + m_impl = impl.release(); m_storage = storage; return true; @@ -275,29 +272,29 @@ void NzBuffer::Unmap() const #endif if (!m_impl->Unmap()) - NazaraWarning("Failed to unmap buffer (it's content is undefined)"); ///TODO: Unexpected ? + NazaraWarning("Failed to unmap buffer (it's content may be undefined)"); ///TODO: Unexpected ? } -bool NzBuffer::IsSupported(nzBufferStorage storage) +bool NzBuffer::IsStorageSupported(nzUInt32 storage) { - return s_bufferFunctions[storage] != nullptr; + return s_bufferFactories[storage] != nullptr; } -void NzBuffer::SetBufferFunction(nzBufferStorage storage, BufferFunction func) +void NzBuffer::SetBufferFactory(nzUInt32 storage, BufferFactory func) { - s_bufferFunctions[storage] = func; + s_bufferFactories[storage] = func; } bool NzBuffer::Initialize() { - s_bufferFunctions[nzBufferStorage_Software] = SoftwareBufferFunction; + s_bufferFactories[nzDataStorage_Software] = SoftwareBufferFactory; return true; } void NzBuffer::Uninitialize() { - std::memset(s_bufferFunctions, 0, (nzBufferStorage_Max+1)*sizeof(NzBuffer::BufferFunction)); + std::memset(s_bufferFactories, 0, (nzDataStorage_Max+1)*sizeof(NzBuffer::BufferFactory)); } -NzBuffer::BufferFunction NzBuffer::s_bufferFunctions[nzBufferStorage_Max+1] = {0}; +NzBuffer::BufferFactory NzBuffer::s_bufferFactories[nzDataStorage_Max+1] = {nullptr}; diff --git a/src/Nazara/Utility/Cursor.cpp b/src/Nazara/Utility/Cursor.cpp index 7f5534e9d..7a14fd921 100644 --- a/src/Nazara/Utility/Cursor.cpp +++ b/src/Nazara/Utility/Cursor.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Font.cpp b/src/Nazara/Utility/Font.cpp new file mode 100644 index 000000000..6fe5bcd2c --- /dev/null +++ b/src/Nazara/Utility/Font.cpp @@ -0,0 +1,588 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include + +namespace +{ + const nzUInt8 r_cabinRegular[] = { + #include + }; +} + +bool NzFontParams::IsValid() const +{ + return true; // Rien à tester +} + +NzFont::NzFont() : +m_atlas(s_defaultAtlas), +m_glyphBorder(s_defaultGlyphBorder), +m_minimumStepSize(s_defaultMinimumStepSize) +{ +} + +NzFont::~NzFont() +{ + Destroy(); + SetAtlas(nullptr); // On libère l'atlas proprement +} + +void NzFont::ClearGlyphCache() +{ + if (m_atlas) + { + if (m_atlas.unique()) + m_atlas->Clear(); // Appellera OnAtlasCleared + else + { + // Au moins une autre police utilise cet atlas, on vire nos glyphes un par un + for (auto mapIt = m_glyphes.begin(); mapIt != m_glyphes.end(); ++mapIt) + { + GlyphMap& glyphMap = mapIt->second; + for (auto glyphIt = glyphMap.begin(); glyphIt != glyphMap.end(); ++glyphIt) + { + Glyph& glyph = glyphIt->second; + m_atlas->Free(&glyph.atlasRect, &glyph.layerIndex, 1); + } + } + + // Destruction des glyphes mémorisés et notification + m_glyphes.clear(); + NotifyModified(ModificationCode_GlyphCacheCleared); + } + } +} + +void NzFont::ClearKerningCache() +{ + m_kerningCache.clear(); + NotifyModified(ModificationCode_KerningCacheCleared); +} + +void NzFont::ClearSizeInfoCache() +{ + m_sizeInfoCache.clear(); + NotifyModified(ModificationCode_SizeInfoCacheCleared); +} + +bool NzFont::Create(NzFontData* data) +{ + Destroy(); + + #if NAZARA_UTILITY_SAFE + if (!data) + { + NazaraError("Invalid font data"); + return false; + } + #endif + + m_data.reset(data); + + return true; +} + +void NzFont::Destroy() +{ + ClearGlyphCache(); + + m_data.reset(); + m_kerningCache.clear(); + m_sizeInfoCache.clear(); +} + +bool NzFont::ExtractGlyph(unsigned int characterSize, char32_t character, nzUInt32 style, NzFontGlyph* glyph) const +{ + #if NAZARA_UTILITY_SAFE + if (!IsValid()) + { + NazaraError("Invalid font"); + return false; + } + #endif + + return m_data->ExtractGlyph(characterSize, character, style, glyph); +} + +const std::shared_ptr& NzFont::GetAtlas() const +{ + return m_atlas; +} + +unsigned int NzFont::GetCachedGlyphCount(unsigned int characterSize, nzUInt32 style) const +{ + nzUInt64 key = ComputeKey(characterSize, style); + auto it = m_glyphes.find(key); + if (it == m_glyphes.end()) + return 0; + + return it->second.size(); +} + +unsigned int NzFont::GetCachedGlyphCount() const +{ + unsigned int count = 0; + for (auto& pair : m_glyphes) + count += pair.second.size(); + + return count; +} + +NzString NzFont::GetFamilyName() const +{ + #if NAZARA_UTILITY_SAFE + if (!IsValid()) + { + NazaraError("Invalid font"); + return NzString("Invalid font"); + } + #endif + + return m_data->GetFamilyName(); +} + +int NzFont::GetKerning(unsigned int characterSize, char32_t first, char32_t second) const +{ + #if NAZARA_UTILITY_SAFE + if (!IsValid()) + { + NazaraError("Invalid font"); + return 0; + } + #endif + + // On utilise un cache car la méthode interne QueryKerning peut se révéler coûteuse (car pouvant induire un changement de taille) + auto& map = m_kerningCache[characterSize]; + + nzUInt64 key = (static_cast(first) << 32) | second; // Combinaison de deux caractères 32 bits dans un nombre 64 bits + + auto it = map.find(key); + if (it == map.end()) + { + // Absent du cache: on va demander l'information à la police + int kerning = m_data->QueryKerning(characterSize, first, second); + map.insert(std::make_pair(key, kerning)); + + return kerning; + } + else + return it->second; // Présent dans le cache, tout va bien +} + +const NzFont::Glyph& NzFont::GetGlyph(unsigned int characterSize, nzUInt32 style, char32_t character) const +{ + nzUInt64 key = ComputeKey(characterSize, style); + return PrecacheGlyph(m_glyphes[key], characterSize, style, character); +} + +unsigned int NzFont::GetGlyphBorder() const +{ + return m_glyphBorder; +} + +unsigned int NzFont::GetMinimumStepSize() const +{ + return m_minimumStepSize; +} + +const NzFont::SizeInfo& NzFont::GetSizeInfo(unsigned int characterSize) const +{ + #if NAZARA_UTILITY_SAFE + if (!IsValid()) + { + NazaraError("Invalid font"); + + static SizeInfo dummy; + return dummy; + } + #endif + + auto it = m_sizeInfoCache.find(characterSize); + if (it == m_sizeInfoCache.end()) + { + SizeInfo sizeInfo; + sizeInfo.lineHeight = m_data->QueryLineHeight(characterSize); + sizeInfo.underlinePosition = m_data->QueryUnderlinePosition(characterSize); + sizeInfo.underlineThickness = m_data->QueryUnderlineThickness(characterSize); + + NzFontGlyph glyph; + if (m_data->ExtractGlyph(characterSize, ' ', nzTextStyle_Regular, &glyph)) + sizeInfo.spaceAdvance = glyph.advance; + else + { + NazaraWarning("Failed to extract space character from font, using half the size"); + sizeInfo.spaceAdvance = characterSize/2; + } + + it = m_sizeInfoCache.insert(std::make_pair(characterSize, sizeInfo)).first; + } + + return it->second; +} + +NzString NzFont::GetStyleName() const +{ + #if NAZARA_UTILITY_SAFE + if (!IsValid()) + { + NazaraError("Invalid font"); + return NzString("Invalid font"); + } + #endif + + return m_data->GetStyleName(); +} + +bool NzFont::IsValid() const +{ + return m_data != nullptr; +} + +bool NzFont::Precache(unsigned int characterSize, nzUInt32 style, char32_t character) const +{ + nzUInt64 key = ComputeKey(characterSize, style); + return PrecacheGlyph(m_glyphes[key], characterSize, style, character).valid; +} + +bool NzFont::Precache(unsigned int characterSize, nzUInt32 style, const NzString& characterSet) const +{ + unsigned int size; + std::unique_ptr characters(characterSet.GetUtf32Buffer(&size)); + if (!characters) + { + NazaraError("Invalid character set"); + return false; + } + + nzUInt64 key = ComputeKey(characterSize, style); + auto& glyphMap = m_glyphes[key]; + for (unsigned int i = 0; i < size; ++i) + PrecacheGlyph(glyphMap, characterSize, style, characters[i]); + + return true; +} + +bool NzFont::OpenFromFile(const NzString& filePath, const NzFontParams& params) +{ + return NzFontLoader::LoadFromFile(this, filePath, params); +} + +bool NzFont::OpenFromMemory(const void* data, std::size_t size, const NzFontParams& params) +{ + return NzFontLoader::LoadFromMemory(this, data, size, params); +} + +bool NzFont::OpenFromStream(NzInputStream& stream, const NzFontParams& params) +{ + return NzFontLoader::LoadFromStream(this, stream, params); +} + +void NzFont::SetAtlas(const std::shared_ptr& atlas) +{ + if (m_atlas != atlas) + { + ClearGlyphCache(); + + if (m_atlas) + m_atlas->RemoveListener(this); + + m_atlas = atlas; + if (m_atlas) + m_atlas->AddListener(this); + + NotifyModified(ModificationCode_AtlasChanged); + } +} + +void NzFont::SetGlyphBorder(unsigned int borderSize) +{ + if (m_glyphBorder != borderSize) + { + m_glyphBorder = borderSize; + ClearGlyphCache(); + } +} + +void NzFont::SetMinimumStepSize(unsigned int minimumStepSize) +{ + if (m_minimumStepSize != minimumStepSize) + { + #if NAZARA_UTILITY_SAFE + if (minimumStepSize == 0) + { + NazaraError("Minimum step size cannot be zero as it implies division by zero"); + return; + } + #endif + + m_minimumStepSize = minimumStepSize; + ClearGlyphCache(); + } +} + +std::shared_ptr NzFont::GetDefaultAtlas() +{ + return s_defaultAtlas; +} + +NzFont* NzFont::GetDefault() +{ + // Nous n'initialisons la police par défaut qu'à la demande pour qu'elle prenne + // les paramètres par défaut (qui peuvent avoir étés changés par l'utilisateur), + // et pour ne pas consommer de la mémoire vive inutilement (si elle n'est jamais utilisée, elle n'est jamais ouverte). + + if (!s_defaultFont) + { + std::unique_ptr cabin(new NzFont); + cabin->SetPersistent(true); + + if (!cabin->OpenFromMemory(r_cabinRegular, sizeof(r_cabinRegular))) + { + NazaraError("Failed to open default font"); + return nullptr; + } + + s_defaultFont = cabin.release(); + } + + return s_defaultFont; +} + +unsigned int NzFont::GetDefaultGlyphBorder() +{ + return s_defaultGlyphBorder; +} + +unsigned int NzFont::GetDefaultMinimumStepSize() +{ + return s_defaultMinimumStepSize; +} + +bool NzFont::Initialize() +{ + s_defaultAtlas.reset(new NzGuillotineImageAtlas); + s_defaultGlyphBorder = 1; + s_defaultMinimumStepSize = 1; + + return true; +} + +void NzFont::SetDefaultAtlas(const std::shared_ptr& atlas) +{ + s_defaultAtlas = atlas; +} + +void NzFont::SetDefaultGlyphBorder(unsigned int borderSize) +{ + s_defaultGlyphBorder = borderSize; +} + +void NzFont::SetDefaultMinimumStepSize(unsigned int minimumStepSize) +{ + #if NAZARA_UTILITY_SAFE + if (minimumStepSize == 0) + { + NazaraError("Minimum step size cannot be zero as it implies division by zero"); + return; + } + #endif + + s_defaultMinimumStepSize = minimumStepSize; +} + +void NzFont::Uninitialize() +{ + s_defaultAtlas.reset(); + + // On rend la police non-persistente et on demande la vérification du compteur (pouvant entraîner la libération de la ressource) + if (s_defaultFont) + { + s_defaultFont->SetPersistent(false, true); + s_defaultFont = nullptr; + } +} + +nzUInt64 NzFont::ComputeKey(unsigned int characterSize, nzUInt32 style) const +{ + // On prend le pas en compte + nzUInt64 sizePart = static_cast((characterSize/m_minimumStepSize)*m_minimumStepSize); + + // Ainsi que le style (uniquement le gras et l'italique, les autres sont gérés par un TextDrawer) + nzUInt64 stylePart = 0; + + if (style & nzTextStyle_Bold) + stylePart |= nzTextStyle_Bold; + + if (style & nzTextStyle_Italic) + stylePart |= nzTextStyle_Italic; + + return (stylePart << 32) | sizePart; +} + +bool NzFont::OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) +{ + NazaraUnused(atlas); + NazaraUnused(userdata); + + #ifdef NAZARA_DEBUG + // Est-ce qu'il s'agit bien de notre atlas ? + if (m_atlas.get() != atlas) + { + NazaraInternalError("Notified by a non-listening-to resource"); + return false; // On ne veut plus être notifié par cette ressource, évidemment + } + #endif + + // Notre atlas vient d'être vidé, détruisons le cache de glyphe + m_glyphes.clear(); + NotifyModified(ModificationCode_GlyphCacheCleared); + + return true; +} + +bool NzFont::OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata) +{ + NazaraUnused(atlas); + NazaraUnused(oldLayer); + NazaraUnused(newLayer); + NazaraUnused(userdata); + + #ifdef NAZARA_DEBUG + // Est-ce qu'il s'agit bien de notre atlas ? + if (m_atlas.get() != atlas) + { + NazaraInternalError("Notified by a non-listening-to resource"); + return false; // On ne veut plus être notifié par cette ressource, évidemment + } + #endif + + // Pour faciliter le travail des ressources qui nous écoutent + NotifyModified(ModificationCode_AtlasLayerChanged); + + return true; +} + +void NzFont::OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata) +{ + NazaraUnused(atlas); + NazaraUnused(userdata); + + #ifdef NAZARA_DEBUG + // Est-ce qu'il s'agit bien de notre atlas ? + if (m_atlas.get() != atlas) + { + NazaraInternalError("Notified by a non-listening-to resource"); + return; + } + #endif + + // Nous ne pouvons pas faire grand chose d'autre que de balancer une erreur à la tête de l'utilisateur avant un potentiel crash... + NazaraError("Atlas has been released while in use"); +} + +const NzFont::Glyph& NzFont::PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, nzUInt32 style, char32_t character) const +{ + auto it = glyphMap.find(character); + if (it != glyphMap.end()) // Si le glyphe n'est pas déjà chargé + return it->second; + + Glyph& glyph = glyphMap[character]; // Insertion du glyphe + glyph.valid = false; + + #if NAZARA_UTILITY_SAFE + if (!m_atlas) + { + NazaraError("Font has no atlas"); + return glyph; + } + #endif + + // On vérifie que le style demandé est supporté par la police (dans le cas contraire il devra être simulé au rendu) + glyph.requireFauxBold = false; + glyph.requireFauxItalic = false; + + nzUInt32 supportedStyle = style; + if (style & nzTextStyle_Bold && !m_data->SupportsStyle(nzTextStyle_Bold)) + { + glyph.requireFauxBold = true; + supportedStyle &= ~nzTextStyle_Bold; + } + + if (style & nzTextStyle_Italic && !m_data->SupportsStyle(nzTextStyle_Italic)) + { + glyph.requireFauxItalic = true; + supportedStyle &= ~nzTextStyle_Italic; + } + + // Est-ce que la police supporte le style demandé ? + if (style == supportedStyle) + { + // On extrait le glyphe depuis la police + NzFontGlyph fontGlyph; + if (ExtractGlyph(characterSize, character, style, &fontGlyph)) + { + glyph.atlasRect.width = fontGlyph.image.GetWidth(); + glyph.atlasRect.height = fontGlyph.image.GetHeight(); + + // Insertion du rectangle dans l'un des atlas + if (glyph.atlasRect.width > 0 && glyph.atlasRect.height > 0) // Si l'image contient quelque chose + { + // Bordure (pour éviter le débordement lors du filtrage) + glyph.atlasRect.width += m_glyphBorder*2; + glyph.atlasRect.height += m_glyphBorder*2; + + // Insertion du rectangle dans l'atlas virtuel + if (!m_atlas->Insert(fontGlyph.image, &glyph.atlasRect, &glyph.flipped, &glyph.layerIndex)) + { + NazaraError("Failed to insert glyph into atlas"); + return glyph; + } + + // Compensation de la bordure (centrage du glyphe) + glyph.atlasRect.x += m_glyphBorder; + glyph.atlasRect.y += m_glyphBorder; + glyph.atlasRect.width -= m_glyphBorder*2; + glyph.atlasRect.height -= m_glyphBorder*2; + } + + glyph.aabb = fontGlyph.aabb; + glyph.advance = fontGlyph.advance; + glyph.valid = true; + } + else + { + NazaraWarning("Failed to extract glyph \"" + NzString::Unicode(character) + "\""); + } + } + else + { + // La police ne supporte pas le style demandé, nous allons donc précharger le glyphe supportant le style "minimum" supporté + // et copier ses données + nzUInt64 newKey = ComputeKey(characterSize, supportedStyle); + const Glyph& referenceGlyph = PrecacheGlyph(m_glyphes[newKey], characterSize, supportedStyle, character); + if (referenceGlyph.valid) + { + glyph.aabb = referenceGlyph.aabb; + glyph.advance = referenceGlyph.advance; + glyph.atlasRect = referenceGlyph.atlasRect; + glyph.flipped = referenceGlyph.flipped; + glyph.layerIndex = referenceGlyph.layerIndex; + glyph.valid = true; + } + } + + return glyph; +} + +std::shared_ptr NzFont::s_defaultAtlas; +NzFont* NzFont::s_defaultFont; +NzFontLoader::LoaderList NzFont::s_loaders; +unsigned int NzFont::s_defaultGlyphBorder; +unsigned int NzFont::s_defaultMinimumStepSize; diff --git a/src/Nazara/Utility/FontData.cpp b/src/Nazara/Utility/FontData.cpp new file mode 100644 index 000000000..8a9f9d5b5 --- /dev/null +++ b/src/Nazara/Utility/FontData.cpp @@ -0,0 +1,8 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +NzFontData::~NzFontData() = default; diff --git a/src/Nazara/Utility/GuillotineImageAtlas.cpp b/src/Nazara/Utility/GuillotineImageAtlas.cpp new file mode 100644 index 000000000..96d52f12a --- /dev/null +++ b/src/Nazara/Utility/GuillotineImageAtlas.cpp @@ -0,0 +1,264 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace +{ + const unsigned int s_atlasStartSize = 512; +} + +NzGuillotineImageAtlas::NzGuillotineImageAtlas() : +m_rectChoiceHeuristic(NzGuillotineBinPack::RectBestAreaFit), +m_rectSplitHeuristic(NzGuillotineBinPack::SplitMinimizeArea) +{ +} + +NzGuillotineImageAtlas::~NzGuillotineImageAtlas() = default; + +void NzGuillotineImageAtlas::Clear() +{ + m_layers.clear(); + NotifyCleared(); +} + +void NzGuillotineImageAtlas::Free(NzSparsePtr rects, NzSparsePtr layers, unsigned int count) +{ + for (unsigned int i = 0; i < count; ++i) + { + #ifdef NAZARA_DEBUG + if (layers[i] >= m_layers.size()) + { + NazaraWarning("Rectangle #" + NzString::Number(i) + " belong to an out-of-bounds layer (" + NzString::Number(i) + " >= " + NzString::Number(m_layers.size()) + ")"); + continue; + } + #endif + + m_layers[layers[i]].binPack.FreeRectangle(rects[i]); + m_layers[layers[i]].freedRectangles++; + } +} + +NzGuillotineBinPack::FreeRectChoiceHeuristic NzGuillotineImageAtlas::GetRectChoiceHeuristic() const +{ + return m_rectChoiceHeuristic; +} + +NzGuillotineBinPack::GuillotineSplitHeuristic NzGuillotineImageAtlas::GetRectSplitHeuristic() const +{ + return m_rectSplitHeuristic; +} + +NzAbstractImage* NzGuillotineImageAtlas::GetLayer(unsigned int layerIndex) const +{ + #if NAZARA_UTILITY_SAFE + if (layerIndex >= m_layers.size()) + { + NazaraError("Layer index out of range (" + NzString::Number(layerIndex) + " >= " + NzString::Number(m_layers.size()) + ')'); + return nullptr; + } + #endif + + Layer& layer = m_layers[layerIndex]; + ProcessGlyphQueue(layer); + + return layer.image.get(); +} + +unsigned int NzGuillotineImageAtlas::GetLayerCount() const +{ + return m_layers.size(); +} + +nzUInt32 NzGuillotineImageAtlas::GetStorage() const +{ + return nzDataStorage_Software; +} + +bool NzGuillotineImageAtlas::Insert(const NzImage& image, NzRectui* rect, bool* flipped, unsigned int* layerIndex) +{ + if (m_layers.empty()) + // On créé une première couche s'il n'y en a pas + m_layers.resize(1); + + // Cette fonction ne fait qu'insérer un rectangle de façon virtuelle, l'insertion des images se fait après + for (unsigned int i = 0; i < m_layers.size(); ++i) + { + Layer& layer = m_layers[i]; + + // Une fois qu'un certain nombre de rectangles ont étés libérés d'une couche, on fusionne les rectangles libres + if (layer.freedRectangles > 10) // Valeur totalement arbitraire + { + while (layer.binPack.MergeFreeRectangles()); // Tant qu'une fusion est possible + layer.freedRectangles = 0; // Et on repart de zéro + } + + if (layer.binPack.Insert(rect, flipped, 1, false, m_rectChoiceHeuristic, m_rectSplitHeuristic)) + { + // Insertion réussie dans l'une des couches, on place le glyphe en file d'attente + layer.queuedGlyphs.resize(layer.queuedGlyphs.size()+1); + QueuedGlyph& glyph = layer.queuedGlyphs.back(); + glyph.flipped = *flipped; + glyph.image = image; // Merci le Copy-On-Write + glyph.rect = *rect; + + *layerIndex = i; + return true; + } + else if (i == m_layers.size() - 1) // Dernière itération ? + { + // Dernière couche, et le glyphe ne rentre pas, peut-on agrandir la taille de l'image ? + NzVector2ui newSize = layer.binPack.GetSize()*2; + if (newSize == NzVector2ui::Zero()) + newSize.Set(s_atlasStartSize); + + if (ResizeLayer(layer, newSize)) + { + // Oui on peut ! + layer.binPack.Expand(newSize); // On ajuste l'atlas virtuel + + // Et on relance la boucle sur la nouvelle dernière couche + i--; + } + else + { + // On ne peut plus agrandir la dernière couche, il est temps d'en créer une nouvelle + newSize.Set(s_atlasStartSize); + + Layer newLayer; + if (!ResizeLayer(newLayer, newSize)) + { + // Impossible d'allouer une nouvelle couche, nous manquons probablement de mémoire (ou le glyphe est trop grand) + NazaraError("Failed to allocate new layer, we are probably out of memory"); + return false; + } + + newLayer.binPack.Reset(newSize); + + m_layers.emplace_back(std::move(newLayer)); // Insertion du layer + + // On laisse la boucle insérer toute seule le rectangle à la prochaine itération + } + } + } + + NazaraInternalError("Unknown error"); // Normalement on ne peut pas arriver ici + return false; +} + +void NzGuillotineImageAtlas::SetRectChoiceHeuristic(NzGuillotineBinPack::FreeRectChoiceHeuristic heuristic) +{ + m_rectChoiceHeuristic = heuristic; +} + +void NzGuillotineImageAtlas::SetRectSplitHeuristic(NzGuillotineBinPack::GuillotineSplitHeuristic heuristic) +{ + m_rectSplitHeuristic = heuristic; +} + +NzAbstractImage* NzGuillotineImageAtlas::ResizeImage(NzAbstractImage* oldImage, const NzVector2ui& size) const +{ + std::unique_ptr newImage(new NzImage(nzImageType_2D, nzPixelFormat_A8, size.x, size.y)); + if (oldImage) + { + NzImage& image = *static_cast(oldImage); + newImage->Copy(image, NzRectui(size), NzVector2ui(0, 0)); // Copie des anciennes données + } + + return newImage.release(); +} + +bool NzGuillotineImageAtlas::ResizeLayer(Layer& layer, const NzVector2ui& size) +{ + NzAbstractImage* oldLayer = layer.image.get(); + + std::unique_ptr newImage(ResizeImage(layer.image.get(), size)); + if (!newImage) + return false; // Nous n'avons pas pu allouer + + if (newImage.get() == oldLayer) // Le layer a été agrandi dans le même objet, pas de souci + { + newImage.release(); // On possède déjà un unique_ptr sur cette ressource + return true; + } + + // On indique à ceux que ça intéresse qu'on a changé de pointeur + // (chose très importante pour ceux qui le stockent) + NotifyLayerChange(layer.image.get(), newImage.get()); + + // Et on ne met à jour le pointeur qu'après (car cette ligne libère également l'ancienne image) + layer.image = std::move(newImage); + + return true; +} + +void NzGuillotineImageAtlas::ProcessGlyphQueue(Layer& layer) const +{ + std::vector pixelBuffer; + + for (QueuedGlyph& glyph : layer.queuedGlyphs) + { + unsigned int glyphWidth = glyph.image.GetWidth(); + unsigned int glyphHeight = glyph.image.GetHeight(); + + // Calcul de l'éventuel padding (pixels de contour) + unsigned int paddingX; + unsigned int paddingY; + if (glyph.flipped) + { + paddingX = (glyph.rect.height - glyphWidth)/2; + paddingY = (glyph.rect.width - glyphHeight)/2; + } + else + { + paddingX = (glyph.rect.width - glyphWidth)/2; + paddingY = (glyph.rect.height - glyphHeight)/2; + } + + if (paddingX > 0 || paddingY > 0) + { + // On remplit les contours + pixelBuffer.resize(glyph.rect.width * glyph.rect.height); + std::memset(pixelBuffer.data(), 0, glyph.rect.width*glyph.rect.height*sizeof(nzUInt8)); + + layer.image->Update(pixelBuffer.data(), glyph.rect); + } + + const nzUInt8* pixels; + // On copie le glyphe dans l'atlas + if (glyph.flipped) + { + pixelBuffer.resize(glyphHeight * glyphWidth); + + // On tourne le glyphe pour qu'il rentre dans le rectangle + const nzUInt8* src = glyph.image.GetConstPixels(); + nzUInt8* ptr = pixelBuffer.data(); + + unsigned int lineStride = glyphWidth*sizeof(nzUInt8); // BPP = 1 + src += lineStride-1; // Départ en haut à droite + for (unsigned int x = 0; x < glyphWidth; ++x) + { + for (unsigned int y = 0; y < glyphHeight; ++y) + { + *ptr++ = *src; + src += lineStride; + } + + src -= glyphHeight*lineStride + 1; + } + + pixels = pixelBuffer.data(); + std::swap(glyphWidth, glyphHeight); + } + else + pixels = glyph.image.GetConstPixels(); + + layer.image->Update(pixels, NzRectui(glyph.rect.x + paddingX, glyph.rect.y + paddingY, glyphWidth, glyphHeight), 0, glyphWidth, glyphHeight); + glyph.image.Destroy(); // On libère l'image dès que possible (pour réduire la consommation) + } + + layer.queuedGlyphs.clear(); +} diff --git a/src/Nazara/Utility/Icon.cpp b/src/Nazara/Utility/Icon.cpp index b52165262..ffd2b4f67 100644 --- a/src/Nazara/Utility/Icon.cpp +++ b/src/Nazara/Utility/Icon.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Image.cpp b/src/Nazara/Utility/Image.cpp index 18ab39727..246fef3ec 100644 --- a/src/Nazara/Utility/Image.cpp +++ b/src/Nazara/Utility/Image.cpp @@ -1,22 +1,28 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include +#include #include +#include #include #include #include #include ///TODO: Rajouter des warnings (Formats compressés avec les méthodes Copy/Update, tests taille dans Copy) -///TODO: Rendre les méthodes exception-safe +///TODO: Rendre les méthodes exception-safe (Virer toute cette merde de calcul de pointeurs, faire usage du RAII) +///FIXME: Gérer correctement les formats utilisant moins d'un octet par pixel namespace { inline unsigned int GetLevelSize(unsigned int size, nzUInt8 level) { + if (size == 0) // Possible dans le cas d'une image invalide + return 0; + return std::max(size >> level, 1U); } @@ -28,7 +34,7 @@ namespace bool NzImageParams::IsValid() const { - return true; + return true; // Rien à vérifier } NzImage::NzImage() : @@ -39,15 +45,8 @@ m_sharedImage(&emptyImage) NzImage::NzImage(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount) : m_sharedImage(&emptyImage) { + NzErrorFlags flags(nzErrorFlag_ThrowException); Create(type, format, width, height, depth, levelCount); - - #ifdef NAZARA_DEBUG - if (!m_sharedImage) - { - NazaraError("Failed to create image"); - throw std::runtime_error("Constructor failed"); - } - #endif } NzImage::NzImage(const NzImage& image) : @@ -59,12 +58,6 @@ m_sharedImage(image.m_sharedImage) m_sharedImage->refCount++; } -NzImage::NzImage(NzImage&& image) noexcept : -m_sharedImage(image.m_sharedImage) -{ - image.m_sharedImage = &emptyImage; -} - NzImage::NzImage(SharedImage* sharedImage) : m_sharedImage(sharedImage) { @@ -196,7 +189,7 @@ void NzImage::Copy(const NzImage& source, const NzBoxui& srcBox, const NzVector3 bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount) { - ReleaseImage(); + Destroy(); #if NAZARA_UTILITY_SAFE if (!NzPixelFormat::IsValid(format)) @@ -228,13 +221,13 @@ bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width, case nzImageType_1D: if (height > 1) { - NazaraError("1D textures must be 1 height"); + NazaraError("1D textures must be 1 tall"); return false; } if (depth > 1) { - NazaraError("1D textures must be 1 depth"); + NazaraError("1D textures must be 1 deep"); return false; } break; @@ -243,7 +236,7 @@ bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width, case nzImageType_2D: if (depth > 1) { - NazaraError("2D textures must be 1 depth"); + NazaraError("2D textures must be 1 deep"); return false; } break; @@ -255,7 +248,7 @@ bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width, case nzImageType_Cubemap: if (depth > 1) { - NazaraError("Cubemaps must be 1 depth"); + NazaraError("Cubemaps must be 1 deep"); return false; } @@ -272,7 +265,7 @@ bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width, } #endif - levelCount = std::min(levelCount, GetMaxLevel(width, height, depth)); + levelCount = std::min(levelCount, GetMaxLevel(type, width, height, depth)); nzUInt8** levels = new nzUInt8*[levelCount]; @@ -465,7 +458,7 @@ bool NzImage::Fill(const NzColor& color, const NzRectui& rect, unsigned int z) return false; } - if (rect.x+rect.width > m_sharedImage->width || rect.y+rect.height > m_sharedImage->height) + if (rect.x + rect.width > m_sharedImage->width || rect.y + rect.height > m_sharedImage->height) { NazaraError("Rectangle dimensions are out of bounds"); return false; @@ -474,7 +467,7 @@ bool NzImage::Fill(const NzColor& color, const NzRectui& rect, unsigned int z) unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth; if (z >= depth) { - NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= (" + NzString::Number(depth) + ')'); + NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= " + NzString::Number(depth) + ')'); return false; } #endif @@ -587,11 +580,6 @@ bool NzImage::FlipVertically() return true; } -nzUInt8 NzImage::GetBytesPerPixel() const -{ - return NzPixelFormat::GetBytesPerPixel(m_sharedImage->format); -} - const nzUInt8* NzImage::GetConstPixels(unsigned int x, unsigned int y, unsigned int z, nzUInt8 level) const { #if NAZARA_UTILITY_SAFE @@ -674,7 +662,50 @@ nzUInt8 NzImage::GetLevelCount() const nzUInt8 NzImage::GetMaxLevel() const { - return GetMaxLevel(m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth); + return GetMaxLevel(m_sharedImage->type, m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth); +} + +unsigned int NzImage::GetMemoryUsage() const +{ + unsigned int width = m_sharedImage->width; + unsigned int height = m_sharedImage->height; + unsigned int depth = m_sharedImage->depth; + + unsigned int size = 0; + for (unsigned int i = 0; i < m_sharedImage->levelCount; ++i) + { + size += width * height * depth; + + if (width > 1) + width >>= 1; + + if (height > 1) + height >>= 1; + + if (depth > 1) + depth >>= 1; + } + + if (m_sharedImage->type == nzImageType_Cubemap) + size *= 6; + + return size * NzPixelFormat::GetBytesPerPixel(m_sharedImage->format); +} + +unsigned int NzImage::GetMemoryUsage(nzUInt8 level) const +{ + #if NAZARA_UTILITY_SAFE + if (level >= m_sharedImage->levelCount) + { + NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')'); + return 0; + } + #endif + + return (GetLevelSize(m_sharedImage->width, level)) * + (GetLevelSize(m_sharedImage->height, level)) * + ((m_sharedImage->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_sharedImage->depth, level)) * + NzPixelFormat::GetBytesPerPixel(m_sharedImage->format); } NzColor NzImage::GetPixelColor(unsigned int x, unsigned int y, unsigned int z) const @@ -694,20 +725,20 @@ NzColor NzImage::GetPixelColor(unsigned int x, unsigned int y, unsigned int z) c if (x >= m_sharedImage->width) { - NazaraError("X value exceeds width (" + NzString::Number(x) + " >= (" + NzString::Number(m_sharedImage->width) + ')'); + NazaraError("X value exceeds width (" + NzString::Number(x) + " >= " + NzString::Number(m_sharedImage->width) + ')'); return NzColor(); } if (y >= m_sharedImage->height) { - NazaraError("Y value exceeds height (" + NzString::Number(y) + " >= (" + NzString::Number(m_sharedImage->height) + ')'); + NazaraError("Y value exceeds height (" + NzString::Number(y) + " >= " + NzString::Number(m_sharedImage->height) + ')'); return NzColor(); } unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth; if (z >= depth) { - NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= (" + NzString::Number(depth) + ')'); + NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= " + NzString::Number(depth) + ')'); return NzColor(); } #endif @@ -741,7 +772,7 @@ nzUInt8* NzImage::GetPixels(unsigned int x, unsigned int y, unsigned int z, nzUI #if NAZARA_UTILITY_SAFE if (x >= width) { - NazaraError("X value exceeds width (" + NzString::Number(x) + " >= (" + NzString::Number(width) + ')'); + NazaraError("X value exceeds width (" + NzString::Number(x) + " >= " + NzString::Number(width) + ')'); return nullptr; } #endif @@ -750,14 +781,14 @@ nzUInt8* NzImage::GetPixels(unsigned int x, unsigned int y, unsigned int z, nzUI #if NAZARA_UTILITY_SAFE if (y >= height) { - NazaraError("Y value exceeds height (" + NzString::Number(y) + " >= (" + NzString::Number(height) + ')'); + NazaraError("Y value exceeds height (" + NzString::Number(y) + " >= " + NzString::Number(height) + ')'); return nullptr; } unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_sharedImage->depth, level); if (z >= depth) { - NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= (" + NzString::Number(depth) + ')'); + NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= " + NzString::Number(depth) + ')'); return nullptr; } @@ -773,47 +804,17 @@ nzUInt8* NzImage::GetPixels(unsigned int x, unsigned int y, unsigned int z, nzUI return GetPixelPtr(m_sharedImage->pixels[level], NzPixelFormat::GetBytesPerPixel(m_sharedImage->format), x, y, z, width, height); } -unsigned int NzImage::GetSize() const -{ - unsigned int width = m_sharedImage->width; - unsigned int height = m_sharedImage->height; - unsigned int depth = m_sharedImage->depth; - - unsigned int size = 0; - for (unsigned int i = 0; i < m_sharedImage->levelCount; ++i) - { - size += width * height * depth; - - if (width > 1) - width >>= 1; - - if (height > 1) - height >>= 1; - - if (depth > 1) - depth >>= 1; - } - - if (m_sharedImage->type == nzImageType_Cubemap) - size *= 6; - - return size * NzPixelFormat::GetBytesPerPixel(m_sharedImage->format); -} - -unsigned int NzImage::GetSize(nzUInt8 level) const +NzVector3ui NzImage::GetSize(nzUInt8 level) const { #if NAZARA_UTILITY_SAFE if (level >= m_sharedImage->levelCount) { NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')'); - return 0; + return NzVector3ui::Zero(); } #endif - return (GetLevelSize(m_sharedImage->width, level)) * - (GetLevelSize(m_sharedImage->height, level)) * - ((m_sharedImage->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_sharedImage->depth, level)) * - NzPixelFormat::GetBytesPerPixel(m_sharedImage->format); + return NzVector3ui(GetLevelSize(m_sharedImage->width, level), GetLevelSize(m_sharedImage->height, level), GetLevelSize(m_sharedImage->depth, level)); } nzImageType NzImage::GetType() const @@ -834,16 +835,6 @@ unsigned int NzImage::GetWidth(nzUInt8 level) const return GetLevelSize(m_sharedImage->width, level); } -bool NzImage::IsCompressed() const -{ - return NzPixelFormat::IsCompressed(m_sharedImage->format); -} - -bool NzImage::IsCubemap() const -{ - return m_sharedImage->type == nzImageType_Cubemap; -} - bool NzImage::IsValid() const { return m_sharedImage != &emptyImage; @@ -864,6 +855,105 @@ bool NzImage::LoadFromStream(NzInputStream& stream, const NzImageParams& params) return NzImageLoader::LoadFromStream(this, stream, params); } +// LoadArray +bool NzImage::LoadArrayFromFile(const NzString& filePath, const NzImageParams& imageParams, const NzVector2ui& atlasSize) +{ + NzImage image; + if (!image.LoadFromFile(filePath, imageParams)) + { + NazaraError("Failed to load image"); + return false; + } + + return LoadArrayFromImage(image, atlasSize); +} + +bool NzImage::LoadArrayFromImage(const NzImage& image, const NzVector2ui& atlasSize) +{ + #if NAZARA_UTILITY_SAFE + if (!image.IsValid()) + { + NazaraError("Image must be valid"); + return false; + } + + if (atlasSize.x == 0) + { + NazaraError("Atlas width must be over zero"); + return false; + } + + if (atlasSize.y == 0) + { + NazaraError("Atlas height must be over zero"); + return false; + } + #endif + + nzImageType type = image.GetType(); + + #if NAZARA_UTILITY_SAFE + if (type != nzImageType_1D && type != nzImageType_2D) + { + NazaraError("Image type not handled (0x" + NzString::Number(type, 16) + ')'); + return false; + } + #endif + + NzVector2ui imageSize(image.GetWidth(), image.GetHeight()); + + if (imageSize.x % atlasSize.x != 0) + { + NazaraWarning("Image width is not divisible by atlas width (" + NzString::Number(imageSize.x) + " mod " + NzString::Number(atlasSize.x) + " != 0)"); + } + + if (imageSize.y % atlasSize.y != 0) + { + NazaraWarning("Image height is not divisible by atlas height (" + NzString::Number(imageSize.y) + " mod " + NzString::Number(atlasSize.y) + " != 0)"); + } + + NzVector2ui faceSize = imageSize/atlasSize; + + unsigned int layerCount = atlasSize.x*atlasSize.y; + + // Selon le type de l'image de base, on va créer un array d'images 2D ou 1D + if (type == nzImageType_2D) + Create(nzImageType_2D_Array, image.GetFormat(), faceSize.x, faceSize.y, layerCount); + else + Create(nzImageType_1D_Array, image.GetFormat(), faceSize.x, layerCount); + + unsigned int layer = 0; + for (unsigned int j = 0; j < atlasSize.y; ++j) + for (unsigned int i = 0; i < atlasSize.x; ++i) + Copy(image, NzRectui(i*faceSize.x, j*faceSize.y, faceSize.x, faceSize.y), NzVector3ui(0, 0, layer++)); + + return true; +} + +bool NzImage::LoadArrayFromMemory(const void* data, std::size_t size, const NzImageParams& imageParams, const NzVector2ui& atlasSize) +{ + NzImage image; + if (!image.LoadFromMemory(data, size, imageParams)) + { + NazaraError("Failed to load image"); + return false; + } + + return LoadArrayFromImage(image, atlasSize); +} + +bool NzImage::LoadArrayFromStream(NzInputStream& stream, const NzImageParams& imageParams, const NzVector2ui& atlasSize) +{ + NzImage image; + if (!image.LoadFromStream(stream, imageParams)) + { + NazaraError("Failed to load image"); + return false; + } + + return LoadArrayFromImage(image, atlasSize); +} + bool NzImage::LoadCubemapFromFile(const NzString& filePath, const NzImageParams& imageParams, const NzCubemapParams& cubemapParams) { NzImage image; @@ -884,6 +974,13 @@ bool NzImage::LoadCubemapFromImage(const NzImage& image, const NzCubemapParams& NazaraError("Image must be valid"); return false; } + + nzImageType type = image.GetType(); + if (type != nzImageType_2D) + { + NazaraError("Image type not handled (0x" + NzString::Number(type, 16) + ')'); + return false; + } #endif unsigned int width = image.GetWidth(); @@ -1004,7 +1101,7 @@ void NzImage::SetLevelCount(nzUInt8 levelCount) } #endif - levelCount = std::min(levelCount, GetMaxLevel(m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth)); + levelCount = std::min(levelCount, GetMaxLevel()); if (m_sharedImage->levelCount == levelCount) return; @@ -1013,7 +1110,7 @@ void NzImage::SetLevelCount(nzUInt8 levelCount) nzUInt8 oldLevelCount = m_sharedImage->levelCount; nzUInt8 maxLevelCount = std::max(levelCount, oldLevelCount); - m_sharedImage->levelCount = levelCount; // Pour faire fonctionner GetSize + m_sharedImage->levelCount = levelCount; // Pour faire fonctionner GetMemoryUsage nzUInt8** pixels = new nzUInt8*[levelCount]; for (unsigned int i = 0; i < maxLevelCount; ++i) @@ -1021,7 +1118,7 @@ void NzImage::SetLevelCount(nzUInt8 levelCount) if (i < oldLevelCount) pixels[i] = m_sharedImage->pixels[i]; else if (i < levelCount) - pixels[i] = new nzUInt8[GetSize(i)]; + pixels[i] = new nzUInt8[GetMemoryUsage(i)]; else delete[] m_sharedImage->pixels[i]; } @@ -1048,20 +1145,20 @@ bool NzImage::SetPixelColor(const NzColor& color, unsigned int x, unsigned int y if (x >= m_sharedImage->width) { - NazaraError("X value exceeds width (" + NzString::Number(x) + " >= (" + NzString::Number(m_sharedImage->width) + ')'); + NazaraError("X value exceeds width (" + NzString::Number(x) + " >= " + NzString::Number(m_sharedImage->width) + ')'); return false; } if (y >= m_sharedImage->height) { - NazaraError("Y value exceeds height (" + NzString::Number(y) + " >= (" + NzString::Number(m_sharedImage->height) + ')'); + NazaraError("Y value exceeds height (" + NzString::Number(y) + " >= " + NzString::Number(m_sharedImage->height) + ')'); return false; } unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth; if (z >= depth) { - NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= (" + NzString::Number(depth) + ')'); + NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= " + NzString::Number(depth) + ')'); return false; } #endif @@ -1077,25 +1174,25 @@ bool NzImage::SetPixelColor(const NzColor& color, unsigned int x, unsigned int y return true; } -void NzImage::Update(const nzUInt8* pixels, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level) +bool NzImage::Update(const nzUInt8* pixels, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level) { #if NAZARA_UTILITY_SAFE if (m_sharedImage == &emptyImage) { NazaraError("Image must be valid"); - return; + return false; } if (!pixels) { NazaraError("Invalid pixel source"); - return; + return false; } if (level >= m_sharedImage->levelCount) { NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')'); - return; + return false; } #endif @@ -1107,27 +1204,29 @@ void NzImage::Update(const nzUInt8* pixels, unsigned int srcWidth, unsigned int GetLevelSize(m_sharedImage->depth, level), 0, 0, srcWidth, srcHeight); + + return true; } -void NzImage::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level) +bool NzImage::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level) { #if NAZARA_UTILITY_SAFE if (m_sharedImage == &emptyImage) { NazaraError("Image must be valid"); - return; + return false; } if (!pixels) { NazaraError("Invalid pixel source"); - return; + return false; } if (level >= m_sharedImage->levelCount) { NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')'); - return; + return false; } #endif @@ -1138,14 +1237,15 @@ void NzImage::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int src if (!box.IsValid()) { NazaraError("Invalid box"); - return; + return false; } - // Nous n'autorisons pas de modifier plus d'une face du cubemap à la fois (Nous prenons donc la profondeur de base) - if (box.x+box.width > width || box.y+box.height > height || box.z+box.depth > GetLevelSize(m_sharedImage->depth, level)) + unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_sharedImage->depth, level); + if (box.x+box.width > width || box.y+box.height > height || box.z+box.depth > depth || + (m_sharedImage->type == nzImageType_Cubemap && box.depth > 1)) // Nous n'autorisons pas de modifier plus d'une face du cubemap à la fois { NazaraError("Box dimensions are out of bounds"); - return; + return false; } #endif @@ -1158,63 +1258,13 @@ void NzImage::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int src box.width, box.height, box.depth, width, height, srcWidth, srcHeight); + + return true; } -void NzImage::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level) +bool NzImage::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level) { - #if NAZARA_UTILITY_SAFE - if (m_sharedImage == &emptyImage) - { - NazaraError("Image must be valid"); - return; - } - - if (!pixels) - { - NazaraError("Invalid pixel source"); - return; - } - - if (!rect.IsValid()) - { - NazaraError("Invalid rectangle"); - return; - } - - if (level >= m_sharedImage->levelCount) - { - NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')'); - return; - } - #endif - - unsigned int width = GetLevelSize(m_sharedImage->width, level); - unsigned int height = GetLevelSize(m_sharedImage->height, level); - - #if NAZARA_UTILITY_SAFE - if (rect.x+rect.width > width || rect.y+rect.height > height) - { - NazaraError("Rectangle dimensions are out of bounds"); - return; - } - - unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_sharedImage->depth, level); - if (z >= depth) - { - NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= " + NzString::Number(depth) + ')'); - return; - } - #endif - - EnsureOwnership(); - - nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format); - nzUInt8* dstPixels = GetPixelPtr(m_sharedImage->pixels[level], bpp, rect.x, rect.y, z, width, height); - - Copy(dstPixels, pixels, bpp, - rect.width, rect.height, 1, - width, height, - srcWidth, srcHeight); + return Update(pixels, NzBoxui(rect.x, rect.y, z, rect.width, rect.height, 1), srcWidth, srcHeight, level); } NzImage& NzImage::operator=(const NzImage& image) @@ -1228,13 +1278,6 @@ NzImage& NzImage::operator=(const NzImage& image) return *this; } -NzImage& NzImage::operator=(NzImage&& image) noexcept -{ - std::swap(m_sharedImage, image.m_sharedImage); - - return *this; -} - void NzImage::Copy(nzUInt8* destination, const nzUInt8* source, nzUInt8 bpp, unsigned int width, unsigned int height, unsigned int depth, unsigned int dstWidth, unsigned int dstHeight, unsigned int srcWidth, unsigned int srcHeight) { if (dstWidth == 0) @@ -1288,6 +1331,29 @@ nzUInt8 NzImage::GetMaxLevel(unsigned int width, unsigned int height, unsigned i return std::max(std::max(std::max(widthLevel, heightLevel), depthLevel), 1U); } +nzUInt8 NzImage::GetMaxLevel(nzImageType type, unsigned int width, unsigned int height, unsigned int depth) +{ + // Pour éviter que la profondeur ne soit comptée dans le calcul des niveaux + switch (type) + { + case nzImageType_1D: + case nzImageType_1D_Array: + return GetMaxLevel(width, 1U, 1U); + + case nzImageType_2D: + case nzImageType_2D_Array: + case nzImageType_Cubemap: + return GetMaxLevel(width, height, 1U); + + case nzImageType_3D: + return GetMaxLevel(width, height, depth); + } + + NazaraError("Image type not handled (0x" + NzString::Number(type, 16) + ')'); + return 0; + +} + void NzImage::EnsureOwnership() { if (m_sharedImage == &emptyImage) @@ -1300,7 +1366,7 @@ void NzImage::EnsureOwnership() nzUInt8** pixels = new nzUInt8*[m_sharedImage->levelCount]; for (unsigned int i = 0; i < m_sharedImage->levelCount; ++i) { - unsigned int size = GetSize(i); + unsigned int size = GetMemoryUsage(i); pixels[i] = new nzUInt8[size]; std::memcpy(pixels[i], m_sharedImage->pixels[i], size); } diff --git a/src/Nazara/Utility/IndexBuffer.cpp b/src/Nazara/Utility/IndexBuffer.cpp index 542a872d1..27347b237 100644 --- a/src/Nazara/Utility/IndexBuffer.cpp +++ b/src/Nazara/Utility/IndexBuffer.cpp @@ -1,9 +1,10 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include +#include #include #include #include @@ -11,13 +12,21 @@ #include #include +NzIndexBuffer::NzIndexBuffer(bool largeIndices, NzBuffer* buffer) +{ + NzErrorFlags(nzErrorFlag_ThrowException, true); + Reset(largeIndices, buffer); +} + NzIndexBuffer::NzIndexBuffer(bool largeIndices, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset) { + NzErrorFlags(nzErrorFlag_ThrowException, true); Reset(largeIndices, buffer, startOffset, endOffset); } -NzIndexBuffer::NzIndexBuffer(bool largeIndices, unsigned int length, nzBufferStorage storage, nzBufferUsage usage) +NzIndexBuffer::NzIndexBuffer(bool largeIndices, unsigned int length, nzUInt32 storage, nzBufferUsage usage) { + NzErrorFlags(nzErrorFlag_ThrowException, true); Reset(largeIndices, length, storage, usage); } @@ -31,16 +40,6 @@ m_startOffset(indexBuffer.m_startOffset) { } -NzIndexBuffer::NzIndexBuffer(NzIndexBuffer&& indexBuffer) noexcept : -NzRefCounted(), -m_buffer(std::move(indexBuffer.m_buffer)), -m_largeIndices(indexBuffer.m_largeIndices), -m_endOffset(indexBuffer.m_endOffset), -m_indexCount(indexBuffer.m_indexCount), -m_startOffset(indexBuffer.m_startOffset) -{ -} - NzIndexBuffer::~NzIndexBuffer() { NotifyDestroy(); @@ -168,6 +167,11 @@ void NzIndexBuffer::Reset() m_buffer.Reset(); } +void NzIndexBuffer::Reset(bool largeIndices, NzBuffer* buffer) +{ + Reset(largeIndices, buffer, 0, buffer->GetSize()-1); +} + void NzIndexBuffer::Reset(bool largeIndices, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset) { #if NAZARA_UTILITY_SAFE @@ -177,9 +181,9 @@ void NzIndexBuffer::Reset(bool largeIndices, NzBuffer* buffer, unsigned int star return; } - if (endOffset > startOffset) + if (startOffset > endOffset) { - NazaraError("End offset cannot be over start offset"); + NazaraError("Start offset cannot be over end offset"); return; } @@ -206,7 +210,7 @@ void NzIndexBuffer::Reset(bool largeIndices, NzBuffer* buffer, unsigned int star m_startOffset = startOffset; } -void NzIndexBuffer::Reset(bool largeIndices, unsigned int length, nzBufferStorage storage, nzBufferUsage usage) +void NzIndexBuffer::Reset(bool largeIndices, unsigned int length, nzUInt32 storage, nzBufferUsage usage) { unsigned int stride = (largeIndices) ? sizeof(nzUInt32) : sizeof(nzUInt16); @@ -228,16 +232,7 @@ void NzIndexBuffer::Reset(const NzIndexBuffer& indexBuffer) m_startOffset = indexBuffer.m_startOffset; } -void NzIndexBuffer::Reset(NzIndexBuffer&& indexBuffer) noexcept -{ - m_buffer = std::move(indexBuffer.m_buffer); - m_endOffset = indexBuffer.m_endOffset; - m_indexCount = indexBuffer.m_indexCount; - m_largeIndices = indexBuffer.m_largeIndices; - m_startOffset = indexBuffer.m_startOffset; -} - -bool NzIndexBuffer::SetStorage(nzBufferStorage storage) +bool NzIndexBuffer::SetStorage(nzUInt32 storage) { return m_buffer->SetStorage(storage); } @@ -253,10 +248,3 @@ NzIndexBuffer& NzIndexBuffer::operator=(const NzIndexBuffer& indexBuffer) return *this; } - -NzIndexBuffer& NzIndexBuffer::operator=(NzIndexBuffer&& indexBuffer) noexcept -{ - Reset(indexBuffer); - - return *this; -} diff --git a/src/Nazara/Utility/IndexMapper.cpp b/src/Nazara/Utility/IndexMapper.cpp index f006e35e1..ab7419374 100644 --- a/src/Nazara/Utility/IndexMapper.cpp +++ b/src/Nazara/Utility/IndexMapper.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Joint.cpp b/src/Nazara/Utility/Joint.cpp index 8a46ff227..0e83874ca 100644 --- a/src/Nazara/Utility/Joint.cpp +++ b/src/Nazara/Utility/Joint.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Keyboard.cpp b/src/Nazara/Utility/Keyboard.cpp index 3dcae6855..28faa4db7 100644 --- a/src/Nazara/Utility/Keyboard.cpp +++ b/src/Nazara/Utility/Keyboard.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Loaders/FreeType.hpp b/src/Nazara/Utility/Loaders/FreeType.hpp new file mode 100644 index 000000000..3d24bfa93 --- /dev/null +++ b/src/Nazara/Utility/Loaders/FreeType.hpp @@ -0,0 +1,15 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_LOADERS_FREETYPE_HPP +#define NAZARA_LOADERS_FREETYPE_HPP + +#include + +void NzLoaders_FreeType_Register(); +void NzLoaders_FreeType_Unregister(); + +#endif // NAZARA_LOADERS_FREETYPE_HPP diff --git a/src/Nazara/Utility/Loaders/FreeType/Loader.cpp b/src/Nazara/Utility/Loaders/FreeType/Loader.cpp new file mode 100644 index 000000000..70f65bc89 --- /dev/null +++ b/src/Nazara/Utility/Loaders/FreeType/Loader.cpp @@ -0,0 +1,454 @@ +// Copyright (C) 2015 Jérôme Leclercq - 2009 Cruden BV +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include FT_FREETYPE_H +#include FT_BITMAP_H +#include FT_OUTLINE_H +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + class FreeTypeLibrary; + + FT_Library s_library; + std::shared_ptr s_libraryOwner; + float s_invScaleFactor = 1.f / (1 << 6); // 1/64 + + extern "C" + unsigned long FT_StreamRead(FT_Stream stream, unsigned long offset, unsigned char* buffer, unsigned long count) + { + // http://www.freetype.org/freetype2/docs/reference/ft2-system_interface.html#FT_Stream_IoFunc + NzInputStream& inputStream = *static_cast(stream->descriptor.pointer); + + // La valeur de count indique une opération de lecture ou de positionnement + if (count > 0) + { + // Dans le premier cas, une erreur est symbolisée par un retour nul + if (inputStream.SetCursorPos(offset)) + return static_cast(inputStream.Read(buffer, count)); + else + return 0; + } + else + { + // Dans le second cas, une erreur est symbolisée par un retour non-nul + if (inputStream.SetCursorPos(offset)) + return 0; + else + return 42; // La réponse à la grande question + } + } + + extern "C" + void FT_StreamClose(FT_Stream stream) + { + // http://www.freetype.org/freetype2/docs/reference/ft2-system_interface.html#FT_Stream_CloseFunc + // Les streams dans Nazara ne se ferment pas explicitement + NazaraUnused(stream); + } + + class FreeTypeLibrary + { + // Cette classe ne sert qu'à être utilisée avec un std::shared_ptr + // pour ne libérer FreeType que lorsque plus personne ne l'utilise + + public: + FreeTypeLibrary() = default; + ~FreeTypeLibrary() + { + FT_Done_FreeType(s_library); + s_library = nullptr; + } + }; + + class FreeTypeStream : public NzFontData + { + public: + FreeTypeStream() : + m_face(nullptr), + m_library(s_libraryOwner), + m_characterSize(0) + { + } + + ~FreeTypeStream() + { + if (m_face) + FT_Done_Face(m_face); + } + + bool Check() + { + // Test d'ouverture (http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Open_Face) + return FT_Open_Face(s_library, &m_args, -1, nullptr) == 0; + } + + bool ExtractGlyph(unsigned int characterSize, char32_t character, nzUInt32 style, NzFontGlyph* dst) override + { + #ifdef NAZARA_DEBUG + if (!dst) + { + NazaraError("Glyph destination cannot be null"); + return false; + } + #endif + + SetCharacterSize(characterSize); + + if (FT_Load_Char(m_face, character, FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_NORMAL) != 0) + { + NazaraError("Failed to load character"); + return false; + } + + FT_GlyphSlot& glyph = m_face->glyph; + + const FT_Pos boldStrength = 2 << 6; + + bool embolden = (style & nzTextStyle_Bold); + + dst->advance = (embolden) ? boldStrength >> 6 : 0; + + if (embolden && glyph->format == FT_GLYPH_FORMAT_OUTLINE) + { + // http://www.freetype.org/freetype2/docs/reference/ft2-outline_processing.html#FT_Outline_Embolden + FT_Outline_Embolden(&glyph->outline, boldStrength); + embolden = false; + } + + // http://www.freetype.org/freetype2/docs/reference/ft2-glyph_management.html#FT_Glyph_To_Bitmap + // Conversion du glyphe vers le format bitmap + // Cette fonction ne fait rien dans le cas où le glyphe est déjà un bitmap + if (FT_Render_Glyph(glyph, FT_RENDER_MODE_NORMAL) != 0) + { + NazaraError("Failed to convert glyph to bitmap"); + return false; + } + + // Dans le cas où nous voulons des caractères gras mais que nous n'avons pas pu agir plus tôt + // nous demandons à FreeType d'agir directement sur le bitmap généré + if (embolden) + { + // http://www.freetype.org/freetype2/docs/reference/ft2-bitmap_handling.html#FT_Bitmap_Embolden + // "If you want to embolden the bitmap owned by a FT_GlyphSlot_Rec, you should call FT_GlyphSlot_Own_Bitmap on the slot first" + FT_GlyphSlot_Own_Bitmap(glyph); + FT_Bitmap_Embolden(s_library, &glyph->bitmap, boldStrength, boldStrength); + embolden = false; + } + + dst->advance += glyph->metrics.horiAdvance >> 6; + dst->aabb.x = glyph->metrics.horiBearingX >> 6; + dst->aabb.y = -(glyph->metrics.horiBearingY >> 6); // Inversion du repère + dst->aabb.width = glyph->metrics.width >> 6; + dst->aabb.height = glyph->metrics.height >> 6; + + unsigned int width = glyph->bitmap.width; + unsigned int height = glyph->bitmap.rows; + + if (width > 0 && height > 0) + { + dst->image.Create(nzImageType_2D, nzPixelFormat_A8, width, height); + nzUInt8* pixels = dst->image.GetPixels(); + + const nzUInt8* data = glyph->bitmap.buffer; + + // Selon la documentation FreeType, le glyphe peut être encodé en format A8 (huit bits d'alpha par pixel) + // ou au format A1 (un bit d'alpha par pixel). + // Cependant dans un cas comme dans l'autre, il nous faut gérer le pitch (les données peuvent ne pas être contigues) + // ainsi que le padding dans le cas du format A1 (Chaque ligne prends un nombre fixe d'octets) + if (glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) + { + // Format A1 + for (unsigned int y = 0; y < height; ++y) + { + for (unsigned int x = 0; x < width; ++x) + *pixels++ = (data[x/8] & (1 << (7 - x%8)) ? 255 : 0); + + data += glyph->bitmap.pitch; + } + } + else + { + // Format A8 + if (glyph->bitmap.pitch == static_cast(width*sizeof(nzUInt8))) // Pouvons-nous copier directement ? + dst->image.Update(glyph->bitmap.buffer); + else + { + for (unsigned int y = 0; y < height; ++y) + { + std::memcpy(pixels, data, width*sizeof(nzUInt8)); + data += glyph->bitmap.pitch; + pixels += width*sizeof(nzUInt8); + } + } + } + } + else + dst->image.Destroy(); // On s'assure que l'image ne contient alors rien + + return true; + } + + NzString GetFamilyName() const override + { + return m_face->family_name; + } + + NzString GetStyleName() const override + { + return m_face->style_name; + } + + bool HasKerning() const override + { + return FT_HAS_KERNING(m_face); + } + + bool IsScalable() const override + { + return FT_IS_SCALABLE(m_face); + } + + bool Open() + { + return FT_Open_Face(s_library, &m_args, 0, &m_face) == 0; + } + + int QueryKerning(unsigned int characterSize, char32_t first, char32_t second) const override + { + if (FT_HAS_KERNING(m_face)) + { + SetCharacterSize(characterSize); + + FT_Vector kerning; + FT_Get_Kerning(m_face, FT_Get_Char_Index(m_face, first), FT_Get_Char_Index(m_face, second), FT_KERNING_DEFAULT, &kerning); + + if (!FT_IS_SCALABLE(m_face)) + return kerning.x; // Taille déjà précisée en pixels dans ce cas + + return kerning.x >> 6; + } + else + return 0; + } + + unsigned int QueryLineHeight(unsigned int characterSize) const override + { + SetCharacterSize(characterSize); + + // http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Size_Metrics + return m_face->size->metrics.height >> 6; + } + + float QueryUnderlinePosition(unsigned int characterSize) const override + { + if (FT_IS_SCALABLE(m_face)) + { + SetCharacterSize(characterSize); + + // http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_FaceRec + return static_cast(FT_MulFix(m_face->underline_position, m_face->size->metrics.y_scale)) * s_invScaleFactor; + } + else + return characterSize / 10.f; // Joker ? + } + + float QueryUnderlineThickness(unsigned int characterSize) const override + { + if (FT_IS_SCALABLE(m_face)) + { + SetCharacterSize(characterSize); + + // http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_FaceRec + return static_cast(FT_MulFix(m_face->underline_thickness, m_face->size->metrics.y_scale)) * s_invScaleFactor; + } + else + return characterSize/15.f; // Joker ? + } + + bool SetFile(const NzString& filePath) + { + std::unique_ptr file(new NzFile); + if (!file->Open(filePath, NzFile::ReadOnly)) + { + NazaraError("Failed to open stream from file: " + NzError::GetLastError()); + return false; + } + m_ownedStream = std::move(file); + + SetStream(*m_ownedStream); + return true; + } + + void SetMemory(const void* data, std::size_t size) + { + m_ownedStream.reset(new NzMemoryStream(data, size)); + SetStream(*m_ownedStream); + } + + void SetStream(NzInputStream& stream) + { + m_stream.base = nullptr; + m_stream.close = FT_StreamClose; + m_stream.descriptor.pointer = &stream; + m_stream.read = FT_StreamRead; + m_stream.pos = 0; + m_stream.size = stream.GetSize(); + + m_args.driver = 0; + m_args.flags = FT_OPEN_STREAM; + m_args.stream = &m_stream; + } + + bool SupportsStyle(nzUInt32 style) const override + { + ///TODO + return style == nzTextStyle_Regular || style == nzTextStyle_Bold; + } + + private: + void SetCharacterSize(unsigned int characterSize) const + { + if (m_characterSize != characterSize) + { + FT_Set_Pixel_Sizes(m_face, 0, characterSize); + m_characterSize = characterSize; + } + } + + FT_Open_Args m_args; + FT_Face m_face; + FT_StreamRec m_stream; + std::shared_ptr m_library; + std::unique_ptr m_ownedStream; + mutable unsigned int m_characterSize; + }; + + bool IsSupported(const NzString& extension) + { + ///FIXME: Je suppose qu'il en manque quelques unes.. + static std::set supportedExtensions = { + "afm", "bdf", "cff", "cid", "dfont", "fnt", "fon", "otf", "pfa", "pfb", "pfm", "pfr", "sfnt", "ttc", "tte", "ttf" + }; + + return supportedExtensions.find(extension) != supportedExtensions.end(); + } + + nzTernary Check(NzInputStream& stream, const NzFontParams& parameters) + { + NazaraUnused(parameters); + + FreeTypeStream face; + face.SetStream(stream); + + if (face.Check()) + return nzTernary_True; + else + return nzTernary_False; + } + + bool LoadFile(NzFont* font, const NzString& filePath, const NzFontParams& parameters) + { + NazaraUnused(parameters); + + std::unique_ptr face(new FreeTypeStream); + + if (!face->SetFile(filePath)) + { + NazaraError("Failed to open file"); + return false; + } + + if (!face->Open()) + { + NazaraError("Failed to open face"); + return false; + } + + if (font->Create(face.get())) + { + face.release(); + return true; + } + else + return false; + } + + bool LoadMemory(NzFont* font, const void* data, std::size_t size, const NzFontParams& parameters) + { + NazaraUnused(parameters); + + std::unique_ptr face(new FreeTypeStream); + face->SetMemory(data, size); + + if (!face->Open()) + { + NazaraError("Failed to open face"); + return false; + } + + if (font->Create(face.get())) + { + face.release(); + return true; + } + else + return false; + } + + bool LoadStream(NzFont* font, NzInputStream& stream, const NzFontParams& parameters) + { + NazaraUnused(parameters); + + std::unique_ptr face(new FreeTypeStream); + face->SetStream(stream); + + if (!face->Open()) + { + NazaraError("Failed to open face"); + return false; + } + + if (font->Create(face.get())) + { + face.release(); + return true; + } + else + return false; + } +} + +void NzLoaders_FreeType_Register() +{ + if (FT_Init_FreeType(&s_library) == 0) + { + s_libraryOwner.reset(new FreeTypeLibrary); + NzFontLoader::RegisterLoader(IsSupported, Check, LoadStream, LoadFile, LoadMemory); + } + else + { + s_library = nullptr; // On s'assure que le pointeur ne pointe pas sur n'importe quoi + NazaraWarning("Failed to initialize FreeType library"); + } +} + +void NzLoaders_FreeType_Unregister() +{ + if (s_library) + { + NzFontLoader::UnregisterLoader(IsSupported, Check, LoadStream, LoadFile, LoadMemory); + s_libraryOwner.reset(); + } +} diff --git a/src/Nazara/Utility/Loaders/MD2.hpp b/src/Nazara/Utility/Loaders/MD2.hpp index 3c3d53f98..57dec180d 100644 --- a/src/Nazara/Utility/Loaders/MD2.hpp +++ b/src/Nazara/Utility/Loaders/MD2.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Loaders/MD2/Constants.cpp b/src/Nazara/Utility/Loaders/MD2/Constants.cpp index 9de6f1abb..aee90f183 100644 --- a/src/Nazara/Utility/Loaders/MD2/Constants.cpp +++ b/src/Nazara/Utility/Loaders/MD2/Constants.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Loaders/MD2/Constants.hpp b/src/Nazara/Utility/Loaders/MD2/Constants.hpp index e062c9d65..07e574b4c 100644 --- a/src/Nazara/Utility/Loaders/MD2/Constants.hpp +++ b/src/Nazara/Utility/Loaders/MD2/Constants.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Loaders/MD2/Loader.cpp b/src/Nazara/Utility/Loaders/MD2/Loader.cpp index 84653a8ae..0483e2dac 100644 --- a/src/Nazara/Utility/Loaders/MD2/Loader.cpp +++ b/src/Nazara/Utility/Loaders/MD2/Loader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -200,7 +200,10 @@ namespace { const unsigned int fixedIndex = indexFix[j]; const MD2_TexCoord& texC = texCoords[triangles[i].texCoords[fixedIndex]]; - vertex[triangles[i].vertices[fixedIndex]].uv.Set(static_cast(texC.u) / header.skinwidth, 1.f - static_cast(texC.v)/header.skinheight); + float u = static_cast(texC.u) / header.skinwidth; + float v = static_cast(texC.v) / header.skinheight; + + vertex[triangles[i].vertices[fixedIndex]].uv.Set(u, (parameters.flipUVs) ? 1.f - v : v); } } diff --git a/src/Nazara/Utility/Loaders/MD5Anim.hpp b/src/Nazara/Utility/Loaders/MD5Anim.hpp index 54571dd7c..642edb978 100644 --- a/src/Nazara/Utility/Loaders/MD5Anim.hpp +++ b/src/Nazara/Utility/Loaders/MD5Anim.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Loaders/MD5Anim/Loader.cpp b/src/Nazara/Utility/Loaders/MD5Anim/Loader.cpp index 8f9a34783..1fe7c6396 100644 --- a/src/Nazara/Utility/Loaders/MD5Anim/Loader.cpp +++ b/src/Nazara/Utility/Loaders/MD5Anim/Loader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -15,14 +15,69 @@ namespace nzTernary Check(NzInputStream& stream, const NzAnimationParams& parameters) { - NzMD5AnimParser parser(stream, parameters); + NazaraUnused(parameters); + + NzMD5AnimParser parser(stream); return parser.Check(); } bool Load(NzAnimation* animation, NzInputStream& stream, const NzAnimationParams& parameters) { - NzMD5AnimParser parser(stream, parameters); - return parser.Parse(animation); + ///TODO: Utiliser les paramètres + NzMD5AnimParser parser(stream); + + if (!parser.Parse()) + { + NazaraError("MD5Anim parser failed"); + return false; + } + + const NzMD5AnimParser::Frame* frames = parser.GetFrames(); + unsigned int frameCount = parser.GetFrameCount(); + unsigned int frameRate = parser.GetFrameRate(); + const NzMD5AnimParser::Joint* joints = parser.GetJoints(); + unsigned int jointCount = parser.GetJointCount(); + + // À ce stade, nous sommes censés avoir assez d'informations pour créer l'animation + animation->CreateSkeletal(frameCount, jointCount); + + NzSequence sequence; + sequence.firstFrame = 0; + sequence.frameCount = frameCount; + sequence.frameRate = frameRate; + sequence.name = stream.GetPath().SubStringFrom(NAZARA_DIRECTORY_SEPARATOR, -1, true); + + animation->AddSequence(sequence); + + NzSequenceJoint* sequenceJoints = animation->GetSequenceJoints(); + + // Pour que le squelette soit correctement aligné, il faut appliquer un quaternion "de correction" aux joints à la base du squelette + NzQuaternionf rotationQuat = NzQuaternionf::RotationBetween(NzVector3f::UnitX(), NzVector3f::Forward()) * + NzQuaternionf::RotationBetween(NzVector3f::UnitZ(), NzVector3f::Up()); + + for (unsigned int i = 0; i < jointCount; ++i) + { + int parent = joints[i].parent; + for (unsigned int j = 0; j < frameCount; ++j) + { + NzSequenceJoint& sequenceJoint = sequenceJoints[j*jointCount + i]; + + if (parent >= 0) + { + sequenceJoint.position = frames[j].joints[i].pos; + sequenceJoint.rotation = frames[j].joints[i].orient; + } + else + { + sequenceJoint.position = rotationQuat * frames[j].joints[i].pos; + sequenceJoint.rotation = rotationQuat * frames[j].joints[i].orient; + } + + sequenceJoint.scale.Set(1.f); + } + } + + return true; } } diff --git a/src/Nazara/Utility/Loaders/MD5Anim/Parser.cpp b/src/Nazara/Utility/Loaders/MD5Anim/Parser.cpp index 8d5399596..1890f9d7f 100644 --- a/src/Nazara/Utility/Loaders/MD5Anim/Parser.cpp +++ b/src/Nazara/Utility/Loaders/MD5Anim/Parser.cpp @@ -1,10 +1,10 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include -#include +#include #include #include #include @@ -13,9 +13,8 @@ #include #include -NzMD5AnimParser::NzMD5AnimParser(NzInputStream& stream, const NzAnimationParams& parameters) : +NzMD5AnimParser::NzMD5AnimParser(NzInputStream& stream) : m_stream(stream), -m_parameters(parameters), m_keepLastLine(false), m_frameIndex(0), m_frameRate(0), @@ -47,7 +46,37 @@ nzTernary NzMD5AnimParser::Check() return nzTernary_False; } -bool NzMD5AnimParser::Parse(NzAnimation* animation) +unsigned int NzMD5AnimParser::GetAnimatedComponentCount() const +{ + return m_animatedComponents.size(); +} + +const NzMD5AnimParser::Frame* NzMD5AnimParser::GetFrames() const +{ + return m_frames.data(); +} + +unsigned int NzMD5AnimParser::GetFrameCount() const +{ + return m_frames.size(); +} + +unsigned int NzMD5AnimParser::GetFrameRate() const +{ + return m_frameRate; +} + +const NzMD5AnimParser::Joint* NzMD5AnimParser::GetJoints() const +{ + return m_joints.data(); +} + +unsigned int NzMD5AnimParser::GetJointCount() const +{ + return m_joints.size(); +} + +bool NzMD5AnimParser::Parse() { while (Advance(false)) { @@ -204,47 +233,6 @@ bool NzMD5AnimParser::Parse(NzAnimation* animation) m_frameRate = 24; } - // À ce stade, nous sommes censés avoir assez d'informations pour créer l'animation - if (!animation->CreateSkeletal(frameCount, jointCount)) - { - NazaraError("Failed to create animation"); - return false; - } - - NzSequence sequence; - sequence.firstFrame = 0; - sequence.frameCount = m_frames.size(); - sequence.frameRate = m_frameRate; - sequence.name = m_stream.GetPath().SubStringFrom(NAZARA_DIRECTORY_SEPARATOR, -1, true); - if (!animation->AddSequence(sequence)) - NazaraWarning("Failed to add sequence"); - - NzSequenceJoint* sequenceJoints = animation->GetSequenceJoints(); - - // Pour que le squelette soit correctement aligné, il faut appliquer un quaternion "de correction" aux joints à la base du squelette - NzQuaternionf rotationQuat = NzEulerAnglesf(-90.f, 90.f, 0.f); - for (unsigned int i = 0; i < jointCount; ++i) - { - int parent = m_joints[i].parent; - for (unsigned int j = 0; j < frameCount; ++j) - { - NzSequenceJoint& sequenceJoint = sequenceJoints[j*jointCount + i]; - - if (parent >= 0) - { - sequenceJoint.position = m_frames[j].joints[i].pos; - sequenceJoint.rotation = m_frames[j].joints[i].orient; - } - else - { - sequenceJoint.position = rotationQuat * m_frames[j].joints[i].pos; - sequenceJoint.rotation = rotationQuat * m_frames[j].joints[i].orient; - } - - sequenceJoint.scale.Set(1.f); - } - } - return true; } @@ -340,7 +328,7 @@ bool NzMD5AnimParser::ParseBounds() return false; } - m_frames[i].aabb.Set(min, max); + m_frames[i].bounds.Set(min, max); } if (!Advance()) diff --git a/src/Nazara/Utility/Loaders/MD5Anim/Parser.hpp b/src/Nazara/Utility/Loaders/MD5Anim/Parser.hpp index 1fc097f59..8dc57fe28 100644 --- a/src/Nazara/Utility/Loaders/MD5Anim/Parser.hpp +++ b/src/Nazara/Utility/Loaders/MD5Anim/Parser.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -18,23 +18,16 @@ class NzMD5AnimParser { public: - NzMD5AnimParser(NzInputStream& stream, const NzAnimationParams& parameters); - ~NzMD5AnimParser(); + struct FrameJoint + { + NzQuaternionf orient; + NzVector3f pos; + }; - nzTernary Check(); - bool Parse(NzAnimation* animation); - - private: struct Frame { - struct Joint - { - NzQuaternionf orient; - NzVector3f pos; - }; - - std::vector joints; - NzBoxf aabb; + std::vector joints; + NzBoxf bounds; }; struct Joint @@ -47,6 +40,21 @@ class NzMD5AnimParser unsigned int index; }; + NzMD5AnimParser(NzInputStream& stream); + ~NzMD5AnimParser(); + + nzTernary Check(); + + unsigned int GetAnimatedComponentCount() const; + const Frame* GetFrames() const; + unsigned int GetFrameCount() const; + unsigned int GetFrameRate() const; + const Joint* GetJoints() const; + unsigned int GetJointCount() const; + + bool Parse(); + + private: bool Advance(bool required = true); void Error(const NzString& message); bool ParseBaseframe(); @@ -61,7 +69,6 @@ class NzMD5AnimParser std::vector m_joints; NzInputStream& m_stream; NzString m_currentLine; - const NzAnimationParams& m_parameters; bool m_keepLastLine; unsigned int m_frameIndex; unsigned int m_frameRate; diff --git a/src/Nazara/Utility/Loaders/MD5Mesh.hpp b/src/Nazara/Utility/Loaders/MD5Mesh.hpp index 7d1d8c805..2589ca068 100644 --- a/src/Nazara/Utility/Loaders/MD5Mesh.hpp +++ b/src/Nazara/Utility/Loaders/MD5Mesh.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp b/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp index 9973fbc84..925c589ab 100644 --- a/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp +++ b/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp @@ -1,9 +1,14 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include +#include +#include +#include +#include +#include #include namespace @@ -15,14 +20,297 @@ namespace nzTernary Check(NzInputStream& stream, const NzMeshParams& parameters) { - NzMD5MeshParser parser(stream, parameters); + NazaraUnused(parameters); + + NzMD5MeshParser parser(stream); return parser.Check(); } bool Load(NzMesh* mesh, NzInputStream& stream, const NzMeshParams& parameters) { - NzMD5MeshParser parser(stream, parameters); - return parser.Parse(mesh); + NzMD5MeshParser parser(stream); + if (!parser.Parse()) + { + NazaraError("MD5Mesh parser failed"); + return false; + } + + // Pour que le squelette soit correctement aligné, il faut appliquer un quaternion "de correction" aux joints à la base du squelette + NzQuaternionf rotationQuat = NzQuaternionf::RotationBetween(NzVector3f::UnitX(), NzVector3f::Forward()) * + NzQuaternionf::RotationBetween(NzVector3f::UnitZ(), NzVector3f::Up()); + + NzString baseDir = stream.GetDirectory(); + + // Le hellknight de Doom 3 fait ~120 unités, et il est dit qu'il fait trois mètres + // Nous réduisons donc la taille générale des fichiers MD5 de 1/40 + NzVector3f scale(parameters.scale/40.f); + + const NzMD5MeshParser::Joint* joints = parser.GetJoints(); + const NzMD5MeshParser::Mesh* meshes = parser.GetMeshes(); + unsigned int jointCount = parser.GetJointCount(); + unsigned int meshCount = parser.GetMeshCount(); + + if (parameters.animated) + { + mesh->CreateSkeletal(jointCount); + + NzSkeleton* skeleton = mesh->GetSkeleton(); + for (unsigned int i = 0; i < jointCount; ++i) + { + NzJoint* joint = skeleton->GetJoint(i); + + int parent = joints[i].parent; + if (parent >= 0) + joint->SetParent(skeleton->GetJoint(parent)); + + joint->SetName(joints[i].name); + + NzMatrix4f bindMatrix; + + if (parent >= 0) + bindMatrix.MakeTransform(joints[i].bindPos, joints[i].bindOrient); + else + bindMatrix.MakeTransform(rotationQuat * joints[i].bindPos, rotationQuat * joints[i].bindOrient); + + joint->SetInverseBindMatrix(bindMatrix.InverseAffine()); + } + + mesh->SetMaterialCount(meshCount); + for (unsigned int i = 0; i < meshCount; ++i) + { + const NzMD5MeshParser::Mesh& md5Mesh = meshes[i]; + + unsigned int indexCount = md5Mesh.triangles.size()*3; + unsigned int vertexCount = md5Mesh.vertices.size(); + + bool largeIndices = (vertexCount > std::numeric_limits::max()); + + std::unique_ptr indexBuffer(new NzIndexBuffer(largeIndices, indexCount, parameters.storage)); + indexBuffer->SetPersistent(false); + + std::unique_ptr vertexBuffer(new NzVertexBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Normal_UV_Tangent_Skinning), vertexCount, parameters.storage, nzBufferUsage_Static)); + vertexBuffer->SetPersistent(false); + + // Index buffer + NzIndexMapper indexMapper(indexBuffer.get(), nzBufferAccess_DiscardAndWrite); + + // Le format définit un set de triangles nous permettant de retrouver facilement les indices + // Cependant les sommets des triangles ne sont pas spécifiés dans le même ordre que ceux du moteur + // (On parle ici de winding) + unsigned int index = 0; + for (const NzMD5MeshParser::Triangle& triangle : md5Mesh.triangles) + { + // On les respécifie dans le bon ordre (inversion du winding) + indexMapper.Set(index++, triangle.x); + indexMapper.Set(index++, triangle.z); + indexMapper.Set(index++, triangle.y); + } + + indexMapper.Unmap(); + + // Vertex buffer + struct Weight + { + float bias; + unsigned int jointIndex; + }; + + std::vector tempWeights; + + NzBufferMapper vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly); + NzSkeletalMeshVertex* vertices = static_cast(vertexMapper.GetPointer()); + for (const NzMD5MeshParser::Vertex& vertex : md5Mesh.vertices) + { + // Skinning MD5 (Formule d'Id Tech) + NzVector3f finalPos(NzVector3f::Zero()); + + // On stocke tous les poids dans le tableau temporaire en même temps qu'on calcule la position finale du sommet. + tempWeights.resize(vertex.weightCount); + for (unsigned int j = 0; j < vertex.weightCount; ++j) + { + const NzMD5MeshParser::Weight& weight = md5Mesh.weights[vertex.startWeight + j]; + const NzMD5MeshParser::Joint& joint = joints[weight.joint]; + + finalPos += (joint.bindPos + joint.bindOrient*weight.pos) * weight.bias; + + // Avant d'ajouter les poids, il faut s'assurer qu'il n'y en ait pas plus que le maximum supporté + // et dans le cas contraire, garder les poids les plus importants et les renormaliser + tempWeights[j] = {weight.bias, weight.joint}; + } + + // Avons nous plus de poids que le moteur ne peut en supporter ? + unsigned int weightCount = vertex.weightCount; + if (weightCount > NAZARA_UTILITY_SKINNING_MAX_WEIGHTS) + { + // Pour augmenter la qualité du skinning tout en ne gardant que X poids, on ne garde que les poids + // les plus importants, ayant le plus d'impact sur le sommet final + std::sort(tempWeights.begin(), tempWeights.end(), [] (const Weight& a, const Weight& b) -> bool { + return a.bias > b.bias; + }); + + // Sans oublier bien sûr de renormaliser les poids (que leur somme soit 1) + float weightSum = 0.f; + for (unsigned int j = 0; j < NAZARA_UTILITY_SKINNING_MAX_WEIGHTS; ++j) + weightSum += tempWeights[j].bias; + + for (unsigned int j = 0; j < NAZARA_UTILITY_SKINNING_MAX_WEIGHTS; ++j) + tempWeights[j].bias /= weightSum; + + weightCount = NAZARA_UTILITY_SKINNING_MAX_WEIGHTS; + } + + vertices->weightCount = weightCount; + for (unsigned int j = 0; j < NAZARA_UTILITY_SKINNING_MAX_WEIGHTS; ++j) + { + if (j < weightCount) + { + // On donne une valeur aux poids présents + vertices->weights[j] = tempWeights[j].bias; + vertices->jointIndexes[j] = tempWeights[j].jointIndex; + } + else + { + // Et un poids de 0 sur le joint 0 pour les autres (nécessaire pour le GPU Skinning) + // La raison est que le GPU ne tiendra pas compte du nombre de poids pour des raisons de performances. + vertices->weights[j] = 0.f; + vertices->jointIndexes[j] = 0; + } + } + + vertices->position = finalPos; + vertices->uv.Set(vertex.uv.x, (parameters.flipUVs) ? 1.f - vertex.uv.y : vertex.uv.y); // Inversion des UV si demandé + vertices++; + } + + vertexMapper.Unmap(); + + // Material + mesh->SetMaterial(i, baseDir + md5Mesh.shader); + + // Submesh + std::unique_ptr subMesh(new NzSkeletalMesh(mesh)); + subMesh->Create(vertexBuffer.get()); + vertexBuffer.release(); + + if (parameters.optimizeIndexBuffers) + indexBuffer->Optimize(); + + subMesh->SetIndexBuffer(indexBuffer.get()); + indexBuffer.release(); + + subMesh->GenerateNormalsAndTangents(); + subMesh->SetMaterialIndex(i); + subMesh->SetPrimitiveMode(nzPrimitiveMode_TriangleList); + + mesh->AddSubMesh(subMesh.get()); + subMesh.release(); + + // Animation + // Il est peut-être éventuellement possible que la probabilité que l'animation ait le même nom soit non-nulle. + NzString path = stream.GetPath(); + if (!path.IsEmpty()) + { + path.Replace(".md5mesh", ".md5anim", -8, NzString::CaseInsensitive); + if (NzFile::Exists(path)) + mesh->SetAnimation(path); + } + } + } + else + { + if (!mesh->CreateStatic()) // Ne devrait jamais échouer + { + NazaraInternalError("Failed to create mesh"); + return false; + } + + mesh->SetMaterialCount(meshCount); + for (unsigned int i = 0; i < meshCount; ++i) + { + const NzMD5MeshParser::Mesh& md5Mesh = meshes[i]; + unsigned int indexCount = md5Mesh.triangles.size()*3; + unsigned int vertexCount = md5Mesh.vertices.size(); + + // Index buffer + bool largeIndices = (vertexCount > std::numeric_limits::max()); + + std::unique_ptr indexBuffer(new NzIndexBuffer(largeIndices, indexCount, parameters.storage)); + indexBuffer->SetPersistent(false); + + NzIndexMapper indexMapper(indexBuffer.get(), nzBufferAccess_DiscardAndWrite); + NzIndexIterator index = indexMapper.begin(); + + for (const NzMD5MeshParser::Triangle& triangle : md5Mesh.triangles) + { + // On les respécifie dans le bon ordre + *index++ = triangle.x; + *index++ = triangle.z; + *index++ = triangle.y; + } + indexMapper.Unmap(); + + // Vertex buffer + std::unique_ptr vertexBuffer(new NzVertexBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Normal_UV_Tangent), vertexCount, parameters.storage)); + NzBufferMapper vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly); + + NzMeshVertex* vertex = reinterpret_cast(vertexMapper.GetPointer()); + for (const NzMD5MeshParser::Vertex& md5Vertex : md5Mesh.vertices) + { + // Skinning MD5 (Formule d'Id Tech) + NzVector3f finalPos(NzVector3f::Zero()); + for (unsigned int j = 0; j < md5Vertex.weightCount; ++j) + { + const NzMD5MeshParser::Weight& weight = md5Mesh.weights[md5Vertex.startWeight + j]; + const NzMD5MeshParser::Joint& joint = joints[weight.joint]; + + finalPos += (joint.bindPos + joint.bindOrient*weight.pos) * weight.bias; + } + + // On retourne le modèle dans le bon sens + vertex->position = scale * (rotationQuat * finalPos); + vertex->uv.Set(md5Vertex.uv.x, (parameters.flipUVs) ? 1.f - md5Vertex.uv.y : md5Vertex.uv.y); // Inversion des UV si demandé + vertex++; + } + + vertexMapper.Unmap(); + + // Submesh + std::unique_ptr subMesh(new NzStaticMesh(mesh)); + subMesh->Create(vertexBuffer.get()); + + vertexBuffer->SetPersistent(false); + vertexBuffer.release(); + + if (parameters.optimizeIndexBuffers) + indexBuffer->Optimize(); + + subMesh->SetIndexBuffer(indexBuffer.get()); + indexBuffer.release(); + + // Material + mesh->SetMaterial(i, baseDir + md5Mesh.shader); + + subMesh->GenerateAABB(); + subMesh->GenerateNormalsAndTangents(); + subMesh->SetMaterialIndex(i); + + mesh->AddSubMesh(subMesh.get()); + subMesh.release(); + } + + if (parameters.center) + { + for (unsigned int i = 0; i < meshCount; ++i) + { + NzStaticMesh* subMesh = static_cast(mesh->GetSubMesh(i)); + subMesh->Center(); + } + + mesh->InvalidateAABB(); + } + } + + return true; } } diff --git a/src/Nazara/Utility/Loaders/MD5Mesh/Parser.cpp b/src/Nazara/Utility/Loaders/MD5Mesh/Parser.cpp index 03e244a0c..19d64d103 100644 --- a/src/Nazara/Utility/Loaders/MD5Mesh/Parser.cpp +++ b/src/Nazara/Utility/Loaders/MD5Mesh/Parser.cpp @@ -1,10 +1,10 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include -#include +#include #include #include #include @@ -19,9 +19,8 @@ #include #include -NzMD5MeshParser::NzMD5MeshParser(NzInputStream& stream, const NzMeshParams& parameters) : +NzMD5MeshParser::NzMD5MeshParser(NzInputStream& stream) : m_stream(stream), -m_parameters(parameters), m_keepLastLine(false), m_lineCount(0), m_meshIndex(0), @@ -52,7 +51,27 @@ nzTernary NzMD5MeshParser::Check() return nzTernary_False; } -bool NzMD5MeshParser::Parse(NzMesh* mesh) +const NzMD5MeshParser::Joint* NzMD5MeshParser::GetJoints() const +{ + return m_joints.data(); +} + +unsigned int NzMD5MeshParser::GetJointCount() const +{ + return m_joints.size(); +} + +const NzMD5MeshParser::Mesh* NzMD5MeshParser::GetMeshes() const +{ + return m_meshes.data(); +} + +unsigned int NzMD5MeshParser::GetMeshCount() const +{ + return m_meshes.size(); +} + +bool NzMD5MeshParser::Parse() { while (Advance(false)) { @@ -151,271 +170,6 @@ bool NzMD5MeshParser::Parse(NzMesh* mesh) } } - // Pour que le squelette soit correctement aligné, il faut appliquer un quaternion "de correction" aux joints à la base du squelette - NzQuaternionf rotationQuat = NzEulerAnglesf(-90.f, 180.f, 0.f); - NzString baseDir = m_stream.GetDirectory(); - - // Le hellknight de Doom 3 fait ~120 unités, et il est dit qu'il fait trois mètres - // Nous réduisons donc la taille générale des fichiers MD5 de 1/40 - NzVector3f scale(m_parameters.scale/40.f); - - if (m_parameters.animated) - { - if (!mesh->CreateSkeletal(m_joints.size())) // Ne devrait jamais échouer - { - NazaraInternalError("Failed to create mesh"); - return false; - } - - NzSkeleton* skeleton = mesh->GetSkeleton(); - for (unsigned int i = 0; i < m_joints.size(); ++i) - { - NzJoint* joint = skeleton->GetJoint(i); - - int parent = m_joints[i].parent; - if (parent >= 0) - joint->SetParent(skeleton->GetJoint(parent)); - - joint->SetName(m_joints[i].name); - - NzMatrix4f bindMatrix; - - if (parent >= 0) - bindMatrix.MakeTransform(m_joints[i].bindPos, m_joints[i].bindOrient); - else - bindMatrix.MakeTransform(rotationQuat * m_joints[i].bindPos, rotationQuat * m_joints[i].bindOrient); - - joint->SetInverseBindMatrix(bindMatrix.InverseAffine()); - } - - mesh->SetMaterialCount(m_meshes.size()); - for (unsigned int i = 0; i < m_meshes.size(); ++i) - { - const Mesh& md5Mesh = m_meshes[i]; - - unsigned int indexCount = md5Mesh.triangles.size()*3; - unsigned int vertexCount = md5Mesh.vertices.size(); - - bool largeIndices = (vertexCount > std::numeric_limits::max()); - - std::unique_ptr indexBuffer(new NzIndexBuffer(largeIndices, indexCount, m_parameters.storage)); - indexBuffer->SetPersistent(false); - - std::unique_ptr vertexBuffer(new NzVertexBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Normal_UV_Tangent_Skinning), vertexCount, m_parameters.storage, nzBufferUsage_Static)); - vertexBuffer->SetPersistent(false); - - // Index buffer - NzIndexMapper indexMapper(indexBuffer.get(), nzBufferAccess_DiscardAndWrite); - - unsigned int index = 0; - for (const Mesh::Triangle& triangle : md5Mesh.triangles) - { - // On les respécifie dans le bon ordre - indexMapper.Set(index++, triangle.x); - indexMapper.Set(index++, triangle.z); - indexMapper.Set(index++, triangle.y); - } - - indexMapper.Unmap(); - - // Vertex buffer - struct Weight - { - float bias; - unsigned int jointIndex; - }; - - std::vector tempWeights(NAZARA_UTILITY_SKINNING_MAX_WEIGHTS); - - NzBufferMapper vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly); - NzSkeletalMeshVertex* vertices = static_cast(vertexMapper.GetPointer()); - for (const Mesh::Vertex& vertex : md5Mesh.vertices) - { - // Skinning MD5 (Formule d'Id Tech) - NzVector3f finalPos(NzVector3f::Zero()); - - tempWeights.resize(vertex.weightCount); - for (unsigned int j = 0; j < vertex.weightCount; ++j) - { - const Mesh::Weight& weight = md5Mesh.weights[vertex.startWeight + j]; - const Joint& joint = m_joints[weight.joint]; - - finalPos += (joint.bindPos + joint.bindOrient*weight.pos) * weight.bias; - - // Avant d'ajouter les poids, il faut s'assurer qu'il n'y en ait pas plus que le maximum supporté - // et dans le cas contraire, garder les poids les plus importants et les renormaliser - tempWeights[j] = {weight.bias, weight.joint}; - } - - unsigned int weightCount = vertex.weightCount; - if (weightCount > NAZARA_UTILITY_SKINNING_MAX_WEIGHTS) - { - // Pour augmenter la qualité du skinning tout en ne gardant que X poids, on ne garde que les poids - // les plus importants, ayant le plus d'impact sur le sommet final - std::sort(tempWeights.begin(), tempWeights.end(), [] (const Weight& a, const Weight& b) -> bool { - return a.bias > b.bias; - }); - - // Sans oublier bien sûr de renormaliser les poids (que leur somme soit 1) - float weightSum = 0.f; - for (unsigned int j = 0; j < NAZARA_UTILITY_SKINNING_MAX_WEIGHTS; ++j) - weightSum += tempWeights[j].bias; - - for (unsigned int j = 0; j < NAZARA_UTILITY_SKINNING_MAX_WEIGHTS; ++j) - tempWeights[j].bias /= weightSum; - - weightCount = NAZARA_UTILITY_SKINNING_MAX_WEIGHTS; - } - - vertices->weightCount = weightCount; - for (unsigned int j = 0; j < NAZARA_UTILITY_SKINNING_MAX_WEIGHTS; ++j) - { - // On donne une valeur aux poids présents, et 0 pour les autres (nécessaire pour le GPU Skinning) - if (j < weightCount) - { - vertices->weights[j] = tempWeights[j].bias; - vertices->jointIndexes[j] = tempWeights[j].jointIndex; - } - else - { - vertices->weights[j] = 0.f; - vertices->jointIndexes[j] = 0; - } - } - - vertices->position = finalPos; - vertices->uv.Set(vertex.uv.x, 1.f-vertex.uv.y); - vertices++; - } - - vertexMapper.Unmap(); - - // Material - mesh->SetMaterial(i, baseDir + md5Mesh.shader); - - // Submesh - std::unique_ptr subMesh(new NzSkeletalMesh(mesh)); - if (!subMesh->Create(vertexBuffer.get())) - { - NazaraError("Failed to create skeletal mesh"); - continue; - } - vertexBuffer.release(); - - if (m_parameters.optimizeIndexBuffers) - indexBuffer->Optimize(); - - subMesh->SetIndexBuffer(indexBuffer.get()); - indexBuffer.release(); - - subMesh->GenerateNormalsAndTangents(); - subMesh->SetMaterialIndex(i); - subMesh->SetPrimitiveMode(nzPrimitiveMode_TriangleList); - - mesh->AddSubMesh(subMesh.get()); - subMesh.release(); - - // Animation - // Il est peut-être éventuellement possible que la probabilité que l'animation ait le même nom soit non-nulle. - NzString path = m_stream.GetPath(); - if (!path.IsEmpty()) - { - path.Replace(".md5mesh", ".md5anim", -8, NzString::CaseInsensitive); - if (NzFile::Exists(path)) - mesh->SetAnimation(path); - } - } - } - else - { - if (!mesh->CreateStatic()) // Ne devrait jamais échouer - { - NazaraInternalError("Failed to create mesh"); - return false; - } - - mesh->SetMaterialCount(m_meshes.size()); - for (unsigned int i = 0; i < m_meshes.size(); ++i) - { - const Mesh& md5Mesh = m_meshes[i]; - unsigned int indexCount = md5Mesh.triangles.size()*3; - unsigned int vertexCount = md5Mesh.vertices.size(); - - // Index buffer - bool largeIndices = (vertexCount > std::numeric_limits::max()); - - std::unique_ptr indexBuffer(new NzIndexBuffer(largeIndices, indexCount, m_parameters.storage)); - indexBuffer->SetPersistent(false); - - NzIndexMapper indexMapper(indexBuffer.get(), nzBufferAccess_DiscardAndWrite); - NzIndexIterator index = indexMapper.begin(); - - for (const Mesh::Triangle& triangle : md5Mesh.triangles) - { - // On les respécifie dans le bon ordre - *index++ = triangle.x; - *index++ = triangle.z; - *index++ = triangle.y; - } - indexMapper.Unmap(); - - // Vertex buffer - std::unique_ptr vertexBuffer(new NzVertexBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Normal_UV_Tangent), vertexCount, m_parameters.storage)); - NzBufferMapper vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly); - - NzMeshVertex* vertex = reinterpret_cast(vertexMapper.GetPointer()); - for (const Mesh::Vertex& md5Vertex : md5Mesh.vertices) - { - // Skinning MD5 (Formule d'Id Tech) - NzVector3f finalPos(NzVector3f::Zero()); - for (unsigned int j = 0; j < md5Vertex.weightCount; ++j) - { - const Mesh::Weight& weight = md5Mesh.weights[md5Vertex.startWeight + j]; - const Joint& joint = m_joints[weight.joint]; - - finalPos += (joint.bindPos + joint.bindOrient*weight.pos) * weight.bias; - } - - // On retourne le modèle dans le bon sens - vertex->position = scale * (rotationQuat * finalPos); - vertex->uv.Set(md5Vertex.uv.x, 1.f - md5Vertex.uv.y); - vertex++; - } - - vertexMapper.Unmap(); - - // Submesh - std::unique_ptr subMesh(new NzStaticMesh(mesh)); - if (!subMesh->Create(vertexBuffer.get())) - { - NazaraError("Failed to create static submesh"); - continue; - } - - vertexBuffer->SetPersistent(false); - vertexBuffer.release(); - - if (m_parameters.optimizeIndexBuffers) - indexBuffer->Optimize(); - - subMesh->SetIndexBuffer(indexBuffer.get()); - indexBuffer.release(); - - // Material - mesh->SetMaterial(i, baseDir + md5Mesh.shader); - - subMesh->GenerateAABB(); - subMesh->GenerateNormalsAndTangents(); - subMesh->SetMaterialIndex(i); - - if (m_parameters.center) - subMesh->Center(); - - mesh->AddSubMesh(subMesh.get()); - subMesh.release(); - } - } - return true; } @@ -555,7 +309,7 @@ bool NzMD5MeshParser::ParseMesh() if (!Advance()) return false; - Mesh::Triangle& triangle = m_meshes[m_meshIndex].triangles[i]; + Triangle& triangle = m_meshes[m_meshIndex].triangles[i]; unsigned int index; if (std::sscanf(&m_currentLine[0], "tri %u %u %u %u", &index, &triangle.x, &triangle.y, &triangle.z) != 4) { @@ -578,7 +332,7 @@ bool NzMD5MeshParser::ParseMesh() if (!Advance()) return false; - Mesh::Vertex& vertex = m_meshes[m_meshIndex].vertices[i]; + Vertex& vertex = m_meshes[m_meshIndex].vertices[i]; unsigned int index; if (std::sscanf(&m_currentLine[0], "vert %u ( %f %f ) %u %u", &index, &vertex.uv.x, &vertex.uv.y, &vertex.startWeight, &vertex.weightCount) != 5) { @@ -601,7 +355,7 @@ bool NzMD5MeshParser::ParseMesh() if (!Advance()) return false; - Mesh::Weight& weight = m_meshes[m_meshIndex].weights[i]; + Weight& weight = m_meshes[m_meshIndex].weights[i]; unsigned int index; if (std::sscanf(&m_currentLine[0], "weight %u %u %f ( %f %f %f )", &index, &weight.joint, &weight.bias, &weight.pos.x, &weight.pos.y, &weight.pos.z) != 6) diff --git a/src/Nazara/Utility/Loaders/MD5Mesh/Parser.hpp b/src/Nazara/Utility/Loaders/MD5Mesh/Parser.hpp index 18f0dbc39..647779b1c 100644 --- a/src/Nazara/Utility/Loaders/MD5Mesh/Parser.hpp +++ b/src/Nazara/Utility/Loaders/MD5Mesh/Parser.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -18,13 +18,6 @@ class NzMD5MeshParser { public: - NzMD5MeshParser(NzInputStream& stream, const NzMeshParams& parameters); - ~NzMD5MeshParser(); - - nzTernary Check(); - bool Parse(NzMesh* mesh); - - private: struct Joint { NzQuaternionf bindOrient; @@ -33,30 +26,43 @@ class NzMD5MeshParser int parent; }; + typedef NzVector3ui Triangle; + + struct Vertex + { + NzVector2f uv; + unsigned int startWeight; + unsigned int weightCount; + }; + + struct Weight + { + NzVector3f pos; + float bias; + unsigned int joint; + }; + struct Mesh { - typedef NzVector3ui Triangle; - - struct Vertex - { - NzVector2f uv; - unsigned int startWeight; - unsigned int weightCount; - }; - - struct Weight - { - NzVector3f pos; - float bias; - unsigned int joint; - }; - std::vector triangles; std::vector vertices; std::vector weights; NzString shader; }; + NzMD5MeshParser(NzInputStream& stream); + ~NzMD5MeshParser(); + + nzTernary Check(); + + const Joint* GetJoints() const; + unsigned int GetJointCount() const; + const Mesh* GetMeshes() const; + unsigned int GetMeshCount() const; + + bool Parse(); + + private: bool Advance(bool required = true); void Error(const NzString& message); bool ParseJoints(); @@ -68,7 +74,6 @@ class NzMD5MeshParser std::vector m_meshes; NzInputStream& m_stream; NzString m_currentLine; - const NzMeshParams& m_parameters; bool m_keepLastLine; unsigned int m_lineCount; unsigned int m_meshIndex; diff --git a/src/Nazara/Utility/Loaders/PCX.hpp b/src/Nazara/Utility/Loaders/PCX.hpp index 14cf1465c..c3836529f 100644 --- a/src/Nazara/Utility/Loaders/PCX.hpp +++ b/src/Nazara/Utility/Loaders/PCX.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Loaders/PCX/Loader.cpp b/src/Nazara/Utility/Loaders/PCX/Loader.cpp index 6f3558f95..48af53229 100644 --- a/src/Nazara/Utility/Loaders/PCX/Loader.cpp +++ b/src/Nazara/Utility/Loaders/PCX/Loader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -287,7 +287,7 @@ namespace /* for each color plane */ for (int c = 0; c < 3; ++c) { - nzUInt8* ptr = &pixels[y * width * 4]; + nzUInt8* ptr = &pixels[y * width * 3]; int bytes = header.bytesPerScanLine; /* decode line number y */ @@ -324,7 +324,7 @@ namespace } default: - NazaraError("Failed to load " + NzString::Number(bitCount) + " bitcount pcx files"); + NazaraError("Unsupported " + NzString::Number(bitCount) + " bitcount for pcx files"); return false; } diff --git a/src/Nazara/Utility/Loaders/STB.hpp b/src/Nazara/Utility/Loaders/STB.hpp index 4c3838c66..83e0d9036 100644 --- a/src/Nazara/Utility/Loaders/STB.hpp +++ b/src/Nazara/Utility/Loaders/STB.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Loaders/STB/Loader.cpp b/src/Nazara/Utility/Loaders/STB/Loader.cpp index 64f0f6aee..dbf36e4b4 100644 --- a/src/Nazara/Utility/Loaders/STB/Loader.cpp +++ b/src/Nazara/Utility/Loaders/STB/Loader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -15,29 +15,29 @@ namespace { - int Read(void* userdata, char* data, int size) + int Read(void* userdata, char* data, int size) + { + NzInputStream* stream = static_cast(userdata); + return static_cast(stream->Read(data, size)); + } + + void Skip(void* userdata, int size) { - NzInputStream* stream = reinterpret_cast(userdata); - return static_cast(stream->Read(data, size)); + NzInputStream* stream = static_cast(userdata); + stream->SetCursorPos(static_cast(stream->GetCursorPos()) + static_cast(size)); } - void Skip(void* userdata, unsigned int size) - { - NzInputStream* stream = reinterpret_cast(userdata); - stream->Read(nullptr, size); - } - - int Eof(void* userdata) - { - NzInputStream* stream = reinterpret_cast(userdata); - return stream->GetCursorPos() >= stream->GetSize(); - } + int Eof(void* userdata) + { + NzInputStream* stream = static_cast(userdata); + return stream->GetCursorPos() >= stream->GetSize(); + } static stbi_io_callbacks callbacks = {Read, Skip, Eof}; bool IsSupported(const NzString& extension) { - static std::set supportedExtensions = {"bmp", "gif", "hdr", "jpg", "jpeg", "pic", "png", "psd", "tga"}; + static std::set supportedExtensions = {"bmp", "gif", "hdr", "jpg", "jpeg", "pic", "png", "ppm", "pgm", "psd", "tga"}; return supportedExtensions.find(extension) != supportedExtensions.end(); } diff --git a/src/Nazara/Utility/Mesh.cpp b/src/Nazara/Utility/Mesh.cpp index 634a3c36d..c0edd3a00 100644 --- a/src/Nazara/Utility/Mesh.cpp +++ b/src/Nazara/Utility/Mesh.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -25,13 +25,13 @@ NzMeshParams::NzMeshParams() { - if (!NzBuffer::IsSupported(storage)) - storage = nzBufferStorage_Software; + if (!NzBuffer::IsStorageSupported(storage)) + storage = nzDataStorage_Software; } bool NzMeshParams::IsValid() const { - if (!NzBuffer::IsSupported(storage)) + if (!NzBuffer::IsStorageSupported(storage)) { NazaraError("Storage not supported"); return false; @@ -55,7 +55,7 @@ struct NzMeshImpl std::unordered_map subMeshMap; std::vector materials; - std::vector subMeshes; + std::vector subMeshes; nzAnimationType animationType; NzBoxf aabb; NzSkeleton skeleton; // Uniquement pour les meshs squelettiques @@ -91,9 +91,6 @@ void NzMesh::AddSubMesh(NzSubMesh* subMesh) } #endif - subMesh->AddObjectListener(this, m_impl->subMeshes.size()); - subMesh->AddReference(); - m_impl->aabbUpdated = false; // On invalide l'AABB m_impl->subMeshes.push_back(subMesh); } @@ -135,9 +132,6 @@ void NzMesh::AddSubMesh(const NzString& identifier, NzSubMesh* subMesh) int index = m_impl->subMeshes.size(); - subMesh->AddObjectListener(this, index); - subMesh->AddReference(); - m_impl->aabbUpdated = false; // On invalide l'AABB m_impl->subMeshes.push_back(subMesh); m_impl->subMeshMap[identifier] = index; @@ -371,12 +365,6 @@ void NzMesh::Destroy() { NotifyDestroy(); - for (NzSubMesh* subMesh : m_impl->subMeshes) - { - subMesh->RemoveObjectListener(this); - subMesh->RemoveReference(); - } - delete m_impl; m_impl = nullptr; } @@ -863,12 +851,6 @@ void NzMesh::RemoveSubMesh(const NzString& identifier) // On déplace l'itérateur du début d'une distance de x auto it2 = m_impl->subMeshes.begin(); std::advance(it2, index); - - // On libère la ressource - NzSubMesh* subMesh = *it2; - subMesh->RemoveObjectListener(this); - subMesh->RemoveReference(); - m_impl->subMeshes.erase(it2); m_impl->aabbUpdated = false; // On invalide l'AABB @@ -893,12 +875,6 @@ void NzMesh::RemoveSubMesh(unsigned int index) // On déplace l'itérateur du début de x auto it = m_impl->subMeshes.begin(); std::advance(it, index); - - // On libère la ressource - NzSubMesh* subMesh = *it; - subMesh->RemoveObjectListener(this); - subMesh->RemoveReference(); - m_impl->subMeshes.erase(it); m_impl->aabbUpdated = false; // On invalide l'AABB @@ -1011,11 +987,4 @@ void NzMesh::Transform(const NzMatrix4f& matrix) m_impl->aabbUpdated = false; } -void NzMesh::OnObjectReleased(const NzRefCounted* object, int index) -{ - NazaraUnused(object); - - RemoveSubMesh(index); -} - NzMeshLoader::LoaderList NzMesh::s_loaders; diff --git a/src/Nazara/Utility/Mouse.cpp b/src/Nazara/Utility/Mouse.cpp index 393453878..cdd8be2f1 100644 --- a/src/Nazara/Utility/Mouse.cpp +++ b/src/Nazara/Utility/Mouse.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Node.cpp b/src/Nazara/Utility/Node.cpp index 459f6d74f..2d7661e7a 100644 --- a/src/Nazara/Utility/Node.cpp +++ b/src/Nazara/Utility/Node.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -125,11 +125,6 @@ NzVector3f NzNode::GetLeft() const return m_derivedRotation * NzVector3f::Left(); } -const NzString& NzNode::GetName() const -{ - return m_name; -} - nzNodeType NzNode::GetNodeType() const { return nzNodeType_Default; @@ -270,7 +265,7 @@ NzNode& NzNode::Move(const NzVector3f& movement, nzCoordSys coordSys) } case nzCoordSys_Local: - m_position += m_scale * (m_rotation * movement); + m_position += m_rotation * movement; break; } @@ -413,11 +408,6 @@ void NzNode::SetInitialScale(float scaleX, float scaleY, float scaleZ) InvalidateNode(); } -void NzNode::SetName(const NzString& name) -{ - m_name = name; -} - void NzNode::SetParent(const NzNode* node, bool keepDerived) { #if NAZARA_UTILITY_SAFE @@ -621,7 +611,6 @@ NzNode& NzNode::operator=(const NzNode& node) m_initialPosition = node.m_initialPosition; m_initialRotation = node.m_initialRotation; m_initialScale = node.m_initialScale; - m_name = node.m_name; m_position = node.m_position; m_rotation = node.m_rotation; m_scale = node.m_scale; @@ -685,7 +674,7 @@ void NzNode::UpdateDerived() const m_derivedRotation.Normalize(); } else - m_derivedRotation = m_initialRotation * m_rotation; ///FIXME: Besoin d'une normalisation ? + m_derivedRotation = m_initialRotation * m_rotation; m_derivedScale = m_initialScale * m_scale; if (m_inheritScale) diff --git a/src/Nazara/Utility/PixelFormat.cpp b/src/Nazara/Utility/PixelFormat.cpp index 776781251..a71e3f700 100644 --- a/src/Nazara/Utility/PixelFormat.cpp +++ b/src/Nazara/Utility/PixelFormat.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -50,6 +50,94 @@ namespace return nullptr; } + /**********************************A8***********************************/ + template<> + nzUInt8* ConvertPixels(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) + { + while (start < end) + { + *dst++ = 0xFF; + *dst++ = 0xFF; + *dst++ = 0xFF; + *dst++ = *start; + + start += 1; + } + + return dst; + } + + template<> + nzUInt8* ConvertPixels(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) + { + while (start < end) + { + *dst++ = 0xFF; + *dst++ = *start; + + start += 1; + } + + return dst; + } + + template<> + nzUInt8* ConvertPixels(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) + { + nzUInt16* ptr = reinterpret_cast(dst); + while (start < end) + { + *ptr = (static_cast(0x1F) << 11) | + (static_cast(0x1F) << 6) | + (static_cast(0x1F) << 1) | + ((*start > 0xF) ? 1 : 0); // > 128 + + #ifdef NAZARA_BIG_ENDIAN + NzByteSwap(ptr, sizeof(nzUInt16)); + #endif + + ptr++; + start += 1; + } + + return reinterpret_cast(ptr); + } + + template<> + nzUInt8* ConvertPixels(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) + { + nzUInt16* ptr = reinterpret_cast(dst); + while (start < end) + { + *ptr = 0xFFF0 | c8to4(*start); + + #ifdef NAZARA_BIG_ENDIAN + NzByteSwap(ptr, sizeof(nzUInt16)); + #endif + + ptr++; + start += 1; + } + + return dst; + } + + template<> + nzUInt8* ConvertPixels(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) + { + while (start < end) + { + *dst++ = 0xFF; + *dst++ = 0xFF; + *dst++ = 0xFF; + *dst++ = *start; + + start += 1; + } + + return dst; + } + /**********************************BGR8***********************************/ template<> nzUInt8* ConvertPixels(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) @@ -170,6 +258,19 @@ namespace } /**********************************BGRA8**********************************/ + template<> + nzUInt8* ConvertPixels(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) + { + while (start < end) + { + *dst++ = start[3]; + + start += 4; + } + + return dst; + } + template<> nzUInt8* ConvertPixels(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) { @@ -243,7 +344,7 @@ namespace *ptr = (static_cast(c8to5(start[2])) << 11) | (static_cast(c8to5(start[1])) << 6) | (static_cast(c8to5(start[0])) << 1) | - ((start[3] == 0xFF) ? 1 : 0); + ((start[3] > 0xF) ? 1 : 0); // > 128 #ifdef NAZARA_BIG_ENDIAN NzByteSwap(ptr, sizeof(nzUInt16)); @@ -413,6 +514,19 @@ namespace } /***********************************LA8***********************************/ + template<> + nzUInt8* ConvertPixels(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) + { + while (start < end) + { + *dst++ = start[1]; + + start += 2; + } + + return dst; + } + template<> nzUInt8* ConvertPixels(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) { @@ -465,7 +579,7 @@ namespace { nzUInt16 l = static_cast(c8to5(start[0])); - *ptr = (l << 11) | (l << 6) | (l << 1) | ((start[1] == 0xFF) ? 1 : 0); + *ptr = (l << 11) | (l << 6) | (l << 1) | ((start[1] > 0xF) ? 1 : 0); #ifdef NAZARA_BIG_ENDIAN NzByteSwap(ptr, sizeof(nzUInt16)); @@ -531,6 +645,25 @@ namespace } /*********************************RGBA4***********************************/ + template<> + nzUInt8* ConvertPixels(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) + { + while (start < end) + { + nzUInt16 pixel = *reinterpret_cast(start); + + #ifdef NAZARA_BIG_ENDIAN + NzByteSwap(&pixel, sizeof(nzUInt16)); + #endif + + *dst++ = c4to8(pixel & 0x000F); + + start += 2; + } + + return dst; + } + template<> nzUInt8* ConvertPixels(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) { @@ -638,7 +771,7 @@ namespace nzUInt16 b = c4to5((pixel & 0x00F0) >> 4); nzUInt16 a = c4to5((pixel & 0x000F) >> 0); - *ptr = (r << 11) | (g << 6) | (b << 1) | ((a == 0xFF) ? 1 : 0); + *ptr = (r << 11) | (g << 6) | (b << 1) | ((a > 0x3) ? 1 : 0); #ifdef NAZARA_BIG_ENDIAN NzByteSwap(ptr, sizeof(nzUInt16)); @@ -695,6 +828,25 @@ namespace } /*********************************RGB5A1**********************************/ + template<> + nzUInt8* ConvertPixels(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) + { + while (start < end) + { + nzUInt16 pixel = *reinterpret_cast(start); + + #ifdef NAZARA_BIG_ENDIAN + NzByteSwap(&pixel, sizeof(nzUInt16)); + #endif + + *dst++ = static_cast((pixel & 0x1)*0xFF); + + start += 2; + } + + return dst; + } + template<> nzUInt8* ConvertPixels(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) { @@ -977,6 +1129,19 @@ namespace } /**********************************RGBA8**********************************/ + template<> + nzUInt8* ConvertPixels(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) + { + while (start < end) + { + *dst++ = start[3]; + + start += 4; + } + + return dst; + } + template<> nzUInt8* ConvertPixels(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) { @@ -1044,7 +1209,7 @@ namespace *ptr = (static_cast(c8to5(start[0])) << 11) | (static_cast(c8to5(start[1])) << 6) | (static_cast(c8to5(start[2])) << 1) | - ((start[3] == 0xFF) ? 1 : 0); + ((start[3] > 0xF) ? 1 : 0); // > 128 #ifdef NAZARA_BIG_ENDIAN NzByteSwap(ptr, sizeof(nzUInt16)); @@ -1106,6 +1271,13 @@ bool NzPixelFormat::Initialize() // Réinitialisation std::memset(s_convertFunctions, 0, (nzPixelFormat_Max+1)*(nzPixelFormat_Max+1)*sizeof(NzPixelFormat::ConvertFunction)); + /***********************************A8************************************/ + RegisterConverter(); + RegisterConverter(); + RegisterConverter(); + RegisterConverter(); + RegisterConverter(); + /**********************************BGR8***********************************/ RegisterConverter(); RegisterConverter(); @@ -1124,6 +1296,7 @@ bool NzPixelFormat::Initialize() RegisterConverter(); /**********************************BGRA8**********************************/ + RegisterConverter(); RegisterConverter(); RegisterConverter(); RegisterConverter();/* @@ -1227,6 +1400,7 @@ bool NzPixelFormat::Initialize() RegisterConverter(); /***********************************LA8***********************************/ + RegisterConverter(); RegisterConverter(); RegisterConverter(); RegisterConverter();/* @@ -1244,6 +1418,7 @@ bool NzPixelFormat::Initialize() RegisterConverter(); /**********************************RGBA4**********************************/ + RegisterConverter(); RegisterConverter(); RegisterConverter(); RegisterConverter(); @@ -1261,6 +1436,7 @@ bool NzPixelFormat::Initialize() RegisterConverter(); /*********************************RGB5A1**********************************/ + RegisterConverter(); RegisterConverter(); RegisterConverter(); RegisterConverter(); @@ -1295,6 +1471,7 @@ bool NzPixelFormat::Initialize() RegisterConverter(); /**********************************RGBA8**********************************/ + RegisterConverter(); RegisterConverter(); RegisterConverter(); RegisterConverter(); diff --git a/src/Nazara/Utility/Resources/Fonts/Cabin-Regular.ttf b/src/Nazara/Utility/Resources/Fonts/Cabin-Regular.ttf new file mode 100644 index 000000000..7c57306e7 Binary files /dev/null and b/src/Nazara/Utility/Resources/Fonts/Cabin-Regular.ttf differ diff --git a/src/Nazara/Utility/Resources/Fonts/Cabin-Regular.ttf.h b/src/Nazara/Utility/Resources/Fonts/Cabin-Regular.ttf.h new file mode 100644 index 000000000..d4e6b4702 --- /dev/null +++ b/src/Nazara/Utility/Resources/Fonts/Cabin-Regular.ttf.h @@ -0,0 +1 @@ +0,1,0,0,0,20,1,0,0,4,0,64,71,80,79,83,151,54,140,15,0,0,1,76,0,0,80,136,71,83,85,66,106,170,88,44,0,0,81,212,0,0,0,226,76,84,83,72,238,121,138,113,0,2,166,40,0,0,1,17,79,83,47,50,107,102,16,29,0,0,82,184,0,0,0,96,86,68,77,88,244,48,222,91,0,2,211,228,0,0,11,186,99,109,97,112,219,189,238,36,0,0,83,24,0,0,3,214,99,118,116,32,10,218,1,14,0,0,86,240,0,0,0,40,102,112,103,109,6,89,156,55,0,0,87,24,0,0,1,115,103,97,115,112,0,7,0,7,0,0,88,140,0,0,0,12,103,108,121,102,165,131,172,68,0,0,88,152,0,1,62,120,104,100,109,120,89,143,73,52,0,2,167,60,0,0,44,168,104,101,97,100,249,107,226,196,0,1,151,16,0,0,0,54,104,104,101,97,8,46,4,154,0,1,151,72,0,0,0,36,104,109,116,120,14,254,41,164,0,1,151,108,0,0,4,52,107,101,114,110,78,121,118,225,0,1,155,160,0,0,248,4,108,111,99,97,52,140,127,38,0,2,147,164,0,0,2,28,109,97,120,112,3,38,4,200,0,2,149,192,0,0,0,32,110,97,109,101,249,131,24,59,0,2,149,224,0,0,11,113,112,111,115,116,73,171,162,27,0,2,161,84,0,0,3,158,112,114,101,112,203,107,102,228,0,2,164,244,0,0,1,52,0,1,0,0,0,10,0,30,0,44,0,1,108,97,116,110,0,8,0,4,0,0,0,0,255,255,0,1,0,0,0,1,107,101,114,110,0,8,0,0,0,1,0,0,0,1,0,4,0,2,0,0,0,2,0,10,21,92,0,1,74,236,0,4,0,0,0,104,0,218,0,224,1,26,1,32,1,130,1,188,1,206,1,216,2,22,2,100,2,162,2,172,2,182,2,188,2,238,2,248,3,46,3,164,3,178,3,216,3,226,4,4,4,22,4,140,4,162,4,184,4,202,5,84,5,126,5,176,5,254,6,104,6,198,7,16,7,70,7,76,8,10,8,28,8,170,9,36,9,110,9,164,9,198,10,108,10,178,10,228,11,34,11,84,11,130,11,188,11,242,12,64,12,106,12,160,12,254,13,48,13,110,13,200,14,30,14,100,14,162,14,208,15,82,15,96,15,134,15,144,15,226,16,40,16,78,16,88,16,106,16,116,16,126,16,144,16,194,16,220,17,6,17,12,17,62,17,68,17,94,17,100,17,122,17,200,17,218,18,44,18,50,18,104,18,138,18,172,18,190,18,252,19,70,19,132,19,174,19,216,20,10,20,64,20,114,20,160,20,174,20,232,20,250,21,64,0,1,0,173,0,29,0,14,0,53,255,202,0,55,255,217,0,56,255,233,0,71,255,242,0,77,255,251,0,85,255,235,0,87,255,243,0,88,255,247,0,158,255,243,0,210,255,210,1,4,255,214,1,6,255,242,1,7,255,247,1,9,255,222,0,1,0,173,0,29,0,24,0,17,255,230,0,21,255,234,0,23,255,229,0,25,255,237,0,26,255,245,0,43,0,22,0,46,255,239,0,71,255,239,0,72,255,232,0,84,255,233,0,85,255,231,0,87,255,231,0,88,255,232,0,158,255,236,0,175,255,232,0,197,255,244,0,244,255,235,0,252,255,237,1,3,255,236,1,4,255,241,1,5,255,230,1,6,255,245,1,7,255,242,1,9,255,248,0,14,0,46,255,238,0,53,0,11,0,55,0,16,0,56,0,9,0,72,255,238,0,133,255,203,0,171,0,16,0,172,0,12,0,173,0,65,0,174,0,43,0,175,255,232,0,251,255,220,0,252,255,238,0,255,255,217,0,4,0,18,255,229,0,19,255,218,0,20,255,238,0,24,255,216,0,2,0,17,255,239,0,18,255,242,0,15,0,17,255,239,0,18,255,242,0,53,255,214,0,55,255,213,0,56,255,226,0,71,255,241,0,85,255,239,0,87,255,227,0,88,255,236,0,158,255,243,1,4,255,222,1,5,255,248,1,6,255,223,1,7,255,232,1,9,255,221,0,19,0,16,255,197,0,17,255,246,0,21,255,217,0,23,255,228,0,46,255,237,0,72,255,218,0,84,255,221,0,133,255,202,0,173,0,13,0,174,0,14,0,175,255,234,0,197,255,231,0,244,255,243,0,249,255,243,0,251,255,200,0,252,255,223,0,255,255,197,1,3,255,235,1,5,255,246,0,15,0,10,255,230,0,13,255,238,0,15,255,238,0,16,255,243,0,24,255,245,0,34,255,246,0,53,255,236,0,55,255,246,0,57,255,246,0,58,255,233,0,59,255,241,0,61,255,248,0,62,255,237,0,94,255,240,0,251,255,245,0,2,0,10,255,245,0,12,255,248,0,2,0,12,255,239,255,255,255,242,0,1,0,10,255,239,0,12,0,10,255,235,0,13,255,240,0,15,255,241,0,53,255,238,0,55,255,244,0,56,255,245,0,58,255,242,0,59,255,248,0,61,255,247,0,91,255,247,0,111,255,245,1,4,255,248,0,2,1,4,255,239,1,9,255,244,0,13,0,10,255,239,0,18,255,248,0,24,255,248,0,53,255,231,0,55,255,240,0,56,255,244,0,58,255,235,0,61,255,244,0,90,255,247,0,111,255,245,1,4,255,225,1,6,255,244,1,9,255,227,0,29,0,4,255,228,0,12,255,220,0,13,255,217,0,15,255,217,0,16,255,200,0,17,255,247,0,21,255,221,0,23,255,232,0,34,255,210,0,46,255,236,0,53,0,17,0,55,0,30,0,56,0,19,0,57,0,22,0,58,0,33,0,62,0,25,0,66,255,223,0,72,255,222,0,84,255,224,0,86,255,233,0,91,255,245,0,94,0,28,0,244,255,245,0,249,255,245,0,251,255,204,0,252,255,226,1,3,255,240,1,5,255,248,255,255,255,238,0,3,0,10,255,238,0,53,255,248,0,58,255,246,0,9,0,10,255,236,0,13,255,234,0,15,255,234,0,16,255,225,0,34,255,232,0,46,255,246,0,59,255,246,0,251,255,229,0,252,255,246,0,2,0,19,255,246,0,24,255,238,0,8,0,53,255,203,0,55,255,227,0,56,255,236,0,57,255,240,0,58,255,211,0,59,255,236,0,210,255,236,1,9,255,241,0,4,0,18,255,239,0,26,255,242,0,158,255,242,0,175,255,250,0,29,0,10,255,231,0,11,255,247,0,19,255,247,0,24,255,243,0,32,255,240,0,53,255,228,0,55,255,240,0,56,255,245,0,57,255,241,0,61,255,241,0,62,255,227,0,71,255,242,0,72,255,249,0,77,255,250,0,85,255,239,0,87,255,239,0,88,255,243,0,89,255,234,0,94,255,231,0,133,255,248,0,158,255,242,0,240,255,244,0,255,255,247,1,4,255,242,1,6,255,248,1,7,255,249,1,8,255,242,1,9,255,243,1,10,255,251,0,5,0,21,255,207,0,158,255,250,0,173,0,31,0,174,0,12,0,175,255,249,0,5,0,20,255,248,0,24,255,240,0,158,255,250,0,175,255,249,0,255,255,226,0,4,0,21,255,220,0,158,255,243,0,173,0,21,0,175,255,246,0,34,0,7,255,245,0,11,0,11,0,13,255,186,0,16,255,199,0,21,255,223,0,23,255,243,0,27,255,243,0,28,255,243,0,33,255,222,0,46,255,239,0,53,0,5,0,62,0,16,0,71,255,244,0,72,255,216,0,85,255,247,0,87,255,247,0,88,255,248,0,89,255,239,0,94,0,19,0,133,255,155,0,158,255,241,0,162,255,206,0,173,0,52,0,174,0,28,0,175,255,222,0,240,0,16,0,244,255,240,0,249,255,240,0,251,255,187,0,252,255,219,0,255,255,146,1,3,255,239,1,5,255,244,1,10,255,250,0,10,0,10,255,248,0,53,255,251,0,71,255,246,0,72,255,250,0,77,255,250,0,85,255,244,0,87,255,244,0,88,255,247,0,158,255,244,1,4,255,251,0,12,0,10,255,246,0,46,255,251,0,71,255,247,0,72,255,241,0,77,255,246,0,85,255,247,0,87,255,247,0,88,255,248,0,158,255,244,0,175,255,243,0,252,255,250,1,5,255,251,0,19,0,7,255,247,0,11,0,9,0,62,0,33,0,71,255,246,0,72,255,238,0,85,255,229,0,87,255,201,0,88,255,211,0,94,0,33,0,110,255,238,0,158,255,245,0,171,0,10,0,173,0,24,0,174,0,41,0,175,255,239,0,240,0,27,1,4,255,247,1,5,255,241,1,7,255,251,0,26,0,11,255,166,0,17,255,243,0,18,255,236,0,21,255,194,0,26,255,227,0,32,255,231,0,53,255,189,0,55,255,154,0,56,255,203,0,61,255,187,0,62,255,240,0,71,255,241,0,72,255,249,0,85,255,232,0,87,255,199,0,88,255,212,0,94,255,241,0,110,255,220,0,158,255,243,0,240,255,166,1,4,255,199,1,5,255,247,1,6,255,194,1,7,255,213,1,9,255,186,255,255,255,198,0,23,0,10,255,242,0,11,255,238,0,18,255,247,0,32,255,242,0,43,255,251,0,53,255,231,0,55,255,236,0,56,255,238,0,61,255,239,0,71,255,240,0,72,255,243,0,77,255,245,0,85,255,236,0,87,255,234,0,88,255,236,0,158,255,238,0,175,255,247,0,240,255,237,1,4,255,240,1,5,255,250,1,6,255,244,1,7,255,243,1,9,255,243,0,18,0,7,255,250,0,10,255,241,0,13,255,175,0,16,255,210,0,20,255,248,0,21,255,242,0,33,255,241,0,46,255,246,0,57,255,242,0,72,255,246,0,77,255,251,0,133,255,187,0,173,0,25,0,174,0,4,0,175,255,234,0,251,255,214,0,252,255,242,0,255,255,182,0,13,0,21,255,234,0,53,255,243,0,55,255,251,0,62,255,240,0,71,255,249,0,72,255,243,0,77,255,248,0,85,255,248,0,87,255,248,0,88,255,250,0,94,255,247,0,158,255,247,0,175,255,242,0,1,0,158,255,244,0,47,0,7,255,241,0,11,0,12,0,13,255,213,0,16,255,205,0,17,255,235,0,21,255,211,0,23,255,218,0,25,255,248,0,27,255,222,0,28,255,222,0,33,255,197,0,46,255,230,0,62,0,18,0,71,255,231,0,72,255,175,0,77,255,250,0,84,255,197,0,85,255,230,0,87,255,173,0,88,255,182,0,89,255,170,0,94,0,21,0,110,255,232,0,133,255,183,0,158,255,227,0,162,255,203,0,171,255,254,0,172,255,254,0,173,0,52,0,174,0,30,0,175,255,215,0,189,255,208,0,197,255,216,0,240,0,16,0,244,255,207,0,249,255,207,0,251,255,186,0,252,255,201,0,255,255,166,1,3,255,225,1,4,255,211,1,5,255,202,1,6,255,213,1,7,255,213,1,8,255,209,1,9,255,214,1,10,255,229,0,4,0,158,255,248,0,173,255,251,0,175,255,242,0,255,255,232,0,35,0,7,255,243,0,11,0,16,0,13,255,213,0,16,255,201,0,17,255,246,0,21,255,220,0,23,255,230,0,28,255,248,0,33,255,213,0,46,255,235,0,62,0,29,0,71,255,244,0,72,255,203,0,84,255,217,0,85,255,239,0,87,255,242,0,88,255,241,0,89,255,243,0,94,0,29,0,110,255,245,0,133,255,196,0,158,255,242,0,171,0,9,0,173,0,44,0,174,0,40,0,175,255,216,0,197,255,227,0,240,0,26,0,244,255,241,0,249,255,241,0,251,255,199,0,252,255,218,0,255,255,186,1,3,255,237,1,5,255,244,0,30,0,7,255,247,0,11,0,17,0,13,255,225,0,16,255,215,0,21,255,233,0,23,255,241,0,33,255,223,0,46,255,239,0,62,0,26,0,71,255,247,0,72,255,216,0,85,255,243,0,87,255,247,0,88,255,247,0,89,255,249,0,94,0,28,0,133,255,209,0,158,255,245,0,171,0,4,0,173,0,44,0,174,0,36,0,175,255,222,0,240,0,23,0,244,255,246,0,249,255,246,0,251,255,215,0,252,255,228,0,255,255,209,1,3,255,245,1,5,255,249,0,18,0,7,255,246,0,62,0,31,0,71,255,245,0,72,255,238,0,85,255,228,0,87,255,207,0,88,255,213,0,94,0,31,0,110,255,238,0,158,255,243,0,171,0,7,0,173,0,23,0,174,0,38,0,175,255,239,0,240,0,24,1,4,255,248,1,5,255,240,1,7,255,251,0,13,0,17,255,233,0,21,255,206,0,23,255,218,0,25,255,246,0,33,255,198,0,158,255,230,0,171,0,16,0,173,0,38,0,174,0,47,0,175,255,216,0,189,255,225,0,197,255,234,0,255,255,174,0,8,0,17,255,243,0,21,255,199,0,23,255,247,0,158,255,239,0,171,0,6,0,173,0,29,0,174,0,37,0,175,255,235,0,41,0,17,255,232,0,21,255,228,0,23,255,229,0,25,255,248,0,43,0,49,0,46,255,244,0,53,0,22,0,55,0,31,0,56,0,27,0,57,0,28,0,75,0,7,0,81,255,223,0,84,255,218,0,85,255,224,0,87,255,216,0,88,255,218,0,89,255,226,0,91,255,219,0,133,255,243,0,158,255,244,0,162,255,228,0,171,0,15,0,173,0,34,0,174,0,45,0,175,255,231,0,189,255,252,0,197,255,232,0,200,255,246,0,244,255,215,0,249,0,32,0,251,255,225,0,252,255,216,0,255,255,236,1,3,255,222,1,4,255,219,1,5,255,215,1,6,255,219,1,7,255,218,1,8,255,228,1,9,255,220,1,10,255,223,0,17,0,17,255,244,0,18,255,241,0,26,255,242,0,43,0,16,0,53,255,205,0,55,255,201,0,56,255,216,0,85,255,240,0,87,255,222,0,88,255,231,0,210,255,214,0,249,0,14,1,4,255,220,1,5,255,243,1,6,255,217,1,7,255,226,1,9,255,215,0,12,0,18,255,234,0,26,255,247,0,38,255,240,0,43,255,240,0,46,255,248,0,52,255,250,0,53,255,173,0,54,255,227,0,55,255,193,0,56,255,210,0,58,255,165,0,158,255,249,0,15,0,18,255,235,0,19,255,232,0,24,255,226,0,38,255,237,0,43,255,237,0,46,255,239,0,52,255,237,0,53,255,171,0,54,255,238,0,55,255,193,0,56,255,212,0,57,255,217,0,58,255,167,0,59,255,227,0,158,255,248,0,12,0,21,255,231,0,24,255,245,0,38,255,247,0,43,255,247,0,46,255,251,0,52,255,244,0,53,255,190,0,54,255,243,0,55,255,236,0,56,255,241,0,58,255,218,0,175,255,251,0,11,0,7,255,244,0,38,255,242,0,43,255,242,0,46,255,240,0,52,255,246,0,53,255,245,0,54,255,240,0,55,255,250,0,56,255,248,0,58,255,251,0,59,255,245,0,14,0,18,255,235,0,19,255,245,0,24,255,230,0,38,255,241,0,43,255,241,0,46,255,243,0,52,255,241,0,53,255,187,0,54,255,240,0,55,255,209,0,56,255,213,0,57,255,243,0,58,255,174,0,59,255,243,0,13,0,7,255,235,0,13,255,229,0,16,255,234,0,21,255,244,0,33,255,239,0,38,255,244,0,43,255,244,0,46,255,229,0,54,255,247,0,59,255,243,0,72,255,252,0,94,0,8,0,175,255,224,0,19,0,7,255,244,0,10,0,5,0,16,0,14,0,24,255,225,0,32,255,217,0,38,255,245,0,43,0,45,0,46,255,242,0,53,255,208,0,54,255,246,0,55,255,247,0,56,255,250,0,57,255,250,0,58,255,238,0,59,255,245,0,62,0,25,0,75,0,19,0,94,0,29,0,175,255,250,0,10,0,7,255,242,0,32,255,237,0,53,255,166,0,54,255,251,0,55,255,245,0,56,255,251,0,58,255,217,0,62,255,239,0,72,255,238,0,175,255,230,0,13,0,7,255,244,0,11,255,246,0,38,255,240,0,43,255,240,0,46,255,248,0,53,255,234,0,54,255,228,0,55,255,239,0,56,255,237,0,58,255,241,0,85,255,251,0,87,255,249,0,88,255,251,0,23,0,7,255,237,0,10,255,232,0,13,255,227,0,16,255,225,0,20,255,231,0,21,255,238,0,24,255,200,0,32,255,202,0,33,255,232,0,38,255,243,0,43,255,243,0,46,255,230,0,53,255,163,0,54,255,247,0,55,255,243,0,56,255,247,0,57,255,214,0,58,255,225,0,59,255,227,0,62,255,217,0,72,255,250,0,94,255,228,0,175,255,218,0,12,0,24,255,234,0,38,255,241,0,43,255,241,0,46,255,245,0,52,255,248,0,53,255,202,0,54,255,238,0,55,255,216,0,56,255,224,0,57,255,244,0,58,255,209,0,59,255,245,0,15,0,7,255,246,0,21,255,234,0,24,255,246,0,32,255,229,0,38,255,248,0,43,255,248,0,46,255,248,0,53,255,209,0,54,255,246,0,55,255,237,0,56,255,243,0,58,255,211,0,62,255,230,0,94,255,242,0,175,255,251,0,22,0,7,255,238,0,10,255,231,0,13,255,227,0,16,255,223,0,20,255,231,0,24,255,200,0,32,255,206,0,33,255,240,0,38,255,242,0,43,255,242,0,46,255,229,0,53,255,170,0,54,255,245,0,55,255,237,0,56,255,242,0,57,255,208,0,58,255,210,0,59,255,224,0,62,255,214,0,72,255,250,0,94,255,227,0,175,255,238,0,21,0,7,255,240,0,10,255,232,0,13,255,235,0,16,255,231,0,20,255,240,0,24,255,207,0,32,255,211,0,33,255,247,0,38,255,243,0,43,255,243,0,46,255,232,0,53,255,178,0,54,255,246,0,55,255,236,0,56,255,242,0,57,255,213,0,58,255,211,0,59,255,228,0,62,255,218,0,94,255,229,0,175,255,246,0,17,0,7,255,238,0,32,255,227,0,38,255,247,0,43,255,247,0,46,255,250,0,52,255,248,0,53,255,167,0,54,255,244,0,55,255,236,0,56,255,242,0,58,255,208,0,61,255,247,0,62,255,230,0,72,255,247,0,94,255,237,0,175,255,240,0,240,255,248,0,15,0,19,255,227,0,20,255,230,0,24,255,198,0,33,255,238,0,38,255,243,0,43,255,243,0,46,255,229,0,53,255,168,0,54,255,245,0,55,255,238,0,56,255,242,0,57,255,208,0,58,255,211,0,59,255,225,0,175,255,236,0,11,0,21,255,225,0,24,255,244,0,38,255,242,0,43,255,242,0,46,255,245,0,53,255,203,0,54,255,239,0,55,255,240,0,56,255,243,0,58,255,227,0,175,255,247,0,32,0,17,255,238,0,21,255,238,0,23,255,235,0,43,0,47,0,46,255,247,0,53,0,21,0,55,0,29,0,56,0,25,0,57,0,28,0,85,255,231,0,87,255,227,0,88,255,228,0,89,255,238,0,158,255,247,0,171,0,12,0,173,0,33,0,174,0,44,0,175,255,234,0,189,255,249,0,244,255,233,0,249,0,30,0,251,255,236,0,252,255,228,0,255,255,247,1,3,255,232,1,4,255,230,1,5,255,225,1,6,255,231,1,7,255,229,1,8,255,246,1,9,255,232,1,10,255,238,0,3,0,53,255,200,0,55,255,236,0,56,255,244,0,9,0,46,255,247,0,53,255,230,0,55,255,243,0,56,255,248,0,57,255,236,0,133,255,236,0,251,255,236,0,252,255,248,0,255,255,235,0,2,0,21,255,229,0,23,255,239,0,20,0,43,0,19,0,46,255,238,0,53,255,192,0,55,255,233,0,56,255,241,0,57,255,231,0,72,255,243,0,75,0,20,0,77,255,247,0,89,255,248,0,133,255,235,0,175,255,240,0,244,255,246,0,251,255,227,0,252,255,233,0,255,255,231,1,5,255,244,1,8,255,243,1,9,255,246,1,10,255,240,0,17,0,10,255,228,0,13,255,177,0,16,255,221,0,32,255,223,0,46,255,251,0,53,255,202,0,55,255,248,0,57,255,205,0,61,255,247,0,62,255,214,0,66,255,247,0,89,255,250,0,94,255,226,0,133,255,201,0,251,255,233,0,252,255,251,1,8,255,250,0,9,0,10,255,239,0,11,255,241,0,71,255,250,0,85,255,247,0,87,255,245,0,88,255,248,0,89,255,251,0,90,255,245,0,240,255,242,0,2,0,62,255,246,0,94,255,248,0,4,0,61,255,220,0,94,255,248,0,210,255,195,0,213,255,195,0,2,0,62,255,245,0,94,255,248,0,2,0,11,0,30,0,240,0,28,0,4,0,11,0,18,0,62,0,9,0,94,0,14,0,240,0,18,0,12,0,3,0,29,0,8,0,29,0,11,0,76,0,32,0,39,0,61,0,13,0,62,0,44,0,94,0,33,0,209,0,37,0,210,0,24,0,212,0,37,0,213,0,24,0,240,0,81,0,6,0,11,0,43,0,32,0,27,0,61,0,14,0,62,0,39,0,94,0,44,0,240,0,48,0,10,0,7,255,247,0,10,255,232,0,11,255,240,0,13,255,247,0,32,255,242,0,61,255,246,0,62,255,240,0,89,255,248,0,94,255,243,0,240,255,241,0,1,0,173,0,37,0,12,0,7,255,239,0,11,0,5,0,16,255,209,0,33,255,210,0,110,255,245,0,161,255,187,0,169,255,174,0,173,0,44,0,174,0,28,0,189,255,224,0,197,255,232,0,240,0,9,0,1,0,173,0,37,0,6,0,161,255,187,0,169,255,174,0,173,0,44,0,174,0,28,0,189,255,224,0,197,255,232,0,1,0,143,0,6,0,5,0,133,255,228,0,143,0,10,0,173,0,11,0,251,255,236,0,255,255,235,0,19,0,2,255,247,0,10,255,228,0,11,255,241,0,18,255,242,0,19,255,240,0,24,255,229,0,26,255,248,0,32,255,221,0,61,255,220,0,62,255,214,0,94,255,224,0,240,255,235,0,255,255,247,1,4,255,238,1,6,255,244,1,7,255,246,1,8,255,243,1,9,255,233,1,10,255,250,0,4,0,21,255,221,0,32,255,242,0,62,255,238,0,94,255,246,0,20,0,10,255,224,0,11,255,244,0,16,255,246,0,18,255,241,0,19,255,229,0,24,255,222,0,32,255,223,0,61,255,222,0,62,255,213,0,94,255,222,0,240,255,240,0,251,255,247,0,252,255,251,0,255,255,231,1,4,255,242,1,6,255,247,1,7,255,249,1,8,255,232,1,9,255,234,1,10,255,242,0,1,0,21,255,241,0,13,0,10,255,240,0,13,255,199,0,16,255,217,0,20,255,245,0,21,255,247,0,24,255,218,0,32,255,218,0,33,255,242,0,62,255,215,0,94,255,228,0,251,255,213,0,252,255,243,0,255,255,188,0,8,0,10,255,239,0,11,255,244,0,24,255,247,0,32,255,236,0,61,255,240,0,62,255,226,0,94,255,232,0,240,255,239,0,8,0,10,255,235,0,24,255,244,0,32,255,237,0,61,255,243,0,62,255,217,0,94,255,233,0,240,255,243,0,252,255,252,0,4,0,21,255,247,0,62,255,234,0,94,255,248,1,3,255,252,0,15,0,11,255,221,0,17,255,246,0,18,255,232,0,26,255,237,0,32,255,232,0,61,255,201,0,62,255,231,0,94,255,236,0,110,255,236,0,240,255,220,1,4,255,210,1,5,255,243,1,6,255,219,1,7,255,227,1,9,255,205,0,18,0,10,255,237,0,11,255,238,0,18,255,241,0,24,255,243,0,26,255,247,0,32,255,229,0,61,255,223,0,62,255,220,0,94,255,228,0,110,255,248,0,240,255,234,0,244,255,252,0,249,255,252,1,4,255,238,1,5,255,249,1,6,255,240,1,7,255,241,1,9,255,236,0,15,0,10,255,227,0,13,255,188,0,16,255,223,0,19,255,245,0,20,255,234,0,24,255,215,0,32,255,223,0,61,255,243,0,62,255,213,0,94,255,224,0,251,255,227,0,252,255,248,0,255,255,199,1,8,255,243,1,10,255,251,0,10,0,21,255,242,0,24,255,244,0,32,255,226,0,61,255,228,0,62,255,224,0,94,255,232,0,240,255,243,1,4,255,249,1,6,255,252,1,9,255,246,0,10,0,10,255,233,0,11,255,245,0,24,255,244,0,32,255,232,0,61,255,239,0,62,255,223,0,94,255,230,0,240,255,238,0,255,255,250,1,8,255,252,0,12,0,10,255,241,0,13,255,222,0,16,255,220,0,21,255,230,0,24,255,219,0,32,255,216,0,33,255,223,0,62,255,218,0,94,255,230,0,251,255,210,0,252,255,238,0,255,255,195,0,13,0,10,255,230,0,13,255,248,0,16,255,243,0,24,255,240,0,32,255,236,0,61,255,246,0,62,255,215,0,94,255,225,0,240,255,245,0,251,255,244,0,252,255,249,0,255,255,247,1,10,255,252,0,12,0,10,255,245,0,13,255,223,0,16,255,217,0,21,255,243,0,24,255,223,0,32,255,222,0,33,255,230,0,62,255,217,0,94,255,230,0,251,255,219,0,252,255,240,0,255,255,213,0,11,0,10,255,243,0,13,255,231,0,16,255,226,0,24,255,223,0,32,255,222,0,33,255,239,0,62,255,218,0,94,255,230,0,251,255,227,0,252,255,242,0,255,255,221,0,3,0,21,255,247,0,62,255,233,0,94,255,247,0,14,0,10,255,248,0,13,255,221,0,16,255,215,0,21,255,226,0,23,255,247,0,24,255,225,0,32,255,222,0,33,255,219,0,62,255,218,0,94,255,232,0,251,255,205,0,252,255,236,0,255,255,198,1,3,255,252,0,4,0,21,255,220,0,32,255,227,0,62,255,222,0,94,255,236,0,17,0,11,255,197,0,17,255,241,0,18,255,231,0,21,255,199,0,26,255,228,0,32,255,228,0,61,255,186,0,62,255,227,0,94,255,233,0,110,255,221,0,240,255,192,1,4,255,207,1,5,255,245,1,6,255,186,1,7,255,210,1,9,255,176,255,255,255,208,0,4,0,19,255,239,0,20,255,246,0,24,255,235,0,18,255,240,0,2,54,70,0,4,0,0,54,206,56,224,0,89,0,77,0,0,255,248,255,146,255,220,255,237,255,245,255,234,255,238,255,241,255,203,255,237,255,223,255,218,255,243,255,234,255,146,255,213,255,243,255,236,255,244,255,241,255,146,255,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,210,255,203,255,250,255,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,231,255,224,0,0,0,0,0,0,255,224,0,0,0,0,255,227,255,231,255,243,255,229,255,243,255,245,255,243,255,233,255,247,255,235,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,146,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,124,255,121,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,234,255,222,0,0,0,0,0,0,0,0,0,0,255,243,0,0,0,0,255,231,0,0,0,0,255,193,255,216,255,238,255,248,255,242,255,237,255,247,255,248,255,247,255,248,255,225,255,243,255,238,255,236,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,146,255,215,0,0,255,222,0,0,255,242,0,0,0,0,255,243,0,0,0,0,0,0,255,124,255,121,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,208,255,218,255,214,0,0,0,0,0,0,255,222,0,0,0,7,255,230,0,0,0,0,255,243,0,0,0,0,0,0,255,228,255,241,255,243,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,244,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,218,0,0,0,0,0,0,255,226,0,0,0,0,0,0,0,0,0,0,255,246,0,0,0,0,0,0,255,232,0,0,255,245,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,247,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,245,0,0,255,247,0,0,255,250,255,213,255,192,255,244,255,217,0,0,255,245,0,0,0,0,255,240,0,0,0,0,0,0,255,205,255,204,255,202,255,207,255,219,0,0,0,0,255,241,255,229,0,0,0,0,255,214,0,0,255,213,0,0,255,212,255,239,255,208,255,249,255,221,255,228,255,246,255,241,255,212,255,246,255,223,255,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,251,0,0,0,0,0,0,0,0,255,229,255,251,255,236,0,0,0,0,0,0,255,251,0,0,255,250,255,242,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,250,255,250,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,241,0,0,0,0,0,0,0,0,0,0,255,195,0,0,0,0,0,0,255,242,0,0,255,226,0,0,255,246,0,0,0,0,255,241,255,249,0,0,255,242,0,0,0,0,0,0,255,249,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,249,255,249,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,249,255,250,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,241,255,237,0,0,0,0,0,0,255,250,255,250,255,226,0,0,255,240,0,0,255,249,0,0,255,242,255,244,255,248,255,250,255,250,0,0,255,241,0,0,0,0,255,227,255,250,0,0,0,0,0,0,0,0,0,0,0,0,255,249,255,250,0,0,0,0,255,247,255,228,255,243,255,248,255,225,255,235,0,0,0,0,255,244,0,0,0,0,255,245,0,0,255,251,0,0,255,237,255,244,255,249,0,0,0,0,255,229,0,0,255,246,0,0,0,0,0,0,255,249,255,249,255,228,255,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,241,0,0,0,0,0,0,0,0,0,0,255,244,0,0,0,0,0,0,255,240,255,251,255,235,0,0,255,246,0,0,0,0,255,238,255,240,0,0,255,245,0,0,0,0,0,0,255,247,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,243,255,242,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,241,255,243,0,0,255,248,0,0,255,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,186,255,203,255,199,255,212,255,217,255,236,255,186,255,234,0,0,0,0,255,217,255,248,0,0,255,248,0,0,0,0,0,0,255,211,255,236,255,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,251,255,249,0,0,0,0,255,217,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,251,0,0,0,0,0,0,0,0,0,0,0,0,255,249,255,242,0,0,0,0,0,0,0,0,0,0,255,250,255,249,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,250,255,250,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,251,255,241,0,0,255,243,0,0,0,0,255,250,0,0,0,0,0,0,255,246,255,242,255,246,0,0,0,0,0,0,0,0,0,0,255,245,255,247,0,0,0,0,0,0,0,0,0,0,255,247,255,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,247,255,247,0,0,255,244,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,246,255,247,255,248,0,0,0,0,0,0,255,251,0,0,0,0,255,247,255,247,255,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,246,255,242,255,246,0,0,0,0,0,0,0,0,0,0,255,245,255,247,0,0,0,0,0,0,0,0,0,0,255,247,255,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,247,255,247,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,244,0,0,0,0,0,0,255,222,0,0,255,227,0,0,255,224,0,0,0,0,255,232,255,199,0,0,255,228,0,0,255,250,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,196,0,0,0,0,0,0,255,246,0,0,255,222,0,0,255,249,255,166,255,158,255,249,255,181,0,0,255,232,0,0,0,0,255,238,0,0,0,0,0,0,255,167,255,167,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,250,255,244,255,250,0,0,0,0,255,251,255,238,255,233,255,244,255,233,255,251,255,251,255,251,0,0,255,248,255,246,255,249,0,0,255,236,255,236,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,245,255,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,242,255,239,0,0,0,0,0,0,255,251,255,250,255,229,255,250,255,242,255,228,255,250,0,0,255,242,255,245,255,247,255,250,255,250,0,0,255,242,0,0,0,0,255,230,255,251,0,0,0,0,0,0,0,0,0,0,0,0,255,249,255,250,0,0,0,0,255,247,255,232,255,244,255,248,255,229,255,238,0,0,0,0,255,245,255,251,0,0,255,246,0,0,0,0,0,0,255,240,255,245,255,250,0,0,0,0,255,231,0,0,255,246,0,0,0,0,0,0,255,250,255,249,255,229,255,227,0,0,255,243,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,175,255,216,255,242,255,243,255,248,0,0,255,175,0,0,0,0,0,0,255,250,0,0,0,0,0,0,0,0,0,0,0,0,255,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,251,255,250,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,251,255,237,0,0,255,242,0,0,255,248,0,0,255,245,255,244,255,248,0,0,0,0,0,0,0,0,0,0,255,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,250,255,249,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,250,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,251,0,0,0,0,0,0,0,0,0,0,255,250,255,240,0,0,0,0,0,0,0,0,0,0,255,250,255,244,0,0,0,0,0,0,0,0,0,0,0,0,255,251,0,0,255,243,255,241,255,242,0,0,255,251,0,0,0,0,0,0,0,0,0,0,0,0,255,250,255,241,255,244,0,0,0,0,0,0,0,0,0,0,0,0,255,250,255,250,255,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,216,255,214,255,202,255,195,255,177,0,0,255,195,255,213,255,197,0,0,0,0,255,169,255,171,0,0,255,232,0,0,0,0,0,0,255,168,255,208,255,207,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,250,255,247,0,0,0,0,255,197,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,243,255,234,0,0,0,0,0,0,255,248,255,242,255,240,0,0,255,233,0,0,255,245,0,0,255,243,255,240,255,242,255,243,255,243,0,0,255,243,0,0,0,0,0,0,255,242,255,250,0,0,0,0,0,0,0,0,0,0,255,240,255,244,255,250,0,0,0,0,0,0,0,0,0,0,0,0,255,251,255,250,255,249,255,250,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,244,255,250,255,250,0,0,0,0,0,0,0,0,0,0,0,0,255,245,255,243,255,245,0,0,0,0,0,0,255,250,255,250,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,238,255,213,255,207,255,216,255,196,0,0,255,220,255,213,255,214,0,0,0,0,255,220,255,243,0,0,255,244,0,0,0,0,0,0,255,220,255,243,255,241,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,244,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,248,255,226,255,219,255,216,255,217,255,219,255,230,255,225,255,230,0,0,0,0,255,227,255,248,0,0,255,249,0,0,0,0,0,0,255,224,255,247,255,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,251,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,243,0,0,0,0,0,0,255,223,0,0,255,226,0,0,255,224,0,0,0,0,255,232,255,206,0,0,255,229,0,0,255,251,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,237,255,215,255,201,0,0,0,0,0,0,255,232,255,180,255,180,0,0,255,181,0,0,255,197,255,222,255,215,255,192,255,189,255,171,255,186,255,198,255,215,255,193,0,0,0,0,255,190,255,217,0,0,255,230,0,0,0,0,0,0,255,187,255,229,255,223,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,237,255,221,255,214,0,0,0,0,0,0,0,0,255,248,0,13,0,13,0,7,0,0,255,215,255,216,0,33,255,230,0,33,255,228,0,0,0,0,0,0,0,0,0,0,0,31,255,225,0,0,255,223,255,223,255,235,255,235,255,214,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,229,0,0,0,0,0,0,0,0,255,251,255,217,0,0,0,0,255,246,255,227,255,245,255,214,0,0,255,234,0,0,0,0,255,224,255,242,0,0,255,238,0,0,0,0,0,0,255,235,255,248,255,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,241,255,241,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,241,255,241,0,23,255,233,0,24,255,237,0,0,0,0,0,0,255,250,0,0,0,23,0,0,0,0,255,246,255,246,0,0,0,0,255,251,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,227,255,218,255,213,0,0,0,0,0,0,255,214,0,0,0,36,255,215,255,216,0,0,255,226,0,0,0,0,0,0,255,214,0,0,255,215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,247,255,220,255,201,0,0,255,219,0,0,255,236,0,0,0,0,255,234,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,245,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,234,0,0,0,0,255,236,255,240,255,237,0,0,0,0,0,0,0,0,0,0,0,0,255,186,255,183,0,0,0,0,0,0,0,0,0,0,255,251,255,246,0,0,0,0,0,0,0,0,0,0,0,0,255,231,255,229,255,210,0,0,255,238,255,243,255,231,255,248,255,230,0,0,0,0,0,0,0,0,0,0,255,246,255,227,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,246,255,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,247,255,240,0,0,0,0,0,0,0,0,255,246,0,0,255,234,0,0,0,0,255,245,255,237,255,246,0,0,0,0,0,0,0,0,255,246,0,0,255,181,255,178,0,0,0,0,0,0,0,0,0,0,255,251,255,250,255,238,0,0,0,0,0,0,0,0,0,0,255,232,255,224,255,217,0,0,255,247,255,251,255,226,0,0,255,234,0,0,0,0,0,0,0,0,0,0,255,227,255,217,255,247,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,219,0,0,0,0,0,0,255,249,0,0,255,243,0,0,0,0,0,0,0,0,0,0,0,0,255,247,255,244,0,0,0,0,0,0,0,0,0,0,0,0,255,216,255,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,228,255,240,0,0,0,0,0,0,255,239,0,0,255,245,0,0,0,0,0,0,0,0,0,0,255,244,255,232,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,249,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,242,255,245,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,251,0,0,0,0,0,0,0,0,0,0,0,0,255,241,0,0,0,0,255,251,255,241,255,250,0,0,0,0,0,0,0,0,0,0,0,0,255,189,255,186,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,251,0,0,0,0,0,0,0,0,0,0,255,238,255,223,255,220,0,0,255,252,0,0,255,227,0,0,255,237,0,0,0,0,0,0,0,0,0,0,255,230,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,232,255,229,255,211,255,251,255,246,0,0,255,239,255,229,0,0,0,0,0,0,0,0,0,0,255,244,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,249,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,245,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,223,255,221,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,245,0,0,0,0,0,0,0,0,0,0,255,241,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,250,0,0,0,0,0,0,0,0,0,0,0,0,255,238,255,163,0,0,255,242,255,238,255,243,255,238,255,241,255,231,0,0,0,0,0,0,255,187,255,184,255,162,255,198,255,214,255,249,255,245,255,251,255,248,0,0,255,248,0,0,0,0,0,0,0,0,255,235,255,224,255,214,0,0,255,243,255,248,255,225,0,0,255,235,0,0,0,0,0,0,0,0,0,0,255,232,255,216,0,0,255,233,0,0,0,0,0,0,0,0,0,0,255,248,255,231,255,238,0,0,0,0,255,244,0,0,0,0,0,0,0,0,0,0,255,241,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,247,0,0,0,0,255,242,255,244,255,242,255,244,255,238,0,0,0,0,0,0,0,0,0,0,255,242,255,247,255,246,0,0,255,245,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,242,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,241,0,0,0,0,255,251,255,234,0,0,255,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,234,0,0,0,0,0,0,0,0,0,0,0,0,255,229,255,227,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,251,0,0,255,247,0,0,0,0,255,247,0,0,0,0,255,249,255,240,255,237,0,0,0,0,0,0,0,0,0,0,0,0,255,245,255,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,246,0,0,0,0,0,0,0,0,0,0,255,239,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,240,0,0,0,0,0,0,0,0,0,0,0,0,255,236,255,167,0,0,255,245,255,237,255,246,255,237,255,238,255,238,0,0,255,246,0,0,255,182,255,179,255,173,255,192,255,212,255,218,255,227,255,251,255,249,255,237,255,248,0,0,0,0,0,0,0,0,255,234,255,222,255,214,0,0,255,247,255,251,255,222,0,0,255,236,0,0,0,0,0,0,0,0,0,0,255,224,255,213,255,247,255,223,0,0,0,0,0,0,0,0,0,0,0,0,255,230,255,237,255,229,0,0,255,244,0,0,0,0,0,0,0,0,0,0,255,241,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,183,0,0,0,0,255,242,255,244,255,242,255,243,255,235,0,0,0,0,0,0,255,211,255,209,255,164,255,216,255,218,255,246,255,242,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,244,255,223,255,228,0,0,0,0,0,0,255,226,0,0,255,239,0,0,0,0,0,0,0,0,0,0,255,233,255,215,0,0,255,232,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,242,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,234,255,227,255,211,255,249,255,243,0,0,255,237,255,227,0,0,0,0,0,0,0,0,0,0,255,243,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,233,255,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,241,255,244,0,0,0,0,0,0,0,0,0,0,0,0,255,203,255,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,241,255,224,255,225,0,0,0,0,0,0,255,229,0,0,255,235,0,0,0,0,0,0,0,0,0,0,255,231,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,252,0,0,255,244,0,0,0,0,0,0,0,0,0,0,0,0,255,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,234,255,233,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,227,255,216,255,250,255,247,255,252,0,0,255,227,0,0,0,0,0,0,0,0,0,0,255,242,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,226,255,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,236,255,223,255,252,255,251,0,0,0,0,255,235,0,0,0,0,0,0,0,0,0,0,255,243,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,227,255,225,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,247,0,0,0,0,255,252,255,238,0,0,255,236,0,0,0,0,0,0,0,0,0,0,0,0,255,247,255,240,0,0,0,0,0,0,0,0,0,0,0,0,255,224,255,222,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,238,255,225,255,220,0,0,0,0,0,0,0,0,255,250,0,0,0,0,0,0,0,0,0,0,0,0,255,225,255,214,255,250,255,246,255,252,0,0,255,225,0,0,0,0,0,0,0,0,0,0,255,243,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,227,255,225,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,205,0,0,0,0,0,0,0,0,255,227,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,231,255,214,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,245,0,0,0,0,0,0,0,0,0,0,0,0,255,251,0,0,0,0,0,0,0,0,0,0,255,240,0,0,0,0,0,0,255,245,0,0,255,232,0,0,0,0,0,0,0,0,0,0,0,0,255,242,255,244,0,0,0,0,0,0,0,0,0,0,0,0,255,219,255,216,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,221,255,242,0,0,0,0,0,0,255,232,0,0,255,242,0,0,0,0,0,0,0,0,0,0,255,246,255,222,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,244,255,229,255,222,255,229,0,0,0,0,255,223,0,0,0,34,255,225,255,227,0,0,255,231,0,0,0,0,0,0,255,227,255,232,255,233,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,247,0,0,0,0,0,0,255,248,0,0,255,226,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,229,255,197,255,245,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,237,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,229,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,243,0,0,255,240,255,238,0,0,0,0,0,0,255,247,0,0,0,0,0,0,0,0,0,0,0,0,255,241,255,198,0,0,255,248,0,0,0,0,0,0,255,234,0,0,0,0,255,233,0,0,0,0,255,204,255,195,255,220,255,230,255,224,255,223,0,0,255,247,255,236,255,248,255,226,255,227,255,223,255,226,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,240,255,247,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,233,255,241,255,243,255,241,0,0,0,0,255,246,0,0,255,219,255,243,0,0,255,247,0,0,255,247,0,0,255,245,255,241,255,241,255,246,0,0,0,0,0,0,0,0,0,0,0,0,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,247,255,242,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,177,255,235,0,0,0,0,0,0,0,0,255,177,0,0,0,0,255,228,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,203,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,243,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,245,255,243,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,247,0,0,0,0,0,0,0,0,0,0,255,247,0,0,255,245,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,236,255,237,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,123,0,0,0,0,0,0,0,0,255,236,255,189,255,190,255,235,255,217,255,209,255,241,0,0,255,124,255,205,255,194,255,182,255,193,0,0,0,0,255,228,0,0,0,0,255,213,255,227,0,0,0,0,0,0,0,0,0,0,255,211,255,217,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,243,255,248,255,225,255,245,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,226,255,227,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,245,0,0,0,0,0,0,0,0,0,0,0,0,255,110,0,0,0,0,0,0,0,0,255,234,255,174,255,184,255,237,255,210,255,203,255,234,255,181,255,110,255,200,255,179,255,167,255,178,255,192,255,110,255,223,0,0,0,6,255,200,255,215,0,0,255,234,0,0,0,0,0,0,255,198,255,204,255,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,243,255,244,255,213,255,241,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,214,255,215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,220,0,0,255,248,255,248,0,0,0,0,255,234,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,146,255,215,0,0,255,222,0,0,255,242,0,0,0,0,255,243,0,0,0,0,0,0,0,0,255,121,255,214,255,213,255,226,0,0,0,0,255,241,255,239,0,0,255,242,255,222,0,0,255,221,0,0,0,0,0,0,0,0,0,0,255,227,255,236,0,0,0,0,0,0,255,248,255,223,255,232,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,232,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,240,0,0,255,248,255,223,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,217,255,216,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,246,0,0,255,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,239,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,228,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,240,255,239,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,197,0,0,0,0,0,0,0,0,0,0,255,233,0,0,255,247,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,227,255,225,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,247,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,199,0,0,0,0,0,0,0,0,0,0,255,199,255,252,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,252,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,237,255,243,0,0,0,0,0,0,255,233,0,0,255,243,0,0,0,0,0,0,0,0,0,0,255,235,255,217,0,0,255,244,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,243,0,0,0,0,0,0,0,0,0,0,255,227,0,0,255,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,208,0,0,0,0,0,0,0,0,0,0,255,221,0,0,255,244,255,203,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,203,255,201,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,251,255,243,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,252,255,241,255,239,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,247,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,248,255,232,255,251,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,228,255,227,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,243,255,234,255,235,255,244,255,244,255,223,255,222,0,0,0,0,0,0,255,223,0,0,255,240,0,0,255,247,255,250,0,0,0,0,255,224,255,214,255,248,255,223,0,0,0,0,0,0,0,0,0,0,0,0,255,242,0,0,255,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,188,0,0,0,0,0,0,0,0,0,0,255,188,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,225,255,222,0,0,0,0,0,0,0,0,255,226,255,222,255,243,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,223,0,0,0,0,0,0,0,0,255,240,255,223,255,247,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,232,0,0,0,0,0,0,0,0,255,247,255,231,255,250,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,243,0,0,0,0,0,0,0,0,0,0,255,227,0,0,255,232,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,238,255,221,0,0,0,0,0,0,0,0,255,223,255,221,255,235,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,236,0,0,0,0,0,0,0,0,0,0,255,226,0,0,255,244,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,28,0,3,0,3,0,0,0,7,0,9,0,1,0,11,0,13,0,4,0,15,0,26,0,7,0,30,0,30,0,19,0,33,0,40,0,20,0,43,0,46,0,28,0,49,0,49,0,32,0,51,0,61,0,33,0,66,0,72,0,44,0,76,0,77,0,51,0,83,0,85,0,53,0,87,0,92,0,56,0,97,0,97,0,62,0,110,0,111,0,63,0,126,0,126,0,65,0,157,0,158,0,66,0,161,0,163,0,68,0,171,0,175,0,71,0,209,0,210,0,76,0,212,0,213,0,78,0,221,0,221,0,80,0,240,0,246,0,81,0,249,0,252,0,88,1,0,1,0,0,92,1,2,1,10,0,93,1,12,1,12,0,102,255,255,255,255,0,103,0,2,0,22,0,3,0,3,0,0,0,7,0,7,0,1,0,9,0,9,0,2,0,13,0,16,0,3,0,21,0,21,0,7,0,24,0,24,0,8,0,33,0,61,0,9,0,66,0,92,0,38,0,97,0,97,0,65,0,107,0,107,0,66,0,110,0,110,0,67,0,122,0,122,0,68,0,126,0,149,0,69,0,151,0,181,0,93,0,183,0,190,0,124,0,193,0,200,0,132,0,207,0,214,0,140,0,220,0,221,0,148,0,240,0,245,0,150,0,247,0,248,0,156,0,250,1,2,0,158,1,4,1,12,0,167,0,1,0,7,1,6,0,1,0,0,0,2,0,0,0,0,0,0,0,3,0,4,0,5,0,6,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,10,0,11,0,12,0,13,0,14,0,15,0,16,0,17,0,17,0,18,0,19,0,20,0,21,0,17,0,22,0,23,0,22,0,24,0,25,0,26,0,27,0,28,0,29,0,30,0,31,0,32,0,33,0,34,0,0,0,0,0,0,0,0,0,35,0,36,0,37,0,38,0,39,0,40,0,41,0,42,0,43,0,43,0,44,0,45,0,42,0,42,0,46,0,46,0,47,0,48,0,49,0,50,0,47,0,51,0,52,0,53,0,54,0,55,0,56,0,0,0,0,0,0,0,0,0,57,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,58,0,0,0,0,0,59,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,60,0,0,0,0,0,0,0,61,0,10,0,10,0,10,0,10,0,10,0,10,0,14,0,12,0,14,0,14,0,14,0,14,0,17,0,17,0,17,0,17,0,13,0,17,0,22,0,22,0,22,0,22,0,22,0,0,0,22,0,27,0,27,0,27,0,27,0,31,0,62,0,63,0,35,0,35,0,35,0,35,0,35,0,35,0,39,0,37,0,39,0,39,0,39,0,39,0,43,0,43,0,43,0,43,0,64,0,42,0,46,0,46,0,46,0,46,0,46,0,0,0,46,0,47,0,47,0,47,0,47,0,54,0,36,0,54,0,0,0,0,0,43,0,14,0,39,0,25,0,49,0,31,0,32,0,55,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,4,0,65,0,66,0,67,0,65,0,66,0,67,0,0,0,0,0,0,0,0,0,0,0,58,0,60,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,0,71,0,72,0,73,0,70,0,74,0,0,0,75,0,75,0,0,0,76,0,69,0,78,0,75,0,79,0,70,0,80,0,79,0,81,0,0,0,82,0,83,0,84,0,85,0,86,0,87,0,88,0,70,0,77,0,1,0,2,1,11,0,73,0,23,0,0,0,0,0,0,0,1,0,23,0,0,0,64,0,50,0,0,0,2,0,14,0,15,0,3,0,0,0,74,0,76,0,0,0,4,0,0,0,5,0,67,0,0,0,0,0,70,0,71,0,0,0,0,0,0,0,51,0,6,0,16,0,27,0,28,0,27,0,29,0,27,0,28,0,27,0,27,0,75,0,27,0,27,0,7,0,27,0,28,0,27,0,28,0,27,0,30,0,37,0,31,0,38,0,39,0,40,0,24,0,41,0,0,0,52,0,65,0,0,0,0,0,0,0,17,0,62,0,18,0,18,0,18,0,42,0,8,0,62,0,63,0,63,0,62,0,53,0,32,0,32,0,18,0,32,0,18,0,32,0,19,0,43,0,25,0,54,0,55,0,44,0,26,0,33,0,0,0,0,0,56,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,0,57,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66,0,0,0,0,0,0,0,0,0,16,0,16,0,16,0,16,0,16,0,16,0,9,0,28,0,29,0,29,0,29,0,29,0,27,0,27,0,27,0,27,0,27,0,27,0,28,0,28,0,28,0,28,0,28,0,0,0,28,0,31,0,31,0,31,0,31,0,24,0,27,0,45,0,17,0,17,0,17,0,17,0,17,0,17,0,17,0,18,0,18,0,18,0,18,0,18,0,63,0,63,0,63,0,63,0,10,0,32,0,18,0,18,0,18,0,18,0,18,0,0,0,18,0,25,0,25,0,25,0,25,0,26,0,32,0,26,0,0,0,0,0,63,0,28,0,18,0,30,0,19,0,24,0,41,0,33,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,14,0,35,0,36,0,21,0,35,0,36,0,21,0,0,0,0,0,0,0,15,0,0,0,20,0,66,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,58,0,34,0,22,0,34,0,68,0,34,0,22,0,34,0,34,0,69,0,34,0,11,0,13,0,34,0,22,0,12,0,34,0,22,0,34,0,72,0,46,0,59,0,60,0,61,0,47,0,48,0,49,0,22,0,34,0,1,0,0,0,10,0,32,0,58,0,1,108,97,116,110,0,8,0,4,0,0,0,0,255,255,0,2,0,0,0,1,0,2,97,97,108,116,0,14,115,109,99,112,0,20,0,0,0,1,0,0,0,0,0,1,0,1,0,2,0,6,0,14,0,1,0,0,0,1,0,78,0,1,0,0,0,1,0,8,0,2,0,124,0,28,0,251,0,241,0,242,0,243,0,244,0,245,0,246,0,247,0,248,0,249,0,250,1,12,0,252,0,253,0,254,1,0,1,1,1,2,1,3,1,4,1,5,1,6,1,7,1,8,1,9,1,10,0,255,1,11,0,2,0,62,0,28,0,251,0,241,0,242,0,243,0,244,0,245,0,246,0,247,0,248,0,249,0,250,1,12,0,252,0,253,0,254,1,0,1,1,1,2,1,3,1,4,1,5,1,6,1,7,1,8,1,9,1,10,0,255,1,11,0,2,0,3,0,66,0,91,0,0,0,165,0,165,0,26,0,195,0,195,0,27,0,0,0,3,1,245,1,144,0,5,0,0,2,188,2,138,0,0,0,140,2,188,2,138,0,0,1,221,0,50,0,250,8,2,2,11,8,3,5,2,2,2,0,4,128,0,0,47,0,0,0,11,0,0,0,0,0,0,0,0,80,89,82,83,0,64,0,32,33,34,3,197,255,6,0,0,3,197,0,250,0,0,0,1,0,0,0,0,1,234,2,188,0,0,0,32,0,2,0,0,0,3,0,0,0,3,0,0,2,222,0,1,0,0,0,0,0,28,0,3,0,1,0,0,1,230,0,6,1,202,0,0,0,32,0,224,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10,0,11,0,12,0,13,0,14,0,15,0,16,0,17,0,18,0,19,0,20,0,21,0,22,0,23,0,24,0,25,0,26,0,27,0,28,0,29,0,30,0,31,0,32,0,33,0,34,0,35,0,36,0,37,0,38,0,39,0,40,0,41,0,42,0,43,0,44,0,45,0,46,0,47,0,48,0,49,0,50,0,51,0,52,0,53,0,54,0,55,0,56,0,57,0,58,0,59,0,60,0,61,0,62,0,63,0,64,0,65,0,66,0,67,0,68,0,69,0,70,0,71,0,72,0,73,0,74,0,75,0,76,0,77,0,78,0,79,0,80,0,81,0,82,0,83,0,84,0,85,0,86,0,87,0,88,0,89,0,90,0,91,0,92,0,93,0,94,0,95,0,0,0,239,0,0,0,211,0,201,0,214,0,218,0,215,0,216,0,203,0,219,0,196,0,220,0,194,0,0,0,199,0,0,0,0,0,209,0,210,0,212,0,213,0,217,0,207,0,208,0,206,0,240,0,197,0,221,0,195,0,0,0,200,0,198,0,96,0,97,0,98,0,99,0,100,0,101,0,102,0,103,0,104,0,105,0,106,0,107,0,108,0,109,0,110,0,0,0,111,0,112,0,113,0,114,0,115,0,116,0,117,0,118,0,119,0,120,0,121,0,122,0,123,0,124,0,125,0,126,0,127,0,128,0,129,0,130,0,131,0,132,0,133,0,134,0,135,0,136,0,137,0,138,0,139,0,140,0,141,0,142,0,143,0,144,0,145,0,146,0,147,0,148,0,149,0,150,0,151,0,152,0,153,0,154,0,155,0,156,0,157,0,158,0,159,0,160,0,161,0,162,0,163,0,164,0,165,0,166,0,167,0,168,0,169,0,170,0,171,0,172,0,173,0,174,0,175,0,176,0,177,0,178,0,179,0,180,0,181,0,182,0,183,0,184,0,185,0,186,0,187,0,188,0,189,0,190,0,4,0,248,0,0,0,58,0,32,0,4,0,26,0,126,0,142,0,158,0,174,0,255,1,13,1,49,1,83,1,97,1,120,1,126,1,146,2,55,2,199,2,218,2,220,32,20,32,26,32,30,32,34,32,38,32,48,32,58,32,112,32,121,32,137,32,172,33,34,255,255,0,0,0,32,0,142,0,158,0,160,0,176,1,12,1,49,1,82,1,96,1,120,1,125,1,146,2,55,2,198,2,218,2,220,32,19,32,24,32,28,32,32,32,38,32,48,32,57,32,112,32,116,32,128,32,172,33,34,255,255,255,225,0,57,0,42,255,192,255,191,255,179,255,144,255,112,255,100,255,78,255,74,255,55,254,147,254,5,253,243,253,242,224,188,224,185,224,184,224,183,224,180,224,171,224,163,224,110,224,107,224,101,224,67,223,206,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,248,0,0,0,58,0,32,0,4,0,26,0,126,0,142,0,158,0,174,0,255,1,13,1,49,1,83,1,97,1,120,1,126,1,146,2,55,2,199,2,218,2,220,32,20,32,26,32,30,32,34,32,38,32,48,32,58,32,112,32,121,32,137,32,172,33,34,255,255,0,0,0,32,0,142,0,158,0,160,0,176,1,12,1,49,1,82,1,96,1,120,1,125,1,146,2,55,2,198,2,218,2,220,32,19,32,24,32,28,32,32,32,38,32,48,32,57,32,112,32,116,32,128,32,172,33,34,255,255,255,225,0,57,0,42,255,192,255,191,255,179,255,144,255,112,255,100,255,78,255,74,255,55,254,147,254,5,253,243,253,242,224,188,224,185,224,184,224,183,224,180,224,171,224,163,224,110,224,107,224,101,224,67,223,206,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,70,0,84,0,58,0,96,0,72,0,0,0,14,255,14,0,8,1,64,0,8,1,234,0,10,2,188,0,14,2,48,0,11,2,238,0,5,184,0,0,44,75,184,0,9,80,88,177,1,1,142,89,184,1,255,133,184,0,68,29,185,0,9,0,3,95,94,45,184,0,1,44,32,32,69,105,68,176,1,96,45,184,0,2,44,184,0,1,42,33,45,184,0,3,44,32,70,176,3,37,70,82,88,35,89,32,138,32,138,73,100,138,32,70,32,104,97,100,176,4,37,70,32,104,97,100,82,88,35,101,138,89,47,32,176,0,83,88,105,32,176,0,84,88,33,176,64,89,27,105,32,176,0,84,88,33,176,64,101,89,89,58,45,184,0,4,44,32,70,176,4,37,70,82,88,35,138,89,32,70,32,106,97,100,176,4,37,70,32,106,97,100,82,88,35,138,89,47,253,45,184,0,5,44,75,32,176,3,38,80,88,81,88,176,128,68,27,176,64,68,89,27,33,33,32,69,176,192,80,88,176,192,68,27,33,89,89,45,184,0,6,44,32,32,69,105,68,176,1,96,32,32,69,125,105,24,68,176,1,96,45,184,0,7,44,184,0,6,42,45,184,0,8,44,75,32,176,3,38,83,88,176,64,27,176,0,89,138,138,32,176,3,38,83,88,35,33,176,128,138,138,27,138,35,89,32,176,3,38,83,88,35,33,184,0,192,138,138,27,138,35,89,32,176,3,38,83,88,35,33,184,1,0,138,138,27,138,35,89,32,176,3,38,83,88,35,33,184,1,64,138,138,27,138,35,89,32,184,0,3,38,83,88,176,3,37,69,184,1,128,80,88,35,33,184,1,128,35,33,27,176,3,37,69,35,33,35,33,89,27,33,89,68,45,184,0,9,44,75,83,88,69,68,27,33,33,89,45,0,0,0,0,2,0,8,0,2,255,255,0,3,0,1,0,72,0,250,0,162,1,104,0,3,0,28,184,0,2,47,65,3,0,0,0,2,0,1,93,184,0,3,220,0,184,0,1,47,184,0,2,220,48,49,55,35,53,51,162,90,90,250,110,0,0,2,0,59,0,0,0,183,2,238,0,3,0,7,0,164,187,0,7,0,4,0,6,0,4,43,65,5,0,0,0,7,0,16,0,7,0,2,93,184,0,7,16,184,0,0,208,65,13,0,6,0,0,0,22,0,0,0,38,0,0,0,54,0,0,0,70,0,0,0,86,0,0,0,6,113,65,5,0,0,0,6,0,16,0,6,0,2,93,184,0,6,16,184,0,3,208,65,13,0,9,0,3,0,25,0,3,0,41,0,3,0,57,0,3,0,73,0,3,0,89,0,3,0,6,113,0,184,0,0,69,88,184,0,3,47,27,185,0,3,0,18,62,89,184,0,0,69,88,184,0,4,47,27,185,0,4,0,6,62,89,184,0,7,220,65,3,0,63,0,7,0,1,113,184,0,1,220,48,49,19,3,35,3,19,35,53,51,183,30,64,30,104,84,84,2,238,253,218,2,38,253,18,86,0,2,0,40,1,194,1,106,2,238,0,3,0,7,0,60,184,0,7,47,184,0,3,220,185,0,0,0,4,244,184,0,7,16,185,0,4,0,4,244,0,184,0,0,69,88,184,0,7,47,27,185,0,7,0,18,62,89,184,0,6,220,184,0,2,208,184,0,7,16,184,0,3,208,48,49,1,3,35,3,35,3,35,3,1,106,20,52,20,136,20,54,20,2,238,254,212,1,44,254,212,1,44,0,0,2,0,33,255,245,2,160,2,188,0,27,0,31,1,239,184,0,12,47,65,3,0,137,0,12,0,1,93,65,5,0,0,0,12,0,16,0,12,0,2,93,184,0,8,220,184,0,7,220,184,0,26,208,65,3,0,71,0,26,0,1,93,186,0,27,0,26,0,7,17,18,57,184,0,27,16,184,0,0,208,184,0,0,47,186,0,2,0,26,0,7,17,18,57,186,0,3,0,26,0,7,17,18,57,184,0,3,16,184,0,4,208,184,0,4,47,186,0,6,0,7,0,26,17,18,57,184,0,8,16,184,0,25,208,65,3,0,71,0,25,0,1,93,186,0,9,0,8,0,25,17,18,57,184,0,12,16,184,0,11,220,184,0,22,208,65,3,0,71,0,22,0,1,93,186,0,10,0,11,0,22,17,18,57,184,0,12,16,184,0,21,208,65,3,0,71,0,21,0,1,93,186,0,13,0,12,0,21,17,18,57,184,0,13,16,184,0,14,208,184,0,14,47,186,0,16,0,12,0,21,17,18,57,186,0,17,0,21,0,12,17,18,57,184,0,17,16,184,0,18,208,184,0,18,47,186,0,20,0,21,0,12,17,18,57,186,0,23,0,22,0,11,17,18,57,186,0,24,0,25,0,8,17,18,57,186,0,28,0,25,0,8,17,18,57,186,0,29,0,22,0,11,17,18,57,186,0,30,0,11,0,22,17,18,57,186,0,31,0,8,0,25,17,18,57,0,184,0,0,69,88,184,0,22,47,27,185,0,22,0,14,62,89,184,0,0,69,88,184,0,11,47,27,185,0,11,0,6,62,89,186,0,23,0,22,0,11,17,18,57,184,0,23,47,65,3,0,15,0,23,0,1,93,185,0,29,0,2,244,65,3,0,159,0,29,0,1,93,184,0,2,208,186,0,30,0,11,0,22,17,18,57,184,0,30,47,65,3,0,144,0,30,0,1,93,184,0,3,208,184,0,30,16,185,0,10,0,2,244,65,3,0,159,0,10,0,1,93,184,0,6,208,184,0,11,16,184,0,8,208,184,0,10,16,184,0,13,208,184,0,30,16,184,0,16,208,184,0,29,16,184,0,17,208,184,0,23,16,184,0,20,208,184,0,22,16,184,0,25,208,184,0,23,16,184,0,27,208,48,49,1,7,35,7,51,7,35,7,35,55,35,7,35,55,35,55,51,55,35,55,51,55,51,7,51,55,51,15,1,35,7,51,2,160,29,116,48,128,38,122,87,80,87,133,87,80,86,120,37,115,48,126,29,129,74,80,74,133,75,80,74,113,132,48,132,1,251,84,123,84,227,227,227,227,84,123,84,193,193,193,193,84,123,0,0,0,1,0,42,255,224,1,222,2,236,0,43,2,240,186,0,39,0,17,0,3,43,65,3,0,16,0,39,0,1,93,65,3,0,208,0,39,0,1,93,65,3,0,144,0,39,0,1,93,65,3,0,176,0,39,0,1,93,65,3,0,111,0,17,0,1,93,65,3,0,79,0,17,0,1,93,65,3,0,16,0,17,0,1,93,186,0,2,0,39,0,17,17,18,57,184,0,2,47,185,0,1,0,4,244,186,0,0,0,1,0,2,17,18,57,186,0,3,0,2,0,1,17,18,57,186,0,5,0,17,0,39,17,18,57,184,0,5,47,184,0,39,16,184,0,10,220,65,11,0,79,0,10,0,95,0,10,0,111,0,10,0,127,0,10,0,143,0,10,0,5,93,65,3,0,223,0,10,0,1,93,184,0,3,16,184,0,22,208,184,0,2,16,184,0,23,208,184,0,1,16,184,0,24,208,184,0,0,16,184,0,25,208,186,0,27,0,39,0,17,17,18,57,184,0,27,47,184,0,17,16,184,0,32,220,65,3,0,239,0,32,0,1,93,65,9,0,80,0,32,0,96,0,32,0,112,0,32,0,128,0,32,0,4,93,0,184,0,2,47,184,0,0,69,88,184,0,23,47,27,185,0,23,0,18,62,89,65,5,0,80,0,2,0,96,0,2,0,2,93,186,0,3,0,2,0,23,17,18,57,184,0,3,47,184,0,0,208,184,0,3,16,184,0,6,220,65,3,0,128,0,6,0,1,93,65,3,0,32,0,6,0,1,93,184,0,3,16,185,0,8,0,2,244,186,0,22,0,23,0,2,17,18,57,184,0,22,47,186,0,13,0,3,0,22,17,18,57,65,9,0,90,0,13,0,106,0,13,0,122,0,13,0,138,0,13,0,4,93,184,0,25,208,184,0,22,16,184,0,28,220,184,0,22,16,185,0,30,0,2,244,186,0,35,0,22,0,3,17,18,57,48,49,1,65,3,0,135,0,5,0,1,93,65,3,0,25,0,15,0,1,93,65,3,0,27,0,16,0,1,93,65,3,0,139,0,16,0,1,93,65,3,0,8,0,20,0,1,93,65,11,0,53,0,34,0,69,0,34,0,85,0,34,0,101,0,34,0,117,0,34,0,5,93,65,3,0,21,0,37,0,1,93,65,3,0,117,0,37,0,1,93,65,3,0,38,0,37,0,1,93,65,7,0,71,0,37,0,87,0,37,0,103,0,37,0,3,93,65,3,0,118,0,38,0,1,93,65,3,0,22,0,42,0,1,93,65,3,0,7,0,42,0,1,93,0,65,3,0,139,0,4,0,1,93,65,11,0,60,0,4,0,76,0,4,0,92,0,4,0,108,0,4,0,124,0,4,0,5,93,65,3,0,139,0,5,0,1,93,65,3,0,137,0,12,0,1,93,65,3,0,24,0,15,0,1,93,65,3,0,41,0,15,0,1,93,65,3,0,6,0,20,0,1,93,65,3,0,131,0,26,0,1,93,65,11,0,52,0,26,0,68,0,26,0,84,0,26,0,100,0,26,0,116,0,26,0,5,93,65,11,0,55,0,34,0,71,0,34,0,87,0,34,0,103,0,34,0,119,0,34,0,5,93,65,3,0,69,0,37,0,1,93,65,5,0,22,0,37,0,38,0,37,0,2,93,65,7,0,86,0,37,0,102,0,37,0,118,0,37,0,3,93,65,5,0,9,0,42,0,25,0,42,0,2,93,37,23,35,55,38,39,55,22,51,50,53,52,46,4,53,52,62,2,55,39,51,7,22,23,7,38,35,34,21,20,30,4,21,20,14,2,1,29,15,89,17,117,59,12,70,116,110,47,71,82,71,47,21,45,71,49,17,90,16,108,53,9,102,65,121,49,73,85,73,49,14,42,76,82,114,113,6,32,109,58,63,29,36,26,24,34,52,42,28,53,41,28,5,117,117,6,31,96,48,58,27,32,23,24,38,61,49,22,49,43,33,0,0,0,0,5,0,35,255,242,3,37,2,193,0,3,0,21,0,37,0,55,0,71,2,46,184,0,7,47,184,0,41,47,65,7,0,0,0,41,0,16,0,41,0,32,0,41,0,3,93,184,0,51,220,186,0,1,0,7,0,51,17,18,57,184,0,1,47,184,0,0,220,184,0,1,16,184,0,3,220,184,0,2,220,184,0,7,16,184,0,17,220,184,0,7,16,184,0,27,220,65,3,0,31,0,27,0,1,113,184,0,17,16,184,0,33,220,65,3,0,16,0,33,0,1,113,184,0,41,16,184,0,61,220,65,3,0,31,0,61,0,1,113,184,0,51,16,184,0,67,220,65,3,0,16,0,67,0,1,113,0,184,0,0,69,88,184,0,12,47,27,185,0,12,0,14,62,89,184,0,0,69,88,184,0,2,47,27,185,0,2,0,14,62,89,184,0,0,69,88,184,0,38,47,27,185,0,38,0,6,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,12,16,184,0,4,220,184,0,12,16,184,0,22,220,184,0,4,16,184,0,30,220,184,0,38,16,184,0,46,220,184,0,56,220,184,0,38,16,184,0,64,220,48,49,1,65,3,0,87,0,0,0,1,93,65,7,0,10,0,6,0,26,0,6,0,42,0,6,0,3,93,65,7,0,10,0,9,0,26,0,9,0,42,0,9,0,3,93,65,3,0,200,0,10,0,1,93,65,3,0,199,0,14,0,1,93,65,7,0,5,0,15,0,21,0,15,0,37,0,15,0,3,93,65,7,0,5,0,19,0,21,0,19,0,37,0,19,0,3,93,65,3,0,199,0,20,0,1,93,65,5,0,118,0,24,0,134,0,24,0,2,93,65,3,0,201,0,39,0,1,93,65,7,0,10,0,40,0,26,0,40,0,42,0,40,0,3,93,65,7,0,10,0,43,0,26,0,43,0,42,0,43,0,3,93,65,3,0,200,0,44,0,1,93,65,3,0,199,0,48,0,1,93,65,7,0,5,0,49,0,21,0,49,0,37,0,49,0,3,93,65,7,0,5,0,53,0,21,0,53,0,37,0,53,0,3,93,65,3,0,199,0,54,0,1,93,65,5,0,118,0,58,0,134,0,58,0,2,93,0,65,3,0,203,0,5,0,1,93,65,3,0,197,0,10,0,1,93,65,3,0,195,0,14,0,1,93,65,3,0,202,0,20,0,1,93,65,3,0,201,0,39,0,1,93,65,3,0,199,0,44,0,1,93,65,3,0,198,0,48,0,1,93,65,3,0,202,0,54,0,1,93,23,35,1,51,1,34,38,53,52,62,2,51,50,30,2,21,20,14,2,3,34,14,2,21,20,22,51,50,54,53,52,46,2,1,34,38,53,52,62,2,51,50,30,2,21,20,14,2,3,34,14,2,21,20,22,51,50,54,53,52,46,2,237,75,1,165,74,254,36,64,82,24,42,55,30,31,53,39,23,23,40,55,29,19,34,26,15,54,37,40,54,14,26,33,1,195,64,82,24,42,55,30,31,53,39,23,23,40,55,29,19,34,26,15,54,37,40,54,14,26,33,12,2,200,254,145,94,88,46,71,48,25,24,46,67,44,46,71,49,25,1,64,19,36,52,31,60,70,75,64,29,48,34,18,253,101,94,88,46,71,48,25,24,46,67,44,46,71,49,25,1,64,19,36,52,31,60,70,75,64,29,48,34,18,0,3,0,36,255,233,2,81,2,191,0,30,0,43,0,51,3,97,186,0,28,0,10,0,3,43,65,3,0,127,0,10,0,1,93,65,3,0,16,0,10,0,1,93,184,0,10,16,185,0,47,0,4,244,65,3,0,16,0,28,0,1,93,184,0,28,16,185,0,27,0,5,244,186,0,44,0,47,0,27,17,18,57,65,3,0,105,0,44,0,1,93,186,0,30,0,28,0,10,17,18,57,65,3,0,103,0,30,0,1,93,186,0,2,0,44,0,30,17,18,57,186,0,14,0,10,0,28,17,18,57,184,0,14,47,184,0,22,220,65,3,0,128,0,22,0,1,93,186,0,12,0,14,0,22,17,18,57,65,3,0,25,0,12,0,1,93,65,3,0,8,0,12,0,1,93,186,0,24,0,22,0,14,17,18,57,65,3,0,135,0,24,0,1,93,65,3,0,10,0,24,0,1,93,65,3,0,153,0,24,0,1,93,65,3,0,102,0,24,0,1,93,65,3,0,117,0,24,0,1,93,186,0,25,0,44,0,30,17,18,57,65,3,0,136,0,25,0,1,93,184,0,14,16,184,0,34,220,65,3,0,159,0,34,0,1,93,65,7,0,63,0,34,0,79,0,34,0,95,0,34,0,3,113,186,0,36,0,12,0,24,17,18,57,184,0,22,16,184,0,41,220,65,3,0,161,0,41,0,1,93,65,3,0,144,0,41,0,1,93,186,0,45,0,12,0,24,17,18,57,0,184,0,0,69,88,184,0,19,47,27,185,0,19,0,14,62,89,184,0,0,69,88,184,0,5,47,27,185,0,5,0,6,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,186,0,27,0,19,0,5,17,18,57,184,0,27,47,186,0,2,0,5,0,27,17,18,57,186,0,36,0,19,0,5,17,18,57,65,3,0,101,0,36,0,1,93,65,3,0,133,0,36,0,1,93,186,0,45,0,19,0,5,17,18,57,65,3,0,105,0,45,0,1,93,186,0,12,0,36,0,45,17,18,57,186,0,24,0,36,0,45,17,18,57,186,0,25,0,27,0,5,17,18,57,65,7,0,101,0,25,0,117,0,25,0,133,0,25,0,3,93,186,0,30,0,25,0,2,17,18,57,184,0,19,16,185,0,31,0,1,244,186,0,44,0,25,0,2,17,18,57,65,3,0,103,0,44,0,1,93,184,0,5,16,185,0,50,0,1,244,48,49,1,65,3,0,22,0,3,0,1,93,65,7,0,88,0,7,0,104,0,7,0,120,0,7,0,3,93,65,3,0,105,0,8,0,1,93,65,3,0,137,0,8,0,1,93,65,3,0,10,0,8,0,1,93,65,3,0,90,0,8,0,1,93,65,3,0,122,0,8,0,1,93,65,3,0,89,0,9,0,1,93,65,3,0,9,0,16,0,1,93,65,3,0,27,0,16,0,1,93,65,5,0,6,0,20,0,22,0,20,0,2,93,65,3,0,4,0,21,0,1,93,65,5,0,38,0,21,0,54,0,21,0,2,93,65,3,0,88,0,25,0,1,93,0,65,3,0,25,0,3,0,1,93,65,3,0,89,0,3,0,1,93,65,3,0,122,0,3,0,1,93,65,7,0,89,0,7,0,105,0,7,0,121,0,7,0,3,93,65,3,0,88,0,8,0,1,93,65,3,0,120,0,8,0,1,93,65,3,0,9,0,8,0,1,93,65,3,0,105,0,8,0,1,93,65,3,0,88,0,9,0,1,93,65,3,0,21,0,16,0,1,93,65,3,0,6,0,16,0,1,93,65,3,0,20,0,20,0,1,93,65,3,0,68,0,20,0,1,93,65,3,0,5,0,20,0,1,93,65,3,0,37,0,20,0,1,93,65,3,0,54,0,20,0,1,93,65,3,0,86,0,20,0,1,93,65,3,0,85,0,25,0,1,93,65,3,0,71,0,25,0,1,93,65,3,0,137,0,45,0,1,93,33,35,39,14,1,35,34,46,2,53,52,55,38,53,52,62,2,51,50,22,21,20,7,23,54,55,51,6,7,3,34,6,21,20,23,63,1,62,1,53,52,38,19,39,6,21,20,22,51,50,2,81,92,44,44,86,58,60,87,58,28,126,75,31,53,71,40,72,71,164,190,32,7,81,4,61,236,43,59,55,53,20,29,24,43,106,208,81,75,73,88,46,38,31,27,49,68,41,115,89,91,79,39,61,44,23,69,57,119,102,195,41,149,156,95,2,22,52,48,61,67,41,17,25,44,26,36,39,253,239,208,57,87,55,69,0,0,0,1,0,41,1,194,0,141,2,238,0,3,0,34,184,0,3,47,185,0,0,0,4,244,0,184,0,0,69,88,184,0,3,47,27,185,0,3,0,18,62,89,184,0,2,220,48,49,19,3,35,3,141,18,64,18,2,238,254,212,1,44,0,0,0,1,0,42,255,120,0,237,2,238,0,15,0,150,184,0,6,47,184,0,12,220,184,0,0,208,184,0,12,16,184,0,11,220,184,0,1,208,184,0,6,16,185,0,14,0,5,244,65,3,0,15,0,17,0,1,93,0,184,0,0,47,184,0,0,69,88,184,0,12,47,27,185,0,12,0,18,62,89,48,49,1,65,3,0,134,0,13,0,1,93,65,3,0,55,0,13,0,1,93,65,3,0,151,0,13,0,1,93,65,3,0,134,0,15,0,1,93,65,3,0,151,0,15,0,1,93,0,65,3,0,152,0,13,0,1,93,65,3,0,137,0,13,0,1,93,65,3,0,150,0,15,0,1,93,65,3,0,135,0,15,0,1,93,23,35,46,3,53,52,62,2,55,51,6,21,20,237,79,30,44,28,14,14,29,44,29,79,123,136,45,93,106,124,75,76,124,106,92,45,200,243,244,0,0,1,0,24,255,120,0,219,2,238,0,15,0,149,184,0,11,47,65,3,0,48,0,11,0,1,93,65,3,0,112,0,11,0,1,93,184,0,5,220,184,0,6,220,184,0,0,208,184,0,5,16,184,0,1,208,184,0,11,16,185,0,3,0,5,244,65,3,0,15,0,17,0,1,93,0,184,0,0,47,184,0,0,69,88,184,0,6,47,27,185,0,6,0,18,62,89,48,49,1,65,3,0,152,0,2,0,1,93,65,3,0,137,0,2,0,1,93,65,3,0,56,0,4,0,1,93,65,5,0,137,0,4,0,153,0,4,0,2,93,0,65,3,0,151,0,2,0,1,93,65,5,0,136,0,4,0,152,0,4,0,2,93,23,35,54,53,52,39,51,30,3,21,20,14,2,103,79,123,123,79,29,44,29,14,14,29,43,136,199,244,243,200,45,92,106,124,76,75,124,106,93,0,0,0,1,0,33,1,168,1,137,2,237,0,14,0,193,186,0,9,0,8,0,3,43,0,184,0,0,69,88,184,0,8,47,27,185,0,8,0,18,62,89,184,0,2,220,65,3,0,64,0,2,0,1,93,65,3,0,64,0,2,0,1,113,184,0,0,208,184,0,0,47,48,49,1,65,5,0,40,0,3,0,56,0,3,0,2,113,65,3,0,56,0,4,0,1,113,65,3,0,228,0,5,0,1,93,65,3,0,121,0,5,0,1,93,65,5,0,137,0,11,0,153,0,11,0,2,93,65,3,0,55,0,14,0,1,113,65,3,0,73,0,14,0,1,93,0,65,3,0,7,0,0,0,1,113,65,3,0,53,0,1,0,1,93,65,3,0,167,0,1,0,1,93,65,3,0,230,0,5,0,1,93,65,3,0,231,0,6,0,1,93,65,7,0,184,0,11,0,200,0,11,0,216,0,11,0,3,93,1,39,7,39,55,39,55,23,39,51,7,55,23,7,23,1,59,102,100,32,108,156,23,148,13,46,16,149,23,158,113,1,171,133,136,32,117,65,41,86,156,156,86,42,63,115,0,0,0,0,1,0,46,0,102,1,160,1,196,0,11,0,177,184,0,4,47,65,3,0,143,0,4,0,1,93,65,3,0,160,0,4,0,1,93,65,3,0,0,0,4,0,1,93,184,0,1,220,65,3,0,159,0,1,0,1,93,184,0,0,220,65,3,0,144,0,0,0,1,93,184,0,4,16,184,0,5,220,65,3,0,159,0,5,0,1,93,184,0,4,16,184,0,7,208,184,0,1,16,184,0,10,208,0,184,0,4,47,184,0,1,208,184,0,4,16,184,0,3,220,184,0,4,16,184,0,7,220,65,7,0,64,0,7,0,80,0,7,0,96,0,7,0,3,113,184,0,8,220,65,3,0,47,0,8,0,1,93,65,5,0,31,0,8,0,47,0,8,0,2,113,65,3,0,175,0,8,0,1,93,184,0,7,16,184,0,10,208,48,49,37,35,21,35,53,35,53,51,53,51,21,51,1,160,145,80,145,145,80,145,238,136,136,86,128,128,0,0,0,0,1,0,57,255,147,0,158,0,86,0,6,0,95,187,0,6,0,4,0,5,0,4,43,65,3,0,16,0,5,0,1,93,184,0,5,16,184,0,2,208,65,3,0,16,0,6,0,1,93,186,0,3,0,5,0,6,17,18,57,0,184,0,0,69,88,184,0,4,47,27,185,0,4,0,6,62,89,184,0,0,208,184,0,4,16,184,0,1,220,184,0,4,16,184,0,5,220,65,3,0,63,0,5,0,1,113,48,49,51,7,39,55,39,53,51,158,78,23,35,34,100,109,13,87,9,86,0,0,1,0,57,0,238,1,111,1,68,0,3,0,37,184,0,1,47,65,3,0,0,0,1,0,1,93,184,0,0,220,65,3,0,96,0,0,0,1,93,0,184,0,1,47,184,0,2,220,48,49,37,33,53,33,1,111,254,202,1,54,238,86,0,0,1,0,57,0,0,0,147,0,86,0,3,0,61,187,0,0,0,4,0,1,0,4,43,65,3,0,16,0,0,0,1,93,65,3,0,16,0,1,0,1,93,0,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,184,0,2,220,65,3,0,63,0,2,0,1,113,48,49,51,35,53,51,147,90,90,86,0,0,1,0,19,255,171,1,241,2,188,0,3,0,61,184,0,2,47,184,0,0,220,65,3,0,128,0,0,0,1,93,184,0,2,16,185,0,1,0,4,244,184,0,0,16,185,0,3,0,4,244,0,184,0,1,47,184,0,0,69,88,184,0,3,47,27,185,0,3,0,14,62,89,48,49,9,1,35,1,1,241,254,134,100,1,122,2,188,252,239,3,17,0,2,0,63,255,242,2,139,2,202,0,19,0,35,2,48,186,0,15,0,5,0,3,43,65,3,0,15,0,5,0,1,113,65,3,0,143,0,5,0,1,93,65,3,0,239,0,5,0,1,93,65,5,0,0,0,5,0,16,0,5,0,2,93,65,3,0,32,0,15,0,1,113,65,3,0,80,0,15,0,1,113,65,3,0,64,0,15,0,1,93,65,5,0,0,0,15,0,16,0,15,0,2,93,184,0,5,16,185,0,25,0,4,244,184,0,15,16,185,0,31,0,4,244,0,184,0,0,69,88,184,0,10,47,27,185,0,10,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,10,16,185,0,20,0,2,244,184,0,0,16,185,0,28,0,2,244,48,49,1,65,3,0,25,0,2,0,1,93,65,7,0,105,0,2,0,121,0,2,0,137,0,2,0,3,93,65,3,0,42,0,2,0,1,93,65,3,0,24,0,3,0,1,93,65,7,0,89,0,3,0,105,0,3,0,121,0,3,0,3,93,65,3,0,104,0,8,0,1,93,65,3,0,25,0,8,0,1,93,65,3,0,121,0,8,0,1,93,65,5,0,22,0,12,0,38,0,12,0,2,93,65,3,0,102,0,12,0,1,93,65,3,0,22,0,13,0,1,93,65,7,0,102,0,13,0,118,0,13,0,134,0,13,0,3,93,65,3,0,87,0,13,0,1,93,65,3,0,86,0,17,0,1,93,65,3,0,38,0,18,0,1,93,65,3,0,23,0,18,0,1,93,65,7,0,103,0,18,0,119,0,18,0,135,0,18,0,3,93,65,3,0,89,0,26,0,1,93,0,65,3,0,137,0,1,0,1,93,65,3,0,40,0,2,0,1,93,65,3,0,25,0,2,0,1,93,65,7,0,105,0,2,0,121,0,2,0,137,0,2,0,3,93,65,3,0,24,0,3,0,1,93,65,3,0,104,0,3,0,1,93,65,3,0,121,0,3,0,1,93,65,3,0,22,0,8,0,1,93,65,3,0,118,0,8,0,1,93,65,3,0,103,0,8,0,1,93,65,7,0,103,0,12,0,119,0,12,0,135,0,12,0,3,93,65,3,0,117,0,13,0,1,93,65,3,0,23,0,13,0,1,93,65,3,0,103,0,13,0,1,93,65,3,0,88,0,17,0,1,93,65,5,0,25,0,18,0,41,0,18,0,2,93,65,5,0,105,0,18,0,121,0,18,0,2,93,65,3,0,138,0,18,0,1,93,65,3,0,87,0,26,0,1,93,5,34,46,2,53,52,62,2,51,50,30,2,21,20,14,2,3,34,14,2,21,20,22,51,50,54,53,52,46,2,1,95,65,106,75,42,46,81,110,63,62,106,77,43,43,79,111,57,41,72,53,31,102,87,91,108,29,51,70,14,50,92,130,80,83,139,99,55,53,94,132,78,84,137,97,53,2,130,39,74,108,69,132,134,143,142,64,101,69,37,0,0,0,1,0,34,0,0,0,254,2,188,0,11,0,150,187,0,0,0,4,0,1,0,4,43,65,3,0,16,0,0,0,1,93,65,3,0,16,0,1,0,1,93,184,0,1,16,184,0,5,220,186,0,10,0,1,0,0,17,18,57,0,184,0,0,69,88,184,0,10,47,27,185,0,10,0,14,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,184,0,10,16,184,0,4,220,186,0,2,0,10,0,4,17,18,57,65,5,0,235,0,2,0,251,0,2,0,2,93,65,7,0,11,0,2,0,27,0,2,0,43,0,2,0,3,113,65,5,0,202,0,2,0,218,0,2,0,2,93,185,0,5,0,2,244,48,49,51,35,17,6,7,39,62,3,55,51,254,100,54,50,16,21,43,39,33,11,73,2,51,45,16,89,7,23,29,33,17,0,0,1,0,50,0,0,1,214,2,202,0,28,1,188,186,0,22,0,12,0,3,43,65,3,0,95,0,12,0,1,93,184,0,12,16,184,0,1,208,65,3,0,42,0,1,0,1,113,65,3,0,67,0,1,0,1,113,184,0,22,16,185,0,6,0,4,244,184,0,1,16,184,0,27,208,65,3,0,114,0,27,0,1,93,65,3,0,19,0,27,0,1,113,65,3,0,69,0,27,0,1,93,65,3,0,245,0,27,0,1,93,65,3,0,5,0,27,0,1,113,65,5,0,83,0,27,0,99,0,27,0,2,93,65,5,0,67,0,27,0,83,0,27,0,2,113,65,3,0,33,0,27,0,1,113,65,3,0,128,0,27,0,1,93,184,0,22,16,184,0,28,208,184,0,28,47,0,184,0,0,69,88,184,0,17,47,27,185,0,17,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,186,0,4,0,17,0,0,17,18,57,184,0,17,16,185,0,9,0,2,244,184,0,17,16,184,0,11,220,185,0,12,0,2,244,65,3,0,86,0,12,0,1,93,186,0,25,0,0,0,17,17,18,57,184,0,0,16,185,0,28,0,2,244,48,49,1,65,5,0,105,0,3,0,121,0,3,0,2,93,65,3,0,89,0,4,0,1,93,65,3,0,149,0,19,0,1,93,65,7,0,103,0,19,0,119,0,19,0,135,0,19,0,3,93,65,7,0,101,0,20,0,117,0,20,0,133,0,20,0,3,93,65,3,0,6,0,20,0,1,93,65,3,0,150,0,20,0,1,93,0,65,3,0,118,0,3,0,1,93,65,3,0,133,0,4,0,1,93,65,3,0,22,0,4,0,1,93,65,3,0,87,0,4,0,1,93,65,3,0,133,0,14,0,1,93,65,7,0,6,0,14,0,22,0,14,0,38,0,14,0,3,93,65,7,0,101,0,19,0,117,0,19,0,133,0,19,0,3,93,65,3,0,6,0,20,0,1,93,65,3,0,151,0,20,0,1,93,41,1,62,1,55,54,53,52,38,35,34,7,39,62,3,51,50,30,2,21,20,14,2,7,51,1,214,254,98,91,116,28,56,65,57,93,70,12,7,35,51,67,39,55,75,45,19,23,51,82,59,242,129,179,52,104,48,54,59,93,85,13,34,30,20,35,55,69,33,36,83,103,130,84,0,1,0,40,255,242,1,228,2,202,0,49,2,46,186,0,45,0,5,0,3,43,65,3,0,79,0,5,0,1,93,65,3,0,143,0,5,0,1,93,65,3,0,16,0,5,0,1,93,65,3,0,16,0,45,0,1,113,65,3,0,16,0,45,0,1,93,184,0,45,16,185,0,16,0,4,244,186,0,22,0,45,0,5,17,18,57,184,0,22,47,186,0,40,0,45,0,5,17,18,57,184,0,40,47,185,0,27,0,4,244,186,0,32,0,5,0,45,17,18,57,184,0,32,47,186,0,43,0,22,0,40,17,18,57,65,3,0,117,0,43,0,1,93,65,3,0,86,0,43,0,1,93,65,3,0,100,0,43,0,1,93,65,3,0,132,0,43,0,1,93,0,184,0,0,69,88,184,0,35,47,27,185,0,35,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,6,220,65,3,0,32,0,6,0,1,93,184,0,5,208,65,7,0,10,0,5,0,26,0,5,0,42,0,5,0,3,113,184,0,0,16,185,0,11,0,2,244,186,0,24,0,35,0,0,17,18,57,184,0,24,47,185,0,21,0,2,244,184,0,35,16,185,0,29,0,2,244,184,0,35,16,184,0,31,220,65,5,0,144,0,31,0,160,0,31,0,2,93,186,0,43,0,24,0,21,17,18,57,48,49,1,65,3,0,137,0,3,0,1,93,65,13,0,56,0,33,0,72,0,33,0,88,0,33,0,104,0,33,0,120,0,33,0,136,0,33,0,6,93,65,3,0,7,0,37,0,1,93,65,7,0,87,0,42,0,103,0,42,0,119,0,42,0,3,93,65,5,0,85,0,44,0,101,0,44,0,2,93,65,3,0,133,0,44,0,1,93,65,3,0,118,0,44,0,1,93,65,3,0,87,0,47,0,1,93,0,65,11,0,57,0,3,0,73,0,3,0,89,0,3,0,105,0,3,0,121,0,3,0,5,93,65,3,0,138,0,3,0,1,93,65,13,0,54,0,33,0,70,0,33,0,86,0,33,0,102,0,33,0,118,0,33,0,134,0,33,0,6,93,65,3,0,6,0,37,0,1,93,65,3,0,88,0,42,0,1,93,65,3,0,105,0,42,0,1,93,65,3,0,122,0,42,0,1,93,65,3,0,86,0,44,0,1,93,65,3,0,118,0,44,0,1,93,65,3,0,103,0,44,0,1,93,65,3,0,135,0,44,0,1,93,65,3,0,90,0,47,0,1,93,65,3,0,89,0,48,0,1,93,23,34,46,2,39,55,30,3,51,50,62,2,53,52,46,2,43,1,55,51,50,54,53,52,35,34,7,39,62,1,51,50,30,2,21,20,6,7,22,21,20,14,2,230,30,61,53,39,7,23,28,42,37,38,23,30,55,40,24,17,39,63,47,73,10,37,91,76,119,85,50,17,16,83,63,66,83,47,17,40,51,116,40,69,93,14,11,17,18,7,88,15,20,14,6,15,34,54,38,30,48,34,18,76,58,57,94,41,81,16,30,35,53,63,29,42,69,35,39,135,54,85,59,30,0,2,0,14,0,0,1,244,2,188,0,9,0,12,1,7,186,0,1,0,5,0,3,43,184,0,1,16,184,0,0,220,184,0,1,16,185,0,4,0,4,244,65,3,0,143,0,5,0,1,93,184,0,10,208,184,0,1,16,184,0,8,208,186,0,6,0,10,0,8,17,18,57,65,3,0,137,0,6,0,1,93,184,0,5,16,184,0,12,208,65,3,0,116,0,12,0,1,93,65,3,0,22,0,12,0,1,113,65,3,0,37,0,12,0,1,113,65,3,0,99,0,12,0,1,93,65,3,0,130,0,12,0,1,93,0,184,0,0,69,88,184,0,6,47,27,185,0,6,0,14,62,89,184,0,0,69,88,184,0,3,47,27,185,0,3,0,6,62,89,186,0,1,0,6,0,3,17,18,57,184,0,1,47,65,3,0,144,0,1,0,1,93,184,0,4,208,184,0,1,16,185,0,8,0,2,244,184,0,10,208,184,0,6,16,184,0,11,208,65,3,0,252,0,11,0,1,93,65,3,0,46,0,11,0,1,113,65,5,0,125,0,11,0,141,0,11,0,2,93,65,3,0,11,0,11,0,1,113,65,3,0,106,0,11,0,1,93,48,49,65,3,0,92,0,11,0,1,93,37,35,21,35,53,33,1,51,17,51,35,53,7,1,244,85,100,254,211,1,66,79,85,185,153,190,190,190,1,254,254,88,254,254,0,0,0,0,1,0,51,255,242,1,233,2,188,0,31,1,213,186,0,27,0,5,0,3,43,65,3,0,79,0,5,0,1,113,65,3,0,47,0,5,0,1,93,65,3,0,47,0,5,0,1,113,65,3,0,16,0,5,0,1,93,65,3,0,16,0,27,0,1,93,65,3,0,64,0,27,0,1,93,65,3,0,96,0,27,0,1,93,184,0,27,16,185,0,13,0,4,244,186,0,17,0,5,0,27,17,18,57,184,0,17,47,184,0,16,220,65,3,0,86,0,16,0,1,113,184,0,17,16,184,0,18,208,186,0,19,0,17,0,27,17,18,57,184,0,19,47,184,0,16,16,184,0,21,208,186,0,22,0,21,0,16,17,18,57,65,3,0,39,0,22,0,1,113,0,184,0,0,69,88,184,0,19,47,27,185,0,19,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,6,220,65,3,0,48,0,6,0,1,93,185,0,5,0,2,244,184,0,0,16,185,0,8,0,2,244,186,0,22,0,19,0,0,17,18,57,184,0,22,47,185,0,16,0,2,244,184,0,19,16,185,0,20,0,2,244,48,49,1,65,3,0,72,0,3,0,1,93,65,3,0,137,0,11,0,1,93,65,3,0,70,0,24,0,1,93,65,3,0,102,0,24,0,1,93,65,3,0,55,0,24,0,1,93,65,3,0,100,0,25,0,1,93,65,3,0,69,0,25,0,1,93,65,3,0,54,0,25,0,1,93,65,3,0,86,0,25,0,1,93,65,3,0,119,0,25,0,1,93,65,3,0,55,0,29,0,1,93,65,3,0,71,0,30,0,1,93,0,65,3,0,73,0,3,0,1,93,65,3,0,135,0,11,0,1,93,65,3,0,67,0,24,0,1,93,65,3,0,53,0,24,0,1,93,65,5,0,85,0,24,0,101,0,24,0,2,93,65,9,0,53,0,25,0,69,0,25,0,85,0,25,0,101,0,25,0,4,93,65,3,0,119,0,25,0,1,93,65,3,0,56,0,29,0,1,93,65,3,0,57,0,30,0,1,93,65,3,0,76,0,30,0,1,93,23,34,46,2,39,55,22,51,50,62,2,53,52,38,43,1,19,33,7,35,7,50,30,2,21,20,14,2,220,22,54,50,37,6,23,72,73,35,60,45,26,99,112,85,42,1,62,9,233,20,81,115,72,34,44,73,98,14,7,12,14,6,89,42,25,43,58,34,63,60,1,89,86,174,25,50,77,52,56,92,66,36,0,0,0,0,2,0,62,255,242,2,12,2,188,0,27,0,47,2,74,186,0,23,0,5,0,3,43,65,3,0,239,0,5,0,1,93,65,3,0,31,0,5,0,1,93,65,3,0,143,0,5,0,1,93,65,3,0,0,0,5,0,1,93,65,3,0,0,0,23,0,1,93,65,3,0,192,0,23,0,1,93,65,5,0,48,0,23,0,64,0,23,0,2,93,186,0,11,0,23,0,5,17,18,57,184,0,11,47,184,0,5,16,185,0,33,0,4,244,184,0,16,208,184,0,23,16,185,0,43,0,4,244,0,184,0,0,69,88,184,0,10,47,27,185,0,10,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,10,16,184,0,12,208,65,3,0,249,0,12,0,1,93,184,0,0,16,184,0,18,220,65,3,0,64,0,18,0,1,93,186,0,16,0,18,0,0,17,18,57,65,3,0,243,0,16,0,1,93,185,0,28,0,2,244,184,0,0,16,185,0,38,0,2,244,48,49,1,65,7,0,89,0,2,0,105,0,2,0,121,0,2,0,3,93,65,3,0,138,0,2,0,1,93,65,3,0,91,0,3,0,1,93,65,3,0,136,0,8,0,1,93,65,3,0,247,0,11,0,1,93,65,3,0,69,0,13,0,1,93,65,3,0,117,0,13,0,1,93,65,3,0,54,0,13,0,1,93,65,3,0,103,0,13,0,1,93,65,5,0,102,0,14,0,118,0,14,0,2,93,65,5,0,102,0,20,0,118,0,20,0,2,93,65,5,0,7,0,20,0,23,0,20,0,2,93,65,3,0,135,0,20,0,1,93,65,3,0,102,0,21,0,1,93,65,3,0,134,0,21,0,1,93,65,3,0,119,0,21,0,1,93,65,3,0,87,0,25,0,1,93,65,3,0,86,0,26,0,1,93,0,65,3,0,136,0,2,0,1,93,65,7,0,89,0,2,0,105,0,2,0,121,0,2,0,3,93,65,3,0,135,0,8,0,1,93,65,3,0,6,0,9,0,1,93,65,3,0,250,0,11,0,1,93,65,3,0,72,0,13,0,1,93,65,3,0,120,0,13,0,1,93,65,3,0,107,0,13,0,1,93,65,3,0,122,0,14,0,1,93,65,3,0,87,0,17,0,1,93,65,3,0,117,0,20,0,1,93,65,5,0,6,0,20,0,22,0,20,0,2,93,65,3,0,102,0,20,0,1,93,65,3,0,134,0,20,0,1,93,65,3,0,102,0,21,0,1,93,65,3,0,134,0,21,0,1,93,65,3,0,119,0,21,0,1,93,65,3,0,88,0,25,0,1,93,65,3,0,90,0,26,0,1,93,5,34,46,2,53,52,62,2,55,23,14,3,7,54,51,50,30,2,21,20,14,2,3,34,14,2,21,20,30,2,51,50,62,2,53,52,46,2,1,25,50,80,58,31,61,91,105,43,65,40,76,66,55,19,46,95,45,78,57,32,35,64,89,33,29,51,38,23,20,36,48,27,33,50,34,17,13,30,47,14,30,62,96,66,98,168,123,70,1,38,18,46,69,100,72,63,27,51,76,48,49,84,63,36,1,97,20,36,51,31,33,49,33,17,24,40,52,29,24,45,35,21,0,1,0,39,0,0,1,236,2,188,0,5,0,190,186,0,0,0,5,0,3,43,65,3,0,55,0,0,0,1,93,65,3,0,87,0,0,0,1,93,184,0,0,16,184,0,1,208,184,0,0,16,184,0,3,208,65,7,0,41,0,3,0,57,0,3,0,73,0,3,0,3,93,65,3,0,90,0,3,0,1,93,65,5,0,108,0,3,0,124,0,3,0,2,93,65,3,0,141,0,3,0,1,93,65,5,0,26,0,3,0,42,0,3,0,2,113,65,3,0,249,0,3,0,1,93,65,3,0,9,0,3,0,1,113,65,3,0,232,0,3,0,1,93,65,3,0,151,0,3,0,1,93,184,0,2,208,0,184,0,0,69,88,184,0,5,47,27,185,0,5,0,14,62,89,184,0,0,69,88,184,0,2,47,27,185,0,2,0,6,62,89,184,0,5,16,185,0,4,0,2,244,48,49,9,1,35,1,33,53,1,236,254,209,100,1,9,254,197,2,188,253,68,2,102,86,0,0,0,3,0,59,255,242,2,37,2,201,0,31,0,43,0,57,2,65,186,0,27,0,5,0,3,43,65,3,0,31,0,5,0,1,113,65,3,0,0,0,5,0,1,93,65,5,0,0,0,27,0,16,0,27,0,2,93,65,3,0,80,0,27,0,1,113,65,3,0,32,0,27,0,1,113,186,0,9,0,5,0,27,17,18,57,184,0,9,47,186,0,19,0,27,0,5,17,18,57,184,0,19,47,186,0,7,0,9,0,19,17,18,57,186,0,24,0,19,0,9,17,18,57,184,0,9,16,185,0,32,0,4,244,184,0,19,16,185,0,38,0,4,244,184,0,5,16,185,0,47,0,4,244,184,0,27,16,185,0,55,0,4,244,0,184,0,0,69,88,184,0,14,47,27,185,0,14,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,186,0,35,0,14,0,0,17,18,57,65,3,0,134,0,35,0,1,93,65,3,0,170,0,35,0,1,93,65,3,0,185,0,35,0,1,93,65,3,0,86,0,35,0,1,93,65,5,0,101,0,35,0,117,0,35,0,2,93,186,0,44,0,0,0,14,17,18,57,65,3,0,138,0,44,0,1,93,65,3,0,185,0,44,0,1,93,65,3,0,41,0,44,0,1,93,186,0,7,0,35,0,44,17,18,57,186,0,24,0,35,0,44,17,18,57,184,0,14,16,185,0,41,0,2,244,184,0,0,16,185,0,50,0,2,244,48,49,1,65,3,0,104,0,2,0,1,93,65,3,0,90,0,2,0,1,93,65,3,0,89,0,3,0,1,93,65,3,0,10,0,3,0,1,93,65,3,0,122,0,3,0,1,93,65,3,0,107,0,3,0,1,93,65,5,0,57,0,8,0,73,0,8,0,2,93,65,3,0,24,0,11,0,1,93,65,3,0,9,0,11,0,1,93,65,5,0,6,0,17,0,22,0,17,0,2,93,65,3,0,100,0,26,0,1,93,65,3,0,117,0,26,0,1,93,65,5,0,86,0,29,0,102,0,29,0,2,93,65,3,0,133,0,42,0,1,93,65,5,0,56,0,53,0,72,0,53,0,2,93,0,65,5,0,89,0,2,0,105,0,2,0,2,93,65,7,0,89,0,3,0,105,0,3,0,121,0,3,0,3,93,65,3,0,6,0,11,0,1,93,65,3,0,23,0,11,0,1,93,65,3,0,7,0,17,0,1,93,65,3,0,119,0,26,0,1,93,65,5,0,88,0,29,0,104,0,29,0,2,93,65,3,0,89,0,30,0,1,93,65,3,0,69,0,53,0,1,93,65,3,0,55,0,53,0,1,93,5,34,46,2,53,52,55,38,53,52,62,2,51,50,30,2,21,20,14,2,7,30,1,21,20,14,2,3,20,22,23,62,1,53,52,38,35,34,6,23,14,1,21,20,22,51,50,62,2,53,52,38,1,40,60,89,59,29,134,93,24,50,78,56,54,76,49,23,11,27,45,34,81,75,33,64,95,170,60,51,58,59,58,54,54,62,119,66,77,71,66,32,54,40,22,79,14,33,56,73,41,116,71,72,92,36,64,46,27,25,43,58,32,27,41,38,38,24,28,89,72,40,76,60,36,2,36,34,60,19,17,67,40,39,44,49,241,13,73,63,58,59,19,34,47,27,51,73,0,0,2,0,45,0,0,1,251,2,202,0,26,0,46,2,23,186,0,5,0,22,0,3,43,65,3,0,224,0,5,0,1,93,65,3,0,64,0,5,0,1,93,65,3,0,192,0,5,0,1,93,65,3,0,128,0,5,0,1,93,65,3,0,63,0,22,0,1,93,65,3,0,31,0,22,0,1,93,186,0,11,0,22,0,5,17,18,57,184,0,11,47,184,0,5,16,185,0,32,0,4,244,184,0,16,208,184,0,22,16,185,0,42,0,4,244,0,184,0,0,69,88,184,0,0,47,27,185,0,0,0,14,62,89,184,0,0,69,88,184,0,10,47,27,185,0,10,0,6,62,89,184,0,12,208,65,3,0,246,0,12,0,1,93,184,0,0,16,184,0,19,220,65,3,0,79,0,19,0,1,93,186,0,16,0,0,0,19,17,18,57,185,0,27,0,2,244,184,0,0,16,185,0,37,0,2,244,48,49,1,65,3,0,117,0,2,0,1,93,65,3,0,86,0,2,0,1,93,65,3,0,134,0,2,0,1,93,65,3,0,86,0,3,0,1,93,65,3,0,134,0,6,0,1,93,65,3,0,6,0,8,0,1,93,65,3,0,134,0,8,0,1,93,65,3,0,23,0,8,0,1,93,65,5,0,57,0,13,0,73,0,13,0,2,93,65,5,0,106,0,13,0,122,0,13,0,2,93,65,3,0,88,0,16,0,1,93,65,3,0,87,0,17,0,1,93,65,3,0,136,0,20,0,1,93,65,3,0,121,0,20,0,1,93,65,5,0,9,0,21,0,25,0,21,0,2,93,65,3,0,105,0,21,0,1,93,65,3,0,138,0,21,0,1,93,65,3,0,89,0,24,0,1,93,65,3,0,89,0,25,0,1,93,0,65,3,0,102,0,2,0,1,93,65,3,0,134,0,2,0,1,93,65,3,0,87,0,2,0,1,93,65,3,0,119,0,2,0,1,93,65,3,0,86,0,3,0,1,93,65,3,0,24,0,8,0,1,93,65,3,0,137,0,8,0,1,93,65,3,0,9,0,9,0,1,93,65,3,0,101,0,13,0,1,93,65,3,0,118,0,13,0,1,93,65,3,0,71,0,13,0,1,93,65,3,0,88,0,16,0,1,93,65,3,0,89,0,17,0,1,93,65,3,0,104,0,20,0,1,93,65,5,0,122,0,20,0,138,0,20,0,2,93,65,3,0,86,0,24,0,1,93,65,3,0,85,0,25,0,1,93,1,50,30,2,21,20,14,2,35,39,62,3,55,14,1,35,34,38,53,52,62,2,19,50,62,2,53,52,46,2,35,34,14,2,21,20,30,2,1,32,42,79,61,37,61,89,101,40,73,41,83,70,50,9,20,76,43,100,112,36,64,89,32,30,51,38,22,21,35,48,27,33,50,34,17,13,29,47,2,202,24,58,97,73,110,172,118,62,38,19,51,71,94,63,27,30,102,100,51,85,62,35,254,159,20,37,51,32,31,49,33,17,24,40,53,28,24,46,34,21,0,0,2,0,57,0,0,0,147,1,184,0,3,0,7,0,102,187,0,7,0,4,0,6,0,4,43,65,3,0,16,0,7,0,1,93,184,0,7,16,184,0,0,208,65,3,0,16,0,6,0,1,93,184,0,6,16,184,0,1,208,0,184,0,2,47,184,0,0,69,88,184,0,5,47,27,185,0,5,0,6,62,89,184,0,2,16,184,0,1,220,65,3,0,48,0,1,0,1,113,184,0,5,16,184,0,6,220,65,3,0,63,0,6,0,1,113,48,49,19,35,53,51,17,35,53,51,147,90,90,90,90,1,98,86,254,72,86,0,0,0,0,2,0,57,255,147,0,158,1,184,0,3,0,10,0,136,187,0,10,0,4,0,9,0,4,43,65,3,0,16,0,10,0,1,93,184,0,10,16,184,0,0,208,65,3,0,16,0,9,0,1,93,184,0,9,16,184,0,1,208,184,0,9,16,184,0,6,208,186,0,7,0,9,0,10,17,18,57,0,184,0,2,47,184,0,0,69,88,184,0,8,47,27,185,0,8,0,6,62,89,184,0,2,16,184,0,1,220,65,3,0,48,0,1,0,1,113,184,0,8,16,184,0,4,208,184,0,8,16,184,0,5,220,184,0,8,16,184,0,9,220,65,3,0,63,0,9,0,1,113,48,49,19,35,53,51,17,7,39,55,39,53,51,158,100,100,78,23,35,34,100,1,98,86,254,71,108,13,87,9,86,0,0,0,0,1,0,33,0,78,1,88,1,234,0,5,0,73,184,0,2,47,184,0,4,220,184,0,0,208,184,0,4,16,185,0,3,0,4,244,184,0,1,208,184,0,2,16,185,0,5,0,4,244,0,25,184,0,2,47,24,184,0,1,208,184,0,1,47,184,0,2,16,184,0,3,208,184,0,3,47,184,0,2,16,184,0,5,208,48,49,37,35,39,55,51,7,1,88,95,216,216,95,216,78,206,206,206,0,2,0,66,0,160,1,180,1,138,0,3,0,7,0,61,184,0,5,47,65,3,0,16,0,5,0,1,93,184,0,4,220,184,0,0,208,184,0,5,16,184,0,1,208,0,184,0,5,47,184,0,1,220,65,3,0,15,0,1,0,1,93,184,0,2,220,184,0,5,16,184,0,6,220,48,49,1,33,53,33,21,33,53,33,1,180,254,142,1,114,254,142,1,114,1,62,76,234,76,0,1,0,60,0,78,1,115,1,234,0,5,0,82,184,0,0,47,65,3,0,16,0,0,0,1,93,184,0,4,220,185,0,5,0,4,244,184,0,1,208,184,0,4,16,184,0,2,208,184,0,0,16,185,0,3,0,4,244,0,25,184,0,0,47,24,184,0,1,208,184,0,1,47,184,0,0,16,184,0,3,208,184,0,0,16,184,0,5,208,184,0,5,47,48,49,1,7,35,55,39,51,1,115,216,95,216,216,95,1,28,206,206,206,0,0,0,2,0,30,0,0,1,141,2,238,0,36,0,40,1,93,186,0,29,0,21,0,3,43,65,3,0,16,0,21,0,1,93,65,3,0,16,0,29,0,1,93,186,0,1,0,21,0,29,17,18,57,184,0,1,47,65,5,0,16,0,1,0,32,0,1,0,2,113,65,7,0,16,0,1,0,32,0,1,0,48,0,1,0,3,93,184,0,0,220,184,0,29,16,184,0,10,220,65,7,0,48,0,10,0,64,0,10,0,80,0,10,0,3,113,186,0,39,0,21,0,29,17,18,57,184,0,39,47,185,0,40,0,4,244,0,184,0,0,69,88,184,0,24,47,27,185,0,24,0,18,62,89,184,0,0,69,88,184,0,38,47,27,185,0,38,0,6,62,89,184,0,39,220,65,3,0,63,0,39,0,1,113,184,0,1,220,184,0,24,16,185,0,15,0,1,244,184,0,24,16,184,0,20,220,48,49,1,65,3,0,121,0,8,0,1,93,65,3,0,6,0,26,0,1,93,65,3,0,102,0,26,0,1,93,65,3,0,101,0,27,0,1,93,65,3,0,119,0,27,0,1,93,65,3,0,39,0,33,0,1,93,65,3,0,134,0,34,0,1,93,65,3,0,23,0,34,0,1,93,0,65,7,0,54,0,22,0,70,0,22,0,86,0,22,0,3,93,65,3,0,7,0,26,0,1,93,65,3,0,103,0,26,0,1,93,65,5,0,103,0,27,0,119,0,27,0,2,93,65,3,0,40,0,33,0,1,93,65,3,0,137,0,33,0,1,93,65,3,0,25,0,34,0,1,93,65,3,0,138,0,34,0,1,93,55,35,38,53,52,62,4,53,52,46,2,35,34,14,2,7,39,62,1,51,50,30,2,21,20,6,15,1,14,1,31,1,35,53,51,226,59,3,22,34,38,34,22,21,35,46,26,22,43,35,26,5,25,19,86,54,48,77,54,29,35,25,51,26,35,1,18,91,91,200,40,5,31,53,49,47,49,55,32,30,46,31,16,13,20,24,11,67,29,38,33,54,67,33,35,76,32,65,33,66,29,227,86,0,2,0,49,255,169,2,163,2,41,0,61,0,76,1,131,184,0,38,47,65,3,0,48,0,38,0,1,93,184,0,48,220,186,0,7,0,38,0,48,17,18,57,184,0,7,47,184,0,0,208,65,3,0,102,0,0,0,1,93,65,3,0,70,0,0,0,1,93,184,0,64,208,65,3,0,68,0,64,0,1,93,65,3,0,197,0,64,0,1,93,65,3,0,54,0,64,0,1,93,65,3,0,53,0,64,0,1,113,65,3,0,5,0,64,0,1,93,65,3,0,212,0,64,0,1,93,65,3,0,19,0,64,0,1,93,184,0,15,208,65,3,0,55,0,15,0,1,93,186,0,28,0,38,0,48,17,18,57,186,0,52,0,48,0,38,17,18,57,184,0,0,16,184,0,57,208,184,0,7,16,184,0,72,220,65,3,0,176,0,72,0,1,93,0,184,0,0,69,88,184,0,43,47,27,185,0,43,0,16,62,89,184,0,33,220,186,0,2,0,33,0,43,17,18,57,184,0,2,47,186,0,10,0,43,0,33,17,18,57,184,0,10,47,186,0,15,0,2,0,10,17,18,57,65,3,0,129,0,15,0,1,93,65,3,0,100,0,15,0,1,93,65,3,0,195,0,15,0,1,93,65,3,0,49,0,15,0,1,93,65,7,0,0,0,15,0,16,0,15,0,32,0,15,0,3,93,184,0,23,208,184,0,23,47,186,0,28,0,33,0,43,17,18,57,65,5,0,19,0,28,0,35,0,28,0,2,93,65,3,0,1,0,28,0,1,93,186,0,52,0,43,0,33,17,18,57,184,0,55,220,184,0,2,16,184,0,62,220,184,0,10,16,184,0,69,220,48,49,1,65,5,0,57,0,5,0,73,0,5,0,2,93,0,65,3,0,54,0,5,0,1,93,1,38,35,34,14,2,21,20,22,51,50,62,2,55,20,14,2,21,20,22,51,50,62,2,55,14,3,35,34,46,2,53,52,62,2,51,50,30,2,21,20,14,2,7,6,35,34,53,52,62,2,39,50,23,14,3,35,34,38,53,52,62,2,2,33,51,71,46,91,72,45,44,51,21,50,48,43,14,1,1,1,26,29,15,36,36,34,12,24,70,86,97,51,57,92,65,34,60,104,136,77,58,93,64,34,5,16,33,28,39,27,37,10,16,19,111,47,7,6,41,54,59,25,22,22,34,53,61,1,123,53,50,79,101,51,48,63,17,31,42,26,1,9,10,10,1,32,51,11,18,23,12,43,71,51,28,35,66,96,60,80,140,103,60,36,66,94,58,26,56,51,42,13,17,53,13,48,61,72,30,22,39,85,72,47,36,28,39,73,55,34,0,0,0,2,0,7,0,0,2,97,2,188,0,7,0,10,1,97,187,0,7,0,4,0,6,0,4,43,65,3,0,16,0,7,0,1,93,184,0,7,16,184,0,0,208,65,3,0,246,0,0,0,1,93,65,3,0,86,0,0,0,1,93,65,3,0,22,0,0,0,1,93,185,0,1,0,4,244,65,3,0,16,0,6,0,1,93,186,0,9,0,6,0,7,17,18,57,186,0,2,0,1,0,9,17,18,57,184,0,6,16,184,0,5,208,65,3,0,249,0,5,0,1,93,65,3,0,25,0,5,0,1,93,65,3,0,89,0,5,0,1,93,185,0,4,0,4,244,186,0,3,0,4,0,9,17,18,57,186,0,8,0,9,0,1,17,18,57,186,0,10,0,9,0,4,17,18,57,0,184,0,0,69,88,184,0,7,47,27,185,0,7,0,14,62,89,184,0,0,69,88,184,0,4,47,27,185,0,4,0,6,62,89,184,0,1,208,186,0,8,0,7,0,4,17,18,57,184,0,8,47,185,0,2,0,2,244,184,0,7,16,184,0,9,208,48,49,1,65,3,0,56,0,0,0,1,93,65,5,0,72,0,6,0,88,0,6,0,2,93,65,3,0,57,0,6,0,1,93,65,7,0,105,0,6,0,121,0,6,0,137,0,6,0,3,93,65,7,0,102,0,7,0,118,0,7,0,134,0,7,0,3,93,65,7,0,55,0,7,0,71,0,7,0,87,0,7,0,3,93,0,65,3,0,22,0,9,0,1,93,65,3,0,250,0,9,0,1,93,65,5,0,10,0,9,0,26,0,9,0,2,113,65,3,0,43,0,9,0,1,113,33,35,39,33,7,35,19,51,19,11,1,2,97,100,67,254,244,67,100,251,100,54,104,104,189,189,2,188,254,87,1,36,254,220,0,0,3,0,80,0,0,2,50,2,188,0,20,0,33,0,46,2,71,186,0,16,0,1,0,3,43,65,3,0,191,0,1,0,1,93,65,5,0,0,0,1,0,16,0,1,0,2,93,65,3,0,80,0,1,0,1,113,65,3,0,240,0,16,0,1,93,65,5,0,0,0,16,0,16,0,16,0,2,93,65,3,0,208,0,16,0,1,93,65,3,0,80,0,16,0,1,113,65,3,0,16,0,16,0,1,113,186,0,8,0,16,0,1,17,18,57,184,0,8,47,184,0,1,16,185,0,36,0,4,244,184,0,23,208,186,0,13,0,8,0,23,17,18,57,65,3,0,5,0,13,0,1,93,184,0,8,16,185,0,29,0,4,244,184,0,16,16,185,0,42,0,4,244,0,184,0,0,69,88,184,0,3,47,27,185,0,3,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,186,0,23,0,3,0,0,17,18,57,184,0,23,47,185,0,35,0,2,244,186,0,13,0,23,0,35,17,18,57,184,0,3,16,185,0,21,0,2,244,184,0,0,16,185,0,37,0,2,244,48,49,1,65,3,0,119,0,5,0,1,93,65,3,0,117,0,6,0,1,93,65,3,0,6,0,6,0,1,93,65,3,0,38,0,6,0,1,93,65,3,0,134,0,6,0,1,93,65,3,0,23,0,6,0,1,93,65,5,0,118,0,11,0,134,0,11,0,2,93,65,3,0,118,0,12,0,1,93,65,3,0,135,0,12,0,1,93,65,3,0,85,0,14,0,1,93,65,3,0,102,0,14,0,1,93,65,3,0,134,0,14,0,1,93,65,3,0,117,0,15,0,1,93,65,3,0,116,0,18,0,1,93,65,3,0,6,0,18,0,1,93,65,5,0,86,0,18,0,102,0,18,0,2,93,65,5,0,87,0,19,0,103,0,19,0,2,93,0,65,3,0,133,0,5,0,1,93,65,3,0,118,0,5,0,1,93,65,3,0,133,0,6,0,1,93,65,3,0,118,0,6,0,1,93,65,7,0,7,0,6,0,23,0,6,0,39,0,6,0,3,93,65,3,0,136,0,11,0,1,93,65,3,0,121,0,11,0,1,93,65,3,0,136,0,12,0,1,93,65,3,0,122,0,12,0,1,93,65,3,0,101,0,14,0,1,93,65,3,0,86,0,14,0,1,93,65,3,0,134,0,14,0,1,93,65,3,0,119,0,15,0,1,93,65,3,0,9,0,18,0,1,93,65,5,0,90,0,18,0,106,0,18,0,2,93,65,3,0,123,0,18,0,1,93,65,3,0,106,0,19,0,1,93,65,3,0,91,0,19,0,1,93,33,35,17,51,50,30,2,21,20,14,2,7,30,1,21,20,14,2,3,35,21,51,50,62,2,53,52,46,2,19,35,21,51,50,62,2,53,52,46,2,1,64,240,158,65,99,66,34,3,12,23,19,65,52,43,69,87,98,90,118,24,40,30,17,23,38,50,30,148,98,45,70,49,26,20,36,52,2,188,14,39,67,53,27,40,34,33,20,25,80,60,67,82,44,15,2,103,206,7,22,44,38,33,38,19,5,254,220,237,7,24,44,38,35,47,29,13,0,0,0,1,0,39,255,242,2,71,2,202,0,38,1,174,186,0,12,0,5,0,3,43,65,3,0,95,0,5,0,1,93,65,3,0,127,0,5,0,1,93,65,3,0,63,0,5,0,1,93,65,3,0,16,0,5,0,1,93,65,3,0,0,0,12,0,1,113,65,5,0,0,0,12,0,16,0,12,0,2,93,65,3,0,224,0,12,0,1,93,65,3,0,176,0,12,0,1,93,184,0,5,16,185,0,21,0,4,244,184,0,12,16,184,0,37,208,65,3,0,0,0,40,0,1,93,0,184,0,0,69,88,184,0,10,47,27,185,0,10,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,65,3,0,25,0,5,0,1,93,184,0,10,16,184,0,13,220,65,5,0,144,0,13,0,160,0,13,0,2,93,185,0,12,0,2,244,184,0,10,16,185,0,16,0,2,244,184,0,0,16,185,0,26,0,2,244,184,0,0,16,184,0,36,220,65,5,0,159,0,36,0,175,0,36,0,2,93,185,0,37,0,2,244,48,49,1,65,3,0,104,0,2,0,1,93,65,3,0,25,0,2,0,1,93,65,3,0,121,0,2,0,1,93,65,3,0,90,0,2,0,1,93,65,3,0,90,0,3,0,1,93,65,3,0,24,0,7,0,1,93,65,3,0,88,0,7,0,1,93,65,3,0,24,0,8,0,1,93,65,3,0,88,0,8,0,1,93,65,3,0,121,0,8,0,1,93,65,3,0,106,0,8,0,1,93,65,3,0,71,0,19,0,1,93,0,65,3,0,24,0,2,0,1,93,65,5,0,88,0,2,0,104,0,2,0,2,93,65,3,0,121,0,2,0,1,93,65,3,0,88,0,3,0,1,93,65,3,0,23,0,7,0,1,93,65,3,0,87,0,7,0,1,93,65,5,0,85,0,8,0,101,0,8,0,2,93,65,3,0,118,0,8,0,1,93,65,3,0,23,0,8,0,1,93,5,34,46,2,53,52,62,2,51,50,23,7,39,38,35,34,14,2,21,20,30,2,51,50,54,63,1,54,63,1,54,63,1,23,6,1,134,77,129,93,52,52,93,128,77,107,87,10,57,57,70,59,91,63,33,32,63,93,60,15,28,15,25,8,19,23,5,21,23,10,87,14,52,96,134,82,81,134,96,53,41,88,20,23,42,74,102,60,59,102,75,42,2,3,5,1,7,7,1,8,8,88,40,0,0,2,0,80,0,0,2,175,2,188,0,12,0,25,1,67,186,0,8,0,1,0,3,43,65,3,0,47,0,1,0,1,113,65,3,0,127,0,1,0,1,93,65,3,0,175,0,1,0,1,93,65,3,0,16,0,1,0,1,93,65,3,0,128,0,8,0,1,93,65,3,0,224,0,8,0,1,93,65,3,0,16,0,8,0,1,113,65,3,0,192,0,8,0,1,93,65,5,0,64,0,8,0,80,0,8,0,2,93,65,5,0,16,0,8,0,32,0,8,0,2,93,184,0,1,16,185,0,15,0,4,244,184,0,8,16,185,0,21,0,4,244,0,184,0,0,69,88,184,0,3,47,27,185,0,3,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,3,16,185,0,13,0,2,244,184,0,0,16,185,0,16,0,2,244,48,49,1,65,7,0,86,0,5,0,102,0,5,0,118,0,5,0,3,93,65,3,0,86,0,6,0,1,93,65,3,0,86,0,10,0,1,93,65,3,0,86,0,11,0,1,93,65,3,0,118,0,11,0,1,93,65,3,0,103,0,11,0,1,93,65,3,0,8,0,18,0,1,93,0,65,3,0,86,0,5,0,1,93,65,5,0,103,0,5,0,119,0,5,0,2,93,65,3,0,87,0,6,0,1,93,65,3,0,89,0,10,0,1,93,65,3,0,105,0,11,0,1,93,65,3,0,90,0,11,0,1,93,65,3,0,123,0,11,0,1,93,41,1,17,33,50,30,2,21,20,14,2,3,35,17,51,50,62,2,53,52,46,2,1,83,254,253,1,3,76,128,93,51,51,91,128,78,164,164,58,91,63,32,32,63,91,2,188,48,91,130,81,81,130,90,49,2,102,253,240,37,69,98,60,60,98,69,37,0,0,0,1,0,80,0,0,2,4,2,188,0,11,0,168,186,0,11,0,1,0,3,43,65,3,0,191,0,1,0,1,93,65,3,0,0,0,1,0,1,93,65,3,0,0,0,11,0,1,93,65,3,0,208,0,11,0,1,93,65,3,0,64,0,11,0,1,93,184,0,11,16,184,0,4,208,184,0,4,47,184,0,1,16,185,0,10,0,4,244,184,0,6,208,184,0,11,16,184,0,8,208,184,0,8,47,0,184,0,0,69,88,184,0,2,47,27,185,0,2,0,14,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,184,0,2,16,185,0,5,0,2,244,186,0,6,0,2,0,1,17,18,57,184,0,6,47,185,0,9,0,2,244,184,0,1,16,185,0,10,0,2,244,48,49,41,1,17,33,21,33,21,33,21,33,21,33,2,4,254,76,1,171,254,180,1,8,254,248,1,85,2,188,86,205,86,237,0,0,0,1,0,80,0,0,1,251,2,188,0,9,0,163,186,0,0,0,7,0,3,43,65,3,0,143,0,0,0,1,93,65,5,0,0,0,0,0,16,0,0,0,2,93,65,3,0,64,0,0,0,1,93,65,3,0,143,0,7,0,1,93,65,3,0,191,0,7,0,1,93,65,5,0,0,0,7,0,16,0,7,0,2,93,184,0,7,16,185,0,6,0,4,244,184,0,2,208,184,0,0,16,184,0,3,208,184,0,3,47,0,184,0,0,69,88,184,0,8,47,27,185,0,8,0,14,62,89,184,0,0,69,88,184,0,6,47,27,185,0,6,0,6,62,89,184,0,8,16,185,0,1,0,2,244,186,0,2,0,8,0,6,17,18,57,184,0,2,47,185,0,5,0,2,244,48,49,1,33,21,33,21,33,17,35,17,33,1,251,254,180,1,0,255,0,95,1,171,2,102,205,86,254,189,2,188,0,0,0,1,0,39,255,242,2,109,2,202,0,36,1,79,186,0,31,0,5,0,3,43,65,5,0,63,0,5,0,79,0,5,0,2,93,65,3,0,32,0,5,0,1,93,65,3,0,128,0,31,0,1,93,65,3,0,32,0,31,0,1,113,65,3,0,63,0,31,0,1,93,65,3,0,0,0,31,0,1,113,65,3,0,80,0,31,0,1,93,65,3,0,32,0,31,0,1,93,186,0,12,0,31,0,5,17,18,57,184,0,12,47,184,0,5,16,185,0,20,0,4,244,184,0,31,16,185,0,28,0,4,244,184,0,31,16,184,0,30,220,0,184,0,0,69,88,184,0,10,47,27,185,0,10,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,10,16,184,0,13,220,184,0,10,16,185,0,15,0,2,244,184,0,0,16,185,0,25,0,2,244,186,0,30,0,10,0,0,17,18,57,184,0,30,47,185,0,29,0,2,244,48,49,1,65,3,0,90,0,2,0,1,93,65,3,0,91,0,3,0,1,93,65,3,0,89,0,8,0,1,93,65,3,0,6,0,17,0,1,93,65,3,0,7,0,23,0,1,93,0,65,3,0,90,0,2,0,1,93,65,3,0,83,0,8,0,1,93,65,11,0,70,0,11,0,86,0,11,0,102,0,11,0,118,0,11,0,134,0,11,0,5,93,65,11,0,70,0,12,0,86,0,12,0,102,0,12,0,118,0,12,0,134,0,12,0,5,93,65,3,0,7,0,23,0,1,93,5,34,46,2,53,52,62,2,51,50,23,7,38,35,34,14,2,21,20,30,2,51,50,55,53,35,53,51,17,14,3,1,126,74,126,92,51,52,93,129,77,118,90,9,105,91,61,94,63,32,34,67,99,66,72,45,110,205,20,59,65,67,14,53,96,134,82,82,134,95,52,40,83,37,41,73,103,61,63,103,72,40,19,174,86,254,200,11,19,15,8,0,1,0,80,0,0,2,154,2,188,0,11,0,209,186,0,0,0,5,0,3,43,65,3,0,208,0,0,0,1,93,65,3,0,80,0,0,0,1,113,65,3,0,32,0,0,0,1,113,65,3,0,64,0,0,0,1,93,65,3,0,16,0,0,0,1,93,184,0,0,16,185,0,1,0,4,244,65,3,0,191,0,5,0,1,93,65,3,0,15,0,5,0,1,113,65,3,0,143,0,5,0,1,93,65,3,0,16,0,5,0,1,93,184,0,5,16,185,0,4,0,4,244,184,0,8,208,184,0,1,16,184,0,9,208,65,3,0,64,0,13,0,1,93,0,184,0,0,69,88,184,0,7,47,27,185,0,7,0,14,62,89,184,0,0,69,88,184,0,4,47,27,185,0,4,0,6,62,89,184,0,1,208,186,0,8,0,7,0,4,17,18,57,184,0,8,47,185,0,3,0,2,244,184,0,7,16,184,0,10,208,48,49,1,65,3,0,15,0,12,0,1,93,33,35,17,33,17,35,17,51,17,33,17,51,2,154,95,254,116,95,95,1,140,95,1,65,254,191,2,188,254,223,1,33,0,0,1,0,80,0,0,0,175,2,188,0,3,0,118,187,0,0,0,4,0,1,0,4,43,65,5,0,159,0,0,0,175,0,0,0,2,93,65,3,0,0,0,0,0,1,93,65,3,0,112,0,0,0,1,93,65,5,0,159,0,1,0,175,0,1,0,2,93,65,3,0,112,0,1,0,1,93,65,3,0,0,0,1,0,1,93,65,3,0,80,0,5,0,1,93,0,184,0,0,69,88,184,0,2,47,27,185,0,2,0,14,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,48,49,51,35,17,51,175,95,95,2,188,0,0,0,0,1,255,239,255,84,0,175,2,188,0,12,0,104,187,0,10,0,4,0,9,0,4,43,65,3,0,95,0,9,0,1,93,65,5,0,159,0,9,0,175,0,9,0,2,93,65,3,0,0,0,9,0,1,93,65,5,0,159,0,10,0,175,0,10,0,2,93,65,3,0,95,0,10,0,1,93,65,3,0,0,0,10,0,1,93,0,184,0,1,47,184,0,0,69,88,184,0,9,47,27,185,0,9,0,14,62,89,184,0,1,16,184,0,3,220,48,49,23,35,39,51,50,62,2,53,17,51,17,20,9,16,10,4,27,36,21,9,95,172,56,12,27,43,31,2,191,253,36,140,0,0,0,2,0,80,0,0,2,61,2,188,0,5,0,9,1,44,186,0,1,0,7,0,3,43,65,3,0,80,0,1,0,1,93,65,5,0,0,0,1,0,16,0,1,0,2,93,65,3,0,176,0,1,0,1,93,184,0,1,16,184,0,0,208,65,5,0,85,0,0,0,101,0,0,0,2,93,65,3,0,70,0,0,0,1,93,65,7,0,153,0,0,0,169,0,0,0,185,0,0,0,3,93,65,3,0,57,0,0,0,1,113,65,3,0,39,0,0,0,1,93,65,5,0,22,0,0,0,38,0,0,0,2,113,65,3,0,116,0,0,0,1,93,65,3,0,131,0,0,0,1,93,184,0,1,16,184,0,2,208,65,3,0,70,0,2,0,1,93,184,0,1,16,184,0,3,208,65,3,0,8,0,3,0,1,93,184,0,0,16,184,0,4,208,65,3,0,8,0,4,0,1,93,184,0,0,16,184,0,5,208,65,3,0,70,0,5,0,1,93,65,3,0,143,0,7,0,1,93,65,3,0,16,0,7,0,1,93,184,0,7,16,185,0,6,0,4,244,0,184,0,0,69,88,184,0,9,47,27,185,0,9,0,14,62,89,184,0,0,69,88,184,0,6,47,27,185,0,6,0,6,62,89,184,0,1,208,184,0,9,16,184,0,3,208,186,0,5,0,3,0,1,17,18,57,25,184,0,5,47,24,184,0,2,208,48,49,33,35,9,1,51,1,3,35,17,51,2,61,100,254,253,1,3,100,254,253,139,95,95,1,115,1,73,254,183,254,141,2,188,0,0,0,0,1,0,80,0,0,1,240,2,188,0,5,0,114,186,0,5,0,1,0,3,43,65,3,0,175,0,1,0,1,93,65,5,0,0,0,1,0,16,0,1,0,2,93,65,3,0,144,0,1,0,1,93,184,0,1,16,185,0,4,0,4,244,65,3,0,175,0,5,0,1,93,65,5,0,0,0,5,0,16,0,5,0,2,93,0,184,0,0,69,88,184,0,3,47,27,185,0,3,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,185,0,5,0,2,244,48,49,41,1,17,51,17,33,1,240,254,96,95,1,65,2,188,253,154,0,0,0,0,1,0,48,0,0,2,252,2,188,0,11,2,149,186,0,0,0,6,0,3,43,65,3,0,80,0,0,0,1,113,65,3,0,63,0,0,0,1,93,65,5,0,160,0,0,0,176,0,0,0,2,113,65,5,0,80,0,0,0,96,0,0,0,2,93,65,5,0,0,0,0,0,16,0,0,0,2,93,184,0,0,16,185,0,1,0,4,244,184,0,2,208,65,3,0,7,0,2,0,1,113,65,5,0,22,0,2,0,38,0,2,0,2,113,65,3,0,47,0,6,0,1,113,65,3,0,143,0,6,0,1,93,65,5,0,47,0,6,0,63,0,6,0,2,93,65,3,0,15,0,6,0,1,113,65,3,0,80,0,6,0,1,113,65,5,0,0,0,6,0,16,0,6,0,2,93,186,0,3,0,6,0,0,17,18,57,184,0,6,16,185,0,5,0,4,244,184,0,4,208,65,5,0,25,0,4,0,41,0,4,0,2,113,65,3,0,8,0,4,0,1,113,184,0,6,16,184,0,7,208,65,7,0,57,0,7,0,73,0,7,0,89,0,7,0,3,113,65,3,0,152,0,7,0,1,93,186,0,8,0,4,0,7,17,18,57,65,3,0,7,0,8,0,1,113,184,0,3,16,184,0,9,208,184,0,0,16,184,0,11,208,65,3,0,136,0,11,0,1,93,65,3,0,151,0,11,0,1,93,65,7,0,54,0,11,0,70,0,11,0,86,0,11,0,3,113,186,0,10,0,2,0,11,17,18,57,65,3,0,8,0,10,0,1,113,0,184,0,0,69,88,184,0,8,47,27,185,0,8,0,14,62,89,184,0,0,69,88,184,0,5,47,27,185,0,5,0,6,62,89,184,0,1,208,184,0,8,16,184,0,4,208,65,5,0,91,0,4,0,107,0,4,0,2,113,65,5,0,60,0,4,0,76,0,4,0,2,113,65,3,0,45,0,4,0,1,113,65,3,0,31,0,4,0,1,113,65,3,0,142,0,4,0,1,93,65,3,0,13,0,4,0,1,113,65,3,0,252,0,4,0,1,93,65,5,0,107,0,4,0,123,0,4,0,2,93,65,3,0,89,0,4,0,1,93,184,0,2,208,186,0,3,0,8,0,5,17,18,57,65,5,0,89,0,3,0,105,0,3,0,2,93,184,0,3,16,184,0,9,208,65,7,0,84,0,9,0,100,0,9,0,116,0,9,0,3,93,65,3,0,244,0,9,0,1,93,65,3,0,154,0,9,0,1,93,65,3,0,69,0,9,0,1,93,65,5,0,84,0,9,0,100,0,9,0,2,113,65,3,0,67,0,9,0,1,113,65,3,0,130,0,9,0,1,93,184,0,8,16,184,0,10,208,48,49,1,65,3,0,117,0,8,0,1,93,65,3,0,122,0,10,0,1,93,0,65,3,0,124,0,2,0,1,93,65,3,0,41,0,3,0,1,113,65,3,0,10,0,3,0,1,93,65,3,0,123,0,4,0,1,93,65,5,0,20,0,9,0,36,0,9,0,2,113,33,35,11,3,35,19,51,27,1,51,2,252,100,66,190,194,66,100,94,81,184,182,82,2,17,254,149,1,107,253,239,2,188,254,165,1,91,0,1,0,80,0,0,2,112,2,188,0,9,1,47,186,0,9,0,4,0,3,43,65,3,0,0,0,9,0,1,93,65,3,0,112,0,9,0,1,93,65,3,0,48,0,9,0,1,93,65,3,0,32,0,9,0,1,113,65,3,0,0,0,9,0,1,113,184,0,9,16,185,0,8,0,4,244,184,0,1,208,65,5,0,0,0,4,0,16,0,4,0,2,93,184,0,4,16,185,0,3,0,4,244,184,0,6,208,65,3,0,134,0,6,0,1,93,65,5,0,20,0,6,0,36,0,6,0,2,113,0,184,0,0,69,88,184,0,5,47,27,185,0,5,0,14,62,89,184,0,0,69,88,184,0,3,47,27,185,0,3,0,6,62,89,184,0,1,208,184,0,5,16,184,0,2,208,65,3,0,57,0,2,0,1,93,184,0,1,16,184,0,7,208,184,0,5,16,184,0,8,208,48,49,1,65,3,0,89,0,1,0,1,93,65,3,0,85,0,6,0,1,93,0,65,5,0,74,0,2,0,90,0,2,0,2,93,65,3,0,43,0,2,0,1,113,65,5,0,108,0,2,0,124,0,2,0,2,93,65,3,0,143,0,2,0,1,93,65,3,0,128,0,7,0,1,93,65,3,0,67,0,7,0,1,93,65,5,0,99,0,7,0,115,0,7,0,2,93,65,3,0,35,0,7,0,1,113,65,3,0,84,0,7,0,1,93,33,35,1,17,35,17,51,1,17,51,2,112,81,254,144,95,103,1,89,96,2,41,253,215,2,188,253,244,2,12,0,0,2,0,39,255,242,2,217,2,202,0,18,0,37,1,177,186,0,17,0,7,0,3,43,65,3,0,15,0,7,0,1,93,65,5,0,79,0,7,0,95,0,7,0,2,93,65,5,0,176,0,17,0,192,0,17,0,2,93,65,3,0,32,0,17,0,1,113,65,3,0,113,0,17,0,1,93,65,5,0,224,0,17,0,240,0,17,0,2,93,65,3,0,128,0,17,0,1,93,65,3,0,32,0,17,0,1,93,184,0,7,16,185,0,26,0,4,244,184,0,17,16,185,0,36,0,4,244,0,184,0,0,69,88,184,0,12,47,27,185,0,12,0,14,62,89,184,0,0,69,88,184,0,2,47,27,185,0,2,0,6,62,89,184,0,12,16,185,0,21,0,2,244,184,0,2,16,185,0,31,0,2,244,48,49,1,65,3,0,86,0,0,0,1,93,65,5,0,103,0,0,0,119,0,0,0,2,93,65,3,0,88,0,4,0,1,93,65,5,0,105,0,4,0,121,0,4,0,2,93,65,3,0,88,0,5,0,1,93,65,3,0,88,0,9,0,1,93,65,3,0,120,0,9,0,1,93,65,3,0,105,0,10,0,1,93,65,3,0,90,0,10,0,1,93,65,7,0,87,0,14,0,103,0,14,0,119,0,14,0,3,93,65,3,0,86,0,15,0,1,93,65,3,0,118,0,15,0,1,93,65,3,0,15,0,38,0,1,93,0,65,3,0,104,0,0,0,1,93,65,3,0,90,0,0,0,1,93,65,3,0,122,0,0,0,1,93,65,5,0,89,0,4,0,105,0,4,0,2,93,65,3,0,123,0,4,0,1,93,65,3,0,89,0,5,0,1,93,65,3,0,86,0,9,0,1,93,65,3,0,119,0,9,0,1,93,65,5,0,86,0,10,0,102,0,10,0,2,93,65,3,0,86,0,14,0,1,93,65,5,0,103,0,14,0,119,0,14,0,2,93,65,3,0,86,0,15,0,1,93,65,3,0,119,0,15,0,1,93,37,6,35,34,46,2,53,52,62,2,51,50,30,2,21,20,3,38,35,34,14,2,21,20,30,2,51,50,62,2,53,52,2,120,96,152,76,127,91,51,52,91,127,75,75,127,92,51,167,62,116,58,90,61,32,32,61,90,58,58,90,62,31,85,99,52,95,134,83,83,134,95,52,52,96,134,82,165,1,109,78,42,74,102,60,60,102,74,42,42,75,101,60,122,0,0,2,0,80,0,0,2,36,2,188,0,14,0,25,1,63,186,0,9,0,2,0,3,43,65,5,0,0,0,2,0,16,0,2,0,2,93,65,3,0,143,0,2,0,1,93,65,3,0,175,0,2,0,1,93,65,3,0,144,0,2,0,1,93,65,3,0,112,0,2,0,1,93,184,0,2,16,185,0,1,0,4,244,65,3,0,80,0,9,0,1,93,65,3,0,144,0,9,0,1,93,65,3,0,0,0,9,0,1,113,65,3,0,175,0,9,0,1,93,65,3,0,224,0,9,0,1,93,65,3,0,112,0,9,0,1,93,65,5,0,0,0,9,0,16,0,9,0,2,93,65,3,0,32,0,9,0,1,113,184,0,16,208,184,0,9,16,185,0,20,0,4,244,0,184,0,0,69,88,184,0,4,47,27,185,0,4,0,14,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,186,0,0,0,4,0,1,17,18,57,184,0,0,47,185,0,16,0,2,244,184,0,4,16,185,0,25,0,2,244,48,49,1,65,3,0,135,0,6,0,1,93,65,5,0,101,0,7,0,117,0,7,0,2,93,65,3,0,6,0,7,0,1,93,65,3,0,134,0,7,0,1,93,0,65,3,0,134,0,6,0,1,93,65,5,0,103,0,6,0,119,0,6,0,2,93,65,5,0,101,0,7,0,117,0,7,0,2,93,65,3,0,6,0,7,0,1,93,65,3,0,135,0,7,0,1,93,55,21,35,17,51,50,30,2,21,20,14,2,35,3,17,51,50,54,53,52,46,2,35,180,100,224,49,88,67,40,41,64,76,35,152,134,73,62,16,38,63,46,245,245,2,188,15,47,86,70,68,91,55,23,1,114,254,227,77,71,37,53,32,15,0,0,2,0,39,255,242,2,217,2,202,0,21,0,43,2,27,186,0,19,0,9,0,3,43,65,5,0,224,0,19,0,240,0,19,0,2,93,65,3,0,32,0,19,0,1,93,65,3,0,32,0,19,0,1,113,65,5,0,176,0,19,0,192,0,19,0,2,93,65,3,0,112,0,19,0,1,93,65,5,0,79,0,9,0,95,0,9,0,2,93,65,3,0,15,0,9,0,1,93,186,0,21,0,19,0,9,17,18,57,184,0,21,16,184,0,0,208,186,0,2,0,9,0,19,17,18,57,184,0,2,16,184,0,1,208,65,3,0,88,0,1,0,1,113,184,0,9,16,185,0,27,0,4,244,184,0,19,16,185,0,39,0,4,244,186,0,34,0,27,0,39,17,18,57,65,3,0,121,0,34,0,1,93,184,0,34,16,184,0,35,208,65,3,0,56,0,35,0,1,113,65,3,0,72,0,35,0,1,93,186,0,37,0,39,0,27,17,18,57,184,0,37,16,184,0,36,208,65,3,0,15,0,44,0,1,93,0,184,0,0,69,88,184,0,14,47,27,185,0,14,0,14,62,89,184,0,0,69,88,184,0,4,47,27,185,0,4,0,6,62,89,186,0,2,0,4,0,14,17,18,57,184,0,2,16,184,0,1,208,184,0,1,47,186,0,21,0,14,0,4,17,18,57,184,0,14,16,185,0,22,0,2,244,184,0,4,16,185,0,32,0,2,244,186,0,34,0,32,0,22,17,18,57,186,0,37,0,22,0,32,17,18,57,184,0,37,16,184,0,36,208,184,0,36,47,48,49,1,65,3,0,104,0,1,0,1,93,65,3,0,89,0,6,0,1,93,65,3,0,121,0,6,0,1,93,65,3,0,89,0,7,0,1,93,65,3,0,89,0,11,0,1,93,65,3,0,123,0,11,0,1,93,65,5,0,89,0,12,0,105,0,12,0,2,93,65,7,0,86,0,16,0,102,0,16,0,118,0,16,0,3,93,65,3,0,86,0,17,0,1,93,65,3,0,105,0,35,0,1,93,0,65,3,0,89,0,2,0,1,93,65,3,0,89,0,6,0,1,93,65,3,0,121,0,6,0,1,93,65,3,0,106,0,6,0,1,93,65,3,0,89,0,7,0,1,93,65,3,0,87,0,11,0,1,93,65,3,0,119,0,11,0,1,93,65,5,0,86,0,12,0,102,0,12,0,2,93,65,3,0,86,0,16,0,1,93,65,3,0,118,0,16,0,1,93,37,7,39,6,35,34,46,2,53,52,62,2,51,50,30,2,21,20,7,1,34,14,2,21,20,30,2,51,50,55,39,55,23,54,53,52,46,2,2,203,50,65,100,116,76,127,91,51,52,91,127,75,75,127,92,51,74,254,241,59,89,62,31,31,60,90,60,96,55,103,50,105,48,34,65,93,62,59,54,71,52,95,134,83,83,134,95,52,52,96,134,82,129,110,2,5,41,74,102,61,60,102,74,42,40,84,61,93,75,111,60,101,75,42,0,0,0,0,2,0,80,0,0,2,72,2,188,0,15,0,26,1,159,186,0,12,0,5,0,3,43,65,3,0,15,0,5,0,1,113,65,5,0,0,0,5,0,16,0,5,0,2,93,65,3,0,144,0,5,0,1,93,65,3,0,224,0,12,0,1,93,65,5,0,0,0,12,0,16,0,12,0,2,93,65,3,0,112,0,12,0,1,93,65,3,0,80,0,12,0,1,93,186,0,15,0,5,0,12,17,18,57,65,3,0,38,0,15,0,1,93,65,3,0,23,0,15,0,1,93,65,3,0,135,0,15,0,1,93,65,3,0,102,0,15,0,1,93,65,3,0,85,0,15,0,1,93,65,3,0,117,0,15,0,1,93,184,0,15,16,184,0,0,208,184,0,15,16,185,0,2,0,4,244,65,3,0,136,0,2,0,1,93,184,0,1,208,184,0,5,16,185,0,4,0,4,244,184,0,18,208,184,0,12,16,185,0,24,0,4,244,0,184,0,0,69,88,184,0,7,47,27,185,0,7,0,14,62,89,184,0,0,69,88,184,0,4,47,27,185,0,4,0,6,62,89,184,0,1,208,186,0,3,0,7,0,4,17,18,57,184,0,3,47,186,0,15,0,3,0,7,17,18,57,184,0,7,16,185,0,16,0,2,244,184,0,3,16,185,0,18,0,2,244,48,49,1,65,3,0,102,0,9,0,1,93,65,3,0,100,0,10,0,1,93,65,3,0,134,0,10,0,1,93,65,3,0,22,0,10,0,1,113,65,3,0,7,0,10,0,1,93,65,3,0,119,0,10,0,1,93,65,3,0,89,0,22,0,1,93,65,3,0,89,0,26,0,1,93,0,65,5,0,101,0,9,0,117,0,9,0,2,93,65,3,0,117,0,10,0,1,93,65,3,0,102,0,10,0,1,93,65,3,0,7,0,10,0,1,93,65,3,0,23,0,10,0,1,113,65,3,0,85,0,22,0,1,93,33,35,3,35,17,35,17,51,50,30,2,21,20,6,7,3,35,17,51,50,62,2,53,52,38,2,72,102,155,147,100,227,58,91,61,32,67,61,115,126,151,24,43,33,19,72,1,17,254,239,2,188,22,49,78,56,66,103,28,1,69,254,254,16,32,49,33,61,67,0,1,0,40,255,242,2,41,2,202,0,57,3,109,186,0,53,0,19,0,3,43,65,3,0,79,0,19,0,1,93,65,3,0,111,0,19,0,1,93,65,3,0,80,0,53,0,1,93,65,3,0,160,0,53,0,1,93,65,3,0,224,0,53,0,1,93,65,3,0,192,0,53,0,1,93,65,5,0,112,0,53,0,128,0,53,0,2,93,65,3,0,32,0,53,0,1,93,65,3,0,0,0,53,0,1,93,186,0,2,0,19,0,53,17,18,57,184,0,2,47,184,0,53,16,185,0,10,0,4,244,186,0,29,0,53,0,19,17,18,57,184,0,29,47,184,0,19,16,185,0,37,0,4,244,0,184,0,0,69,88,184,0,24,47,27,185,0,24,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,3,220,65,5,0,112,0,3,0,128,0,3,0,2,93,65,3,0,16,0,3,0,1,93,65,3,0,240,0,3,0,1,93,184,0,0,16,185,0,5,0,2,244,186,0,15,0,0,0,24,17,18,57,65,3,0,137,0,15,0,1,93,184,0,24,16,184,0,30,220,65,3,0,143,0,30,0,1,93,65,3,0,255,0,30,0,1,93,184,0,24,16,185,0,32,0,2,244,186,0,40,0,24,0,0,17,18,57,48,49,1,65,11,0,40,0,2,0,56,0,2,0,72,0,2,0,88,0,2,0,104,0,2,0,5,93,65,3,0,136,0,2,0,1,93,65,5,0,56,0,12,0,72,0,12,0,2,93,65,3,0,138,0,12,0,1,93,65,3,0,105,0,16,0,1,93,65,3,0,72,0,17,0,1,93,65,3,0,72,0,18,0,1,93,65,3,0,58,0,18,0,1,93,65,3,0,138,0,18,0,1,93,65,3,0,105,0,21,0,1,93,65,3,0,137,0,21,0,1,93,65,3,0,121,0,22,0,1,93,65,3,0,106,0,22,0,1,93,65,3,0,120,0,39,0,1,93,65,3,0,6,0,49,0,1,93,65,3,0,101,0,50,0,1,93,65,3,0,6,0,50,0,1,93,65,3,0,38,0,50,0,1,93,65,3,0,118,0,50,0,1,93,65,3,0,100,0,55,0,1,93,65,3,0,132,0,55,0,1,93,65,3,0,117,0,55,0,1,93,65,3,0,6,0,56,0,1,93,65,3,0,102,0,56,0,1,93,65,3,0,119,0,56,0,1,93,0,65,11,0,41,0,1,0,57,0,1,0,73,0,1,0,89,0,1,0,105,0,1,0,5,93,65,11,0,40,0,2,0,56,0,2,0,72,0,2,0,88,0,2,0,104,0,2,0,5,93,65,3,0,138,0,2,0,1,93,65,3,0,123,0,2,0,1,93,65,3,0,136,0,12,0,1,93,65,5,0,57,0,12,0,73,0,12,0,2,93,65,3,0,90,0,14,0,1,93,65,3,0,105,0,16,0,1,93,65,3,0,10,0,17,0,1,93,65,3,0,74,0,17,0,1,93,65,3,0,135,0,18,0,1,93,65,3,0,72,0,18,0,1,93,65,3,0,133,0,21,0,1,93,65,3,0,103,0,21,0,1,93,65,3,0,116,0,22,0,1,93,65,3,0,101,0,22,0,1,93,65,11,0,38,0,27,0,54,0,27,0,70,0,27,0,86,0,27,0,102,0,27,0,5,93,65,3,0,132,0,28,0,1,93,65,13,0,38,0,28,0,54,0,28,0,70,0,28,0,86,0,28,0,102,0,28,0,118,0,28,0,6,93,65,3,0,116,0,39,0,1,93,65,3,0,7,0,49,0,1,93,65,3,0,102,0,50,0,1,93,65,3,0,7,0,50,0,1,93,65,3,0,39,0,50,0,1,93,65,3,0,105,0,55,0,1,93,65,3,0,137,0,55,0,1,93,65,3,0,122,0,55,0,1,93,65,3,0,9,0,56,0,1,93,65,3,0,106,0,56,0,1,93,65,3,0,123,0,56,0,1,93,5,34,39,55,22,51,50,62,2,53,52,46,2,47,1,46,1,53,52,62,2,51,50,30,2,23,7,38,35,34,14,2,21,20,22,23,30,3,31,1,30,1,31,1,30,1,23,20,14,2,1,24,145,84,13,94,124,36,61,45,25,26,47,67,41,70,85,73,24,57,97,74,30,64,59,50,17,10,126,75,29,57,44,27,75,76,21,19,18,31,34,34,13,17,5,25,23,15,3,18,58,107,14,45,111,70,13,27,41,27,28,41,32,26,14,23,28,83,57,30,71,61,40,8,13,18,9,101,63,12,26,38,27,44,49,24,7,4,5,11,15,18,7,10,5,26,24,56,39,30,67,58,39,0,1,0,15,0,0,2,6,2,188,0,7,0,86,187,0,1,0,4,0,4,0,4,43,184,0,1,16,184,0,0,220,184,0,4,16,184,0,5,220,65,3,0,31,0,9,0,1,93,0,184,0,0,69,88,184,0,6,47,27,185,0,6,0,14,62,89,184,0,0,69,88,184,0,3,47,27,185,0,3,0,6,62,89,184,0,6,16,185,0,5,0,2,244,184,0,1,208,48,49,1,35,17,35,17,35,53,33,2,6,204,95,204,1,247,2,102,253,154,2,102,86,0,0,0,1,0,72,255,242,2,140,2,188,0,21,1,207,186,0,15,0,1,0,3,43,65,3,0,223,0,1,0,1,93,65,3,0,143,0,1,0,1,93,65,5,0,175,0,1,0,191,0,1,0,2,93,65,3,0,16,0,1,0,1,93,184,0,1,16,185,0,2,0,4,244,65,3,0,64,0,15,0,1,93,65,3,0,175,0,15,0,1,93,65,3,0,240,0,15,0,1,93,65,3,0,0,0,15,0,1,113,65,3,0,16,0,15,0,1,93,65,3,0,32,0,15,0,1,113,184,0,15,16,185,0,14,0,4,244,65,3,0,15,0,22,0,1,93,0,184,0,0,69,88,184,0,2,47,27,185,0,2,0,14,62,89,184,0,0,69,88,184,0,19,47,27,185,0,19,0,6,62,89,185,0,8,0,2,244,184,0,2,16,184,0,14,208,48,49,1,65,3,0,103,0,5,0,1,93,65,3,0,135,0,5,0,1,93,65,3,0,136,0,10,0,1,93,65,3,0,104,0,11,0,1,93,65,3,0,136,0,11,0,1,93,65,3,0,36,0,17,0,1,93,65,3,0,22,0,17,0,1,93,65,3,0,118,0,17,0,1,93,65,3,0,23,0,18,0,1,93,65,3,0,71,0,18,0,1,93,65,3,0,24,0,20,0,1,93,65,3,0,72,0,20,0,1,93,65,3,0,58,0,20,0,1,93,65,3,0,25,0,21,0,1,93,65,3,0,122,0,21,0,1,93,65,3,0,43,0,21,0,1,93,0,65,3,0,133,0,5,0,1,93,65,3,0,102,0,5,0,1,93,65,3,0,133,0,6,0,1,93,65,3,0,134,0,10,0,1,93,65,3,0,101,0,11,0,1,93,65,3,0,135,0,11,0,1,93,65,3,0,120,0,17,0,1,93,65,3,0,56,0,18,0,1,93,65,3,0,41,0,18,0,1,93,65,3,0,73,0,18,0,1,93,65,3,0,27,0,18,0,1,93,65,3,0,25,0,20,0,1,93,65,3,0,57,0,20,0,1,93,65,3,0,42,0,20,0,1,93,65,3,0,74,0,20,0,1,93,19,17,51,17,20,30,2,51,50,62,2,53,17,51,17,20,6,35,34,38,72,95,14,41,77,63,63,77,42,13,95,145,145,145,145,1,41,1,147,254,155,51,97,77,46,48,76,97,50,1,101,254,109,148,163,163,0,0,0,0,1,0,4,0,0,2,128,2,188,0,6,1,95,187,0,1,0,4,0,2,0,4,43,65,3,0,16,0,1,0,1,93,65,3,0,112,0,1,0,1,93,65,5,0,32,0,1,0,48,0,1,0,2,113,184,0,1,16,184,0,0,208,65,3,0,24,0,0,0,1,93,65,3,0,71,0,0,0,1,93,65,3,0,134,0,0,0,1,93,65,3,0,112,0,2,0,1,93,65,3,0,16,0,2,0,1,93,65,5,0,32,0,2,0,48,0,2,0,2,113,184,0,2,16,184,0,3,208,65,3,0,137,0,3,0,1,93,65,3,0,72,0,3,0,1,93,185,0,4,0,4,244,186,0,5,0,2,0,1,17,18,57,184,0,0,16,185,0,6,0,4,244,65,3,0,79,0,8,0,1,93,0,184,0,0,69,88,184,0,4,47,27,185,0,4,0,14,62,89,184,0,0,69,88,184,0,2,47,27,185,0,2,0,6,62,89,184,0,5,208,184,0,4,16,184,0,6,208,48,49,1,65,3,0,134,0,1,0,1,93,65,13,0,167,0,1,0,183,0,1,0,199,0,1,0,215,0,1,0,231,0,1,0,247,0,1,0,6,93,65,7,0,7,0,1,0,23,0,1,0,39,0,1,0,3,113,65,13,0,168,0,2,0,184,0,2,0,200,0,2,0,216,0,2,0,232,0,2,0,248,0,2,0,6,93,65,7,0,8,0,2,0,24,0,2,0,40,0,2,0,3,113,65,3,0,137,0,2,0,1,93,0,65,5,0,100,0,5,0,116,0,5,0,2,93,65,3,0,85,0,5,0,1,93,9,1,35,1,51,27,1,2,128,254,244,100,254,244,100,219,217,2,188,253,68,2,188,253,177,2,79,0,1,0,14,0,0,3,193,2,188,0,12,1,221,186,0,10,0,9,0,3,43,65,3,0,63,0,10,0,1,93,184,0,10,16,184,0,1,220,65,3,0,47,0,1,0,1,93,184,0,0,208,184,0,1,16,185,0,2,0,4,244,65,3,0,63,0,9,0,1,93,186,0,3,0,9,0,10,17,18,57,184,0,9,16,184,0,5,220,185,0,4,0,4,244,184,0,5,16,184,0,6,208,65,3,0,71,0,6,0,1,93,185,0,7,0,4,244,186,0,8,0,5,0,4,17,18,57,186,0,11,0,2,0,1,17,18,57,184,0,0,16,185,0,12,0,4,244,65,3,0,191,0,14,0,1,93,65,3,0,159,0,14,0,1,93,0,184,0,0,69,88,184,0,7,47,27,185,0,7,0,14,62,89,184,0,0,69,88,184,0,5,47,27,185,0,5,0,6,62,89,184,0,2,208,184,0,7,16,184,0,9,208,184,0,9,47,184,0,3,208,184,0,5,16,184,0,8,208,184,0,11,208,184,0,7,16,184,0,12,208,48,49,1,65,3,0,40,0,1,0,1,93,65,3,0,8,0,2,0,1,93,65,5,0,56,0,2,0,72,0,2,0,2,93,65,3,0,137,0,2,0,1,93,65,3,0,122,0,2,0,1,93,65,7,0,102,0,4,0,118,0,4,0,134,0,4,0,3,93,65,3,0,71,0,4,0,1,93,65,3,0,247,0,4,0,1,93,65,3,0,135,0,7,0,1,93,65,3,0,104,0,9,0,1,93,65,3,0,136,0,9,0,1,93,65,3,0,248,0,9,0,1,93,65,3,0,7,0,10,0,1,93,65,3,0,71,0,10,0,1,93,65,3,0,135,0,10,0,1,93,65,3,0,56,0,10,0,1,93,65,3,0,41,0,10,0,1,93,0,65,3,0,4,0,3,0,1,93,65,3,0,21,0,3,0,1,93,65,3,0,70,0,3,0,1,93,65,3,0,123,0,3,0,1,93,65,3,0,26,0,8,0,1,93,65,3,0,11,0,8,0,1,93,65,3,0,57,0,11,0,1,93,65,3,0,26,0,11,0,1,93,65,3,0,12,0,11,0,1,93,1,3,35,11,1,35,3,51,27,1,51,27,1,3,193,205,105,165,171,105,196,100,155,175,86,177,154,2,188,253,68,2,62,253,194,2,188,253,176,2,66,253,191,2,79,0,1,0,9,0,0,2,82,2,188,0,11,1,205,187,0,11,0,4,0,5,0,4,43,184,0,11,16,184,0,0,208,65,3,0,182,0,0,0,1,93,65,3,0,22,0,0,0,1,113,65,3,0,215,0,0,0,1,93,65,3,0,87,0,0,0,1,93,65,3,0,136,0,0,0,1,93,65,3,0,151,0,0,0,1,93,65,3,0,23,0,0,0,1,93,65,3,0,54,0,0,0,1,113,65,3,0,246,0,0,0,1,93,65,3,0,101,0,0,0,1,93,65,3,0,36,0,0,0,1,93,185,0,1,0,4,244,65,3,0,39,0,1,0,1,93,186,0,2,0,5,0,11,17,18,57,184,0,5,16,184,0,4,208,65,3,0,54,0,4,0,1,93,65,3,0,215,0,4,0,1,93,65,3,0,41,0,4,0,1,93,65,3,0,105,0,4,0,1,93,65,3,0,230,0,4,0,1,93,65,5,0,118,0,4,0,134,0,4,0,2,93,65,3,0,166,0,4,0,1,93,185,0,3,0,4,244,184,0,4,16,184,0,6,208,184,0,3,16,184,0,7,208,65,3,0,118,0,7,0,1,93,186,0,8,0,5,0,11,17,18,57,184,0,1,16,184,0,9,208,184,0,0,16,184,0,10,208,65,3,0,15,0,13,0,1,93,0,184,0,0,69,88,184,0,7,47,27,185,0,7,0,14,62,89,184,0,0,69,88,184,0,3,47,27,185,0,3,0,6,62,89,184,0,1,208,186,0,2,0,3,0,7,17,18,57,65,3,0,150,0,2,0,1,93,186,0,8,0,7,0,3,17,18,57,186,0,5,0,8,0,2,17,18,57,184,0,7,16,184,0,9,208,186,0,11,0,2,0,8,17,18,57,48,49,65,3,0,74,0,2,0,1,93,65,3,0,106,0,2,0,1,93,65,3,0,138,0,2,0,1,93,65,3,0,123,0,2,0,1,93,65,3,0,116,0,8,0,1,93,65,3,0,101,0,8,0,1,93,65,3,0,133,0,8,0,1,93,65,7,0,54,0,8,0,70,0,8,0,86,0,8,0,3,93,33,35,11,1,35,19,3,51,27,1,51,3,2,82,100,202,183,100,235,235,110,180,194,100,250,1,30,254,226,1,93,1,95,254,239,1,17,254,173,0,0,0,1,255,253,0,0,2,57,2,188,0,8,0,233,187,0,1,0,4,0,4,0,4,43,65,3,0,175,0,1,0,1,93,65,3,0,32,0,1,0,1,93,184,0,1,16,184,0,0,208,65,3,0,121,0,0,0,1,93,65,3,0,102,0,0,0,1,93,65,3,0,38,0,0,0,1,93,65,3,0,175,0,4,0,1,93,65,3,0,32,0,4,0,1,93,184,0,4,16,184,0,5,208,65,3,0,105,0,5,0,1,93,65,3,0,41,0,5,0,1,93,65,3,0,118,0,5,0,1,93,185,0,6,0,4,244,186,0,7,0,4,0,1,17,18,57,184,0,0,16,185,0,8,0,4,244,0,184,0,0,69,88,184,0,6,47,27,185,0,6,0,14,62,89,184,0,0,69,88,184,0,2,47,27,185,0,2,0,6,62,89,186,0,7,0,6,0,2,17,18,57,184,0,6,16,184,0,8,208,48,49,65,3,0,88,0,1,0,1,93,65,3,0,89,0,4,0,1,93,65,3,0,131,0,7,0,1,93,65,3,0,116,0,7,0,1,93,1,3,17,35,17,3,51,27,1,2,57,236,99,237,100,186,186,2,188,254,135,254,189,1,67,1,121,254,221,1,35,0,0,0,1,0,9,0,0,2,30,2,188,0,7,1,200,186,0,2,0,6,0,3,43,65,3,0,64,0,2,0,1,93,65,3,0,175,0,2,0,1,93,65,3,0,96,0,2,0,1,93,65,5,0,16,0,2,0,32,0,2,0,2,93,65,3,0,128,0,2,0,1,93,184,0,2,16,184,0,0,208,65,3,0,16,0,6,0,1,93,184,0,6,16,184,0,4,208,184,0,1,208,65,3,0,99,0,1,0,1,93,65,3,0,69,0,1,0,1,93,65,5,0,85,0,1,0,101,0,1,0,2,113,65,3,0,38,0,1,0,1,93,65,3,0,184,0,1,0,1,93,65,5,0,153,0,1,0,169,0,1,0,2,93,65,5,0,54,0,1,0,70,0,1,0,2,113,65,3,0,246,0,1,0,1,93,65,3,0,6,0,1,0,1,113,65,3,0,21,0,1,0,1,113,65,3,0,36,0,1,0,1,113,65,3,0,114,0,1,0,1,93,65,3,0,128,0,1,0,1,93,184,0,0,16,184,0,5,208,65,3,0,24,0,5,0,1,93,65,3,0,41,0,5,0,1,93,65,3,0,58,0,5,0,1,113,65,3,0,74,0,5,0,1,93,65,3,0,43,0,5,0,1,113,65,3,0,125,0,5,0,1,93,65,3,0,143,0,5,0,1,93,65,3,0,108,0,5,0,1,93,65,3,0,26,0,5,0,1,113,65,5,0,90,0,5,0,106,0,5,0,2,113,65,3,0,249,0,5,0,1,93,65,3,0,9,0,5,0,1,113,65,3,0,73,0,5,0,1,113,65,3,0,183,0,5,0,1,93,65,5,0,150,0,5,0,166,0,5,0,2,93,0,184,0,0,69,88,184,0,7,47,27,185,0,7,0,14,62,89,184,0,0,69,88,184,0,3,47,27,185,0,3,0,6,62,89,185,0,2,0,2,244,184,0,7,16,185,0,6,0,2,244,48,49,1,65,3,0,84,0,1,0,1,93,65,3,0,54,0,1,0,1,93,65,3,0,57,0,5,0,1,93,65,3,0,91,0,5,0,1,93,9,1,33,21,33,1,33,53,2,30,254,135,1,76,254,24,1,120,254,181,2,188,253,154,86,2,102,86,0,0,0,1,0,70,255,121,1,71,2,238,0,7,0,78,184,0,1,47,65,3,0,143,0,1,0,1,93,65,5,0,0,0,1,0,16,0,1,0,2,93,184,0,0,220,184,0,4,208,184,0,1,16,184,0,6,220,0,184,0,0,47,184,0,0,69,88,184,0,3,47,27,185,0,3,0,18,62,89,184,0,4,220,184,0,0,16,184,0,7,220,48,49,5,33,17,33,21,35,17,51,1,71,254,255,1,1,174,174,135,3,117,68,253,19,0,0,0,1,0,35,255,171,1,250,2,188,0,3,0,61,184,0,2,47,184,0,0,220,65,5,0,112,0,0,0,128,0,0,0,2,93,185,0,1,0,4,244,184,0,2,16,185,0,3,0,4,244,0,184,0,1,47,184,0,0,69,88,184,0,3,47,27,185,0,3,0,14,62,89,48,49,5,35,1,51,1,250,93,254,134,93,85,3,17,0,1,0,0,255,121,1,1,2,238,0,7,0,82,184,0,2,47,65,3,0,208,0,2,0,1,93,65,3,0,16,0,2,0,1,93,184,0,4,220,184,0,2,16,184,0,5,220,184,0,4,16,184,0,7,208,0,184,0,3,47,184,0,0,69,88,184,0,0,47,27,185,0,0,0,18,62,89,184,0,3,16,184,0,4,220,184,0,0,16,184,0,7,220,48,49,17,33,17,33,53,51,17,35,1,1,254,255,174,174,2,238,252,139,68,2,237,0,0,0,0,1,0,49,1,181,1,205,2,247,0,5,0,95,25,184,0,4,47,24,184,0,1,208,184,0,4,16,184,0,3,208,184,0,3,47,184,0,4,16,184,0,5,208,184,0,5,47,0,184,0,4,47,184,0,2,220,184,0,0,208,184,0,4,16,184,0,1,208,65,7,0,107,0,1,0,123,0,1,0,139,0,1,0,3,93,184,0,2,16,184,0,3,208,65,3,0,181,0,3,0,1,93,184,0,5,208,48,49,1,39,7,53,55,23,1,205,206,206,206,206,1,181,216,216,106,216,216,0,1,0,3,255,134,2,51,255,220,0,3,0,64,184,0,4,47,184,0,5,47,184,0,4,16,184,0,2,208,184,0,2,47,184,0,5,16,184,0,3,208,184,0,3,47,0,184,0,4,47,184,0,2,220,184,0,1,220,65,7,0,79,0,1,0,95,0,1,0,111,0,1,0,3,113,48,49,5,33,53,33,2,51,253,208,2,48,122,86,0,0,0,1,0,58,2,84,0,245,2,220,0,3,0,126,184,0,1,47,65,7,0,0,0,1,0,16,0,1,0,32,0,1,0,3,93,65,5,0,16,0,1,0,32,0,1,0,2,113,184,0,3,220,0,184,0,0,47,65,3,0,16,0,0,0,1,113,65,3,0,64,0,0,0,1,93,65,3,0,32,0,0,0,1,93,184,0,2,220,65,5,0,15,0,2,0,31,0,2,0,2,93,184,0,1,220,184,0,0,16,184,0,3,220,65,11,0,86,0,3,0,102,0,3,0,118,0,3,0,134,0,3,0,150,0,3,0,5,93,48,49,19,39,53,23,245,187,187,2,84,64,72,95,0,2,0,24,255,246,1,216,1,244,0,34,0,43,2,22,186,0,30,0,12,0,3,43,65,3,0,160,0,30,0,1,93,65,3,0,159,0,30,0,1,93,65,3,0,127,0,30,0,1,93,65,3,0,48,0,30,0,1,113,65,3,0,192,0,30,0,1,93,65,3,0,16,0,30,0,1,113,184,0,30,16,184,0,0,208,184,0,0,47,65,3,0,0,0,0,0,1,93,184,0,30,16,185,0,36,0,4,244,186,0,7,0,36,0,30,17,18,57,65,9,0,111,0,12,0,127,0,12,0,143,0,12,0,159,0,12,0,4,93,65,3,0,15,0,12,0,1,113,65,3,0,63,0,12,0,1,93,65,3,0,31,0,12,0,1,93,65,3,0,191,0,12,0,1,93,65,3,0,192,0,12,0,1,93,65,3,0,160,0,12,0,1,93,184,0,17,208,186,0,23,0,12,0,30,17,18,57,184,0,23,47,184,0,12,16,185,0,39,0,4,244,0,184,0,0,69,88,184,0,25,47,27,185,0,25,0,12,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,184,0,0,69,88,184,0,9,47,27,185,0,9,0,6,62,89,186,0,17,0,25,0,9,17,18,57,184,0,17,47,186,0,7,0,17,0,9,17,18,57,184,0,25,16,185,0,20,0,2,244,184,0,25,16,184,0,22,220,65,3,0,79,0,22,0,1,93,184,0,1,16,185,0,34,0,1,244,184,0,17,16,185,0,36,0,1,244,184,0,9,16,185,0,41,0,1,244,48,49,1,65,3,0,56,0,10,0,1,93,65,3,0,25,0,10,0,1,93,65,3,0,41,0,11,0,1,93,65,3,0,26,0,11,0,1,93,65,3,0,24,0,14,0,1,93,65,3,0,136,0,14,0,1,93,65,5,0,120,0,24,0,136,0,24,0,2,93,65,7,0,7,0,27,0,23,0,27,0,39,0,27,0,3,93,65,3,0,6,0,28,0,1,93,0,65,3,0,56,0,10,0,1,93,65,3,0,25,0,10,0,1,93,65,3,0,42,0,10,0,1,93,65,3,0,118,0,14,0,1,93,65,3,0,135,0,14,0,1,93,65,3,0,117,0,24,0,1,93,65,5,0,86,0,24,0,102,0,24,0,2,93,65,3,0,135,0,24,0,1,93,65,5,0,6,0,27,0,22,0,27,0,2,93,65,3,0,39,0,27,0,1,93,37,7,35,34,46,2,39,6,35,34,38,53,52,62,2,55,52,38,35,34,7,39,54,51,50,30,2,29,1,20,22,51,39,53,14,1,21,20,51,50,54,1,216,14,7,30,40,28,19,9,62,88,69,82,55,85,104,49,51,56,64,65,13,66,100,47,66,41,19,20,36,146,108,93,76,36,67,62,72,7,17,28,20,72,79,63,51,66,40,17,1,66,47,44,73,51,25,55,90,65,100,58,45,66,117,4,49,55,75,36,0,2,0,60,255,246,2,11,2,238,0,21,0,41,1,57,186,0,17,0,7,0,3,43,65,3,0,15,0,7,0,1,113,65,3,0,31,0,7,0,1,93,65,3,0,47,0,7,0,1,113,65,3,0,0,0,7,0,1,93,65,3,0,32,0,7,0,1,93,184,0,7,16,185,0,10,0,4,244,184,0,5,208,65,3,0,0,0,17,0,1,93,65,7,0,32,0,17,0,48,0,17,0,64,0,17,0,3,93,65,3,0,96,0,17,0,1,93,65,3,0,16,0,17,0,1,113,184,0,10,16,184,0,27,208,184,0,17,16,185,0,37,0,4,244,0,184,0,0,69,88,184,0,12,47,27,185,0,12,0,12,62,89,184,0,0,69,88,184,0,9,47,27,185,0,9,0,18,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,0,69,88,184,0,6,47,27,185,0,6,0,6,62,89,186,0,5,0,0,0,12,17,18,57,186,0,10,0,12,0,0,17,18,57,184,0,12,16,185,0,22,0,2,244,184,0,0,16,185,0,32,0,2,244,48,49,1,65,3,0,87,0,11,0,1,93,65,3,0,102,0,20,0,1,93,65,3,0,87,0,20,0,1,93,0,65,5,0,85,0,11,0,101,0,11,0,2,93,65,3,0,86,0,14,0,1,93,65,3,0,103,0,14,0,1,93,65,5,0,89,0,20,0,105,0,20,0,2,93,5,34,46,2,39,7,35,17,51,17,54,51,50,30,2,21,20,14,2,3,34,14,2,21,20,30,2,51,50,62,2,53,52,46,2,1,45,18,42,42,37,12,10,80,90,52,100,49,82,58,32,34,60,81,57,29,53,40,24,23,40,53,30,32,52,36,20,20,37,52,10,10,18,27,17,62,2,238,254,199,63,41,70,93,51,53,93,69,40,1,174,23,45,65,42,43,66,44,22,28,48,64,35,37,64,47,27,0,1,0,33,255,246,1,171,1,244,0,25,1,133,186,0,12,0,5,0,3,43,65,3,0,143,0,5,0,1,93,65,3,0,31,0,5,0,1,93,65,9,0,63,0,5,0,79,0,5,0,95,0,5,0,111,0,5,0,4,93,65,3,0,32,0,5,0,1,93,65,3,0,176,0,12,0,1,93,65,3,0,0,0,12,0,1,113,65,3,0,32,0,12,0,1,113,65,3,0,208,0,12,0,1,93,65,3,0,32,0,12,0,1,93,65,3,0,0,0,12,0,1,93,184,0,5,16,185,0,18,0,4,244,184,0,12,16,184,0,24,208,0,184,0,0,69,88,184,0,10,47,27,185,0,10,0,12,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,10,16,184,0,13,220,184,0,10,16,185,0,15,0,2,244,184,0,0,16,185,0,21,0,2,244,184,0,0,16,184,0,23,220,48,49,1,65,5,0,90,0,2,0,106,0,2,0,2,93,65,5,0,89,0,8,0,105,0,8,0,2,93,65,3,0,104,0,11,0,1,93,65,3,0,104,0,24,0,1,93,65,3,0,104,0,25,0,1,93,0,65,3,0,89,0,2,0,1,93,65,3,0,106,0,2,0,1,93,65,3,0,84,0,8,0,1,93,65,3,0,101,0,8,0,1,93,65,3,0,132,0,11,0,1,93,65,5,0,85,0,11,0,101,0,11,0,2,93,65,3,0,84,0,12,0,1,93,65,3,0,116,0,12,0,1,93,65,3,0,101,0,12,0,1,93,65,3,0,133,0,12,0,1,93,65,7,0,90,0,24,0,106,0,24,0,122,0,24,0,3,93,65,3,0,140,0,24,0,1,93,65,5,0,89,0,25,0,105,0,25,0,2,93,5,34,46,2,53,52,62,2,51,50,23,7,38,35,34,6,21,20,22,51,50,55,23,6,1,21,59,90,63,32,32,61,91,59,98,53,14,62,65,81,80,80,81,66,62,12,55,10,39,69,93,55,56,93,68,37,29,81,30,90,84,84,93,30,72,37,0,0,0,0,2,0,32,255,246,1,239,2,238,0,21,0,41,1,39,186,0,21,0,12,0,3,43,65,3,0,143,0,21,0,1,93,65,7,0,0,0,21,0,16,0,21,0,32,0,21,0,3,113,184,0,21,16,185,0,20,0,4,244,184,0,2,208,65,3,0,31,0,12,0,1,93,65,5,0,63,0,12,0,79,0,12,0,2,93,65,3,0,111,0,12,0,1,93,65,3,0,143,0,12,0,1,93,184,0,12,16,185,0,27,0,4,244,184,0,20,16,184,0,37,208,0,184,0,0,69,88,184,0,21,47,27,185,0,21,0,18,62,89,184,0,0,69,88,184,0,17,47,27,185,0,17,0,12,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,0,69,88,184,0,7,47,27,185,0,7,0,6,62,89,186,0,2,0,7,0,17,17,18,57,186,0,19,0,17,0,7,17,18,57,184,0,17,16,185,0,22,0,2,244,184,0,7,16,185,0,32,0,2,244,48,49,1,65,3,0,88,0,9,0,1,93,65,3,0,105,0,9,0,1,93,65,3,0,104,0,15,0,1,93,0,65,5,0,88,0,9,0,104,0,9,0,2,93,65,3,0,103,0,15,0,1,93,65,3,0,85,0,16,0,1,93,65,3,0,101,0,18,0,1,93,65,3,0,86,0,18,0,1,93,33,35,39,14,3,35,34,46,2,53,52,62,2,51,50,23,17,51,3,34,14,2,21,20,30,2,51,50,62,2,53,52,46,2,1,239,80,10,12,37,41,42,18,47,82,60,34,32,59,82,50,99,51,90,233,32,51,36,19,19,35,51,33,30,55,43,25,26,43,55,62,17,26,19,10,40,69,93,53,51,93,70,41,62,1,56,254,182,26,46,64,39,36,64,47,28,21,43,65,43,42,66,46,24,0,0,2,0,31,255,246,1,226,1,244,0,24,0,30,2,2,186,0,23,0,13,0,3,43,65,3,0,175,0,13,0,1,93,65,3,0,79,0,13,0,1,93,65,3,0,47,0,13,0,1,113,65,3,0,143,0,13,0,1,93,65,3,0,111,0,13,0,1,93,184,0,13,16,185,0,1,0,4,244,65,3,0,80,0,23,0,1,93,65,3,0,144,0,23,0,1,93,65,3,0,208,0,23,0,1,93,65,3,0,16,0,23,0,1,113,65,3,0,48,0,23,0,1,113,65,3,0,240,0,23,0,1,93,65,3,0,176,0,23,0,1,93,65,3,0,112,0,23,0,1,93,65,3,0,16,0,23,0,1,93,65,3,0,80,0,23,0,1,113,186,0,6,0,23,0,13,17,18,57,184,0,6,47,184,0,23,16,185,0,28,0,4,244,186,0,27,0,1,0,28,17,18,57,0,184,0,0,69,88,184,0,18,47,27,185,0,18,0,12,62,89,184,0,0,69,88,184,0,8,47,27,185,0,8,0,6,62,89,186,0,1,0,18,0,8,17,18,57,184,0,1,47,65,5,0,144,0,1,0,160,0,1,0,2,93,65,5,0,16,0,1,0,32,0,1,0,2,93,65,5,0,80,0,1,0,96,0,1,0,2,113,184,0,8,16,185,0,3,0,2,244,184,0,8,16,184,0,5,220,184,0,18,16,185,0,25,0,2,244,184,0,1,16,184,0,27,220,65,3,0,255,0,27,0,1,113,65,15,0,159,0,27,0,175,0,27,0,191,0,27,0,207,0,27,0,223,0,27,0,239,0,27,0,255,0,27,0,7,93,48,49,1,65,3,0,69,0,2,0,1,93,65,3,0,54,0,2,0,1,93,65,3,0,135,0,6,0,1,93,65,3,0,103,0,7,0,1,93,65,3,0,120,0,7,0,1,93,65,3,0,88,0,10,0,1,93,65,3,0,135,0,20,0,1,93,65,3,0,132,0,21,0,1,93,65,3,0,6,0,21,0,1,93,0,65,3,0,54,0,2,0,1,93,65,3,0,71,0,2,0,1,93,65,3,0,137,0,6,0,1,93,65,5,0,105,0,7,0,121,0,7,0,2,93,65,3,0,90,0,7,0,1,93,65,3,0,89,0,10,0,1,93,65,3,0,134,0,20,0,1,93,65,3,0,135,0,21,0,1,93,37,33,22,51,50,55,23,6,35,34,46,2,53,52,62,2,51,50,30,2,21,20,39,34,7,33,52,38,1,222,254,157,16,168,75,66,12,87,77,62,99,68,36,34,62,89,55,47,78,55,31,213,109,29,1,2,60,245,175,29,71,38,40,69,95,55,53,92,67,39,28,54,77,48,28,155,113,54,59,0,0,0,0,1,0,10,0,0,1,61,2,238,0,23,0,236,186,0,13,0,4,0,3,43,65,3,0,143,0,4,0,1,93,65,3,0,47,0,4,0,1,113,184,0,4,16,185,0,1,0,4,244,184,0,4,16,184,0,5,208,184,0,5,47,184,0,4,16,184,0,7,208,65,3,0,47,0,13,0,1,113,184,0,1,16,184,0,22,208,184,0,13,16,184,0,23,208,184,0,23,47,0,184,0,0,69,88,184,0,11,47,27,185,0,11,0,18,62,89,184,0,0,69,88,184,0,22,47,27,185,0,22,0,12,62,89,184,0,0,69,88,184,0,3,47,27,185,0,3,0,6,62,89,184,0,22,16,185,0,1,0,1,244,184,0,4,208,184,0,22,16,184,0,7,208,184,0,11,16,185,0,16,0,2,244,48,49,1,65,9,0,73,0,9,0,89,0,9,0,105,0,9,0,121,0,9,0,4,93,65,9,0,10,0,9,0,26,0,9,0,42,0,9,0,58,0,9,0,4,93,0,65,9,0,5,0,10,0,21,0,10,0,37,0,10,0,53,0,10,0,4,93,1,35,17,35,17,35,55,51,53,52,54,51,50,23,7,38,35,34,14,2,29,1,51,1,61,132,90,85,12,73,59,55,64,38,14,29,31,17,20,11,4,132,1,164,254,92,1,164,70,124,61,75,13,76,9,7,25,48,40,60,0,0,0,3,0,26,255,6,1,245,1,244,0,53,0,65,0,78,3,224,186,0,30,0,14,0,3,43,65,3,0,95,0,14,0,1,93,65,3,0,32,0,14,0,1,93,65,3,0,160,0,14,0,1,93,184,0,14,16,184,0,5,208,184,0,5,47,184,0,14,16,184,0,9,208,184,0,9,47,65,3,0,0,0,30,0,1,93,65,3,0,96,0,30,0,1,93,65,3,0,160,0,30,0,1,93,65,3,0,128,0,30,0,1,93,65,3,0,32,0,30,0,1,93,65,3,0,192,0,30,0,1,93,65,3,0,16,0,30,0,1,113,186,0,12,0,14,0,30,17,18,57,186,0,21,0,14,0,30,17,18,57,184,0,30,16,184,0,24,208,184,0,24,47,186,0,28,0,30,0,14,17,18,57,186,0,37,0,30,0,14,17,18,57,184,0,9,16,185,0,39,0,4,244,184,0,30,16,184,0,49,208,184,0,49,47,184,0,14,16,185,0,57,0,4,244,184,0,30,16,185,0,63,0,4,244,184,0,5,16,185,0,71,0,4,244,184,0,49,16,185,0,77,0,4,244,65,3,0,79,0,80,0,1,93,0,184,0,0,69,88,184,0,19,47,27,185,0,19,0,12,62,89,184,0,0,69,88,184,0,24,47,27,185,0,24,0,12,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,8,62,89,65,3,0,0,0,0,0,1,93,186,0,44,0,19,0,0,17,18,57,65,5,0,58,0,44,0,74,0,44,0,2,93,65,3,0,101,0,44,0,1,93,184,0,44,16,185,0,66,0,1,244,186,0,7,0,44,0,66,17,18,57,184,0,19,16,184,0,35,220,65,3,0,111,0,35,0,1,93,65,5,0,63,0,35,0,79,0,35,0,2,93,65,3,0,143,0,35,0,1,93,65,3,0,15,0,35,0,1,113,186,0,12,0,35,0,19,17,18,57,186,0,21,0,19,0,35,17,18,57,184,0,24,16,185,0,25,0,1,244,186,0,28,0,19,0,35,17,18,57,186,0,37,0,35,0,19,17,18,57,184,0,19,16,185,0,54,0,1,244,184,0,35,16,185,0,60,0,1,244,186,0,68,0,66,0,44,17,18,57,184,0,0,16,185,0,74,0,1,244,48,49,1,65,3,0,9,0,3,0,1,93,65,5,0,122,0,8,0,138,0,8,0,2,93,65,3,0,121,0,12,0,1,93,65,3,0,120,0,13,0,1,93,65,3,0,138,0,13,0,1,93,65,3,0,9,0,16,0,1,93,65,3,0,123,0,16,0,1,93,65,3,0,140,0,16,0,1,93,65,3,0,136,0,17,0,1,93,65,3,0,121,0,17,0,1,93,65,3,0,117,0,21,0,1,93,65,3,0,134,0,21,0,1,93,65,3,0,117,0,28,0,1,93,65,3,0,134,0,28,0,1,93,65,3,0,117,0,32,0,1,93,65,3,0,134,0,32,0,1,93,65,3,0,134,0,33,0,1,93,65,3,0,7,0,33,0,1,93,65,3,0,119,0,33,0,1,93,65,3,0,134,0,47,0,1,93,65,5,0,23,0,47,0,39,0,47,0,2,93,65,3,0,119,0,47,0,1,93,65,5,0,118,0,51,0,134,0,51,0,2,93,65,3,0,6,0,52,0,1,93,65,3,0,135,0,52,0,1,93,65,3,0,119,0,69,0,1,93,0,65,3,0,8,0,3,0,1,93,65,3,0,120,0,8,0,1,93,65,3,0,120,0,12,0,1,93,65,3,0,120,0,13,0,1,93,65,3,0,6,0,16,0,1,93,65,3,0,119,0,16,0,1,93,65,3,0,133,0,17,0,1,93,65,3,0,119,0,17,0,1,93,65,3,0,134,0,21,0,1,93,65,3,0,119,0,21,0,1,93,65,5,0,118,0,28,0,134,0,28,0,2,93,65,3,0,137,0,32,0,1,93,65,3,0,122,0,32,0,1,93,65,3,0,9,0,33,0,1,93,65,3,0,121,0,33,0,1,93,65,3,0,138,0,33,0,1,93,65,3,0,102,0,42,0,1,93,65,3,0,134,0,47,0,1,93,65,5,0,23,0,47,0,39,0,47,0,2,93,65,3,0,119,0,47,0,1,93,65,5,0,122,0,51,0,138,0,51,0,2,93,65,3,0,9,0,52,0,1,93,65,3,0,121,0,52,0,1,93,65,3,0,138,0,52,0,1,93,65,3,0,121,0,69,0,1,93,65,3,0,138,0,69,0,1,93,23,34,46,2,53,52,55,38,53,52,54,55,38,53,52,62,2,51,50,23,54,59,1,7,35,34,7,22,21,20,14,2,35,34,39,6,21,20,30,2,23,30,3,23,20,14,2,3,34,6,21,20,22,51,50,54,53,52,38,3,34,39,14,1,21,20,22,51,50,54,53,52,255,58,86,57,28,87,50,27,31,85,27,51,75,47,66,59,52,67,8,11,23,31,27,45,28,51,73,46,39,31,24,11,33,59,49,33,70,57,38,2,34,63,92,75,55,60,65,52,54,62,64,12,17,72,34,44,78,69,72,79,250,24,41,54,29,78,32,24,38,17,41,15,61,99,42,72,53,30,36,28,60,7,54,63,39,70,54,32,9,14,16,9,13,10,11,9,6,18,30,47,35,31,56,42,25,2,166,67,55,57,67,72,55,57,62,254,58,12,10,50,26,35,45,47,31,52,0,1,0,60,0,0,1,230,2,238,0,16,1,44,186,0,0,0,9,0,3,43,65,3,0,223,0,0,0,1,93,65,3,0,32,0,0,0,1,93,65,3,0,64,0,0,0,1,93,184,0,0,16,185,0,1,0,4,244,65,3,0,223,0,9,0,1,93,65,3,0,15,0,9,0,1,113,65,3,0,47,0,9,0,1,113,65,3,0,32,0,9,0,1,93,184,0,9,16,185,0,8,0,4,244,184,0,12,208,65,3,0,128,0,17,0,1,93,65,3,0,239,0,18,0,1,93,65,3,0,31,0,18,0,1,93,65,3,0,207,0,18,0,1,93,65,3,0,175,0,18,0,1,93,0,184,0,0,69,88,184,0,11,47,27,185,0,11,0,18,62,89,184,0,0,69,88,184,0,14,47,27,185,0,14,0,12,62,89,184,0,0,69,88,184,0,8,47,27,185,0,8,0,6,62,89,184,0,1,208,184,0,14,16,185,0,5,0,2,244,65,3,0,6,0,9,0,1,113,186,0,12,0,14,0,8,17,18,57,48,49,1,65,7,0,118,0,15,0,134,0,15,0,150,0,15,0,3,93,65,3,0,7,0,15,0,1,93,0,65,3,0,150,0,4,0,1,93,65,3,0,118,0,15,0,1,93,65,3,0,150,0,15,0,1,93,65,3,0,7,0,15,0,1,93,65,3,0,135,0,15,0,1,93,33,35,17,52,38,35,34,7,17,35,17,51,17,54,51,50,21,1,230,90,52,65,88,40,91,91,49,93,193,1,6,87,71,64,254,156,2,238,254,199,63,238,0,2,0,61,0,0,0,151,2,188,0,3,0,7,0,165,187,0,7,0,4,0,6,0,4,43,65,3,0,143,0,7,0,1,93,65,3,0,223,0,7,0,1,93,65,3,0,63,0,7,0,1,113,65,3,0,32,0,7,0,1,93,184,0,7,16,184,0,0,208,65,3,0,223,0,6,0,1,93,65,3,0,63,0,6,0,1,113,65,3,0,143,0,6,0,1,93,65,3,0,32,0,6,0,1,93,184,0,6,16,184,0,1,208,0,184,0,1,47,184,0,0,69,88,184,0,6,47,27,185,0,6,0,12,62,89,184,0,0,69,88,184,0,5,47,27,185,0,5,0,6,62,89,65,3,0,32,0,1,0,1,93,65,3,0,64,0,1,0,1,93,184,0,1,16,184,0,2,220,48,49,19,35,53,51,17,35,17,51,151,90,90,90,90,2,88,100,253,68,1,234,0,0,0,0,2,255,244,255,14,0,151,2,188,0,14,0,18,0,209,187,0,9,0,4,0,8,0,4,43,65,3,0,63,0,8,0,1,113,65,3,0,143,0,8,0,1,93,65,3,0,223,0,8,0,1,93,65,3,0,32,0,8,0,1,93,184,0,8,16,184,0,2,208,184,0,2,47,65,3,0,143,0,9,0,1,93,65,3,0,223,0,9,0,1,93,65,3,0,63,0,9,0,1,113,65,3,0,32,0,9,0,1,93,184,0,9,16,184,0,15,208,184,0,8,16,184,0,16,208,0,184,0,16,47,184,0,0,69,88,184,0,8,47,27,185,0,8,0,12,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,8,62,89,185,0,2,0,1,244,65,3,0,64,0,16,0,1,93,65,3,0,32,0,16,0,1,93,184,0,16,16,184,0,17,220,48,49,1,65,11,0,5,0,12,0,21,0,12,0,37,0,12,0,53,0,12,0,69,0,12,0,5,93,23,7,39,62,3,53,17,51,17,20,14,2,19,35,53,51,28,30,10,22,28,16,7,90,20,33,45,98,90,90,237,5,69,2,10,21,37,30,2,51,253,171,32,45,31,18,3,65,100,0,0,0,1,0,60,0,0,1,189,2,238,0,10,1,129,186,0,8,0,1,0,3,43,65,3,0,15,0,1,0,1,113,65,3,0,143,0,1,0,1,93,65,3,0,0,0,1,0,1,93,65,3,0,32,0,1,0,1,93,184,0,1,16,185,0,0,0,4,244,184,0,4,208,65,3,0,51,0,8,0,1,93,65,3,0,37,0,8,0,1,93,65,3,0,73,0,8,0,1,93,65,3,0,138,0,8,0,1,93,65,3,0,90,0,8,0,1,93,65,3,0,121,0,8,0,1,93,65,3,0,19,0,8,0,1,93,65,3,0,99,0,8,0,1,93,65,3,0,0,0,8,0,1,93,184,0,8,16,184,0,9,208,65,5,0,73,0,9,0,89,0,9,0,2,93,65,3,0,106,0,9,0,1,93,65,5,0,123,0,9,0,139,0,9,0,2,93,65,3,0,41,0,9,0,1,113,65,7,0,166,0,9,0,182,0,9,0,198,0,9,0,3,93,65,3,0,149,0,9,0,1,93,184,0,5,208,65,3,0,134,0,5,0,1,93,184,0,8,16,184,0,6,208,65,3,0,134,0,6,0,1,93,184,0,4,16,184,0,7,208,65,3,0,38,0,7,0,1,113,65,7,0,101,0,7,0,117,0,7,0,133,0,7,0,3,93,65,3,0,63,0,12,0,1,93,65,3,0,31,0,12,0,1,93,0,184,0,0,69,88,184,0,3,47,27,185,0,3,0,18,62,89,184,0,0,69,88,184,0,5,47,27,185,0,5,0,12,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,9,208,186,0,7,0,5,0,9,17,18,57,25,184,0,7,47,24,184,0,4,208,184,0,7,16,184,0,10,208,48,49,51,35,17,51,17,55,51,7,19,35,39,150,90,90,180,110,202,207,110,185,2,238,254,31,221,226,254,248,249,0,1,0,60,255,246,0,229,2,238,0,12,0,111,186,0,0,0,5,0,3,43,65,3,0,255,0,0,0,1,93,65,3,0,32,0,0,0,1,93,65,3,0,47,0,5,0,1,113,65,3,0,255,0,5,0,1,93,65,3,0,32,0,5,0,1,93,184,0,5,16,185,0,8,0,4,244,65,3,0,16,0,13,0,1,93,65,3,0,175,0,14,0,1,93,0,184,0,7,47,184,0,0,69,88,184,0,2,47,27,185,0,2,0,6,62,89,185,0,0,0,1,244,48,49,55,7,35,34,38,53,17,51,17,20,30,2,229,13,29,66,61,90,5,16,31,62,72,67,51,2,130,253,178,31,39,21,7,0,0,0,1,0,61,0,0,3,53,1,244,0,29,2,14,186,0,9,0,17,0,3,43,65,3,0,0,0,9,0,1,93,65,3,0,255,0,9,0,1,93,65,3,0,32,0,9,0,1,93,65,3,0,64,0,9,0,1,113,184,0,9,16,184,0,1,220,65,3,0,64,0,1,0,1,113,185,0,0,0,4,244,184,0,9,16,185,0,8,0,4,244,65,3,0,255,0,17,0,1,93,65,3,0,32,0,17,0,1,93,65,3,0,0,0,17,0,1,93,184,0,17,16,185,0,16,0,4,244,186,0,20,0,16,0,17,17,18,57,186,0,25,0,8,0,9,17,18,57,65,3,0,95,0,31,0,1,93,0,184,0,0,69,88,184,0,23,47,27,185,0,23,0,12,62,89,184,0,0,69,88,184,0,27,47,27,185,0,27,0,12,62,89,184,0,0,69,88,184,0,19,47,27,185,0,19,0,12,62,89,184,0,0,69,88,184,0,16,47,27,185,0,16,0,6,62,89,184,0,9,208,184,0,1,208,184,0,27,16,185,0,5,0,2,244,184,0,23,16,185,0,13,0,2,244,186,0,20,0,23,0,16,17,18,57,186,0,25,0,27,0,9,17,18,57,48,49,1,65,3,0,168,0,11,0,1,93,65,3,0,154,0,12,0,1,93,65,3,0,123,0,12,0,1,93,65,3,0,87,0,14,0,1,93,65,5,0,88,0,21,0,104,0,21,0,2,93,65,5,0,120,0,25,0,136,0,25,0,2,93,65,3,0,88,0,26,0,1,93,65,3,0,165,0,28,0,1,93,65,3,0,134,0,28,0,1,93,65,5,0,7,0,28,0,23,0,28,0,2,93,65,3,0,151,0,28,0,1,93,0,65,3,0,171,0,11,0,1,93,65,3,0,119,0,12,0,1,93,65,7,0,86,0,14,0,102,0,14,0,118,0,14,0,3,93,65,3,0,85,0,21,0,1,93,65,3,0,102,0,21,0,1,93,65,3,0,119,0,21,0,1,93,65,3,0,164,0,25,0,1,93,65,5,0,133,0,25,0,149,0,25,0,2,93,65,3,0,118,0,25,0,1,93,65,3,0,86,0,26,0,1,93,65,3,0,103,0,26,0,1,93,65,3,0,133,0,28,0,1,93,65,3,0,6,0,28,0,1,93,65,5,0,150,0,28,0,166,0,28,0,2,93,65,3,0,23,0,28,0,1,93,33,35,17,52,38,35,34,21,17,35,17,52,38,35,34,7,17,35,17,51,23,62,1,51,50,23,54,51,50,21,3,53,90,54,61,130,90,59,56,94,36,90,70,10,40,66,41,112,54,51,128,188,1,32,69,63,136,254,228,1,14,84,66,64,254,156,1,234,52,36,26,98,98,211,0,0,0,1,0,61,0,0,1,247,1,244,0,16,1,95,186,0,0,0,9,0,3,43,65,3,0,96,0,0,0,1,93,65,3,0,32,0,0,0,1,113,65,3,0,0,0,0,0,1,93,65,3,0,64,0,0,0,1,113,65,3,0,0,0,0,0,1,113,65,3,0,64,0,0,0,1,93,65,3,0,32,0,0,0,1,93,184,0,0,16,185,0,1,0,4,244,65,3,0,143,0,9,0,1,93,65,3,0,255,0,9,0,1,93,65,3,0,223,0,9,0,1,93,65,3,0,0,0,9,0,1,93,65,3,0,32,0,9,0,1,93,184,0,9,16,185,0,8,0,4,244,184,0,12,208,0,184,0,0,69,88,184,0,14,47,27,185,0,14,0,12,62,89,184,0,0,69,88,184,0,11,47,27,185,0,11,0,12,62,89,184,0,0,69,88,184,0,8,47,27,185,0,8,0,6,62,89,184,0,1,208,184,0,14,16,185,0,5,0,2,244,186,0,7,0,8,0,5,17,18,57,186,0,12,0,14,0,8,17,18,57,48,49,1,65,3,0,117,0,15,0,1,93,65,5,0,6,0,15,0,22,0,15,0,2,93,65,3,0,150,0,15,0,1,93,65,3,0,135,0,15,0,1,93,65,3,0,167,0,15,0,1,93,0,65,3,0,91,0,3,0,1,113,65,3,0,84,0,6,0,1,93,65,3,0,84,0,13,0,1,93,65,3,0,22,0,15,0,1,93,65,3,0,134,0,15,0,1,93,65,3,0,7,0,15,0,1,93,65,3,0,119,0,15,0,1,93,65,3,0,151,0,15,0,1,93,33,35,17,52,38,35,34,7,17,35,17,51,23,54,51,50,21,1,247,90,59,69,98,36,90,70,10,70,92,200,1,14,79,71,64,254,156,1,234,52,62,230,0,0,2,0,32,255,246,2,6,1,244,0,18,0,31,1,107,186,0,17,0,7,0,3,43,65,3,0,31,0,7,0,1,93,65,3,0,95,0,7,0,1,93,65,3,0,159,0,7,0,1,93,65,3,0,47,0,7,0,1,113,65,3,0,127,0,7,0,1,93,65,3,0,63,0,7,0,1,93,65,3,0,32,0,7,0,1,93,65,3,0,160,0,7,0,1,93,65,5,0,160,0,17,0,176,0,17,0,2,93,65,3,0,240,0,17,0,1,93,65,3,0,48,0,17,0,1,113,65,3,0,32,0,17,0,1,93,65,3,0,16,0,17,0,1,113,65,3,0,208,0,17,0,1,93,65,3,0,96,0,17,0,1,93,65,3,0,64,0,17,0,1,93,184,0,7,16,185,0,24,0,4,244,184,0,17,16,185,0,30,0,4,244,0,184,0,0,69,88,184,0,12,47,27,185,0,12,0,12,62,89,184,0,0,69,88,184,0,2,47,27,185,0,2,0,6,62,89,184,0,12,16,185,0,21,0,2,244,184,0,2,16,185,0,27,0,2,244,48,49,1,65,3,0,101,0,0,0,1,93,65,3,0,86,0,0,0,1,93,65,5,0,88,0,4,0,104,0,4,0,2,93,65,3,0,89,0,5,0,1,93,65,5,0,89,0,10,0,105,0,10,0,2,93,65,5,0,86,0,14,0,102,0,14,0,2,93,0,65,5,0,89,0,0,0,105,0,0,0,2,93,65,3,0,88,0,4,0,1,93,65,3,0,105,0,4,0,1,93,65,5,0,87,0,10,0,103,0,10,0,2,93,65,3,0,86,0,14,0,1,93,65,3,0,103,0,14,0,1,93,37,6,35,34,46,2,53,52,62,2,51,50,30,2,21,20,39,38,35,34,6,21,20,22,51,50,54,53,52,1,196,65,112,57,90,63,33,34,63,90,56,56,90,63,34,132,39,72,72,79,79,72,73,78,62,72,39,68,94,54,55,93,68,39,39,69,93,54,110,239,46,91,84,84,91,94,81,83,0,0,0,0,2,0,61,255,14,2,12,1,244,0,22,0,42,1,129,186,0,18,0,7,0,3,43,65,3,0,15,0,7,0,1,113,65,3,0,31,0,7,0,1,93,65,3,0,47,0,7,0,1,113,65,3,0,0,0,7,0,1,93,65,3,0,32,0,7,0,1,93,184,0,7,16,185,0,6,0,4,244,184,0,10,208,65,3,0,0,0,18,0,1,93,65,7,0,32,0,18,0,48,0,18,0,64,0,18,0,3,93,65,3,0,96,0,18,0,1,93,65,3,0,16,0,18,0,1,113,184,0,6,16,184,0,28,208,184,0,18,16,185,0,38,0,4,244,0,184,0,0,69,88,184,0,9,47,27,185,0,9,0,12,62,89,184,0,0,69,88,184,0,13,47,27,185,0,13,0,12,62,89,184,0,0,69,88,184,0,6,47,27,185,0,6,0,8,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,186,0,5,0,0,0,13,17,18,57,65,3,0,34,0,7,0,1,113,186,0,10,0,13,0,0,17,18,57,184,0,13,16,185,0,23,0,2,244,184,0,0,16,185,0,33,0,2,244,48,49,1,65,3,0,104,0,11,0,1,93,65,3,0,91,0,11,0,1,93,65,3,0,86,0,15,0,1,93,65,3,0,103,0,15,0,1,93,65,5,0,86,0,20,0,102,0,20,0,2,93,65,3,0,102,0,21,0,1,93,65,3,0,87,0,21,0,1,93,0,65,3,0,85,0,11,0,1,93,65,3,0,103,0,11,0,1,93,65,5,0,87,0,15,0,103,0,15,0,2,93,65,3,0,104,0,20,0,1,93,65,3,0,89,0,20,0,1,93,65,3,0,89,0,21,0,1,93,65,3,0,106,0,21,0,1,93,5,34,46,2,39,17,35,17,51,23,62,1,51,50,30,2,21,20,14,2,3,34,14,2,21,20,30,2,51,50,62,2,53,52,46,2,1,49,18,43,42,38,13,90,70,10,34,74,57,50,80,57,31,29,55,82,63,29,54,41,25,24,41,54,30,31,51,36,19,19,36,51,10,10,18,27,17,254,208,2,220,70,41,39,41,71,92,51,55,94,68,38,1,174,24,45,65,41,44,65,44,22,27,46,64,38,39,64,46,26,0,0,2,0,33,255,14,1,240,1,244,0,22,0,42,1,65,186,0,16,0,5,0,3,43,65,3,0,31,0,5,0,1,93,65,3,0,111,0,5,0,1,93,65,5,0,63,0,5,0,79,0,5,0,2,93,65,7,0,0,0,16,0,16,0,16,0,32,0,16,0,3,113,184,0,16,16,185,0,17,0,4,244,184,0,13,208,184,0,5,16,185,0,28,0,4,244,184,0,17,16,184,0,38,208,0,184,0,0,69,88,184,0,10,47,27,185,0,10,0,12,62,89,184,0,0,69,88,184,0,15,47,27,185,0,15,0,12,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,0,69,88,184,0,16,47,27,185,0,16,0,8,62,89,65,3,0,69,0,5,0,1,93,186,0,13,0,10,0,0,17,18,57,65,3,0,47,0,16,0,1,113,186,0,18,0,0,0,10,17,18,57,184,0,10,16,185,0,23,0,2,244,184,0,0,16,185,0,33,0,2,244,48,49,1,65,3,0,90,0,2,0,1,93,65,3,0,107,0,2,0,1,93,65,3,0,90,0,3,0,1,93,65,5,0,88,0,8,0,104,0,8,0,2,93,65,3,0,85,0,12,0,1,93,65,3,0,103,0,12,0,1,93,0,65,5,0,89,0,2,0,105,0,2,0,2,93,65,5,0,86,0,8,0,102,0,8,0,2,93,65,3,0,102,0,12,0,1,93,65,3,0,87,0,12,0,1,93,23,34,46,2,53,52,62,2,51,50,22,23,55,51,17,35,17,14,3,3,34,14,2,21,20,30,2,51,50,62,2,53,52,46,2,252,53,82,56,28,31,57,80,50,57,74,34,10,70,90,12,38,42,43,9,32,50,36,19,19,36,50,32,30,55,40,24,25,41,54,10,38,68,94,55,52,92,70,41,39,41,70,253,36,1,48,16,27,19,10,1,174,26,46,64,39,38,64,46,27,23,44,66,42,41,65,45,24,0,0,0,0,1,0,61,0,0,1,64,1,252,0,15,0,166,186,0,0,0,9,0,3,43,65,3,0,0,0,0,0,1,93,65,3,0,32,0,0,0,1,93,65,3,0,31,0,9,0,1,93,65,3,0,0,0,9,0,1,93,65,3,0,32,0,9,0,1,93,184,0,9,16,185,0,8,0,4,244,184,0,12,208,0,184,0,0,69,88,184,0,10,47,27,185,0,10,0,12,62,89,184,0,0,69,88,184,0,9,47,27,185,0,9,0,6,62,89,184,0,10,16,184,0,0,208,184,0,0,47,184,0,1,220,65,5,0,127,0,1,0,143,0,1,0,2,93,65,5,0,31,0,1,0,47,0,1,0,2,113,186,0,7,0,9,0,1,17,18,57,186,0,12,0,0,0,9,17,18,57,48,49,1,7,35,34,14,2,7,17,35,17,51,23,62,1,51,1,64,20,31,15,34,31,26,6,96,74,11,46,75,45,1,252,99,11,18,22,12,254,166,1,234,81,52,47,0,1,0,32,255,246,1,131,1,244,0,39,2,81,186,0,35,0,15,0,3,43,65,3,0,127,0,15,0,1,93,184,0,15,16,184,0,2,208,184,0,2,47,65,3,0,208,0,35,0,1,93,65,3,0,0,0,35,0,1,113,65,3,0,160,0,35,0,1,93,65,3,0,128,0,35,0,1,93,184,0,35,16,185,0,8,0,4,244,186,0,20,0,35,0,15,17,18,57,184,0,20,47,184,0,15,16,185,0,25,0,4,244,65,3,0,31,0,41,0,1,93,65,3,0,79,0,41,0,1,93,0,184,0,0,69,88,184,0,18,47,27,185,0,18,0,12,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,3,220,65,5,0,48,0,3,0,64,0,3,0,2,93,184,0,0,16,185,0,6,0,2,244,186,0,10,0,0,0,18,17,18,57,65,3,0,121,0,10,0,1,93,65,3,0,10,0,10,0,1,93,65,3,0,138,0,10,0,1,93,65,5,0,166,0,10,0,182,0,10,0,2,93,65,3,0,149,0,10,0,1,93,184,0,18,16,184,0,21,220,65,5,0,176,0,21,0,192,0,21,0,2,93,184,0,18,16,185,0,23,0,1,244,186,0,29,0,18,0,0,17,18,57,65,3,0,10,0,29,0,1,93,48,49,1,65,9,0,87,0,1,0,103,0,1,0,119,0,1,0,135,0,1,0,4,93,65,3,0,57,0,13,0,1,93,65,3,0,75,0,13,0,1,93,65,3,0,25,0,16,0,1,93,65,3,0,42,0,16,0,1,93,65,3,0,11,0,16,0,1,93,65,5,0,54,0,33,0,70,0,33,0,2,93,65,5,0,118,0,33,0,134,0,33,0,2,93,65,3,0,37,0,38,0,1,93,65,3,0,22,0,38,0,1,93,65,3,0,7,0,38,0,1,93,0,65,9,0,89,0,1,0,105,0,1,0,121,0,1,0,137,0,1,0,4,93,65,9,0,89,0,2,0,105,0,2,0,121,0,2,0,137,0,2,0,4,93,65,3,0,72,0,13,0,1,93,65,3,0,57,0,13,0,1,93,65,3,0,37,0,16,0,1,93,65,3,0,6,0,16,0,1,93,65,3,0,23,0,16,0,1,93,65,9,0,84,0,19,0,100,0,19,0,116,0,19,0,132,0,19,0,4,93,65,9,0,85,0,20,0,101,0,20,0,117,0,20,0,133,0,20,0,4,93,65,5,0,53,0,33,0,69,0,33,0,2,93,65,3,0,134,0,33,0,1,93,65,3,0,119,0,33,0,1,93,65,3,0,9,0,38,0,1,93,65,5,0,26,0,38,0,42,0,38,0,2,93,23,34,39,55,30,1,51,50,53,52,39,46,3,39,52,54,51,50,23,7,38,35,34,21,20,30,2,23,30,3,21,20,14,2,200,107,61,11,20,83,50,98,98,30,53,42,27,2,90,94,67,66,11,52,68,95,10,26,44,34,21,49,42,28,16,42,73,10,43,87,18,32,61,55,26,7,19,31,48,36,63,84,32,82,43,66,16,22,17,16,10,6,21,34,50,35,24,52,42,28,0,0,1,0,18,255,246,1,65,2,108,0,21,0,215,186,0,14,0,6,0,3,43,65,3,0,95,0,14,0,1,93,65,3,0,0,0,14,0,1,93,184,0,14,16,184,0,0,208,184,0,0,47,65,3,0,95,0,6,0,1,93,65,3,0,0,0,6,0,1,93,184,0,6,16,184,0,7,208,184,0,7,47,184,0,6,16,184,0,9,208,184,0,9,47,184,0,6,16,185,0,15,0,4,244,184,0,12,208,184,0,12,47,0,184,0,0,69,88,184,0,12,47,27,185,0,12,0,12,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,185,0,0,0,1,244,184,0,12,16,185,0,15,0,1,244,184,0,6,208,184,0,12,16,184,0,9,208,184,0,12,16,184,0,11,220,48,49,1,65,9,0,57,0,4,0,73,0,4,0,89,0,4,0,105,0,4,0,4,93,0,65,9,0,57,0,3,0,73,0,3,0,89,0,3,0,105,0,3,0,4,93,37,7,35,34,38,53,17,35,55,51,53,55,21,51,21,35,17,20,30,2,51,1,62,7,81,65,63,84,8,76,90,129,129,4,19,42,38,62,72,68,49,1,57,70,121,9,130,70,254,254,35,40,20,5,0,0,1,0,56,255,246,1,207,1,234,0,15,1,48,186,0,15,0,7,0,3,43,65,3,0,32,0,15,0,1,113,65,3,0,255,0,15,0,1,93,65,3,0,223,0,15,0,1,93,65,3,0,80,0,15,0,1,93,65,3,0,112,0,15,0,1,93,184,0,15,16,185,0,14,0,4,244,184,0,2,208,65,3,0,31,0,7,0,1,113,65,3,0,223,0,7,0,1,93,65,3,0,143,0,7,0,1,93,65,3,0,255,0,7,0,1,93,65,3,0,32,0,7,0,1,93,184,0,7,16,185,0,8,0,4,244,65,3,0,31,0,17,0,1,93,65,3,0,63,0,17,0,1,93,0,184,0,0,69,88,184,0,8,47,27,185,0,8,0,12,62,89,184,0,0,69,88,184,0,4,47,27,185,0,4,0,6,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,184,0,8,16,184,0,14,208,186,0,2,0,4,0,14,17,18,57,184,0,4,16,185,0,11,0,2,244,48,49,1,65,5,0,168,0,5,0,184,0,5,0,2,93,65,3,0,102,0,10,0,1,93,65,3,0,134,0,10,0,1,93,65,3,0,119,0,10,0,1,93,0,65,3,0,185,0,5,0,1,93,65,3,0,170,0,5,0,1,93,65,5,0,102,0,10,0,118,0,10,0,2,93,65,3,0,135,0,10,0,1,93,33,35,39,6,35,34,53,17,51,17,20,51,50,55,17,51,1,207,80,10,46,90,181,90,114,78,35,90,54,64,215,1,29,254,252,160,56,1,108,0,0,0,0,1,0,9,0,0,1,227,1,234,0,6,1,25,187,0,1,0,4,0,2,0,4,43,65,3,0,64,0,1,0,1,93,65,3,0,160,0,1,0,1,93,65,3,0,0,0,1,0,1,93,65,3,0,224,0,1,0,1,93,184,0,1,16,184,0,0,208,65,3,0,89,0,0,0,1,93,65,3,0,151,0,0,0,1,93,65,3,0,5,0,0,0,1,93,65,3,0,160,0,2,0,1,93,65,3,0,224,0,2,0,1,93,65,3,0,64,0,2,0,1,93,65,3,0,0,0,2,0,1,93,184,0,2,16,184,0,3,208,65,3,0,10,0,3,0,1,93,65,3,0,152,0,3,0,1,93,65,3,0,86,0,3,0,1,93,185,0,4,0,4,244,65,3,0,184,0,4,0,1,93,186,0,5,0,2,0,1,17,18,57,184,0,0,16,185,0,6,0,4,244,65,3,0,183,0,6,0,1,93,65,3,0,47,0,8,0,1,93,0,184,0,0,69,88,184,0,4,47,27,185,0,4,0,12,62,89,184,0,0,69,88,184,0,2,47,27,185,0,2,0,6,62,89,184,0,5,208,184,0,4,16,184,0,6,208,48,49,65,3,0,132,0,5,0,1,93,65,3,0,117,0,5,0,1,93,65,3,0,12,0,5,0,1,93,1,3,35,3,51,27,1,1,227,186,101,187,100,137,136,1,234,254,22,1,234,254,121,1,135,0,1,0,12,0,0,2,202,1,234,0,12,1,215,187,0,10,0,4,0,9,0,4,43,65,3,0,144,0,10,0,1,93,184,0,10,16,184,0,1,220,184,0,0,208,65,3,0,134,0,0,0,1,93,65,3,0,38,0,0,0,1,93,184,0,1,16,185,0,2,0,4,244,65,3,0,144,0,9,0,1,93,186,0,3,0,9,0,10,17,18,57,184,0,9,16,184,0,5,220,185,0,4,0,4,244,184,0,5,16,184,0,6,208,65,3,0,41,0,6,0,1,93,65,3,0,137,0,6,0,1,93,185,0,7,0,4,244,186,0,8,0,5,0,4,17,18,57,186,0,11,0,2,0,1,17,18,57,184,0,0,16,185,0,12,0,4,244,65,3,0,15,0,13,0,1,93,0,184,0,0,69,88,184,0,7,47,27,185,0,7,0,12,62,89,184,0,0,69,88,184,0,4,47,27,185,0,4,0,6,62,89,184,0,2,208,184,0,2,47,184,0,7,16,184,0,9,208,184,0,9,47,184,0,3,208,184,0,4,16,184,0,8,208,184,0,11,208,184,0,7,16,184,0,12,208,48,49,1,65,3,0,56,0,1,0,1,93,65,3,0,72,0,2,0,1,93,65,5,0,25,0,2,0,41,0,2,0,2,93,65,5,0,121,0,2,0,137,0,2,0,2,93,65,5,0,22,0,4,0,38,0,4,0,2,93,65,5,0,118,0,4,0,134,0,4,0,2,93,65,3,0,71,0,4,0,1,93,65,3,0,72,0,9,0,1,93,65,5,0,121,0,9,0,137,0,9,0,2,93,65,5,0,118,0,10,0,134,0,10,0,2,93,0,65,3,0,3,0,3,0,1,93,65,3,0,54,0,3,0,1,93,65,3,0,71,0,3,0,1,93,65,3,0,41,0,3,0,1,113,65,3,0,89,0,8,0,1,93,65,3,0,74,0,8,0,1,93,65,3,0,27,0,8,0,1,93,65,3,0,12,0,8,0,1,93,65,3,0,44,0,8,0,1,93,65,5,0,73,0,11,0,89,0,11,0,2,93,65,7,0,12,0,11,0,28,0,11,0,44,0,11,0,3,93,1,3,35,11,1,35,3,51,27,1,51,27,1,2,202,148,101,102,103,101,147,106,94,104,93,105,94,1,234,254,22,1,106,254,150,1,234,254,121,1,120,254,136,1,135,0,0,0,1,0,11,0,0,1,207,1,234,0,11,1,236,186,0,11,0,5,0,3,43,65,3,0,160,0,11,0,1,93,65,3,0,0,0,11,0,1,93,65,3,0,208,0,11,0,1,93,65,5,0,96,0,11,0,112,0,11,0,2,93,65,3,0,64,0,11,0,1,93,184,0,11,16,184,0,0,208,65,3,0,22,0,0,0,1,93,65,3,0,200,0,0,0,1,93,65,3,0,137,0,0,0,1,93,65,3,0,122,0,0,0,1,93,65,3,0,41,0,0,0,1,93,65,3,0,103,0,0,0,1,93,65,3,0,245,0,0,0,1,93,65,3,0,5,0,0,0,1,93,185,0,1,0,4,244,65,3,0,64,0,5,0,1,93,65,3,0,143,0,5,0,1,93,65,3,0,95,0,5,0,1,93,65,3,0,111,0,5,0,1,113,65,3,0,160,0,5,0,1,93,65,3,0,0,0,5,0,1,93,186,0,2,0,5,0,11,17,18,57,184,0,5,16,184,0,4,208,65,3,0,25,0,4,0,1,93,65,3,0,10,0,4,0,1,93,65,3,0,250,0,4,0,1,93,65,3,0,104,0,4,0,1,93,65,3,0,118,0,4,0,1,93,185,0,3,0,4,244,65,3,0,184,0,3,0,1,93,184,0,4,16,184,0,6,208,65,3,0,39,0,6,0,1,93,185,0,7,0,4,244,186,0,8,0,5,0,11,17,18,57,184,0,0,16,184,0,10,208,185,0,9,0,4,244,65,3,0,47,0,13,0,1,93,0,184,0,0,69,88,184,0,7,47,27,185,0,7,0,12,62,89,184,0,0,69,88,184,0,3,47,27,185,0,3,0,6,62,89,184,0,1,208,186,0,2,0,3,0,7,17,18,57,65,3,0,214,0,2,0,1,93,65,3,0,165,0,2,0,1,93,186,0,8,0,7,0,3,17,18,57,65,3,0,170,0,8,0,1,93,65,3,0,217,0,8,0,1,93,186,0,5,0,8,0,2,17,18,57,184,0,7,16,184,0,9,208,186,0,11,0,2,0,8,17,18,57,48,49,65,3,0,149,0,2,0,1,93,65,3,0,6,0,2,0,1,93,65,3,0,9,0,8,0,1,93,65,3,0,153,0,8,0,1,93,33,35,39,7,35,55,39,51,23,55,51,7,1,207,101,124,126,101,171,167,101,123,113,105,161,193,193,244,246,194,194,238,0,0,0,1,0,7,255,14,1,242,1,234,0,7,0,254,186,0,0,0,4,0,3,43,65,3,0,80,0,0,0,1,93,65,3,0,127,0,4,0,1,93,65,3,0,140,0,4,0,1,93,186,0,1,0,4,0,0,17,18,57,65,3,0,57,0,1,0,1,93,65,3,0,11,0,1,0,1,93,65,3,0,89,0,1,0,1,93,65,3,0,71,0,1,0,1,93,65,3,0,133,0,1,0,1,93,184,0,1,16,185,0,2,0,4,244,184,0,0,16,185,0,7,0,4,244,186,0,3,0,2,0,7,17,18,57,65,3,0,89,0,3,0,1,93,65,3,0,137,0,3,0,1,93,184,0,4,16,185,0,5,0,4,244,186,0,6,0,7,0,2,17,18,57,65,3,0,119,0,6,0,1,93,65,3,0,134,0,6,0,1,93,0,184,0,0,69,88,184,0,5,47,27,185,0,5,0,12,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,8,62,89,186,0,3,0,5,0,1,17,18,57,186,0,6,0,1,0,5,17,18,57,65,5,0,115,0,6,0,131,0,6,0,2,93,184,0,5,16,184,0,7,208,48,49,9,1,35,19,3,51,27,1,1,242,254,212,100,113,204,100,153,138,1,234,253,36,1,8,1,212,254,148,1,108,0,0,0,1,0,22,0,0,1,190,1,234,0,7,1,238,186,0,2,0,6,0,3,43,65,3,0,32,0,2,0,1,93,65,3,0,128,0,2,0,1,93,65,3,0,0,0,2,0,1,93,65,3,0,16,0,2,0,1,113,65,3,0,64,0,2,0,1,93,184,0,2,16,184,0,0,208,65,3,0,70,0,0,0,1,113,65,3,0,207,0,6,0,1,93,65,3,0,95,0,6,0,1,93,65,3,0,175,0,6,0,1,93,65,3,0,127,0,6,0,1,93,65,3,0,32,0,6,0,1,93,65,3,0,64,0,6,0,1,93,184,0,6,16,184,0,4,208,65,3,0,10,0,4,0,1,113,65,3,0,73,0,4,0,1,113,65,3,0,249,0,4,0,1,93,184,0,1,208,65,5,0,19,0,1,0,35,0,1,0,2,113,65,3,0,4,0,1,0,1,113,65,5,0,229,0,1,0,245,0,1,0,2,93,65,7,0,38,0,1,0,54,0,1,0,70,0,1,0,3,93,65,3,0,214,0,1,0,1,93,65,3,0,153,0,1,0,1,93,65,5,0,54,0,1,0,70,0,1,0,2,113,65,3,0,101,0,1,0,1,113,65,3,0,84,0,1,0,1,113,65,5,0,84,0,1,0,100,0,1,0,2,93,65,3,0,113,0,1,0,1,93,65,3,0,128,0,1,0,1,93,184,0,0,16,184,0,5,208,65,3,0,233,0,5,0,1,93,65,3,0,10,0,5,0,1,113,65,3,0,202,0,5,0,1,93,65,3,0,107,0,5,0,1,93,65,3,0,92,0,5,0,1,93,65,3,0,30,0,5,0,1,113,65,3,0,143,0,5,0,1,93,65,3,0,124,0,5,0,1,93,65,3,0,44,0,5,0,1,113,65,3,0,91,0,5,0,1,113,65,3,0,106,0,5,0,1,113,65,5,0,57,0,5,0,73,0,5,0,2,113,65,7,0,41,0,5,0,57,0,5,0,73,0,5,0,3,93,65,3,0,150,0,5,0,1,93,0,184,0,0,69,88,184,0,7,47,27,185,0,7,0,12,62,89,184,0,0,69,88,184,0,3,47,27,185,0,3,0,6,62,89,185,0,2,0,1,244,184,0,7,16,185,0,6,0,1,244,48,49,9,1,33,21,33,1,35,53,1,190,254,251,1,0,254,93,1,5,251,1,234,254,92,70,1,164,70,0,0,1,0,19,255,121,1,41,2,238,0,53,0,163,184,0,0,47,184,0,8,220,184,0,0,16,184,0,16,208,184,0,0,16,184,0,50,220,184,0,20,208,184,0,0,16,184,0,45,220,65,7,0,159,0,45,0,175,0,45,0,191,0,45,0,3,93,184,0,30,208,184,0,8,16,184,0,35,208,0,184,0,51,47,184,0,0,69,88,184,0,19,47,27,185,0,19,0,18,62,89,186,0,35,0,19,0,51,17,18,57,25,184,0,35,47,24,184,0,8,208,184,0,19,16,184,0,20,220,184,0,51,16,184,0,50,220,48,49,1,65,3,0,134,0,22,0,1,93,65,3,0,133,0,48,0,1,93,0,65,3,0,136,0,22,0,1,93,65,3,0,134,0,48,0,1,93,55,52,62,2,53,52,38,39,62,1,53,52,46,2,53,52,54,55,21,14,3,21,20,30,2,21,20,14,2,7,30,3,21,20,14,2,21,20,30,2,23,21,46,1,83,2,3,3,32,40,38,34,3,3,2,97,117,53,57,26,5,1,1,1,7,18,32,26,26,33,18,6,1,1,1,8,29,56,48,115,99,14,7,40,46,42,10,54,69,25,26,69,54,10,42,45,40,7,71,75,4,69,1,20,40,64,46,5,24,27,24,6,18,31,27,26,15,14,25,25,28,16,5,25,29,28,7,54,64,36,14,3,69,4,73,0,1,0,70,255,47,0,159,2,238,0,3,0,54,184,0,1,47,65,5,0,0,0,1,0,16,0,1,0,2,93,184,0,0,220,65,3,0,128,0,0,0,1,93,0,184,0,1,47,184,0,0,69,88,184,0,2,47,27,185,0,2,0,18,62,89,48,49,23,35,17,51,159,89,89,209,3,191,0,0,0,1,0,2,255,121,1,24,2,238,0,53,0,171,184,0,38,47,184,0,0,208,184,0,38,16,184,0,35,220,184,0,4,208,184,0,38,16,184,0,29,220,65,7,0,144,0,29,0,160,0,29,0,176,0,29,0,3,93,184,0,9,208,184,0,38,16,184,0,46,220,184,0,19,208,0,184,0,3,47,184,0,0,69,88,184,0,35,47,27,185,0,35,0,18,62,89,184,0,3,16,184,0,4,220,186,0,19,0,35,0,3,17,18,57,25,184,0,19,47,24,184,0,35,16,184,0,34,220,184,0,19,16,184,0,46,208,48,49,1,65,5,0,136,0,6,0,152,0,6,0,2,93,0,65,3,0,149,0,6,0,1,93,65,3,0,134,0,6,0,1,93,65,5,0,138,0,31,0,154,0,31,0,2,93,55,20,6,7,53,62,3,53,52,46,2,53,52,62,2,55,46,3,53,52,62,2,53,52,46,2,39,53,30,1,21,20,14,2,21,20,22,23,14,1,21,20,30,2,216,99,115,54,58,25,4,1,1,1,7,18,32,26,26,32,18,7,1,1,1,8,29,56,48,117,97,3,3,2,34,38,40,32,2,3,3,14,72,73,4,69,1,20,42,64,44,7,27,29,25,6,17,28,24,25,14,15,26,27,31,18,6,24,27,24,5,54,64,36,14,3,69,4,75,71,7,40,45,42,10,54,69,26,25,69,54,10,42,46,40,0,1,0,54,0,179,1,144,1,26,0,23,0,156,184,0,8,47,184,0,7,220,184,0,8,16,184,0,21,220,184,0,20,220,0,184,0,0,47,184,0,13,220,65,9,0,47,0,13,0,63,0,13,0,79,0,13,0,95,0,13,0,4,93,184,0,5,220,65,3,0,128,0,5,0,1,114,184,0,0,16,184,0,7,208,184,0,7,47,184,0,0,16,184,0,18,220,65,3,0,112,0,18,0,1,114,65,3,0,64,0,18,0,1,113,184,0,13,16,184,0,20,208,184,0,20,47,48,49,1,65,5,0,41,0,10,0,57,0,10,0,2,93,65,5,0,38,0,22,0,54,0,22,0,2,93,0,65,5,0,38,0,10,0,54,0,10,0,2,93,37,34,46,2,35,34,7,39,62,3,51,50,30,2,51,50,55,23,14,1,1,37,12,34,44,32,10,53,18,36,6,22,28,32,15,13,36,46,32,13,42,27,34,11,58,179,16,19,16,49,9,22,34,23,11,15,19,15,51,9,43,51,0,2,0,50,255,6,0,174,1,244,0,3,0,7,0,168,187,0,5,0,4,0,4,0,4,43,65,5,0,0,0,4,0,16,0,4,0,2,93,184,0,4,16,184,0,0,208,65,13,0,9,0,0,0,25,0,0,0,41,0,0,0,57,0,0,0,73,0,0,0,89,0,0,0,6,113,65,5,0,0,0,5,0,16,0,5,0,2,93,184,0,5,16,184,0,3,208,65,13,0,6,0,3,0,22,0,3,0,38,0,3,0,54,0,3,0,70,0,3,0,86,0,3,0,6,113,0,184,0,0,69,88,184,0,4,47,27,185,0,4,0,12,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,8,62,89,184,0,4,16,184,0,7,220,65,3,0,48,0,7,0,1,113,184,0,1,220,48,49,23,19,51,19,3,51,21,35,50,30,64,30,104,84,84,250,2,38,253,218,2,238,86,0,0,1,0,34,255,225,1,170,2,236,0,36,1,110,186,0,18,0,7,0,3,43,65,5,0,63,0,7,0,79,0,7,0,2,93,65,3,0,143,0,7,0,1,93,65,3,0,32,0,18,0,1,113,65,3,0,208,0,18,0,1,93,65,3,0,0,0,18,0,1,93,186,0,1,0,7,0,18,17,18,57,184,0,1,47,65,3,0,0,0,1,0,1,93,185,0,0,0,4,244,184,0,1,16,184,0,13,208,184,0,0,16,184,0,14,208,184,0,7,16,185,0,27,0,4,244,184,0,18,16,184,0,33,208,0,184,0,0,47,184,0,0,69,88,184,0,13,47,27,185,0,13,0,18,62,89,65,3,0,16,0,13,0,1,93,65,5,0,96,0,13,0,112,0,13,0,2,93,65,5,0,48,0,13,0,64,0,13,0,2,93,186,0,36,0,13,0,0,17,18,57,184,0,36,47,65,3,0,79,0,36,0,1,113,65,7,0,159,0,36,0,175,0,36,0,191,0,36,0,3,93,65,3,0,96,0,36,0,1,93,184,0,2,208,184,0,36,16,184,0,15,220,65,3,0,160,0,15,0,1,93,184,0,12,208,184,0,15,16,184,0,19,220,185,0,18,0,2,244,184,0,15,16,185,0,22,0,2,244,184,0,36,16,185,0,30,0,2,244,184,0,36,16,184,0,32,220,185,0,33,0,2,244,48,49,1,65,3,0,9,0,5,0,1,93,65,3,0,9,0,10,0,1,93,65,3,0,69,0,24,0,1,93,65,3,0,69,0,29,0,1,93,0,65,3,0,8,0,5,0,1,93,65,3,0,6,0,10,0,1,93,65,3,0,72,0,29,0,1,93,5,35,55,46,3,53,52,62,2,55,39,51,7,30,1,23,7,46,1,35,34,14,2,21,20,22,51,50,55,23,14,1,7,1,63,90,17,46,78,56,32,28,54,79,51,17,90,16,43,57,23,8,30,62,32,41,61,41,21,88,78,61,61,8,17,48,57,31,120,6,42,66,89,54,49,89,69,46,7,142,140,3,15,14,78,16,17,29,50,67,38,82,100,32,78,11,18,3,0,0,0,1,0,34,0,0,1,224,2,202,0,37,1,125,186,0,37,0,29,0,3,43,65,3,0,16,0,37,0,1,93,184,0,37,16,184,0,0,208,65,3,0,139,0,0,0,1,93,65,3,0,143,0,29,0,1,93,65,3,0,16,0,29,0,1,93,184,0,29,16,185,0,8,0,4,244,186,0,10,0,37,0,29,17,18,57,184,0,10,47,184,0,8,16,184,0,12,208,184,0,17,208,65,5,0,101,0,17,0,117,0,17,0,2,93,65,7,0,53,0,17,0,69,0,17,0,85,0,17,0,3,113,65,3,0,53,0,17,0,1,93,65,3,0,132,0,17,0,1,93,184,0,37,16,184,0,18,208,184,0,18,47,184,0,29,16,184,0,25,208,184,0,20,208,184,0,29,16,184,0,26,208,184,0,26,47,0,184,0,0,69,88,184,0,34,47,27,185,0,34,0,14,62,89,184,0,0,69,88,184,0,19,47,27,185,0,19,0,6,62,89,184,0,34,16,184,0,0,220,184,0,34,16,185,0,3,0,2,244,186,0,9,0,34,0,19,17,18,57,184,0,9,47,65,3,0,15,0,9,0,1,93,185,0,12,0,2,244,184,0,19,16,185,0,18,0,2,244,184,0,12,16,184,0,25,208,184,0,9,16,184,0,28,208,48,49,1,65,3,0,8,0,31,0,1,93,65,3,0,26,0,31,0,1,93,65,3,0,9,0,32,0,1,93,65,5,0,37,0,36,0,53,0,36,0,2,93,65,3,0,70,0,36,0,1,93,0,65,5,0,7,0,31,0,23,0,31,0,2,93,65,5,0,6,0,32,0,22,0,32,0,2,93,65,5,0,54,0,36,0,70,0,36,0,2,93,65,3,0,39,0,36,0,1,93,1,46,1,35,34,14,2,29,1,51,7,35,14,3,7,33,21,33,62,3,55,35,55,51,53,52,62,2,51,50,22,23,1,160,14,45,27,31,35,18,4,192,15,183,3,5,10,17,13,1,5,254,97,25,36,24,16,5,95,14,87,13,38,69,55,69,76,14,2,57,29,27,16,34,51,36,93,86,38,54,49,49,33,86,35,68,73,83,50,86,115,40,73,57,34,49,37,0,2,0,61,0,29,2,53,2,155,0,27,0,46,1,77,184,0,11,47,65,7,0,0,0,11,0,16,0,11,0,32,0,11,0,3,93,184,0,25,220,184,0,11,16,185,0,35,0,4,244,184,0,25,16,185,0,45,0,4,244,0,184,0,4,47,184,0,18,220,185,0,30,0,3,244,184,0,4,16,185,0,40,0,3,244,48,49,1,65,5,0,10,0,1,0,26,0,1,0,2,113,65,5,0,73,0,6,0,89,0,6,0,2,93,65,5,0,73,0,16,0,89,0,16,0,2,93,65,5,0,10,0,21,0,26,0,21,0,2,113,65,5,0,40,0,28,0,56,0,28,0,2,93,65,3,0,137,0,28,0,1,93,65,3,0,134,0,32,0,1,93,65,5,0,39,0,32,0,55,0,32,0,2,93,65,5,0,38,0,38,0,54,0,38,0,2,93,65,3,0,135,0,38,0,1,93,65,3,0,136,0,42,0,1,93,65,5,0,41,0,42,0,57,0,42,0,2,93,65,3,0,136,0,43,0,1,93,0,65,5,0,71,0,6,0,87,0,6,0,2,93,65,3,0,229,0,15,0,1,93,65,5,0,72,0,16,0,88,0,16,0,2,93,65,3,0,229,0,21,0,1,93,65,5,0,40,0,32,0,56,0,32,0,2,93,65,3,0,137,0,32,0,1,93,65,5,0,39,0,38,0,55,0,38,0,2,93,65,3,0,135,0,38,0,1,93,65,5,0,38,0,42,0,54,0,42,0,2,93,65,3,0,134,0,42,0,1,93,37,7,39,6,35,34,39,7,39,55,38,53,52,55,39,55,23,54,51,50,23,55,23,7,22,21,20,7,3,38,35,34,14,2,21,20,30,2,51,50,62,2,53,52,2,52,29,79,70,73,74,69,79,28,77,79,80,78,28,78,76,68,71,72,80,28,78,79,80,53,42,77,39,60,41,22,22,41,60,39,39,60,41,22,53,24,103,38,38,103,24,102,82,111,110,83,102,24,103,38,39,104,24,103,82,110,108,86,1,76,54,29,51,70,42,42,71,51,28,29,52,70,41,85,0,0,0,0,1,0,30,0,0,2,134,2,188,0,22,1,100,187,0,9,0,4,0,10,0,4,43,65,3,0,0,0,9,0,1,93,184,0,9,16,184,0,5,208,184,0,1,208,184,0,0,208,65,3,0,40,0,0,0,1,93,65,3,0,23,0,0,0,1,93,65,3,0,86,0,0,0,1,93,184,0,5,16,184,0,6,208,184,0,6,47,184,0,2,208,184,0,2,47,65,3,0,0,0,10,0,1,93,184,0,10,16,184,0,14,208,184,0,12,208,184,0,12,47,184,0,16,208,184,0,16,47,184,0,14,16,184,0,18,208,184,0,19,208,65,3,0,89,0,19,0,1,93,65,3,0,24,0,19,0,1,93,65,3,0,39,0,19,0,1,93,185,0,20,0,4,244,186,0,21,0,18,0,1,17,18,57,184,0,0,16,185,0,22,0,4,244,0,184,0,0,69,88,184,0,20,47,27,185,0,20,0,14,62,89,184,0,0,69,88,184,0,10,47,27,185,0,10,0,6,62,89,186,0,17,0,20,0,10,17,18,57,184,0,17,47,184,0,1,208,184,0,17,16,184,0,16,220,184,0,4,208,184,0,17,16,184,0,13,220,65,5,0,32,0,13,0,48,0,13,0,2,93,184,0,5,208,184,0,13,16,184,0,12,220,184,0,8,208,186,0,21,0,20,0,10,17,18,57,65,3,0,102,0,21,0,1,93,65,3,0,41,0,21,0,1,93,65,3,0,54,0,21,0,1,93,65,3,0,131,0,21,0,1,93,184,0,20,16,184,0,22,208,48,49,65,3,0,134,0,21,0,1,93,65,3,0,9,0,21,0,1,93,9,1,51,7,35,21,51,7,35,21,35,53,35,55,51,53,35,55,51,1,51,27,1,2,134,254,253,177,21,157,178,21,157,96,178,21,157,178,21,156,254,253,93,215,215,2,188,254,128,54,62,54,146,146,54,62,54,1,128,254,205,1,51,0,0,0,0,2,0,72,255,46,0,160,2,238,0,3,0,7,0,78,184,0,6,47,65,5,0,0,0,6,0,16,0,6,0,2,93,184,0,7,220,65,3,0,128,0,7,0,1,93,184,0,0,208,184,0,6,16,184,0,1,208,0,184,0,5,47,184,0,0,69,88,184,0,2,47,27,185,0,2,0,18,62,89,184,0,1,220,184,0,5,16,184,0,6,220,48,49,19,35,17,51,17,35,17,51,160,88,88,88,88,1,52,1,186,252,64,1,117,0,0,2,0,37,255,172,1,163,2,238,0,52,0,64,3,51,186,0,51,0,26,0,3,43,65,3,0,0,0,51,0,1,93,65,3,0,143,0,26,0,1,93,65,3,0,0,0,26,0,1,93,186,0,5,0,51,0,26,17,18,57,184,0,5,47,184,0,26,16,185,0,58,0,5,244,186,0,0,0,5,0,58,17,18,57,186,0,13,0,26,0,51,17,18,57,184,0,13,47,184,0,5,16,185,0,19,0,5,244,186,0,31,0,26,0,51,17,18,57,184,0,31,47,184,0,51,16,185,0,63,0,5,244,186,0,28,0,31,0,63,17,18,57,65,3,0,25,0,28,0,1,93,65,7,0,53,0,28,0,69,0,28,0,85,0,28,0,3,93,65,3,0,116,0,28,0,1,93,186,0,38,0,51,0,26,17,18,57,184,0,38,47,184,0,31,16,185,0,44,0,5,244,186,0,53,0,63,0,31,17,18,57,186,0,60,0,58,0,5,17,18,57,0,184,0,10,47,184,0,0,69,88,184,0,36,47,27,185,0,36,0,18,62,89,186,0,60,0,10,0,36,17,18,57,184,0,60,47,184,0,22,208,65,5,0,121,0,22,0,137,0,22,0,2,93,65,3,0,72,0,22,0,1,93,186,0,0,0,60,0,22,17,18,57,184,0,10,16,184,0,14,220,184,0,10,16,185,0,16,0,3,244,186,0,53,0,36,0,10,17,18,57,184,0,53,47,184,0,47,208,65,5,0,118,0,47,0,134,0,47,0,2,93,65,3,0,22,0,47,0,1,93,65,3,0,69,0,47,0,1,93,186,0,28,0,47,0,53,17,18,57,184,0,36,16,184,0,39,220,184,0,36,16,185,0,41,0,3,244,48,49,1,65,3,0,21,0,7,0,1,93,65,3,0,38,0,7,0,1,93,65,3,0,104,0,13,0,1,93,65,3,0,72,0,23,0,1,93,65,3,0,25,0,24,0,1,93,65,3,0,73,0,24,0,1,93,65,7,0,105,0,24,0,121,0,24,0,137,0,24,0,3,93,65,3,0,73,0,25,0,1,93,65,3,0,26,0,25,0,1,93,65,3,0,139,0,27,0,1,93,65,3,0,40,0,34,0,1,93,65,3,0,25,0,34,0,1,93,65,3,0,133,0,46,0,1,93,65,5,0,103,0,48,0,119,0,48,0,2,93,65,3,0,21,0,49,0,1,93,65,5,0,118,0,49,0,134,0,49,0,2,93,65,3,0,71,0,49,0,1,93,65,3,0,103,0,49,0,1,93,65,3,0,85,0,59,0,1,93,0,65,5,0,24,0,7,0,40,0,7,0,2,93,65,5,0,121,0,12,0,137,0,12,0,2,93,65,3,0,122,0,13,0,1,93,65,3,0,107,0,13,0,1,93,65,3,0,73,0,23,0,1,93,65,3,0,25,0,24,0,1,93,65,3,0,73,0,24,0,1,93,65,5,0,105,0,24,0,121,0,24,0,2,93,65,3,0,138,0,24,0,1,93,65,3,0,133,0,27,0,1,93,65,3,0,20,0,34,0,1,93,65,3,0,37,0,34,0,1,93,65,3,0,101,0,38,0,1,93,65,3,0,133,0,38,0,1,93,65,3,0,118,0,38,0,1,93,65,3,0,135,0,46,0,1,93,65,3,0,117,0,48,0,1,93,65,3,0,102,0,48,0,1,93,65,3,0,116,0,49,0,1,93,65,3,0,21,0,49,0,1,93,65,3,0,70,0,49,0,1,93,65,3,0,102,0,49,0,1,93,65,3,0,134,0,49,0,1,93,65,3,0,83,0,59,0,1,93,65,3,0,37,0,59,0,1,93,65,3,0,41,0,64,0,1,93,65,3,0,91,0,64,0,1,93,37,30,3,21,20,14,2,35,34,38,39,55,22,51,50,54,53,52,46,4,53,52,55,46,1,53,52,62,2,51,50,23,7,38,35,34,6,21,20,30,4,21,20,39,14,3,21,20,23,62,1,53,52,1,59,21,23,12,3,20,41,64,43,43,80,20,13,68,63,48,55,40,61,71,61,40,109,39,25,19,41,62,43,86,61,13,68,62,45,52,39,59,69,59,39,215,14,35,30,20,162,36,42,188,16,26,27,30,20,30,56,42,25,22,17,63,41,41,42,35,39,24,21,37,61,53,116,33,28,51,29,35,60,43,25,40,63,43,50,36,31,37,26,25,40,63,51,99,206,1,11,23,36,25,81,42,10,58,37,81,0,0,2,0,87,2,88,1,79,2,188,0,3,0,7,0,70,184,0,5,47,65,3,0,0,0,5,0,1,93,184,0,1,220,184,0,0,220,184,0,5,16,184,0,4,220,0,184,0,5,47,65,3,0,32,0,5,0,1,93,65,3,0,64,0,5,0,1,93,184,0,1,208,184,0,5,16,184,0,6,220,184,0,2,208,48,49,1,35,53,51,7,35,53,51,1,79,70,70,178,70,70,2,88,100,100,100,0,0,0,3,0,49,0,37,2,158,2,181,0,19,0,39,0,65,3,127,184,0,0,47,184,0,10,220,65,3,0,239,0,10,0,1,93,65,3,0,111,0,10,0,1,93,65,3,0,80,0,10,0,1,93,184,0,0,16,184,0,25,220,184,0,10,16,184,0,35,220,186,0,45,0,0,0,10,17,18,57,184,0,45,47,184,0,52,220,184,0,45,16,184,0,58,220,184,0,52,16,184,0,64,208,0,184,0,5,47,184,0,15,220,184,0,5,16,184,0,20,220,184,0,15,16,184,0,30,220,186,0,40,0,5,0,15,17,18,57,184,0,40,47,65,3,0,15,0,40,0,1,93,65,3,0,111,0,40,0,1,93,184,0,50,220,65,3,0,32,0,50,0,1,93,65,3,0,0,0,50,0,1,93,184,0,53,220,184,0,50,16,184,0,55,220,65,3,0,15,0,55,0,1,113,184,0,40,16,184,0,61,220,184,0,40,16,184,0,63,220,48,49,1,65,5,0,9,0,2,0,25,0,2,0,2,93,65,3,0,41,0,2,0,1,113,65,5,0,106,0,2,0,122,0,2,0,2,93,65,5,0,8,0,3,0,24,0,3,0,2,93,65,3,0,183,0,6,0,1,93,65,3,0,37,0,7,0,1,113,65,5,0,7,0,7,0,23,0,7,0,2,93,65,5,0,101,0,8,0,117,0,8,0,2,93,65,5,0,6,0,8,0,22,0,8,0,2,93,65,5,0,7,0,12,0,23,0,12,0,2,93,65,5,0,6,0,13,0,22,0,13,0,2,93,65,5,0,103,0,13,0,119,0,13,0,2,93,65,3,0,39,0,13,0,1,113,65,5,0,9,0,17,0,25,0,17,0,2,93,65,5,0,106,0,17,0,122,0,17,0,2,93,65,3,0,42,0,17,0,1,113,65,5,0,10,0,18,0,26,0,18,0,2,93,65,9,0,169,0,42,0,185,0,42,0,201,0,42,0,217,0,42,0,4,93,65,9,0,169,0,43,0,185,0,43,0,201,0,43,0,217,0,43,0,4,93,65,3,0,42,0,43,0,1,93,65,9,0,169,0,47,0,185,0,47,0,201,0,47,0,217,0,47,0,4,93,65,3,0,42,0,47,0,1,93,65,9,0,169,0,48,0,185,0,48,0,201,0,48,0,217,0,48,0,4,93,65,9,0,167,0,52,0,183,0,52,0,199,0,52,0,215,0,52,0,4,93,0,65,5,0,6,0,2,0,22,0,2,0,2,93,65,5,0,102,0,2,0,118,0,2,0,2,93,65,3,0,38,0,2,0,1,113,65,5,0,6,0,3,0,22,0,3,0,2,93,65,3,0,182,0,6,0,1,93,65,5,0,7,0,7,0,23,0,7,0,2,93,65,3,0,39,0,7,0,1,113,65,5,0,6,0,8,0,22,0,8,0,2,93,65,5,0,103,0,8,0,119,0,8,0,2,93,65,5,0,8,0,12,0,24,0,12,0,2,93,65,3,0,41,0,13,0,1,113,65,5,0,10,0,13,0,26,0,13,0,2,93,65,5,0,106,0,13,0,122,0,13,0,2,93,65,5,0,9,0,17,0,25,0,17,0,2,93,65,5,0,105,0,17,0,121,0,17,0,2,93,65,3,0,42,0,17,0,1,113,65,5,0,8,0,18,0,24,0,18,0,2,93,65,9,0,168,0,42,0,184,0,42,0,200,0,42,0,216,0,42,0,4,93,65,3,0,40,0,43,0,1,93,65,9,0,169,0,43,0,185,0,43,0,201,0,43,0,217,0,43,0,4,93,65,3,0,38,0,47,0,1,93,65,9,0,167,0,47,0,183,0,47,0,199,0,47,0,215,0,47,0,4,93,65,9,0,165,0,48,0,181,0,48,0,197,0,48,0,213,0,48,0,4,93,65,9,0,165,0,51,0,181,0,51,0,197,0,51,0,213,0,51,0,4,93,65,9,0,165,0,52,0,181,0,52,0,197,0,52,0,213,0,52,0,4,93,65,9,0,172,0,64,0,188,0,64,0,204,0,64,0,220,0,64,0,4,93,19,52,62,2,51,50,30,2,21,20,14,2,35,34,46,2,1,34,14,2,21,20,30,2,51,50,62,2,53,52,46,2,3,34,46,2,53,52,62,2,51,50,23,7,38,35,34,6,21,20,22,51,50,55,23,6,49,46,83,114,68,68,114,82,46,46,82,114,68,68,115,82,46,1,55,63,96,66,34,33,66,97,63,63,96,66,33,34,65,96,54,35,58,42,23,23,42,58,35,48,42,7,45,38,45,46,46,45,37,46,7,38,1,109,74,121,86,47,47,87,121,73,73,120,87,48,48,86,121,1,100,41,75,104,63,63,104,75,41,42,75,104,62,62,104,75,42,254,61,24,43,61,38,38,62,43,24,19,60,19,59,48,48,59,20,59,20,0,2,0,33,1,178,1,57,2,213,0,27,0,35,1,120,184,0,9,47,65,3,0,96,0,9,0,1,93,184,0,24,220,65,3,0,159,0,24,0,1,93,184,0,0,208,184,0,0,47,184,0,24,16,185,0,29,0,5,244,184,0,4,208,184,0,29,16,184,0,14,208,186,0,19,0,24,0,9,17,18,57,184,0,19,47,184,0,9,16,185,0,32,0,5,244,0,184,0,21,47,184,0,6,220,65,3,0,96,0,6,0,1,93,65,3,0,48,0,6,0,1,93,65,3,0,208,0,6,0,1,93,184,0,2,208,186,0,14,0,21,0,6,17,18,57,184,0,14,47,184,0,21,16,185,0,16,0,3,244,184,0,21,16,184,0,18,220,184,0,6,16,185,0,34,0,3,244,184,0,27,208,184,0,14,16,184,0,29,220,48,49,1,65,3,0,151,0,7,0,1,93,65,3,0,183,0,7,0,1,93,65,3,0,217,0,7,0,1,93,65,13,0,59,0,8,0,75,0,8,0,91,0,8,0,107,0,8,0,123,0,8,0,139,0,8,0,6,93,65,3,0,40,0,11,0,1,93,65,3,0,34,0,22,0,1,93,65,13,0,53,0,22,0,69,0,22,0,85,0,22,0,101,0,22,0,117,0,22,0,133,0,22,0,6,93,65,3,0,151,0,22,0,1,93,0,65,7,0,170,0,7,0,186,0,7,0,202,0,7,0,3,93,65,3,0,155,0,7,0,1,93,65,3,0,220,0,7,0,1,93,65,3,0,38,0,11,0,1,93,65,3,0,36,0,22,0,1,93,65,15,0,53,0,22,0,69,0,22,0,85,0,22,0,101,0,22,0,117,0,22,0,133,0,22,0,149,0,22,0,7,93,1,7,35,34,39,6,35,34,38,53,52,62,2,55,38,35,34,7,39,54,51,50,29,1,20,22,51,39,53,14,1,21,20,51,50,1,57,7,27,48,19,31,61,37,50,35,52,58,23,2,51,32,51,6,54,55,109,9,17,101,35,55,40,27,1,239,61,31,31,46,39,29,38,23,10,1,42,20,60,23,108,80,30,12,12,63,1,25,22,32,0,0,0,2,0,15,0,78,2,11,1,234,0,5,0,11,0,156,184,0,8,47,65,3,0,31,0,8,0,1,93,65,3,0,143,0,8,0,1,93,184,0,2,220,184,0,4,220,184,0,0,208,185,0,1,0,4,244,184,0,3,208,184,0,2,16,185,0,5,0,4,244,184,0,8,16,184,0,10,220,184,0,6,208,184,0,10,16,185,0,9,0,4,244,184,0,7,208,184,0,8,16,185,0,11,0,4,244,65,3,0,47,0,13,0,1,93,0,25,184,0,8,47,24,184,0,7,208,184,0,7,47,184,0,1,208,184,0,8,16,184,0,11,208,184,0,2,208,184,0,8,16,184,0,9,208,184,0,9,47,184,0,3,208,184,0,2,16,184,0,5,208,48,49,37,35,39,55,51,15,1,35,39,55,51,7,2,11,101,147,147,101,148,113,100,147,147,100,147,78,206,206,206,206,206,206,206,0,0,0,0,1,0,66,0,151,2,14,1,150,0,5,0,66,184,0,0,47,65,3,0,0,0,0,0,1,93,65,3,0,208,0,0,0,1,93,184,0,1,220,65,7,0,0,0,1,0,16,0,1,0,32,0,1,0,3,113,184,0,0,16,184,0,3,220,0,184,0,3,47,184,0,4,220,184,0,1,220,48,49,37,35,53,33,53,33,2,14,55,254,107,1,204,151,195,60,0,1,0,57,0,230,1,111,1,68,0,3,0,72,184,0,1,47,65,5,0,0,0,1,0,16,0,1,0,2,93,65,3,0,48,0,1,0,1,113,184,0,0,220,65,3,0,96,0,0,0,1,93,0,184,0,1,47,184,0,2,220,65,3,0,32,0,2,0,1,113,65,5,0,112,0,2,0,128,0,2,0,2,93,48,49,37,33,53,33,1,111,254,202,1,54,230,94,0,0,0,4,0,49,0,37,2,158,2,181,0,19,0,39,0,52,0,60,2,254,184,0,0,47,184,0,10,220,65,3,0,239,0,10,0,1,93,65,3,0,111,0,10,0,1,93,65,3,0,80,0,10,0,1,93,184,0,0,16,184,0,25,220,65,3,0,79,0,25,0,1,113,184,0,10,16,184,0,35,220,65,3,0,64,0,35,0,1,113,186,0,45,0,0,0,10,17,18,57,184,0,45,47,65,3,0,64,0,45,0,1,93,184,0,50,220,184,0,45,16,184,0,44,220,65,5,0,239,0,44,0,255,0,44,0,2,93,186,0,52,0,50,0,44,17,18,57,65,5,0,69,0,52,0,85,0,52,0,2,93,65,3,0,100,0,52,0,1,93,184,0,52,16,184,0,40,208,65,5,0,233,0,40,0,249,0,40,0,2,93,184,0,52,16,184,0,42,208,184,0,41,208,184,0,44,16,184,0,55,208,184,0,50,16,184,0,58,220,0,184,0,5,47,184,0,15,220,184,0,5,16,184,0,20,220,184,0,15,16,184,0,30,220,186,0,45,0,5,0,15,17,18,57,184,0,45,47,184,0,41,208,184,0,45,16,184,0,46,220,65,3,0,32,0,46,0,1,93,65,3,0,0,0,46,0,1,93,186,0,43,0,46,0,45,17,18,57,184,0,43,47,186,0,52,0,46,0,43,17,18,57,65,3,0,88,0,52,0,1,93,184,0,46,16,184,0,54,220,184,0,43,16,184,0,55,220,48,49,1,65,5,0,9,0,2,0,25,0,2,0,2,93,65,5,0,106,0,2,0,122,0,2,0,2,93,65,5,0,9,0,3,0,25,0,3,0,2,93,65,3,0,41,0,3,0,1,113,65,5,0,6,0,7,0,22,0,7,0,2,93,65,3,0,38,0,7,0,1,113,65,5,0,6,0,8,0,22,0,8,0,2,93,65,5,0,102,0,8,0,118,0,8,0,2,93,65,3,0,35,0,12,0,1,113,65,5,0,6,0,12,0,22,0,12,0,2,93,65,5,0,102,0,12,0,118,0,12,0,2,93,65,5,0,7,0,13,0,23,0,13,0,2,93,65,5,0,103,0,13,0,119,0,13,0,2,93,65,5,0,8,0,17,0,24,0,17,0,2,93,65,5,0,9,0,18,0,25,0,18,0,2,93,65,3,0,41,0,18,0,1,113,65,5,0,25,0,40,0,41,0,40,0,2,113,65,3,0,90,0,40,0,1,113,0,65,5,0,102,0,2,0,118,0,2,0,2,93,65,5,0,7,0,2,0,23,0,2,0,2,93,65,3,0,39,0,2,0,1,113,65,5,0,6,0,3,0,22,0,3,0,2,93,65,3,0,38,0,3,0,1,113,65,3,0,37,0,7,0,1,113,65,3,0,182,0,7,0,1,93,65,5,0,7,0,7,0,23,0,7,0,2,93,65,5,0,102,0,8,0,118,0,8,0,2,93,65,5,0,7,0,8,0,23,0,8,0,2,93,65,5,0,8,0,12,0,24,0,12,0,2,93,65,5,0,104,0,12,0,120,0,12,0,2,93,65,3,0,40,0,12,0,1,113,65,5,0,9,0,13,0,25,0,13,0,2,93,65,5,0,105,0,13,0,121,0,13,0,2,93,65,5,0,8,0,17,0,24,0,17,0,2,93,65,5,0,106,0,17,0,122,0,17,0,2,93,65,5,0,8,0,18,0,24,0,18,0,2,93,65,3,0,24,0,40,0,1,113,65,3,0,41,0,40,0,1,113,19,52,62,2,51,50,30,2,21,20,14,2,35,34,46,2,1,34,14,2,21,20,30,2,51,50,62,2,53,52,46,2,19,35,39,35,21,35,17,51,50,22,21,20,7,39,35,21,51,50,53,52,38,49,46,83,114,68,68,114,82,46,46,82,114,68,68,115,82,46,1,55,63,97,66,34,33,66,97,64,63,97,65,34,34,66,96,66,63,65,55,62,118,54,56,54,70,42,40,61,26,1,109,74,121,86,47,47,87,121,73,73,120,87,48,48,86,121,1,101,42,75,105,62,62,105,76,41,41,76,105,62,62,105,75,42,254,73,117,117,1,65,45,55,51,36,138,99,50,24,25,0,0,0,0,2,0,34,1,226,1,43,2,243,0,16,0,34,1,110,184,0,5,47,65,3,0,246,0,2,0,1,93,184,0,15,220,65,3,0,79,0,15,0,1,93,65,3,0,15,0,15,0,1,93,184,0,5,16,184,0,22,220,65,3,0,143,0,22,0,1,113,65,5,0,239,0,22,0,255,0,22,0,2,114,184,0,15,16,184,0,30,220,0,184,0,0,69,88,184,0,10,47,27,185,0,10,0,18,62,89,184,0,2,220,65,3,0,255,0,2,0,1,93,65,3,0,0,0,2,0,1,93,184,0,10,16,184,0,17,220,184,0,2,16,184,0,25,220,48,49,1,65,7,0,21,0,0,0,37,0,0,0,53,0,0,0,3,93,65,3,0,6,0,0,0,1,93,65,7,0,26,0,4,0,42,0,4,0,58,0,4,0,3,93,65,3,0,11,0,4,0,1,93,65,7,0,25,0,7,0,41,0,7,0,57,0,7,0,3,93,65,3,0,10,0,7,0,1,93,65,7,0,24,0,8,0,40,0,8,0,56,0,8,0,3,93,65,7,0,22,0,12,0,38,0,12,0,54,0,12,0,3,93,65,3,0,7,0,12,0,1,93,65,3,0,6,0,13,0,1,93,0,65,9,0,9,0,0,0,25,0,0,0,41,0,0,0,57,0,0,0,4,93,65,9,0,9,0,3,0,25,0,3,0,41,0,3,0,57,0,3,0,4,93,65,3,0,6,0,7,0,1,93,65,7,0,23,0,8,0,39,0,8,0,55,0,8,0,3,93,65,7,0,22,0,12,0,38,0,12,0,54,0,12,0,3,93,65,3,0,7,0,12,0,1,93,65,3,0,7,0,13,0,1,93,1,6,35,34,38,53,52,62,2,51,50,30,2,21,20,39,34,14,2,21,20,22,51,50,62,2,53,52,46,2,1,7,36,61,63,69,18,35,49,30,30,50,34,19,133,21,32,23,12,49,44,21,30,21,10,11,22,32,2,8,38,77,59,30,50,36,21,21,37,50,29,59,170,18,30,41,22,48,62,19,31,36,24,22,40,31,18,0,0,0,0,2,0,64,0,42,1,178,2,20,0,11,0,15,0,121,184,0,4,47,65,3,0,0,0,4,0,1,93,184,0,1,220,65,3,0,239,0,1,0,1,93,184,0,0,220,184,0,4,16,184,0,5,220,184,0,4,16,184,0,7,208,184,0,1,16,184,0,10,208,184,0,5,16,184,0,14,208,184,0,0,16,184,0,15,208,0,184,0,13,47,184,0,5,220,184,0,1,208,184,0,5,16,184,0,3,220,184,0,5,16,184,0,6,220,184,0,8,220,184,0,6,16,184,0,10,208,184,0,13,16,184,0,14,220,48,49,1,35,21,35,53,35,53,51,53,51,21,51,17,33,53,33,1,178,153,64,153,153,64,153,254,142,1,114,1,71,144,144,67,138,138,254,160,67,0,0,1,0,25,1,64,1,17,2,194,0,23,1,117,186,0,20,0,12,0,3,43,65,3,0,80,0,12,0,1,93,184,0,12,16,184,0,1,208,65,3,0,80,0,20,0,1,93,65,3,0,32,0,20,0,1,93,184,0,20,16,185,0,6,0,5,244,184,0,1,16,184,0,22,208,65,3,0,102,0,22,0,1,93,65,3,0,38,0,22,0,1,93,65,7,0,21,0,22,0,37,0,22,0,53,0,22,0,3,113,184,0,20,16,184,0,23,208,184,0,23,47,0,184,0,0,69,88,184,0,15,47,27,185,0,15,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,10,62,89,185,0,23,0,1,244,184,0,2,208,184,0,15,16,185,0,9,0,3,244,184,0,15,16,184,0,11,220,65,3,0,239,0,11,0,1,93,184,0,12,220,48,49,1,65,3,0,136,0,3,0,1,93,65,11,0,72,0,13,0,88,0,13,0,104,0,13,0,120,0,13,0,136,0,13,0,5,93,65,11,0,55,0,17,0,71,0,17,0,87,0,17,0,103,0,17,0,119,0,17,0,5,93,65,11,0,54,0,18,0,70,0,18,0,86,0,18,0,102,0,18,0,118,0,18,0,5,93,65,7,0,150,0,22,0,166,0,22,0,182,0,22,0,3,93,0,65,3,0,135,0,3,0,1,93,65,11,0,70,0,13,0,86,0,13,0,102,0,13,0,118,0,13,0,134,0,13,0,5,93,65,11,0,55,0,17,0,71,0,17,0,87,0,17,0,103,0,17,0,119,0,17,0,5,93,65,11,0,55,0,18,0,71,0,18,0,87,0,18,0,103,0,18,0,119,0,18,0,5,93,1,35,62,3,53,52,38,35,34,7,39,62,1,51,50,30,2,21,20,7,51,1,17,248,57,66,33,8,30,27,51,42,9,11,61,45,30,42,27,13,106,120,1,64,77,97,60,30,9,25,28,59,65,19,35,16,28,37,21,68,146,0,1,0,19,1,56,1,21,2,194,0,38,1,205,186,0,34,0,5,0,3,43,65,3,0,159,0,5,0,1,93,65,3,0,111,0,5,0,1,93,65,3,0,95,0,5,0,1,113,65,3,0,240,0,5,0,1,93,65,3,0,32,0,5,0,1,113,65,5,0,16,0,34,0,32,0,34,0,2,93,65,3,0,159,0,34,0,1,93,65,3,0,240,0,34,0,1,93,65,3,0,80,0,34,0,1,93,65,3,0,32,0,34,0,1,113,184,0,34,16,185,0,10,0,5,244,186,0,14,0,5,0,34,17,18,57,184,0,14,47,65,3,0,15,0,14,0,1,93,186,0,30,0,34,0,5,17,18,57,184,0,30,47,185,0,18,0,5,244,186,0,23,0,5,0,34,17,18,57,184,0,23,47,186,0,32,0,14,0,30,17,18,57,65,7,0,38,0,32,0,54,0,32,0,70,0,32,0,3,93,65,5,0,85,0,32,0,101,0,32,0,2,93,0,184,0,0,69,88,184,0,25,47,27,185,0,25,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,10,62,89,184,0,6,220,65,5,0,112,0,6,0,128,0,6,0,2,93,184,0,0,16,185,0,8,0,1,244,186,0,16,0,25,0,0,17,18,57,184,0,16,47,65,3,0,31,0,16,0,1,93,185,0,13,0,3,244,184,0,25,16,185,0,20,0,3,244,184,0,25,16,184,0,22,220,186,0,32,0,16,0,13,17,18,57,48,49,1,65,3,0,38,0,27,0,1,93,65,3,0,70,0,27,0,1,93,65,3,0,55,0,27,0,1,93,65,3,0,87,0,27,0,1,93,65,3,0,104,0,27,0,1,93,65,3,0,38,0,37,0,1,93,65,3,0,71,0,37,0,1,93,0,65,3,0,101,0,27,0,1,93,65,9,0,38,0,27,0,54,0,27,0,70,0,27,0,86,0,27,0,4,93,65,3,0,118,0,27,0,1,93,65,3,0,41,0,37,0,1,93,65,3,0,73,0,37,0,1,93,65,3,0,58,0,37,0,1,93,19,34,46,2,39,55,22,51,50,53,52,38,43,1,55,51,50,53,52,35,34,7,39,54,51,50,30,2,21,20,7,22,21,20,14,2,128,17,35,30,23,4,18,32,56,78,31,43,52,6,27,77,60,49,22,11,26,65,36,48,29,13,39,54,24,41,54,1,56,6,9,10,5,66,26,52,30,34,55,48,44,17,53,25,18,28,36,19,53,22,32,61,30,46,32,17,0,0,1,0,58,2,84,0,245,2,220,0,3,0,105,184,0,2,47,65,3,0,0,0,2,0,1,93,184,0,0,220,0,184,0,1,47,65,3,0,64,0,1,0,1,93,65,3,0,32,0,1,0,1,93,65,3,0,16,0,1,0,1,113,184,0,3,220,65,5,0,15,0,3,0,31,0,3,0,2,93,184,0,0,220,65,11,0,89,0,0,0,105,0,0,0,121,0,0,0,137,0,0,0,153,0,0,0,5,93,184,0,1,16,184,0,2,220,48,49,19,7,53,55,245,187,187,2,148,64,41,95,0,0,1,0,73,255,14,2,44,1,234,0,27,0,252,186,0,23,0,13,0,3,43,65,3,0,143,0,23,0,1,93,65,3,0,0,0,23,0,1,93,65,3,0,32,0,23,0,1,93,184,0,23,16,185,0,22,0,4,244,186,0,4,0,22,0,23,17,18,57,65,3,0,143,0,13,0,1,93,65,3,0,0,0,13,0,1,93,65,3,0,32,0,13,0,1,93,184,0,13,16,185,0,14,0,4,244,184,0,10,208,0,184,0,0,69,88,184,0,14,47,27,185,0,14,0,12,62,89,184,0,0,69,88,184,0,7,47,27,185,0,7,0,6,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,184,0,0,69,88,184,0,12,47,27,185,0,12,0,8,62,89,184,0,1,16,185,0,0,0,1,244,184,0,14,16,184,0,22,208,186,0,4,0,7,0,22,17,18,57,186,0,10,0,14,0,7,17,18,57,65,5,0,122,0,10,0,138,0,10,0,2,93,184,0,7,16,185,0,18,0,2,244,48,49,1,65,5,0,85,0,17,0,101,0,17,0,2,93,0,65,3,0,88,0,17,0,1,93,37,7,35,34,39,14,1,35,34,38,39,17,35,17,51,17,20,22,51,50,54,55,17,51,17,20,22,51,2,44,16,26,79,28,33,57,44,32,47,33,88,89,53,69,38,50,28,87,19,28,62,72,73,38,36,15,23,254,243,2,220,254,254,84,79,26,32,1,107,254,192,57,51,0,0,1,0,33,0,0,2,68,2,188,0,19,0,140,184,0,7,47,65,5,0,0,0,7,0,16,0,7,0,2,93,184,0,3,220,65,5,0,15,0,3,0,31,0,3,0,2,93,184,0,2,220,184,0,0,220,184,0,7,16,184,0,6,220,184,0,7,16,184,0,13,220,65,5,0,15,0,13,0,31,0,13,0,2,93,0,184,0,0,69,88,184,0,19,47,27,185,0,19,0,14,62,89,184,0,0,69,88,184,0,6,47,27,185,0,6,0,6,62,89,184,0,19,16,184,0,0,220,184,0,6,16,184,0,3,208,184,0,0,16,184,0,4,208,184,0,19,16,184,0,8,220,48,49,1,35,17,35,17,35,17,35,53,46,3,53,52,62,2,51,33,2,68,75,48,101,41,70,105,71,36,38,73,108,69,1,3,2,121,253,135,2,121,253,135,243,4,40,63,80,44,45,82,62,37,0,0,0,0,1,0,57,0,213,0,181,1,87,0,3,0,76,184,0,1,47,65,5,0,32,0,1,0,48,0,1,0,2,113,65,5,0,0,0,1,0,16,0,1,0,2,93,184,0,0,220,65,3,0,191,0,0,0,1,93,65,3,0,63,0,0,0,1,93,65,5,0,47,0,0,0,63,0,0,0,2,113,0,184,0,1,47,184,0,2,220,48,49,55,35,53,51,181,124,124,213,130,0,0,1,0,144,255,64,1,22,255,202,0,3,0,54,184,0,2,47,65,3,0,32,0,2,0,1,93,184,0,0,220,65,5,0,31,0,0,0,47,0,0,0,2,93,0,184,0,4,47,184,0,0,220,184,0,2,220,65,3,0,16,0,2,0,1,93,48,49,5,15,1,55,1,22,88,46,68,54,133,5,132,0,0,0,0,1,0,23,1,64,0,155,2,186,0,11,0,171,187,0,0,0,5,0,1,0,4,43,65,5,0,143,0,0,0,159,0,0,0,2,93,65,3,0,207,0,0,0,1,93,65,7,0,0,0,0,0,16,0,0,0,32,0,0,0,3,93,65,5,0,143,0,1,0,159,0,1,0,2,93,65,3,0,207,0,1,0,1,93,65,7,0,0,0,1,0,16,0,1,0,32,0,1,0,3,93,184,0,1,16,184,0,5,208,184,0,5,47,186,0,10,0,1,0,0,17,18,57,0,184,0,0,69,88,184,0,11,47,27,185,0,11,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,10,62,89,184,0,11,16,184,0,4,220,186,0,2,0,4,0,11,17,18,57,185,0,5,0,3,244,48,49,19,35,17,6,7,39,62,3,55,51,155,75,32,19,6,9,24,21,18,3,57,1,64,1,20,14,3,60,1,13,16,20,9,0,0,0,2,0,33,1,178,1,81,2,213,0,18,0,31,0,233,184,0,7,47,65,3,0,96,0,7,0,1,93,184,0,17,220,184,0,7,16,185,0,24,0,5,244,184,0,17,16,185,0,30,0,5,244,0,184,0,12,47,184,0,2,220,65,3,0,208,0,2,0,1,93,65,3,0,96,0,2,0,1,93,65,3,0,48,0,2,0,1,93,184,0,12,16,185,0,21,0,3,244,184,0,2,16,185,0,27,0,3,244,48,49,1,65,7,0,6,0,0,0,22,0,0,0,38,0,0,0,3,93,65,7,0,9,0,5,0,25,0,5,0,41,0,5,0,3,93,65,7,0,8,0,10,0,24,0,10,0,40,0,10,0,3,93,65,7,0,6,0,14,0,22,0,14,0,38,0,14,0,3,93,0,65,7,0,9,0,0,0,25,0,0,0,41,0,0,0,3,93,65,7,0,8,0,5,0,24,0,5,0,40,0,5,0,3,93,65,7,0,6,0,10,0,22,0,10,0,38,0,10,0,3,93,65,7,0,6,0,14,0,22,0,14,0,38,0,14,0,3,93,1,6,35,34,46,2,53,52,62,2,51,50,30,2,21,20,39,38,35,34,6,21,20,22,51,50,54,53,52,1,39,41,69,35,56,39,22,21,39,57,35,35,56,40,21,97,20,35,35,40,40,35,35,40,1,220,42,23,39,53,31,30,53,39,23,23,39,53,30,61,123,24,49,37,38,48,48,38,37,0,2,0,41,0,78,2,36,1,234,0,5,0,11,0,195,184,0,0,47,65,3,0,0,0,0,0,1,93,184,0,4,220,184,0,5,220,65,7,0,96,0,5,0,112,0,5,0,128,0,5,0,3,93,65,7,0,0,0,5,0,16,0,5,0,32,0,5,0,3,113,184,0,1,208,184,0,4,16,184,0,2,208,184,0,0,16,185,0,3,0,4,244,184,0,0,16,184,0,6,220,184,0,10,220,185,0,11,0,4,244,184,0,7,208,184,0,10,16,184,0,8,208,184,0,6,16,185,0,9,0,4,244,65,3,0,47,0,13,0,1,93,0,25,184,0,0,47,24,184,0,1,208,184,0,1,47,184,0,0,16,184,0,3,208,184,0,0,16,184,0,5,208,184,0,5,47,184,0,3,16,184,0,6,208,184,0,1,16,184,0,7,208,184,0,6,16,184,0,9,208,184,0,5,16,184,0,11,208,48,49,1,7,35,55,39,51,15,1,35,55,39,51,2,36,147,100,147,147,100,112,147,101,148,148,101,1,28,206,206,206,206,206,206,206,0,0,0,255,255,0,39,255,171,2,171,2,188,0,38,0,120,16,0,0,38,0,16,42,0,1,7,0,223,1,124,254,193,0,58,0,184,0,0,69,88,184,0,11,47,27,185,0,11,0,14,62,89,184,0,0,69,88,184,0,15,47,27,185,0,15,0,14,62,89,184,0,0,69,88,184,0,18,47,27,185,0,18,0,6,62,89,184,0,26,208,48,49,0,0,255,255,0,36,255,171,2,182,2,188,0,38,0,120,13,0,0,38,0,16,39,0,1,7,0,113,1,165,254,192,0,54,0,184,0,0,69,88,184,0,11,47,27,185,0,11,0,14,62,89,184,0,0,69,88,184,0,15,47,27,185,0,15,0,14,62,89,184,0,0,69,88,184,0,16,47,27,185,0,16,0,6,62,89,48,49,0,0,255,255,0,32,255,171,3,83,2,194,0,38,0,114,13,0,0,39,0,16,0,212,0,0,1,7,0,223,2,36,254,193,0,58,0,184,0,0,69,88,184,0,25,47,27,185,0,25,0,14,62,89,184,0,0,69,88,184,0,42,47,27,185,0,42,0,14,62,89,184,0,0,69,88,184,0,45,47,27,185,0,45,0,6,62,89,184,0,53,208,48,49,0,2,0,62,255,6,1,173,1,244,0,36,0,40,1,65,186,0,21,0,29,0,3,43,186,0,1,0,21,0,29,17,18,57,184,0,1,47,65,5,0,31,0,1,0,47,0,1,0,2,113,184,0,0,220,184,0,29,16,184,0,10,220,65,7,0,63,0,10,0,79,0,10,0,95,0,10,0,3,113,186,0,39,0,29,0,21,17,18,57,184,0,39,47,185,0,40,0,4,244,0,184,0,0,69,88,184,0,37,47,27,185,0,37,0,12,62,89,184,0,0,69,88,184,0,24,47,27,185,0,24,0,8,62,89,184,0,37,16,184,0,40,220,65,3,0,48,0,40,0,1,113,184,0,0,220,184,0,24,16,185,0,15,0,1,244,184,0,24,16,184,0,20,220,48,49,1,65,3,0,118,0,8,0,1,93,65,3,0,135,0,8,0,1,93,65,7,0,54,0,22,0,70,0,22,0,86,0,22,0,3,93,65,3,0,9,0,26,0,1,93,65,7,0,105,0,27,0,121,0,27,0,137,0,27,0,3,93,65,3,0,40,0,33,0,1,93,65,3,0,25,0,33,0,1,93,0,65,3,0,120,0,8,0,1,93,65,3,0,137,0,8,0,1,93,65,7,0,57,0,22,0,73,0,22,0,89,0,22,0,3,93,65,3,0,9,0,26,0,1,93,65,3,0,104,0,27,0,1,93,65,3,0,136,0,27,0,1,93,65,3,0,22,0,33,0,1,93,65,3,0,39,0,33,0,1,93,19,51,22,21,20,14,4,21,20,30,2,51,50,62,2,55,23,14,1,35,34,46,2,53,52,54,63,1,62,1,47,1,51,21,35,233,59,3,22,34,38,34,22,21,35,46,26,22,42,36,26,5,25,19,86,54,47,77,54,30,35,25,50,26,36,1,18,91,91,1,44,41,4,31,53,49,47,49,55,32,30,46,31,16,13,20,24,11,67,29,38,33,52,67,35,35,76,32,65,33,65,30,227,86,0,0,0,255,255,0,7,0,0,2,97,3,173,2,38,0,34,0,0,1,7,0,65,0,157,0,209,0,70,65,5,0,64,0,12,0,80,0,12,0,2,113,65,3,0,16,0,12,0,1,93,65,3,0,112,0,12,0,1,93,65,3,0,48,0,12,0,1,93,0,65,3,0,47,0,11,0,1,93,65,3,0,31,0,11,0,1,113,65,3,0,255,0,11,0,1,93,48,49,255,255,0,7,0,0,2,97,3,173,2,38,0,34,0,0,1,7,0,115,0,157,0,209,0,48,65,3,0,159,0,12,0,1,93,65,3,0,15,0,12,0,1,93,65,3,0,79,0,12,0,1,93,65,3,0,16,0,12,0,1,93,0,65,3,0,47,0,12,0,1,93,48,49,0,0,255,255,0,7,0,0,2,97,3,186,2,38,0,34,0,0,1,7,0,203,0,86,0,209,0,39,65,3,0,79,0,14,0,1,93,65,3,0,143,0,14,0,1,93,65,3,0,16,0,14,0,1,93,0,65,3,0,47,0,14,0,1,93,48,49,0,0,0,255,255,0,7,0,0,2,97,3,143,2,38,0,34,0,0,1,7,0,206,0,44,0,209,0,39,65,3,0,15,0,19,0,1,93,65,3,0,47,0,19,0,1,113,65,3,0,47,0,19,0,1,93,0,65,3,0,47,0,11,0,1,93,48,49,0,0,0,255,255,0,7,0,0,2,97,3,141,2,38,0,34,0,0,1,7,0,104,0,98,0,209,0,77,184,0,16,47,65,3,0,15,0,16,0,1,113,65,5,0,79,0,16,0,95,0,16,0,2,93,65,3,0,16,0,16,0,1,93,65,3,0,64,0,16,0,1,113,184,0,12,208,0,184,0,15,47,65,3,0,47,0,15,0,1,93,65,3,0,175,0,15,0,1,93,184,0,12,208,48,49,0,255,255,0,7,0,0,2,97,3,196,2,38,0,34,0,0,1,7,0,205,0,163,0,209,0,91,184,0,14,47,65,3,0,15,0,14,0,1,93,65,3,0,47,0,14,0,1,93,65,3,0,112,0,14,0,1,93,184,0,26,208,0,184,0,25,47,65,3,0,111,0,25,0,1,93,65,3,0,47,0,25,0,1,93,65,3,0,15,0,25,0,1,113,65,3,0,32,0,25,0,1,113,65,3,0,224,0,25,0,1,93,184,0,29,208,48,49,0,0,0,0,2,255,249,0,0,3,60,2,188,0,15,0,18,1,163,186,0,0,0,1,0,3,43,65,3,0,64,0,0,0,1,93,65,3,0,176,0,0,0,1,93,65,3,0,96,0,0,0,1,93,65,3,0,223,0,1,0,1,93,184,0,1,16,184,0,16,208,184,0,1,16,184,0,5,208,65,3,0,89,0,5,0,1,93,65,3,0,9,0,5,0,1,93,65,3,0,245,0,5,0,1,93,185,0,4,0,4,244,186,0,3,0,16,0,4,17,18,57,65,3,0,138,0,3,0,1,93,184,0,16,16,184,0,6,208,65,3,0,139,0,6,0,1,93,65,3,0,42,0,6,0,1,113,65,3,0,249,0,6,0,1,93,65,5,0,9,0,6,0,25,0,6,0,2,113,184,0,0,16,184,0,8,208,184,0,8,47,184,0,1,16,184,0,14,220,65,5,0,96,0,14,0,112,0,14,0,2,113,65,7,0,208,0,14,0,224,0,14,0,240,0,14,0,3,93,65,7,0,0,0,14,0,16,0,14,0,32,0,14,0,3,113,65,9,0,80,0,14,0,96,0,14,0,112,0,14,0,128,0,14,0,4,93,184,0,10,208,184,0,0,16,184,0,12,208,184,0,12,47,186,0,18,0,16,0,4,17,18,57,65,3,0,22,0,18,0,1,113,0,184,0,0,69,88,184,0,6,47,27,185,0,6,0,14,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,186,0,16,0,1,0,6,17,18,57,184,0,16,47,185,0,2,0,2,244,184,0,1,16,184,0,4,208,184,0,6,16,185,0,9,0,2,244,186,0,10,0,6,0,1,17,18,57,184,0,10,47,185,0,13,0,2,244,184,0,1,16,185,0,14,0,2,244,184,0,9,16,184,0,17,208,48,49,1,65,5,0,105,0,6,0,121,0,6,0,2,93,65,3,0,117,0,18,0,1,93,41,1,53,35,7,35,1,33,21,33,21,51,21,35,21,33,37,17,3,3,60,254,76,214,92,93,1,86,1,227,254,200,241,241,1,66,254,76,171,180,180,2,188,87,204,86,237,186,1,83,254,173,0,255,255,0,39,255,64,2,71,2,202,2,38,0,36,0,0,0,6,0,119,96,0,0,0,255,255,0,80,0,0,2,4,3,173,2,38,0,38,0,0,1,7,0,65,0,126,0,209,0,74,65,7,0,48,0,13,0,64,0,13,0,80,0,13,0,3,93,65,3,0,47,0,13,0,1,93,65,3,0,80,0,13,0,1,113,65,3,0,48,0,13,0,1,113,0,65,3,0,47,0,12,0,1,93,65,3,0,31,0,12,0,1,113,65,3,0,255,0,12,0,1,93,48,49,255,255,0,80,0,0,2,4,3,173,2,38,0,38,0,0,1,7,0,115,0,125,0,209,0,60,65,7,0,143,0,14,0,159,0,14,0,175,0,14,0,3,93,65,3,0,255,0,14,0,1,93,65,3,0,15,0,14,0,1,113,65,5,0,48,0,14,0,64,0,14,0,2,113,0,65,3,0,47,0,13,0,1,93,48,49,0,0,255,255,0,80,0,0,2,4,3,186,2,38,0,38,0,0,1,7,0,203,0,53,0,209,0,30,65,3,0,143,0,15,0,1,93,65,3,0,16,0,15,0,1,93,0,65,3,0,47,0,15,0,1,93,48,49,255,255,0,80,0,0,2,4,3,141,2,38,0,38,0,0,1,7,0,104,0,65,0,209,0,55,184,0,17,47,65,3,0,143,0,17,0,1,93,65,3,0,175,0,17,0,1,93,184,0,13,208,0,184,0,16,47,65,3,0,47,0,16,0,1,93,65,3,0,175,0,16,0,1,93,184,0,13,208,48,49,0,0,0,255,255,0,35,0,0,0,222,3,173,2,38,0,42,0,0,1,7,0,65,255,233,0,209,0,86,65,5,0,239,0,5,0,255,0,5,0,2,93,65,3,0,15,0,5,0,1,113,65,3,0,0,0,5,0,1,93,65,11,0,48,0,5,0,64,0,5,0,80,0,5,0,96,0,5,0,112,0,5,0,5,93,0,65,3,0,47,0,4,0,1,93,65,3,0,31,0,4,0,1,113,65,3,0,255,0,4,0,1,93,48,49,255,255,0,36,0,0,0,223,3,173,2,38,0,42,0,0,1,7,0,115,255,234,0,209,0,12,0,65,3,0,47,0,5,0,1,93,48,49,0,0,255,255,255,240,0,0,1,22,3,186,2,38,0,42,0,0,1,7,0,203,255,164,0,209,0,47,65,3,0,143,0,7,0,1,93,65,7,0,80,0,7,0,96,0,7,0,112,0,7,0,3,93,65,3,0,32,0,7,0,1,113,0,65,3,0,47,0,7,0,1,93,48,49,0,0,0,255,255,0,5,0,0,0,253,3,141,2,38,0,42,0,0,1,7,0,104,255,174,0,209,0,59,184,0,9,47,65,3,0,175,0,9,0,1,93,65,5,0,64,0,9,0,80,0,9,0,2,113,184,0,5,208,0,184,0,8,47,65,3,0,47,0,8,0,1,93,65,3,0,175,0,8,0,1,93,184,0,5,208,48,49,0,0,0,0,2,255,245,0,0,2,175,2,188,0,16,0,31,1,145,186,0,12,0,1,0,3,43,65,3,0,127,0,1,0,1,93,65,3,0,47,0,1,0,1,113,65,3,0,16,0,1,0,1,93,184,0,1,16,184,0,3,208,184,0,3,47,184,0,1,16,184,0,5,208,65,5,0,16,0,12,0,32,0,12,0,2,93,65,3,0,128,0,12,0,1,93,65,3,0,192,0,12,0,1,93,65,3,0,64,0,12,0,1,93,65,3,0,224,0,12,0,1,93,65,3,0,16,0,12,0,1,113,184,0,1,16,185,0,23,0,4,244,184,0,19,208,184,0,23,16,184,0,21,208,184,0,21,47,184,0,12,16,185,0,27,0,4,244,0,184,0,0,69,88,184,0,7,47,27,185,0,7,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,186,0,19,0,7,0,0,17,18,57,184,0,19,47,65,3,0,47,0,19,0,1,93,65,3,0,15,0,19,0,1,93,65,3,0,95,0,19,0,1,93,185,0,22,0,1,244,184,0,2,208,184,0,19,16,184,0,5,208,184,0,7,16,185,0,17,0,2,244,184,0,0,16,185,0,24,0,2,244,48,49,1,65,3,0,86,0,9,0,1,93,65,3,0,103,0,9,0,1,93,65,3,0,86,0,10,0,1,93,65,3,0,119,0,10,0,1,93,65,3,0,87,0,14,0,1,93,65,3,0,86,0,15,0,1,93,65,5,0,103,0,15,0,119,0,15,0,2,93,0,65,5,0,86,0,9,0,102,0,9,0,2,93,65,3,0,87,0,10,0,1,93,65,3,0,119,0,10,0,1,93,65,3,0,88,0,14,0,1,93,65,3,0,120,0,15,0,1,93,65,3,0,105,0,15,0,1,93,65,3,0,90,0,15,0,1,93,41,1,17,35,53,51,17,33,50,30,2,21,20,14,2,3,35,21,51,21,35,21,51,50,54,53,52,46,2,1,86,255,0,97,97,1,0,76,127,92,50,50,90,127,78,166,133,133,166,118,125,32,61,91,1,57,64,1,67,49,90,130,81,81,129,91,49,2,102,237,64,226,140,123,61,98,68,37,0,255,255,0,80,0,0,2,112,3,143,2,38,0,47,0,0,1,7,0,206,0,87,0,209,0,25,65,5,0,144,0,18,0,160,0,18,0,2,93,0,65,3,0,47,0,10,0,1,93,48,49,0,255,255,0,39,255,242,2,217,3,173,2,38,0,48,0,0,1,7,0,65,0,233,0,209,0,30,0,65,3,0,47,0,38,0,1,93,65,3,0,31,0,38,0,1,113,65,3,0,255,0,38,0,1,93,48,49,255,255,0,39,255,242,2,217,3,173,2,38,0,48,0,0,1,7,0,115,0,232,0,209,0,48,65,3,0,239,0,40,0,1,93,65,3,0,15,0,40,0,1,93,65,3,0,175,0,40,0,1,93,65,3,0,32,0,40,0,1,93,0,65,3,0,47,0,39,0,1,93,48,49,0,0,255,255,0,39,255,242,2,217,3,186,2,38,0,48,0,0,1,7,0,203,0,161,0,209,0,34,65,3,0,15,0,41,0,1,93,65,5,0,16,0,41,0,32,0,41,0,2,93,0,65,3,0,47,0,41,0,1,93,48,49,255,255,0,39,255,242,2,217,3,143,2,38,0,48,0,0,1,7,0,206,0,119,0,209,0,30,65,3,0,15,0,46,0,1,93,65,3,0,63,0,46,0,1,93,0,65,3,0,47,0,38,0,1,93,48,49,255,255,0,39,255,242,2,217,3,141,2,38,0,48,0,0,1,7,0,104,0,173,0,209,0,59,184,0,43,47,65,3,0,95,0,43,0,1,93,65,5,0,16,0,43,0,32,0,43,0,2,93,184,0,39,208,0,184,0,42,47,65,3,0,47,0,42,0,1,93,65,3,0,175,0,42,0,1,93,184,0,39,208,48,49,0,0,0,0,1,0,61,0,119,1,122,1,179,0,11,0,109,184,0,4,47,65,3,0,239,0,4,0,1,93,65,5,0,0,0,4,0,16,0,4,0,2,93,184,0,0,220,186,0,5,0,4,0,0,17,18,57,184,0,4,16,184,0,6,208,184,0,0,16,184,0,10,208,186,0,11,0,0,0,4,17,18,57,0,184,0,3,47,184,0,1,208,184,0,3,16,184,0,7,220,186,0,2,0,3,0,7,17,18,57,186,0,8,0,7,0,3,17,18,57,184,0,9,208,48,49,37,7,39,7,39,55,39,55,23,55,23,7,1,122,36,123,122,36,123,123,36,122,123,36,124,155,36,123,123,36,122,122,36,123,123,36,122,0,3,0,39,255,226,2,217,2,204,0,23,0,33,0,43,3,133,186,0,19,0,7,0,3,43,65,3,0,15,0,7,0,1,93,65,5,0,79,0,7,0,95,0,7,0,2,93,65,3,0,32,0,19,0,1,93,65,5,0,176,0,19,0,192,0,19,0,2,93,65,5,0,224,0,19,0,240,0,19,0,2,93,65,5,0,112,0,19,0,128,0,19,0,2,93,65,3,0,32,0,19,0,1,113,186,0,2,0,7,0,19,17,18,57,184,0,2,16,184,0,3,208,186,0,5,0,7,0,19,17,18,57,65,3,0,121,0,5,0,1,93,184,0,5,16,184,0,4,208,65,3,0,25,0,4,0,1,93,186,0,14,0,19,0,7,17,18,57,184,0,14,16,184,0,15,208,65,3,0,138,0,15,0,1,93,186,0,17,0,19,0,7,17,18,57,65,3,0,118,0,17,0,1,93,184,0,17,16,184,0,16,208,65,3,0,57,0,16,0,1,93,184,0,19,16,185,0,32,0,4,244,184,0,7,16,185,0,39,0,4,244,186,0,24,0,32,0,39,17,18,57,186,0,25,0,39,0,32,17,18,57,65,5,0,54,0,25,0,70,0,25,0,2,93,65,7,0,6,0,25,0,22,0,25,0,38,0,25,0,3,113,65,5,0,117,0,25,0,133,0,25,0,2,93,186,0,41,0,39,0,32,17,18,57,186,0,42,0,32,0,39,17,18,57,65,3,0,122,0,42,0,1,93,65,3,0,139,0,42,0,1,93,65,5,0,57,0,42,0,73,0,42,0,2,93,65,7,0,9,0,42,0,25,0,42,0,41,0,42,0,3,113,65,3,0,15,0,44,0,1,93,0,184,0,0,69,88,184,0,12,47,27,185,0,12,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,186,0,2,0,0,0,12,17,18,57,184,0,3,208,184,0,3,47,186,0,5,0,0,0,12,17,18,57,186,0,14,0,12,0,0,17,18,57,65,7,0,6,0,14,0,22,0,14,0,38,0,14,0,3,113,184,0,12,16,184,0,15,208,184,0,15,47,186,0,17,0,12,0,0,17,18,57,184,0,12,16,185,0,34,0,2,244,184,0,0,16,185,0,27,0,2,244,186,0,24,0,34,0,27,17,18,57,65,3,0,138,0,24,0,1,93,65,7,0,9,0,24,0,25,0,24,0,41,0,24,0,3,113,65,3,0,121,0,24,0,1,93,186,0,25,0,27,0,34,17,18,57,186,0,41,0,27,0,34,17,18,57,65,7,0,6,0,41,0,22,0,41,0,38,0,41,0,3,113,65,5,0,118,0,41,0,134,0,41,0,2,93,186,0,42,0,34,0,27,17,18,57,48,49,1,65,3,0,105,0,4,0,1,93,65,3,0,137,0,4,0,1,93,65,3,0,90,0,4,0,1,93,65,3,0,89,0,9,0,1,93,65,3,0,121,0,9,0,1,93,65,5,0,88,0,10,0,104,0,10,0,2,93,65,3,0,137,0,14,0,1,93,65,3,0,86,0,17,0,1,93,65,5,0,86,0,21,0,102,0,21,0,2,93,65,3,0,117,0,22,0,1,93,65,3,0,86,0,22,0,1,93,65,3,0,103,0,24,0,1,93,65,3,0,138,0,30,0,1,93,65,3,0,133,0,37,0,1,93,65,3,0,105,0,41,0,1,93,65,3,0,89,0,42,0,1,93,0,65,3,0,90,0,2,0,1,93,65,3,0,85,0,9,0,1,93,65,3,0,118,0,9,0,1,93,65,3,0,101,0,10,0,1,93,65,3,0,86,0,10,0,1,93,65,3,0,86,0,14,0,1,93,65,3,0,135,0,14,0,1,93,65,3,0,87,0,17,0,1,93,65,3,0,88,0,21,0,1,93,65,3,0,105,0,21,0,1,93,65,3,0,90,0,22,0,1,93,65,3,0,122,0,22,0,1,93,65,3,0,107,0,24,0,1,93,65,3,0,136,0,37,0,1,93,65,3,0,101,0,41,0,1,93,65,3,0,87,0,42,0,1,93,5,34,39,7,35,55,38,53,52,62,2,51,50,23,55,51,7,22,21,20,14,2,19,1,22,51,50,62,2,53,52,39,34,14,2,21,20,23,1,38,1,127,91,85,42,93,73,106,52,91,127,75,86,86,31,92,61,111,51,91,128,104,254,209,69,55,58,89,60,30,238,57,88,60,31,55,1,45,66,12,43,61,105,113,162,83,134,95,52,42,44,89,111,167,81,133,95,52,2,48,254,69,29,41,74,101,60,126,147,41,74,101,60,98,95,1,185,28,0,0,0,255,255,0,72,255,242,2,140,3,173,0,38,0,54,0,0,1,7,0,65,0,211,0,209,0,56,65,3,0,47,0,23,0,1,93,65,7,0,48,0,23,0,64,0,23,0,80,0,23,0,3,93,0,65,3,0,47,0,22,0,1,93,65,3,0,31,0,22,0,1,113,65,3,0,255,0,22,0,1,93,48,49,0,0,255,255,0,72,255,242,2,140,3,173,0,38,0,54,0,0,1,7,0,115,0,211,0,209,0,47,65,3,0,15,0,23,0,1,93,65,7,0,175,0,24,0,191,0,24,0,207,0,24,0,3,93,65,3,0,15,0,24,0,1,113,0,65,3,0,47,0,22,0,1,93,48,49,0,0,0,255,255,0,72,255,242,2,140,3,186,0,38,0,54,0,0,1,7,0,203,0,139,0,209,0,39,65,3,0,15,0,25,0,1,93,65,3,0,143,0,25,0,1,93,65,3,0,32,0,25,0,1,113,0,65,3,0,47,0,25,0,1,93,48,49,0,0,0,255,255,0,72,255,242,2,140,3,141,0,38,0,54,0,0,1,7,0,104,0,152,0,209,0,64,184,0,27,47,65,3,0,15,0,27,0,1,93,65,3,0,16,0,27,0,1,93,65,3,0,80,0,27,0,1,113,184,0,23,208,0,184,0,26,47,65,3,0,47,0,26,0,1,93,65,3,0,175,0,26,0,1,93,184,0,23,208,48,49,0,0,255,255,255,253,0,0,2,57,3,173,2,38,0,58,0,0,1,7,0,115,0,144,0,209,0,52,65,5,0,239,0,11,0,255,0,11,0,2,93,65,3,0,15,0,11,0,1,93,65,3,0,175,0,11,0,1,93,65,3,0,32,0,11,0,1,93,0,65,3,0,47,0,10,0,1,93,48,49,0,0,0,2,0,80,0,0,2,36,2,188,0,16,0,27,1,80,186,0,11,0,2,0,3,43,65,5,0,0,0,2,0,16,0,2,0,2,93,65,3,0,143,0,2,0,1,93,65,3,0,144,0,2,0,1,93,65,3,0,112,0,2,0,1,93,184,0,2,16,185,0,1,0,4,244,184,0,18,208,184,0,5,208,65,3,0,192,0,11,0,1,93,65,3,0,80,0,11,0,1,93,65,3,0,112,0,11,0,1,93,65,5,0,0,0,11,0,16,0,11,0,2,93,65,3,0,224,0,11,0,1,93,65,3,0,32,0,11,0,1,113,184,0,11,16,185,0,22,0,4,244,0,184,0,0,69,88,184,0,4,47,27,185,0,4,0,14,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,186,0,0,0,4,0,1,17,18,57,184,0,0,47,65,7,0,15,0,0,0,31,0,0,0,47,0,0,0,3,113,65,3,0,143,0,0,0,1,93,65,3,0,47,0,0,0,1,93,186,0,5,0,4,0,1,17,18,57,184,0,5,47,185,0,17,0,2,244,184,0,0,16,185,0,18,0,2,244,48,49,1,65,5,0,118,0,8,0,134,0,8,0,2,93,65,7,0,102,0,9,0,118,0,9,0,134,0,9,0,3,93,65,3,0,7,0,9,0,1,93,0,65,3,0,116,0,8,0,1,93,65,3,0,133,0,8,0,1,93,65,3,0,5,0,9,0,1,93,65,3,0,101,0,9,0,1,93,65,3,0,135,0,9,0,1,93,55,21,35,17,51,21,51,50,30,2,21,20,14,2,35,3,17,51,50,54,53,52,46,2,35,180,100,100,124,49,88,67,40,41,64,76,35,152,134,73,62,16,38,63,46,125,125,2,188,120,15,47,86,70,68,91,55,23,1,114,254,227,77,71,37,53,32,15,0,1,0,16,255,120,2,39,2,238,0,62,2,25,186,0,58,0,31,0,3,43,65,3,0,0,0,31,0,1,93,65,3,0,31,0,31,0,1,113,65,3,0,80,0,31,0,1,93,65,3,0,32,0,31,0,1,93,184,0,31,16,185,0,30,0,4,244,65,3,0,32,0,58,0,1,93,65,3,0,160,0,58,0,1,93,65,3,0,80,0,58,0,1,113,65,11,0,64,0,58,0,80,0,58,0,96,0,58,0,112,0,58,0,128,0,58,0,5,93,65,3,0,0,0,58,0,1,93,65,3,0,48,0,58,0,1,113,184,0,58,16,185,0,9,0,4,244,186,0,3,0,30,0,9,17,18,57,184,0,3,47,186,0,16,0,30,0,9,17,18,57,184,0,16,47,186,0,46,0,58,0,31,17,18,57,184,0,46,47,185,0,21,0,4,244,184,0,31,16,184,0,35,208,184,0,33,220,184,0,16,16,185,0,51,0,4,244,0,184,0,30,47,184,0,0,69,88,184,0,41,47,27,185,0,41,0,18,62,89,184,0,0,69,88,184,0,34,47,27,185,0,34,0,12,62,89,184,0,0,69,88,184,0,3,47,27,185,0,3,0,6,62,89,185,0,4,0,1,244,186,0,16,0,41,0,3,17,18,57,25,184,0,16,47,24,184,0,41,16,185,0,26,0,2,244,184,0,34,16,185,0,33,0,1,244,184,0,16,16,184,0,51,208,48,49,1,65,3,0,72,0,12,0,1,93,65,3,0,73,0,19,0,1,93,65,3,0,138,0,19,0,1,93,65,3,0,123,0,19,0,1,93,65,3,0,9,0,38,0,1,93,65,3,0,7,0,43,0,1,93,65,3,0,39,0,43,0,1,93,65,5,0,6,0,44,0,22,0,44,0,2,93,65,3,0,54,0,49,0,1,93,65,7,0,87,0,55,0,103,0,55,0,119,0,55,0,3,93,65,3,0,7,0,60,0,1,93,65,3,0,6,0,61,0,1,93,0,65,3,0,119,0,19,0,1,93,65,3,0,5,0,38,0,1,93,65,3,0,6,0,43,0,1,93,65,3,0,38,0,43,0,1,93,65,5,0,7,0,44,0,23,0,44,0,2,93,65,3,0,57,0,49,0,1,93,65,3,0,101,0,55,0,1,93,65,3,0,86,0,55,0,1,93,65,3,0,119,0,56,0,1,93,65,3,0,8,0,60,0,1,93,65,3,0,9,0,61,0,1,93,5,34,38,39,53,50,62,2,53,52,46,4,53,52,62,2,53,52,46,2,35,34,6,21,17,35,17,35,55,51,53,52,62,2,51,50,30,2,21,20,14,2,21,20,30,4,21,20,14,2,1,72,18,20,12,42,68,46,25,25,38,44,38,25,33,41,33,16,27,36,20,54,52,90,85,12,73,31,54,72,41,35,68,53,32,31,36,31,24,36,42,36,24,38,62,81,10,2,1,77,3,13,29,27,28,47,41,35,33,30,15,18,42,51,63,39,26,33,20,7,51,71,253,84,2,44,70,87,42,64,44,23,18,39,62,45,45,69,50,34,10,8,23,29,38,47,56,34,42,58,36,17,0,255,255,0,24,255,246,1,216,2,220,2,38,0,66,0,0,1,6,0,65,89,0,0,29,65,3,0,0,0,45,0,1,93,65,3,0,80,0,45,0,1,113,65,3,0,160,0,45,0,1,93,48,49,0,0,0,255,255,0,24,255,246,1,216,2,220,2,38,0,66,0,0,1,6,0,115,88,0,0,29,65,3,0,127,0,46,0,1,93,65,3,0,255,0,46,0,1,93,65,3,0,80,0,46,0,1,113,48,49,0,0,0,255,255,0,24,255,246,1,216,2,233,2,38,0,66,0,0,1,6,0,203,17,0,0,24,65,5,0,127,0,47,0,143,0,47,0,2,93,65,3,0,223,0,47,0,1,93,48,49,255,255,0,24,255,246,1,216,2,190,2,38,0,66,0,0,1,6,0,206,228,0,0,29,65,3,0,255,0,52,0,1,93,65,3,0,32,0,52,0,1,93,65,3,0,64,0,52,0,1,93,48,49,0,0,0,255,255,0,24,255,246,1,216,2,188,2,38,0,66,0,0,1,6,0,104,29,0,0,62,184,0,49,47,65,3,0,160,0,49,0,1,93,65,7,0,95,0,49,0,111,0,49,0,127,0,49,0,3,93,65,3,0,64,0,49,0,1,113,65,7,0,192,0,49,0,208,0,49,0,224,0,49,0,3,93,184,0,45,208,48,49,0,0,255,255,0,24,255,246,1,216,2,243,2,38,0,66,0,0,1,6,0,205,95,0,0,37,184,0,47,47,65,3,0,0,0,47,0,1,93,65,3,0,160,0,47,0,1,93,65,3,0,64,0,47,0,1,93,184,0,59,208,48,49,0,0,0,0,3,0,22,255,242,3,0,1,244,0,45,0,50,0,65,3,170,186,0,43,0,20,0,3,43,65,3,0,255,0,20,0,1,93,65,3,0,15,0,20,0,1,113,65,5,0,63,0,20,0,79,0,20,0,2,93,65,3,0,79,0,20,0,1,113,65,5,0,191,0,20,0,207,0,20,0,2,93,65,7,0,111,0,20,0,127,0,20,0,143,0,20,0,3,93,65,3,0,160,0,43,0,1,93,65,3,0,48,0,43,0,1,113,65,3,0,224,0,43,0,1,93,65,5,0,64,0,43,0,80,0,43,0,2,93,65,3,0,0,0,43,0,1,93,186,0,63,0,20,0,43,17,18,57,184,0,63,47,185,0,1,0,4,244,186,0,10,0,63,0,43,17,18,57,184,0,10,47,186,0,14,0,1,0,63,17,18,57,184,0,63,16,184,0,22,208,186,0,28,0,20,0,1,17,18,57,184,0,28,47,186,0,35,0,63,0,1,17,18,57,184,0,1,16,184,0,48,208,184,0,43,16,185,0,49,0,4,244,184,0,20,16,185,0,56,0,4,244,0,184,0,0,69,88,184,0,30,47,27,185,0,30,0,12,62,89,184,0,0,69,88,184,0,40,47,27,185,0,40,0,12,62,89,184,0,0,69,88,184,0,12,47,27,185,0,12,0,6,62,89,184,0,0,69,88,184,0,17,47,27,185,0,17,0,6,62,89,186,0,1,0,40,0,12,17,18,57,184,0,1,47,65,5,0,144,0,1,0,160,0,1,0,2,93,65,5,0,16,0,1,0,32,0,1,0,2,93,184,0,12,16,185,0,4,0,1,244,184,0,12,16,184,0,9,220,186,0,14,0,12,0,40,17,18,57,186,0,22,0,30,0,17,17,18,57,184,0,22,47,65,3,0,0,0,22,0,1,93,184,0,30,16,185,0,25,0,2,244,184,0,30,16,184,0,27,220,186,0,35,0,40,0,12,17,18,57,65,3,0,135,0,35,0,1,93,184,0,40,16,185,0,46,0,2,244,184,0,1,16,184,0,48,220,65,15,0,159,0,48,0,175,0,48,0,191,0,48,0,207,0,48,0,223,0,48,0,239,0,48,0,255,0,48,0,7,93,184,0,22,16,184,0,51,220,65,15,0,144,0,51,0,160,0,51,0,176,0,51,0,192,0,51,0,208,0,51,0,224,0,51,0,240,0,51,0,7,93,184,0,17,16,185,0,58,0,1,244,48,49,1,65,5,0,52,0,3,0,68,0,3,0,2,93,65,5,0,89,0,13,0,105,0,13,0,2,93,65,5,0,85,0,15,0,101,0,15,0,2,93,65,3,0,72,0,18,0,1,93,65,3,0,26,0,19,0,1,93,65,3,0,43,0,19,0,1,93,65,3,0,120,0,21,0,1,93,65,3,0,137,0,21,0,1,93,65,3,0,120,0,23,0,1,93,65,9,0,87,0,28,0,103,0,28,0,119,0,28,0,135,0,28,0,4,93,65,3,0,134,0,33,0,1,93,65,3,0,135,0,41,0,1,93,65,3,0,133,0,42,0,1,93,65,3,0,101,0,54,0,1,93,65,3,0,86,0,54,0,1,93,0,65,3,0,72,0,3,0,1,93,65,9,0,91,0,10,0,107,0,10,0,123,0,10,0,139,0,10,0,4,93,65,9,0,91,0,11,0,107,0,11,0,123,0,11,0,139,0,11,0,4,93,65,3,0,89,0,13,0,1,93,65,3,0,106,0,13,0,1,93,65,3,0,25,0,18,0,1,93,65,3,0,105,0,18,0,1,93,65,7,0,58,0,18,0,74,0,18,0,90,0,18,0,3,93,65,3,0,134,0,21,0,1,93,65,3,0,119,0,21,0,1,93,65,3,0,88,0,23,0,1,93,65,3,0,121,0,23,0,1,93,65,3,0,106,0,23,0,1,93,65,9,0,84,0,28,0,100,0,28,0,116,0,28,0,132,0,28,0,4,93,65,9,0,86,0,29,0,102,0,29,0,118,0,29,0,134,0,29,0,4,93,65,3,0,134,0,33,0,1,93,65,3,0,101,0,35,0,1,93,65,3,0,101,0,37,0,1,93,65,3,0,133,0,41,0,1,93,65,3,0,135,0,42,0,1,93,65,3,0,104,0,54,0,1,93,37,33,20,22,51,50,62,2,55,23,6,35,34,39,14,1,35,34,38,53,52,37,46,1,35,34,7,39,54,51,50,30,2,23,62,3,51,50,22,21,20,6,39,34,7,51,52,5,34,14,2,21,20,51,50,62,2,53,52,38,2,252,254,176,90,75,18,26,29,35,26,17,87,76,148,53,26,110,72,75,75,1,45,9,53,56,53,69,8,84,72,20,50,47,36,6,10,37,49,59,32,88,103,2,193,107,30,246,254,161,36,76,64,41,78,28,51,39,23,1,245,90,93,3,9,14,11,69,40,113,57,60,69,63,174,15,61,52,29,70,39,11,27,46,36,31,45,30,14,104,96,11,28,159,113,113,175,12,29,45,33,64,17,34,51,34,14,24,255,255,0,33,255,64,1,171,1,244,2,38,0,68,0,0,1,6,0,119,48,0,0,19,65,7,0,32,0,28,0,48,0,28,0,64,0,28,0,3,93,48,49,0,255,255,0,31,255,246,1,226,2,220,2,38,0,70,0,0,1,6,0,65,103,0,0,24,65,5,0,239,0,32,0,255,0,32,0,2,93,65,3,0,80,0,32,0,1,113,48,49,255,255,0,31,255,246,1,226,2,220,2,38,0,70,0,0,1,6,0,115,104,0,0,24,65,3,0,79,0,33,0,1,93,65,5,0,223,0,33,0,239,0,33,0,2,93,48,49,255,255,0,31,255,246,1,226,2,233,2,38,0,70,0,0,1,6,0,203,32,0,0,33,65,3,0,15,0,34,0,1,93,65,5,0,63,0,34,0,79,0,34,0,2,93,65,3,0,144,0,34,0,1,93,48,49,0,0,0,255,255,0,31,255,246,1,226,2,188,2,38,0,70,0,0,1,6,0,104,44,0,0,19,184,0,36,47,65,3,0,47,0,36,0,1,113,184,0,32,208,48,49,0,255,255,0,13,0,0,0,200,2,220,2,38,0,193,0,0,1,6,0,65,211,0,0,56,65,3,0,0,0,5,0,1,93,65,3,0,255,0,5,0,1,93,65,3,0,143,0,5,0,1,93,65,3,0,223,0,5,0,1,93,65,3,0,80,0,5,0,1,113,65,3,0,32,0,5,0,1,93,48,49,255,255,0,14,0,0,0,201,2,220,2,38,0,193,0,0,1,6,0,115,212,0,0,55,65,3,0,223,0,6,0,1,93,65,5,0,63,0,6,0,79,0,6,0,2,93,65,3,0,255,0,6,0,1,93,65,5,0,143,0,6,0,159,0,6,0,2,93,65,3,0,32,0,6,0,1,93,48,49,0,255,255,255,217,0,0,0,255,2,233,2,38,0,193,0,0,1,6,0,203,141,0,0,29,65,3,0,223,0,7,0,1,93,65,3,0,32,0,7,0,1,93,65,3,0,143,0,8,0,1,93,48,49,0,0,0,255,255,255,239,0,0,0,231,2,188,2,38,0,193,0,0,1,6,0,104,152,0,0,55,184,0,9,47,65,3,0,15,0,9,0,1,113,65,3,0,143,0,9,0,1,93,65,3,0,63,0,9,0,1,113,65,3,0,32,0,9,0,1,93,65,3,0,224,0,9,0,1,93,184,0,5,208,48,49,0,0,2,0,28,255,244,1,228,2,198,0,41,0,57,2,47,186,0,37,0,5,0,3,43,65,3,0,207,0,5,0,1,93,65,3,0,79,0,5,0,1,93,65,3,0,143,0,5,0,1,93,65,3,0,111,0,5,0,1,93,65,3,0,112,0,37,0,1,93,65,3,0,16,0,37,0,1,93,65,3,0,16,0,37,0,1,113,65,3,0,80,0,37,0,1,93,184,0,37,16,185,0,55,0,4,244,184,0,12,208,186,0,24,0,5,0,37,17,18,57,184,0,24,47,186,0,22,0,24,0,12,17,18,57,186,0,32,0,37,0,24,17,18,57,65,3,0,54,0,32,0,1,93,186,0,17,0,22,0,32,17,18,57,184,0,22,16,184,0,20,208,184,0,20,47,186,0,27,0,22,0,32,17,18,57,65,3,0,55,0,27,0,1,93,65,3,0,86,0,27,0,1,93,65,3,0,69,0,27,0,1,93,184,0,32,16,184,0,30,208,184,0,30,47,184,0,5,16,185,0,47,0,4,244,0,184,0,0,69,88,184,0,25,47,27,185,0,25,0,14,62,89,184,0,0,69,88,184,0,29,47,27,185,0,29,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,65,3,0,200,0,5,0,1,93,184,0,10,220,186,0,17,0,10,0,25,17,18,57,184,0,17,16,184,0,19,208,184,0,19,47,186,0,27,0,25,0,10,17,18,57,65,3,0,55,0,27,0,1,93,65,5,0,70,0,27,0,86,0,27,0,2,93,186,0,22,0,27,0,17,17,18,57,184,0,25,16,184,0,24,220,186,0,32,0,17,0,27,17,18,57,184,0,10,16,185,0,42,0,2,244,184,0,0,16,185,0,52,0,2,244,48,49,1,65,3,0,121,0,2,0,1,93,65,3,0,107,0,2,0,1,93,65,5,0,105,0,8,0,121,0,8,0,2,93,65,3,0,103,0,11,0,1,93,65,3,0,120,0,11,0,1,93,65,3,0,136,0,17,0,1,93,65,3,0,135,0,18,0,1,93,65,3,0,119,0,40,0,1,93,0,65,3,0,122,0,2,0,1,93,65,3,0,107,0,2,0,1,93,65,5,0,102,0,8,0,118,0,8,0,2,93,65,3,0,115,0,11,0,1,93,65,3,0,100,0,11,0,1,93,65,3,0,133,0,11,0,1,93,65,3,0,140,0,17,0,1,93,65,3,0,138,0,18,0,1,93,65,3,0,121,0,40,0,1,93,65,3,0,106,0,40,0,1,93,23,34,46,2,53,52,62,2,51,50,23,46,3,39,6,7,39,54,55,38,35,55,50,23,54,55,23,6,7,30,3,21,20,14,2,3,34,14,2,21,20,30,2,51,50,54,53,52,38,249,48,81,59,33,28,53,79,51,86,49,4,16,23,28,15,77,64,30,65,63,60,61,32,72,77,31,28,46,23,46,32,53,37,21,43,68,84,35,29,46,33,18,18,33,46,28,54,66,65,12,32,57,78,46,42,81,63,39,55,24,55,53,45,12,53,9,55,9,43,54,42,55,28,36,12,33,51,29,81,94,102,51,77,104,62,26,1,99,21,37,48,27,30,50,38,21,77,60,60,75,0,0,0,255,255,0,61,0,0,1,247,2,190,2,38,0,79,0,0,1,6,0,206,15,0,0,11,65,3,0,255,0,25,0,1,93,48,49,0,255,255,0,32,255,246,2,6,2,220,2,38,0,80,0,0,1,6,0,65,123,0,0,24,65,3,0,47,0,33,0,1,113,65,5,0,64,0,33,0,80,0,33,0,2,93,48,49,255,255,0,32,255,246,2,6,2,220,2,38,0,80,0,0,1,6,0,115,123,0,0,51,65,3,0,255,0,34,0,1,93,65,3,0,15,0,34,0,1,113,65,3,0,63,0,34,0,1,93,65,3,0,191,0,34,0,1,93,65,5,0,143,0,34,0,159,0,34,0,2,93,48,49,0,255,255,0,32,255,246,2,6,2,233,2,38,0,80,0,0,1,6,0,203,52,0,0,29,65,3,0,15,0,35,0,1,93,65,3,0,32,0,35,0,1,93,65,3,0,160,0,35,0,1,93,48,49,0,0,0,255,255,0,32,255,246,2,6,2,190,2,38,0,80,0,0,1,6,0,206,10,0,0,24,65,5,0,15,0,40,0,31,0,40,0,2,93,65,3,0,47,0,40,0,1,113,48,49,255,255,0,32,255,246,2,6,2,188,2,38,0,80,0,0,1,6,0,104,64,0,0,28,184,0,37,47,65,3,0,143,0,37,0,1,93,65,3,0,32,0,37,0,1,93,184,0,33,208,48,49,0,3,0,66,0,20,2,14,2,22,0,3,0,7,0,11,0,76,184,0,10,47,184,0,11,220,184,0,0,208,184,0,10,16,184,0,1,208,184,0,11,16,184,0,4,220,184,0,10,16,184,0,5,220,0,184,0,5,47,184,0,6,220,184,0,2,220,184,0,1,220,184,0,5,16,184,0,9,220,65,3,0,191,0,9,0,1,93,184,0,10,220,48,49,1,35,53,51,19,33,53,33,3,35,53,51,1,80,89,89,190,254,52,1,204,190,89,89,1,184,94,254,223,74,254,213,94,0,0,3,0,33,255,216,2,27,2,17,0,23,0,36,0,46,2,114,186,0,19,0,7,0,3,43,65,3,0,143,0,7,0,1,93,65,3,0,31,0,7,0,1,93,65,3,0,175,0,7,0,1,93,65,3,0,111,0,7,0,1,93,65,5,0,63,0,7,0,79,0,7,0,2,93,65,3,0,80,0,19,0,1,93,65,3,0,144,0,19,0,1,93,65,3,0,224,0,19,0,1,93,65,3,0,32,0,19,0,1,113,65,3,0,0,0,19,0,1,113,65,3,0,192,0,19,0,1,93,65,3,0,112,0,19,0,1,93,65,3,0,32,0,19,0,1,93,65,3,0,0,0,19,0,1,93,186,0,2,0,7,0,19,17,18,57,186,0,5,0,7,0,19,17,18,57,186,0,14,0,19,0,7,17,18,57,186,0,17,0,19,0,7,17,18,57,184,0,19,16,185,0,32,0,4,244,184,0,7,16,185,0,42,0,4,244,186,0,24,0,32,0,42,17,18,57,186,0,25,0,42,0,32,17,18,57,65,3,0,102,0,25,0,1,93,65,3,0,134,0,25,0,1,93,186,0,44,0,42,0,32,17,18,57,186,0,45,0,32,0,42,17,18,57,65,3,0,105,0,45,0,1,93,65,3,0,137,0,45,0,1,93,65,3,0,128,0,48,0,1,93,0,184,0,0,69,88,184,0,12,47,27,185,0,12,0,12,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,186,0,2,0,0,0,12,17,18,57,184,0,3,208,184,0,3,47,186,0,5,0,0,0,12,17,18,57,186,0,14,0,12,0,0,17,18,57,184,0,12,16,184,0,15,208,184,0,15,47,65,3,0,144,0,15,0,1,93,186,0,17,0,12,0,0,17,18,57,184,0,12,16,185,0,37,0,1,244,184,0,0,16,185,0,27,0,1,244,186,0,24,0,37,0,27,17,18,57,65,3,0,137,0,24,0,1,93,65,3,0,105,0,24,0,1,93,65,3,0,38,0,24,0,1,93,186,0,25,0,27,0,37,17,18,57,186,0,44,0,27,0,37,17,18,57,65,3,0,102,0,44,0,1,93,65,3,0,134,0,44,0,1,93,186,0,45,0,37,0,27,17,18,57,48,49,1,65,3,0,92,0,6,0,1,93,65,3,0,90,0,10,0,1,93,65,3,0,86,0,17,0,1,93,65,3,0,85,0,22,0,1,93,65,3,0,73,0,24,0,1,93,65,3,0,70,0,25,0,1,93,65,3,0,87,0,25,0,1,93,65,3,0,74,0,30,0,1,93,65,3,0,69,0,39,0,1,93,65,5,0,73,0,45,0,89,0,45,0,2,93,0,65,3,0,85,0,10,0,1,93,65,3,0,86,0,17,0,1,93,65,3,0,91,0,22,0,1,93,65,3,0,87,0,25,0,1,93,5,34,39,7,35,55,38,53,52,62,2,51,50,23,55,51,7,22,21,20,14,2,19,3,22,51,50,62,2,53,52,46,2,39,34,14,2,21,20,23,19,38,1,30,33,53,19,71,32,109,35,66,93,58,36,48,19,74,34,111,35,66,94,51,163,42,13,37,58,39,21,6,12,17,123,36,57,40,21,46,161,38,13,11,38,66,81,137,54,94,69,40,12,40,66,84,136,54,94,69,39,1,150,254,182,6,29,50,68,39,21,46,41,33,47,28,50,69,41,68,80,1,73,7,255,255,0,56,255,246,1,207,2,220,2,38,0,86,0,0,1,6,0,65,127,0,0,37,65,3,0,255,0,17,0,1,93,65,7,0,48,0,17,0,64,0,17,0,80,0,17,0,3,93,65,3,0,176,0,17,0,1,93,48,49,0,0,0,255,255,0,56,255,246,1,207,2,220,2,38,0,86,0,0,1,6,0,115,127,0,0,59,65,3,0,255,0,17,0,1,93,65,3,0,15,0,17,0,1,113,65,5,0,15,0,17,0,31,0,17,0,2,93,65,3,0,223,0,17,0,1,93,65,7,0,143,0,17,0,159,0,17,0,175,0,17,0,3,93,48,49,0,255,255,0,56,255,246,1,207,2,233,2,38,0,86,0,0,1,6,0,203,56,0,0,56,65,3,0,32,0,19,0,1,113,65,3,0,223,0,19,0,1,93,65,3,0,143,0,19,0,1,93,65,3,0,32,0,19,0,1,93,65,3,0,144,0,19,0,1,93,65,3,0,80,0,19,0,1,93,48,49,255,255,0,56,255,246,1,207,2,188,2,38,0,86,0,0,1,6,0,104,68,0,0,46,184,0,21,47,65,3,0,32,0,21,0,1,93,65,3,0,143,0,21,0,1,93,65,3,0,0,0,21,0,1,113,65,3,0,224,0,21,0,1,93,184,0,17,208,48,49,0,0,255,255,0,7,255,14,1,242,2,220,2,38,0,90,0,0,1,6,0,115,101,0,0,11,65,3,0,79,0,9,0,1,93,48,49,0,0,2,0,60,255,15,2,36,2,238,0,18,0,30,1,158,186,0,14,0,4,0,3,43,65,3,0,255,0,4,0,1,93,65,3,0,223,0,4,0,1,93,65,3,0,31,0,4,0,1,113,65,3,0,0,0,4,0,1,93,65,3,0,32,0,4,0,1,93,184,0,4,16,185,0,3,0,4,244,184,0,6,208,65,17,0,0,0,14,0,16,0,14,0,32,0,14,0,48,0,14,0,64,0,14,0,80,0,14,0,96,0,14,0,112,0,14,0,8,93,65,3,0,0,0,14,0,1,113,65,3,0,144,0,14,0,1,93,65,5,0,32,0,14,0,48,0,14,0,2,113,65,3,0,80,0,14,0,1,113,184,0,3,16,184,0,19,208,184,0,14,16,185,0,25,0,4,244,65,3,0,64,0,32,0,1,93,65,3,0,96,0,32,0,1,93,65,3,0,128,0,32,0,1,93,0,184,0,0,69,88,184,0,6,47,27,185,0,6,0,18,62,89,184,0,0,69,88,184,0,9,47,27,185,0,9,0,12,62,89,184,0,0,69,88,184,0,3,47,27,185,0,3,0,8,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,186,0,2,0,0,0,9,17,18,57,186,0,7,0,9,0,0,17,18,57,185,0,22,0,1,244,184,0,9,16,185,0,28,0,2,244,48,49,1,65,3,0,105,0,1,0,1,93,65,3,0,102,0,11,0,1,93,65,3,0,87,0,11,0,1,93,65,3,0,102,0,17,0,1,93,65,3,0,87,0,17,0,1,93,0,65,3,0,105,0,1,0,1,93,65,3,0,91,0,1,0,1,93,65,5,0,85,0,8,0,101,0,8,0,2,93,65,3,0,86,0,11,0,1,93,65,3,0,103,0,11,0,1,93,65,5,0,89,0,17,0,105,0,17,0,2,93,65,3,0,149,0,29,0,1,93,5,34,39,17,35,17,51,17,54,51,50,30,2,21,20,14,2,39,20,22,51,50,54,53,52,38,35,34,6,1,46,103,49,90,90,62,96,55,88,63,34,33,63,92,217,74,77,78,85,85,78,78,73,10,66,254,215,3,223,254,200,62,40,69,93,53,53,93,69,40,255,82,101,101,82,81,94,94,255,255,0,7,255,14,1,242,2,188,2,38,0,90,0,0,1,6,0,104,40,0,0,28,184,0,13,47,65,3,0,15,0,13,0,1,93,65,3,0,63,0,13,0,1,93,184,0,9,208,48,49,255,255,0,39,255,242,2,71,3,181,2,38,0,36,0,0,1,7,0,204,0,178,0,209,0,34,65,5,0,0,0,41,0,16,0,41,0,2,93,65,3,0,176,0,41,0,1,93,0,65,3,0,47,0,40,0,1,93,48,49,255,255,0,33,255,246,1,171,2,228,2,38,0,68,0,0,1,6,0,204,45,0,0,20,65,3,0,31,0,28,0,1,93,65,3,0,32,0,28,0,1,93,48,49,0,1,0,61,0,0,0,151,1,234,0,3,0,119,187,0,3,0,4,0,2,0,4,43,65,3,0,63,0,2,0,1,113,65,3,0,143,0,2,0,1,93,65,3,0,223,0,2,0,1,93,65,3,0,32,0,2,0,1,93,65,3,0,63,0,3,0,1,113,65,3,0,143,0,3,0,1,93,65,3,0,223,0,3,0,1,93,65,3,0,32,0,3,0,1,93,0,184,0,0,69,88,184,0,3,47,27,185,0,3,0,12,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,48,49,51,35,17,51,151,90,90,1,234,0,0,0,2,0,40,255,242,4,10,2,202,0,28,0,48,2,150,186,0,28,0,1,0,3,43,65,3,0,176,0,1,0,1,93,184,0,1,16,184,0,10,208,184,0,10,47,65,5,0,63,0,10,0,79,0,10,0,2,93,65,3,0,159,0,10,0,1,93,65,3,0,47,0,10,0,1,113,65,3,0,111,0,10,0,1,93,65,3,0,15,0,10,0,1,93,65,3,0,191,0,10,0,1,93,184,0,1,16,184,0,18,208,65,3,0,176,0,28,0,1,93,184,0,28,16,184,0,21,208,184,0,21,47,184,0,1,16,185,0,27,0,4,244,184,0,23,208,184,0,28,16,184,0,25,208,184,0,25,47,184,0,10,16,185,0,34,0,4,244,184,0,1,16,184,0,44,208,65,3,0,137,0,44,0,1,93,65,7,0,9,0,44,0,25,0,44,0,41,0,44,0,3,113,65,3,0,169,0,44,0,1,93,65,3,0,72,0,44,0,1,93,0,184,0,0,69,88,184,0,15,47,27,185,0,15,0,14,62,89,184,0,0,69,88,184,0,19,47,27,185,0,19,0,14,62,89,184,0,0,69,88,184,0,5,47,27,185,0,5,0,6,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,186,0,2,0,5,0,15,17,18,57,65,3,0,92,0,2,0,1,93,65,7,0,12,0,2,0,28,0,2,0,44,0,2,0,3,113,65,3,0,107,0,2,0,1,93,65,5,0,122,0,2,0,138,0,2,0,2,93,65,3,0,66,0,10,0,1,93,186,0,18,0,15,0,5,17,18,57,65,3,0,100,0,18,0,1,93,65,3,0,118,0,18,0,1,93,65,3,0,133,0,18,0,1,93,65,3,0,83,0,18,0,1,93,65,7,0,3,0,18,0,19,0,18,0,35,0,18,0,3,113,184,0,19,16,185,0,22,0,2,244,186,0,23,0,19,0,1,17,18,57,184,0,23,47,185,0,26,0,2,244,184,0,1,16,185,0,27,0,2,244,184,0,15,16,185,0,29,0,2,244,184,0,5,16,185,0,39,0,2,244,48,49,1,65,3,0,120,0,3,0,1,93,65,7,0,89,0,7,0,105,0,7,0,121,0,7,0,3,93,65,3,0,90,0,8,0,1,93,65,3,0,89,0,12,0,1,93,65,3,0,121,0,12,0,1,93,65,3,0,104,0,13,0,1,93,65,3,0,89,0,13,0,1,93,65,3,0,120,0,17,0,1,93,0,65,5,0,89,0,3,0,105,0,3,0,2,93,65,3,0,122,0,3,0,1,93,65,5,0,104,0,7,0,120,0,7,0,2,93,65,3,0,89,0,7,0,1,93,65,3,0,88,0,8,0,1,93,65,3,0,86,0,12,0,1,93,65,3,0,118,0,12,0,1,93,65,5,0,86,0,13,0,102,0,13,0,2,93,65,3,0,84,0,17,0,1,93,65,5,0,102,0,17,0,118,0,17,0,2,93,65,3,0,114,0,18,0,1,93,41,1,53,14,1,35,34,46,2,53,52,62,2,51,50,22,23,53,33,21,33,21,51,21,35,21,33,1,34,14,2,21,20,30,2,51,50,62,2,53,52,46,2,4,10,254,102,69,115,62,75,124,90,49,50,90,124,74,62,115,69,1,145,254,202,238,238,1,63,253,112,58,89,60,31,30,60,89,59,58,89,60,30,31,60,89,83,53,44,52,96,134,82,82,135,95,52,44,53,82,85,205,86,237,2,30,41,74,102,61,60,102,74,42,42,74,102,60,61,102,74,41,0,3,0,32,255,246,3,104,1,244,0,43,0,49,0,61,3,73,186,0,42,0,22,0,3,43,65,9,0,63,0,22,0,79,0,22,0,95,0,22,0,111,0,22,0,4,93,65,3,0,207,0,22,0,1,93,65,5,0,96,0,42,0,112,0,42,0,2,93,65,3,0,240,0,42,0,1,93,65,7,0,16,0,42,0,32,0,42,0,48,0,42,0,3,113,65,7,0,144,0,42,0,160,0,42,0,176,0,42,0,3,93,65,3,0,64,0,42,0,1,93,65,5,0,0,0,42,0,16,0,42,0,2,93,186,0,59,0,22,0,42,17,18,57,184,0,59,47,185,0,1,0,4,244,184,0,42,16,184,0,9,208,184,0,9,47,186,0,14,0,1,0,59,17,18,57,186,0,32,0,59,0,1,17,18,57,184,0,1,16,184,0,46,208,184,0,42,16,185,0,47,0,4,244,184,0,22,16,185,0,53,0,4,244,65,3,0,64,0,63,0,1,93,65,3,0,96,0,63,0,1,93,65,3,0,240,0,63,0,1,93,0,184,0,0,69,88,184,0,27,47,27,185,0,27,0,12,62,89,184,0,0,69,88,184,0,37,47,27,185,0,37,0,12,62,89,184,0,0,69,88,184,0,17,47,27,185,0,17,0,6,62,89,184,0,0,69,88,184,0,11,47,27,185,0,11,0,6,62,89,186,0,1,0,37,0,11,17,18,57,184,0,1,47,65,5,0,16,0,1,0,32,0,1,0,2,93,65,5,0,144,0,1,0,160,0,1,0,2,93,184,0,11,16,185,0,6,0,1,244,184,0,11,16,184,0,8,220,186,0,14,0,11,0,37,17,18,57,186,0,32,0,37,0,11,17,18,57,184,0,37,16,185,0,44,0,2,244,184,0,1,16,184,0,46,220,65,15,0,159,0,46,0,175,0,46,0,191,0,46,0,207,0,46,0,223,0,46,0,239,0,46,0,255,0,46,0,7,93,184,0,27,16,185,0,50,0,2,244,184,0,17,16,185,0,56,0,2,244,48,49,1,65,3,0,54,0,3,0,1,93,65,3,0,71,0,3,0,1,93,65,3,0,89,0,13,0,1,93,65,3,0,106,0,13,0,1,93,65,3,0,123,0,13,0,1,93,65,3,0,84,0,15,0,1,93,65,3,0,102,0,15,0,1,93,65,3,0,105,0,19,0,1,93,65,3,0,90,0,19,0,1,93,65,3,0,105,0,25,0,1,93,65,3,0,90,0,25,0,1,93,65,3,0,85,0,30,0,1,93,65,3,0,102,0,30,0,1,93,65,3,0,104,0,34,0,1,93,65,3,0,121,0,34,0,1,93,65,3,0,118,0,39,0,1,93,65,3,0,135,0,39,0,1,93,65,3,0,118,0,40,0,1,93,65,3,0,135,0,40,0,1,93,65,3,0,105,0,45,0,1,93,0,65,5,0,55,0,3,0,71,0,3,0,2,93,65,9,0,91,0,9,0,107,0,9,0,123,0,9,0,139,0,9,0,4,93,65,5,0,104,0,13,0,120,0,13,0,2,93,65,3,0,89,0,13,0,1,93,65,5,0,90,0,14,0,106,0,14,0,2,93,65,3,0,104,0,15,0,1,93,65,3,0,89,0,15,0,1,93,65,5,0,89,0,19,0,105,0,19,0,2,93,65,3,0,85,0,25,0,1,93,65,3,0,102,0,25,0,1,93,65,3,0,85,0,30,0,1,93,65,3,0,102,0,30,0,1,93,65,3,0,101,0,32,0,1,93,65,5,0,118,0,32,0,134,0,32,0,2,93,65,3,0,100,0,34,0,1,93,65,3,0,118,0,34,0,1,93,65,5,0,118,0,39,0,134,0,39,0,2,93,65,3,0,118,0,40,0,1,93,65,3,0,135,0,40,0,1,93,65,3,0,102,0,45,0,1,93,37,33,20,30,2,51,50,55,23,6,35,34,38,39,14,1,35,34,46,2,53,52,62,2,51,50,30,2,23,62,3,51,50,30,2,21,20,39,34,7,51,46,1,33,34,6,21,20,22,51,50,54,53,52,38,3,100,254,169,32,48,55,23,84,71,10,72,81,93,102,23,22,110,67,57,91,64,34,35,65,93,57,28,59,53,40,11,13,42,49,55,27,48,79,55,31,214,107,24,253,4,64,254,82,78,80,79,78,75,77,79,245,57,71,41,14,37,77,32,53,54,51,56,40,70,95,55,54,92,66,38,13,26,38,25,24,38,26,14,28,53,75,48,31,155,113,54,59,91,84,85,90,99,79,78,94,0,255,255,0,40,255,242,2,41,3,181,2,38,0,52,0,0,1,7,0,204,0,69,0,209,0,38,65,3,0,79,0,60,0,1,93,65,7,0,0,0,60,0,16,0,60,0,32,0,60,0,3,93,0,65,3,0,47,0,59,0,1,93,48,49,255,255,0,32,255,246,1,131,2,228,2,38,0,84,0,0,1,6,0,204,232,0,0,29,65,3,0,79,0,42,0,1,93,65,3,0,63,0,43,0,1,93,65,3,0,0,0,43,0,1,93,48,49,0,0,0,255,255,255,253,0,0,2,57,3,141,2,38,0,58,0,0,1,7,0,104,0,85,0,209,0,68,184,0,14,47,65,5,0,16,0,14,0,32,0,14,0,2,93,65,3,0,80,0,14,0,1,113,65,3,0,144,0,14,0,1,93,184,0,10,208,0,184,0,13,47,65,3,0,47,0,13,0,1,93,65,3,0,175,0,13,0,1,93,184,0,10,208,48,49,0,0,255,255,0,9,0,0,2,30,3,181,2,38,0,59,0,0,1,7,0,204,0,60,0,209,0,34,65,5,0,0,0,10,0,16,0,10,0,2,93,65,3,0,32,0,10,0,1,113,0,65,3,0,47,0,9,0,1,93,48,49,255,255,0,22,0,0,1,190,2,228,2,38,0,91,0,0,1,6,0,204,14,0,0,33,65,5,0,111,0,10,0,127,0,10,0,2,93,65,3,0,223,0,10,0,1,93,65,3,0,0,0,10,0,1,93,48,49,0,0,0,0,1,255,222,255,15,1,115,2,202,0,32,1,43,187,0,11,0,5,0,22,0,4,43,184,0,22,16,184,0,25,208,184,0,0,208,184,0,0,47,184,0,11,16,184,0,8,208,184,0,9,208,184,0,9,47,184,0,11,16,184,0,12,208,184,0,19,208,184,0,19,47,184,0,22,16,184,0,21,208,184,0,25,16,184,0,24,208,184,0,24,47,0,184,0,0,69,88,184,0,31,47,27,185,0,31,0,14,62,89,184,0,0,69,88,184,0,8,47,27,185,0,8,0,12,62,89,184,0,0,69,88,184,0,17,47,27,185,0,17,0,8,62,89,184,0,31,16,185,0,3,0,3,244,184,0,8,16,185,0,11,0,3,244,184,0,17,16,185,0,19,0,3,244,184,0,11,16,184,0,22,208,184,0,8,16,184,0,25,208,48,49,1,65,3,0,133,0,6,0,1,93,65,7,0,38,0,6,0,54,0,6,0,70,0,6,0,3,93,65,3,0,102,0,6,0,1,93,65,5,0,119,0,15,0,135,0,15,0,2,93,65,3,0,89,0,28,0,1,93,65,3,0,122,0,28,0,1,93,0,65,3,0,135,0,6,0,1,93,65,5,0,57,0,6,0,73,0,6,0,2,93,65,5,0,121,0,15,0,137,0,15,0,2,93,65,3,0,116,0,28,0,1,93,65,3,0,87,0,28,0,1,93,1,7,38,35,34,14,2,7,51,7,35,3,14,3,43,1,39,54,55,19,35,55,51,55,62,3,51,50,1,115,7,13,19,30,43,30,20,8,148,6,153,86,6,27,32,34,13,13,13,57,14,80,94,7,96,9,6,33,49,61,35,17,2,191,55,8,16,39,64,47,56,253,242,40,56,36,17,63,12,89,1,255,56,61,39,60,42,22,0,0,0,0,1,255,244,255,14,0,151,1,234,0,14,0,163,187,0,9,0,4,0,8,0,4,43,65,3,0,63,0,8,0,1,113,65,3,0,143,0,8,0,1,93,65,3,0,223,0,8,0,1,93,65,3,0,32,0,8,0,1,93,184,0,8,16,184,0,2,208,184,0,2,47,65,3,0,143,0,9,0,1,93,65,3,0,223,0,9,0,1,93,65,3,0,63,0,9,0,1,113,65,3,0,32,0,9,0,1,93,0,184,0,0,69,88,184,0,9,47,27,185,0,9,0,12,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,8,62,89,185,0,2,0,1,244,48,49,1,65,11,0,5,0,12,0,21,0,12,0,37,0,12,0,53,0,12,0,69,0,12,0,5,93,23,7,39,62,3,53,17,51,17,20,14,2,28,30,10,22,28,16,7,90,20,33,45,237,5,69,2,10,21,37,30,2,51,253,171,32,45,31,18,0,1,0,76,2,91,1,114,2,233,0,5,0,130,25,184,0,4,47,24,65,3,0,0,0,4,0,1,93,184,0,1,208,184,0,4,16,184,0,3,208,184,0,3,47,184,0,4,16,184,0,5,208,184,0,5,47,0,184,0,2,47,65,3,0,64,0,2,0,1,93,65,3,0,32,0,2,0,1,93,184,0,0,208,184,0,2,16,184,0,4,220,65,5,0,15,0,4,0,31,0,4,0,2,93,65,9,0,95,0,4,0,111,0,4,0,127,0,4,0,143,0,4,0,4,93,184,0,1,220,184,0,2,16,184,0,3,220,184,0,5,208,48,49,1,39,7,53,55,23,1,114,147,147,147,147,2,91,82,82,36,106,106,0,0,1,0,76,2,88,1,114,2,228,0,5,0,130,25,184,0,1,47,24,184,0,0,208,184,0,0,47,184,0,1,16,184,0,2,208,184,0,2,47,184,0,1,16,184,0,4,208,0,184,0,1,47,65,3,0,64,0,1,0,1,93,65,3,0,32,0,1,0,1,93,184,0,3,220,65,9,0,95,0,3,0,111,0,3,0,127,0,3,0,143,0,3,0,4,93,65,5,0,15,0,3,0,31,0,3,0,2,93,184,0,2,220,184,0,0,208,184,0,1,16,184,0,4,220,65,3,0,240,0,4,0,1,93,184,0,3,16,184,0,5,208,48,49,1,7,39,53,23,55,1,114,147,147,147,147,2,187,99,99,41,76,76,0,0,2,0,42,2,64,0,249,2,243,0,14,0,26,1,101,184,0,3,47,184,0,11,220,65,3,0,32,0,11,0,1,113,65,3,0,208,0,11,0,1,93,184,0,3,16,184,0,15,220,184,0,11,16,184,0,21,220,0,184,0,14,47,65,3,0,95,0,14,0,1,113,65,3,0,239,0,14,0,1,93,65,3,0,207,0,14,0,1,93,65,3,0,128,0,14,0,1,93,65,3,0,96,0,14,0,1,93,184,0,6,220,65,3,0,15,0,6,0,1,113,65,7,0,143,0,6,0,159,0,6,0,175,0,6,0,3,93,65,3,0,79,0,6,0,1,93,184,0,14,16,184,0,18,220,184,0,6,16,184,0,24,220,48,49,1,65,9,0,74,0,2,0,90,0,2,0,106,0,2,0,122,0,2,0,4,93,65,9,0,73,0,4,0,89,0,4,0,105,0,4,0,121,0,4,0,4,93,65,9,0,70,0,9,0,86,0,9,0,102,0,9,0,118,0,9,0,4,93,65,9,0,70,0,12,0,86,0,12,0,102,0,12,0,118,0,12,0,4,93,0,65,9,0,73,0,1,0,89,0,1,0,105,0,1,0,121,0,1,0,4,93,65,9,0,70,0,5,0,86,0,5,0,102,0,5,0,118,0,5,0,4,93,65,9,0,70,0,8,0,86,0,8,0,102,0,8,0,118,0,8,0,4,93,65,9,0,72,0,12,0,88,0,12,0,104,0,12,0,120,0,12,0,4,93,65,9,0,73,0,13,0,89,0,13,0,105,0,13,0,121,0,13,0,4,93,65,7,0,53,0,16,0,69,0,16,0,85,0,16,0,3,113,19,34,38,53,52,54,51,50,30,2,21,20,6,35,39,20,22,51,50,54,53,52,38,35,34,6,146,49,55,58,52,24,37,24,12,48,48,67,36,24,24,36,35,25,25,35,2,64,52,37,39,51,15,26,32,17,34,55,89,27,33,33,27,26,33,33,0,0,1,0,92,2,87,1,182,2,190,0,23,1,42,184,0,8,47,65,3,0,0,0,8,0,1,93,184,0,7,220,184,0,8,16,184,0,21,220,184,0,20,220,0,184,0,0,47,65,3,0,64,0,0,0,1,93,65,3,0,32,0,0,0,1,93,184,0,13,220,65,9,0,47,0,13,0,63,0,13,0,79,0,13,0,95,0,13,0,4,93,184,0,5,220,65,5,0,48,0,5,0,64,0,5,0,2,113,184,0,0,16,184,0,7,208,184,0,7,47,184,0,0,16,184,0,18,220,65,3,0,63,0,18,0,1,113,184,0,13,16,184,0,20,208,184,0,20,47,48,49,1,65,7,0,6,0,6,0,22,0,6,0,38,0,6,0,3,113,65,5,0,40,0,10,0,56,0,10,0,2,93,65,5,0,40,0,11,0,56,0,11,0,2,93,65,7,0,11,0,19,0,27,0,19,0,43,0,19,0,3,113,65,5,0,37,0,22,0,53,0,22,0,2,93,0,65,7,0,9,0,6,0,25,0,6,0,41,0,6,0,3,113,65,5,0,37,0,10,0,53,0,10,0,2,93,65,5,0,38,0,11,0,54,0,11,0,2,93,65,7,0,7,0,19,0,23,0,19,0,39,0,19,0,3,113,65,5,0,40,0,22,0,56,0,22,0,2,93,65,5,0,41,0,23,0,57,0,23,0,2,93,1,34,46,2,35,34,7,39,62,3,51,50,30,2,51,50,55,23,14,1,1,75,12,36,41,32,11,53,18,36,6,20,30,32,15,13,36,46,35,10,42,27,34,11,58,2,87,16,19,16,49,9,22,34,23,11,15,19,15,51,9,43,51,0,0,1,0,57,0,238,1,189,1,68,0,3,0,19,184,0,1,47,184,0,0,220,0,184,0,1,47,184,0,2,220,48,49,37,33,53,33,1,189,254,124,1,132,238,86,0,0,0,0,1,0,57,0,238,2,25,1,68,0,3,0,28,184,0,1,47,65,3,0,0,0,1,0,1,93,184,0,0,220,0,184,0,1,47,184,0,2,220,48,49,37,33,53,33,2,25,254,32,1,224,238,86,0,0,0,1,0,43,2,43,0,144,2,238,0,6,0,58,184,0,0,47,184,0,4,220,184,0,2,208,186,0,3,0,0,0,4,17,18,57,0,184,0,0,69,88,184,0,1,47,27,185,0,1,0,18,62,89,184,0,4,220,184,0,0,208,184,0,4,16,184,0,5,220,48,49,19,55,23,7,23,21,35,43,78,23,35,34,100,2,129,109,13,87,9,86,0,1,0,42,2,43,0,143,2,238,0,6,0,58,184,0,0,47,184,0,4,220,184,0,2,208,186,0,3,0,4,0,0,17,18,57,0,184,0,0,69,88,184,0,5,47,27,185,0,5,0,18,62,89,184,0,4,220,184,0,0,208,184,0,4,16,184,0,1,220,48,49,19,7,39,55,39,53,51,143,78,23,35,34,100,2,152,109,13,87,9,86,0,1,0,57,255,147,0,158,0,86,0,6,0,62,184,0,0,47,184,0,4,220,184,0,2,208,186,0,3,0,4,0,0,17,18,57,0,184,0,0,69,88,184,0,4,47,27,185,0,4,0,6,62,89,184,0,0,208,184,0,4,16,184,0,1,220,184,0,4,16,184,0,5,220,48,49,51,7,39,55,39,53,51,158,78,23,35,34,100,109,13,87,9,86,0,0,0,2,0,43,2,43,1,98,2,238,0,6,0,13,0,116,184,0,6,47,184,0,5,220,184,0,2,208,186,0,3,0,6,0,5,17,18,57,184,0,6,16,184,0,13,220,184,0,12,220,184,0,9,208,186,0,10,0,13,0,12,17,18,57,0,184,0,0,69,88,184,0,1,47,27,185,0,1,0,18,62,89,184,0,4,220,184,0,0,208,184,0,4,16,184,0,5,220,184,0,4,16,184,0,7,208,184,0,1,16,184,0,8,208,184,0,7,16,184,0,11,208,184,0,5,16,184,0,13,208,48,49,19,55,23,7,23,21,35,63,1,23,7,23,21,35,43,78,23,35,34,100,210,78,23,35,34,100,2,129,109,13,87,9,86,86,109,13,87,9,86,0,0,2,0,42,2,43,1,97,2,238,0,6,0,13,0,118,184,0,6,47,184,0,5,220,184,0,2,208,186,0,3,0,5,0,6,17,18,57,184,0,6,16,184,0,13,220,184,0,12,220,184,0,9,208,186,0,10,0,12,0,13,17,18,57,0,184,0,0,69,88,184,0,12,47,27,185,0,12,0,18,62,89,184,0,11,220,184,0,4,208,184,0,0,208,184,0,11,16,184,0,8,220,184,0,1,208,184,0,12,16,184,0,5,208,184,0,11,16,184,0,7,208,48,49,1,65,3,0,89,0,1,0,1,93,1,7,39,55,39,53,51,15,1,39,55,39,53,51,1,97,78,23,35,34,100,210,78,23,35,34,100,2,152,109,13,87,9,86,86,109,13,87,9,86,0,0,0,2,0,57,255,147,1,132,0,86,0,6,0,13,0,138,184,0,7,47,65,3,0,80,0,7,0,1,113,184,0,0,220,65,5,0,79,0,0,0,95,0,0,0,2,113,184,0,4,220,184,0,2,208,186,0,3,0,4,0,0,17,18,57,184,0,7,16,184,0,11,220,184,0,9,208,186,0,10,0,11,0,7,17,18,57,0,184,0,0,69,88,184,0,4,47,27,185,0,4,0,6,62,89,184,0,0,208,184,0,4,16,184,0,1,220,184,0,4,16,184,0,5,220,184,0,4,16,184,0,11,208,184,0,7,208,184,0,1,16,184,0,8,208,184,0,5,16,184,0,12,208,48,49,51,7,39,55,39,53,51,23,7,39,55,39,53,51,158,78,23,35,34,100,230,78,23,35,34,100,109,13,87,9,86,86,109,13,87,9,86,0,0,1,0,35,0,0,1,133,2,95,0,13,0,196,184,0,10,47,65,3,0,16,0,10,0,1,93,184,0,11,220,65,9,0,80,0,11,0,96,0,11,0,112,0,11,0,128,0,11,0,4,93,186,0,12,0,11,0,10,17,18,57,184,0,12,16,184,0,1,208,184,0,11,16,184,0,2,208,184,0,10,16,184,0,5,208,186,0,9,0,10,0,11,17,18,57,184,0,9,16,184,0,6,208,184,0,10,16,184,0,8,220,184,0,11,16,184,0,13,220,0,184,0,10,47,184,0,0,69,88,184,0,4,47,27,185,0,4,0,6,62,89,186,0,8,0,10,0,4,17,18,57,184,0,8,47,184,0,7,220,184,0,0,208,186,0,6,0,7,0,8,17,18,57,184,0,6,16,184,0,1,208,186,0,9,0,8,0,7,17,18,57,184,0,9,16,184,0,12,208,184,0,8,16,184,0,13,208,48,49,1,39,23,7,35,39,55,7,53,23,39,51,7,55,1,133,158,41,31,58,31,41,158,156,34,110,34,156,1,117,30,151,252,252,151,30,85,31,180,180,31,0,0,1,0,53,255,197,1,151,2,95,0,21,1,61,184,0,13,47,65,3,0,0,0,13,0,1,93,184,0,14,220,65,9,0,80,0,14,0,96,0,14,0,112,0,14,0,128,0,14,0,4,93,186,0,15,0,14,0,13,17,18,57,184,0,15,16,184,0,1,208,184,0,14,16,184,0,2,208,184,0,13,16,184,0,3,208,186,0,12,0,13,0,14,17,18,57,184,0,12,16,184,0,4,208,184,0,13,16,184,0,11,220,184,0,6,208,184,0,4,16,184,0,7,208,184,0,13,16,184,0,8,208,184,0,12,16,184,0,9,208,184,0,14,16,184,0,16,220,184,0,15,16,184,0,18,208,184,0,14,16,184,0,19,208,184,0,1,16,184,0,20,208,184,0,16,16,184,0,21,208,0,184,0,14,47,184,0,3,47,186,0,0,0,3,0,14,17,18,57,184,0,0,47,184,0,21,220,186,0,1,0,0,0,21,17,18,57,184,0,1,16,184,0,4,208,184,0,0,16,184,0,5,208,184,0,21,16,184,0,6,208,186,0,20,0,21,0,0,17,18,57,184,0,20,16,184,0,7,208,186,0,16,0,14,0,3,17,18,57,184,0,16,47,184,0,17,220,186,0,18,0,17,0,16,17,18,57,184,0,18,16,184,0,9,208,184,0,17,16,184,0,10,208,184,0,16,16,184,0,11,208,186,0,15,0,16,0,17,17,18,57,184,0,15,16,184,0,12,208,48,49,37,39,23,35,55,7,53,23,39,55,7,53,23,39,51,7,55,21,39,23,7,55,1,151,156,34,110,34,156,160,43,43,160,156,34,110,34,156,160,43,43,160,88,30,177,177,30,84,30,132,133,30,84,30,176,176,30,84,30,133,132,30,0,0,0,0,1,0,44,0,169,1,6,1,131,0,20,0,19,184,0,8,47,184,0,18,220,0,184,0,3,47,184,0,13,220,48,49,55,14,1,35,34,46,2,53,52,62,2,51,50,30,2,21,20,6,230,17,39,21,22,39,30,18,18,30,39,22,22,39,30,18,16,201,17,15,18,30,39,22,22,39,30,18,18,30,39,22,21,40,0,0,0,0,3,0,57,0,0,2,107,0,86,0,3,0,7,0,11,0,121,184,0,1,47,65,3,0,0,0,1,0,1,93,65,3,0,32,0,1,0,1,93,185,0,0,0,4,244,184,0,1,16,184,0,5,220,185,0,4,0,4,244,184,0,5,16,184,0,9,220,185,0,8,0,4,244,0,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,184,0,2,220,65,3,0,63,0,2,0,1,113,184,0,1,16,184,0,5,208,184,0,2,16,184,0,6,208,184,0,5,16,184,0,9,208,184,0,6,16,184,0,10,208,48,49,51,35,53,51,23,35,53,51,23,35,53,51,147,90,90,236,90,90,236,90,90,86,86,86,86,86,0,0,0,0,7,0,36,255,242,4,141,2,193,0,3,0,21,0,37,0,55,0,71,0,89,0,105,3,55,184,0,7,47,184,0,41,47,65,7,0,0,0,41,0,16,0,41,0,32,0,41,0,3,93,184,0,51,220,186,0,1,0,7,0,51,17,18,57,184,0,1,47,184,0,0,220,184,0,1,16,184,0,3,220,184,0,2,220,184,0,7,16,184,0,17,220,184,0,7,16,184,0,27,220,65,3,0,31,0,27,0,1,113,184,0,17,16,184,0,33,220,65,3,0,16,0,33,0,1,113,184,0,41,16,184,0,61,220,65,3,0,31,0,61,0,1,113,184,0,51,16,184,0,67,220,65,3,0,16,0,67,0,1,113,184,0,41,16,184,0,75,220,184,0,85,220,184,0,75,16,184,0,95,220,65,3,0,31,0,95,0,1,113,184,0,85,16,184,0,101,220,65,3,0,16,0,101,0,1,113,0,184,0,0,69,88,184,0,12,47,27,185,0,12,0,14,62,89,184,0,0,69,88,184,0,2,47,27,185,0,2,0,14,62,89,184,0,0,69,88,184,0,38,47,27,185,0,38,0,6,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,12,16,184,0,4,220,184,0,12,16,184,0,22,220,184,0,4,16,184,0,30,220,184,0,38,16,184,0,46,220,184,0,56,220,184,0,38,16,184,0,64,220,184,0,38,16,184,0,72,208,184,0,46,16,184,0,80,208,184,0,56,16,184,0,90,208,184,0,64,16,184,0,98,208,48,49,1,65,3,0,87,0,0,0,1,93,65,3,0,202,0,5,0,1,93,65,7,0,10,0,6,0,26,0,6,0,42,0,6,0,3,93,65,7,0,10,0,9,0,26,0,9,0,42,0,9,0,3,93,65,3,0,202,0,10,0,1,93,65,3,0,198,0,14,0,1,93,65,7,0,6,0,15,0,22,0,15,0,38,0,15,0,3,93,65,7,0,5,0,19,0,21,0,19,0,37,0,19,0,3,93,65,3,0,198,0,20,0,1,93,65,5,0,118,0,24,0,134,0,24,0,2,93,65,7,0,10,0,40,0,26,0,40,0,42,0,40,0,3,93,65,7,0,9,0,43,0,25,0,43,0,41,0,43,0,3,93,65,3,0,201,0,44,0,1,93,65,3,0,197,0,48,0,1,93,65,7,0,5,0,49,0,21,0,49,0,37,0,49,0,3,93,65,7,0,5,0,53,0,21,0,53,0,37,0,53,0,3,93,65,3,0,198,0,54,0,1,93,65,5,0,118,0,58,0,134,0,58,0,2,93,65,3,0,200,0,73,0,1,93,65,7,0,10,0,74,0,26,0,74,0,42,0,74,0,3,93,65,7,0,10,0,77,0,26,0,77,0,42,0,77,0,3,93,65,3,0,201,0,78,0,1,93,65,3,0,197,0,82,0,1,93,65,7,0,5,0,83,0,21,0,83,0,37,0,83,0,3,93,65,7,0,5,0,87,0,21,0,87,0,37,0,87,0,3,93,65,3,0,198,0,88,0,1,93,65,5,0,118,0,92,0,134,0,92,0,2,93,0,65,3,0,202,0,5,0,1,93,65,7,0,5,0,9,0,21,0,9,0,37,0,9,0,3,93,65,3,0,197,0,10,0,1,93,65,3,0,198,0,14,0,1,93,65,7,0,7,0,15,0,23,0,15,0,39,0,15,0,3,93,65,3,0,200,0,20,0,1,93,65,3,0,202,0,39,0,1,93,65,3,0,198,0,44,0,1,93,65,3,0,198,0,48,0,1,93,65,3,0,203,0,54,0,1,93,65,3,0,201,0,73,0,1,93,65,3,0,199,0,78,0,1,93,65,3,0,198,0,82,0,1,93,65,3,0,202,0,88,0,1,93,23,35,1,51,1,34,38,53,52,62,2,51,50,30,2,21,20,14,2,3,34,14,2,21,20,22,51,50,54,53,52,46,2,1,34,38,53,52,62,2,51,50,30,2,21,20,14,2,3,34,14,2,21,20,22,51,50,54,53,52,46,2,1,34,38,53,52,62,2,51,50,30,2,21,20,14,2,3,34,14,2,21,20,22,51,50,54,53,52,46,2,238,75,1,165,74,254,36,64,82,24,42,55,30,31,53,39,23,23,40,55,29,19,34,26,15,54,37,40,54,14,26,33,1,195,64,82,24,42,55,30,31,53,39,23,23,40,55,29,19,34,26,15,54,37,40,54,14,26,33,1,81,64,82,24,42,55,30,31,53,39,23,23,40,55,29,19,34,26,15,54,37,40,54,14,26,33,12,2,200,254,145,94,88,46,71,48,25,24,46,67,44,46,71,49,25,1,64,19,36,52,31,60,70,75,64,29,48,34,18,253,101,94,88,46,71,48,25,24,46,67,44,46,71,49,25,1,64,19,36,52,31,60,70,75,64,29,48,34,18,254,192,94,88,46,71,48,25,24,46,67,44,46,71,49,25,1,64,19,36,52,31,60,70,75,64,29,48,34,18,0,0,1,0,14,0,78,1,26,1,234,0,5,0,219,184,0,2,47,65,9,0,95,0,2,0,111,0,2,0,127,0,2,0,143,0,2,0,4,93,65,3,0,255,0,2,0,1,93,184,0,4,220,65,3,0,128,0,4,0,1,93,65,3,0,80,0,4,0,1,93,184,0,0,208,184,0,4,16,184,0,3,220,65,9,0,95,0,3,0,111,0,3,0,127,0,3,0,143,0,3,0,4,93,65,5,0,239,0,3,0,255,0,3,0,2,93,65,7,0,15,0,3,0,31,0,3,0,47,0,3,0,3,113,184,0,1,208,184,0,2,16,184,0,5,220,65,9,0,80,0,5,0,96,0,5,0,112,0,5,0,128,0,5,0,4,93,65,5,0,224,0,5,0,240,0,5,0,2,93,65,7,0,0,0,5,0,16,0,5,0,32,0,5,0,3,113,0,25,184,0,2,47,24,184,0,1,208,184,0,1,47,184,0,2,16,184,0,3,208,184,0,3,47,184,0,2,16,184,0,5,208,48,49,37,35,39,55,51,7,1,26,109,159,159,109,159,78,206,206,206,0,0,0,1,0,41,0,78,1,53,1,234,0,5,0,207,184,0,0,47,65,3,0,0,0,0,0,1,93,65,3,0,160,0,0,0,1,93,184,0,4,220,65,3,0,143,0,4,0,1,93,65,3,0,95,0,4,0,1,93,184,0,5,220,65,9,0,80,0,5,0,96,0,5,0,112,0,5,0,128,0,5,0,4,93,65,5,0,224,0,5,0,240,0,5,0,2,93,65,7,0,0,0,5,0,16,0,5,0,32,0,5,0,3,113,184,0,1,208,184,0,4,16,184,0,2,208,184,0,0,16,184,0,3,220,65,9,0,95,0,3,0,111,0,3,0,127,0,3,0,143,0,3,0,4,93,65,5,0,239,0,3,0,255,0,3,0,2,93,65,7,0,15,0,3,0,31,0,3,0,47,0,3,0,3,113,0,25,184,0,0,47,24,184,0,1,208,184,0,1,47,184,0,0,16,184,0,3,208,184,0,0,16,184,0,5,208,184,0,5,47,48,49,1,7,35,55,39,51,1,53,159,109,159,159,109,1,28,206,206,206,0,0,2,0,33,1,56,1,118,2,194,0,19,0,31,2,137,186,0,15,0,5,0,3,43,65,3,0,223,0,5,0,1,93,65,3,0,143,0,5,0,1,93,65,3,0,16,0,5,0,1,93,65,3,0,64,0,5,0,1,93,65,3,0,176,0,15,0,1,93,65,3,0,0,0,15,0,1,113,65,3,0,48,0,15,0,1,113,65,3,0,224,0,15,0,1,93,65,3,0,64,0,15,0,1,93,65,5,0,16,0,15,0,32,0,15,0,2,93,184,0,5,16,185,0,20,0,5,244,184,0,15,16,185,0,26,0,5,244,0,184,0,0,69,88,184,0,10,47,27,185,0,10,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,10,62,89,65,3,0,135,0,5,0,1,93,185,0,23,0,1,244,184,0,10,16,185,0,29,0,1,244,48,49,1,65,3,0,152,0,1,0,1,93,65,3,0,184,0,2,0,1,93,65,3,0,169,0,2,0,1,93,65,3,0,24,0,3,0,1,93,65,3,0,9,0,3,0,1,93,65,3,0,41,0,3,0,1,93,65,5,0,74,0,3,0,90,0,3,0,2,113,65,5,0,73,0,7,0,89,0,7,0,2,113,65,3,0,10,0,7,0,1,93,65,5,0,166,0,12,0,182,0,12,0,2,93,65,3,0,39,0,12,0,1,93,65,3,0,151,0,12,0,1,93,65,5,0,68,0,13,0,84,0,13,0,2,113,65,5,0,6,0,13,0,22,0,13,0,2,93,65,3,0,6,0,18,0,1,93,65,3,0,182,0,18,0,1,93,65,5,0,23,0,18,0,39,0,18,0,2,93,65,5,0,151,0,18,0,167,0,18,0,2,93,65,3,0,217,0,21,0,1,93,65,3,0,234,0,21,0,1,93,65,5,0,75,0,21,0,91,0,21,0,2,113,65,3,0,138,0,24,0,1,93,65,3,0,138,0,28,0,1,93,65,3,0,132,0,30,0,1,93,65,5,0,71,0,30,0,87,0,30,0,2,113,0,65,3,0,153,0,1,0,1,93,65,3,0,168,0,2,0,1,93,65,3,0,186,0,2,0,1,93,65,5,0,71,0,3,0,87,0,3,0,2,113,65,7,0,8,0,3,0,24,0,3,0,40,0,3,0,3,93,65,3,0,7,0,7,0,1,93,65,3,0,181,0,12,0,1,93,65,3,0,38,0,12,0,1,93,65,5,0,150,0,12,0,166,0,12,0,2,93,65,5,0,7,0,13,0,23,0,13,0,2,93,65,5,0,71,0,13,0,87,0,13,0,2,113,65,5,0,72,0,17,0,88,0,17,0,2,113,65,3,0,184,0,18,0,1,93,65,7,0,9,0,18,0,25,0,18,0,41,0,18,0,3,93,65,5,0,153,0,18,0,169,0,18,0,2,93,65,3,0,231,0,21,0,1,93,65,3,0,216,0,21,0,1,93,65,3,0,135,0,24,0,1,93,19,34,46,2,53,52,62,2,51,50,30,2,21,20,14,2,39,20,22,51,50,54,53,52,38,35,34,6,200,38,61,44,24,27,46,64,37,36,61,45,25,25,46,64,132,52,42,45,55,55,40,40,59,1,56,27,50,71,43,44,74,54,31,29,52,71,42,45,74,52,29,191,64,62,66,69,63,67,72,0,2,0,5,1,64,1,47,2,186,0,9,0,12,0,160,186,0,2,0,5,0,3,43,65,3,0,159,0,2,0,1,93,65,3,0,16,0,2,0,1,93,184,0,2,16,185,0,3,0,5,244,184,0,10,208,184,0,2,16,184,0,8,208,186,0,6,0,10,0,8,17,18,57,184,0,9,208,184,0,9,47,184,0,5,16,184,0,12,208,65,3,0,70,0,12,0,1,93,0,184,0,0,69,88,184,0,6,47,27,185,0,6,0,14,62,89,184,0,0,69,88,184,0,2,47,27,185,0,2,0,10,62,89,186,0,1,0,6,0,2,17,18,57,184,0,1,47,184,0,4,208,184,0,1,16,185,0,8,0,3,244,184,0,10,208,184,0,6,16,184,0,11,208,48,49,1,35,21,35,53,35,19,51,21,51,35,53,7,1,47,49,74,175,187,62,49,123,74,1,167,103,103,1,19,218,110,110,0,1,0,24,1,57,1,22,2,186,0,24,1,71,186,0,20,0,4,0,3,43,65,5,0,111,0,4,0,127,0,4,0,2,93,65,5,0,159,0,4,0,175,0,4,0,2,93,65,3,0,80,0,20,0,1,113,65,3,0,127,0,20,0,1,93,65,5,0,16,0,20,0,32,0,20,0,2,93,65,3,0,32,0,20,0,1,113,65,3,0,80,0,20,0,1,93,184,0,20,16,185,0,9,0,5,244,186,0,12,0,4,0,20,17,18,57,184,0,12,47,184,0,11,208,184,0,12,16,184,0,13,208,186,0,14,0,4,0,20,17,18,57,184,0,14,47,184,0,11,16,184,0,16,208,186,0,17,0,16,0,11,17,18,57,0,184,0,0,69,88,184,0,14,47,27,185,0,14,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,10,62,89,184,0,5,220,65,5,0,112,0,5,0,128,0,5,0,2,93,184,0,0,16,185,0,7,0,1,244,186,0,17,0,14,0,0,17,18,57,184,0,17,47,185,0,11,0,3,244,184,0,14,16,185,0,15,0,1,244,48,49,1,65,5,0,52,0,19,0,68,0,19,0,2,93,65,5,0,86,0,19,0,102,0,19,0,2,93,65,3,0,68,0,22,0,1,93,65,3,0,52,0,23,0,1,93,65,3,0,22,0,23,0,1,93,65,3,0,39,0,23,0,1,93,0,65,3,0,41,0,23,0,1,93,65,3,0,26,0,23,0,1,93,19,34,46,1,39,55,22,51,50,53,52,43,1,55,51,7,35,7,30,1,21,20,14,2,130,17,36,31,22,17,35,52,78,99,62,25,187,8,123,10,85,77,24,41,53,1,57,7,10,15,65,29,61,55,201,70,71,1,54,58,32,48,34,17,0,0,0,0,2,0,32,1,56,1,44,2,186,0,23,0,35,1,231,186,0,19,0,3,0,3,43,65,3,0,207,0,3,0,1,93,65,3,0,111,0,3,0,1,93,65,5,0,143,0,3,0,159,0,3,0,2,93,65,3,0,64,0,3,0,1,93,65,3,0,64,0,19,0,1,93,65,3,0,207,0,19,0,1,93,65,3,0,111,0,19,0,1,93,65,3,0,159,0,19,0,1,93,65,3,0,16,0,19,0,1,93,65,5,0,48,0,19,0,64,0,19,0,2,113,65,3,0,0,0,19,0,1,113,186,0,9,0,19,0,3,17,18,57,184,0,9,47,184,0,3,16,185,0,27,0,5,244,184,0,14,208,65,7,0,39,0,14,0,55,0,14,0,71,0,14,0,3,93,184,0,19,16,185,0,33,0,5,244,0,184,0,0,69,88,184,0,8,47,27,185,0,8,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,10,62,89,184,0,8,16,185,0,11,0,3,244,184,0,0,16,184,0,16,220,65,3,0,95,0,16,0,1,93,65,3,0,47,0,16,0,1,113,186,0,14,0,16,0,0,17,18,57,185,0,24,0,3,244,184,0,0,16,185,0,30,0,1,244,48,49,1,65,7,0,42,0,2,0,58,0,2,0,74,0,2,0,3,93,65,3,0,104,0,6,0,1,93,65,3,0,136,0,6,0,1,93,65,3,0,89,0,6,0,1,93,65,3,0,121,0,6,0,1,93,65,5,0,87,0,17,0,103,0,17,0,2,93,65,7,0,37,0,18,0,53,0,18,0,69,0,18,0,3,93,65,3,0,118,0,18,0,1,93,65,3,0,135,0,18,0,1,93,65,7,0,37,0,21,0,53,0,21,0,69,0,21,0,3,93,0,65,3,0,116,0,6,0,1,93,65,3,0,101,0,6,0,1,93,65,3,0,87,0,6,0,1,93,65,3,0,135,0,6,0,1,93,65,3,0,86,0,7,0,1,93,65,7,0,37,0,17,0,53,0,17,0,69,0,17,0,3,93,65,3,0,102,0,17,0,1,93,65,3,0,87,0,17,0,1,93,65,3,0,118,0,18,0,1,93,65,3,0,135,0,18,0,1,93,19,34,38,53,52,62,2,51,23,34,14,2,7,54,51,50,22,21,20,14,2,39,34,6,21,20,22,51,50,54,53,52,38,158,57,69,36,53,61,24,49,16,49,45,32,3,18,50,54,68,21,37,53,16,31,38,39,23,29,36,30,1,56,71,75,48,87,66,39,28,29,43,49,21,19,55,54,26,45,35,20,177,30,29,24,29,37,26,19,30,0,0,0,0,1,0,23,1,64,1,34,2,186,0,5,0,150,186,0,0,0,5,0,3,43,65,3,0,175,0,0,0,1,93,65,5,0,10,0,0,0,26,0,0,0,2,93,65,3,0,118,0,0,0,1,93,184,0,0,16,184,0,1,208,184,0,0,16,184,0,3,208,65,3,0,138,0,3,0,1,93,65,5,0,105,0,3,0,121,0,3,0,2,93,65,5,0,73,0,3,0,89,0,3,0,2,113,184,0,2,208,65,3,0,175,0,5,0,1,93,0,184,0,0,69,88,184,0,5,47,27,185,0,5,0,14,62,89,184,0,0,69,88,184,0,2,47,27,185,0,2,0,10,62,89,184,0,5,16,185,0,4,0,1,244,48,49,1,3,35,19,35,53,1,34,170,77,139,159,2,186,254,134,1,52,70,0,0,3,0,31,1,56,1,59,2,194,0,22,0,30,0,42,2,97,186,0,18,0,3,0,3,43,65,5,0,127,0,3,0,143,0,3,0,2,93,65,3,0,191,0,3,0,1,93,65,3,0,48,0,3,0,1,93,65,3,0,80,0,18,0,1,113,65,5,0,0,0,18,0,16,0,18,0,2,93,65,3,0,192,0,18,0,1,93,65,3,0,48,0,18,0,1,93,186,0,7,0,3,0,18,17,18,57,184,0,7,47,186,0,13,0,18,0,3,17,18,57,184,0,13,47,186,0,5,0,7,0,13,17,18,57,65,3,0,25,0,5,0,1,113,65,7,0,40,0,5,0,56,0,5,0,72,0,5,0,3,93,186,0,15,0,13,0,7,17,18,57,184,0,7,16,185,0,25,0,5,244,184,0,13,16,185,0,29,0,5,244,184,0,3,16,185,0,34,0,5,244,184,0,18,16,185,0,40,0,5,244,0,184,0,0,69,88,184,0,10,47,27,185,0,10,0,14,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,10,62,89,186,0,27,0,10,0,0,17,18,57,184,0,27,47,65,5,0,223,0,27,0,239,0,27,0,2,93,65,3,0,31,0,27,0,1,93,185,0,31,0,3,244,186,0,5,0,27,0,31,17,18,57,186,0,15,0,27,0,31,17,18,57,184,0,10,16,185,0,23,0,3,244,184,0,0,16,185,0,37,0,3,244,48,49,1,65,3,0,104,0,1,0,1,93,65,3,0,89,0,2,0,1,93,65,7,0,42,0,2,0,58,0,2,0,74,0,2,0,3,93,65,7,0,41,0,8,0,57,0,8,0,73,0,8,0,3,93,65,5,0,105,0,8,0,121,0,8,0,2,93,65,3,0,90,0,8,0,1,93,65,3,0,103,0,9,0,1,93,65,7,0,40,0,9,0,56,0,9,0,72,0,9,0,3,93,65,3,0,103,0,11,0,1,93,65,3,0,116,0,12,0,1,93,65,9,0,37,0,12,0,53,0,12,0,69,0,12,0,85,0,12,0,4,93,65,7,0,39,0,21,0,55,0,21,0,71,0,21,0,3,93,0,65,7,0,42,0,1,0,58,0,1,0,74,0,1,0,3,93,65,7,0,106,0,1,0,122,0,1,0,138,0,1,0,3,93,65,3,0,100,0,9,0,1,93,65,3,0,133,0,9,0,1,93,65,7,0,38,0,9,0,54,0,9,0,70,0,9,0,3,93,65,3,0,118,0,9,0,1,93,65,7,0,37,0,11,0,53,0,11,0,69,0,11,0,3,93,65,3,0,101,0,11,0,1,93,65,3,0,133,0,11,0,1,93,65,3,0,87,0,12,0,1,93,65,7,0,41,0,21,0,57,0,21,0,73,0,21,0,3,93,19,34,38,53,52,55,38,53,52,54,51,50,22,21,20,7,30,1,21,20,14,2,3,34,21,20,23,54,53,52,7,14,1,21,20,22,51,50,54,53,52,38,167,67,69,63,40,57,64,63,55,50,32,40,19,37,56,30,54,51,55,50,30,43,36,32,34,38,38,1,56,62,46,60,44,28,58,42,54,49,39,54,36,13,52,32,23,43,33,20,1,82,47,41,12,13,42,45,151,4,39,30,27,30,32,27,29,36,0,0,2,0,22,1,64,1,35,2,194,0,23,0,34,1,99,186,0,3,0,19,0,3,43,65,3,0,16,0,3,0,1,93,65,3,0,111,0,3,0,1,93,65,3,0,159,0,3,0,1,93,65,3,0,64,0,3,0,1,113,65,3,0,64,0,3,0,1,93,65,3,0,15,0,19,0,1,113,65,3,0,63,0,19,0,1,113,65,5,0,143,0,19,0,159,0,19,0,2,93,65,3,0,111,0,19,0,1,93,186,0,9,0,19,0,3,17,18,57,184,0,9,47,184,0,3,16,185,0,27,0,5,244,184,0,14,208,184,0,19,16,185,0,32,0,5,244,0,184,0,0,69,88,184,0,0,47,27,185,0,0,0,14,62,89,184,0,0,69,88,184,0,8,47,27,185,0,8,0,10,62,89,185,0,11,0,3,244,184,0,0,16,184,0,16,220,65,3,0,80,0,16,0,1,93,65,3,0,32,0,16,0,1,113,186,0,14,0,0,0,16,17,18,57,185,0,24,0,3,244,184,0,0,16,185,0,29,0,1,244,48,49,1,65,7,0,41,0,18,0,57,0,18,0,73,0,18,0,3,93,65,9,0,90,0,18,0,106,0,18,0,122,0,18,0,138,0,18,0,4,93,65,7,0,41,0,22,0,57,0,22,0,73,0,22,0,3,93,0,65,7,0,36,0,1,0,52,0,1,0,68,0,1,0,3,93,65,9,0,90,0,7,0,106,0,7,0,122,0,7,0,138,0,7,0,4,93,65,7,0,42,0,17,0,58,0,17,0,74,0,17,0,3,93,65,7,0,37,0,22,0,53,0,22,0,69,0,22,0,3,93,19,50,22,21,20,14,2,35,39,50,62,2,55,6,35,34,38,53,52,62,2,23,50,54,53,52,35,34,6,21,20,22,164,57,70,31,53,62,29,47,16,49,46,33,2,19,52,55,67,21,38,52,18,31,38,61,30,34,27,2,194,72,73,47,87,67,40,28,25,40,51,26,19,55,52,27,46,35,20,177,29,29,54,36,24,22,30,0,0,255,255,0,45,255,249,1,130,1,131,1,7,0,222,0,12,254,193,0,24,0,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,23,208,48,49,255,255,0,38,0,1,0,170,1,123,1,7,0,120,0,15,254,193,0,20,0,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,48,49,255,255,0,38,0,1,1,30,1,131,1,7,0,113,0,13,254,193,0,20,0,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,48,49,255,255,0,32,255,249,1,34,1,131,1,7,0,114,0,13,254,193,0,20,0,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,48,49,255,255,0,18,0,1,1,60,1,123,1,7,0,223,0,13,254,193,0,24,0,184,0,0,69,88,184,0,2,47,27,185,0,2,0,6,62,89,184,0,10,208,48,49,255,255,0,35,255,250,1,33,1,123,1,7,0,224,0,11,254,193,0,20,0,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,48,49,255,255,0,45,255,249,1,57,1,123,1,7,0,225,0,13,254,193,0,24,0,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,30,208,48,49,255,255,0,42,0,1,1,53,1,123,1,7,0,226,0,19,254,193,0,20,0,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,48,49,255,255,0,44,255,249,1,72,1,131,1,7,0,227,0,13,254,193,0,32,0,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,27,208,184,0,0,16,184,0,37,208,48,49,255,255,0,32,0,1,1,45,1,131,1,7,0,228,0,10,254,193,0,24,0,184,0,0,69,88,184,0,8,47,27,185,0,8,0,6,62,89,184,0,24,208,48,49,0,1,0,33,0,17,2,134,2,171,0,41,2,76,186,0,17,0,6,0,3,43,65,5,0,127,0,6,0,143,0,6,0,2,93,65,3,0,95,0,6,0,1,113,65,3,0,0,0,6,0,1,93,184,0,6,16,184,0,0,208,184,0,6,16,184,0,1,208,184,0,1,47,184,0,6,16,184,0,8,208,184,0,8,47,65,3,0,112,0,8,0,1,93,184,0,6,16,184,0,10,208,65,3,0,0,0,17,0,1,93,184,0,6,16,184,0,26,220,65,3,0,208,0,26,0,1,93,65,11,0,64,0,26,0,80,0,26,0,96,0,26,0,112,0,26,0,128,0,26,0,5,93,184,0,22,208,186,0,23,0,26,0,17,17,18,57,184,0,23,47,186,0,30,0,17,0,26,17,18,57,184,0,30,47,184,0,26,16,184,0,32,208,65,3,0,7,0,32,0,1,93,65,5,0,22,0,32,0,38,0,32,0,2,93,65,7,0,69,0,32,0,85,0,32,0,101,0,32,0,3,93,65,3,0,56,0,34,0,1,113,184,0,17,16,184,0,37,208,0,184,0,15,47,184,0,39,47,186,0,23,0,15,0,39,17,18,57,184,0,23,47,65,3,0,175,0,23,0,1,93,65,3,0,31,0,23,0,1,93,65,7,0,223,0,23,0,239,0,23,0,255,0,23,0,3,93,65,3,0,47,0,23,0,1,113,184,0,30,220,65,3,0,95,0,30,0,1,113,185,0,31,0,1,244,184,0,0,208,184,0,30,16,184,0,3,208,184,0,23,16,185,0,24,0,1,244,184,0,7,208,184,0,23,16,184,0,10,208,184,0,15,16,184,0,18,220,65,5,0,47,0,18,0,63,0,18,0,2,113,184,0,15,16,184,0,20,220,65,5,0,127,0,20,0,143,0,20,0,2,93,65,5,0,47,0,20,0,63,0,20,0,2,113,184,0,39,16,184,0,34,220,65,5,0,32,0,34,0,48,0,34,0,2,113,65,5,0,112,0,34,0,128,0,34,0,2,93,184,0,39,16,184,0,36,220,65,5,0,32,0,36,0,48,0,36,0,2,113,48,49,1,65,3,0,105,0,12,0,1,93,65,3,0,90,0,12,0,1,93,0,65,5,0,117,0,12,0,133,0,12,0,2,93,65,5,0,86,0,12,0,102,0,12,0,2,93,65,11,0,53,0,16,0,69,0,16,0,85,0,16,0,101,0,16,0,117,0,16,0,5,93,65,11,0,53,0,17,0,69,0,17,0,85,0,17,0,101,0,17,0,117,0,17,0,5,93,65,11,0,59,0,37,0,75,0,37,0,91,0,37,0,107,0,37,0,123,0,37,0,5,93,55,35,55,51,46,1,61,1,35,55,51,62,3,51,50,23,7,38,35,34,7,33,7,35,21,20,22,23,51,7,35,22,51,50,55,23,6,35,34,38,174,141,24,99,2,2,89,22,76,14,57,80,101,57,104,72,12,91,73,146,46,1,2,24,244,3,2,243,24,198,59,117,73,91,12,72,104,102,156,215,69,19,33,14,19,69,57,91,63,34,34,98,38,151,69,19,17,33,16,69,104,38,98,34,104,0,0,2,0,31,1,81,2,156,2,188,0,12,0,20,1,63,184,0,17,47,184,0,4,220,184,0,10,220,65,3,0,16,0,10,0,1,93,65,3,0,32,0,10,0,1,113,186,0,7,0,4,0,10,17,18,57,184,0,7,16,184,0,1,208,184,0,4,16,184,0,3,220,65,3,0,63,0,3,0,1,113,184,0,2,208,184,0,4,16,184,0,5,208,186,0,6,0,2,0,5,17,18,57,184,0,10,16,184,0,11,220,184,0,12,208,184,0,10,16,184,0,9,208,65,3,0,56,0,9,0,1,93,186,0,8,0,12,0,9,17,18,57,184,0,17,16,184,0,16,220,65,5,0,63,0,16,0,79,0,16,0,2,113,184,0,14,220,184,0,17,16,184,0,19,220,0,184,0,0,69,88,184,0,20,47,27,185,0,20,0,14,62,89,184,0,5,208,184,0,20,16,184,0,17,220,184,0,4,208,186,0,1,0,5,0,4,17,18,57,184,0,1,47,184,0,5,16,184,0,2,208,65,3,0,85,0,2,0,1,93,65,3,0,67,0,2,0,1,93,184,0,1,16,184,0,7,208,65,3,0,77,0,7,0,1,93,65,3,0,92,0,7,0,1,93,184,0,5,16,184,0,8,208,184,0,4,16,184,0,11,208,184,0,2,16,184,0,12,208,184,0,20,16,184,0,19,220,65,5,0,48,0,19,0,64,0,19,0,2,113,184,0,15,208,48,49,65,3,0,107,0,7,0,1,93,1,35,39,3,35,19,51,23,55,51,19,35,3,37,7,35,17,35,17,35,53,1,233,6,92,33,52,47,29,105,104,29,48,54,31,254,219,6,100,51,102,1,187,163,254,243,1,107,179,179,254,149,1,12,95,50,254,199,1,57,50,0,3,0,74,0,0,1,242,2,48,0,17,0,25,0,33,1,115,186,0,13,0,1,0,3,43,65,3,0,16,0,1,0,1,93,65,3,0,176,0,1,0,1,93,65,3,0,64,0,13,0,1,93,65,5,0,0,0,13,0,16,0,13,0,2,93,65,3,0,0,0,13,0,1,113,65,3,0,224,0,13,0,1,93,186,0,8,0,13,0,1,17,18,57,184,0,8,47,184,0,1,16,185,0,28,0,4,244,184,0,20,208,186,0,10,0,20,0,8,17,18,57,65,5,0,4,0,10,0,20,0,10,0,2,93,184,0,8,16,185,0,23,0,4,244,184,0,13,16,185,0,32,0,4,244,65,3,0,79,0,35,0,1,113,0,184,0,0,69,88,184,0,3,47,27,185,0,3,0,16,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,186,0,20,0,3,0,0,17,18,57,184,0,20,47,185,0,27,0,2,244,186,0,10,0,20,0,27,17,18,57,184,0,3,16,185,0,18,0,2,244,184,0,0,16,185,0,29,0,2,244,48,49,1,65,3,0,4,0,6,0,1,93,65,7,0,22,0,6,0,38,0,6,0,54,0,6,0,3,93,65,3,0,71,0,6,0,1,93,65,7,0,89,0,10,0,105,0,10,0,121,0,10,0,3,93,65,3,0,135,0,11,0,1,93,65,3,0,5,0,15,0,1,93,65,3,0,133,0,15,0,1,93,0,65,3,0,70,0,6,0,1,93,65,9,0,7,0,6,0,23,0,6,0,39,0,6,0,55,0,6,0,4,93,65,3,0,133,0,11,0,1,93,65,3,0,8,0,15,0,1,93,65,3,0,138,0,15,0,1,93,33,35,17,51,50,30,2,21,20,7,30,1,21,20,14,2,3,35,21,51,50,53,52,38,7,35,21,51,50,54,53,52,1,34,216,146,57,85,56,28,49,54,47,36,59,75,75,86,103,85,52,16,120,95,70,69,2,48,12,32,55,43,80,39,19,63,52,49,64,37,15,1,224,148,74,44,30,224,175,36,49,90,0,0,1,0,39,255,245,1,245,2,59,0,29,1,180,186,0,12,0,5,0,3,43,65,3,0,15,0,5,0,1,93,65,3,0,47,0,5,0,1,93,65,3,0,128,0,5,0,1,93,65,3,0,128,0,12,0,1,93,65,3,0,192,0,12,0,1,93,65,3,0,0,0,12,0,1,113,65,3,0,224,0,12,0,1,93,65,3,0,160,0,12,0,1,93,65,3,0,48,0,12,0,1,93,65,3,0,16,0,12,0,1,93,184,0,5,16,185,0,20,0,4,244,184,0,12,16,184,0,28,208,0,184,0,0,69,88,184,0,10,47,27,185,0,10,0,16,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,10,16,184,0,13,220,65,3,0,95,0,13,0,1,113,184,0,10,16,185,0,15,0,2,244,184,0,0,16,185,0,25,0,2,244,184,0,0,16,184,0,27,220,65,3,0,80,0,27,0,1,113,48,49,1,65,3,0,137,0,2,0,1,93,65,3,0,56,0,8,0,1,93,65,3,0,136,0,8,0,1,93,65,11,0,71,0,11,0,87,0,11,0,103,0,11,0,119,0,11,0,135,0,11,0,5,93,65,5,0,23,0,11,0,39,0,11,0,2,113,0,65,3,0,56,0,2,0,1,93,65,3,0,138,0,2,0,1,93,65,3,0,131,0,8,0,1,93,65,3,0,54,0,8,0,1,93,65,5,0,17,0,11,0,33,0,11,0,2,113,65,11,0,70,0,11,0,86,0,11,0,102,0,11,0,118,0,11,0,134,0,11,0,5,93,65,11,0,70,0,12,0,86,0,12,0,102,0,12,0,118,0,12,0,134,0,12,0,5,93,65,11,0,73,0,28,0,89,0,28,0,105,0,28,0,121,0,28,0,137,0,28,0,5,93,65,11,0,74,0,29,0,90,0,29,0,106,0,29,0,122,0,29,0,138,0,29,0,5,93,65,5,0,27,0,29,0,43,0,29,0,2,113,5,34,46,2,53,52,62,2,51,50,23,7,38,35,34,14,2,21,20,30,2,51,50,55,23,6,1,79,65,109,78,44,44,78,109,65,97,69,10,91,65,47,72,49,26,26,49,73,47,64,91,10,73,11,42,76,108,65,65,107,77,42,33,87,32,30,53,75,45,45,75,53,30,32,88,32,0,0,0,2,0,74,0,0,2,78,2,48,0,12,0,21,0,235,186,0,8,0,1,0,3,43,65,3,0,207,0,1,0,1,93,65,3,0,15,0,1,0,1,93,65,3,0,175,0,1,0,1,93,65,3,0,16,0,1,0,1,93,65,3,0,96,0,8,0,1,93,65,3,0,224,0,8,0,1,93,65,3,0,32,0,8,0,1,113,65,3,0,0,0,8,0,1,113,65,3,0,176,0,8,0,1,93,65,3,0,64,0,8,0,1,93,65,5,0,16,0,8,0,32,0,8,0,2,93,184,0,1,16,185,0,15,0,4,244,184,0,8,16,185,0,19,0,4,244,0,184,0,0,69,88,184,0,3,47,27,185,0,3,0,16,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,3,16,185,0,13,0,2,244,184,0,0,16,185,0,16,0,2,244,48,49,1,65,3,0,135,0,5,0,1,93,65,3,0,133,0,10,0,1,93,0,65,3,0,133,0,5,0,1,93,65,3,0,136,0,10,0,1,93,65,3,0,138,0,11,0,1,93,33,35,17,51,50,30,2,21,20,14,2,3,35,17,51,50,54,53,52,38,1,39,221,221,64,110,78,43,44,78,109,64,128,128,94,99,99,2,48,39,72,104,65,66,104,72,38,1,216,254,128,102,90,90,102,0,0,0,1,0,74,0,0,1,197,2,48,0,11,0,152,186,0,0,0,1,0,3,43,65,3,0,16,0,0,0,1,93,65,3,0,224,0,0,0,1,93,65,3,0,16,0,1,0,1,93,184,0,0,16,184,0,4,208,184,0,4,47,184,0,1,16,185,0,10,0,4,244,184,0,6,208,186,0,8,0,0,0,1,17,18,57,184,0,8,47,0,184,0,0,69,88,184,0,2,47,27,185,0,2,0,16,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,184,0,2,16,185,0,5,0,2,244,186,0,6,0,2,0,1,17,18,57,184,0,6,47,185,0,9,0,2,244,184,0,1,16,185,0,10,0,2,244,48,49,41,1,17,33,21,33,21,51,21,35,21,33,1,197,254,133,1,115,254,236,217,217,1,28,2,48,88,136,88,160,0,1,0,74,0,0,1,182,2,48,0,9,0,166,186,0,0,0,7,0,3,43,65,3,0,175,0,0,0,1,93,65,3,0,16,0,0,0,1,93,65,3,0,176,0,0,0,1,93,65,3,0,175,0,7,0,1,93,65,3,0,16,0,7,0,1,93,65,3,0,176,0,7,0,1,93,184,0,7,16,185,0,6,0,4,244,184,0,2,208,186,0,3,0,0,0,7,17,18,57,184,0,3,47,0,184,0,0,69,88,184,0,8,47,27,185,0,8,0,16,62,89,184,0,0,69,88,184,0,6,47,27,185,0,6,0,6,62,89,184,0,8,16,185,0,1,0,2,244,186,0,2,0,8,0,6,17,18,57,184,0,2,47,185,0,5,0,2,244,65,3,0,165,0,7,0,1,93,48,49,1,33,21,51,21,35,21,35,17,33,1,182,254,241,210,210,93,1,108,1,216,136,88,248,2,48,0,0,0,1,0,39,255,245,2,22,2,59,0,32,1,48,186,0,27,0,5,0,3,43,65,3,0,80,0,27,0,1,93,65,3,0,112,0,27,0,1,93,186,0,12,0,27,0,5,17,18,57,184,0,12,47,184,0,5,16,185,0,18,0,4,244,184,0,27,16,185,0,24,0,4,244,184,0,27,16,184,0,26,208,184,0,26,47,0,184,0,0,69,88,184,0,10,47,27,185,0,10,0,16,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,10,16,184,0,13,220,184,0,10,16,185,0,15,0,2,244,184,0,0,16,185,0,21,0,2,244,186,0,26,0,10,0,0,17,18,57,184,0,26,47,185,0,25,0,2,244,48,49,1,65,3,0,137,0,2,0,1,93,65,3,0,136,0,7,0,1,93,65,3,0,136,0,8,0,1,93,65,5,0,21,0,16,0,37,0,16,0,2,93,65,3,0,21,0,20,0,1,93,65,3,0,38,0,20,0,1,93,0,65,3,0,138,0,2,0,1,93,65,3,0,135,0,7,0,1,93,65,3,0,134,0,8,0,1,93,65,9,0,85,0,11,0,101,0,11,0,117,0,11,0,133,0,11,0,4,93,65,3,0,69,0,12,0,1,93,65,9,0,86,0,12,0,102,0,12,0,118,0,12,0,134,0,12,0,4,93,65,3,0,23,0,16,0,1,93,5,34,46,2,53,52,62,2,51,50,23,7,38,35,34,6,21,20,22,51,50,55,53,35,53,51,21,14,3,1,74,63,107,77,44,43,79,110,66,102,75,9,87,79,98,100,105,103,49,42,81,175,17,49,56,57,11,42,76,108,66,65,107,76,42,32,87,31,111,90,94,111,11,114,79,250,8,15,12,7,0,0,0,1,0,74,0,0,2,60,2,48,0,11,0,127,186,0,0,0,5,0,3,43,65,3,0,16,0,0,0,1,93,184,0,0,16,185,0,1,0,4,244,65,3,0,16,0,5,0,1,93,184,0,5,16,185,0,4,0,4,244,184,0,8,208,184,0,1,16,184,0,9,208,0,184,0,0,69,88,184,0,7,47,27,185,0,7,0,16,62,89,184,0,0,69,88,184,0,4,47,27,185,0,4,0,6,62,89,184,0,1,208,186,0,8,0,7,0,4,17,18,57,184,0,8,47,185,0,3,0,2,244,184,0,7,16,184,0,10,208,48,49,33,35,53,33,21,35,17,51,21,33,53,51,2,60,93,254,200,93,93,1,56,93,248,248,2,48,223,223,0,0,0,0,1,0,74,0,0,0,167,2,48,0,3,0,109,187,0,0,0,4,0,1,0,4,43,65,3,0,175,0,0,0,1,93,65,5,0,0,0,0,0,16,0,0,0,2,93,65,3,0,128,0,0,0,1,93,65,3,0,175,0,1,0,1,93,65,3,0,128,0,1,0,1,93,65,5,0,0,0,1,0,16,0,1,0,2,93,0,184,0,0,69,88,184,0,2,47,27,185,0,2,0,16,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,48,49,51,35,17,51,167,93,93,2,48,0,1,255,254,255,118,0,167,2,48,0,10,0,119,187,0,8,0,4,0,7,0,4,43,65,3,0,175,0,7,0,1,93,65,3,0,16,0,7,0,1,93,65,3,0,128,0,7,0,1,93,184,0,7,16,184,0,2,208,184,0,2,47,65,3,0,175,0,8,0,1,93,65,3,0,16,0,8,0,1,93,65,3,0,128,0,8,0,1,93,65,3,0,15,0,12,0,1,93,0,184,0,1,47,184,0,0,69,88,184,0,8,47,27,185,0,8,0,16,62,89,184,0,1,16,185,0,2,0,1,244,48,49,23,35,39,51,50,54,53,17,51,17,20,28,21,9,12,37,27,93,138,66,34,39,2,47,253,186,116,0,2,0,74,0,0,2,0,2,48,0,5,0,9,1,0,186,0,0,0,7,0,3,43,65,5,0,96,0,0,0,112,0,0,0,2,93,65,3,0,32,0,0,0,1,113,65,3,0,217,0,0,0,1,93,65,3,0,240,0,0,0,1,93,65,3,0,0,0,0,0,1,113,65,3,0,64,0,0,0,1,93,65,5,0,16,0,0,0,32,0,0,0,2,93,184,0,0,16,185,0,1,0,4,244,65,11,0,182,0,1,0,198,0,1,0,214,0,1,0,230,0,1,0,246,0,1,0,5,93,65,7,0,6,0,1,0,22,0,1,0,38,0,1,0,3,113,184,0,2,208,184,0,1,16,184,0,3,208,184,0,0,16,184,0,4,208,184,0,0,16,184,0,5,208,65,3,0,223,0,7,0,1,93,65,3,0,16,0,7,0,1,93,184,0,7,16,185,0,6,0,4,244,0,184,0,0,69,88,184,0,9,47,27,185,0,9,0,16,62,89,184,0,0,69,88,184,0,6,47,27,185,0,6,0,6,62,89,184,0,1,208,184,0,9,16,184,0,3,208,186,0,2,0,3,0,1,17,18,57,25,184,0,2,47,24,184,0,5,208,48,49,33,35,3,19,51,11,1,35,17,51,2,0,102,215,215,102,215,130,93,93,1,40,1,8,254,248,254,216,2,48,0,0,0,2,0,8,0,0,2,14,2,48,0,7,0,10,2,64,187,0,7,0,4,0,6,0,4,43,65,3,0,255,0,7,0,1,93,65,3,0,0,0,7,0,1,113,65,3,0,96,0,7,0,1,93,184,0,7,16,184,0,0,208,65,3,0,136,0,0,0,1,93,65,3,0,23,0,0,0,1,113,65,3,0,55,0,0,0,1,93,185,0,1,0,4,244,65,3,0,255,0,6,0,1,93,65,3,0,0,0,6,0,1,113,65,3,0,96,0,6,0,1,93,186,0,9,0,6,0,7,17,18,57,186,0,2,0,1,0,9,17,18,57,184,0,6,16,184,0,5,208,65,3,0,56,0,5,0,1,93,65,3,0,24,0,5,0,1,113,65,3,0,135,0,5,0,1,93,185,0,4,0,4,244,186,0,3,0,4,0,9,17,18,57,186,0,8,0,9,0,1,17,18,57,186,0,10,0,9,0,4,17,18,57,65,3,0,63,0,12,0,1,93,65,3,0,31,0,12,0,1,93,0,184,0,0,69,88,184,0,6,47,27,185,0,6,0,16,62,89,184,0,0,69,88,184,0,4,47,27,185,0,4,0,6,62,89,184,0,1,208,186,0,10,0,6,0,4,17,18,57,184,0,10,47,185,0,3,0,2,244,184,0,6,16,184,0,9,208,65,3,0,42,0,9,0,1,113,48,49,1,65,3,0,167,0,1,0,1,93,65,3,0,120,0,3,0,1,93,65,3,0,168,0,4,0,1,93,65,3,0,136,0,6,0,1,93,65,7,0,216,0,6,0,232,0,6,0,248,0,6,0,3,93,65,13,0,8,0,6,0,24,0,6,0,40,0,6,0,56,0,6,0,72,0,6,0,88,0,6,0,6,113,65,7,0,89,0,6,0,105,0,6,0,121,0,6,0,3,93,65,5,0,86,0,7,0,102,0,7,0,2,93,65,5,0,119,0,7,0,135,0,7,0,2,93,65,7,0,215,0,7,0,231,0,7,0,247,0,7,0,3,93,65,13,0,7,0,7,0,23,0,7,0,39,0,7,0,55,0,7,0,71,0,7,0,87,0,7,0,6,113,65,3,0,136,0,8,0,1,93,65,3,0,89,0,8,0,1,93,65,3,0,86,0,10,0,1,93,65,3,0,135,0,10,0,1,93,0,65,3,0,41,0,9,0,1,93,65,3,0,74,0,9,0,1,93,65,7,0,218,0,9,0,234,0,9,0,250,0,9,0,3,93,65,5,0,10,0,9,0,26,0,9,0,2,113,65,3,0,59,0,9,0,1,93,65,3,0,43,0,9,0,1,113,65,3,0,140,0,9,0,1,93,33,35,39,35,7,35,19,51,19,39,7,2,14,97,55,214,54,98,213,93,29,76,76,141,141,2,48,254,181,189,189,0,0,1,0,46,0,0,2,154,2,48,0,11,2,50,186,0,0,0,6,0,3,43,65,3,0,0,0,0,0,1,113,65,3,0,47,0,0,0,1,93,65,3,0,16,0,0,0,1,93,65,5,0,112,0,0,0,128,0,0,0,2,93,65,3,0,64,0,0,0,1,93,184,0,0,16,185,0,1,0,4,244,184,0,2,208,65,3,0,87,0,2,0,1,93,65,5,0,31,0,6,0,47,0,6,0,2,113,65,3,0,47,0,6,0,1,93,65,3,0,16,0,6,0,1,93,186,0,3,0,6,0,0,17,18,57,184,0,6,16,185,0,5,0,4,244,184,0,4,208,65,3,0,88,0,4,0,1,93,184,0,6,16,184,0,7,208,186,0,8,0,7,0,4,17,18,57,65,3,0,39,0,8,0,1,93,65,3,0,102,0,8,0,1,93,184,0,3,16,184,0,9,208,65,3,0,232,0,9,0,1,93,184,0,0,16,184,0,11,208,186,0,10,0,2,0,11,17,18,57,65,3,0,40,0,10,0,1,93,0,184,0,0,69,88,184,0,7,47,27,185,0,7,0,16,62,89,184,0,0,69,88,184,0,5,47,27,185,0,5,0,6,62,89,184,0,1,208,184,0,7,16,184,0,4,208,65,5,0,27,0,4,0,43,0,4,0,2,113,65,3,0,139,0,4,0,1,93,65,3,0,12,0,4,0,1,113,65,5,0,108,0,4,0,124,0,4,0,2,93,65,5,0,76,0,4,0,92,0,4,0,2,113,65,3,0,251,0,4,0,1,93,65,3,0,91,0,4,0,1,93,65,3,0,234,0,4,0,1,93,65,3,0,73,0,4,0,1,93,184,0,2,208,186,0,3,0,7,0,5,17,18,57,184,0,3,47,184,0,9,208,65,5,0,66,0,9,0,82,0,9,0,2,113,65,7,0,83,0,9,0,99,0,9,0,115,0,9,0,3,93,65,3,0,52,0,9,0,1,113,65,5,0,53,0,9,0,69,0,9,0,2,93,65,3,0,230,0,9,0,1,93,65,5,0,197,0,9,0,213,0,9,0,2,93,65,3,0,132,0,9,0,1,93,65,3,0,4,0,9,0,1,113,65,3,0,243,0,9,0,1,93,65,3,0,18,0,9,0,1,113,65,3,0,33,0,9,0,1,113,184,0,7,16,184,0,10,208,48,49,1,65,3,0,200,0,7,0,1,93,65,3,0,54,0,8,0,1,93,65,3,0,57,0,10,0,1,93,65,3,0,199,0,11,0,1,93,0,65,3,0,38,0,9,0,1,113,33,35,11,3,35,19,51,27,1,51,2,154,98,54,157,159,54,98,81,78,152,150,78,1,136,254,243,1,13,254,120,2,48,254,249,1,7,0,0,0,0,1,0,74,0,0,2,28,2,48,0,9,2,14,186,0,9,0,4,0,3,43,65,3,0,16,0,9,0,1,93,65,5,0,80,0,9,0,96,0,9,0,2,93,65,3,0,176,0,9,0,1,93,65,3,0,175,0,9,0,1,93,65,3,0,224,0,9,0,1,93,65,5,0,128,0,9,0,144,0,9,0,2,93,65,3,0,48,0,9,0,1,93,65,3,0,32,0,9,0,1,113,65,3,0,0,0,9,0,1,113,184,0,9,16,185,0,8,0,4,244,184,0,1,208,65,3,0,176,0,4,0,1,93,65,3,0,207,0,4,0,1,93,65,3,0,175,0,4,0,1,93,65,3,0,16,0,4,0,1,93,65,3,0,144,0,4,0,1,93,184,0,4,16,185,0,3,0,4,244,184,0,6,208,0,184,0,0,69,88,184,0,6,47,27,185,0,6,0,16,62,89,184,0,0,69,88,184,0,3,47,27,185,0,3,0,6,62,89,184,0,1,208,184,0,6,16,184,0,2,208,65,3,0,74,0,2,0,1,113,65,3,0,27,0,2,0,1,113,65,3,0,44,0,2,0,1,113,65,3,0,142,0,2,0,1,93,65,5,0,108,0,2,0,124,0,2,0,2,93,65,3,0,91,0,2,0,1,113,65,5,0,74,0,2,0,90,0,2,0,2,93,65,3,0,250,0,2,0,1,93,65,3,0,10,0,2,0,1,113,65,5,0,41,0,2,0,57,0,2,0,2,93,65,3,0,167,0,4,0,1,93,184,0,1,16,184,0,7,208,65,3,0,83,0,7,0,1,113,65,3,0,68,0,7,0,1,93,65,3,0,85,0,7,0,1,93,65,3,0,53,0,7,0,1,93,65,3,0,38,0,7,0,1,93,65,3,0,245,0,7,0,1,93,65,7,0,4,0,7,0,20,0,7,0,36,0,7,0,3,113,65,3,0,68,0,7,0,1,113,65,3,0,131,0,7,0,1,93,65,5,0,98,0,7,0,114,0,7,0,2,93,184,0,6,16,184,0,8,208,48,49,1,65,3,0,85,0,6,0,1,93,65,3,0,71,0,6,0,1,93,0,65,5,0,122,0,2,0,138,0,2,0,2,93,65,3,0,43,0,2,0,1,113,65,3,0,69,0,7,0,1,93,65,3,0,117,0,7,0,1,93,65,3,0,37,0,7,0,1,113,65,3,0,87,0,7,0,1,93,33,35,1,17,35,17,51,1,17,51,2,28,78,254,217,93,96,1,20,94,1,149,254,107,2,48,254,130,1,126,0,0,0,2,0,39,255,245,2,114,2,59,0,18,0,37,2,43,186,0,17,0,7,0,3,43,65,3,0,79,0,7,0,1,93,65,3,0,159,0,7,0,1,93,65,3,0,111,0,7,0,1,93,65,3,0,15,0,7,0,1,93,65,3,0,128,0,7,0,1,93,65,3,0,0,0,17,0,1,113,65,3,0,128,0,17,0,1,93,65,3,0,32,0,17,0,1,113,65,3,0,224,0,17,0,1,93,65,3,0,176,0,17,0,1,93,184,0,7,16,185,0,26,0,4,244,184,0,17,16,185,0,36,0,4,244,65,3,0,47,0,39,0,1,93,65,3,0,95,0,39,0,1,93,0,184,0,0,69,88,184,0,12,47,27,185,0,12,0,16,62,89,184,0,0,69,88,184,0,2,47,27,185,0,2,0,6,62,89,184,0,12,16,185,0,21,0,2,244,184,0,2,16,185,0,31,0,2,244,48,49,1,65,3,0,134,0,0,0,1,93,65,3,0,138,0,5,0,1,93,65,3,0,137,0,9,0,1,93,65,3,0,135,0,14,0,1,93,65,3,0,135,0,15,0,1,93,65,3,0,181,0,19,0,1,93,65,3,0,166,0,19,0,1,93,65,5,0,24,0,19,0,40,0,19,0,2,93,65,3,0,121,0,19,0,1,93,65,5,0,23,0,23,0,39,0,23,0,2,93,65,3,0,168,0,24,0,1,93,65,3,0,185,0,24,0,1,93,65,5,0,22,0,29,0,38,0,29,0,2,93,65,3,0,168,0,29,0,1,93,65,3,0,185,0,29,0,1,93,65,3,0,120,0,33,0,1,93,65,5,0,25,0,33,0,41,0,33,0,2,93,65,3,0,165,0,34,0,1,93,65,3,0,182,0,34,0,1,93,0,65,3,0,137,0,0,0,1,93,65,3,0,136,0,5,0,1,93,65,3,0,134,0,9,0,1,93,65,3,0,135,0,14,0,1,93,65,3,0,134,0,15,0,1,93,65,3,0,166,0,19,0,1,93,65,3,0,183,0,19,0,1,93,65,5,0,24,0,19,0,40,0,19,0,2,93,65,3,0,182,0,24,0,1,93,65,3,0,167,0,24,0,1,93,65,5,0,24,0,24,0,40,0,24,0,2,93,65,5,0,23,0,29,0,39,0,29,0,2,93,65,3,0,169,0,29,0,1,93,65,3,0,186,0,29,0,1,93,65,5,0,22,0,33,0,38,0,33,0,2,93,65,3,0,118,0,33,0,1,93,65,5,0,168,0,34,0,184,0,34,0,2,93,37,6,35,34,46,2,53,52,62,2,51,50,30,2,21,20,3,38,35,34,14,2,21,20,30,2,51,50,62,2,53,52,2,31,83,128,64,108,78,43,43,78,108,64,64,108,78,44,153,50,91,46,71,49,25,25,49,71,46,46,71,49,25,69,80,42,76,108,65,65,107,77,42,42,77,107,65,131,1,22,56,29,54,75,45,45,75,54,29,30,53,75,45,91,0,0,0,0,2,255,248,0,0,2,193,2,48,0,15,0,18,1,118,186,0,0,0,1,0,3,43,65,3,0,16,0,0,0,1,93,65,3,0,15,0,0,0,1,113,65,3,0,144,0,0,0,1,93,65,3,0,96,0,0,0,1,93,65,3,0,15,0,1,0,1,113,65,3,0,127,0,1,0,1,93,184,0,1,16,184,0,5,208,65,3,0,170,0,5,0,1,93,65,3,0,26,0,5,0,1,93,65,3,0,38,0,5,0,1,93,185,0,4,0,4,244,184,0,1,16,184,0,16,208,186,0,3,0,4,0,16,17,18,57,65,3,0,250,0,3,0,1,93,184,0,6,208,65,5,0,234,0,6,0,250,0,6,0,2,93,65,7,0,106,0,6,0,122,0,6,0,138,0,6,0,3,93,65,5,0,25,0,6,0,41,0,6,0,2,113,65,3,0,89,0,6,0,1,93,184,0,0,16,184,0,8,208,184,0,8,47,184,0,1,16,185,0,14,0,4,244,184,0,10,208,184,0,0,16,184,0,12,208,184,0,12,47,186,0,18,0,16,0,4,17,18,57,65,3,0,86,0,18,0,1,93,65,3,0,38,0,18,0,1,93,0,184,0,0,69,88,184,0,6,47,27,185,0,6,0,16,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,186,0,16,0,1,0,6,17,18,57,184,0,16,47,185,0,2,0,2,244,184,0,1,16,184,0,4,208,184,0,6,16,185,0,9,0,2,244,186,0,10,0,6,0,1,17,18,57,184,0,10,47,185,0,13,0,2,244,184,0,1,16,185,0,14,0,2,244,184,0,9,16,184,0,17,208,65,3,0,42,0,17,0,1,113,48,49,41,1,53,35,7,35,1,33,21,33,21,51,21,35,21,33,37,53,7,2,193,254,142,175,74,94,1,34,1,159,254,253,200,200,1,11,254,142,132,138,138,2,48,89,135,88,160,140,241,241,0,2,0,74,0,0,1,227,2,48,0,14,0,23,1,63,186,0,10,0,3,0,3,43,65,3,0,16,0,3,0,1,93,65,3,0,207,0,3,0,1,93,65,3,0,176,0,3,0,1,93,65,3,0,48,0,3,0,1,93,184,0,3,16,185,0,2,0,4,244,65,3,0,48,0,10,0,1,93,65,3,0,176,0,10,0,1,93,65,3,0,112,0,10,0,1,93,65,3,0,16,0,10,0,1,93,65,5,0,16,0,10,0,32,0,10,0,2,113,184,0,17,208,184,0,10,16,185,0,21,0,4,244,0,184,0,0,69,88,184,0,4,47,27,185,0,4,0,16,62,89,184,0,0,69,88,184,0,2,47,27,185,0,2,0,6,62,89,186,0,1,0,4,0,2,17,18,57,184,0,1,47,184,0,4,16,185,0,16,0,2,244,184,0,1,16,185,0,17,0,2,244,48,49,1,65,3,0,135,0,7,0,1,93,65,5,0,165,0,8,0,181,0,8,0,2,93,65,3,0,6,0,8,0,1,93,65,3,0,134,0,8,0,1,93,65,3,0,198,0,8,0,1,93,65,3,0,23,0,8,0,1,93,65,3,0,6,0,12,0,1,93,0,65,3,0,134,0,7,0,1,93,65,3,0,134,0,8,0,1,93,65,3,0,198,0,8,0,1,93,65,5,0,7,0,8,0,23,0,8,0,2,93,65,5,0,167,0,8,0,183,0,8,0,2,93,65,3,0,9,0,12,0,1,93,37,35,21,35,17,51,50,30,2,21,20,14,2,3,35,21,51,50,54,53,52,38,1,33,119,96,180,54,86,60,29,36,56,69,62,90,104,60,53,55,188,188,2,48,15,39,68,54,56,75,45,20,1,37,207,51,57,54,45,0,0,0,2,0,39,255,245,2,114,2,59,0,21,0,43,2,248,186,0,19,0,9,0,3,43,65,3,0,224,0,19,0,1,93,65,3,0,32,0,19,0,1,113,65,3,0,0,0,19,0,1,113,65,3,0,176,0,19,0,1,93,65,3,0,128,0,19,0,1,93,65,3,0,111,0,9,0,1,93,65,3,0,15,0,9,0,1,93,65,3,0,159,0,9,0,1,93,65,3,0,79,0,9,0,1,93,65,3,0,128,0,9,0,1,93,186,0,21,0,19,0,9,17,18,57,184,0,21,16,184,0,0,208,184,0,0,47,186,0,2,0,9,0,19,17,18,57,184,0,9,16,185,0,27,0,4,244,184,0,19,16,185,0,39,0,4,244,186,0,34,0,27,0,39,17,18,57,65,3,0,106,0,34,0,1,93,65,3,0,121,0,34,0,1,93,184,0,34,16,184,0,35,208,184,0,35,47,65,3,0,47,0,35,0,1,113,65,3,0,127,0,35,0,1,93,65,5,0,31,0,35,0,47,0,35,0,2,93,186,0,37,0,39,0,27,17,18,57,65,3,0,47,0,45,0,1,93,65,3,0,95,0,45,0,1,93,0,184,0,0,69,88,184,0,14,47,27,185,0,14,0,16,62,89,184,0,0,69,88,184,0,4,47,27,185,0,4,0,6,62,89,186,0,2,0,4,0,14,17,18,57,184,0,2,16,184,0,1,208,184,0,1,47,186,0,21,0,14,0,4,17,18,57,65,3,0,135,0,21,0,1,93,184,0,14,16,185,0,22,0,2,244,184,0,4,16,185,0,32,0,2,244,186,0,34,0,32,0,22,17,18,57,186,0,37,0,22,0,32,17,18,57,184,0,37,16,184,0,36,208,184,0,36,47,48,49,1,65,5,0,23,0,2,0,39,0,2,0,2,113,65,3,0,137,0,2,0,1,93,65,3,0,136,0,3,0,1,93,65,3,0,137,0,6,0,1,93,65,3,0,137,0,7,0,1,93,65,3,0,138,0,11,0,1,93,65,3,0,133,0,17,0,1,93,65,3,0,19,0,21,0,1,113,65,3,0,36,0,21,0,1,113,65,5,0,20,0,24,0,36,0,24,0,2,93,65,5,0,22,0,29,0,38,0,29,0,2,93,65,3,0,117,0,30,0,1,93,65,3,0,184,0,30,0,1,93,65,3,0,169,0,30,0,1,93,65,3,0,24,0,34,0,1,113,65,3,0,43,0,34,0,1,113,65,3,0,138,0,35,0,1,93,65,3,0,23,0,37,0,1,113,65,3,0,40,0,37,0,1,113,65,3,0,121,0,42,0,1,93,65,5,0,26,0,42,0,42,0,42,0,2,93,0,65,3,0,25,0,2,0,1,113,65,3,0,42,0,2,0,1,113,65,3,0,138,0,3,0,1,93,65,3,0,136,0,7,0,1,93,65,3,0,134,0,11,0,1,93,65,3,0,134,0,16,0,1,93,65,3,0,39,0,21,0,1,113,65,3,0,182,0,24,0,1,93,65,3,0,167,0,24,0,1,93,65,5,0,24,0,24,0,40,0,24,0,2,93,65,3,0,118,0,30,0,1,93,65,5,0,168,0,30,0,184,0,30,0,2,93,65,5,0,24,0,34,0,40,0,34,0,2,113,65,3,0,37,0,36,0,1,113,65,3,0,20,0,37,0,1,113,65,3,0,117,0,37,0,1,93,65,3,0,37,0,37,0,1,113,65,3,0,121,0,42,0,1,93,37,7,39,6,35,34,46,2,53,52,62,2,51,50,30,2,21,20,7,3,34,14,2,21,20,30,2,51,50,55,39,55,23,54,53,52,46,2,2,107,52,57,78,100,64,108,78,43,43,78,108,64,64,108,78,44,59,235,46,71,49,25,25,49,71,46,65,44,80,51,83,33,26,51,73,58,62,44,51,42,76,108,65,65,107,77,42,42,77,107,65,101,80,1,128,29,54,75,45,45,75,54,29,23,60,64,65,46,75,45,75,54,29,0,0,0,0,2,0,74,0,0,2,3,2,48,0,11,0,19,1,143,186,0,9,0,5,0,3,43,65,7,0,16,0,9,0,32,0,9,0,48,0,9,0,3,93,65,3,0,144,0,9,0,1,93,65,3,0,176,0,9,0,1,93,65,3,0,112,0,9,0,1,93,65,3,0,240,0,9,0,1,93,65,5,0,16,0,9,0,32,0,9,0,2,113,65,3,0,16,0,5,0,1,93,65,3,0,175,0,5,0,1,93,65,3,0,48,0,5,0,1,93,65,3,0,176,0,5,0,1,93,65,3,0,144,0,5,0,1,93,186,0,11,0,9,0,5,17,18,57,65,3,0,54,0,11,0,1,93,65,9,0,86,0,11,0,102,0,11,0,118,0,11,0,134,0,11,0,4,93,184,0,11,16,184,0,0,208,65,3,0,70,0,0,0,1,93,184,0,11,16,185,0,2,0,4,244,184,0,1,208,184,0,5,16,185,0,4,0,4,244,184,0,14,208,184,0,9,16,185,0,18,0,4,244,0,184,0,0,69,88,184,0,7,47,27,185,0,7,0,16,62,89,184,0,0,69,88,184,0,4,47,27,185,0,4,0,6,62,89,184,0,1,208,186,0,3,0,7,0,4,17,18,57,184,0,3,47,186,0,11,0,3,0,7,17,18,57,184,0,7,16,185,0,12,0,2,244,184,0,3,16,185,0,14,0,2,244,48,49,1,65,3,0,132,0,8,0,1,93,65,7,0,7,0,8,0,23,0,8,0,39,0,8,0,3,93,65,3,0,133,0,10,0,1,93,65,3,0,118,0,10,0,1,93,65,3,0,122,0,19,0,1,93,0,65,3,0,5,0,8,0,1,93,65,3,0,134,0,8,0,1,93,65,3,0,23,0,8,0,1,93,65,3,0,138,0,10,0,1,93,65,3,0,120,0,19,0,1,93,33,35,39,35,21,35,17,51,50,21,20,7,39,35,21,51,50,54,53,52,2,3,99,128,118,96,204,205,105,112,96,106,52,58,212,212,2,48,162,110,52,247,183,48,45,90,0,0,0,0,1,0,41,255,245,1,221,2,59,0,48,2,215,186,0,44,0,16,0,3,43,65,3,0,47,0,16,0,1,93,65,3,0,111,0,16,0,1,93,65,3,0,15,0,16,0,1,93,65,3,0,79,0,16,0,1,93,65,3,0,16,0,16,0,1,93,65,3,0,48,0,16,0,1,93,65,3,0,80,0,44,0,1,93,65,3,0,176,0,44,0,1,93,65,3,0,208,0,44,0,1,93,65,7,0,112,0,44,0,128,0,44,0,144,0,44,0,3,93,65,3,0,48,0,44,0,1,93,65,3,0,16,0,44,0,1,93,186,0,2,0,16,0,44,17,18,57,184,0,2,47,184,0,44,16,185,0,7,0,4,244,186,0,26,0,44,0,16,17,18,57,184,0,26,47,184,0,16,16,185,0,34,0,4,244,0,184,0,0,69,88,184,0,21,47,27,185,0,21,0,16,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,184,0,3,220,65,3,0,32,0,3,0,1,93,184,0,0,16,185,0,5,0,2,244,186,0,11,0,0,0,21,17,18,57,65,3,0,138,0,11,0,1,93,65,7,0,89,0,11,0,105,0,11,0,121,0,11,0,3,93,184,0,21,16,184,0,27,220,65,3,0,47,0,27,0,1,93,65,3,0,144,0,27,0,1,93,184,0,21,16,185,0,29,0,2,244,186,0,37,0,21,0,0,17,18,57,48,49,1,65,3,0,121,0,9,0,1,93,65,3,0,25,0,14,0,1,93,65,3,0,121,0,14,0,1,93,65,3,0,43,0,14,0,1,93,65,3,0,9,0,19,0,1,93,65,13,0,55,0,25,0,71,0,25,0,87,0,25,0,103,0,25,0,119,0,25,0,135,0,25,0,6,93,65,3,0,133,0,36,0,1,93,65,3,0,135,0,39,0,1,93,65,3,0,6,0,41,0,1,93,65,3,0,38,0,41,0,1,93,65,3,0,23,0,41,0,1,93,65,3,0,87,0,41,0,1,93,65,3,0,37,0,42,0,1,93,65,3,0,101,0,42,0,1,93,65,3,0,22,0,42,0,1,93,65,5,0,6,0,47,0,22,0,47,0,2,93,0,65,15,0,58,0,1,0,74,0,1,0,90,0,1,0,106,0,1,0,122,0,1,0,138,0,1,0,154,0,1,0,7,93,65,3,0,43,0,1,0,1,113,65,3,0,28,0,1,0,1,113,65,13,0,58,0,2,0,74,0,2,0,90,0,2,0,106,0,2,0,122,0,2,0,138,0,2,0,6,93,65,3,0,121,0,9,0,1,93,65,3,0,41,0,14,0,1,93,65,3,0,121,0,14,0,1,93,65,3,0,26,0,14,0,1,93,65,3,0,5,0,19,0,1,93,65,13,0,53,0,25,0,69,0,25,0,85,0,25,0,101,0,25,0,117,0,25,0,133,0,25,0,6,93,65,3,0,134,0,39,0,1,93,65,3,0,84,0,41,0,1,93,65,3,0,6,0,41,0,1,93,65,5,0,23,0,41,0,39,0,41,0,2,93,65,3,0,22,0,42,0,1,93,65,3,0,102,0,42,0,1,93,65,3,0,39,0,42,0,1,93,65,3,0,40,0,47,0,1,93,65,5,0,10,0,47,0,26,0,47,0,2,93,23,34,39,55,22,51,50,53,52,46,2,47,1,46,1,53,52,62,2,51,50,30,2,23,7,38,35,34,14,2,21,20,30,2,23,30,3,21,20,14,2,246,129,67,12,71,115,126,29,53,75,46,48,35,47,26,52,81,56,27,55,49,42,15,10,102,70,24,45,34,20,26,53,78,53,23,46,36,23,15,49,91,11,39,107,58,70,24,34,26,23,14,21,15,54,48,31,60,46,28,7,11,15,8,96,50,8,16,26,18,24,26,20,22,20,9,24,35,51,36,24,56,48,32,0,0,0,0,1,0,17,0,0,1,197,2,48,0,7,0,113,187,0,1,0,4,0,4,0,4,43,65,3,0,176,0,1,0,1,93,184,0,1,16,184,0,0,220,65,3,0,176,0,4,0,1,93,184,0,4,16,184,0,5,220,65,3,0,15,0,9,0,1,93,65,3,0,112,0,9,0,1,93,0,184,0,0,69,88,184,0,6,47,27,185,0,6,0,16,62,89,184,0,0,69,88,184,0,3,47,27,185,0,3,0,6,62,89,184,0,6,16,185,0,5,0,2,244,184,0,1,208,48,49,1,35,17,35,17,35,53,33,1,197,171,94,171,1,180,1,216,254,40,1,216,88,0,0,0,0,1,0,67,255,245,2,48,2,48,0,21,1,39,186,0,18,0,4,0,3,43,65,3,0,175,0,4,0,1,93,65,3,0,223,0,4,0,1,93,65,3,0,16,0,4,0,1,93,184,0,4,16,185,0,5,0,4,244,65,3,0,240,0,18,0,1,93,65,3,0,223,0,18,0,1,93,65,3,0,175,0,18,0,1,93,65,3,0,16,0,18,0,1,93,65,3,0,16,0,18,0,1,113,184,0,18,16,185,0,17,0,4,244,0,184,0,0,69,88,184,0,5,47,27,185,0,5,0,16,62,89,184,0,0,69,88,184,0,0,47,27,185,0,0,0,6,62,89,185,0,11,0,2,244,184,0,5,16,184,0,17,208,48,49,1,65,3,0,88,0,1,0,1,93,65,5,0,55,0,9,0,71,0,9,0,2,93,65,5,0,57,0,13,0,73,0,13,0,2,93,65,3,0,85,0,20,0,1,93,65,3,0,103,0,20,0,1,93,65,5,0,88,0,21,0,104,0,21,0,2,93,0,65,3,0,105,0,1,0,1,93,65,3,0,90,0,1,0,1,93,65,3,0,54,0,9,0,1,93,65,3,0,71,0,9,0,1,93,65,3,0,70,0,13,0,1,93,65,3,0,55,0,13,0,1,93,65,3,0,104,0,20,0,1,93,65,5,0,89,0,21,0,105,0,21,0,2,93,5,34,38,53,17,51,17,20,30,2,51,50,62,2,53,17,51,17,20,6,1,58,123,124,93,14,36,59,45,47,60,34,12,93,123,11,133,117,1,65,254,226,46,73,51,27,30,53,72,42,1,30,254,191,118,132,0,0,0,0,1,0,6,0,0,2,42,2,48,0,6,1,51,187,0,1,0,4,0,2,0,4,43,65,3,0,176,0,1,0,1,93,65,3,0,96,0,1,0,1,93,184,0,1,16,184,0,0,208,65,3,0,56,0,0,0,1,93,65,3,0,118,0,0,0,1,93,65,3,0,96,0,2,0,1,93,65,3,0,176,0,2,0,1,93,184,0,2,16,184,0,3,208,65,3,0,121,0,3,0,1,93,65,3,0,55,0,3,0,1,93,185,0,4,0,4,244,186,0,5,0,2,0,1,17,18,57,184,0,0,16,185,0,6,0,4,244,0,184,0,0,69,88,184,0,4,47,27,185,0,4,0,16,62,89,184,0,0,69,88,184,0,2,47,27,185,0,2,0,6,62,89,184,0,5,208,65,3,0,70,0,5,0,1,93,65,5,0,85,0,5,0,101,0,5,0,2,93,184,0,4,16,184,0,6,208,48,49,1,65,13,0,167,0,1,0,183,0,1,0,199,0,1,0,215,0,1,0,231,0,1,0,247,0,1,0,6,93,65,7,0,7,0,1,0,23,0,1,0,39,0,1,0,3,113,65,13,0,168,0,2,0,184,0,2,0,200,0,2,0,216,0,2,0,232,0,2,0,248,0,2,0,6,93,65,7,0,8,0,2,0,24,0,2,0,40,0,2,0,3,113,0,65,3,0,130,0,5,0,1,93,65,3,0,116,0,5,0,1,93,1,3,35,3,51,27,1,2,42,220,106,222,98,177,175,2,48,253,208,2,48,254,70,1,186,0,0,0,1,0,17,0,0,3,54,2,48,0,12,2,97,186,0,10,0,9,0,3,43,65,3,0,175,0,10,0,1,93,65,3,0,39,0,10,0,1,93,65,3,0,16,0,10,0,1,93,184,0,10,16,184,0,1,220,184,0,0,208,65,3,0,103,0,0,0,1,93,65,3,0,6,0,0,0,1,93,184,0,1,16,185,0,2,0,4,244,65,3,0,41,0,2,0,1,93,65,3,0,175,0,9,0,1,93,65,3,0,16,0,9,0,1,93,186,0,3,0,9,0,10,17,18,57,184,0,9,16,184,0,5,220,185,0,4,0,4,244,184,0,5,16,184,0,6,208,65,3,0,9,0,6,0,1,93,65,3,0,104,0,6,0,1,93,185,0,7,0,4,244,186,0,8,0,5,0,4,17,18,57,186,0,11,0,2,0,1,17,18,57,184,0,0,16,185,0,12,0,4,244,0,184,0,0,69,88,184,0,7,47,27,185,0,7,0,16,62,89,184,0,0,69,88,184,0,4,47,27,185,0,4,0,6,62,89,184,0,2,208,184,0,7,16,184,0,9,208,184,0,9,47,184,0,3,208,65,9,0,74,0,3,0,90,0,3,0,106,0,3,0,122,0,3,0,4,93,184,0,4,16,184,0,8,208,65,3,0,70,0,8,0,1,93,65,3,0,85,0,8,0,1,93,65,3,0,37,0,8,0,1,113,184,0,11,208,184,0,7,16,184,0,12,208,48,49,1,65,3,0,69,0,1,0,1,113,65,3,0,246,0,1,0,1,93,65,7,0,6,0,1,0,22,0,1,0,38,0,1,0,3,113,65,3,0,200,0,2,0,1,93,65,7,0,73,0,2,0,89,0,2,0,105,0,2,0,3,93,65,3,0,70,0,4,0,1,93,65,3,0,102,0,4,0,1,93,65,3,0,87,0,4,0,1,93,65,3,0,199,0,4,0,1,93,65,3,0,249,0,5,0,1,93,65,7,0,9,0,5,0,25,0,5,0,41,0,5,0,3,113,65,3,0,74,0,5,0,1,113,65,3,0,135,0,7,0,1,93,65,3,0,135,0,8,0,1,93,65,5,0,232,0,9,0,248,0,9,0,2,93,65,7,0,8,0,9,0,24,0,9,0,40,0,9,0,3,113,65,5,0,231,0,10,0,247,0,10,0,2,93,65,7,0,7,0,10,0,23,0,10,0,39,0,10,0,3,113,65,3,0,136,0,12,0,1,93,0,65,5,0,74,0,3,0,90,0,3,0,2,93,65,3,0,138,0,3,0,1,93,65,3,0,107,0,3,0,1,93,65,3,0,251,0,3,0,1,93,65,7,0,11,0,3,0,27,0,3,0,43,0,3,0,3,113,65,3,0,75,0,3,0,1,113,65,3,0,125,0,3,0,1,93,1,3,35,11,1,35,3,51,27,1,51,27,1,3,54,174,93,136,140,95,167,98,126,141,74,145,123,2,48,253,208,1,148,254,108,2,48,254,87,1,165,254,98,1,162,0,1,0,14,0,0,2,17,2,48,0,11,1,176,187,0,11,0,4,0,5,0,4,43,65,5,0,87,0,11,0,103,0,11,0,2,93,65,3,0,48,0,11,0,1,93,184,0,11,16,184,0,0,208,65,3,0,5,0,0,0,1,113,65,3,0,166,0,0,0,1,93,65,3,0,135,0,0,0,1,93,65,3,0,89,0,0,0,1,93,65,3,0,8,0,0,0,1,93,65,3,0,55,0,0,0,1,93,65,3,0,214,0,0,0,1,93,65,3,0,181,0,0,0,1,93,65,3,0,69,0,0,0,1,93,185,0,1,0,4,244,65,3,0,7,0,1,0,1,113,65,3,0,48,0,5,0,1,93,186,0,2,0,5,0,11,17,18,57,184,0,5,16,184,0,4,208,65,3,0,103,0,4,0,1,93,65,3,0,40,0,4,0,1,113,65,3,0,73,0,4,0,1,93,65,3,0,185,0,4,0,1,93,65,3,0,168,0,4,0,1,93,65,3,0,6,0,4,0,1,93,65,3,0,86,0,4,0,1,93,185,0,3,0,4,244,184,0,4,16,184,0,6,208,184,0,3,16,184,0,7,208,186,0,8,0,5,0,11,17,18,57,184,0,1,16,184,0,9,208,184,0,0,16,184,0,10,208,65,3,0,31,0,13,0,1,93,0,184,0,0,69,88,184,0,7,47,27,185,0,7,0,16,62,89,184,0,0,69,88,184,0,3,47,27,185,0,3,0,6,62,89,184,0,1,208,186,0,2,0,3,0,7,17,18,57,186,0,8,0,7,0,3,17,18,57,65,3,0,54,0,8,0,1,93,65,3,0,69,0,8,0,1,93,186,0,5,0,8,0,2,17,18,57,184,0,7,16,184,0,9,208,186,0,11,0,2,0,8,17,18,57,48,49,1,65,3,0,119,0,11,0,1,93,0,65,3,0,122,0,2,0,1,93,65,3,0,139,0,2,0,1,93,65,5,0,117,0,8,0,133,0,8,0,2,93,33,35,39,7,35,19,3,51,23,55,51,3,2,17,104,159,149,103,204,200,108,146,148,103,205,214,214,1,23,1,25,205,205,254,242,0,0,0,0,1,0,1,0,0,1,247,2,48,0,8,1,20,187,0,1,0,4,0,4,0,4,43,65,3,0,48,0,1,0,1,93,65,3,0,144,0,1,0,1,93,184,0,1,16,184,0,0,208,65,3,0,9,0,0,0,1,93,65,3,0,89,0,0,0,1,93,65,3,0,135,0,0,0,1,93,65,3,0,70,0,0,0,1,93,65,3,0,144,0,4,0,1,93,65,3,0,48,0,4,0,1,93,184,0,4,16,184,0,5,208,65,3,0,136,0,5,0,1,93,65,3,0,73,0,5,0,1,93,65,3,0,6,0,5,0,1,93,65,3,0,86,0,5,0,1,93,185,0,6,0,4,244,186,0,7,0,4,0,1,17,18,57,184,0,0,16,185,0,8,0,4,244,0,184,0,0,69,88,184,0,6,47,27,185,0,6,0,16,62,89,184,0,0,69,88,184,0,3,47,27,185,0,3,0,6,62,89,186,0,7,0,6,0,3,17,18,57,65,3,0,38,0,7,0,1,93,184,0,6,16,184,0,8,208,48,49,65,3,0,132,0,7,0,1,93,65,7,0,85,0,7,0,101,0,7,0,117,0,7,0,3,93,65,3,0,246,0,7,0,1,93,65,7,0,6,0,7,0,22,0,7,0,38,0,7,0,3,113,1,3,21,35,53,3,51,23,55,1,247,203,96,203,99,152,152,2,48,254,204,252,252,1,52,225,225,0,0,0,0,1,0,15,0,0,1,212,2,48,0,7,1,79,186,0,2,0,6,0,3,43,65,3,0,64,0,2,0,1,93,65,3,0,223,0,2,0,1,93,65,3,0,176,0,2,0,1,93,65,3,0,96,0,2,0,1,93,184,0,2,16,184,0,0,208,184,0,6,16,184,0,4,208,184,0,1,208,65,3,0,99,0,1,0,1,93,65,3,0,36,0,1,0,1,113,65,3,0,85,0,1,0,1,113,65,3,0,70,0,1,0,1,113,65,3,0,154,0,1,0,1,93,65,3,0,246,0,1,0,1,93,65,5,0,5,0,1,0,21,0,1,0,2,113,65,5,0,68,0,1,0,84,0,1,0,2,93,65,3,0,114,0,1,0,1,93,65,3,0,128,0,1,0,1,93,184,0,0,16,184,0,5,208,65,3,0,249,0,5,0,1,93,65,3,0,90,0,5,0,1,113,65,3,0,43,0,5,0,1,113,65,3,0,108,0,5,0,1,93,65,3,0,143,0,5,0,1,93,65,3,0,125,0,5,0,1,93,65,3,0,91,0,5,0,1,93,65,3,0,74,0,5,0,1,93,65,5,0,10,0,5,0,26,0,5,0,2,113,65,3,0,73,0,5,0,1,113,65,3,0,149,0,5,0,1,93,65,3,0,47,0,9,0,1,93,0,184,0,0,69,88,184,0,7,47,27,185,0,7,0,16,62,89,184,0,0,69,88,184,0,3,47,27,185,0,3,0,6,62,89,185,0,2,0,2,244,184,0,7,16,185,0,6,0,2,244,48,49,9,1,33,21,33,1,33,53,1,212,254,213,1,5,254,97,1,43,254,251,2,48,254,40,88,1,216,88,0,0,0,0,2,0,39,255,245,3,116,2,59,0,26,0,45,2,173,186,0,0,0,1,0,3,43,65,3,0,95,0,0,0,1,93,65,5,0,0,0,0,0,16,0,0,0,2,93,65,3,0,176,0,0,0,1,93,65,5,0,0,0,1,0,16,0,1,0,2,93,65,3,0,255,0,1,0,1,93,65,3,0,95,0,1,0,1,93,65,3,0,176,0,1,0,1,93,65,3,0,144,0,1,0,1,93,184,0,1,16,184,0,9,220,65,3,0,159,0,9,0,1,93,65,3,0,191,0,9,0,1,93,65,3,0,127,0,9,0,1,93,65,5,0,15,0,9,0,31,0,9,0,2,93,184,0,1,16,184,0,16,208,184,0,0,16,184,0,19,208,184,0,19,47,184,0,1,16,185,0,25,0,4,244,184,0,21,208,186,0,23,0,0,0,1,17,18,57,184,0,23,47,184,0,9,16,185,0,34,0,4,244,184,0,1,16,184,0,44,208,65,5,0,121,0,44,0,137,0,44,0,2,93,0,184,0,0,69,88,184,0,14,47,27,185,0,14,0,16,62,89,184,0,0,69,88,184,0,17,47,27,185,0,17,0,16,62,89,184,0,0,69,88,184,0,4,47,27,185,0,4,0,6,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,186,0,2,0,4,0,14,17,18,57,65,5,0,27,0,2,0,43,0,2,0,2,113,65,5,0,58,0,2,0,74,0,2,0,2,113,186,0,16,0,14,0,4,17,18,57,65,9,0,20,0,16,0,36,0,16,0,52,0,16,0,68,0,16,0,4,113,184,0,17,16,185,0,20,0,2,244,186,0,21,0,17,0,1,17,18,57,184,0,21,47,185,0,24,0,2,244,184,0,1,16,185,0,25,0,2,244,184,0,14,16,185,0,29,0,2,244,184,0,4,16,185,0,39,0,2,244,48,49,1,65,3,0,136,0,6,0,1,93,65,3,0,138,0,7,0,1,93,65,3,0,137,0,11,0,1,93,65,3,0,136,0,12,0,1,93,65,3,0,56,0,15,0,1,93,65,3,0,41,0,27,0,1,93,65,3,0,137,0,27,0,1,93,65,3,0,169,0,27,0,1,93,65,3,0,38,0,31,0,1,93,65,3,0,39,0,37,0,1,93,65,3,0,40,0,41,0,1,93,65,3,0,136,0,41,0,1,93,65,3,0,168,0,41,0,1,93,65,3,0,169,0,42,0,1,93,0,65,3,0,73,0,3,0,1,93,65,3,0,58,0,3,0,1,93,65,3,0,137,0,6,0,1,93,65,3,0,136,0,7,0,1,93,65,3,0,134,0,11,0,1,93,65,3,0,134,0,12,0,1,93,65,3,0,51,0,15,0,1,93,65,3,0,69,0,15,0,1,93,65,3,0,168,0,27,0,1,93,65,3,0,41,0,27,0,1,93,65,3,0,137,0,27,0,1,93,65,3,0,40,0,31,0,1,93,65,3,0,38,0,37,0,1,93,65,3,0,38,0,41,0,1,93,65,3,0,134,0,41,0,1,93,65,3,0,166,0,41,0,1,93,41,1,53,6,35,34,46,2,53,52,62,2,51,50,23,53,33,21,33,21,51,21,35,21,33,1,38,35,34,14,2,21,20,30,2,51,50,62,2,53,52,3,116,254,153,98,98,64,106,77,43,43,77,106,64,98,98,1,95,254,254,199,199,1,10,254,97,48,92,46,71,48,25,25,48,71,46,46,71,48,24,52,63,42,76,108,65,65,107,77,42,63,52,88,136,88,160,1,83,56,29,54,75,45,45,75,54,29,30,53,75,45,92,0,0,0,1,0,74,0,0,1,172,2,48,0,5,0,124,186,0,5,0,1,0,3,43,65,3,0,16,0,1,0,1,93,65,3,0,175,0,1,0,1,93,65,3,0,176,0,1,0,1,93,65,3,0,144,0,1,0,1,93,184,0,1,16,185,0,4,0,4,244,65,3,0,144,0,5,0,1,93,65,3,0,16,0,5,0,1,93,65,3,0,176,0,5,0,1,93,0,184,0,0,69,88,184,0,2,47,27,185,0,2,0,16,62,89,184,0,0,69,88,184,0,1,47,27,185,0,1,0,6,62,89,185,0,4,0,2,244,48,49,41,1,17,51,17,33,1,172,254,158,93,1,5,2,48,254,40,0,0,1,0,0,0,1,1,72,59,245,254,62,95,15,60,245,0,31,3,232,0,0,0,0,202,233,78,152,0,0,0,0,202,233,79,52,255,217,255,6,4,141,3,196,0,0,0,9,0,2,0,0,0,0,0,0,0,1,0,0,3,197,255,6,0,0,4,177,255,217,255,213,4,141,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,13,0,250,0,72,0,225,0,0,0,242,0,59,1,146,0,40,2,192,0,33,2,2,0,42,3,72,0,35,2,99,0,36,0,182,0,41,1,5,0,42,1,5,0,24,1,170,0,33,1,207,0,46,0,216,0,57,1,168,0,57,0,204,0,57,2,20,0,19,2,202,0,63,1,99,0,34,2,12,0,50,2,35,0,40,2,47,0,14,2,29,0,51,2,56,0,62,1,246,0,39,2,97,0,59,2,58,0,45,0,204,0,57,0,216,0,57,1,149,0,33,1,246,0,66,1,148,0,60,1,185,0,30,2,210,0,49,2,104,0,7,2,85,0,80,2,104,0,39,2,215,0,80,2,42,0,80,2,11,0,80,2,160,0,39,2,234,0,80,0,255,0,80,0,255,255,239,2,65,0,80,1,245,0,80,3,44,0,48,2,192,0,80,3,0,0,39,2,60,0,80,3,0,0,39,2,91,0,80,2,72,0,40,2,21,0,15,2,212,0,72,2,132,0,4,3,203,0,14,2,87,0,9,2,55,255,253,2,37,0,9,1,71,0,70,2,13,0,35,1,71,0,0,1,255,0,49,2,54,0,3,1,47,0,58,1,224,0,24,2,43,0,60,1,198,0,33,2,43,0,32,2,0,0,31,1,75,0,10,1,242,0,26,2,30,0,60,0,212,0,61,0,212,255,244,1,192,0,60,0,236,0,60,3,109,0,61,2,47,0,61,2,38,0,32,2,45,0,61,2,45,0,33,1,65,0,61,1,158,0,32,1,81,0,18,2,12,0,56,1,236,0,9,2,213,0,12,1,218,0,11,1,249,0,7,1,215,0,22,1,43,0,19,0,229,0,70,1,43,0,2,1,199,0,54,0,225,0,0,0,224,0,50,1,221,0,34,1,244,0,34,2,114,0,61,2,162,0,30,0,232,0,72,1,200,0,37,1,166,0,87,2,208,0,49,1,93,0,33,2,51,0,15,2,84,0,66,1,168,0,57,2,208,0,49,1,77,0,34,1,242,0,64,1,48,0,25,1,54,0,19,1,47,0,58,2,79,0,73,2,110,0,33,0,238,0,57,1,47,0,144,0,216,0,23,1,114,0,33,2,51,0,41,2,205,0,39,2,217,0,36,3,117,0,32,1,193,0,62,2,104,0,7,2,104,0,7,2,104,0,7,2,104,0,7,2,104,0,7,2,104,0,7,3,97,255,249,2,104,0,39,2,42,0,80,2,42,0,80,2,42,0,80,2,42,0,80,0,255,0,35,0,255,0,36,0,255,255,240,0,255,0,5,2,215,255,245,2,192,0,80,3,0,0,39,3,0,0,39,3,0,0,39,3,0,0,39,3,0,0,39,1,183,0,61,3,0,0,39,2,214,0,72,2,214,0,72,2,214,0,72,2,214,0,72,2,55,255,253,2,58,0,80,2,45,0,16,1,224,0,24,1,224,0,24,1,224,0,24,1,224,0,24,1,224,0,24,1,224,0,24,3,30,0,22,1,198,0,33,2,0,0,31,2,0,0,31,2,0,0,31,2,0,0,31,0,212,0,13,0,212,0,14,0,212,255,217,0,212,255,239,2,5,0,28,2,47,0,61,2,38,0,32,2,38,0,32,2,38,0,32,2,38,0,32,2,38,0,32,2,80,0,66,2,58,0,33,2,12,0,56,2,12,0,56,2,12,0,56,2,12,0,56,1,249,0,7,2,68,0,60,1,249,0,7,2,104,0,39,1,198,0,33,0,212,0,61,4,47,0,40,3,134,0,32,2,72,0,40,1,158,0,32,2,55,255,253,2,37,0,9,1,215,0,22,1,95,255,222,0,212,255,244,1,190,0,76,1,190,0,76,1,36,0,42,2,16,0,92,1,246,0,57,2,82,0,57,0,186,0,43,0,169,0,42,0,216,0,57,1,140,0,43,1,123,0,42,1,190,0,57,1,168,0,35,1,204,0,53,1,50,0,44,2,164,0,57,4,177,0,36,1,66,0,14,1,67,0,41,1,151,0,33,1,74,0,5,1,51,0,24,1,66,0,32,1,34,0,23,1,90,0,31,1,68,0,22,1,175,0,45,0,237,0,38,1,76,0,38,1,81,0,32,1,101,0,18,1,76,0,35,1,91,0,45,1,76,0,42,1,116,0,44,1,90,0,32,2,191,0,33,2,215,0,31,2,22,0,74,2,25,0,39,2,117,0,74,1,234,0,74,1,203,0,74,2,71,0,39,2,134,0,74,0,241,0,74,0,241,255,254,2,13,0,74,2,22,0,8,2,200,0,46,2,102,0,74,2,153,0,39,2,230,255,248,1,254,0,74,2,153,0,39,2,25,0,74,1,255,0,41,1,214,0,17,2,115,0,67,2,49,0,6,3,67,0,17,2,28,0,14,1,248,0,1,1,227,0,15,3,153,0,39,1,184,0,74,0,0,0,1,0,0,248,0,0,1,41,83,192,0,0,13,55,242,0,3,0,7,255,248,0,3,0,13,255,146,0,3,0,14,255,234,0,3,0,15,255,146,0,3,0,16,255,220,0,3,0,21,255,237,0,3,0,23,255,245,0,3,0,33,255,234,0,3,0,34,255,213,0,3,0,46,255,238,0,3,0,66,255,243,0,3,0,68,255,236,0,3,0,69,255,236,0,3,0,70,255,236,0,3,0,72,255,241,0,3,0,80,255,236,0,3,0,82,255,236,0,3,0,84,255,244,0,3,0,107,255,241,0,3,0,127,255,213,0,3,0,128,255,213,0,3,0,129,255,213,0,3,0,130,255,213,0,3,0,131,255,213,0,3,0,132,255,213,0,3,0,133,255,203,0,3,0,159,255,243,0,3,0,160,255,243,0,3,0,161,255,243,0,3,0,162,255,243,0,3,0,163,255,243,0,3,0,164,255,243,0,3,0,165,255,243,0,3,0,166,255,236,0,3,0,167,255,236,0,3,0,168,255,236,0,3,0,169,255,236,0,3,0,170,255,236,0,3,0,173,0,29,0,3,0,175,255,237,0,3,0,177,255,236,0,3,0,178,255,236,0,3,0,179,255,236,0,3,0,180,255,236,0,3,0,181,255,236,0,3,0,183,255,236,0,3,0,195,255,236,0,3,0,197,255,244,0,3,0,207,255,234,0,3,0,208,255,234,0,3,0,211,255,146,0,3,0,214,255,146,0,3,0,218,255,146,0,3,0,220,255,241,0,7,0,3,255,210,0,7,0,8,255,210,0,7,0,53,255,202,0,7,0,55,255,217,0,7,0,56,255,233,0,7,0,58,255,203,0,7,0,71,255,242,0,7,0,77,255,251,0,7,0,85,255,235,0,7,0,86,255,250,0,7,0,87,255,243,0,7,0,88,255,247,0,7,0,90,255,240,0,7,0,156,255,203,0,7,0,158,255,243,0,7,0,184,255,250,0,7,0,185,255,250,0,7,0,186,255,250,0,7,0,187,255,250,0,7,0,188,255,240,0,7,0,190,255,240,0,7,0,198,255,203,0,7,0,210,255,210,0,7,0,213,255,210,0,8,0,173,0,29,0,9,0,17,255,230,0,9,0,21,255,234,0,9,0,23,255,229,0,9,0,25,255,237,0,9,0,26,255,245,0,9,0,35,255,243,0,9,0,36,255,229,0,9,0,37,255,243,0,9,0,38,255,243,0,9,0,39,255,243,0,9,0,40,255,229,0,9,0,41,255,243,0,9,0,42,255,243,0,9,0,43,0,22,0,9,0,44,255,243,0,9,0,45,255,243,0,9,0,46,255,239,0,9,0,47,255,243,0,9,0,48,255,229,0,9,0,49,255,243,0,9,0,50,255,229,0,9,0,51,255,243,0,9,0,52,255,245,0,9,0,54,255,243,0,9,0,66,255,231,0,9,0,68,255,224,0,9,0,69,255,224,0,9,0,70,255,224,0,9,0,71,255,239,0,9,0,72,255,232,0,9,0,78,255,233,0,9,0,79,255,233,0,9,0,80,255,224,0,9,0,81,255,233,0,9,0,82,255,224,0,9,0,83,255,233,0,9,0,84,255,233,0,9,0,85,255,231,0,9,0,86,255,227,0,9,0,87,255,231,0,9,0,88,255,232,0,9,0,90,255,231,0,9,0,91,255,247,0,9,0,134,255,229,0,9,0,135,255,243,0,9,0,136,255,243,0,9,0,137,255,243,0,9,0,138,255,243,0,9,0,139,255,243,0,9,0,140,255,243,0,9,0,141,255,243,0,9,0,142,255,243,0,9,0,143,255,243,0,9,0,144,255,243,0,9,0,145,255,229,0,9,0,146,255,229,0,9,0,147,255,229,0,9,0,148,255,229,0,9,0,149,255,229,0,9,0,151,255,229,0,9,0,152,255,243,0,9,0,153,255,243,0,9,0,154,255,243,0,9,0,155,255,243,0,9,0,157,255,243,0,9,0,158,255,236,0,9,0,159,255,231,0,9,0,160,255,231,0,9,0,161,255,231,0,9,0,162,255,231,0,9,0,163,255,231,0,9,0,164,255,231,0,9,0,165,255,231,0,9,0,166,255,224,0,9,0,167,255,224,0,9,0,168,255,224,0,9,0,169,255,224,0,9,0,170,255,224,0,9,0,175,255,232,0,9,0,176,255,233,0,9,0,177,255,224,0,9,0,178,255,224,0,9,0,179,255,224,0,9,0,180,255,224,0,9,0,181,255,224,0,9,0,183,255,224,0,9,0,184,255,227,0,9,0,185,255,227,0,9,0,186,255,227,0,9,0,187,255,227,0,9,0,188,255,231,0,9,0,189,255,233,0,9,0,190,255,231,0,9,0,194,255,229,0,9,0,195,255,224,0,9,0,196,255,245,0,9,0,197,255,244,0,9,0,200,255,247,0,11,0,46,255,238,0,11,0,53,0,11,0,11,0,55,0,16,0,11,0,56,0,9,0,11,0,72,255,238,0,11,0,133,255,203,0,11,0,171,0,16,0,11,0,172,0,12,0,11,0,173,0,65,0,11,0,174,0,43,0,11,0,175,255,232,0,12,0,18,255,229,0,12,0,19,255,218,0,12,0,20,255,238,0,12,0,24,255,216,0,13,0,3,255,146,0,13,0,8,255,146,0,13,0,17,255,239,0,13,0,18,255,242,0,13,0,209,255,124,0,13,0,210,255,121,0,13,0,212,255,124,0,13,0,213,255,121,0,14,0,3,255,234,0,14,0,8,255,234,0,14,0,52,255,243,0,14,0,53,255,216,0,14,0,55,255,238,0,14,0,56,255,248,0,14,0,57,255,242,0,14,0,58,255,222,0,14,0,59,255,237,0,14,0,71,255,247,0,14,0,85,255,248,0,14,0,89,255,247,0,14,0,91,255,231,0,14,0,156,255,222,0,14,0,158,255,248,0,14,0,196,255,243,0,14,0,198,255,222,0,14,0,199,255,237,0,14,0,200,255,231,0,14,0,210,255,193,0,14,0,213,255,193,0,15,0,3,255,146,0,15,0,8,255,146,0,15,0,17,255,239,0,15,0,18,255,242,0,15,0,36,255,242,0,15,0,40,255,242,0,15,0,48,255,242,0,15,0,50,255,242,0,15,0,53,255,214,0,15,0,54,255,243,0,15,0,55,255,213,0,15,0,56,255,226,0,15,0,58,255,215,0,15,0,71,255,241,0,15,0,85,255,239,0,15,0,87,255,227,0,15,0,88,255,236,0,15,0,90,255,222,0,15,0,134,255,242,0,15,0,145,255,242,0,15,0,146,255,242,0,15,0,147,255,242,0,15,0,148,255,242,0,15,0,149,255,242,0,15,0,151,255,242,0,15,0,152,255,243,0,15,0,153,255,243,0,15,0,154,255,243,0,15,0,155,255,243,0,15,0,156,255,215,0,15,0,158,255,243,0,15,0,188,255,222,0,15,0,190,255,222,0,15,0,194,255,242,0,15,0,198,255,215,0,15,0,209,255,124,0,15,0,210,255,121,0,15,0,212,255,124,0,15,0,213,255,121,0,16,0,16,255,197,0,16,0,17,255,246,0,16,0,21,255,217,0,16,0,23,255,228,0,16,0,34,255,208,0,16,0,36,255,243,0,16,0,40,255,243,0,16,0,46,255,237,0,16,0,48,255,243,0,16,0,50,255,243,0,16,0,58,0,7,0,16,0,66,255,218,0,16,0,68,255,214,0,16,0,69,255,214,0,16,0,70,255,214,0,16,0,72,255,218,0,16,0,78,255,228,0,16,0,79,255,228,0,16,0,80,255,214,0,16,0,81,255,228,0,16,0,82,255,214,0,16,0,83,255,228,0,16,0,84,255,221,0,16,0,86,255,230,0,16,0,91,255,241,0,16,0,127,255,208,0,16,0,128,255,208,0,16,0,129,255,208,0,16,0,130,255,208,0,16,0,131,255,208,0,16,0,132,255,208,0,16,0,133,255,202,0,16,0,134,255,243,0,16,0,145,255,243,0,16,0,146,255,243,0,16,0,147,255,243,0,16,0,148,255,243,0,16,0,149,255,243,0,16,0,151,255,243,0,16,0,156,0,7,0,16,0,159,255,218,0,16,0,160,255,218,0,16,0,161,255,218,0,16,0,162,255,218,0,16,0,163,255,218,0,16,0,164,255,218,0,16,0,165,255,218,0,16,0,166,255,214,0,16,0,167,255,214,0,16,0,168,255,214,0,16,0,169,255,214,0,16,0,170,255,214,0,16,0,173,0,13,0,16,0,174,0,14,0,16,0,175,255,234,0,16,0,176,255,228,0,16,0,177,255,214,0,16,0,178,255,214,0,16,0,179,255,214,0,16,0,180,255,214,0,16,0,181,255,214,0,16,0,183,255,214,0,16,0,184,255,230,0,16,0,185,255,230,0,16,0,186,255,230,0,16,0,187,255,230,0,16,0,189,255,228,0,16,0,194,255,243,0,16,0,195,255,214,0,16,0,197,255,231,0,16,0,198,0,7,0,16,0,200,255,241,0,17,0,10,255,230,0,17,0,13,255,238,0,17,0,15,255,238,0,17,0,16,255,243,0,17,0,24,255,245,0,17,0,34,255,246,0,17,0,53,255,236,0,17,0,55,255,246,0,17,0,57,255,246,0,17,0,58,255,233,0,17,0,59,255,241,0,17,0,61,255,248,0,17,0,62,255,237,0,17,0,94,255,240,0,17,0,127,255,246,0,17,0,128,255,246,0,17,0,129,255,246,0,17,0,130,255,246,0,17,0,131,255,246,0,17,0,132,255,246,0,17,0,156,255,233,0,17,0,198,255,233,0,17,0,199,255,241,0,17,0,218,255,238,0,18,0,10,255,245,0,18,0,12,255,248,0,19,0,12,255,239,0,20,0,10,255,239,0,21,0,3,255,244,0,21,0,8,255,244,0,21,0,10,255,235,0,21,0,13,255,240,0,21,0,15,255,241,0,21,0,53,255,238,0,21,0,55,255,244,0,21,0,56,255,245,0,21,0,58,255,242,0,21,0,59,255,248,0,21,0,61,255,247,0,21,0,91,255,247,0,21,0,111,255,245,0,21,0,156,255,242,0,21,0,198,255,242,0,21,0,199,255,248,0,21,0,200,255,247,0,21,0,218,255,241,0,23,0,10,255,239,0,23,0,18,255,248,0,23,0,24,255,248,0,23,0,53,255,231,0,23,0,55,255,240,0,23,0,56,255,244,0,23,0,58,255,235,0,23,0,61,255,244,0,23,0,90,255,247,0,23,0,111,255,245,0,23,0,156,255,235,0,23,0,188,255,247,0,23,0,190,255,247,0,23,0,198,255,235,0,24,0,4,255,228,0,24,0,12,255,220,0,24,0,13,255,217,0,24,0,15,255,217,0,24,0,16,255,200,0,24,0,17,255,247,0,24,0,21,255,221,0,24,0,23,255,232,0,24,0,34,255,210,0,24,0,36,255,246,0,24,0,40,255,246,0,24,0,46,255,236,0,24,0,48,255,246,0,24,0,50,255,246,0,24,0,53,0,17,0,24,0,55,0,30,0,24,0,56,0,19,0,24,0,57,0,22,0,24,0,58,0,33,0,24,0,62,0,25,0,24,0,66,255,223,0,24,0,68,255,218,0,24,0,69,255,218,0,24,0,70,255,218,0,24,0,72,255,222,0,24,0,78,255,232,0,24,0,79,255,232,0,24,0,80,255,218,0,24,0,81,255,232,0,24,0,82,255,218,0,24,0,83,255,232,0,24,0,84,255,224,0,24,0,86,255,233,0,24,0,91,255,245,0,24,0,94,0,28,0,24,0,127,255,210,0,24,0,128,255,210,0,24,0,129,255,210,0,24,0,130,255,210,0,24,0,131,255,210,0,24,0,132,255,210,0,24,0,134,255,246,0,24,0,145,255,246,0,24,0,146,255,246,0,24,0,147,255,246,0,24,0,148,255,246,0,24,0,149,255,246,0,24,0,151,255,246,0,24,0,156,0,33,0,24,0,159,255,223,0,24,0,160,255,223,0,24,0,161,255,223,0,24,0,162,255,223,0,24,0,163,255,223,0,24,0,164,255,223,0,24,0,165,255,223,0,24,0,166,255,218,0,24,0,167,255,218,0,24,0,168,255,218,0,24,0,169,255,218,0,24,0,170,255,218,0,24,0,176,255,232,0,24,0,177,255,218,0,24,0,178,255,218,0,24,0,179,255,218,0,24,0,180,255,218,0,24,0,181,255,218,0,24,0,183,255,218,0,24,0,184,255,233,0,24,0,185,255,233,0,24,0,186,255,233,0,24,0,187,255,233,0,24,0,189,255,232,0,24,0,194,255,246,0,24,0,195,255,218,0,24,0,197,255,224,0,24,0,198,0,33,0,24,0,200,255,245,0,24,0,218,255,217,0,25,0,10,255,238,0,25,0,53,255,248,0,25,0,58,255,246,0,25,0,156,255,246,0,25,0,198,255,246,0,26,0,10,255,236,0,26,0,13,255,234,0,26,0,15,255,234,0,26,0,16,255,225,0,26,0,34,255,232,0,26,0,46,255,246,0,26,0,59,255,246,0,26,0,127,255,232,0,26,0,128,255,232,0,26,0,129,255,232,0,26,0,130,255,232,0,26,0,131,255,232,0,26,0,132,255,232,0,26,0,199,255,246,0,26,0,218,255,234,0,30,0,19,255,246,0,30,0,24,255,238,0,33,0,3,255,247,0,33,0,8,255,247,0,33,0,53,255,203,0,33,0,55,255,227,0,33,0,56,255,236,0,33,0,57,255,240,0,33,0,58,255,211,0,33,0,59,255,236,0,33,0,156,255,211,0,33,0,198,255,211,0,33,0,199,255,236,0,33,0,210,255,236,0,33,0,213,255,236,0,34,0,3,255,213,0,34,0,8,255,213,0,34,0,11,255,212,0,34,0,18,255,239,0,34,0,26,255,242,0,34,0,32,255,239,0,34,0,36,255,245,0,34,0,40,255,245,0,34,0,48,255,245,0,34,0,50,255,245,0,34,0,53,255,202,0,34,0,54,255,240,0,34,0,55,255,207,0,34,0,56,255,219,0,34,0,58,255,192,0,34,0,61,255,208,0,34,0,68,255,245,0,34,0,69,255,245,0,34,0,70,255,245,0,34,0,71,255,241,0,34,0,72,255,248,0,34,0,77,255,249,0,34,0,80,255,245,0,34,0,82,255,245,0,34,0,85,255,229,0,34,0,86,255,244,0,34,0,87,255,221,0,34,0,88,255,228,0,34,0,90,255,217,0,34,0,94,255,246,0,34,0,107,255,247,0,34,0,110,255,241,0,34,0,134,255,245,0,34,0,145,255,245,0,34,0,146,255,245,0,34,0,147,255,245,0,34,0,148,255,245,0,34,0,149,255,245,0,34,0,151,255,245,0,34,0,152,255,240,0,34,0,153,255,240,0,34,0,154,255,240,0,34,0,155,255,240,0,34,0,156,255,192,0,34,0,158,255,242,0,34,0,166,255,245,0,34,0,167,255,245,0,34,0,168,255,245,0,34,0,169,255,245,0,34,0,170,255,245,0,34,0,175,255,250,0,34,0,177,255,245,0,34,0,178,255,245,0,34,0,179,255,245,0,34,0,180,255,245,0,34,0,181,255,245,0,34,0,183,255,245,0,34,0,184,255,244,0,34,0,185,255,244,0,34,0,186,255,244,0,34,0,187,255,244,0,34,0,188,255,217,0,34,0,190,255,217,0,34,0,194,255,245,0,34,0,195,255,245,0,34,0,198,255,192,0,34,0,209,255,205,0,34,0,210,255,204,0,34,0,212,255,205,0,34,0,213,255,204,0,34,0,220,255,247,0,34,0,240,255,212,0,35,0,10,255,231,0,35,0,11,255,247,0,35,0,19,255,247,0,35,0,24,255,243,0,35,0,32,255,240,0,35,0,52,255,251,0,35,0,53,255,228,0,35,0,55,255,240,0,35,0,56,255,245,0,35,0,57,255,241,0,35,0,58,255,229,0,35,0,59,255,248,0,35,0,61,255,241,0,35,0,62,255,227,0,35,0,67,255,250,0,35,0,71,255,242,0,35,0,72,255,249,0,35,0,73,255,250,0,35,0,74,255,250,0,35,0,75,255,250,0,35,0,76,255,250,0,35,0,77,255,250,0,35,0,78,255,250,0,35,0,79,255,250,0,35,0,81,255,250,0,35,0,83,255,250,0,35,0,84,255,251,0,35,0,85,255,239,0,35,0,86,255,251,0,35,0,87,255,239,0,35,0,88,255,243,0,35,0,89,255,234,0,35,0,90,255,236,0,35,0,91,255,242,0,35,0,94,255,231,0,35,0,133,255,248,0,35,0,156,255,229,0,35,0,158,255,242,0,35,0,171,255,250,0,35,0,172,255,250,0,35,0,173,255,250,0,35,0,174,255,250,0,35,0,176,255,250,0,35,0,184,255,251,0,35,0,185,255,251,0,35,0,186,255,251,0,35,0,187,255,251,0,35,0,188,255,236,0,35,0,189,255,250,0,35,0,190,255,236,0,35,0,193,255,250,0,35,0,196,255,251,0,35,0,197,255,251,0,35,0,198,255,229,0,35,0,199,255,248,0,35,0,200,255,242,0,35,0,240,255,244,0,36,0,14,255,195,0,36,0,21,255,207,0,36,0,36,255,242,0,36,0,40,255,242,0,36,0,48,255,242,0,36,0,50,255,242,0,36,0,68,255,242,0,36,0,69,255,242,0,36,0,70,255,242,0,36,0,71,255,249,0,36,0,72,255,241,0,36,0,78,255,249,0,36,0,79,255,249,0,36,0,80,255,242,0,36,0,81,255,249,0,36,0,82,255,242,0,36,0,83,255,249,0,36,0,85,255,249,0,36,0,86,255,241,0,36,0,87,255,249,0,36,0,88,255,250,0,36,0,90,255,249,0,36,0,107,255,226,0,36,0,134,255,242,0,36,0,145,255,242,0,36,0,146,255,242,0,36,0,147,255,242,0,36,0,148,255,242,0,36,0,149,255,242,0,36,0,151,255,242,0,36,0,158,255,250,0,36,0,166,255,242,0,36,0,167,255,242,0,36,0,168,255,242,0,36,0,169,255,242,0,36,0,170,255,242,0,36,0,173,0,31,0,36,0,174,0,12,0,36,0,175,255,249,0,36,0,176,255,249,0,36,0,177,255,242,0,36,0,178,255,242,0,36,0,179,255,242,0,36,0,180,255,242,0,36,0,181,255,242,0,36,0,183,255,242,0,36,0,184,255,241,0,36,0,185,255,241,0,36,0,186,255,241,0,36,0,187,255,241,0,36,0,188,255,249,0,36,0,189,255,249,0,36,0,190,255,249,0,36,0,194,255,242,0,36,0,195,255,242,0,36,0,207,255,195,0,36,0,208,255,195,0,36,0,220,255,226,0,37,0,10,255,228,0,37,0,13,255,241,0,37,0,15,255,242,0,37,0,16,255,237,0,37,0,20,255,248,0,37,0,24,255,240,0,37,0,32,255,237,0,37,0,34,255,244,0,37,0,46,255,250,0,37,0,53,255,228,0,37,0,55,255,243,0,37,0,56,255,248,0,37,0,57,255,225,0,37,0,58,255,227,0,37,0,59,255,235,0,37,0,61,255,244,0,37,0,62,255,224,0,37,0,66,255,248,0,37,0,67,255,249,0,37,0,68,255,250,0,37,0,69,255,250,0,37,0,70,255,250,0,37,0,72,255,250,0,37,0,73,255,249,0,37,0,74,255,249,0,37,0,75,255,249,0,37,0,76,255,249,0,37,0,77,255,249,0,37,0,78,255,249,0,37,0,79,255,249,0,37,0,80,255,250,0,37,0,81,255,249,0,37,0,82,255,250,0,37,0,83,255,249,0,37,0,84,255,250,0,37,0,86,255,250,0,37,0,89,255,244,0,37,0,91,255,250,0,37,0,94,255,229,0,37,0,127,255,244,0,37,0,128,255,244,0,37,0,129,255,244,0,37,0,130,255,244,0,37,0,131,255,244,0,37,0,132,255,244,0,37,0,133,255,226,0,37,0,156,255,227,0,37,0,158,255,250,0,37,0,159,255,248,0,37,0,160,255,248,0,37,0,161,255,248,0,37,0,162,255,248,0,37,0,163,255,248,0,37,0,164,255,248,0,37,0,165,255,248,0,37,0,166,255,250,0,37,0,167,255,250,0,37,0,168,255,250,0,37,0,169,255,250,0,37,0,170,255,250,0,37,0,171,255,249,0,37,0,172,255,249,0,37,0,173,255,249,0,37,0,174,255,249,0,37,0,175,255,249,0,37,0,176,255,249,0,37,0,177,255,250,0,37,0,178,255,250,0,37,0,179,255,250,0,37,0,180,255,250,0,37,0,181,255,250,0,37,0,183,255,250,0,37,0,184,255,250,0,37,0,185,255,250,0,37,0,186,255,250,0,37,0,187,255,250,0,37,0,189,255,249,0,37,0,193,255,249,0,37,0,195,255,250,0,37,0,197,255,250,0,37,0,198,255,227,0,37,0,199,255,235,0,37,0,200,255,250,0,37,0,210,255,247,0,37,0,211,255,241,0,37,0,213,255,247,0,37,0,214,255,241,0,37,0,218,255,242,0,37,0,240,255,246,0,38,0,14,255,244,0,38,0,21,255,220,0,38,0,36,255,245,0,38,0,40,255,245,0,38,0,48,255,245,0,38,0,50,255,245,0,38,0,68,255,240,0,38,0,69,255,240,0,38,0,70,255,240,0,38,0,71,255,243,0,38,0,72,255,241,0,38,0,78,255,247,0,38,0,79,255,247,0,38,0,80,255,240,0,38,0,81,255,247,0,38,0,82,255,240,0,38,0,83,255,247,0,38,0,84,255,251,0,38,0,85,255,242,0,38,0,86,255,238,0,38,0,87,255,241,0,38,0,88,255,243,0,38,0,90,255,240,0,38,0,107,255,235,0,38,0,110,255,248,0,38,0,134,255,245,0,38,0,145,255,245,0,38,0,146,255,245,0,38,0,147,255,245,0,38,0,148,255,245,0,38,0,149,255,245,0,38,0,151,255,245,0,38,0,158,255,243,0,38,0,166,255,240,0,38,0,167,255,240,0,38,0,168,255,240,0,38,0,169,255,240,0,38,0,170,255,240,0,38,0,173,0,21,0,38,0,175,255,246,0,38,0,176,255,247,0,38,0,177,255,240,0,38,0,178,255,240,0,38,0,179,255,240,0,38,0,180,255,240,0,38,0,181,255,240,0,38,0,183,255,240,0,38,0,184,255,238,0,38,0,185,255,238,0,38,0,186,255,238,0,38,0,187,255,238,0,38,0,188,255,240,0,38,0,189,255,247,0,38,0,190,255,240,0,38,0,194,255,245,0,38,0,195,255,240,0,38,0,197,255,251,0,38,0,207,255,244,0,38,0,208,255,244,0,38,0,220,255,235,0,39,0,7,255,245,0,39,0,11,0,11,0,39,0,13,255,186,0,39,0,15,255,186,0,39,0,16,255,199,0,39,0,21,255,223,0,39,0,23,255,243,0,39,0,27,255,243,0,39,0,28,255,243,0,39,0,33,255,222,0,39,0,34,255,203,0,39,0,36,255,248,0,39,0,40,255,248,0,39,0,46,255,239,0,39,0,48,255,248,0,39,0,50,255,248,0,39,0,53,0,5,0,39,0,62,0,16,0,39,0,66,255,199,0,39,0,67,255,251,0,39,0,68,255,212,0,39,0,69,255,212,0,39,0,70,255,212,0,39,0,71,255,244,0,39,0,72,255,216,0,39,0,73,255,251,0,39,0,74,255,249,0,39,0,75,255,249,0,39,0,76,255,251,0,39,0,78,255,211,0,39,0,79,255,211,0,39,0,80,255,212,0,39,0,81,255,211,0,39,0,82,255,212,0,39,0,83,255,211,0,39,0,84,255,217,0,39,0,85,255,247,0,39,0,86,255,217,0,39,0,87,255,247,0,39,0,88,255,248,0,39,0,89,255,239,0,39,0,90,255,248,0,39,0,91,255,236,0,39,0,94,0,19,0,39,0,107,255,236,0,39,0,122,255,217,0,39,0,127,255,203,0,39,0,128,255,203,0,39,0,129,255,203,0,39,0,130,255,203,0,39,0,131,255,203,0,39,0,132,255,203,0,39,0,133,255,155,0,39,0,134,255,248,0,39,0,145,255,248,0,39,0,146,255,248,0,39,0,147,255,248,0,39,0,148,255,248,0,39,0,149,255,248,0,39,0,151,255,248,0,39,0,158,255,241,0,39,0,159,255,199,0,39,0,160,255,199,0,39,0,161,255,199,0,39,0,162,255,206,0,39,0,163,255,199,0,39,0,164,255,199,0,39,0,165,255,199,0,39,0,166,255,212,0,39,0,167,255,212,0,39,0,168,255,212,0,39,0,169,255,212,0,39,0,170,255,212,0,39,0,171,255,249,0,39,0,172,255,249,0,39,0,173,0,52,0,39,0,174,0,28,0,39,0,175,255,222,0,39,0,176,255,211,0,39,0,177,255,212,0,39,0,178,255,212,0,39,0,179,255,212,0,39,0,180,255,212,0,39,0,181,255,212,0,39,0,183,255,212,0,39,0,184,255,217,0,39,0,185,255,217,0,39,0,186,255,217,0,39,0,187,255,217,0,39,0,188,255,248,0,39,0,189,255,211,0,39,0,190,255,248,0,39,0,193,255,249,0,39,0,194,255,248,0,39,0,195,255,212,0,39,0,197,255,217,0,39,0,200,255,236,0,39,0,211,255,186,0,39,0,214,255,186,0,39,0,218,255,186,0,39,0,220,255,236,0,39,0,221,255,217,0,39,0,240,0,16,0,40,0,10,255,248,0,40,0,53,255,251,0,40,0,67,255,250,0,40,0,68,255,251,0,40,0,69,255,251,0,40,0,70,255,251,0,40,0,71,255,246,0,40,0,72,255,250,0,40,0,73,255,250,0,40,0,74,255,250,0,40,0,75,255,250,0,40,0,76,255,250,0,40,0,77,255,250,0,40,0,78,255,250,0,40,0,79,255,250,0,40,0,80,255,251,0,40,0,81,255,250,0,40,0,82,255,251,0,40,0,83,255,250,0,40,0,85,255,244,0,40,0,86,255,249,0,40,0,87,255,244,0,40,0,88,255,247,0,40,0,90,255,242,0,40,0,91,255,249,0,40,0,158,255,244,0,40,0,166,255,251,0,40,0,167,255,251,0,40,0,168,255,251,0,40,0,169,255,251,0,40,0,170,255,251,0,40,0,171,255,250,0,40,0,172,255,250,0,40,0,173,255,250,0,40,0,174,255,250,0,40,0,176,255,250,0,40,0,177,255,251,0,40,0,178,255,251,0,40,0,179,255,251,0,40,0,180,255,251,0,40,0,181,255,251,0,40,0,183,255,251,0,40,0,184,255,249,0,40,0,185,255,249,0,40,0,186,255,249,0,40,0,187,255,249,0,40,0,188,255,242,0,40,0,189,255,250,0,40,0,190,255,242,0,40,0,193,255,250,0,40,0,195,255,251,0,40,0,200,255,249,0,41,0,10,255,246,0,41,0,46,255,251,0,41,0,66,255,246,0,41,0,67,255,247,0,41,0,68,255,242,0,41,0,69,255,242,0,41,0,70,255,242,0,41,0,71,255,247,0,41,0,72,255,241,0,41,0,73,255,247,0,41,0,74,255,247,0,41,0,75,255,247,0,41,0,76,255,247,0,41,0,77,255,246,0,41,0,78,255,247,0,41,0,79,255,247,0,41,0,80,255,242,0,41,0,81,255,247,0,41,0,82,255,242,0,41,0,83,255,247,0,41,0,84,255,246,0,41,0,85,255,247,0,41,0,86,255,245,0,41,0,87,255,247,0,41,0,88,255,248,0,41,0,90,255,247,0,41,0,91,255,246,0,41,0,158,255,244,0,41,0,159,255,246,0,41,0,160,255,246,0,41,0,161,255,246,0,41,0,162,255,246,0,41,0,163,255,246,0,41,0,164,255,246,0,41,0,165,255,246,0,41,0,166,255,242,0,41,0,167,255,242,0,41,0,168,255,242,0,41,0,169,255,242,0,41,0,170,255,242,0,41,0,171,255,247,0,41,0,172,255,247,0,41,0,173,255,247,0,41,0,174,255,247,0,41,0,175,255,243,0,41,0,176,255,247,0,41,0,177,255,242,0,41,0,178,255,242,0,41,0,179,255,242,0,41,0,180,255,242,0,41,0,181,255,242,0,41,0,183,255,242,0,41,0,184,255,245,0,41,0,185,255,245,0,41,0,186,255,245,0,41,0,187,255,245,0,41,0,188,255,247,0,41,0,189,255,247,0,41,0,190,255,247,0,41,0,193,255,247,0,41,0,195,255,242,0,41,0,197,255,246,0,41,0,200,255,246,0,42,0,10,255,246,0,42,0,46,255,251,0,42,0,66,255,246,0,42,0,67,255,247,0,42,0,68,255,242,0,42,0,69,255,242,0,42,0,70,255,242,0,42,0,71,255,247,0,42,0,72,255,241,0,42,0,73,255,247,0,42,0,74,255,247,0,42,0,75,255,247,0,42,0,76,255,247,0,42,0,77,255,246,0,42,0,78,255,247,0,42,0,79,255,247,0,42,0,80,255,242,0,42,0,81,255,247,0,42,0,82,255,242,0,42,0,83,255,247,0,42,0,84,255,246,0,42,0,85,255,247,0,42,0,86,255,245,0,42,0,87,255,247,0,42,0,88,255,248,0,42,0,90,255,247,0,42,0,91,255,246,0,42,0,158,255,244,0,42,0,159,255,246,0,42,0,160,255,246,0,42,0,161,255,246,0,42,0,162,255,246,0,42,0,163,255,246,0,42,0,164,255,246,0,42,0,165,255,246,0,42,0,166,255,242,0,42,0,167,255,242,0,42,0,168,255,242,0,42,0,169,255,242,0,42,0,170,255,242,0,42,0,171,255,247,0,42,0,172,255,247,0,42,0,173,255,247,0,42,0,174,255,247,0,42,0,175,255,243,0,42,0,176,255,247,0,42,0,177,255,242,0,42,0,178,255,242,0,42,0,179,255,242,0,42,0,180,255,242,0,42,0,181,255,242,0,42,0,183,255,242,0,42,0,184,255,245,0,42,0,185,255,245,0,42,0,186,255,245,0,42,0,187,255,245,0,42,0,188,255,247,0,42,0,189,255,247,0,42,0,190,255,247,0,42,0,193,255,247,0,42,0,195,255,242,0,42,0,197,255,246,0,42,0,200,255,246,0,43,0,10,255,246,0,43,0,46,255,251,0,43,0,66,255,246,0,43,0,67,255,247,0,43,0,68,255,242,0,43,0,69,255,242,0,43,0,70,255,242,0,43,0,71,255,247,0,43,0,72,255,241,0,43,0,73,255,247,0,43,0,74,255,247,0,43,0,75,255,247,0,43,0,76,255,247,0,43,0,77,255,246,0,43,0,78,255,247,0,43,0,79,255,247,0,43,0,80,255,242,0,43,0,81,255,247,0,43,0,82,255,242,0,43,0,83,255,247,0,43,0,84,255,246,0,43,0,85,255,247,0,43,0,86,255,245,0,43,0,87,255,247,0,43,0,88,255,248,0,43,0,90,255,247,0,43,0,91,255,246,0,43,0,158,255,244,0,43,0,159,255,246,0,43,0,160,255,246,0,43,0,161,255,246,0,43,0,162,255,246,0,43,0,163,255,246,0,43,0,164,255,246,0,43,0,165,255,246,0,43,0,166,255,242,0,43,0,167,255,242,0,43,0,168,255,242,0,43,0,169,255,242,0,43,0,170,255,242,0,43,0,171,255,247,0,43,0,172,255,247,0,43,0,173,255,247,0,43,0,174,255,247,0,43,0,175,255,243,0,43,0,176,255,247,0,43,0,177,255,242,0,43,0,178,255,242,0,43,0,179,255,242,0,43,0,180,255,242,0,43,0,181,255,242,0,43,0,183,255,242,0,43,0,184,255,245,0,43,0,185,255,245,0,43,0,186,255,245,0,43,0,187,255,245,0,43,0,188,255,247,0,43,0,189,255,247,0,43,0,190,255,247,0,43,0,193,255,247,0,43,0,195,255,242,0,43,0,197,255,246,0,43,0,200,255,246,0,44,0,7,255,247,0,44,0,11,0,9,0,44,0,14,255,244,0,44,0,36,255,228,0,44,0,40,255,228,0,44,0,48,255,228,0,44,0,50,255,228,0,44,0,52,255,250,0,44,0,62,0,33,0,44,0,68,255,222,0,44,0,69,255,222,0,44,0,70,255,222,0,44,0,71,255,246,0,44,0,72,255,238,0,44,0,80,255,222,0,44,0,82,255,222,0,44,0,85,255,229,0,44,0,86,255,232,0,44,0,87,255,201,0,44,0,88,255,211,0,44,0,90,255,199,0,44,0,94,0,33,0,44,0,107,255,227,0,44,0,110,255,238,0,44,0,134,255,228,0,44,0,145,255,228,0,44,0,146,255,228,0,44,0,147,255,228,0,44,0,148,255,228,0,44,0,149,255,228,0,44,0,151,255,228,0,44,0,158,255,245,0,44,0,166,255,222,0,44,0,167,255,222,0,44,0,168,255,222,0,44,0,169,255,222,0,44,0,170,255,222,0,44,0,171,0,10,0,44,0,173,0,24,0,44,0,174,0,41,0,44,0,175,255,239,0,44,0,177,255,222,0,44,0,178,255,222,0,44,0,179,255,222,0,44,0,180,255,222,0,44,0,181,255,222,0,44,0,183,255,222,0,44,0,184,255,232,0,44,0,185,255,232,0,44,0,186,255,232,0,44,0,187,255,232,0,44,0,188,255,199,0,44,0,190,255,199,0,44,0,194,255,228,0,44,0,195,255,222,0,44,0,196,255,250,0,44,0,207,255,244,0,44,0,208,255,244,0,44,0,220,255,227,0,44,0,240,0,27,0,45,0,3,255,166,0,45,0,8,255,166,0,45,0,11,255,166,0,45,0,14,255,196,0,45,0,17,255,243,0,45,0,18,255,236,0,45,0,21,255,194,0,45,0,26,255,227,0,45,0,32,255,231,0,45,0,36,255,232,0,45,0,40,255,232,0,45,0,48,255,232,0,45,0,50,255,232,0,45,0,53,255,189,0,45,0,54,255,238,0,45,0,55,255,154,0,45,0,56,255,203,0,45,0,58,255,158,0,45,0,61,255,187,0,45,0,62,255,240,0,45,0,68,255,246,0,45,0,69,255,246,0,45,0,70,255,246,0,45,0,71,255,241,0,45,0,72,255,249,0,45,0,80,255,246,0,45,0,82,255,246,0,45,0,85,255,232,0,45,0,86,255,249,0,45,0,87,255,199,0,45,0,88,255,212,0,45,0,90,255,181,0,45,0,94,255,241,0,45,0,107,255,222,0,45,0,110,255,220,0,45,0,134,255,232,0,45,0,145,255,232,0,45,0,146,255,232,0,45,0,147,255,232,0,45,0,148,255,232,0,45,0,149,255,232,0,45,0,151,255,232,0,45,0,152,255,238,0,45,0,153,255,238,0,45,0,154,255,238,0,45,0,155,255,238,0,45,0,156,255,158,0,45,0,158,255,243,0,45,0,166,255,246,0,45,0,167,255,246,0,45,0,168,255,246,0,45,0,169,255,246,0,45,0,170,255,246,0,45,0,177,255,246,0,45,0,178,255,246,0,45,0,179,255,246,0,45,0,180,255,246,0,45,0,181,255,246,0,45,0,183,255,246,0,45,0,184,255,249,0,45,0,185,255,249,0,45,0,186,255,249,0,45,0,187,255,249,0,45,0,188,255,181,0,45,0,190,255,181,0,45,0,194,255,232,0,45,0,195,255,246,0,45,0,198,255,158,0,45,0,207,255,196,0,45,0,208,255,196,0,45,0,209,255,167,0,45,0,210,255,167,0,45,0,212,255,167,0,45,0,213,255,167,0,45,0,220,255,222,0,45,0,240,255,166,0,46,0,3,255,238,0,46,0,8,255,238,0,46,0,10,255,242,0,46,0,11,255,238,0,46,0,18,255,247,0,46,0,32,255,242,0,46,0,35,255,251,0,46,0,36,255,251,0,46,0,37,255,251,0,46,0,38,255,251,0,46,0,39,255,251,0,46,0,40,255,251,0,46,0,41,255,251,0,46,0,42,255,251,0,46,0,43,255,251,0,46,0,44,255,251,0,46,0,45,255,251,0,46,0,47,255,251,0,46,0,48,255,251,0,46,0,49,255,251,0,46,0,50,255,251,0,46,0,51,255,251,0,46,0,53,255,231,0,46,0,54,255,248,0,46,0,55,255,236,0,46,0,56,255,238,0,46,0,58,255,233,0,46,0,61,255,239,0,46,0,66,255,250,0,46,0,67,255,245,0,46,0,68,255,244,0,46,0,69,255,244,0,46,0,70,255,244,0,46,0,71,255,240,0,46,0,72,255,243,0,46,0,73,255,245,0,46,0,74,255,246,0,46,0,75,255,246,0,46,0,76,255,245,0,46,0,77,255,245,0,46,0,78,255,246,0,46,0,79,255,246,0,46,0,80,255,244,0,46,0,81,255,246,0,46,0,82,255,244,0,46,0,83,255,246,0,46,0,84,255,250,0,46,0,85,255,236,0,46,0,86,255,244,0,46,0,87,255,234,0,46,0,88,255,236,0,46,0,90,255,233,0,46,0,91,255,249,0,46,0,134,255,251,0,46,0,135,255,251,0,46,0,136,255,251,0,46,0,137,255,251,0,46,0,138,255,251,0,46,0,139,255,251,0,46,0,140,255,251,0,46,0,141,255,251,0,46,0,142,255,251,0,46,0,143,255,251,0,46,0,144,255,251,0,46,0,145,255,251,0,46,0,146,255,251,0,46,0,147,255,251,0,46,0,148,255,251,0,46,0,149,255,251,0,46,0,151,255,251,0,46,0,152,255,248,0,46,0,153,255,248,0,46,0,154,255,248,0,46,0,155,255,248,0,46,0,156,255,233,0,46,0,157,255,251,0,46,0,158,255,238,0,46,0,159,255,250,0,46,0,160,255,250,0,46,0,161,255,250,0,46,0,162,255,250,0,46,0,163,255,250,0,46,0,164,255,250,0,46,0,165,255,250,0,46,0,166,255,244,0,46,0,167,255,244,0,46,0,168,255,244,0,46,0,169,255,244,0,46,0,170,255,244,0,46,0,171,255,246,0,46,0,172,255,246,0,46,0,173,255,246,0,46,0,174,255,246,0,46,0,175,255,247,0,46,0,176,255,246,0,46,0,177,255,244,0,46,0,178,255,244,0,46,0,179,255,244,0,46,0,180,255,244,0,46,0,181,255,244,0,46,0,183,255,244,0,46,0,184,255,244,0,46,0,185,255,244,0,46,0,186,255,244,0,46,0,187,255,244,0,46,0,188,255,233,0,46,0,189,255,246,0,46,0,190,255,233,0,46,0,193,255,246,0,46,0,194,255,251,0,46,0,195,255,244,0,46,0,197,255,250,0,46,0,198,255,233,0,46,0,200,255,249,0,46,0,209,255,236,0,46,0,210,255,236,0,46,0,212,255,236,0,46,0,213,255,236,0,46,0,240,255,237,0,47,0,10,255,246,0,47,0,46,255,251,0,47,0,66,255,246,0,47,0,67,255,247,0,47,0,68,255,242,0,47,0,69,255,242,0,47,0,70,255,242,0,47,0,71,255,247,0,47,0,72,255,241,0,47,0,73,255,247,0,47,0,74,255,247,0,47,0,75,255,247,0,47,0,76,255,247,0,47,0,77,255,246,0,47,0,78,255,247,0,47,0,79,255,247,0,47,0,80,255,242,0,47,0,81,255,247,0,47,0,82,255,242,0,47,0,83,255,247,0,47,0,84,255,246,0,47,0,85,255,247,0,47,0,86,255,245,0,47,0,87,255,247,0,47,0,88,255,248,0,47,0,90,255,247,0,47,0,91,255,246,0,47,0,158,255,244,0,47,0,159,255,246,0,47,0,160,255,246,0,47,0,161,255,246,0,47,0,162,255,246,0,47,0,163,255,246,0,47,0,164,255,246,0,47,0,165,255,246,0,47,0,166,255,242,0,47,0,167,255,242,0,47,0,168,255,242,0,47,0,169,255,242,0,47,0,170,255,242,0,47,0,171,255,247,0,47,0,172,255,247,0,47,0,173,255,247,0,47,0,174,255,247,0,47,0,175,255,243,0,47,0,176,255,247,0,47,0,177,255,242,0,47,0,178,255,242,0,47,0,179,255,242,0,47,0,180,255,242,0,47,0,181,255,242,0,47,0,183,255,242,0,47,0,184,255,245,0,47,0,185,255,245,0,47,0,186,255,245,0,47,0,187,255,245,0,47,0,188,255,247,0,47,0,189,255,247,0,47,0,190,255,247,0,47,0,193,255,247,0,47,0,195,255,242,0,47,0,197,255,246,0,47,0,200,255,246,0,48,0,10,255,229,0,48,0,13,255,242,0,48,0,15,255,242,0,48,0,16,255,239,0,48,0,24,255,243,0,48,0,32,255,240,0,48,0,34,255,245,0,48,0,46,255,251,0,48,0,53,255,232,0,48,0,55,255,244,0,48,0,56,255,248,0,48,0,57,255,229,0,48,0,58,255,230,0,48,0,59,255,238,0,48,0,61,255,245,0,48,0,62,255,227,0,48,0,66,255,247,0,48,0,67,255,250,0,48,0,68,255,250,0,48,0,69,255,250,0,48,0,70,255,250,0,48,0,72,255,250,0,48,0,73,255,250,0,48,0,74,255,249,0,48,0,75,255,249,0,48,0,76,255,250,0,48,0,77,255,250,0,48,0,78,255,249,0,48,0,79,255,249,0,48,0,80,255,250,0,48,0,81,255,249,0,48,0,82,255,250,0,48,0,83,255,249,0,48,0,84,255,250,0,48,0,86,255,251,0,48,0,89,255,245,0,48,0,91,255,250,0,48,0,94,255,231,0,48,0,127,255,245,0,48,0,128,255,245,0,48,0,129,255,245,0,48,0,130,255,245,0,48,0,131,255,245,0,48,0,132,255,245,0,48,0,133,255,229,0,48,0,156,255,230,0,48,0,158,255,251,0,48,0,159,255,247,0,48,0,160,255,247,0,48,0,161,255,247,0,48,0,162,255,247,0,48,0,163,255,247,0,48,0,164,255,247,0,48,0,165,255,247,0,48,0,166,255,250,0,48,0,167,255,250,0,48,0,168,255,250,0,48,0,169,255,250,0,48,0,170,255,250,0,48,0,171,255,249,0,48,0,172,255,249,0,48,0,173,255,249,0,48,0,174,255,249,0,48,0,175,255,250,0,48,0,176,255,249,0,48,0,177,255,250,0,48,0,178,255,250,0,48,0,179,255,250,0,48,0,180,255,250,0,48,0,181,255,250,0,48,0,183,255,250,0,48,0,184,255,251,0,48,0,185,255,251,0,48,0,186,255,251,0,48,0,187,255,251,0,48,0,189,255,249,0,48,0,193,255,249,0,48,0,195,255,250,0,48,0,197,255,250,0,48,0,198,255,230,0,48,0,199,255,238,0,48,0,200,255,250,0,48,0,210,255,247,0,48,0,211,255,242,0,48,0,213,255,247,0,48,0,214,255,242,0,48,0,218,255,242,0,48,0,240,255,246,0,49,0,7,255,250,0,49,0,10,255,241,0,49,0,13,255,175,0,49,0,15,255,175,0,49,0,16,255,210,0,49,0,20,255,248,0,49,0,21,255,242,0,49,0,33,255,241,0,49,0,34,255,216,0,49,0,46,255,246,0,49,0,57,255,242,0,49,0,59,255,248,0,49,0,66,255,242,0,49,0,67,255,251,0,49,0,68,255,243,0,49,0,69,255,243,0,49,0,70,255,243,0,49,0,72,255,246,0,49,0,73,255,251,0,49,0,74,255,250,0,49,0,75,255,250,0,49,0,76,255,251,0,49,0,77,255,251,0,49,0,78,255,248,0,49,0,79,255,248,0,49,0,80,255,243,0,49,0,81,255,248,0,49,0,82,255,243,0,49,0,83,255,248,0,49,0,84,255,248,0,49,0,86,255,250,0,49,0,127,255,216,0,49,0,128,255,216,0,49,0,129,255,216,0,49,0,130,255,216,0,49,0,131,255,216,0,49,0,132,255,216,0,49,0,133,255,187,0,49,0,159,255,242,0,49,0,160,255,242,0,49,0,161,255,242,0,49,0,162,255,242,0,49,0,163,255,242,0,49,0,164,255,242,0,49,0,165,255,242,0,49,0,166,255,243,0,49,0,167,255,243,0,49,0,168,255,243,0,49,0,169,255,243,0,49,0,170,255,243,0,49,0,171,255,250,0,49,0,172,255,250,0,49,0,173,0,25,0,49,0,174,0,4,0,49,0,175,255,234,0,49,0,176,255,248,0,49,0,177,255,243,0,49,0,178,255,243,0,49,0,179,255,243,0,49,0,180,255,243,0,49,0,181,255,243,0,49,0,183,255,243,0,49,0,184,255,250,0,49,0,185,255,250,0,49,0,186,255,250,0,49,0,187,255,250,0,49,0,189,255,248,0,49,0,193,255,250,0,49,0,195,255,243,0,49,0,197,255,248,0,49,0,199,255,248,0,49,0,211,255,175,0,49,0,214,255,175,0,49,0,218,255,175,0,50,0,10,255,229,0,50,0,13,255,242,0,50,0,15,255,242,0,50,0,16,255,239,0,50,0,24,255,243,0,50,0,32,255,240,0,50,0,34,255,245,0,50,0,46,255,251,0,50,0,53,255,232,0,50,0,55,255,244,0,50,0,56,255,248,0,50,0,57,255,229,0,50,0,58,255,230,0,50,0,59,255,238,0,50,0,61,255,245,0,50,0,62,255,227,0,50,0,66,255,247,0,50,0,67,255,250,0,50,0,68,255,250,0,50,0,69,255,250,0,50,0,70,255,250,0,50,0,72,255,250,0,50,0,73,255,250,0,50,0,74,255,249,0,50,0,75,255,249,0,50,0,76,255,250,0,50,0,77,255,250,0,50,0,78,255,249,0,50,0,79,255,249,0,50,0,80,255,250,0,50,0,81,255,249,0,50,0,82,255,250,0,50,0,83,255,249,0,50,0,84,255,250,0,50,0,86,255,251,0,50,0,89,255,245,0,50,0,91,255,250,0,50,0,94,255,231,0,50,0,127,255,245,0,50,0,128,255,245,0,50,0,129,255,245,0,50,0,130,255,245,0,50,0,131,255,245,0,50,0,132,255,245,0,50,0,133,255,229,0,50,0,156,255,230,0,50,0,158,255,251,0,50,0,159,255,247,0,50,0,160,255,247,0,50,0,161,255,247,0,50,0,162,255,247,0,50,0,163,255,247,0,50,0,164,255,247,0,50,0,165,255,247,0,50,0,166,255,250,0,50,0,167,255,250,0,50,0,168,255,250,0,50,0,169,255,250,0,50,0,170,255,250,0,50,0,171,255,249,0,50,0,172,255,249,0,50,0,173,255,249,0,50,0,174,255,249,0,50,0,175,255,250,0,50,0,176,255,249,0,50,0,177,255,250,0,50,0,178,255,250,0,50,0,179,255,250,0,50,0,180,255,250,0,50,0,181,255,250,0,50,0,183,255,250,0,50,0,184,255,251,0,50,0,185,255,251,0,50,0,186,255,251,0,50,0,187,255,251,0,50,0,189,255,249,0,50,0,193,255,249,0,50,0,195,255,250,0,50,0,197,255,250,0,50,0,198,255,230,0,50,0,199,255,238,0,50,0,200,255,250,0,50,0,210,255,247,0,50,0,211,255,242,0,50,0,213,255,247,0,50,0,214,255,242,0,50,0,218,255,242,0,50,0,240,255,246,0,51,0,21,255,234,0,51,0,53,255,243,0,51,0,55,255,251,0,51,0,58,255,245,0,51,0,62,255,240,0,51,0,66,255,251,0,51,0,67,255,250,0,51,0,68,255,237,0,51,0,69,255,237,0,51,0,70,255,237,0,51,0,71,255,249,0,51,0,72,255,243,0,51,0,73,255,250,0,51,0,74,255,249,0,51,0,75,255,249,0,51,0,76,255,250,0,51,0,77,255,248,0,51,0,78,255,248,0,51,0,79,255,248,0,51,0,80,255,237,0,51,0,81,255,248,0,51,0,82,255,237,0,51,0,83,255,248,0,51,0,85,255,248,0,51,0,86,255,244,0,51,0,87,255,248,0,51,0,88,255,250,0,51,0,90,255,248,0,51,0,94,255,247,0,51,0,107,255,242,0,51,0,156,255,245,0,51,0,158,255,247,0,51,0,159,255,251,0,51,0,160,255,251,0,51,0,161,255,251,0,51,0,162,255,251,0,51,0,163,255,251,0,51,0,164,255,251,0,51,0,165,255,251,0,51,0,166,255,237,0,51,0,167,255,237,0,51,0,168,255,237,0,51,0,169,255,237,0,51,0,170,255,237,0,51,0,171,255,249,0,51,0,172,255,249,0,51,0,173,255,249,0,51,0,174,255,249,0,51,0,175,255,242,0,51,0,176,255,248,0,51,0,177,255,237,0,51,0,178,255,237,0,51,0,179,255,237,0,51,0,180,255,237,0,51,0,181,255,237,0,51,0,183,255,237,0,51,0,184,255,244,0,51,0,185,255,244,0,51,0,186,255,244,0,51,0,187,255,244,0,51,0,188,255,248,0,51,0,189,255,248,0,51,0,190,255,248,0,51,0,193,255,249,0,51,0,195,255,237,0,51,0,198,255,245,0,51,0,220,255,242,0,52,0,10,255,246,0,52,0,57,255,251,0,52,0,67,255,250,0,52,0,71,255,243,0,52,0,72,255,250,0,52,0,73,255,250,0,52,0,74,255,250,0,52,0,75,255,250,0,52,0,76,255,250,0,52,0,77,255,250,0,52,0,78,255,250,0,52,0,79,255,250,0,52,0,81,255,250,0,52,0,83,255,250,0,52,0,84,255,251,0,52,0,85,255,241,0,52,0,86,255,250,0,52,0,87,255,241,0,52,0,88,255,244,0,52,0,89,255,242,0,52,0,90,255,240,0,52,0,91,255,244,0,52,0,158,255,244,0,52,0,171,255,250,0,52,0,172,255,250,0,52,0,173,255,250,0,52,0,174,255,250,0,52,0,176,255,250,0,52,0,184,255,250,0,52,0,185,255,250,0,52,0,186,255,250,0,52,0,187,255,250,0,52,0,188,255,240,0,52,0,189,255,250,0,52,0,190,255,240,0,52,0,193,255,250,0,52,0,197,255,251,0,52,0,200,255,244,0,53,0,7,255,241,0,53,0,11,0,12,0,53,0,13,255,213,0,53,0,14,255,216,0,53,0,15,255,214,0,53,0,16,255,205,0,53,0,17,255,235,0,53,0,21,255,211,0,53,0,23,255,218,0,53,0,25,255,248,0,53,0,27,255,222,0,53,0,28,255,222,0,53,0,33,255,197,0,53,0,34,255,202,0,53,0,36,255,232,0,53,0,40,255,232,0,53,0,46,255,230,0,53,0,48,255,232,0,53,0,50,255,232,0,53,0,62,0,18,0,53,0,66,255,195,0,53,0,67,255,250,0,53,0,68,255,177,0,53,0,69,255,177,0,53,0,70,255,177,0,53,0,71,255,231,0,53,0,72,255,175,0,53,0,73,255,250,0,53,0,74,255,247,0,53,0,75,255,247,0,53,0,76,255,250,0,53,0,77,255,250,0,53,0,78,255,168,0,53,0,79,255,168,0,53,0,80,255,177,0,53,0,81,255,168,0,53,0,82,255,177,0,53,0,83,255,168,0,53,0,84,255,197,0,53,0,85,255,230,0,53,0,86,255,169,0,53,0,87,255,173,0,53,0,88,255,182,0,53,0,89,255,170,0,53,0,90,255,171,0,53,0,91,255,208,0,53,0,94,0,21,0,53,0,107,255,195,0,53,0,110,255,232,0,53,0,122,255,197,0,53,0,127,255,202,0,53,0,128,255,202,0,53,0,129,255,202,0,53,0,130,255,202,0,53,0,131,255,202,0,53,0,132,255,202,0,53,0,133,255,183,0,53,0,134,255,232,0,53,0,145,255,232,0,53,0,146,255,232,0,53,0,147,255,232,0,53,0,148,255,232,0,53,0,149,255,232,0,53,0,151,255,232,0,53,0,158,255,227,0,53,0,159,255,195,0,53,0,160,255,195,0,53,0,161,255,195,0,53,0,162,255,203,0,53,0,163,255,195,0,53,0,164,255,195,0,53,0,165,255,195,0,53,0,166,255,177,0,53,0,167,255,177,0,53,0,168,255,177,0,53,0,169,255,177,0,53,0,170,255,177,0,53,0,171,255,254,0,53,0,172,255,254,0,53,0,173,0,52,0,53,0,174,0,30,0,53,0,175,255,215,0,53,0,176,255,168,0,53,0,177,255,177,0,53,0,178,255,177,0,53,0,179,255,177,0,53,0,180,255,177,0,53,0,181,255,177,0,53,0,183,255,177,0,53,0,184,255,169,0,53,0,185,255,169,0,53,0,186,255,169,0,53,0,187,255,169,0,53,0,188,255,171,0,53,0,189,255,208,0,53,0,190,255,171,0,53,0,193,255,247,0,53,0,194,255,232,0,53,0,195,255,177,0,53,0,197,255,216,0,53,0,200,255,208,0,53,0,207,255,216,0,53,0,208,255,216,0,53,0,211,255,213,0,53,0,214,255,213,0,53,0,218,255,214,0,53,0,220,255,195,0,53,0,221,255,197,0,53,0,240,0,16,0,54,0,10,255,245,0,54,0,13,255,243,0,54,0,15,255,243,0,54,0,16,255,234,0,54,0,34,255,240,0,54,0,46,255,248,0,54,0,59,255,251,0,54,0,66,255,242,0,54,0,67,255,245,0,54,0,68,255,243,0,54,0,69,255,243,0,54,0,70,255,243,0,54,0,71,255,250,0,54,0,72,255,242,0,54,0,73,255,245,0,54,0,74,255,243,0,54,0,75,255,243,0,54,0,76,255,245,0,54,0,77,255,244,0,54,0,78,255,240,0,54,0,79,255,240,0,54,0,80,255,243,0,54,0,81,255,240,0,54,0,82,255,243,0,54,0,83,255,240,0,54,0,84,255,243,0,54,0,85,255,249,0,54,0,86,255,242,0,54,0,87,255,250,0,54,0,88,255,250,0,54,0,89,255,250,0,54,0,90,255,250,0,54,0,91,255,244,0,54,0,127,255,240,0,54,0,128,255,240,0,54,0,129,255,240,0,54,0,130,255,240,0,54,0,131,255,240,0,54,0,132,255,240,0,54,0,133,255,240,0,54,0,158,255,248,0,54,0,159,255,242,0,54,0,160,255,242,0,54,0,161,255,242,0,54,0,162,255,242,0,54,0,163,255,242,0,54,0,164,255,242,0,54,0,165,255,242,0,54,0,166,255,243,0,54,0,167,255,243,0,54,0,168,255,243,0,54,0,169,255,243,0,54,0,170,255,243,0,54,0,171,255,243,0,54,0,172,255,243,0,54,0,173,255,251,0,54,0,174,255,243,0,54,0,175,255,242,0,54,0,176,255,240,0,54,0,177,255,243,0,54,0,178,255,243,0,54,0,179,255,243,0,54,0,180,255,243,0,54,0,181,255,243,0,54,0,183,255,243,0,54,0,184,255,242,0,54,0,185,255,242,0,54,0,186,255,242,0,54,0,187,255,242,0,54,0,188,255,250,0,54,0,189,255,240,0,54,0,190,255,250,0,54,0,193,255,243,0,54,0,195,255,243,0,54,0,197,255,243,0,54,0,199,255,251,0,54,0,200,255,244,0,54,0,211,255,243,0,54,0,214,255,243,0,54,0,218,255,243,0,55,0,7,255,243,0,55,0,11,0,16,0,55,0,13,255,213,0,55,0,14,255,238,0,55,0,15,255,213,0,55,0,16,255,201,0,55,0,17,255,246,0,55,0,21,255,220,0,55,0,23,255,230,0,55,0,28,255,248,0,55,0,33,255,213,0,55,0,34,255,207,0,55,0,36,255,244,0,55,0,40,255,244,0,55,0,46,255,235,0,55,0,48,255,244,0,55,0,50,255,244,0,55,0,62,0,29,0,55,0,66,255,216,0,55,0,68,255,196,0,55,0,69,255,196,0,55,0,70,255,196,0,55,0,71,255,244,0,55,0,72,255,203,0,55,0,78,255,220,0,55,0,79,255,220,0,55,0,80,255,196,0,55,0,81,255,220,0,55,0,82,255,196,0,55,0,83,255,220,0,55,0,84,255,217,0,55,0,85,255,239,0,55,0,86,255,220,0,55,0,87,255,242,0,55,0,88,255,241,0,55,0,89,255,243,0,55,0,90,255,243,0,55,0,91,255,243,0,55,0,94,0,29,0,55,0,107,255,220,0,55,0,110,255,245,0,55,0,122,255,244,0,55,0,127,255,207,0,55,0,128,255,207,0,55,0,129,255,207,0,55,0,130,255,207,0,55,0,131,255,207,0,55,0,132,255,207,0,55,0,133,255,196,0,55,0,134,255,244,0,55,0,145,255,244,0,55,0,146,255,244,0,55,0,147,255,244,0,55,0,148,255,244,0,55,0,149,255,244,0,55,0,151,255,244,0,55,0,158,255,242,0,55,0,159,255,216,0,55,0,160,255,216,0,55,0,161,255,216,0,55,0,162,255,216,0,55,0,163,255,216,0,55,0,164,255,216,0,55,0,165,255,216,0,55,0,166,255,196,0,55,0,167,255,196,0,55,0,168,255,196,0,55,0,169,255,196,0,55,0,170,255,196,0,55,0,171,0,9,0,55,0,173,0,44,0,55,0,174,0,40,0,55,0,175,255,216,0,55,0,176,255,220,0,55,0,177,255,196,0,55,0,178,255,196,0,55,0,179,255,196,0,55,0,180,255,196,0,55,0,181,255,196,0,55,0,183,255,196,0,55,0,184,255,220,0,55,0,185,255,220,0,55,0,186,255,220,0,55,0,187,255,220,0,55,0,188,255,243,0,55,0,189,255,220,0,55,0,190,255,243,0,55,0,194,255,244,0,55,0,195,255,196,0,55,0,197,255,227,0,55,0,200,255,243,0,55,0,207,255,238,0,55,0,208,255,238,0,55,0,211,255,213,0,55,0,214,255,213,0,55,0,218,255,213,0,55,0,220,255,220,0,55,0,221,255,244,0,55,0,240,0,26,0,56,0,7,255,247,0,56,0,11,0,17,0,56,0,13,255,225,0,56,0,14,255,248,0,56,0,15,255,226,0,56,0,16,255,215,0,56,0,21,255,233,0,56,0,23,255,241,0,56,0,33,255,223,0,56,0,34,255,219,0,56,0,36,255,249,0,56,0,40,255,249,0,56,0,46,255,239,0,56,0,48,255,249,0,56,0,50,255,249,0,56,0,62,0,26,0,56,0,66,255,216,0,56,0,68,255,217,0,56,0,69,255,217,0,56,0,70,255,217,0,56,0,71,255,247,0,56,0,72,255,216,0,56,0,74,255,251,0,56,0,75,255,251,0,56,0,78,255,224,0,56,0,79,255,224,0,56,0,80,255,217,0,56,0,81,255,224,0,56,0,82,255,217,0,56,0,83,255,224,0,56,0,84,255,219,0,56,0,85,255,243,0,56,0,86,255,227,0,56,0,87,255,247,0,56,0,88,255,247,0,56,0,89,255,249,0,56,0,90,255,248,0,56,0,91,255,247,0,56,0,94,0,28,0,56,0,107,255,230,0,56,0,127,255,219,0,56,0,128,255,219,0,56,0,129,255,219,0,56,0,130,255,219,0,56,0,131,255,219,0,56,0,132,255,219,0,56,0,133,255,209,0,56,0,134,255,249,0,56,0,145,255,249,0,56,0,146,255,249,0,56,0,147,255,249,0,56,0,148,255,249,0,56,0,149,255,249,0,56,0,151,255,249,0,56,0,158,255,245,0,56,0,159,255,216,0,56,0,160,255,216,0,56,0,161,255,216,0,56,0,162,255,216,0,56,0,163,255,216,0,56,0,164,255,216,0,56,0,165,255,216,0,56,0,166,255,217,0,56,0,167,255,217,0,56,0,168,255,217,0,56,0,169,255,217,0,56,0,170,255,217,0,56,0,171,0,4,0,56,0,172,255,251,0,56,0,173,0,44,0,56,0,174,0,36,0,56,0,175,255,222,0,56,0,176,255,224,0,56,0,177,255,217,0,56,0,178,255,217,0,56,0,179,255,217,0,56,0,180,255,217,0,56,0,181,255,217,0,56,0,183,255,217,0,56,0,184,255,227,0,56,0,185,255,227,0,56,0,186,255,227,0,56,0,187,255,227,0,56,0,188,255,248,0,56,0,189,255,224,0,56,0,190,255,248,0,56,0,193,255,251,0,56,0,194,255,249,0,56,0,195,255,217,0,56,0,197,255,219,0,56,0,200,255,247,0,56,0,207,255,248,0,56,0,208,255,248,0,56,0,211,255,225,0,56,0,214,255,225,0,56,0,218,255,226,0,56,0,220,255,230,0,56,0,240,0,23,0,57,0,7,255,246,0,57,0,14,255,243,0,57,0,36,255,229,0,57,0,40,255,229,0,57,0,48,255,229,0,57,0,50,255,229,0,57,0,52,255,251,0,57,0,62,0,31,0,57,0,68,255,223,0,57,0,69,255,223,0,57,0,70,255,223,0,57,0,71,255,245,0,57,0,72,255,238,0,57,0,80,255,223,0,57,0,82,255,223,0,57,0,85,255,228,0,57,0,86,255,232,0,57,0,87,255,207,0,57,0,88,255,213,0,57,0,90,255,206,0,57,0,94,0,31,0,57,0,107,255,226,0,57,0,110,255,238,0,57,0,134,255,229,0,57,0,145,255,229,0,57,0,146,255,229,0,57,0,147,255,229,0,57,0,148,255,229,0,57,0,149,255,229,0,57,0,151,255,229,0,57,0,158,255,243,0,57,0,166,255,223,0,57,0,167,255,223,0,57,0,168,255,223,0,57,0,169,255,223,0,57,0,170,255,223,0,57,0,171,0,7,0,57,0,173,0,23,0,57,0,174,0,38,0,57,0,175,255,239,0,57,0,177,255,223,0,57,0,178,255,223,0,57,0,179,255,223,0,57,0,180,255,223,0,57,0,181,255,223,0,57,0,183,255,223,0,57,0,184,255,232,0,57,0,185,255,232,0,57,0,186,255,232,0,57,0,187,255,232,0,57,0,188,255,206,0,57,0,190,255,206,0,57,0,194,255,229,0,57,0,195,255,223,0,57,0,196,255,251,0,57,0,207,255,243,0,57,0,208,255,243,0,57,0,220,255,226,0,57,0,240,0,24,0,58,0,7,255,237,0,58,0,11,0,13,0,58,0,13,255,215,0,58,0,14,255,222,0,58,0,15,255,215,0,58,0,16,255,201,0,58,0,17,255,233,0,58,0,21,255,206,0,58,0,23,255,218,0,58,0,25,255,246,0,58,0,27,255,235,0,58,0,28,255,235,0,58,0,32,0,13,0,58,0,33,255,198,0,58,0,34,255,192,0,58,0,36,255,230,0,58,0,40,255,230,0,58,0,46,255,232,0,58,0,48,255,230,0,58,0,50,255,230,0,58,0,61,0,7,0,58,0,62,0,31,0,58,0,66,255,189,0,58,0,68,255,171,0,58,0,69,255,171,0,58,0,70,255,171,0,58,0,71,255,237,0,58,0,72,255,180,0,58,0,78,255,187,0,58,0,79,255,187,0,58,0,80,255,171,0,58,0,81,255,187,0,58,0,82,255,171,0,58,0,83,255,187,0,58,0,84,255,186,0,58,0,85,255,221,0,58,0,86,255,190,0,58,0,87,255,215,0,58,0,88,255,216,0,58,0,89,255,214,0,58,0,90,255,217,0,58,0,91,255,229,0,58,0,94,0,33,0,58,0,107,255,198,0,58,0,110,255,230,0,58,0,122,255,225,0,58,0,127,255,192,0,58,0,128,255,192,0,58,0,129,255,192,0,58,0,130,255,192,0,58,0,131,255,192,0,58,0,132,255,192,0,58,0,133,255,180,0,58,0,134,255,230,0,58,0,145,255,230,0,58,0,146,255,230,0,58,0,147,255,230,0,58,0,148,255,230,0,58,0,149,255,230,0,58,0,151,255,230,0,58,0,158,255,230,0,58,0,159,255,189,0,58,0,160,255,189,0,58,0,161,255,189,0,58,0,162,255,189,0,58,0,163,255,189,0,58,0,164,255,189,0,58,0,165,255,189,0,58,0,166,255,171,0,58,0,167,255,171,0,58,0,168,255,171,0,58,0,169,255,171,0,58,0,170,255,171,0,58,0,171,0,16,0,58,0,173,0,38,0,58,0,174,0,47,0,58,0,175,255,216,0,58,0,176,255,187,0,58,0,177,255,171,0,58,0,178,255,171,0,58,0,179,255,171,0,58,0,180,255,171,0,58,0,181,255,171,0,58,0,183,255,171,0,58,0,184,255,190,0,58,0,185,255,190,0,58,0,186,255,190,0,58,0,187,255,190,0,58,0,188,255,217,0,58,0,189,255,225,0,58,0,190,255,217,0,58,0,194,255,230,0,58,0,195,255,171,0,58,0,197,255,234,0,58,0,200,255,229,0,58,0,207,255,222,0,58,0,208,255,222,0,58,0,211,255,215,0,58,0,214,255,215,0,58,0,218,255,215,0,58,0,220,255,198,0,58,0,221,255,225,0,58,0,240,0,33,0,59,0,14,255,217,0,59,0,17,255,243,0,59,0,21,255,199,0,59,0,23,255,247,0,59,0,36,255,238,0,59,0,40,255,238,0,59,0,48,255,238,0,59,0,50,255,238,0,59,0,62,0,23,0,59,0,66,255,246,0,59,0,68,255,227,0,59,0,69,255,227,0,59,0,70,255,227,0,59,0,71,255,241,0,59,0,72,255,229,0,59,0,74,255,250,0,59,0,75,255,250,0,59,0,78,255,235,0,59,0,79,255,235,0,59,0,80,255,227,0,59,0,81,255,235,0,59,0,82,255,227,0,59,0,83,255,235,0,59,0,84,255,245,0,59,0,85,255,241,0,59,0,86,255,224,0,59,0,87,255,241,0,59,0,88,255,241,0,59,0,90,255,242,0,59,0,91,255,248,0,59,0,94,0,23,0,59,0,107,255,214,0,59,0,110,255,233,0,59,0,134,255,238,0,59,0,145,255,238,0,59,0,146,255,238,0,59,0,147,255,238,0,59,0,148,255,238,0,59,0,149,255,238,0,59,0,151,255,238,0,59,0,158,255,239,0,59,0,159,255,246,0,59,0,160,255,246,0,59,0,161,255,246,0,59,0,162,255,246,0,59,0,163,255,246,0,59,0,164,255,246,0,59,0,165,255,246,0,59,0,166,255,227,0,59,0,167,255,227,0,59,0,168,255,227,0,59,0,169,255,227,0,59,0,170,255,227,0,59,0,171,0,6,0,59,0,172,255,250,0,59,0,173,0,29,0,59,0,174,0,37,0,59,0,175,255,235,0,59,0,176,255,235,0,59,0,177,255,227,0,59,0,178,255,227,0,59,0,179,255,227,0,59,0,180,255,227,0,59,0,181,255,227,0,59,0,183,255,227,0,59,0,184,255,224,0,59,0,185,255,224,0,59,0,186,255,224,0,59,0,187,255,224,0,59,0,188,255,242,0,59,0,189,255,235,0,59,0,190,255,242,0,59,0,193,255,250,0,59,0,194,255,238,0,59,0,195,255,227,0,59,0,197,255,245,0,59,0,200,255,248,0,59,0,207,255,217,0,59,0,208,255,217,0,59,0,220,255,214,0,59,0,240,0,24,0,60,0,17,255,232,0,60,0,21,255,228,0,60,0,23,255,229,0,60,0,25,255,248,0,60,0,34,255,227,0,60,0,36,255,226,0,60,0,40,255,226,0,60,0,43,0,49,0,60,0,46,255,244,0,60,0,48,255,226,0,60,0,50,255,226,0,60,0,53,0,22,0,60,0,55,0,31,0,60,0,56,0,27,0,60,0,57,0,28,0,60,0,58,0,36,0,60,0,66,255,218,0,60,0,68,255,213,0,60,0,69,255,213,0,60,0,70,255,213,0,60,0,75,0,7,0,60,0,78,255,214,0,60,0,79,255,214,0,60,0,80,255,213,0,60,0,81,255,223,0,60,0,82,255,213,0,60,0,83,255,214,0,60,0,84,255,218,0,60,0,85,255,224,0,60,0,86,255,215,0,60,0,87,255,216,0,60,0,88,255,218,0,60,0,89,255,226,0,60,0,90,255,216,0,60,0,91,255,219,0,60,0,127,255,227,0,60,0,128,255,227,0,60,0,129,255,227,0,60,0,130,255,227,0,60,0,131,255,227,0,60,0,132,255,227,0,60,0,133,255,243,0,60,0,134,255,226,0,60,0,145,255,226,0,60,0,146,255,226,0,60,0,147,255,226,0,60,0,148,255,226,0,60,0,149,255,226,0,60,0,151,255,226,0,60,0,156,0,36,0,60,0,158,255,244,0,60,0,159,255,218,0,60,0,160,255,218,0,60,0,161,255,218,0,60,0,162,255,228,0,60,0,163,255,218,0,60,0,164,255,218,0,60,0,165,255,218,0,60,0,166,255,213,0,60,0,167,255,213,0,60,0,168,255,213,0,60,0,169,255,213,0,60,0,170,255,213,0,60,0,171,0,15,0,60,0,173,0,34,0,60,0,174,0,45,0,60,0,175,255,231,0,60,0,176,255,214,0,60,0,177,255,213,0,60,0,178,255,213,0,60,0,179,255,213,0,60,0,180,255,213,0,60,0,181,255,213,0,60,0,183,255,213,0,60,0,184,255,215,0,60,0,185,255,215,0,60,0,186,255,215,0,60,0,187,255,215,0,60,0,188,255,216,0,60,0,189,255,252,0,60,0,190,255,216,0,60,0,194,255,226,0,60,0,195,255,213,0,60,0,197,255,232,0,60,0,198,0,36,0,60,0,200,255,246,0,61,0,3,255,220,0,61,0,8,255,220,0,61,0,17,255,244,0,61,0,18,255,241,0,61,0,26,255,242,0,61,0,36,255,236,0,61,0,40,255,236,0,61,0,43,0,16,0,61,0,48,255,236,0,61,0,50,255,236,0,61,0,53,255,205,0,61,0,54,255,234,0,61,0,55,255,201,0,61,0,56,255,216,0,61,0,58,255,201,0,61,0,85,255,240,0,61,0,87,255,222,0,61,0,88,255,231,0,61,0,90,255,219,0,61,0,134,255,236,0,61,0,145,255,236,0,61,0,146,255,236,0,61,0,147,255,236,0,61,0,148,255,236,0,61,0,149,255,236,0,61,0,151,255,236,0,61,0,152,255,234,0,61,0,153,255,234,0,61,0,154,255,234,0,61,0,155,255,234,0,61,0,156,255,201,0,61,0,188,255,219,0,61,0,190,255,219,0,61,0,194,255,236,0,61,0,198,255,201,0,61,0,210,255,214,0,61,0,213,255,214,0,66,0,3,255,234,0,66,0,7,255,245,0,66,0,8,255,234,0,66,0,10,255,246,0,66,0,11,255,231,0,66,0,18,255,234,0,66,0,26,255,247,0,66,0,32,255,229,0,66,0,35,255,240,0,66,0,36,255,237,0,66,0,37,255,240,0,66,0,38,255,240,0,66,0,39,255,240,0,66,0,40,255,237,0,66,0,41,255,240,0,66,0,42,255,240,0,66,0,43,255,240,0,66,0,44,255,240,0,66,0,45,255,240,0,66,0,46,255,248,0,66,0,47,255,240,0,66,0,48,255,237,0,66,0,49,255,240,0,66,0,50,255,237,0,66,0,51,255,240,0,66,0,52,255,250,0,66,0,53,255,173,0,66,0,54,255,227,0,66,0,55,255,193,0,66,0,56,255,210,0,66,0,58,255,165,0,66,0,61,255,210,0,66,0,62,255,227,0,66,0,71,255,251,0,66,0,85,255,246,0,66,0,87,255,238,0,66,0,88,255,243,0,66,0,90,255,236,0,66,0,94,255,231,0,66,0,110,255,248,0,66,0,134,255,237,0,66,0,135,255,240,0,66,0,136,255,240,0,66,0,137,255,240,0,66,0,138,255,240,0,66,0,139,255,240,0,66,0,140,255,240,0,66,0,141,255,240,0,66,0,142,255,240,0,66,0,143,255,240,0,66,0,144,255,240,0,66,0,145,255,237,0,66,0,146,255,237,0,66,0,147,255,237,0,66,0,148,255,237,0,66,0,149,255,237,0,66,0,151,255,237,0,66,0,152,255,227,0,66,0,153,255,227,0,66,0,154,255,227,0,66,0,155,255,227,0,66,0,156,255,165,0,66,0,157,255,240,0,66,0,158,255,249,0,66,0,188,255,236,0,66,0,190,255,236,0,66,0,194,255,237,0,66,0,196,255,250,0,66,0,198,255,165,0,66,0,209,255,186,0,66,0,210,255,183,0,66,0,212,255,186,0,66,0,213,255,183,0,66,0,240,255,230,0,67,0,3,255,234,0,67,0,7,255,246,0,67,0,8,255,234,0,67,0,10,255,227,0,67,0,11,255,232,0,67,0,13,255,246,0,67,0,15,255,247,0,67,0,18,255,235,0,67,0,19,255,232,0,67,0,24,255,226,0,67,0,32,255,224,0,67,0,34,255,240,0,67,0,35,255,237,0,67,0,36,255,246,0,67,0,37,255,237,0,67,0,38,255,237,0,67,0,39,255,237,0,67,0,40,255,246,0,67,0,41,255,237,0,67,0,42,255,237,0,67,0,43,255,237,0,67,0,44,255,237,0,67,0,45,255,237,0,67,0,46,255,239,0,67,0,47,255,237,0,67,0,48,255,246,0,67,0,49,255,237,0,67,0,50,255,246,0,67,0,51,255,237,0,67,0,52,255,237,0,67,0,53,255,171,0,67,0,54,255,238,0,67,0,55,255,193,0,67,0,56,255,212,0,67,0,57,255,217,0,67,0,58,255,167,0,67,0,59,255,227,0,67,0,61,255,217,0,67,0,62,255,217,0,67,0,71,255,251,0,67,0,85,255,250,0,67,0,87,255,247,0,67,0,88,255,251,0,67,0,89,255,238,0,67,0,90,255,245,0,67,0,91,255,246,0,67,0,94,255,226,0,67,0,122,255,247,0,67,0,127,255,240,0,67,0,128,255,240,0,67,0,129,255,240,0,67,0,130,255,240,0,67,0,131,255,240,0,67,0,132,255,240,0,67,0,134,255,246,0,67,0,135,255,237,0,67,0,136,255,237,0,67,0,137,255,237,0,67,0,138,255,237,0,67,0,139,255,237,0,67,0,140,255,237,0,67,0,141,255,237,0,67,0,142,255,237,0,67,0,143,255,237,0,67,0,144,255,237,0,67,0,145,255,246,0,67,0,146,255,246,0,67,0,147,255,246,0,67,0,148,255,246,0,67,0,149,255,246,0,67,0,151,255,246,0,67,0,152,255,238,0,67,0,153,255,238,0,67,0,154,255,238,0,67,0,155,255,238,0,67,0,156,255,167,0,67,0,157,255,237,0,67,0,158,255,248,0,67,0,188,255,245,0,67,0,190,255,245,0,67,0,194,255,246,0,67,0,196,255,237,0,67,0,198,255,167,0,67,0,199,255,227,0,67,0,200,255,246,0,67,0,209,255,181,0,67,0,210,255,178,0,67,0,211,255,246,0,67,0,212,255,181,0,67,0,213,255,178,0,67,0,214,255,246,0,67,0,218,255,247,0,67,0,221,255,247,0,67,0,240,255,234,0,68,0,7,255,240,0,68,0,10,255,244,0,68,0,14,255,219,0,68,0,21,255,231,0,68,0,24,255,245,0,68,0,32,255,228,0,68,0,35,255,247,0,68,0,36,255,244,0,68,0,37,255,247,0,68,0,38,255,247,0,68,0,39,255,247,0,68,0,40,255,244,0,68,0,41,255,247,0,68,0,42,255,247,0,68,0,43,255,247,0,68,0,44,255,247,0,68,0,45,255,247,0,68,0,46,255,251,0,68,0,47,255,247,0,68,0,48,255,244,0,68,0,49,255,247,0,68,0,50,255,244,0,68,0,51,255,247,0,68,0,52,255,244,0,68,0,53,255,190,0,68,0,54,255,243,0,68,0,55,255,236,0,68,0,56,255,241,0,68,0,58,255,218,0,68,0,61,255,240,0,68,0,62,255,232,0,68,0,68,255,249,0,68,0,69,255,249,0,68,0,70,255,249,0,68,0,80,255,249,0,68,0,82,255,249,0,68,0,94,255,239,0,68,0,107,255,243,0,68,0,134,255,244,0,68,0,135,255,247,0,68,0,136,255,247,0,68,0,137,255,247,0,68,0,138,255,247,0,68,0,139,255,247,0,68,0,140,255,247,0,68,0,141,255,247,0,68,0,142,255,247,0,68,0,143,255,247,0,68,0,144,255,247,0,68,0,145,255,244,0,68,0,146,255,244,0,68,0,147,255,244,0,68,0,148,255,244,0,68,0,149,255,244,0,68,0,151,255,244,0,68,0,152,255,243,0,68,0,153,255,243,0,68,0,154,255,243,0,68,0,155,255,243,0,68,0,156,255,218,0,68,0,157,255,247,0,68,0,166,255,249,0,68,0,167,255,249,0,68,0,168,255,249,0,68,0,169,255,249,0,68,0,170,255,249,0,68,0,175,255,251,0,68,0,177,255,249,0,68,0,178,255,249,0,68,0,179,255,249,0,68,0,180,255,249,0,68,0,181,255,249,0,68,0,183,255,249,0,68,0,194,255,244,0,68,0,195,255,249,0,68,0,196,255,244,0,68,0,198,255,218,0,68,0,207,255,219,0,68,0,208,255,219,0,68,0,209,255,216,0,68,0,210,255,213,0,68,0,212,255,216,0,68,0,213,255,213,0,68,0,220,255,243,0,68,0,240,255,245,0,69,0,7,255,244,0,69,0,34,255,249,0,69,0,35,255,242,0,69,0,36,255,245,0,69,0,37,255,242,0,69,0,38,255,242,0,69,0,39,255,242,0,69,0,40,255,245,0,69,0,41,255,242,0,69,0,42,255,242,0,69,0,43,255,242,0,69,0,44,255,242,0,69,0,45,255,242,0,69,0,46,255,240,0,69,0,47,255,242,0,69,0,48,255,245,0,69,0,49,255,242,0,69,0,50,255,245,0,69,0,51,255,242,0,69,0,52,255,246,0,69,0,53,255,245,0,69,0,54,255,240,0,69,0,55,255,250,0,69,0,56,255,248,0,69,0,58,255,251,0,69,0,59,255,245,0,69,0,127,255,249,0,69,0,128,255,249,0,69,0,129,255,249,0,69,0,130,255,249,0,69,0,131,255,249,0,69,0,132,255,249,0,69,0,134,255,245,0,69,0,135,255,242,0,69,0,136,255,242,0,69,0,137,255,242,0,69,0,138,255,242,0,69,0,139,255,242,0,69,0,140,255,242,0,69,0,141,255,242,0,69,0,142,255,242,0,69,0,143,255,242,0,69,0,144,255,242,0,69,0,145,255,245,0,69,0,146,255,245,0,69,0,147,255,245,0,69,0,148,255,245,0,69,0,149,255,245,0,69,0,151,255,245,0,69,0,152,255,240,0,69,0,153,255,240,0,69,0,154,255,240,0,69,0,155,255,240,0,69,0,156,255,251,0,69,0,157,255,242,0,69,0,194,255,245,0,69,0,196,255,246,0,69,0,198,255,251,0,69,0,199,255,245,0,70,0,3,255,241,0,70,0,7,255,246,0,70,0,8,255,241,0,70,0,10,255,230,0,70,0,11,255,238,0,70,0,18,255,235,0,70,0,19,255,245,0,70,0,24,255,230,0,70,0,32,255,223,0,70,0,34,255,251,0,70,0,35,255,241,0,70,0,36,255,250,0,70,0,37,255,241,0,70,0,38,255,241,0,70,0,39,255,241,0,70,0,40,255,250,0,70,0,41,255,241,0,70,0,42,255,241,0,70,0,43,255,241,0,70,0,44,255,241,0,70,0,45,255,241,0,70,0,46,255,243,0,70,0,47,255,241,0,70,0,48,255,250,0,70,0,49,255,241,0,70,0,50,255,250,0,70,0,51,255,241,0,70,0,52,255,241,0,70,0,53,255,187,0,70,0,54,255,240,0,70,0,55,255,209,0,70,0,56,255,213,0,70,0,57,255,243,0,70,0,58,255,174,0,70,0,59,255,243,0,70,0,61,255,220,0,70,0,62,255,220,0,70,0,87,255,252,0,70,0,89,255,251,0,70,0,90,255,251,0,70,0,94,255,227,0,70,0,127,255,251,0,70,0,128,255,251,0,70,0,129,255,251,0,70,0,130,255,251,0,70,0,131,255,251,0,70,0,132,255,251,0,70,0,134,255,250,0,70,0,135,255,241,0,70,0,136,255,241,0,70,0,137,255,241,0,70,0,138,255,241,0,70,0,139,255,241,0,70,0,140,255,241,0,70,0,141,255,241,0,70,0,142,255,241,0,70,0,143,255,241,0,70,0,144,255,241,0,70,0,145,255,250,0,70,0,146,255,250,0,70,0,147,255,250,0,70,0,148,255,250,0,70,0,149,255,250,0,70,0,151,255,250,0,70,0,152,255,240,0,70,0,153,255,240,0,70,0,154,255,240,0,70,0,155,255,240,0,70,0,156,255,174,0,70,0,157,255,241,0,70,0,188,255,251,0,70,0,190,255,251,0,70,0,194,255,250,0,70,0,196,255,241,0,70,0,198,255,174,0,70,0,199,255,243,0,70,0,209,255,189,0,70,0,210,255,186,0,70,0,212,255,189,0,70,0,213,255,186,0,70,0,240,255,237,0,71,0,7,255,235,0,71,0,13,255,229,0,71,0,14,255,232,0,71,0,15,255,229,0,71,0,16,255,234,0,71,0,21,255,244,0,71,0,33,255,239,0,71,0,34,255,211,0,71,0,35,255,244,0,71,0,37,255,244,0,71,0,38,255,244,0,71,0,39,255,244,0,71,0,41,255,244,0,71,0,42,255,244,0,71,0,43,255,244,0,71,0,44,255,244,0,71,0,45,255,244,0,71,0,46,255,229,0,71,0,47,255,244,0,71,0,49,255,244,0,71,0,51,255,244,0,71,0,54,255,247,0,71,0,59,255,243,0,71,0,66,255,251,0,71,0,68,255,246,0,71,0,69,255,246,0,71,0,70,255,246,0,71,0,72,255,252,0,71,0,80,255,246,0,71,0,82,255,246,0,71,0,94,0,8,0,71,0,107,255,239,0,71,0,127,255,211,0,71,0,128,255,211,0,71,0,129,255,211,0,71,0,130,255,211,0,71,0,131,255,211,0,71,0,132,255,211,0,71,0,135,255,244,0,71,0,136,255,244,0,71,0,137,255,244,0,71,0,138,255,244,0,71,0,139,255,244,0,71,0,140,255,244,0,71,0,141,255,244,0,71,0,142,255,244,0,71,0,143,255,244,0,71,0,144,255,244,0,71,0,152,255,247,0,71,0,153,255,247,0,71,0,154,255,247,0,71,0,155,255,247,0,71,0,157,255,244,0,71,0,159,255,251,0,71,0,160,255,251,0,71,0,161,255,251,0,71,0,162,255,251,0,71,0,163,255,251,0,71,0,164,255,251,0,71,0,165,255,251,0,71,0,166,255,246,0,71,0,167,255,246,0,71,0,168,255,246,0,71,0,169,255,246,0,71,0,170,255,246,0,71,0,175,255,224,0,71,0,177,255,246,0,71,0,178,255,246,0,71,0,179,255,246,0,71,0,180,255,246,0,71,0,181,255,246,0,71,0,183,255,246,0,71,0,195,255,246,0,71,0,199,255,243,0,71,0,207,255,232,0,71,0,208,255,232,0,71,0,211,255,229,0,71,0,214,255,229,0,71,0,218,255,229,0,71,0,220,255,239,0,72,0,7,255,244,0,72,0,10,0,5,0,72,0,16,0,14,0,72,0,24,255,225,0,72,0,32,255,217,0,72,0,34,255,249,0,72,0,35,255,245,0,72,0,37,255,245,0,72,0,38,255,245,0,72,0,39,255,245,0,72,0,41,255,245,0,72,0,42,255,245,0,72,0,43,0,45,0,72,0,44,255,245,0,72,0,45,255,245,0,72,0,46,255,242,0,72,0,47,255,245,0,72,0,49,255,245,0,72,0,51,255,245,0,72,0,53,255,208,0,72,0,54,255,246,0,72,0,55,255,247,0,72,0,56,255,250,0,72,0,57,255,250,0,72,0,58,255,238,0,72,0,59,255,245,0,72,0,62,0,25,0,72,0,75,0,19,0,72,0,94,0,29,0,72,0,127,255,249,0,72,0,128,255,249,0,72,0,129,255,249,0,72,0,130,255,249,0,72,0,131,255,249,0,72,0,132,255,249,0,72,0,135,255,245,0,72,0,136,255,245,0,72,0,137,255,245,0,72,0,138,255,245,0,72,0,139,255,245,0,72,0,140,255,245,0,72,0,141,255,245,0,72,0,142,255,245,0,72,0,143,255,245,0,72,0,144,255,245,0,72,0,152,255,246,0,72,0,153,255,246,0,72,0,154,255,246,0,72,0,155,255,246,0,72,0,156,255,238,0,72,0,157,255,245,0,72,0,175,255,250,0,72,0,198,255,238,0,72,0,199,255,245,0,72,0,209,255,223,0,72,0,210,255,221,0,72,0,212,255,223,0,72,0,213,255,221,0,73,0,2,255,248,0,73,0,3,255,238,0,73,0,7,255,245,0,73,0,8,255,238,0,73,0,10,255,232,0,73,0,11,255,235,0,73,0,18,255,231,0,73,0,24,255,233,0,73,0,32,255,224,0,73,0,34,255,250,0,73,0,35,255,238,0,73,0,36,255,243,0,73,0,37,255,238,0,73,0,38,255,238,0,73,0,39,255,238,0,73,0,40,255,243,0,73,0,41,255,238,0,73,0,42,255,238,0,73,0,43,255,238,0,73,0,44,255,238,0,73,0,45,255,238,0,73,0,46,255,241,0,73,0,47,255,238,0,73,0,48,255,243,0,73,0,49,255,238,0,73,0,50,255,243,0,73,0,51,255,238,0,73,0,52,255,241,0,73,0,53,255,162,0,73,0,54,255,231,0,73,0,55,255,198,0,73,0,56,255,214,0,73,0,57,255,249,0,73,0,58,255,163,0,73,0,59,255,245,0,73,0,61,255,214,0,73,0,62,255,216,0,73,0,71,255,251,0,73,0,85,255,248,0,73,0,87,255,243,0,73,0,88,255,248,0,73,0,90,255,242,0,73,0,94,255,225,0,73,0,127,255,250,0,73,0,128,255,250,0,73,0,129,255,250,0,73,0,130,255,250,0,73,0,131,255,250,0,73,0,132,255,250,0,73,0,134,255,243,0,73,0,135,255,238,0,73,0,136,255,238,0,73,0,137,255,238,0,73,0,138,255,238,0,73,0,139,255,238,0,73,0,140,255,238,0,73,0,141,255,238,0,73,0,142,255,238,0,73,0,143,255,238,0,73,0,144,255,238,0,73,0,145,255,243,0,73,0,146,255,243,0,73,0,147,255,243,0,73,0,148,255,243,0,73,0,149,255,243,0,73,0,151,255,243,0,73,0,152,255,231,0,73,0,153,255,231,0,73,0,154,255,231,0,73,0,155,255,231,0,73,0,156,255,163,0,73,0,157,255,238,0,73,0,158,255,248,0,73,0,188,255,242,0,73,0,190,255,242,0,73,0,194,255,243,0,73,0,196,255,241,0,73,0,198,255,163,0,73,0,199,255,245,0,73,0,209,255,187,0,73,0,210,255,184,0,73,0,212,255,187,0,73,0,213,255,184,0,73,0,240,255,235,0,74,0,7,255,244,0,74,0,34,255,248,0,74,0,35,255,242,0,74,0,36,255,244,0,74,0,37,255,242,0,74,0,38,255,242,0,74,0,39,255,242,0,74,0,40,255,244,0,74,0,41,255,242,0,74,0,42,255,242,0,74,0,43,255,242,0,74,0,44,255,242,0,74,0,45,255,242,0,74,0,46,255,241,0,74,0,47,255,242,0,74,0,48,255,244,0,74,0,49,255,242,0,74,0,50,255,244,0,74,0,51,255,242,0,74,0,52,255,244,0,74,0,53,255,242,0,74,0,54,255,238,0,74,0,55,255,247,0,74,0,56,255,246,0,74,0,58,255,247,0,74,0,59,255,245,0,74,0,127,255,248,0,74,0,128,255,248,0,74,0,129,255,248,0,74,0,130,255,248,0,74,0,131,255,248,0,74,0,132,255,248,0,74,0,134,255,244,0,74,0,135,255,242,0,74,0,136,255,242,0,74,0,137,255,242,0,74,0,138,255,242,0,74,0,139,255,242,0,74,0,140,255,242,0,74,0,141,255,242,0,74,0,142,255,242,0,74,0,143,255,242,0,74,0,144,255,242,0,74,0,145,255,244,0,74,0,146,255,244,0,74,0,147,255,244,0,74,0,148,255,244,0,74,0,149,255,244,0,74,0,151,255,244,0,74,0,152,255,238,0,74,0,153,255,238,0,74,0,154,255,238,0,74,0,155,255,238,0,74,0,156,255,247,0,74,0,157,255,242,0,74,0,194,255,244,0,74,0,196,255,244,0,74,0,198,255,247,0,74,0,199,255,245,0,75,0,7,255,244,0,75,0,34,255,248,0,75,0,35,255,242,0,75,0,36,255,244,0,75,0,37,255,242,0,75,0,38,255,242,0,75,0,39,255,242,0,75,0,40,255,244,0,75,0,41,255,242,0,75,0,42,255,242,0,75,0,43,255,242,0,75,0,44,255,242,0,75,0,45,255,242,0,75,0,46,255,241,0,75,0,47,255,242,0,75,0,48,255,244,0,75,0,49,255,242,0,75,0,50,255,244,0,75,0,51,255,242,0,75,0,52,255,244,0,75,0,53,255,242,0,75,0,54,255,238,0,75,0,55,255,247,0,75,0,56,255,246,0,75,0,58,255,247,0,75,0,59,255,245,0,75,0,127,255,248,0,75,0,128,255,248,0,75,0,129,255,248,0,75,0,130,255,248,0,75,0,131,255,248,0,75,0,132,255,248,0,75,0,134,255,244,0,75,0,135,255,242,0,75,0,136,255,242,0,75,0,137,255,242,0,75,0,138,255,242,0,75,0,139,255,242,0,75,0,140,255,242,0,75,0,141,255,242,0,75,0,142,255,242,0,75,0,143,255,242,0,75,0,144,255,242,0,75,0,145,255,244,0,75,0,146,255,244,0,75,0,147,255,244,0,75,0,148,255,244,0,75,0,149,255,244,0,75,0,151,255,244,0,75,0,152,255,238,0,75,0,153,255,238,0,75,0,154,255,238,0,75,0,155,255,238,0,75,0,156,255,247,0,75,0,157,255,242,0,75,0,194,255,244,0,75,0,196,255,244,0,75,0,198,255,247,0,75,0,199,255,245,0,76,0,7,255,242,0,76,0,14,255,241,0,76,0,32,255,237,0,76,0,36,255,234,0,76,0,40,255,234,0,76,0,48,255,234,0,76,0,50,255,234,0,76,0,53,255,166,0,76,0,54,255,251,0,76,0,55,255,245,0,76,0,56,255,251,0,76,0,58,255,217,0,76,0,62,255,239,0,76,0,66,255,251,0,76,0,68,255,234,0,76,0,69,255,234,0,76,0,70,255,234,0,76,0,72,255,238,0,76,0,80,255,234,0,76,0,82,255,234,0,76,0,107,255,238,0,76,0,134,255,234,0,76,0,145,255,234,0,76,0,146,255,234,0,76,0,147,255,234,0,76,0,148,255,234,0,76,0,149,255,234,0,76,0,151,255,234,0,76,0,152,255,251,0,76,0,153,255,251,0,76,0,154,255,251,0,76,0,155,255,251,0,76,0,156,255,217,0,76,0,159,255,251,0,76,0,160,255,251,0,76,0,161,255,251,0,76,0,162,255,251,0,76,0,163,255,251,0,76,0,164,255,251,0,76,0,165,255,251,0,76,0,166,255,234,0,76,0,167,255,234,0,76,0,168,255,234,0,76,0,169,255,234,0,76,0,170,255,234,0,76,0,175,255,230,0,76,0,177,255,234,0,76,0,178,255,234,0,76,0,179,255,234,0,76,0,180,255,234,0,76,0,181,255,234,0,76,0,183,255,234,0,76,0,194,255,234,0,76,0,195,255,234,0,76,0,198,255,217,0,76,0,207,255,241,0,76,0,208,255,241,0,76,0,209,255,229,0,76,0,210,255,227,0,76,0,212,255,229,0,76,0,213,255,227,0,76,0,220,255,238,0,77,0,3,255,247,0,77,0,7,255,244,0,77,0,8,255,247,0,77,0,11,255,246,0,77,0,35,255,240,0,77,0,36,255,237,0,77,0,37,255,240,0,77,0,38,255,240,0,77,0,39,255,240,0,77,0,40,255,237,0,77,0,41,255,240,0,77,0,42,255,240,0,77,0,43,255,240,0,77,0,44,255,240,0,77,0,45,255,240,0,77,0,46,255,248,0,77,0,47,255,240,0,77,0,48,255,237,0,77,0,49,255,240,0,77,0,50,255,237,0,77,0,51,255,240,0,77,0,53,255,234,0,77,0,54,255,228,0,77,0,55,255,239,0,77,0,56,255,237,0,77,0,58,255,241,0,77,0,68,255,251,0,77,0,69,255,251,0,77,0,70,255,251,0,77,0,80,255,251,0,77,0,82,255,251,0,77,0,85,255,251,0,77,0,87,255,249,0,77,0,88,255,251,0,77,0,90,255,249,0,77,0,107,255,247,0,77,0,134,255,237,0,77,0,135,255,240,0,77,0,136,255,240,0,77,0,137,255,240,0,77,0,138,255,240,0,77,0,139,255,240,0,77,0,140,255,240,0,77,0,141,255,240,0,77,0,142,255,240,0,77,0,143,255,240,0,77,0,144,255,240,0,77,0,145,255,237,0,77,0,146,255,237,0,77,0,147,255,237,0,77,0,148,255,237,0,77,0,149,255,237,0,77,0,151,255,237,0,77,0,152,255,228,0,77,0,153,255,228,0,77,0,154,255,228,0,77,0,155,255,228,0,77,0,156,255,241,0,77,0,157,255,240,0,77,0,166,255,251,0,77,0,167,255,251,0,77,0,168,255,251,0,77,0,169,255,251,0,77,0,170,255,251,0,77,0,177,255,251,0,77,0,178,255,251,0,77,0,179,255,251,0,77,0,180,255,251,0,77,0,181,255,251,0,77,0,183,255,251,0,77,0,188,255,249,0,77,0,190,255,249,0,77,0,194,255,237,0,77,0,195,255,251,0,77,0,198,255,241,0,77,0,209,255,245,0,77,0,210,255,246,0,77,0,212,255,245,0,77,0,213,255,246,0,77,0,220,255,247,0,78,0,2,255,248,0,78,0,3,255,238,0,78,0,7,255,245,0,78,0,8,255,238,0,78,0,10,255,232,0,78,0,11,255,235,0,78,0,18,255,231,0,78,0,24,255,233,0,78,0,32,255,224,0,78,0,34,255,250,0,78,0,35,255,238,0,78,0,36,255,243,0,78,0,37,255,238,0,78,0,38,255,238,0,78,0,39,255,238,0,78,0,40,255,243,0,78,0,41,255,238,0,78,0,42,255,238,0,78,0,43,255,238,0,78,0,44,255,238,0,78,0,45,255,238,0,78,0,46,255,241,0,78,0,47,255,238,0,78,0,48,255,243,0,78,0,49,255,238,0,78,0,50,255,243,0,78,0,51,255,238,0,78,0,52,255,241,0,78,0,53,255,162,0,78,0,54,255,231,0,78,0,55,255,198,0,78,0,56,255,214,0,78,0,57,255,249,0,78,0,58,255,163,0,78,0,59,255,245,0,78,0,61,255,214,0,78,0,62,255,216,0,78,0,71,255,251,0,78,0,85,255,248,0,78,0,87,255,243,0,78,0,88,255,248,0,78,0,90,255,242,0,78,0,94,255,225,0,78,0,127,255,250,0,78,0,128,255,250,0,78,0,129,255,250,0,78,0,130,255,250,0,78,0,131,255,250,0,78,0,132,255,250,0,78,0,134,255,243,0,78,0,135,255,238,0,78,0,136,255,238,0,78,0,137,255,238,0,78,0,138,255,238,0,78,0,139,255,238,0,78,0,140,255,238,0,78,0,141,255,238,0,78,0,142,255,238,0,78,0,143,255,238,0,78,0,144,255,238,0,78,0,145,255,243,0,78,0,146,255,243,0,78,0,147,255,243,0,78,0,148,255,243,0,78,0,149,255,243,0,78,0,151,255,243,0,78,0,152,255,231,0,78,0,153,255,231,0,78,0,154,255,231,0,78,0,155,255,231,0,78,0,156,255,163,0,78,0,157,255,238,0,78,0,158,255,248,0,78,0,188,255,242,0,78,0,190,255,242,0,78,0,194,255,243,0,78,0,196,255,241,0,78,0,198,255,163,0,78,0,199,255,245,0,78,0,209,255,187,0,78,0,210,255,184,0,78,0,212,255,187,0,78,0,213,255,184,0,78,0,240,255,235,0,79,0,2,255,248,0,79,0,3,255,238,0,79,0,7,255,245,0,79,0,8,255,238,0,79,0,10,255,232,0,79,0,11,255,235,0,79,0,18,255,231,0,79,0,24,255,233,0,79,0,32,255,224,0,79,0,34,255,250,0,79,0,35,255,238,0,79,0,36,255,243,0,79,0,37,255,238,0,79,0,38,255,238,0,79,0,39,255,238,0,79,0,40,255,243,0,79,0,41,255,238,0,79,0,42,255,238,0,79,0,43,255,238,0,79,0,44,255,238,0,79,0,45,255,238,0,79,0,46,255,241,0,79,0,47,255,238,0,79,0,48,255,243,0,79,0,49,255,238,0,79,0,50,255,243,0,79,0,51,255,238,0,79,0,52,255,241,0,79,0,53,255,162,0,79,0,54,255,231,0,79,0,55,255,198,0,79,0,56,255,214,0,79,0,57,255,249,0,79,0,58,255,163,0,79,0,59,255,245,0,79,0,61,255,214,0,79,0,62,255,216,0,79,0,71,255,251,0,79,0,85,255,248,0,79,0,87,255,243,0,79,0,88,255,248,0,79,0,90,255,242,0,79,0,94,255,225,0,79,0,127,255,250,0,79,0,128,255,250,0,79,0,129,255,250,0,79,0,130,255,250,0,79,0,131,255,250,0,79,0,132,255,250,0,79,0,134,255,243,0,79,0,135,255,238,0,79,0,136,255,238,0,79,0,137,255,238,0,79,0,138,255,238,0,79,0,139,255,238,0,79,0,140,255,238,0,79,0,141,255,238,0,79,0,142,255,238,0,79,0,143,255,238,0,79,0,144,255,238,0,79,0,145,255,243,0,79,0,146,255,243,0,79,0,147,255,243,0,79,0,148,255,243,0,79,0,149,255,243,0,79,0,151,255,243,0,79,0,152,255,231,0,79,0,153,255,231,0,79,0,154,255,231,0,79,0,155,255,231,0,79,0,156,255,163,0,79,0,157,255,238,0,79,0,158,255,248,0,79,0,188,255,242,0,79,0,190,255,242,0,79,0,194,255,243,0,79,0,196,255,241,0,79,0,198,255,163,0,79,0,199,255,245,0,79,0,209,255,187,0,79,0,210,255,184,0,79,0,212,255,187,0,79,0,213,255,184,0,79,0,240,255,235,0,80,0,3,255,236,0,80,0,7,255,246,0,80,0,8,255,236,0,80,0,10,255,224,0,80,0,11,255,234,0,80,0,18,255,230,0,80,0,19,255,229,0,80,0,24,255,223,0,80,0,32,255,222,0,80,0,34,255,240,0,80,0,35,255,237,0,80,0,36,255,246,0,80,0,37,255,237,0,80,0,38,255,237,0,80,0,39,255,237,0,80,0,40,255,246,0,80,0,41,255,237,0,80,0,42,255,237,0,80,0,43,255,237,0,80,0,44,255,237,0,80,0,45,255,237,0,80,0,46,255,239,0,80,0,47,255,237,0,80,0,48,255,246,0,80,0,49,255,237,0,80,0,50,255,246,0,80,0,51,255,237,0,80,0,52,255,238,0,80,0,53,255,173,0,80,0,54,255,238,0,80,0,55,255,192,0,80,0,56,255,212,0,80,0,57,255,218,0,80,0,58,255,167,0,80,0,59,255,227,0,80,0,61,255,214,0,80,0,62,255,213,0,80,0,71,255,251,0,80,0,85,255,249,0,80,0,87,255,247,0,80,0,88,255,251,0,80,0,89,255,237,0,80,0,90,255,245,0,80,0,91,255,246,0,80,0,94,255,222,0,80,0,122,255,247,0,80,0,127,255,240,0,80,0,128,255,240,0,80,0,129,255,240,0,80,0,130,255,240,0,80,0,131,255,240,0,80,0,132,255,240,0,80,0,134,255,246,0,80,0,135,255,237,0,80,0,136,255,237,0,80,0,137,255,237,0,80,0,138,255,237,0,80,0,139,255,237,0,80,0,140,255,237,0,80,0,141,255,237,0,80,0,142,255,237,0,80,0,143,255,237,0,80,0,144,255,237,0,80,0,145,255,246,0,80,0,146,255,246,0,80,0,147,255,246,0,80,0,148,255,246,0,80,0,149,255,246,0,80,0,151,255,246,0,80,0,152,255,238,0,80,0,153,255,238,0,80,0,154,255,238,0,80,0,155,255,238,0,80,0,156,255,167,0,80,0,157,255,237,0,80,0,158,255,248,0,80,0,188,255,245,0,80,0,190,255,245,0,80,0,194,255,246,0,80,0,196,255,238,0,80,0,198,255,167,0,80,0,199,255,227,0,80,0,200,255,246,0,80,0,209,255,182,0,80,0,210,255,179,0,80,0,212,255,182,0,80,0,213,255,179,0,80,0,221,255,247,0,80,0,240,255,236,0,81,0,3,255,236,0,81,0,7,255,246,0,81,0,8,255,236,0,81,0,10,255,224,0,81,0,11,255,234,0,81,0,18,255,230,0,81,0,19,255,229,0,81,0,24,255,223,0,81,0,32,255,222,0,81,0,34,255,240,0,81,0,35,255,237,0,81,0,36,255,246,0,81,0,37,255,237,0,81,0,38,255,237,0,81,0,39,255,237,0,81,0,40,255,246,0,81,0,41,255,237,0,81,0,42,255,237,0,81,0,43,255,237,0,81,0,44,255,237,0,81,0,45,255,237,0,81,0,46,255,239,0,81,0,47,255,237,0,81,0,48,255,246,0,81,0,49,255,237,0,81,0,50,255,246,0,81,0,51,255,237,0,81,0,52,255,238,0,81,0,53,255,173,0,81,0,54,255,238,0,81,0,55,255,192,0,81,0,56,255,212,0,81,0,57,255,218,0,81,0,58,255,167,0,81,0,59,255,227,0,81,0,61,255,214,0,81,0,62,255,213,0,81,0,71,255,251,0,81,0,85,255,249,0,81,0,87,255,247,0,81,0,88,255,251,0,81,0,89,255,237,0,81,0,90,255,245,0,81,0,91,255,246,0,81,0,94,255,222,0,81,0,122,255,247,0,81,0,127,255,240,0,81,0,128,255,240,0,81,0,129,255,240,0,81,0,130,255,240,0,81,0,131,255,240,0,81,0,132,255,240,0,81,0,134,255,246,0,81,0,135,255,237,0,81,0,136,255,237,0,81,0,137,255,237,0,81,0,138,255,237,0,81,0,139,255,237,0,81,0,140,255,237,0,81,0,141,255,237,0,81,0,142,255,237,0,81,0,143,255,237,0,81,0,144,255,237,0,81,0,145,255,246,0,81,0,146,255,246,0,81,0,147,255,246,0,81,0,148,255,246,0,81,0,149,255,246,0,81,0,151,255,246,0,81,0,152,255,238,0,81,0,153,255,238,0,81,0,154,255,238,0,81,0,155,255,238,0,81,0,156,255,167,0,81,0,157,255,237,0,81,0,158,255,248,0,81,0,188,255,245,0,81,0,190,255,245,0,81,0,194,255,246,0,81,0,196,255,238,0,81,0,198,255,167,0,81,0,199,255,227,0,81,0,200,255,246,0,81,0,209,255,182,0,81,0,210,255,179,0,81,0,212,255,182,0,81,0,213,255,179,0,81,0,221,255,247,0,81,0,240,255,236,0,82,0,7,255,244,0,82,0,10,255,233,0,82,0,11,255,244,0,82,0,24,255,232,0,82,0,32,255,223,0,82,0,34,255,248,0,82,0,35,255,242,0,82,0,36,255,244,0,82,0,37,255,242,0,82,0,38,255,242,0,82,0,39,255,242,0,82,0,40,255,244,0,82,0,41,255,242,0,82,0,42,255,242,0,82,0,43,255,242,0,82,0,44,255,242,0,82,0,45,255,242,0,82,0,46,255,241,0,82,0,47,255,242,0,82,0,48,255,244,0,82,0,49,255,242,0,82,0,50,255,244,0,82,0,51,255,242,0,82,0,52,255,243,0,82,0,53,255,164,0,82,0,54,255,235,0,82,0,55,255,216,0,82,0,56,255,218,0,82,0,57,255,246,0,82,0,58,255,183,0,82,0,59,255,242,0,82,0,61,255,228,0,82,0,62,255,215,0,82,0,94,255,226,0,82,0,127,255,248,0,82,0,128,255,248,0,82,0,129,255,248,0,82,0,130,255,248,0,82,0,131,255,248,0,82,0,132,255,248,0,82,0,134,255,244,0,82,0,135,255,242,0,82,0,136,255,242,0,82,0,137,255,242,0,82,0,138,255,242,0,82,0,139,255,242,0,82,0,140,255,242,0,82,0,141,255,242,0,82,0,142,255,242,0,82,0,143,255,242,0,82,0,144,255,242,0,82,0,145,255,244,0,82,0,146,255,244,0,82,0,147,255,244,0,82,0,148,255,244,0,82,0,149,255,244,0,82,0,151,255,244,0,82,0,152,255,235,0,82,0,153,255,235,0,82,0,154,255,235,0,82,0,155,255,235,0,82,0,156,255,183,0,82,0,157,255,242,0,82,0,194,255,244,0,82,0,196,255,243,0,82,0,198,255,183,0,82,0,199,255,242,0,82,0,209,255,211,0,82,0,210,255,209,0,82,0,212,255,211,0,82,0,213,255,209,0,82,0,240,255,239,0,83,0,7,255,237,0,83,0,10,255,232,0,83,0,13,255,227,0,83,0,14,255,234,0,83,0,15,255,227,0,83,0,16,255,225,0,83,0,20,255,231,0,83,0,21,255,238,0,83,0,24,255,200,0,83,0,32,255,202,0,83,0,33,255,232,0,83,0,34,255,211,0,83,0,35,255,243,0,83,0,37,255,243,0,83,0,38,255,243,0,83,0,39,255,243,0,83,0,41,255,243,0,83,0,42,255,243,0,83,0,43,255,243,0,83,0,44,255,243,0,83,0,45,255,243,0,83,0,46,255,230,0,83,0,47,255,243,0,83,0,49,255,243,0,83,0,51,255,243,0,83,0,53,255,163,0,83,0,54,255,247,0,83,0,55,255,243,0,83,0,56,255,247,0,83,0,57,255,214,0,83,0,58,255,225,0,83,0,59,255,227,0,83,0,62,255,217,0,83,0,66,255,249,0,83,0,68,255,243,0,83,0,69,255,243,0,83,0,70,255,243,0,83,0,72,255,250,0,83,0,80,255,243,0,83,0,82,255,243,0,83,0,94,255,228,0,83,0,107,255,237,0,83,0,127,255,211,0,83,0,128,255,211,0,83,0,129,255,211,0,83,0,130,255,211,0,83,0,131,255,211,0,83,0,132,255,211,0,83,0,135,255,243,0,83,0,136,255,243,0,83,0,137,255,243,0,83,0,138,255,243,0,83,0,139,255,243,0,83,0,140,255,243,0,83,0,141,255,243,0,83,0,142,255,243,0,83,0,143,255,243,0,83,0,144,255,243,0,83,0,152,255,247,0,83,0,153,255,247,0,83,0,154,255,247,0,83,0,155,255,247,0,83,0,156,255,225,0,83,0,157,255,243,0,83,0,159,255,249,0,83,0,160,255,249,0,83,0,161,255,249,0,83,0,162,255,249,0,83,0,163,255,249,0,83,0,164,255,249,0,83,0,165,255,249,0,83,0,166,255,243,0,83,0,167,255,243,0,83,0,168,255,243,0,83,0,169,255,243,0,83,0,170,255,243,0,83,0,175,255,218,0,83,0,177,255,243,0,83,0,178,255,243,0,83,0,179,255,243,0,83,0,180,255,243,0,83,0,181,255,243,0,83,0,183,255,243,0,83,0,195,255,243,0,83,0,198,255,225,0,83,0,199,255,227,0,83,0,207,255,234,0,83,0,208,255,234,0,83,0,209,255,233,0,83,0,210,255,230,0,83,0,211,255,227,0,83,0,212,255,233,0,83,0,213,255,230,0,83,0,214,255,227,0,83,0,218,255,227,0,83,0,220,255,237,0,84,0,10,255,231,0,84,0,11,255,241,0,84,0,24,255,234,0,84,0,32,255,224,0,84,0,35,255,241,0,84,0,36,255,244,0,84,0,37,255,241,0,84,0,38,255,241,0,84,0,39,255,241,0,84,0,40,255,244,0,84,0,41,255,241,0,84,0,42,255,241,0,84,0,43,255,241,0,84,0,44,255,241,0,84,0,45,255,241,0,84,0,46,255,245,0,84,0,47,255,241,0,84,0,48,255,244,0,84,0,49,255,241,0,84,0,50,255,244,0,84,0,51,255,241,0,84,0,52,255,248,0,84,0,53,255,202,0,84,0,54,255,238,0,84,0,55,255,216,0,84,0,56,255,224,0,84,0,57,255,244,0,84,0,58,255,209,0,84,0,59,255,245,0,84,0,61,255,225,0,84,0,62,255,220,0,84,0,94,255,229,0,84,0,134,255,244,0,84,0,135,255,241,0,84,0,136,255,241,0,84,0,137,255,241,0,84,0,138,255,241,0,84,0,139,255,241,0,84,0,140,255,241,0,84,0,141,255,241,0,84,0,142,255,241,0,84,0,143,255,241,0,84,0,144,255,241,0,84,0,145,255,244,0,84,0,146,255,244,0,84,0,147,255,244,0,84,0,148,255,244,0,84,0,149,255,244,0,84,0,151,255,244,0,84,0,152,255,238,0,84,0,153,255,238,0,84,0,154,255,238,0,84,0,155,255,238,0,84,0,156,255,209,0,84,0,157,255,241,0,84,0,194,255,244,0,84,0,196,255,248,0,84,0,198,255,209,0,84,0,199,255,245,0,84,0,209,255,203,0,84,0,210,255,200,0,84,0,212,255,203,0,84,0,213,255,200,0,84,0,240,255,235,0,85,0,7,255,246,0,85,0,21,255,234,0,85,0,24,255,246,0,85,0,32,255,229,0,85,0,35,255,248,0,85,0,37,255,248,0,85,0,38,255,248,0,85,0,39,255,248,0,85,0,41,255,248,0,85,0,42,255,248,0,85,0,43,255,248,0,85,0,44,255,248,0,85,0,45,255,248,0,85,0,46,255,248,0,85,0,47,255,248,0,85,0,49,255,248,0,85,0,51,255,248,0,85,0,53,255,209,0,85,0,54,255,246,0,85,0,55,255,237,0,85,0,56,255,243,0,85,0,58,255,211,0,85,0,62,255,230,0,85,0,68,255,252,0,85,0,69,255,252,0,85,0,70,255,252,0,85,0,80,255,252,0,85,0,82,255,252,0,85,0,94,255,242,0,85,0,107,255,244,0,85,0,135,255,248,0,85,0,136,255,248,0,85,0,137,255,248,0,85,0,138,255,248,0,85,0,139,255,248,0,85,0,140,255,248,0,85,0,141,255,248,0,85,0,142,255,248,0,85,0,143,255,248,0,85,0,144,255,248,0,85,0,152,255,246,0,85,0,153,255,246,0,85,0,154,255,246,0,85,0,155,255,246,0,85,0,156,255,211,0,85,0,157,255,248,0,85,0,166,255,252,0,85,0,167,255,252,0,85,0,168,255,252,0,85,0,169,255,252,0,85,0,170,255,252,0,85,0,175,255,251,0,85,0,177,255,252,0,85,0,178,255,252,0,85,0,179,255,252,0,85,0,180,255,252,0,85,0,181,255,252,0,85,0,183,255,252,0,85,0,195,255,252,0,85,0,198,255,211,0,85,0,209,255,234,0,85,0,210,255,233,0,85,0,212,255,234,0,85,0,213,255,233,0,85,0,220,255,244,0,86,0,7,255,244,0,86,0,10,255,233,0,86,0,11,255,244,0,86,0,24,255,232,0,86,0,32,255,223,0,86,0,34,255,248,0,86,0,35,255,242,0,86,0,36,255,244,0,86,0,37,255,242,0,86,0,38,255,242,0,86,0,39,255,242,0,86,0,40,255,244,0,86,0,41,255,242,0,86,0,42,255,242,0,86,0,43,255,242,0,86,0,44,255,242,0,86,0,45,255,242,0,86,0,46,255,241,0,86,0,47,255,242,0,86,0,48,255,244,0,86,0,49,255,242,0,86,0,50,255,244,0,86,0,51,255,242,0,86,0,52,255,243,0,86,0,53,255,164,0,86,0,54,255,235,0,86,0,55,255,216,0,86,0,56,255,218,0,86,0,57,255,246,0,86,0,58,255,183,0,86,0,59,255,242,0,86,0,61,255,228,0,86,0,62,255,215,0,86,0,94,255,226,0,86,0,127,255,248,0,86,0,128,255,248,0,86,0,129,255,248,0,86,0,130,255,248,0,86,0,131,255,248,0,86,0,132,255,248,0,86,0,134,255,244,0,86,0,135,255,242,0,86,0,136,255,242,0,86,0,137,255,242,0,86,0,138,255,242,0,86,0,139,255,242,0,86,0,140,255,242,0,86,0,141,255,242,0,86,0,142,255,242,0,86,0,143,255,242,0,86,0,144,255,242,0,86,0,145,255,244,0,86,0,146,255,244,0,86,0,147,255,244,0,86,0,148,255,244,0,86,0,149,255,244,0,86,0,151,255,244,0,86,0,152,255,235,0,86,0,153,255,235,0,86,0,154,255,235,0,86,0,155,255,235,0,86,0,156,255,183,0,86,0,157,255,242,0,86,0,194,255,244,0,86,0,196,255,243,0,86,0,198,255,183,0,86,0,199,255,242,0,86,0,209,255,211,0,86,0,210,255,209,0,86,0,212,255,211,0,86,0,213,255,209,0,86,0,240,255,239,0,87,0,7,255,238,0,87,0,10,255,231,0,87,0,13,255,227,0,87,0,15,255,227,0,87,0,16,255,223,0,87,0,20,255,231,0,87,0,24,255,200,0,87,0,32,255,206,0,87,0,33,255,240,0,87,0,34,255,216,0,87,0,35,255,242,0,87,0,37,255,242,0,87,0,38,255,242,0,87,0,39,255,242,0,87,0,41,255,242,0,87,0,42,255,242,0,87,0,43,255,242,0,87,0,44,255,242,0,87,0,45,255,242,0,87,0,46,255,229,0,87,0,47,255,242,0,87,0,49,255,242,0,87,0,51,255,242,0,87,0,53,255,170,0,87,0,54,255,245,0,87,0,55,255,237,0,87,0,56,255,242,0,87,0,57,255,208,0,87,0,58,255,210,0,87,0,59,255,224,0,87,0,62,255,214,0,87,0,66,255,250,0,87,0,68,255,247,0,87,0,69,255,247,0,87,0,70,255,247,0,87,0,72,255,250,0,87,0,80,255,247,0,87,0,82,255,247,0,87,0,84,255,252,0,87,0,94,255,227,0,87,0,127,255,216,0,87,0,128,255,216,0,87,0,129,255,216,0,87,0,130,255,216,0,87,0,131,255,216,0,87,0,132,255,216,0,87,0,135,255,242,0,87,0,136,255,242,0,87,0,137,255,242,0,87,0,138,255,242,0,87,0,139,255,242,0,87,0,140,255,242,0,87,0,141,255,242,0,87,0,142,255,242,0,87,0,143,255,242,0,87,0,144,255,242,0,87,0,152,255,245,0,87,0,153,255,245,0,87,0,154,255,245,0,87,0,155,255,245,0,87,0,156,255,210,0,87,0,157,255,242,0,87,0,159,255,250,0,87,0,160,255,250,0,87,0,161,255,250,0,87,0,162,255,250,0,87,0,163,255,250,0,87,0,164,255,250,0,87,0,165,255,250,0,87,0,166,255,247,0,87,0,167,255,247,0,87,0,168,255,247,0,87,0,169,255,247,0,87,0,170,255,247,0,87,0,175,255,238,0,87,0,177,255,247,0,87,0,178,255,247,0,87,0,179,255,247,0,87,0,180,255,247,0,87,0,181,255,247,0,87,0,183,255,247,0,87,0,195,255,247,0,87,0,197,255,252,0,87,0,198,255,210,0,87,0,199,255,224,0,87,0,209,255,226,0,87,0,210,255,224,0,87,0,211,255,227,0,87,0,212,255,226,0,87,0,213,255,224,0,87,0,214,255,227,0,87,0,218,255,227,0,88,0,7,255,240,0,88,0,10,255,232,0,88,0,13,255,235,0,88,0,15,255,236,0,88,0,16,255,231,0,88,0,20,255,240,0,88,0,24,255,207,0,88,0,32,255,211,0,88,0,33,255,247,0,88,0,34,255,223,0,88,0,35,255,243,0,88,0,37,255,243,0,88,0,38,255,243,0,88,0,39,255,243,0,88,0,41,255,243,0,88,0,42,255,243,0,88,0,43,255,243,0,88,0,44,255,243,0,88,0,45,255,243,0,88,0,46,255,232,0,88,0,47,255,243,0,88,0,49,255,243,0,88,0,51,255,243,0,88,0,53,255,178,0,88,0,54,255,246,0,88,0,55,255,236,0,88,0,56,255,242,0,88,0,57,255,213,0,88,0,58,255,211,0,88,0,59,255,228,0,88,0,62,255,218,0,88,0,66,255,252,0,88,0,68,255,251,0,88,0,69,255,251,0,88,0,70,255,251,0,88,0,80,255,251,0,88,0,82,255,251,0,88,0,94,255,229,0,88,0,127,255,223,0,88,0,128,255,223,0,88,0,129,255,223,0,88,0,130,255,223,0,88,0,131,255,223,0,88,0,132,255,223,0,88,0,135,255,243,0,88,0,136,255,243,0,88,0,137,255,243,0,88,0,138,255,243,0,88,0,139,255,243,0,88,0,140,255,243,0,88,0,141,255,243,0,88,0,142,255,243,0,88,0,143,255,243,0,88,0,144,255,243,0,88,0,152,255,246,0,88,0,153,255,246,0,88,0,154,255,246,0,88,0,155,255,246,0,88,0,156,255,211,0,88,0,157,255,243,0,88,0,159,255,252,0,88,0,160,255,252,0,88,0,161,255,252,0,88,0,162,255,252,0,88,0,163,255,252,0,88,0,164,255,252,0,88,0,165,255,252,0,88,0,166,255,251,0,88,0,167,255,251,0,88,0,168,255,251,0,88,0,169,255,251,0,88,0,170,255,251,0,88,0,175,255,246,0,88,0,177,255,251,0,88,0,178,255,251,0,88,0,179,255,251,0,88,0,180,255,251,0,88,0,181,255,251,0,88,0,183,255,251,0,88,0,195,255,251,0,88,0,198,255,211,0,88,0,199,255,228,0,88,0,209,255,227,0,88,0,210,255,225,0,88,0,211,255,235,0,88,0,212,255,227,0,88,0,213,255,225,0,88,0,214,255,235,0,88,0,218,255,236,0,89,0,7,255,238,0,89,0,14,255,247,0,89,0,32,255,227,0,89,0,35,255,247,0,89,0,36,255,240,0,89,0,37,255,247,0,89,0,38,255,247,0,89,0,39,255,247,0,89,0,40,255,240,0,89,0,41,255,247,0,89,0,42,255,247,0,89,0,43,255,247,0,89,0,44,255,247,0,89,0,45,255,247,0,89,0,46,255,250,0,89,0,47,255,247,0,89,0,48,255,240,0,89,0,49,255,247,0,89,0,50,255,240,0,89,0,51,255,247,0,89,0,52,255,248,0,89,0,53,255,167,0,89,0,54,255,244,0,89,0,55,255,236,0,89,0,56,255,242,0,89,0,58,255,208,0,89,0,61,255,247,0,89,0,62,255,230,0,89,0,66,255,252,0,89,0,68,255,238,0,89,0,69,255,238,0,89,0,70,255,238,0,89,0,72,255,247,0,89,0,80,255,238,0,89,0,82,255,238,0,89,0,94,255,237,0,89,0,107,255,236,0,89,0,134,255,240,0,89,0,135,255,247,0,89,0,136,255,247,0,89,0,137,255,247,0,89,0,138,255,247,0,89,0,139,255,247,0,89,0,140,255,247,0,89,0,141,255,247,0,89,0,142,255,247,0,89,0,143,255,247,0,89,0,144,255,247,0,89,0,145,255,240,0,89,0,146,255,240,0,89,0,147,255,240,0,89,0,148,255,240,0,89,0,149,255,240,0,89,0,151,255,240,0,89,0,152,255,244,0,89,0,153,255,244,0,89,0,154,255,244,0,89,0,155,255,244,0,89,0,156,255,208,0,89,0,157,255,247,0,89,0,159,255,252,0,89,0,160,255,252,0,89,0,161,255,252,0,89,0,162,255,252,0,89,0,163,255,252,0,89,0,164,255,252,0,89,0,165,255,252,0,89,0,166,255,238,0,89,0,167,255,238,0,89,0,168,255,238,0,89,0,169,255,238,0,89,0,170,255,238,0,89,0,175,255,240,0,89,0,177,255,238,0,89,0,178,255,238,0,89,0,179,255,238,0,89,0,180,255,238,0,89,0,181,255,238,0,89,0,183,255,238,0,89,0,194,255,240,0,89,0,195,255,238,0,89,0,196,255,248,0,89,0,198,255,208,0,89,0,207,255,247,0,89,0,208,255,247,0,89,0,209,255,224,0,89,0,210,255,222,0,89,0,212,255,224,0,89,0,213,255,222,0,89,0,220,255,236,0,89,0,240,255,248,0,90,0,7,255,238,0,90,0,10,255,231,0,90,0,13,255,225,0,90,0,15,255,225,0,90,0,16,255,220,0,90,0,19,255,227,0,90,0,20,255,230,0,90,0,24,255,198,0,90,0,32,255,205,0,90,0,33,255,238,0,90,0,34,255,214,0,90,0,35,255,243,0,90,0,37,255,243,0,90,0,38,255,243,0,90,0,39,255,243,0,90,0,41,255,243,0,90,0,42,255,243,0,90,0,43,255,243,0,90,0,44,255,243,0,90,0,45,255,243,0,90,0,46,255,229,0,90,0,47,255,243,0,90,0,49,255,243,0,90,0,51,255,243,0,90,0,53,255,168,0,90,0,54,255,245,0,90,0,55,255,238,0,90,0,56,255,242,0,90,0,57,255,208,0,90,0,58,255,211,0,90,0,59,255,225,0,90,0,62,255,214,0,90,0,66,255,250,0,90,0,68,255,246,0,90,0,69,255,246,0,90,0,70,255,246,0,90,0,72,255,250,0,90,0,80,255,246,0,90,0,82,255,246,0,90,0,84,255,252,0,90,0,94,255,227,0,90,0,127,255,214,0,90,0,128,255,214,0,90,0,129,255,214,0,90,0,130,255,214,0,90,0,131,255,214,0,90,0,132,255,214,0,90,0,135,255,243,0,90,0,136,255,243,0,90,0,137,255,243,0,90,0,138,255,243,0,90,0,139,255,243,0,90,0,140,255,243,0,90,0,141,255,243,0,90,0,142,255,243,0,90,0,143,255,243,0,90,0,144,255,243,0,90,0,152,255,245,0,90,0,153,255,245,0,90,0,154,255,245,0,90,0,155,255,245,0,90,0,156,255,211,0,90,0,157,255,243,0,90,0,159,255,250,0,90,0,160,255,250,0,90,0,161,255,250,0,90,0,162,255,250,0,90,0,163,255,250,0,90,0,164,255,250,0,90,0,165,255,250,0,90,0,166,255,246,0,90,0,167,255,246,0,90,0,168,255,246,0,90,0,169,255,246,0,90,0,170,255,246,0,90,0,175,255,236,0,90,0,177,255,246,0,90,0,178,255,246,0,90,0,179,255,246,0,90,0,180,255,246,0,90,0,181,255,246,0,90,0,183,255,246,0,90,0,195,255,246,0,90,0,197,255,252,0,90,0,198,255,211,0,90,0,199,255,225,0,90,0,209,255,227,0,90,0,210,255,225,0,90,0,211,255,225,0,90,0,212,255,227,0,90,0,213,255,225,0,90,0,214,255,225,0,90,0,218,255,225,0,91,0,7,255,245,0,91,0,10,255,246,0,91,0,14,255,240,0,91,0,21,255,225,0,91,0,24,255,244,0,91,0,32,255,221,0,91,0,35,255,242,0,91,0,36,255,244,0,91,0,37,255,242,0,91,0,38,255,242,0,91,0,39,255,242,0,91,0,40,255,244,0,91,0,41,255,242,0,91,0,42,255,242,0,91,0,43,255,242,0,91,0,44,255,242,0,91,0,45,255,242,0,91,0,46,255,245,0,91,0,47,255,242,0,91,0,48,255,244,0,91,0,49,255,242,0,91,0,50,255,244,0,91,0,51,255,242,0,91,0,53,255,203,0,91,0,54,255,239,0,91,0,55,255,240,0,91,0,56,255,243,0,91,0,58,255,227,0,91,0,61,255,242,0,91,0,62,255,222,0,91,0,68,255,245,0,91,0,69,255,245,0,91,0,70,255,245,0,91,0,72,255,251,0,91,0,80,255,245,0,91,0,82,255,245,0,91,0,94,255,232,0,91,0,107,255,232,0,91,0,134,255,244,0,91,0,135,255,242,0,91,0,136,255,242,0,91,0,137,255,242,0,91,0,138,255,242,0,91,0,139,255,242,0,91,0,140,255,242,0,91,0,141,255,242,0,91,0,142,255,242,0,91,0,143,255,242,0,91,0,144,255,242,0,91,0,145,255,244,0,91,0,146,255,244,0,91,0,147,255,244,0,91,0,148,255,244,0,91,0,149,255,244,0,91,0,151,255,244,0,91,0,152,255,239,0,91,0,153,255,239,0,91,0,154,255,239,0,91,0,155,255,239,0,91,0,156,255,227,0,91,0,157,255,242,0,91,0,166,255,245,0,91,0,167,255,245,0,91,0,168,255,245,0,91,0,169,255,245,0,91,0,170,255,245,0,91,0,175,255,247,0,91,0,177,255,245,0,91,0,178,255,245,0,91,0,179,255,245,0,91,0,180,255,245,0,91,0,181,255,245,0,91,0,183,255,245,0,91,0,194,255,244,0,91,0,195,255,245,0,91,0,198,255,227,0,91,0,207,255,240,0,91,0,208,255,240,0,91,0,209,255,219,0,91,0,210,255,216,0,91,0,212,255,219,0,91,0,213,255,216,0,91,0,220,255,232,0,91,0,240,255,242,0,92,0,17,255,238,0,92,0,21,255,238,0,92,0,23,255,235,0,92,0,34,255,244,0,92,0,36,255,231,0,92,0,40,255,231,0,92,0,43,0,47,0,92,0,46,255,247,0,92,0,48,255,231,0,92,0,50,255,231,0,92,0,53,0,21,0,92,0,55,0,29,0,92,0,56,0,25,0,92,0,57,0,28,0,92,0,58,0,34,0,92,0,66,255,229,0,92,0,68,255,222,0,92,0,69,255,222,0,92,0,70,255,222,0,92,0,78,255,227,0,92,0,79,255,227,0,92,0,80,255,222,0,92,0,81,255,227,0,92,0,82,255,222,0,92,0,83,255,227,0,92,0,84,255,229,0,92,0,85,255,231,0,92,0,86,255,225,0,92,0,87,255,227,0,92,0,88,255,228,0,92,0,89,255,238,0,92,0,90,255,227,0,92,0,91,255,232,0,92,0,127,255,244,0,92,0,128,255,244,0,92,0,129,255,244,0,92,0,130,255,244,0,92,0,131,255,244,0,92,0,132,255,244,0,92,0,134,255,231,0,92,0,145,255,231,0,92,0,146,255,231,0,92,0,147,255,231,0,92,0,148,255,231,0,92,0,149,255,231,0,92,0,151,255,231,0,92,0,156,0,34,0,92,0,158,255,247,0,92,0,159,255,229,0,92,0,160,255,229,0,92,0,161,255,229,0,92,0,162,255,229,0,92,0,163,255,229,0,92,0,164,255,229,0,92,0,165,255,229,0,92,0,166,255,222,0,92,0,167,255,222,0,92,0,168,255,222,0,92,0,169,255,222,0,92,0,170,255,222,0,92,0,171,0,12,0,92,0,173,0,33,0,92,0,174,0,44,0,92,0,175,255,234,0,92,0,176,255,227,0,92,0,177,255,222,0,92,0,178,255,222,0,92,0,179,255,222,0,92,0,180,255,222,0,92,0,181,255,222,0,92,0,183,255,222,0,92,0,184,255,225,0,92,0,185,255,225,0,92,0,186,255,225,0,92,0,187,255,225,0,92,0,188,255,227,0,92,0,189,255,249,0,92,0,190,255,227,0,92,0,194,255,231,0,92,0,195,255,222,0,92,0,197,255,229,0,92,0,198,0,34,0,92,0,200,255,232,0,97,0,53,255,200,0,97,0,55,255,236,0,97,0,56,255,244,0,97,0,58,255,224,0,97,0,156,255,224,0,97,0,198,255,224,0,107,0,53,255,197,0,107,0,55,255,245,0,107,0,58,255,226,0,107,0,68,255,247,0,107,0,69,255,247,0,107,0,70,255,247,0,107,0,80,255,247,0,107,0,82,255,247,0,107,0,156,255,226,0,107,0,166,255,247,0,107,0,167,255,247,0,107,0,168,255,247,0,107,0,169,255,247,0,107,0,170,255,247,0,107,0,177,255,247,0,107,0,178,255,247,0,107,0,179,255,247,0,107,0,180,255,247,0,107,0,181,255,247,0,107,0,183,255,247,0,107,0,195,255,247,0,107,0,198,255,226,0,107,0,210,255,229,0,107,0,213,255,229,0,110,0,34,255,237,0,110,0,46,255,247,0,110,0,53,255,230,0,110,0,55,255,243,0,110,0,56,255,248,0,110,0,57,255,236,0,110,0,58,255,229,0,110,0,59,255,231,0,110,0,127,255,237,0,110,0,128,255,237,0,110,0,129,255,237,0,110,0,130,255,237,0,110,0,131,255,237,0,110,0,132,255,237,0,110,0,133,255,236,0,110,0,156,255,229,0,110,0,198,255,229,0,110,0,199,255,231,0,111,0,21,255,229,0,111,0,23,255,239,0,122,0,3,255,241,0,122,0,8,255,241,0,122,0,34,255,247,0,122,0,52,255,234,0,122,0,53,255,195,0,122,0,55,255,220,0,122,0,56,255,230,0,122,0,57,255,224,0,122,0,58,255,198,0,122,0,59,255,223,0,122,0,85,255,247,0,122,0,89,255,236,0,122,0,90,255,248,0,122,0,91,255,233,0,122,0,127,255,247,0,122,0,128,255,247,0,122,0,129,255,247,0,122,0,130,255,247,0,122,0,131,255,247,0,122,0,132,255,247,0,122,0,133,255,243,0,122,0,156,255,198,0,122,0,158,255,248,0,122,0,188,255,248,0,122,0,190,255,248,0,122,0,196,255,234,0,122,0,198,255,198,0,122,0,199,255,223,0,122,0,200,255,233,0,122,0,210,255,204,0,122,0,213,255,204,0,126,0,34,255,233,0,126,0,35,255,247,0,126,0,37,255,247,0,126,0,38,255,247,0,126,0,39,255,247,0,126,0,41,255,247,0,126,0,42,255,247,0,126,0,43,0,19,0,126,0,44,255,247,0,126,0,45,255,247,0,126,0,46,255,238,0,126,0,47,255,247,0,126,0,49,255,247,0,126,0,51,255,247,0,126,0,53,255,192,0,126,0,54,255,245,0,126,0,55,255,233,0,126,0,56,255,241,0,126,0,57,255,231,0,126,0,58,255,219,0,126,0,59,255,220,0,126,0,66,255,241,0,126,0,67,255,247,0,126,0,68,255,243,0,126,0,69,255,243,0,126,0,70,255,243,0,126,0,72,255,243,0,126,0,73,255,247,0,126,0,74,255,242,0,126,0,75,0,20,0,126,0,76,255,247,0,126,0,77,255,247,0,126,0,78,255,241,0,126,0,79,255,241,0,126,0,80,255,243,0,126,0,81,255,241,0,126,0,82,255,243,0,126,0,83,255,241,0,126,0,84,255,241,0,126,0,86,255,243,0,126,0,89,255,248,0,126,0,91,255,241,0,126,0,127,255,233,0,126,0,128,255,233,0,126,0,129,255,233,0,126,0,130,255,233,0,126,0,131,255,233,0,126,0,132,255,233,0,126,0,133,255,235,0,126,0,135,255,247,0,126,0,136,255,247,0,126,0,137,255,247,0,126,0,138,255,247,0,126,0,139,255,247,0,126,0,140,255,247,0,126,0,141,255,247,0,126,0,142,255,247,0,126,0,143,255,247,0,126,0,144,255,247,0,126,0,152,255,245,0,126,0,153,255,245,0,126,0,154,255,245,0,126,0,155,255,245,0,126,0,156,255,219,0,126,0,157,255,247,0,126,0,159,255,241,0,126,0,160,255,241,0,126,0,161,255,241,0,126,0,162,255,241,0,126,0,163,255,241,0,126,0,164,255,241,0,126,0,165,255,241,0,126,0,166,255,243,0,126,0,167,255,243,0,126,0,168,255,243,0,126,0,169,255,243,0,126,0,170,255,243,0,126,0,171,255,242,0,126,0,172,255,242,0,126,0,173,255,242,0,126,0,174,255,242,0,126,0,175,255,240,0,126,0,176,255,241,0,126,0,177,255,243,0,126,0,178,255,243,0,126,0,179,255,243,0,126,0,180,255,243,0,126,0,181,255,243,0,126,0,183,255,243,0,126,0,184,255,243,0,126,0,185,255,243,0,126,0,186,255,243,0,126,0,187,255,243,0,126,0,189,255,241,0,126,0,193,255,242,0,126,0,195,255,243,0,126,0,197,255,241,0,126,0,198,255,219,0,126,0,199,255,220,0,126,0,200,255,241,0,127,0,3,255,213,0,127,0,8,255,213,0,127,0,11,255,212,0,127,0,18,255,239,0,127,0,26,255,242,0,127,0,32,255,239,0,127,0,36,255,245,0,127,0,40,255,245,0,127,0,48,255,245,0,127,0,50,255,245,0,127,0,53,255,202,0,127,0,54,255,240,0,127,0,55,255,207,0,127,0,56,255,219,0,127,0,58,255,192,0,127,0,61,255,208,0,127,0,68,255,245,0,127,0,69,255,245,0,127,0,70,255,245,0,127,0,71,255,241,0,127,0,72,255,248,0,127,0,77,255,249,0,127,0,80,255,245,0,127,0,82,255,245,0,127,0,85,255,229,0,127,0,86,255,244,0,127,0,87,255,221,0,127,0,88,255,228,0,127,0,90,255,217,0,127,0,94,255,246,0,127,0,107,255,247,0,127,0,110,255,241,0,127,0,134,255,245,0,127,0,145,255,245,0,127,0,146,255,245,0,127,0,147,255,245,0,127,0,148,255,245,0,127,0,149,255,245,0,127,0,151,255,245,0,127,0,152,255,240,0,127,0,153,255,240,0,127,0,154,255,240,0,127,0,155,255,240,0,127,0,156,255,192,0,127,0,158,255,242,0,127,0,166,255,245,0,127,0,167,255,245,0,127,0,168,255,245,0,127,0,169,255,245,0,127,0,170,255,245,0,127,0,175,255,250,0,127,0,177,255,245,0,127,0,178,255,245,0,127,0,179,255,245,0,127,0,180,255,245,0,127,0,181,255,245,0,127,0,183,255,245,0,127,0,184,255,244,0,127,0,185,255,244,0,127,0,186,255,244,0,127,0,187,255,244,0,127,0,188,255,217,0,127,0,190,255,217,0,127,0,194,255,245,0,127,0,195,255,245,0,127,0,198,255,192,0,127,0,209,255,205,0,127,0,210,255,204,0,127,0,212,255,205,0,127,0,213,255,204,0,127,0,220,255,247,0,127,0,240,255,212,0,128,0,3,255,213,0,128,0,8,255,213,0,128,0,11,255,212,0,128,0,18,255,239,0,128,0,26,255,242,0,128,0,32,255,239,0,128,0,36,255,245,0,128,0,40,255,245,0,128,0,48,255,245,0,128,0,50,255,245,0,128,0,53,255,202,0,128,0,54,255,240,0,128,0,55,255,207,0,128,0,56,255,219,0,128,0,58,255,192,0,128,0,61,255,208,0,128,0,68,255,245,0,128,0,69,255,245,0,128,0,70,255,245,0,128,0,71,255,241,0,128,0,72,255,248,0,128,0,77,255,249,0,128,0,80,255,245,0,128,0,82,255,245,0,128,0,85,255,229,0,128,0,86,255,244,0,128,0,87,255,221,0,128,0,88,255,228,0,128,0,90,255,217,0,128,0,94,255,246,0,128,0,107,255,247,0,128,0,110,255,241,0,128,0,134,255,245,0,128,0,145,255,245,0,128,0,146,255,245,0,128,0,147,255,245,0,128,0,148,255,245,0,128,0,149,255,245,0,128,0,151,255,245,0,128,0,152,255,240,0,128,0,153,255,240,0,128,0,154,255,240,0,128,0,155,255,240,0,128,0,156,255,192,0,128,0,158,255,242,0,128,0,166,255,245,0,128,0,167,255,245,0,128,0,168,255,245,0,128,0,169,255,245,0,128,0,170,255,245,0,128,0,175,255,250,0,128,0,177,255,245,0,128,0,178,255,245,0,128,0,179,255,245,0,128,0,180,255,245,0,128,0,181,255,245,0,128,0,183,255,245,0,128,0,184,255,244,0,128,0,185,255,244,0,128,0,186,255,244,0,128,0,187,255,244,0,128,0,188,255,217,0,128,0,190,255,217,0,128,0,194,255,245,0,128,0,195,255,245,0,128,0,198,255,192,0,128,0,209,255,205,0,128,0,210,255,204,0,128,0,212,255,205,0,128,0,213,255,204,0,128,0,220,255,247,0,128,0,240,255,212,0,129,0,3,255,213,0,129,0,8,255,213,0,129,0,11,255,212,0,129,0,18,255,239,0,129,0,26,255,242,0,129,0,32,255,239,0,129,0,36,255,245,0,129,0,40,255,245,0,129,0,48,255,245,0,129,0,50,255,245,0,129,0,53,255,202,0,129,0,54,255,240,0,129,0,55,255,207,0,129,0,56,255,219,0,129,0,58,255,192,0,129,0,61,255,208,0,129,0,68,255,245,0,129,0,69,255,245,0,129,0,70,255,245,0,129,0,71,255,241,0,129,0,72,255,248,0,129,0,77,255,249,0,129,0,80,255,245,0,129,0,82,255,245,0,129,0,85,255,229,0,129,0,86,255,244,0,129,0,87,255,221,0,129,0,88,255,228,0,129,0,90,255,217,0,129,0,94,255,246,0,129,0,107,255,247,0,129,0,110,255,241,0,129,0,134,255,245,0,129,0,145,255,245,0,129,0,146,255,245,0,129,0,147,255,245,0,129,0,148,255,245,0,129,0,149,255,245,0,129,0,151,255,245,0,129,0,152,255,240,0,129,0,153,255,240,0,129,0,154,255,240,0,129,0,155,255,240,0,129,0,156,255,192,0,129,0,158,255,242,0,129,0,166,255,245,0,129,0,167,255,245,0,129,0,168,255,245,0,129,0,169,255,245,0,129,0,170,255,245,0,129,0,175,255,250,0,129,0,177,255,245,0,129,0,178,255,245,0,129,0,179,255,245,0,129,0,180,255,245,0,129,0,181,255,245,0,129,0,183,255,245,0,129,0,184,255,244,0,129,0,185,255,244,0,129,0,186,255,244,0,129,0,187,255,244,0,129,0,188,255,217,0,129,0,190,255,217,0,129,0,194,255,245,0,129,0,195,255,245,0,129,0,198,255,192,0,129,0,209,255,205,0,129,0,210,255,204,0,129,0,212,255,205,0,129,0,213,255,204,0,129,0,220,255,247,0,129,0,240,255,212,0,130,0,3,255,213,0,130,0,8,255,213,0,130,0,11,255,212,0,130,0,18,255,239,0,130,0,26,255,242,0,130,0,32,255,239,0,130,0,36,255,245,0,130,0,40,255,245,0,130,0,48,255,245,0,130,0,50,255,245,0,130,0,53,255,202,0,130,0,54,255,240,0,130,0,55,255,207,0,130,0,56,255,219,0,130,0,58,255,192,0,130,0,61,255,208,0,130,0,68,255,245,0,130,0,69,255,245,0,130,0,70,255,245,0,130,0,71,255,241,0,130,0,72,255,248,0,130,0,77,255,249,0,130,0,80,255,245,0,130,0,82,255,245,0,130,0,85,255,229,0,130,0,86,255,244,0,130,0,87,255,221,0,130,0,88,255,228,0,130,0,90,255,217,0,130,0,94,255,246,0,130,0,107,255,247,0,130,0,110,255,241,0,130,0,134,255,245,0,130,0,145,255,245,0,130,0,146,255,245,0,130,0,147,255,245,0,130,0,148,255,245,0,130,0,149,255,245,0,130,0,151,255,245,0,130,0,152,255,240,0,130,0,153,255,240,0,130,0,154,255,240,0,130,0,155,255,240,0,130,0,156,255,192,0,130,0,158,255,242,0,130,0,166,255,245,0,130,0,167,255,245,0,130,0,168,255,245,0,130,0,169,255,245,0,130,0,170,255,245,0,130,0,175,255,250,0,130,0,177,255,245,0,130,0,178,255,245,0,130,0,179,255,245,0,130,0,180,255,245,0,130,0,181,255,245,0,130,0,183,255,245,0,130,0,184,255,244,0,130,0,185,255,244,0,130,0,186,255,244,0,130,0,187,255,244,0,130,0,188,255,217,0,130,0,190,255,217,0,130,0,194,255,245,0,130,0,195,255,245,0,130,0,198,255,192,0,130,0,209,255,205,0,130,0,210,255,204,0,130,0,212,255,205,0,130,0,213,255,204,0,130,0,220,255,247,0,130,0,240,255,212,0,131,0,3,255,213,0,131,0,8,255,213,0,131,0,11,255,212,0,131,0,18,255,239,0,131,0,26,255,242,0,131,0,32,255,239,0,131,0,36,255,245,0,131,0,40,255,245,0,131,0,48,255,245,0,131,0,50,255,245,0,131,0,53,255,202,0,131,0,54,255,240,0,131,0,55,255,207,0,131,0,56,255,219,0,131,0,58,255,192,0,131,0,61,255,208,0,131,0,68,255,245,0,131,0,69,255,245,0,131,0,70,255,245,0,131,0,71,255,241,0,131,0,72,255,248,0,131,0,77,255,249,0,131,0,80,255,245,0,131,0,82,255,245,0,131,0,85,255,229,0,131,0,86,255,244,0,131,0,87,255,221,0,131,0,88,255,228,0,131,0,90,255,217,0,131,0,94,255,246,0,131,0,107,255,247,0,131,0,110,255,241,0,131,0,134,255,245,0,131,0,145,255,245,0,131,0,146,255,245,0,131,0,147,255,245,0,131,0,148,255,245,0,131,0,149,255,245,0,131,0,151,255,245,0,131,0,152,255,240,0,131,0,153,255,240,0,131,0,154,255,240,0,131,0,155,255,240,0,131,0,156,255,192,0,131,0,158,255,242,0,131,0,166,255,245,0,131,0,167,255,245,0,131,0,168,255,245,0,131,0,169,255,245,0,131,0,170,255,245,0,131,0,175,255,250,0,131,0,177,255,245,0,131,0,178,255,245,0,131,0,179,255,245,0,131,0,180,255,245,0,131,0,181,255,245,0,131,0,183,255,245,0,131,0,184,255,244,0,131,0,185,255,244,0,131,0,186,255,244,0,131,0,187,255,244,0,131,0,188,255,217,0,131,0,190,255,217,0,131,0,194,255,245,0,131,0,195,255,245,0,131,0,198,255,192,0,131,0,209,255,205,0,131,0,210,255,204,0,131,0,212,255,205,0,131,0,213,255,204,0,131,0,220,255,247,0,131,0,240,255,212,0,132,0,3,255,213,0,132,0,8,255,213,0,132,0,11,255,212,0,132,0,18,255,239,0,132,0,26,255,242,0,132,0,32,255,239,0,132,0,36,255,245,0,132,0,40,255,245,0,132,0,48,255,245,0,132,0,50,255,245,0,132,0,53,255,202,0,132,0,54,255,240,0,132,0,55,255,207,0,132,0,56,255,219,0,132,0,58,255,192,0,132,0,61,255,208,0,132,0,68,255,245,0,132,0,69,255,245,0,132,0,70,255,245,0,132,0,71,255,241,0,132,0,72,255,248,0,132,0,77,255,249,0,132,0,80,255,245,0,132,0,82,255,245,0,132,0,85,255,229,0,132,0,86,255,244,0,132,0,87,255,221,0,132,0,88,255,228,0,132,0,90,255,217,0,132,0,94,255,246,0,132,0,107,255,247,0,132,0,110,255,241,0,132,0,134,255,245,0,132,0,145,255,245,0,132,0,146,255,245,0,132,0,147,255,245,0,132,0,148,255,245,0,132,0,149,255,245,0,132,0,151,255,245,0,132,0,152,255,240,0,132,0,153,255,240,0,132,0,154,255,240,0,132,0,155,255,240,0,132,0,156,255,192,0,132,0,158,255,242,0,132,0,166,255,245,0,132,0,167,255,245,0,132,0,168,255,245,0,132,0,169,255,245,0,132,0,170,255,245,0,132,0,175,255,250,0,132,0,177,255,245,0,132,0,178,255,245,0,132,0,179,255,245,0,132,0,180,255,245,0,132,0,181,255,245,0,132,0,183,255,245,0,132,0,184,255,244,0,132,0,185,255,244,0,132,0,186,255,244,0,132,0,187,255,244,0,132,0,188,255,217,0,132,0,190,255,217,0,132,0,194,255,245,0,132,0,195,255,245,0,132,0,198,255,192,0,132,0,209,255,205,0,132,0,210,255,204,0,132,0,212,255,205,0,132,0,213,255,204,0,132,0,220,255,247,0,132,0,240,255,212,0,133,0,14,255,244,0,133,0,21,255,220,0,133,0,36,255,245,0,133,0,40,255,245,0,133,0,48,255,245,0,133,0,50,255,245,0,133,0,68,255,240,0,133,0,69,255,240,0,133,0,70,255,240,0,133,0,71,255,243,0,133,0,72,255,241,0,133,0,78,255,247,0,133,0,79,255,247,0,133,0,80,255,240,0,133,0,81,255,247,0,133,0,82,255,240,0,133,0,83,255,247,0,133,0,84,255,251,0,133,0,85,255,242,0,133,0,86,255,238,0,133,0,87,255,241,0,133,0,88,255,243,0,133,0,90,255,240,0,133,0,107,255,235,0,133,0,110,255,248,0,133,0,134,255,245,0,133,0,145,255,245,0,133,0,146,255,245,0,133,0,147,255,245,0,133,0,148,255,245,0,133,0,149,255,245,0,133,0,151,255,245,0,133,0,158,255,243,0,133,0,166,255,240,0,133,0,167,255,240,0,133,0,168,255,240,0,133,0,169,255,240,0,133,0,170,255,240,0,133,0,173,0,21,0,133,0,175,255,246,0,133,0,176,255,247,0,133,0,177,255,240,0,133,0,178,255,240,0,133,0,179,255,240,0,133,0,180,255,240,0,133,0,181,255,240,0,133,0,183,255,240,0,133,0,184,255,238,0,133,0,185,255,238,0,133,0,186,255,238,0,133,0,187,255,238,0,133,0,188,255,240,0,133,0,189,255,247,0,133,0,190,255,240,0,133,0,194,255,245,0,133,0,195,255,240,0,133,0,197,255,251,0,133,0,207,255,244,0,133,0,208,255,244,0,133,0,220,255,235,0,134,0,14,255,195,0,134,0,21,255,207,0,134,0,36,255,242,0,134,0,40,255,242,0,134,0,48,255,242,0,134,0,50,255,242,0,134,0,68,255,242,0,134,0,69,255,242,0,134,0,70,255,242,0,134,0,71,255,249,0,134,0,72,255,241,0,134,0,78,255,249,0,134,0,79,255,249,0,134,0,80,255,242,0,134,0,81,255,249,0,134,0,82,255,242,0,134,0,83,255,249,0,134,0,85,255,249,0,134,0,86,255,241,0,134,0,87,255,249,0,134,0,88,255,250,0,134,0,90,255,249,0,134,0,107,255,226,0,134,0,134,255,242,0,134,0,145,255,242,0,134,0,146,255,242,0,134,0,147,255,242,0,134,0,148,255,242,0,134,0,149,255,242,0,134,0,151,255,242,0,134,0,158,255,250,0,134,0,166,255,242,0,134,0,167,255,242,0,134,0,168,255,242,0,134,0,169,255,242,0,134,0,170,255,242,0,134,0,173,0,31,0,134,0,174,0,12,0,134,0,175,255,249,0,134,0,176,255,249,0,134,0,177,255,242,0,134,0,178,255,242,0,134,0,179,255,242,0,134,0,180,255,242,0,134,0,181,255,242,0,134,0,183,255,242,0,134,0,184,255,241,0,134,0,185,255,241,0,134,0,186,255,241,0,134,0,187,255,241,0,134,0,188,255,249,0,134,0,189,255,249,0,134,0,190,255,249,0,134,0,194,255,242,0,134,0,195,255,242,0,134,0,207,255,195,0,134,0,208,255,195,0,134,0,220,255,226,0,135,0,14,255,244,0,135,0,21,255,220,0,135,0,36,255,245,0,135,0,40,255,245,0,135,0,48,255,245,0,135,0,50,255,245,0,135,0,68,255,240,0,135,0,69,255,240,0,135,0,70,255,240,0,135,0,71,255,243,0,135,0,72,255,241,0,135,0,78,255,247,0,135,0,79,255,247,0,135,0,80,255,240,0,135,0,81,255,247,0,135,0,82,255,240,0,135,0,83,255,247,0,135,0,84,255,251,0,135,0,85,255,242,0,135,0,86,255,238,0,135,0,87,255,241,0,135,0,88,255,243,0,135,0,90,255,240,0,135,0,107,255,235,0,135,0,110,255,248,0,135,0,134,255,245,0,135,0,145,255,245,0,135,0,146,255,245,0,135,0,147,255,245,0,135,0,148,255,245,0,135,0,149,255,245,0,135,0,151,255,245,0,135,0,158,255,243,0,135,0,166,255,240,0,135,0,167,255,240,0,135,0,168,255,240,0,135,0,169,255,240,0,135,0,170,255,240,0,135,0,173,0,21,0,135,0,175,255,246,0,135,0,176,255,247,0,135,0,177,255,240,0,135,0,178,255,240,0,135,0,179,255,240,0,135,0,180,255,240,0,135,0,181,255,240,0,135,0,183,255,240,0,135,0,184,255,238,0,135,0,185,255,238,0,135,0,186,255,238,0,135,0,187,255,238,0,135,0,188,255,240,0,135,0,189,255,247,0,135,0,190,255,240,0,135,0,194,255,245,0,135,0,195,255,240,0,135,0,197,255,251,0,135,0,207,255,244,0,135,0,208,255,244,0,135,0,220,255,235,0,136,0,14,255,244,0,136,0,21,255,220,0,136,0,36,255,245,0,136,0,40,255,245,0,136,0,48,255,245,0,136,0,50,255,245,0,136,0,68,255,240,0,136,0,69,255,240,0,136,0,70,255,240,0,136,0,71,255,243,0,136,0,72,255,241,0,136,0,78,255,247,0,136,0,79,255,247,0,136,0,80,255,240,0,136,0,81,255,247,0,136,0,82,255,240,0,136,0,83,255,247,0,136,0,84,255,251,0,136,0,85,255,242,0,136,0,86,255,238,0,136,0,87,255,241,0,136,0,88,255,243,0,136,0,90,255,240,0,136,0,107,255,235,0,136,0,110,255,248,0,136,0,134,255,245,0,136,0,145,255,245,0,136,0,146,255,245,0,136,0,147,255,245,0,136,0,148,255,245,0,136,0,149,255,245,0,136,0,151,255,245,0,136,0,158,255,243,0,136,0,166,255,240,0,136,0,167,255,240,0,136,0,168,255,240,0,136,0,169,255,240,0,136,0,170,255,240,0,136,0,173,0,21,0,136,0,175,255,246,0,136,0,176,255,247,0,136,0,177,255,240,0,136,0,178,255,240,0,136,0,179,255,240,0,136,0,180,255,240,0,136,0,181,255,240,0,136,0,183,255,240,0,136,0,184,255,238,0,136,0,185,255,238,0,136,0,186,255,238,0,136,0,187,255,238,0,136,0,188,255,240,0,136,0,189,255,247,0,136,0,190,255,240,0,136,0,194,255,245,0,136,0,195,255,240,0,136,0,197,255,251,0,136,0,207,255,244,0,136,0,208,255,244,0,136,0,220,255,235,0,137,0,14,255,244,0,137,0,21,255,220,0,137,0,36,255,245,0,137,0,40,255,245,0,137,0,48,255,245,0,137,0,50,255,245,0,137,0,68,255,240,0,137,0,69,255,240,0,137,0,70,255,240,0,137,0,71,255,243,0,137,0,72,255,241,0,137,0,78,255,247,0,137,0,79,255,247,0,137,0,80,255,240,0,137,0,81,255,247,0,137,0,82,255,240,0,137,0,83,255,247,0,137,0,84,255,251,0,137,0,85,255,242,0,137,0,86,255,238,0,137,0,87,255,241,0,137,0,88,255,243,0,137,0,90,255,240,0,137,0,107,255,235,0,137,0,110,255,248,0,137,0,134,255,245,0,137,0,145,255,245,0,137,0,146,255,245,0,137,0,147,255,245,0,137,0,148,255,245,0,137,0,149,255,245,0,137,0,151,255,245,0,137,0,158,255,243,0,137,0,166,255,240,0,137,0,167,255,240,0,137,0,168,255,240,0,137,0,169,255,240,0,137,0,170,255,240,0,137,0,173,0,21,0,137,0,175,255,246,0,137,0,176,255,247,0,137,0,177,255,240,0,137,0,178,255,240,0,137,0,179,255,240,0,137,0,180,255,240,0,137,0,181,255,240,0,137,0,183,255,240,0,137,0,184,255,238,0,137,0,185,255,238,0,137,0,186,255,238,0,137,0,187,255,238,0,137,0,188,255,240,0,137,0,189,255,247,0,137,0,190,255,240,0,137,0,194,255,245,0,137,0,195,255,240,0,137,0,197,255,251,0,137,0,207,255,244,0,137,0,208,255,244,0,137,0,220,255,235,0,138,0,14,255,244,0,138,0,21,255,220,0,138,0,36,255,245,0,138,0,40,255,245,0,138,0,48,255,245,0,138,0,50,255,245,0,138,0,68,255,240,0,138,0,69,255,240,0,138,0,70,255,240,0,138,0,71,255,243,0,138,0,72,255,241,0,138,0,78,255,247,0,138,0,79,255,247,0,138,0,80,255,240,0,138,0,81,255,247,0,138,0,82,255,240,0,138,0,83,255,247,0,138,0,84,255,251,0,138,0,85,255,242,0,138,0,86,255,238,0,138,0,87,255,241,0,138,0,88,255,243,0,138,0,90,255,240,0,138,0,107,255,235,0,138,0,110,255,248,0,138,0,134,255,245,0,138,0,145,255,245,0,138,0,146,255,245,0,138,0,147,255,245,0,138,0,148,255,245,0,138,0,149,255,245,0,138,0,151,255,245,0,138,0,158,255,243,0,138,0,166,255,240,0,138,0,167,255,240,0,138,0,168,255,240,0,138,0,169,255,240,0,138,0,170,255,240,0,138,0,173,0,21,0,138,0,175,255,246,0,138,0,176,255,247,0,138,0,177,255,240,0,138,0,178,255,240,0,138,0,179,255,240,0,138,0,180,255,240,0,138,0,181,255,240,0,138,0,183,255,240,0,138,0,184,255,238,0,138,0,185,255,238,0,138,0,186,255,238,0,138,0,187,255,238,0,138,0,188,255,240,0,138,0,189,255,247,0,138,0,190,255,240,0,138,0,194,255,245,0,138,0,195,255,240,0,138,0,197,255,251,0,138,0,207,255,244,0,138,0,208,255,244,0,138,0,220,255,235,0,139,0,10,255,246,0,139,0,46,255,251,0,139,0,66,255,246,0,139,0,67,255,247,0,139,0,68,255,242,0,139,0,69,255,242,0,139,0,70,255,242,0,139,0,71,255,247,0,139,0,72,255,241,0,139,0,73,255,247,0,139,0,74,255,247,0,139,0,75,255,247,0,139,0,76,255,247,0,139,0,77,255,246,0,139,0,78,255,247,0,139,0,79,255,247,0,139,0,80,255,242,0,139,0,81,255,247,0,139,0,82,255,242,0,139,0,83,255,247,0,139,0,84,255,246,0,139,0,85,255,247,0,139,0,86,255,245,0,139,0,87,255,247,0,139,0,88,255,248,0,139,0,90,255,247,0,139,0,91,255,246,0,139,0,158,255,244,0,139,0,159,255,246,0,139,0,160,255,246,0,139,0,161,255,246,0,139,0,162,255,246,0,139,0,163,255,246,0,139,0,164,255,246,0,139,0,165,255,246,0,139,0,166,255,242,0,139,0,167,255,242,0,139,0,168,255,242,0,139,0,169,255,242,0,139,0,170,255,242,0,139,0,171,255,247,0,139,0,172,255,247,0,139,0,173,255,247,0,139,0,174,255,247,0,139,0,175,255,243,0,139,0,176,255,247,0,139,0,177,255,242,0,139,0,178,255,242,0,139,0,179,255,242,0,139,0,180,255,242,0,139,0,181,255,242,0,139,0,183,255,242,0,139,0,184,255,245,0,139,0,185,255,245,0,139,0,186,255,245,0,139,0,187,255,245,0,139,0,188,255,247,0,139,0,189,255,247,0,139,0,190,255,247,0,139,0,193,255,247,0,139,0,195,255,242,0,139,0,197,255,246,0,139,0,200,255,246,0,140,0,10,255,246,0,140,0,46,255,251,0,140,0,66,255,246,0,140,0,67,255,247,0,140,0,68,255,242,0,140,0,69,255,242,0,140,0,70,255,242,0,140,0,71,255,247,0,140,0,72,255,241,0,140,0,73,255,247,0,140,0,74,255,247,0,140,0,75,255,247,0,140,0,76,255,247,0,140,0,77,255,246,0,140,0,78,255,247,0,140,0,79,255,247,0,140,0,80,255,242,0,140,0,81,255,247,0,140,0,82,255,242,0,140,0,83,255,247,0,140,0,84,255,246,0,140,0,85,255,247,0,140,0,86,255,245,0,140,0,87,255,247,0,140,0,88,255,248,0,140,0,90,255,247,0,140,0,91,255,246,0,140,0,158,255,244,0,140,0,159,255,246,0,140,0,160,255,246,0,140,0,161,255,246,0,140,0,162,255,246,0,140,0,163,255,246,0,140,0,164,255,246,0,140,0,165,255,246,0,140,0,166,255,242,0,140,0,167,255,242,0,140,0,168,255,242,0,140,0,169,255,242,0,140,0,170,255,242,0,140,0,171,255,247,0,140,0,172,255,247,0,140,0,173,255,247,0,140,0,174,255,247,0,140,0,175,255,243,0,140,0,176,255,247,0,140,0,177,255,242,0,140,0,178,255,242,0,140,0,179,255,242,0,140,0,180,255,242,0,140,0,181,255,242,0,140,0,183,255,242,0,140,0,184,255,245,0,140,0,185,255,245,0,140,0,186,255,245,0,140,0,187,255,245,0,140,0,188,255,247,0,140,0,189,255,247,0,140,0,190,255,247,0,140,0,193,255,247,0,140,0,195,255,242,0,140,0,197,255,246,0,140,0,200,255,246,0,141,0,10,255,246,0,141,0,46,255,251,0,141,0,66,255,246,0,141,0,67,255,247,0,141,0,68,255,242,0,141,0,69,255,242,0,141,0,70,255,242,0,141,0,71,255,247,0,141,0,72,255,241,0,141,0,73,255,247,0,141,0,74,255,247,0,141,0,75,255,247,0,141,0,76,255,247,0,141,0,77,255,246,0,141,0,78,255,247,0,141,0,79,255,247,0,141,0,80,255,242,0,141,0,81,255,247,0,141,0,82,255,242,0,141,0,83,255,247,0,141,0,84,255,246,0,141,0,85,255,247,0,141,0,86,255,245,0,141,0,87,255,247,0,141,0,88,255,248,0,141,0,90,255,247,0,141,0,91,255,246,0,141,0,158,255,244,0,141,0,159,255,246,0,141,0,160,255,246,0,141,0,161,255,246,0,141,0,162,255,246,0,141,0,163,255,246,0,141,0,164,255,246,0,141,0,165,255,246,0,141,0,166,255,242,0,141,0,167,255,242,0,141,0,168,255,242,0,141,0,169,255,242,0,141,0,170,255,242,0,141,0,171,255,247,0,141,0,172,255,247,0,141,0,173,255,247,0,141,0,174,255,247,0,141,0,175,255,243,0,141,0,176,255,247,0,141,0,177,255,242,0,141,0,178,255,242,0,141,0,179,255,242,0,141,0,180,255,242,0,141,0,181,255,242,0,141,0,183,255,242,0,141,0,184,255,245,0,141,0,185,255,245,0,141,0,186,255,245,0,141,0,187,255,245,0,141,0,188,255,247,0,141,0,189,255,247,0,141,0,190,255,247,0,141,0,193,255,247,0,141,0,195,255,242,0,141,0,197,255,246,0,141,0,200,255,246,0,142,0,10,255,246,0,142,0,46,255,251,0,142,0,66,255,246,0,142,0,67,255,247,0,142,0,68,255,242,0,142,0,69,255,242,0,142,0,70,255,242,0,142,0,71,255,247,0,142,0,72,255,241,0,142,0,73,255,247,0,142,0,74,255,247,0,142,0,75,255,247,0,142,0,76,255,247,0,142,0,77,255,246,0,142,0,78,255,247,0,142,0,79,255,247,0,142,0,80,255,242,0,142,0,81,255,247,0,142,0,82,255,242,0,142,0,83,255,247,0,142,0,84,255,246,0,142,0,85,255,247,0,142,0,86,255,245,0,142,0,87,255,247,0,142,0,88,255,248,0,142,0,90,255,247,0,142,0,91,255,246,0,142,0,158,255,244,0,142,0,159,255,246,0,142,0,160,255,246,0,142,0,161,255,246,0,142,0,162,255,246,0,142,0,163,255,246,0,142,0,164,255,246,0,142,0,165,255,246,0,142,0,166,255,242,0,142,0,167,255,242,0,142,0,168,255,242,0,142,0,169,255,242,0,142,0,170,255,242,0,142,0,171,255,247,0,142,0,172,255,247,0,142,0,173,255,247,0,142,0,174,255,247,0,142,0,175,255,243,0,142,0,176,255,247,0,142,0,177,255,242,0,142,0,178,255,242,0,142,0,179,255,242,0,142,0,180,255,242,0,142,0,181,255,242,0,142,0,183,255,242,0,142,0,184,255,245,0,142,0,185,255,245,0,142,0,186,255,245,0,142,0,187,255,245,0,142,0,188,255,247,0,142,0,189,255,247,0,142,0,190,255,247,0,142,0,193,255,247,0,142,0,195,255,242,0,142,0,197,255,246,0,142,0,200,255,246,0,143,0,10,255,228,0,143,0,13,255,241,0,143,0,15,255,242,0,143,0,16,255,237,0,143,0,20,255,248,0,143,0,24,255,240,0,143,0,32,255,237,0,143,0,34,255,244,0,143,0,46,255,250,0,143,0,53,255,228,0,143,0,55,255,243,0,143,0,56,255,248,0,143,0,57,255,225,0,143,0,58,255,227,0,143,0,59,255,235,0,143,0,61,255,244,0,143,0,62,255,224,0,143,0,66,255,248,0,143,0,67,255,249,0,143,0,68,255,250,0,143,0,69,255,250,0,143,0,70,255,250,0,143,0,72,255,250,0,143,0,73,255,249,0,143,0,74,255,249,0,143,0,75,255,249,0,143,0,76,255,249,0,143,0,77,255,249,0,143,0,78,255,249,0,143,0,79,255,249,0,143,0,80,255,250,0,143,0,81,255,249,0,143,0,82,255,250,0,143,0,83,255,249,0,143,0,84,255,250,0,143,0,86,255,250,0,143,0,89,255,244,0,143,0,91,255,250,0,143,0,94,255,229,0,143,0,127,255,244,0,143,0,128,255,244,0,143,0,129,255,244,0,143,0,130,255,244,0,143,0,131,255,244,0,143,0,132,255,244,0,143,0,133,255,226,0,143,0,156,255,227,0,143,0,158,255,250,0,143,0,159,255,248,0,143,0,160,255,248,0,143,0,161,255,248,0,143,0,162,255,248,0,143,0,163,255,248,0,143,0,164,255,248,0,143,0,165,255,248,0,143,0,166,255,250,0,143,0,167,255,250,0,143,0,168,255,250,0,143,0,169,255,250,0,143,0,170,255,250,0,143,0,171,255,249,0,143,0,172,255,249,0,143,0,173,255,249,0,143,0,174,255,249,0,143,0,175,255,249,0,143,0,176,255,249,0,143,0,177,255,250,0,143,0,178,255,250,0,143,0,179,255,250,0,143,0,180,255,250,0,143,0,181,255,250,0,143,0,183,255,250,0,143,0,184,255,250,0,143,0,185,255,250,0,143,0,186,255,250,0,143,0,187,255,250,0,143,0,189,255,249,0,143,0,193,255,249,0,143,0,195,255,250,0,143,0,197,255,250,0,143,0,198,255,227,0,143,0,199,255,235,0,143,0,200,255,250,0,143,0,210,255,247,0,143,0,211,255,241,0,143,0,213,255,247,0,143,0,214,255,241,0,143,0,218,255,242,0,143,0,240,255,246,0,144,0,10,255,246,0,144,0,46,255,251,0,144,0,66,255,246,0,144,0,67,255,247,0,144,0,68,255,242,0,144,0,69,255,242,0,144,0,70,255,242,0,144,0,71,255,247,0,144,0,72,255,241,0,144,0,73,255,247,0,144,0,74,255,247,0,144,0,75,255,247,0,144,0,76,255,247,0,144,0,77,255,246,0,144,0,78,255,247,0,144,0,79,255,247,0,144,0,80,255,242,0,144,0,81,255,247,0,144,0,82,255,242,0,144,0,83,255,247,0,144,0,84,255,246,0,144,0,85,255,247,0,144,0,86,255,245,0,144,0,87,255,247,0,144,0,88,255,248,0,144,0,90,255,247,0,144,0,91,255,246,0,144,0,158,255,244,0,144,0,159,255,246,0,144,0,160,255,246,0,144,0,161,255,246,0,144,0,162,255,246,0,144,0,163,255,246,0,144,0,164,255,246,0,144,0,165,255,246,0,144,0,166,255,242,0,144,0,167,255,242,0,144,0,168,255,242,0,144,0,169,255,242,0,144,0,170,255,242,0,144,0,171,255,247,0,144,0,172,255,247,0,144,0,173,255,247,0,144,0,174,255,247,0,144,0,175,255,243,0,144,0,176,255,247,0,144,0,177,255,242,0,144,0,178,255,242,0,144,0,179,255,242,0,144,0,180,255,242,0,144,0,181,255,242,0,144,0,183,255,242,0,144,0,184,255,245,0,144,0,185,255,245,0,144,0,186,255,245,0,144,0,187,255,245,0,144,0,188,255,247,0,144,0,189,255,247,0,144,0,190,255,247,0,144,0,193,255,247,0,144,0,195,255,242,0,144,0,197,255,246,0,144,0,200,255,246,0,145,0,10,255,229,0,145,0,13,255,242,0,145,0,15,255,242,0,145,0,16,255,239,0,145,0,24,255,243,0,145,0,32,255,240,0,145,0,34,255,245,0,145,0,46,255,251,0,145,0,53,255,232,0,145,0,55,255,244,0,145,0,56,255,248,0,145,0,57,255,229,0,145,0,58,255,230,0,145,0,59,255,238,0,145,0,61,255,245,0,145,0,62,255,227,0,145,0,66,255,247,0,145,0,67,255,250,0,145,0,68,255,250,0,145,0,69,255,250,0,145,0,70,255,250,0,145,0,72,255,250,0,145,0,73,255,250,0,145,0,74,255,249,0,145,0,75,255,249,0,145,0,76,255,250,0,145,0,77,255,250,0,145,0,78,255,249,0,145,0,79,255,249,0,145,0,80,255,250,0,145,0,81,255,249,0,145,0,82,255,250,0,145,0,83,255,249,0,145,0,84,255,250,0,145,0,86,255,251,0,145,0,89,255,245,0,145,0,91,255,250,0,145,0,94,255,231,0,145,0,127,255,245,0,145,0,128,255,245,0,145,0,129,255,245,0,145,0,130,255,245,0,145,0,131,255,245,0,145,0,132,255,245,0,145,0,133,255,229,0,145,0,156,255,230,0,145,0,158,255,251,0,145,0,159,255,247,0,145,0,160,255,247,0,145,0,161,255,247,0,145,0,162,255,247,0,145,0,163,255,247,0,145,0,164,255,247,0,145,0,165,255,247,0,145,0,166,255,250,0,145,0,167,255,250,0,145,0,168,255,250,0,145,0,169,255,250,0,145,0,170,255,250,0,145,0,171,255,249,0,145,0,172,255,249,0,145,0,173,255,249,0,145,0,174,255,249,0,145,0,175,255,250,0,145,0,176,255,249,0,145,0,177,255,250,0,145,0,178,255,250,0,145,0,179,255,250,0,145,0,180,255,250,0,145,0,181,255,250,0,145,0,183,255,250,0,145,0,184,255,251,0,145,0,185,255,251,0,145,0,186,255,251,0,145,0,187,255,251,0,145,0,189,255,249,0,145,0,193,255,249,0,145,0,195,255,250,0,145,0,197,255,250,0,145,0,198,255,230,0,145,0,199,255,238,0,145,0,200,255,250,0,145,0,210,255,247,0,145,0,211,255,242,0,145,0,213,255,247,0,145,0,214,255,242,0,145,0,218,255,242,0,145,0,240,255,246,0,146,0,10,255,229,0,146,0,13,255,242,0,146,0,15,255,242,0,146,0,16,255,239,0,146,0,24,255,243,0,146,0,32,255,240,0,146,0,34,255,245,0,146,0,46,255,251,0,146,0,53,255,232,0,146,0,55,255,244,0,146,0,56,255,248,0,146,0,57,255,229,0,146,0,58,255,230,0,146,0,59,255,238,0,146,0,61,255,245,0,146,0,62,255,227,0,146,0,66,255,247,0,146,0,67,255,250,0,146,0,68,255,250,0,146,0,69,255,250,0,146,0,70,255,250,0,146,0,72,255,250,0,146,0,73,255,250,0,146,0,74,255,249,0,146,0,75,255,249,0,146,0,76,255,250,0,146,0,77,255,250,0,146,0,78,255,249,0,146,0,79,255,249,0,146,0,80,255,250,0,146,0,81,255,249,0,146,0,82,255,250,0,146,0,83,255,249,0,146,0,84,255,250,0,146,0,86,255,251,0,146,0,89,255,245,0,146,0,91,255,250,0,146,0,94,255,231,0,146,0,127,255,245,0,146,0,128,255,245,0,146,0,129,255,245,0,146,0,130,255,245,0,146,0,131,255,245,0,146,0,132,255,245,0,146,0,133,255,229,0,146,0,156,255,230,0,146,0,158,255,251,0,146,0,159,255,247,0,146,0,160,255,247,0,146,0,161,255,247,0,146,0,162,255,247,0,146,0,163,255,247,0,146,0,164,255,247,0,146,0,165,255,247,0,146,0,166,255,250,0,146,0,167,255,250,0,146,0,168,255,250,0,146,0,169,255,250,0,146,0,170,255,250,0,146,0,171,255,249,0,146,0,172,255,249,0,146,0,173,255,249,0,146,0,174,255,249,0,146,0,175,255,250,0,146,0,176,255,249,0,146,0,177,255,250,0,146,0,178,255,250,0,146,0,179,255,250,0,146,0,180,255,250,0,146,0,181,255,250,0,146,0,183,255,250,0,146,0,184,255,251,0,146,0,185,255,251,0,146,0,186,255,251,0,146,0,187,255,251,0,146,0,189,255,249,0,146,0,193,255,249,0,146,0,195,255,250,0,146,0,197,255,250,0,146,0,198,255,230,0,146,0,199,255,238,0,146,0,200,255,250,0,146,0,210,255,247,0,146,0,211,255,242,0,146,0,213,255,247,0,146,0,214,255,242,0,146,0,218,255,242,0,146,0,240,255,246,0,147,0,10,255,229,0,147,0,13,255,242,0,147,0,15,255,242,0,147,0,16,255,239,0,147,0,24,255,243,0,147,0,32,255,240,0,147,0,34,255,245,0,147,0,46,255,251,0,147,0,53,255,232,0,147,0,55,255,244,0,147,0,56,255,248,0,147,0,57,255,229,0,147,0,58,255,230,0,147,0,59,255,238,0,147,0,61,255,245,0,147,0,62,255,227,0,147,0,66,255,247,0,147,0,67,255,250,0,147,0,68,255,250,0,147,0,69,255,250,0,147,0,70,255,250,0,147,0,72,255,250,0,147,0,73,255,250,0,147,0,74,255,249,0,147,0,75,255,249,0,147,0,76,255,250,0,147,0,77,255,250,0,147,0,78,255,249,0,147,0,79,255,249,0,147,0,80,255,250,0,147,0,81,255,249,0,147,0,82,255,250,0,147,0,83,255,249,0,147,0,84,255,250,0,147,0,86,255,251,0,147,0,89,255,245,0,147,0,91,255,250,0,147,0,94,255,231,0,147,0,127,255,245,0,147,0,128,255,245,0,147,0,129,255,245,0,147,0,130,255,245,0,147,0,131,255,245,0,147,0,132,255,245,0,147,0,133,255,229,0,147,0,156,255,230,0,147,0,158,255,251,0,147,0,159,255,247,0,147,0,160,255,247,0,147,0,161,255,247,0,147,0,162,255,247,0,147,0,163,255,247,0,147,0,164,255,247,0,147,0,165,255,247,0,147,0,166,255,250,0,147,0,167,255,250,0,147,0,168,255,250,0,147,0,169,255,250,0,147,0,170,255,250,0,147,0,171,255,249,0,147,0,172,255,249,0,147,0,173,255,249,0,147,0,174,255,249,0,147,0,175,255,250,0,147,0,176,255,249,0,147,0,177,255,250,0,147,0,178,255,250,0,147,0,179,255,250,0,147,0,180,255,250,0,147,0,181,255,250,0,147,0,183,255,250,0,147,0,184,255,251,0,147,0,185,255,251,0,147,0,186,255,251,0,147,0,187,255,251,0,147,0,189,255,249,0,147,0,193,255,249,0,147,0,195,255,250,0,147,0,197,255,250,0,147,0,198,255,230,0,147,0,199,255,238,0,147,0,200,255,250,0,147,0,210,255,247,0,147,0,211,255,242,0,147,0,213,255,247,0,147,0,214,255,242,0,147,0,218,255,242,0,147,0,240,255,246,0,148,0,10,255,229,0,148,0,13,255,242,0,148,0,15,255,242,0,148,0,16,255,239,0,148,0,24,255,243,0,148,0,32,255,240,0,148,0,34,255,245,0,148,0,46,255,251,0,148,0,53,255,232,0,148,0,55,255,244,0,148,0,56,255,248,0,148,0,57,255,229,0,148,0,58,255,230,0,148,0,59,255,238,0,148,0,61,255,245,0,148,0,62,255,227,0,148,0,66,255,247,0,148,0,67,255,250,0,148,0,68,255,250,0,148,0,69,255,250,0,148,0,70,255,250,0,148,0,72,255,250,0,148,0,73,255,250,0,148,0,74,255,249,0,148,0,75,255,249,0,148,0,76,255,250,0,148,0,77,255,250,0,148,0,78,255,249,0,148,0,79,255,249,0,148,0,80,255,250,0,148,0,81,255,249,0,148,0,82,255,250,0,148,0,83,255,249,0,148,0,84,255,250,0,148,0,86,255,251,0,148,0,89,255,245,0,148,0,91,255,250,0,148,0,94,255,231,0,148,0,127,255,245,0,148,0,128,255,245,0,148,0,129,255,245,0,148,0,130,255,245,0,148,0,131,255,245,0,148,0,132,255,245,0,148,0,133,255,229,0,148,0,156,255,230,0,148,0,158,255,251,0,148,0,159,255,247,0,148,0,160,255,247,0,148,0,161,255,247,0,148,0,162,255,247,0,148,0,163,255,247,0,148,0,164,255,247,0,148,0,165,255,247,0,148,0,166,255,250,0,148,0,167,255,250,0,148,0,168,255,250,0,148,0,169,255,250,0,148,0,170,255,250,0,148,0,171,255,249,0,148,0,172,255,249,0,148,0,173,255,249,0,148,0,174,255,249,0,148,0,175,255,250,0,148,0,176,255,249,0,148,0,177,255,250,0,148,0,178,255,250,0,148,0,179,255,250,0,148,0,180,255,250,0,148,0,181,255,250,0,148,0,183,255,250,0,148,0,184,255,251,0,148,0,185,255,251,0,148,0,186,255,251,0,148,0,187,255,251,0,148,0,189,255,249,0,148,0,193,255,249,0,148,0,195,255,250,0,148,0,197,255,250,0,148,0,198,255,230,0,148,0,199,255,238,0,148,0,200,255,250,0,148,0,210,255,247,0,148,0,211,255,242,0,148,0,213,255,247,0,148,0,214,255,242,0,148,0,218,255,242,0,148,0,240,255,246,0,149,0,10,255,229,0,149,0,13,255,242,0,149,0,15,255,242,0,149,0,16,255,239,0,149,0,24,255,243,0,149,0,32,255,240,0,149,0,34,255,245,0,149,0,46,255,251,0,149,0,53,255,232,0,149,0,55,255,244,0,149,0,56,255,248,0,149,0,57,255,229,0,149,0,58,255,230,0,149,0,59,255,238,0,149,0,61,255,245,0,149,0,62,255,227,0,149,0,66,255,247,0,149,0,67,255,250,0,149,0,68,255,250,0,149,0,69,255,250,0,149,0,70,255,250,0,149,0,72,255,250,0,149,0,73,255,250,0,149,0,74,255,249,0,149,0,75,255,249,0,149,0,76,255,250,0,149,0,77,255,250,0,149,0,78,255,249,0,149,0,79,255,249,0,149,0,80,255,250,0,149,0,81,255,249,0,149,0,82,255,250,0,149,0,83,255,249,0,149,0,84,255,250,0,149,0,86,255,251,0,149,0,89,255,245,0,149,0,91,255,250,0,149,0,94,255,231,0,149,0,127,255,245,0,149,0,128,255,245,0,149,0,129,255,245,0,149,0,130,255,245,0,149,0,131,255,245,0,149,0,132,255,245,0,149,0,133,255,229,0,149,0,156,255,230,0,149,0,158,255,251,0,149,0,159,255,247,0,149,0,160,255,247,0,149,0,161,255,247,0,149,0,162,255,247,0,149,0,163,255,247,0,149,0,164,255,247,0,149,0,165,255,247,0,149,0,166,255,250,0,149,0,167,255,250,0,149,0,168,255,250,0,149,0,169,255,250,0,149,0,170,255,250,0,149,0,171,255,249,0,149,0,172,255,249,0,149,0,173,255,249,0,149,0,174,255,249,0,149,0,175,255,250,0,149,0,176,255,249,0,149,0,177,255,250,0,149,0,178,255,250,0,149,0,179,255,250,0,149,0,180,255,250,0,149,0,181,255,250,0,149,0,183,255,250,0,149,0,184,255,251,0,149,0,185,255,251,0,149,0,186,255,251,0,149,0,187,255,251,0,149,0,189,255,249,0,149,0,193,255,249,0,149,0,195,255,250,0,149,0,197,255,250,0,149,0,198,255,230,0,149,0,199,255,238,0,149,0,200,255,250,0,149,0,210,255,247,0,149,0,211,255,242,0,149,0,213,255,247,0,149,0,214,255,242,0,149,0,218,255,242,0,149,0,240,255,246,0,151,0,10,255,229,0,151,0,13,255,242,0,151,0,15,255,242,0,151,0,16,255,239,0,151,0,24,255,243,0,151,0,32,255,240,0,151,0,34,255,245,0,151,0,46,255,251,0,151,0,53,255,232,0,151,0,55,255,244,0,151,0,56,255,248,0,151,0,57,255,229,0,151,0,58,255,230,0,151,0,59,255,238,0,151,0,61,255,245,0,151,0,62,255,227,0,151,0,66,255,247,0,151,0,67,255,250,0,151,0,68,255,250,0,151,0,69,255,250,0,151,0,70,255,250,0,151,0,72,255,250,0,151,0,73,255,250,0,151,0,74,255,249,0,151,0,75,255,249,0,151,0,76,255,250,0,151,0,77,255,250,0,151,0,78,255,249,0,151,0,79,255,249,0,151,0,80,255,250,0,151,0,81,255,249,0,151,0,82,255,250,0,151,0,83,255,249,0,151,0,84,255,250,0,151,0,86,255,251,0,151,0,89,255,245,0,151,0,91,255,250,0,151,0,94,255,231,0,151,0,127,255,245,0,151,0,128,255,245,0,151,0,129,255,245,0,151,0,130,255,245,0,151,0,131,255,245,0,151,0,132,255,245,0,151,0,133,255,229,0,151,0,156,255,230,0,151,0,158,255,251,0,151,0,159,255,247,0,151,0,160,255,247,0,151,0,161,255,247,0,151,0,162,255,247,0,151,0,163,255,247,0,151,0,164,255,247,0,151,0,165,255,247,0,151,0,166,255,250,0,151,0,167,255,250,0,151,0,168,255,250,0,151,0,169,255,250,0,151,0,170,255,250,0,151,0,171,255,249,0,151,0,172,255,249,0,151,0,173,255,249,0,151,0,174,255,249,0,151,0,175,255,250,0,151,0,176,255,249,0,151,0,177,255,250,0,151,0,178,255,250,0,151,0,179,255,250,0,151,0,180,255,250,0,151,0,181,255,250,0,151,0,183,255,250,0,151,0,184,255,251,0,151,0,185,255,251,0,151,0,186,255,251,0,151,0,187,255,251,0,151,0,189,255,249,0,151,0,193,255,249,0,151,0,195,255,250,0,151,0,197,255,250,0,151,0,198,255,230,0,151,0,199,255,238,0,151,0,200,255,250,0,151,0,210,255,247,0,151,0,211,255,242,0,151,0,213,255,247,0,151,0,214,255,242,0,151,0,218,255,242,0,151,0,240,255,246,0,152,0,10,255,245,0,152,0,13,255,243,0,152,0,15,255,243,0,152,0,16,255,234,0,152,0,34,255,240,0,152,0,46,255,248,0,152,0,59,255,251,0,152,0,66,255,242,0,152,0,67,255,245,0,152,0,68,255,243,0,152,0,69,255,243,0,152,0,70,255,243,0,152,0,71,255,250,0,152,0,72,255,242,0,152,0,73,255,245,0,152,0,74,255,243,0,152,0,75,255,243,0,152,0,76,255,245,0,152,0,77,255,244,0,152,0,78,255,240,0,152,0,79,255,240,0,152,0,80,255,243,0,152,0,81,255,240,0,152,0,82,255,243,0,152,0,83,255,240,0,152,0,84,255,243,0,152,0,85,255,249,0,152,0,86,255,242,0,152,0,87,255,250,0,152,0,88,255,250,0,152,0,89,255,250,0,152,0,90,255,250,0,152,0,91,255,244,0,152,0,127,255,240,0,152,0,128,255,240,0,152,0,129,255,240,0,152,0,130,255,240,0,152,0,131,255,240,0,152,0,132,255,240,0,152,0,133,255,240,0,152,0,158,255,248,0,152,0,159,255,242,0,152,0,160,255,242,0,152,0,161,255,242,0,152,0,162,255,242,0,152,0,163,255,242,0,152,0,164,255,242,0,152,0,165,255,242,0,152,0,166,255,243,0,152,0,167,255,243,0,152,0,168,255,243,0,152,0,169,255,243,0,152,0,170,255,243,0,152,0,171,255,243,0,152,0,172,255,243,0,152,0,173,255,251,0,152,0,174,255,243,0,152,0,175,255,242,0,152,0,176,255,240,0,152,0,177,255,243,0,152,0,178,255,243,0,152,0,179,255,243,0,152,0,180,255,243,0,152,0,181,255,243,0,152,0,183,255,243,0,152,0,184,255,242,0,152,0,185,255,242,0,152,0,186,255,242,0,152,0,187,255,242,0,152,0,188,255,250,0,152,0,189,255,240,0,152,0,190,255,250,0,152,0,193,255,243,0,152,0,195,255,243,0,152,0,197,255,243,0,152,0,199,255,251,0,152,0,200,255,244,0,152,0,211,255,243,0,152,0,214,255,243,0,152,0,218,255,243,0,153,0,10,255,245,0,153,0,13,255,243,0,153,0,15,255,243,0,153,0,16,255,234,0,153,0,34,255,240,0,153,0,46,255,248,0,153,0,59,255,251,0,153,0,66,255,242,0,153,0,67,255,245,0,153,0,68,255,243,0,153,0,69,255,243,0,153,0,70,255,243,0,153,0,71,255,250,0,153,0,72,255,242,0,153,0,73,255,245,0,153,0,74,255,243,0,153,0,75,255,243,0,153,0,76,255,245,0,153,0,77,255,244,0,153,0,78,255,240,0,153,0,79,255,240,0,153,0,80,255,243,0,153,0,81,255,240,0,153,0,82,255,243,0,153,0,83,255,240,0,153,0,84,255,243,0,153,0,85,255,249,0,153,0,86,255,242,0,153,0,87,255,250,0,153,0,88,255,250,0,153,0,89,255,250,0,153,0,90,255,250,0,153,0,91,255,244,0,153,0,127,255,240,0,153,0,128,255,240,0,153,0,129,255,240,0,153,0,130,255,240,0,153,0,131,255,240,0,153,0,132,255,240,0,153,0,133,255,240,0,153,0,158,255,248,0,153,0,159,255,242,0,153,0,160,255,242,0,153,0,161,255,242,0,153,0,162,255,242,0,153,0,163,255,242,0,153,0,164,255,242,0,153,0,165,255,242,0,153,0,166,255,243,0,153,0,167,255,243,0,153,0,168,255,243,0,153,0,169,255,243,0,153,0,170,255,243,0,153,0,171,255,243,0,153,0,172,255,243,0,153,0,173,255,251,0,153,0,174,255,243,0,153,0,175,255,242,0,153,0,176,255,240,0,153,0,177,255,243,0,153,0,178,255,243,0,153,0,179,255,243,0,153,0,180,255,243,0,153,0,181,255,243,0,153,0,183,255,243,0,153,0,184,255,242,0,153,0,185,255,242,0,153,0,186,255,242,0,153,0,187,255,242,0,153,0,188,255,250,0,153,0,189,255,240,0,153,0,190,255,250,0,153,0,193,255,243,0,153,0,195,255,243,0,153,0,197,255,243,0,153,0,199,255,251,0,153,0,200,255,244,0,153,0,211,255,243,0,153,0,214,255,243,0,153,0,218,255,243,0,154,0,10,255,245,0,154,0,13,255,243,0,154,0,15,255,243,0,154,0,16,255,234,0,154,0,34,255,240,0,154,0,46,255,248,0,154,0,59,255,251,0,154,0,66,255,242,0,154,0,67,255,245,0,154,0,68,255,243,0,154,0,69,255,243,0,154,0,70,255,243,0,154,0,71,255,250,0,154,0,72,255,242,0,154,0,73,255,245,0,154,0,74,255,243,0,154,0,75,255,243,0,154,0,76,255,245,0,154,0,77,255,244,0,154,0,78,255,240,0,154,0,79,255,240,0,154,0,80,255,243,0,154,0,81,255,240,0,154,0,82,255,243,0,154,0,83,255,240,0,154,0,84,255,243,0,154,0,85,255,249,0,154,0,86,255,242,0,154,0,87,255,250,0,154,0,88,255,250,0,154,0,89,255,250,0,154,0,90,255,250,0,154,0,91,255,244,0,154,0,127,255,240,0,154,0,128,255,240,0,154,0,129,255,240,0,154,0,130,255,240,0,154,0,131,255,240,0,154,0,132,255,240,0,154,0,133,255,240,0,154,0,158,255,248,0,154,0,159,255,242,0,154,0,160,255,242,0,154,0,161,255,242,0,154,0,162,255,242,0,154,0,163,255,242,0,154,0,164,255,242,0,154,0,165,255,242,0,154,0,166,255,243,0,154,0,167,255,243,0,154,0,168,255,243,0,154,0,169,255,243,0,154,0,170,255,243,0,154,0,171,255,243,0,154,0,172,255,243,0,154,0,173,255,251,0,154,0,174,255,243,0,154,0,175,255,242,0,154,0,176,255,240,0,154,0,177,255,243,0,154,0,178,255,243,0,154,0,179,255,243,0,154,0,180,255,243,0,154,0,181,255,243,0,154,0,183,255,243,0,154,0,184,255,242,0,154,0,185,255,242,0,154,0,186,255,242,0,154,0,187,255,242,0,154,0,188,255,250,0,154,0,189,255,240,0,154,0,190,255,250,0,154,0,193,255,243,0,154,0,195,255,243,0,154,0,197,255,243,0,154,0,199,255,251,0,154,0,200,255,244,0,154,0,211,255,243,0,154,0,214,255,243,0,154,0,218,255,243,0,155,0,10,255,245,0,155,0,13,255,243,0,155,0,15,255,243,0,155,0,16,255,234,0,155,0,34,255,240,0,155,0,46,255,248,0,155,0,59,255,251,0,155,0,66,255,242,0,155,0,67,255,245,0,155,0,68,255,243,0,155,0,69,255,243,0,155,0,70,255,243,0,155,0,71,255,250,0,155,0,72,255,242,0,155,0,73,255,245,0,155,0,74,255,243,0,155,0,75,255,243,0,155,0,76,255,245,0,155,0,77,255,244,0,155,0,78,255,240,0,155,0,79,255,240,0,155,0,80,255,243,0,155,0,81,255,240,0,155,0,82,255,243,0,155,0,83,255,240,0,155,0,84,255,243,0,155,0,85,255,249,0,155,0,86,255,242,0,155,0,87,255,250,0,155,0,88,255,250,0,155,0,89,255,250,0,155,0,90,255,250,0,155,0,91,255,244,0,155,0,127,255,240,0,155,0,128,255,240,0,155,0,129,255,240,0,155,0,130,255,240,0,155,0,131,255,240,0,155,0,132,255,240,0,155,0,133,255,240,0,155,0,158,255,248,0,155,0,159,255,242,0,155,0,160,255,242,0,155,0,161,255,242,0,155,0,162,255,242,0,155,0,163,255,242,0,155,0,164,255,242,0,155,0,165,255,242,0,155,0,166,255,243,0,155,0,167,255,243,0,155,0,168,255,243,0,155,0,169,255,243,0,155,0,170,255,243,0,155,0,171,255,243,0,155,0,172,255,243,0,155,0,173,255,251,0,155,0,174,255,243,0,155,0,175,255,242,0,155,0,176,255,240,0,155,0,177,255,243,0,155,0,178,255,243,0,155,0,179,255,243,0,155,0,180,255,243,0,155,0,181,255,243,0,155,0,183,255,243,0,155,0,184,255,242,0,155,0,185,255,242,0,155,0,186,255,242,0,155,0,187,255,242,0,155,0,188,255,250,0,155,0,189,255,240,0,155,0,190,255,250,0,155,0,193,255,243,0,155,0,195,255,243,0,155,0,197,255,243,0,155,0,199,255,251,0,155,0,200,255,244,0,155,0,211,255,243,0,155,0,214,255,243,0,155,0,218,255,243,0,156,0,7,255,237,0,156,0,11,0,13,0,156,0,13,255,215,0,156,0,14,255,222,0,156,0,15,255,215,0,156,0,16,255,201,0,156,0,17,255,233,0,156,0,21,255,206,0,156,0,23,255,218,0,156,0,25,255,246,0,156,0,27,255,235,0,156,0,28,255,235,0,156,0,32,0,13,0,156,0,33,255,198,0,156,0,34,255,192,0,156,0,36,255,230,0,156,0,40,255,230,0,156,0,46,255,232,0,156,0,48,255,230,0,156,0,50,255,230,0,156,0,61,0,7,0,156,0,62,0,31,0,156,0,66,255,189,0,156,0,68,255,171,0,156,0,69,255,171,0,156,0,70,255,171,0,156,0,71,255,237,0,156,0,72,255,180,0,156,0,78,255,187,0,156,0,79,255,187,0,156,0,80,255,171,0,156,0,81,255,187,0,156,0,82,255,171,0,156,0,83,255,187,0,156,0,84,255,186,0,156,0,85,255,221,0,156,0,86,255,190,0,156,0,87,255,215,0,156,0,88,255,216,0,156,0,89,255,214,0,156,0,90,255,217,0,156,0,91,255,229,0,156,0,94,0,33,0,156,0,107,255,198,0,156,0,110,255,230,0,156,0,122,255,225,0,156,0,127,255,192,0,156,0,128,255,192,0,156,0,129,255,192,0,156,0,130,255,192,0,156,0,131,255,192,0,156,0,132,255,192,0,156,0,133,255,180,0,156,0,134,255,230,0,156,0,145,255,230,0,156,0,146,255,230,0,156,0,147,255,230,0,156,0,148,255,230,0,156,0,149,255,230,0,156,0,151,255,230,0,156,0,158,255,230,0,156,0,159,255,189,0,156,0,160,255,189,0,156,0,161,255,189,0,156,0,162,255,189,0,156,0,163,255,189,0,156,0,164,255,189,0,156,0,165,255,189,0,156,0,166,255,171,0,156,0,167,255,171,0,156,0,168,255,171,0,156,0,169,255,171,0,156,0,170,255,171,0,156,0,171,0,16,0,156,0,173,0,38,0,156,0,174,0,47,0,156,0,175,255,216,0,156,0,176,255,187,0,156,0,177,255,171,0,156,0,178,255,171,0,156,0,179,255,171,0,156,0,180,255,171,0,156,0,181,255,171,0,156,0,183,255,171,0,156,0,184,255,190,0,156,0,185,255,190,0,156,0,186,255,190,0,156,0,187,255,190,0,156,0,188,255,217,0,156,0,189,255,225,0,156,0,190,255,217,0,156,0,194,255,230,0,156,0,195,255,171,0,156,0,197,255,234,0,156,0,200,255,229,0,156,0,207,255,222,0,156,0,208,255,222,0,156,0,211,255,215,0,156,0,214,255,215,0,156,0,218,255,215,0,156,0,220,255,198,0,156,0,221,255,225,0,156,0,240,0,33,0,157,0,10,255,228,0,157,0,13,255,177,0,157,0,15,255,177,0,157,0,16,255,221,0,157,0,32,255,223,0,157,0,34,255,235,0,157,0,46,255,251,0,157,0,53,255,202,0,157,0,55,255,248,0,157,0,57,255,205,0,157,0,58,255,228,0,157,0,59,255,203,0,157,0,61,255,247,0,157,0,62,255,214,0,157,0,66,255,247,0,157,0,89,255,250,0,157,0,94,255,226,0,157,0,127,255,235,0,157,0,128,255,235,0,157,0,129,255,235,0,157,0,130,255,235,0,157,0,131,255,235,0,157,0,132,255,235,0,157,0,133,255,201,0,157,0,156,255,228,0,157,0,159,255,247,0,157,0,160,255,247,0,157,0,161,255,247,0,157,0,162,255,247,0,157,0,163,255,247,0,157,0,164,255,247,0,157,0,165,255,247,0,157,0,198,255,228,0,157,0,199,255,203,0,157,0,211,255,177,0,157,0,214,255,177,0,157,0,218,255,177,0,158,0,3,255,243,0,158,0,8,255,243,0,158,0,10,255,239,0,158,0,11,255,241,0,158,0,71,255,250,0,158,0,85,255,247,0,158,0,87,255,245,0,158,0,88,255,248,0,158,0,89,255,251,0,158,0,90,255,245,0,158,0,188,255,245,0,158,0,190,255,245,0,158,0,209,255,245,0,158,0,210,255,243,0,158,0,212,255,245,0,158,0,213,255,243,0,158,0,240,255,242,0,159,0,3,255,234,0,159,0,7,255,245,0,159,0,8,255,234,0,159,0,10,255,246,0,159,0,11,255,231,0,159,0,18,255,234,0,159,0,26,255,247,0,159,0,32,255,229,0,159,0,35,255,240,0,159,0,36,255,237,0,159,0,37,255,240,0,159,0,38,255,240,0,159,0,39,255,240,0,159,0,40,255,237,0,159,0,41,255,240,0,159,0,42,255,240,0,159,0,43,255,240,0,159,0,44,255,240,0,159,0,45,255,240,0,159,0,46,255,248,0,159,0,47,255,240,0,159,0,48,255,237,0,159,0,49,255,240,0,159,0,50,255,237,0,159,0,51,255,240,0,159,0,52,255,250,0,159,0,53,255,173,0,159,0,54,255,227,0,159,0,55,255,193,0,159,0,56,255,210,0,159,0,58,255,165,0,159,0,61,255,210,0,159,0,62,255,227,0,159,0,71,255,251,0,159,0,85,255,246,0,159,0,87,255,238,0,159,0,88,255,243,0,159,0,90,255,236,0,159,0,94,255,231,0,159,0,110,255,248,0,159,0,134,255,237,0,159,0,135,255,240,0,159,0,136,255,240,0,159,0,137,255,240,0,159,0,138,255,240,0,159,0,139,255,240,0,159,0,140,255,240,0,159,0,141,255,240,0,159,0,142,255,240,0,159,0,143,255,240,0,159,0,144,255,240,0,159,0,145,255,237,0,159,0,146,255,237,0,159,0,147,255,237,0,159,0,148,255,237,0,159,0,149,255,237,0,159,0,151,255,237,0,159,0,152,255,227,0,159,0,153,255,227,0,159,0,154,255,227,0,159,0,155,255,227,0,159,0,156,255,165,0,159,0,157,255,240,0,159,0,158,255,249,0,159,0,188,255,236,0,159,0,190,255,236,0,159,0,194,255,237,0,159,0,196,255,250,0,159,0,198,255,165,0,159,0,209,255,186,0,159,0,210,255,183,0,159,0,212,255,186,0,159,0,213,255,183,0,159,0,240,255,230,0,160,0,3,255,234,0,160,0,7,255,245,0,160,0,8,255,234,0,160,0,10,255,246,0,160,0,11,255,231,0,160,0,18,255,234,0,160,0,26,255,247,0,160,0,32,255,229,0,160,0,35,255,240,0,160,0,36,255,237,0,160,0,37,255,240,0,160,0,38,255,240,0,160,0,39,255,240,0,160,0,40,255,237,0,160,0,41,255,240,0,160,0,42,255,240,0,160,0,43,255,240,0,160,0,44,255,240,0,160,0,45,255,240,0,160,0,46,255,248,0,160,0,47,255,240,0,160,0,48,255,237,0,160,0,49,255,240,0,160,0,50,255,237,0,160,0,51,255,240,0,160,0,52,255,250,0,160,0,53,255,173,0,160,0,54,255,227,0,160,0,55,255,193,0,160,0,56,255,210,0,160,0,58,255,165,0,160,0,61,255,210,0,160,0,62,255,227,0,160,0,71,255,251,0,160,0,85,255,246,0,160,0,87,255,238,0,160,0,88,255,243,0,160,0,90,255,236,0,160,0,94,255,231,0,160,0,110,255,248,0,160,0,134,255,237,0,160,0,135,255,240,0,160,0,136,255,240,0,160,0,137,255,240,0,160,0,138,255,240,0,160,0,139,255,240,0,160,0,140,255,240,0,160,0,141,255,240,0,160,0,142,255,240,0,160,0,143,255,240,0,160,0,144,255,240,0,160,0,145,255,237,0,160,0,146,255,237,0,160,0,147,255,237,0,160,0,148,255,237,0,160,0,149,255,237,0,160,0,151,255,237,0,160,0,152,255,227,0,160,0,153,255,227,0,160,0,154,255,227,0,160,0,155,255,227,0,160,0,156,255,165,0,160,0,157,255,240,0,160,0,158,255,249,0,160,0,188,255,236,0,160,0,190,255,236,0,160,0,194,255,237,0,160,0,196,255,250,0,160,0,198,255,165,0,160,0,209,255,186,0,160,0,210,255,183,0,160,0,212,255,186,0,160,0,213,255,183,0,160,0,240,255,230,0,161,0,3,255,234,0,161,0,7,255,245,0,161,0,8,255,234,0,161,0,10,255,246,0,161,0,11,255,231,0,161,0,18,255,234,0,161,0,26,255,247,0,161,0,32,255,229,0,161,0,35,255,240,0,161,0,36,255,237,0,161,0,37,255,240,0,161,0,38,255,240,0,161,0,39,255,240,0,161,0,40,255,237,0,161,0,41,255,240,0,161,0,42,255,240,0,161,0,43,255,240,0,161,0,44,255,240,0,161,0,45,255,240,0,161,0,46,255,248,0,161,0,47,255,240,0,161,0,48,255,237,0,161,0,49,255,240,0,161,0,50,255,237,0,161,0,51,255,240,0,161,0,52,255,250,0,161,0,53,255,173,0,161,0,54,255,227,0,161,0,55,255,193,0,161,0,56,255,210,0,161,0,58,255,165,0,161,0,61,255,210,0,161,0,62,255,246,0,161,0,71,255,251,0,161,0,85,255,246,0,161,0,87,255,238,0,161,0,88,255,243,0,161,0,90,255,236,0,161,0,94,255,248,0,161,0,110,255,248,0,161,0,134,255,237,0,161,0,135,255,240,0,161,0,136,255,240,0,161,0,137,255,240,0,161,0,138,255,240,0,161,0,139,255,240,0,161,0,140,255,240,0,161,0,141,255,240,0,161,0,142,255,240,0,161,0,143,255,240,0,161,0,144,255,240,0,161,0,145,255,237,0,161,0,146,255,237,0,161,0,147,255,237,0,161,0,148,255,237,0,161,0,149,255,237,0,161,0,151,255,237,0,161,0,152,255,227,0,161,0,153,255,227,0,161,0,154,255,227,0,161,0,155,255,227,0,161,0,156,255,165,0,161,0,157,255,240,0,161,0,158,255,249,0,161,0,188,255,236,0,161,0,190,255,236,0,161,0,194,255,237,0,161,0,196,255,250,0,161,0,198,255,165,0,161,0,209,255,186,0,161,0,210,255,183,0,161,0,212,255,186,0,161,0,213,255,183,0,161,0,240,255,230,0,162,0,3,255,234,0,162,0,7,255,245,0,162,0,8,255,234,0,162,0,10,255,246,0,162,0,11,255,231,0,162,0,18,255,234,0,162,0,26,255,247,0,162,0,32,255,229,0,162,0,35,255,240,0,162,0,36,255,237,0,162,0,37,255,240,0,162,0,38,255,240,0,162,0,39,255,240,0,162,0,40,255,237,0,162,0,41,255,240,0,162,0,42,255,240,0,162,0,43,255,240,0,162,0,44,255,240,0,162,0,45,255,240,0,162,0,46,255,248,0,162,0,47,255,240,0,162,0,48,255,237,0,162,0,49,255,240,0,162,0,50,255,237,0,162,0,51,255,240,0,162,0,52,255,250,0,162,0,53,255,173,0,162,0,54,255,227,0,162,0,55,255,193,0,162,0,56,255,210,0,162,0,58,255,165,0,162,0,61,255,220,0,162,0,62,255,227,0,162,0,71,255,251,0,162,0,85,255,246,0,162,0,87,255,238,0,162,0,88,255,243,0,162,0,90,255,236,0,162,0,94,255,248,0,162,0,110,255,248,0,162,0,134,255,237,0,162,0,135,255,240,0,162,0,136,255,240,0,162,0,137,255,240,0,162,0,138,255,240,0,162,0,139,255,240,0,162,0,140,255,240,0,162,0,141,255,240,0,162,0,142,255,240,0,162,0,143,255,240,0,162,0,144,255,240,0,162,0,145,255,237,0,162,0,146,255,237,0,162,0,147,255,237,0,162,0,148,255,237,0,162,0,149,255,237,0,162,0,151,255,237,0,162,0,152,255,227,0,162,0,153,255,227,0,162,0,154,255,227,0,162,0,155,255,227,0,162,0,156,255,165,0,162,0,157,255,240,0,162,0,158,255,249,0,162,0,188,255,236,0,162,0,190,255,236,0,162,0,194,255,237,0,162,0,196,255,250,0,162,0,198,255,165,0,162,0,209,255,186,0,162,0,210,255,195,0,162,0,212,255,186,0,162,0,213,255,195,0,162,0,240,255,230,0,163,0,3,255,234,0,163,0,7,255,245,0,163,0,8,255,234,0,163,0,10,255,246,0,163,0,11,255,231,0,163,0,18,255,234,0,163,0,26,255,247,0,163,0,32,255,229,0,163,0,35,255,240,0,163,0,36,255,237,0,163,0,37,255,240,0,163,0,38,255,240,0,163,0,39,255,240,0,163,0,40,255,237,0,163,0,41,255,240,0,163,0,42,255,240,0,163,0,43,255,240,0,163,0,44,255,240,0,163,0,45,255,240,0,163,0,46,255,248,0,163,0,47,255,240,0,163,0,48,255,237,0,163,0,49,255,240,0,163,0,50,255,237,0,163,0,51,255,240,0,163,0,52,255,250,0,163,0,53,255,173,0,163,0,54,255,227,0,163,0,55,255,193,0,163,0,56,255,210,0,163,0,58,255,165,0,163,0,61,255,210,0,163,0,62,255,245,0,163,0,71,255,251,0,163,0,85,255,246,0,163,0,87,255,238,0,163,0,88,255,243,0,163,0,90,255,236,0,163,0,94,255,248,0,163,0,110,255,248,0,163,0,134,255,237,0,163,0,135,255,240,0,163,0,136,255,240,0,163,0,137,255,240,0,163,0,138,255,240,0,163,0,139,255,240,0,163,0,140,255,240,0,163,0,141,255,240,0,163,0,142,255,240,0,163,0,143,255,240,0,163,0,144,255,240,0,163,0,145,255,237,0,163,0,146,255,237,0,163,0,147,255,237,0,163,0,148,255,237,0,163,0,149,255,237,0,163,0,151,255,237,0,163,0,152,255,227,0,163,0,153,255,227,0,163,0,154,255,227,0,163,0,155,255,227,0,163,0,156,255,165,0,163,0,157,255,240,0,163,0,158,255,249,0,163,0,188,255,236,0,163,0,190,255,236,0,163,0,194,255,237,0,163,0,196,255,250,0,163,0,198,255,165,0,163,0,209,255,186,0,163,0,210,255,183,0,163,0,212,255,186,0,163,0,213,255,183,0,163,0,240,255,230,0,164,0,3,255,234,0,164,0,7,255,245,0,164,0,8,255,234,0,164,0,10,255,246,0,164,0,11,255,231,0,164,0,18,255,234,0,164,0,26,255,247,0,164,0,32,255,229,0,164,0,35,255,240,0,164,0,36,255,237,0,164,0,37,255,240,0,164,0,38,255,240,0,164,0,39,255,240,0,164,0,40,255,237,0,164,0,41,255,240,0,164,0,42,255,240,0,164,0,43,255,240,0,164,0,44,255,240,0,164,0,45,255,240,0,164,0,46,255,248,0,164,0,47,255,240,0,164,0,48,255,237,0,164,0,49,255,240,0,164,0,50,255,237,0,164,0,51,255,240,0,164,0,52,255,250,0,164,0,53,255,173,0,164,0,54,255,227,0,164,0,55,255,193,0,164,0,56,255,210,0,164,0,58,255,165,0,164,0,61,255,210,0,164,0,62,255,227,0,164,0,71,255,251,0,164,0,85,255,246,0,164,0,87,255,238,0,164,0,88,255,243,0,164,0,90,255,236,0,164,0,94,255,231,0,164,0,110,255,248,0,164,0,134,255,237,0,164,0,135,255,240,0,164,0,136,255,240,0,164,0,137,255,240,0,164,0,138,255,240,0,164,0,139,255,240,0,164,0,140,255,240,0,164,0,141,255,240,0,164,0,142,255,240,0,164,0,143,255,240,0,164,0,144,255,240,0,164,0,145,255,237,0,164,0,146,255,237,0,164,0,147,255,237,0,164,0,148,255,237,0,164,0,149,255,237,0,164,0,151,255,237,0,164,0,152,255,227,0,164,0,153,255,227,0,164,0,154,255,227,0,164,0,155,255,227,0,164,0,156,255,165,0,164,0,157,255,240,0,164,0,158,255,249,0,164,0,188,255,236,0,164,0,190,255,236,0,164,0,194,255,237,0,164,0,196,255,250,0,164,0,198,255,165,0,164,0,209,255,186,0,164,0,210,255,183,0,164,0,212,255,186,0,164,0,213,255,183,0,164,0,240,255,230,0,165,0,3,255,241,0,165,0,7,255,246,0,165,0,8,255,241,0,165,0,10,255,230,0,165,0,11,255,238,0,165,0,18,255,235,0,165,0,19,255,245,0,165,0,24,255,230,0,165,0,32,255,223,0,165,0,34,255,251,0,165,0,35,255,241,0,165,0,36,255,250,0,165,0,37,255,241,0,165,0,38,255,241,0,165,0,39,255,241,0,165,0,40,255,250,0,165,0,41,255,241,0,165,0,42,255,241,0,165,0,43,255,241,0,165,0,44,255,241,0,165,0,45,255,241,0,165,0,46,255,243,0,165,0,47,255,241,0,165,0,48,255,250,0,165,0,49,255,241,0,165,0,50,255,250,0,165,0,51,255,241,0,165,0,52,255,241,0,165,0,53,255,187,0,165,0,54,255,240,0,165,0,55,255,209,0,165,0,56,255,213,0,165,0,57,255,243,0,165,0,58,255,174,0,165,0,59,255,243,0,165,0,61,255,220,0,165,0,62,255,220,0,165,0,87,255,252,0,165,0,89,255,251,0,165,0,90,255,251,0,165,0,94,255,227,0,165,0,127,255,251,0,165,0,128,255,251,0,165,0,129,255,251,0,165,0,130,255,251,0,165,0,131,255,251,0,165,0,132,255,251,0,165,0,134,255,250,0,165,0,135,255,241,0,165,0,136,255,241,0,165,0,137,255,241,0,165,0,138,255,241,0,165,0,139,255,241,0,165,0,140,255,241,0,165,0,141,255,241,0,165,0,142,255,241,0,165,0,143,255,241,0,165,0,144,255,241,0,165,0,145,255,250,0,165,0,146,255,250,0,165,0,147,255,250,0,165,0,148,255,250,0,165,0,149,255,250,0,165,0,151,255,250,0,165,0,152,255,240,0,165,0,153,255,240,0,165,0,154,255,240,0,165,0,155,255,240,0,165,0,156,255,174,0,165,0,157,255,241,0,165,0,188,255,251,0,165,0,190,255,251,0,165,0,194,255,250,0,165,0,196,255,241,0,165,0,198,255,174,0,165,0,199,255,243,0,165,0,209,255,189,0,165,0,210,255,186,0,165,0,212,255,189,0,165,0,213,255,186,0,165,0,240,255,237,0,166,0,7,255,240,0,166,0,10,255,244,0,166,0,14,255,219,0,166,0,21,255,231,0,166,0,24,255,245,0,166,0,32,255,228,0,166,0,35,255,247,0,166,0,36,255,244,0,166,0,37,255,247,0,166,0,38,255,247,0,166,0,39,255,247,0,166,0,40,255,244,0,166,0,41,255,247,0,166,0,42,255,247,0,166,0,43,255,247,0,166,0,44,255,247,0,166,0,45,255,247,0,166,0,46,255,251,0,166,0,47,255,247,0,166,0,48,255,244,0,166,0,49,255,247,0,166,0,50,255,244,0,166,0,51,255,247,0,166,0,52,255,244,0,166,0,53,255,190,0,166,0,54,255,243,0,166,0,55,255,236,0,166,0,56,255,241,0,166,0,58,255,218,0,166,0,61,255,240,0,166,0,62,255,232,0,166,0,68,255,249,0,166,0,69,255,249,0,166,0,70,255,249,0,166,0,80,255,249,0,166,0,82,255,249,0,166,0,94,255,239,0,166,0,107,255,243,0,166,0,134,255,244,0,166,0,135,255,247,0,166,0,136,255,247,0,166,0,137,255,247,0,166,0,138,255,247,0,166,0,139,255,247,0,166,0,140,255,247,0,166,0,141,255,247,0,166,0,142,255,247,0,166,0,143,255,247,0,166,0,144,255,247,0,166,0,145,255,244,0,166,0,146,255,244,0,166,0,147,255,244,0,166,0,148,255,244,0,166,0,149,255,244,0,166,0,151,255,244,0,166,0,152,255,243,0,166,0,153,255,243,0,166,0,154,255,243,0,166,0,155,255,243,0,166,0,156,255,218,0,166,0,157,255,247,0,166,0,166,255,249,0,166,0,167,255,249,0,166,0,168,255,249,0,166,0,169,255,249,0,166,0,170,255,249,0,166,0,175,255,251,0,166,0,177,255,249,0,166,0,178,255,249,0,166,0,179,255,249,0,166,0,180,255,249,0,166,0,181,255,249,0,166,0,183,255,249,0,166,0,194,255,244,0,166,0,195,255,249,0,166,0,196,255,244,0,166,0,198,255,218,0,166,0,207,255,219,0,166,0,208,255,219,0,166,0,209,255,216,0,166,0,210,255,213,0,166,0,212,255,216,0,166,0,213,255,213,0,166,0,220,255,243,0,166,0,240,255,245,0,167,0,3,255,241,0,167,0,7,255,246,0,167,0,8,255,241,0,167,0,10,255,230,0,167,0,11,255,238,0,167,0,18,255,235,0,167,0,19,255,245,0,167,0,24,255,230,0,167,0,32,255,223,0,167,0,34,255,251,0,167,0,35,255,241,0,167,0,36,255,250,0,167,0,37,255,241,0,167,0,38,255,241,0,167,0,39,255,241,0,167,0,40,255,250,0,167,0,41,255,241,0,167,0,42,255,241,0,167,0,43,255,241,0,167,0,44,255,241,0,167,0,45,255,241,0,167,0,46,255,243,0,167,0,47,255,241,0,167,0,48,255,250,0,167,0,49,255,241,0,167,0,50,255,250,0,167,0,51,255,241,0,167,0,52,255,241,0,167,0,53,255,187,0,167,0,54,255,240,0,167,0,55,255,209,0,167,0,56,255,213,0,167,0,57,255,243,0,167,0,58,255,174,0,167,0,59,255,243,0,167,0,61,255,220,0,167,0,62,255,220,0,167,0,87,255,252,0,167,0,89,255,251,0,167,0,90,255,251,0,167,0,94,255,227,0,167,0,127,255,251,0,167,0,128,255,251,0,167,0,129,255,251,0,167,0,130,255,251,0,167,0,131,255,251,0,167,0,132,255,251,0,167,0,134,255,250,0,167,0,135,255,241,0,167,0,136,255,241,0,167,0,137,255,241,0,167,0,138,255,241,0,167,0,139,255,241,0,167,0,140,255,241,0,167,0,141,255,241,0,167,0,142,255,241,0,167,0,143,255,241,0,167,0,144,255,241,0,167,0,145,255,250,0,167,0,146,255,250,0,167,0,147,255,250,0,167,0,148,255,250,0,167,0,149,255,250,0,167,0,151,255,250,0,167,0,152,255,240,0,167,0,153,255,240,0,167,0,154,255,240,0,167,0,155,255,240,0,167,0,156,255,174,0,167,0,157,255,241,0,167,0,188,255,251,0,167,0,190,255,251,0,167,0,194,255,250,0,167,0,196,255,241,0,167,0,198,255,174,0,167,0,199,255,243,0,167,0,209,255,189,0,167,0,210,255,186,0,167,0,212,255,189,0,167,0,213,255,186,0,167,0,240,255,237,0,168,0,3,255,241,0,168,0,7,255,246,0,168,0,8,255,241,0,168,0,10,255,230,0,168,0,11,255,238,0,168,0,18,255,235,0,168,0,19,255,245,0,168,0,24,255,230,0,168,0,32,255,223,0,168,0,34,255,251,0,168,0,35,255,241,0,168,0,36,255,250,0,168,0,37,255,241,0,168,0,38,255,241,0,168,0,39,255,241,0,168,0,40,255,250,0,168,0,41,255,241,0,168,0,42,255,241,0,168,0,43,255,241,0,168,0,44,255,241,0,168,0,45,255,241,0,168,0,46,255,243,0,168,0,47,255,241,0,168,0,48,255,250,0,168,0,49,255,241,0,168,0,50,255,250,0,168,0,51,255,241,0,168,0,52,255,241,0,168,0,53,255,187,0,168,0,54,255,240,0,168,0,55,255,209,0,168,0,56,255,213,0,168,0,57,255,243,0,168,0,58,255,174,0,168,0,59,255,243,0,168,0,61,255,220,0,168,0,62,255,220,0,168,0,87,255,252,0,168,0,89,255,251,0,168,0,90,255,251,0,168,0,94,255,227,0,168,0,127,255,251,0,168,0,128,255,251,0,168,0,129,255,251,0,168,0,130,255,251,0,168,0,131,255,251,0,168,0,132,255,251,0,168,0,134,255,250,0,168,0,135,255,241,0,168,0,136,255,241,0,168,0,137,255,241,0,168,0,138,255,241,0,168,0,139,255,241,0,168,0,140,255,241,0,168,0,141,255,241,0,168,0,142,255,241,0,168,0,143,255,241,0,168,0,144,255,241,0,168,0,145,255,250,0,168,0,146,255,250,0,168,0,147,255,250,0,168,0,148,255,250,0,168,0,149,255,250,0,168,0,151,255,250,0,168,0,152,255,240,0,168,0,153,255,240,0,168,0,154,255,240,0,168,0,155,255,240,0,168,0,156,255,174,0,168,0,157,255,241,0,168,0,188,255,251,0,168,0,190,255,251,0,168,0,194,255,250,0,168,0,196,255,241,0,168,0,198,255,174,0,168,0,199,255,243,0,168,0,209,255,189,0,168,0,210,255,186,0,168,0,212,255,189,0,168,0,213,255,186,0,168,0,240,255,237,0,169,0,3,255,241,0,169,0,7,255,246,0,169,0,8,255,241,0,169,0,10,255,230,0,169,0,11,255,238,0,169,0,18,255,235,0,169,0,19,255,245,0,169,0,24,255,230,0,169,0,32,255,223,0,169,0,34,255,251,0,169,0,35,255,241,0,169,0,36,255,250,0,169,0,37,255,241,0,169,0,38,255,241,0,169,0,39,255,241,0,169,0,40,255,250,0,169,0,41,255,241,0,169,0,42,255,241,0,169,0,43,255,241,0,169,0,44,255,241,0,169,0,45,255,241,0,169,0,46,255,243,0,169,0,47,255,241,0,169,0,48,255,250,0,169,0,49,255,241,0,169,0,50,255,250,0,169,0,51,255,241,0,169,0,52,255,241,0,169,0,53,255,187,0,169,0,54,255,240,0,169,0,55,255,209,0,169,0,56,255,213,0,169,0,57,255,243,0,169,0,58,255,174,0,169,0,59,255,243,0,169,0,61,255,220,0,169,0,62,255,220,0,169,0,87,255,252,0,169,0,89,255,251,0,169,0,90,255,251,0,169,0,94,255,227,0,169,0,127,255,251,0,169,0,128,255,251,0,169,0,129,255,251,0,169,0,130,255,251,0,169,0,131,255,251,0,169,0,132,255,251,0,169,0,134,255,250,0,169,0,135,255,241,0,169,0,136,255,241,0,169,0,137,255,241,0,169,0,138,255,241,0,169,0,139,255,241,0,169,0,140,255,241,0,169,0,141,255,241,0,169,0,142,255,241,0,169,0,143,255,241,0,169,0,144,255,241,0,169,0,145,255,250,0,169,0,146,255,250,0,169,0,147,255,250,0,169,0,148,255,250,0,169,0,149,255,250,0,169,0,151,255,250,0,169,0,152,255,240,0,169,0,153,255,240,0,169,0,154,255,240,0,169,0,155,255,240,0,169,0,156,255,174,0,169,0,157,255,241,0,169,0,188,255,251,0,169,0,190,255,251,0,169,0,194,255,250,0,169,0,196,255,241,0,169,0,198,255,174,0,169,0,199,255,243,0,169,0,209,255,189,0,169,0,210,255,186,0,169,0,212,255,189,0,169,0,213,255,186,0,169,0,240,255,237,0,170,0,3,255,241,0,170,0,7,255,246,0,170,0,8,255,241,0,170,0,10,255,230,0,170,0,11,255,238,0,170,0,18,255,235,0,170,0,19,255,245,0,170,0,24,255,230,0,170,0,32,255,223,0,170,0,34,255,251,0,170,0,35,255,241,0,170,0,36,255,250,0,170,0,37,255,241,0,170,0,38,255,241,0,170,0,39,255,241,0,170,0,40,255,250,0,170,0,41,255,241,0,170,0,42,255,241,0,170,0,43,255,241,0,170,0,44,255,241,0,170,0,45,255,241,0,170,0,46,255,243,0,170,0,47,255,241,0,170,0,48,255,250,0,170,0,49,255,241,0,170,0,50,255,250,0,170,0,51,255,241,0,170,0,52,255,241,0,170,0,53,255,187,0,170,0,54,255,240,0,170,0,55,255,209,0,170,0,56,255,213,0,170,0,57,255,243,0,170,0,58,255,174,0,170,0,59,255,243,0,170,0,61,255,220,0,170,0,62,255,220,0,170,0,87,255,252,0,170,0,89,255,251,0,170,0,90,255,251,0,170,0,94,255,227,0,170,0,127,255,251,0,170,0,128,255,251,0,170,0,129,255,251,0,170,0,130,255,251,0,170,0,131,255,251,0,170,0,132,255,251,0,170,0,134,255,250,0,170,0,135,255,241,0,170,0,136,255,241,0,170,0,137,255,241,0,170,0,138,255,241,0,170,0,139,255,241,0,170,0,140,255,241,0,170,0,141,255,241,0,170,0,142,255,241,0,170,0,143,255,241,0,170,0,144,255,241,0,170,0,145,255,250,0,170,0,146,255,250,0,170,0,147,255,250,0,170,0,148,255,250,0,170,0,149,255,250,0,170,0,151,255,250,0,170,0,152,255,240,0,170,0,153,255,240,0,170,0,154,255,240,0,170,0,155,255,240,0,170,0,156,255,174,0,170,0,157,255,241,0,170,0,188,255,251,0,170,0,190,255,251,0,170,0,194,255,250,0,170,0,196,255,241,0,170,0,198,255,174,0,170,0,199,255,243,0,170,0,209,255,189,0,170,0,210,255,186,0,170,0,212,255,189,0,170,0,213,255,186,0,170,0,240,255,237,0,171,0,7,255,244,0,171,0,11,0,30,0,171,0,34,255,248,0,171,0,35,255,242,0,171,0,36,255,244,0,171,0,37,255,242,0,171,0,38,255,242,0,171,0,39,255,242,0,171,0,40,255,244,0,171,0,41,255,242,0,171,0,42,255,242,0,171,0,43,255,242,0,171,0,44,255,242,0,171,0,45,255,242,0,171,0,46,255,241,0,171,0,47,255,242,0,171,0,48,255,244,0,171,0,49,255,242,0,171,0,50,255,244,0,171,0,51,255,242,0,171,0,52,255,244,0,171,0,53,255,242,0,171,0,54,255,238,0,171,0,55,255,247,0,171,0,56,255,246,0,171,0,58,255,247,0,171,0,59,255,245,0,171,0,127,255,248,0,171,0,128,255,248,0,171,0,129,255,248,0,171,0,130,255,248,0,171,0,131,255,248,0,171,0,132,255,248,0,171,0,134,255,244,0,171,0,135,255,242,0,171,0,136,255,242,0,171,0,137,255,242,0,171,0,138,255,242,0,171,0,139,255,242,0,171,0,140,255,242,0,171,0,141,255,242,0,171,0,142,255,242,0,171,0,143,255,242,0,171,0,144,255,242,0,171,0,145,255,244,0,171,0,146,255,244,0,171,0,147,255,244,0,171,0,148,255,244,0,171,0,149,255,244,0,171,0,151,255,244,0,171,0,152,255,238,0,171,0,153,255,238,0,171,0,154,255,238,0,171,0,155,255,238,0,171,0,156,255,247,0,171,0,157,255,242,0,171,0,194,255,244,0,171,0,196,255,244,0,171,0,198,255,247,0,171,0,199,255,245,0,171,0,240,0,28,0,172,0,7,255,244,0,172,0,11,0,18,0,172,0,34,255,248,0,172,0,35,255,242,0,172,0,36,255,244,0,172,0,37,255,242,0,172,0,38,255,242,0,172,0,39,255,242,0,172,0,40,255,244,0,172,0,41,255,242,0,172,0,42,255,242,0,172,0,43,255,242,0,172,0,44,255,242,0,172,0,45,255,242,0,172,0,46,255,241,0,172,0,47,255,242,0,172,0,48,255,244,0,172,0,49,255,242,0,172,0,50,255,244,0,172,0,51,255,242,0,172,0,52,255,244,0,172,0,53,255,242,0,172,0,54,255,238,0,172,0,55,255,247,0,172,0,56,255,246,0,172,0,58,255,247,0,172,0,59,255,245,0,172,0,62,0,9,0,172,0,94,0,14,0,172,0,127,255,248,0,172,0,128,255,248,0,172,0,129,255,248,0,172,0,130,255,248,0,172,0,131,255,248,0,172,0,132,255,248,0,172,0,134,255,244,0,172,0,135,255,242,0,172,0,136,255,242,0,172,0,137,255,242,0,172,0,138,255,242,0,172,0,139,255,242,0,172,0,140,255,242,0,172,0,141,255,242,0,172,0,142,255,242,0,172,0,143,255,242,0,172,0,144,255,242,0,172,0,145,255,244,0,172,0,146,255,244,0,172,0,147,255,244,0,172,0,148,255,244,0,172,0,149,255,244,0,172,0,151,255,244,0,172,0,152,255,238,0,172,0,153,255,238,0,172,0,154,255,238,0,172,0,155,255,238,0,172,0,156,255,247,0,172,0,157,255,242,0,172,0,194,255,244,0,172,0,196,255,244,0,172,0,198,255,247,0,172,0,199,255,245,0,172,0,240,0,18,0,173,0,3,0,29,0,173,0,7,255,244,0,173,0,8,0,29,0,173,0,11,0,76,0,173,0,32,0,39,0,173,0,34,255,248,0,173,0,35,255,242,0,173,0,36,255,244,0,173,0,37,255,242,0,173,0,38,255,242,0,173,0,39,255,242,0,173,0,40,255,244,0,173,0,41,255,242,0,173,0,42,255,242,0,173,0,43,255,242,0,173,0,44,255,242,0,173,0,45,255,242,0,173,0,46,255,241,0,173,0,47,255,242,0,173,0,48,255,244,0,173,0,49,255,242,0,173,0,50,255,244,0,173,0,51,255,242,0,173,0,52,255,244,0,173,0,53,255,242,0,173,0,54,255,238,0,173,0,55,255,247,0,173,0,56,255,246,0,173,0,58,255,247,0,173,0,59,255,245,0,173,0,61,0,13,0,173,0,62,0,44,0,173,0,94,0,33,0,173,0,127,255,248,0,173,0,128,255,248,0,173,0,129,255,248,0,173,0,130,255,248,0,173,0,131,255,248,0,173,0,132,255,248,0,173,0,134,255,244,0,173,0,135,255,242,0,173,0,136,255,242,0,173,0,137,255,242,0,173,0,138,255,242,0,173,0,139,255,242,0,173,0,140,255,242,0,173,0,141,255,242,0,173,0,142,255,242,0,173,0,143,255,242,0,173,0,144,255,242,0,173,0,145,255,244,0,173,0,146,255,244,0,173,0,147,255,244,0,173,0,148,255,244,0,173,0,149,255,244,0,173,0,151,255,244,0,173,0,152,255,238,0,173,0,153,255,238,0,173,0,154,255,238,0,173,0,155,255,238,0,173,0,156,255,247,0,173,0,157,255,242,0,173,0,194,255,244,0,173,0,196,255,244,0,173,0,198,255,247,0,173,0,199,255,245,0,173,0,209,0,37,0,173,0,210,0,24,0,173,0,212,0,37,0,173,0,213,0,24,0,173,0,240,0,81,0,174,0,7,255,244,0,174,0,11,0,43,0,174,0,32,0,27,0,174,0,34,255,248,0,174,0,35,255,242,0,174,0,36,255,244,0,174,0,37,255,242,0,174,0,38,255,242,0,174,0,39,255,242,0,174,0,40,255,244,0,174,0,41,255,242,0,174,0,42,255,242,0,174,0,43,255,242,0,174,0,44,255,242,0,174,0,45,255,242,0,174,0,46,255,241,0,174,0,47,255,242,0,174,0,48,255,244,0,174,0,49,255,242,0,174,0,50,255,244,0,174,0,51,255,242,0,174,0,52,255,244,0,174,0,53,255,242,0,174,0,54,255,238,0,174,0,55,255,247,0,174,0,56,255,246,0,174,0,58,255,247,0,174,0,59,255,245,0,174,0,61,0,14,0,174,0,62,0,39,0,174,0,94,0,44,0,174,0,127,255,248,0,174,0,128,255,248,0,174,0,129,255,248,0,174,0,130,255,248,0,174,0,131,255,248,0,174,0,132,255,248,0,174,0,134,255,244,0,174,0,135,255,242,0,174,0,136,255,242,0,174,0,137,255,242,0,174,0,138,255,242,0,174,0,139,255,242,0,174,0,140,255,242,0,174,0,141,255,242,0,174,0,142,255,242,0,174,0,143,255,242,0,174,0,144,255,242,0,174,0,145,255,244,0,174,0,146,255,244,0,174,0,147,255,244,0,174,0,148,255,244,0,174,0,149,255,244,0,174,0,151,255,244,0,174,0,152,255,238,0,174,0,153,255,238,0,174,0,154,255,238,0,174,0,155,255,238,0,174,0,156,255,247,0,174,0,157,255,242,0,174,0,194,255,244,0,174,0,196,255,244,0,174,0,198,255,247,0,174,0,199,255,245,0,174,0,240,0,48,0,175,0,3,255,245,0,175,0,7,255,247,0,175,0,8,255,245,0,175,0,10,255,232,0,175,0,11,255,240,0,175,0,13,255,247,0,175,0,15,255,247,0,175,0,32,255,242,0,175,0,61,255,246,0,175,0,62,255,240,0,175,0,89,255,248,0,175,0,94,255,243,0,175,0,209,255,236,0,175,0,210,255,237,0,175,0,211,255,247,0,175,0,212,255,236,0,175,0,213,255,237,0,175,0,214,255,247,0,175,0,218,255,247,0,175,0,240,255,241,0,176,0,2,255,248,0,176,0,3,255,238,0,176,0,7,255,245,0,176,0,8,255,238,0,176,0,10,255,232,0,176,0,11,255,235,0,176,0,18,255,231,0,176,0,24,255,233,0,176,0,32,255,224,0,176,0,34,255,250,0,176,0,35,255,238,0,176,0,36,255,243,0,176,0,37,255,238,0,176,0,38,255,238,0,176,0,39,255,238,0,176,0,40,255,243,0,176,0,41,255,238,0,176,0,42,255,238,0,176,0,43,255,238,0,176,0,44,255,238,0,176,0,45,255,238,0,176,0,46,255,241,0,176,0,47,255,238,0,176,0,48,255,243,0,176,0,49,255,238,0,176,0,50,255,243,0,176,0,51,255,238,0,176,0,52,255,241,0,176,0,53,255,162,0,176,0,54,255,231,0,176,0,55,255,198,0,176,0,56,255,214,0,176,0,57,255,249,0,176,0,58,255,163,0,176,0,59,255,245,0,176,0,61,255,214,0,176,0,62,255,216,0,176,0,71,255,251,0,176,0,85,255,248,0,176,0,87,255,243,0,176,0,88,255,248,0,176,0,90,255,242,0,176,0,94,255,225,0,176,0,127,255,250,0,176,0,128,255,250,0,176,0,129,255,250,0,176,0,130,255,250,0,176,0,131,255,250,0,176,0,132,255,250,0,176,0,134,255,243,0,176,0,135,255,238,0,176,0,136,255,238,0,176,0,137,255,238,0,176,0,138,255,238,0,176,0,139,255,238,0,176,0,140,255,238,0,176,0,141,255,238,0,176,0,142,255,238,0,176,0,143,255,238,0,176,0,144,255,238,0,176,0,145,255,243,0,176,0,146,255,243,0,176,0,147,255,243,0,176,0,148,255,243,0,176,0,149,255,243,0,176,0,151,255,243,0,176,0,152,255,231,0,176,0,153,255,231,0,176,0,154,255,231,0,176,0,155,255,231,0,176,0,156,255,163,0,176,0,157,255,238,0,176,0,158,255,248,0,176,0,188,255,242,0,176,0,190,255,242,0,176,0,194,255,243,0,176,0,196,255,241,0,176,0,198,255,163,0,176,0,199,255,245,0,176,0,209,255,187,0,176,0,210,255,184,0,176,0,212,255,187,0,176,0,213,255,184,0,176,0,240,255,235,0,177,0,3,255,236,0,177,0,7,255,246,0,177,0,8,255,236,0,177,0,10,255,224,0,177,0,11,255,234,0,177,0,18,255,230,0,177,0,19,255,229,0,177,0,24,255,223,0,177,0,32,255,222,0,177,0,34,255,240,0,177,0,35,255,237,0,177,0,36,255,246,0,177,0,37,255,237,0,177,0,38,255,237,0,177,0,39,255,237,0,177,0,40,255,246,0,177,0,41,255,237,0,177,0,42,255,237,0,177,0,43,255,237,0,177,0,44,255,237,0,177,0,45,255,237,0,177,0,46,255,239,0,177,0,47,255,237,0,177,0,48,255,246,0,177,0,49,255,237,0,177,0,50,255,246,0,177,0,51,255,237,0,177,0,52,255,238,0,177,0,53,255,173,0,177,0,54,255,238,0,177,0,55,255,192,0,177,0,56,255,212,0,177,0,57,255,218,0,177,0,58,255,167,0,177,0,59,255,227,0,177,0,61,255,214,0,177,0,62,255,213,0,177,0,71,255,251,0,177,0,85,255,249,0,177,0,87,255,247,0,177,0,88,255,251,0,177,0,89,255,237,0,177,0,90,255,245,0,177,0,91,255,246,0,177,0,94,255,222,0,177,0,122,255,247,0,177,0,127,255,240,0,177,0,128,255,240,0,177,0,129,255,240,0,177,0,130,255,240,0,177,0,131,255,240,0,177,0,132,255,240,0,177,0,134,255,246,0,177,0,135,255,237,0,177,0,136,255,237,0,177,0,137,255,237,0,177,0,138,255,237,0,177,0,139,255,237,0,177,0,140,255,237,0,177,0,141,255,237,0,177,0,142,255,237,0,177,0,143,255,237,0,177,0,144,255,237,0,177,0,145,255,246,0,177,0,146,255,246,0,177,0,147,255,246,0,177,0,148,255,246,0,177,0,149,255,246,0,177,0,151,255,246,0,177,0,152,255,238,0,177,0,153,255,238,0,177,0,154,255,238,0,177,0,155,255,238,0,177,0,156,255,167,0,177,0,157,255,237,0,177,0,158,255,248,0,177,0,188,255,245,0,177,0,190,255,245,0,177,0,194,255,246,0,177,0,196,255,238,0,177,0,198,255,167,0,177,0,199,255,227,0,177,0,200,255,246,0,177,0,209,255,182,0,177,0,210,255,179,0,177,0,212,255,182,0,177,0,213,255,179,0,177,0,221,255,247,0,177,0,240,255,236,0,178,0,3,255,236,0,178,0,7,255,246,0,178,0,8,255,236,0,178,0,10,255,224,0,178,0,11,255,234,0,178,0,18,255,230,0,178,0,19,255,229,0,178,0,24,255,223,0,178,0,32,255,222,0,178,0,34,255,240,0,178,0,35,255,237,0,178,0,36,255,246,0,178,0,37,255,237,0,178,0,38,255,237,0,178,0,39,255,237,0,178,0,40,255,246,0,178,0,41,255,237,0,178,0,42,255,237,0,178,0,43,255,237,0,178,0,44,255,237,0,178,0,45,255,237,0,178,0,46,255,239,0,178,0,47,255,237,0,178,0,48,255,246,0,178,0,49,255,237,0,178,0,50,255,246,0,178,0,51,255,237,0,178,0,52,255,238,0,178,0,53,255,173,0,178,0,54,255,238,0,178,0,55,255,192,0,178,0,56,255,212,0,178,0,57,255,218,0,178,0,58,255,167,0,178,0,59,255,227,0,178,0,61,255,214,0,178,0,62,255,213,0,178,0,71,255,251,0,178,0,85,255,249,0,178,0,87,255,247,0,178,0,88,255,251,0,178,0,89,255,237,0,178,0,90,255,245,0,178,0,91,255,246,0,178,0,94,255,222,0,178,0,122,255,247,0,178,0,127,255,240,0,178,0,128,255,240,0,178,0,129,255,240,0,178,0,130,255,240,0,178,0,131,255,240,0,178,0,132,255,240,0,178,0,134,255,246,0,178,0,135,255,237,0,178,0,136,255,237,0,178,0,137,255,237,0,178,0,138,255,237,0,178,0,139,255,237,0,178,0,140,255,237,0,178,0,141,255,237,0,178,0,142,255,237,0,178,0,143,255,237,0,178,0,144,255,237,0,178,0,145,255,246,0,178,0,146,255,246,0,178,0,147,255,246,0,178,0,148,255,246,0,178,0,149,255,246,0,178,0,151,255,246,0,178,0,152,255,238,0,178,0,153,255,238,0,178,0,154,255,238,0,178,0,155,255,238,0,178,0,156,255,167,0,178,0,157,255,237,0,178,0,158,255,248,0,178,0,188,255,245,0,178,0,190,255,245,0,178,0,194,255,246,0,178,0,196,255,238,0,178,0,198,255,167,0,178,0,199,255,227,0,178,0,200,255,246,0,178,0,209,255,182,0,178,0,210,255,179,0,178,0,212,255,182,0,178,0,213,255,179,0,178,0,221,255,247,0,178,0,240,255,236,0,179,0,3,255,236,0,179,0,7,255,246,0,179,0,8,255,236,0,179,0,10,255,224,0,179,0,11,255,234,0,179,0,18,255,230,0,179,0,19,255,229,0,179,0,24,255,223,0,179,0,32,255,222,0,179,0,34,255,240,0,179,0,35,255,237,0,179,0,36,255,246,0,179,0,37,255,237,0,179,0,38,255,237,0,179,0,39,255,237,0,179,0,40,255,246,0,179,0,41,255,237,0,179,0,42,255,237,0,179,0,43,255,237,0,179,0,44,255,237,0,179,0,45,255,237,0,179,0,46,255,239,0,179,0,47,255,237,0,179,0,48,255,246,0,179,0,49,255,237,0,179,0,50,255,246,0,179,0,51,255,237,0,179,0,52,255,238,0,179,0,53,255,173,0,179,0,54,255,238,0,179,0,55,255,192,0,179,0,56,255,212,0,179,0,57,255,218,0,179,0,58,255,167,0,179,0,59,255,227,0,179,0,61,255,214,0,179,0,62,255,213,0,179,0,71,255,251,0,179,0,85,255,249,0,179,0,87,255,247,0,179,0,88,255,251,0,179,0,89,255,237,0,179,0,90,255,245,0,179,0,91,255,246,0,179,0,94,255,222,0,179,0,122,255,247,0,179,0,127,255,240,0,179,0,128,255,240,0,179,0,129,255,240,0,179,0,130,255,240,0,179,0,131,255,240,0,179,0,132,255,240,0,179,0,134,255,246,0,179,0,135,255,237,0,179,0,136,255,237,0,179,0,137,255,237,0,179,0,138,255,237,0,179,0,139,255,237,0,179,0,140,255,237,0,179,0,141,255,237,0,179,0,142,255,237,0,179,0,143,255,237,0,179,0,144,255,237,0,179,0,145,255,246,0,179,0,146,255,246,0,179,0,147,255,246,0,179,0,148,255,246,0,179,0,149,255,246,0,179,0,151,255,246,0,179,0,152,255,238,0,179,0,153,255,238,0,179,0,154,255,238,0,179,0,155,255,238,0,179,0,156,255,167,0,179,0,157,255,237,0,179,0,158,255,248,0,179,0,188,255,245,0,179,0,190,255,245,0,179,0,194,255,246,0,179,0,196,255,238,0,179,0,198,255,167,0,179,0,199,255,227,0,179,0,200,255,246,0,179,0,209,255,182,0,179,0,210,255,179,0,179,0,212,255,182,0,179,0,213,255,179,0,179,0,221,255,247,0,179,0,240,255,236,0,180,0,3,255,236,0,180,0,7,255,246,0,180,0,8,255,236,0,180,0,10,255,224,0,180,0,11,255,234,0,180,0,18,255,230,0,180,0,19,255,229,0,180,0,24,255,223,0,180,0,32,255,222,0,180,0,34,255,240,0,180,0,35,255,237,0,180,0,36,255,246,0,180,0,37,255,237,0,180,0,38,255,237,0,180,0,39,255,237,0,180,0,40,255,246,0,180,0,41,255,237,0,180,0,42,255,237,0,180,0,43,255,237,0,180,0,44,255,237,0,180,0,45,255,237,0,180,0,46,255,239,0,180,0,47,255,237,0,180,0,48,255,246,0,180,0,49,255,237,0,180,0,50,255,246,0,180,0,51,255,237,0,180,0,52,255,238,0,180,0,53,255,173,0,180,0,54,255,238,0,180,0,55,255,192,0,180,0,56,255,212,0,180,0,57,255,218,0,180,0,58,255,167,0,180,0,59,255,227,0,180,0,61,255,214,0,180,0,62,255,213,0,180,0,71,255,251,0,180,0,85,255,249,0,180,0,87,255,247,0,180,0,88,255,251,0,180,0,89,255,237,0,180,0,90,255,245,0,180,0,91,255,246,0,180,0,94,255,222,0,180,0,122,255,247,0,180,0,127,255,240,0,180,0,128,255,240,0,180,0,129,255,240,0,180,0,130,255,240,0,180,0,131,255,240,0,180,0,132,255,240,0,180,0,134,255,246,0,180,0,135,255,237,0,180,0,136,255,237,0,180,0,137,255,237,0,180,0,138,255,237,0,180,0,139,255,237,0,180,0,140,255,237,0,180,0,141,255,237,0,180,0,142,255,237,0,180,0,143,255,237,0,180,0,144,255,237,0,180,0,145,255,246,0,180,0,146,255,246,0,180,0,147,255,246,0,180,0,148,255,246,0,180,0,149,255,246,0,180,0,151,255,246,0,180,0,152,255,238,0,180,0,153,255,238,0,180,0,154,255,238,0,180,0,155,255,238,0,180,0,156,255,167,0,180,0,157,255,237,0,180,0,158,255,248,0,180,0,188,255,245,0,180,0,190,255,245,0,180,0,194,255,246,0,180,0,196,255,238,0,180,0,198,255,167,0,180,0,199,255,227,0,180,0,200,255,246,0,180,0,209,255,182,0,180,0,210,255,179,0,180,0,212,255,182,0,180,0,213,255,179,0,180,0,221,255,247,0,180,0,240,255,236,0,181,0,3,255,236,0,181,0,7,255,246,0,181,0,8,255,236,0,181,0,10,255,224,0,181,0,11,255,234,0,181,0,18,255,230,0,181,0,19,255,229,0,181,0,24,255,223,0,181,0,32,255,222,0,181,0,34,255,240,0,181,0,35,255,237,0,181,0,36,255,246,0,181,0,37,255,237,0,181,0,38,255,237,0,181,0,39,255,237,0,181,0,40,255,246,0,181,0,41,255,237,0,181,0,42,255,237,0,181,0,43,255,237,0,181,0,44,255,237,0,181,0,45,255,237,0,181,0,46,255,239,0,181,0,47,255,237,0,181,0,48,255,246,0,181,0,49,255,237,0,181,0,50,255,246,0,181,0,51,255,237,0,181,0,52,255,238,0,181,0,53,255,173,0,181,0,54,255,238,0,181,0,55,255,192,0,181,0,56,255,212,0,181,0,57,255,218,0,181,0,58,255,167,0,181,0,59,255,227,0,181,0,61,255,214,0,181,0,62,255,213,0,181,0,71,255,251,0,181,0,85,255,249,0,181,0,87,255,247,0,181,0,88,255,251,0,181,0,89,255,237,0,181,0,90,255,245,0,181,0,91,255,246,0,181,0,94,255,222,0,181,0,122,255,247,0,181,0,127,255,240,0,181,0,128,255,240,0,181,0,129,255,240,0,181,0,130,255,240,0,181,0,131,255,240,0,181,0,132,255,240,0,181,0,134,255,246,0,181,0,135,255,237,0,181,0,136,255,237,0,181,0,137,255,237,0,181,0,138,255,237,0,181,0,139,255,237,0,181,0,140,255,237,0,181,0,141,255,237,0,181,0,142,255,237,0,181,0,143,255,237,0,181,0,144,255,237,0,181,0,145,255,246,0,181,0,146,255,246,0,181,0,147,255,246,0,181,0,148,255,246,0,181,0,149,255,246,0,181,0,151,255,246,0,181,0,152,255,238,0,181,0,153,255,238,0,181,0,154,255,238,0,181,0,155,255,238,0,181,0,156,255,167,0,181,0,157,255,237,0,181,0,158,255,248,0,181,0,188,255,245,0,181,0,190,255,245,0,181,0,194,255,246,0,181,0,196,255,238,0,181,0,198,255,167,0,181,0,199,255,227,0,181,0,200,255,246,0,181,0,209,255,182,0,181,0,210,255,179,0,181,0,212,255,182,0,181,0,213,255,179,0,181,0,221,255,247,0,181,0,240,255,236,0,183,0,3,255,236,0,183,0,7,255,246,0,183,0,8,255,236,0,183,0,10,255,224,0,183,0,11,255,234,0,183,0,18,255,230,0,183,0,19,255,229,0,183,0,24,255,223,0,183,0,32,255,222,0,183,0,34,255,240,0,183,0,35,255,237,0,183,0,36,255,246,0,183,0,37,255,237,0,183,0,38,255,237,0,183,0,39,255,237,0,183,0,40,255,246,0,183,0,41,255,237,0,183,0,42,255,237,0,183,0,43,255,237,0,183,0,44,255,237,0,183,0,45,255,237,0,183,0,46,255,239,0,183,0,47,255,237,0,183,0,48,255,246,0,183,0,49,255,237,0,183,0,50,255,246,0,183,0,51,255,237,0,183,0,52,255,238,0,183,0,53,255,173,0,183,0,54,255,238,0,183,0,55,255,192,0,183,0,56,255,212,0,183,0,57,255,218,0,183,0,58,255,167,0,183,0,59,255,227,0,183,0,61,255,214,0,183,0,62,255,213,0,183,0,71,255,251,0,183,0,85,255,249,0,183,0,87,255,247,0,183,0,88,255,251,0,183,0,89,255,237,0,183,0,90,255,245,0,183,0,91,255,246,0,183,0,94,255,222,0,183,0,122,255,247,0,183,0,127,255,240,0,183,0,128,255,240,0,183,0,129,255,240,0,183,0,130,255,240,0,183,0,131,255,240,0,183,0,132,255,240,0,183,0,134,255,246,0,183,0,135,255,237,0,183,0,136,255,237,0,183,0,137,255,237,0,183,0,138,255,237,0,183,0,139,255,237,0,183,0,140,255,237,0,183,0,141,255,237,0,183,0,142,255,237,0,183,0,143,255,237,0,183,0,144,255,237,0,183,0,145,255,246,0,183,0,146,255,246,0,183,0,147,255,246,0,183,0,148,255,246,0,183,0,149,255,246,0,183,0,151,255,246,0,183,0,152,255,238,0,183,0,153,255,238,0,183,0,154,255,238,0,183,0,155,255,238,0,183,0,156,255,167,0,183,0,157,255,237,0,183,0,158,255,248,0,183,0,188,255,245,0,183,0,190,255,245,0,183,0,194,255,246,0,183,0,196,255,238,0,183,0,198,255,167,0,183,0,199,255,227,0,183,0,200,255,246,0,183,0,209,255,182,0,183,0,210,255,179,0,183,0,212,255,182,0,183,0,213,255,179,0,183,0,221,255,247,0,183,0,240,255,236,0,184,0,7,255,244,0,184,0,10,255,233,0,184,0,11,255,244,0,184,0,24,255,232,0,184,0,32,255,223,0,184,0,34,255,248,0,184,0,35,255,242,0,184,0,36,255,244,0,184,0,37,255,242,0,184,0,38,255,242,0,184,0,39,255,242,0,184,0,40,255,244,0,184,0,41,255,242,0,184,0,42,255,242,0,184,0,43,255,242,0,184,0,44,255,242,0,184,0,45,255,242,0,184,0,46,255,241,0,184,0,47,255,242,0,184,0,48,255,244,0,184,0,49,255,242,0,184,0,50,255,244,0,184,0,51,255,242,0,184,0,52,255,243,0,184,0,53,255,164,0,184,0,54,255,235,0,184,0,55,255,216,0,184,0,56,255,218,0,184,0,57,255,246,0,184,0,58,255,183,0,184,0,59,255,242,0,184,0,61,255,228,0,184,0,62,255,215,0,184,0,94,255,226,0,184,0,127,255,248,0,184,0,128,255,248,0,184,0,129,255,248,0,184,0,130,255,248,0,184,0,131,255,248,0,184,0,132,255,248,0,184,0,134,255,244,0,184,0,135,255,242,0,184,0,136,255,242,0,184,0,137,255,242,0,184,0,138,255,242,0,184,0,139,255,242,0,184,0,140,255,242,0,184,0,141,255,242,0,184,0,142,255,242,0,184,0,143,255,242,0,184,0,144,255,242,0,184,0,145,255,244,0,184,0,146,255,244,0,184,0,147,255,244,0,184,0,148,255,244,0,184,0,149,255,244,0,184,0,151,255,244,0,184,0,152,255,235,0,184,0,153,255,235,0,184,0,154,255,235,0,184,0,155,255,235,0,184,0,156,255,183,0,184,0,157,255,242,0,184,0,194,255,244,0,184,0,196,255,243,0,184,0,198,255,183,0,184,0,199,255,242,0,184,0,209,255,211,0,184,0,210,255,209,0,184,0,212,255,211,0,184,0,213,255,209,0,184,0,240,255,239,0,185,0,7,255,244,0,185,0,10,255,233,0,185,0,11,255,244,0,185,0,24,255,232,0,185,0,32,255,223,0,185,0,34,255,248,0,185,0,35,255,242,0,185,0,36,255,244,0,185,0,37,255,242,0,185,0,38,255,242,0,185,0,39,255,242,0,185,0,40,255,244,0,185,0,41,255,242,0,185,0,42,255,242,0,185,0,43,255,242,0,185,0,44,255,242,0,185,0,45,255,242,0,185,0,46,255,241,0,185,0,47,255,242,0,185,0,48,255,244,0,185,0,49,255,242,0,185,0,50,255,244,0,185,0,51,255,242,0,185,0,52,255,243,0,185,0,53,255,164,0,185,0,54,255,235,0,185,0,55,255,216,0,185,0,56,255,218,0,185,0,57,255,246,0,185,0,58,255,183,0,185,0,59,255,242,0,185,0,61,255,228,0,185,0,62,255,215,0,185,0,94,255,226,0,185,0,127,255,248,0,185,0,128,255,248,0,185,0,129,255,248,0,185,0,130,255,248,0,185,0,131,255,248,0,185,0,132,255,248,0,185,0,134,255,244,0,185,0,135,255,242,0,185,0,136,255,242,0,185,0,137,255,242,0,185,0,138,255,242,0,185,0,139,255,242,0,185,0,140,255,242,0,185,0,141,255,242,0,185,0,142,255,242,0,185,0,143,255,242,0,185,0,144,255,242,0,185,0,145,255,244,0,185,0,146,255,244,0,185,0,147,255,244,0,185,0,148,255,244,0,185,0,149,255,244,0,185,0,151,255,244,0,185,0,152,255,235,0,185,0,153,255,235,0,185,0,154,255,235,0,185,0,155,255,235,0,185,0,156,255,183,0,185,0,157,255,242,0,185,0,194,255,244,0,185,0,196,255,243,0,185,0,198,255,183,0,185,0,199,255,242,0,185,0,209,255,211,0,185,0,210,255,209,0,185,0,212,255,211,0,185,0,213,255,209,0,185,0,240,255,239,0,186,0,7,255,244,0,186,0,10,255,233,0,186,0,11,255,244,0,186,0,24,255,232,0,186,0,32,255,223,0,186,0,34,255,248,0,186,0,35,255,242,0,186,0,36,255,244,0,186,0,37,255,242,0,186,0,38,255,242,0,186,0,39,255,242,0,186,0,40,255,244,0,186,0,41,255,242,0,186,0,42,255,242,0,186,0,43,255,242,0,186,0,44,255,242,0,186,0,45,255,242,0,186,0,46,255,241,0,186,0,47,255,242,0,186,0,48,255,244,0,186,0,49,255,242,0,186,0,50,255,244,0,186,0,51,255,242,0,186,0,52,255,243,0,186,0,53,255,164,0,186,0,54,255,235,0,186,0,55,255,216,0,186,0,56,255,218,0,186,0,57,255,246,0,186,0,58,255,183,0,186,0,59,255,242,0,186,0,61,255,228,0,186,0,62,255,215,0,186,0,94,255,226,0,186,0,127,255,248,0,186,0,128,255,248,0,186,0,129,255,248,0,186,0,130,255,248,0,186,0,131,255,248,0,186,0,132,255,248,0,186,0,134,255,244,0,186,0,135,255,242,0,186,0,136,255,242,0,186,0,137,255,242,0,186,0,138,255,242,0,186,0,139,255,242,0,186,0,140,255,242,0,186,0,141,255,242,0,186,0,142,255,242,0,186,0,143,255,242,0,186,0,144,255,242,0,186,0,145,255,244,0,186,0,146,255,244,0,186,0,147,255,244,0,186,0,148,255,244,0,186,0,149,255,244,0,186,0,151,255,244,0,186,0,152,255,235,0,186,0,153,255,235,0,186,0,154,255,235,0,186,0,155,255,235,0,186,0,156,255,183,0,186,0,157,255,242,0,186,0,194,255,244,0,186,0,196,255,243,0,186,0,198,255,183,0,186,0,199,255,242,0,186,0,209,255,211,0,186,0,210,255,209,0,186,0,212,255,211,0,186,0,213,255,209,0,186,0,240,255,239,0,187,0,7,255,244,0,187,0,10,255,233,0,187,0,11,255,244,0,187,0,24,255,232,0,187,0,32,255,223,0,187,0,34,255,248,0,187,0,35,255,242,0,187,0,36,255,244,0,187,0,37,255,242,0,187,0,38,255,242,0,187,0,39,255,242,0,187,0,40,255,244,0,187,0,41,255,242,0,187,0,42,255,242,0,187,0,43,255,242,0,187,0,44,255,242,0,187,0,45,255,242,0,187,0,46,255,241,0,187,0,47,255,242,0,187,0,48,255,244,0,187,0,49,255,242,0,187,0,50,255,244,0,187,0,51,255,242,0,187,0,52,255,243,0,187,0,53,255,164,0,187,0,54,255,235,0,187,0,55,255,216,0,187,0,56,255,218,0,187,0,57,255,246,0,187,0,58,255,183,0,187,0,59,255,242,0,187,0,61,255,228,0,187,0,62,255,215,0,187,0,94,255,226,0,187,0,127,255,248,0,187,0,128,255,248,0,187,0,129,255,248,0,187,0,130,255,248,0,187,0,131,255,248,0,187,0,132,255,248,0,187,0,134,255,244,0,187,0,135,255,242,0,187,0,136,255,242,0,187,0,137,255,242,0,187,0,138,255,242,0,187,0,139,255,242,0,187,0,140,255,242,0,187,0,141,255,242,0,187,0,142,255,242,0,187,0,143,255,242,0,187,0,144,255,242,0,187,0,145,255,244,0,187,0,146,255,244,0,187,0,147,255,244,0,187,0,148,255,244,0,187,0,149,255,244,0,187,0,151,255,244,0,187,0,152,255,235,0,187,0,153,255,235,0,187,0,154,255,235,0,187,0,155,255,235,0,187,0,156,255,183,0,187,0,157,255,242,0,187,0,194,255,244,0,187,0,196,255,243,0,187,0,198,255,183,0,187,0,199,255,242,0,187,0,209,255,211,0,187,0,210,255,209,0,187,0,212,255,211,0,187,0,213,255,209,0,187,0,240,255,239,0,188,0,7,255,238,0,188,0,10,255,231,0,188,0,13,255,225,0,188,0,15,255,225,0,188,0,16,255,220,0,188,0,19,255,227,0,188,0,20,255,230,0,188,0,24,255,198,0,188,0,32,255,205,0,188,0,33,255,238,0,188,0,34,255,214,0,188,0,35,255,243,0,188,0,37,255,243,0,188,0,38,255,243,0,188,0,39,255,243,0,188,0,41,255,243,0,188,0,42,255,243,0,188,0,43,255,243,0,188,0,44,255,243,0,188,0,45,255,243,0,188,0,46,255,229,0,188,0,47,255,243,0,188,0,49,255,243,0,188,0,51,255,243,0,188,0,53,255,168,0,188,0,54,255,245,0,188,0,55,255,238,0,188,0,56,255,242,0,188,0,57,255,208,0,188,0,58,255,211,0,188,0,59,255,225,0,188,0,62,255,214,0,188,0,66,255,250,0,188,0,68,255,246,0,188,0,69,255,246,0,188,0,70,255,246,0,188,0,72,255,250,0,188,0,80,255,246,0,188,0,82,255,246,0,188,0,84,255,252,0,188,0,94,255,227,0,188,0,127,255,214,0,188,0,128,255,214,0,188,0,129,255,214,0,188,0,130,255,214,0,188,0,131,255,214,0,188,0,132,255,214,0,188,0,135,255,243,0,188,0,136,255,243,0,188,0,137,255,243,0,188,0,138,255,243,0,188,0,139,255,243,0,188,0,140,255,243,0,188,0,141,255,243,0,188,0,142,255,243,0,188,0,143,255,243,0,188,0,144,255,243,0,188,0,152,255,245,0,188,0,153,255,245,0,188,0,154,255,245,0,188,0,155,255,245,0,188,0,156,255,211,0,188,0,157,255,243,0,188,0,159,255,250,0,188,0,160,255,250,0,188,0,161,255,250,0,188,0,162,255,250,0,188,0,163,255,250,0,188,0,164,255,250,0,188,0,165,255,250,0,188,0,166,255,246,0,188,0,167,255,246,0,188,0,168,255,246,0,188,0,169,255,246,0,188,0,170,255,246,0,188,0,175,255,236,0,188,0,177,255,246,0,188,0,178,255,246,0,188,0,179,255,246,0,188,0,180,255,246,0,188,0,181,255,246,0,188,0,183,255,246,0,188,0,195,255,246,0,188,0,197,255,252,0,188,0,198,255,211,0,188,0,199,255,225,0,188,0,209,255,227,0,188,0,210,255,225,0,188,0,211,255,225,0,188,0,212,255,227,0,188,0,213,255,225,0,188,0,214,255,225,0,188,0,218,255,225,0,189,0,3,255,234,0,189,0,7,255,246,0,189,0,8,255,234,0,189,0,10,255,227,0,189,0,11,255,232,0,189,0,13,255,246,0,189,0,15,255,247,0,189,0,18,255,235,0,189,0,19,255,232,0,189,0,24,255,226,0,189,0,32,255,224,0,189,0,34,255,240,0,189,0,35,255,237,0,189,0,36,255,246,0,189,0,37,255,237,0,189,0,38,255,237,0,189,0,39,255,237,0,189,0,40,255,246,0,189,0,41,255,237,0,189,0,42,255,237,0,189,0,43,255,237,0,189,0,44,255,237,0,189,0,45,255,237,0,189,0,46,255,239,0,189,0,47,255,237,0,189,0,48,255,246,0,189,0,49,255,237,0,189,0,50,255,246,0,189,0,51,255,237,0,189,0,52,255,237,0,189,0,53,255,171,0,189,0,54,255,238,0,189,0,55,255,193,0,189,0,56,255,212,0,189,0,57,255,217,0,189,0,58,255,167,0,189,0,59,255,227,0,189,0,61,255,217,0,189,0,62,255,217,0,189,0,71,255,251,0,189,0,85,255,250,0,189,0,87,255,247,0,189,0,88,255,251,0,189,0,89,255,238,0,189,0,90,255,245,0,189,0,91,255,246,0,189,0,94,255,226,0,189,0,122,255,247,0,189,0,127,255,240,0,189,0,128,255,240,0,189,0,129,255,240,0,189,0,130,255,240,0,189,0,131,255,240,0,189,0,132,255,240,0,189,0,134,255,246,0,189,0,135,255,237,0,189,0,136,255,237,0,189,0,137,255,237,0,189,0,138,255,237,0,189,0,139,255,237,0,189,0,140,255,237,0,189,0,141,255,237,0,189,0,142,255,237,0,189,0,143,255,237,0,189,0,144,255,237,0,189,0,145,255,246,0,189,0,146,255,246,0,189,0,147,255,246,0,189,0,148,255,246,0,189,0,149,255,246,0,189,0,151,255,246,0,189,0,152,255,238,0,189,0,153,255,238,0,189,0,154,255,238,0,189,0,155,255,238,0,189,0,156,255,167,0,189,0,157,255,237,0,189,0,158,255,248,0,189,0,188,255,245,0,189,0,190,255,245,0,189,0,194,255,246,0,189,0,196,255,237,0,189,0,198,255,167,0,189,0,199,255,227,0,189,0,200,255,246,0,189,0,209,255,181,0,189,0,210,255,178,0,189,0,211,255,246,0,189,0,212,255,181,0,189,0,213,255,178,0,189,0,214,255,246,0,189,0,218,255,247,0,189,0,221,255,247,0,189,0,240,255,234,0,190,0,7,255,238,0,190,0,10,255,231,0,190,0,13,255,225,0,190,0,15,255,225,0,190,0,16,255,220,0,190,0,19,255,227,0,190,0,20,255,230,0,190,0,24,255,198,0,190,0,32,255,205,0,190,0,33,255,238,0,190,0,34,255,214,0,190,0,35,255,243,0,190,0,37,255,243,0,190,0,38,255,243,0,190,0,39,255,243,0,190,0,41,255,243,0,190,0,42,255,243,0,190,0,43,255,243,0,190,0,44,255,243,0,190,0,45,255,243,0,190,0,46,255,229,0,190,0,47,255,243,0,190,0,49,255,243,0,190,0,51,255,243,0,190,0,53,255,168,0,190,0,54,255,245,0,190,0,55,255,238,0,190,0,56,255,242,0,190,0,57,255,208,0,190,0,58,255,211,0,190,0,59,255,225,0,190,0,62,255,214,0,190,0,66,255,250,0,190,0,68,255,246,0,190,0,69,255,246,0,190,0,70,255,246,0,190,0,72,255,250,0,190,0,80,255,246,0,190,0,82,255,246,0,190,0,84,255,252,0,190,0,94,255,227,0,190,0,127,255,214,0,190,0,128,255,214,0,190,0,129,255,214,0,190,0,130,255,214,0,190,0,131,255,214,0,190,0,132,255,214,0,190,0,135,255,243,0,190,0,136,255,243,0,190,0,137,255,243,0,190,0,138,255,243,0,190,0,139,255,243,0,190,0,140,255,243,0,190,0,141,255,243,0,190,0,142,255,243,0,190,0,143,255,243,0,190,0,144,255,243,0,190,0,152,255,245,0,190,0,153,255,245,0,190,0,154,255,245,0,190,0,155,255,245,0,190,0,156,255,211,0,190,0,157,255,243,0,190,0,159,255,250,0,190,0,160,255,250,0,190,0,161,255,250,0,190,0,162,255,250,0,190,0,163,255,250,0,190,0,164,255,250,0,190,0,165,255,250,0,190,0,166,255,246,0,190,0,167,255,246,0,190,0,168,255,246,0,190,0,169,255,246,0,190,0,170,255,246,0,190,0,175,255,236,0,190,0,177,255,246,0,190,0,178,255,246,0,190,0,179,255,246,0,190,0,180,255,246,0,190,0,181,255,246,0,190,0,183,255,246,0,190,0,195,255,246,0,190,0,197,255,252,0,190,0,198,255,211,0,190,0,199,255,225,0,190,0,209,255,227,0,190,0,210,255,225,0,190,0,211,255,225,0,190,0,212,255,227,0,190,0,213,255,225,0,190,0,214,255,225,0,190,0,218,255,225,0,193,0,7,255,244,0,193,0,34,255,248,0,193,0,35,255,242,0,193,0,36,255,244,0,193,0,37,255,242,0,193,0,38,255,242,0,193,0,39,255,242,0,193,0,40,255,244,0,193,0,41,255,242,0,193,0,42,255,242,0,193,0,43,255,242,0,193,0,44,255,242,0,193,0,45,255,242,0,193,0,46,255,241,0,193,0,47,255,242,0,193,0,48,255,244,0,193,0,49,255,242,0,193,0,50,255,244,0,193,0,51,255,242,0,193,0,52,255,244,0,193,0,53,255,242,0,193,0,54,255,238,0,193,0,55,255,247,0,193,0,56,255,246,0,193,0,58,255,247,0,193,0,59,255,245,0,193,0,127,255,248,0,193,0,128,255,248,0,193,0,129,255,248,0,193,0,130,255,248,0,193,0,131,255,248,0,193,0,132,255,248,0,193,0,134,255,244,0,193,0,135,255,242,0,193,0,136,255,242,0,193,0,137,255,242,0,193,0,138,255,242,0,193,0,139,255,242,0,193,0,140,255,242,0,193,0,141,255,242,0,193,0,142,255,242,0,193,0,143,255,242,0,193,0,144,255,242,0,193,0,145,255,244,0,193,0,146,255,244,0,193,0,147,255,244,0,193,0,148,255,244,0,193,0,149,255,244,0,193,0,151,255,244,0,193,0,152,255,238,0,193,0,153,255,238,0,193,0,154,255,238,0,193,0,155,255,238,0,193,0,156,255,247,0,193,0,157,255,242,0,193,0,194,255,244,0,193,0,196,255,244,0,193,0,198,255,247,0,193,0,199,255,245,0,194,0,14,255,244,0,194,0,21,255,220,0,194,0,36,255,245,0,194,0,40,255,245,0,194,0,48,255,245,0,194,0,50,255,245,0,194,0,68,255,240,0,194,0,69,255,240,0,194,0,70,255,240,0,194,0,71,255,243,0,194,0,72,255,241,0,194,0,78,255,247,0,194,0,79,255,247,0,194,0,80,255,240,0,194,0,81,255,247,0,194,0,82,255,240,0,194,0,83,255,247,0,194,0,84,255,251,0,194,0,85,255,242,0,194,0,86,255,238,0,194,0,87,255,241,0,194,0,88,255,243,0,194,0,90,255,240,0,194,0,107,255,235,0,194,0,110,255,248,0,194,0,134,255,245,0,194,0,145,255,245,0,194,0,146,255,245,0,194,0,147,255,245,0,194,0,148,255,245,0,194,0,149,255,245,0,194,0,151,255,245,0,194,0,158,255,243,0,194,0,166,255,240,0,194,0,167,255,240,0,194,0,168,255,240,0,194,0,169,255,240,0,194,0,170,255,240,0,194,0,173,0,21,0,194,0,175,255,246,0,194,0,176,255,247,0,194,0,177,255,240,0,194,0,178,255,240,0,194,0,179,255,240,0,194,0,180,255,240,0,194,0,181,255,240,0,194,0,183,255,240,0,194,0,184,255,238,0,194,0,185,255,238,0,194,0,186,255,238,0,194,0,187,255,238,0,194,0,188,255,240,0,194,0,189,255,247,0,194,0,190,255,240,0,194,0,194,255,245,0,194,0,195,255,240,0,194,0,197,255,251,0,194,0,207,255,244,0,194,0,208,255,244,0,194,0,220,255,235,0,195,0,3,255,241,0,195,0,7,255,246,0,195,0,8,255,241,0,195,0,10,255,230,0,195,0,11,255,238,0,195,0,18,255,235,0,195,0,19,255,245,0,195,0,24,255,230,0,195,0,32,255,223,0,195,0,34,255,251,0,195,0,35,255,241,0,195,0,36,255,250,0,195,0,37,255,241,0,195,0,38,255,241,0,195,0,39,255,241,0,195,0,40,255,250,0,195,0,41,255,241,0,195,0,42,255,241,0,195,0,43,255,241,0,195,0,44,255,241,0,195,0,45,255,241,0,195,0,46,255,243,0,195,0,47,255,241,0,195,0,48,255,250,0,195,0,49,255,241,0,195,0,50,255,250,0,195,0,51,255,241,0,195,0,52,255,241,0,195,0,53,255,187,0,195,0,54,255,240,0,195,0,55,255,209,0,195,0,56,255,213,0,195,0,57,255,243,0,195,0,58,255,174,0,195,0,59,255,243,0,195,0,61,255,220,0,195,0,62,255,220,0,195,0,87,255,252,0,195,0,89,255,251,0,195,0,90,255,251,0,195,0,94,255,227,0,195,0,127,255,251,0,195,0,128,255,251,0,195,0,129,255,251,0,195,0,130,255,251,0,195,0,131,255,251,0,195,0,132,255,251,0,195,0,134,255,250,0,195,0,135,255,241,0,195,0,136,255,241,0,195,0,137,255,241,0,195,0,138,255,241,0,195,0,139,255,241,0,195,0,140,255,241,0,195,0,141,255,241,0,195,0,142,255,241,0,195,0,143,255,241,0,195,0,144,255,241,0,195,0,145,255,250,0,195,0,146,255,250,0,195,0,147,255,250,0,195,0,148,255,250,0,195,0,149,255,250,0,195,0,151,255,250,0,195,0,152,255,240,0,195,0,153,255,240,0,195,0,154,255,240,0,195,0,155,255,240,0,195,0,156,255,174,0,195,0,157,255,241,0,195,0,188,255,251,0,195,0,190,255,251,0,195,0,194,255,250,0,195,0,196,255,241,0,195,0,198,255,174,0,195,0,199,255,243,0,195,0,209,255,189,0,195,0,210,255,186,0,195,0,212,255,189,0,195,0,213,255,186,0,195,0,240,255,237,0,196,0,10,255,246,0,196,0,57,255,251,0,196,0,67,255,250,0,196,0,71,255,243,0,196,0,72,255,250,0,196,0,73,255,250,0,196,0,74,255,250,0,196,0,75,255,250,0,196,0,76,255,250,0,196,0,77,255,250,0,196,0,78,255,250,0,196,0,79,255,250,0,196,0,81,255,250,0,196,0,83,255,250,0,196,0,84,255,251,0,196,0,85,255,241,0,196,0,86,255,250,0,196,0,87,255,241,0,196,0,88,255,244,0,196,0,89,255,242,0,196,0,90,255,240,0,196,0,91,255,244,0,196,0,158,255,244,0,196,0,171,255,250,0,196,0,172,255,250,0,196,0,173,255,250,0,196,0,174,255,250,0,196,0,176,255,250,0,196,0,184,255,250,0,196,0,185,255,250,0,196,0,186,255,250,0,196,0,187,255,250,0,196,0,188,255,240,0,196,0,189,255,250,0,196,0,190,255,240,0,196,0,193,255,250,0,196,0,197,255,251,0,196,0,200,255,244,0,197,0,10,255,231,0,197,0,11,255,241,0,197,0,24,255,234,0,197,0,32,255,224,0,197,0,35,255,241,0,197,0,36,255,244,0,197,0,37,255,241,0,197,0,38,255,241,0,197,0,39,255,241,0,197,0,40,255,244,0,197,0,41,255,241,0,197,0,42,255,241,0,197,0,43,255,241,0,197,0,44,255,241,0,197,0,45,255,241,0,197,0,46,255,245,0,197,0,47,255,241,0,197,0,48,255,244,0,197,0,49,255,241,0,197,0,50,255,244,0,197,0,51,255,241,0,197,0,52,255,248,0,197,0,53,255,202,0,197,0,54,255,238,0,197,0,55,255,216,0,197,0,56,255,224,0,197,0,57,255,244,0,197,0,58,255,209,0,197,0,59,255,245,0,197,0,61,255,225,0,197,0,62,255,220,0,197,0,94,255,229,0,197,0,134,255,244,0,197,0,135,255,241,0,197,0,136,255,241,0,197,0,137,255,241,0,197,0,138,255,241,0,197,0,139,255,241,0,197,0,140,255,241,0,197,0,141,255,241,0,197,0,142,255,241,0,197,0,143,255,241,0,197,0,144,255,241,0,197,0,145,255,244,0,197,0,146,255,244,0,197,0,147,255,244,0,197,0,148,255,244,0,197,0,149,255,244,0,197,0,151,255,244,0,197,0,152,255,238,0,197,0,153,255,238,0,197,0,154,255,238,0,197,0,155,255,238,0,197,0,156,255,209,0,197,0,157,255,241,0,197,0,194,255,244,0,197,0,196,255,248,0,197,0,198,255,209,0,197,0,199,255,245,0,197,0,209,255,203,0,197,0,210,255,200,0,197,0,212,255,203,0,197,0,213,255,200,0,197,0,240,255,235,0,198,0,7,255,237,0,198,0,11,0,13,0,198,0,13,255,215,0,198,0,14,255,222,0,198,0,15,255,215,0,198,0,16,255,201,0,198,0,17,255,233,0,198,0,21,255,206,0,198,0,23,255,218,0,198,0,25,255,246,0,198,0,27,255,235,0,198,0,28,255,235,0,198,0,32,0,13,0,198,0,33,255,198,0,198,0,34,255,192,0,198,0,36,255,230,0,198,0,40,255,230,0,198,0,46,255,232,0,198,0,48,255,230,0,198,0,50,255,230,0,198,0,61,0,7,0,198,0,62,0,31,0,198,0,66,255,189,0,198,0,68,255,171,0,198,0,69,255,171,0,198,0,70,255,171,0,198,0,71,255,237,0,198,0,72,255,180,0,198,0,78,255,187,0,198,0,79,255,187,0,198,0,80,255,171,0,198,0,81,255,187,0,198,0,82,255,171,0,198,0,83,255,187,0,198,0,84,255,186,0,198,0,85,255,221,0,198,0,86,255,190,0,198,0,87,255,215,0,198,0,88,255,216,0,198,0,89,255,214,0,198,0,90,255,217,0,198,0,91,255,229,0,198,0,94,0,33,0,198,0,107,255,198,0,198,0,110,255,230,0,198,0,122,255,225,0,198,0,127,255,192,0,198,0,128,255,192,0,198,0,129,255,192,0,198,0,130,255,192,0,198,0,131,255,192,0,198,0,132,255,192,0,198,0,133,255,180,0,198,0,134,255,230,0,198,0,145,255,230,0,198,0,146,255,230,0,198,0,147,255,230,0,198,0,148,255,230,0,198,0,149,255,230,0,198,0,151,255,230,0,198,0,158,255,230,0,198,0,159,255,189,0,198,0,160,255,189,0,198,0,161,255,189,0,198,0,162,255,189,0,198,0,163,255,189,0,198,0,164,255,189,0,198,0,165,255,189,0,198,0,166,255,171,0,198,0,167,255,171,0,198,0,168,255,171,0,198,0,169,255,171,0,198,0,170,255,171,0,198,0,171,0,16,0,198,0,173,0,38,0,198,0,174,0,47,0,198,0,175,255,216,0,198,0,176,255,187,0,198,0,177,255,171,0,198,0,178,255,171,0,198,0,179,255,171,0,198,0,180,255,171,0,198,0,181,255,171,0,198,0,183,255,171,0,198,0,184,255,190,0,198,0,185,255,190,0,198,0,186,255,190,0,198,0,187,255,190,0,198,0,188,255,217,0,198,0,189,255,225,0,198,0,190,255,217,0,198,0,194,255,230,0,198,0,195,255,171,0,198,0,197,255,234,0,198,0,200,255,229,0,198,0,207,255,222,0,198,0,208,255,222,0,198,0,211,255,215,0,198,0,214,255,215,0,198,0,218,255,215,0,198,0,220,255,198,0,198,0,221,255,225,0,198,0,240,0,33,0,199,0,14,255,217,0,199,0,17,255,243,0,199,0,21,255,199,0,199,0,23,255,247,0,199,0,36,255,238,0,199,0,40,255,238,0,199,0,48,255,238,0,199,0,50,255,238,0,199,0,62,0,23,0,199,0,66,255,246,0,199,0,68,255,227,0,199,0,69,255,227,0,199,0,70,255,227,0,199,0,71,255,241,0,199,0,72,255,229,0,199,0,74,255,250,0,199,0,75,255,250,0,199,0,78,255,235,0,199,0,79,255,235,0,199,0,80,255,227,0,199,0,81,255,235,0,199,0,82,255,227,0,199,0,83,255,235,0,199,0,84,255,245,0,199,0,85,255,241,0,199,0,86,255,224,0,199,0,87,255,241,0,199,0,88,255,241,0,199,0,90,255,242,0,199,0,91,255,248,0,199,0,94,0,23,0,199,0,107,255,214,0,199,0,110,255,233,0,199,0,134,255,238,0,199,0,145,255,238,0,199,0,146,255,238,0,199,0,147,255,238,0,199,0,148,255,238,0,199,0,149,255,238,0,199,0,151,255,238,0,199,0,158,255,239,0,199,0,159,255,246,0,199,0,160,255,246,0,199,0,161,255,246,0,199,0,162,255,246,0,199,0,163,255,246,0,199,0,164,255,246,0,199,0,165,255,246,0,199,0,166,255,227,0,199,0,167,255,227,0,199,0,168,255,227,0,199,0,169,255,227,0,199,0,170,255,227,0,199,0,171,0,6,0,199,0,172,255,250,0,199,0,173,0,29,0,199,0,174,0,37,0,199,0,175,255,235,0,199,0,176,255,235,0,199,0,177,255,227,0,199,0,178,255,227,0,199,0,179,255,227,0,199,0,180,255,227,0,199,0,181,255,227,0,199,0,183,255,227,0,199,0,184,255,224,0,199,0,185,255,224,0,199,0,186,255,224,0,199,0,187,255,224,0,199,0,188,255,242,0,199,0,189,255,235,0,199,0,190,255,242,0,199,0,193,255,250,0,199,0,194,255,238,0,199,0,195,255,227,0,199,0,197,255,245,0,199,0,200,255,248,0,199,0,207,255,217,0,199,0,208,255,217,0,199,0,220,255,214,0,199,0,240,0,24,0,200,0,7,255,245,0,200,0,10,255,246,0,200,0,14,255,240,0,200,0,21,255,225,0,200,0,24,255,244,0,200,0,32,255,221,0,200,0,35,255,242,0,200,0,36,255,244,0,200,0,37,255,242,0,200,0,38,255,242,0,200,0,39,255,242,0,200,0,40,255,244,0,200,0,41,255,242,0,200,0,42,255,242,0,200,0,43,255,242,0,200,0,44,255,242,0,200,0,45,255,242,0,200,0,46,255,245,0,200,0,47,255,242,0,200,0,48,255,244,0,200,0,49,255,242,0,200,0,50,255,244,0,200,0,51,255,242,0,200,0,53,255,203,0,200,0,54,255,239,0,200,0,55,255,240,0,200,0,56,255,243,0,200,0,58,255,227,0,200,0,61,255,242,0,200,0,62,255,222,0,200,0,68,255,245,0,200,0,69,255,245,0,200,0,70,255,245,0,200,0,72,255,251,0,200,0,80,255,245,0,200,0,82,255,245,0,200,0,94,255,232,0,200,0,107,255,232,0,200,0,134,255,244,0,200,0,135,255,242,0,200,0,136,255,242,0,200,0,137,255,242,0,200,0,138,255,242,0,200,0,139,255,242,0,200,0,140,255,242,0,200,0,141,255,242,0,200,0,142,255,242,0,200,0,143,255,242,0,200,0,144,255,242,0,200,0,145,255,244,0,200,0,146,255,244,0,200,0,147,255,244,0,200,0,148,255,244,0,200,0,149,255,244,0,200,0,151,255,244,0,200,0,152,255,239,0,200,0,153,255,239,0,200,0,154,255,239,0,200,0,155,255,239,0,200,0,156,255,227,0,200,0,157,255,242,0,200,0,166,255,245,0,200,0,167,255,245,0,200,0,168,255,245,0,200,0,169,255,245,0,200,0,170,255,245,0,200,0,175,255,247,0,200,0,177,255,245,0,200,0,178,255,245,0,200,0,179,255,245,0,200,0,180,255,245,0,200,0,181,255,245,0,200,0,183,255,245,0,200,0,194,255,244,0,200,0,195,255,245,0,200,0,198,255,227,0,200,0,207,255,240,0,200,0,208,255,240,0,200,0,209,255,219,0,200,0,210,255,216,0,200,0,212,255,219,0,200,0,213,255,216,0,200,0,220,255,232,0,200,0,240,255,242,0,207,0,3,255,234,0,207,0,8,255,234,0,207,0,52,255,243,0,207,0,53,255,216,0,207,0,55,255,238,0,207,0,56,255,248,0,207,0,57,255,242,0,207,0,58,255,222,0,207,0,59,255,237,0,207,0,71,255,247,0,207,0,85,255,248,0,207,0,89,255,247,0,207,0,91,255,231,0,207,0,156,255,222,0,207,0,158,255,248,0,207,0,196,255,243,0,207,0,198,255,222,0,207,0,199,255,237,0,207,0,200,255,231,0,207,0,210,255,193,0,207,0,213,255,193,0,208,0,3,255,234,0,208,0,8,255,234,0,208,0,52,255,243,0,208,0,53,255,216,0,208,0,55,255,238,0,208,0,56,255,248,0,208,0,57,255,242,0,208,0,58,255,222,0,208,0,59,255,237,0,208,0,71,255,247,0,208,0,85,255,248,0,208,0,89,255,247,0,208,0,91,255,231,0,208,0,156,255,222,0,208,0,158,255,248,0,208,0,196,255,243,0,208,0,198,255,222,0,208,0,199,255,237,0,208,0,200,255,231,0,208,0,210,255,193,0,208,0,213,255,193,0,209,0,13,255,123,0,209,0,15,255,124,0,209,0,34,255,205,0,209,0,46,255,236,0,209,0,66,255,194,0,209,0,68,255,182,0,209,0,69,255,182,0,209,0,70,255,182,0,209,0,71,255,243,0,209,0,72,255,189,0,209,0,78,255,211,0,209,0,79,255,211,0,209,0,80,255,182,0,209,0,81,255,211,0,209,0,82,255,182,0,209,0,83,255,211,0,209,0,84,255,193,0,209,0,85,255,248,0,209,0,86,255,213,0,209,0,87,255,226,0,209,0,88,255,227,0,209,0,89,255,225,0,209,0,90,255,227,0,209,0,91,255,217,0,209,0,127,255,205,0,209,0,128,255,205,0,209,0,129,255,205,0,209,0,130,255,205,0,209,0,131,255,205,0,209,0,132,255,205,0,209,0,133,255,190,0,209,0,158,255,245,0,209,0,159,255,194,0,209,0,160,255,194,0,209,0,161,255,194,0,209,0,162,255,194,0,209,0,163,255,194,0,209,0,164,255,194,0,209,0,165,255,194,0,209,0,166,255,182,0,209,0,167,255,182,0,209,0,168,255,182,0,209,0,169,255,182,0,209,0,170,255,182,0,209,0,173,0,37,0,209,0,175,255,235,0,209,0,176,255,211,0,209,0,177,255,182,0,209,0,178,255,182,0,209,0,179,255,182,0,209,0,180,255,182,0,209,0,181,255,182,0,209,0,183,255,182,0,209,0,184,255,213,0,209,0,185,255,213,0,209,0,186,255,213,0,209,0,187,255,213,0,209,0,188,255,227,0,209,0,189,255,211,0,209,0,190,255,227,0,209,0,195,255,182,0,209,0,197,255,193,0,209,0,200,255,217,0,209,0,218,255,124,0,210,0,7,255,239,0,210,0,11,0,5,0,210,0,13,255,110,0,210,0,14,255,181,0,210,0,15,255,110,0,210,0,16,255,209,0,210,0,33,255,210,0,210,0,34,255,200,0,210,0,36,255,234,0,210,0,40,255,234,0,210,0,46,255,234,0,210,0,48,255,234,0,210,0,50,255,234,0,210,0,58,0,6,0,210,0,66,255,179,0,210,0,68,255,167,0,210,0,69,255,167,0,210,0,70,255,167,0,210,0,71,255,243,0,210,0,72,255,174,0,210,0,78,255,198,0,210,0,79,255,198,0,210,0,80,255,167,0,210,0,81,255,198,0,210,0,82,255,167,0,210,0,83,255,198,0,210,0,84,255,178,0,210,0,85,255,244,0,210,0,86,255,200,0,210,0,87,255,214,0,210,0,88,255,215,0,210,0,89,255,213,0,210,0,90,255,215,0,210,0,91,255,204,0,210,0,107,255,192,0,210,0,110,255,245,0,210,0,122,255,220,0,210,0,127,255,200,0,210,0,128,255,200,0,210,0,129,255,200,0,210,0,130,255,200,0,210,0,131,255,200,0,210,0,132,255,200,0,210,0,133,255,184,0,210,0,134,255,234,0,210,0,145,255,234,0,210,0,146,255,234,0,210,0,147,255,234,0,210,0,148,255,234,0,210,0,149,255,234,0,210,0,151,255,234,0,210,0,156,0,6,0,210,0,158,255,241,0,210,0,159,255,179,0,210,0,160,255,179,0,210,0,161,255,187,0,210,0,162,255,179,0,210,0,163,255,179,0,210,0,164,255,179,0,210,0,165,255,179,0,210,0,166,255,167,0,210,0,167,255,167,0,210,0,168,255,167,0,210,0,169,255,174,0,210,0,170,255,167,0,210,0,173,0,44,0,210,0,174,0,28,0,210,0,175,255,237,0,210,0,176,255,198,0,210,0,177,255,167,0,210,0,178,255,167,0,210,0,179,255,167,0,210,0,180,255,167,0,210,0,181,255,167,0,210,0,183,255,167,0,210,0,184,255,200,0,210,0,185,255,200,0,210,0,186,255,200,0,210,0,187,255,200,0,210,0,188,255,215,0,210,0,189,255,224,0,210,0,190,255,215,0,210,0,194,255,234,0,210,0,195,255,167,0,210,0,197,255,232,0,210,0,198,0,6,0,210,0,200,255,204,0,210,0,207,255,181,0,210,0,208,255,181,0,210,0,211,255,110,0,210,0,214,255,110,0,210,0,218,255,110,0,210,0,220,255,192,0,210,0,221,255,220,0,210,0,240,0,9,0,211,0,3,255,146,0,211,0,8,255,146,0,211,0,36,255,242,0,211,0,40,255,242,0,211,0,48,255,242,0,211,0,50,255,242,0,211,0,53,255,214,0,211,0,54,255,243,0,211,0,55,255,213,0,211,0,56,255,226,0,211,0,58,255,215,0,211,0,71,255,241,0,211,0,85,255,239,0,211,0,87,255,227,0,211,0,88,255,236,0,211,0,90,255,222,0,211,0,134,255,242,0,211,0,145,255,242,0,211,0,146,255,242,0,211,0,147,255,242,0,211,0,148,255,242,0,211,0,149,255,242,0,211,0,151,255,242,0,211,0,152,255,243,0,211,0,153,255,243,0,211,0,154,255,243,0,211,0,155,255,243,0,211,0,156,255,215,0,211,0,158,255,242,0,211,0,188,255,222,0,211,0,190,255,222,0,211,0,194,255,242,0,211,0,198,255,215,0,211,0,210,255,121,0,211,0,213,255,121,0,212,0,13,255,123,0,212,0,15,255,124,0,212,0,34,255,205,0,212,0,46,255,236,0,212,0,66,255,194,0,212,0,68,255,182,0,212,0,69,255,182,0,212,0,70,255,182,0,212,0,71,255,243,0,212,0,72,255,189,0,212,0,78,255,211,0,212,0,79,255,211,0,212,0,80,255,182,0,212,0,81,255,211,0,212,0,82,255,182,0,212,0,83,255,211,0,212,0,84,255,193,0,212,0,85,255,248,0,212,0,86,255,213,0,212,0,87,255,226,0,212,0,88,255,227,0,212,0,89,255,225,0,212,0,90,255,227,0,212,0,91,255,217,0,212,0,127,255,205,0,212,0,128,255,205,0,212,0,129,255,205,0,212,0,130,255,205,0,212,0,131,255,205,0,212,0,132,255,205,0,212,0,133,255,190,0,212,0,158,255,245,0,212,0,159,255,194,0,212,0,160,255,194,0,212,0,161,255,194,0,212,0,162,255,194,0,212,0,163,255,194,0,212,0,164,255,194,0,212,0,165,255,194,0,212,0,166,255,182,0,212,0,167,255,182,0,212,0,168,255,182,0,212,0,169,255,182,0,212,0,170,255,182,0,212,0,173,0,37,0,212,0,175,255,235,0,212,0,176,255,211,0,212,0,177,255,182,0,212,0,178,255,182,0,212,0,179,255,182,0,212,0,180,255,182,0,212,0,181,255,182,0,212,0,183,255,182,0,212,0,184,255,213,0,212,0,185,255,213,0,212,0,186,255,213,0,212,0,187,255,213,0,212,0,188,255,227,0,212,0,189,255,211,0,212,0,190,255,227,0,212,0,195,255,182,0,212,0,197,255,193,0,212,0,200,255,217,0,212,0,218,255,124,0,213,0,7,255,239,0,213,0,11,0,5,0,213,0,13,255,110,0,213,0,14,255,181,0,213,0,15,255,110,0,213,0,16,255,209,0,213,0,33,255,210,0,213,0,34,255,200,0,213,0,36,255,234,0,213,0,40,255,234,0,213,0,46,255,234,0,213,0,48,255,234,0,213,0,50,255,234,0,213,0,58,0,6,0,213,0,66,255,179,0,213,0,68,255,167,0,213,0,69,255,167,0,213,0,70,255,167,0,213,0,71,255,243,0,213,0,72,255,174,0,213,0,78,255,198,0,213,0,79,255,198,0,213,0,80,255,167,0,213,0,81,255,198,0,213,0,82,255,167,0,213,0,83,255,198,0,213,0,84,255,178,0,213,0,85,255,244,0,213,0,86,255,200,0,213,0,87,255,214,0,213,0,88,255,215,0,213,0,89,255,213,0,213,0,90,255,215,0,213,0,91,255,204,0,213,0,107,255,192,0,213,0,110,255,245,0,213,0,122,255,220,0,213,0,127,255,200,0,213,0,128,255,200,0,213,0,129,255,200,0,213,0,130,255,200,0,213,0,131,255,200,0,213,0,132,255,200,0,213,0,133,255,184,0,213,0,134,255,234,0,213,0,145,255,234,0,213,0,146,255,234,0,213,0,147,255,234,0,213,0,148,255,234,0,213,0,149,255,234,0,213,0,151,255,234,0,213,0,156,0,6,0,213,0,158,255,241,0,213,0,159,255,179,0,213,0,160,255,179,0,213,0,161,255,187,0,213,0,162,255,179,0,213,0,163,255,179,0,213,0,164,255,179,0,213,0,165,255,179,0,213,0,166,255,167,0,213,0,167,255,167,0,213,0,168,255,167,0,213,0,169,255,174,0,213,0,170,255,167,0,213,0,173,0,44,0,213,0,174,0,28,0,213,0,175,255,237,0,213,0,176,255,198,0,213,0,177,255,167,0,213,0,178,255,167,0,213,0,179,255,167,0,213,0,180,255,167,0,213,0,181,255,167,0,213,0,183,255,167,0,213,0,184,255,200,0,213,0,185,255,200,0,213,0,186,255,200,0,213,0,187,255,200,0,213,0,188,255,215,0,213,0,189,255,224,0,213,0,190,255,215,0,213,0,194,255,234,0,213,0,195,255,167,0,213,0,197,255,232,0,213,0,198,0,6,0,213,0,200,255,204,0,213,0,207,255,181,0,213,0,208,255,181,0,213,0,211,255,110,0,213,0,214,255,110,0,213,0,218,255,110,0,213,0,220,255,192,0,213,0,221,255,220,0,213,0,240,0,9,0,214,0,3,255,146,0,214,0,8,255,146,0,214,0,36,255,242,0,214,0,40,255,242,0,214,0,48,255,242,0,214,0,50,255,242,0,214,0,53,255,214,0,214,0,54,255,243,0,214,0,55,255,213,0,214,0,56,255,226,0,214,0,58,255,215,0,214,0,71,255,241,0,214,0,85,255,239,0,214,0,87,255,227,0,214,0,88,255,236,0,214,0,90,255,222,0,214,0,134,255,242,0,214,0,145,255,242,0,214,0,146,255,242,0,214,0,147,255,242,0,214,0,148,255,242,0,214,0,149,255,242,0,214,0,151,255,242,0,214,0,152,255,243,0,214,0,153,255,243,0,214,0,154,255,243,0,214,0,155,255,243,0,214,0,156,255,215,0,214,0,158,255,242,0,214,0,188,255,222,0,214,0,190,255,222,0,214,0,194,255,242,0,214,0,198,255,215,0,214,0,210,255,121,0,214,0,213,255,121,0,220,0,53,255,197,0,220,0,55,255,245,0,220,0,58,255,226,0,220,0,68,255,247,0,220,0,69,255,247,0,220,0,70,255,247,0,220,0,80,255,247,0,220,0,82,255,247,0,220,0,156,255,226,0,220,0,166,255,247,0,220,0,167,255,247,0,220,0,168,255,247,0,220,0,169,255,247,0,220,0,170,255,247,0,220,0,177,255,247,0,220,0,178,255,247,0,220,0,179,255,247,0,220,0,180,255,247,0,220,0,181,255,247,0,220,0,183,255,247,0,220,0,195,255,247,0,220,0,198,255,226,0,220,0,210,255,229,0,220,0,213,255,229,0,221,0,3,255,241,0,221,0,8,255,241,0,221,0,34,255,247,0,221,0,52,255,234,0,221,0,53,255,195,0,221,0,55,255,220,0,221,0,56,255,230,0,221,0,57,255,224,0,221,0,58,255,198,0,221,0,59,255,223,0,221,0,85,255,247,0,221,0,89,255,236,0,221,0,90,255,248,0,221,0,91,255,233,0,221,0,127,255,247,0,221,0,128,255,247,0,221,0,129,255,247,0,221,0,130,255,247,0,221,0,131,255,247,0,221,0,132,255,247,0,221,0,133,255,243,0,221,0,143,0,6,0,221,0,156,255,198,0,221,0,158,255,248,0,221,0,188,255,248,0,221,0,190,255,248,0,221,0,196,255,234,0,221,0,198,255,198,0,221,0,199,255,223,0,221,0,200,255,233,0,221,0,210,255,204,0,221,0,213,255,204,0,240,0,34,255,232,0,240,0,127,255,232,0,240,0,128,255,232,0,240,0,129,255,232,0,240,0,130,255,232,0,240,0,131,255,232,0,240,0,132,255,232,0,240,0,133,255,228,0,240,0,143,0,10,0,240,0,173,0,11,0,0,0,26,0,26,0,128,0,180,1,222,3,150,5,20,7,18,7,50,7,152,7,254,8,126,8,236,9,44,9,76,9,118,9,164,10,242,11,84,12,94,13,186,14,88,15,116,16,222,17,80,18,196,20,20,20,90,20,182,20,234,21,28,21,86,22,64,23,106,24,52,25,156,26,174,27,122,27,230,28,78,29,42,29,170,29,242,30,62,30,238,31,56,32,156,33,74,34,90,35,34,36,114,37,108,39,118,39,180,40,192,41,132,42,144,43,146,44,30,45,24,45,82,45,126,45,186,45,250,46,40,46,116,47,190,48,152,49,132,50,84,51,134,52,34,54,126,55,48,55,150,56,32,56,246,57,70,58,122,59,70,60,44,61,44,62,12,62,124,63,222,64,108,65,32,65,192,66,202,67,216,68,110,69,122,70,22,70,62,70,222,71,82,71,82,71,186,72,170,73,160,74,142,75,104,75,162,77,148,77,202,79,230,80,216,81,64,81,112,81,162,83,120,84,100,84,188,85,156,86,186,86,252,87,166,88,14,88,64,88,106,88,216,89,124,89,248,90,38,90,82,90,128,91,94,91,142,91,180,91,214,91,248,92,44,92,104,93,92,93,104,93,154,93,198,93,226,94,12,94,68,94,88,94,126,94,170,95,162,95,188,95,216,95,254,96,28,96,56,96,100,96,180,98,188,98,230,99,12,99,46,99,92,99,132,100,86,101,182,101,210,101,238,102,6,102,34,102,78,102,110,104,160,104,182,104,206,104,230,105,4,105,26,105,66,105,106,105,134,105,174,107,26,107,44,107,68,107,106,107,134,107,158,107,184,107,248,109,120,109,152,109,194,109,234,110,14,110,32,111,30,111,56,111,86,111,108,111,180,113,68,115,64,115,96,115,124,115,172,115,202,115,232,116,178,117,30,117,112,117,194,118,158,119,90,119,114,119,142,119,188,119,234,120,26,120,112,120,200,121,40,121,166,122,108,122,152,122,236,125,28,125,154,126,18,127,134,127,238,128,186,129,228,130,64,131,176,132,150,132,172,132,192,132,212,132,232,132,254,133,18,133,40,133,60,133,86,133,108,134,206,135,148,136,128,137,136,138,34,138,132,138,236,139,180,140,10,140,76,140,156,141,52,142,108,143,160,144,190,146,12,146,232,147,174,149,108,150,84,152,6,152,82,153,10,153,184,155,6,155,248,156,152,157,86,158,238,159,60,0,1,0,0,1,13,0,106,0,7,0,71,0,4,0,1,0,0,0,0,0,10,0,0,2,0,4,21,0,3,0,1,0,0,0,31,1,122,0,1,0,0,0,0,0,0,0,106,0,0,0,1,0,0,0,0,0,1,0,5,0,106,0,1,0,0,0,0,0,2,0,7,0,111,0,1,0,0,0,0,0,3,0,75,0,118,0,1,0,0,0,0,0,4,0,13,0,193,0,1,0,0,0,0,0,5,0,13,0,206,0,1,0,0,0,0,0,6,0,13,0,219,0,1,0,0,0,0,0,7,0,95,0,232,0,1,0,0,0,0,0,8,0,62,1,71,0,1,0,0,0,0,0,9,0,15,1,133,0,1,0,0,0,0,0,10,0,127,1,148,0,1,0,0,0,0,0,11,0,17,2,19,0,1,0,0,0,0,0,12,0,17,2,36,0,1,0,0,0,0,0,13,0,255,2,53,0,1,0,0,0,0,0,14,0,26,3,52,0,1,0,0,0,0,0,18,0,13,3,78,0,3,0,1,4,9,0,0,0,212,3,91,0,3,0,1,4,9,0,1,0,10,4,47,0,3,0,1,4,9,0,2,0,14,4,57,0,3,0,1,4,9,0,3,0,150,4,71,0,3,0,1,4,9,0,4,0,26,4,221,0,3,0,1,4,9,0,5,0,26,4,247,0,3,0,1,4,9,0,6,0,26,5,17,0,3,0,1,4,9,0,7,0,190,5,43,0,3,0,1,4,9,0,8,0,124,5,233,0,3,0,1,4,9,0,9,0,30,6,101,0,3,0,1,4,9,0,10,0,254,6,131,0,3,0,1,4,9,0,11,0,34,7,129,0,3,0,1,4,9,0,12,0,34,7,163,0,3,0,1,4,9,0,13,1,254,7,197,0,3,0,1,4,9,0,14,0,52,9,195,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,49,49,32,98,121,32,80,97,98,108,111,32,73,109,112,97,108,108,97,114,105,46,32,119,119,119,46,105,109,112,97,108,108,97,114,105,46,99,111,109,32,73,103,105,110,111,32,77,97,114,105,110,105,46,32,119,119,119,46,105,107,101,114,110,46,99,111,109,46,32,65,108,108,32,114,105,103,104,116,115,32,114,101,115,101,114,118,101,100,46,67,97,98,105,110,82,101,103,117,108,97,114,80,97,98,108,111,73,109,112,97,108,108,97,114,105,46,119,119,119,46,105,109,112,97,108,108,97,114,105,46,99,111,109,73,103,105,110,111,77,97,114,105,110,105,46,119,119,119,46,105,107,101,114,110,46,99,111,109,58,32,67,97,98,105,110,32,66,111,108,100,58,32,50,48,49,48,67,97,98,105,110,32,82,101,103,117,108,97,114,86,101,114,115,105,111,110,32,49,46,48,48,53,67,97,98,105,110,45,82,101,103,117,108,97,114,67,97,98,105,110,32,82,101,103,117,108,97,114,32,105,115,32,97,32,116,114,97,100,101,109,97,114,107,32,111,102,32,80,97,98,108,111,32,73,109,112,97,108,108,97,114,105,46,32,119,119,119,46,105,109,112,97,108,108,97,114,105,46,99,111,109,32,73,103,105,110,111,32,77,97,114,105,110,105,46,32,119,119,119,46,105,107,101,114,110,46,99,111,109,46,80,97,98,108,111,32,73,109,112,97,108,108,97,114,105,46,32,119,119,119,46,105,109,112,97,108,108,97,114,105,46,99,111,109,32,73,103,105,110,111,32,77,97,114,105,110,105,46,32,119,119,119,46,105,107,101,114,110,46,99,111,109,80,97,98,108,111,32,73,109,112,97,108,108,97,114,105,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,49,49,32,98,121,32,80,97,98,108,111,32,73,109,112,97,108,108,97,114,105,46,32,119,119,119,46,105,109,112,97,108,108,97,114,105,46,99,111,109,32,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,49,49,32,98,121,32,73,103,105,110,111,32,77,97,114,105,110,105,46,32,119,119,119,46,105,107,101,114,110,46,99,111,109,32,65,108,108,32,114,105,103,104,116,115,32,114,101,115,101,114,118,101,100,46,119,119,119,46,105,109,112,97,108,108,97,114,105,46,99,111,109,119,119,119,46,105,109,112,97,108,108,97,114,105,46,99,111,109,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,49,48,44,32,80,97,98,108,111,32,73,109,112,97,108,108,97,114,105,32,40,119,119,119,46,105,109,112,97,108,108,97,114,105,46,99,111,109,124,105,109,112,97,108,108,97,114,105,64,103,109,97,105,108,46,99,111,109,41,44,13,10,119,105,116,104,32,82,101,115,101,114,118,101,100,32,70,111,110,116,32,78,97,109,101,32,67,97,98,105,110,46,13,10,84,104,105,115,32,70,111,110,116,32,83,111,102,116,119,97,114,101,32,105,115,32,108,105,99,101,110,115,101,100,32,117,110,100,101,114,32,116,104,101,32,83,73,76,32,79,112,101,110,32,70,111,110,116,32,76,105,99,101,110,115,101,44,32,86,101,114,115,105,111,110,32,49,46,49,46,13,10,84,104,105,115,32,108,105,99,101,110,115,101,32,105,115,32,97,118,97,105,108,97,98,108,101,32,119,105,116,104,32,97,32,70,65,81,32,97,116,58,32,104,116,116,112,58,47,47,115,99,114,105,112,116,115,46,115,105,108,46,111,114,103,47,79,70,76,104,116,116,112,58,47,47,115,99,114,105,112,116,115,46,115,105,108,46,111,114,103,47,79,70,76,67,97,98,105,110,32,82,101,103,117,108,97,114,0,67,0,111,0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,32,0,40,0,99,0,41,0,32,0,50,0,48,0,49,0,49,0,32,0,98,0,121,0,32,0,80,0,97,0,98,0,108,0,111,0,32,0,73,0,109,0,112,0,97,0,108,0,108,0,97,0,114,0,105,0,46,0,32,0,119,0,119,0,119,0,46,0,105,0,109,0,112,0,97,0,108,0,108,0,97,0,114,0,105,0,46,0,99,0,111,0,109,0,32,0,73,0,103,0,105,0,110,0,111,0,32,0,77,0,97,0,114,0,105,0,110,0,105,0,46,0,32,0,119,0,119,0,119,0,46,0,105,0,107,0,101,0,114,0,110,0,46,0,99,0,111,0,109,0,46,0,32,0,65,0,108,0,108,0,32,0,114,0,105,0,103,0,104,0,116,0,115,0,32,0,114,0,101,0,115,0,101,0,114,0,118,0,101,0,100,0,46,0,67,0,97,0,98,0,105,0,110,0,82,0,101,0,103,0,117,0,108,0,97,0,114,0,80,0,97,0,98,0,108,0,111,0,73,0,109,0,112,0,97,0,108,0,108,0,97,0,114,0,105,0,46,0,119,0,119,0,119,0,46,0,105,0,109,0,112,0,97,0,108,0,108,0,97,0,114,0,105,0,46,0,99,0,111,0,109,0,73,0,103,0,105,0,110,0,111,0,77,0,97,0,114,0,105,0,110,0,105,0,46,0,119,0,119,0,119,0,46,0,105,0,107,0,101,0,114,0,110,0,46,0,99,0,111,0,109,0,58,0,32,0,67,0,97,0,98,0,105,0,110,0,32,0,66,0,111,0,108,0,100,0,58,0,32,0,50,0,48,0,49,0,48,0,67,0,97,0,98,0,105,0,110,0,32,0,82,0,101,0,103,0,117,0,108,0,97,0,114,0,86,0,101,0,114,0,115,0,105,0,111,0,110,0,32,0,49,0,46,0,48,0,48,0,53,0,67,0,97,0,98,0,105,0,110,0,45,0,82,0,101,0,103,0,117,0,108,0,97,0,114,0,67,0,97,0,98,0,105,0,110,0,32,0,82,0,101,0,103,0,117,0,108,0,97,0,114,0,32,0,105,0,115,0,32,0,97,0,32,0,116,0,114,0,97,0,100,0,101,0,109,0,97,0,114,0,107,0,32,0,111,0,102,0,32,0,80,0,97,0,98,0,108,0,111,0,32,0,73,0,109,0,112,0,97,0,108,0,108,0,97,0,114,0,105,0,46,0,32,0,119,0,119,0,119,0,46,0,105,0,109,0,112,0,97,0,108,0,108,0,97,0,114,0,105,0,46,0,99,0,111,0,109,0,32,0,73,0,103,0,105,0,110,0,111,0,32,0,77,0,97,0,114,0,105,0,110,0,105,0,46,0,32,0,119,0,119,0,119,0,46,0,105,0,107,0,101,0,114,0,110,0,46,0,99,0,111,0,109,0,46,0,80,0,97,0,98,0,108,0,111,0,32,0,73,0,109,0,112,0,97,0,108,0,108,0,97,0,114,0,105,0,46,0,32,0,119,0,119,0,119,0,46,0,105,0,109,0,112,0,97,0,108,0,108,0,97,0,114,0,105,0,46,0,99,0,111,0,109,0,32,0,73,0,103,0,105,0,110,0,111,0,32,0,77,0,97,0,114,0,105,0,110,0,105,0,46,0,32,0,119,0,119,0,119,0,46,0,105,0,107,0,101,0,114,0,110,0,46,0,99,0,111,0,109,0,80,0,97,0,98,0,108,0,111,0,32,0,73,0,109,0,112,0,97,0,108,0,108,0,97,0,114,0,105,0,67,0,111,0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,32,0,40,0,99,0,41,0,32,0,50,0,48,0,49,0,49,0,32,0,98,0,121,0,32,0,80,0,97,0,98,0,108,0,111,0,32,0,73,0,109,0,112,0,97,0,108,0,108,0,97,0,114,0,105,0,46,0,32,0,119,0,119,0,119,0,46,0,105,0,109,0,112,0,97,0,108,0,108,0,97,0,114,0,105,0,46,0,99,0,111,0,109,0,32,0,67,0,111,0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,32,0,40,0,99,0,41,0,32,0,50,0,48,0,49,0,49,0,32,0,98,0,121,0,32,0,73,0,103,0,105,0,110,0,111,0,32,0,77,0,97,0,114,0,105,0,110,0,105,0,46,0,32,0,119,0,119,0,119,0,46,0,105,0,107,0,101,0,114,0,110,0,46,0,99,0,111,0,109,0,32,0,65,0,108,0,108,0,32,0,114,0,105,0,103,0,104,0,116,0,115,0,32,0,114,0,101,0,115,0,101,0,114,0,118,0,101,0,100,0,46,0,119,0,119,0,119,0,46,0,105,0,109,0,112,0,97,0,108,0,108,0,97,0,114,0,105,0,46,0,99,0,111,0,109,0,119,0,119,0,119,0,46,0,105,0,109,0,112,0,97,0,108,0,108,0,97,0,114,0,105,0,46,0,99,0,111,0,109,0,67,0,111,0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,32,0,40,0,99,0,41,0,32,0,50,0,48,0,49,0,48,0,44,0,32,0,80,0,97,0,98,0,108,0,111,0,32,0,73,0,109,0,112,0,97,0,108,0,108,0,97,0,114,0,105,0,32,0,40,0,119,0,119,0,119,0,46,0,105,0,109,0,112,0,97,0,108,0,108,0,97,0,114,0,105,0,46,0,99,0,111,0,109,0,124,0,105,0,109,0,112,0,97,0,108,0,108,0,97,0,114,0,105,0,64,0,103,0,109,0,97,0,105,0,108,0,46,0,99,0,111,0,109,0,41,0,44,0,13,0,10,0,119,0,105,0,116,0,104,0,32,0,82,0,101,0,115,0,101,0,114,0,118,0,101,0,100,0,32,0,70,0,111,0,110,0,116,0,32,0,78,0,97,0,109,0,101,0,32,0,67,0,97,0,98,0,105,0,110,0,46,0,13,0,10,0,84,0,104,0,105,0,115,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,105,0,115,0,32,0,108,0,105,0,99,0,101,0,110,0,115,0,101,0,100,0,32,0,117,0,110,0,100,0,101,0,114,0,32,0,116,0,104,0,101,0,32,0,83,0,73,0,76,0,32,0,79,0,112,0,101,0,110,0,32,0,70,0,111,0,110,0,116,0,32,0,76,0,105,0,99,0,101,0,110,0,115,0,101,0,44,0,32,0,86,0,101,0,114,0,115,0,105,0,111,0,110,0,32,0,49,0,46,0,49,0,46,0,13,0,10,0,84,0,104,0,105,0,115,0,32,0,108,0,105,0,99,0,101,0,110,0,115,0,101,0,32,0,105,0,115,0,32,0,97,0,118,0,97,0,105,0,108,0,97,0,98,0,108,0,101,0,32,0,119,0,105,0,116,0,104,0,32,0,97,0,32,0,70,0,65,0,81,0,32,0,97,0,116,0,58,0,32,0,104,0,116,0,116,0,112,0,58,0,47,0,47,0,115,0,99,0,114,0,105,0,112,0,116,0,115,0,46,0,115,0,105,0,108,0,46,0,111,0,114,0,103,0,47,0,79,0,70,0,76,0,104,0,116,0,116,0,112,0,58,0,47,0,47,0,115,0,99,0,114,0,105,0,112,0,116,0,115,0,46,0,115,0,105,0,108,0,46,0,111,0,114,0,103,0,47,0,79,0,70,0,76,0,0,0,0,2,0,0,0,0,0,0,255,181,0,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,13,0,0,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10,0,11,0,12,0,13,0,14,0,15,0,16,0,17,0,18,0,19,0,20,0,21,0,22,0,23,0,24,0,25,0,26,0,27,0,28,0,29,0,30,0,31,0,32,0,33,0,34,0,35,0,36,0,37,0,38,0,39,0,40,0,41,0,42,0,43,0,44,0,45,0,46,0,47,0,48,0,49,0,50,0,51,0,52,0,53,0,54,0,55,0,56,0,57,0,58,0,59,0,60,0,61,0,62,0,63,0,64,0,65,0,66,0,67,0,68,0,69,0,70,0,71,0,72,0,73,0,74,0,75,0,76,0,77,0,78,0,79,0,80,0,81,0,82,0,83,0,84,0,85,0,86,0,87,0,88,0,89,0,90,0,91,0,92,0,93,0,94,0,95,0,96,0,97,1,2,0,163,0,132,0,133,0,189,0,150,0,232,0,134,0,142,0,139,0,157,0,169,0,164,1,3,0,138,0,131,0,147,1,4,1,5,0,141,1,6,0,136,1,7,0,222,1,8,0,158,0,170,0,245,0,244,0,246,0,162,0,173,0,201,0,199,0,174,0,98,0,99,0,144,0,100,0,203,0,101,0,200,0,202,0,207,0,204,0,205,0,206,0,233,0,102,0,211,0,208,0,209,0,175,0,103,0,240,0,145,0,214,0,212,0,213,0,104,0,235,0,237,0,137,0,106,0,105,0,107,0,109,0,108,0,110,0,160,0,111,0,113,0,112,0,114,0,115,0,117,0,116,0,118,0,119,0,234,0,120,0,122,0,121,0,123,0,125,0,124,0,184,0,161,0,127,0,126,0,128,0,129,0,236,0,238,0,186,0,255,1,0,0,215,0,176,0,177,0,228,0,229,0,187,0,230,0,231,0,166,1,9,0,216,0,225,0,221,0,217,0,178,0,179,0,182,0,183,0,196,0,180,0,181,0,197,0,130,0,194,0,135,0,171,0,198,0,190,0,191,1,10,1,11,1,12,1,13,1,14,1,15,1,16,1,17,1,18,1,19,1,20,1,21,1,22,1,23,1,24,1,25,1,26,1,27,0,140,1,28,1,29,1,30,1,31,1,32,1,33,1,34,1,35,1,36,1,37,1,38,1,39,1,40,1,41,1,42,1,43,1,44,1,45,1,46,1,47,1,48,1,49,1,50,1,51,1,52,1,53,1,54,1,55,7,117,110,105,48,48,65,48,7,117,110,105,48,48,65,68,7,117,110,105,48,48,66,50,7,117,110,105,48,48,66,51,7,117,110,105,48,48,66,53,14,112,101,114,105,111,100,99,101,110,116,101,114,101,100,7,117,110,105,48,48,66,57,7,117,110,105,48,50,51,55,7,117,110,105,50,48,55,48,7,117,110,105,50,48,55,52,7,117,110,105,50,48,55,53,7,117,110,105,50,48,55,54,7,117,110,105,50,48,55,55,7,117,110,105,50,48,55,56,7,117,110,105,50,48,55,57,7,117,110,105,50,48,56,48,7,117,110,105,50,48,56,49,7,117,110,105,50,48,56,50,7,117,110,105,50,48,56,51,7,117,110,105,50,48,56,52,7,117,110,105,50,48,56,53,7,117,110,105,50,48,56,54,7,117,110,105,50,48,56,55,7,117,110,105,50,48,56,56,7,117,110,105,50,48,56,57,4,69,117,114,111,4,66,46,115,99,4,67,46,115,99,4,68,46,115,99,4,69,46,115,99,4,70,46,115,99,4,71,46,115,99,4,72,46,115,99,4,73,46,115,99,4,74,46,115,99,4,75,46,115,99,4,65,46,115,99,4,77,46,115,99,4,78,46,115,99,4,79,46,115,99,5,65,69,46,115,99,4,80,46,115,99,4,81,46,115,99,4,82,46,115,99,4,83,46,115,99,4,84,46,115,99,4,85,46,115,99,4,86,46,115,99,4,87,46,115,99,4,88,46,115,99,4,89,46,115,99,4,90,46,115,99,5,79,69,46,115,99,4,76,46,115,99,0,0,184,0,0,43,0,186,0,1,0,3,0,2,43,1,186,0,4,0,2,0,2,43,1,191,0,4,0,58,0,47,0,37,0,28,0,18,0,0,0,8,43,191,0,5,0,77,0,63,0,50,0,34,0,18,0,0,0,8,43,0,191,0,1,0,79,0,65,0,50,0,34,0,18,0,0,0,8,43,191,0,2,0,66,0,54,0,42,0,32,0,18,0,0,0,8,43,191,0,3,0,95,0,78,0,61,0,44,0,22,0,0,0,8,43,0,186,0,6,0,7,0,7,43,184,0,0,32,69,125,105,24,68,186,0,16,0,8,0,1,115,186,0,144,0,8,0,1,115,186,0,208,0,8,0,1,115,186,0,144,0,10,0,1,115,186,0,240,0,10,0,1,115,186,0,32,0,10,0,1,116,186,0,80,0,10,0,1,116,186,0,127,0,10,0,1,116,186,0,32,0,10,0,1,115,186,0,207,0,12,0,1,115,186,0,239,0,12,0,1,115,186,0,79,0,14,0,1,116,186,0,63,0,14,0,1,115,186,0,175,0,14,0,1,115,186,0,223,0,14,0,1,115,186,0,31,0,14,0,1,116,186,0,127,0,14,0,1,116,186,0,223,0,16,0,1,115,186,0,255,0,16,0,1,115,186,0,111,0,16,0,1,116,186,0,127,0,16,0,1,116,186,0,143,0,16,0,1,116,0,0,1,13,1,1,1,1,50,1,1,46,1,10,10,1,1,1,1,1,1,1,1,1,1,1,1,23,1,1,1,1,1,1,1,1,18,28,1,1,10,1,38,1,1,14,50,50,1,1,9,50,10,1,10,1,1,11,10,14,21,10,1,1,1,1,1,1,1,1,1,1,1,1,1,1,14,24,1,1,13,37,15,1,1,36,36,15,14,1,13,12,10,12,1,1,6,25,6,1,1,30,23,1,1,1,29,1,1,1,1,12,27,1,1,1,4,1,1,1,1,1,1,1,1,1,12,1,25,1,1,1,1,1,1,1,1,1,10,38,38,38,38,50,50,50,50,1,50,10,10,10,10,10,1,10,1,1,1,1,1,1,36,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,39,18,13,13,13,13,1,18,1,10,1,1,8,25,1,14,1,1,1,48,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,40,1,30,1,1,1,50,1,1,1,1,40,33,1,45,28,32,1,1,19,1,1,10,1,45,34,1,15,1,1,15,28,1,17,1,1,1,11,1,12,20,1,0,0,0,0,0,0,42,0,0,1,16,9,11,2,2,2,4,6,5,8,6,2,3,3,4,4,2,4,2,5,6,3,5,5,5,5,5,5,5,5,2,2,4,5,4,4,7,6,5,5,7,5,5,6,6,2,2,5,5,7,6,6,5,6,5,5,5,6,6,9,6,5,5,3,5,3,5,5,3,4,5,4,5,5,3,4,5,2,2,4,2,8,5,5,5,5,3,4,3,5,4,6,4,5,4,3,2,3,4,2,2,4,5,6,6,2,4,4,6,3,5,5,4,6,3,4,3,3,3,5,6,2,3,2,3,5,6,7,8,4,6,6,6,6,6,6,8,5,5,5,5,5,2,2,2,2,7,6,6,6,6,6,6,4,6,7,7,7,7,5,5,5,4,4,4,4,4,4,7,4,5,5,5,5,2,2,2,2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4,2,10,8,5,4,5,5,4,3,2,4,4,3,5,5,5,2,2,2,4,3,4,4,4,3,6,11,3,3,4,3,3,3,3,3,3,4,2,3,3,3,3,3,3,3,3,6,7,5,5,6,4,4,5,6,2,3,5,5,6,6,6,7,5,6,5,5,5,6,5,8,5,5,4,8,4,0,10,12,3,2,2,4,7,5,8,6,2,3,3,4,5,2,4,2,5,7,4,5,5,6,5,6,5,6,6,2,2,4,5,4,4,7,6,6,6,7,6,5,7,7,3,3,6,5,8,7,8,6,8,6,6,6,7,6,10,6,6,5,3,5,3,5,6,3,5,6,5,6,5,3,5,6,2,2,5,3,9,6,6,6,6,3,5,3,6,5,7,5,5,5,3,2,3,5,2,2,5,5,6,7,2,5,4,7,3,6,6,4,7,3,5,3,3,3,6,6,2,3,2,4,6,7,7,9,4,6,6,6,6,6,6,9,6,6,6,6,6,3,3,3,3,7,7,8,8,8,8,8,4,8,7,7,7,7,6,6,6,5,5,5,5,5,5,8,5,5,5,5,5,2,2,2,2,5,6,6,6,6,6,6,6,6,6,6,6,6,5,6,5,6,5,2,11,9,6,5,6,5,5,4,2,4,4,3,5,5,6,2,2,2,4,4,4,4,5,3,7,12,3,3,4,3,3,3,3,3,3,4,2,3,3,4,3,3,3,4,3,7,7,5,5,6,5,5,6,6,2,2,5,6,7,6,7,7,5,7,5,5,5,6,6,8,6,5,5,9,4,0,11,13,3,2,3,4,8,6,9,7,2,3,3,5,5,2,5,2,6,8,4,6,6,6,6,6,6,7,6,2,2,4,6,4,5,8,7,7,7,8,6,6,7,8,3,3,6,6,9,8,8,6,8,7,6,6,8,7,11,7,6,6,4,6,4,6,6,3,5,6,5,6,6,4,5,6,2,2,5,3,10,6,6,6,6,4,5,4,6,6,8,6,6,5,3,3,3,5,2,2,5,6,7,7,3,5,5,8,4,7,7,5,8,4,5,3,3,3,7,7,3,3,2,4,7,8,8,10,5,7,7,7,7,7,7,10,7,6,6,6,6,3,3,3,3,8,8,8,8,8,8,8,5,8,8,8,8,8,6,6,6,5,5,5,5,5,5,9,5,6,6,6,6,2,2,2,2,6,6,6,6,6,6,6,7,6,6,6,6,6,6,6,6,7,5,2,12,10,6,5,6,6,5,4,2,5,5,3,6,6,7,2,2,2,4,4,5,5,5,3,7,13,4,4,4,4,3,4,3,4,4,5,3,4,4,4,4,4,4,4,4,8,8,6,6,7,5,5,6,7,3,3,6,6,8,7,8,8,6,8,6,6,5,7,6,9,6,6,6,10,5,0,12,14,3,3,3,5,8,6,10,7,2,3,3,5,6,3,5,2,6,9,4,6,7,7,6,7,6,7,7,2,3,5,6,5,5,9,7,7,7,9,7,6,8,9,3,3,7,6,10,8,9,7,9,7,7,6,9,8,12,7,7,7,4,6,4,6,7,4,6,7,5,7,6,4,6,7,3,3,6,3,11,7,7,7,7,4,5,4,7,6,9,6,6,6,4,3,4,5,3,3,6,6,8,8,3,5,5,9,4,7,7,5,9,4,6,4,4,4,7,7,3,4,3,4,7,9,9,11,5,7,7,7,7,7,7,10,7,7,7,7,7,3,3,3,3,9,8,9,9,9,9,9,5,9,9,9,9,9,7,7,7,6,6,6,6,6,6,10,5,6,6,6,6,3,3,3,3,6,7,7,7,7,7,7,7,7,7,7,7,7,6,7,6,7,5,3,13,11,7,5,7,7,6,4,3,5,5,4,6,6,7,2,2,3,5,5,5,5,6,4,8,14,4,4,5,4,4,4,3,4,4,5,3,4,4,4,4,4,4,4,4,8,9,6,6,8,6,6,7,8,3,3,6,7,9,7,8,9,6,8,6,6,6,8,7,10,6,6,6,11,5,0,13,16,3,3,3,5,9,7,11,8,2,3,3,6,6,3,6,3,7,9,5,7,7,7,7,7,7,8,7,3,3,5,7,5,6,9,8,8,8,9,7,7,9,9,3,3,8,7,11,9,10,7,10,8,8,7,9,9,13,8,7,7,4,7,4,7,7,4,6,7,6,7,7,4,7,7,3,3,6,3,11,7,7,7,7,4,6,4,7,6,9,6,7,6,4,3,4,6,3,3,6,7,8,9,3,6,5,9,5,7,8,6,9,4,6,4,4,4,8,8,3,4,3,5,7,9,9,12,6,8,8,8,8,8,8,11,8,7,7,7,7,3,3,3,3,9,9,10,10,10,10,10,6,10,9,9,9,9,7,7,7,6,6,6,6,6,6,10,6,7,7,7,7,3,3,3,3,7,7,7,7,7,7,7,8,7,7,7,7,7,7,7,7,8,6,3,14,11,8,6,7,7,6,5,3,6,6,4,7,7,8,2,2,3,5,5,6,6,6,4,9,16,4,4,5,4,4,4,4,5,4,6,3,4,4,5,4,5,4,5,5,9,9,7,7,8,6,6,8,8,3,3,7,7,9,8,9,10,7,9,7,7,6,8,7,11,7,7,6,12,6,0,14,17,4,3,3,6,10,7,12,9,3,4,4,6,6,3,6,3,7,10,5,7,8,8,8,8,7,9,8,3,3,6,7,6,6,10,9,8,9,10,8,7,9,10,3,4,8,7,11,10,11,8,11,8,8,7,10,9,14,8,8,8,5,7,5,7,8,4,7,8,6,8,7,5,7,8,3,3,6,3,13,8,8,8,8,5,6,5,7,7,10,7,7,7,4,3,4,6,3,3,7,7,9,9,3,6,6,10,5,8,8,6,10,5,7,4,4,4,8,9,3,4,3,5,8,10,10,12,6,9,9,9,9,9,9,12,9,8,8,8,8,3,3,3,3,10,10,11,11,11,11,11,6,11,10,10,10,10,8,8,8,7,7,7,7,7,7,11,6,7,7,7,7,3,3,3,3,7,8,8,8,8,8,8,8,8,7,7,7,7,7,8,7,9,6,3,15,13,8,6,8,8,7,5,3,6,6,4,7,7,8,3,2,3,6,5,6,6,6,4,9,17,5,5,6,5,4,5,4,5,5,6,3,5,5,5,5,5,5,5,5,10,10,7,8,9,7,6,8,9,3,3,7,7,10,9,10,10,7,10,8,7,7,9,8,12,8,7,7,13,6,0,15,18,4,3,4,6,11,8,13,9,3,4,4,6,7,3,6,3,8,11,5,8,8,8,8,9,8,9,9,3,3,6,8,6,7,11,9,9,9,11,8,8,10,11,4,4,9,8,12,11,12,9,12,9,9,8,11,10,15,9,9,8,5,8,5,8,8,5,7,8,7,8,8,5,7,8,3,3,7,4,13,8,8,8,8,5,6,5,8,7,11,7,8,7,4,3,4,7,3,3,7,8,9,10,3,7,6,11,5,8,9,6,11,5,7,5,5,5,9,9,4,5,3,6,8,11,11,13,7,9,9,9,9,9,9,13,9,8,8,8,8,4,4,4,4,11,11,12,12,12,12,12,7,12,11,11,11,11,9,9,8,7,7,7,7,7,7,12,7,8,8,8,8,3,3,3,3,8,8,8,8,8,8,8,9,9,8,8,8,8,8,8,8,9,7,3,16,13,9,6,9,8,7,5,3,7,7,4,8,8,9,3,3,3,6,6,7,6,7,5,10,18,5,5,6,5,5,5,4,5,5,6,4,5,5,5,5,5,5,6,5,11,11,8,8,9,7,7,9,10,4,4,8,8,11,9,10,11,8,10,8,8,7,9,8,13,8,8,7,14,7,0,16,19,4,4,4,6,11,8,13,10,3,4,4,7,7,3,7,3,9,11,6,8,9,9,9,9,8,10,9,3,3,6,8,6,7,12,10,10,10,12,9,8,11,12,4,4,9,8,13,11,12,9,12,10,9,9,12,10,16,10,9,9,5,8,5,8,9,5,8,9,7,9,8,5,8,9,3,3,7,4,14,9,9,9,9,5,7,5,8,8,12,8,8,8,5,4,5,7,4,4,8,8,10,11,4,7,7,12,6,9,10,7,12,5,8,5,5,5,9,10,4,5,3,6,9,11,12,14,7,10,10,10,10,10,10,14,10,9,9,9,9,4,4,4,4,12,11,12,12,12,12,12,7,12,12,12,12,12,9,9,9,8,8,8,8,8,8,13,7,8,8,8,8,3,3,3,3,8,9,9,9,9,9,9,9,9,8,8,8,8,8,9,8,10,7,3,17,14,9,7,9,9,8,6,3,7,7,5,8,8,10,3,3,3,6,6,7,7,7,5,11,19,5,5,7,5,5,5,5,6,5,7,4,5,5,6,5,6,5,6,6,11,12,9,9,10,8,7,9,10,4,4,8,9,11,10,11,12,8,11,9,8,7,10,9,13,9,8,8,15,7,0,17,20,4,4,4,7,12,9,14,10,3,4,4,7,8,4,7,3,9,12,6,9,9,10,9,10,9,10,10,3,4,7,9,7,8,12,10,10,10,12,9,9,11,13,4,4,10,9,14,12,13,10,13,10,10,9,12,11,17,10,10,9,6,9,6,9,10,5,8,9,8,9,9,6,8,10,4,4,8,4,15,10,9,9,9,5,7,6,9,8,12,8,9,8,5,4,5,8,4,4,8,9,11,11,4,8,7,12,6,10,10,7,12,6,8,5,5,5,10,11,4,5,4,6,10,12,12,15,8,10,10,10,10,10,10,15,10,9,9,9,9,4,4,4,4,12,12,13,13,13,13,13,7,13,12,12,12,12,10,10,9,8,8,8,8,8,8,14,8,9,9,9,9,4,4,4,4,9,10,9,9,9,9,9,10,9,9,9,9,9,9,9,9,10,8,4,18,15,10,7,10,9,8,6,4,8,8,5,9,9,10,3,3,4,7,6,8,7,8,5,11,20,5,5,7,6,5,5,5,6,6,7,4,6,6,6,6,6,6,6,6,12,12,9,9,11,8,8,10,11,4,4,9,9,12,10,11,13,9,11,9,9,8,11,10,14,9,9,8,16,7,0,18,22,5,4,4,7,13,9,15,11,3,5,5,8,8,4,8,4,10,13,6,9,10,10,10,10,9,11,10,4,4,7,9,7,8,13,11,11,11,13,10,9,12,13,5,5,10,9,15,13,14,10,14,11,11,10,13,12,18,11,10,10,6,9,6,9,10,5,9,10,8,10,9,6,9,10,4,4,8,4,16,10,10,10,10,6,7,6,9,9,13,9,9,8,5,4,5,8,4,4,9,9,11,12,4,8,8,13,6,10,11,8,13,6,9,5,6,5,11,11,4,5,4,7,10,13,13,16,8,11,11,11,11,11,11,16,11,10,10,10,10,5,5,5,5,13,13,14,14,14,14,14,8,14,13,13,13,13,10,10,10,9,9,9,9,9,9,14,8,9,9,9,9,4,4,4,4,9,10,10,10,10,10,10,11,10,9,9,9,9,9,10,9,11,8,4,19,16,11,7,10,10,8,6,4,8,8,5,10,9,11,3,3,4,7,7,8,8,8,6,12,22,6,6,7,6,6,6,5,6,6,8,4,6,6,6,6,6,6,7,6,13,13,10,10,11,9,8,11,12,4,4,9,10,13,11,12,13,9,12,10,9,8,11,10,15,10,9,9,17,8,0,19,23,5,4,5,8,13,10,16,12,3,5,5,8,9,4,8,4,10,14,7,10,10,11,10,11,10,12,11,4,4,8,10,8,8,14,12,11,12,14,11,10,13,14,5,5,11,10,15,13,15,11,15,11,11,10,14,12,18,11,11,10,6,10,6,10,11,6,9,11,9,11,10,6,9,11,4,4,9,5,17,11,10,11,11,6,8,6,10,9,14,9,10,9,6,4,6,9,4,4,9,10,12,13,4,9,8,14,7,11,11,8,14,6,9,6,6,6,11,12,5,6,4,7,11,14,14,17,9,12,12,12,12,12,12,16,12,11,11,11,11,5,5,5,5,14,13,15,15,15,15,15,8,15,14,14,14,14,11,11,11,9,9,9,9,9,9,15,9,10,10,10,10,4,4,4,4,10,11,10,10,10,10,10,11,11,10,10,10,10,10,11,10,12,9,4,20,17,11,8,11,10,9,7,4,8,8,6,10,10,11,4,3,4,8,7,8,8,9,6,13,23,6,6,8,6,6,6,6,7,6,8,5,6,6,7,6,7,6,7,7,13,14,10,10,12,9,9,11,12,5,5,10,10,14,12,13,14,10,13,10,10,9,12,11,16,10,10,9,18,8,0,20,24,5,5,5,8,14,10,17,12,4,5,5,9,9,4,8,4,11,14,7,10,11,11,11,11,10,12,11,4,4,8,10,8,9,14,12,12,12,15,11,10,13,15,5,5,12,10,16,14,15,11,15,12,12,11,14,13,20,12,11,11,7,11,7,10,11,6,10,11,9,11,10,7,10,11,4,4,9,5,18,11,11,11,11,6,8,7,10,10,15,9,10,9,6,5,6,9,5,4,10,10,13,13,5,9,8,14,7,11,12,8,14,7,10,6,6,6,12,12,5,6,4,7,11,14,15,18,9,12,12,12,12,12,12,17,12,11,11,11,11,5,5,5,5,15,14,15,15,15,15,15,9,15,15,15,15,15,11,11,11,10,10,10,10,10,10,16,9,10,10,10,10,4,4,4,4,10,11,11,11,11,11,11,12,11,10,10,10,10,10,12,10,12,9,4,21,18,12,8,11,11,9,7,4,9,9,6,11,10,12,4,3,4,8,8,9,8,9,6,14,24,6,6,8,7,6,6,6,7,6,9,5,7,7,7,7,7,7,7,7,14,15,11,11,13,10,9,12,13,5,5,11,11,14,12,13,15,10,13,11,10,9,13,11,17,11,10,10,18,9,0,21,25,5,5,5,8,15,11,18,13,4,5,5,9,10,5,9,4,11,15,7,11,11,12,11,12,11,13,12,4,5,9,11,8,9,15,13,13,13,15,12,11,14,16,5,5,12,11,17,15,16,12,16,13,12,11,15,14,20,13,12,12,7,11,7,11,12,6,10,12,10,12,11,7,10,12,4,4,9,5,18,12,12,12,12,7,9,7,11,10,15,10,11,10,6,5,6,10,5,5,10,11,13,14,5,10,9,15,7,12,13,9,15,7,10,6,7,6,12,13,5,6,5,8,12,15,15,19,9,13,13,13,13,13,13,18,13,12,12,12,12,5,5,5,5,15,15,16,16,16,16,16,9,16,15,15,15,15,12,12,12,10,10,10,10,10,10,17,10,11,11,11,11,4,4,4,4,11,12,12,12,12,12,12,12,12,11,11,11,11,11,12,11,13,10,4,22,19,12,9,12,12,10,7,4,9,9,6,11,11,12,4,4,5,8,8,9,9,10,6,14,25,7,7,9,7,6,7,6,7,7,9,5,7,7,8,7,7,7,8,7,15,15,11,11,13,10,10,12,14,5,5,11,11,15,13,14,16,11,14,11,11,10,13,12,18,11,11,10,19,9,0,22,26,6,5,5,9,15,11,18,13,4,6,6,9,10,5,9,4,12,16,8,12,12,12,12,13,11,13,13,4,5,9,11,9,10,16,14,13,14,16,12,12,15,16,6,6,13,11,18,15,17,13,17,13,13,12,16,14,21,13,12,12,7,12,7,11,12,7,11,12,10,12,11,7,11,12,5,5,10,5,19,12,12,12,12,7,9,7,12,11,16,10,11,10,7,5,7,10,5,5,11,11,14,15,5,10,9,16,8,12,13,9,16,7,11,7,7,7,13,14,5,7,5,8,12,16,16,19,10,14,14,14,14,14,14,19,14,12,12,12,12,6,6,6,6,16,15,17,17,17,17,17,10,17,16,16,16,16,12,13,12,11,11,11,11,11,11,18,10,11,11,11,11,5,5,5,5,11,12,12,12,12,12,12,13,13,12,12,12,12,11,13,11,14,10,5,24,20,13,9,12,12,10,8,5,10,10,6,12,11,13,4,4,5,9,8,10,9,10,7,15,26,7,7,9,7,7,7,6,8,7,9,5,7,7,8,7,8,7,8,8,15,16,12,12,14,11,10,13,14,5,5,12,12,16,14,15,16,11,15,12,11,10,14,12,18,12,11,11,20,10,0,23,28,6,5,6,9,16,12,19,14,4,6,6,10,11,5,10,5,12,16,8,12,13,13,12,13,12,14,13,5,5,9,12,9,10,17,14,14,14,17,13,12,15,17,6,6,13,12,19,16,18,13,18,14,13,12,17,15,22,14,13,13,8,12,8,12,13,7,11,13,10,13,12,8,11,13,5,5,10,5,20,13,13,13,13,7,10,8,12,11,17,11,12,11,7,5,7,10,5,5,11,12,14,16,5,10,10,17,8,13,14,10,17,8,11,7,7,7,14,14,5,7,5,9,13,16,17,20,10,14,14,14,14,14,14,20,14,13,13,13,13,6,6,6,6,17,16,18,18,18,18,18,10,18,17,17,17,17,13,13,13,11,11,11,11,11,11,18,10,12,12,12,12,5,5,5,5,12,13,13,13,13,13,13,14,13,12,12,12,12,12,13,12,14,10,5,25,21,13,10,13,13,11,8,5,10,10,7,12,12,14,4,4,5,9,9,10,10,11,7,16,28,7,7,9,8,7,7,7,8,7,10,5,8,8,8,8,8,8,9,8,16,17,12,12,14,11,11,13,15,6,6,12,12,16,14,15,17,12,15,12,12,11,14,13,19,12,12,11,21,10,0,24,29,6,5,6,10,17,12,20,15,4,6,6,10,11,5,10,5,13,17,9,13,13,13,13,14,12,15,14,5,5,10,12,10,11,17,15,14,15,17,13,13,16,18,6,6,14,12,19,17,18,14,18,14,14,13,17,15,23,14,14,13,8,13,8,12,14,7,12,13,11,13,12,8,12,13,5,5,11,6,21,13,13,13,13,8,10,8,13,12,17,11,12,11,7,6,7,11,5,5,11,12,15,16,6,11,10,17,8,14,14,10,17,8,12,7,7,7,14,15,6,7,5,9,14,17,18,21,11,15,15,15,15,15,15,21,15,13,13,13,13,6,6,6,6,17,17,18,18,18,18,18,11,18,17,17,17,17,14,14,13,12,12,12,12,12,12,19,11,12,12,12,12,5,5,5,5,12,13,13,13,13,13,13,14,14,13,13,13,13,12,14,12,15,11,5,26,21,14,10,14,13,11,8,5,11,11,7,13,12,14,4,4,5,10,9,11,10,11,7,16,29,8,8,10,8,7,8,7,8,8,10,6,8,8,9,8,8,8,9,8,17,17,13,13,15,12,11,14,16,6,6,13,13,17,15,16,18,12,16,13,12,11,15,13,20,13,12,12,22,11,0,25,30,6,6,6,10,18,13,21,15,5,7,7,11,12,5,11,5,13,18,9,13,14,14,14,14,13,15,14,5,5,10,13,10,11,18,15,15,15,18,14,13,17,19,6,6,14,13,20,18,19,14,19,15,15,13,18,16,24,15,14,14,8,13,8,13,14,8,12,14,11,14,13,8,12,14,5,5,11,6,22,14,14,14,14,8,10,8,13,12,18,12,13,12,7,6,7,11,6,6,12,13,16,17,6,11,11,18,9,14,15,11,18,8,12,8,8,8,15,16,6,8,5,9,14,18,18,22,11,15,15,15,15,15,15,22,15,14,14,14,14,6,6,6,6,18,18,19,19,19,19,19,11,19,18,18,18,18,14,14,14,12,12,12,12,12,12,20,11,13,13,13,13,5,5,5,5,13,14,14,14,14,14,14,15,14,13,13,13,13,13,15,13,15,11,5,27,23,15,10,14,14,12,9,5,11,11,7,13,13,15,5,4,5,10,9,11,11,12,8,17,30,8,8,10,8,8,8,7,9,8,11,6,8,8,9,8,9,8,9,9,18,18,13,13,16,12,11,15,16,6,6,13,13,18,15,17,19,13,17,13,13,12,16,14,21,14,13,12,23,11,0,26,31,7,6,6,10,18,13,22,16,5,7,7,11,12,6,11,5,14,19,9,14,14,15,14,15,13,16,15,5,6,11,13,11,11,19,16,16,16,19,14,14,17,19,7,7,15,13,21,18,20,15,20,16,15,14,19,17,25,16,15,14,9,14,9,13,15,8,12,14,12,14,13,9,13,14,6,6,12,6,23,15,14,14,14,8,11,9,14,13,19,12,13,12,8,6,8,12,6,6,12,13,16,18,6,12,11,19,9,15,16,11,19,9,13,8,8,8,15,16,6,8,6,10,15,19,19,23,12,16,16,16,16,16,16,22,16,14,14,14,14,7,7,7,7,19,18,20,20,20,20,20,11,20,19,19,19,19,15,15,14,12,12,12,12,12,12,21,12,13,13,13,13,6,6,6,6,13,15,14,14,14,14,14,15,15,14,14,14,14,13,15,13,16,12,6,28,23,15,11,15,14,12,9,6,12,12,8,14,13,15,5,4,6,10,10,12,11,12,8,18,31,8,8,11,9,8,8,8,9,8,11,6,9,9,9,9,9,9,10,9,18,19,14,14,16,13,12,15,17,6,6,14,14,19,16,17,19,13,17,14,13,12,16,15,22,14,13,13,24,11,0,27,32,7,6,7,11,19,14,23,17,5,7,7,12,13,6,11,6,14,19,10,14,15,15,15,15,14,16,15,6,6,11,14,11,12,20,17,16,17,20,15,14,18,20,7,7,16,14,22,19,21,15,21,16,16,14,20,17,26,16,15,15,9,14,9,14,15,8,13,15,12,15,14,9,13,15,6,6,12,6,24,15,15,15,15,9,11,9,14,13,20,13,14,13,8,6,8,12,6,6,13,14,17,18,6,12,11,19,9,15,16,11,19,9,13,8,8,8,16,17,6,8,6,10,15,19,20,24,12,17,17,17,17,17,17,23,17,15,15,15,15,7,7,7,7,20,19,21,21,21,21,21,12,21,20,20,20,20,15,15,15,13,13,13,13,13,13,22,12,14,14,14,14,6,6,6,6,14,15,15,15,15,15,15,16,15,14,14,14,14,14,16,14,17,12,6,29,24,16,11,15,15,13,9,6,12,12,8,14,14,16,5,5,6,11,10,12,11,12,8,18,32,9,9,11,9,8,9,8,9,9,12,6,9,9,10,9,9,9,10,9,19,20,14,15,17,13,12,16,17,7,7,14,14,19,17,18,20,14,18,15,14,13,17,15,23,15,14,13,25,12,0,28,34,7,6,7,11,20,14,24,17,5,7,7,12,13,6,12,6,15,20,10,15,15,16,15,16,14,17,16,6,6,11,14,11,12,20,17,17,17,20,16,15,19,21,7,7,16,14,23,20,22,16,22,17,16,15,20,18,27,17,16,15,9,15,9,14,16,8,13,16,13,16,14,9,14,15,6,6,13,7,25,16,15,16,16,9,12,9,15,14,20,13,14,13,8,6,8,13,6,6,13,14,18,19,7,13,12,20,10,16,17,12,20,9,14,9,9,8,17,17,7,8,6,10,16,20,20,25,13,17,17,17,17,17,17,24,17,16,16,16,16,7,7,7,7,20,20,22,22,22,22,22,12,22,20,20,20,20,16,16,16,13,13,13,13,13,13,22,13,14,14,14,14,6,6,6,6,14,16,15,15,15,15,15,17,16,15,15,15,15,14,16,14,17,13,6,30,25,16,12,16,15,13,10,6,12,12,8,15,14,17,5,5,6,11,11,12,12,13,9,19,34,9,9,11,9,9,9,8,10,9,12,7,9,9,10,9,10,9,10,10,20,20,15,15,18,14,13,16,18,7,7,15,15,20,17,19,21,14,19,15,14,13,18,16,23,15,14,14,26,12,0,29,35,7,7,7,12,20,15,24,18,5,8,8,12,13,6,12,6,15,21,10,15,16,16,16,16,15,18,17,6,6,12,15,12,13,21,18,17,18,21,16,15,19,22,7,7,17,15,24,20,22,17,22,17,17,15,21,19,28,17,16,16,9,15,9,15,16,9,14,16,13,16,15,10,14,16,6,6,13,7,25,16,16,16,16,9,12,10,15,14,21,14,15,14,9,7,9,13,7,7,14,15,18,20,7,13,12,21,10,16,17,12,21,10,14,9,9,9,17,18,7,9,6,11,16,21,21,26,13,18,18,18,18,18,18,25,18,16,16,16,16,7,7,7,7,21,20,22,22,22,22,22,13,22,21,21,21,21,16,17,16,14,14,14,14,14,14,23,13,15,15,15,15,6,6,6,6,15,16,16,16,16,16,16,17,17,15,15,15,15,15,17,15,18,13,6,31,26,17,12,16,16,14,10,6,13,13,8,15,15,17,5,5,6,11,11,13,12,13,9,20,35,9,9,12,10,9,9,8,10,9,13,7,10,10,10,10,10,10,11,10,20,21,16,16,18,14,13,17,19,7,7,15,15,21,18,19,22,15,19,16,15,14,18,16,24,16,15,14,27,13,0,30,36,8,7,7,12,21,15,25,18,5,8,8,13,14,6,13,6,16,21,11,16,16,17,16,17,15,18,17,6,6,12,15,12,13,22,18,18,18,22,17,16,20,22,8,8,17,15,24,21,23,17,23,18,18,16,22,19,29,18,17,16,10,16,10,15,17,9,14,17,14,17,15,10,15,16,6,6,13,7,26,17,17,17,17,10,12,10,16,15,22,14,15,14,9,7,9,14,7,7,14,15,19,20,7,14,13,22,10,17,18,13,22,10,15,9,9,9,18,19,7,9,6,11,17,22,22,27,13,18,18,18,18,18,18,26,18,17,17,17,17,8,8,8,8,22,21,23,23,23,23,23,13,23,22,22,22,22,17,17,17,14,14,14,14,14,14,24,14,15,15,15,15,6,6,6,6,16,17,17,17,17,17,17,18,17,16,16,16,16,15,17,15,18,14,6,32,27,18,12,17,16,14,11,6,13,13,9,16,15,18,6,5,6,12,11,13,13,14,9,20,36,10,10,12,10,9,10,9,10,10,13,7,10,10,11,10,10,10,11,10,21,22,16,16,19,15,14,17,19,7,7,16,16,21,18,20,22,15,20,16,15,14,19,17,25,16,15,14,28,13,0,31,37,8,7,8,12,22,16,26,19,6,8,8,13,14,7,13,6,16,22,11,16,17,17,17,18,16,19,18,6,7,13,16,13,14,22,19,19,19,23,17,16,21,23,8,8,18,16,25,22,24,18,24,19,18,17,22,20,30,19,18,17,10,16,10,16,18,9,15,17,14,17,16,10,15,17,7,7,14,7,27,17,17,17,17,10,13,10,16,15,22,15,16,15,9,7,9,14,7,7,15,16,19,21,7,14,13,22,11,17,18,13,22,10,15,9,10,9,18,19,7,9,7,11,17,22,23,27,14,19,19,19,19,19,19,27,19,17,17,17,17,8,8,8,8,23,22,24,24,24,24,24,14,24,23,23,23,23,18,18,17,15,15,15,15,15,15,25,14,16,16,16,16,7,7,7,7,16,17,17,17,17,17,17,18,18,16,16,16,16,16,18,16,19,14,7,33,28,18,13,18,17,15,11,7,14,14,9,16,16,18,6,5,7,12,12,14,13,14,9,21,37,10,10,13,10,10,10,9,11,10,13,7,10,10,11,10,11,10,12,11,22,23,17,17,20,15,14,18,20,7,7,16,17,22,19,21,23,16,21,17,16,15,19,17,26,17,16,15,29,14,0,32,38,8,7,8,13,23,16,27,20,6,8,8,14,15,7,14,7,17,23,11,17,18,18,17,18,16,19,18,7,7,13,16,13,14,23,20,19,20,23,18,17,22,24,8,8,18,16,26,23,25,18,25,19,19,17,23,21,31,19,18,18,10,17,10,16,18,10,15,18,15,18,16,11,16,17,7,7,14,8,28,18,18,18,18,10,13,11,17,16,23,15,16,15,10,7,10,15,7,7,15,16,20,22,7,15,14,23,11,18,19,14,23,11,16,10,10,10,19,20,8,10,7,12,18,23,23,28,14,20,20,20,20,20,20,28,20,18,18,18,18,8,8,8,8,23,23,25,25,25,25,25,14,25,23,23,23,23,18,18,18,15,15,15,15,15,15,26,15,16,16,16,16,7,7,7,7,17,18,18,18,18,18,18,19,18,17,17,17,17,16,19,16,20,15,7,34,29,19,13,18,18,15,11,7,14,14,9,17,16,19,6,5,7,13,12,14,14,15,10,22,38,10,10,13,11,10,10,9,11,10,14,8,11,11,11,11,11,11,12,11,23,23,17,17,20,16,15,19,21,8,8,17,17,23,20,21,24,16,21,17,16,15,20,18,27,17,16,15,29,14,0,33,40,8,7,8,13,23,17,28,20,6,9,9,14,15,7,14,7,18,24,12,17,18,18,18,19,17,20,19,7,7,13,17,13,15,24,20,20,20,24,18,17,22,25,8,8,19,17,27,23,25,19,25,20,19,18,24,21,32,20,19,18,11,17,11,17,19,10,16,18,15,18,17,11,16,18,7,7,15,8,29,18,18,18,18,11,14,11,17,16,24,16,17,16,10,8,10,15,7,7,16,17,21,22,8,15,14,24,12,19,20,14,24,11,16,10,10,10,20,21,8,10,7,12,19,24,24,29,15,20,20,20,20,20,20,29,20,18,18,18,18,8,8,8,8,24,23,25,25,25,25,25,14,25,24,24,24,24,19,19,18,16,16,16,16,16,16,26,15,17,17,17,17,7,7,7,7,17,18,18,18,18,18,18,20,19,17,17,17,17,17,19,17,20,15,7,35,30,19,14,19,18,16,12,7,15,15,10,17,17,20,6,6,7,13,13,15,14,15,10,22,40,11,11,13,11,10,11,10,11,11,14,8,11,11,12,11,11,11,12,11,23,24,18,18,21,16,15,19,21,8,8,17,18,24,20,22,24,17,22,18,17,16,21,19,28,18,17,16,30,15,0,34,41,9,8,8,14,24,17,29,21,6,9,9,14,16,7,14,7,18,24,12,18,19,19,18,19,17,21,19,7,7,14,17,14,15,25,21,20,21,25,19,18,23,25,9,9,20,17,28,24,26,19,26,21,20,18,25,22,33,20,19,19,11,18,11,17,19,10,16,19,15,19,17,11,17,18,7,7,15,8,30,19,19,19,19,11,14,11,18,17,25,16,17,16,10,8,10,15,8,8,16,17,21,23,8,16,14,24,12,19,20,14,24,11,17,10,11,10,20,21,8,10,7,13,19,24,25,30,15,21,21,21,21,21,21,29,21,19,19,19,19,9,9,9,9,25,24,26,26,26,26,26,15,26,25,25,25,25,19,19,19,16,16,16,16,16,16,27,15,17,17,17,17,7,7,7,7,18,19,19,19,19,19,19,20,19,18,18,18,18,17,20,17,21,15,7,36,31,20,14,19,19,16,12,7,15,15,10,18,17,20,6,6,7,13,13,15,14,16,10,23,41,11,11,14,11,10,11,10,12,11,15,8,11,11,12,11,12,11,13,12,24,25,18,18,21,17,16,20,22,8,8,18,18,24,21,23,25,17,23,18,17,16,21,19,28,18,17,16,31,15,0,35,42,9,8,8,14,25,18,29,21,6,9,9,15,16,8,15,7,19,25,12,18,19,20,19,20,18,21,20,7,8,14,18,14,15,25,22,21,22,25,19,18,24,26,9,9,20,18,28,25,27,20,27,21,20,19,25,23,34,21,20,19,11,18,11,18,20,11,17,19,16,19,18,12,17,19,7,7,16,8,31,20,19,20,20,11,14,12,18,17,25,17,18,16,10,8,10,16,8,8,17,18,22,24,8,16,15,25,12,20,21,15,25,12,17,11,11,11,21,22,8,11,8,13,20,25,26,31,16,22,22,22,22,22,22,30,22,19,19,19,19,9,9,9,9,25,25,27,27,27,27,27,15,27,25,25,25,25,20,20,20,17,17,17,17,17,17,28,16,18,18,18,18,7,7,7,7,18,20,19,19,19,19,19,21,20,18,18,18,18,18,20,18,22,16,7,37,32,20,14,20,19,16,12,7,16,16,10,18,18,21,7,6,8,14,13,16,15,16,11,24,42,11,11,14,12,11,11,10,12,11,15,8,12,12,13,12,12,12,13,12,25,25,19,19,22,17,16,20,23,8,8,18,19,25,21,23,26,18,23,19,18,16,22,20,29,19,18,17,32,15,0,36,43,9,8,9,14,25,19,30,22,7,9,9,15,17,8,15,7,19,26,13,19,20,20,19,20,18,22,21,7,8,15,18,15,16,26,22,21,22,26,20,19,24,27,9,9,21,18,29,25,28,21,28,22,21,19,26,23,35,22,20,20,12,19,12,18,20,11,17,20,16,20,18,12,18,20,8,8,16,9,32,20,20,20,20,12,15,12,19,18,26,17,18,17,11,8,11,16,8,8,17,18,23,24,8,16,15,26,13,20,21,15,26,12,18,11,11,11,21,22,9,11,8,13,20,26,26,32,16,22,22,22,22,22,22,31,22,20,20,20,20,9,9,9,9,26,25,28,28,28,28,28,16,28,26,26,26,26,20,21,20,17,17,17,17,17,17,29,16,18,18,18,18,8,8,8,8,19,20,20,20,20,20,20,21,21,19,19,19,19,18,21,18,22,16,8,39,32,21,15,20,20,17,13,8,16,16,11,19,18,21,7,6,8,14,14,16,15,17,11,24,43,12,12,15,12,11,12,10,12,12,16,9,12,12,13,12,12,12,13,12,25,26,19,19,23,18,17,21,23,9,9,19,19,26,22,24,27,18,24,19,18,17,23,20,30,19,18,17,33,16,0,37,44,9,8,9,15,26,19,31,23,7,10,10,16,17,8,16,8,20,26,13,19,20,21,20,21,19,23,21,8,8,15,19,15,16,27,23,22,23,27,21,19,25,28,9,9,21,19,30,26,28,21,28,22,22,20,27,24,36,22,21,20,12,19,12,19,21,11,18,21,17,21,19,12,18,20,8,8,17,9,32,21,20,21,21,12,15,12,19,18,27,18,19,17,11,8,11,17,8,8,18,19,23,25,9,17,16,27,13,21,22,16,27,12,18,11,11,11,22,23,9,11,8,14,21,27,27,33,17,23,23,23,23,23,23,32,23,21,21,21,21,9,9,9,9,27,26,28,28,28,28,28,16,28,27,27,27,27,21,21,21,18,18,18,18,18,18,30,17,19,19,19,19,8,8,8,8,19,21,20,20,20,20,20,22,21,19,19,19,19,19,21,19,23,17,8,40,33,22,15,21,20,17,13,8,17,17,11,20,19,22,7,6,8,15,14,17,16,17,11,25,44,12,12,15,12,11,12,11,13,12,16,9,12,12,13,12,13,12,14,13,26,27,20,20,23,18,17,22,24,9,9,19,20,26,23,25,27,19,25,20,19,17,23,21,31,20,19,18,34,16,0,38,46,10,9,9,15,27,20,32,23,7,10,10,16,18,8,16,8,20,27,13,20,21,21,21,22,19,23,22,8,8,15,19,15,17,27,23,23,23,28,21,20,26,28,10,10,22,19,31,27,29,22,29,23,22,20,28,24,37,23,22,21,12,20,12,19,22,12,18,21,17,21,19,13,19,21,8,8,17,9,33,21,21,21,21,12,16,13,20,19,28,18,19,18,11,9,11,17,9,9,18,19,24,26,9,17,16,27,13,21,23,16,27,13,19,12,12,12,22,24,9,12,8,14,21,27,28,34,17,23,23,23,23,23,23,33,23,21,21,21,21,10,10,10,10,28,27,29,29,29,29,29,17,29,28,28,28,28,22,22,21,18,18,18,18,18,18,30,17,19,19,19,19,8,8,8,8,20,21,21,21,21,21,21,23,22,20,20,20,20,19,22,19,23,17,8,41,34,22,16,22,21,18,13,8,17,17,11,20,19,23,7,6,8,15,14,17,16,17,12,26,46,12,12,15,13,12,12,11,13,12,16,9,13,13,14,13,13,13,14,13,27,28,20,20,24,19,17,22,25,9,9,20,20,27,23,25,28,19,25,20,19,18,24,21,32,21,19,18,35,17,0,39,47,10,9,9,16,27,20,33,24,7,10,10,17,18,8,17,8,21,28,14,20,21,22,21,22,20,24,22,8,8,16,20,16,17,28,24,23,24,28,22,20,26,29,10,10,23,20,32,27,30,22,30,24,23,21,28,25,38,23,22,21,13,20,13,20,22,12,19,22,18,22,20,13,19,21,8,8,17,9,34,22,21,22,22,13,16,13,20,19,28,18,20,18,12,9,12,18,9,9,19,20,24,26,9,18,16,28,14,22,23,17,28,13,19,12,12,12,23,24,9,12,8,14,22,28,28,35,18,24,24,24,24,24,24,34,24,22,22,22,22,10,10,10,10,28,27,30,30,30,30,30,17,30,28,28,28,28,22,22,22,19,19,19,19,19,19,31,18,20,20,20,20,8,8,8,8,20,22,21,21,21,21,21,23,22,20,20,20,20,20,23,20,24,18,8,42,35,23,16,22,21,18,14,8,17,17,11,21,20,23,7,7,8,15,15,17,17,18,12,26,47,13,13,16,13,12,13,11,14,13,17,9,13,13,14,13,14,13,15,14,27,28,21,21,25,19,18,23,25,9,9,20,21,28,24,26,29,20,26,21,20,18,24,22,33,21,20,19,36,17,0,40,48,10,9,10,16,28,21,34,24,7,10,10,17,19,9,17,8,21,29,14,21,22,22,22,23,20,24,23,8,9,16,20,16,18,29,25,24,25,29,22,21,27,30,10,10,23,20,32,28,31,23,31,24,23,21,29,26,39,24,23,22,13,21,13,20,23,12,19,22,18,22,20,13,20,22,8,8,18,9,35,22,22,22,22,13,17,13,21,20,29,19,20,19,12,9,12,18,9,9,19,20,25,27,9,18,17,29,14,23,24,17,29,13,20,12,12,12,24,25,10,12,9,15,23,29,29,35,18,25,25,25,25,25,25,35,25,22,22,22,22,10,10,10,10,29,28,31,31,31,31,31,18,31,29,29,29,29,23,23,22,19,19,19,19,19,19,32,18,20,20,20,20,8,8,8,8,21,22,22,22,22,22,22,24,23,21,21,21,21,20,23,20,25,18,8,43,36,23,17,23,22,19,14,8,18,18,12,21,20,24,7,7,9,16,15,18,17,18,12,27,48,13,13,16,13,12,13,12,14,13,17,9,13,13,14,13,14,13,15,14,28,29,21,21,25,20,18,23,26,10,10,21,21,28,25,27,30,20,27,21,20,19,25,22,33,22,20,19,37,18,0,41,49,10,9,10,16,29,21,34,25,7,11,11,17,19,9,17,8,22,29,15,21,22,23,22,23,21,25,23,8,9,17,21,17,18,30,25,24,25,30,23,21,28,31,10,10,24,21,33,29,31,23,31,25,24,22,30,26,40,25,23,23,13,22,13,21,23,12,20,23,19,23,21,14,20,22,9,9,18,10,36,23,23,23,23,13,17,14,21,20,30,19,21,19,12,9,12,19,9,9,20,21,26,28,10,19,17,30,14,23,24,17,30,14,20,12,13,12,24,26,10,12,9,15,23,29,30,36,18,25,25,25,25,25,25,35,25,23,23,23,23,10,10,10,10,30,29,31,31,31,31,31,18,31,30,30,30,30,23,23,23,20,20,20,20,20,20,33,19,21,21,21,21,9,9,9,9,21,23,23,23,23,23,23,24,23,21,21,21,21,21,24,21,25,19,9,44,37,24,17,23,23,19,14,9,18,18,12,22,21,24,8,7,9,16,16,18,17,19,13,28,49,13,13,17,14,13,13,12,14,13,18,10,14,14,15,14,14,14,15,14,29,30,22,22,26,20,19,24,26,10,10,22,22,29,25,27,30,21,27,22,21,19,26,23,34,22,21,20,38,18,0,42,50,11,9,10,17,30,22,35,26,8,11,11,18,19,9,18,9,22,30,15,22,23,23,23,24,21,26,24,9,9,17,21,17,19,30,26,25,26,31,23,22,28,31,11,11,24,21,34,30,32,24,32,25,25,22,30,27,41,25,24,23,14,22,14,21,24,13,20,23,19,23,22,14,21,23,9,9,19,10,37,23,23,23,23,13,17,14,22,21,30,20,21,20,13,10,13,19,9,9,20,21,26,28,10,19,18,30,15,24,25,18,30,14,21,13,13,13,25,26,10,13,9,16,24,30,31,37,19,26,26,26,26,26,26,36,26,23,23,23,23,11,11,11,11,31,30,32,32,32,32,32,18,32,30,30,30,30,24,24,23,20,20,20,20,20,20,34,19,22,22,22,22,9,9,9,9,22,23,23,23,23,23,23,25,24,22,22,22,22,21,24,21,26,19,9,45,38,25,17,24,23,20,15,9,19,19,12,22,21,25,8,7,9,17,16,19,18,19,13,28,50,14,14,17,14,13,14,12,15,14,18,10,14,14,15,14,15,14,16,15,30,31,22,23,26,21,19,24,27,10,10,22,22,30,26,28,31,21,28,23,21,20,26,24,35,23,21,20,39,18,0,43,52,11,10,10,17,30,22,36,26,8,11,11,18,20,9,18,9,23,31,15,23,24,24,23,24,22,26,25,9,9,17,22,17,19,31,26,26,26,31,24,22,29,32,11,11,25,22,35,30,33,25,33,26,25,23,31,28,42,26,24,24,14,23,14,22,24,13,21,24,20,24,22,14,21,23,9,9,19,10,38,24,24,24,24,14,18,14,23,21,31,20,22,20,13,10,13,20,10,10,21,22,27,29,10,20,18,31,15,24,26,18,31,14,21,13,13,13,25,27,10,13,9,16,24,31,31,38,19,26,26,26,26,26,26,37,26,24,24,24,24,11,11,11,11,31,30,33,33,33,33,33,19,33,31,31,31,31,24,25,24,21,21,21,21,21,21,34,20,22,22,22,22,9,9,9,9,22,24,24,24,24,24,24,25,25,23,23,23,23,22,25,22,26,20,9,46,39,25,18,24,24,20,15,9,19,19,13,23,22,26,8,7,9,17,16,19,18,20,13,29,52,14,14,18,14,13,14,12,15,14,19,10,14,14,15,14,15,14,16,15,30,31,23,23,27,21,20,25,28,10,10,23,23,31,26,29,32,22,29,23,22,20,27,24,36,23,22,21,40,19,0,44,53,11,10,11,18,31,23,37,27,8,11,11,19,20,10,19,9,23,31,16,23,24,25,24,25,22,27,25,9,10,18,22,18,19,32,27,26,27,32,24,23,30,33,11,11,25,22,36,31,34,25,34,27,26,23,32,28,43,26,25,24,14,23,14,22,25,13,21,24,20,24,23,15,22,24,9,9,20,10,39,25,24,25,25,14,18,15,23,22,32,21,22,21,13,10,13,20,10,10,21,22,28,30,10,20,19,32,15,25,26,19,32,15,22,13,14,13,26,27,10,13,10,16,25,32,32,39,20,27,27,27,27,27,27,38,27,24,24,24,24,11,11,11,11,32,31,34,34,34,34,34,19,34,32,32,32,32,25,25,25,21,21,21,21,21,21,35,20,23,23,23,23,9,9,9,9,23,25,24,24,24,24,24,26,25,23,23,23,23,22,26,22,27,20,9,47,40,26,18,25,24,21,15,9,20,20,13,23,22,26,8,7,10,17,17,20,19,20,13,30,53,14,14,18,15,14,14,13,15,14,19,10,15,15,16,15,15,15,16,15,31,32,24,24,28,22,20,26,28,11,11,23,24,31,27,29,33,22,29,24,22,21,28,25,37,24,22,21,41,19,0,45,54,11,10,11,18,32,23,38,28,8,12,12,19,21,10,19,9,24,32,16,24,25,25,24,26,23,27,26,9,10,18,23,18,20,32,28,27,28,33,25,24,30,34,11,11,26,23,37,32,35,26,35,27,26,24,33,29,44,27,26,25,15,24,15,23,25,14,22,25,20,25,23,15,22,24,10,10,20,11,39,25,25,25,25,14,19,15,24,22,33,21,23,21,13,10,13,20,10,10,21,23,28,30,10,21,19,32,16,25,27,19,32,15,22,14,14,14,27,28,11,14,10,17,25,32,33,40,20,28,28,28,28,28,28,39,28,25,25,25,25,11,11,11,11,33,32,35,35,35,35,35,20,35,33,33,33,33,26,26,25,22,22,22,22,22,22,36,20,23,23,23,23,10,10,10,10,23,25,25,25,25,25,25,27,26,24,24,24,24,23,26,23,28,20,10,48,41,26,19,26,25,21,16,10,20,20,13,24,23,27,8,8,10,18,17,20,19,21,14,30,54,14,15,18,15,14,14,13,16,15,19,11,15,15,16,15,16,15,17,16,32,33,24,24,28,22,21,26,29,11,11,24,24,32,28,30,33,23,30,24,23,21,28,25,38,24,23,22,41,20,0,46,55,12,10,11,18,32,24,39,28,8,12,12,20,21,10,20,9,24,33,16,24,25,26,25,26,23,28,26,9,10,19,23,19,20,33,28,27,28,33,25,24,31,34,12,12,27,23,37,32,35,26,35,28,27,25,33,30,45,28,26,25,15,24,15,24,26,14,22,26,21,26,24,15,23,25,10,10,21,11,40,26,25,26,26,15,19,16,24,23,33,22,23,22,14,11,14,21,10,10,22,23,29,31,11,21,19,33,16,26,27,20,33,15,23,14,14,14,27,29,11,14,10,17,26,33,34,41,21,28,28,28,28,28,28,40,28,25,25,25,25,12,12,12,12,33,32,35,35,35,35,35,20,35,33,33,33,33,26,26,26,22,22,22,22,22,22,37,21,24,24,24,24,10,10,10,10,24,26,25,25,25,25,25,27,26,24,24,24,24,23,27,23,28,21,10,49,41,27,19,26,25,22,16,10,21,21,13,24,23,27,9,8,10,18,17,21,20,21,14,31,55,15,15,19,15,14,15,13,16,15,20,11,15,16,16,15,16,15,17,16,32,33,25,25,29,23,21,27,30,11,11,24,25,33,28,31,34,23,31,25,24,22,29,26,38,25,23,22,42,20,0,47,56,12,11,11,19,33,24,39,29,9,12,12,20,22,10,20,10,25,34,17,25,26,26,25,27,24,29,27,10,10,19,24,19,21,34,29,28,29,34,26,25,32,35,12,12,27,24,38,33,36,27,36,28,27,25,34,30,46,28,27,26,15,25,15,24,27,14,23,26,21,26,24,16,23,25,10,10,21,11,41,26,26,26,26,15,19,16,25,23,34,22,24,22,14,11,14,21,11,11,22,24,29,32,11,21,20,34,16,26,28,20,34,16,23,14,15,14,28,29,11,14,10,17,26,34,34,42,21,29,29,29,29,29,29,41,29,26,26,26,26,12,12,12,12,34,33,36,36,36,36,36,21,36,34,34,34,34,27,27,26,23,23,23,23,23,23,38,21,24,24,24,24,10,10,10,10,24,26,26,26,26,26,26,28,27,25,25,25,25,24,27,24,29,21,10,50,42,27,19,27,26,22,17,10,21,21,14,25,24,28,9,8,10,19,18,21,20,22,14,32,56,15,15,19,16,14,15,14,16,15,20,11,16,16,17,16,16,16,17,16,33,34,25,25,30,23,22,27,30,11,11,25,25,33,29,31,35,24,31,25,24,22,29,26,39,25,24,23,43,21,0,48,58,12,11,12,19,34,25,40,29,9,13,13,20,22,10,20,10,26,34,17,25,26,27,26,27,24,29,27,10,10,19,24,19,21,35,30,29,30,35,27,25,32,36,12,12,28,24,39,34,37,27,37,29,28,26,35,31,47,29,27,26,16,25,16,25,27,15,23,27,22,27,25,16,24,26,10,10,22,11,42,27,26,27,27,15,20,16,25,24,35,23,24,23,14,11,14,22,11,11,23,24,30,32,11,22,20,35,17,27,29,20,35,16,24,15,15,15,28,30,11,15,10,18,27,34,35,42,22,30,30,30,30,30,30,42,30,27,27,27,27,12,12,12,12,35,34,37,37,37,37,37,21,37,35,35,35,35,27,27,27,23,23,23,23,23,23,38,22,25,25,25,25,10,10,10,10,25,27,26,26,26,26,26,28,27,25,25,25,25,24,28,24,30,22,10,51,43,28,20,27,26,23,17,10,21,21,14,25,24,29,9,8,10,19,18,21,20,22,15,32,58,15,16,20,16,15,15,14,17,16,21,11,16,16,17,16,17,16,18,17,34,35,26,26,30,24,22,28,31,12,12,25,26,34,29,32,36,24,32,26,25,23,30,27,40,26,24,23,44,21,0,49,59,12,11,12,20,35,25,41,30,9,13,13,21,23,11,21,10,26,35,17,26,27,27,27,28,25,30,28,10,11,20,25,20,22,35,30,29,30,36,27,26,33,37,13,13,28,25,40,35,38,28,38,30,29,26,35,32,48,29,28,27,16,26,16,25,28,15,24,27,22,27,25,16,24,27,10,10,22,12,43,27,27,27,27,16,20,17,26,24,36,23,25,23,15,11,15,22,11,11,23,25,31,33,11,22,21,35,17,28,29,21,35,16,24,15,15,15,29,30,12,15,11,18,28,35,36,43,22,30,30,30,30,30,30,42,30,27,27,27,27,13,13,13,13,36,35,38,38,38,38,38,22,38,36,36,36,36,28,28,27,24,24,24,24,24,24,39,22,25,25,25,25,10,10,10,10,25,27,27,27,27,27,27,29,28,26,26,26,26,25,28,25,30,22,10,52,44,29,20,28,27,23,17,10,22,22,14,26,25,29,9,8,11,19,19,22,21,23,15,33,59,16,16,20,16,15,16,14,17,16,21,12,16,17,18,16,17,16,18,17,34,36,26,26,31,24,22,29,32,12,12,26,26,35,30,33,36,25,33,26,25,23,31,27,41,26,25,24,45,22,0,50,60,13,11,12,20,35,26,42,31,9,13,13,21,23,11,21,10,27,36,18,26,27,28,27,28,25,30,29,10,11,20,25,20,22,36,31,30,31,36,28,26,34,37,13,13,29,25,41,35,38,29,38,30,29,27,36,32,49,30,28,27,16,26,16,26,28,15,24,28,23,28,26,17,25,27,11,11,22,12,44,28,28,28,28,16,21,17,26,25,36,24,25,24,15,11,15,23,11,11,24,25,31,34,12,23,21,36,17,28,30,21,36,17,25,15,16,15,30,31,12,15,11,19,28,36,36,44,22,31,31,31,31,31,31,43,31,28,28,28,28,13,13,13,13,36,35,38,38,38,38,38,22,38,36,36,36,36,28,29,28,24,24,24,24,24,24,40,23,26,26,26,26,11,11,11,11,26,28,28,28,28,28,28,30,29,26,26,26,26,25,29,25,31,23,11,54,45,29,21,28,27,24,18,11,22,22,15,26,25,30,9,8,11,20,19,22,21,23,15,34,60,16,16,20,17,15,16,15,17,16,22,12,17,17,18,17,17,17,19,17,35,36,27,27,31,25,23,29,32,12,12,26,27,36,31,33,37,26,33,27,26,24,31,28,42,27,25,24,46,22,0,0,1,0,2,0,2,1,1,1,1,1,0,0,0,0,18,5,230,0,248,8,255,0,8,0,8,255,254,0,9,0,9,255,253,0,10,0,10,255,253,0,11,0,11,255,253,0,12,0,12,255,253,0,13,0,13,255,253,0,14,0,14,255,253,0,15,0,15,255,252,0,16,0,16,255,252,0,17,0,17,255,252,0,18,0,18,255,251,0,19,0,19,255,251,0,20,0,20,255,251,0,21,0,21,255,251,0,22,0,22,255,250,0,23,0,22,255,250,0,24,0,23,255,250,0,25,0,25,255,250,0,26,0,25,255,250,0,27,0,26,255,249,0,28,0,27,255,249,0,29,0,28,255,249,0,30,0,29,255,249,0,31,0,30,255,248,0,32,0,31,255,248,0,33,0,32,255,248,0,34,0,33,255,248,0,35,0,33,255,248,0,36,0,35,255,247,0,37,0,36,255,247,0,38,0,37,255,247,0,39,0,38,255,247,0,40,0,38,255,246,0,41,0,40,255,246,0,42,0,41,255,246,0,43,0,42,255,246,0,44,0,42,255,245,0,45,0,43,255,245,0,46,0,45,255,245,0,47,0,45,255,245,0,48,0,47,255,244,0,49,0,47,255,244,0,50,0,48,255,243,0,51,0,49,255,243,0,52,0,50,255,243,0,53,0,51,255,243,0,54,0,52,255,242,0,55,0,54,255,242,0,56,0,54,255,242,0,57,0,55,255,242,0,58,0,55,255,241,0,59,0,57,255,241,0,60,0,59,255,241,0,61,0,59,255,241,0,62,0,60,255,240,0,63,0,60,255,240,0,64,0,61,255,240,0,65,0,63,255,240,0,66,0,64,255,239,0,67,0,65,255,239,0,68,0,65,255,239,0,69,0,66,255,239,0,70,0,68,255,238,0,71,0,69,255,238,0,72,0,69,255,238,0,73,0,70,255,238,0,74,0,71,255,237,0,75,0,72,255,237,0,76,0,74,255,237,0,77,0,74,255,237,0,78,0,75,255,236,0,79,0,77,255,236,0,80,0,77,255,236,0,81,0,79,255,236,0,82,0,79,255,235,0,83,0,80,255,235,0,84,0,81,255,235,0,85,0,82,255,235,0,86,0,83,255,234,0,87,0,84,255,234,0,88,0,85,255,234,0,89,0,86,255,234,0,90,0,87,255,233,0,91,0,87,255,233,0,92,0,88,255,233,0,93,0,90,255,233,0,94,0,91,255,232,0,95,0,92,255,232,0,96,0,92,255,232,0,97,0,93,255,232,0,98,0,94,255,231,0,99,0,96,255,231,0,100,0,97,255,231,0,101,0,97,255,231,0,102,0,98,255,230,0,103,0,99,255,230,0,104,0,101,255,230,0,105,0,101,255,230,0,106,0,102,255,229,0,107,0,103,255,229,0,108,0,104,255,229,0,109,0,106,255,229,0,110,0,106,255,228,0,111,0,107,255,228,0,112,0,108,255,228,0,113,0,109,255,228,0,114,0,110,255,227,0,115,0,111,255,227,0,116,0,112,255,227,0,117,0,112,255,227,0,118,0,114,255,226,0,119,0,115,255,226,0,120,0,115,255,226,0,121,0,117,255,226,0,122,0,118,255,225,0,123,0,119,255,225,0,124,0,119,255,225,0,125,0,120,255,225,0,126,0,122,255,224,0,127,0,123,255,224,0,128,0,124,255,224,0,129,0,124,255,224,0,130,0,125,255,223,0,131,0,125,255,223,0,132,0,128,255,223,0,133,0,129,255,223,0,134,0,129,255,222,0,135,0,130,255,222,0,136,0,130,255,222,0,137,0,133,255,222,0,138,0,133,255,221,0,139,0,134,255,221,0,140,0,135,255,221,0,141,0,135,255,221,0,142,0,137,255,220,0,143,0,138,255,220,0,144,0,139,255,220,0,145,0,140,255,220,0,146,0,141,255,219,0,147,0,142,255,219,0,148,0,142,255,219,0,149,0,144,255,219,0,150,0,144,255,218,0,151,0,146,255,218,0,152,0,147,255,218,0,153,0,147,255,218,0,154,0,149,255,217,0,155,0,149,255,217,0,156,0,151,255,217,0,157,0,151,255,217,0,158,0,152,255,216,0,159,0,153,255,216,0,160,0,154,255,216,0,161,0,156,255,216,0,162,0,156,255,215,0,163,0,157,255,215,0,164,0,157,255,215,0,165,0,159,255,215,0,166,0,161,255,214,0,167,0,161,255,214,0,168,0,162,255,214,0,169,0,162,255,214,0,170,0,164,255,213,0,171,0,166,255,213,0,172,0,166,255,213,0,173,0,167,255,213,0,174,0,167,255,212,0,175,0,169,255,212,0,176,0,170,255,212,0,177,0,171,255,212,0,178,0,172,255,211,0,179,0,172,255,211,0,180,0,174,255,211,0,181,0,174,255,211,0,182,0,176,255,210,0,183,0,176,255,210,0,184,0,177,255,210,0,185,0,179,255,210,0,186,0,179,255,209,0,187,0,180,255,209,0,188,0,181,255,209,0,189,0,183,255,209,0,190,0,183,255,208,0,191,0,184,255,208,0,192,0,185,255,208,0,193,0,186,255,208,0,194,0,188,255,207,0,195,0,188,255,207,0,196,0,189,255,207,0,197,0,189,255,207,0,198,0,190,255,206,0,199,0,193,255,206,0,200,0,193,255,206,0,201,0,194,255,206,0,202,0,194,255,205,0,203,0,195,255,205,0,204,0,198,255,205,0,205,0,198,255,205,0,206,0,199,255,204,0,207,0,199,255,204,0,208,0,200,255,204,0,209,0,201,255,204,0,210,0,203,255,203,0,211,0,204,255,203,0,212,0,204,255,203,0,213,0,206,255,203,0,214,0,206,255,202,0,215,0,207,255,202,0,216,0,208,255,202,0,217,0,209,255,202,0,218,0,211,255,201,0,219,0,211,255,201,0,220,0,212,255,201,0,221,0,213,255,201,0,222,0,214,255,200,0,223,0,215,255,200,0,224,0,216,255,200,0,225,0,217,255,200,0,226,0,217,255,199,0,227,0,219,255,199,0,228,0,220,255,199,0,229,0,221,255,199,0,230,0,221,255,198,0,231,0,222,255,198,0,232,0,224,255,198,0,233,0,225,255,198,0,234,0,226,255,197,0,235,0,226,255,197,0,236,0,227,255,197,0,237,0,229,255,197,0,238,0,230,255,196,0,239,0,231,255,196,0,240,0,231,255,196,0,241,0,232,255,196,0,242,0,233,255,195,0,243,0,235,255,195,0,244,0,236,255,195,0,245,0,236,255,195,0,246,0,237,255,194,0,247,0,238,255,194,0,248,0,239,255,194,0,249,0,240,255,194,0,250,0,241,255,193,0,251,0,242,255,193,0,252,0,243,255,193,0,253,0,244,255,193,0,254,0,244,255,192,0,255,0,246,255,192,0,248,8,255,0,8,0,8,255,254,0,9,0,9,255,253,0,10,0,10,255,253,0,11,0,11,255,253,0,12,0,12,255,253,0,13,0,13,255,253,0,14,0,14,255,253,0,15,0,15,255,252,0,16,0,16,255,252,0,17,0,17,255,252,0,18,0,18,255,251,0,19,0,19,255,251,0,20,0,20,255,251,0,21,0,21,255,251,0,22,0,22,255,250,0,23,0,22,255,250,0,24,0,23,255,250,0,25,0,25,255,250,0,26,0,25,255,250,0,27,0,26,255,249,0,28,0,27,255,249,0,29,0,28,255,249,0,30,0,29,255,249,0,31,0,30,255,248,0,32,0,31,255,248,0,33,0,32,255,248,0,34,0,33,255,248,0,35,0,33,255,248,0,36,0,35,255,247,0,37,0,36,255,247,0,38,0,37,255,247,0,39,0,38,255,247,0,40,0,38,255,246,0,41,0,40,255,246,0,42,0,41,255,246,0,43,0,42,255,246,0,44,0,42,255,245,0,45,0,43,255,245,0,46,0,45,255,245,0,47,0,45,255,245,0,48,0,47,255,244,0,49,0,47,255,244,0,50,0,48,255,243,0,51,0,49,255,243,0,52,0,50,255,243,0,53,0,51,255,243,0,54,0,52,255,242,0,55,0,54,255,242,0,56,0,54,255,242,0,57,0,55,255,242,0,58,0,55,255,241,0,59,0,57,255,241,0,60,0,59,255,241,0,61,0,59,255,241,0,62,0,60,255,240,0,63,0,60,255,240,0,64,0,61,255,240,0,65,0,63,255,240,0,66,0,64,255,239,0,67,0,65,255,239,0,68,0,65,255,239,0,69,0,66,255,239,0,70,0,68,255,238,0,71,0,69,255,238,0,72,0,69,255,238,0,73,0,70,255,238,0,74,0,71,255,237,0,75,0,72,255,237,0,76,0,74,255,237,0,77,0,74,255,237,0,78,0,75,255,236,0,79,0,77,255,236,0,80,0,77,255,236,0,81,0,79,255,236,0,82,0,79,255,235,0,83,0,80,255,235,0,84,0,81,255,235,0,85,0,82,255,235,0,86,0,83,255,234,0,87,0,84,255,234,0,88,0,85,255,234,0,89,0,86,255,234,0,90,0,87,255,233,0,91,0,87,255,233,0,92,0,88,255,233,0,93,0,90,255,233,0,94,0,91,255,232,0,95,0,92,255,232,0,96,0,92,255,232,0,97,0,93,255,232,0,98,0,94,255,231,0,99,0,96,255,231,0,100,0,97,255,231,0,101,0,97,255,231,0,102,0,98,255,230,0,103,0,99,255,230,0,104,0,101,255,230,0,105,0,101,255,230,0,106,0,102,255,229,0,107,0,103,255,229,0,108,0,104,255,229,0,109,0,106,255,229,0,110,0,106,255,228,0,111,0,107,255,228,0,112,0,108,255,228,0,113,0,109,255,228,0,114,0,110,255,227,0,115,0,111,255,227,0,116,0,112,255,227,0,117,0,112,255,227,0,118,0,114,255,226,0,119,0,115,255,226,0,120,0,115,255,226,0,121,0,117,255,226,0,122,0,118,255,225,0,123,0,119,255,225,0,124,0,119,255,225,0,125,0,120,255,225,0,126,0,122,255,224,0,127,0,123,255,224,0,128,0,124,255,224,0,129,0,124,255,224,0,130,0,125,255,223,0,131,0,125,255,223,0,132,0,128,255,223,0,133,0,129,255,223,0,134,0,129,255,222,0,135,0,130,255,222,0,136,0,130,255,222,0,137,0,133,255,222,0,138,0,133,255,221,0,139,0,134,255,221,0,140,0,135,255,221,0,141,0,135,255,221,0,142,0,137,255,220,0,143,0,138,255,220,0,144,0,139,255,220,0,145,0,140,255,220,0,146,0,141,255,219,0,147,0,142,255,219,0,148,0,142,255,219,0,149,0,144,255,219,0,150,0,144,255,218,0,151,0,146,255,218,0,152,0,147,255,218,0,153,0,147,255,218,0,154,0,149,255,217,0,155,0,149,255,217,0,156,0,151,255,217,0,157,0,151,255,217,0,158,0,152,255,216,0,159,0,153,255,216,0,160,0,154,255,216,0,161,0,156,255,216,0,162,0,156,255,215,0,163,0,157,255,215,0,164,0,157,255,215,0,165,0,159,255,215,0,166,0,161,255,214,0,167,0,161,255,214,0,168,0,162,255,214,0,169,0,162,255,214,0,170,0,164,255,213,0,171,0,166,255,213,0,172,0,166,255,213,0,173,0,167,255,213,0,174,0,167,255,212,0,175,0,169,255,212,0,176,0,170,255,212,0,177,0,171,255,212,0,178,0,172,255,211,0,179,0,172,255,211,0,180,0,174,255,211,0,181,0,174,255,211,0,182,0,176,255,210,0,183,0,176,255,210,0,184,0,177,255,210,0,185,0,179,255,210,0,186,0,179,255,209,0,187,0,180,255,209,0,188,0,181,255,209,0,189,0,183,255,209,0,190,0,183,255,208,0,191,0,184,255,208,0,192,0,185,255,208,0,193,0,186,255,208,0,194,0,188,255,207,0,195,0,188,255,207,0,196,0,189,255,207,0,197,0,189,255,207,0,198,0,190,255,206,0,199,0,193,255,206,0,200,0,193,255,206,0,201,0,194,255,206,0,202,0,194,255,205,0,203,0,195,255,205,0,204,0,198,255,205,0,205,0,198,255,205,0,206,0,199,255,204,0,207,0,199,255,204,0,208,0,200,255,204,0,209,0,201,255,204,0,210,0,203,255,203,0,211,0,204,255,203,0,212,0,204,255,203,0,213,0,206,255,203,0,214,0,206,255,202,0,215,0,207,255,202,0,216,0,208,255,202,0,217,0,209,255,202,0,218,0,211,255,201,0,219,0,211,255,201,0,220,0,212,255,201,0,221,0,213,255,201,0,222,0,214,255,200,0,223,0,215,255,200,0,224,0,216,255,200,0,225,0,217,255,200,0,226,0,217,255,199,0,227,0,219,255,199,0,228,0,220,255,199,0,229,0,221,255,199,0,230,0,221,255,198,0,231,0,222,255,198,0,232,0,224,255,198,0,233,0,225,255,198,0,234,0,226,255,197,0,235,0,226,255,197,0,236,0,227,255,197,0,237,0,229,255,197,0,238,0,230,255,196,0,239,0,231,255,196,0,240,0,231,255,196,0,241,0,232,255,196,0,242,0,233,255,195,0,243,0,235,255,195,0,244,0,236,255,195,0,245,0,236,255,195,0,246,0,237,255,194,0,247,0,238,255,194,0,248,0,239,255,194,0,249,0,240,255,194,0,250,0,241,255,193,0,251,0,242,255,193,0,252,0,243,255,193,0,253,0,244,255,193,0,254,0,244,255,192,0,255,0,246,255,192,0,0, \ No newline at end of file diff --git a/src/Nazara/Utility/SimpleTextDrawer.cpp b/src/Nazara/Utility/SimpleTextDrawer.cpp new file mode 100644 index 000000000..dc5e50dd0 --- /dev/null +++ b/src/Nazara/Utility/SimpleTextDrawer.cpp @@ -0,0 +1,302 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +NzSimpleTextDrawer::NzSimpleTextDrawer() : +m_color(NzColor::White), +m_fontListener(this), +m_style(nzTextStyle_Regular) +{ + SetFont(NzFont::GetDefault()); +} + +const NzRectui& NzSimpleTextDrawer::GetBounds() const +{ + if (!m_glyphUpdated) + UpdateGlyphs(); + + return m_bounds; +} + +unsigned int NzSimpleTextDrawer::GetCharacterSize() const +{ + return m_characterSize; +} + +const NzColor& NzSimpleTextDrawer::GetColor() const +{ + return m_color; +} + +NzFont* NzSimpleTextDrawer::GetFont() const +{ + return m_font; +} + +nzUInt32 NzSimpleTextDrawer::GetStyle() const +{ + return m_style; +} + +void NzSimpleTextDrawer::SetCharacterSize(unsigned int characterSize) +{ + m_characterSize = characterSize; + + m_glyphUpdated = false; +} + +void NzSimpleTextDrawer::SetColor(const NzColor& color) +{ + m_color = color; + + m_glyphUpdated = false; +} + +void NzSimpleTextDrawer::SetFont(NzFont* font) +{ + m_font = font; + m_fontListener = font; + + m_glyphUpdated = false; +} + +void NzSimpleTextDrawer::SetStyle(nzUInt32 style) +{ + m_style = style; + + m_glyphUpdated = false; +} + +void NzSimpleTextDrawer::SetText(const NzString& str) +{ + m_text = str; + + m_glyphUpdated = false; +} + +NzSimpleTextDrawer NzSimpleTextDrawer::Draw(const NzString& str, unsigned int characterSize, nzUInt32 style, const NzColor& color) +{ + NzSimpleTextDrawer drawer; + drawer.SetCharacterSize(characterSize); + drawer.SetColor(color); + drawer.SetStyle(style); + drawer.SetText(str); + + return drawer; +} + +NzSimpleTextDrawer NzSimpleTextDrawer::Draw(NzFont* font, const NzString& str, unsigned int characterSize, nzUInt32 style, const NzColor& color) +{ + NzSimpleTextDrawer drawer; + drawer.SetCharacterSize(characterSize); + drawer.SetColor(color); + drawer.SetFont(font); + drawer.SetStyle(style); + drawer.SetText(str); + + return drawer; +} + +NzFont* NzSimpleTextDrawer::GetFont(unsigned int index) const +{ + #if NAZARA_UTILITY_SAFE + if (index > 0) + { + NazaraError("Font index out of range (" + NzString::Number(index) + " >= 1)"); + return nullptr; + } + #endif + + return m_font; +} + +unsigned int NzSimpleTextDrawer::GetFontCount() const +{ + return 1; +} + +const NzAbstractTextDrawer::Glyph& NzSimpleTextDrawer::GetGlyph(unsigned int index) const +{ + if (!m_glyphUpdated) + UpdateGlyphs(); + + return m_glyphs[index]; +} + +unsigned int NzSimpleTextDrawer::GetGlyphCount() const +{ + if (!m_glyphUpdated) + UpdateGlyphs(); + + return m_glyphs.size(); +} + +bool NzSimpleTextDrawer::OnObjectModified(const NzRefCounted* object, int index, unsigned int code) +{ + NazaraUnused(object); + NazaraUnused(index); + + #ifdef NAZARA_DEBUG + if (m_font != object) + { + NazaraInternalError("Not listening to " + NzString::Pointer(object)); + return false; + } + #endif + + if (code == NzFont::ModificationCode_AtlasChanged || + code == NzFont::ModificationCode_AtlasLayerChanged || + code == NzFont::ModificationCode_GlyphCacheCleared) + { + m_glyphUpdated = false; + } + + return true; +} + +void NzSimpleTextDrawer::OnObjectReleased(const NzRefCounted* object, int index) +{ + NazaraUnused(object); + NazaraUnused(index); + + #ifdef NAZARA_DEBUG + if (m_font != object) + { + NazaraInternalError("Not listening to " + NzString::Pointer(object)); + return; + } + #endif + + SetFont(nullptr); +} + +void NzSimpleTextDrawer::UpdateGlyphs() const +{ + m_bounds.MakeZero(); + m_glyphs.clear(); + m_glyphUpdated = true; + + #if NAZARA_UTILITY_SAFE + if (!m_font || !m_font->IsValid()) + { + NazaraError("Invalid font"); + return; + } + #endif + + if (m_text.IsEmpty()) + return; + + ///TODO: Itération UTF-8 => UTF-32 sans allocation de buffer (Exposer utf8cpp ?) + unsigned int size; + std::unique_ptr characters(m_text.GetUtf32Buffer(&size)); + if (!characters) + { + NazaraError("Invalid character set"); + return; + } + + const NzFont::SizeInfo& sizeInfo = m_font->GetSizeInfo(m_characterSize); + + // "Curseur" de dessin + NzVector2ui drawPos(0, m_characterSize); + + // On calcule les bornes en flottants pour accélérer les calculs (il est coûteux de changer de type trop souvent) + bool firstGlyph = true; + NzRectf textBounds = NzRectf::Zero(); + m_glyphs.reserve(size); + nzUInt32 previousCharacter = 0; + for (unsigned int i = 0; i < size; ++i) + { + char32_t character = characters[i]; + + if (previousCharacter != 0) + drawPos.x += m_font->GetKerning(m_characterSize, previousCharacter, character); + + previousCharacter = character; + + bool whitespace = true; + switch (character) + { + case ' ': + drawPos.x += sizeInfo.spaceAdvance; + break; + + case '\n': + drawPos.x = 0; + drawPos.y += sizeInfo.lineHeight; + break; + + case '\t': + drawPos.x += sizeInfo.spaceAdvance*4; + break; + + default: + whitespace = false; + break; + } + + if (whitespace) + continue; // Inutile d'avoir un glyphe pour un espace blanc + + const NzFont::Glyph& fontGlyph = m_font->GetGlyph(m_characterSize, m_style, character); + if (!fontGlyph.valid) + continue; // Le glyphe n'a pas été correctement chargé, que pouvons-nous faire d'autre que le passer + + Glyph glyph; + glyph.atlas = m_font->GetAtlas()->GetLayer(fontGlyph.layerIndex); + glyph.atlasRect = fontGlyph.atlasRect; + glyph.color = m_color; + glyph.flipped = fontGlyph.flipped; + + int advance = fontGlyph.advance; + + NzRectf bounds(fontGlyph.aabb); + bounds.x += drawPos.x; + bounds.y += drawPos.y; + + if (fontGlyph.requireFauxBold) + { + // On va agrandir le glyphe pour simuler le gras (idée moisie, mais idée quand même) + NzVector2f center = bounds.GetCenter(); + + bounds.width *= 1.1f; + bounds.height *= 1.1f; + + // On le replace à la bonne hauteur + NzVector2f offset(bounds.GetCenter() - center); + bounds.y -= offset.y; + + // On ajuste l'espacement + advance += advance/10; + } + + // On "penche" le glyphe pour obtenir un semblant d'italique + float italic = (fontGlyph.requireFauxItalic) ? 0.208f : 0.f; + float italicTop = italic * bounds.y; + float italicBottom = italic * bounds.GetMaximum().y; + + glyph.corners[0].Set(bounds.x - italicTop, bounds.y); + glyph.corners[1].Set(bounds.x + bounds.width - italicTop, bounds.y); + glyph.corners[2].Set(bounds.x - italicBottom, bounds.y + bounds.height); + glyph.corners[3].Set(bounds.x + bounds.width - italicBottom, bounds.y + bounds.height); + + if (firstGlyph) + { + textBounds.Set(glyph.corners[0]); + firstGlyph = false; + } + + for (unsigned int j = 0; j < 4; ++j) + textBounds.ExtendTo(glyph.corners[j]); + + drawPos.x += advance; + m_glyphs.push_back(glyph); + } + + m_bounds.Set(std::floor(textBounds.x), std::floor(textBounds.y), std::ceil(textBounds.width), std::ceil(textBounds.height)); +} diff --git a/src/Nazara/Utility/SkeletalMesh.cpp b/src/Nazara/Utility/SkeletalMesh.cpp index 5926e7880..5604bb4d8 100644 --- a/src/Nazara/Utility/SkeletalMesh.cpp +++ b/src/Nazara/Utility/SkeletalMesh.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Skeleton.cpp b/src/Nazara/Utility/Skeleton.cpp index 7d3a38f24..84ddf661b 100644 --- a/src/Nazara/Utility/Skeleton.cpp +++ b/src/Nazara/Utility/Skeleton.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -32,7 +32,7 @@ bool NzSkeleton::Create(unsigned int jointCount) #if NAZARA_UTILITY_SAFE if (jointCount == 0) { - NazaraError("Joint count must be over 0"); + NazaraError("Joint count must be over zero"); return false; } #endif diff --git a/src/Nazara/Utility/SoftwareBuffer.cpp b/src/Nazara/Utility/SoftwareBuffer.cpp index b91ca76d0..b21259dfa 100644 --- a/src/Nazara/Utility/SoftwareBuffer.cpp +++ b/src/Nazara/Utility/SoftwareBuffer.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/SoftwareBuffer.hpp b/src/Nazara/Utility/SoftwareBuffer.hpp index 556eeaa0f..abe5419db 100644 --- a/src/Nazara/Utility/SoftwareBuffer.hpp +++ b/src/Nazara/Utility/SoftwareBuffer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/StaticMesh.cpp b/src/Nazara/Utility/StaticMesh.cpp index b54126008..229ce0cd0 100644 --- a/src/Nazara/Utility/StaticMesh.cpp +++ b/src/Nazara/Utility/StaticMesh.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -23,7 +23,9 @@ NzStaticMesh::~NzStaticMesh() void NzStaticMesh::Center() { - NzVector3f offset(m_aabb.x + m_aabb.width/2.f, m_aabb.y + m_aabb.height/2.f, m_aabb.z + m_aabb.depth/2.f); + ///DOC: Invalider l'AABB après ça + NzBoxf aabb(m_parent->GetAABB()); + NzVector3f offset(aabb.x + aabb.width/2.f, aabb.y + aabb.height/2.f, aabb.z + aabb.depth/2.f); NzVertexMapper mapper(this); NzSparsePtr position = mapper.GetComponentPtr(nzVertexComponent_Position); diff --git a/src/Nazara/Utility/SubMesh.cpp b/src/Nazara/Utility/SubMesh.cpp index 3db528225..5ed92b956 100644 --- a/src/Nazara/Utility/SubMesh.cpp +++ b/src/Nazara/Utility/SubMesh.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/TriangleIterator.cpp b/src/Nazara/Utility/TriangleIterator.cpp index 72003cf8b..7057d6d8f 100644 --- a/src/Nazara/Utility/TriangleIterator.cpp +++ b/src/Nazara/Utility/TriangleIterator.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -46,8 +46,8 @@ bool NzTriangleIterator::Advance() case nzPrimitiveMode_TriangleStrip: m_triangleIndices[2] = m_indexMapper.Get(m_currentIndex++); - m_triangleIndices[1] = m_triangleIndices[2]; m_triangleIndices[0] = m_triangleIndices[1]; + m_triangleIndices[1] = m_triangleIndices[2]; break; default: diff --git a/src/Nazara/Utility/Utility.cpp b/src/Nazara/Utility/Utility.cpp index df38b312c..dab509037 100644 --- a/src/Nazara/Utility/Utility.cpp +++ b/src/Nazara/Utility/Utility.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -48,6 +50,12 @@ bool NzUtility::Initialize() return false; } + if (!NzFont::Initialize()) + { + NazaraError("Failed to initialize fonts"); + return false; + } + if (!NzPixelFormat::Initialize()) { NazaraError("Failed to initialize pixel formats"); @@ -70,6 +78,9 @@ bool NzUtility::Initialize() // Il s'agit ici d'une liste LIFO, le dernier loader enregistré possède la priorité /// Loaders génériques + // Font + NzLoaders_FreeType_Register(); + // Image NzLoaders_STB_Register(); // Loader générique (STB) @@ -109,6 +120,7 @@ void NzUtility::Uninitialize() // Libération du module s_moduleReferenceCounter = 0; + NzLoaders_FreeType_Unregister(); NzLoaders_MD2_Unregister(); NzLoaders_MD5Anim_Unregister(); NzLoaders_MD5Mesh_Unregister(); @@ -118,6 +130,7 @@ void NzUtility::Uninitialize() NzWindow::Uninitialize(); NzVertexDeclaration::Uninitialize(); NzPixelFormat::Uninitialize(); + NzFont::Uninitialize(); NzBuffer::Uninitialize(); NazaraNotice("Uninitialized: Utility module"); @@ -146,7 +159,7 @@ unsigned int NzUtility::ComponentCount[nzComponentType_Max+1] = static_assert(nzComponentType_Max+1 == 14, "Component count array is incomplete"); -unsigned int NzUtility::ComponentStride[nzComponentType_Max+1] = +std::size_t NzUtility::ComponentStride[nzComponentType_Max+1] = { 4*sizeof(nzUInt8), // nzComponentType_Color 1*sizeof(double), // nzComponentType_Double1 diff --git a/src/Nazara/Utility/VertexBuffer.cpp b/src/Nazara/Utility/VertexBuffer.cpp index 08f12381f..ffdf4a42c 100644 --- a/src/Nazara/Utility/VertexBuffer.cpp +++ b/src/Nazara/Utility/VertexBuffer.cpp @@ -1,19 +1,28 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include +#include #include #include +NzVertexBuffer::NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer) +{ + NzErrorFlags(nzErrorFlag_ThrowException, true); + Reset(vertexDeclaration, buffer); +} + NzVertexBuffer::NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset) { + NzErrorFlags(nzErrorFlag_ThrowException, true); Reset(vertexDeclaration, buffer, startOffset, endOffset); } -NzVertexBuffer::NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzBufferStorage storage, nzBufferUsage usage) +NzVertexBuffer::NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzUInt32 storage, nzBufferUsage usage) { + NzErrorFlags(nzErrorFlag_ThrowException, true); Reset(vertexDeclaration, length, storage, usage); } @@ -27,15 +36,6 @@ m_vertexCount(vertexBuffer.m_vertexCount) { } -NzVertexBuffer::NzVertexBuffer(NzVertexBuffer&& vertexBuffer) noexcept : -m_buffer(std::move(vertexBuffer.m_buffer)), -m_vertexDeclaration(std::move(vertexBuffer.m_vertexDeclaration)), -m_endOffset(vertexBuffer.m_endOffset), -m_startOffset(vertexBuffer.m_startOffset), -m_vertexCount(vertexBuffer.m_vertexCount) -{ -} - NzVertexBuffer::~NzVertexBuffer() { NotifyDestroy(); @@ -50,6 +50,12 @@ bool NzVertexBuffer::Fill(const void* data, unsigned int startVertex, unsigned i bool NzVertexBuffer::FillRaw(const void* data, unsigned int offset, unsigned int size, bool forceDiscard) { #if NAZARA_UTILITY_SAFE + if (!m_buffer) + { + NazaraError("No buffer"); + return nullptr; + } + if (m_startOffset + offset + size > m_endOffset) { NazaraError("Exceeding virtual buffer size"); @@ -118,6 +124,12 @@ void* NzVertexBuffer::Map(nzBufferAccess access, unsigned int startVertex, unsig void* NzVertexBuffer::Map(nzBufferAccess access, unsigned int startVertex, unsigned int length) const { #if NAZARA_UTILITY_SAFE + if (!m_buffer) + { + NazaraError("No buffer"); + return nullptr; + } + if (!m_vertexDeclaration) { NazaraError("No vertex declaration"); @@ -168,6 +180,11 @@ void NzVertexBuffer::Reset() m_vertexDeclaration.Reset(); } +void NzVertexBuffer::Reset(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer) +{ + Reset(vertexDeclaration, buffer, 0, buffer->GetSize()-1); +} + void NzVertexBuffer::Reset(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset) { #if NAZARA_UTILITY_SAFE @@ -177,9 +194,9 @@ void NzVertexBuffer::Reset(const NzVertexDeclaration* vertexDeclaration, NzBuffe return; } - if (endOffset > startOffset) + if (startOffset > endOffset) { - NazaraError("End offset cannot be over start offset"); + NazaraError("Start offset cannot be over end offset"); return; } @@ -204,7 +221,7 @@ void NzVertexBuffer::Reset(const NzVertexDeclaration* vertexDeclaration, NzBuffe m_vertexDeclaration = vertexDeclaration; } -void NzVertexBuffer::Reset(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzBufferStorage storage, nzBufferUsage usage) +void NzVertexBuffer::Reset(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzUInt32 storage, nzBufferUsage usage) { m_endOffset = length * ((vertexDeclaration) ? vertexDeclaration->GetStride() : 1); m_startOffset = 0; @@ -224,16 +241,7 @@ void NzVertexBuffer::Reset(const NzVertexBuffer& vertexBuffer) m_vertexDeclaration = vertexBuffer.m_vertexDeclaration; } -void NzVertexBuffer::Reset(NzVertexBuffer&& vertexBuffer) noexcept -{ - m_buffer = std::move(vertexBuffer.m_buffer); - m_endOffset = vertexBuffer.m_endOffset; - m_startOffset = vertexBuffer.m_startOffset; - m_vertexCount = vertexBuffer.m_vertexCount; - m_vertexDeclaration = std::move(vertexBuffer.m_vertexDeclaration); -} - -bool NzVertexBuffer::SetStorage(nzBufferStorage storage) +bool NzVertexBuffer::SetStorage(nzUInt32 storage) { return m_buffer->SetStorage(storage); } @@ -263,10 +271,3 @@ NzVertexBuffer& NzVertexBuffer::operator=(const NzVertexBuffer& vertexBuffer) return *this; } - -NzVertexBuffer& NzVertexBuffer::operator=(NzVertexBuffer&& vertexBuffer) noexcept -{ - Reset(vertexBuffer); - - return *this; -} diff --git a/src/Nazara/Utility/VertexDeclaration.cpp b/src/Nazara/Utility/VertexDeclaration.cpp index 8b0633573..05f680380 100644 --- a/src/Nazara/Utility/VertexDeclaration.cpp +++ b/src/Nazara/Utility/VertexDeclaration.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -192,6 +192,13 @@ bool NzVertexDeclaration::Initialize() NazaraAssert(declaration->GetStride() == sizeof(NzVertexStruct_XY), "Invalid stride for declaration nzVertexLayout_XY"); + // nzVertexLayout_XY_Color : NzVertexStruct_XY_Color + declaration = &s_declarations[nzVertexLayout_XY_Color]; + declaration->EnableComponent(nzVertexComponent_Position, nzComponentType_Float2, NzOffsetOf(NzVertexStruct_XY_Color, position)); + declaration->EnableComponent(nzVertexComponent_Color, nzComponentType_Color, NzOffsetOf(NzVertexStruct_XY_Color, color)); + + NazaraAssert(declaration->GetStride() == sizeof(NzVertexStruct_XY_Color), "Invalid stride for declaration nzVertexLayout_XY_Color"); + // nzVertexLayout_XY_UV : NzVertexStruct_XY_UV declaration = &s_declarations[nzVertexLayout_XY_UV]; declaration->EnableComponent(nzVertexComponent_Position, nzComponentType_Float2, NzOffsetOf(NzVertexStruct_XY_UV, position)); @@ -205,6 +212,21 @@ bool NzVertexDeclaration::Initialize() NazaraAssert(declaration->GetStride() == sizeof(NzVertexStruct_XYZ), "Invalid stride for declaration nzVertexLayout_XYZ"); + // nzVertexLayout_XYZ_Color : NzVertexStruct_XYZ_Color + declaration = &s_declarations[nzVertexLayout_XYZ_Color]; + declaration->EnableComponent(nzVertexComponent_Position, nzComponentType_Float3, NzOffsetOf(NzVertexStruct_XYZ_Color, position)); + declaration->EnableComponent(nzVertexComponent_Color, nzComponentType_Color, NzOffsetOf(NzVertexStruct_XYZ_Color, color)); + + NazaraAssert(declaration->GetStride() == sizeof(NzVertexStruct_XYZ_Color), "Invalid stride for declaration nzVertexLayout_XYZ_Color"); + + // nzVertexLayout_XYZ_Color_UV : NzVertexStruct_XYZ_Color_UV + declaration = &s_declarations[nzVertexLayout_XYZ_Color_UV]; + declaration->EnableComponent(nzVertexComponent_Position, nzComponentType_Float3, NzOffsetOf(NzVertexStruct_XYZ_Color_UV, position)); + declaration->EnableComponent(nzVertexComponent_Color, nzComponentType_Color, NzOffsetOf(NzVertexStruct_XYZ_Color_UV, color)); + declaration->EnableComponent(nzVertexComponent_TexCoord, nzComponentType_Float2, NzOffsetOf(NzVertexStruct_XYZ_Color_UV, uv)); + + NazaraAssert(declaration->GetStride() == sizeof(NzVertexStruct_XYZ_Color_UV), "Invalid stride for declaration nzVertexLayout_XYZ_Color_UV"); + // nzVertexLayout_XYZ_Normal : NzVertexStruct_XYZ_Normal declaration = &s_declarations[nzVertexLayout_XYZ_Normal]; declaration->EnableComponent(nzVertexComponent_Position, nzComponentType_Float3, NzOffsetOf(NzVertexStruct_XYZ_Normal, position)); diff --git a/src/Nazara/Utility/VertexMapper.cpp b/src/Nazara/Utility/VertexMapper.cpp index 08f257f2c..e4b272803 100644 --- a/src/Nazara/Utility/VertexMapper.cpp +++ b/src/Nazara/Utility/VertexMapper.cpp @@ -1,11 +1,10 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include -#include #include #include #include @@ -13,7 +12,8 @@ NzVertexMapper::NzVertexMapper(NzSubMesh* subMesh) { - NzErrorFlags flags(nzErrorFlag_ThrowException); + NzErrorFlags flags(nzErrorFlag_ThrowException, true); + NzVertexBuffer* buffer = nullptr; switch (subMesh->GetAnimationType()) { @@ -37,12 +37,19 @@ NzVertexMapper::NzVertexMapper(NzSubMesh* subMesh) NazaraInternalError("Animation type not handled (0x" + NzString::Number(subMesh->GetAnimationType(), 16) + ')'); } - m_declaration = buffer->GetVertexDeclaration(); m_vertexCount = subMesh->GetVertexCount(); m_mapper.Map(buffer, nzBufferAccess_ReadWrite); } +NzVertexMapper::NzVertexMapper(NzVertexBuffer* vertexBuffer, unsigned int vertexCount) +{ + NzErrorFlags flags(nzErrorFlag_ThrowException, true); + + m_mapper.Map(vertexBuffer, nzBufferAccess_ReadWrite); + m_vertexCount = vertexCount; +} + NzVertexMapper::~NzVertexMapper() = default; unsigned int NzVertexMapper::GetVertexCount() const diff --git a/src/Nazara/Utility/VideoMode.cpp b/src/Nazara/Utility/VideoMode.cpp index ce28eeed3..69abdf4a1 100644 --- a/src/Nazara/Utility/VideoMode.cpp +++ b/src/Nazara/Utility/VideoMode.cpp @@ -1,10 +1,11 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include +#include #include NzVideoMode::NzVideoMode() : diff --git a/src/Nazara/Utility/VideoModeImpl.hpp b/src/Nazara/Utility/VideoModeImpl.hpp index e58e82ce3..229a6de0a 100644 --- a/src/Nazara/Utility/VideoModeImpl.hpp +++ b/src/Nazara/Utility/VideoModeImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Win32/CursorImpl.cpp b/src/Nazara/Utility/Win32/CursorImpl.cpp index 68014b6ae..1b5f2ddf1 100644 --- a/src/Nazara/Utility/Win32/CursorImpl.cpp +++ b/src/Nazara/Utility/Win32/CursorImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Win32/CursorImpl.hpp b/src/Nazara/Utility/Win32/CursorImpl.hpp index 56ed97b00..d539886c8 100644 --- a/src/Nazara/Utility/Win32/CursorImpl.hpp +++ b/src/Nazara/Utility/Win32/CursorImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Win32/IconImpl.cpp b/src/Nazara/Utility/Win32/IconImpl.cpp index f356d206d..078a9fece 100644 --- a/src/Nazara/Utility/Win32/IconImpl.cpp +++ b/src/Nazara/Utility/Win32/IconImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Win32/IconImpl.hpp b/src/Nazara/Utility/Win32/IconImpl.hpp index 05c3495fa..a384fc852 100644 --- a/src/Nazara/Utility/Win32/IconImpl.hpp +++ b/src/Nazara/Utility/Win32/IconImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Win32/InputImpl.cpp b/src/Nazara/Utility/Win32/InputImpl.cpp index bafaf0f24..306f6b6ca 100644 --- a/src/Nazara/Utility/Win32/InputImpl.cpp +++ b/src/Nazara/Utility/Win32/InputImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -222,7 +222,7 @@ NzVector2i NzEventImpl::GetMousePosition(const NzWindow& relativeTo) } else { - NazaraError("Window's handle is invalid"); + NazaraError("Invalid window handle"); // Attention que (-1, -1) est une position tout à fait valide et ne doit pas servir de test return NzVector2i(-1, -1); @@ -289,5 +289,5 @@ void NzEventImpl::SetMousePosition(int x, int y, const NzWindow& relativeTo) SetCursorPos(pos.x, pos.y); } else - NazaraError("Window's handle is invalid"); + NazaraError("Invalid window handle"); } diff --git a/src/Nazara/Utility/Win32/InputImpl.hpp b/src/Nazara/Utility/Win32/InputImpl.hpp index 2c176377f..0d3f3fb19 100644 --- a/src/Nazara/Utility/Win32/InputImpl.hpp +++ b/src/Nazara/Utility/Win32/InputImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Win32/VideoModeImpl.cpp b/src/Nazara/Utility/Win32/VideoModeImpl.cpp index 638724485..b6d03bb96 100644 --- a/src/Nazara/Utility/Win32/VideoModeImpl.cpp +++ b/src/Nazara/Utility/Win32/VideoModeImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Utility/Win32/WindowImpl.cpp b/src/Nazara/Utility/Win32/WindowImpl.cpp index 64a1fae74..e1690def1 100644 --- a/src/Nazara/Utility/Win32/WindowImpl.cpp +++ b/src/Nazara/Utility/Win32/WindowImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -79,7 +79,7 @@ m_scrolling(0) { } -bool NzWindowImpl::Create(NzVideoMode mode, const NzString& title, nzUInt32 style) +bool NzWindowImpl::Create(const NzVideoMode& mode, const NzString& title, nzUInt32 style) { bool fullscreen = (style & nzWindowStyle_Fullscreen) != 0; DWORD win32Style, win32StyleEx; @@ -183,7 +183,7 @@ bool NzWindowImpl::Create(NzVideoMode mode, const NzString& title, nzUInt32 styl GetWindowRect(m_handle, &windowRect); m_position.Set(windowRect.left, windowRect.top); - m_size.Set(clientRect.right-clientRect.left, clientRect.bottom-clientRect.top); + m_size.Set(clientRect.right - clientRect.left, clientRect.bottom - clientRect.top); return true; } diff --git a/src/Nazara/Utility/Win32/WindowImpl.hpp b/src/Nazara/Utility/Win32/WindowImpl.hpp index ebd91f9ee..309cd20e7 100644 --- a/src/Nazara/Utility/Win32/WindowImpl.hpp +++ b/src/Nazara/Utility/Win32/WindowImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -34,7 +34,7 @@ class NzWindowImpl : NzNonCopyable NzWindowImpl(NzWindow* parent); ~NzWindowImpl() = default; - bool Create(NzVideoMode mode, const NzString& title, nzUInt32 style); + bool Create(const NzVideoMode& mode, const NzString& title, nzUInt32 style); bool Create(NzWindowHandle handle); void Destroy(); diff --git a/src/Nazara/Utility/Window.cpp b/src/Nazara/Utility/Window.cpp index 00b01a0f5..673396889 100644 --- a/src/Nazara/Utility/Window.cpp +++ b/src/Nazara/Utility/Window.cpp @@ -1,9 +1,10 @@ -// Copyright (C) 2014 Jérôme Leclercq +// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include +#include #include #include #include @@ -45,15 +46,8 @@ m_waitForEvent(false) m_impl(nullptr) #endif { + NzErrorFlags flags(nzErrorFlag_ThrowException, true); Create(mode, title, style); - - #ifdef NAZARA_DEBUG - if (!m_impl) - { - NazaraError("Failed to create window"); - throw std::runtime_error("Constructor failed"); - } - #endif } NzWindow::NzWindow(NzWindowHandle handle) : @@ -65,15 +59,8 @@ m_waitForEvent(false) m_impl(nullptr) #endif { + NzErrorFlags flags(nzErrorFlag_ThrowException, true); Create(handle); - - #ifdef NAZARA_DEBUG - if (!m_impl) - { - NazaraError("Failed to create window"); - throw std::runtime_error("Constructor failed"); - } - #endif } NzWindow::~NzWindow() diff --git a/writing style.md b/writing style.md new file mode 100644 index 000000000..cc6da29f7 --- /dev/null +++ b/writing style.md @@ -0,0 +1,84 @@ +Examples writing-style: + +Alphabetical order for everything and try to regroup each methods beginning with the same letter in the header + +Class header: + +// Copyright (C) 2014 AUTHOR +// This file is part of the "Nazara Engine - MODULE module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_FILENAME_HPP +#define NAZARA_FILENAME_HPP + +#include +#include +#include + +struct NzPossibleImplementation; + +class NAZARA_API NzClassName +{ + friend NzClassFriend; + + public: + Constructors(); + Destructor(); + + FunctionInAClass(); + + protected: + + private: + NzClass m_variableName; + STL m_variableName; + dataType m_variableName; + + NzPossibleImplementation* m_impl; +}; + +#endif // NAZARA_FILENAME_HPP + +Class source: + +// Copyright (C) 2014 AUTHOR +// This file is part of the "Nazara Engine - MODULE module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +struct NzPossibleImplementation {}; + +NzClassName::Constructors() : +m_variableName(init) +{ + testsAndOtherInits; +} + +NzClassName::PublicFunctions() +NzClassName::ProtectedFunctions() +NzClassName::PrivateFunctions() + +Structure: + +/!\ enum in Enums.hpp + +enum nzEnum +{ + nzEnum_1, + nzEnum_2, + + nzEnum_Max = nzEnum_2 +}; + +Function: + +FunctionName() +{ + variableName = init; +} \ No newline at end of file