Graphics: Add Tilemap

This commit is contained in:
Lynix 2022-11-25 19:28:22 +01:00
parent e555b7ab73
commit 02387b8fe3
5 changed files with 653 additions and 7 deletions

View File

@ -2,7 +2,6 @@
#include <Nazara/Core/Systems.hpp>
#include <Nazara/Platform.hpp>
#include <Nazara/Graphics.hpp>
#include <Nazara/Graphics/TextSprite.hpp>
#include <Nazara/Graphics/Components.hpp>
#include <Nazara/Graphics/Systems.hpp>
#include <Nazara/Math/PidController.hpp>
@ -93,13 +92,28 @@ int main()
entt::entity groundEntity = registry.create();
{
std::shared_ptr<Nz::Sprite> sprite = std::make_shared<Nz::Sprite>(Nz::Graphics::Instance()->GetDefaultMaterials().basicDefault);
sprite->SetSize({ 800.f, 20.f });
sprite->SetOrigin({ 400.f, 10.f, 0.f });
std::shared_ptr<Nz::Tilemap> tilemap = std::make_shared<Nz::Tilemap>(Nz::Vector2ui(40, 20), Nz::Vector2f(64.f, 64.f), 18);
tilemap->SetOrigin(Nz::Vector2f(0.5f, 0.5f));
tilemap->EnableIsometricMode(true);
for (std::size_t i = 0; i < 18; ++i)
{
std::shared_ptr<Nz::MaterialInstance> material = Nz::Graphics::Instance()->GetDefaultMaterials().basicTransparent->Clone();
material->SetTextureProperty("BaseColorMap", Nz::Texture::LoadFromFile(resourceDir / "tiles" / (std::to_string(i + 1) + ".png"), texParams));
registry.emplace<Nz::NodeComponent>(groundEntity).SetPosition(1920.f / 2.f, 50.f);
registry.emplace<Nz::GraphicsComponent>(groundEntity).AttachRenderable(sprite, 1);
auto& rigidBody = registry.emplace<Nz::RigidBody2DComponent>(groundEntity, physSytem.CreateRigidBody(0.f, std::make_shared<Nz::BoxCollider2D>(Nz::Vector2f(800.f, 20.f))));
tilemap->SetMaterial(i, material);
}
for (unsigned int y = 0; y < 20; ++y)
{
for (unsigned int x = 0; x < 40; ++x)
{
tilemap->EnableTile({ x, y }, Nz::Rectf{ 0.f, 0.f, 1.f, 1.f }, Nz::Color::White, (y == 0) ? 1 : 4);
}
}
registry.emplace<Nz::NodeComponent>(groundEntity).SetPosition(1920.f / 2.f, 0.f);
registry.emplace<Nz::GraphicsComponent>(groundEntity).AttachRenderable(tilemap, 1);
auto& rigidBody = registry.emplace<Nz::RigidBody2DComponent>(groundEntity, physSytem.CreateRigidBody(0.f, std::make_shared<Nz::BoxCollider2D>(tilemap->GetSize())));
rigidBody.SetElasticity(0.99f);
}

View File

@ -80,6 +80,7 @@
#include <Nazara/Graphics/SubmeshRenderer.hpp>
#include <Nazara/Graphics/TextSprite.hpp>
#include <Nazara/Graphics/TextureSamplerCache.hpp>
#include <Nazara/Graphics/Tilemap.hpp>
#include <Nazara/Graphics/TransferInterface.hpp>
#include <Nazara/Graphics/UberShader.hpp>
#include <Nazara/Graphics/ViewerInstance.hpp>

View File

