Merge branch 'enet_wip_nothing_to_see_here' of https://github.com/DigitalPulseSoftware/NazaraEngine into enet_wip_nothing_to_see_here
This commit is contained in:
@@ -101,7 +101,7 @@ namespace Nz
|
||||
{
|
||||
struct HashMD5_state
|
||||
{
|
||||
UInt32 count[2]; /* message length in bits, lsw first */
|
||||
std::size_t count[2]; /* message length in bits, lsw first */
|
||||
UInt32 abcd[4]; /* digest buffer */
|
||||
UInt8 buf[64]; /* accumulate block */
|
||||
};
|
||||
@@ -280,9 +280,9 @@ namespace Nz
|
||||
void HashMD5::Append(const UInt8* data, std::size_t len)
|
||||
{
|
||||
const UInt8 *p = data;
|
||||
int left = len;
|
||||
std::size_t left = len;
|
||||
int offset = (m_state->count[0] >> 3) & 63;
|
||||
UInt32 nbits = len << 3;
|
||||
std::size_t nbits = len << 3;
|
||||
|
||||
if (len <= 0)
|
||||
return;
|
||||
@@ -296,7 +296,7 @@ namespace Nz
|
||||
/* Process an initial partial block. */
|
||||
if (offset)
|
||||
{
|
||||
int copy = (offset + len > 64 ? 64 - offset : len);
|
||||
std::size_t copy = (offset + len > 64 ? 64 - offset : len);
|
||||
|
||||
std::memcpy(m_state->buf + offset, p, copy);
|
||||
if (offset + copy < 64)
|
||||
|
||||
@@ -75,8 +75,8 @@ namespace Nz
|
||||
{
|
||||
struct HashWhirlpool_state
|
||||
{
|
||||
int bufferBits; // current number of bits on the buffer */
|
||||
int bufferPos; // current (possibly incomplete) byte slot on the buffer */
|
||||
std::size_t bufferBits; // current number of bits on the buffer */
|
||||
std::size_t bufferPos; // current (possibly incomplete) byte slot on the buffer */
|
||||
UInt8 bitLength[32]; // global number of hashed bits (256-bit counter) */
|
||||
UInt8 buffer[64]; // buffer of data to hash */
|
||||
UInt64 hash[8]; // the hashing state */
|
||||
@@ -877,8 +877,8 @@ namespace Nz
|
||||
UInt32 b;
|
||||
UInt8* buffer = m_state->buffer;
|
||||
UInt8* bitLength = m_state->bitLength;
|
||||
int bufferBits = m_state->bufferBits;
|
||||
int bufferPos = m_state->bufferPos;
|
||||
std::size_t bufferBits = m_state->bufferBits;
|
||||
std::size_t bufferPos = m_state->bufferPos;
|
||||
|
||||
// tally the length of the added data
|
||||
UInt64 value = len;
|
||||
@@ -968,8 +968,8 @@ namespace Nz
|
||||
|
||||
UInt8 *buffer = m_state->buffer;
|
||||
UInt8 *bitLength = m_state->bitLength;
|
||||
int bufferBits = m_state->bufferBits;
|
||||
int bufferPos = m_state->bufferPos;
|
||||
std::size_t bufferBits = m_state->bufferBits;
|
||||
std::size_t bufferPos = m_state->bufferPos;
|
||||
UInt8 *digest = result;
|
||||
|
||||
// append a '1'-bit
|
||||
|
||||
@@ -2115,7 +2115,7 @@ namespace Nz
|
||||
|
||||
return ptr - m_sharedString->string.get();
|
||||
}
|
||||
catch (utf8::not_enough_room& e)
|
||||
catch (utf8::not_enough_room& /*e*/)
|
||||
{
|
||||
// Returns npos
|
||||
}
|
||||
|
||||
@@ -191,8 +191,8 @@ namespace Nz
|
||||
|
||||
void DeferredRenderQueue::AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix)
|
||||
{
|
||||
if (material->IsBlendingEnabled())
|
||||
// One transparent material ? I don't like it, go see if I'm in the forward queue
|
||||
if (material->IsBlendingEnabled() || material->IsDepthSortingEnabled()) //< Fixme: Deferred Shading should be able to handle depth sorting
|
||||
// Deferred Shading cannot handle blended objects, put them in the forward list
|
||||
m_forwardQueue->AddMesh(renderOrder, material, meshData, meshAABB, transformMatrix);
|
||||
else
|
||||
{
|
||||
@@ -254,7 +254,7 @@ namespace Nz
|
||||
* \param overlay Texture of the sprites
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay)
|
||||
void DeferredRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay)
|
||||
{
|
||||
m_forwardQueue->AddSprites(renderOrder, material, vertices, spriteCount, overlay);
|
||||
}
|
||||
|
||||
@@ -351,7 +351,7 @@ namespace Nz
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void DepthRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay)
|
||||
void DepthRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
NazaraUnused(renderOrder);
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace Nz
|
||||
if (!layer.opaqueModels.empty())
|
||||
DrawOpaqueModels(sceneData, layer);
|
||||
|
||||
if (!layer.basicSprites.empty())
|
||||
if (!layer.opaqueSprites.empty())
|
||||
DrawBasicSprites(sceneData, layer);
|
||||
|
||||
if (!layer.billboards.empty())
|
||||
@@ -219,7 +219,7 @@ namespace Nz
|
||||
Renderer::SetMatrix(MatrixType_World, Matrix4f::Identity());
|
||||
Renderer::SetVertexBuffer(&m_spriteBuffer);
|
||||
|
||||
for (auto& pipelinePair : layer.basicSprites)
|
||||
for (auto& pipelinePair : layer.opaqueSprites)
|
||||
{
|
||||
const MaterialPipeline* pipeline = pipelinePair.first;
|
||||
auto& pipelineEntry = pipelinePair.second;
|
||||
|
||||
@@ -376,23 +376,23 @@ namespace Nz
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
||||
if (material->IsBlendingEnabled())
|
||||
if (material->IsDepthSortingEnabled())
|
||||
{
|
||||
Layer& currentLayer = GetLayer(renderOrder);
|
||||
auto& transparentModels = currentLayer.transparentModels;
|
||||
auto& transparentModelData = currentLayer.transparentModelData;
|
||||
auto& transparentMeshes = currentLayer.depthSortedMeshes;
|
||||
auto& transparentData = currentLayer.depthSortedMeshData;
|
||||
|
||||
// The material is transparent, we must draw this mesh using another way (after the rendering of opages objects while sorting them)
|
||||
std::size_t index = transparentModelData.size();
|
||||
transparentModelData.resize(index+1);
|
||||
// The material is marked for depth sorting, we must draw this mesh using another way (after the rendering of opaques objects while sorting them)
|
||||
std::size_t index = transparentData.size();
|
||||
transparentData.resize(index+1);
|
||||
|
||||
TransparentModelData& data = transparentModelData.back();
|
||||
UnbatchedModelData& data = transparentData.back();
|
||||
data.material = material;
|
||||
data.meshData = meshData;
|
||||
data.squaredBoundingSphere = Spheref(transformMatrix.GetTranslation() + meshAABB.GetCenter(), meshAABB.GetSquaredRadius());
|
||||
data.obbSphere = Spheref(transformMatrix.GetTranslation() + meshAABB.GetCenter(), meshAABB.GetSquaredRadius());
|
||||
data.transformMatrix = transformMatrix;
|
||||
|
||||
transparentModels.push_back(index);
|
||||
transparentMeshes.push_back(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -457,53 +457,74 @@ namespace Nz
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
void ForwardRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay)
|
||||
void ForwardRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
||||
Layer& currentLayer = GetLayer(renderOrder);
|
||||
SpritePipelineBatches& basicSprites = currentLayer.basicSprites;
|
||||
|
||||
const MaterialPipeline* materialPipeline = material->GetPipeline();
|
||||
|
||||
auto pipelineIt = basicSprites.find(materialPipeline);
|
||||
if (pipelineIt == basicSprites.end())
|
||||
if (material->IsDepthSortingEnabled())
|
||||
{
|
||||
BatchedSpritePipelineEntry materialEntry;
|
||||
pipelineIt = basicSprites.insert(SpritePipelineBatches::value_type(materialPipeline, std::move(materialEntry))).first;
|
||||
auto& transparentSprites = currentLayer.depthSortedSprites;
|
||||
auto& transparentData = currentLayer.depthSortedSpriteData;
|
||||
|
||||
// The material is marked for depth sorting, we must draw this mesh using another way (after the rendering of opaques objects while sorting them)
|
||||
std::size_t index = transparentData.size();
|
||||
transparentData.resize(index + 1);
|
||||
|
||||
UnbatchedSpriteData& data = transparentData.back();
|
||||
data.material = material;
|
||||
data.overlay = overlay;
|
||||
data.spriteCount = spriteCount;
|
||||
data.vertices = vertices;
|
||||
|
||||
transparentSprites.push_back(index);
|
||||
}
|
||||
|
||||
BatchedSpritePipelineEntry& pipelineEntry = pipelineIt->second;
|
||||
pipelineEntry.enabled = true;
|
||||
|
||||
SpriteMaterialBatches& materialMap = pipelineEntry.materialMap;
|
||||
|
||||
auto matIt = materialMap.find(material);
|
||||
if (matIt == materialMap.end())
|
||||
else
|
||||
{
|
||||
BatchedBasicSpriteEntry entry;
|
||||
entry.materialReleaseSlot.Connect(material->OnMaterialRelease, this, &ForwardRenderQueue::OnMaterialInvalidation);
|
||||
SpritePipelineBatches& sprites = currentLayer.opaqueSprites;
|
||||
|
||||
matIt = materialMap.insert(SpriteMaterialBatches::value_type(material, std::move(entry))).first;
|
||||
const MaterialPipeline* materialPipeline = material->GetPipeline();
|
||||
|
||||
auto pipelineIt = sprites.find(materialPipeline);
|
||||
if (pipelineIt == sprites.end())
|
||||
{
|
||||
BatchedSpritePipelineEntry materialEntry;
|
||||
pipelineIt = sprites.insert(SpritePipelineBatches::value_type(materialPipeline, std::move(materialEntry))).first;
|
||||
}
|
||||
|
||||
BatchedSpritePipelineEntry& pipelineEntry = pipelineIt->second;
|
||||
pipelineEntry.enabled = true;
|
||||
|
||||
SpriteMaterialBatches& materialMap = pipelineEntry.materialMap;
|
||||
|
||||
auto matIt = materialMap.find(material);
|
||||
if (matIt == materialMap.end())
|
||||
{
|
||||
BatchedBasicSpriteEntry entry;
|
||||
entry.materialReleaseSlot.Connect(material->OnMaterialRelease, this, &ForwardRenderQueue::OnMaterialInvalidation);
|
||||
|
||||
matIt = materialMap.insert(SpriteMaterialBatches::value_type(material, std::move(entry))).first;
|
||||
}
|
||||
|
||||
BatchedBasicSpriteEntry& entry = matIt->second;
|
||||
entry.enabled = true;
|
||||
|
||||
auto& overlayMap = entry.overlayMap;
|
||||
|
||||
auto overlayIt = overlayMap.find(overlay);
|
||||
if (overlayIt == overlayMap.end())
|
||||
{
|
||||
BatchedSpriteEntry overlayEntry;
|
||||
if (overlay)
|
||||
overlayEntry.textureReleaseSlot.Connect(overlay->OnTextureRelease, this, &ForwardRenderQueue::OnTextureInvalidation);
|
||||
|
||||
overlayIt = overlayMap.insert(std::make_pair(overlay, std::move(overlayEntry))).first;
|
||||
}
|
||||
|
||||
auto& spriteVector = overlayIt->second.spriteChains;
|
||||
spriteVector.push_back(SpriteChain_XYZ_Color_UV({vertices, spriteCount}));
|
||||
}
|
||||
|
||||
BatchedBasicSpriteEntry& entry = matIt->second;
|
||||
entry.enabled = true;
|
||||
|
||||
auto& overlayMap = entry.overlayMap;
|
||||
|
||||
auto overlayIt = overlayMap.find(overlay);
|
||||
if (overlayIt == overlayMap.end())
|
||||
{
|
||||
BatchedSpriteEntry overlayEntry;
|
||||
if (overlay)
|
||||
overlayEntry.textureReleaseSlot.Connect(overlay->OnTextureRelease, this, &ForwardRenderQueue::OnTextureInvalidation);
|
||||
|
||||
overlayIt = overlayMap.insert(std::make_pair(overlay, std::move(overlayEntry))).first;
|
||||
}
|
||||
|
||||
auto& spriteVector = overlayIt->second.spriteChains;
|
||||
spriteVector.push_back(SpriteChain_XYZ_Color_UV({vertices, spriteCount}));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -545,7 +566,7 @@ namespace Nz
|
||||
pipelineEntry.enabled = false;
|
||||
}
|
||||
|
||||
for (auto& pipelinePair : layer.basicSprites)
|
||||
for (auto& pipelinePair : layer.opaqueSprites)
|
||||
{
|
||||
auto& pipelineEntry = pipelinePair.second;
|
||||
|
||||
@@ -596,9 +617,11 @@ namespace Nz
|
||||
}
|
||||
}
|
||||
|
||||
layer.depthSortedMeshes.clear();
|
||||
layer.depthSortedMeshData.clear();
|
||||
layer.depthSortedSpriteData.clear();
|
||||
layer.depthSortedSprites.clear();
|
||||
layer.otherDrawables.clear();
|
||||
layer.transparentModels.clear();
|
||||
layer.transparentModelData.clear();
|
||||
++it;
|
||||
}
|
||||
}
|
||||
@@ -613,44 +636,10 @@ namespace Nz
|
||||
|
||||
void ForwardRenderQueue::Sort(const AbstractViewer* viewer)
|
||||
{
|
||||
Planef nearPlane = viewer->GetFrustum().GetPlane(FrustumPlane_Near);
|
||||
Vector3f viewerPos = viewer->GetEyePosition();
|
||||
Vector3f viewerNormal = viewer->GetForward();
|
||||
|
||||
for (auto& pair : layers)
|
||||
{
|
||||
Layer& layer = pair.second;
|
||||
|
||||
std::sort(layer.transparentModels.begin(), layer.transparentModels.end(), [&layer, &nearPlane, &viewerNormal] (std::size_t index1, std::size_t index2)
|
||||
{
|
||||
const Spheref& sphere1 = layer.transparentModelData[index1].squaredBoundingSphere;
|
||||
const Spheref& sphere2 = layer.transparentModelData[index2].squaredBoundingSphere;
|
||||
|
||||
Vector3f position1 = sphere1.GetNegativeVertex(viewerNormal);
|
||||
Vector3f position2 = sphere2.GetNegativeVertex(viewerNormal);
|
||||
|
||||
return nearPlane.Distance(position1) > nearPlane.Distance(position2);
|
||||
});
|
||||
|
||||
for (auto& pipelinePair : layer.billboards)
|
||||
{
|
||||
for (auto& matPair : pipelinePair.second.materialMap)
|
||||
{
|
||||
const Material* mat = matPair.first;
|
||||
|
||||
if (mat->IsDepthSortingEnabled())
|
||||
{
|
||||
BatchedBillboardEntry& entry = matPair.second;
|
||||
auto& billboardVector = entry.billboards;
|
||||
|
||||
std::sort(billboardVector.begin(), billboardVector.end(), [&viewerPos] (const BillboardData& data1, const BillboardData& data2)
|
||||
{
|
||||
return viewerPos.SquaredDistance(data1.center) > viewerPos.SquaredDistance(data2.center);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (viewer->GetProjectionType() == ProjectionType_Orthogonal)
|
||||
SortForOrthographic(viewer);
|
||||
else
|
||||
SortForPerspective(viewer);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -715,12 +704,91 @@ namespace Nz
|
||||
return layer;
|
||||
}
|
||||
|
||||
void ForwardRenderQueue::SortBillboards(Layer& layer, const Planef& nearPlane)
|
||||
{
|
||||
for (auto& pipelinePair : layer.billboards)
|
||||
{
|
||||
for (auto& matPair : pipelinePair.second.materialMap)
|
||||
{
|
||||
const Material* mat = matPair.first;
|
||||
|
||||
if (mat->IsDepthSortingEnabled())
|
||||
{
|
||||
BatchedBillboardEntry& entry = matPair.second;
|
||||
auto& billboardVector = entry.billboards;
|
||||
|
||||
std::sort(billboardVector.begin(), billboardVector.end(), [&nearPlane] (const BillboardData& data1, const BillboardData& data2)
|
||||
{
|
||||
return nearPlane.Distance(data1.center) > nearPlane.Distance(data2.center);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ForwardRenderQueue::SortForOrthographic(const AbstractViewer * viewer)
|
||||
{
|
||||
Planef nearPlane = viewer->GetFrustum().GetPlane(FrustumPlane_Near);
|
||||
Vector3f viewerPos = viewer->GetEyePosition();
|
||||
|
||||
for (auto& pair : layers)
|
||||
{
|
||||
Layer& layer = pair.second;
|
||||
|
||||
std::sort(layer.depthSortedMeshes.begin(), layer.depthSortedMeshes.end(), [&layer, &nearPlane] (std::size_t index1, std::size_t index2)
|
||||
{
|
||||
const Spheref& sphere1 = layer.depthSortedMeshData[index1].obbSphere;
|
||||
const Spheref& sphere2 = layer.depthSortedMeshData[index2].obbSphere;
|
||||
|
||||
return nearPlane.Distance(sphere1.GetPosition()) < nearPlane.Distance(sphere2.GetPosition());
|
||||
});
|
||||
|
||||
std::sort(layer.depthSortedSprites.begin(), layer.depthSortedSprites.end(), [&layer, &nearPlane] (std::size_t index1, std::size_t index2)
|
||||
{
|
||||
const Vector3f& pos1 = layer.depthSortedSpriteData[index1].vertices[0].position;
|
||||
const Vector3f& pos2 = layer.depthSortedSpriteData[index2].vertices[0].position;
|
||||
|
||||
return nearPlane.Distance(pos1) < nearPlane.Distance(pos2);
|
||||
});
|
||||
|
||||
SortBillboards(layer, nearPlane);
|
||||
}
|
||||
}
|
||||
|
||||
void ForwardRenderQueue::SortForPerspective(const AbstractViewer* viewer)
|
||||
{
|
||||
Planef nearPlane = viewer->GetFrustum().GetPlane(FrustumPlane_Near);
|
||||
Vector3f viewerPos = viewer->GetEyePosition();
|
||||
|
||||
for (auto& pair : layers)
|
||||
{
|
||||
Layer& layer = pair.second;
|
||||
|
||||
std::sort(layer.depthSortedMeshes.begin(), layer.depthSortedMeshes.end(), [&layer, &viewerPos] (std::size_t index1, std::size_t index2)
|
||||
{
|
||||
const Spheref& sphere1 = layer.depthSortedMeshData[index1].obbSphere;
|
||||
const Spheref& sphere2 = layer.depthSortedMeshData[index2].obbSphere;
|
||||
|
||||
return viewerPos.SquaredDistance(sphere1.GetPosition()) > viewerPos.SquaredDistance(sphere2.GetPosition());
|
||||
});
|
||||
|
||||
std::sort(layer.depthSortedSprites.begin(), layer.depthSortedSprites.end(), [&layer, &viewerPos] (std::size_t index1, std::size_t index2)
|
||||
{
|
||||
const Vector3f& pos1 = layer.depthSortedSpriteData[index1].vertices[0].position;
|
||||
const Vector3f& pos2 = layer.depthSortedSpriteData[index2].vertices[0].position;
|
||||
|
||||
return viewerPos.SquaredDistance(pos1) > viewerPos.SquaredDistance(pos2);
|
||||
});
|
||||
|
||||
SortBillboards(layer, nearPlane);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handle the invalidation of an index buffer
|
||||
*
|
||||
* \param indexBuffer Index buffer being invalidated
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::OnIndexBufferInvalidation(const IndexBuffer* indexBuffer)
|
||||
{
|
||||
for (auto& pair : layers)
|
||||
@@ -757,7 +825,7 @@ namespace Nz
|
||||
{
|
||||
Layer& layer = pair.second;
|
||||
|
||||
for (auto& pipelineEntry : layer.basicSprites)
|
||||
for (auto& pipelineEntry : layer.opaqueSprites)
|
||||
pipelineEntry.second.materialMap.erase(material);
|
||||
|
||||
for (auto& pipelineEntry : layer.billboards)
|
||||
@@ -779,7 +847,7 @@ namespace Nz
|
||||
for (auto& pair : layers)
|
||||
{
|
||||
Layer& layer = pair.second;
|
||||
for (auto& pipelineEntry : layer.basicSprites)
|
||||
for (auto& pipelineEntry : layer.opaqueSprites)
|
||||
{
|
||||
for (auto& materialEntry : pipelineEntry.second.materialMap)
|
||||
materialEntry.second.overlayMap.erase(texture);
|
||||
|
||||
@@ -33,8 +33,8 @@ namespace Nz
|
||||
Vector2f uv;
|
||||
};
|
||||
|
||||
std::size_t s_maxQuads = std::numeric_limits<UInt16>::max() / 6;
|
||||
std::size_t s_vertexBufferSize = 4 * 1024 * 1024; // 4 MiB
|
||||
UInt32 s_maxQuads = std::numeric_limits<UInt16>::max() / 6;
|
||||
UInt32 s_vertexBufferSize = 4 * 1024 * 1024; // 4 MiB
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -101,12 +101,15 @@ namespace Nz
|
||||
if (!layer.opaqueModels.empty())
|
||||
DrawOpaqueModels(sceneData, layer);
|
||||
|
||||
if (!layer.transparentModels.empty())
|
||||
if (!layer.depthSortedMeshes.empty())
|
||||
DrawTransparentModels(sceneData, layer);
|
||||
|
||||
if (!layer.basicSprites.empty())
|
||||
if (!layer.opaqueSprites.empty())
|
||||
DrawBasicSprites(sceneData, layer);
|
||||
|
||||
if (!layer.depthSortedSprites.empty())
|
||||
DrawOrderedSprites(sceneData, layer);
|
||||
|
||||
if (!layer.billboards.empty())
|
||||
DrawBillboards(sceneData, layer);
|
||||
|
||||
@@ -301,7 +304,10 @@ namespace Nz
|
||||
Renderer::SetMatrix(MatrixType_World, Matrix4f::Identity());
|
||||
Renderer::SetVertexBuffer(&m_spriteBuffer);
|
||||
|
||||
for (auto& pipelinePair : layer.basicSprites)
|
||||
const unsigned int overlayTextureUnit = Material::GetTextureUnit(TextureMap_Overlay);
|
||||
const std::size_t maxSpriteCount = std::min<std::size_t>(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4);
|
||||
|
||||
for (auto& pipelinePair : layer.opaqueSprites)
|
||||
{
|
||||
const MaterialPipeline* pipeline = pipelinePair.first;
|
||||
auto& pipelineEntry = pipelinePair.second;
|
||||
@@ -323,6 +329,9 @@ namespace Nz
|
||||
// Position of the camera
|
||||
shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition());
|
||||
|
||||
// Overlay texture unit
|
||||
shader->SendInteger(shaderUniforms->textureOverlay, overlayTextureUnit);
|
||||
|
||||
lastShader = shader;
|
||||
}
|
||||
|
||||
@@ -335,10 +344,6 @@ namespace Nz
|
||||
{
|
||||
material->Apply(pipelineInstance);
|
||||
|
||||
unsigned int overlayTextureUnit = Material::GetTextureUnit(TextureMap_Overlay);
|
||||
|
||||
shader->SendInteger(shaderUniforms->textureOverlay, overlayTextureUnit);
|
||||
|
||||
Renderer::SetTextureSampler(overlayTextureUnit, material->GetDiffuseSampler());
|
||||
|
||||
auto& overlayMap = matEntry.overlayMap;
|
||||
@@ -362,7 +367,6 @@ namespace Nz
|
||||
VertexStruct_XYZ_Color_UV* vertices = static_cast<VertexStruct_XYZ_Color_UV*>(vertexMapper.GetPointer());
|
||||
|
||||
std::size_t spriteCount = 0;
|
||||
std::size_t maxSpriteCount = std::min<std::size_t>(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4);
|
||||
|
||||
do
|
||||
{
|
||||
@@ -777,6 +781,142 @@ namespace Nz
|
||||
}
|
||||
}
|
||||
|
||||
void ForwardRenderTechnique::DrawOrderedSprites(const SceneData & sceneData, ForwardRenderQueue::Layer & layer) const
|
||||
{
|
||||
NazaraAssert(sceneData.viewer, "Invalid viewer");
|
||||
|
||||
Renderer::SetIndexBuffer(&s_quadIndexBuffer);
|
||||
Renderer::SetMatrix(MatrixType_World, Matrix4f::Identity());
|
||||
Renderer::SetVertexBuffer(&m_spriteBuffer);
|
||||
|
||||
const Material* lastMaterial = nullptr;
|
||||
const MaterialPipeline* lastPipeline = nullptr;
|
||||
const Shader* lastShader = nullptr;
|
||||
const Texture* lastOverlay = nullptr;
|
||||
const MaterialPipeline::Instance* pipelineInstance = nullptr;
|
||||
|
||||
const unsigned int overlayTextureUnit = Material::GetTextureUnit(TextureMap_Overlay);
|
||||
|
||||
bool updateVertexBuffer = true;
|
||||
const std::size_t maxSpriteCount = std::min<std::size_t>(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4);
|
||||
|
||||
std::size_t alreadyDrawnCount = 0;
|
||||
std::size_t spriteIndex = 0;
|
||||
std::size_t spriteChainOffset = 0;
|
||||
auto splitChainIt = layer.depthSortedSprites.end();
|
||||
|
||||
for (auto it = layer.depthSortedSprites.begin(); it != layer.depthSortedSprites.end();)
|
||||
{
|
||||
if (updateVertexBuffer)
|
||||
{
|
||||
// We open the buffer in writing mode
|
||||
BufferMapper<VertexBuffer> vertexMapper(m_spriteBuffer, BufferAccess_DiscardAndWrite);
|
||||
VertexStruct_XYZ_Color_UV* vertices = static_cast<VertexStruct_XYZ_Color_UV*>(vertexMapper.GetPointer());
|
||||
|
||||
std::size_t availableSpriteSpace = maxSpriteCount;
|
||||
bool split = false;
|
||||
for (auto it2 = it; it2 != layer.depthSortedSprites.end(); ++it2)
|
||||
{
|
||||
const ForwardRenderQueue::UnbatchedSpriteData& spriteData = layer.depthSortedSpriteData[*it2];
|
||||
|
||||
std::size_t count = std::min(availableSpriteSpace, spriteData.spriteCount - spriteChainOffset);
|
||||
|
||||
std::memcpy(vertices, spriteData.vertices + spriteChainOffset * 4, 4 * count * sizeof(VertexStruct_XYZ_Color_UV));
|
||||
vertices += count * 4;
|
||||
|
||||
availableSpriteSpace -= count;
|
||||
|
||||
// Have we treated the entire chain ?
|
||||
if (count != spriteData.spriteCount)
|
||||
{
|
||||
// Oops, not enough space to store current chain
|
||||
spriteChainOffset += count;
|
||||
splitChainIt = it2;
|
||||
split = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Switch to next sprite chain, if any
|
||||
spriteChainOffset = 0;
|
||||
}
|
||||
|
||||
spriteIndex = 0;
|
||||
updateVertexBuffer = false;
|
||||
|
||||
if (!split)
|
||||
splitChainIt = layer.depthSortedSprites.end();
|
||||
}
|
||||
|
||||
std::size_t index = *it;
|
||||
|
||||
const ForwardRenderQueue::UnbatchedSpriteData& spriteData = layer.depthSortedSpriteData[index];
|
||||
|
||||
const Material* material = spriteData.material;
|
||||
if (material != lastMaterial)
|
||||
{
|
||||
const MaterialPipeline* pipeline = material->GetPipeline();
|
||||
if (pipeline != lastPipeline)
|
||||
{
|
||||
pipelineInstance = &pipeline->Apply(ShaderFlags_TextureOverlay | ShaderFlags_VertexColor);
|
||||
|
||||
const Shader* shader = pipelineInstance->uberInstance->GetShader();
|
||||
|
||||
// Uniforms are conserved in our program, there's no point to send them back until they change
|
||||
if (shader != lastShader)
|
||||
{
|
||||
// Index of uniforms in the shader
|
||||
const ShaderUniforms* shaderUniforms = GetShaderUniforms(shader);
|
||||
|
||||
// Ambient color of the scene
|
||||
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
||||
// Position of the camera
|
||||
shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition());
|
||||
// Overlay texture unit
|
||||
shader->SendInteger(shaderUniforms->textureOverlay, overlayTextureUnit);
|
||||
|
||||
lastShader = shader;
|
||||
}
|
||||
|
||||
lastPipeline = pipeline;
|
||||
}
|
||||
|
||||
material->Apply(*pipelineInstance);
|
||||
|
||||
Renderer::SetTextureSampler(overlayTextureUnit, material->GetDiffuseSampler());
|
||||
|
||||
lastMaterial = material;
|
||||
}
|
||||
|
||||
const Texture* overlay = (spriteData.overlay) ? spriteData.overlay : &m_whiteTexture;
|
||||
if (overlay != lastOverlay)
|
||||
{
|
||||
Renderer::SetTexture(overlayTextureUnit, overlay);
|
||||
lastOverlay = overlay;
|
||||
}
|
||||
|
||||
std::size_t spriteCount;
|
||||
if (it != splitChainIt)
|
||||
{
|
||||
spriteCount = spriteData.spriteCount - alreadyDrawnCount;
|
||||
alreadyDrawnCount = 0;
|
||||
|
||||
++it;
|
||||
}
|
||||
else
|
||||
{
|
||||
spriteCount = spriteChainOffset;
|
||||
|
||||
alreadyDrawnCount = spriteCount;
|
||||
updateVertexBuffer = true;
|
||||
|
||||
// Restart at current iterator next time
|
||||
}
|
||||
|
||||
Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, spriteIndex * 6, spriteCount * 6);
|
||||
spriteIndex += spriteCount;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Draws transparent models
|
||||
*
|
||||
@@ -796,9 +936,9 @@ namespace Nz
|
||||
const ShaderUniforms* shaderUniforms = nullptr;
|
||||
unsigned int lightCount = 0;
|
||||
|
||||
for (unsigned int index : layer.transparentModels)
|
||||
for (std::size_t index : layer.depthSortedMeshes)
|
||||
{
|
||||
const ForwardRenderQueue::TransparentModelData& modelData = layer.transparentModelData[index];
|
||||
const ForwardRenderQueue::UnbatchedModelData& modelData = layer.depthSortedMeshData[index];
|
||||
|
||||
// Material
|
||||
const Material* material = modelData.material;
|
||||
@@ -865,8 +1005,8 @@ namespace Nz
|
||||
if (shaderUniforms->hasLightUniforms && lightCount < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS)
|
||||
{
|
||||
// Compute the closest lights
|
||||
Vector3f position = matrix.GetTranslation() + modelData.squaredBoundingSphere.GetPosition();
|
||||
float radius = modelData.squaredBoundingSphere.radius;
|
||||
Vector3f position = matrix.GetTranslation() + modelData.obbSphere.GetPosition();
|
||||
float radius = modelData.obbSphere.radius;
|
||||
ChooseLights(Spheref(position, radius), false);
|
||||
|
||||
for (std::size_t i = lightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
|
||||
|
||||
@@ -197,6 +197,7 @@ namespace Nz
|
||||
pipelineInfo.blending = true;
|
||||
pipelineInfo.depthWrite = false;
|
||||
pipelineInfo.faceCulling = false;
|
||||
pipelineInfo.depthSorting = true;
|
||||
pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha;
|
||||
pipelineInfo.srcBlend = BlendFunc_SrcAlpha;
|
||||
|
||||
@@ -207,6 +208,7 @@ namespace Nz
|
||||
pipelineInfo.depthBuffer = true;
|
||||
pipelineInfo.depthWrite = false;
|
||||
pipelineInfo.faceCulling = false;
|
||||
pipelineInfo.depthSorting = true;
|
||||
pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha;
|
||||
pipelineInfo.srcBlend = BlendFunc_SrcAlpha;
|
||||
|
||||
|
||||
@@ -280,7 +280,7 @@ namespace Nz
|
||||
|
||||
m_serviceTime = GetElapsedMilliseconds();
|
||||
}
|
||||
while (m_poller.IsReady(m_socket));
|
||||
while (m_poller.IsReadyToRead(m_socket));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -327,7 +327,7 @@ namespace Nz
|
||||
}
|
||||
}
|
||||
|
||||
m_poller.RegisterSocket(m_socket);
|
||||
m_poller.RegisterSocket(m_socket, SocketPollEvent_Read);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -23,13 +23,19 @@ namespace Nz
|
||||
|
||||
void SocketPollerImpl::Clear()
|
||||
{
|
||||
m_activeSockets.clear();
|
||||
m_readyToReadSockets.clear();
|
||||
m_readyToWriteSockets.clear();
|
||||
m_sockets.clear();
|
||||
}
|
||||
|
||||
bool SocketPollerImpl::IsReady(SocketHandle socket) const
|
||||
bool SocketPollerImpl::IsReadyToRead(SocketHandle socket) const
|
||||
{
|
||||
return m_activeSockets.count(socket) != 0;
|
||||
return m_readyToReadSockets.count(socket) != 0;
|
||||
}
|
||||
|
||||
bool SocketPollerImpl::IsReadyToWrite(SocketHandle socket) const
|
||||
{
|
||||
return m_readyToWriteSockets.count(socket) != 0;
|
||||
}
|
||||
|
||||
bool SocketPollerImpl::IsRegistered(SocketHandle socket) const
|
||||
@@ -37,15 +43,21 @@ namespace Nz
|
||||
return m_sockets.count(socket) != 0;
|
||||
}
|
||||
|
||||
bool SocketPollerImpl::RegisterSocket(SocketHandle socket)
|
||||
bool SocketPollerImpl::RegisterSocket(SocketHandle socket, SocketPollEventFlags eventFlags)
|
||||
{
|
||||
NazaraAssert(!IsRegistered(socket), "Socket is already registered");
|
||||
|
||||
epoll_event event;
|
||||
event.events = EPOLLIN;
|
||||
event.data.fd = socket;
|
||||
epoll_event entry;
|
||||
entry.events = 0;
|
||||
entry.data.fd = socket;
|
||||
|
||||
if (epoll_ctl(m_handle, EPOLL_CTL_ADD, socket, &event) != 0)
|
||||
if (eventFlags & SocketPollEvent_Read)
|
||||
entry.events |= EPOLLIN;
|
||||
|
||||
if (eventFlags & SocketPollEvent_Write)
|
||||
entry.events |= EPOLLOUT;
|
||||
|
||||
if (epoll_ctl(m_handle, EPOLL_CTL_ADD, socket, &entry) != 0)
|
||||
{
|
||||
NazaraError("Failed to add socket to epoll structure (errno " + String::Number(errno) + ": " + Error::GetLastSystemError() + ')');
|
||||
return false;
|
||||
@@ -60,7 +72,8 @@ namespace Nz
|
||||
{
|
||||
NazaraAssert(IsRegistered(socket), "Socket is not registered");
|
||||
|
||||
m_activeSockets.erase(socket);
|
||||
m_readyToReadSockets.erase(socket);
|
||||
m_readyToWriteSockets.erase(socket);
|
||||
m_sockets.erase(socket);
|
||||
|
||||
if (epoll_ctl(m_handle, EPOLL_CTL_DEL, socket, nullptr) != 0)
|
||||
@@ -84,21 +97,27 @@ namespace Nz
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_activeSockets.clear();
|
||||
m_readyToReadSockets.clear();
|
||||
m_readyToWriteSockets.clear();
|
||||
if (activeSockets > 0)
|
||||
{
|
||||
int socketCount = activeSockets;
|
||||
for (int i = 0; i < socketCount; ++i)
|
||||
{
|
||||
if (m_events[i].events & (EPOLLIN | EPOLLHUP | EPOLLERR))
|
||||
if (m_events[i].events & (EPOLLIN | EPOLLOUT | EPOLLHUP | EPOLLERR))
|
||||
{
|
||||
m_activeSockets.insert(m_events[i].data.fd);
|
||||
if (m_events[i].events & (EPOLLIN | EPOLLHUP | EPOLLERR))
|
||||
m_readyToReadSockets.insert(m_events[i].data.fd);
|
||||
|
||||
if (m_events[i].events & (EPOLLOUT | EPOLLERR))
|
||||
m_readyToWriteSockets.insert(m_events[i].data.fd);
|
||||
|
||||
if (m_events[i].events & EPOLLERR)
|
||||
NazaraWarning("Descriptor " + String::Number(m_events[i].data.fd) + " was returned by epoll with EPOLLERR status");
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraWarning("Descriptor " + String::Number(m_events[i].data.fd) + " was returned by epoll without EPOLLIN (events: 0x" + String::Number(m_events[i].events, 16) + ')');
|
||||
NazaraWarning("Descriptor " + String::Number(m_events[i].data.fd) + " was returned by epoll without EPOLLIN nor EPOLLOUT flags (events: 0x" + String::Number(m_events[i].events, 16) + ')');
|
||||
activeSockets--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,16 +23,18 @@ namespace Nz
|
||||
|
||||
void Clear();
|
||||
|
||||
bool IsReady(SocketHandle socket) const;
|
||||
bool IsReadyToRead(SocketHandle socket) const;
|
||||
bool IsReadyToWrite(SocketHandle socket) const;
|
||||
bool IsRegistered(SocketHandle socket) const;
|
||||
|
||||
bool RegisterSocket(SocketHandle socket);
|
||||
bool RegisterSocket(SocketHandle socket, SocketPollEventFlags eventFlags);
|
||||
void UnregisterSocket(SocketHandle socket);
|
||||
|
||||
int Wait(UInt64 msTimeout, SocketError* error);
|
||||
|
||||
private:
|
||||
std::unordered_set<SocketHandle> m_activeSockets;
|
||||
std::unordered_set<SocketHandle> m_readyToReadSockets;
|
||||
std::unordered_set<SocketHandle> m_readyToWriteSockets;
|
||||
std::unordered_set<SocketHandle> m_sockets;
|
||||
std::vector<epoll_event> m_events;
|
||||
int m_handle;
|
||||
|
||||
@@ -10,14 +10,20 @@ namespace Nz
|
||||
{
|
||||
void SocketPollerImpl::Clear()
|
||||
{
|
||||
m_activeSockets.clear();
|
||||
m_readyToReadSockets.clear();
|
||||
m_readyToWriteSockets.clear();
|
||||
m_allSockets.clear();
|
||||
m_sockets.clear();
|
||||
}
|
||||
|
||||
bool SocketPollerImpl::IsReady(SocketHandle socket) const
|
||||
bool SocketPollerImpl::IsReadyToRead(SocketHandle socket) const
|
||||
{
|
||||
return m_activeSockets.count(socket) != 0;
|
||||
return m_readyToReadSockets.count(socket) != 0;
|
||||
}
|
||||
|
||||
bool SocketPollerImpl::IsReadyToWrite(SocketHandle socket) const
|
||||
{
|
||||
return m_readyToWriteSockets.count(socket) != 0;
|
||||
}
|
||||
|
||||
bool SocketPollerImpl::IsRegistered(SocketHandle socket) const
|
||||
@@ -25,16 +31,22 @@ namespace Nz
|
||||
return m_allSockets.count(socket) != 0;
|
||||
}
|
||||
|
||||
bool SocketPollerImpl::RegisterSocket(SocketHandle socket)
|
||||
bool SocketPollerImpl::RegisterSocket(SocketHandle socket, SocketPollEventFlags eventFlags)
|
||||
{
|
||||
NazaraAssert(!IsRegistered(socket), "Socket is already registered");
|
||||
|
||||
PollSocket entry = {
|
||||
socket,
|
||||
POLLRDNORM,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
if (eventFlags & SocketPollEvent_Read)
|
||||
entry.events |= POLLRDNORM;
|
||||
|
||||
if (eventFlags & SocketPollEvent_Write)
|
||||
entry.events |= POLLWRNORM;
|
||||
|
||||
m_allSockets[socket] = m_sockets.size();
|
||||
m_sockets.emplace_back(entry);
|
||||
|
||||
@@ -57,10 +69,11 @@ namespace Nz
|
||||
// Now move it properly (lastElement is invalid after the following line) and pop it
|
||||
m_sockets[entry] = std::move(m_sockets.back());
|
||||
}
|
||||
|
||||
m_sockets.pop_back();
|
||||
m_activeSockets.erase(socket);
|
||||
|
||||
m_allSockets.erase(socket);
|
||||
m_readyToReadSockets.erase(socket);
|
||||
m_readyToWriteSockets.erase(socket);
|
||||
}
|
||||
|
||||
int SocketPollerImpl::Wait(UInt64 msTimeout, SocketError* error)
|
||||
@@ -68,20 +81,25 @@ namespace Nz
|
||||
int activeSockets;
|
||||
|
||||
// Reset status of sockets
|
||||
for (PollSocket& entry : m_sockets)
|
||||
entry.revents = 0;
|
||||
|
||||
activeSockets = SocketImpl::Poll(m_sockets.data(), m_sockets.size(), static_cast<int>(msTimeout), error);
|
||||
|
||||
m_activeSockets.clear();
|
||||
if (activeSockets > 0)
|
||||
m_readyToReadSockets.clear();
|
||||
m_readyToWriteSockets.clear();
|
||||
if (activeSockets > 0U)
|
||||
{
|
||||
int socketRemaining = activeSockets;
|
||||
for (PollSocket& entry : m_sockets)
|
||||
{
|
||||
if (entry.revents & POLLRDNORM)
|
||||
if (entry.revents != 0)
|
||||
{
|
||||
m_activeSockets.insert(entry.fd);
|
||||
if (entry.revents & POLLRDNORM)
|
||||
m_readyToReadSockets.insert(entry.fd);
|
||||
|
||||
if (entry.revents & POLLWRNORM)
|
||||
m_readyToWriteSockets.insert(entry.fd);
|
||||
|
||||
entry.revents = 0;
|
||||
|
||||
if (--socketRemaining == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -27,13 +27,14 @@ namespace Nz
|
||||
bool IsReady(SocketHandle socket) const;
|
||||
bool IsRegistered(SocketHandle socket) const;
|
||||
|
||||
bool RegisterSocket(SocketHandle socket);
|
||||
bool RegisterSocket(SocketHandle socket, SocketPollEventFlags eventFlags);
|
||||
void UnregisterSocket(SocketHandle socket);
|
||||
|
||||
int Wait(UInt64 msTimeout, SocketError* error);
|
||||
|
||||
private:
|
||||
std::unordered_set<SocketHandle> m_activeSockets;
|
||||
std::unordered_set<SocketHandle> m_readyToReadSockets;
|
||||
std::unordered_set<SocketHandle> m_readyToWriteSockets;
|
||||
std::unordered_map<SocketHandle, std::size_t> m_allSockets;
|
||||
std::vector<PollSocket> m_sockets;
|
||||
};
|
||||
|
||||
@@ -57,12 +57,13 @@ namespace Nz
|
||||
/*!
|
||||
* \brief Checks if a specific socket is ready to read data
|
||||
*
|
||||
* This function allows you to read the results of the last Wait operation and if a specific socket is ready.
|
||||
* This function allows you to read the results of the last Wait operation and if a specific socket is ready to read (has incoming data).
|
||||
*
|
||||
* A socket in the ready state (with the exception of TcpServer) has incoming data and can be read without blocking.
|
||||
* A socket in the ready to read state (with the exception of TcpServer) has incoming data and can be read without blocking.
|
||||
*
|
||||
* \remark When used on a TcpServer socket, this function returns true if the server is ready to accept a new client.
|
||||
* \remark You must call Wait before using this function in order to refresh the state.
|
||||
* \remark You must call Wait before using this function in order to refresh the read state.
|
||||
* \remark A socket must be registered with SocketPollerEvent_Read event flag for its read state to be watched
|
||||
* \remark A TcpServer socket becomes ready to read when it is ready to accept a new client.
|
||||
*
|
||||
* \param socket Reference to the socket to check
|
||||
*
|
||||
@@ -70,11 +71,32 @@ namespace Nz
|
||||
*
|
||||
* \see Wait
|
||||
*/
|
||||
bool SocketPoller::IsReady(const AbstractSocket& socket) const
|
||||
bool SocketPoller::IsReadyToRead(const AbstractSocket& socket) const
|
||||
{
|
||||
NazaraAssert(IsRegistered(socket), "Socket is not registered in the poller");
|
||||
|
||||
return m_impl->IsReady(socket.GetNativeHandle());
|
||||
return m_impl->IsReadyToRead(socket.GetNativeHandle());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks if a specific socket is ready to write data
|
||||
*
|
||||
* This function allows you to read the results of the last Wait operation and if a specific socket is ready to write (can be written to without blocking).
|
||||
*
|
||||
* \remark You must call Wait before using this function in order to refresh the read state.
|
||||
* \remark A socket must be registered with SocketPollerEvent_Write event flag for its read state to be watched
|
||||
*
|
||||
* \param socket Reference to the socket to check
|
||||
*
|
||||
* \return True if the socket is available for writing without blocking, false otherwise
|
||||
*
|
||||
* \see Wait
|
||||
*/
|
||||
bool SocketPoller::IsReadyToWrite(const AbstractSocket& socket) const
|
||||
{
|
||||
NazaraAssert(IsRegistered(socket), "Socket is not registered in the poller");
|
||||
|
||||
return m_impl->IsReadyToWrite(socket.GetNativeHandle());
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -97,7 +119,7 @@ namespace Nz
|
||||
/*!
|
||||
* \brief Register a socket in the SocketPoller
|
||||
*
|
||||
* A registered socket is part of the SocketPoller and will be checked by the next Wait operations.
|
||||
* A registered socket is part of the SocketPoller and will be checked by the next Wait operations according to the event flags passed when registered.
|
||||
*
|
||||
* The SocketPoller keeps a reference to the internal handle of registered socket, which should not be freed while it is registered in the SocketPooler.
|
||||
*
|
||||
@@ -107,17 +129,18 @@ namespace Nz
|
||||
* \remark The socket should not be freed while it is registered in the SocketPooler.
|
||||
*
|
||||
* \param socket Reference to the socket to register
|
||||
* \param eventFlags Socket events to watch
|
||||
*
|
||||
* \return True if the socket is registered, false otherwise
|
||||
*
|
||||
* \see IsRegistered
|
||||
* \see UnregisterSocket
|
||||
*/
|
||||
bool SocketPoller::RegisterSocket(AbstractSocket& socket)
|
||||
bool SocketPoller::RegisterSocket(AbstractSocket& socket, SocketPollEventFlags eventFlags)
|
||||
{
|
||||
NazaraAssert(!IsRegistered(socket), "This socket is already registered in this SocketPoller");
|
||||
|
||||
return m_impl->RegisterSocket(socket.GetNativeHandle());
|
||||
return m_impl->RegisterSocket(socket.GetNativeHandle(), eventFlags);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -145,7 +168,7 @@ namespace Nz
|
||||
* \brief Wait until any registered socket switches to a ready state.
|
||||
*
|
||||
* Waits a specific/undetermined amount of time until at least one socket part of the SocketPoller becomes ready.
|
||||
* To query the ready state of the registered socket, use the IsReady function.
|
||||
* To query the ready state of the registered socket, use the IsReadyToRead or IsReadyToWrite functions.
|
||||
*
|
||||
* \param msTimeout Maximum time to wait in milliseconds, 0 for infinity
|
||||
*
|
||||
|
||||
@@ -10,29 +10,43 @@ namespace Nz
|
||||
SocketPollerImpl::SocketPollerImpl()
|
||||
{
|
||||
#if !NAZARA_NETWORK_POLL_SUPPORT
|
||||
FD_ZERO(&m_activeSockets);
|
||||
FD_ZERO(&m_sockets);
|
||||
FD_ZERO(&m_readSockets);
|
||||
FD_ZERO(&m_readyToReadSockets);
|
||||
FD_ZERO(&m_readyToWriteSockets);
|
||||
FD_ZERO(&m_writeSockets);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SocketPollerImpl::Clear()
|
||||
{
|
||||
#if NAZARA_NETWORK_POLL_SUPPORT
|
||||
m_activeSockets.clear();
|
||||
m_allSockets.clear();
|
||||
m_readyToReadSockets.clear();
|
||||
m_readyToWriteSockets.clear();
|
||||
m_sockets.clear();
|
||||
#else
|
||||
FD_ZERO(&m_activeSockets);
|
||||
FD_ZERO(&m_sockets);
|
||||
FD_ZERO(&m_readSockets);
|
||||
FD_ZERO(&m_readyToReadSockets);
|
||||
FD_ZERO(&m_readyToWriteSockets);
|
||||
FD_ZERO(&m_writeSockets);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SocketPollerImpl::IsReady(SocketHandle socket) const
|
||||
bool SocketPollerImpl::IsReadyToRead(SocketHandle socket) const
|
||||
{
|
||||
#if NAZARA_NETWORK_POLL_SUPPORT
|
||||
return m_activeSockets.count(socket) != 0;
|
||||
return m_readyToReadSockets.count(socket) != 0;
|
||||
#else
|
||||
return FD_ISSET(socket, &m_activeSockets) != 0;
|
||||
return FD_ISSET(socket, &m_readyToReadSockets) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SocketPollerImpl::IsReadyToWrite(SocketHandle socket) const
|
||||
{
|
||||
#if NAZARA_NETWORK_POLL_SUPPORT
|
||||
return m_readyToWriteSockets.count(socket) != 0;
|
||||
#else
|
||||
return FD_ISSET(socket, &m_readyToWriteSockets) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -41,31 +55,45 @@ namespace Nz
|
||||
#if NAZARA_NETWORK_POLL_SUPPORT
|
||||
return m_allSockets.count(socket) != 0;
|
||||
#else
|
||||
return FD_ISSET(socket, &m_sockets) != 0;
|
||||
return FD_ISSET(socket, &m_readSockets) != 0 ||
|
||||
FD_ISSET(socket, &m_writeSockets) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SocketPollerImpl::RegisterSocket(SocketHandle socket)
|
||||
bool SocketPollerImpl::RegisterSocket(SocketHandle socket, SocketPollEventFlags eventFlags)
|
||||
{
|
||||
NazaraAssert(!IsRegistered(socket), "Socket is already registered");
|
||||
|
||||
#if NAZARA_NETWORK_POLL_SUPPORT
|
||||
PollSocket entry = {
|
||||
socket,
|
||||
POLLRDNORM,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
if (eventFlags & SocketPollEvent_Read)
|
||||
entry.events |= POLLRDNORM;
|
||||
|
||||
if (eventFlags & SocketPollEvent_Write)
|
||||
entry.events |= POLLWRNORM;
|
||||
|
||||
m_allSockets[socket] = m_sockets.size();
|
||||
m_sockets.emplace_back(entry);
|
||||
#else
|
||||
if (m_sockets.fd_count > FD_SETSIZE)
|
||||
for (std::size_t i = 0; i < 2; ++i)
|
||||
{
|
||||
NazaraError("Socket count exceeding FD_SETSIZE (" + String::Number(FD_SETSIZE) + ")");
|
||||
return false;
|
||||
}
|
||||
if ((eventFlags & ((i == 0) ? SocketPollEvent_Read : SocketPollEvent_Write)) == 0)
|
||||
continue;
|
||||
|
||||
FD_SET(socket, &m_sockets);
|
||||
fd_set& targetSet = (i == 0) ? m_readSockets : m_writeSockets;
|
||||
if (targetSet.fd_count > FD_SETSIZE)
|
||||
{
|
||||
NazaraError("Socket count exceeding hard-coded FD_SETSIZE (" + String::Number(FD_SETSIZE) + ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
FD_SET(socket, &targetSet);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@@ -88,13 +116,16 @@ namespace Nz
|
||||
// Now move it properly (lastElement is invalid after the following line) and pop it
|
||||
m_sockets[entry] = std::move(m_sockets.back());
|
||||
}
|
||||
|
||||
m_sockets.pop_back();
|
||||
m_activeSockets.erase(socket);
|
||||
|
||||
m_allSockets.erase(socket);
|
||||
m_readyToReadSockets.erase(socket);
|
||||
m_readyToWriteSockets.erase(socket);
|
||||
#else
|
||||
FD_CLR(socket, &m_activeSockets);
|
||||
FD_CLR(socket, &m_sockets);
|
||||
FD_CLR(socket, &m_readSockets);
|
||||
FD_CLR(socket, &m_readyToReadSockets);
|
||||
FD_CLR(socket, &m_readyToWriteSockets);
|
||||
FD_CLR(socket, &m_writeSockets);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -103,35 +134,28 @@ namespace Nz
|
||||
int activeSockets;
|
||||
|
||||
#if NAZARA_NETWORK_POLL_SUPPORT
|
||||
// Reset status of sockets
|
||||
for (PollSocket& entry : m_sockets)
|
||||
entry.revents = 0;
|
||||
|
||||
activeSockets = SocketImpl::Poll(m_sockets.data(), m_sockets.size(), static_cast<int>(msTimeout), error);
|
||||
|
||||
m_activeSockets.clear();
|
||||
if (activeSockets > 0U)
|
||||
{
|
||||
int socketRemaining = activeSockets;
|
||||
for (PollSocket& entry : m_sockets)
|
||||
{
|
||||
if (entry.revents & POLLRDNORM)
|
||||
{
|
||||
m_activeSockets.insert(entry.fd);
|
||||
if (--socketRemaining == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
fd_set* readSet = nullptr;
|
||||
fd_set* writeSet = nullptr;
|
||||
|
||||
m_activeSockets = m_sockets;
|
||||
if (m_readSockets.fd_count > 0)
|
||||
{
|
||||
m_readyToReadSockets = m_readSockets;
|
||||
readSet = &m_readyToReadSockets;
|
||||
}
|
||||
|
||||
if (m_writeSockets.fd_count > 0)
|
||||
{
|
||||
m_readyToWriteSockets = m_writeSockets;
|
||||
readSet = &m_readyToWriteSockets;
|
||||
}
|
||||
|
||||
timeval tv;
|
||||
tv.tv_sec = static_cast<long>(msTimeout / 1000ULL);
|
||||
tv.tv_usec = static_cast<long>((msTimeout % 1000ULL) * 1000ULL);
|
||||
|
||||
activeSockets = ::select(0xDEADBEEF, &m_activeSockets, nullptr, nullptr, (msTimeout > 0) ? &tv : nullptr); //< The first argument is ignored on Windows
|
||||
activeSockets = ::select(0xDEADBEEF, readSet, writeSet, nullptr, (msTimeout > 0) ? &tv : nullptr); //< The first argument is ignored on Windows
|
||||
if (activeSockets == SOCKET_ERROR)
|
||||
{
|
||||
if (error)
|
||||
|
||||
@@ -25,24 +25,28 @@ namespace Nz
|
||||
|
||||
void Clear();
|
||||
|
||||
bool IsReady(SocketHandle socket) const;
|
||||
bool IsReadyToRead(SocketHandle socket) const;
|
||||
bool IsReadyToWrite(SocketHandle socket) const;
|
||||
bool IsRegistered(SocketHandle socket) const;
|
||||
|
||||
bool RegisterSocket(SocketHandle socket);
|
||||
bool RegisterSocket(SocketHandle socket, SocketPollEventFlags eventFlags);
|
||||
void UnregisterSocket(SocketHandle socket);
|
||||
|
||||
int Wait(UInt64 msTimeout, SocketError* error);
|
||||
|
||||
private:
|
||||
#if NAZARA_NETWORK_POLL_SUPPORT
|
||||
std::unordered_set<SocketHandle> m_activeSockets;
|
||||
std::unordered_set<SocketHandle> m_readyToReadSockets;
|
||||
std::unordered_set<SocketHandle> m_readyToWriteSockets;
|
||||
std::unordered_map<SocketHandle, std::size_t> m_allSockets;
|
||||
std::vector<PollSocket> m_sockets;
|
||||
#else
|
||||
fd_set m_sockets;
|
||||
fd_set m_activeSockets;
|
||||
fd_set m_readSockets;
|
||||
fd_set m_readyToReadSockets;
|
||||
fd_set m_readyToWriteSockets;
|
||||
fd_set m_writeSockets;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_SOCKETPOLLERIMPL_HPP
|
||||
#endif // NAZARA_SOCKETPOLLERIMPL_HPP
|
||||
|
||||
@@ -62,9 +62,9 @@ namespace Nz
|
||||
|
||||
if (cpShape* shape = cpSpacePointQueryNearest(m_handle, { from.x, from.y }, maxDistance, filter, &queryInfo))
|
||||
{
|
||||
result->closestPoint.Set(queryInfo.point.x, queryInfo.point.y);
|
||||
result->distance = queryInfo.distance;
|
||||
result->fraction.Set(queryInfo.gradient.x, queryInfo.gradient.y);
|
||||
result->closestPoint.Set(Nz::Vector2<cpFloat>(queryInfo.point.x, queryInfo.point.y));
|
||||
result->distance = float(queryInfo.distance);
|
||||
result->fraction.Set(Nz::Vector2<cpFloat>(queryInfo.gradient.x, queryInfo.gradient.y));
|
||||
result->nearestBody = static_cast<Nz::RigidBody2D*>(cpShapeGetUserData(shape));
|
||||
|
||||
return true;
|
||||
@@ -90,9 +90,9 @@ namespace Nz
|
||||
ResultType results = static_cast<ResultType>(data);
|
||||
|
||||
RaycastHit hitInfo;
|
||||
hitInfo.fraction = alpha;
|
||||
hitInfo.hitNormal.Set(normal.x, normal.y);
|
||||
hitInfo.hitPos.Set(point.x, point.y);
|
||||
hitInfo.fraction = float(alpha);
|
||||
hitInfo.hitNormal.Set(Nz::Vector2<cpFloat>(normal.x, normal.y));
|
||||
hitInfo.hitPos.Set(Nz::Vector2<cpFloat>(point.x, point.y));
|
||||
hitInfo.nearestBody = static_cast<Nz::RigidBody2D*>(cpShapeGetUserData(shape));
|
||||
|
||||
results->emplace_back(std::move(hitInfo));
|
||||
@@ -116,9 +116,9 @@ namespace Nz
|
||||
|
||||
if (cpShape* shape = cpSpaceSegmentQueryFirst(m_handle, { from.x, from.y }, { to.x, to.y }, radius, filter, &queryInfo))
|
||||
{
|
||||
hitInfo->fraction = queryInfo.alpha;
|
||||
hitInfo->hitNormal.Set(queryInfo.normal.x, queryInfo.normal.y);
|
||||
hitInfo->hitPos.Set(queryInfo.point.x, queryInfo.point.y);
|
||||
hitInfo->fraction = float(queryInfo.alpha);
|
||||
hitInfo->hitNormal.Set(Nz::Vector2<cpFloat>(queryInfo.normal.x, queryInfo.normal.y));
|
||||
hitInfo->hitPos.Set(Nz::Vector2<cpFloat>(queryInfo.point.x, queryInfo.point.y));
|
||||
hitInfo->nearestBody = static_cast<Nz::RigidBody2D*>(cpShapeGetUserData(queryInfo.shape));
|
||||
|
||||
return true;
|
||||
|
||||
@@ -215,7 +215,7 @@ namespace Nz
|
||||
cpVect vel = cpBodyGetVelocity(m_handle);
|
||||
|
||||
Destroy();
|
||||
Create(mass, moment);
|
||||
Create(float(mass), float(moment));
|
||||
|
||||
cpBodySetAngle(m_handle, rot);
|
||||
cpBodySetPosition(m_handle, pos);
|
||||
|
||||
@@ -121,9 +121,7 @@ namespace Nz
|
||||
break;
|
||||
|
||||
default:
|
||||
// Peut être rajouté par une extension
|
||||
ss << "Unknown";
|
||||
break;
|
||||
return; //< Block NVidia buffer usage hint for now
|
||||
}
|
||||
ss << '\n';
|
||||
|
||||
|
||||
@@ -91,8 +91,8 @@ namespace Nz
|
||||
|
||||
bool largeIndices = (vertexCount > std::numeric_limits<UInt16>::max());
|
||||
|
||||
IndexBufferRef indexBuffer = IndexBuffer::New(largeIndices, indexCount, parameters.storage, 0);
|
||||
VertexBufferRef vertexBuffer = VertexBuffer::New(VertexDeclaration::Get(VertexLayout_XYZ_Normal_UV_Tangent_Skinning), vertexCount, parameters.storage, 0);
|
||||
IndexBufferRef indexBuffer = IndexBuffer::New(largeIndices, UInt32(indexCount), parameters.storage, 0);
|
||||
VertexBufferRef vertexBuffer = VertexBuffer::New(VertexDeclaration::Get(VertexLayout_XYZ_Normal_UV_Tangent_Skinning), UInt32(vertexCount), parameters.storage, 0);
|
||||
|
||||
// Index buffer
|
||||
IndexMapper indexMapper(indexBuffer, BufferAccess_DiscardAndWrite);
|
||||
@@ -236,7 +236,7 @@ namespace Nz
|
||||
// Index buffer
|
||||
bool largeIndices = (vertexCount > std::numeric_limits<UInt16>::max());
|
||||
|
||||
IndexBufferRef indexBuffer = IndexBuffer::New(largeIndices, indexCount, parameters.storage, 0);
|
||||
IndexBufferRef indexBuffer = IndexBuffer::New(largeIndices, UInt32(indexCount), parameters.storage, 0);
|
||||
|
||||
IndexMapper indexMapper(indexBuffer, BufferAccess_DiscardAndWrite);
|
||||
IndexIterator index = indexMapper.begin();
|
||||
@@ -251,7 +251,7 @@ namespace Nz
|
||||
indexMapper.Unmap();
|
||||
|
||||
// Vertex buffer
|
||||
VertexBufferRef vertexBuffer = VertexBuffer::New(VertexDeclaration::Get(VertexLayout_XYZ_Normal_UV_Tangent), vertexCount, parameters.storage, 0);
|
||||
VertexBufferRef vertexBuffer = VertexBuffer::New(VertexDeclaration::Get(VertexLayout_XYZ_Normal_UV_Tangent), UInt32(vertexCount), parameters.storage, 0);
|
||||
BufferMapper<VertexBuffer> vertexMapper(vertexBuffer, BufferAccess_WriteOnly);
|
||||
|
||||
MeshVertex* vertices = static_cast<MeshVertex*>(vertexMapper.GetPointer());
|
||||
|
||||
@@ -233,8 +233,8 @@ namespace Nz
|
||||
}
|
||||
|
||||
// Création des buffers
|
||||
IndexBufferRef indexBuffer = IndexBuffer::New(vertexCount > std::numeric_limits<UInt16>::max(), indices.size(), parameters.storage, 0);
|
||||
VertexBufferRef vertexBuffer = VertexBuffer::New(VertexDeclaration::Get(VertexLayout_XYZ_Normal_UV_Tangent), vertexCount, parameters.storage, 0);
|
||||
IndexBufferRef indexBuffer = IndexBuffer::New(vertexCount > std::numeric_limits<UInt16>::max(), UInt32(indices.size()), parameters.storage, 0);
|
||||
VertexBufferRef vertexBuffer = VertexBuffer::New(VertexDeclaration::Get(VertexLayout_XYZ_Normal_UV_Tangent), UInt32(vertexCount), parameters.storage, 0);
|
||||
|
||||
// Remplissage des indices
|
||||
IndexMapper indexMapper(indexBuffer, BufferAccess_WriteOnly);
|
||||
|
||||
@@ -228,7 +228,7 @@ namespace Nz
|
||||
|
||||
if (p < 0)
|
||||
{
|
||||
p += m_positions.size() - 1;
|
||||
p += static_cast<int>(m_positions.size() - 1);
|
||||
if (p < 0)
|
||||
{
|
||||
Error("Vertex index out of range (" + String::Number(p) + " < 0");
|
||||
@@ -239,7 +239,7 @@ namespace Nz
|
||||
|
||||
if (n < 0)
|
||||
{
|
||||
n += m_normals.size() - 1;
|
||||
n += static_cast<int>(m_normals.size() - 1);
|
||||
if (n < 0)
|
||||
{
|
||||
Error("Normal index out of range (" + String::Number(n) + " < 0");
|
||||
@@ -250,7 +250,7 @@ namespace Nz
|
||||
|
||||
if (t < 0)
|
||||
{
|
||||
t += m_texCoords.size() - 1;
|
||||
t += static_cast<int>(m_texCoords.size() - 1);
|
||||
if (t < 0)
|
||||
{
|
||||
Error("Texture coordinates index out of range (" + String::Number(t) + " < 0");
|
||||
|
||||
@@ -12,38 +12,38 @@ namespace Nz
|
||||
{
|
||||
namespace
|
||||
{
|
||||
UInt32 GetterSequential(const void* buffer, unsigned int i)
|
||||
UInt32 GetterSequential(const void* buffer, std::size_t i)
|
||||
{
|
||||
NazaraUnused(buffer);
|
||||
|
||||
return i;
|
||||
return static_cast<UInt32>(i);
|
||||
}
|
||||
|
||||
UInt32 Getter16(const void* buffer, unsigned int i)
|
||||
UInt32 Getter16(const void* buffer, std::size_t i)
|
||||
{
|
||||
const UInt16* ptr = static_cast<const UInt16*>(buffer);
|
||||
return ptr[i];
|
||||
}
|
||||
|
||||
UInt32 Getter32(const void* buffer, unsigned int i)
|
||||
UInt32 Getter32(const void* buffer, std::size_t i)
|
||||
{
|
||||
const UInt32* ptr = static_cast<const UInt32*>(buffer);
|
||||
return ptr[i];
|
||||
}
|
||||
|
||||
void Setter16(void* buffer, unsigned int i, UInt32 value)
|
||||
void Setter16(void* buffer, std::size_t i, UInt32 value)
|
||||
{
|
||||
UInt16* ptr = static_cast<UInt16*>(buffer);
|
||||
ptr[i] = static_cast<UInt16>(value);
|
||||
}
|
||||
|
||||
void Setter32(void* buffer, unsigned int i, UInt32 value)
|
||||
void Setter32(void* buffer, std::size_t i, UInt32 value)
|
||||
{
|
||||
UInt32* ptr = static_cast<UInt32*>(buffer);
|
||||
ptr[i] = value;
|
||||
}
|
||||
|
||||
void SetterError(void*, unsigned int, UInt32)
|
||||
void SetterError(void*, std::size_t, UInt32)
|
||||
{
|
||||
NazaraError("Index buffer opened with read-only access");
|
||||
}
|
||||
@@ -113,15 +113,9 @@ namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
UInt32 IndexMapper::Get(unsigned int i) const
|
||||
UInt32 IndexMapper::Get(std::size_t i) const
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (i >= m_indexCount)
|
||||
{
|
||||
NazaraError("Index out of range (" + String::Number(i) + " >= " + String::Number(m_indexCount) + ')');
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
NazaraAssert(i < m_indexCount, "Index out of range");
|
||||
|
||||
return m_getter(m_mapper.GetPointer(), i);
|
||||
}
|
||||
@@ -131,20 +125,14 @@ namespace Nz
|
||||
return m_mapper.GetBuffer();
|
||||
}
|
||||
|
||||
unsigned int IndexMapper::GetIndexCount() const
|
||||
std::size_t IndexMapper::GetIndexCount() const
|
||||
{
|
||||
return m_indexCount;
|
||||
}
|
||||
|
||||
void IndexMapper::Set(unsigned int i, UInt32 value)
|
||||
void IndexMapper::Set(std::size_t i, UInt32 value)
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (i >= m_indexCount)
|
||||
{
|
||||
NazaraError("Index out of range (" + String::Number(i) + " >= " + String::Number(m_indexCount) + ')');
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
NazaraAssert(i < m_indexCount, "Index out of range");
|
||||
|
||||
m_setter(m_mapper.GetPointer(), i, value);
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace Nz
|
||||
NazaraAssert(subMesh, "Invalid submesh");
|
||||
NazaraAssert(subMesh->GetAnimationType() == m_impl->animationType, "Submesh animation type doesn't match mesh animation type");
|
||||
|
||||
m_impl->subMeshes.push_back(subMesh);
|
||||
m_impl->subMeshes.emplace_back(subMesh);
|
||||
|
||||
InvalidateAABB();
|
||||
}
|
||||
@@ -92,10 +92,10 @@ namespace Nz
|
||||
NazaraAssert(subMesh, "Invalid submesh");
|
||||
NazaraAssert(subMesh->GetAnimationType() == m_impl->animationType, "Submesh animation type doesn't match mesh animation type");
|
||||
|
||||
UInt32 index = m_impl->subMeshes.size();
|
||||
std::size_t index = m_impl->subMeshes.size();
|
||||
|
||||
m_impl->subMeshes.push_back(subMesh);
|
||||
m_impl->subMeshMap[identifier] = index;
|
||||
m_impl->subMeshes.emplace_back(subMesh);
|
||||
m_impl->subMeshMap[identifier] = static_cast<UInt32>(index);
|
||||
|
||||
InvalidateAABB();
|
||||
}
|
||||
@@ -349,11 +349,11 @@ namespace Nz
|
||||
|
||||
if (!m_impl->aabbUpdated)
|
||||
{
|
||||
UInt32 subMeshCount = m_impl->subMeshes.size();
|
||||
std::size_t subMeshCount = m_impl->subMeshes.size();
|
||||
if (subMeshCount > 0)
|
||||
{
|
||||
m_impl->aabb.Set(m_impl->subMeshes[0]->GetAABB());
|
||||
for (UInt32 i = 1; i < subMeshCount; ++i)
|
||||
for (std::size_t i = 1; i < subMeshCount; ++i)
|
||||
m_impl->aabb.ExtendTo(m_impl->subMeshes[i]->GetAABB());
|
||||
}
|
||||
else
|
||||
@@ -407,7 +407,7 @@ namespace Nz
|
||||
{
|
||||
NazaraAssert(m_impl, "Mesh should be created first");
|
||||
|
||||
return m_impl->materialData.size();
|
||||
return static_cast<UInt32>(m_impl->materialData.size());
|
||||
}
|
||||
|
||||
Skeleton* Mesh::GetSkeleton()
|
||||
@@ -466,7 +466,7 @@ namespace Nz
|
||||
{
|
||||
NazaraAssert(m_impl, "Mesh should be created first");
|
||||
|
||||
return m_impl->subMeshes.size();
|
||||
return static_cast<UInt32>(m_impl->subMeshes.size());
|
||||
}
|
||||
|
||||
UInt32 Mesh::GetSubMeshIndex(const String& identifier) const
|
||||
|
||||
@@ -243,7 +243,7 @@ namespace Nz
|
||||
m_workingBounds.MakeZero(); //< Compute bounds as float to speedup bounds computation (as casting between floats and integers is costly)
|
||||
|
||||
if (m_font)
|
||||
m_lines.emplace_back(Line{Rectf(0.f, 0.f, 0.f, m_font->GetSizeInfo(m_characterSize).lineHeight), 0});
|
||||
m_lines.emplace_back(Line{Rectf(0.f, 0.f, 0.f, float(m_font->GetSizeInfo(m_characterSize).lineHeight)), 0});
|
||||
else
|
||||
m_lines.emplace_back(Line{Rectf::Zero(), 0});
|
||||
}
|
||||
@@ -354,7 +354,7 @@ namespace Nz
|
||||
{
|
||||
glyph.atlas = nullptr;
|
||||
|
||||
glyph.bounds.Set(m_drawPos.x, m_drawPos.y, float(advance), sizeInfo.lineHeight);
|
||||
glyph.bounds.Set(float(m_drawPos.x), float(m_drawPos.y), float(advance), float(sizeInfo.lineHeight));
|
||||
|
||||
glyph.corners[0].Set(glyph.bounds.GetCorner(RectCorner_LeftTop));
|
||||
glyph.corners[1].Set(glyph.bounds.GetCorner(RectCorner_RightTop));
|
||||
@@ -377,7 +377,7 @@ namespace Nz
|
||||
m_drawPos.x = 0;
|
||||
m_drawPos.y += sizeInfo.lineHeight;
|
||||
|
||||
m_lines.emplace_back(Line{Rectf(0.f, sizeInfo.lineHeight * m_lines.size(), 0.f, sizeInfo.lineHeight), m_glyphs.size() + 1});
|
||||
m_lines.emplace_back(Line{Rectf(0.f, float(sizeInfo.lineHeight * m_lines.size()), 0.f, float(sizeInfo.lineHeight)), m_glyphs.size() + 1});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,12 +72,12 @@ namespace Nz
|
||||
|
||||
if (!m_impl->aabbUpdated)
|
||||
{
|
||||
UInt32 jointCount = m_impl->joints.size();
|
||||
std::size_t jointCount = m_impl->joints.size();
|
||||
if (jointCount > 0)
|
||||
{
|
||||
Vector3f pos = m_impl->joints[0].GetPosition();
|
||||
m_impl->aabb.Set(pos.x, pos.y, pos.z, 0.f, 0.f, 0.f);
|
||||
for (UInt32 i = 1; i < jointCount; ++i)
|
||||
for (std::size_t i = 1; i < jointCount; ++i)
|
||||
m_impl->aabb.ExtendTo(m_impl->joints[i].GetPosition());
|
||||
}
|
||||
else
|
||||
@@ -219,7 +219,7 @@ namespace Nz
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->joints.size();
|
||||
return static_cast<UInt32>(m_impl->joints.size());
|
||||
}
|
||||
|
||||
int Skeleton::GetJointIndex(const String& jointName) const
|
||||
@@ -411,16 +411,9 @@ namespace Nz
|
||||
String name = m_impl->joints[i].GetName();
|
||||
if (!name.IsEmpty())
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
auto it = m_impl->jointMap.find(name);
|
||||
if (it != m_impl->jointMap.end())
|
||||
{
|
||||
NazaraWarning("Joint name \"" + name + "\" is already present in joint map for joint #" + String::Number(it->second));
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
NazaraAssert(m_impl->jointMap.find(name) == m_impl->jointMap.end(), "Joint name \"" + name + "\" is already present in joint map");
|
||||
|
||||
m_impl->jointMap[name] = i;
|
||||
m_impl->jointMap[name] = static_cast<UInt32>(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,18 +66,9 @@ namespace Nz
|
||||
return true;
|
||||
}
|
||||
|
||||
UInt32 TriangleIterator::operator[](unsigned int i) const
|
||||
UInt32 TriangleIterator::operator[](std::size_t i) const
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (i >= 3)
|
||||
{
|
||||
StringStream ss;
|
||||
ss << "Index out of range: (" << i << " >= 3)";
|
||||
|
||||
NazaraError(ss);
|
||||
throw std::domain_error(ss.ToString());
|
||||
}
|
||||
#endif
|
||||
NazaraAssert(i < 3, "Index out of range");
|
||||
|
||||
return m_triangleIndices[i];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user