From 4b2e3370d95b70f70b87cf1786f7c03ffb79356f Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 26 Nov 2014 02:35:59 +0100 Subject: [PATCH 01/64] Added GuillotineBinPack algorithm Former-commit-id: 9f2fb342e7bd9e1b33937a4fd462c993ae5cec3e --- include/Nazara/Core/GuillotineBinPack.hpp | 73 ++++ src/Nazara/Core/GuillotineBinPack.cpp | 387 ++++++++++++++++++++++ 2 files changed, 460 insertions(+) create mode 100644 include/Nazara/Core/GuillotineBinPack.hpp create mode 100644 src/Nazara/Core/GuillotineBinPack.cpp diff --git a/include/Nazara/Core/GuillotineBinPack.hpp b/include/Nazara/Core/GuillotineBinPack.hpp new file mode 100644 index 000000000..f0464a3f7 --- /dev/null +++ b/include/Nazara/Core/GuillotineBinPack.hpp @@ -0,0 +1,73 @@ +// Copyright (C) 2014 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() = default; + + void Clear(); + + void FreeRectangle(const NzRectui& rect); + + unsigned int GetHeight() const; + float GetOccupancy() const; + NzVector2ui GetSize() const; + unsigned int GetWidth() const; + + bool Insert(NzRectui* rects, bool* flipped, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod); + + bool MergeFreeRectangles(); + + void Reset(); + void Reset(unsigned int width, unsigned int height); + + 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; + float m_occupancy; + unsigned int m_height; + unsigned int m_width; +}; + +#endif // NAZARA_GUILLOTINEBINPACK_HPP diff --git a/src/Nazara/Core/GuillotineBinPack.cpp b/src/Nazara/Core/GuillotineBinPack.cpp new file mode 100644 index 000000000..6cbae97aa --- /dev/null +++ b/src/Nazara/Core/GuillotineBinPack.cpp @@ -0,0 +1,387 @@ +// Copyright (C) 2014 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 + +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); +} + +void NzGuillotineBinPack::Clear() +{ + m_freeRectangles.clear(); + m_freeRectangles.push_back(NzRectui(0, 0, m_width, m_height)); + + m_occupancy = 0.f; +} + +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_occupancy -= static_cast(rect.width * rect.height) / (m_width*m_height); +} + +unsigned int NzGuillotineBinPack::GetHeight() const +{ + return m_height; +} + +float NzGuillotineBinPack::GetOccupancy() const +{ + return m_occupancy; +} + +NzVector2ui NzGuillotineBinPack::GetSize() const +{ + return NzVector2ui(m_width, m_height); +} + +unsigned int NzGuillotineBinPack::GetWidth() const +{ + return m_width; +} + +bool NzGuillotineBinPack::Insert(NzRectui* rects, bool* flipped, 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()) + 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; + + // 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_occupancy += static_cast(rect.width * rect.height) / (m_width*m_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::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(); +} From d22c4a5ac9e0f94ee2d4fcf88fe6a4274f3a7504 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 7 Dec 2014 03:09:39 +0100 Subject: [PATCH 02/64] Added A8 pixel format PixelFormat::GetBytesPerPixel() will no longer warn with less-than-one-byte formats Former-commit-id: af41f0c2bc7a35c2ee617980878628ff1c8bf868 --- include/Nazara/Utility/Enums.hpp | 1 + include/Nazara/Utility/PixelFormat.inl | 18 +++-- src/Nazara/Renderer/OpenGL.cpp | 3 + src/Nazara/Renderer/Texture.cpp | 15 ++-- src/Nazara/Utility/PixelFormat.cpp | 103 ++++++++++++++++++++++++- 5 files changed, 121 insertions(+), 19 deletions(-) diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index 25e09c10a..a5aec05bc 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -130,6 +130,7 @@ enum nzPixelFormat { nzPixelFormat_Undefined = -1, + nzPixelFormat_A8, // 1*uint8 nzPixelFormat_BGR8, // 3*uint8 nzPixelFormat_BGRA8, // 4*uint8 nzPixelFormat_DXT1, diff --git a/include/Nazara/Utility/PixelFormat.inl b/include/Nazara/Utility/PixelFormat.inl index c92f8b8c0..2154d2f05 100644 --- a/include/Nazara/Utility/PixelFormat.inl +++ b/include/Nazara/Utility/PixelFormat.inl @@ -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/src/Nazara/Renderer/OpenGL.cpp b/src/Nazara/Renderer/OpenGL.cpp index ef9e096d9..3c8b5c872 100644 --- a/src/Nazara/Renderer/OpenGL.cpp +++ b/src/Nazara/Renderer/OpenGL.cpp @@ -1465,6 +1465,9 @@ bool NzOpenGL::TranslateFormat(nzPixelFormat pixelFormat, Format* format, Format { switch (pixelFormat) { + case nzPixelFormat_A8: + return false; ///FIXME: Tester le mode d'OpenGL pour se permettre une fonctionnalité dépréciée ? + case nzPixelFormat_BGR8: format->dataFormat = GL_BGR; format->dataType = GL_UNSIGNED_BYTE; diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index cb5b4ff45..b2d59cb6e 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -1272,6 +1272,13 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format) case nzPixelFormat_RGBA32UI: return NzOpenGL::GetVersion() >= 300; + // Dépréciés depuis OpenGL 3 + ///FIXME: Accepter si le contexte OpenGL est de compatibilité/OpenGL 2 ? + case nzPixelFormat_A8: + case nzPixelFormat_L8: + case nzPixelFormat_LA8: + return false; + // Formats de profondeur (Supportés avec les FBOs) case nzPixelFormat_Depth16: case nzPixelFormat_Depth24: @@ -1286,12 +1293,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: @@ -1302,7 +1304,6 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format) } NazaraError("Invalid pixel format"); - return false; } diff --git a/src/Nazara/Utility/PixelFormat.cpp b/src/Nazara/Utility/PixelFormat.cpp index 776781251..07fc36431 100644 --- a/src/Nazara/Utility/PixelFormat.cpp +++ b/src/Nazara/Utility/PixelFormat.cpp @@ -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(c8to5(start[2])) << 11) | + (static_cast(c8to5(start[1])) << 6) | + (static_cast(c8to5(start[0])) << 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) @@ -243,7 +331,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)); @@ -465,7 +553,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)); @@ -638,7 +726,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)); @@ -1044,7 +1132,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 +1194,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(); From a393271f0426f4e97cb2ae05e9ac47bb1bd0cead Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 10 Dec 2014 14:38:32 +0100 Subject: [PATCH 03/64] Improved GuillotineBinPack Added explicit copy/move constructor/operator Added Expand method Added Insert overloads (you are now able to query which rectangles were inserted) Made occupancy computation more precise Overloaded methods taking a unsigned int pair with Vector2ui Former-commit-id: f063c04a1aea0d26594db642c2466264fe139450 --- include/Nazara/Core/GuillotineBinPack.hpp | 14 ++++- src/Nazara/Core/GuillotineBinPack.cpp | 67 +++++++++++++++++++++-- 2 files changed, 76 insertions(+), 5 deletions(-) diff --git a/include/Nazara/Core/GuillotineBinPack.hpp b/include/Nazara/Core/GuillotineBinPack.hpp index f0464a3f7..fecac3d00 100644 --- a/include/Nazara/Core/GuillotineBinPack.hpp +++ b/include/Nazara/Core/GuillotineBinPack.hpp @@ -40,10 +40,16 @@ class NAZARA_API NzGuillotineBinPack 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; @@ -51,12 +57,18 @@ class NAZARA_API NzGuillotineBinPack 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); @@ -65,8 +77,8 @@ class NAZARA_API NzGuillotineBinPack static int ScoreByHeuristic(int width, int height, const NzRectui& freeRect, FreeRectChoiceHeuristic rectChoice); std::vector m_freeRectangles; - float m_occupancy; unsigned int m_height; + unsigned int m_usedArea; unsigned int m_width; }; diff --git a/src/Nazara/Core/GuillotineBinPack.cpp b/src/Nazara/Core/GuillotineBinPack.cpp index 6cbae97aa..7a32f3ae1 100644 --- a/src/Nazara/Core/GuillotineBinPack.cpp +++ b/src/Nazara/Core/GuillotineBinPack.cpp @@ -7,6 +7,7 @@ // 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 @@ -63,12 +64,40 @@ 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_occupancy = 0.f; + 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) @@ -76,7 +105,7 @@ 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_occupancy -= static_cast(rect.width * rect.height) / (m_width*m_height); + m_usedArea -= rect.width * rect.height; } unsigned int NzGuillotineBinPack::GetHeight() const @@ -86,7 +115,7 @@ unsigned int NzGuillotineBinPack::GetHeight() const float NzGuillotineBinPack::GetOccupancy() const { - return m_occupancy; + return static_cast(m_usedArea)/(m_width*m_height); } NzVector2ui NzGuillotineBinPack::GetSize() const @@ -99,7 +128,17 @@ 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) @@ -171,7 +210,19 @@ bool NzGuillotineBinPack::Insert(NzRectui* rects, bool* flipped, unsigned int co // 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; @@ -185,6 +236,9 @@ bool NzGuillotineBinPack::Insert(NzRectui* rects, bool* flipped, unsigned int co 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); @@ -196,7 +250,7 @@ bool NzGuillotineBinPack::Insert(NzRectui* rects, bool* flipped, unsigned int co if (merge) MergeFreeRectangles(); - m_occupancy += static_cast(rect.width * rect.height) / (m_width*m_height); + m_usedArea += rect.width * rect.height; } return true; @@ -271,6 +325,11 @@ void NzGuillotineBinPack::Reset(unsigned int width, unsigned int height) 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. From db0bbd5be463d33ce8891840254232dfd659c95b Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 10 Dec 2014 14:41:12 +0100 Subject: [PATCH 04/64] Added conversions to A8 pixel format Former-commit-id: 8fc541a3bba588572a7fd87e69c695b470708181 --- src/Nazara/Utility/PixelFormat.cpp | 82 ++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/src/Nazara/Utility/PixelFormat.cpp b/src/Nazara/Utility/PixelFormat.cpp index 07fc36431..e72e503ba 100644 --- a/src/Nazara/Utility/PixelFormat.cpp +++ b/src/Nazara/Utility/PixelFormat.cpp @@ -258,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) { @@ -501,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) { @@ -619,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) { @@ -783,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) { @@ -1065,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) { @@ -1219,6 +1296,7 @@ bool NzPixelFormat::Initialize() RegisterConverter(); /**********************************BGRA8**********************************/ + RegisterConverter(); RegisterConverter(); RegisterConverter(); RegisterConverter();/* @@ -1322,6 +1400,7 @@ bool NzPixelFormat::Initialize() RegisterConverter(); /***********************************LA8***********************************/ + RegisterConverter(); RegisterConverter(); RegisterConverter(); RegisterConverter();/* @@ -1339,6 +1418,7 @@ bool NzPixelFormat::Initialize() RegisterConverter(); /**********************************RGBA4**********************************/ + RegisterConverter(); RegisterConverter(); RegisterConverter(); RegisterConverter(); @@ -1356,6 +1436,7 @@ bool NzPixelFormat::Initialize() RegisterConverter(); /*********************************RGB5A1**********************************/ + RegisterConverter(); RegisterConverter(); RegisterConverter(); RegisterConverter(); @@ -1390,6 +1471,7 @@ bool NzPixelFormat::Initialize() RegisterConverter(); /**********************************RGBA8**********************************/ + RegisterConverter(); RegisterConverter(); RegisterConverter(); RegisterConverter(); From 3a5868b915e54e441984f6a1687c4ad344e44435 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 10 Dec 2014 14:41:43 +0100 Subject: [PATCH 05/64] Fixed pixel format conversion from A8 to RGB5A1 Former-commit-id: ae5dbe7dd41f5b2856661820bf40ae93e3556c36 --- src/Nazara/Utility/PixelFormat.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Nazara/Utility/PixelFormat.cpp b/src/Nazara/Utility/PixelFormat.cpp index e72e503ba..b6679598d 100644 --- a/src/Nazara/Utility/PixelFormat.cpp +++ b/src/Nazara/Utility/PixelFormat.cpp @@ -87,9 +87,9 @@ namespace nzUInt16* ptr = reinterpret_cast(dst); while (start < end) { - *ptr = (static_cast(c8to5(start[2])) << 11) | - (static_cast(c8to5(start[1])) << 6) | - (static_cast(c8to5(start[0])) << 1) | + *ptr = (static_cast(0x1F) << 11) | + (static_cast(0x1F) << 6) | + (static_cast(0x1F) << 1) | ((*start > 0xF) ? 1 : 0); // > 128 #ifdef NAZARA_BIG_ENDIAN From 96798da027c87932ff932ce5e90877c05324c078 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 10 Dec 2014 14:41:56 +0100 Subject: [PATCH 06/64] Added TODO Former-commit-id: 11658e200641ba0846bc8b89376e034cd0b6c9a4 --- include/Nazara/Utility/PixelFormat.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/Nazara/Utility/PixelFormat.hpp b/include/Nazara/Utility/PixelFormat.hpp index 9f864e9ad..f4443c22b 100644 --- a/include/Nazara/Utility/PixelFormat.hpp +++ b/include/Nazara/Utility/PixelFormat.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ît donc pas) mais ça permettrait au moteur de faire la conversion +/// entre n'importe quel formats non-compressés. + class NzPixelFormat { friend class NzUtility; From 7316cbb6940fb1ce71f3498bba0e85c019a9e2e5 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 10 Dec 2014 19:01:03 +0100 Subject: [PATCH 07/64] Added OpenGL support for pixel formats A8/L8/LA8 Former-commit-id: b17942f7bf22daf90ddf5d8093da6c26b64a67ce --- include/Nazara/Renderer/OpenGL.hpp | 1 + src/Nazara/Renderer/OpenGL.cpp | 85 +++++++++++++++++++++++++++++- src/Nazara/Renderer/Texture.cpp | 19 ++++--- 3 files changed, 96 insertions(+), 9 deletions(-) diff --git a/include/Nazara/Renderer/OpenGL.hpp b/include/Nazara/Renderer/OpenGL.hpp index df6c199d7..8aa5a438d 100644 --- a/include/Nazara/Renderer/OpenGL.hpp +++ b/include/Nazara/Renderer/OpenGL.hpp @@ -69,6 +69,7 @@ class NAZARA_API NzOpenGL GLenum dataFormat; GLenum dataType; GLint internalFormat; + GLint swizzle[4]; }; NzOpenGL() = delete; diff --git a/src/Nazara/Renderer/OpenGL.cpp b/src/Nazara/Renderer/OpenGL.cpp index 3c8b5c872..3edf4e499 100644 --- a/src/Nazara/Renderer/OpenGL.cpp +++ b/src/Nazara/Renderer/OpenGL.cpp @@ -1463,10 +1463,41 @@ 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: - return false; ///FIXME: Tester le mode d'OpenGL pour se permettre une fonctionnalité dépréciée ? + 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; @@ -1499,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; diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index b2d59cb6e..6e73cc545 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -133,6 +133,15 @@ namespace return false; } + // Application du swizzle + if (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; } @@ -1226,8 +1235,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; @@ -1272,13 +1284,6 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format) case nzPixelFormat_RGBA32UI: return NzOpenGL::GetVersion() >= 300; - // Dépréciés depuis OpenGL 3 - ///FIXME: Accepter si le contexte OpenGL est de compatibilité/OpenGL 2 ? - case nzPixelFormat_A8: - case nzPixelFormat_L8: - case nzPixelFormat_LA8: - return false; - // Formats de profondeur (Supportés avec les FBOs) case nzPixelFormat_Depth16: case nzPixelFormat_Depth24: From 7c47a93a72d51be27b1f8f03e7cebaea9dd25022 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 3 Jan 2015 22:31:25 +0100 Subject: [PATCH 08/64] Renamed Corner enum to BoxCorner Added RectCorner and Rect::GetCorner method Former-commit-id: dc99823ceb17f6e91cdf12779c982ab7e024ec24 --- include/Nazara/Math/Box.hpp | 2 +- include/Nazara/Math/Box.inl | 18 +++--- include/Nazara/Math/Enums.hpp | 30 ++++++--- include/Nazara/Math/Frustum.hpp | 4 +- include/Nazara/Math/Frustum.inl | 50 +++++++-------- include/Nazara/Math/OrientedBox.hpp | 4 +- include/Nazara/Math/OrientedBox.inl | 30 ++++----- include/Nazara/Math/Ray.inl | 6 +- include/Nazara/Math/Rect.hpp | 2 + include/Nazara/Math/Rect.inl | 22 +++++++ src/Nazara/Renderer/DebugDrawer.cpp | 96 ++++++++++++++--------------- 11 files changed, 149 insertions(+), 115 deletions(-) diff --git a/include/Nazara/Math/Box.hpp b/include/Nazara/Math/Box.hpp index 0409caffc..1705f25df 100644 --- a/include/Nazara/Math/Box.hpp +++ b/include/Nazara/Math/Box.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 651a6de13..11578f605 100644 --- a/include/Nazara/Math/Box.inl +++ b/include/Nazara/Math/Box.inl @@ -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); } diff --git a/include/Nazara/Math/Enums.hpp b/include/Nazara/Math/Enums.hpp index efa249643..214c9958c 100644 --- a/include/Nazara/Math/Enums.hpp +++ b/include/Nazara/Math/Enums.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/Frustum.hpp b/include/Nazara/Math/Frustum.hpp index e5de19b50..f94c229b0 100644 --- a/include/Nazara/Math/Frustum.hpp +++ b/include/Nazara/Math/Frustum.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 0a7b02215..336f5ad0a 100644 --- a/include/Nazara/Math/Frustum.inl +++ b/include/Nazara/Math/Frustum.inl @@ -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/OrientedBox.hpp b/include/Nazara/Math/OrientedBox.hpp index 9f5b711b6..b6ea75fd7 100644 --- a/include/Nazara/Math/OrientedBox.hpp +++ b/include/Nazara/Math/OrientedBox.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 992698bad..8d242d52e 100644 --- a/include/Nazara/Math/OrientedBox.inl +++ b/include/Nazara/Math/OrientedBox.inl @@ -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/Ray.inl b/include/Nazara/Math/Ray.inl index ec4802bca..900ec2bbf 100644 --- a/include/Nazara/Math/Ray.inl +++ b/include/Nazara/Math/Ray.inl @@ -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), diff --git a/include/Nazara/Math/Rect.hpp b/include/Nazara/Math/Rect.hpp index a91c7b0e9..424d69079 100644 --- a/include/Nazara/Math/Rect.hpp +++ b/include/Nazara/Math/Rect.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 3d1908b83..5cee6602d 100644 --- a/include/Nazara/Math/Rect.inl +++ b/include/Nazara/Math/Rect.inl @@ -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 { diff --git a/src/Nazara/Renderer/DebugDrawer.cpp b/src/Nazara/Renderer/DebugDrawer.cpp index 066566bc1..f0ee2e133 100644 --- a/src/Nazara/Renderer/DebugDrawer.cpp +++ b/src/Nazara/Renderer/DebugDrawer.cpp @@ -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(); From 596f407a7978a1e4da8c29f3bbcf8621e5cb7bf4 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 3 Jan 2015 22:32:56 +0100 Subject: [PATCH 09/64] Added DebugDrawer::Draw(position, size) Draws a "size"-sized box centered on "position" Former-commit-id: 9385762a4118fe76364faa5819fd9a94efceefbf --- include/Nazara/Renderer/DebugDrawer.hpp | 1 + src/Nazara/Renderer/DebugDrawer.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/include/Nazara/Renderer/DebugDrawer.hpp b/include/Nazara/Renderer/DebugDrawer.hpp index fc632765a..1bb055c37 100644 --- a/include/Nazara/Renderer/DebugDrawer.hpp +++ b/include/Nazara/Renderer/DebugDrawer.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/src/Nazara/Renderer/DebugDrawer.cpp b/src/Nazara/Renderer/DebugDrawer.cpp index f0ee2e133..47c4388ef 100644 --- a/src/Nazara/Renderer/DebugDrawer.cpp +++ b/src/Nazara/Renderer/DebugDrawer.cpp @@ -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()) From ed1cc7a0926970b9cfc11d5c37d0b8c385fc677f Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 3 Jan 2015 22:39:51 +0100 Subject: [PATCH 10/64] Added viewer-relative directions Former-commit-id: 9d80744bd227689426b76df7e3c273de13424041 --- include/Nazara/Graphics/AbstractViewer.hpp | 3 + include/Nazara/Graphics/Camera.hpp | 3 + include/Nazara/Graphics/Scene.hpp | 6 ++ include/Nazara/Graphics/SceneNode.hpp | 6 ++ include/Nazara/Graphics/View.hpp | 3 + include/Nazara/Utility/Node.hpp | 14 ++-- src/Nazara/Graphics/Camera.cpp | 15 ++++ src/Nazara/Graphics/Scene.cpp | 86 +++++++++++++++++++++- src/Nazara/Graphics/SceneNode.cpp | 79 ++++++++++++++++++++ src/Nazara/Graphics/View.cpp | 15 ++++ src/Nazara/Utility/Node.cpp | 2 +- 11 files changed, 223 insertions(+), 9 deletions(-) diff --git a/include/Nazara/Graphics/AbstractViewer.hpp b/include/Nazara/Graphics/AbstractViewer.hpp index 7e0306689..d6c3d5f3f 100644 --- a/include/Nazara/Graphics/AbstractViewer.hpp +++ b/include/Nazara/Graphics/AbstractViewer.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..3cdb0eb41 100644 --- a/include/Nazara/Graphics/Camera.hpp +++ b/include/Nazara/Graphics/Camera.hpp @@ -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/Scene.hpp b/include/Nazara/Graphics/Scene.hpp index d286c4c19..8a9b1b89c 100644 --- a/include/Nazara/Graphics/Scene.hpp +++ b/include/Nazara/Graphics/Scene.hpp @@ -41,9 +41,15 @@ class NAZARA_API NzScene NzColor GetAmbientColor() const; NzAbstractBackground* GetBackground() const; + NzVector3f GetBackward() const; + NzVector3f GetDown() const; + NzVector3f GetForward() const; + NzVector3f GetLeft() const; NzAbstractRenderTechnique* GetRenderTechnique() const; + NzVector3f GetRight() const; NzSceneNode& GetRoot() const; NzAbstractViewer* GetViewer() const; + NzVector3f GetUp() const; float GetUpdateTime() const; unsigned int GetUpdatePerSecond() const; diff --git a/include/Nazara/Graphics/SceneNode.hpp b/include/Nazara/Graphics/SceneNode.hpp index 09aa1fab3..e5d70d10c 100644 --- a/include/Nazara/Graphics/SceneNode.hpp +++ b/include/Nazara/Graphics/SceneNode.hpp @@ -27,10 +27,16 @@ class NAZARA_API NzSceneNode : public NzNode void EnableDrawing(bool drawingEnabled); + NzVector3f GetBackward() const; virtual const NzBoundingVolumef& GetBoundingVolume() const = 0; + NzVector3f GetDown() const; + NzVector3f GetForward() const; + NzVector3f GetLeft() const; nzNodeType GetNodeType() const final; + NzVector3f GetRight() const; NzScene* GetScene() const; virtual nzSceneNodeType GetSceneNodeType() const = 0; + NzVector3f GetUp() const; virtual bool IsDrawable() const = 0; bool IsDrawingEnabled() const; diff --git a/include/Nazara/Graphics/View.hpp b/include/Nazara/Graphics/View.hpp index bc048aeb6..e9d0de8da 100644 --- a/include/Nazara/Graphics/View.hpp +++ b/include/Nazara/Graphics/View.hpp @@ -32,6 +32,9 @@ 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; diff --git a/include/Nazara/Utility/Node.hpp b/include/Nazara/Utility/Node.hpp index 4536739a7..11f9d1f15 100644 --- a/include/Nazara/Utility/Node.hpp +++ b/include/Nazara/Utility/Node.hpp @@ -24,26 +24,26 @@ 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; + virtual NzVector3f GetLeft() const; const NzString& GetName() 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; @@ -95,7 +95,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; diff --git a/src/Nazara/Graphics/Camera.cpp b/src/Nazara/Graphics/Camera.cpp index a0eb272a6..570b1f289 100644 --- a/src/Nazara/Graphics/Camera.cpp +++ b/src/Nazara/Graphics/Camera.cpp @@ -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/Scene.cpp b/src/Nazara/Graphics/Scene.cpp index 2c9f286a8..e66a99f03 100644 --- a/src/Nazara/Graphics/Scene.cpp +++ b/src/Nazara/Graphics/Scene.cpp @@ -134,6 +134,58 @@ NzAbstractBackground* NzScene::GetBackground() const return m_impl->background.get(); } +NzVector3f NzScene::GetBackward() const +{ + #if NAZARA_GRAPHICS_SAFE + if (!m_impl->viewer) + { + NazaraError("No viewer"); + return NzVector3f::Backward(); + } + #endif + + return -m_impl->viewer->GetGlobalForward(); +} + +NzVector3f NzScene::GetDown() const +{ + #if NAZARA_GRAPHICS_SAFE + if (!m_impl->viewer) + { + NazaraError("No viewer"); + return NzVector3f::Down(); + } + #endif + + return -m_impl->viewer->GetGlobalUp(); +} + +NzVector3f NzScene::GetForward() const +{ + #if NAZARA_GRAPHICS_SAFE + if (!m_impl->viewer) + { + NazaraError("No viewer"); + return NzVector3f::Forward(); + } + #endif + + return m_impl->viewer->GetGlobalForward(); +} + +NzVector3f NzScene::GetLeft() const +{ + #if NAZARA_GRAPHICS_SAFE + if (!m_impl->viewer) + { + NazaraError("No viewer"); + return NzVector3f::Left(); + } + #endif + + return -m_impl->viewer->GetGlobalRight(); +} + NzAbstractRenderTechnique* NzScene::GetRenderTechnique() const { if (!m_impl->renderTechnique) @@ -142,6 +194,19 @@ NzAbstractRenderTechnique* NzScene::GetRenderTechnique() const return m_impl->renderTechnique.get(); } +NzVector3f NzScene::GetRight() const +{ + #if NAZARA_GRAPHICS_SAFE + if (!m_impl->viewer) + { + NazaraError("No viewer"); + return NzVector3f::Right(); + } + #endif + + return m_impl->viewer->GetGlobalRight(); +} + NzSceneNode& NzScene::GetRoot() const { return m_impl->root; @@ -152,6 +217,19 @@ NzAbstractViewer* NzScene::GetViewer() const return m_impl->viewer; } +NzVector3f NzScene::GetUp() const +{ + #if NAZARA_GRAPHICS_SAFE + if (!m_impl->viewer) + { + NazaraError("No viewer"); + return NzVector3f::Up(); + } + #endif + + return m_impl->viewer->GetGlobalUp(); +} + float NzScene::GetUpdateTime() const { return m_impl->updateTime; @@ -197,7 +275,13 @@ void NzScene::SetRenderTechnique(NzAbstractRenderTechnique* renderTechnique) void NzScene::SetViewer(NzAbstractViewer* viewer) { - m_impl->viewer = viewer; + if (m_impl->viewer != viewer) + { + m_impl->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_impl->root.InvalidateNode(); + } } void NzScene::SetViewer(NzAbstractViewer& viewer) diff --git a/src/Nazara/Graphics/SceneNode.cpp b/src/Nazara/Graphics/SceneNode.cpp index fbd88b866..fcaf02743 100644 --- a/src/Nazara/Graphics/SceneNode.cpp +++ b/src/Nazara/Graphics/SceneNode.cpp @@ -31,16 +31,94 @@ 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(); +} + +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(); +} + 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; @@ -82,6 +160,7 @@ 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); } diff --git a/src/Nazara/Graphics/View.cpp b/src/Nazara/Graphics/View.cpp index 44d00294c..045b22a22 100644 --- a/src/Nazara/Graphics/View.cpp +++ b/src/Nazara/Graphics/View.cpp @@ -80,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) diff --git a/src/Nazara/Utility/Node.cpp b/src/Nazara/Utility/Node.cpp index 459f6d74f..6361ea3de 100644 --- a/src/Nazara/Utility/Node.cpp +++ b/src/Nazara/Utility/Node.cpp @@ -685,7 +685,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) From 97ff9bc4ace9b187cab70eb75e32480b563c67f9 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 4 Jan 2015 12:50:56 +0100 Subject: [PATCH 11/64] Improved texture creation Fixed possible wasted space on NVidia hardware Former-commit-id: 42a26c88d8bd03b1ac845c62984cf8c355f1902a --- include/Nazara/Renderer/Texture.hpp | 1 + src/Nazara/Renderer/Texture.cpp | 279 ++++++++++++++-------------- 2 files changed, 143 insertions(+), 137 deletions(-) diff --git a/include/Nazara/Renderer/Texture.hpp b/include/Nazara/Renderer/Texture.hpp index 024216d70..f78feb490 100644 --- a/include/Nazara/Renderer/Texture.hpp +++ b/include/Nazara/Renderer/Texture.hpp @@ -101,6 +101,7 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable static bool IsTypeSupported(nzImageType type); private: + bool CreateTexture(bool proxy); void InvalidateMipmaps(); NzTextureImpl* m_impl = nullptr; diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index 6e73cc545..9605244c4 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include #include @@ -28,123 +29,6 @@ struct NzTextureImpl namespace { - bool CreateTexture(NzTextureImpl* impl, bool proxy) - { - 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; - } - - // Application du swizzle - if (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; - } - inline void SetUnpackAlignement(nzUInt8 bpp) { if (bpp % 8 == 0) @@ -273,40 +157,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; @@ -1336,6 +1224,123 @@ bool NzTexture::IsTypeSupported(nzImageType type) return false; } +bool NzTexture::CreateTexture(bool proxy) +{ + NzOpenGL::Format openGLFormat; + if (!NzOpenGL::TranslateFormat(m_impl->format, &openGLFormat, NzOpenGL::FormatType_Texture)) + { + NazaraError("Format " + NzPixelFormat::ToString(m_impl->format) + " not supported by OpenGL"); + return 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; +} + void NzTexture::InvalidateMipmaps() { #if NAZARA_RENDERER_SAFE From 4de17fdffb27608f4740e0c70d06535f7a4eb421 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 4 Jan 2015 13:19:07 +0100 Subject: [PATCH 12/64] Remade sprite rendering Added VertexColor shader flag Added color sprite attribute Added VertexStruct_XY_Color(_UV) struct & declaration Former-commit-id: b664f4520aa55f4502f85f9dedab9b92040a8c16 --- .../Nazara/Graphics/AbstractRenderQueue.hpp | 3 +- .../Nazara/Graphics/DeferredRenderQueue.hpp | 2 +- include/Nazara/Graphics/Enums.hpp | 7 +- .../Nazara/Graphics/ForwardRenderQueue.hpp | 12 +- .../Graphics/ForwardRenderTechnique.hpp | 2 +- include/Nazara/Graphics/Sprite.hpp | 7 + include/Nazara/Utility/Enums.hpp | 2 + include/Nazara/Utility/VertexStruct.hpp | 25 ++- src/Nazara/Graphics/DeferredRenderQueue.cpp | 18 +- src/Nazara/Graphics/ForwardRenderQueue.cpp | 43 +++-- .../Graphics/ForwardRenderTechnique.cpp | 157 +++++++++--------- src/Nazara/Graphics/Material.cpp | 5 +- .../Resources/Shaders/Basic/core.frag | 3 +- .../Resources/Shaders/Basic/core.frag.h | 2 +- .../Resources/Shaders/Basic/core.vert | 9 + .../Resources/Shaders/Basic/core.vert.h | 2 +- .../Resources/Shaders/PhongLighting/core.frag | 3 +- .../Shaders/PhongLighting/core.frag.h | 2 +- .../Resources/Shaders/PhongLighting/core.vert | 10 ++ .../Shaders/PhongLighting/core.vert.h | 2 +- src/Nazara/Graphics/Sprite.cpp | 78 ++++++++- src/Nazara/Utility/VertexDeclaration.cpp | 15 ++ 22 files changed, 264 insertions(+), 145 deletions(-) diff --git a/include/Nazara/Graphics/AbstractRenderQueue.hpp b/include/Nazara/Graphics/AbstractRenderQueue.hpp index c3a9de2e4..5159a8fce 100644 --- a/include/Nazara/Graphics/AbstractRenderQueue.hpp +++ b/include/Nazara/Graphics/AbstractRenderQueue.hpp @@ -12,6 +12,7 @@ #include #include #include +#include class NzDrawable; class NzLight; @@ -28,7 +29,7 @@ class NAZARA_API NzAbstractRenderQueue : NzNonCopyable 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) = 0; virtual void Clear(bool fully) = 0; }; diff --git a/include/Nazara/Graphics/DeferredRenderQueue.hpp b/include/Nazara/Graphics/DeferredRenderQueue.hpp index 8cec0ecea..8020dffd7 100644 --- a/include/Nazara/Graphics/DeferredRenderQueue.hpp +++ b/include/Nazara/Graphics/DeferredRenderQueue.hpp @@ -31,7 +31,7 @@ class NAZARA_API NzDeferredRenderQueue : public NzAbstractRenderQueue, NzResourc 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) override; void Clear(bool fully); diff --git a/include/Nazara/Graphics/Enums.hpp b/include/Nazara/Graphics/Enums.hpp index 59a8104c4..60b05238d 100644 --- a/include/Nazara/Graphics/Enums.hpp +++ b/include/Nazara/Graphics/Enums.hpp @@ -85,10 +85,11 @@ enum nzShaderFlags { nzShaderFlags_None = 0, - nzShaderFlags_Deferred = 0x1, - nzShaderFlags_Instancing = 0x2, + nzShaderFlags_Deferred = 0x1, + nzShaderFlags_Instancing = 0x2, + nzShaderFlags_VertexColor = 0x4, - 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 85710cd0d..e7c7c3087 100644 --- a/include/Nazara/Graphics/ForwardRenderQueue.hpp +++ b/include/Nazara/Graphics/ForwardRenderQueue.hpp @@ -33,7 +33,7 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource 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) override; void Clear(bool fully); @@ -43,6 +43,12 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource bool OnResourceDestroy(const NzResource* resource, int index) override; void OnResourceReleased(const NzResource* resource, int index) override; + struct SpriteChain_XYZ_Color_UV + { + const NzVertexStruct_XYZ_Color_UV* vertices; + unsigned int spriteCount; + }; + struct TransparentModelData { NzMatrix4f transformMatrix; @@ -68,12 +74,12 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource typedef std::map>, MeshDataComparator> MeshInstanceContainer; typedef std::map, BatchedModelMaterialComparator> ModelBatches; - typedef std::map> BatchedSpriteContainer; + typedef std::map> BasicSpriteBatches; typedef std::vector LightContainer; typedef std::vector TransparentModelContainer; + 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 9050cda20..18caea522 100644 --- a/include/Nazara/Graphics/ForwardRenderTechnique.hpp +++ b/include/Nazara/Graphics/ForwardRenderTechnique.hpp @@ -34,8 +34,8 @@ class NAZARA_API NzForwardRenderTechnique : public NzAbstractRenderTechnique, Nz private: struct LightUniforms; + void DrawBasicSprites(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; diff --git a/include/Nazara/Graphics/Sprite.hpp b/include/Nazara/Graphics/Sprite.hpp index b383f1e44..a6040823c 100644 --- a/include/Nazara/Graphics/Sprite.hpp +++ b/include/Nazara/Graphics/Sprite.hpp @@ -10,6 +10,7 @@ #include #include #include +#include class NAZARA_API NzSprite : public NzSceneNode { @@ -23,6 +24,7 @@ class NAZARA_API NzSprite : public NzSceneNode void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; const NzBoundingVolumef& GetBoundingVolume() const override; + const NzColor& GetColor() const; NzMaterial* GetMaterial() const; nzSceneNodeType GetSceneNodeType() const override; const NzVector2f& GetSize() const; @@ -30,6 +32,7 @@ class NAZARA_API NzSprite : public NzSceneNode bool IsDrawable() const; + void SetColor(const NzColor& color); void SetMaterial(NzMaterial* material, bool resizeSprite = true); void SetSize(const NzVector2f& size); void SetSize(float sizeX, float sizeY); @@ -42,12 +45,16 @@ class NAZARA_API NzSprite : public NzSceneNode 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 NzVertexStruct_XYZ_Color_UV m_vertices[4]; mutable bool m_boundingVolumeUpdated; + mutable bool m_verticesUpdated; }; #endif // NAZARA_SPRITE_HPP diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index a5aec05bc..b6c1db419 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -254,6 +254,8 @@ enum nzVertexLayout nzVertexLayout_XY, 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/VertexStruct.hpp b/include/Nazara/Utility/VertexStruct.hpp index 62c01c439..15cb02d28 100644 --- a/include/Nazara/Utility/VertexStruct.hpp +++ b/include/Nazara/Utility/VertexStruct.hpp @@ -7,6 +7,7 @@ #ifndef NAZARA_VERTEXSTRUCT_HPP #define NAZARA_VERTEXSTRUCT_HPP +#include #include #include @@ -17,7 +18,7 @@ struct NzVertexStruct_XY NzVector2f position; }; -struct NzVertexStruct_XY_UV : public NzVertexStruct_XY +struct NzVertexStruct_XY_UV : NzVertexStruct_XY { NzVector2f uv; }; @@ -29,29 +30,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/src/Nazara/Graphics/DeferredRenderQueue.cpp b/src/Nazara/Graphics/DeferredRenderQueue.cpp index c4e393ec1..4c3d0cd35 100644 --- a/src/Nazara/Graphics/DeferredRenderQueue.cpp +++ b/src/Nazara/Graphics/DeferredRenderQueue.cpp @@ -103,29 +103,15 @@ void NzDeferredRenderQueue::AddMesh(const NzMaterial* material, const NzMeshData } } -void NzDeferredRenderQueue::AddSprite(const NzSprite* sprite) +void NzDeferredRenderQueue::AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount) { - #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); } void NzDeferredRenderQueue::Clear(bool fully) diff --git a/src/Nazara/Graphics/ForwardRenderQueue.cpp b/src/Nazara/Graphics/ForwardRenderQueue.cpp index 90770660d..b0d1be9d6 100644 --- a/src/Nazara/Graphics/ForwardRenderQueue.cpp +++ b/src/Nazara/Graphics/ForwardRenderQueue.cpp @@ -12,6 +12,8 @@ #include #include +///FIXME: Régler ce problème de dépendance aux ressources + namespace { enum ResourceType @@ -121,23 +123,17 @@ void NzForwardRenderQueue::AddMesh(const NzMaterial* material, const NzMeshData& } } -void NzForwardRenderQueue::AddSprite(const NzSprite* sprite) +void NzForwardRenderQueue::AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount) { - #if NAZARA_GRAPHICS_SAFE - if (!sprite) + BasicSpriteBatches::iterator it = basicSprites.find(material); + if (it == basicSprites.end()) { - NazaraError("Invalid sprite"); - return; + it = basicSprites.insert(std::make_pair(material, BasicSpriteBatches::mapped_type())).first; + material->AddResourceListener(this, ResourceType_Material); } - if (!sprite->IsDrawable()) - { - NazaraError("Sprite is not drawable"); - return; - } - #endif - - sprites[sprite->GetMaterial()].push_back(sprite); + auto& spriteVector = it->second; + spriteVector.push_back(SpriteChain_XYZ_Color_UV({vertices, spriteCount})); } void NzForwardRenderQueue::Clear(bool fully) @@ -150,6 +146,13 @@ void NzForwardRenderQueue::Clear(bool fully) if (fully) { + for (auto& matIt : basicSprites) + { + const NzMaterial* material = matIt.first; + material->RemoveResourceListener(this); + } + basicSprites.clear(); + for (auto& matIt : opaqueModels) { const NzMaterial* material = matIt.first; @@ -167,7 +170,6 @@ void NzForwardRenderQueue::Clear(bool fully) } } opaqueModels.clear(); - sprites.clear(); } } @@ -210,6 +212,7 @@ bool NzForwardRenderQueue::OnResourceDestroy(const NzResource* resource, int ind } case ResourceType_Material: + basicSprites.erase(static_cast(resource)); opaqueModels.erase(static_cast(resource)); break; @@ -260,6 +263,15 @@ void NzForwardRenderQueue::OnResourceReleased(const NzResource* resource, int in case ResourceType_Material: { + for (auto it = basicSprites.begin(); it != basicSprites.end(); ++it) + { + if (it->first == resource) + { + basicSprites.erase(it); + break; + } + } + for (auto it = opaqueModels.begin(); it != opaqueModels.end(); ++it) { if (it->first == resource) @@ -268,6 +280,7 @@ void NzForwardRenderQueue::OnResourceReleased(const NzResource* resource, int in break; } } + break; } @@ -299,7 +312,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 +332,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 896e7c70a..bc962cc19 100644 --- a/src/Nazara/Graphics/ForwardRenderTechnique.cpp +++ b/src/Nazara/Graphics/ForwardRenderTechnique.cpp @@ -49,7 +49,7 @@ namespace } NzForwardRenderTechnique::NzForwardRenderTechnique() : -m_spriteBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_UV), s_maxSprites*4, nzBufferStorage_Hardware, nzBufferUsage_Dynamic), +m_spriteBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Color_UV), s_maxSprites*4, nzBufferStorage_Hardware, nzBufferUsage_Dynamic), m_maxLightPassPerObject(3) { if (!s_indexBuffer) @@ -87,8 +87,8 @@ 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); // Les autres drawables (Exemple: Terrain) for (const NzDrawable* drawable : m_renderQueue.otherDrawables) @@ -162,6 +162,77 @@ void NzForwardRenderTechnique::SetMaxLightPassPerObject(unsigned int passCount) m_maxLightPassPerObject = passCount; } +void NzForwardRenderTechnique::DrawBasicSprites(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.basicSprites) + { + const NzMaterial* material = matIt.first; + auto& spriteChainVector = matIt.second; + + unsigned int spriteChainCount = spriteChainVector.size(); + if (spriteChainCount > 0) + { + // On commence par appliquer du matériau (et récupérer le shader ainsi activé) + const NzShader* shader = material->Apply(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(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor()); + // Position de la caméra + shader->SendVector(shader->GetUniformLocation(nzShaderUniform_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; + { + NzForwardRenderQueue::SpriteChain_XYZ_Color_UV& currentChain = spriteChainVector[spriteChain]; + unsigned int count = std::min(s_maxSprites - 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 < s_maxSprites && spriteChain < spriteChainCount); + + vertexMapper.Unmap(); + + NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, spriteCount*6); + } + while (spriteChain < spriteChainCount); + + spriteChainVector.clear(); + } + } +} + void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const { NzAbstractViewer* viewer = scene->GetViewer(); @@ -275,7 +346,7 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const 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) { @@ -351,7 +422,7 @@ 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) @@ -373,82 +444,6 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const } } -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(); - } - } -} - void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene) const { NzAbstractViewer* viewer = scene->GetViewer(); diff --git a/src/Nazara/Graphics/Material.cpp b/src/Nazara/Graphics/Material.cpp index 3c9861acc..2774b42fa 100644 --- a/src/Nazara/Graphics/Material.cpp +++ b/src/Nazara/Graphics/Material.cpp @@ -692,6 +692,7 @@ void NzMaterial::GenerateShader(nzUInt32 flags) const list.SetParameter("FLAG_DEFERRED", static_cast((flags & nzShaderFlags_Deferred) != 0)); list.SetParameter("FLAG_INSTANCING", static_cast((flags & nzShaderFlags_Instancing) != 0)); + list.SetParameter("FLAG_VERTEXCOLOR", static_cast((flags & nzShaderFlags_VertexColor) != 0)); ShaderInstance& instance = m_shaders[flags]; instance.uberInstance = m_uberShader->Get(list); @@ -759,7 +760,7 @@ bool NzMaterial::Initialize() } 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_Vertex, vertexShader, "FLAG_INSTANCING FLAG_VERTEXCOLOR TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH"); NzUberShaderLibrary::Register("Basic", uberShader.get()); uberShader.release(); @@ -800,7 +801,7 @@ bool NzMaterial::Initialize() } 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_Vertex, vertexShader, "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/Resources/Shaders/Basic/core.frag b/src/Nazara/Graphics/Resources/Shaders/Basic/core.frag index a789242b9..57068325d 100644 --- a/src/Nazara/Graphics/Resources/Shaders/Basic/core.frag +++ b/src/Nazara/Graphics/Resources/Shaders/Basic/core.frag @@ -3,6 +3,7 @@ layout(early_fragment_tests) in; #endif /********************Entrant********************/ +in vec4 vColor; in vec2 vTexCoord; /********************Sortant********************/ @@ -18,7 +19,7 @@ uniform vec2 InvTargetSize; /********************Fonctions********************/ void main() { - vec4 fragmentColor = MaterialDiffuse; + vec4 fragmentColor = MaterialDiffuse * vColor; #if AUTO_TEXCOORDS vec2 texCoord = gl_FragCoord.xy * InvTargetSize; diff --git a/src/Nazara/Graphics/Resources/Shaders/Basic/core.frag.h b/src/Nazara/Graphics/Resources/Shaders/Basic/core.frag.h index 97c8ee9b1..319917ab6 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,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,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,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..6a5143444 100644 --- a/src/Nazara/Graphics/Resources/Shaders/Basic/core.vert +++ b/src/Nazara/Graphics/Resources/Shaders/Basic/core.vert @@ -1,9 +1,11 @@ /********************Entrant********************/ in mat4 InstanceData0; +in vec4 VertexColor; in vec3 VertexPosition; in vec2 VertexTexCoord; /********************Sortant********************/ +out vec4 vColor; out vec2 vTexCoord; /********************Uniformes********************/ @@ -14,6 +16,12 @@ uniform mat4 WorldViewProjMatrix; /********************Fonctions********************/ void main() { +#if FLAG_VERTEXCOLOR + vec4 color = VertexColor; +#else + vec4 color = vec4(1.0); +#endif + #if FLAG_INSTANCING #if TRANSFORM gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0); @@ -36,6 +44,7 @@ void main() #endif #endif + vColor = color; #if TEXTURE_MAPPING vTexCoord = vec2(VertexTexCoord); #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..6532129d4 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,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,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,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,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,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,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,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 diff --git a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag index 055b5472e..cf0f596da 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; @@ -76,7 +77,7 @@ vec4 EncodeNormal(in vec3 normal) void main() { - vec4 diffuseColor = MaterialDiffuse; + vec4 diffuseColor = MaterialDiffuse * vColor; vec2 texCoord = vTexCoord; #if LIGHTING && PARALLAX_MAPPING float height = texture(MaterialHeightMap, texCoord).r; diff --git a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag.h b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag.h index 54e4bb415..60271acaf 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,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,32,42,32,118,67,111,108,111,114,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 diff --git a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert index 09430bb06..454df5b82 100644 --- a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert +++ b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert @@ -1,11 +1,13 @@ /********************Entrant********************/ in mat4 InstanceData0; +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,6 +24,12 @@ uniform mat4 WorldViewProjMatrix; /********************Fonctions********************/ void main() { +#if FLAG_VERTEXCOLOR + vec4 color = VertexColor; +#else + vec4 color = vec4(1.0); +#endif + #if FLAG_INSTANCING #if TRANSFORM gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0); @@ -44,6 +52,8 @@ void main() #endif #endif + vColor = color; + #if LIGHTING #if FLAG_INSTANCING mat3 rotationMatrix = mat3(InstanceData0); diff --git a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert.h b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert.h index c920136a2..3382bc09f 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,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,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,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,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,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,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,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,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,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 diff --git a/src/Nazara/Graphics/Sprite.cpp b/src/Nazara/Graphics/Sprite.cpp index df181ac5d..b6dcf5ae0 100644 --- a/src/Nazara/Graphics/Sprite.cpp +++ b/src/Nazara/Graphics/Sprite.cpp @@ -3,20 +3,25 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #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_boundingVolumeUpdated(true), +m_verticesUpdated(false) { } 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_verticesUpdated(false) { if (texture) { @@ -44,7 +49,9 @@ m_boundingVolume(sprite.m_boundingVolume), 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_boundingVolumeUpdated(sprite.m_boundingVolumeUpdated), +m_verticesUpdated(sprite.m_verticesUpdated) { SetParent(sprite); } @@ -55,7 +62,9 @@ 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) +m_vertices(sprite.m_vertices), +m_boundingVolumeUpdated(sprite.m_boundingVolumeUpdated), +m_verticesUpdated(sprite.m_verticesUpdated) { } @@ -63,13 +72,23 @@ 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 { - static NzBoundingVolumef infinity(NzBoundingVolumef::Infinite()); - return infinity; + if (!m_boundingVolumeUpdated) + UpdateBoundingVolume(); + + return m_boundingVolume; +} + +const NzColor& NzSprite::GetColor() const +{ + return m_color; } NzMaterial* NzSprite::GetMaterial() const @@ -97,6 +116,12 @@ bool NzSprite::IsDrawable() const return m_material != nullptr; } +void NzSprite::SetColor(const NzColor& color) +{ + m_color = color; + m_verticesUpdated = false; +} + void NzSprite::SetMaterial(NzMaterial* material, bool resizeSprite) { m_material = material; @@ -113,6 +138,7 @@ void NzSprite::SetSize(const NzVector2f& size) // On invalide la bounding box m_boundingVolume.MakeNull(); m_boundingVolumeUpdated = false; + m_verticesUpdated = false; } void NzSprite::SetSize(float sizeX, float sizeY) @@ -136,6 +162,7 @@ void NzSprite::SetTexture(NzTexture* texture, bool resizeSprite) void NzSprite::SetTextureCoords(const NzRectf& coords) { m_textureCoords = coords; + m_verticesUpdated = false; } void NzSprite::SetTextureRect(const NzRectui& rect) @@ -167,10 +194,13 @@ 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() @@ -180,7 +210,12 @@ void NzSprite::Unregister() void NzSprite::UpdateBoundingVolume() 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->GetDown(); + NzVector3f right = m_scene->GetRight(); + + m_boundingVolume.Set(NzVector3f(0.f), m_size.x*right + m_size.y*down); + } if (!m_transformMatrixUpdated) UpdateTransformMatrix(); @@ -188,3 +223,30 @@ void NzSprite::UpdateBoundingVolume() const m_boundingVolume.Update(m_transformMatrix); m_boundingVolumeUpdated = true; } + +void NzSprite::UpdateVertices() const +{ + if (!m_transformMatrixUpdated) + UpdateTransformMatrix(); + + NzVector3f down = m_scene->GetDown(); + NzVector3f right = m_scene->GetRight(); + + 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/Utility/VertexDeclaration.cpp b/src/Nazara/Utility/VertexDeclaration.cpp index de4860d82..00e9d9768 100644 --- a/src/Nazara/Utility/VertexDeclaration.cpp +++ b/src/Nazara/Utility/VertexDeclaration.cpp @@ -205,6 +205,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_UV]; + 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)); From 8a836b20605873d77ee18f5cb692f9c8f1201194 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 4 Jan 2015 14:21:09 +0100 Subject: [PATCH 13/64] Added Font class (+ FreeType loader) Former-commit-id: 1811304cd0efe9a86cbae83faaf4c39d9fae248f --- include/Nazara/Utility/Enums.hpp | 21 + include/Nazara/Utility/Font.hpp | 133 +++++ include/Nazara/Utility/FontData.hpp | 36 ++ include/Nazara/Utility/FontGlyph.hpp | 19 + src/Nazara/Utility/Font.cpp | 507 ++++++++++++++++++ src/Nazara/Utility/FontData.cpp | 8 + src/Nazara/Utility/Loaders/FreeType.hpp | 15 + .../Utility/Loaders/FreeType/Loader.cpp | 393 ++++++++++++++ src/Nazara/Utility/Utility.cpp | 5 + 9 files changed, 1137 insertions(+) create mode 100644 include/Nazara/Utility/Font.hpp create mode 100644 include/Nazara/Utility/FontData.hpp create mode 100644 include/Nazara/Utility/FontGlyph.hpp create mode 100644 src/Nazara/Utility/Font.cpp create mode 100644 src/Nazara/Utility/FontData.cpp create mode 100644 src/Nazara/Utility/Loaders/FreeType.hpp create mode 100644 src/Nazara/Utility/Loaders/FreeType/Loader.cpp diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index b6c1db419..06e2a5c2a 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -218,6 +218,27 @@ enum nzPrimitiveMode nzPrimitiveMode_Max = nzPrimitiveMode_TriangleFan }; +enum nzTextAlign +{ + nzTextAlign_Left, + nzTextAlign_Middle, + nzTextAlign_Right, + + nzTextAlign_Max = nzTextAlign_Right +}; + +enum nzTextStyleFlags +{ + nzTextStyle_None = 0x0, + + nzTextStyle_Bold = 0x1, + nzTextStyle_Italic = 0x2, + nzTextStyle_StrikeThrough = 0x4, + nzTextStyle_Underlined = 0x8, + + nzTextStyle_Max = nzTextStyle_Underlined*2-1 +}; + enum nzVertexComponent { nzVertexComponent_Unused = -1, diff --git a/include/Nazara/Utility/Font.hpp b/include/Nazara/Utility/Font.hpp new file mode 100644 index 000000000..190d3c716 --- /dev/null +++ b/include/Nazara/Utility/Font.hpp @@ -0,0 +1,133 @@ +// Copyright (C) 2014 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 + +struct NAZARA_API NzFontParams +{ + bool IsValid() const; +}; + +class NzFont; +class NzFontData; + +struct NzFontGlyph; // TEMP + +using NzFontConstRef = NzResourceRef; +using NzFontLoader = NzResourceLoader; +using NzFontRef = NzResourceRef; + +class NAZARA_API NzFont : public NzResource, NzNonCopyable +{ + friend NzFontLoader; + + public: + struct Atlas + { + NzGuillotineBinPack binPack; + NzImage image; + }; + + struct Glyph + { + NzRecti aabb; + NzRectui atlasRect; + bool flipped; + bool valid; + int advance; + unsigned int atlasIndex; + }; + + struct SizeInfo + { + unsigned int lineHeight; + float underlinePosition; + float underlineThickness; + }; + + NzFont(); + NzFont(NzFont&& font) = default; + ~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 Atlas& GetAtlas(unsigned int atlasIndex) const; + unsigned int GetAtlasCount() 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 GetMaxAtlasSize() 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 SetMaxAtlasSize(unsigned int maxAtlasSize); + void SetMinimumStepSize(unsigned int minimumSizeStep); + + NzFont& operator=(NzFont&& font) = default; + + static unsigned int GetDefaultMaxAtlasSize(); + static void SetDefaultMaxAtlasSize(unsigned int maxAtlasSize); + + private: + using GlyphMap = std::unordered_map; + + struct QueuedGlyph + { + char32_t codepoint; + NzImage image; + GlyphMap* map; + }; + + nzUInt64 ComputeKey(unsigned int characterSize, nzUInt32 style) const; + unsigned int GetRealMaxAtlasSize() const; + unsigned int InsertRect(NzRectui* rect, bool* flipped) const; + const Glyph& PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, bool bold, char32_t character) const; + void ProcessGlyphQueue() const; + + std::unique_ptr m_data; + mutable std::unordered_map> m_kerningCache; + mutable std::unordered_map m_glyphes; + mutable std::unordered_map m_sizeInfoCache; + mutable std::vector m_atlases; + mutable std::vector m_glyphQueue; + unsigned int m_maxAtlasSize; + unsigned int m_minimumSizeStep; + + static NzFontLoader::LoaderList s_loaders; + static unsigned int s_maxAtlasSize; +}; + +#endif // NAZARA_FONT_HPP diff --git a/include/Nazara/Utility/FontData.hpp b/include/Nazara/Utility/FontData.hpp new file mode 100644 index 000000000..9805c1d2b --- /dev/null +++ b/include/Nazara/Utility/FontData.hpp @@ -0,0 +1,36 @@ +// Copyright (C) 2014 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, bool bold, 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; +}; + +#endif // NAZARA_FONTDATA_HPP diff --git a/include/Nazara/Utility/FontGlyph.hpp b/include/Nazara/Utility/FontGlyph.hpp new file mode 100644 index 000000000..11bceb255 --- /dev/null +++ b/include/Nazara/Utility/FontGlyph.hpp @@ -0,0 +1,19 @@ +// Copyright (C) 2014 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/src/Nazara/Utility/Font.cpp b/src/Nazara/Utility/Font.cpp new file mode 100644 index 000000000..c6a888929 --- /dev/null +++ b/src/Nazara/Utility/Font.cpp @@ -0,0 +1,507 @@ +// Copyright (C) 2014 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 + +namespace +{ + const unsigned int s_atlasStartSize = 512; +} + +bool NzFontParams::IsValid() const +{ + return true; // Rien à tester +} + +NzFont::NzFont() : +m_maxAtlasSize(0), +m_minimumSizeStep(1) +{ +} + +NzFont::~NzFont() +{ + Destroy(); +} + +void NzFont::ClearGlyphCache() +{ + // Destruction des atlas et glyphes mémorisés + m_atlases.clear(); + m_glyphes.clear(); + m_glyphQueue.clear(); + + // Création du premier atlas + m_atlases.resize(1); + Atlas& atlas = m_atlases.back(); + atlas.binPack.Reset(s_atlasStartSize, s_atlasStartSize); +} + +void NzFont::ClearKerningCache() +{ + m_kerningCache.clear(); +} + +void NzFont::ClearSizeInfoCache() +{ + m_sizeInfoCache.clear(); +} + +bool NzFont::Create(NzFontData* data) +{ + Destroy(); + + #if NAZARA_UTILITY_SAFE + if (!data) + { + NazaraError("Invalid font data"); + return false; + } + #endif + + m_data.reset(data); + + ClearGlyphCache(); // Création du premier atlas en mémoire + + return true; +} + +void NzFont::Destroy() +{ + m_atlases.clear(); + m_data.reset(); + m_kerningCache.clear(); + m_glyphes.clear(); + m_glyphQueue.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 & nzTextStyle_Bold, glyph); +} + +const NzFont::Atlas& NzFont::GetAtlas(unsigned int atlasIndex) const +{ + if (!m_glyphQueue.empty()) + ProcessGlyphQueue(); + + return m_atlases.at(atlasIndex); +} + +unsigned int NzFont::GetAtlasCount() const +{ + return m_atlases.size(); +} + +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::GetMaxAtlasSize() const +{ + return m_maxAtlasSize; +} + +unsigned int NzFont::GetMinimumStepSize() const +{ + return m_minimumSizeStep; +} + +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); + + 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::SetMaxAtlasSize(unsigned int maxAtlasSize) +{ + unsigned int oldMaxAtlasSize = GetRealMaxAtlasSize(); + m_maxAtlasSize = maxAtlasSize; + + // Si l'un de nos atlas dépasse la nouvelle taille, on doit vider le cache + maxAtlasSize = GetRealMaxAtlasSize(); + if (maxAtlasSize < oldMaxAtlasSize) + { + for (Atlas& atlas : m_atlases) + { + unsigned int atlasSize = atlas.binPack.GetWidth(); + if (atlasSize > maxAtlasSize) + { + NazaraWarning("At least one atlas was over new max atlas size (" + NzString::Number(atlasSize) + " > " + NzString::Number(maxAtlasSize) + "), clearing glyph cache..."); + ClearGlyphCache(); + return; + } + } + } +} + +void NzFont::SetMinimumStepSize(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 + + m_minimumSizeStep = minimumStepSize; +} + +unsigned int NzFont::GetDefaultMaxAtlasSize() +{ + return s_maxAtlasSize; +} + +void NzFont::SetDefaultMaxAtlasSize(unsigned int maxAtlasSize) +{ + s_maxAtlasSize = maxAtlasSize; +} + +nzUInt64 NzFont::ComputeKey(unsigned int characterSize, nzUInt32 style) const +{ + nzUInt64 sizePart = static_cast((characterSize/m_minimumSizeStep)*m_minimumSizeStep); + nzUInt64 stylePart = 0; + + if (style & nzTextStyle_Bold) // Les caractères gras sont générés différemment + stylePart |= nzTextStyle_Bold; + + // Les caractères italiques peuvent venir d'une autre police, dans le cas contraire ils sont générés au runtime + //if (style & nzTextStyle_Italic) + // stylePart |= nzTextStyle_Italic; + + return (stylePart << 32) | sizePart; +} + +unsigned int NzFont::GetRealMaxAtlasSize() const +{ + unsigned int maxAtlasSize = (m_maxAtlasSize == 0) ? s_maxAtlasSize : m_maxAtlasSize; + if (maxAtlasSize == 0) + maxAtlasSize = std::numeric_limits::max(); + + return maxAtlasSize; +} + +unsigned int NzFont::InsertRect(NzRectui* rect, bool* flipped) const +{ + ///DOC: Tous les pointeurs doivent être valides + // Précondition: Un rectangle ne peut pas être plus grand dans une dimension que la taille maximale de l'atlas + + unsigned int maxAtlasSize = GetRealMaxAtlasSize(); + + // 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_atlases.size(); ++i) + { + Atlas& atlas = m_atlases[i]; + if (atlas.binPack.Insert(rect, flipped, 1, false, NzGuillotineBinPack::RectBestAreaFit, NzGuillotineBinPack::SplitMinimizeArea)) + // Insertion réussie dans l'un des atlas, pas de question à se poser + return i; + else if (i == m_atlases.size() - 1) // Dernière itération ? + { + // Dernier atlas, et le glyphe ne rentre pas, peut-on agrandir la taille de l'atlas ? + unsigned int size = atlas.binPack.GetWidth(); // l'atlas étant carré, on ne teste qu'une dimension + if (size < maxAtlasSize) + { + // On peut encore agrandir l'atlas + size = std::min(size*2, maxAtlasSize); + atlas.binPack.Expand(size, size); + + // On relance la boucle sur le dernier atlas + i--; + } + else + { + // On ne peut plus agrandir le dernier atlas, il est temps d'en créer un nouveau + m_atlases.resize(m_atlases.size() + 1); + Atlas& newAtlas = m_atlases.back(); + + newAtlas.binPack.Reset(s_atlasStartSize, s_atlasStartSize); + + // On laisse la boucle insérer toute seule le rectangle à la prochaine itération + } + } + } + + // Si nous arrivons ici, c'est qu'une erreur a eu lieu en amont + NazaraInternalError("This shouldn't happen"); + return std::numeric_limits::max(); +} + +const NzFont::Glyph& NzFont::PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, bool bold, 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; + glyph.valid = false; + + // On extrait le glyphe depuis la police + NzFontGlyph fontGlyph; + if (ExtractGlyph(characterSize, character, bold, &fontGlyph)) + { + glyph.atlasRect.width = fontGlyph.image.GetWidth(); + glyph.atlasRect.height = fontGlyph.image.GetHeight(); + + unsigned int maxAtlasSize = GetRealMaxAtlasSize(); + if (glyph.atlasRect.width <= maxAtlasSize && glyph.atlasRect.height <= maxAtlasSize) + { + // Insertion du rectangle dans l'un des atlas + glyph.aabb = fontGlyph.aabb; + glyph.advance = fontGlyph.advance; + glyph.valid = true; + + if (glyph.atlasRect.width > 0 && glyph.atlasRect.height > 0) // Si l'image contient quelque chose + { + // Padding (pour éviter le débordement lors du filtrage) + const unsigned int padding = 1; // Un pixel entre chaque glyphe + + glyph.atlasRect.width += padding; + glyph.atlasRect.height += padding; + + // Insertion du rectangle dans l'atlas virtuel + glyph.atlasIndex = InsertRect(&glyph.atlasRect, &glyph.flipped); + + glyph.atlasRect.width -= padding; + glyph.atlasRect.height -= padding; + + // Mise en queue pour insertion dans l'atlas réel + m_glyphQueue.resize(m_glyphQueue.size()+1); + QueuedGlyph& queuedGlyph = m_glyphQueue.back(); + queuedGlyph.codepoint = character; + queuedGlyph.image = std::move(fontGlyph.image); + queuedGlyph.map = &glyphMap; + } + } + else + { + NazaraWarning("Glyph \"" + NzString::Unicode(character) + "\" is bigger than max atlas size"); + } + } + else + { + NazaraWarning("Failed to extract glyph \"" + NzString::Unicode(character) + "\""); + } + + return glyphMap.insert(std::make_pair(character, std::move(glyph))).first->second; +} + +void NzFont::ProcessGlyphQueue() const +{ + for (QueuedGlyph& queuedGlyph : m_glyphQueue) + { + GlyphMap& glyphMap = *queuedGlyph.map; + auto glyphIt = glyphMap.find(queuedGlyph.codepoint); + if (glyphIt == glyphMap.end()) + continue; // Le glyphe a certainement été supprimé du cache avant la mise à jour de l'atlas + + Glyph& glyph = glyphIt->second; + Atlas& atlas = m_atlases[glyph.atlasIndex]; + + // On s'assure que l'atlas est de la bonne taille + NzVector2ui atlasSize(atlas.image.GetWidth(), atlas.image.GetHeight()); + NzVector2ui binPackSize = atlas.binPack.GetSize(); + if (atlasSize != binPackSize) + { + // Création d'une nouvelle image + NzImage newAtlas(nzImageType_2D, nzPixelFormat_A8, binPackSize.x, binPackSize.y); + if (atlas.image.IsValid()) + { + newAtlas.Copy(atlas.image, NzRectui(atlasSize), NzVector2ui(0, 0)); // On copie les anciennes données + + // On initialise les nouvelles régions + newAtlas.Fill(NzColor(255, 255, 255, 0), NzRectui(0, atlasSize.y, binPackSize.x, binPackSize.y - atlasSize.y)); + newAtlas.Fill(NzColor(255, 255, 255, 0), NzRectui(atlasSize.x, 0, binPackSize.x - atlasSize.x, atlasSize.y)); + } + else + newAtlas.Fill(NzColor(255, 255, 255, 0)); // On initialise les pixels + + atlas.image = std::move(newAtlas); // On déplace la nouvelle image vers l'atlas + } + + unsigned int glyphWidth = queuedGlyph.image.GetWidth(); + unsigned int glyphHeight = queuedGlyph.image.GetHeight(); + + // On copie le glyphe dans l'atlas + if (glyph.flipped) + { + // On tourne le glyphe pour qu'il rentre dans le rectangle + const nzUInt8* src = queuedGlyph.image.GetConstPixels(); + nzUInt8* ptr = atlas.image.GetPixels(glyph.atlasRect.x, glyph.atlasRect.y + glyphWidth - 1); + + unsigned int lineStride = atlas.image.GetWidth(); // BPP = 1 + for (unsigned int y = 0; y < glyphHeight; ++y) + { + for (unsigned int x = 0; x < glyphWidth; ++x) + { + *ptr = *src++; // On copie et on avance dans le glyphe + ptr -= lineStride; // On remonte d'une ligne + } + + ptr += lineStride*glyphWidth + 1; + } + } + else + atlas.image.Copy(queuedGlyph.image, NzRectui(glyphWidth, glyphHeight), glyph.atlasRect.GetPosition()); + + queuedGlyph.image.Destroy(); // On libère l'image dès que possible (pour réduire la consommation) + } + + m_glyphQueue.clear(); +} + +NzFontLoader::LoaderList NzFont::s_loaders; +unsigned int NzFont::s_maxAtlasSize = 8192; // Valeur totalement arbitraire diff --git a/src/Nazara/Utility/FontData.cpp b/src/Nazara/Utility/FontData.cpp new file mode 100644 index 000000000..a5f4b13bd --- /dev/null +++ b/src/Nazara/Utility/FontData.cpp @@ -0,0 +1,8 @@ +// Copyright (C) 2014 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/Loaders/FreeType.hpp b/src/Nazara/Utility/Loaders/FreeType.hpp new file mode 100644 index 000000000..6ee1f60ab --- /dev/null +++ b/src/Nazara/Utility/Loaders/FreeType.hpp @@ -0,0 +1,15 @@ +// Copyright (C) 2014 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..71269d9da --- /dev/null +++ b/src/Nazara/Utility/Loaders/FreeType/Loader.cpp @@ -0,0 +1,393 @@ +// Copyright (C) 2014 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 + +namespace +{ + FT_Library s_library = nullptr; + 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 FreeTypeStream : public NzFontData + { + public: + FreeTypeStream() : + m_face(nullptr), + 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, bool bold, NzFontGlyph* dst) + { + #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 = 1 << 6; + + bool outlineFormat = (glyph->format == FT_GLYPH_FORMAT_OUTLINE); + if (outlineFormat && bold) + // http://www.freetype.org/freetype2/docs/reference/ft2-outline_processing.html#FT_Outline_Embolden + FT_Outline_Embolden(&glyph->outline, boldStrength); + + // 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 (!outlineFormat && bold) + { + // 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); + } + + dst->advance = glyph->metrics.horiAdvance >> 6; + if (bold) + dst->advance += boldStrength >> 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 + { + return m_face->family_name; + } + + NzString GetStyleName() const + { + return m_face->style_name; + } + + bool HasKerning() const + { + return FT_HAS_KERNING(m_face); + } + + bool IsScalable() const + { + 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 + { + 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 + { + 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 + { + 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 + { + 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) + { + if (!m_file.Open(filePath, NzFile::ReadOnly)) + { + NazaraError("Failed to open stream from file: " + NzError::GetLastError()); + return false; + } + + SetStream(m_file); + return true; + } + + 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; + } + + 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; + NzFile m_file; + mutable unsigned int m_characterSize; + }; + + bool IsSupported(const NzString& extension) + { + ///FIXME: Je suppose qu'il en manque quelques uns.. + static std::set supportedExtensions = { + "afm", "bdf", "cff", "cid", "dfont", "fnt", "pfa", "pfb", "pfm", "pfr", "sfnt", "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 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) + NzFontLoader::RegisterLoader(IsSupported, Check, LoadStream, LoadFile); + 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); + + FT_Done_FreeType(s_library); + s_library = nullptr; + } +} diff --git a/src/Nazara/Utility/Utility.cpp b/src/Nazara/Utility/Utility.cpp index 885e4a578..c12459277 100644 --- a/src/Nazara/Utility/Utility.cpp +++ b/src/Nazara/Utility/Utility.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -70,6 +71,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 +113,7 @@ void NzUtility::Uninitialize() // Libération du module s_moduleReferenceCounter = 0; + NzLoaders_FreeType_Unregister(); NzLoaders_MD2_Unregister(); NzLoaders_MD5Anim_Unregister(); NzLoaders_MD5Mesh_Unregister(); From b3d72ec09407dcb3f17d8bb79cc3951d29bfe511 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 4 Jan 2015 18:16:31 +0100 Subject: [PATCH 14/64] Renamed BufferStorage enum to DataStorage Former-commit-id: 97eede03eb6bb85e506c640d40c9d6e7acb2e099 --- build/codeblocks/CppCheckResults.xml | 15 ++++++++++++++ include/Nazara/Utility/Buffer.hpp | 16 +++++++-------- include/Nazara/Utility/Enums.hpp | 18 ++++++++--------- include/Nazara/Utility/IndexBuffer.hpp | 6 +++--- include/Nazara/Utility/Mesh.hpp | 2 +- include/Nazara/Utility/VertexBuffer.hpp | 6 +++--- .../Graphics/ForwardRenderTechnique.cpp | 4 ++-- src/Nazara/Graphics/SkinningManager.cpp | 2 +- src/Nazara/Graphics/SkyboxBackground.cpp | 4 ++-- src/Nazara/Renderer/DebugDrawer.cpp | 2 +- src/Nazara/Renderer/Renderer.cpp | 6 +++--- src/Nazara/Utility/Buffer.cpp | 20 +++++++++---------- src/Nazara/Utility/IndexBuffer.cpp | 6 +++--- src/Nazara/Utility/Mesh.cpp | 2 +- src/Nazara/Utility/VertexBuffer.cpp | 6 +++--- 15 files changed, 65 insertions(+), 50 deletions(-) create mode 100644 build/codeblocks/CppCheckResults.xml diff --git a/build/codeblocks/CppCheckResults.xml b/build/codeblocks/CppCheckResults.xml new file mode 100644 index 000000000..8bd3586b0 --- /dev/null +++ b/build/codeblocks/CppCheckResults.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/include/Nazara/Utility/Buffer.hpp b/include/Nazara/Utility/Buffer.hpp index be48b34ad..a41e65e98 100644 --- a/include/Nazara/Utility/Buffer.hpp +++ b/include/Nazara/Utility/Buffer.hpp @@ -28,19 +28,19 @@ class NAZARA_API NzBuffer : public NzResource, NzNonCopyable using BufferFunction = 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, nzDataStorage 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, nzDataStorage 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; + nzDataStorage GetStorage() const; nzBufferType GetType() const; nzBufferUsage GetUsage() const; @@ -50,24 +50,24 @@ class NAZARA_API NzBuffer : public NzResource, 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(nzDataStorage storage); void Unmap() const; - static bool IsSupported(nzBufferStorage storage); - static void SetBufferFunction(nzBufferStorage storage, BufferFunction func); + static bool IsSupported(nzDataStorage storage); + static void SetBufferFunction(nzDataStorage storage, BufferFunction func); private: static bool Initialize(); static void Uninitialize(); - nzBufferStorage m_storage; nzBufferType m_type; nzBufferUsage m_usage; + nzDataStorage m_storage; NzAbstractBuffer* m_impl; unsigned int m_size; - static BufferFunction s_bufferFunctions[nzBufferStorage_Max+1]; + static BufferFunction s_bufferFunctions[nzDataStorage_Max+1]; }; #endif // NAZARA_BUFFER_HPP diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index 06e2a5c2a..6d0ec4f2a 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.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,15 @@ enum nzCubemapFace nzCubemapFace_Max = nzCubemapFace_NegativeZ }; +enum nzDataStorage +{ + nzDataStorage_Both, + nzDataStorage_Hardware, + nzDataStorage_Software, + + nzDataStorage_Max = nzDataStorage_Software +}; + enum nzEventType { nzEventType_GainedFocus, diff --git a/include/Nazara/Utility/IndexBuffer.hpp b/include/Nazara/Utility/IndexBuffer.hpp index 3088a0fd1..3f7eb59d6 100644 --- a/include/Nazara/Utility/IndexBuffer.hpp +++ b/include/Nazara/Utility/IndexBuffer.hpp @@ -23,7 +23,7 @@ class NAZARA_API NzIndexBuffer : public NzResource 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, nzDataStorage storage = nzDataStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); NzIndexBuffer(const NzIndexBuffer& indexBuffer); NzIndexBuffer(NzIndexBuffer&& indexBuffer) noexcept; ~NzIndexBuffer(); @@ -54,11 +54,11 @@ class NAZARA_API NzIndexBuffer : public NzResource 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, nzDataStorage storage = nzDataStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); void Reset(const NzIndexBuffer& indexBuffer); void Reset(NzIndexBuffer&& indexBuffer) noexcept; - bool SetStorage(nzBufferStorage storage); + bool SetStorage(nzDataStorage storage); void Unmap() const; diff --git a/include/Nazara/Utility/Mesh.hpp b/include/Nazara/Utility/Mesh.hpp index 116bbc3e7..6f4f83c61 100644 --- a/include/Nazara/Utility/Mesh.hpp +++ b/include/Nazara/Utility/Mesh.hpp @@ -25,7 +25,7 @@ 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; + nzDataStorage storage = nzDataStorage_Hardware; // La mise à l'échelle éventuelle que subira le mesh NzVector3f scale = NzVector3f::Unit(); diff --git a/include/Nazara/Utility/VertexBuffer.hpp b/include/Nazara/Utility/VertexBuffer.hpp index 6b009561d..6acada650 100644 --- a/include/Nazara/Utility/VertexBuffer.hpp +++ b/include/Nazara/Utility/VertexBuffer.hpp @@ -24,7 +24,7 @@ class NAZARA_API NzVertexBuffer : public NzResource 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, nzDataStorage storage = nzDataStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); NzVertexBuffer(const NzVertexBuffer& vertexBuffer); NzVertexBuffer(NzVertexBuffer&& vertexBuffer) noexcept; ~NzVertexBuffer(); @@ -50,11 +50,11 @@ class NAZARA_API NzVertexBuffer : public NzResource 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, nzDataStorage storage = nzDataStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); void Reset(const NzVertexBuffer& vertexBuffer); void Reset(NzVertexBuffer&& vertexBuffer) noexcept; - bool SetStorage(nzBufferStorage storage); + bool SetStorage(nzDataStorage storage); void SetVertexDeclaration(const NzVertexDeclaration* vertexDeclaration); void Unmap() const; diff --git a/src/Nazara/Graphics/ForwardRenderTechnique.cpp b/src/Nazara/Graphics/ForwardRenderTechnique.cpp index bc962cc19..03cac541c 100644 --- a/src/Nazara/Graphics/ForwardRenderTechnique.cpp +++ b/src/Nazara/Graphics/ForwardRenderTechnique.cpp @@ -27,7 +27,7 @@ namespace NzIndexBuffer* BuildIndexBuffer() { - std::unique_ptr indexBuffer(new NzIndexBuffer(false, s_maxSprites*6, nzBufferStorage_Hardware, nzBufferUsage_Static)); + std::unique_ptr indexBuffer(new NzIndexBuffer(false, s_maxSprites*6, nzDataStorage_Hardware, nzBufferUsage_Static)); indexBuffer->SetPersistent(false); NzBufferMapper mapper(indexBuffer.get(), nzBufferAccess_WriteOnly); @@ -49,7 +49,7 @@ namespace } NzForwardRenderTechnique::NzForwardRenderTechnique() : -m_spriteBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Color_UV), s_maxSprites*4, nzBufferStorage_Hardware, nzBufferUsage_Dynamic), +m_spriteBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Color_UV), s_maxSprites*4, nzDataStorage_Hardware, nzBufferUsage_Dynamic), m_maxLightPassPerObject(3) { if (!s_indexBuffer) diff --git a/src/Nazara/Graphics/SkinningManager.cpp b/src/Nazara/Graphics/SkinningManager.cpp index 9200b1186..2e47fc11e 100644 --- a/src/Nazara/Graphics/SkinningManager.cpp +++ b/src/Nazara/Graphics/SkinningManager.cpp @@ -174,7 +174,7 @@ NzVertexBuffer* NzSkinningManager::GetBuffer(const NzSkeletalMesh* mesh, const N { 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)); diff --git a/src/Nazara/Graphics/SkyboxBackground.cpp b/src/Nazara/Graphics/SkyboxBackground.cpp index d1d7b8ca3..76cbd7b08 100644 --- a/src/Nazara/Graphics/SkyboxBackground.cpp +++ b/src/Nazara/Graphics/SkyboxBackground.cpp @@ -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] = @@ -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/Renderer/DebugDrawer.cpp b/src/Nazara/Renderer/DebugDrawer.cpp index 47c4388ef..5f7090a81 100644 --- a/src/Nazara/Renderer/DebugDrawer.cpp +++ b/src/Nazara/Renderer/DebugDrawer.cpp @@ -667,7 +667,7 @@ bool NzDebugDrawer::Initialize() try { NzErrorFlags flags(nzErrorFlag_ThrowException, true); - s_vertexBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XYZ), 65365, nzBufferStorage_Hardware, nzBufferUsage_Dynamic); + s_vertexBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XYZ), 65365, nzDataStorage_Hardware, nzBufferUsage_Dynamic); } catch (const std::exception& e) { diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index 28e0b5288..c96b1de9c 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -692,7 +692,7 @@ bool NzRenderer::Initialize() return false; } - NzBuffer::SetBufferFunction(nzBufferStorage_Hardware, [](NzBuffer* parent, nzBufferType type) -> NzAbstractBuffer* { return new NzHardwareBuffer(parent, type); } ); + NzBuffer::SetBufferFunction(nzDataStorage_Hardware, [](NzBuffer* parent, nzBufferType type) -> NzAbstractBuffer* { return new NzHardwareBuffer(parent, type); } ); for (unsigned int i = 0; i <= nzMatrixType_Max; ++i) { @@ -775,7 +775,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] = { @@ -796,7 +796,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) { diff --git a/src/Nazara/Utility/Buffer.cpp b/src/Nazara/Utility/Buffer.cpp index 18d4e0583..5fd1764b9 100644 --- a/src/Nazara/Utility/Buffer.cpp +++ b/src/Nazara/Utility/Buffer.cpp @@ -29,7 +29,7 @@ m_size(0) { } -NzBuffer::NzBuffer(nzBufferType type, unsigned int size, nzBufferStorage storage, nzBufferUsage usage) : +NzBuffer::NzBuffer(nzBufferType type, unsigned int size, nzDataStorage storage, nzBufferUsage usage) : m_type(type), m_impl(nullptr) { @@ -63,7 +63,7 @@ bool NzBuffer::CopyContent(const NzBuffer& buffer) return Fill(mapper.GetPointer(), 0, buffer.GetSize()); } -bool NzBuffer::Create(unsigned int size, nzBufferStorage storage, nzBufferUsage usage) +bool NzBuffer::Create(unsigned int size, nzDataStorage storage, nzBufferUsage usage) { Destroy(); @@ -131,7 +131,7 @@ unsigned int NzBuffer::GetSize() const return m_size; } -nzBufferStorage NzBuffer::GetStorage() const +nzDataStorage NzBuffer::GetStorage() const { return m_storage; } @@ -148,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 @@ -200,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(nzDataStorage storage) { #if NAZARA_UTILITY_SAFE if (!m_impl) @@ -272,26 +272,26 @@ void NzBuffer::Unmap() const NazaraWarning("Failed to unmap buffer (it's content is undefined)"); ///TODO: Unexpected ? } -bool NzBuffer::IsSupported(nzBufferStorage storage) +bool NzBuffer::IsSupported(nzDataStorage storage) { return s_bufferFunctions[storage] != nullptr; } -void NzBuffer::SetBufferFunction(nzBufferStorage storage, BufferFunction func) +void NzBuffer::SetBufferFunction(nzDataStorage storage, BufferFunction func) { s_bufferFunctions[storage] = func; } bool NzBuffer::Initialize() { - s_bufferFunctions[nzBufferStorage_Software] = SoftwareBufferFunction; + s_bufferFunctions[nzDataStorage_Software] = SoftwareBufferFunction; return true; } void NzBuffer::Uninitialize() { - std::memset(s_bufferFunctions, 0, (nzBufferStorage_Max+1)*sizeof(NzBuffer::BufferFunction)); + std::memset(s_bufferFunctions, 0, (nzDataStorage_Max+1)*sizeof(NzBuffer::BufferFunction)); } -NzBuffer::BufferFunction NzBuffer::s_bufferFunctions[nzBufferStorage_Max+1] = {0}; +NzBuffer::BufferFunction NzBuffer::s_bufferFunctions[nzDataStorage_Max+1] = {0}; diff --git a/src/Nazara/Utility/IndexBuffer.cpp b/src/Nazara/Utility/IndexBuffer.cpp index f96c220b8..65cc22757 100644 --- a/src/Nazara/Utility/IndexBuffer.cpp +++ b/src/Nazara/Utility/IndexBuffer.cpp @@ -24,7 +24,7 @@ NzIndexBuffer::NzIndexBuffer(bool largeIndices, NzBuffer* buffer, unsigned int s Reset(largeIndices, buffer, startOffset, endOffset); } -NzIndexBuffer::NzIndexBuffer(bool largeIndices, unsigned int length, nzBufferStorage storage, nzBufferUsage usage) +NzIndexBuffer::NzIndexBuffer(bool largeIndices, unsigned int length, nzDataStorage storage, nzBufferUsage usage) { NzErrorFlags(nzErrorFlag_ThrowException, true); Reset(largeIndices, length, storage, usage); @@ -220,7 +220,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, nzDataStorage storage, nzBufferUsage usage) { unsigned int stride = (largeIndices) ? sizeof(nzUInt32) : sizeof(nzUInt16); @@ -251,7 +251,7 @@ void NzIndexBuffer::Reset(NzIndexBuffer&& indexBuffer) noexcept m_startOffset = indexBuffer.m_startOffset; } -bool NzIndexBuffer::SetStorage(nzBufferStorage storage) +bool NzIndexBuffer::SetStorage(nzDataStorage storage) { return m_buffer->SetStorage(storage); } diff --git a/src/Nazara/Utility/Mesh.cpp b/src/Nazara/Utility/Mesh.cpp index 61427fa3d..bb588a7ae 100644 --- a/src/Nazara/Utility/Mesh.cpp +++ b/src/Nazara/Utility/Mesh.cpp @@ -26,7 +26,7 @@ NzMeshParams::NzMeshParams() { if (!NzBuffer::IsSupported(storage)) - storage = nzBufferStorage_Software; + storage = nzDataStorage_Software; } bool NzMeshParams::IsValid() const diff --git a/src/Nazara/Utility/VertexBuffer.cpp b/src/Nazara/Utility/VertexBuffer.cpp index 45c572fea..31af8c2e9 100644 --- a/src/Nazara/Utility/VertexBuffer.cpp +++ b/src/Nazara/Utility/VertexBuffer.cpp @@ -20,7 +20,7 @@ NzVertexBuffer::NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, NzB 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, nzDataStorage storage, nzBufferUsage usage) { NzErrorFlags(nzErrorFlag_ThrowException, true); Reset(vertexDeclaration, length, storage, usage); @@ -230,7 +230,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, nzDataStorage storage, nzBufferUsage usage) { m_endOffset = length * ((vertexDeclaration) ? vertexDeclaration->GetStride() : 1); m_startOffset = 0; @@ -259,7 +259,7 @@ void NzVertexBuffer::Reset(NzVertexBuffer&& vertexBuffer) noexcept m_vertexDeclaration = std::move(vertexBuffer.m_vertexDeclaration); } -bool NzVertexBuffer::SetStorage(nzBufferStorage storage) +bool NzVertexBuffer::SetStorage(nzDataStorage storage) { return m_buffer->SetStorage(storage); } From d560975e096f9d1e35439c470a29d465c384e402 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 4 Jan 2015 18:23:06 +0100 Subject: [PATCH 15/64] Renamed (Set)BufferFunction to (Set)BufferFactory Former-commit-id: 6165dcd881716461a9886be6ce7fd6bb2b335ef0 --- include/Nazara/Utility/Buffer.hpp | 6 +++--- src/Nazara/Renderer/Renderer.cpp | 5 ++++- src/Nazara/Utility/Buffer.cpp | 23 +++++++++++------------ 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/include/Nazara/Utility/Buffer.hpp b/include/Nazara/Utility/Buffer.hpp index a41e65e98..1a24e4d9a 100644 --- a/include/Nazara/Utility/Buffer.hpp +++ b/include/Nazara/Utility/Buffer.hpp @@ -25,7 +25,7 @@ class NAZARA_API NzBuffer : public NzResource, 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, nzDataStorage storage = nzDataStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); @@ -55,7 +55,7 @@ class NAZARA_API NzBuffer : public NzResource, NzNonCopyable void Unmap() const; static bool IsSupported(nzDataStorage storage); - static void SetBufferFunction(nzDataStorage storage, BufferFunction func); + static void SetBufferFactory(nzDataStorage storage, BufferFactory func); private: static bool Initialize(); @@ -67,7 +67,7 @@ class NAZARA_API NzBuffer : public NzResource, NzNonCopyable NzAbstractBuffer* m_impl; unsigned int m_size; - static BufferFunction s_bufferFunctions[nzDataStorage_Max+1]; + static BufferFactory s_bufferFactories[nzDataStorage_Max+1]; }; #endif // NAZARA_BUFFER_HPP diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index c96b1de9c..9243f02a0 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -692,7 +692,10 @@ bool NzRenderer::Initialize() return false; } - NzBuffer::SetBufferFunction(nzDataStorage_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) { diff --git a/src/Nazara/Utility/Buffer.cpp b/src/Nazara/Utility/Buffer.cpp index 5fd1764b9..e05a15db2 100644 --- a/src/Nazara/Utility/Buffer.cpp +++ b/src/Nazara/Utility/Buffer.cpp @@ -16,7 +16,7 @@ namespace { - NzAbstractBuffer* SoftwareBufferFunction(NzBuffer* parent, nzBufferType type) + NzAbstractBuffer* SoftwareBufferFactory(NzBuffer* parent, nzBufferType type) { return new NzSoftwareBuffer(parent, type); } @@ -59,7 +59,6 @@ bool NzBuffer::CopyContent(const NzBuffer& buffer) #endif NzBufferMapper mapper(buffer, nzBufferAccess_ReadOnly); - return Fill(mapper.GetPointer(), 0, buffer.GetSize()); } @@ -68,13 +67,13 @@ bool NzBuffer::Create(unsigned int size, nzDataStorage storage, nzBufferUsage us Destroy(); // Notre buffer est-il supporté ? - if (!s_bufferFunctions[storage]) + if (!IsSupported(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"); @@ -228,7 +227,7 @@ bool NzBuffer::SetStorage(nzDataStorage storage) return false; } - NzAbstractBuffer* impl = s_bufferFunctions[storage](this, m_type); + NzAbstractBuffer* impl = s_bufferFactories[storage](this, m_type); if (!impl->Create(m_size, m_usage)) { NazaraError("Failed to create buffer"); @@ -269,29 +268,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(nzDataStorage storage) { - return s_bufferFunctions[storage] != nullptr; + return s_bufferFactories[storage] != nullptr; } -void NzBuffer::SetBufferFunction(nzDataStorage storage, BufferFunction func) +void NzBuffer::SetBufferFactory(nzDataStorage storage, BufferFactory func) { - s_bufferFunctions[storage] = func; + s_bufferFactories[storage] = func; } bool NzBuffer::Initialize() { - s_bufferFunctions[nzDataStorage_Software] = SoftwareBufferFunction; + s_bufferFactories[nzDataStorage_Software] = SoftwareBufferFactory; return true; } void NzBuffer::Uninitialize() { - std::memset(s_bufferFunctions, 0, (nzDataStorage_Max+1)*sizeof(NzBuffer::BufferFunction)); + std::memset(s_bufferFactories, 0, (nzDataStorage_Max+1)*sizeof(NzBuffer::BufferFactory)); } -NzBuffer::BufferFunction NzBuffer::s_bufferFunctions[nzDataStorage_Max+1] = {0}; +NzBuffer::BufferFactory NzBuffer::s_bufferFactories[nzDataStorage_Max+1] = {0}; From 911e10fa8408d0fedb3aaf1c583f0a97e75a5882 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 4 Jan 2015 18:30:50 +0100 Subject: [PATCH 16/64] Renamed Buffer::IsSupported to IsStorageSupported Former-commit-id: 12309ca590820fd68ab2b15a4c41ffb554832603 --- include/Nazara/Utility/Buffer.hpp | 2 +- src/Nazara/Utility/Buffer.cpp | 8 +++----- src/Nazara/Utility/Mesh.cpp | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/include/Nazara/Utility/Buffer.hpp b/include/Nazara/Utility/Buffer.hpp index 1a24e4d9a..b1b0b64b1 100644 --- a/include/Nazara/Utility/Buffer.hpp +++ b/include/Nazara/Utility/Buffer.hpp @@ -54,7 +54,7 @@ class NAZARA_API NzBuffer : public NzResource, NzNonCopyable void Unmap() const; - static bool IsSupported(nzDataStorage storage); + static bool IsStorageSupported(nzDataStorage storage); static void SetBufferFactory(nzDataStorage storage, BufferFactory func); private: diff --git a/src/Nazara/Utility/Buffer.cpp b/src/Nazara/Utility/Buffer.cpp index e05a15db2..c35f8bf70 100644 --- a/src/Nazara/Utility/Buffer.cpp +++ b/src/Nazara/Utility/Buffer.cpp @@ -67,7 +67,7 @@ bool NzBuffer::Create(unsigned int size, nzDataStorage storage, nzBufferUsage us Destroy(); // Notre buffer est-il supporté ? - if (!IsSupported(storage)) + if (!IsStorageSupported(storage)) { NazaraError("Buffer storage not supported"); return false; @@ -212,13 +212,11 @@ bool NzBuffer::SetStorage(nzDataStorage 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) @@ -271,7 +269,7 @@ void NzBuffer::Unmap() const NazaraWarning("Failed to unmap buffer (it's content may be undefined)"); ///TODO: Unexpected ? } -bool NzBuffer::IsSupported(nzDataStorage storage) +bool NzBuffer::IsStorageSupported(nzDataStorage storage) { return s_bufferFactories[storage] != nullptr; } diff --git a/src/Nazara/Utility/Mesh.cpp b/src/Nazara/Utility/Mesh.cpp index bb588a7ae..ee6489dfc 100644 --- a/src/Nazara/Utility/Mesh.cpp +++ b/src/Nazara/Utility/Mesh.cpp @@ -25,13 +25,13 @@ NzMeshParams::NzMeshParams() { - if (!NzBuffer::IsSupported(storage)) + 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; From 0f033eaed974eb3a5b54b1b9ee66a4b572aab38f Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 4 Jan 2015 18:57:01 +0100 Subject: [PATCH 17/64] Added CallOnExit::CallAndReset() Former-commit-id: 045ff61445203999757971deeeafee719fc5506a --- include/Nazara/Core/CallOnExit.hpp | 1 + include/Nazara/Core/CallOnExit.inl | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/include/Nazara/Core/CallOnExit.hpp b/include/Nazara/Core/CallOnExit.hpp index 3f8fc1f2f..45ea2622d 100644 --- a/include/Nazara/Core/CallOnExit.hpp +++ b/include/Nazara/Core/CallOnExit.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..fd7f4de80 100644 --- a/include/Nazara/Core/CallOnExit.inl +++ b/include/Nazara/Core/CallOnExit.inl @@ -2,6 +2,7 @@ // 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; From 0d143a64a2f3c108fef9f0c4b25e8cd81eb4d8f7 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 4 Jan 2015 19:02:35 +0100 Subject: [PATCH 18/64] Made Buffer::SetStorage exception-safe Former-commit-id: 46e9f9416aa3bd93e130f784a42d23533ec60dea --- src/Nazara/Utility/Buffer.cpp | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/Nazara/Utility/Buffer.cpp b/src/Nazara/Utility/Buffer.cpp index c35f8bf70..71b568f5b 100644 --- a/src/Nazara/Utility/Buffer.cpp +++ b/src/Nazara/Utility/Buffer.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include #include @@ -225,31 +226,36 @@ bool NzBuffer::SetStorage(nzDataStorage storage) return false; } - NzAbstractBuffer* impl = s_bufferFactories[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; From 5daf09e41b81039ece23fe6ba9010dc1e6ce5985 Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 5 Jan 2015 02:32:57 +0100 Subject: [PATCH 19/64] Added OpenGL-like Vector constructors Former-commit-id: 302389b6a915d66a0a0fb4cc9a748ed5266ae98c --- include/Nazara/Math/Vector2.hpp | 7 ++++ include/Nazara/Math/Vector2.inl | 30 +++++++++++++ include/Nazara/Math/Vector3.hpp | 11 ++++- include/Nazara/Math/Vector3.inl | 32 ++++++++++++++ include/Nazara/Math/Vector4.hpp | 17 ++++++-- include/Nazara/Math/Vector4.inl | 74 +++++++++++++++++++++++++++++++-- 6 files changed, 163 insertions(+), 8 deletions(-) diff --git a/include/Nazara/Math/Vector2.hpp b/include/Nazara/Math/Vector2.hpp index 357babaa5..53850c631 100644 --- a/include/Nazara/Math/Vector2.hpp +++ b/include/Nazara/Math/Vector2.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 227d95425..f97786610 100644 --- a/include/Nazara/Math/Vector2.inl +++ b/include/Nazara/Math/Vector2.inl @@ -36,6 +36,18 @@ 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 { @@ -208,6 +220,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..e8fe8f7d0 100644 --- a/include/Nazara/Math/Vector3.hpp +++ b/include/Nazara/Math/Vector3.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 f300330b8..fb395a748 100644 --- a/include/Nazara/Math/Vector3.inl +++ b/include/Nazara/Math/Vector3.inl @@ -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,6 +48,12 @@ NzVector3::NzVector3(const NzVector3& vec) Set(vec); } +template +NzVector3::NzVector3(const NzVector4& vec) +{ + Set(vec); +} + template T NzVector3::AbsDotProduct(const NzVector3& vec) const { @@ -255,6 +267,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) { @@ -302,6 +324,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..7bad9b918 100644 --- a/include/Nazara/Math/Vector4.hpp +++ b/include/Nazara/Math/Vector4.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 2f6002fbc..c1d7f4d1c 100644 --- a/include/Nazara/Math/Vector4.inl +++ b/include/Nazara/Math/Vector4.inl @@ -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) { @@ -155,10 +179,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 +223,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 +239,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 +273,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; } From b2b18a9f5124f0971ae3024132cbbfb8098e71dd Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 5 Jan 2015 13:41:56 +0100 Subject: [PATCH 20/64] Added Image::GetSize (returning the image's dimensions) Renamed original Image::GetSize to GetMemoryImage Former-commit-id: a2b54f171353b8197639b5f2b3911e4b3f2a8db2 --- include/Nazara/Utility/Image.hpp | 5 +- src/Nazara/Utility/Image.cpp | 83 ++++++++++++++++++-------------- 2 files changed, 51 insertions(+), 37 deletions(-) diff --git a/include/Nazara/Utility/Image.hpp b/include/Nazara/Utility/Image.hpp index 21cefa6b3..f59811d40 100644 --- a/include/Nazara/Utility/Image.hpp +++ b/include/Nazara/Utility/Image.hpp @@ -75,10 +75,11 @@ class NAZARA_API NzImage : public NzResource 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; diff --git a/src/Nazara/Utility/Image.cpp b/src/Nazara/Utility/Image.cpp index 7dc412dc8..4f7aabc9a 100644 --- a/src/Nazara/Utility/Image.cpp +++ b/src/Nazara/Utility/Image.cpp @@ -680,6 +680,49 @@ nzUInt8 NzImage::GetMaxLevel() const 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 { #if NAZARA_UTILITY_SAFE @@ -776,34 +819,7 @@ 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) @@ -813,10 +829,7 @@ unsigned int NzImage::GetSize(nzUInt8 level) const } #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 @@ -1122,7 +1135,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) @@ -1130,7 +1143,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]; } @@ -1434,7 +1447,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); } From d13ab1a0506a466dc5790c1c01544b29e1f51298 Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 5 Jan 2015 13:51:46 +0100 Subject: [PATCH 21/64] (Texture) Reflected Image interface (size getters) Former-commit-id: 4d979671c7b49191fb44b5fae7e9bfb266cd1417 --- include/Nazara/Renderer/Texture.hpp | 8 +++--- src/Nazara/Renderer/Texture.cpp | 43 +++++++++++++++++------------ 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/include/Nazara/Renderer/Texture.hpp b/include/Nazara/Renderer/Texture.hpp index f78feb490..816c6b1e5 100644 --- a/include/Nazara/Renderer/Texture.hpp +++ b/include/Nazara/Renderer/Texture.hpp @@ -43,12 +43,12 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable 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; + NzVector3ui GetSize(nzUInt8 level = 0) const; nzImageType GetType() const; - unsigned int GetWidth() const; + unsigned int GetWidth(nzUInt8 level = 0) const; bool HasMipmaps() const; diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index 9605244c4..e080bab0a 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -29,6 +29,12 @@ struct NzTextureImpl namespace { + inline unsigned int GetLevelSize(unsigned int size, nzUInt8 level) + { + // Contrairement à la classe Image, un appel à GetLevelSize(0, level) n'est pas possible + return std::max(size >> level, 1U); + } + inline void SetUnpackAlignement(nzUInt8 bpp) { if (bpp % 8 == 0) @@ -113,7 +119,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; @@ -122,7 +128,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; @@ -134,7 +140,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; } @@ -320,7 +326,7 @@ nzUInt8 NzTexture::GetBytesPerPixel() const return NzPixelFormat::GetBytesPerPixel(m_impl->format); } -unsigned int NzTexture::GetDepth() const +unsigned int NzTexture::GetDepth(nzUInt8 level) const { #if NAZARA_RENDERER_SAFE if (!m_impl) @@ -330,7 +336,7 @@ unsigned int NzTexture::GetDepth() const } #endif - return m_impl->depth; + return GetLevelSize(m_impl->depth, level); } nzPixelFormat NzTexture::GetFormat() const @@ -346,7 +352,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) @@ -356,20 +362,20 @@ unsigned int NzTexture::GetHeight() const } #endif - return m_impl->height; + return GetLevelSize(m_impl->height, level); } -NzVector2ui NzTexture::GetSize() const +NzVector3ui NzTexture::GetSize(nzUInt8 level) const { #if NAZARA_RENDERER_SAFE if (!m_impl) { NazaraError("Texture must be valid"); - return NzVector2ui(0, 0); + return NzVector3ui(0, 0, 0); } #endif - return NzVector2ui(m_impl->width, m_impl->height); + return NzVector3ui(GetLevelSize(m_impl->width, level), GetLevelSize(m_impl->height, level), GetLevelSize(m_impl->depth, level)); } nzImageType NzTexture::GetType() const @@ -385,7 +391,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) @@ -395,7 +401,7 @@ unsigned int NzTexture::GetWidth() const } #endif - return m_impl->width; + return GetLevelSize(m_impl->width, level); } bool NzTexture::HasMipmaps() const @@ -470,6 +476,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) + "..."); @@ -889,7 +896,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) @@ -920,12 +927,12 @@ 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) || + if (box.x+box.width > GetLevelSize(m_impl->width, level) || box.y+box.height > height || - box.z+box.depth > std::max(m_impl->depth >> level, 1U)) + box.z+box.depth > GetLevelSize(m_impl->depth, level)) { NazaraError("Cube dimensions are out of bounds"); return false; @@ -1058,10 +1065,10 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe } #endif - unsigned int height = std::max(m_impl->height >> level, 1U); + unsigned int height = GetLevelSize(m_impl->height, level); #if NAZARA_RENDERER_SAFE - if (rect.x+rect.width > std::max(m_impl->width >> level, 1U) || rect.y+rect.height > height) + if (rect.x+rect.width > GetLevelSize(m_impl->width, level) || rect.y+rect.height > height) { NazaraError("Rectangle dimensions are out of bounds"); return false; From 1c168fed21680fcb1232729afed909f23687eac3 Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 5 Jan 2015 14:31:28 +0100 Subject: [PATCH 22/64] Fixed Image::Update(UInt*, const Boxui&, ...) not working well with cubemaps Former-commit-id: 6f8c83c6a4ace3006543646df9bb2e2838c6cac0 --- src/Nazara/Utility/Image.cpp | 61 +++--------------------------------- 1 file changed, 4 insertions(+), 57 deletions(-) diff --git a/src/Nazara/Utility/Image.cpp b/src/Nazara/Utility/Image.cpp index 4f7aabc9a..70bdd5da9 100644 --- a/src/Nazara/Utility/Image.cpp +++ b/src/Nazara/Utility/Image.cpp @@ -1263,9 +1263,9 @@ void NzImage::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int src return; } - // Nous n'autorisons pas de modifier plus d'une face du cubemap à la fois (Nous prenons donc la profondeur de base) - ///FIXME: Ce code n'autorise même pas la modification d'une autre face du cubemap Oo - 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; @@ -1285,60 +1285,7 @@ void NzImage::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int src void NzImage::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level) { - ///FIXME: Cette surcharge possède-t-elle la moindre utilité ? (Update(pixels, NzBoxui(rect.x, rect.y, z, rect.width, rect.height, 1), srcWidth, ..) devrait donner le même résultat - #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) From 304b4d13cceadb51e784fb0e681f1db39b1d5d53 Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 5 Jan 2015 14:32:34 +0100 Subject: [PATCH 23/64] Removed Texture::UpdateFace Texture::Update is now able to update cubemaps faces (one at a time) Former-commit-id: 7468761d1f08fc9477af8da5a38722508c044917 --- include/Nazara/Renderer/Texture.hpp | 4 - src/Nazara/Renderer/Texture.cpp | 148 +++------------------------- 2 files changed, 16 insertions(+), 136 deletions(-) diff --git a/include/Nazara/Renderer/Texture.hpp b/include/Nazara/Renderer/Texture.hpp index 816c6b1e5..f433a8d7d 100644 --- a/include/Nazara/Renderer/Texture.hpp +++ b/include/Nazara/Renderer/Texture.hpp @@ -87,10 +87,6 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable 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; diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index e080bab0a..148d06031 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -12,8 +12,6 @@ #include #include -///TODO: Virer les méthodes faisant référence aux faces et gérer ces dernières comme de simples niveaux de profondeurs (malgré OpenGL) - struct NzTextureImpl { GLuint id; @@ -508,17 +506,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; } } @@ -531,13 +532,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; } @@ -697,7 +698,7 @@ bool NzTexture::LoadFaceFromFile(nzCubemapFace face, const NzString& filePath, c 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) @@ -736,7 +737,7 @@ bool NzTexture::LoadFaceFromMemory(nzCubemapFace face, const void* data, std::si 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) @@ -776,7 +777,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) @@ -908,12 +909,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"); @@ -930,9 +925,10 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int s unsigned int height = GetLevelSize(m_impl->height, level); #if NAZARA_RENDERER_SAFE - if (box.x+box.width > GetLevelSize(m_impl->width, level) || - box.y+box.height > height || - box.z+box.depth > GetLevelSize(m_impl->depth, level)) + 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; @@ -974,7 +970,7 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int s break; case nzImageType_Cubemap: - NazaraError("Update used on a cubemap texture, please enable safe mode"); + glTexSubImage2D(NzOpenGL::CubemapFace[box.z], level, box.x, height-box.height-box.y, box.width, box.height, format.dataFormat, format.dataType, pixels); break; } @@ -986,118 +982,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 = GetLevelSize(m_impl->height, level); - - #if NAZARA_RENDERER_SAFE - if (rect.x+rect.width > GetLevelSize(m_impl->width, level) || 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; - } - - 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); - glTexSubImage2D(NzOpenGL::CubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, pixels); - - return true; -} - unsigned int NzTexture::GetOpenGLID() const { #if NAZARA_RENDERER_SAFE From e3f7644831fb910e81c8f3925adbd513427876bf Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 5 Jan 2015 15:08:29 +0100 Subject: [PATCH 24/64] Added class AbstractImage, inherited by Image and Texture Former-commit-id: 16e5db4937a145ac244d6c70e4c74662622f86d9 --- include/Nazara/Renderer/Texture.hpp | 11 +- include/Nazara/Utility/AbstractImage.hpp | 42 ++++++++ include/Nazara/Utility/Image.hpp | 17 +--- src/Nazara/Renderer/RenderTexture.cpp | 1 + src/Nazara/Renderer/Texture.cpp | 123 ++++++++++++++++------- src/Nazara/Utility/AbstractImage.cpp | 24 +++++ src/Nazara/Utility/Image.cpp | 42 +++----- 7 files changed, 178 insertions(+), 82 deletions(-) create mode 100644 include/Nazara/Utility/AbstractImage.hpp create mode 100644 src/Nazara/Utility/AbstractImage.cpp diff --git a/include/Nazara/Renderer/Texture.hpp b/include/Nazara/Renderer/Texture.hpp index f433a8d7d..52abbe3fc 100644 --- a/include/Nazara/Renderer/Texture.hpp +++ b/include/Nazara/Renderer/Texture.hpp @@ -12,9 +12,9 @@ #include #include #include +#include #include #include -#include class NzTexture; @@ -23,7 +23,7 @@ using NzTextureRef = NzResourceRef; struct NzTextureImpl; -class NAZARA_API NzTexture : public NzResource, NzNonCopyable +class NAZARA_API NzTexture : public NzAbstractImage, public NzResource, NzNonCopyable { friend class NzRenderer; friend class NzRenderTexture; @@ -42,18 +42,19 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable void EnsureMipmapsUpdate() const; - nzUInt8 GetBytesPerPixel() 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; NzVector3ui GetSize(nzUInt8 level = 0) const; nzImageType GetType() const; unsigned int GetWidth(nzUInt8 level = 0) const; bool HasMipmaps() const; - bool IsCompressed() const; - bool IsCubemap() const; bool IsValid() const; // Load diff --git a/include/Nazara/Utility/AbstractImage.hpp b/include/Nazara/Utility/AbstractImage.hpp new file mode 100644 index 000000000..345868890 --- /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; + ~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/Image.hpp b/include/Nazara/Utility/Image.hpp index f59811d40..d94177bbe 100644 --- a/include/Nazara/Utility/Image.hpp +++ b/include/Nazara/Utility/Image.hpp @@ -13,12 +13,8 @@ #include #include #include -#include -#include -#include +#include #include -#include -#include #include ///TODO: Filtres @@ -40,7 +36,7 @@ using NzImageConstRef = NzResourceRef; using NzImageLoader = NzResourceLoader; using NzImageRef = NzResourceRef; -class NAZARA_API NzImage : public NzResource +class NAZARA_API NzImage : public NzAbstractImage, public NzResource { friend NzImageLoader; @@ -68,7 +64,6 @@ class NAZARA_API NzImage : 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; @@ -83,8 +78,6 @@ class NAZARA_API NzImage : public NzResource nzImageType GetType() const; unsigned int GetWidth(nzUInt8 level = 0) const; - bool IsCompressed() const; - bool IsCubemap() const; bool IsValid() const; // Load @@ -107,9 +100,9 @@ class NAZARA_API NzImage : 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; diff --git a/src/Nazara/Renderer/RenderTexture.cpp b/src/Nazara/Renderer/RenderTexture.cpp index 5c5ae4cdf..ee53e0ed0 100644 --- a/src/Nazara/Renderer/RenderTexture.cpp +++ b/src/Nazara/Renderer/RenderTexture.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index 148d06031..855a70e2f 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -311,19 +312,6 @@ void NzTexture::EnsureMipmapsUpdate() const } } -nzUInt8 NzTexture::GetBytesPerPixel() const -{ - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return 0; - } - #endif - - return NzPixelFormat::GetBytesPerPixel(m_impl->format); -} - unsigned int NzTexture::GetDepth(nzUInt8 level) const { #if NAZARA_RENDERER_SAFE @@ -363,6 +351,89 @@ unsigned int NzTexture::GetHeight(nzUInt8 level) const return GetLevelSize(m_impl->height, level); } +nzUInt8 NzTexture::GetLevelCount() const +{ + #if NAZARA_RENDERER_SAFE + if (!m_impl) + { + NazaraError("Texture must be valid"); + return 0; + } + #endif + + 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 @@ -415,32 +486,6 @@ bool NzTexture::HasMipmaps() const return m_impl->levelCount > 1; } -bool NzTexture::IsCompressed() const -{ - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return false; - } - #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; -} - bool NzTexture::IsValid() const { return m_impl != nullptr; 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/Image.cpp b/src/Nazara/Utility/Image.cpp index 70bdd5da9..0532294bb 100644 --- a/src/Nazara/Utility/Image.cpp +++ b/src/Nazara/Utility/Image.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -590,11 +591,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 @@ -850,16 +846,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; @@ -1199,25 +1185,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 @@ -1229,27 +1215,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 @@ -1260,7 +1248,7 @@ void NzImage::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int src if (!box.IsValid()) { NazaraError("Invalid box"); - return; + return false; } unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_sharedImage->depth, level); @@ -1268,7 +1256,7 @@ void NzImage::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int src (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 @@ -1281,9 +1269,11 @@ 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) { return Update(pixels, NzBoxui(rect.x, rect.y, z, rect.width, rect.height, 1), srcWidth, srcHeight, level); } From fc1e75d379637e801407f9f957d70e0f366ffb64 Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 5 Jan 2015 15:12:07 +0100 Subject: [PATCH 25/64] Fixed compilation error (from 683866baee26a12cf63b20914fff338cc872a4c8 [formerly a885b69881c30dcad29f87c3ffee41808761b6c9]) Former-commit-id: 8d96d5dee5666bbce41f406bcbabe269e101fafb --- src/Nazara/Graphics/Sprite.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nazara/Graphics/Sprite.cpp b/src/Nazara/Graphics/Sprite.cpp index b6dcf5ae0..3d7a6d48e 100644 --- a/src/Nazara/Graphics/Sprite.cpp +++ b/src/Nazara/Graphics/Sprite.cpp @@ -128,7 +128,7 @@ void NzSprite::SetMaterial(NzMaterial* material, bool resizeSprite) NzTexture* diffuseMap = m_material->GetDiffuseMap(); if (resizeSprite && diffuseMap && diffuseMap->IsValid()) - SetSize(NzVector2f(diffuseMap->GetSize())); + SetSize(NzVector2f(NzVector2ui(diffuseMap->GetSize()))); } void NzSprite::SetSize(const NzVector2f& size) From 5cbdd8832c86be469d13810c16f8e9f081e86c43 Mon Sep 17 00:00:00 2001 From: Lynix Date: Tue, 6 Jan 2015 13:36:58 +0100 Subject: [PATCH 26/64] Turned DataStorage enum into flags Allowing for example hybrid buffer implementation Former-commit-id: 74af1ba5b11b945abdfa6b46d0c11d600eca6d7c --- include/Nazara/Utility/Buffer.hpp | 14 +++++++------- include/Nazara/Utility/Enums.hpp | 11 ++++++----- include/Nazara/Utility/IndexBuffer.hpp | 6 +++--- include/Nazara/Utility/Mesh.hpp | 6 +++--- include/Nazara/Utility/VertexBuffer.hpp | 6 +++--- src/Nazara/Utility/Buffer.cpp | 14 +++++++------- src/Nazara/Utility/IndexBuffer.cpp | 6 +++--- src/Nazara/Utility/VertexBuffer.cpp | 6 +++--- 8 files changed, 35 insertions(+), 34 deletions(-) diff --git a/include/Nazara/Utility/Buffer.hpp b/include/Nazara/Utility/Buffer.hpp index b1b0b64b1..b7a81e094 100644 --- a/include/Nazara/Utility/Buffer.hpp +++ b/include/Nazara/Utility/Buffer.hpp @@ -28,19 +28,19 @@ class NAZARA_API NzBuffer : public NzResource, NzNonCopyable using BufferFactory = NzAbstractBuffer* (*)(NzBuffer* parent, nzBufferType type); NzBuffer(nzBufferType type); - NzBuffer(nzBufferType type, unsigned int size, nzDataStorage storage = nzDataStorage_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, nzDataStorage storage = nzDataStorage_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; - nzDataStorage GetStorage() const; + nzUInt32 GetStorage() const; nzBufferType GetType() const; nzBufferUsage GetUsage() const; @@ -50,12 +50,12 @@ class NAZARA_API NzBuffer : public NzResource, 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(nzDataStorage storage); + bool SetStorage(nzUInt32 storage); void Unmap() const; - static bool IsStorageSupported(nzDataStorage storage); - static void SetBufferFactory(nzDataStorage storage, BufferFactory func); + static bool IsStorageSupported(nzUInt32 storage); + static void SetBufferFactory(nzUInt32 storage, BufferFactory func); private: static bool Initialize(); @@ -63,7 +63,7 @@ class NAZARA_API NzBuffer : public NzResource, NzNonCopyable nzBufferType m_type; nzBufferUsage m_usage; - nzDataStorage m_storage; + nzUInt32 m_storage; NzAbstractBuffer* m_impl; unsigned int m_size; diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index 6d0ec4f2a..4c00fdad6 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -75,13 +75,14 @@ enum nzCubemapFace nzCubemapFace_Max = nzCubemapFace_NegativeZ }; -enum nzDataStorage +enum nzDataStorageFlags { - nzDataStorage_Both, - nzDataStorage_Hardware, - nzDataStorage_Software, + nzDataStorage_Hardware = 0x1, + nzDataStorage_Software = 0x2, - nzDataStorage_Max = nzDataStorage_Software + nzDataStorage_Both = nzDataStorage_Hardware | nzDataStorage_Software, + + nzDataStorage_Max = nzDataStorage_Software*2-1 }; enum nzEventType diff --git a/include/Nazara/Utility/IndexBuffer.hpp b/include/Nazara/Utility/IndexBuffer.hpp index 3f7eb59d6..cd1860199 100644 --- a/include/Nazara/Utility/IndexBuffer.hpp +++ b/include/Nazara/Utility/IndexBuffer.hpp @@ -23,7 +23,7 @@ class NAZARA_API NzIndexBuffer : public NzResource NzIndexBuffer() = default; NzIndexBuffer(bool largeIndices, NzBuffer* buffer); NzIndexBuffer(bool largeIndices, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset); - NzIndexBuffer(bool largeIndices, unsigned int length, nzDataStorage storage = nzDataStorage_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(); @@ -54,11 +54,11 @@ class NAZARA_API NzIndexBuffer : public NzResource 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, nzDataStorage storage = nzDataStorage_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(nzDataStorage storage); + bool SetStorage(nzUInt32 storage); void Unmap() const; diff --git a/include/Nazara/Utility/Mesh.hpp b/include/Nazara/Utility/Mesh.hpp index 6f4f83c61..296d72f7c 100644 --- a/include/Nazara/Utility/Mesh.hpp +++ b/include/Nazara/Utility/Mesh.hpp @@ -24,12 +24,12 @@ 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 - nzDataStorage storage = nzDataStorage_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; diff --git a/include/Nazara/Utility/VertexBuffer.hpp b/include/Nazara/Utility/VertexBuffer.hpp index 6acada650..feb09ae16 100644 --- a/include/Nazara/Utility/VertexBuffer.hpp +++ b/include/Nazara/Utility/VertexBuffer.hpp @@ -24,7 +24,7 @@ class NAZARA_API NzVertexBuffer : public NzResource 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, nzDataStorage storage = nzDataStorage_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(); @@ -50,11 +50,11 @@ class NAZARA_API NzVertexBuffer : public NzResource 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, nzDataStorage storage = nzDataStorage_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(nzDataStorage storage); + bool SetStorage(nzUInt32 storage); void SetVertexDeclaration(const NzVertexDeclaration* vertexDeclaration); void Unmap() const; diff --git a/src/Nazara/Utility/Buffer.cpp b/src/Nazara/Utility/Buffer.cpp index 71b568f5b..1a631e990 100644 --- a/src/Nazara/Utility/Buffer.cpp +++ b/src/Nazara/Utility/Buffer.cpp @@ -30,7 +30,7 @@ m_size(0) { } -NzBuffer::NzBuffer(nzBufferType type, unsigned int size, nzDataStorage storage, nzBufferUsage usage) : +NzBuffer::NzBuffer(nzBufferType type, unsigned int size, nzUInt32 storage, nzBufferUsage usage) : m_type(type), m_impl(nullptr) { @@ -63,7 +63,7 @@ bool NzBuffer::CopyContent(const NzBuffer& buffer) return Fill(mapper.GetPointer(), 0, buffer.GetSize()); } -bool NzBuffer::Create(unsigned int size, nzDataStorage storage, nzBufferUsage usage) +bool NzBuffer::Create(unsigned int size, nzUInt32 storage, nzBufferUsage usage) { Destroy(); @@ -131,7 +131,7 @@ unsigned int NzBuffer::GetSize() const return m_size; } -nzDataStorage NzBuffer::GetStorage() const +nzUInt32 NzBuffer::GetStorage() const { return m_storage; } @@ -148,7 +148,7 @@ nzBufferUsage NzBuffer::GetUsage() const bool NzBuffer::IsHardware() const { - return m_storage == nzDataStorage_Hardware; + return m_storage & nzDataStorage_Hardware; } bool NzBuffer::IsValid() const @@ -200,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(nzDataStorage storage) +bool NzBuffer::SetStorage(nzUInt32 storage) { #if NAZARA_UTILITY_SAFE if (!m_impl) @@ -275,12 +275,12 @@ void NzBuffer::Unmap() const NazaraWarning("Failed to unmap buffer (it's content may be undefined)"); ///TODO: Unexpected ? } -bool NzBuffer::IsStorageSupported(nzDataStorage storage) +bool NzBuffer::IsStorageSupported(nzUInt32 storage) { return s_bufferFactories[storage] != nullptr; } -void NzBuffer::SetBufferFactory(nzDataStorage storage, BufferFactory func) +void NzBuffer::SetBufferFactory(nzUInt32 storage, BufferFactory func) { s_bufferFactories[storage] = func; } diff --git a/src/Nazara/Utility/IndexBuffer.cpp b/src/Nazara/Utility/IndexBuffer.cpp index 65cc22757..5a4f5007a 100644 --- a/src/Nazara/Utility/IndexBuffer.cpp +++ b/src/Nazara/Utility/IndexBuffer.cpp @@ -24,7 +24,7 @@ NzIndexBuffer::NzIndexBuffer(bool largeIndices, NzBuffer* buffer, unsigned int s Reset(largeIndices, buffer, startOffset, endOffset); } -NzIndexBuffer::NzIndexBuffer(bool largeIndices, unsigned int length, nzDataStorage storage, nzBufferUsage usage) +NzIndexBuffer::NzIndexBuffer(bool largeIndices, unsigned int length, nzUInt32 storage, nzBufferUsage usage) { NzErrorFlags(nzErrorFlag_ThrowException, true); Reset(largeIndices, length, storage, usage); @@ -220,7 +220,7 @@ void NzIndexBuffer::Reset(bool largeIndices, NzBuffer* buffer, unsigned int star m_startOffset = startOffset; } -void NzIndexBuffer::Reset(bool largeIndices, unsigned int length, nzDataStorage storage, nzBufferUsage usage) +void NzIndexBuffer::Reset(bool largeIndices, unsigned int length, nzUInt32 storage, nzBufferUsage usage) { unsigned int stride = (largeIndices) ? sizeof(nzUInt32) : sizeof(nzUInt16); @@ -251,7 +251,7 @@ void NzIndexBuffer::Reset(NzIndexBuffer&& indexBuffer) noexcept m_startOffset = indexBuffer.m_startOffset; } -bool NzIndexBuffer::SetStorage(nzDataStorage storage) +bool NzIndexBuffer::SetStorage(nzUInt32 storage) { return m_buffer->SetStorage(storage); } diff --git a/src/Nazara/Utility/VertexBuffer.cpp b/src/Nazara/Utility/VertexBuffer.cpp index 31af8c2e9..12f72051f 100644 --- a/src/Nazara/Utility/VertexBuffer.cpp +++ b/src/Nazara/Utility/VertexBuffer.cpp @@ -20,7 +20,7 @@ NzVertexBuffer::NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, NzB Reset(vertexDeclaration, buffer, startOffset, endOffset); } -NzVertexBuffer::NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzDataStorage storage, nzBufferUsage usage) +NzVertexBuffer::NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzUInt32 storage, nzBufferUsage usage) { NzErrorFlags(nzErrorFlag_ThrowException, true); Reset(vertexDeclaration, length, storage, usage); @@ -230,7 +230,7 @@ void NzVertexBuffer::Reset(const NzVertexDeclaration* vertexDeclaration, NzBuffe m_vertexDeclaration = vertexDeclaration; } -void NzVertexBuffer::Reset(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzDataStorage 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; @@ -259,7 +259,7 @@ void NzVertexBuffer::Reset(NzVertexBuffer&& vertexBuffer) noexcept m_vertexDeclaration = std::move(vertexBuffer.m_vertexDeclaration); } -bool NzVertexBuffer::SetStorage(nzDataStorage storage) +bool NzVertexBuffer::SetStorage(nzUInt32 storage) { return m_buffer->SetStorage(storage); } From 72a24c4d7c4914271034b1ad23d0cfdb285c7878 Mon Sep 17 00:00:00 2001 From: Lynix Date: Tue, 6 Jan 2015 19:03:39 +0100 Subject: [PATCH 27/64] Aded Renderer::GetMaxTextureSize() + minor changes Former-commit-id: 6b80280d018c323ceb393c58aab96d68a15f3ff2 --- include/Nazara/Renderer/Renderer.hpp | 1 + src/Nazara/Renderer/Renderer.cpp | 37 ++++++++++++++++++---------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index aff9101fa..42832c661 100644 --- a/include/Nazara/Renderer/Renderer.hpp +++ b/include/Nazara/Renderer/Renderer.hpp @@ -57,6 +57,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/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index 9243f02a0..0e5b42855 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -92,6 +92,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; @@ -612,6 +613,11 @@ unsigned int NzRenderer::GetMaxRenderTargets() return s_maxRenderTarget; } +unsigned int NzRenderer::GetMaxTextureSize() +{ + return s_maxTextureSize; +} + unsigned int NzRenderer::GetMaxTextureUnits() { return s_maxTextureUnit; @@ -706,19 +712,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(); @@ -762,6 +768,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); @@ -1966,7 +1976,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 } } From 6c4f8e7396570daf565c4d3366366b0701884411 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 7 Jan 2015 19:19:53 +0100 Subject: [PATCH 28/64] Added SparsePtr::operator[+|-](unsigned int) overload Let's hope it will be enough to stop GCC from barking at me Former-commit-id: 0bcdf37acdc2e49a4ddd310dcdeb5bd6c66225a1 --- include/Nazara/Core/SparsePtr.hpp | 2 ++ include/Nazara/Core/SparsePtr.inl | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/include/Nazara/Core/SparsePtr.hpp b/include/Nazara/Core/SparsePtr.hpp index 8d104827c..b077b6d56 100644 --- a/include/Nazara/Core/SparsePtr.hpp +++ b/include/Nazara/Core/SparsePtr.hpp @@ -46,7 +46,9 @@ class NzSparsePtr 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+=(int count); diff --git a/include/Nazara/Core/SparsePtr.inl b/include/Nazara/Core/SparsePtr.inl index eb6c988ae..188996d4b 100644 --- a/include/Nazara/Core/SparsePtr.inl +++ b/include/Nazara/Core/SparsePtr.inl @@ -127,12 +127,24 @@ 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 +{ + return NzSparsePtr(m_ptr - count*m_stride, m_stride); +} + template std::ptrdiff_t NzSparsePtr::operator-(const NzSparsePtr& ptr) const { From 9293022e71fc0e622c21a0d2764ffdba21e461f7 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 7 Jan 2015 19:27:15 +0100 Subject: [PATCH 29/64] Added sprite overlay rendering Former-commit-id: 1e25a7d85f06f4a4bc3ed0ead76df01db440671d --- .../Nazara/Graphics/AbstractRenderQueue.hpp | 3 +- .../Nazara/Graphics/DeferredRenderQueue.hpp | 2 +- include/Nazara/Graphics/Enums.hpp | 7 +- .../Nazara/Graphics/ForwardRenderQueue.hpp | 5 +- .../Graphics/ForwardRenderTechnique.hpp | 18 +- include/Nazara/Renderer/Enums.hpp | 1 + src/Nazara/Graphics/DeferredRenderQueue.cpp | 4 +- src/Nazara/Graphics/ForwardRenderQueue.cpp | 55 +++++- .../Graphics/ForwardRenderTechnique.cpp | 183 ++++++++++-------- src/Nazara/Graphics/Material.cpp | 8 +- .../Resources/Shaders/Basic/core.frag | 7 +- .../Resources/Shaders/Basic/core.frag.h | 2 +- .../Resources/Shaders/PhongLighting/core.frag | 6 + .../Shaders/PhongLighting/core.frag.h | 2 +- 14 files changed, 192 insertions(+), 111 deletions(-) diff --git a/include/Nazara/Graphics/AbstractRenderQueue.hpp b/include/Nazara/Graphics/AbstractRenderQueue.hpp index 5159a8fce..d10685882 100644 --- a/include/Nazara/Graphics/AbstractRenderQueue.hpp +++ b/include/Nazara/Graphics/AbstractRenderQueue.hpp @@ -18,6 +18,7 @@ class NzDrawable; class NzLight; class NzMaterial; class NzSprite; +class NzTexture; struct NzMeshData; class NAZARA_API NzAbstractRenderQueue : NzNonCopyable @@ -29,7 +30,7 @@ class NAZARA_API NzAbstractRenderQueue : NzNonCopyable 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 AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount) = 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/DeferredRenderQueue.hpp b/include/Nazara/Graphics/DeferredRenderQueue.hpp index 8020dffd7..8ad147042 100644 --- a/include/Nazara/Graphics/DeferredRenderQueue.hpp +++ b/include/Nazara/Graphics/DeferredRenderQueue.hpp @@ -31,7 +31,7 @@ class NAZARA_API NzDeferredRenderQueue : public NzAbstractRenderQueue, NzResourc 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 AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount) override; + void AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const NzTexture* overlay = nullptr) override; void Clear(bool fully); diff --git a/include/Nazara/Graphics/Enums.hpp b/include/Nazara/Graphics/Enums.hpp index 60b05238d..4f4cb1472 100644 --- a/include/Nazara/Graphics/Enums.hpp +++ b/include/Nazara/Graphics/Enums.hpp @@ -85,9 +85,10 @@ enum nzShaderFlags { nzShaderFlags_None = 0, - nzShaderFlags_Deferred = 0x1, - nzShaderFlags_Instancing = 0x2, - nzShaderFlags_VertexColor = 0x4, + nzShaderFlags_Deferred = 0x1, + nzShaderFlags_Instancing = 0x2, + nzShaderFlags_TextureOverlay = 0x4, + nzShaderFlags_VertexColor = 0x8, nzShaderFlags_Max = nzShaderFlags_VertexColor*2-1 }; diff --git a/include/Nazara/Graphics/ForwardRenderQueue.hpp b/include/Nazara/Graphics/ForwardRenderQueue.hpp index e7c7c3087..a7571a848 100644 --- a/include/Nazara/Graphics/ForwardRenderQueue.hpp +++ b/include/Nazara/Graphics/ForwardRenderQueue.hpp @@ -33,7 +33,7 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource 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 AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount) override; + void AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const NzTexture* overlay = nullptr) override; void Clear(bool fully); @@ -74,7 +74,8 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource typedef std::map>, MeshDataComparator> MeshInstanceContainer; typedef std::map, BatchedModelMaterialComparator> ModelBatches; - typedef std::map> BasicSpriteBatches; + typedef std::map> BasicSpriteOverlayContainer; + typedef std::map BasicSpriteBatches; typedef std::vector LightContainer; typedef std::vector TransparentModelContainer; diff --git a/include/Nazara/Graphics/ForwardRenderTechnique.hpp b/include/Nazara/Graphics/ForwardRenderTechnique.hpp index 18caea522..6aa2da571 100644 --- a/include/Nazara/Graphics/ForwardRenderTechnique.hpp +++ b/include/Nazara/Graphics/ForwardRenderTechnique.hpp @@ -32,23 +32,27 @@ class NAZARA_API NzForwardRenderTechnique : public NzAbstractRenderTechnique, Nz void SetMaxLightPassPerObject(unsigned int passCount); private: - struct LightUniforms; + struct ShaderUniforms; void DrawBasicSprites(const NzScene* scene) const; void DrawOpaqueModels(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 textureOverlay; }; - mutable std::unordered_map m_lightUniforms; + mutable std::unordered_map m_shaderUniforms; mutable NzForwardRenderQueue m_renderQueue; NzIndexBufferRef m_indexBuffer; mutable NzLightManager m_directionalLights; diff --git a/include/Nazara/Renderer/Enums.hpp b/include/Nazara/Renderer/Enums.hpp index fa9fc9a3d..0065f55b2 100644 --- a/include/Nazara/Renderer/Enums.hpp +++ b/include/Nazara/Renderer/Enums.hpp @@ -187,6 +187,7 @@ enum nzSamplerWrap enum nzShaderUniform { + ///FIXME: Virer EyePosition, SceneAmbient et TargetSize de l'énumération (ils n'ont rien à faire dans le module de rendu) nzShaderUniform_EyePosition, nzShaderUniform_InvProjMatrix, nzShaderUniform_InvTargetSize, diff --git a/src/Nazara/Graphics/DeferredRenderQueue.cpp b/src/Nazara/Graphics/DeferredRenderQueue.cpp index 4c3d0cd35..821e92d86 100644 --- a/src/Nazara/Graphics/DeferredRenderQueue.cpp +++ b/src/Nazara/Graphics/DeferredRenderQueue.cpp @@ -103,7 +103,7 @@ void NzDeferredRenderQueue::AddMesh(const NzMaterial* material, const NzMeshData } } -void NzDeferredRenderQueue::AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount) +void NzDeferredRenderQueue::AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const NzTexture* overlay) { /*NzMaterial* material = sprite->GetMaterial(); if (!material->IsLightingEnabled() || material->IsEnabled(nzRendererParameter_Blend)) @@ -111,7 +111,7 @@ void NzDeferredRenderQueue::AddSprites(const NzMaterial* material, const NzVerte else sprites[material].push_back(sprite);*/ - m_forwardQueue->AddSprites(material, vertices, spriteCount); + m_forwardQueue->AddSprites(material, vertices, spriteCount, overlay); } void NzDeferredRenderQueue::Clear(bool fully) diff --git a/src/Nazara/Graphics/ForwardRenderQueue.cpp b/src/Nazara/Graphics/ForwardRenderQueue.cpp index b0d1be9d6..254194e87 100644 --- a/src/Nazara/Graphics/ForwardRenderQueue.cpp +++ b/src/Nazara/Graphics/ForwardRenderQueue.cpp @@ -20,6 +20,7 @@ namespace { ResourceType_IndexBuffer, ResourceType_Material, + ResourceType_Texture, ResourceType_VertexBuffer }; } @@ -123,16 +124,25 @@ void NzForwardRenderQueue::AddMesh(const NzMaterial* material, const NzMeshData& } } -void NzForwardRenderQueue::AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount) +void NzForwardRenderQueue::AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const NzTexture* overlay) { - BasicSpriteBatches::iterator it = basicSprites.find(material); - if (it == basicSprites.end()) + auto matIt = basicSprites.find(material); + if (matIt == basicSprites.end()) { - it = basicSprites.insert(std::make_pair(material, BasicSpriteBatches::mapped_type())).first; + matIt = basicSprites.insert(std::make_pair(material, BasicSpriteBatches::mapped_type())).first; material->AddResourceListener(this, ResourceType_Material); } - auto& spriteVector = it->second; + auto& overlayMap = matIt->second; + auto overlayIt = overlayMap.find(overlay); + if (overlayIt == overlayMap.end()) + { + overlayIt = overlayMap.insert(std::make_pair(overlay, BasicSpriteOverlayContainer::mapped_type())).first; + if (overlay) + overlay->AddResourceListener(this, ResourceType_Texture); + } + + auto& spriteVector = overlayIt->second; spriteVector.push_back(SpriteChain_XYZ_Color_UV({vertices, spriteCount})); } @@ -146,19 +156,26 @@ void NzForwardRenderQueue::Clear(bool fully) if (fully) { - for (auto& matIt : basicSprites) + for (auto& matPair : basicSprites) { - const NzMaterial* material = matIt.first; + const NzMaterial* material = matPair.first; material->RemoveResourceListener(this); + + auto& overlayMap = matPair.second; + for (auto& overlayPair : overlayMap) + { + const NzTexture* overlay = overlayPair.first; + overlay->RemoveResourceListener(this); + } } basicSprites.clear(); - for (auto& matIt : opaqueModels) + for (auto& matPair : opaqueModels) { - const NzMaterial* material = matIt.first; + const NzMaterial* material = matPair.first; material->RemoveResourceListener(this); - MeshInstanceContainer& instances = std::get<2>(matIt.second); + MeshInstanceContainer& instances = std::get<2>(matPair.second); for (auto& instanceIt : instances) { const NzMeshData& renderData = instanceIt.first; @@ -284,6 +301,24 @@ void NzForwardRenderQueue::OnResourceReleased(const NzResource* resource, int in break; } + case ResourceType_Texture: + { + for (auto matIt = basicSprites.begin(); matIt != basicSprites.end(); ++matIt) + { + auto& overlayMap = matIt->second; + for (auto overlayIt = overlayMap.begin(); overlayIt != overlayMap.end(); ++overlayIt) + { + if (overlayIt->first == resource) + { + overlayMap.erase(overlayIt); + break; + } + } + } + + break; + } + case ResourceType_VertexBuffer: { for (auto& modelPair : opaqueModels) diff --git a/src/Nazara/Graphics/ForwardRenderTechnique.cpp b/src/Nazara/Graphics/ForwardRenderTechnique.cpp index 03cac541c..6764c271a 100644 --- a/src/Nazara/Graphics/ForwardRenderTechnique.cpp +++ b/src/Nazara/Graphics/ForwardRenderTechnique.cpp @@ -166,6 +166,7 @@ void NzForwardRenderTechnique::DrawBasicSprites(const NzScene* scene) const { NzAbstractViewer* viewer = scene->GetViewer(); const NzShader* lastShader = nullptr; + const ShaderUniforms* shaderUniforms = nullptr; NzRenderer::SetIndexBuffer(m_indexBuffer); NzRenderer::SetMatrix(nzMatrixType_World, NzMatrix4f::Identity()); @@ -174,61 +175,84 @@ void NzForwardRenderTechnique::DrawBasicSprites(const NzScene* scene) const for (auto& matIt : m_renderQueue.basicSprites) { const NzMaterial* material = matIt.first; - auto& spriteChainVector = matIt.second; + auto& overlayMap = matIt.second; - unsigned int spriteChainCount = spriteChainVector.size(); - if (spriteChainCount > 0) + for (auto& overlayIt : overlayMap) { - // On commence par appliquer du matériau (et récupérer le shader ainsi activé) - const NzShader* shader = material->Apply(nzShaderFlags_VertexColor); + const NzTexture* overlay = overlayIt.first; + auto& spriteChainVector = overlayIt.second; - // Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas - if (shader != lastShader) + unsigned int spriteChainCount = spriteChainVector.size(); + if (spriteChainCount > 0) { - // 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()); + // On commence par appliquer du matériau (et récupérer le shader ainsi activé) + nzUInt32 flags = nzShaderFlags_VertexColor; + if (overlay) + flags |= nzShaderFlags_TextureOverlay; - lastShader = shader; - } + nzUInt8 overlayUnit; + const NzShader* shader = material->Apply(flags, 0, &overlayUnit); - 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; + if (overlay) { - NzForwardRenderQueue::SpriteChain_XYZ_Color_UV& currentChain = spriteChainVector[spriteChain]; - unsigned int count = std::min(s_maxSprites - 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; - } + overlayUnit++; + NzRenderer::SetTexture(overlayUnit, overlay); + NzRenderer::SetTextureSampler(overlayUnit, material->GetDiffuseSampler()); } - while (spriteCount < s_maxSprites && spriteChain < spriteChainCount); - vertexMapper.Unmap(); + // 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); - NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, spriteCount*6); + // Couleur ambiante de la scène + shader->SendColor(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor()); + // Overlay + shader->SendInteger(shaderUniforms->textureOverlay, overlayUnit); + // Position de la caméra + shader->SendVector(shader->GetUniformLocation(nzShaderUniform_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; + { + NzForwardRenderQueue::SpriteChain_XYZ_Color_UV& currentChain = spriteChainVector[spriteChain]; + unsigned int count = std::min(s_maxSprites - 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 < s_maxSprites && spriteChain < spriteChainCount); + + vertexMapper.Unmap(); + + NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, spriteCount*6); + } + while (spriteChain < spriteChainCount); + + spriteChainVector.clear(); } - while (spriteChain < spriteChainCount); - - spriteChainVector.clear(); } } } @@ -236,8 +260,8 @@ void NzForwardRenderTechnique::DrawBasicSprites(const NzScene* scene) const 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) { @@ -262,14 +286,14 @@ 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) { + // Index des uniformes dans le shader + shaderUniforms = GetShaderUniforms(shader); + // 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 d'éclairage dans le shader - lightUniforms = GetLightUniforms(shader); - lastShader = shader; } @@ -321,7 +345,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; @@ -338,10 +362,10 @@ 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]; @@ -369,7 +393,7 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const } else { - if (lightUniforms->exists) + if (shaderUniforms->hasLightUniforms) { for (const NzMatrix4f& matrix : instances) { @@ -403,14 +427,14 @@ 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); @@ -438,8 +462,8 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const } // Et on remet à zéro les données - renderQueueInstancing = false; used = false; + renderQueueInstancing = false; } } } @@ -447,8 +471,8 @@ void NzForwardRenderTechnique::DrawOpaqueModels(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) @@ -464,18 +488,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) { + // Index des uniformes dans le shader + shaderUniforms = GetShaderUniforms(shader); + // 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 d'éclairage dans le shader - lightUniforms = GetLightUniforms(shader); - // 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; } @@ -510,45 +534,46 @@ void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene) const { 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)); 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); } } -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()) + auto it = m_shaderUniforms.find(shader); + if (it != m_shaderUniforms.end()) return &(it->second); else { + ShaderUniforms uniforms; + 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); + auto pair = m_shaderUniforms.emplace(shader, uniforms); return &(pair.first->second); } } diff --git a/src/Nazara/Graphics/Material.cpp b/src/Nazara/Graphics/Material.cpp index 2774b42fa..24e26613d 100644 --- a/src/Nazara/Graphics/Material.cpp +++ b/src/Nazara/Graphics/Material.cpp @@ -687,11 +687,13 @@ 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) != 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]; @@ -759,7 +761,7 @@ bool NzMaterial::Initialize() vertexShader.Set(reinterpret_cast(compatibilityVertexShader), sizeof(compatibilityVertexShader)); } - uberShader->SetShader(nzShaderStage_Fragment, fragmentShader, "ALPHA_MAPPING ALPHA_TEST AUTO_TEXCOORDS DIFFUSE_MAPPING"); + uberShader->SetShader(nzShaderStage_Fragment, fragmentShader, "FLAG_TEXTUREOVERLAY ALPHA_MAPPING ALPHA_TEST AUTO_TEXCOORDS DIFFUSE_MAPPING"); uberShader->SetShader(nzShaderStage_Vertex, vertexShader, "FLAG_INSTANCING FLAG_VERTEXCOLOR TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH"); NzUberShaderLibrary::Register("Basic", uberShader.get()); @@ -800,7 +802,7 @@ 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_Fragment, fragmentShader, "FLAG_DEFERRED FLAG_TEXTUREOVERLAY ALPHA_MAPPING ALPHA_TEST DIFFUSE_MAPPING EMISSIVE_MAPPING LIGHTING NORMAL_MAPPING PARALLAX_MAPPING SPECULAR_MAPPING"); uberShader->SetShader(nzShaderStage_Vertex, vertexShader, "FLAG_DEFERRED FLAG_INSTANCING FLAG_VERTEXCOLOR COMPUTE_TBNMATRIX LIGHTING PARALLAX_MAPPING TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH"); NzUberShaderLibrary::Register("PhongLighting", uberShader.get()); diff --git a/src/Nazara/Graphics/Resources/Shaders/Basic/core.frag b/src/Nazara/Graphics/Resources/Shaders/Basic/core.frag index 57068325d..53844cbc6 100644 --- a/src/Nazara/Graphics/Resources/Shaders/Basic/core.frag +++ b/src/Nazara/Graphics/Resources/Shaders/Basic/core.frag @@ -10,11 +10,12 @@ in vec2 vTexCoord; 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() @@ -35,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 319917ab6..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,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,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,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,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/PhongLighting/core.frag b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag index cf0f596da..b60249edf 100644 --- a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag +++ b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag @@ -50,6 +50,8 @@ uniform float ParallaxBias = -0.03; uniform float ParallaxScale = 0.02; uniform vec4 SceneAmbient; +uniform sampler2D TextureOverlay; + /********************Fonctions********************/ vec3 FloatToColor(float f) { @@ -91,6 +93,10 @@ 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é) diff --git a/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag.h b/src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag.h index 60271acaf..bd6058130 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,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,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,32,42,32,118,67,111,108,111,114,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,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,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,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,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,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 From 904319ee90e6e562535143b648086839b7349e3e Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 7 Jan 2015 21:03:29 +0100 Subject: [PATCH 30/64] Improved/Fixed Texture class Allowed move constructor/operator Fixed Texture::Download/Texture::Update Made InvalidateMipmaps public Former-commit-id: b8b6a54bc5d6250f640fed6582dc694df6405f73 --- include/Nazara/Renderer/Texture.hpp | 7 +++- src/Nazara/Renderer/Texture.cpp | 59 +++++++++++++++-------------- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/include/Nazara/Renderer/Texture.hpp b/include/Nazara/Renderer/Texture.hpp index 52abbe3fc..5c082cc2e 100644 --- a/include/Nazara/Renderer/Texture.hpp +++ b/include/Nazara/Renderer/Texture.hpp @@ -26,11 +26,12 @@ struct NzTextureImpl; class NAZARA_API NzTexture : public NzAbstractImage, 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(NzTexture&& texture); ~NzTexture(); bool Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth = 1, nzUInt8 levelCount = 1); @@ -55,6 +56,7 @@ class NAZARA_API NzTexture : public NzAbstractImage, public NzResource, NzNonCop bool HasMipmaps() const; + void InvalidateMipmaps(); bool IsValid() const; // Load @@ -92,6 +94,8 @@ class NAZARA_API NzTexture : public NzAbstractImage, public NzResource, NzNonCop // Fonctions OpenGL unsigned int GetOpenGLID() const; + NzTexture& operator=(NzTexture&& texture); + static unsigned int GetValidSize(unsigned int size); static bool IsFormatSupported(nzPixelFormat format); static bool IsMipmappingSupported(); @@ -99,7 +103,6 @@ class NAZARA_API NzTexture : public NzAbstractImage, public NzResource, NzNonCop private: bool CreateTexture(bool proxy); - void InvalidateMipmaps(); NzTextureImpl* m_impl = nullptr; }; diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index 855a70e2f..6861a8e69 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -47,17 +48,22 @@ 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(NzTexture&& texture) : +m_impl(texture.m_impl) +{ + texture.m_impl = nullptr; } NzTexture::~NzTexture() @@ -248,30 +254,11 @@ 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"); - return true; } @@ -292,7 +279,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; @@ -1006,16 +997,16 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int s 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, pixels); + 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, pixels); + 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: - glTexSubImage2D(NzOpenGL::CubemapFace[box.z], level, box.x, height-box.height-box.y, box.width, box.height, format.dataFormat, format.dataType, pixels); + glTexSubImage2D(NzOpenGL::CubemapFace[box.z], level, box.x, box.y, box.width, box.height, format.dataFormat, format.dataType, pixels); break; } @@ -1040,6 +1031,16 @@ unsigned int NzTexture::GetOpenGLID() const return m_impl->id; } +NzTexture& NzTexture::operator=(NzTexture&& texture) +{ + Destroy(); + + m_impl = texture.m_impl; + texture.m_impl = nullptr; + + return *this; +} + unsigned int NzTexture::GetValidSize(unsigned int size) { if (NzRenderer::HasCapability(nzRendererCap_TextureNPOT)) From 586aac534bee7b5e79a7bfb05ac0c0b4b411ff2a Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 7 Jan 2015 21:03:57 +0100 Subject: [PATCH 31/64] Improved Image error on construction handling Former-commit-id: 5b40aab103d90bb29baedf65d481b2495717af8d --- src/Nazara/Utility/Image.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Nazara/Utility/Image.cpp b/src/Nazara/Utility/Image.cpp index 0532294bb..4cc9297d2 100644 --- a/src/Nazara/Utility/Image.cpp +++ b/src/Nazara/Utility/Image.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -44,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) : From 09856d42e3e8676c07501c061e235f60cdf2eb6c Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 7 Jan 2015 23:42:07 +0100 Subject: [PATCH 32/64] Fixed Texture::Download with mipmaps Former-commit-id: 1c2f6bd9fdd580e3fd5a6425bfa49251766676d2 --- src/Nazara/Renderer/Texture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index 6861a8e69..80b580312 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -257,7 +257,7 @@ bool NzTexture::Download(NzImage* image) const // 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)); + glGetTexImage(NzOpenGL::TextureTarget[m_impl->type], level, format.dataFormat, format.dataType, image->GetPixels(0, 0, 0, level)); return true; } From b61ff3a0d17e196151cb85d883a5a8738b3d9eb4 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 7 Jan 2015 23:42:45 +0100 Subject: [PATCH 33/64] (FreeType) Made Bold more strong Former-commit-id: 9bee352eb567fc51d9d34e73a16fe9340de49d82 --- src/Nazara/Utility/Loaders/FreeType/Loader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nazara/Utility/Loaders/FreeType/Loader.cpp b/src/Nazara/Utility/Loaders/FreeType/Loader.cpp index 71269d9da..46b91ffe8 100644 --- a/src/Nazara/Utility/Loaders/FreeType/Loader.cpp +++ b/src/Nazara/Utility/Loaders/FreeType/Loader.cpp @@ -95,7 +95,7 @@ namespace FT_GlyphSlot& glyph = m_face->glyph; - const FT_Pos boldStrength = 1 << 6; + const FT_Pos boldStrength = 2 << 6; bool outlineFormat = (glyph->format == FT_GLYPH_FORMAT_OUTLINE); if (outlineFormat && bold) From b6c5668232624bd1cd144ea5f5ec3ab9c9c11c0e Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 7 Jan 2015 23:46:26 +0100 Subject: [PATCH 34/64] Separated atlases from Font class First use of shared_ptr, yay! Former-commit-id: 4c22341fba5674746d5299cf0e8dbf6dc31d5362 --- .../Graphics/GuillotineTextureAtlas.hpp | 24 ++ include/Nazara/Utility/AbstractFontAtlas.hpp | 40 +++ include/Nazara/Utility/Font.hpp | 77 +++-- .../Nazara/Utility/GuillotineImageAtlas.hpp | 68 +++++ .../Graphics/GuillotineTextureAtlas.cpp | 57 ++++ src/Nazara/Utility/Font.cpp | 265 ++++-------------- src/Nazara/Utility/GuillotineImageAtlas.cpp | 244 ++++++++++++++++ 7 files changed, 522 insertions(+), 253 deletions(-) create mode 100644 include/Nazara/Graphics/GuillotineTextureAtlas.hpp create mode 100644 include/Nazara/Utility/AbstractFontAtlas.hpp create mode 100644 include/Nazara/Utility/GuillotineImageAtlas.hpp create mode 100644 src/Nazara/Graphics/GuillotineTextureAtlas.cpp create mode 100644 src/Nazara/Utility/GuillotineImageAtlas.cpp diff --git a/include/Nazara/Graphics/GuillotineTextureAtlas.hpp b/include/Nazara/Graphics/GuillotineTextureAtlas.hpp new file mode 100644 index 000000000..3eb14dd68 --- /dev/null +++ b/include/Nazara/Graphics/GuillotineTextureAtlas.hpp @@ -0,0 +1,24 @@ +// 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; + + private: + unsigned int GetMaxAtlasSize() const override; + bool ResizeImage(Layer& layer, const NzVector2ui& size) const override; +}; + +#endif // NAZARA_GUILLOTINETEXTUREATLAS_HPP diff --git a/include/Nazara/Utility/AbstractFontAtlas.hpp b/include/Nazara/Utility/AbstractFontAtlas.hpp new file mode 100644 index 000000000..f3f06346a --- /dev/null +++ b/include/Nazara/Utility/AbstractFontAtlas.hpp @@ -0,0 +1,40 @@ +// 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_ABSTRACTFONTATLAS_HPP +#define NAZARA_ABSTRACTFONTATLAS_HPP + +#include +#include +#include +#include + +class NzAbstractImage; +class NzFont; +class NzImage; + +class NAZARA_API NzAbstractFontAtlas +{ + public: + NzAbstractFontAtlas() = default; + virtual ~NzAbstractFontAtlas(); + + 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 bool Insert(const NzImage& image, NzRectui* rect, bool* flipped, unsigned int* layerIndex) = 0; + void RegisterFont(NzFont* font); + void UnregisterFont(NzFont* font); + + protected: + void NotifyCleared(); + + private: + std::set m_registredFonts; +}; + +#endif // NAZARA_ABSTRACTFONTATLAS_HPP diff --git a/include/Nazara/Utility/Font.hpp b/include/Nazara/Utility/Font.hpp index 190d3c716..2264b7604 100644 --- a/include/Nazara/Utility/Font.hpp +++ b/include/Nazara/Utility/Font.hpp @@ -8,11 +8,10 @@ #define NAZARA_FONT_HPP #include -#include #include #include #include -#include +#include #include #include @@ -24,7 +23,7 @@ struct NAZARA_API NzFontParams class NzFont; class NzFontData; -struct NzFontGlyph; // TEMP +struct NzFontGlyph; using NzFontConstRef = NzResourceRef; using NzFontLoader = NzResourceLoader; @@ -32,31 +31,12 @@ using NzFontRef = NzResourceRef; class NAZARA_API NzFont : public NzResource, NzNonCopyable { + friend NzAbstractFontAtlas; friend NzFontLoader; public: - struct Atlas - { - NzGuillotineBinPack binPack; - NzImage image; - }; - - struct Glyph - { - NzRecti aabb; - NzRectui atlasRect; - bool flipped; - bool valid; - int advance; - unsigned int atlasIndex; - }; - - struct SizeInfo - { - unsigned int lineHeight; - float underlinePosition; - float underlineThickness; - }; + struct Glyph; + struct SizeInfo; NzFont(); NzFont(NzFont&& font) = default; @@ -71,14 +51,12 @@ class NAZARA_API NzFont : public NzResource, NzNonCopyable bool ExtractGlyph(unsigned int characterSize, char32_t character, nzUInt32 style, NzFontGlyph* glyph) const; - const Atlas& GetAtlas(unsigned int atlasIndex) const; - unsigned int GetAtlasCount() const; + const NzAbstractFontAtlas* 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 GetMaxAtlasSize() const; unsigned int GetMinimumStepSize() const; const SizeInfo& GetSizeInfo(unsigned int characterSize) const; NzString GetStyleName() const; @@ -93,41 +71,50 @@ class NAZARA_API NzFont : public NzResource, NzNonCopyable bool OpenFromMemory(const void* data, std::size_t size, const NzFontParams& params = NzFontParams()); bool OpenFromStream(NzInputStream& stream, const NzFontParams& params = NzFontParams()); - void SetMaxAtlasSize(unsigned int maxAtlasSize); + void SetAtlas(std::shared_ptr atlas); void SetMinimumStepSize(unsigned int minimumSizeStep); NzFont& operator=(NzFont&& font) = default; - static unsigned int GetDefaultMaxAtlasSize(); - static void SetDefaultMaxAtlasSize(unsigned int maxAtlasSize); + enum ModicationCode + { + ModificationCode_GlyphCacheCleared, + ModificationCode_KerningCacheCleared, + ModificationCode_SizeInfoCacheCleared + }; + + struct Glyph + { + NzRecti aabb; + NzRectui atlasRect; + bool flipped; + bool valid; + int advance; + unsigned int layerIndex; + }; + + struct SizeInfo + { + unsigned int lineHeight; + float underlinePosition; + float underlineThickness; + }; private: using GlyphMap = std::unordered_map; - struct QueuedGlyph - { - char32_t codepoint; - NzImage image; - GlyphMap* map; - }; - nzUInt64 ComputeKey(unsigned int characterSize, nzUInt32 style) const; - unsigned int GetRealMaxAtlasSize() const; - unsigned int InsertRect(NzRectui* rect, bool* flipped) const; + void OnAtlasCleared(); const Glyph& PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, bool bold, char32_t character) const; - void ProcessGlyphQueue() 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; - mutable std::vector m_atlases; - mutable std::vector m_glyphQueue; - unsigned int m_maxAtlasSize; unsigned int m_minimumSizeStep; static NzFontLoader::LoaderList s_loaders; - static unsigned int s_maxAtlasSize; }; #endif // NAZARA_FONT_HPP diff --git a/include/Nazara/Utility/GuillotineImageAtlas.hpp b/include/Nazara/Utility/GuillotineImageAtlas.hpp new file mode 100644 index 000000000..dc1542560 --- /dev/null +++ b/include/Nazara/Utility/GuillotineImageAtlas.hpp @@ -0,0 +1,68 @@ +// 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 +#include + +class NAZARA_API NzGuillotineImageAtlas : public NzAbstractFontAtlas +{ + 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; + + 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 unsigned int GetMaxAtlasSize() const; + virtual bool ResizeImage(Layer& layer, const NzVector2ui& size) const; + + 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; + + std::set m_fonts; + mutable std::vector m_layers; + NzGuillotineBinPack::FreeRectChoiceHeuristic m_rectChoiceHeuristic; + NzGuillotineBinPack::GuillotineSplitHeuristic m_rectSplitHeuristic; +}; + +#endif // NAZARA_GUILLOTINEIMAGEATLAS_HPP diff --git a/src/Nazara/Graphics/GuillotineTextureAtlas.cpp b/src/Nazara/Graphics/GuillotineTextureAtlas.cpp new file mode 100644 index 000000000..7ff8bfa0c --- /dev/null +++ b/src/Nazara/Graphics/GuillotineTextureAtlas.cpp @@ -0,0 +1,57 @@ +// 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 + +bool NzGuillotineTextureAtlas::ResizeImage(Layer& layer, const NzVector2ui& size) const +{ + NzTexture newTexture; + if (newTexture.Create(nzImageType_2D, nzPixelFormat_A8, size.x, size.y, 1, 0xFF)) + { + newTexture.EnableMipmapping(true); + + if (layer.image) + { + NzTexture& texture = *static_cast(layer.image.get()); + + // Copie des anciennes données + ///TODO: Copie de texture à texture + NzImage image; + if (!texture.Download(&image)) + { + NazaraError("Failed to download old texture"); + return false; + } + + if (!newTexture.Update(image, NzRectui(0, 0, image.GetWidth(), image.GetHeight()))) + { + NazaraError("Failed to update texture"); + return false; + } + + texture = std::move(newTexture); + } + else + layer.image.reset(new NzTexture(std::move(newTexture))); + + return true; + } + else + { + NazaraError("Failed to create texture"); + return false; + } +} + +unsigned int NzGuillotineTextureAtlas::GetMaxAtlasSize() const +{ + ///FIXME: D'après la documentation OpenGL, cette valeur n'est qu'une approximation et les texture proxies sont une meilleure solution + /// Cependant le test ne se fait pas au même moment, penser à adapter le code pour gérer ce cas ? + /// (Cela permettrait au passage de gérer le cas où une image ne peut être allouée car il n'y a pas assez de mémoire contigüe pour la contenir) + + return NzRenderer::GetMaxTextureSize(); +} diff --git a/src/Nazara/Utility/Font.cpp b/src/Nazara/Utility/Font.cpp index c6a888929..e41d6b755 100644 --- a/src/Nazara/Utility/Font.cpp +++ b/src/Nazara/Utility/Font.cpp @@ -8,18 +8,12 @@ #include #include -namespace -{ - const unsigned int s_atlasStartSize = 512; -} - bool NzFontParams::IsValid() const { return true; // Rien à tester } NzFont::NzFont() : -m_maxAtlasSize(0), m_minimumSizeStep(1) { } @@ -31,25 +25,39 @@ NzFont::~NzFont() void NzFont::ClearGlyphCache() { - // Destruction des atlas et glyphes mémorisés - m_atlases.clear(); - m_glyphes.clear(); - m_glyphQueue.clear(); + if (m_atlas) + { + if (m_atlas.use_count() > 1) // Au moins une autre police utilise cet atlas, on vire nos glyphes + { + 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); + } + } - // Création du premier atlas - m_atlases.resize(1); - Atlas& atlas = m_atlases.back(); - atlas.binPack.Reset(s_atlasStartSize, s_atlasStartSize); + // Destruction des glyphes mémorisés + m_glyphes.clear(); + NotifyModified(ModificationCode_GlyphCacheCleared); + } + else + m_atlas->Clear(); + } } void NzFont::ClearKerningCache() { m_kerningCache.clear(); + NotifyModified(ModificationCode_KerningCacheCleared); } void NzFont::ClearSizeInfoCache() { m_sizeInfoCache.clear(); + NotifyModified(ModificationCode_SizeInfoCacheCleared); } bool NzFont::Create(NzFontData* data) @@ -66,18 +74,15 @@ bool NzFont::Create(NzFontData* data) m_data.reset(data); - ClearGlyphCache(); // Création du premier atlas en mémoire - return true; } void NzFont::Destroy() { - m_atlases.clear(); + ClearGlyphCache(); + m_data.reset(); m_kerningCache.clear(); - m_glyphes.clear(); - m_glyphQueue.clear(); m_sizeInfoCache.clear(); } @@ -94,17 +99,9 @@ bool NzFont::ExtractGlyph(unsigned int characterSize, char32_t character, nzUInt return m_data->ExtractGlyph(characterSize, character, style & nzTextStyle_Bold, glyph); } -const NzFont::Atlas& NzFont::GetAtlas(unsigned int atlasIndex) const +const NzAbstractFontAtlas* NzFont::GetAtlas() const { - if (!m_glyphQueue.empty()) - ProcessGlyphQueue(); - - return m_atlases.at(atlasIndex); -} - -unsigned int NzFont::GetAtlasCount() const -{ - return m_atlases.size(); + return m_atlas.get(); } unsigned int NzFont::GetCachedGlyphCount(unsigned int characterSize, nzUInt32 style) const @@ -173,11 +170,6 @@ const NzFont::Glyph& NzFont::GetGlyph(unsigned int characterSize, nzUInt32 style return PrecacheGlyph(m_glyphes[key], characterSize, style, character); } -unsigned int NzFont::GetMaxAtlasSize() const -{ - return m_maxAtlasSize; -} - unsigned int NzFont::GetMinimumStepSize() const { return m_minimumSizeStep; @@ -266,26 +258,11 @@ bool NzFont::OpenFromStream(NzInputStream& stream, const NzFontParams& params) return NzFontLoader::LoadFromStream(this, stream, params); } -void NzFont::SetMaxAtlasSize(unsigned int maxAtlasSize) +void NzFont::SetAtlas(std::shared_ptr atlas) { - unsigned int oldMaxAtlasSize = GetRealMaxAtlasSize(); - m_maxAtlasSize = maxAtlasSize; + ClearGlyphCache(); - // Si l'un de nos atlas dépasse la nouvelle taille, on doit vider le cache - maxAtlasSize = GetRealMaxAtlasSize(); - if (maxAtlasSize < oldMaxAtlasSize) - { - for (Atlas& atlas : m_atlases) - { - unsigned int atlasSize = atlas.binPack.GetWidth(); - if (atlasSize > maxAtlasSize) - { - NazaraWarning("At least one atlas was over new max atlas size (" + NzString::Number(atlasSize) + " > " + NzString::Number(maxAtlasSize) + "), clearing glyph cache..."); - ClearGlyphCache(); - return; - } - } - } + m_atlas = atlas; } void NzFont::SetMinimumStepSize(unsigned int minimumStepSize) @@ -299,16 +276,7 @@ void NzFont::SetMinimumStepSize(unsigned int minimumStepSize) #endif m_minimumSizeStep = minimumStepSize; -} - -unsigned int NzFont::GetDefaultMaxAtlasSize() -{ - return s_maxAtlasSize; -} - -void NzFont::SetDefaultMaxAtlasSize(unsigned int maxAtlasSize) -{ - s_maxAtlasSize = maxAtlasSize; + ClearGlyphCache(); } nzUInt64 NzFont::ComputeKey(unsigned int characterSize, nzUInt32 style) const @@ -326,58 +294,12 @@ nzUInt64 NzFont::ComputeKey(unsigned int characterSize, nzUInt32 style) const return (stylePart << 32) | sizePart; } -unsigned int NzFont::GetRealMaxAtlasSize() const +void NzFont::OnAtlasCleared() { - unsigned int maxAtlasSize = (m_maxAtlasSize == 0) ? s_maxAtlasSize : m_maxAtlasSize; - if (maxAtlasSize == 0) - maxAtlasSize = std::numeric_limits::max(); + // Notre atlas vient d'être vidé, détruisons le cache de glyphe + m_glyphes.clear(); - return maxAtlasSize; -} - -unsigned int NzFont::InsertRect(NzRectui* rect, bool* flipped) const -{ - ///DOC: Tous les pointeurs doivent être valides - // Précondition: Un rectangle ne peut pas être plus grand dans une dimension que la taille maximale de l'atlas - - unsigned int maxAtlasSize = GetRealMaxAtlasSize(); - - // 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_atlases.size(); ++i) - { - Atlas& atlas = m_atlases[i]; - if (atlas.binPack.Insert(rect, flipped, 1, false, NzGuillotineBinPack::RectBestAreaFit, NzGuillotineBinPack::SplitMinimizeArea)) - // Insertion réussie dans l'un des atlas, pas de question à se poser - return i; - else if (i == m_atlases.size() - 1) // Dernière itération ? - { - // Dernier atlas, et le glyphe ne rentre pas, peut-on agrandir la taille de l'atlas ? - unsigned int size = atlas.binPack.GetWidth(); // l'atlas étant carré, on ne teste qu'une dimension - if (size < maxAtlasSize) - { - // On peut encore agrandir l'atlas - size = std::min(size*2, maxAtlasSize); - atlas.binPack.Expand(size, size); - - // On relance la boucle sur le dernier atlas - i--; - } - else - { - // On ne peut plus agrandir le dernier atlas, il est temps d'en créer un nouveau - m_atlases.resize(m_atlases.size() + 1); - Atlas& newAtlas = m_atlases.back(); - - newAtlas.binPack.Reset(s_atlasStartSize, s_atlasStartSize); - - // On laisse la boucle insérer toute seule le rectangle à la prochaine itération - } - } - } - - // Si nous arrivons ici, c'est qu'une erreur a eu lieu en amont - NazaraInternalError("This shouldn't happen"); - return std::numeric_limits::max(); + NotifyModified(ModificationCode_GlyphCacheCleared); } const NzFont::Glyph& NzFont::PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, bool bold, char32_t character) const @@ -386,7 +308,7 @@ const NzFont::Glyph& NzFont::PrecacheGlyph(GlyphMap& glyphMap, unsigned int char if (it != glyphMap.end()) // Si le glyphe n'est pas déjà chargé return it->second; - Glyph glyph; + Glyph& glyph = glyphMap[character]; // Insertion du glyphe glyph.valid = false; // On extrait le glyphe depuis la police @@ -396,112 +318,39 @@ const NzFont::Glyph& NzFont::PrecacheGlyph(GlyphMap& glyphMap, unsigned int char glyph.atlasRect.width = fontGlyph.image.GetWidth(); glyph.atlasRect.height = fontGlyph.image.GetHeight(); - unsigned int maxAtlasSize = GetRealMaxAtlasSize(); - if (glyph.atlasRect.width <= maxAtlasSize && glyph.atlasRect.height <= maxAtlasSize) + // Insertion du rectangle dans l'un des atlas + if (glyph.atlasRect.width > 0 && glyph.atlasRect.height > 0) // Si l'image contient quelque chose { - // Insertion du rectangle dans l'un des atlas - glyph.aabb = fontGlyph.aabb; - glyph.advance = fontGlyph.advance; - glyph.valid = true; + // Padding (pour éviter le débordement lors du filtrage) + const unsigned int padding = 1; // Un pixel de contour - if (glyph.atlasRect.width > 0 && glyph.atlasRect.height > 0) // Si l'image contient quelque chose + glyph.atlasRect.width += padding*2; + glyph.atlasRect.height += padding*2; + + // Insertion du rectangle dans l'atlas virtuel + if (!m_atlas->Insert(fontGlyph.image, &glyph.atlasRect, &glyph.flipped, &glyph.layerIndex)) { - // Padding (pour éviter le débordement lors du filtrage) - const unsigned int padding = 1; // Un pixel entre chaque glyphe - - glyph.atlasRect.width += padding; - glyph.atlasRect.height += padding; - - // Insertion du rectangle dans l'atlas virtuel - glyph.atlasIndex = InsertRect(&glyph.atlasRect, &glyph.flipped); - - glyph.atlasRect.width -= padding; - glyph.atlasRect.height -= padding; - - // Mise en queue pour insertion dans l'atlas réel - m_glyphQueue.resize(m_glyphQueue.size()+1); - QueuedGlyph& queuedGlyph = m_glyphQueue.back(); - queuedGlyph.codepoint = character; - queuedGlyph.image = std::move(fontGlyph.image); - queuedGlyph.map = &glyphMap; + NazaraError("Failed to insert glyph into atlas"); + return glyph; } + + // Compensation du contour (centrage du glyphe) + glyph.atlasRect.x += padding; + glyph.atlasRect.y += padding; + glyph.atlasRect.width -= padding*2; + glyph.atlasRect.height -= padding*2; } - else - { - NazaraWarning("Glyph \"" + NzString::Unicode(character) + "\" is bigger than max atlas size"); - } + + glyph.aabb = fontGlyph.aabb; + glyph.advance = fontGlyph.advance; + glyph.valid = true; } else { NazaraWarning("Failed to extract glyph \"" + NzString::Unicode(character) + "\""); } - return glyphMap.insert(std::make_pair(character, std::move(glyph))).first->second; -} - -void NzFont::ProcessGlyphQueue() const -{ - for (QueuedGlyph& queuedGlyph : m_glyphQueue) - { - GlyphMap& glyphMap = *queuedGlyph.map; - auto glyphIt = glyphMap.find(queuedGlyph.codepoint); - if (glyphIt == glyphMap.end()) - continue; // Le glyphe a certainement été supprimé du cache avant la mise à jour de l'atlas - - Glyph& glyph = glyphIt->second; - Atlas& atlas = m_atlases[glyph.atlasIndex]; - - // On s'assure que l'atlas est de la bonne taille - NzVector2ui atlasSize(atlas.image.GetWidth(), atlas.image.GetHeight()); - NzVector2ui binPackSize = atlas.binPack.GetSize(); - if (atlasSize != binPackSize) - { - // Création d'une nouvelle image - NzImage newAtlas(nzImageType_2D, nzPixelFormat_A8, binPackSize.x, binPackSize.y); - if (atlas.image.IsValid()) - { - newAtlas.Copy(atlas.image, NzRectui(atlasSize), NzVector2ui(0, 0)); // On copie les anciennes données - - // On initialise les nouvelles régions - newAtlas.Fill(NzColor(255, 255, 255, 0), NzRectui(0, atlasSize.y, binPackSize.x, binPackSize.y - atlasSize.y)); - newAtlas.Fill(NzColor(255, 255, 255, 0), NzRectui(atlasSize.x, 0, binPackSize.x - atlasSize.x, atlasSize.y)); - } - else - newAtlas.Fill(NzColor(255, 255, 255, 0)); // On initialise les pixels - - atlas.image = std::move(newAtlas); // On déplace la nouvelle image vers l'atlas - } - - unsigned int glyphWidth = queuedGlyph.image.GetWidth(); - unsigned int glyphHeight = queuedGlyph.image.GetHeight(); - - // On copie le glyphe dans l'atlas - if (glyph.flipped) - { - // On tourne le glyphe pour qu'il rentre dans le rectangle - const nzUInt8* src = queuedGlyph.image.GetConstPixels(); - nzUInt8* ptr = atlas.image.GetPixels(glyph.atlasRect.x, glyph.atlasRect.y + glyphWidth - 1); - - unsigned int lineStride = atlas.image.GetWidth(); // BPP = 1 - for (unsigned int y = 0; y < glyphHeight; ++y) - { - for (unsigned int x = 0; x < glyphWidth; ++x) - { - *ptr = *src++; // On copie et on avance dans le glyphe - ptr -= lineStride; // On remonte d'une ligne - } - - ptr += lineStride*glyphWidth + 1; - } - } - else - atlas.image.Copy(queuedGlyph.image, NzRectui(glyphWidth, glyphHeight), glyph.atlasRect.GetPosition()); - - queuedGlyph.image.Destroy(); // On libère l'image dès que possible (pour réduire la consommation) - } - - m_glyphQueue.clear(); + return glyph; } NzFontLoader::LoaderList NzFont::s_loaders; -unsigned int NzFont::s_maxAtlasSize = 8192; // Valeur totalement arbitraire diff --git a/src/Nazara/Utility/GuillotineImageAtlas.cpp b/src/Nazara/Utility/GuillotineImageAtlas.cpp new file mode 100644 index 000000000..a04eed25a --- /dev/null +++ b/src/Nazara/Utility/GuillotineImageAtlas.cpp @@ -0,0 +1,244 @@ +// 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(); +} + +bool NzGuillotineImageAtlas::Insert(const NzImage& image, NzRectui* rect, bool* flipped, unsigned int* layerIndex) +{ + unsigned int maxAtlasSize = GetMaxAtlasSize(); + + if (m_layers.empty()) + { + // On créé une première couche s'il n'y en a pas + m_layers.resize(1); + Layer& layer = m_layers.back(); + layer.binPack.Reset(s_atlasStartSize, s_atlasStartSize); + } + + // 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 ? + unsigned int size = layer.binPack.GetWidth(); // l'image étant carrée, on ne teste qu'une dimension + if (size < maxAtlasSize) + { + // On peut encore agrandir la couche + size = std::min(size*2, maxAtlasSize); + layer.binPack.Expand(size, size); + + // 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 + m_layers.resize(m_layers.size() + 1); + Layer& newLayer = m_layers.back(); + + newLayer.binPack.Reset(s_atlasStartSize, s_atlasStartSize); + + // On laisse la boucle insérer toute seule le rectangle à la prochaine itération + } + } + } + + return false; // Normalement impossible +} + +void NzGuillotineImageAtlas::SetRectChoiceHeuristic(NzGuillotineBinPack::FreeRectChoiceHeuristic heuristic) +{ + m_rectChoiceHeuristic = heuristic; +} + +void NzGuillotineImageAtlas::SetRectSplitHeuristic(NzGuillotineBinPack::GuillotineSplitHeuristic heuristic) +{ + m_rectSplitHeuristic = heuristic; +} + +unsigned int NzGuillotineImageAtlas::GetMaxAtlasSize() const +{ + return 8192; // Valeur totalement arbitraire +} + +void NzGuillotineImageAtlas::ProcessGlyphQueue(Layer& layer) const +{ + std::vector pixelBuffer; + + // On s'assure que l'image est de la bonne taille + NzVector2ui binPackSize(layer.binPack.GetSize()); + NzVector2ui imageSize((layer.image) ? layer.image->GetSize() : NzVector3ui(0U)); + if (binPackSize != imageSize) + ResizeImage(layer, binPackSize); + + 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(); +} + +bool NzGuillotineImageAtlas::ResizeImage(Layer& layer, const NzVector2ui& size) const +{ + NzImage newImage(nzImageType_2D, nzPixelFormat_A8, size.x, size.y); + if (layer.image) + { + NzImage& image = *static_cast(layer.image.get()); + newImage.Copy(image, NzRectui(size), NzVector2ui(0, 0)); // Copie des anciennes données + + image = std::move(newImage); + } + else + layer.image.reset(new NzImage(std::move(newImage))); + + return true; +} From 88af94b9877f7e00870b5c09a3501537e4b58117 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 7 Jan 2015 23:47:09 +0100 Subject: [PATCH 35/64] Added ResourceConstListener I don't know yet if it's a good idea but at least it's an idea Former-commit-id: b034a787d8d8ccce0804f1276958b32c9e149147 --- include/Nazara/Core/Resource.hpp | 6 ++ include/Nazara/Core/ResourceConstListener.hpp | 26 ++++++++ src/Nazara/Core/Resource.cpp | 63 +++++++++++++++++++ src/Nazara/Core/ResourceConstListener.cpp | 39 ++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 include/Nazara/Core/ResourceConstListener.hpp create mode 100644 src/Nazara/Core/ResourceConstListener.cpp diff --git a/include/Nazara/Core/Resource.hpp b/include/Nazara/Core/Resource.hpp index adf0eace2..e82b33fad 100644 --- a/include/Nazara/Core/Resource.hpp +++ b/include/Nazara/Core/Resource.hpp @@ -17,6 +17,7 @@ #include #endif +class NzResourceConstListener; class NzResourceListener; class NAZARA_API NzResource @@ -25,6 +26,7 @@ class NAZARA_API NzResource NzResource(bool persistent = true); virtual ~NzResource(); + void AddResourceConstListener(const NzResourceConstListener* listener, int index = 0) const; void AddResourceListener(NzResourceListener* listener, int index = 0) const; void AddResourceReference() const; @@ -32,6 +34,7 @@ class NAZARA_API NzResource bool IsPersistent() const; + void RemoveResourceConstListener(const NzResourceConstListener* listener) const; void RemoveResourceListener(NzResourceListener* listener) const; bool RemoveResourceReference() const; @@ -43,13 +46,16 @@ class NAZARA_API NzResource void NotifyModified(unsigned int code); private: + using ResourceConstListenerMap = std::unordered_map>; using ResourceListenerMap = std::unordered_map>; + void RemoveResourceConstListenerIterator(ResourceConstListenerMap::iterator iterator) const; void RemoveResourceListenerIterator(ResourceListenerMap::iterator iterator) const; NazaraMutexAttrib(m_mutex, mutable) // Je fais précéder le nom par 'resource' pour éviter les éventuels conflits de noms + mutable ResourceConstListenerMap m_resourceConstListeners; mutable ResourceListenerMap m_resourceListeners; std::atomic_bool m_resourcePersistent; mutable std::atomic_uint m_resourceReferenceCount; diff --git a/include/Nazara/Core/ResourceConstListener.hpp b/include/Nazara/Core/ResourceConstListener.hpp new file mode 100644 index 000000000..7113c3c94 --- /dev/null +++ b/include/Nazara/Core/ResourceConstListener.hpp @@ -0,0 +1,26 @@ +// 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_RESOURCECONSTLISTENER_HPP +#define NAZARA_RESOURCECONSTLISTENER_HPP + +#include + +class NzResource; + +class NAZARA_API NzResourceConstListener +{ + public: + NzResourceConstListener() = default; + virtual ~NzResourceConstListener(); + + virtual bool OnResourceCreated(const NzResource* resource, int index) const; + virtual bool OnResourceDestroy(const NzResource* resource, int index) const; + virtual bool OnResourceModified(const NzResource* resource, int index, unsigned int code) const; + virtual void OnResourceReleased(const NzResource* resource, int index) const; +}; + +#endif // NAZARA_RESOURCECONSTLISTENER_HPP diff --git a/src/Nazara/Core/Resource.cpp b/src/Nazara/Core/Resource.cpp index 5610d9d13..fbdaf1853 100644 --- a/src/Nazara/Core/Resource.cpp +++ b/src/Nazara/Core/Resource.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_RESOURCE @@ -34,6 +35,19 @@ NzResource::~NzResource() #endif } +void NzResource::AddResourceConstListener(const NzResourceConstListener* listener, int index) const +{ + ///DOC: Est ignoré si appelé depuis un évènement + NazaraLock(m_mutex) + + if (!m_resourceListenersLocked) + { + auto pair = m_resourceConstListeners.insert(std::make_pair(listener, std::make_pair(index, 1U))); + if (!pair.second) + pair.first->second.second++; + } +} + void NzResource::AddResourceListener(NzResourceListener* listener, int index) const { ///DOC: Est ignoré si appelé depuis un évènement @@ -62,6 +76,19 @@ bool NzResource::IsPersistent() const return m_resourcePersistent; } +void NzResource::RemoveResourceConstListener(const NzResourceConstListener* listener) const +{ + ///DOC: Est ignoré si appelé depuis un évènement + NazaraLock(m_mutex); + + if (!m_resourceListenersLocked) + { + ResourceConstListenerMap::iterator it = m_resourceConstListeners.find(listener); + if (it != m_resourceConstListeners.end()) + RemoveResourceConstListenerIterator(it); + } +} + void NzResource::RemoveResourceListener(NzResourceListener* listener) const { ///DOC: Est ignoré si appelé depuis un évènement @@ -115,6 +142,15 @@ void NzResource::NotifyCreated() m_resourceListenersLocked = true; + auto constIt = m_resourceConstListeners.begin(); + while (constIt != m_resourceConstListeners.end()) + { + if (!constIt->first->OnResourceCreated(this, constIt->second.first)) + RemoveResourceConstListenerIterator(constIt++); + else + ++constIt; + } + auto it = m_resourceListeners.begin(); while (it != m_resourceListeners.end()) { @@ -133,6 +169,15 @@ void NzResource::NotifyDestroy() m_resourceListenersLocked = true; + auto constIt = m_resourceConstListeners.begin(); + while (constIt != m_resourceConstListeners.end()) + { + if (!constIt->first->OnResourceDestroy(this, constIt->second.first)) + RemoveResourceConstListenerIterator(constIt++); + else + ++constIt; + } + auto it = m_resourceListeners.begin(); while (it != m_resourceListeners.end()) { @@ -151,6 +196,15 @@ void NzResource::NotifyModified(unsigned int code) m_resourceListenersLocked = true; + auto constIt = m_resourceConstListeners.begin(); + while (constIt != m_resourceConstListeners.end()) + { + if (!constIt->first->OnResourceModified(this, constIt->second.first, code)) + RemoveResourceConstListenerIterator(constIt++); + else + ++constIt; + } + auto it = m_resourceListeners.begin(); while (it != m_resourceListeners.end()) { @@ -163,6 +217,15 @@ void NzResource::NotifyModified(unsigned int code) m_resourceListenersLocked = false; } +void NzResource::RemoveResourceConstListenerIterator(ResourceConstListenerMap::iterator iterator) const +{ + unsigned int& referenceCount = iterator->second.second; + if (referenceCount == 1) + m_resourceConstListeners.erase(iterator); + else + referenceCount--; +} + void NzResource::RemoveResourceListenerIterator(ResourceListenerMap::iterator iterator) const { unsigned int& referenceCount = iterator->second.second; diff --git a/src/Nazara/Core/ResourceConstListener.cpp b/src/Nazara/Core/ResourceConstListener.cpp new file mode 100644 index 000000000..ebcbdc0ec --- /dev/null +++ b/src/Nazara/Core/ResourceConstListener.cpp @@ -0,0 +1,39 @@ +// Copyright (C) 2014 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 + +NzResourceConstListener::~NzResourceConstListener() = default; + +bool NzResourceConstListener::OnResourceCreated(const NzResource* resource, int index) const +{ + NazaraUnused(resource); + NazaraUnused(index); + + return true; +} + +bool NzResourceConstListener::OnResourceDestroy(const NzResource* resource, int index) const +{ + NazaraUnused(resource); + NazaraUnused(index); + + return true; +} + +bool NzResourceConstListener::OnResourceModified(const NzResource* resource, int index, unsigned int code) const +{ + NazaraUnused(resource); + NazaraUnused(index); + NazaraUnused(code); + + return true; +} + +void NzResourceConstListener::OnResourceReleased(const NzResource* resource, int index) const +{ + NazaraUnused(resource); + NazaraUnused(index); +} From a9ef2f7e3675ea1c9fed76c2ab617ec3bcd037a8 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 8 Jan 2015 14:19:53 +0100 Subject: [PATCH 36/64] Added support for faux-bold and faux-italic Former-commit-id: 259429e8d38b0299e30d539253b50e3aab12c76b --- include/Nazara/Utility/Font.hpp | 4 +- include/Nazara/Utility/FontData.hpp | 4 +- src/Nazara/Utility/Font.cpp | 99 +++++++++++++------ .../Utility/Loaders/FreeType/Loader.cpp | 44 +++++---- 4 files changed, 100 insertions(+), 51 deletions(-) diff --git a/include/Nazara/Utility/Font.hpp b/include/Nazara/Utility/Font.hpp index 2264b7604..4ebef9d3d 100644 --- a/include/Nazara/Utility/Font.hpp +++ b/include/Nazara/Utility/Font.hpp @@ -87,6 +87,8 @@ class NAZARA_API NzFont : public NzResource, NzNonCopyable { NzRecti aabb; NzRectui atlasRect; + bool requireFauxBold; + bool requireFauxItalic; bool flipped; bool valid; int advance; @@ -105,7 +107,7 @@ class NAZARA_API NzFont : public NzResource, NzNonCopyable nzUInt64 ComputeKey(unsigned int characterSize, nzUInt32 style) const; void OnAtlasCleared(); - const Glyph& PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, bool bold, char32_t character) const; + const Glyph& PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, nzUInt32 style, char32_t character) const; std::shared_ptr m_atlas; std::unique_ptr m_data; diff --git a/include/Nazara/Utility/FontData.hpp b/include/Nazara/Utility/FontData.hpp index 9805c1d2b..171735b10 100644 --- a/include/Nazara/Utility/FontData.hpp +++ b/include/Nazara/Utility/FontData.hpp @@ -18,7 +18,7 @@ class NAZARA_API NzFontData NzFontData() = default; virtual ~NzFontData(); - virtual bool ExtractGlyph(unsigned int characterSize, char32_t character, bool bold, NzFontGlyph* dst) = 0; + virtual bool ExtractGlyph(unsigned int characterSize, char32_t character, nzUInt32 style, NzFontGlyph* dst) = 0; virtual NzString GetFamilyName() const = 0; virtual NzString GetStyleName() const = 0; @@ -31,6 +31,8 @@ class NAZARA_API NzFontData 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/src/Nazara/Utility/Font.cpp b/src/Nazara/Utility/Font.cpp index e41d6b755..65909fe05 100644 --- a/src/Nazara/Utility/Font.cpp +++ b/src/Nazara/Utility/Font.cpp @@ -96,7 +96,7 @@ bool NzFont::ExtractGlyph(unsigned int characterSize, char32_t character, nzUInt } #endif - return m_data->ExtractGlyph(characterSize, character, style & nzTextStyle_Bold, glyph); + return m_data->ExtractGlyph(characterSize, character, style, glyph); } const NzAbstractFontAtlas* NzFont::GetAtlas() const @@ -284,12 +284,11 @@ nzUInt64 NzFont::ComputeKey(unsigned int characterSize, nzUInt32 style) const nzUInt64 sizePart = static_cast((characterSize/m_minimumSizeStep)*m_minimumSizeStep); nzUInt64 stylePart = 0; - if (style & nzTextStyle_Bold) // Les caractères gras sont générés différemment + if (style & nzTextStyle_Bold) stylePart |= nzTextStyle_Bold; - // Les caractères italiques peuvent venir d'une autre police, dans le cas contraire ils sont générés au runtime - //if (style & nzTextStyle_Italic) - // stylePart |= nzTextStyle_Italic; + if (style & nzTextStyle_Italic) + stylePart |= nzTextStyle_Italic; return (stylePart << 32) | sizePart; } @@ -302,52 +301,88 @@ void NzFont::OnAtlasCleared() NotifyModified(ModificationCode_GlyphCacheCleared); } -const NzFont::Glyph& NzFont::PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, bool bold, char32_t character) const +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.requireFauxBold = false; + glyph.requireFauxItalic = false; glyph.valid = false; - // On extrait le glyphe depuis la police - NzFontGlyph fontGlyph; - if (ExtractGlyph(characterSize, character, bold, &fontGlyph)) + // On vérifie que le style demandé est supporté par la police (dans le cas contraire il devra être simulé au rendu) + nzUInt32 supportedStyle = style; + if (style & nzTextStyle_Bold && !m_data->SupportsStyle(nzTextStyle_Bold)) { - glyph.atlasRect.width = fontGlyph.image.GetWidth(); - glyph.atlasRect.height = fontGlyph.image.GetHeight(); + glyph.requireFauxBold = true; + supportedStyle &= ~nzTextStyle_Bold; + } - // Insertion du rectangle dans l'un des atlas - if (glyph.atlasRect.width > 0 && glyph.atlasRect.height > 0) // Si l'image contient quelque chose + 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)) { - // Padding (pour éviter le débordement lors du filtrage) - const unsigned int padding = 1; // Un pixel de contour + glyph.atlasRect.width = fontGlyph.image.GetWidth(); + glyph.atlasRect.height = fontGlyph.image.GetHeight(); - glyph.atlasRect.width += padding*2; - glyph.atlasRect.height += padding*2; - - // Insertion du rectangle dans l'atlas virtuel - if (!m_atlas->Insert(fontGlyph.image, &glyph.atlasRect, &glyph.flipped, &glyph.layerIndex)) + // Insertion du rectangle dans l'un des atlas + if (glyph.atlasRect.width > 0 && glyph.atlasRect.height > 0) // Si l'image contient quelque chose { - NazaraError("Failed to insert glyph into atlas"); - return glyph; + // Padding (pour éviter le débordement lors du filtrage) + const unsigned int padding = 1; // Un pixel de contour + + glyph.atlasRect.width += padding*2; + glyph.atlasRect.height += padding*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 du contour (centrage du glyphe) + glyph.atlasRect.x += padding; + glyph.atlasRect.y += padding; + glyph.atlasRect.width -= padding*2; + glyph.atlasRect.height -= padding*2; } - // Compensation du contour (centrage du glyphe) - glyph.atlasRect.x += padding; - glyph.atlasRect.y += padding; - glyph.atlasRect.width -= padding*2; - glyph.atlasRect.height -= padding*2; + glyph.aabb = fontGlyph.aabb; + glyph.advance = fontGlyph.advance; + glyph.valid = true; + } + else + { + NazaraWarning("Failed to extract glyph \"" + NzString::Unicode(character) + "\""); } - - glyph.aabb = fontGlyph.aabb; - glyph.advance = fontGlyph.advance; - glyph.valid = true; } else { - NazaraWarning("Failed to extract glyph \"" + NzString::Unicode(character) + "\""); + // 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; diff --git a/src/Nazara/Utility/Loaders/FreeType/Loader.cpp b/src/Nazara/Utility/Loaders/FreeType/Loader.cpp index 46b91ffe8..35d6f0ff3 100644 --- a/src/Nazara/Utility/Loaders/FreeType/Loader.cpp +++ b/src/Nazara/Utility/Loaders/FreeType/Loader.cpp @@ -75,7 +75,7 @@ namespace return FT_Open_Face(s_library, &m_args, -1, nullptr) == 0; } - bool ExtractGlyph(unsigned int characterSize, char32_t character, bool bold, NzFontGlyph* dst) + bool ExtractGlyph(unsigned int characterSize, char32_t character, nzUInt32 style, NzFontGlyph* dst) override { #ifdef NAZARA_DEBUG if (!dst) @@ -97,10 +97,16 @@ namespace const FT_Pos boldStrength = 2 << 6; - bool outlineFormat = (glyph->format == FT_GLYPH_FORMAT_OUTLINE); - if (outlineFormat && bold) + 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 @@ -113,18 +119,16 @@ namespace // 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 (!outlineFormat && bold) + 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; - if (bold) - dst->advance += boldStrength >> 6; - + 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; @@ -177,22 +181,22 @@ namespace return true; } - NzString GetFamilyName() const + NzString GetFamilyName() const override { return m_face->family_name; } - NzString GetStyleName() const + NzString GetStyleName() const override { return m_face->style_name; } - bool HasKerning() const + bool HasKerning() const override { return FT_HAS_KERNING(m_face); } - bool IsScalable() const + bool IsScalable() const override { return FT_IS_SCALABLE(m_face); } @@ -202,7 +206,7 @@ namespace return FT_Open_Face(s_library, &m_args, 0, &m_face) == 0; } - int QueryKerning(unsigned int characterSize, char32_t first, char32_t second) const + int QueryKerning(unsigned int characterSize, char32_t first, char32_t second) const override { if (FT_HAS_KERNING(m_face)) { @@ -220,7 +224,7 @@ namespace return 0; } - unsigned int QueryLineHeight(unsigned int characterSize) const + unsigned int QueryLineHeight(unsigned int characterSize) const override { SetCharacterSize(characterSize); @@ -228,7 +232,7 @@ namespace return m_face->size->metrics.height >> 6; } - float QueryUnderlinePosition(unsigned int characterSize) const + float QueryUnderlinePosition(unsigned int characterSize) const override { if (FT_IS_SCALABLE(m_face)) { @@ -241,7 +245,7 @@ namespace return characterSize / 10.f; // Joker ? } - float QueryUnderlineThickness(unsigned int characterSize) const + float QueryUnderlineThickness(unsigned int characterSize) const override { if (FT_IS_SCALABLE(m_face)) { @@ -280,6 +284,12 @@ namespace m_args.stream = &m_stream; } + bool SupportsStyle(nzUInt32 style) const override + { + ///TODO + return style == nzTextStyle_None || style == nzTextStyle_Bold; + } + private: void SetCharacterSize(unsigned int characterSize) const { @@ -299,7 +309,7 @@ namespace bool IsSupported(const NzString& extension) { - ///FIXME: Je suppose qu'il en manque quelques uns.. + ///FIXME: Je suppose qu'il en manque quelques unes.. static std::set supportedExtensions = { "afm", "bdf", "cff", "cid", "dfont", "fnt", "pfa", "pfb", "pfm", "pfr", "sfnt", "tte", "ttf" }; From 703ea6e9c8e14f6ec966446a02e0f38fd950f194 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 8 Jan 2015 14:20:00 +0100 Subject: [PATCH 37/64] Removed useless call Former-commit-id: 1c3d84596b5c6b61c6bb64e9067653b8d2279955 --- src/Nazara/Graphics/GuillotineTextureAtlas.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Nazara/Graphics/GuillotineTextureAtlas.cpp b/src/Nazara/Graphics/GuillotineTextureAtlas.cpp index 7ff8bfa0c..20e4c6db4 100644 --- a/src/Nazara/Graphics/GuillotineTextureAtlas.cpp +++ b/src/Nazara/Graphics/GuillotineTextureAtlas.cpp @@ -12,8 +12,6 @@ bool NzGuillotineTextureAtlas::ResizeImage(Layer& layer, const NzVector2ui& size NzTexture newTexture; if (newTexture.Create(nzImageType_2D, nzPixelFormat_A8, size.x, size.y, 1, 0xFF)) { - newTexture.EnableMipmapping(true); - if (layer.image) { NzTexture& texture = *static_cast(layer.image.get()); From 1b266e7d7cf98f368d2d6b6d4321384ccc42f471 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 8 Jan 2015 14:24:35 +0100 Subject: [PATCH 38/64] Allowed font to set glyph border Former-commit-id: f410fb83ecd0e1ace639e32fd809d00caa4145bc --- include/Nazara/Utility/Font.hpp | 3 +++ src/Nazara/Utility/Font.cpp | 30 ++++++++++++++++++++---------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/include/Nazara/Utility/Font.hpp b/include/Nazara/Utility/Font.hpp index 4ebef9d3d..c2a5f1412 100644 --- a/include/Nazara/Utility/Font.hpp +++ b/include/Nazara/Utility/Font.hpp @@ -57,6 +57,7 @@ class NAZARA_API NzFont : public NzResource, NzNonCopyable 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; @@ -72,6 +73,7 @@ class NAZARA_API NzFont : public NzResource, NzNonCopyable bool OpenFromStream(NzInputStream& stream, const NzFontParams& params = NzFontParams()); void SetAtlas(std::shared_ptr atlas); + void SetGlyphBorder(unsigned int borderSize); void SetMinimumStepSize(unsigned int minimumSizeStep); NzFont& operator=(NzFont&& font) = default; @@ -114,6 +116,7 @@ class NAZARA_API NzFont : public NzResource, NzNonCopyable 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_minimumSizeStep; static NzFontLoader::LoaderList s_loaders; diff --git a/src/Nazara/Utility/Font.cpp b/src/Nazara/Utility/Font.cpp index 65909fe05..81def3c1e 100644 --- a/src/Nazara/Utility/Font.cpp +++ b/src/Nazara/Utility/Font.cpp @@ -14,6 +14,7 @@ bool NzFontParams::IsValid() const } NzFont::NzFont() : +m_glyphBorder(1), m_minimumSizeStep(1) { } @@ -170,6 +171,11 @@ const NzFont::Glyph& NzFont::GetGlyph(unsigned int characterSize, nzUInt32 style return PrecacheGlyph(m_glyphes[key], characterSize, style, character); } +unsigned int NzFont::GetGlyphBorder() const +{ + return m_glyphBorder; +} + unsigned int NzFont::GetMinimumStepSize() const { return m_minimumSizeStep; @@ -265,6 +271,12 @@ void NzFont::SetAtlas(std::shared_ptr atlas) m_atlas = atlas; } +void NzFont::SetGlyphBorder(unsigned int borderSize) +{ + m_glyphBorder = borderSize; + ClearGlyphCache(); +} + void NzFont::SetMinimumStepSize(unsigned int minimumStepSize) { #if NAZARA_UTILITY_SAFE @@ -339,11 +351,9 @@ const NzFont::Glyph& NzFont::PrecacheGlyph(GlyphMap& glyphMap, unsigned int char // Insertion du rectangle dans l'un des atlas if (glyph.atlasRect.width > 0 && glyph.atlasRect.height > 0) // Si l'image contient quelque chose { - // Padding (pour éviter le débordement lors du filtrage) - const unsigned int padding = 1; // Un pixel de contour - - glyph.atlasRect.width += padding*2; - glyph.atlasRect.height += padding*2; + // 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)) @@ -352,11 +362,11 @@ const NzFont::Glyph& NzFont::PrecacheGlyph(GlyphMap& glyphMap, unsigned int char return glyph; } - // Compensation du contour (centrage du glyphe) - glyph.atlasRect.x += padding; - glyph.atlasRect.y += padding; - glyph.atlasRect.width -= padding*2; - glyph.atlasRect.height -= padding*2; + // 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; From 6885166dc5cce1592c65e518181fb803087f754b Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 11:15:59 +0100 Subject: [PATCH 39/64] Removed useless file Former-commit-id: a171ca369adc2e7fddf1c7b5ce8e40f4cb1fac91 --- build/codeblocks/CppCheckResults.xml | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 build/codeblocks/CppCheckResults.xml diff --git a/build/codeblocks/CppCheckResults.xml b/build/codeblocks/CppCheckResults.xml deleted file mode 100644 index 8bd3586b0..000000000 --- a/build/codeblocks/CppCheckResults.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - From e3de7e6f3cbf79b4be8a12aae1141955494f43c6 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 12:36:13 +0100 Subject: [PATCH 40/64] Added Atlas listeners Former-commit-id: a487b6ed53d9b97bfee27b28ba5523e43c1e9e7e --- include/Nazara/Utility/AbstractFontAtlas.hpp | 26 ++++++-- include/Nazara/Utility/Font.hpp | 5 +- .../Nazara/Utility/GuillotineImageAtlas.hpp | 2 - src/Nazara/Utility/AbstractFontAtlas.cpp | 63 +++++++++++++++++++ src/Nazara/Utility/Font.cpp | 52 +++++++++++++-- 5 files changed, 132 insertions(+), 16 deletions(-) create mode 100644 src/Nazara/Utility/AbstractFontAtlas.cpp diff --git a/include/Nazara/Utility/AbstractFontAtlas.hpp b/include/Nazara/Utility/AbstractFontAtlas.hpp index f3f06346a..f029731f2 100644 --- a/include/Nazara/Utility/AbstractFontAtlas.hpp +++ b/include/Nazara/Utility/AbstractFontAtlas.hpp @@ -10,31 +10,45 @@ #include #include #include -#include +#include class NzAbstractImage; -class NzFont; class NzImage; class NAZARA_API NzAbstractFontAtlas { public: - NzAbstractFontAtlas() = default; + class Listener; + + NzAbstractFontAtlas(); virtual ~NzAbstractFontAtlas(); + 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 bool Insert(const NzImage& image, NzRectui* rect, bool* flipped, unsigned int* layerIndex) = 0; - void RegisterFont(NzFont* font); - void UnregisterFont(NzFont* font); + + void RemoveListener(Listener* font) const; + + class Listener + { + public: + Listener() = default; + virtual ~Listener(); + + virtual bool OnAtlasCleared(const NzAbstractFontAtlas* atlas, void* userdata); + virtual void OnAtlasReleased(const NzAbstractFontAtlas* atlas, void* userdata); + }; protected: void NotifyCleared(); private: - std::set m_registredFonts; + mutable std::unordered_map m_listeners; + bool m_listenersLocked; }; #endif // NAZARA_ABSTRACTFONTATLAS_HPP diff --git a/include/Nazara/Utility/Font.hpp b/include/Nazara/Utility/Font.hpp index c2a5f1412..82164b09f 100644 --- a/include/Nazara/Utility/Font.hpp +++ b/include/Nazara/Utility/Font.hpp @@ -29,7 +29,7 @@ using NzFontConstRef = NzResourceRef; using NzFontLoader = NzResourceLoader; using NzFontRef = NzResourceRef; -class NAZARA_API NzFont : public NzResource, NzNonCopyable +class NAZARA_API NzFont : public NzResource, NzAbstractFontAtlas::Listener, NzNonCopyable { friend NzAbstractFontAtlas; friend NzFontLoader; @@ -108,7 +108,8 @@ class NAZARA_API NzFont : public NzResource, NzNonCopyable using GlyphMap = std::unordered_map; nzUInt64 ComputeKey(unsigned int characterSize, nzUInt32 style) const; - void OnAtlasCleared(); + bool OnAtlasCleared(const NzAbstractFontAtlas* atlas, void* userdata) override; + void OnAtlasReleased(const NzAbstractFontAtlas* atlas, void* userdata) override; const Glyph& PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, nzUInt32 style, char32_t character) const; std::shared_ptr m_atlas; diff --git a/include/Nazara/Utility/GuillotineImageAtlas.hpp b/include/Nazara/Utility/GuillotineImageAtlas.hpp index dc1542560..1bc478427 100644 --- a/include/Nazara/Utility/GuillotineImageAtlas.hpp +++ b/include/Nazara/Utility/GuillotineImageAtlas.hpp @@ -13,7 +13,6 @@ #include #include #include -#include #include class NAZARA_API NzGuillotineImageAtlas : public NzAbstractFontAtlas @@ -59,7 +58,6 @@ class NAZARA_API NzGuillotineImageAtlas : public NzAbstractFontAtlas private: void ProcessGlyphQueue(Layer& layer) const; - std::set m_fonts; mutable std::vector m_layers; NzGuillotineBinPack::FreeRectChoiceHeuristic m_rectChoiceHeuristic; NzGuillotineBinPack::GuillotineSplitHeuristic m_rectSplitHeuristic; diff --git a/src/Nazara/Utility/AbstractFontAtlas.cpp b/src/Nazara/Utility/AbstractFontAtlas.cpp new file mode 100644 index 000000000..710c52d8f --- /dev/null +++ b/src/Nazara/Utility/AbstractFontAtlas.cpp @@ -0,0 +1,63 @@ +// 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 + +NzAbstractFontAtlas::NzAbstractFontAtlas() : +m_listenersLocked(false) +{ +} + +NzAbstractFontAtlas::~NzAbstractFontAtlas() +{ + m_listenersLocked = true; + for (auto& pair : m_listeners) + pair.first->OnAtlasReleased(this, pair.second); +} + +void NzAbstractFontAtlas::AddListener(Listener* listener, void* userdata) const +{ + if (!m_listenersLocked) + m_listeners.insert(std::make_pair(listener, userdata)); +} + +void NzAbstractFontAtlas::RemoveListener(Listener* listener) const +{ + if (!m_listenersLocked) + m_listeners.erase(listener); +} + +void NzAbstractFontAtlas::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; +} + +NzAbstractFontAtlas::Listener::~Listener() = default; + +bool NzAbstractFontAtlas::Listener::OnAtlasCleared(const NzAbstractFontAtlas* atlas, void* userdata) +{ + NazaraUnused(atlas); + NazaraUnused(userdata); + + return true; +} + +void NzAbstractFontAtlas::Listener::OnAtlasReleased(const NzAbstractFontAtlas* atlas, void* userdata) +{ + NazaraUnused(atlas); + NazaraUnused(userdata); +} diff --git a/src/Nazara/Utility/Font.cpp b/src/Nazara/Utility/Font.cpp index 81def3c1e..d1e061b0b 100644 --- a/src/Nazara/Utility/Font.cpp +++ b/src/Nazara/Utility/Font.cpp @@ -28,8 +28,11 @@ void NzFont::ClearGlyphCache() { if (m_atlas) { - if (m_atlas.use_count() > 1) // Au moins une autre police utilise cet atlas, on vire nos glyphes + 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; @@ -40,12 +43,10 @@ void NzFont::ClearGlyphCache() } } - // Destruction des glyphes mémorisés + // Destruction des glyphes mémorisés et notification m_glyphes.clear(); NotifyModified(ModificationCode_GlyphCacheCleared); } - else - m_atlas->Clear(); } } @@ -268,7 +269,12 @@ void NzFont::SetAtlas(std::shared_ptr atlas) { ClearGlyphCache(); + if (m_atlas) + m_atlas->RemoveListener(this); + m_atlas = atlas; + if (m_atlas) + m_atlas->AddListener(this); } void NzFont::SetGlyphBorder(unsigned int borderSize) @@ -293,7 +299,10 @@ void NzFont::SetMinimumStepSize(unsigned int minimumStepSize) nzUInt64 NzFont::ComputeKey(unsigned int characterSize, nzUInt32 style) const { + // On prend le pas en compte nzUInt64 sizePart = static_cast((characterSize/m_minimumSizeStep)*m_minimumSizeStep); + + // 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) @@ -305,12 +314,43 @@ nzUInt64 NzFont::ComputeKey(unsigned int characterSize, nzUInt32 style) const return (stylePart << 32) | sizePart; } -void NzFont::OnAtlasCleared() +bool NzFont::OnAtlasCleared(const NzAbstractFontAtlas* atlas, void* userdata) { + NazaraUnused(atlas); + NazaraUnused(userdata); + + #ifdef NAZARA_DEBUG + // Est-ce qu'il s'agit bien de notre atlas ? + if (m_atlas != 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; +} + +void NzFont::OnAtlasReleased(const NzAbstractFontAtlas* atlas, void* userdata) +{ + NazaraUnused(atlas); + NazaraUnused(userdata); + + #ifdef NAZARA_DEBUG + // Est-ce qu'il s'agit bien de notre atlas ? + if (m_atlas != atlas) + { + NazaraInternalError("Notified by a non-listening-to resource"); + return; + } + #endif + + // Nous ne pouvons pas faire grand chose d'autre que se 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 From 1781e934624fa94e8cb2f1c457db2a92fdc63e39 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 12:40:23 +0100 Subject: [PATCH 41/64] Renamed AbstractFontAtlas to AbstractAtlas Former-commit-id: 2908a05a7d2d6d44e2e29e96c52cafe962382b71 --- ...bstractFontAtlas.hpp => AbstractAtlas.hpp} | 16 ++++++++-------- include/Nazara/Utility/Font.hpp | 15 +++++++-------- .../Nazara/Utility/GuillotineImageAtlas.hpp | 4 ++-- ...bstractFontAtlas.cpp => AbstractAtlas.cpp} | 19 +++++++++---------- src/Nazara/Utility/Font.cpp | 8 ++++---- 5 files changed, 30 insertions(+), 32 deletions(-) rename include/Nazara/Utility/{AbstractFontAtlas.hpp => AbstractAtlas.hpp} (74%) rename src/Nazara/Utility/{AbstractFontAtlas.cpp => AbstractAtlas.cpp} (58%) diff --git a/include/Nazara/Utility/AbstractFontAtlas.hpp b/include/Nazara/Utility/AbstractAtlas.hpp similarity index 74% rename from include/Nazara/Utility/AbstractFontAtlas.hpp rename to include/Nazara/Utility/AbstractAtlas.hpp index f029731f2..6cb56f41f 100644 --- a/include/Nazara/Utility/AbstractFontAtlas.hpp +++ b/include/Nazara/Utility/AbstractAtlas.hpp @@ -4,8 +4,8 @@ #pragma once -#ifndef NAZARA_ABSTRACTFONTATLAS_HPP -#define NAZARA_ABSTRACTFONTATLAS_HPP +#ifndef NAZARA_ABSTRACTATLAS_HPP +#define NAZARA_ABSTRACTATLAS_HPP #include #include @@ -15,13 +15,13 @@ class NzAbstractImage; class NzImage; -class NAZARA_API NzAbstractFontAtlas +class NAZARA_API NzAbstractAtlas { public: class Listener; - NzAbstractFontAtlas(); - virtual ~NzAbstractFontAtlas(); + NzAbstractAtlas(); + virtual ~NzAbstractAtlas(); void AddListener(Listener* font, void* userdata = nullptr) const; @@ -39,8 +39,8 @@ class NAZARA_API NzAbstractFontAtlas Listener() = default; virtual ~Listener(); - virtual bool OnAtlasCleared(const NzAbstractFontAtlas* atlas, void* userdata); - virtual void OnAtlasReleased(const NzAbstractFontAtlas* atlas, void* userdata); + virtual bool OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata); + virtual void OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata); }; protected: @@ -51,4 +51,4 @@ class NAZARA_API NzAbstractFontAtlas bool m_listenersLocked; }; -#endif // NAZARA_ABSTRACTFONTATLAS_HPP +#endif // NAZARA_ABSTRACTATLAS_HPP diff --git a/include/Nazara/Utility/Font.hpp b/include/Nazara/Utility/Font.hpp index 82164b09f..0c6080429 100644 --- a/include/Nazara/Utility/Font.hpp +++ b/include/Nazara/Utility/Font.hpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include @@ -29,9 +29,8 @@ using NzFontConstRef = NzResourceRef; using NzFontLoader = NzResourceLoader; using NzFontRef = NzResourceRef; -class NAZARA_API NzFont : public NzResource, NzAbstractFontAtlas::Listener, NzNonCopyable +class NAZARA_API NzFont : public NzResource, NzAbstractAtlas::Listener, NzNonCopyable { - friend NzAbstractFontAtlas; friend NzFontLoader; public: @@ -51,7 +50,7 @@ class NAZARA_API NzFont : public NzResource, NzAbstractFontAtlas::Listener, NzNo bool ExtractGlyph(unsigned int characterSize, char32_t character, nzUInt32 style, NzFontGlyph* glyph) const; - const NzAbstractFontAtlas* GetAtlas() const; + const NzAbstractAtlas* GetAtlas() const; unsigned int GetCachedGlyphCount(unsigned int characterSize, nzUInt32 style) const; unsigned int GetCachedGlyphCount() const; NzString GetFamilyName() const; @@ -72,7 +71,7 @@ class NAZARA_API NzFont : public NzResource, NzAbstractFontAtlas::Listener, NzNo bool OpenFromMemory(const void* data, std::size_t size, const NzFontParams& params = NzFontParams()); bool OpenFromStream(NzInputStream& stream, const NzFontParams& params = NzFontParams()); - void SetAtlas(std::shared_ptr atlas); + void SetAtlas(std::shared_ptr atlas); void SetGlyphBorder(unsigned int borderSize); void SetMinimumStepSize(unsigned int minimumSizeStep); @@ -108,11 +107,11 @@ class NAZARA_API NzFont : public NzResource, NzAbstractFontAtlas::Listener, NzNo using GlyphMap = std::unordered_map; nzUInt64 ComputeKey(unsigned int characterSize, nzUInt32 style) const; - bool OnAtlasCleared(const NzAbstractFontAtlas* atlas, void* userdata) override; - void OnAtlasReleased(const NzAbstractFontAtlas* atlas, void* userdata) override; + bool OnAtlasCleared(const NzAbstractAtlas* atlas, 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::shared_ptr m_atlas; std::unique_ptr m_data; mutable std::unordered_map> m_kerningCache; mutable std::unordered_map m_glyphes; diff --git a/include/Nazara/Utility/GuillotineImageAtlas.hpp b/include/Nazara/Utility/GuillotineImageAtlas.hpp index 1bc478427..b17e2c647 100644 --- a/include/Nazara/Utility/GuillotineImageAtlas.hpp +++ b/include/Nazara/Utility/GuillotineImageAtlas.hpp @@ -9,13 +9,13 @@ #include #include -#include +#include #include #include #include #include -class NAZARA_API NzGuillotineImageAtlas : public NzAbstractFontAtlas +class NAZARA_API NzGuillotineImageAtlas : public NzAbstractAtlas { public: NzGuillotineImageAtlas(); diff --git a/src/Nazara/Utility/AbstractFontAtlas.cpp b/src/Nazara/Utility/AbstractAtlas.cpp similarity index 58% rename from src/Nazara/Utility/AbstractFontAtlas.cpp rename to src/Nazara/Utility/AbstractAtlas.cpp index 710c52d8f..5fa7a2ca1 100644 --- a/src/Nazara/Utility/AbstractFontAtlas.cpp +++ b/src/Nazara/Utility/AbstractAtlas.cpp @@ -2,35 +2,34 @@ // 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 -NzAbstractFontAtlas::NzAbstractFontAtlas() : +NzAbstractAtlas::NzAbstractAtlas() : m_listenersLocked(false) { } -NzAbstractFontAtlas::~NzAbstractFontAtlas() +NzAbstractAtlas::~NzAbstractAtlas() { m_listenersLocked = true; for (auto& pair : m_listeners) pair.first->OnAtlasReleased(this, pair.second); } -void NzAbstractFontAtlas::AddListener(Listener* listener, void* userdata) const +void NzAbstractAtlas::AddListener(Listener* listener, void* userdata) const { if (!m_listenersLocked) m_listeners.insert(std::make_pair(listener, userdata)); } -void NzAbstractFontAtlas::RemoveListener(Listener* listener) const +void NzAbstractAtlas::RemoveListener(Listener* listener) const { if (!m_listenersLocked) m_listeners.erase(listener); } -void NzAbstractFontAtlas::NotifyCleared() +void NzAbstractAtlas::NotifyCleared() { m_listenersLocked = true; @@ -46,9 +45,9 @@ void NzAbstractFontAtlas::NotifyCleared() m_listenersLocked = false; } -NzAbstractFontAtlas::Listener::~Listener() = default; +NzAbstractAtlas::Listener::~Listener() = default; -bool NzAbstractFontAtlas::Listener::OnAtlasCleared(const NzAbstractFontAtlas* atlas, void* userdata) +bool NzAbstractAtlas::Listener::OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) { NazaraUnused(atlas); NazaraUnused(userdata); @@ -56,7 +55,7 @@ bool NzAbstractFontAtlas::Listener::OnAtlasCleared(const NzAbstractFontAtlas* at return true; } -void NzAbstractFontAtlas::Listener::OnAtlasReleased(const NzAbstractFontAtlas* atlas, void* userdata) +void NzAbstractAtlas::Listener::OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata) { NazaraUnused(atlas); NazaraUnused(userdata); diff --git a/src/Nazara/Utility/Font.cpp b/src/Nazara/Utility/Font.cpp index d1e061b0b..70122458a 100644 --- a/src/Nazara/Utility/Font.cpp +++ b/src/Nazara/Utility/Font.cpp @@ -101,7 +101,7 @@ bool NzFont::ExtractGlyph(unsigned int characterSize, char32_t character, nzUInt return m_data->ExtractGlyph(characterSize, character, style, glyph); } -const NzAbstractFontAtlas* NzFont::GetAtlas() const +const NzAbstractAtlas* NzFont::GetAtlas() const { return m_atlas.get(); } @@ -265,7 +265,7 @@ bool NzFont::OpenFromStream(NzInputStream& stream, const NzFontParams& params) return NzFontLoader::LoadFromStream(this, stream, params); } -void NzFont::SetAtlas(std::shared_ptr atlas) +void NzFont::SetAtlas(std::shared_ptr atlas) { ClearGlyphCache(); @@ -314,7 +314,7 @@ nzUInt64 NzFont::ComputeKey(unsigned int characterSize, nzUInt32 style) const return (stylePart << 32) | sizePart; } -bool NzFont::OnAtlasCleared(const NzAbstractFontAtlas* atlas, void* userdata) +bool NzFont::OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) { NazaraUnused(atlas); NazaraUnused(userdata); @@ -335,7 +335,7 @@ bool NzFont::OnAtlasCleared(const NzAbstractFontAtlas* atlas, void* userdata) return true; } -void NzFont::OnAtlasReleased(const NzAbstractFontAtlas* atlas, void* userdata) +void NzFont::OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata) { NazaraUnused(atlas); NazaraUnused(userdata); From 9d83f3f474db74cb335e5c63deb1bf771b6a19e3 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 12:42:27 +0100 Subject: [PATCH 42/64] (Font) Added spaceAdvance SizeInfo Former-commit-id: 2767915c2554103615918347c6e742cb324092c5 --- include/Nazara/Utility/Font.hpp | 1 + src/Nazara/Utility/Font.cpp | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/include/Nazara/Utility/Font.hpp b/include/Nazara/Utility/Font.hpp index 0c6080429..4605fe975 100644 --- a/include/Nazara/Utility/Font.hpp +++ b/include/Nazara/Utility/Font.hpp @@ -98,6 +98,7 @@ class NAZARA_API NzFont : public NzResource, NzAbstractAtlas::Listener, NzNonCop struct SizeInfo { + int spaceAdvance; unsigned int lineHeight; float underlinePosition; float underlineThickness; diff --git a/src/Nazara/Utility/Font.cpp b/src/Nazara/Utility/Font.cpp index 70122458a..c15756a67 100644 --- a/src/Nazara/Utility/Font.cpp +++ b/src/Nazara/Utility/Font.cpp @@ -202,6 +202,15 @@ const NzFont::SizeInfo& NzFont::GetSizeInfo(unsigned int characterSize) const sizeInfo.underlinePosition = m_data->QueryUnderlinePosition(characterSize); sizeInfo.underlineThickness = m_data->QueryUnderlineThickness(characterSize); + NzFontGlyph glyph; + if (m_data->ExtractGlyph(characterSize, ' ', nzTextStyle_None, &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; } From bdaa4f283889929667b256a2aaa14191d91d58fa Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 12:45:29 +0100 Subject: [PATCH 43/64] Renamed TextStyle_None to TextStyle_Regular Former-commit-id: 3bd44c785f8c6f011bcade1242b051d8662287d2 --- include/Nazara/Utility/Enums.hpp | 2 +- src/Nazara/Utility/Font.cpp | 2 +- src/Nazara/Utility/Loaders/FreeType/Loader.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index 4c00fdad6..d243a4864 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -230,7 +230,7 @@ enum nzTextAlign enum nzTextStyleFlags { - nzTextStyle_None = 0x0, + nzTextStyle_Regular = 0x0, nzTextStyle_Bold = 0x1, nzTextStyle_Italic = 0x2, diff --git a/src/Nazara/Utility/Font.cpp b/src/Nazara/Utility/Font.cpp index c15756a67..f73eceee9 100644 --- a/src/Nazara/Utility/Font.cpp +++ b/src/Nazara/Utility/Font.cpp @@ -203,7 +203,7 @@ const NzFont::SizeInfo& NzFont::GetSizeInfo(unsigned int characterSize) const sizeInfo.underlineThickness = m_data->QueryUnderlineThickness(characterSize); NzFontGlyph glyph; - if (m_data->ExtractGlyph(characterSize, ' ', nzTextStyle_None, &glyph)) + if (m_data->ExtractGlyph(characterSize, ' ', nzTextStyle_Regular, &glyph)) sizeInfo.spaceAdvance = glyph.advance; else { diff --git a/src/Nazara/Utility/Loaders/FreeType/Loader.cpp b/src/Nazara/Utility/Loaders/FreeType/Loader.cpp index 35d6f0ff3..92c9b0910 100644 --- a/src/Nazara/Utility/Loaders/FreeType/Loader.cpp +++ b/src/Nazara/Utility/Loaders/FreeType/Loader.cpp @@ -287,7 +287,7 @@ namespace bool SupportsStyle(nzUInt32 style) const override { ///TODO - return style == nzTextStyle_None || style == nzTextStyle_Bold; + return style == nzTextStyle_Regular || style == nzTextStyle_Bold; } private: From e85c6afa1201737dcd3d3705ef9837c3e00023db Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 12:46:07 +0100 Subject: [PATCH 44/64] Added some formats (.fon, .otf and .ttc) support to FreeType loader Former-commit-id: ff5d9f9522c920976929603f25d056ed68e6d971 --- src/Nazara/Utility/Loaders/FreeType/Loader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nazara/Utility/Loaders/FreeType/Loader.cpp b/src/Nazara/Utility/Loaders/FreeType/Loader.cpp index 92c9b0910..1bf65dcbd 100644 --- a/src/Nazara/Utility/Loaders/FreeType/Loader.cpp +++ b/src/Nazara/Utility/Loaders/FreeType/Loader.cpp @@ -311,7 +311,7 @@ namespace { ///FIXME: Je suppose qu'il en manque quelques unes.. static std::set supportedExtensions = { - "afm", "bdf", "cff", "cid", "dfont", "fnt", "pfa", "pfb", "pfm", "pfr", "sfnt", "tte", "ttf" + "afm", "bdf", "cff", "cid", "dfont", "fnt", "fon", "otf", "pfa", "pfb", "pfm", "pfr", "sfnt", "ttc", "tte", "ttf" }; return supportedExtensions.find(extension) != supportedExtensions.end(); From fbcdd6bb2bc726ffca3c2f9bff6245a5ab7e92be Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 12:46:27 +0100 Subject: [PATCH 45/64] Fixed potential crash Former-commit-id: df8cde180c157f08031cd04d37bb735aa266ee53 --- src/Nazara/Graphics/ForwardRenderQueue.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Nazara/Graphics/ForwardRenderQueue.cpp b/src/Nazara/Graphics/ForwardRenderQueue.cpp index 254194e87..c148d56f1 100644 --- a/src/Nazara/Graphics/ForwardRenderQueue.cpp +++ b/src/Nazara/Graphics/ForwardRenderQueue.cpp @@ -165,7 +165,8 @@ void NzForwardRenderQueue::Clear(bool fully) for (auto& overlayPair : overlayMap) { const NzTexture* overlay = overlayPair.first; - overlay->RemoveResourceListener(this); + if (overlay) + overlay->RemoveResourceListener(this); } } basicSprites.clear(); From 3139e80902557f24fd7e7219a8fb5e930374d636 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 12:46:42 +0100 Subject: [PATCH 46/64] Fixed do-while Former-commit-id: 08f2520ddee6e6f006f04d60df4a3da52b2ec356 --- src/Nazara/Graphics/ForwardRenderTechnique.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Nazara/Graphics/ForwardRenderTechnique.cpp b/src/Nazara/Graphics/ForwardRenderTechnique.cpp index 6764c271a..0a73e8641 100644 --- a/src/Nazara/Graphics/ForwardRenderTechnique.cpp +++ b/src/Nazara/Graphics/ForwardRenderTechnique.cpp @@ -226,6 +226,8 @@ void NzForwardRenderTechnique::DrawBasicSprites(const NzScene* scene) const NzVertexStruct_XYZ_Color_UV* vertices = reinterpret_cast(vertexMapper.GetPointer()); unsigned int spriteCount = 0; + + do { NzForwardRenderQueue::SpriteChain_XYZ_Color_UV& currentChain = spriteChainVector[spriteChain]; unsigned int count = std::min(s_maxSprites - spriteCount, currentChain.spriteCount - spriteChainOffset); From b5dbe6f03f454c35701208d4ff2c180ae953f209 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 12:52:10 +0100 Subject: [PATCH 47/64] Added XY_Color VertexLayout Former-commit-id: 0f53126584b61738b25b1d86cec819d6166ad678 --- include/Nazara/Utility/Enums.hpp | 1 + include/Nazara/Utility/VertexStruct.hpp | 5 +++++ src/Nazara/Utility/VertexDeclaration.cpp | 7 +++++++ 3 files changed, 13 insertions(+) diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index d243a4864..ac056a41b 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -274,6 +274,7 @@ enum nzVertexLayout { // Déclarations destinées au rendu nzVertexLayout_XY, + nzVertexLayout_XY_Color, nzVertexLayout_XY_UV, nzVertexLayout_XYZ, nzVertexLayout_XYZ_Color, diff --git a/include/Nazara/Utility/VertexStruct.hpp b/include/Nazara/Utility/VertexStruct.hpp index 15cb02d28..9cc365aee 100644 --- a/include/Nazara/Utility/VertexStruct.hpp +++ b/include/Nazara/Utility/VertexStruct.hpp @@ -18,6 +18,11 @@ struct NzVertexStruct_XY NzVector2f position; }; +struct NzVertexStruct_XY_Color : NzVertexStruct_XY +{ + NzColor color; +}; + struct NzVertexStruct_XY_UV : NzVertexStruct_XY { NzVector2f uv; diff --git a/src/Nazara/Utility/VertexDeclaration.cpp b/src/Nazara/Utility/VertexDeclaration.cpp index 00e9d9768..9cb0162de 100644 --- a/src/Nazara/Utility/VertexDeclaration.cpp +++ b/src/Nazara/Utility/VertexDeclaration.cpp @@ -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)); From e36e8a21e04effe20af6e644ffa2cdb1f25ed616 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 12:52:48 +0100 Subject: [PATCH 48/64] Fixed VertexLayout_XYZ_Color_UV declaration Former-commit-id: e9aa4604e88467c23dd889da943d9e00b75ae637 --- src/Nazara/Utility/VertexDeclaration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nazara/Utility/VertexDeclaration.cpp b/src/Nazara/Utility/VertexDeclaration.cpp index 9cb0162de..e65814660 100644 --- a/src/Nazara/Utility/VertexDeclaration.cpp +++ b/src/Nazara/Utility/VertexDeclaration.cpp @@ -213,7 +213,7 @@ 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_UV]; + 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)); From 40db7a729298550fa842f770014f1ddcec60537d Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 12:53:23 +0100 Subject: [PATCH 49/64] Fixed AbstractImage destructor not being virtual Former-commit-id: fd93b711d9b4ffbd370a61d1a7515da71e3d6001 --- include/Nazara/Utility/AbstractImage.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Nazara/Utility/AbstractImage.hpp b/include/Nazara/Utility/AbstractImage.hpp index 345868890..8697ea813 100644 --- a/include/Nazara/Utility/AbstractImage.hpp +++ b/include/Nazara/Utility/AbstractImage.hpp @@ -17,7 +17,7 @@ class NAZARA_API NzAbstractImage { public: NzAbstractImage() = default; - ~NzAbstractImage(); + virtual ~NzAbstractImage(); nzUInt8 GetBytesPerPixel() const; virtual unsigned int GetDepth(nzUInt8 level = 0) const = 0; From c2f3ba00f28e2e4f09bb4f3c2396e67179dbda6f Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 13:02:53 +0100 Subject: [PATCH 50/64] Revert "Added ResourceConstListener" This reverts commit 2492f87ba89bafa180308c60d2470b07e3aac27d [formerly 793b9a8884fb6153d5da152e2cf22659fc7e511b]. Former-commit-id: 05a9dff26921db1e7c1c5b90c0cd50073a839f3c --- include/Nazara/Core/Resource.hpp | 6 -- include/Nazara/Core/ResourceConstListener.hpp | 26 -------- src/Nazara/Core/Resource.cpp | 63 ------------------- src/Nazara/Core/ResourceConstListener.cpp | 39 ------------ 4 files changed, 134 deletions(-) delete mode 100644 include/Nazara/Core/ResourceConstListener.hpp delete mode 100644 src/Nazara/Core/ResourceConstListener.cpp diff --git a/include/Nazara/Core/Resource.hpp b/include/Nazara/Core/Resource.hpp index e82b33fad..adf0eace2 100644 --- a/include/Nazara/Core/Resource.hpp +++ b/include/Nazara/Core/Resource.hpp @@ -17,7 +17,6 @@ #include #endif -class NzResourceConstListener; class NzResourceListener; class NAZARA_API NzResource @@ -26,7 +25,6 @@ class NAZARA_API NzResource NzResource(bool persistent = true); virtual ~NzResource(); - void AddResourceConstListener(const NzResourceConstListener* listener, int index = 0) const; void AddResourceListener(NzResourceListener* listener, int index = 0) const; void AddResourceReference() const; @@ -34,7 +32,6 @@ class NAZARA_API NzResource bool IsPersistent() const; - void RemoveResourceConstListener(const NzResourceConstListener* listener) const; void RemoveResourceListener(NzResourceListener* listener) const; bool RemoveResourceReference() const; @@ -46,16 +43,13 @@ class NAZARA_API NzResource void NotifyModified(unsigned int code); private: - using ResourceConstListenerMap = std::unordered_map>; using ResourceListenerMap = std::unordered_map>; - void RemoveResourceConstListenerIterator(ResourceConstListenerMap::iterator iterator) const; void RemoveResourceListenerIterator(ResourceListenerMap::iterator iterator) const; NazaraMutexAttrib(m_mutex, mutable) // Je fais précéder le nom par 'resource' pour éviter les éventuels conflits de noms - mutable ResourceConstListenerMap m_resourceConstListeners; mutable ResourceListenerMap m_resourceListeners; std::atomic_bool m_resourcePersistent; mutable std::atomic_uint m_resourceReferenceCount; diff --git a/include/Nazara/Core/ResourceConstListener.hpp b/include/Nazara/Core/ResourceConstListener.hpp deleted file mode 100644 index 7113c3c94..000000000 --- a/include/Nazara/Core/ResourceConstListener.hpp +++ /dev/null @@ -1,26 +0,0 @@ -// 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_RESOURCECONSTLISTENER_HPP -#define NAZARA_RESOURCECONSTLISTENER_HPP - -#include - -class NzResource; - -class NAZARA_API NzResourceConstListener -{ - public: - NzResourceConstListener() = default; - virtual ~NzResourceConstListener(); - - virtual bool OnResourceCreated(const NzResource* resource, int index) const; - virtual bool OnResourceDestroy(const NzResource* resource, int index) const; - virtual bool OnResourceModified(const NzResource* resource, int index, unsigned int code) const; - virtual void OnResourceReleased(const NzResource* resource, int index) const; -}; - -#endif // NAZARA_RESOURCECONSTLISTENER_HPP diff --git a/src/Nazara/Core/Resource.cpp b/src/Nazara/Core/Resource.cpp index fbdaf1853..5610d9d13 100644 --- a/src/Nazara/Core/Resource.cpp +++ b/src/Nazara/Core/Resource.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_RESOURCE @@ -35,19 +34,6 @@ NzResource::~NzResource() #endif } -void NzResource::AddResourceConstListener(const NzResourceConstListener* listener, int index) const -{ - ///DOC: Est ignoré si appelé depuis un évènement - NazaraLock(m_mutex) - - if (!m_resourceListenersLocked) - { - auto pair = m_resourceConstListeners.insert(std::make_pair(listener, std::make_pair(index, 1U))); - if (!pair.second) - pair.first->second.second++; - } -} - void NzResource::AddResourceListener(NzResourceListener* listener, int index) const { ///DOC: Est ignoré si appelé depuis un évènement @@ -76,19 +62,6 @@ bool NzResource::IsPersistent() const return m_resourcePersistent; } -void NzResource::RemoveResourceConstListener(const NzResourceConstListener* listener) const -{ - ///DOC: Est ignoré si appelé depuis un évènement - NazaraLock(m_mutex); - - if (!m_resourceListenersLocked) - { - ResourceConstListenerMap::iterator it = m_resourceConstListeners.find(listener); - if (it != m_resourceConstListeners.end()) - RemoveResourceConstListenerIterator(it); - } -} - void NzResource::RemoveResourceListener(NzResourceListener* listener) const { ///DOC: Est ignoré si appelé depuis un évènement @@ -142,15 +115,6 @@ void NzResource::NotifyCreated() m_resourceListenersLocked = true; - auto constIt = m_resourceConstListeners.begin(); - while (constIt != m_resourceConstListeners.end()) - { - if (!constIt->first->OnResourceCreated(this, constIt->second.first)) - RemoveResourceConstListenerIterator(constIt++); - else - ++constIt; - } - auto it = m_resourceListeners.begin(); while (it != m_resourceListeners.end()) { @@ -169,15 +133,6 @@ void NzResource::NotifyDestroy() m_resourceListenersLocked = true; - auto constIt = m_resourceConstListeners.begin(); - while (constIt != m_resourceConstListeners.end()) - { - if (!constIt->first->OnResourceDestroy(this, constIt->second.first)) - RemoveResourceConstListenerIterator(constIt++); - else - ++constIt; - } - auto it = m_resourceListeners.begin(); while (it != m_resourceListeners.end()) { @@ -196,15 +151,6 @@ void NzResource::NotifyModified(unsigned int code) m_resourceListenersLocked = true; - auto constIt = m_resourceConstListeners.begin(); - while (constIt != m_resourceConstListeners.end()) - { - if (!constIt->first->OnResourceModified(this, constIt->second.first, code)) - RemoveResourceConstListenerIterator(constIt++); - else - ++constIt; - } - auto it = m_resourceListeners.begin(); while (it != m_resourceListeners.end()) { @@ -217,15 +163,6 @@ void NzResource::NotifyModified(unsigned int code) m_resourceListenersLocked = false; } -void NzResource::RemoveResourceConstListenerIterator(ResourceConstListenerMap::iterator iterator) const -{ - unsigned int& referenceCount = iterator->second.second; - if (referenceCount == 1) - m_resourceConstListeners.erase(iterator); - else - referenceCount--; -} - void NzResource::RemoveResourceListenerIterator(ResourceListenerMap::iterator iterator) const { unsigned int& referenceCount = iterator->second.second; diff --git a/src/Nazara/Core/ResourceConstListener.cpp b/src/Nazara/Core/ResourceConstListener.cpp deleted file mode 100644 index ebcbdc0ec..000000000 --- a/src/Nazara/Core/ResourceConstListener.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (C) 2014 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 - -NzResourceConstListener::~NzResourceConstListener() = default; - -bool NzResourceConstListener::OnResourceCreated(const NzResource* resource, int index) const -{ - NazaraUnused(resource); - NazaraUnused(index); - - return true; -} - -bool NzResourceConstListener::OnResourceDestroy(const NzResource* resource, int index) const -{ - NazaraUnused(resource); - NazaraUnused(index); - - return true; -} - -bool NzResourceConstListener::OnResourceModified(const NzResource* resource, int index, unsigned int code) const -{ - NazaraUnused(resource); - NazaraUnused(index); - NazaraUnused(code); - - return true; -} - -void NzResourceConstListener::OnResourceReleased(const NzResource* resource, int index) const -{ - NazaraUnused(resource); - NazaraUnused(index); -} From 96743375d9d4ff6181cafefd41ea449ee4fdff45 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 13:25:51 +0100 Subject: [PATCH 51/64] Fixed debug build Former-commit-id: 5a7ebd258d4b453412d0d74e7be8590905b26a78 --- src/Nazara/Utility/Font.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nazara/Utility/Font.cpp b/src/Nazara/Utility/Font.cpp index f73eceee9..495e0dc7f 100644 --- a/src/Nazara/Utility/Font.cpp +++ b/src/Nazara/Utility/Font.cpp @@ -330,7 +330,7 @@ bool NzFont::OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) #ifdef NAZARA_DEBUG // Est-ce qu'il s'agit bien de notre atlas ? - if (m_atlas != 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 @@ -351,7 +351,7 @@ void NzFont::OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata) #ifdef NAZARA_DEBUG // Est-ce qu'il s'agit bien de notre atlas ? - if (m_atlas != atlas) + if (m_atlas.get() != atlas) { NazaraInternalError("Notified by a non-listening-to resource"); return; From 5eec0d2abe4fb8ae18efa693ba938e4e8dec3a48 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 14:03:06 +0100 Subject: [PATCH 52/64] Improved (Fixed ?) Material Copy/Move Former-commit-id: 8eb9b716e2b028c6d2e249f9706ad6f5567c95dc --- include/Nazara/Graphics/Material.hpp | 1 + src/Nazara/Graphics/Material.cpp | 89 ++++++++++++++++------------ 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/include/Nazara/Graphics/Material.hpp b/include/Nazara/Graphics/Material.hpp index 0f41e0f39..a4192b0e3 100644 --- a/include/Nazara/Graphics/Material.hpp +++ b/include/Nazara/Graphics/Material.hpp @@ -140,6 +140,7 @@ class NAZARA_API NzMaterial : public NzResource }; void Copy(const NzMaterial& material); + void Move(NzMaterial&& material); void GenerateShader(nzUInt32 flags) const; void InvalidateShaders(); diff --git a/src/Nazara/Graphics/Material.cpp b/src/Nazara/Graphics/Material.cpp index 24e26613d..e674f8e96 100644 --- a/src/Nazara/Graphics/Material.cpp +++ b/src/Nazara/Graphics/Material.cpp @@ -36,16 +36,7 @@ NzResource() 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(); + Move(material); } NzMaterial::~NzMaterial() @@ -624,16 +615,7 @@ NzMaterial& NzMaterial::operator=(const NzMaterial& material) 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(); + Move(material); return *this; } @@ -645,33 +627,62 @@ 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(); - - 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(); + // Copie des états de base + m_alphaTestEnabled = material.m_alphaTestEnabled; + m_alphaThreshold = material.m_alphaThreshold; + m_ambientColor = material.m_ambientColor; + 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; + // 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_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::Move(NzMaterial&& material) +{ + // Copie des états de base + m_alphaTestEnabled = material.m_alphaTestEnabled; + m_alphaThreshold = material.m_alphaThreshold; + m_ambientColor = material.m_ambientColor; + 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; + + // Vol des références de texture + m_alphaMap = std::move(material.m_alphaMap); + m_diffuseMap = std::move(material.m_diffuseMap); + m_emissiveMap = std::move(material.m_emissiveMap); + m_heightMap = std::move(material.m_heightMap); + m_normalMap = std::move(material.m_normalMap); + m_specularMap = std::move(material.m_specularMap); + + // Vol de la référence vers l'Über-Shader + m_uberShader = std::move(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 From ff7cfa226e59f5d6989582c81c105dcaf20a26cd Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 16:26:15 +0100 Subject: [PATCH 53/64] Improved Atlas class It now handles layer resize failure and will notify listeners of a pointer change Former-commit-id: df5e2a129897128a4e41e0b3205f6a1dbeb2069c --- .../Graphics/GuillotineTextureAtlas.hpp | 3 +- include/Nazara/Utility/AbstractAtlas.hpp | 2 + .../Nazara/Utility/GuillotineImageAtlas.hpp | 4 +- .../Graphics/GuillotineTextureAtlas.cpp | 38 +++----- src/Nazara/Utility/AbstractAtlas.cpp | 27 ++++++ src/Nazara/Utility/GuillotineImageAtlas.cpp | 88 +++++++++++-------- 6 files changed, 97 insertions(+), 65 deletions(-) diff --git a/include/Nazara/Graphics/GuillotineTextureAtlas.hpp b/include/Nazara/Graphics/GuillotineTextureAtlas.hpp index 3eb14dd68..04197a41b 100644 --- a/include/Nazara/Graphics/GuillotineTextureAtlas.hpp +++ b/include/Nazara/Graphics/GuillotineTextureAtlas.hpp @@ -17,8 +17,7 @@ class NAZARA_API NzGuillotineTextureAtlas : public NzGuillotineImageAtlas ~NzGuillotineTextureAtlas() = default; private: - unsigned int GetMaxAtlasSize() const override; - bool ResizeImage(Layer& layer, const NzVector2ui& size) const override; + NzAbstractImage* ResizeImage(NzAbstractImage* oldImage, const NzVector2ui& size) const override; }; #endif // NAZARA_GUILLOTINETEXTUREATLAS_HPP diff --git a/include/Nazara/Utility/AbstractAtlas.hpp b/include/Nazara/Utility/AbstractAtlas.hpp index 6cb56f41f..2d290153b 100644 --- a/include/Nazara/Utility/AbstractAtlas.hpp +++ b/include/Nazara/Utility/AbstractAtlas.hpp @@ -40,11 +40,13 @@ class NAZARA_API NzAbstractAtlas 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; diff --git a/include/Nazara/Utility/GuillotineImageAtlas.hpp b/include/Nazara/Utility/GuillotineImageAtlas.hpp index b17e2c647..22c50fdcb 100644 --- a/include/Nazara/Utility/GuillotineImageAtlas.hpp +++ b/include/Nazara/Utility/GuillotineImageAtlas.hpp @@ -37,8 +37,8 @@ class NAZARA_API NzGuillotineImageAtlas : public NzAbstractAtlas protected: struct Layer; - virtual unsigned int GetMaxAtlasSize() const; - virtual bool ResizeImage(Layer& layer, const NzVector2ui& size) const; + virtual NzAbstractImage* ResizeImage(NzAbstractImage* oldImage, const NzVector2ui& size) const; + bool ResizeLayer(Layer& layer, const NzVector2ui& size); struct QueuedGlyph { diff --git a/src/Nazara/Graphics/GuillotineTextureAtlas.cpp b/src/Nazara/Graphics/GuillotineTextureAtlas.cpp index 20e4c6db4..0963eddf3 100644 --- a/src/Nazara/Graphics/GuillotineTextureAtlas.cpp +++ b/src/Nazara/Graphics/GuillotineTextureAtlas.cpp @@ -7,49 +7,37 @@ #include #include -bool NzGuillotineTextureAtlas::ResizeImage(Layer& layer, const NzVector2ui& size) const +NzAbstractImage* NzGuillotineTextureAtlas::ResizeImage(NzAbstractImage* oldImage, const NzVector2ui& size) const { - NzTexture newTexture; - if (newTexture.Create(nzImageType_2D, nzPixelFormat_A8, size.x, size.y, 1, 0xFF)) + std::unique_ptr newTexture(new NzTexture); + if (newTexture->Create(nzImageType_2D, nzPixelFormat_A8, size.x, size.y, 1, 0xFF)) { - if (layer.image) + if (oldImage) { - NzTexture& texture = *static_cast(layer.image.get()); + NzTexture* oldTexture = static_cast(oldImage); // Copie des anciennes données ///TODO: Copie de texture à texture NzImage image; - if (!texture.Download(&image)) + if (!oldTexture->Download(&image)) { NazaraError("Failed to download old texture"); - return false; + return nullptr; } - if (!newTexture.Update(image, NzRectui(0, 0, image.GetWidth(), image.GetHeight()))) + if (!newTexture->Update(image, NzRectui(0, 0, image.GetWidth(), image.GetHeight()))) { NazaraError("Failed to update texture"); - return false; + return nullptr; } - - texture = std::move(newTexture); } - else - layer.image.reset(new NzTexture(std::move(newTexture))); - return true; + return newTexture.release(); } else { - NazaraError("Failed to create texture"); - return false; + // 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; } } - -unsigned int NzGuillotineTextureAtlas::GetMaxAtlasSize() const -{ - ///FIXME: D'après la documentation OpenGL, cette valeur n'est qu'une approximation et les texture proxies sont une meilleure solution - /// Cependant le test ne se fait pas au même moment, penser à adapter le code pour gérer ce cas ? - /// (Cela permettrait au passage de gérer le cas où une image ne peut être allouée car il n'y a pas assez de mémoire contigüe pour la contenir) - - return NzRenderer::GetMaxTextureSize(); -} diff --git a/src/Nazara/Utility/AbstractAtlas.cpp b/src/Nazara/Utility/AbstractAtlas.cpp index 5fa7a2ca1..dac73acf7 100644 --- a/src/Nazara/Utility/AbstractAtlas.cpp +++ b/src/Nazara/Utility/AbstractAtlas.cpp @@ -45,6 +45,23 @@ void NzAbstractAtlas::NotifyCleared() 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) @@ -55,6 +72,16 @@ bool NzAbstractAtlas::Listener::OnAtlasCleared(const NzAbstractAtlas* atlas, voi 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); diff --git a/src/Nazara/Utility/GuillotineImageAtlas.cpp b/src/Nazara/Utility/GuillotineImageAtlas.cpp index a04eed25a..bd7486ab7 100644 --- a/src/Nazara/Utility/GuillotineImageAtlas.cpp +++ b/src/Nazara/Utility/GuillotineImageAtlas.cpp @@ -75,8 +75,6 @@ unsigned int NzGuillotineImageAtlas::GetLayerCount() const bool NzGuillotineImageAtlas::Insert(const NzImage& image, NzRectui* rect, bool* flipped, unsigned int* layerIndex) { - unsigned int maxAtlasSize = GetMaxAtlasSize(); - if (m_layers.empty()) { // On créé une première couche s'il n'y en a pas @@ -112,30 +110,39 @@ bool NzGuillotineImageAtlas::Insert(const NzImage& image, NzRectui* rect, bool* 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 ? - unsigned int size = layer.binPack.GetWidth(); // l'image étant carrée, on ne teste qu'une dimension - if (size < maxAtlasSize) + NzVector2ui newSize = layer.binPack.GetSize()*2; + if (ResizeLayer(layer, newSize)) { - // On peut encore agrandir la couche - size = std::min(size*2, maxAtlasSize); - layer.binPack.Expand(size, size); + // Oui on peut ! + layer.binPack.Expand(newSize); // On ajuste l'atlas virtuel - // On relance la boucle sur la nouvelle dernière couche + // 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 - m_layers.resize(m_layers.size() + 1); - Layer& newLayer = m_layers.back(); + newSize.Set(s_atlasStartSize); - newLayer.binPack.Reset(s_atlasStartSize, 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 } } } - return false; // Normalement impossible + NazaraInternalError("Unknown error"); // Normalement on ne peut pas arriver ici + return false; } void NzGuillotineImageAtlas::SetRectChoiceHeuristic(NzGuillotineBinPack::FreeRectChoiceHeuristic heuristic) @@ -148,21 +155,46 @@ void NzGuillotineImageAtlas::SetRectSplitHeuristic(NzGuillotineBinPack::Guilloti m_rectSplitHeuristic = heuristic; } -unsigned int NzGuillotineImageAtlas::GetMaxAtlasSize() const +NzAbstractImage* NzGuillotineImageAtlas::ResizeImage(NzAbstractImage* oldImage, const NzVector2ui& size) const { - return 8192; // Valeur totalement arbitraire + 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; - // On s'assure que l'image est de la bonne taille - NzVector2ui binPackSize(layer.binPack.GetSize()); - NzVector2ui imageSize((layer.image) ? layer.image->GetSize() : NzVector3ui(0U)); - if (binPackSize != imageSize) - ResizeImage(layer, binPackSize); - for (QueuedGlyph& glyph : layer.queuedGlyphs) { unsigned int glyphWidth = glyph.image.GetWidth(); @@ -226,19 +258,3 @@ void NzGuillotineImageAtlas::ProcessGlyphQueue(Layer& layer) const layer.queuedGlyphs.clear(); } - -bool NzGuillotineImageAtlas::ResizeImage(Layer& layer, const NzVector2ui& size) const -{ - NzImage newImage(nzImageType_2D, nzPixelFormat_A8, size.x, size.y); - if (layer.image) - { - NzImage& image = *static_cast(layer.image.get()); - newImage.Copy(image, NzRectui(size), NzVector2ui(0, 0)); // Copie des anciennes données - - image = std::move(newImage); - } - else - layer.image.reset(new NzImage(std::move(newImage))); - - return true; -} From cd5399459d3e3ea22a09a55ee0f170e633bfb2af Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 16:28:38 +0100 Subject: [PATCH 54/64] Made Resource copying/moving impossible It is still possible to copy some Resource-based classes though Former-commit-id: bbb6066f736c210015ff9fdfded7d95eb9695359 --- include/Nazara/Core/Resource.hpp | 5 ++++ include/Nazara/Graphics/Material.hpp | 2 -- include/Nazara/Renderer/Texture.hpp | 3 -- include/Nazara/Utility/Image.hpp | 2 -- src/Nazara/Graphics/Material.cpp | 42 ---------------------------- src/Nazara/Renderer/Texture.cpp | 42 +++++++++------------------- src/Nazara/Utility/Image.cpp | 13 --------- 7 files changed, 18 insertions(+), 91 deletions(-) diff --git a/include/Nazara/Core/Resource.hpp b/include/Nazara/Core/Resource.hpp index adf0eace2..2bc392734 100644 --- a/include/Nazara/Core/Resource.hpp +++ b/include/Nazara/Core/Resource.hpp @@ -23,6 +23,8 @@ class NAZARA_API NzResource { public: NzResource(bool persistent = true); + NzResource(const NzResource& resource) = delete; + NzResource(NzResource&& resource) = delete; virtual ~NzResource(); void AddResourceListener(NzResourceListener* listener, int index = 0) const; @@ -37,6 +39,9 @@ class NAZARA_API NzResource bool SetPersistent(bool persistent = true, bool checkReferenceCount = false); + NzResource& operator=(const NzResource& resource) = delete; + NzResource& operator=(NzResource&& resource) = delete; + protected: void NotifyCreated(); void NotifyDestroy(); diff --git a/include/Nazara/Graphics/Material.hpp b/include/Nazara/Graphics/Material.hpp index a4192b0e3..ffe7f8217 100644 --- a/include/Nazara/Graphics/Material.hpp +++ b/include/Nazara/Graphics/Material.hpp @@ -46,7 +46,6 @@ class NAZARA_API NzMaterial : 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; @@ -127,7 +126,6 @@ class NAZARA_API NzMaterial : public NzResource void SetSrcBlend(nzBlendFunc func); NzMaterial& operator=(const NzMaterial& material); - NzMaterial& operator=(NzMaterial&& material); static NzMaterial* GetDefault(); diff --git a/include/Nazara/Renderer/Texture.hpp b/include/Nazara/Renderer/Texture.hpp index 5c082cc2e..02a1a208f 100644 --- a/include/Nazara/Renderer/Texture.hpp +++ b/include/Nazara/Renderer/Texture.hpp @@ -31,7 +31,6 @@ class NAZARA_API NzTexture : public NzAbstractImage, public NzResource, NzNonCop 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(NzTexture&& texture); ~NzTexture(); bool Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth = 1, nzUInt8 levelCount = 1); @@ -94,8 +93,6 @@ class NAZARA_API NzTexture : public NzAbstractImage, public NzResource, NzNonCop // Fonctions OpenGL unsigned int GetOpenGLID() const; - NzTexture& operator=(NzTexture&& texture); - static unsigned int GetValidSize(unsigned int size); static bool IsFormatSupported(nzPixelFormat format); static bool IsMipmappingSupported(); diff --git a/include/Nazara/Utility/Image.hpp b/include/Nazara/Utility/Image.hpp index d94177bbe..57c188822 100644 --- a/include/Nazara/Utility/Image.hpp +++ b/include/Nazara/Utility/Image.hpp @@ -46,7 +46,6 @@ class NAZARA_API NzImage : public NzAbstractImage, 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(); @@ -105,7 +104,6 @@ class NAZARA_API NzImage : public NzAbstractImage, public NzResource 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); diff --git a/src/Nazara/Graphics/Material.cpp b/src/Nazara/Graphics/Material.cpp index e674f8e96..8a6ca4357 100644 --- a/src/Nazara/Graphics/Material.cpp +++ b/src/Nazara/Graphics/Material.cpp @@ -34,11 +34,6 @@ NzResource() Copy(material); } -NzMaterial::NzMaterial(NzMaterial&& material) -{ - Move(material); -} - NzMaterial::~NzMaterial() { NotifyDestroy(); @@ -613,13 +608,6 @@ NzMaterial& NzMaterial::operator=(const NzMaterial& material) return *this; } -NzMaterial& NzMaterial::operator=(NzMaterial&& material) -{ - Move(material); - - return *this; -} - NzMaterial* NzMaterial::GetDefault() { return s_defaultMaterial; @@ -655,36 +643,6 @@ void NzMaterial::Copy(const NzMaterial& material) std::memcpy(&m_shaders[0], &material.m_shaders[0], (nzShaderFlags_Max+1)*sizeof(ShaderInstance)); } -void NzMaterial::Move(NzMaterial&& material) -{ - // Copie des états de base - m_alphaTestEnabled = material.m_alphaTestEnabled; - m_alphaThreshold = material.m_alphaThreshold; - m_ambientColor = material.m_ambientColor; - 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; - - // Vol des références de texture - m_alphaMap = std::move(material.m_alphaMap); - m_diffuseMap = std::move(material.m_diffuseMap); - m_emissiveMap = std::move(material.m_emissiveMap); - m_heightMap = std::move(material.m_heightMap); - m_normalMap = std::move(material.m_normalMap); - m_specularMap = std::move(material.m_specularMap); - - // Vol de la référence vers l'Über-Shader - m_uberShader = std::move(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 { NzParameterList list; diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index 80b580312..bee9c9ae8 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -60,12 +60,6 @@ NzTexture::NzTexture(const NzImage& image) LoadFromImage(image); } -NzTexture::NzTexture(NzTexture&& texture) : -m_impl(texture.m_impl) -{ - texture.m_impl = nullptr; -} - NzTexture::~NzTexture() { Destroy(); @@ -477,6 +471,19 @@ bool NzTexture::HasMipmaps() const return m_impl->levelCount > 1; } +void NzTexture::InvalidateMipmaps() +{ + #if NAZARA_RENDERER_SAFE + if (!m_impl) + { + NazaraInternalError("Texture must be valid"); + return; + } + #endif + + m_impl->mipmapsUpdated = false; +} + bool NzTexture::IsValid() const { return m_impl != nullptr; @@ -1031,16 +1038,6 @@ unsigned int NzTexture::GetOpenGLID() const return m_impl->id; } -NzTexture& NzTexture::operator=(NzTexture&& texture) -{ - Destroy(); - - m_impl = texture.m_impl; - texture.m_impl = nullptr; - - return *this; -} - unsigned int NzTexture::GetValidSize(unsigned int size) { if (NzRenderer::HasCapability(nzRendererCap_TextureNPOT)) @@ -1277,16 +1274,3 @@ bool NzTexture::CreateTexture(bool proxy) return true; } - -void NzTexture::InvalidateMipmaps() -{ - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraInternalError("Texture must be valid"); - return; - } - #endif - - m_impl->mipmapsUpdated = false; -} diff --git a/src/Nazara/Utility/Image.cpp b/src/Nazara/Utility/Image.cpp index 4cc9297d2..b25ccdfd4 100644 --- a/src/Nazara/Utility/Image.cpp +++ b/src/Nazara/Utility/Image.cpp @@ -57,12 +57,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) { @@ -1283,13 +1277,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) From 77347c8582ad3d7a63f4367730aa425ffcec1d71 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 18:57:09 +0100 Subject: [PATCH 55/64] (Font) Added notification on atlas change Will only clear glyphes when setting differents parameters Former-commit-id: b16a289742c0f23fa5066d3c52ce35b4abc626c6 --- include/Nazara/Utility/Font.hpp | 1 + src/Nazara/Utility/Font.cpp | 31 +++++++++++++++++++++---------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/include/Nazara/Utility/Font.hpp b/include/Nazara/Utility/Font.hpp index 4605fe975..30b5e385c 100644 --- a/include/Nazara/Utility/Font.hpp +++ b/include/Nazara/Utility/Font.hpp @@ -79,6 +79,7 @@ class NAZARA_API NzFont : public NzResource, NzAbstractAtlas::Listener, NzNonCop enum ModicationCode { + ModificationCode_AtlasChanged, ModificationCode_GlyphCacheCleared, ModificationCode_KerningCacheCleared, ModificationCode_SizeInfoCacheCleared diff --git a/src/Nazara/Utility/Font.cpp b/src/Nazara/Utility/Font.cpp index 495e0dc7f..e164d57c3 100644 --- a/src/Nazara/Utility/Font.cpp +++ b/src/Nazara/Utility/Font.cpp @@ -276,20 +276,28 @@ bool NzFont::OpenFromStream(NzInputStream& stream, const NzFontParams& params) void NzFont::SetAtlas(std::shared_ptr atlas) { - ClearGlyphCache(); + if (m_atlas != atlas) + { + ClearGlyphCache(); - if (m_atlas) - m_atlas->RemoveListener(this); + if (m_atlas) + m_atlas->RemoveListener(this); - m_atlas = atlas; - if (m_atlas) - m_atlas->AddListener(this); + m_atlas = atlas; + if (m_atlas) + m_atlas->AddListener(this); + + NotifyModified(ModificationCode_AtlasChanged); + } } void NzFont::SetGlyphBorder(unsigned int borderSize) { - m_glyphBorder = borderSize; - ClearGlyphCache(); + if (m_glyphBorder != borderSize) + { + m_glyphBorder = borderSize; + ClearGlyphCache(); + } } void NzFont::SetMinimumStepSize(unsigned int minimumStepSize) @@ -302,8 +310,11 @@ void NzFont::SetMinimumStepSize(unsigned int minimumStepSize) } #endif - m_minimumSizeStep = minimumStepSize; - ClearGlyphCache(); + if (m_minimumSizeStep != minimumStepSize) + { + m_minimumSizeStep = minimumStepSize; + ClearGlyphCache(); + } } nzUInt64 NzFont::ComputeKey(unsigned int characterSize, nzUInt32 style) const From 48ecb058f0b9d4e79871b55896a489404ae96c69 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 23:34:56 +0100 Subject: [PATCH 56/64] (Font) Added notification on atlas layer change Fixed irrelevant error message when a font destroy an atlas Former-commit-id: ddbd04e9172f2d35a8e0cf8a37fe48724aeb5c64 --- include/Nazara/Utility/Font.hpp | 2 ++ src/Nazara/Utility/Font.cpp | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/Nazara/Utility/Font.hpp b/include/Nazara/Utility/Font.hpp index 30b5e385c..80b175f5f 100644 --- a/include/Nazara/Utility/Font.hpp +++ b/include/Nazara/Utility/Font.hpp @@ -80,6 +80,7 @@ class NAZARA_API NzFont : public NzResource, NzAbstractAtlas::Listener, NzNonCop enum ModicationCode { ModificationCode_AtlasChanged, + ModificationCode_AtlasLayerChanged, ModificationCode_GlyphCacheCleared, ModificationCode_KerningCacheCleared, ModificationCode_SizeInfoCacheCleared @@ -110,6 +111,7 @@ class NAZARA_API NzFont : public NzResource, NzAbstractAtlas::Listener, NzNonCop 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; diff --git a/src/Nazara/Utility/Font.cpp b/src/Nazara/Utility/Font.cpp index e164d57c3..79ce37878 100644 --- a/src/Nazara/Utility/Font.cpp +++ b/src/Nazara/Utility/Font.cpp @@ -22,6 +22,7 @@ m_minimumSizeStep(1) NzFont::~NzFont() { Destroy(); + SetAtlas(nullptr); // On libère l'atlas par la même occasion } void NzFont::ClearGlyphCache() @@ -355,6 +356,28 @@ bool NzFont::OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) 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); From 6d3228477f211b6a937ef4431252aec209d99801 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 16 Jan 2015 23:36:20 +0100 Subject: [PATCH 57/64] Added TextDrawer classes Former-commit-id: 4c5ace385f1a9b9ceebb774022bbc001b69a3bb4 --- include/Nazara/Utility/AbstractTextDrawer.hpp | 42 +++ include/Nazara/Utility/SimpleTextDrawer.hpp | 59 ++++ src/Nazara/Utility/AbstractTextDrawer.cpp | 9 + src/Nazara/Utility/SimpleTextDrawer.cpp | 305 ++++++++++++++++++ 4 files changed, 415 insertions(+) create mode 100644 include/Nazara/Utility/AbstractTextDrawer.hpp create mode 100644 include/Nazara/Utility/SimpleTextDrawer.hpp create mode 100644 src/Nazara/Utility/AbstractTextDrawer.cpp create mode 100644 src/Nazara/Utility/SimpleTextDrawer.cpp 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/SimpleTextDrawer.hpp b/include/Nazara/Utility/SimpleTextDrawer.hpp new file mode 100644 index 000000000..ca4b11845 --- /dev/null +++ b/include/Nazara/Utility/SimpleTextDrawer.hpp @@ -0,0 +1,59 @@ +// 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, NzResourceListener +{ + public: + NzSimpleTextDrawer(); + virtual ~NzSimpleTextDrawer(); + + 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(unsigned int characterSize, const NzString& str, nzUInt32 style = nzTextStyle_Regular, const NzColor& color = NzColor::White); + static NzSimpleTextDrawer Draw(NzFont* font, unsigned int characterSize, const NzString& str, 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 OnResourceModified(const NzResource* resource, int index, unsigned int code) override; + void OnResourceReleased(const NzResource* resource, int index) override; + void UpdateGlyphs() const; + + mutable std::vector m_glyphs; + NzColor m_color; + NzFontRef m_font; + 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/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/SimpleTextDrawer.cpp b/src/Nazara/Utility/SimpleTextDrawer.cpp new file mode 100644 index 000000000..e16161d69 --- /dev/null +++ b/src/Nazara/Utility/SimpleTextDrawer.cpp @@ -0,0 +1,305 @@ +// 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 + +///TODO: Listener de font (cas où l'atlas a changé) + +NzSimpleTextDrawer::NzSimpleTextDrawer() : +m_color(NzColor::White), +m_style(nzTextStyle_Regular) +{ + // SetFont(NzFont::GetDefault()); +} + +NzSimpleTextDrawer::~NzSimpleTextDrawer() +{ + if (m_font) + m_font->RemoveResourceListener(this); +} + +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) +{ + if (m_font) + m_font->RemoveResourceListener(this); + + m_font = font; + if (m_font) + m_font->AddResourceListener(this); + + 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(unsigned int characterSize, const NzString& str, nzUInt32 style, const NzColor& color) +{ + ///FIXME: Sans default font ça n'a aucun intérêt + NzSimpleTextDrawer drawer; + drawer.SetCharacterSize(characterSize); + drawer.SetColor(color); + drawer.SetStyle(style); + drawer.SetText(str); + + return drawer; +} + +NzSimpleTextDrawer NzSimpleTextDrawer::Draw(NzFont* font, unsigned int characterSize, const NzString& str, 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::OnResourceModified(const NzResource* resource, int index, unsigned int code) +{ + NazaraUnused(resource); + NazaraUnused(index); + + #ifdef NAZARA_DEBUG + if (m_font != resource) + { + NazaraInternalError("Not listening to " + NzString::Pointer(resource)); + return false; + } + #endif + + if (code == NzFont::ModificationCode_AtlasChanged || + code == NzFont::ModificationCode_AtlasLayerChanged || + code == NzFont::ModificationCode_GlyphCacheCleared) + { + m_glyphUpdated = false; + } + + return true; +} + +void NzSimpleTextDrawer::OnResourceReleased(const NzResource* resource, int index) +{ + NazaraUnused(resource); + NazaraUnused(index); + + #ifdef NAZARA_DEBUG + if (m_font != resource) + { + NazaraInternalError("Not listening to " + NzString::Pointer(resource)); + 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); + NzVector2ui lastPos(0, 0); + + 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; + + float 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 *= 1.1f; + } + + // 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); + + m_glyphs.push_back(glyph); + + lastPos = drawPos; + drawPos.x += advance; + } + + m_bounds.ExtendTo(lastPos); +} From fdb722ef14bcc2031c868ad7f0b60b9dec9cac41 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 17 Jan 2015 00:15:01 +0100 Subject: [PATCH 58/64] Made SceneNodes non-movable Fixed SceneNodes copy constructor not parenting the right object Former-commit-id: 21a08e3bb0931af426d97399dab86dda9acdf172 --- include/Nazara/Graphics/Model.hpp | 2 -- include/Nazara/Graphics/SceneNode.hpp | 3 ++- include/Nazara/Graphics/Sprite.hpp | 5 +++-- src/Nazara/Graphics/Light.cpp | 2 +- src/Nazara/Graphics/Model.cpp | 28 ++--------------------- src/Nazara/Graphics/SceneNode.cpp | 11 --------- src/Nazara/Graphics/Sprite.cpp | 32 ++++++++++++++------------- 7 files changed, 25 insertions(+), 58 deletions(-) diff --git a/include/Nazara/Graphics/Model.hpp b/include/Nazara/Graphics/Model.hpp index ea5b937ba..3249cdd48 100644 --- a/include/Nazara/Graphics/Model.hpp +++ b/include/Nazara/Graphics/Model.hpp @@ -36,7 +36,6 @@ class NAZARA_API NzModel : public NzSceneNode public: NzModel(); NzModel(const NzModel& model); - NzModel(NzModel&& model); virtual ~NzModel(); void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; @@ -83,7 +82,6 @@ class NAZARA_API NzModel : public NzSceneNode void SetSkinCount(unsigned int skinCount); NzModel& operator=(const NzModel& node); - NzModel& operator=(NzModel&& node); protected: void InvalidateNode() override; diff --git a/include/Nazara/Graphics/SceneNode.hpp b/include/Nazara/Graphics/SceneNode.hpp index e5d70d10c..edfdf56e2 100644 --- a/include/Nazara/Graphics/SceneNode.hpp +++ b/include/Nazara/Graphics/SceneNode.hpp @@ -21,6 +21,7 @@ class NAZARA_API NzSceneNode : public NzNode public: NzSceneNode(); NzSceneNode(const NzSceneNode& sceneNode); + NzSceneNode(NzSceneNode& sceneNode) = delete; virtual ~NzSceneNode(); virtual void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const = 0; @@ -43,7 +44,7 @@ class NAZARA_API NzSceneNode : public NzNode bool IsVisible() const; NzSceneNode& operator=(const NzSceneNode& sceneNode); - NzSceneNode& operator=(NzSceneNode&& sceneNode); + NzSceneNode& operator=(NzSceneNode&& sceneNode) = delete; protected: virtual bool FrustumCull(const NzFrustumf& frustum) const; diff --git a/include/Nazara/Graphics/Sprite.hpp b/include/Nazara/Graphics/Sprite.hpp index a6040823c..ed4b99f20 100644 --- a/include/Nazara/Graphics/Sprite.hpp +++ b/include/Nazara/Graphics/Sprite.hpp @@ -18,8 +18,7 @@ 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; @@ -40,6 +39,8 @@ class NAZARA_API NzSprite : public NzSceneNode void SetTextureCoords(const NzRectf& coords); void SetTextureRect(const NzRectui& rect); + NzSprite& operator=(const NzSprite& sprite); + private: void InvalidateNode() override; void Register() override; diff --git a/src/Nazara/Graphics/Light.cpp b/src/Nazara/Graphics/Light.cpp index ff3d5bfdd..e3288adc2 100644 --- a/src/Nazara/Graphics/Light.cpp +++ b/src/Nazara/Graphics/Light.cpp @@ -41,7 +41,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 diff --git a/src/Nazara/Graphics/Model.cpp b/src/Nazara/Graphics/Model.cpp index 54e9b964f..64e68a709 100644 --- a/src/Nazara/Graphics/Model.cpp +++ b/src/Nazara/Graphics/Model.cpp @@ -35,20 +35,14 @@ m_skinCount(1) NzModel::NzModel(const NzModel& model) : NzSceneNode(model), m_materials(model.m_materials), +m_mesh(model.m_mesh), m_boundingVolume(model.m_boundingVolume), m_boundingVolumeUpdated(model.m_boundingVolumeUpdated), 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() @@ -420,24 +414,6 @@ NzModel& NzModel::operator=(const NzModel& node) return *this; } -NzModel& NzModel::operator=(NzModel&& node) -{ - 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(); diff --git a/src/Nazara/Graphics/SceneNode.cpp b/src/Nazara/Graphics/SceneNode.cpp index fcaf02743..d5ae7da72 100644 --- a/src/Nazara/Graphics/SceneNode.cpp +++ b/src/Nazara/Graphics/SceneNode.cpp @@ -140,17 +140,6 @@ 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()); diff --git a/src/Nazara/Graphics/Sprite.cpp b/src/Nazara/Graphics/Sprite.cpp index 3d7a6d48e..24778dbd6 100644 --- a/src/Nazara/Graphics/Sprite.cpp +++ b/src/Nazara/Graphics/Sprite.cpp @@ -53,23 +53,9 @@ m_vertices(sprite.m_vertices), m_boundingVolumeUpdated(sprite.m_boundingVolumeUpdated), 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_vertices(sprite.m_vertices), -m_boundingVolumeUpdated(sprite.m_boundingVolumeUpdated), -m_verticesUpdated(sprite.m_verticesUpdated) -{ -} - -NzSprite::~NzSprite() = default; - void NzSprite::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const { if (!m_verticesUpdated) @@ -189,6 +175,22 @@ 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_boundingVolumeUpdated = false; + m_verticesUpdated = false; + + return *this; +} + void NzSprite::InvalidateNode() { NzSceneNode::InvalidateNode(); From a0054def7bf1195f4e2dd7ca1eae79c1eb9069a0 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 17 Jan 2015 00:16:52 +0100 Subject: [PATCH 59/64] Added TextSprites Former-commit-id: 85bef5ec14336710b2fdc782d3d0d77787ab65dd --- include/Nazara/Graphics/Enums.hpp | 9 +- include/Nazara/Graphics/TextSprite.hpp | 75 +++++ src/Nazara/Graphics/TextSprite.cpp | 407 +++++++++++++++++++++++++ 3 files changed, 487 insertions(+), 4 deletions(-) create mode 100644 include/Nazara/Graphics/TextSprite.hpp create mode 100644 src/Nazara/Graphics/TextSprite.cpp diff --git a/include/Nazara/Graphics/Enums.hpp b/include/Nazara/Graphics/Enums.hpp index 4f4cb1472..257928a66 100644 --- a/include/Nazara/Graphics/Enums.hpp +++ b/include/Nazara/Graphics/Enums.hpp @@ -71,10 +71,11 @@ enum nzRenderTechniqueType enum nzSceneNodeType { - nzSceneNodeType_Light, // NzLight - nzSceneNodeType_Model, // NzModel - nzSceneNodeType_Root, // NzSceneRoot - nzSceneNodeType_Sprite, // NzSprite + nzSceneNodeType_Light, // NzLight + nzSceneNodeType_Model, // NzModel + nzSceneNodeType_Root, // NzSceneRoot + nzSceneNodeType_Sprite, // NzSprite + nzSceneNodeType_TextSprite, // NzTextSprite nzSceneNodeType_User, nzSceneNodeType_Max = nzSceneNodeType_User diff --git a/include/Nazara/Graphics/TextSprite.hpp b/include/Nazara/Graphics/TextSprite.hpp new file mode 100644 index 000000000..be8df8b69 --- /dev/null +++ b/include/Nazara/Graphics/TextSprite.hpp @@ -0,0 +1,75 @@ +// 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_TEXTSPRITE_HPP +#define NAZARA_TEXTSPRITE_HPP + +#include +#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(); + + const NzBoundingVolumef& GetBoundingVolume() const override; + 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 SetText(const NzAbstractTextDrawer& drawer); + + NzTextSprite& operator=(const NzTextSprite& text); + + private: + void ClearAtlases(); + void InvalidateNode() 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 UpdateBoundingVolume() const; + 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; + mutable NzBoundingVolumef m_boundingVolume; + NzColor m_color; + NzMaterialRef m_material; + NzRectui m_localBounds; + mutable bool m_boundingVolumeUpdated; + mutable bool m_verticesUpdated; +}; + +#endif // NAZARA_TEXTSPRITE_HPP diff --git a/src/Nazara/Graphics/TextSprite.cpp b/src/Nazara/Graphics/TextSprite.cpp new file mode 100644 index 000000000..ab028ec91 --- /dev/null +++ b/src/Nazara/Graphics/TextSprite.cpp @@ -0,0 +1,407 @@ +// 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 + +#include +#include +#include +#include +#include +#include + +///TODO: Gérer allocation nouvel atlas + +NzTextSprite::NzTextSprite() : +m_boundingVolume(NzBoundingVolumef::Null()), +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_boundingVolume(sprite.m_boundingVolume), +m_color(sprite.m_color), +m_material(sprite.m_material), +m_localBounds(sprite.m_localBounds), +m_boundingVolumeUpdated(sprite.m_boundingVolumeUpdated), +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(); +} + +const NzBoundingVolumef& NzTextSprite::GetBoundingVolume() const +{ + if (!m_boundingVolumeUpdated) + UpdateBoundingVolume(); + + return m_boundingVolume; +} + +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::SetText(const NzAbstractTextDrawer& drawer) +{ + ClearAtlases(); + + unsigned int fontCount = drawer.GetFontCount(); + for (unsigned int i = 0; i < fontCount; ++i) + { + const NzAbstractAtlas* atlas = drawer.GetFont(i)->GetAtlas(); + 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; +} + +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_boundingVolumeUpdated = false; + 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_boundingVolumeUpdated = false; + m_verticesUpdated = false; +} + +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::UpdateBoundingVolume() const +{ + if (m_boundingVolume.IsNull()) + { + NzVector3f down = m_scene->GetDown(); + NzVector3f right = m_scene->GetRight(); + + m_boundingVolume.Set(NzVector3f(0.f), static_cast(m_localBounds.width)*right + static_cast(m_localBounds.height)*down); + } + + if (!m_transformMatrixUpdated) + UpdateTransformMatrix(); + + m_boundingVolume.Update(m_transformMatrix); + m_boundingVolumeUpdated = true; +} + +void NzTextSprite::UpdateVertices() const +{ + if (!m_transformMatrixUpdated) + UpdateTransformMatrix(); + + NzVector3f down = m_scene->GetDown(); + NzVector3f right = m_scene->GetRight(); + + 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; +} From 71c1d5f527f3c4b2efb2c16a7d462c0e8d09ee95 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 17 Jan 2015 00:29:26 +0100 Subject: [PATCH 60/64] Fixed reordered warning Former-commit-id: e825c3f282e1b1c3f65d32be8512210c92a3a1d9 --- src/Nazara/Graphics/Model.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nazara/Graphics/Model.cpp b/src/Nazara/Graphics/Model.cpp index 64e68a709..cf32336b8 100644 --- a/src/Nazara/Graphics/Model.cpp +++ b/src/Nazara/Graphics/Model.cpp @@ -35,8 +35,8 @@ m_skinCount(1) NzModel::NzModel(const NzModel& model) : NzSceneNode(model), m_materials(model.m_materials), -m_mesh(model.m_mesh), m_boundingVolume(model.m_boundingVolume), +m_mesh(model.m_mesh), m_boundingVolumeUpdated(model.m_boundingVolumeUpdated), m_matCount(model.m_matCount), m_skin(model.m_skin), From 3ed18e70da6c155d57575e994ac154b0e30dae3a Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 17 Jan 2015 00:34:09 +0100 Subject: [PATCH 61/64] Added default material to sprites Former-commit-id: 8a68d3d9b251ff93a793d4e001aed721558a8eef --- include/Nazara/Graphics/Sprite.hpp | 1 + src/Nazara/Graphics/Sprite.cpp | 63 ++++++++++++++++-------------- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/include/Nazara/Graphics/Sprite.hpp b/include/Nazara/Graphics/Sprite.hpp index ed4b99f20..b3739cb07 100644 --- a/include/Nazara/Graphics/Sprite.hpp +++ b/include/Nazara/Graphics/Sprite.hpp @@ -32,6 +32,7 @@ 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); diff --git a/src/Nazara/Graphics/Sprite.cpp b/src/Nazara/Graphics/Sprite.cpp index 24778dbd6..542f17cd4 100644 --- a/src/Nazara/Graphics/Sprite.cpp +++ b/src/Nazara/Graphics/Sprite.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -15,32 +16,18 @@ m_size(64.f, 64.f), m_boundingVolumeUpdated(true), m_verticesUpdated(false) { + SetDefaultMaterial(); } NzSprite::NzSprite(NzTexture* texture) : 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(false), 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) : @@ -108,13 +95,27 @@ void NzSprite::SetColor(const NzColor& 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(NzVector2ui(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) @@ -134,15 +135,17 @@ void NzSprite::SetSize(float sizeX, float 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->GetResourceReferenceCount() > 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) From 03b91575fb3d06b0103d36bd08f15f3b9e254371 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 17 Jan 2015 00:34:37 +0100 Subject: [PATCH 62/64] Fixed Node::Move taking local scale into account Former-commit-id: ce7b2c086e141c8cfa9981838c9d695f997b3941 --- src/Nazara/Utility/Node.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nazara/Utility/Node.cpp b/src/Nazara/Utility/Node.cpp index 6361ea3de..b9105aece 100644 --- a/src/Nazara/Utility/Node.cpp +++ b/src/Nazara/Utility/Node.cpp @@ -270,7 +270,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; } From 18367d26daaa40adb846d976710c14f74d74846c Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 17 Jan 2015 00:34:59 +0100 Subject: [PATCH 63/64] Added View::SetSize(width, height) Former-commit-id: 9afd04b62e99702720cb10feae2462eaad33a90b --- include/Nazara/Graphics/View.hpp | 1 + src/Nazara/Graphics/View.cpp | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/Nazara/Graphics/View.hpp b/include/Nazara/Graphics/View.hpp index e9d0de8da..b7f016afc 100644 --- a/include/Nazara/Graphics/View.hpp +++ b/include/Nazara/Graphics/View.hpp @@ -45,6 +45,7 @@ class NAZARA_API NzView : public NzAbstractViewer, public NzNode, NzRenderTarget 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); diff --git a/src/Nazara/Graphics/View.cpp b/src/Nazara/Graphics/View.cpp index 045b22a22..fb55c5054 100644 --- a/src/Nazara/Graphics/View.cpp +++ b/src/Nazara/Graphics/View.cpp @@ -24,7 +24,7 @@ m_zNear(-1.f) NzView::NzView(const NzVector2f& size) : NzView() // On délègue { - m_size = size; + SetSize(size); } NzView::~NzView() @@ -147,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) From a244029e116c64e5562bc68635aa93b0e5f71e72 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 17 Jan 2015 00:35:20 +0100 Subject: [PATCH 64/64] Fixed RenderTarget destructor not being virtual Even though it's pretty useless Former-commit-id: 9140fc3bc8aeabf041c5cf90ea3efcabc4ed4940 --- include/Nazara/Renderer/RenderTarget.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Nazara/Renderer/RenderTarget.hpp b/include/Nazara/Renderer/RenderTarget.hpp index eaec9f2ce..b04edd177 100644 --- a/include/Nazara/Renderer/RenderTarget.hpp +++ b/include/Nazara/Renderer/RenderTarget.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);