@ -0,0 +1,94 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// 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_GRAPHICS_TILEMAP_HPP
#define NAZARA_GRAPHICS_TILEMAP_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/Color.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/InstancedRenderable.hpp>
#include <Nazara/Utility/VertexStruct.hpp>
#include <memory>
#include <set>
namespace Nz
{
class MaterialInstance;
class NAZARA_GRAPHICS_API Tilemap : public InstancedRenderable
{
public:
struct Tile;
Tilemap(const Vector2ui& mapSize, const Vector2f& tileSize, std::size_t materialCount = 1);
Tilemap(const Tilemap&) = delete;
Tilemap(Tilemap&&) noexcept = default;
~Tilemap() = default;
void BuildElement(ElementRendererRegistry& registry, const ElementData& elementData, std::size_t passIndex, std::vector<RenderElementOwner>& elements) const override;
inline void DisableTile(const Vector2ui& tilePos);
inline void DisableTiles();
inline void DisableTiles(const Vector2ui* tilesPos, std::size_t tileCount);
inline void EnableIsometricMode(bool isometric);
inline void EnableTile(const Vector2ui& tilePos, const Rectf& coords, const Color& color = Color::White, std::size_t materialIndex = 0U);
inline void EnableTile(const Vector2ui& tilePos, const Rectui& rect, const Color& color = Color::White, std::size_t materialIndex = 0U);
inline void EnableTiles(const Rectf& coords, const Color& color = Color::White, std::size_t materialIndex = 0U);
inline void EnableTiles(const Rectui& rect, const Color& color = Color::White, std::size_t materialIndex = 0U);
inline void EnableTiles(const Vector2ui* tilesPos, std::size_t tileCount, const Rectf& coords, const Color& color = Color::White, std::size_t materialIndex = 0U);
inline void EnableTiles(const Vector2ui* tilesPos, std::size_t tileCount, const Rectui& rect, const Color& color = Color::White, std::size_t materialIndex = 0U);
inline const Vector2ui& GetMapSize() const;
const std::shared_ptr<MaterialInstance>& GetMaterial(std::size_t i) const override;
std::size_t GetMaterialCount() const override;
inline Vector2f GetSize() const;
inline const Tile& GetTile(const Vector2ui& tilePos) const;
inline const Vector2f& GetTileSize() const;
inline bool IsIsometricModeEnabled() const;
void SetMaterial(std::size_t matIndex, std::shared_ptr<MaterialInstance> material);
inline void SetOrigin(const Vector3f& origin);
struct Tile
{
std::size_t layerIndex = 0U;
Color color = Color::White;
Rectf textureCoords = Rectf::Zero();
bool enabled = false;
};
Tilemap& operator=(const Tilemap&) = delete;
Tilemap& operator=(Tilemap&&) noexcept = default;
private:
Vector3ui GetTextureSize(std::size_t matIndex) const;
inline void InvalidateVertices();
void UpdateVertices() const;
struct Layer
{
std::set<std::size_t> tiles;
std::shared_ptr<MaterialInstance> material;
};
mutable std::vector<VertexStruct_XYZ_Color_UV> m_vertices;
std::vector<Tile> m_tiles;
std::vector<Layer> m_layers;
Vector2ui m_mapSize;
Vector2f m_tileSize;
Vector3f m_origin;
bool m_isometricModeEnabled;
mutable bool m_shouldRebuildVertices;
};
}
#include <Nazara/Graphics/Tilemap.inl>
#endif // NAZARA_GRAPHICS_TILEMAP_HPP

View File

@ -0,0 +1,376 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/Tilemap.hpp>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
/*!
* \brief Disable the tile at position tilePos, disabling rendering at this location
*
* \param tilePos Position of the tile to disable
*
* \see DisableTiles
*/
inline void Tilemap::DisableTile(const Vector2ui& tilePos)
{
NazaraAssert(tilePos.x < m_mapSize.x&& tilePos.y < m_mapSize.y, "Tile position is out of bounds");
std::size_t tileIndex = tilePos.y * m_mapSize.x + tilePos.x;
Tile& tile = m_tiles[tileIndex];
tile.enabled = false;
m_layers[tile.layerIndex].tiles.erase(tileIndex);
InvalidateVertices();
}
/*!
* \brief Disable all tiles
*/
inline void Tilemap::DisableTiles()
{
for (Tile& tile : m_tiles)
tile.enabled = false;
for (Layer& layer : m_layers)
layer.tiles.clear();
InvalidateVertices();
}
/*!
* \brief Disable tileCount tiles at positions contained at tilesPos location, disabling rendering at those locations
*
* This is equivalent to calling tileCount times DisableTile with the positions contained at tilesPos
*
* \param tilesPos Pointer to a valid array of at least tileCount positions
* \param tileCount Number of tiles to disable
*
* \remark if tileCount is zero, this is a no-op and the value of tilesPos is not used
*
* \see DisableTile
*/
inline void Tilemap::DisableTiles(const Vector2ui* tilesPos, std::size_t tileCount)
{
NazaraAssert(tilesPos || tileCount == 0, "Invalid tile position array with a non-zero tileCount");
UInt32 invalidatedLayers = 0;
for (std::size_t i = 0; i < tileCount; ++i)
{
NazaraAssert(tilesPos->x < m_mapSize.x&& tilesPos->y < m_mapSize.y, "Tile position is out of bounds");
std::size_t tileIndex = tilesPos->y * m_mapSize.x + tilesPos->x;
Tile& tile = m_tiles[tileIndex];
tile.enabled = false;
m_layers[tile.layerIndex].tiles.erase(tileIndex);
invalidatedLayers |= 1U << tile.layerIndex;
tilesPos++;
}
if (tileCount > 0)
InvalidateVertices();
}
/*!
* \brief Enable/Disable isometric mode
*
* If enabled, every odd line will overlap by half the tile size with the upper line
*
* \param isometric Should the isometric mode be enabled for this Tilemap
*
* \see IsIsometricModeEnabled
*/
inline void Tilemap::EnableIsometricMode(bool isometric)
{
m_isometricModeEnabled = isometric;
InvalidateVertices();
}
/*!
* \brief Enable and sets the tile at position tilePos
*
* Setup the tile at position tilePos using color, normalized coordinates coords and materialIndex
*
* \param tilePos Position of the tile to enable
* \param coords Normalized coordinates ([0..1]) used to specify which region of the material textures will be used
* \param color The multiplicative color applied to the tile
* \param materialIndex The material which will be used for rendering this tile
*
* \see EnableTiles
*/
inline void Tilemap::EnableTile(const Vector2ui& tilePos, const Rectf& coords, const Color& color, std::size_t materialIndex)
{
NazaraAssert(tilePos.x < m_mapSize.x&& tilePos.y < m_mapSize.y, "Tile position is out of bounds");
NazaraAssert(materialIndex < m_layers.size(), "Material out of bounds");
UInt32 invalidatedLayers = 1U << materialIndex;
std::size_t tileIndex = tilePos.y * m_mapSize.x + tilePos.x;
Tile& tile = m_tiles[tilePos.y * m_mapSize.x + tilePos.x];
if (!tile.enabled)
m_layers[materialIndex].tiles.insert(tileIndex);
else if (materialIndex != tile.layerIndex)
{
m_layers[tile.layerIndex].tiles.erase(tileIndex);
m_layers[materialIndex].tiles.insert(tileIndex);
invalidatedLayers |= 1U << tile.layerIndex;
}
tile.enabled = true;
tile.color = color;
tile.textureCoords = coords;
tile.layerIndex = materialIndex;
InvalidateVertices();
}
/*!
* \brief Enable and sets the tile at position tilePos
*
* Setup the tile at position tilePos using color, unnormalized coordinates rect and materialIndex
*
* \param tilePos Position of the tile to enable
* \param coords Unnormalized coordinates ([0..size]) used to specify which region of the material textures will be used
* \param color The multiplicative color applied to the tile
* \param materialIndex The material which will be used for rendering this tile
*
* \remark The material at [materialIndex] must have a valid diffuse map before using this function,
* as the size of the material diffuse map is used to compute normalized texture coordinates before returning.
*
* \see EnableTiles
*/
inline void Tilemap::EnableTile(const Vector2ui& tilePos, const Rectui& rect, const Color& color, std::size_t materialIndex)
{
NazaraAssert(materialIndex < m_layers.size(), "Material out of bounds");
Vector2ui textureSize(GetTextureSize(materialIndex));
float invWidth = 1.f / textureSize.x;
float invHeight = 1.f / textureSize.y;
Rectf unnormalizedCoords(invWidth * rect.x, invHeight * rect.y, invWidth * rect.width, invHeight * rect.height);
EnableTile(tilePos, unnormalizedCoords, color, materialIndex);
}
/*!
* \brief Enable and sets all the tiles
*
* Setup all tiles using color, normalized coordinates coords and materialIndex
*
* \param coords Normalized coordinates ([0..1]) used to specify which region of the material textures will be used
* \param color The multiplicative color applied to the tile
* \param materialIndex The material which will be used for rendering this tile
*
* \remark The material at [materialIndex] must have a valid diffuse map before using this function,
* as the size of the material diffuse map is used to compute normalized texture coordinates before returning.
*
* \see EnableTile
*/
inline void Tilemap::EnableTiles(const Rectf& coords, const Color& color, std::size_t materialIndex)
{
NazaraAssert(materialIndex < m_layers.size(), "Material out of bounds");
for (Layer& layer : m_layers)
layer.tiles.clear();
std::size_t tileIndex = 0;
for (Tile& tile : m_tiles)
{
tile.enabled = true;
tile.color = color;
tile.textureCoords = coords;
tile.layerIndex = materialIndex;
m_layers[materialIndex].tiles.insert(tileIndex++);
}
InvalidateVertices();
}
/*!
* \brief Enable and sets all the tiles
*
* Setup all tiles using color, unnormalized coordinates coords and materialIndex
*
* \param coords Unnormalized coordinates ([0..size]) used to specify which region of the material textures will be used
* \param color The multiplicative color applied to the tile
* \param materialIndex The material which will be used for rendering this tile
*
* \remark The material at [materialIndex] must have a valid diffuse map before using this function,
* as the size of the material diffuse map is used to compute normalized texture coordinates before returning.
*
* \see EnableTile
*/
inline void Tilemap::EnableTiles(const Rectui& rect, const Color& color, std::size_t materialIndex)
{
NazaraAssert(materialIndex < m_layers.size(), "Material out of bounds");
Vector2ui textureSize(GetTextureSize(materialIndex));
float invWidth = 1.f / textureSize.x;
float invHeight = 1.f / textureSize.y;
Rectf unnormalizedCoords(invWidth * rect.x, invHeight * rect.y, invWidth * rect.width, invHeight * rect.height);
EnableTiles(unnormalizedCoords, color, materialIndex);
}
/*!
* \brief Enable and sets tileCount tiles at positions contained at tilesPos location, enabling rendering at those locations
*
* Setup all tiles using color, normalized coordinates coords and materialIndex
*
* \param tilesPos Pointer to a valid array of at least tileCount positions
* \param tileCount Number of tiles to enable
* \param coords Normalized coordinates ([0..1]) used to specify which region of the material textures will be used
* \param color The multiplicative color applied to the tile
* \param materialIndex The material which will be used for rendering this tile
*
* \see EnableTile
*/
inline void Tilemap::EnableTiles(const Vector2ui* tilesPos, std::size_t tileCount, const Rectf& coords, const Color& color, std::size_t materialIndex)
{
NazaraAssert(tilesPos || tileCount == 0, "Invalid tile position array with a non-zero tileCount");
NazaraAssert(materialIndex < m_layers.size(), "Material out of bounds");
UInt32 invalidatedLayers = 1U << materialIndex;
for (std::size_t i = 0; i < tileCount; ++i)
{
NazaraAssert(tilesPos->x < m_mapSize.x&& tilesPos->y < m_mapSize.y, "Tile position is out of bounds");
std::size_t tileIndex = tilesPos->y * m_mapSize.x + tilesPos->x;
Tile& tile = m_tiles[tileIndex];
if (!tile.enabled)
m_layers[materialIndex].tiles.insert(tileIndex);
else if (materialIndex != tile.layerIndex)
{
m_layers[tile.layerIndex].tiles.erase(tileIndex);
m_layers[materialIndex].tiles.insert(tileIndex);
invalidatedLayers |= 1U << tile.layerIndex;
}
tile.enabled = true;
tile.color = color;
tile.textureCoords = coords;
tile.layerIndex = materialIndex;
tilesPos++;
}
if (tileCount > 0)
InvalidateVertices();
}
/*!
* \brief Enable and sets tileCount tiles at positions contained at tilesPos location, enabling rendering at those locations
*
* Setup all tiles using color, unnormalized coordinates coords and materialIndex
*
* \param tilesPos Pointer to a valid array of at least tileCount positions
* \param tileCount Number of tiles to enable
* \param coords Unnormalized coordinates ([0..size]) used to specify which region of the material textures will be used
* \param color The multiplicative color applied to the tile
* \param materialIndex The material which will be used for rendering this tile
*
* \remark The material at [materialIndex] must have a valid diffuse map before using this function,
* as the size of the material diffuse map is used to compute normalized texture coordinates before returning.
*
* \see EnableTile
*/
inline void Tilemap::EnableTiles(const Vector2ui* tilesPos, std::size_t tileCount, const Rectui& rect, const Color& color, std::size_t materialIndex)
{
NazaraAssert(materialIndex < m_layers.size(), "Material out of bounds");
Vector2ui textureSize(GetTextureSize(materialIndex));
float invWidth = 1.f / textureSize.x;
float invHeight = 1.f / textureSize.y;
Rectf unnormalizedCoords(invWidth * rect.x, invHeight * rect.y, invWidth * rect.width, invHeight * rect.height);
EnableTiles(tilesPos, tileCount, unnormalizedCoords, color, materialIndex);
}
/*!
* \brief Gets the tilemap size (i.e. number of tiles in each dimension)
* \return Number of tiles in each dimension
*
* \see GetSize
* \see GetTileSize
*/
inline const Vector2ui& Tilemap::GetMapSize() const
{
return m_mapSize;
}
/*!
* \brief Returns the size of the tilemap in units (which is equivalent to GetMapSize() * GetTileSize())
* \return Maximum size in units occupied by this tilemap
*
* \see GetMapSize
* \see GetTileSize
*/
inline Vector2f Tilemap::GetSize() const
{
return Vector2f(m_mapSize) * m_tileSize;
}
/*!
* \brief Returns informations about a particular tile
*
* \param tilePos Position of the tile to get (enabled or not)
*
* \return Maximum size in units occupied by this tilemap
*/
inline const Tilemap::Tile& Tilemap::GetTile(const Vector2ui& tilePos) const
{
NazaraAssert(tilePos.x < m_mapSize.x&& tilePos.y < m_mapSize.y, "Tile position is out of bounds");
return m_tiles[tilePos.y * m_mapSize.x + tilePos.x];
}
/*!
* \brief Gets the tile size (i.e. number of units occupied by a tile in each dimension)
* \return Tile size in each dimension
*
* \see GetMapSize
* \see GetSize
*/
inline const Vector2f& Tilemap::GetTileSize() const
{
return m_tileSize;
}
/*!
* \brief Gets the actual state of the isometric mode
* \return True if the isometric mode is enabled
*
* \see EnableIsometricMode
*/
inline bool Tilemap::IsIsometricModeEnabled() const
{
return m_isometricModeEnabled;
}
inline void Tilemap::SetOrigin(const Vector3f& origin)
{
m_origin = origin;
InvalidateVertices();
}
inline void Tilemap::InvalidateVertices()
{
m_shouldRebuildVertices = true;
OnElementInvalidated(this);
}
}
#include <Nazara/Graphics/DebugOff.hpp>

View File

@ -0,0 +1,161 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/Tilemap.hpp>
#include <Nazara/Graphics/ElementRendererRegistry.hpp>
#include <Nazara/Graphics/Graphics.hpp>
#include <Nazara/Graphics/RenderSpriteChain.hpp>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
/*!
* \brief Constructs a Tilemap object, containing mapSize tileSize-sized tiles
*
* \param mapSize Number of tiles in each dimension, must be
* \param tileSize Size of each tile of the Tilemap
* \param materialCount The maximum number of differents Material this Tilemap will use
*
* \remark When constructed, a Tilemap has no tile active and will not be rendered
* To use it, you have to enable some tiles.
*
* \remark The default material is used for every material requested
*/
Tilemap::Tilemap(const Vector2ui& mapSize, const Vector2f& tileSize, std::size_t materialCount) :
m_tiles(mapSize.x* mapSize.y),
m_layers(materialCount),
m_mapSize(mapSize),
m_tileSize(tileSize),
m_isometricModeEnabled(false),
m_shouldRebuildVertices(false)
{
NazaraAssert(m_tiles.size() != 0U, "Invalid map size");
NazaraAssert(m_tileSize.x > 0 && m_tileSize.y > 0, "Invalid tile size");
NazaraAssert(m_layers.size() != 0U, "Invalid material count");
std::shared_ptr<MaterialInstance> defaultMaterialInstance = Graphics::Instance()->GetDefaultMaterials().basicDefault;
for (auto& layer : m_layers)
layer.material = defaultMaterialInstance;
}
void Tilemap::BuildElement(ElementRendererRegistry& registry, const ElementData& elementData, std::size_t passIndex, std::vector<RenderElementOwner>& elements) const
{
if (m_shouldRebuildVertices)
UpdateVertices();
const std::shared_ptr<VertexDeclaration>& vertexDeclaration = VertexDeclaration::Get(VertexLayout::XYZ_Color_UV);
RenderPipelineInfo::VertexBufferData vertexBufferData = {
0,
vertexDeclaration
};
const auto& whiteTexture = Graphics::Instance()->GetDefaultTextures().whiteTextures[UnderlyingCast(ImageType::E2D)];
const VertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<const VertexStruct_XYZ_Color_UV*>(m_vertices.data());
for (std::size_t layerIndex = 0; layerIndex < m_layers.size(); ++layerIndex)
{
const auto& layer = m_layers[layerIndex];
if (layer.tiles.empty())
continue;
const auto& materialPipeline = layer.material->GetPipeline(passIndex);
if (!materialPipeline)
return;
MaterialPassFlags passFlags = layer.material->GetPassFlags(passIndex);
const auto& renderPipeline = materialPipeline->GetRenderPipeline(&vertexBufferData, 1);
std::size_t spriteCount = layer.tiles.size();
elements.emplace_back(registry.AllocateElement<RenderSpriteChain>(GetRenderLayer(), layer.material, passFlags, renderPipeline, *elementData.worldInstance, vertexDeclaration, whiteTexture, spriteCount, vertices, *elementData.scissorBox));
vertices += 4 * spriteCount;
}
}
const std::shared_ptr<MaterialInstance>& Tilemap::GetMaterial(std::size_t i) const
{
assert(i < m_layers.size());
return m_layers[i].material;
}
std::size_t Tilemap::GetMaterialCount() const
{
return m_layers.size();
}
void Tilemap::SetMaterial(std::size_t matIndex, std::shared_ptr<MaterialInstance> material)
{
NazaraAssert(matIndex < m_layers.size(), "Material index out of bounds");
NazaraAssert(material, "invalid material");
OnMaterialInvalidated(this, matIndex, material);
m_layers[matIndex].material = std::move(material);
}
Vector3ui Tilemap::GetTextureSize(std::size_t matIndex) const
{
assert(matIndex < m_layers.size());
//TODO: Cache index in registry?
if (const std::shared_ptr<Texture>* textureOpt = m_layers[matIndex].material->GetTextureProperty("BaseColorMap"))
{
// Material should always have textures but we're better safe than sorry
if (const std::shared_ptr<Texture>& texture = *textureOpt)
return texture->GetSize();
}
// Couldn't get material pass or texture
return Vector3ui::Unit(); //< prevents division by zero
}
void Tilemap::UpdateVertices() const
{
std::size_t spriteCount = 0;
for (const Layer& layer : m_layers)
spriteCount += layer.tiles.size();
m_vertices.resize(spriteCount * 4);
VertexStruct_XYZ_Color_UV* vertexPtr = reinterpret_cast<VertexStruct_XYZ_Color_UV*>(m_vertices.data());
Vector3f originShift = m_origin * GetSize();
float topCorner = m_tileSize.y * (m_mapSize.y - 1);
for (const Layer& layer : m_layers)
{
for (std::size_t tileIndex : layer.tiles)
{
const Tile& tile = m_tiles[tileIndex];
NazaraAssert(tile.enabled, "Tile specified for rendering is not enabled");
std::size_t x = tileIndex % m_mapSize.x;
std::size_t y = tileIndex / m_mapSize.x;
Vector3f tileLeftBottom;
if (m_isometricModeEnabled)
tileLeftBottom.Set(x * m_tileSize.x + m_tileSize.x / 2.f * (y % 2), topCorner - y / 2.f * m_tileSize.y, 0.f);
else
tileLeftBottom.Set(x * m_tileSize.x, topCorner - y * m_tileSize.y, 0.f);
std::array<Vector2f, RectCornerCount> cornerExtent;
cornerExtent[UnderlyingCast(RectCorner::LeftBottom)] = Vector2f(0.f, 0.f);
cornerExtent[UnderlyingCast(RectCorner::RightBottom)] = Vector2f(1.f, 0.f);
cornerExtent[UnderlyingCast(RectCorner::LeftTop)] = Vector2f(0.f, 1.f);
cornerExtent[UnderlyingCast(RectCorner::RightTop)] = Vector2f(1.f, 1.f);
for (RectCorner corner : { RectCorner::LeftBottom, RectCorner::RightBottom, RectCorner::LeftTop, RectCorner::RightTop })
{
vertexPtr->color = tile.color;
vertexPtr->position = tileLeftBottom + Vector3f(m_tileSize * cornerExtent[UnderlyingCast(corner)], 0.f) - originShift;
vertexPtr->uv = tile.textureCoords.GetCorner(corner);
++vertexPtr;
}
}
}
m_shouldRebuildVertices = false;
}
}